Shows the agentId (e.g. 'main') with a bot icon in the header subtitle,
making it clear which agent is handling the current conversation.
Useful for multi-agent setups.
Replace raw session keys/UUIDs with readable names derived from
session metadata (label, kind, channel). Priority: label > kind-based
name (Main, Cron, Task) with channel suffix > cleaned key fallback.
New utility: src/lib/sessionName.ts used by both Header and Sidebar.
The looksLikeCode/isCodeLine heuristics were too aggressive:
- Pattern /^\s*(\/\/|#|\/\*|\*)/ matched markdown bold (**text**) and
headings (# title) as code comments, causing entire sections to be
wrapped in code fences and rendered as raw text
- Pattern /^\s*(\/\/|#)/ in isCodeLine caught markdown headers
- Added early bail-out when text contains markdown indicators (**bold**,
headings, bullet lists) to prevent false positives
- Narrowed comment detection to actual code comments only
Fixes: raw **bold** shown in long assistant messages (reported by Josh)
System events (heartbeats, cron triggers, webhooks, channel events)
now render as subtle inline notifications instead of full user bubbles.
Detection based on content patterns ([EVENT], [cron:], [HEARTBEAT], etc.).
- New release.yml: triggers on v* tags, builds/pushes Docker with vX.Y.Z, vX.Y, vX, latest tags, creates GitHub Release with changelog
- Updated docker.yml: main pushes now tag as 'edge' (dev) instead of 'latest'
- latest tag is now only set by the release workflow on version tags
- Pin icon appears on hover for each session, filled when pinned
- Pinned sessions sort to top of list (preserved across page reloads via localStorage)
- Subtle divider separates pinned from unpinned sessions
- i18n support for pin/unpin labels (EN + FR)
Shows the model (e.g. claude-opus-4-6) as a subtle chip next to the
session label in the header. Hovering reveals agent ID if available.
Model and agentId are now extracted from sessions.list response.
Display a header bar above code blocks with the detected language
name (e.g. TypeScript, Python, Shell). Pretty-prints common language
identifiers. The copy button remains in the top-right corner.
Shows how long the agent has been thinking (e.g. '5s', '1m 23s').
Timer appears after 2 seconds to avoid flicker on fast responses.
Helps users gauge if a request is still processing or stuck.
Arrow Up/Down to navigate sessions, Enter to select, Escape to close.
Sessions use role='option' with aria-selected for screen reader support.
Mouse hover syncs with keyboard focus index for smooth interaction.
- Add Vite define for __APP_VERSION__ from package.json
- Use dynamic version in gateway connect handshake and userAgent
- Show version number in sidebar footer
- Add globals.d.ts type declaration
Updates document.title dynamically to show the current session label
(e.g. 'main — PinchChat'). Integrates with the existing notification
system so unread badges still work correctly (e.g. '(3) main — PinchChat').
Resets to plain 'PinchChat' when no session is selected.
The Chat component (and its heavy markdown dependencies ~476KB) are now
loaded via React.lazy() + Suspense. Users see the login screen faster
since only ~245KB is needed initially instead of ~750KB.
- Generate 192x192, 512x512, 180x180, 32x32, and 16x16 icons from logo
- Add manifest.json for PWA install support (standalone display)
- Add apple-touch-icon for iOS home screen
- Use sized favicons instead of full 1024x1024 logo.png
Check typeof Notification before accessing .permission or
requestPermission(). Fixes crash on browsers/contexts where
the Notification API is unavailable (e.g. some WebViews).
Show inline hint when the gateway URL doesn't start with ws:// or wss://
and disable the connect button until it's valid. Prevents confusing
connection errors from malformed URLs.
Show a spinner with 'Loading messages…' text while chat history
is being fetched during session switches, instead of briefly
flashing the empty welcome screen. Includes EN/FR i18n.