Commit Graph
597 Commits
Author SHA1 Message Date
Bohdan Triapitsyn df13a54f37 fix(vscode): hide Save-as-plan and Add-to-notes actions in VS Code runtime
Both flows write into ~/.config/openchamber which isn't reachable from the
VS Code webview, so the buttons were dead weight there.
2026-04-18 13:50:09 +03:00
Bohdan Triapitsyn 8d43678fea feat(notes): add selected chat text to project notes with AI-distilled insight
Extend the text selection popover with an Add to notes action that runs the
selection through the shared text summarizer in note mode and appends the
distilled insight to the active project's notes.
2026-04-18 13:47:16 +03:00
Bohdan Triapitsyn 799a202e99 feat(plans): save assistant messages as editable project plans with improve/implement flows
Add Save-as-plan action on assistant messages that writes a markdown plan
into the project plans directory and suggests a title from the text. Plan
view opens a specific saved plan via targetPath, supports inline edits, and
can kick off improve or implement flows in a new or worktree session.

Ship the matching hidden magic prompts (plan.todo/improve/implement) so the
instructions applied by these flows are visible and editable in the Magic
Prompts page.

Remove the plan editor font override, CodeMirror now uses the app font stack.
2026-04-18 13:47:05 +03:00
jwcrystal f5535dcaf1 fix: recover from sleep/wake disconnection with connection state tracking and immediate health check (#940)
When the computer sleeps and wakes, the SSE/WS event stream drops
silently. Messages appeared sent (optimistic insert) but never reached
the OpenCode server, and the user had no indication the system was
disconnected.

Three fixes:

1. Connection state tracking: add onDisconnect callback to the event
   pipeline. Stream failures set isConnected=false in useConfigStore;
   successful reconnect sets isConnected=true.

2. Send guard: optimisticSend, respondToPermission, and
   respondToQuestion now check isConnected before making API calls,
   throwing a clear error that surfaces as a toast to the user.
   The /compact command also checks connection with error feedback.

3. Faster server recovery: add triggerHealthCheck() to the server
   lifecycle and wire it into the WS event stream runtime. When the
   upstream OpenCode connection fails, the server immediately checks
   health and restarts if needed, instead of waiting up to 15s for
   the periodic health check.
2026-04-17 18:48:39 +03:00
Bohdan Triapitsyn 71eac0d2f6 fix: improve session export and empty chat states
Move session export into the sidebar menu
Add desktop save-and-reveal flow for exported markdown
Show empty-state UI instead of a loading skeleton for empty sessions
2026-04-17 15:33:26 +03:00
coldbrow a17d159e18 feat(chat): add export session as markdown workflow (#934)
Add a download button in the chat view that exports the current session's
messages as a formatted Markdown file. User and assistant turns are
separated by horizontal rules. The filename is derived from the session
title and today's date (e.g. fix-login-bug-2026-04-17.md).
2026-04-17 14:50:26 +03:00
Bohdan Triapitsyn 2146e346a0 fix: show empty chat state for loaded sessions
Show the empty chat logo when a session has no messages
Keep skeletons only for real session hydration
Avoid misleading loading UI after reverting the last message
2026-04-17 14:33:08 +03:00
Bohdan Triapitsyn 4590e1684f fix: improve sorted chat activity rendering
Show tools and reasoning live in sorted mode
Keep ambiguous text deferred until final output
Avoid duplicate reasoning outside Activity
2026-04-17 14:26:55 +03:00
YifanandBohdan Triapitsyn bee9d19f3a feat(web): add WebSocket transport for message event streaming with SSE fallback (#764)
* feat: add websocket message stream transport

* fix: avoid false missing session directories in sidebar

* fix: re-probe project root session directories

* refactor: use button group for message stream transport

* fix: resolve chat input hook dependency warning

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-04-17 11:07:26 +03:00
ricautomationandBohdan Triapitsyn 324cf49755 feat: Latex support (#929)
* feat: implement LaTeX math rendering via KaTeX

- Add katex, remark-math, and rehype-katex dependencies
- Integrate KaTeX CSS with light/dark theme color overrides
- Wire remark-math and rehype-katex plugins into MarkdownRenderer
- Support inline ($...$) and display ($$...$$) math delimiters
- Add plan and task documentation

* fix(katex): display inline error messages for invalid LaTeX

- Configure rehypeKatex with throwOnError: false to render errors inline
- Use destructive color var for error text
- Update feature documentation with verification results

* chore: remove latex PR artifacts and hardcoded color fallback

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-04-16 23:30:52 +03:00
jwcrystalandBohdan Triapitsyn fccf4bad32 feat: session worktree isolation (#913)
* feat: add session-worktree contract types and canonicalizeWorktreeState API

- Add SessionWorktreeAttachment type and worktree metadata fields (worktreeRoot,
  worktreeStatus, headState, worktreeSource) to session/worktree types
- Add GitAPI.validateWorktreeDirectory() and canonicalizeWorktreeState() methods
  with full HTTP delegation chain (gitApiHttp → routes.js → service.js)
- Add canonicalizeWorktreeState() implementation that resolves worktreeRoot,
  headState (branch/detached/unborn), attentionReason (merge/rebase/etc), and
  worktreeStatus (ready/missing/invalid/not-a-repo) for a given directory
- Add validateWorktreeDirectory() to check whether a cwd is inside a worktreeRoot
- Add session-worktree-contract.ts: pure functions for resolving session worktree
  state, formatting badges, and building repair actions
- Add session-worktree-store.ts: authoritative Zustand store for session-to-worktree
  attachments, replacing session-ui-store as the source of truth for worktree binding
- Add unit tests for contract functions and store operations

* feat: canonicalize worktree metadata producers

- worktreeManager.listProjectWorktrees: derive headState (branch/detached/unborn)
  from worktree list entry instead of relying on external state, and populate
  all Phase 1 canonical fields (worktreeRoot, worktreeStatus, worktreeSource)
  for each discovered worktree entry
- worktreeManager.createWorktree: include all Phase 1 canonical fields
  (worktreeRoot, worktreeStatus, headState, worktreeSource) in returned metadata
- useDetectedWorktreeRoot: populate fallback canonical fields so that
  sessions without store-based metadata still have worktreeRoot/worktreeStatus/
  headState/worktreeSource when resolved through the fallback path

* feat: route sessions through authoritative worktree attachments

- session-ui-store: import session-worktree-store as the authoritative source
  for session↔worktree attachment state
- setWorktreeMetadata: mirror all writes to session-worktree-store so that
  session-worktree-store.attachments is always the authoritative record;
  local worktreeMetadata map is kept for backward-compatible reads
- Add session-ui-store.test.js with unit tests covering: valid cwd routing,
  degraded fallback, created-for-session attachments, legacy upgrade recovery,
  missing/not-a-repo status handling

* feat: clarify session worktree targets

- session-worktree-contract: extend buildSessionTargetOptions to accept
  pendingBootstrapDirectory and mark pending worktrees with pending=true;
  extend SessionTargetOption to include optional pending flag
- ChatInput: replace manual worktree branch options construction with
  buildSessionTargetOptions; add  prefix for pending bootstrap worktrees
- Add test for pending bootstrap worktree distinction

* feat: show worktree-backed session state

- Header: read worktree attachment from authoritative session-worktree-store
  and render needs-attention/degraded/missing badge with alert icon next to
  current session info when session has degraded/missing/invalid state
- GitView: show 'Worktree features are unavailable' message when session has
  missing worktree status and open-without-worktree-features repair action

* feat: enforce safe mutations for attached worktrees

- session-worktree-contract: add getMutationBlockingReasons helper that returns
  blocking reasons (missing/invalid/attention state) for high-risk mutations
- GitView: gate handleCheckoutBranch, handleCreateBranch, and handleRenameBranch
  with getMutationBlockingReasons; block with explicit toast message when
  worktree is missing, invalid, or has an in-progress git operation
- session-worktree-contract.test: add 7 tests covering mutation blocking for
  missing/invalid/attention states (merge/rebase/cherry-pick)

* feat: implement session worktree isolation

This adds a shared session↔worktree contract that makes session switching
worktree-backed. Sessions attached to different worktrees keep stable branch
context without shared-directory auto-checkout.

Commits:
- feat: add session-worktree contract types and canonicalizeWorktreeState API
- feat: canonicalize worktree metadata producers
- feat: route sessions through authoritative worktree attachments
- feat: clarify session worktree targets
- feat: show worktree-backed session state
- feat: enforce safe mutations for attached worktrees

* feat: make authoritative attachment first-priority source for session directory resolution

Phase A: resolveSessionDirectory, getDirectoryForSession, hooks read
authoritative attachment before falling back to worktreeMetadata.

Phase B: createSession canonicalizes and writes attachment on creation;
setCurrentSession recovers legacy/missing attachments via async
canonicalization.

* feat: make authoritative attachment the primary branch source in Header/GitView

Phase C: Header branch label and GitView project root now read from
authoritative SessionWorktreeAttachment first, falling back to live git
and legacy sources only when attachment is absent, degraded, or legacy.

Adds getAttachmentBranchLabel() helper with 7 tests.

* feat: add runtime parity for validateWorktreeDirectory and canonicalizeWorktreeState

Phase D: Web runtime API, VS Code bridge, and VS Code gitService now
expose validateWorktreeDirectory and canonicalizeWorktreeState, matching
the server-side implementations. All three runtimes (web, desktop, VS Code)
can now delegate worktree canonicalization without HTTP fallback.

* feat: add dirty-tree blocking to mutation safety gates

getMutationBlockingReasons now accepts an optional gitStatus param
and blocks branch mutations when the tree has uncommitted changes.
GitView passes live status to all three blocking call sites.
5 new tests covering dirty, clean, null, combined, and no-file-count cases.

* refactor: revert branch label to live-git-first, remove getAttachmentBranchLabel

Live git is the correct source for branch labels in all scenarios:
dedicated worktree sessions have identical live/attachment branches,
and shared-directory sessions must show the real current branch.

Attachment remains authoritative for worktreeRoot, cwd, degraded/
missing/repair status, and mutation blocking.

* chore: remove session worktree isolation plan doc

* refactor: simplify session worktree isolation implementation

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-04-16 20:13:59 +03:00
Bohdan Triapitsyn 16ec1f605e fix(chat): show blocking requests in sub-session threads too 2026-04-16 19:16:32 +03:00
jwcrystalandBohdan Triapitsyn bb1d522838 fix(task): prevent subagent silent failures in session resolution and polling lifecycle (#903)
* fix(task): prevent subagent silent failures in session resolution and polling lifecycle

Two failure points fixed:

1. Fallback session resolution window too narrow (3s):
   - resolveFallbackTaskSessionId now accepts hasRetried boolean
   - First attempt uses 3s window (avoids binding wrong sessions)
   - Subsequent attempts widen to 8s (handles late-appearing child sessions)
   - Uses useState + useEffect instead of side effects in Zustand selector

2. Polling stops before child results are captured:
   - When child session goes idle before parent sees it active, polling
     would stop without fetching results
   - Added final-fetch-before-stop: a one-shot delayed fetch that runs
     after the settle grace period, ensuring child results are captured
   - Uses taskFinalFetchDoneRef to guarantee exactly one final fetch
   - Preserves existing happy path (active child → normal settle timer)

* fix(task): serialize final fetch after polling stops

Move the subagent final-fetch into a dedicated effect that runs only after
polling has stopped, avoiding races between polling writes and final-fetch
writes to the child sync store.

Also retry safely on final-fetch failure by reopening polling instead of
marking the final fetch as done before the request succeeds.

* feat(task): distinguish child session errors from normal idle

When a subagent terminates with an error, abort, timeout, or failure,
the parent session could not tell it apart from a normal completion.

Changes:
- event-reducer.ts: session.error now stores { type: 'error' } instead of
  { type: 'idle' }, so consumers can distinguish failed from completed sessions
- useSessionActivity.ts: add 'error' phase to SessionActivityPhase and
  isError flag to SessionActivityResult; error phase is non-active (like idle)
  but distinguishable via isError
- ToolPart.tsx: pass childSessionError to TaskToolSummary and show
  'Subagent session ended with an error.' instead of the generic
  'No subagent session id on task metadata.' when the child errored

Other consumers of session_status that only check 'busy'/'idle' are
unaffected — 'error' falls through to existing idle-like behavior.

* Revert "feat(task): distinguish child session errors from normal idle"

This reverts commit b3cc749bde16ed8fc55e4f304dcc455484335fba.

* fix(task): delay fallback retry window widening

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-04-14 20:17:52 +03:00
jwcrystalandBohdan Triapitsyn 5584537da5 fix: question tool content disappears after refresh (#879) (#909)
* fix: show question content in ToolPart instead of 'Awaiting response...' after refresh

Previously, when the question tool was pending/running or completed
without parseable output, the ToolPart fell through to a generic
'Awaiting response...' message. After a page refresh or app restart,
this made questions appear empty even though the tool state still
contained the question input data.

Now the ToolPart reads question text, headers, and options from the
tool state's input field, ensuring question content persists across
refreshes regardless of QuestionCard store availability.

Fixes #879

* fix: restore QuestionCard after refresh and pause working status during active questions

Two fixes for question tool UX:

1. ChatContainer: sessionIsWorking now returns false when there are
   active questions (same as it already did for permissions). This
   prevents the status row from showing 'Asking question...' and
   instead shows the QuestionCard.

2. sync-context: resyncDirectoryAfterReconnect now re-fetches
   pending questions via listPendingQuestions(). Previously only
   sessions and messages were re-fetched on SSE reconnect, so
   questions asked during disconnection were lost, causing
   QuestionCard to disappear after page refresh.

Refs #879

* fix: hide assistant working status while questions are pending

The assistant status hook only special-cased pending permissions, so
question tools still surfaced 'Asking question...' after refresh even
when the UI was already waiting on a QuestionCard response.

Treat pending questions like other blocking requests by clearing the
working indicator until the user answers.

Refs #879

* fix: merge question/permission stores instead of full replace on bootstrap and reconnect

The root cause of QuestionCard disappearing after refresh was a race
condition between SSE events and HTTP bootstrap. Bootstrap and reconnect
both did full replacement of state.question, wiping SSE-delivered data
that arrived between the HTTP call initiation and response arrival.

Changes:
- bootstrap.ts: question and permission stores now use merge semantics.
  Only sessions present in the API response are overwritten. Sessions
  absent from the response are left untouched (they may hold SSE data).
- sync-context.tsx: reconnect question resync uses the same merge pattern.
  No longer clears question entries for sessions not in the API response.
- bootstrap.ts: sdk.question.list() now passes directory parameter to
  scope the query correctly.

This ensures SSE-delivered question data survives the bootstrap window,
while still allowing the API response to be authoritative for sessions
it covers.

Refs #879

* fix: prune stale pending requests after reconnect

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-04-14 20:02:07 +03:00
Bohdan Triapitsyn 01ca471776 fix: render JSON code block quotes correctly 2026-04-14 19:40:36 +03:00
Alexander BusseandAlexander Busse 055b6f6af0 feat(tts): add OpenAI-compatible custom server TTS provider with configurable model, pitch, and volume (#859)
Co-authored-by: Alexander Busse <alex@ableph.net>
2026-04-12 10:33:15 +03:00
Bohdan Triapitsyn 844052e599 fix: restore desktop startup and align tool previews with SDK updates
Add reflect-metadata bootstrap so desktop sidecar no longer crashes on startup.
Update SDK v1.4 compatibility for model variant and diff payload handling.
Unify write/edit/apply patch expanded previews and hide write success output noise.
2026-04-12 00:40:49 +03:00
Gyumin Lee e6ac6badde fix: restore variant restoration for OpenCode 1.4.0 (#871)
OpenCode 1.4.0 moved `UserMessage.variant` from the top-level to
`UserMessage.model.variant`. OpenChamber still read the legacy location,
so variant selection silently stopped being restored on sessions served
by OpenCode 1.4.0+.

Read `model.variant` first and fall back to the legacy top-level field
so both pre-1.4 and 1.4+ OpenCode servers keep working.
2026-04-11 23:50:13 +03:00
jwcrystal b91a72c74b fix(chat): replace hover bridge with padding to unblock desktop interactions (#885)
* fix(chat): replace hover bridge with padding to unblock desktop interactions

PR #826 removed pointer-events-none from the hover bridge div to fix
short user message revert button hover, but the transparent 44px
full-width bridge blocked all interactions (clicks, text selection)
with messages below it on Tauri desktop where the rendering difference
made the overlay consume pointer events across the entire message area.

Replacing the bridge div approach with pb-12 padding on the message
bubble container (max-w-[85%]) when sticky inline hover is active.
This extends the hover hit area downward within the bubble's own
padding, maintaining continuous hover path from bubble to action
buttons without any overlay that could block sibling elements.

The padding approach works because:
- The 48px bottom padding extends max-w-[85%]'s hover area to cover
  the gap between bubble bottom and the absolute-positioned buttons
- Hovering the padding counts as hovering group/user-shell (parent)
- No absolute-positioned invisible layer means nothing blocks the
  next message's interactive content

* fix(chat): reduce hover padding from pb-12 to pb-5 for tighter spacing
2026-04-11 23:27:47 +03:00
jwcrystal 4fd1d68eb9 fix(chat): allow revert button hover on short user messages (#826) 2026-04-08 10:44:17 +03:00
Bohdan Triapitsyn 46d166e205 fix: drop stale chat memo boundaries
Remove remaining chat row and body memo comparators that were still keeping finished background session responses blank or stale in the UI.
2026-04-07 21:48:56 +03:00
Bohdan Triapitsyn 952132a08d fix: remove desktop translucency to reduce macOS compositing cost 2026-04-07 21:46:38 +03:00
Bohdan Triapitsyn 605e4bf42c fix: stop stale chat renders after session switches
Roll back aggressive chat reuse paths that froze message parts, tool state, and completed assistant bodies when sessions were inactive or backgrounded.
2026-04-07 20:33:55 +03:00
Bohdan Triapitsyn db19f83f46 fix: restore remote OpenCode providers and startup errors
- Fix OpenChamber proxying to the correct OpenCode host for remote VPS setups
- Show a clear empty-state error when OpenCode is not reachable
- Harden session event routing for early or mismatched directory events
2026-04-07 01:17:12 +03:00
Bohdan Triapitsyn 8de1884f5c refactor: remove plan polling, add message-driven detection via usePlanDetection hook 2026-04-06 20:44:13 +03:00
Bohdan Triapitsyn a516650f96 fix: stabilize chat auto-scroll and bottom resume
- Unify send and session resumes around the latest chat tail
- Keep smooth follow active during assistant message growth
Remove staged chat rendering from the main scroll path
2026-04-06 20:18:20 +03:00
Bohdan Triapitsyn 9254ec0783 fix desktop notifications and chat scroll stability 2026-04-06 17:36:08 +03:00
Bohdan Triapitsyn e42471ee7b chore: update workspace dependencies and chat behavior
- Adjust package metadata and lockfiles across the workspace
- Refine chat sidebar and auto-scroll behavior in the UI
- Update PWA install handling alongside runtime package changes
2026-04-06 13:04:36 +03:00
Bohdan Triapitsyn 4db1e6baad perf: reduce active-turn chat rerenders during streaming
- Keep older assistant messages in the active turn stable while new content streams
- Prevent existing tool rows from rerendering when new tool activity is appended
- Tighten message and tool memo comparisons to isolate render work to changed rows
2026-04-06 00:43:19 +03:00
Bohdan Triapitsyn 4a3b7ec5c9 fix: restore smooth chat auto-scroll and live compaction updates
- Keep assistant auto-scroll smooth during active responses without periodic snaps
- Restore live `/compact` rendering and streamed compaction summaries without refresh
- Preserve global event handling while routing session and message updates efficiently
2026-04-05 23:01:12 +03:00
Bohdan Triapitsyn f2f57ca281 fix: restore live compaction updates in chat
- Show `/compact` command and streamed compaction summary live without refresh
- Handle versioned sync event types so message and part updates are processed
- Route session/message events via indexed lookup to avoid hot-path store scans
2026-04-05 21:22:17 +03:00
Bohdan Triapitsyn dfc61d7671 refactor: replace chat markdown renderer
- Replace Streamdown-based chat markdown rendering with the new renderer path
- Preserve OpenChamber table, code block, and mermaid presentation
- Remove leftover Streamdown dependencies and compatibility hooks
2026-04-05 19:24:23 +03:00
Bohdan Triapitsyn 3bf9947388 perf: reduce status row streaming churn
Replace live assistant-part status subscriptions with coarse session phase, retry, permission, and abort state so the composing row no longer rerenders on every text delta.
2026-04-05 17:29:14 +03:00
Bohdan Triapitsyn c88e68e5f7 perf: reduce chat streaming rerenders
- Keep historical chat messages stable during streaming
- Isolate active stream state to the current message path
- Reduce chat container churn from sync message updates
2026-04-05 16:56:05 +03:00
Bohdan Triapitsyn e56f2f99cf perf: freeze detached chat history updates
Stop historical chat view from waking on live tail deltas by suspending detached part updates, narrowing scroll manager dependencies, and hardening sync-context HMR behavior during dev.
2026-04-05 15:58:06 +03:00
Bohdan Triapitsyn 4663abd6f3 refactor: isolate chat hot paths and lazy server watchers
Split static history from live tail, stabilize chat data identities, and reduce scroll-shell churn so old viewport content stops waking on stream deltas. Also defer watcher startup and health polling so idle runtime work better matches actual usage.
2026-04-05 15:36:11 +03:00
Iuliia Ivashko fc44465c00 fix(chat): render LSP diagnostics in tool output (#837) 2026-04-04 11:15:32 +03:00
Bohdan Triapitsyn 8587db89b1 perf: reduce UI render fanout and scroll jitter
- Cut broad render fanout across the app by replacing shared-store whole-object subscriptions with leaf selectors, memoizing hot chrome boundaries, and isolating disabled global providers from live session/message state. This keeps header controls, composer toolbars, side panels, and other non-hot UI surfaces from repainting on every assistant update or keystroke.

- Rework sidebar session ordering so recent, project groups, and worktree groups derive from one ordering source while avoiding streaming-time thrash. The sidebar now uses a stabilized session snapshot, preserves structural identity for unchanged rows, reads live row status/details per session, and applies a one-shot sort bump on idle->busy instead of continuously resorting during activity.

- Fix chat/input scroll instability by separating viewport-resize handling from message-growth handling, disabling conflicting native scroll anchoring, and stopping textarea autosize from collapsing on every growth keystroke. This removes the multiline typing jiggle during streaming and reduces unnecessary composer rerenders.

- Also gate voice context wiring behind voice-mode enablement and codify the learned render/scroll/order anti-patterns in AGENTS.md so future changes avoid the same classes of regressions.
2026-04-04 02:19:55 +03:00
Bohdan Triapitsyn d982171689 refactor: centralize git and pr store refresh 2026-04-03 19:47:01 +03:00
Bohdan Triapitsyn 246464a325 perf: remove animated logo from idle and loading surfaces 2026-04-03 16:44:31 +03:00
Bohdan Triapitsyn 5045d21821 perf: reduce idle desktop load by gating plan-mode checks
- Add startup feature flag for plan mode from OPENCODE_EXPERIMENTAL* env vars.
- Stop recurring app health polling and keep a one-time startup check.
- Skip plan-mode synthetic parsing and plan tab/file work when flag is off.
2026-04-03 13:59:10 +03:00
Bohdan Triapitsyn a36b11d54e fix: limit PWA input spacing behavior to mobile
- Prevent desktop chat input from inheriting mobile bottom safe-area gap
- Apply chat input safe-area classes only on mobile
- Scope standalone PWA safe-area and blur overlay CSS to mobile runtime
2026-04-03 12:45:00 +03:00
Bohdan Triapitsyn 9d78c48949 fix: keep selected session header details stable
- Prevent header flicker to Untitled during session refresh
- Resolve header session data from global sessions first
- Pass session directory hints on more session-switch paths
2026-04-03 12:38:03 +03:00
jwcrystalandBohdan Triapitsyn e63450ae2c fix: resync session state after SSE reconnect to prevent stuck subagent UI (#817)
* fix: resync session state after SSE reconnect to prevent stuck subagent UI

When a subagent completes while the page is in the background (common on
mobile PWA and desktop webview), the final SSE events are lost. The UI
then stays stuck on 'Waiting for subagent activity...' because:

- part.state.status never transitions to 'completed'
- session_status is never updated to 'idle'
- activeLatched remains true indefinitely

Fix:
- Add onReconnect callback to event pipeline, fired after SSE reconnect
- Add pageshow listener for bfcache restores (mobile PWA back-forward)
- On reconnect, re-fetch session list for directories with active sessions
- Pass explicit directory to useSessionActivity in ToolPart for subagents
  to ensure the correct child store is queried

Closes #810

* fix(chat): resolve pending subagent task binding before metadata arrives

* fix: restore subagent activity and tool visibility after reconnect

- Resyncs session status and child session data after SSE reconnect
- Ensures child task tool messages are read from the correct directory
- Prevents stale assistant fallback from keeping sessions stuck as active

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-04-03 00:29:49 +03:00
Nguyễn Ngô Thượng d68bec491c fix(chat): improve error message display with better styling and word-break (#767)
- Add error icon and colored background/border for error messages
- Add break-all and max-w-full to prevent long error text overflow
- CSS: word-break and overflow-wrap for inline code in error messages
2026-04-01 18:36:47 +03:00
Nguyễn Ngô ThượngandBohdan Triapitsyn 6180f388e8 feat(json): add interactive JSON tree viewer with collapse/expand and rainbow colors (#786)
- Add JsonTreeViewer component with collapse/expand for nested objects and arrays
- Add rainbow colors by depth level using CSS color-mix() with syntax theme tokens
- Add virtualization support (@tanstack/react-virtual) for large JSON files (>200 nodes)
- Add JsonTreeView wrapper with Expand All / Collapse All toolbar
- Integrate into FilesView: tree/text toggle button, JSON file detection
- Integrate into ToolPart: auto-detect JSON tool outputs, render as tree
- Integrate into ToolOutputDialog: JSON tree view in expanded dialog
- Add jsonTreeUtils.ts: parse, flatten, path utilities

No new dependencies - uses existing @tanstack/react-virtual.
Colors derived from existing syntax.* theme tokens - works across all themes.

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-04-01 17:30:28 +03:00
Dave Otero 1af2b9468f feat(chat): add arrow key navigation for thinking mode in model selector (#769)
* feat(chat): add arrow key navigation for thinking mode in model selector

Adds keyboard arrow key navigation for thinking mode selection within the model picker, enabling a fully keyboard-driven workflow for model and variant selection.

Changes:
- Model Selector: Added ←/→ arrow key handling to cycle thinking variants while picker is open
- Introduced transient state to track per-model variant selections during picker lifecycle
- Updated metadata display logic to show thinking mode only after adjustment with arrow keys
- Added contextual footer hints that appear only when highlighted model supports thinking variants
- Modified Enter key behavior to apply both selected model and pending thinking variant together
- Help Dialog: Added in-picker navigation shortcuts (↑↓ navigate, ←→ adjust thinking)
- Documentation: Updated CHANGELOG.md files with feature entry

Behavior:
- Navigate models with ↑↓, adjust thinking with ←→, press Enter to apply both
- Footer hints update dynamically based on highlighted model capabilities
- Thinking display persists only for models adjusted with arrow keys
- No-op for models without variants (clean, no feedback)

Testing:
- Type-check, lint, and build all pass
- Manual testing verified on dev server
2026-04-01 16:17:04 +03:00
Bohdan Triapitsyn 81c41388ac refactor: simplify file reference interactions by removing unused validation logic 2026-04-01 12:25:58 +03:00
YifanandBohdan Triapitsyn 14fc741cc9 feat(fs): add stat API for markdown file validation (#774)
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-04-01 10:18:05 +03:00
kalac2232and郭皓楠 b59040ff18 feat: escape HTML in user messages (#782)
- Add HTML escaping for user messages in Markdown mode
- Fix agent mention link rendering order issue
- Plain mode remains unchanged (uses React elements)

Tested:
- User messages: <div> now displays as &lt;div&gt;
- Agent mentions render correctly as clickable links in Markdown mode

Co-authored-by: 郭皓楠 <guohaonan@MacBook-Neo.local>
2026-04-01 09:49:58 +03:00