Replace the legacy terminal flow with a shared authenticated WebSocket
runtime used across web, desktop, relay, and mobile surfaces.
- introduce the v3 terminal protocol with scoped attachments, snapshots,
ordered output, bounded replay history, reconnects, and explicit lifecycle
- harden PTY creation, restart, resize, close, force-kill, idle cleanup,
shell selection, login mode, environment sanitization, and appearance sync
- add runtime-aware terminal APIs with relay authentication and Electron parity
- add a fullscreen mobile terminal workspace with touch scrolling,
long-press selection, safe-area controls, quick keys, and Ctrl/Alt input
- add terminal selection attachments, preview detection, project actions,
shell settings, and localized UI
- harden Ghostty rendering, resize recovery, Unicode handling, block
characters, line height, and stale-row behavior
- remove the obsolete terminal SSE path and update reverse-proxy guidance
- expand terminal runtime, transport, input, selection, and store coverage
- avoid duplicate web builds when preparing mobile assets in root CI builds
Add pin and unpin actions for user and assistant text messages, with clear compaction-survival labels, localized tooltips, status-info active styling, and VS Code gating where the server runtime is unavailable.
Persist pinned message IDs, creation timestamps, and roles under the OpenChamber session metadata namespace using fresh-read merge updates so goal, review, and other metadata remain intact.
Introduce a server runtime that reacts to OpenCode's dedicated session.compacted event, fetches pinned messages by ID, extracts and chronologically orders their text parts, and injects them as hidden synthetic context through prompt_async. The restoration prompt tells the agent to use the context silently while work remains and limits idle summaries to one short paragraph.
Track the last handled compaction summary to avoid replay duplication, tolerate individually missing pinned messages, integrate runtime shutdown, document ownership and limitations, and cover metadata round trips plus compaction injection behavior with focused tests.
Use the Task part's state.metadata.sessionId as the only live identity contract for child sessions. Remove timestamp, status, and ordering heuristics that could misassociate concurrent subagents or repeatedly scan directory sessions while parts stream.
Extract Task metadata parsing and child-summary projection into a focused model with cached projections for unchanged message records. Preserve output and part-level metadata parsing only for legacy persisted records, and keep standalone Task rows visible when sorted activity groups are rendered.
Validated with focused Task and turn projection tests, UI type-check, lint, and dead-code analysis.
* feat(chat): prompt navigator list preview with prompt filtering
The hover preview is now an interactive scrolling mini-list of prompts:
rows render as bordered two-line cards, the highlighted row stays inside
a center dead zone and the list glides only near the window edges, wheel
steps the highlight, and the panel stays open when the pointer moves into
it so a click can be corrected inside the list.
Rail entries are filtered to real prompts: previews are built from
normalized user display parts (synthetic context stripped), fully
synthetic user messages are excluded, and shell-mode messages show their
extracted command via the shared shell bridge helpers.
* fix(chat): render shell command status transitions
The injected /shell text part carries live state in shellAction, which
the render-relevant part comparator ignored — a running→completed update
reached the store but never re-rendered the message row until the next
send. Compare shellAction command/output/status for text parts.
* fix(sync): stream shell bridge part updates while running
Streaming suspension keeps part updates out of the static message records
while an assistant message streams, relying on the live streaming-tail
path to render it. Shell-mode bridge messages are hidden from the
timeline and rendered inside the user row, so they have no live path —
suspension froze their output chunks and left the card without a Show
output action until the run finished. Exempt shell bridges (single bash
tool part parented to a synthetic shell-marker user message) from
suspension; their updates arrive at command-output pace, not delta pace.
* feat(chat): syntax-highlight shell command card
Render the shell-mode command and its output through the shared
WorkerHighlightedCode (Shiki) with bash grammar, matching the bash tool
part presentation, instead of plain pre blocks.
React error #31 (Objects are not valid as a React child) was thrown
intermittently when a task/subagent tool returned structured data
(e.g. { TODO: '...' }) in a field that the OpenCode SDK types as a
plain string. Pathological payloads would propagate into JSX children
without runtime validation, white-screening the chat until refresh.
This change adds a single `coerceToText` helper in toolRenderers.tsx
and applies it at every vulnerable JSX expression:
- ToolPart.tsx:1807,1975 {state.error} (typed string, can be object)
- ToolPart.tsx:1825 {q.question} (QuestionCard input cast)
- ToolPart.tsx:1830 {opt.label} (QuestionCard input cast)
- ToolPart.tsx:1848 task tool markdown output
- ToolPart.tsx:1898 ToolScrollableTextOutput entry
- toolRenderers.tsx {todo.content} x4 in renderTodoOutput
renderTodoOutput now also validates the parsed array at the boundary
(JSON.parse result is filtered to objects whose content and status are
runtime strings), so a single bad row no longer poisons the whole
tool output.
Tests: 12 new unit tests in
packages/ui/src/components/chat/message/parts/__tests__/issue-2011-react-error-31.test.ts
covering the {TODO}-key object path, circular references, and
non-string content/status on parsed todos.
Co-authored-by: bashrusakh <bashrusakh@users.noreply.github.com>
Tool JSON output now starts with a compact navigable summary view.
Expandable tool output includes quick open-file and diff actions for changed files.
Reasoning headers strip stray HTML comments, and navigation tools stay compact.
Normalizes bare ---/+++ headers and paths before rendering
Repairs loosely formatted hunk bodies for patch display
Recounts hunk ranges so diff headers stay accurate
Adds a Last turn scope to DiffView that renders OpenCode snapshot diffs from the latest user message summary without re-fetching git contents. The view hides Review in that mode and carries the selected diff scope through main and context-panel navigation.
Connects latest-turn changed-file chips in chat to the snapshot diff view on desktop and mobile, while keeping older turn chips static/read-only to avoid misleading affordances and extra subscriptions. Updates localized labels and empty states plus changelog.
Validation: bun run type-check (packages/ui); bun run lint (packages/ui).
Keeps the textarea reference available during mobile viewport adjustments
Ensures the composer scrolls back into view after keyboard interactions
Updates text selection menu dependencies to include the current session
Adds a server-side "small model" capability: direct, cheap LLM calls that
reuse the user's existing OpenCode provider logins — the mechanism OpenCode
uses internally for titles and summaries but does not expose through the
SDK or plugins. Zero new dependencies; plain fetch with per-provider wire
formats, credentials never leave the server.
Core (packages/web/server/lib/small-model):
- Resolution mirrors OpenCode's session scoping: explicit settings override
→ small_model from the OpenCode config → family scan within the session's
provider → the session's own model. The global provider scan only serves
callers without a session context, and background callers forbid it
entirely (restrictToPreferredProvider), so conversation content never
reaches a provider the user didn't pick — explicit choices excepted.
- Per-provider auth replicating OpenCode's plugin loaders: GitHub Copilot
(device token as bearer, no exchange), ChatGPT plan via the codex
Responses API (single-flight OAuth refresh written back to auth.json),
Anthropic messages, Google generateContent, generic OpenAI-compatible.
- OpenCode's free models (opencode/big-pickle, *-free) are never called
directly; unauthenticated providers are skipped by design.
- Prompt clamping to the model's catalog context limit; thinking disabled
where a wire switch exists (Z.AI/GLM, MiniMax-M3, Gemini Flash); robust
content parsing with a clear error when a thinking model spends its whol
budget on reasoning.
- Settings → Sessions gains a Small Model group: use-default checkbox plus
an override picker limited to authenticated providers, persisted with
web/desktop/VS Code sanitization parity.
Consumers:
- Session assist: a server-side watcher on the global SSE hub generates a
short recap and one suggested follow-up after a session idles quietly fo
a minute, stored on session metadata (openchamber.assist). Freshness is
keyed to the last assistant message id, so new activity invalidates the
payload everywhere with no extra writes. The chat shows the recap under
the last message after five quiet minutes and the suggestion as a
dismissible chip above the composer (tap fills the input, never sends).
Gated by a new Chat setting (default on) that is a hard generation
switch. Language is anchored to the conversation itself, with a
script-mismatch guard against model/backend language hallucination.
- TTS: a third input mode, summarized — long replies are condensed to
spoken prose before playback on any TTS engine.
- Git: commit-message and PR generation moved off the active chat session
onto the small model fed with real diffs and the commit list (bodies
included), with a session-transport fallback for free-model-only setups.
- Notes: Add to notes distills long selections into 1-3 dense sentences
preserving exact identifiers, with verbatim fallback on failure.
Fixes along the way:
- The global event watcher now starts unconditionally; it was gated behind
the desktop-notify env, leaving the server-side event hub dead in
packaged apps.
- OpenCode re-emits message.updated for old user messages after idle; the
watcher no longer mistakes those for new activity.
- Session metadata merges from a fresh read right before the PATCH, so
writes made during the generation window (suggestion dismissals, review
links) are preserved; the assist runtime stops during graceful shutdown.
- Migrate sidebar session groups, git changes panel, virtualized code
blocks, and JSON tree viewer from virtua to @tanstack/react-virtual;
virtua remains only inside the Pierre diff viewer integration
- Sidebar: preserve scroll position when virtualization enables
mid-session (enable only once the ancestor scroll element is resolved,
seed initial offset from its live scrollTop, render plain rows for the
single pre-paint frame); disable native scroll anchoring on the
sessions scroller; keep row spacing identical between plain and
virtualized modes; absolute row positioning so variable-height rows
cannot drift past the container
- Chat: expand tool/thinking blocks downward by only adjusting scroll
for rows growing above the viewport; raise the desktop history-load
lead to 1.5 viewports so prepends land above the visible area
- Git changes: compute the prefetch window from the first visible row,
skipping overscan rows above the viewport
- Sidebar rows: make the whole highlighted row area clickable, guarded
against double-firing from interactive children
Render a streaming Thinking block inline instead of inside a capped,
independently-scrollable max-height box (the cap now applies only to finished
thinking, for compact review). The nested scroll box was capturing the wheel and
auto-pinning to its own bottom, so the chat could not be scrolled while thinking
streamed. With it gone the chat's own auto-follow owns the scroll.
Two auto-follow refinements make that solid:
- Direction-aware bottom-zone re-engage: scrolling UP into the bottom spacer zone
no longer re-arms follow (which the next growth would yank back). Follow resumes
only when the user arrives at the bottom by scrolling down, is already
following, or is at the true bottom. Kills the dead-zone fight near the bottom.
- Animation guard: while a Thinking block COLLAPSE animation runs, transient
geometry / trailing async scroll events are treated as our own and never
trigger a false release. Genuine user gestures still release instantly.
Gate passive auto-follow on active (working/settling) state so idle layout
churn from virtualizer re-measurement no longer re-pins the viewport to the
bottom. Render default-open tool bodies synchronously on mount so the
virtualizer measures the real row height up front instead of growing a frame
later and lurching scroll past several messages.
* fix(chat): preserve tool duration across session switches
Fix#1636: ToolPart.tsx reset pinnedTime to empty on unmount/remount,
causing LiveDuration to not render on first paint. Now initializes
pinnedTime from server-provided time?.start/time?.end in the useState
initializer, eliminating the one-frame gap.
* fix(sync): preserve tool state.time in materialization merge
---------
Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
Reworks the chat and session-sidebar render paths to cut render cascades, memory
churn, and UI jank on large sessions and big session trees. Behavior is preserved;
the changes are about *when* and *how much* the UI re-renders.
## Chat streaming
- Freeze the streaming message's parts in the bulk turn projection during streaming,
and re-inject live parts only in an isolated tail leaf, so a ~60/sec delta stream
no longer re-runs the whole-session projection or re-renders unrelated rows.
session with referential reuse of unchanged turns.
- Memoize message rows with field-aware comparators instead of reference equality.
- Replace the manual child-session polling in the task tool with the live SSE
stream + a one-shot load, removing a fetch/settle state machine.
## History loading & scroll
- Load an initial page fast, then prepend one older page in the background so the
scroll container has headroom and "load older on scroll-up" fires before the user
hits the absolute top.
- Compensate scroll synchronously (in a layout effect, before paint) for prepends —
including background prepends that don't originate from a user scroll — so the
viewport stays stable instead of judder-correcting on the next frame.
## Markdown rendering
- Render markdown synchronously *styled* on first paint (paragraphs, lists, code
cards, tables, inline code) instead of raw escaped text; the async pass then only
upgrades syntax-highlight colors. Eliminates the flash of full-width raw text.
- Load KaTeX CSS eagerly with the main bundle instead of inside the lazy markdown
chunk, avoiding a late stylesheet injection on first render.
## Sidebar
- Hoist per-row recursive tree walks out of row comparators into per-group
precomputed sets/keys; batch live-session lookups into a single map; add a
group-level memo boundary.
- Isolate rename drafts so per-keystroke typing doesn't repaint the row tree.
## Sync layer
- Add a staleness guard so a slow message fetch can't repopulate a session the user
navigated away from.
- Throw on fetch failure for authoritative loaders so a transient blip can't read as
an empty server response.
## Cleanup
- Remove dead code (unused hooks, params, duplicated inline types) surfaced while
reworking the above.
## Known issue
- A rare, purely cosmetic first-paint width flash can still appear on large sessions;
it has no behavioral or data impact and is tracked for a follow-up runtime trace.
The Prism syntaxTheme prop is no longer read after code highlighting moved to
the Shiki worker. Remove the now-dead prop threading and its source.
- Drop syntaxTheme from interfaces, destructures, prop passes, and React.memo
comparators across ChatMessage, MessageBody, ProgressiveGroup, ToolPart,
TurnActivity, ToolOutputDialog, and ChatInput.
- Drop the unused _syntaxTheme param from renderWebSearchOutput.
- Remove the dead generateSyntaxTheme usages (ChatMessage memo, PlanView
unassigned memo) and delete the now-unimported syntaxThemeGenerator module.
Route all non-markdown code highlighting through the off-main-thread Shiki
worker, removing react-syntax-highlighter and prismjs entirely.
- Extend the worker with highlightLines: tokenize a whole block once and return
per-line inner HTML, so per-line layouts (diffs, gutters, virtualization) make
one worker call instead of one highlighter per line.
- Add shared WorkerHighlightedCode (whole-block) and useWorkerHighlightedLines
(per-line) primitives. Colors resolve via the --md-syntax-* CSS variables, so
theme changes never re-highlight.
- Migrate all 12 react-syntax-highlighter call sites: PermissionCard,
ToolPart, ContextSidebarTab, ToolOutputDialog (whole block) and
DiffPreview/WritePreview (per line).
- Migrate VirtualizedCodeBlock off prismjs to the worker, keeping virtua
virtualization; whole-block tokenization also restores cross-line syntax
context that per-line highlighting lost.
- Drop react-syntax-highlighter (+types) from ui and web, prismjs (+types) from
ui, and the orphaned create-element type shim.
Thread onShowPopup from MessageBody through AssistantTextPart into the
markdown renderer so clicking a rendered mermaid diagram in assistant
messages opens the existing pan/zoom fullscreen preview dialog.
- Bump mobile line-height on tool/reasoning rows from leading-4 to leading-5
so descenders (g, y, p) are no longer clipped by truncate overflow
- Show the tool icon (not the chevron) for collapsed expandable tools on
mobile, matching reasoning rows; chevron now appears only when expanded
Replace useDirectoryStore.currentDirectory with useEffectiveDirectory() in
both TaskToolSummary and ToolPartContent to align the directory key used for
ContextPanel tab storage/lookup. Previously ToolPart used the global project
root while ContextPanel resolved session/worktree-scoped directories via
useEffectiveDirectory(), causing a key mismatch that left the iframe blank
when opening sub-tasks from chat messages.
Agent @mentions in markdown use the primary accent instead of generic link color
Mentions render without external URL favicons
Markdown mode now matches plain text mention styling
* feat: add French locale runtime
Add French to OpenChamber's shared i18n runtime, dictionaries, and parity tests so the existing language picker can load a complete fr locale across shared UI surfaces.
* fix: localize shared UI formatting
Remove remaining shared UI locale hardcodings so dates, numbers, and first-party helper copy follow the active app locale instead of leaking English on French surfaces.
* feat: localize VS Code French surfaces
Localize VS Code bootstrap, native runtime messages, panel titles, and manifest contribution strings so French users get consistent first-party copy across the extension experience.
* fix: TASK-2026-05-30-008 correct French review findings
Fix broken French relative-time and weekday strings reported on PR #1482 and restore proper import order in quota utils without broadening scope.
* fix: TASK-2026-05-30-008 address final PR review comments
Capture the localized More Info label once in the VS Code CLI-missing flow and replace the remaining inline French-only utility strings with dictionary-driven copy plus required locale keys.
* fix: TASK-2026-05-30-008 normalize French glossary
Correct glossary-level French terminology on the live PR branch, keeping canonical technical terms like PR, worktree, stash, HEAD, Mermaid, Markdown, remote, and session while replacing misleading literal translations.
* fix: TASK-2026-05-30-008 refine French terminology pass
Clean up remaining glossary mistakes on the French PR branch, especially around Mermaid, Markdown, PR, worktree, stash, branch, remote, and commit terminology, while keeping behavior unchanged.
* fix: TASK-2026-05-30-008 clean remaining French false friends
Correct the SOCKS5 mistranslation and a final small set of obvious false-friend technical nouns on the French branch without changing behavior.
* fix: TASK-2026-05-30-008 correct French glossary terms
Replace remaining false-friend translations in the French UI dictionaries and normalize technical labels for the French PR branch.
* fix: TASK-2026-05-30-008 remove remaining French Mermaid false friend
Replace the last confirmed Sirène translation with Mermaid and re-run the requested blacklist and build verification on the PR branch.
* fix: TASK-2026-05-30-008 enforce French glossary policy
Keep skill/PR/worktree/remote terminology developer-credible in French and remove remaining machine-translated Git and settings copy.
* fix: TASK-2026-05-30-008 keep prompt terminology in French
Replace remaining technical invite translations with prompt wording across scheduled tasks, multi-run, prompt templates, and Magic Prompts.
* fix: TASK-2026-05-30-008 finalize French terminology cleanup
Polish remaining worktree/remote wording, remove visible metadata leakage, and correct final Git and settings labels on the French PR branch.
* fix: TASK-2026-05-30-008 polish final French strings
Correct the last aria-like artifacts and awkward worktree/remote/GitHub URL phrasing in the French dictionaries.
* fix: TASK-2026-05-30-008 normalize final French glossary framing
Tighten the last worktree/remote/checkout wording and fix remaining French grammar around canonical technical terms.
* fix: TASK-2026-05-30-008 align final developer glossary wording
Normalize the last French framing around canonical developer terms like worktree, remote, prompt, and checkout.
* fix: TASK-2026-05-30-008 harmonize final French sentence framing
Replace the last raw franglais around checkout, remote, worktree, and prompt-facing labels with more natural French framing while keeping the chosen technical terms.
* fix: TASK-2026-05-30-008 add compact relative date keys
Replace French-specific prefix stripping in compact session date labels with dedicated i18n keys across locale dictionaries, preserving existing compact label output while making French wording robust.
* docs: add French documentation
* docs: mention French locale folder
---------
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
* feat: add draw.io diagram editor integration
Embed draw.io editor via react-drawio (MIT, zero deps) for inline
editing of .drawio files. Changes auto-save to disk. Includes
inline editor in FilesView with Visual/Source toggle, dark mode
support, template picker for new files, and chat file attachment
integration.
* fix: debounce diagram autosave to prevent reload loop
* fix: ignore watcher-triggered xml prop changes to prevent reload loop
* fix: remove auto-save-to-disk, add manual save button for diagrams
Autosave writes triggered file watcher cascade that reloaded the
draw.io iframe and reset zoom. Replaced with explicit Save button
in the toolbar (floppy disk icon). Editor XML is stable on mount
and ignores watcher-triggered prop changes.
* fix: remove auto-save write from DiagramView, add save button
* fix: hide draw.io save/exit buttons in editor
* fix: also hide save-and-exit button
* fix: brighten save button styling, add saved confirmation
* fix: remove autoSaveStatus toggle on diagram save to prevent toolbar collapse
* fix: add local save confirmation state for diagram button
* fix: remount drawio iframe on theme change, persisting XML across mounts
* fix: clear persisted xml on mount to prevent leaking between files
* fix: initialize dark mode synchronously, preserve edits across theme remount
* fix: auto-focus drawio iframe on mount/theme-change for keyboard shortcuts
* fix: add diagram i18n keys to Traditional Chinese locale
* fix: restore upstream HMR host and LAN address support
* fix: load sub-agent sessions on bootstrap for sidebar visibility
Two-phase session load: first fetch root sessions (for accurate
sessionTotal), then fetch all sessions and include child sessions
(sub-agent delegations). This ensures sub-agent sessions appear
in the sidebar immediately instead of relying on the async global
session store.
* remove opencode-drawio from PR branch
* fix: atomic file writes to prevent concurrent read/write truncation
Three-layer defense against the O_TRUNC race:
1. Write side (server): replace direct writeFile with write-to-temp-
then-rename. fs.rename is atomic on POSIX.
2. Read side (server): retry up to 3 times with 50ms backoff when
readFile returns empty but stat reported non-zero size.
3. FilesView client: refuse to save empty draftContent when the
original fileContent was non-empty.
* fix(dev): clean up orphaned OpenCode processes on Ctrl+C
* fix: allow empty file saves, log warning instead of blocking
Replaces the hard block on saving empty content with a console.warn.
The atomic write + read retry on the server side handle the O_TRUNC
race properly. The previous guard caused a UX regression by silently
preventing users from clearing a file and saving.
* fix: remove time window from sub-agent fallback for live tasks
While a task tool is active, the fallback now matches any session
with the correct parentID regardless of creation time. This allows
late-appearing child sessions to be found when the OpenCode server
is slow or the SSE event pipeline is delayed. The time window is
still applied once the task tool has completed, as a final sanity
check.
* fix: three diagram editor bugs from Greptile review
1. stableXmlRef now resets when xml prop changes — switching
between .drawio files renders the correct content.
2. Focus effect only runs on mount, not on isDark changes —
theme toggle no longer steals keyboard focus 600ms later.
3. saveDiagram updates xml state after writing — dirty-check
guard works correctly for subsequent saves.
* fix: route session.created SSE events to correct directory
Three-layer fix for sub-agent sessions not appearing in sidebar and
inline chat:
1. protocol.js: parseSseEventEnvelope now extracts directory from
properties.info.directory (where session.created/updated events
carry it) in addition to properties.directory. WS frames relayed
to the browser now carry the real directory instead of 'global',
so child sessions routed to the correct directory store.
2. event-pipeline.ts: same fallback in resolveEventDirectory for
defense-in-depth when SSE events bypass the WS relay.
3. resolveFallbackTaskSessionId.ts: time window lower bound now
allows 2s grace before taskStartTime to accommodate server timing
jitter (child session creation timestamps consistently precede the
tool's recorded start by ~6-9ms), fixing the 'Open subtask'
button not rendering in OpenChamber's inline chat.
* fix: sub-agent sidebar visibility, file zeroing guard, inline badge fallback
- Sync watchdog: periodic child session discovery poll (every 15s) detects
sessions created by other OpenCode instances, triggers parent materialization
- protocol.js: parseSseEventEnvelope extracts directory from
properties.info.directory for session.created/updated events
- event-pipeline.ts: same fallback in resolveEventDirectory for defense-in-depth
- resolveFallbackTaskSessionId: don't require taskStartTime (cross-OpenCode);
pick most recent child when multiple idle candidates exist
- readTaskSessionIdFromOutput: parse <task id="ses_xxx"> format from output
- FilesView: reinstate empty-draft guard (block save when draftContent='' but
fileContent had content) to prevent file zeroing on tab switch
* Fix diagram autosave reload loop
* Highlight drawio files as XML
* Use diff-compatible highlighting for drawio files
* Restore drawio file icon mapping
* Stabilize drawio source preview toggle
---------
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
Compute review transfer state once per chat render
Hide transfer actions when linked review sessions are inactive
Remove session-list scans from individual message rows
Introduce a desktop/web-only /handoff-review flow that generates a handoff from the active implementation session, creates or reuses a separate review session in the same directory, and links the pair through hidden OpenChamber session metadata.
Add review flow orchestration, metadata helpers, magic prompts, localized command/action labels, session metadata create/update support, and assistant message transfer actions for sending reviewer feedback back to the implementer or implementation responses back to the reviewer.
Review sessions are ordinary sessions, not child sessions. The flow avoids exposing session IDs or routing metadata to agents, hides review controls on mobile and VS Code, hides unrelated assistant actions inside review sessions, cleans up stale metadata where possible, and uses the optimistic send path so cross-session sends scroll like normal composer messages.
Add shared time formatting helpers that apply the Appearance time format preference consistently. Update visible time labels across chat, quota usage, scheduled tasks, tunnels, context details, git views, PR metadata, and passkey settings to use the selected 12-hour, 24-hour, or automatic format. Leave date-only and non-UI formatting untouched so unrelated behavior does not change.
* feat: add dialog for "Start new session from this answer"
Replace the one-click fork action on assistant messages with a dialog
(ForkSessionDialog) that lets the user pick model, thinking level, and
agent, plus edit the instructions sent to the new session.
The instructions field is prefilled with the previous fixed fork prompt
and is mandatory. The composed message is now fully visible (no synthetic
preface): the user's instructions sit above a short fixed connective that
opens the assistant content. createSessionFromAssistantMessage takes the
chosen execution params instead of reading from config.
Also fix TodoSendDialog visuals: narrower vertical layout, model trigger
no longer stretches with centered text, and the agent/thinking dropdowns
portal to body so opening them no longer nudges the dialog height. Extract
the shared ThinkingPill into its own component.
* fix: address review feedback on fork session dialog
- Fix "bellow" -> "below" typo in the fork content preface (now user-visible
since the message is no longer synthetic)
- Reset ForkSessionDialog state only on open transition, reading the config
store snapshot via getState() so background store refreshes can't discard
in-progress instruction edits
Add a packaged-client runtime boundary so the shared UI can talk to local,
desktop, remote, and VS Code runtimes through the right transport instead of
assuming one same-origin web server.
Centralize OpenChamber-owned API access behind RuntimeAPIs, runtimeFetch, and
runtime URL helpers, while keeping official OpenCode traffic on the SDK path.
Support runtime switching, remote host selection, desktop client credentials,
and headless connection links for pairing packaged clients with remote
OpenChamber servers.
Harden the new auth model by moving long-lived client tokens out of browser
URLs, introducing short-lived scoped URL tokens for browser-owned transports,
restricting URL-token access to explicit readable/realtime routes, and making
client-token management session-scoped or self-scoped as appropriate.
Update browser-owned assets and preview proxy flows to work with the split
runtime model, including authenticated project icons, preview token propagation,
CSP-safe preview bridge injection, and preview proxy auth that survives
short-lived URL-token expiry.
Tighten Electron security boundaries for packaged clients by gating privileged
preload state to trusted origins and requiring explicit confirmation before
connect deep-links import or switch remote runtimes.
Also refresh agent guidance and project skills so future runtime/API, auth,
preview, UI, CLI, settings, locale, and drag-to-reorder work follows the new
architecture.
* fix: make upstream sync actions target the selected remote
Ensure fetch and pull actually honor upstream selection so fork maintenance works from the Git sidebar, and surface upstream branch status alongside the primary origin-tracking indicators.
* feat: add Windows Electron desktop foundation
* fix(electron): stabilize Windows desktop packaging
* fix(electron): stabilize Windows desktop chrome
Use native Windows titlebar behavior with an Alt-accessible hidden menu, and harden Windows dev command launching so the desktop app follows platform conventions.
* fix(electron): stabilize Windows dev startup
* fix(electron): clarify desktop artifact names
* fix(electron): harden Windows desktop release and launch
* fix(electron): address Windows release review
* fix(electron): point updater and release links to org repo
* Fix Windows settings persistence fallback
* Fix Windows Electron dev startup
* Add Windows Electron window controls
* Fix Windows Electron install and opencode launch
* fix: resolve git status for repositories without upstream
Fixes repository detection stuck on Checking repository
Handles git status when no upstream is configured
Adds regression coverage for git status loading
* Add Windows app menu button
* fix: preserve file editor line endings
* ci: add desktop release smoke workflow
---------
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
Safely falls back to raw patch text for invalid diffs
Protects individual tool parts from crashing the chat
Covers malformed apply_patch and edit diff cases