Fetch agent identity via agent.identity.get WS method after connect.
Display avatar in message bubbles (replacing Bot icon) and in the
header (replacing the PinchChat logo when an avatar is configured).
Falls back to default icons when no avatar is set.
Small info button appears on hover of each message bubble.
Click to expand a panel showing raw message metadata (id, role,
timestamp, channel, sender info, etc.) from the gateway.
Useful for debugging and understanding message routing.
Collapsed by default, doesn't clutter the UI.
Closes feedback item #39
Deleted sessions would reappear after page refresh because the
gateway sessions.list response still included them. Now maintains
a localStorage blacklist of deleted session keys that filters them
out on every load, regardless of gateway-side deletion support.
- Show relative time (2m, 3h, 1d) next to each session name
- Display last message preview below session name (truncated to 80 chars)
- Sort sessions by most recently updated (within pinned/unpinned groups)
- Map updatedAt and lastMessagePreview from gateway sessions.list response
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.).
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.
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.
Show Discord, Telegram, WhatsApp, Signal, Slack brand icons,
clock icon for cron sessions, bot icon for sub-agents, and
globe icon for webchat sessions. Falls back to message bubble
for unknown channels.
Closes feedback #23
- Chat.tsx: replace mutable variable in render IIFE with useMemo+reduce
to satisfy react-hooks/immutability rule
- ConnectionBanner.tsx: move setState calls into a useCallback to avoid
synchronous setState in effect body (react-hooks/set-state-in-effect)
- useGateway.ts: suppress set-state-in-effect for legitimate mount init
- Add GatewayMessage and JsonPayload interfaces to gateway.ts
- Type WebSocket message parsing with GatewayMessage instead of any
- Use ReturnType<typeof setTimeout> for timer refs
- Type chat event payload destructuring explicitly
- Add ChatPayloadMessage interface for extractText()
- Replace any casts in loadSessions/loadHistory with typed assertions
- Add str() helper in ToolCall.tsx for safe unknown→string extraction
- Use Extract<MessageBlock, ...> type guards instead of `as any` casts
- Type CodeBlock children prop properly
- Add image block type for base64 and URL images
- Parse image/image_url blocks from gateway history
- Render images inline in chat messages (rounded, dark-themed)
- Click-to-zoom lightbox with Escape to close
- Markdown images also use the lightbox component
- Detect base64 images in tool results (e.g. Read tool on image files)
- Support png, jpg, gif, webp formats
- Add LoginScreen component with Gateway URL + Token fields
- Store credentials in localStorage (not in bundle)
- Auto-reconnect with stored credentials on reload
- Add logout button (LogOut icon) in Header
- Remove VITE_GATEWAY_TOKEN from .env.example
- VITE_GATEWAY_WS_URL now only pre-fills the URL field
- Dark neon theme consistent with rest of app
Closes feedback item #4