Commit Graph
100 Commits
Author SHA1 Message Date
Bohdan Triapitsyn 32df7e1997 fix: require question tool for clarifying prompts 2026-07-22 16:46:57 +03:00
Bohdan Triapitsyn 1ba3807df5 fix: hide duplicated bash permission pattern
Removes permission patterns already shown as the rendered bash command
Keeps distinct patterns visible in the permission card
Adds tests for the pattern filtering behavior
2026-07-22 16:40:42 +03:00
Bohdan Triapitsyn 63d37eecdf fix: map PR summaries to directory branch keys
Preserves a stable lookup key for PR status summaries
Displays PR indicators using directory and branch labels
Skips unmatched summary entries safely
2026-07-22 16:34:25 +03:00
Bohdan Triapitsyn de6fa36960 docs: update unreleased changelog entries 2026-07-22 16:22:28 +03:00
Bohdan Triapitsyn d654911925 feat: warn about unsupported attachment inputs
Compare normalized attachment MIME types with the selected model's declared input modalities and show a non-blocking warning for incompatible files.

Recheck newly added attachments, restored drafts, async metadata, and existing files after model changes while avoiding warnings when capability metadata is unavailable. Summarize affected filenames and localize the warning across every supported locale.

Add focused modality compatibility coverage, document the composer behavior, and keep model metadata subscriptions stable to prevent startup render loops.
2026-07-22 14:40:40 +03:00
Bohdan Triapitsyn fd0f6a6bac feat: support Office documents in chat attachments
Users can now attach Microsoft Office documents (.docx, .pptx, and .xlsx) and OpenDocument files (.odt, .odp, and .ods) from the shared web, desktop, mobile, and VS Code chat surfaces.

Document text is extracted locally and sent as a text/plain file part with the original filename, keeping the visible user message clean. Supported embedded PNG, JPEG, GIF, and WebP images are sent as separate image parts, with matching [filename] citations preserved near their source paragraph, slide object, spreadsheet cell anchor, or OpenDocument position. Presentation notes, spreadsheet values, headers, and footers are included where available.

Document expansion is metadata-validated and bounded against oversized entries, excessive uncompressed data, unsafe paths, invalid image signatures, attachment-name races, and dangling citations after truncation. Generated document parts are published to the composer atomically.

Add fflate for worker-backed ZIP extraction and narrowly allow blob workers in the VS Code webview CSP without permitting blob scripts. Include focused fixtures for every supported format, extraction limits, positional citations, collision recovery, atomic attachment state, and CSP behavior.
2026-07-22 13:11:42 +03:00
Bohdan Triapitsyn d7a93c5ec0 docs: add simplifier agent guidance 2026-07-22 12:06:58 +03:00
Bohdan Triapitsyn a68443c559 feat: expand chat attachment processing
Add picker and MIME support for more source-code, diff, notebook, structured-log, SVG, and Draw.io formats.

Convert Jupyter notebooks into readable text while omitting binary outputs, and sanitize HAR credentials, cookies, sensitive query parameters, and request/response bodies before files enter chat state.

Convert HEIC and HEIF images to JPEG up front, centralize attachment preparation in a focused module, and cover the new validation and transformation behavior with regression tests.
2026-07-22 11:54:03 +03:00
Bohdan Triapitsyn 55013ecb25 chore: update opencode sdk version 2026-07-22 11:44:47 +03:00
Bohdan Triapitsyn d3a2564cf6 feat: normalize and filter chat attachments
Attachment pickers now share an allowlist for supported file types
Local attachments are normalized to consistent MIME types before upload
VS Code file picker now respects extension filters and larger files are allowed
2026-07-22 11:33:22 +03:00
Bohdan Triapitsyn 6525c11042 fix(ui): align assistant message actions next to footer metadata 2026-07-22 11:31:00 +03:00
Bohdan Triapitsyn 090952dd94 fix(ui): unify tool attachment handling 2026-07-22 10:52:05 +03:00
Bohdan Triapitsyn 733bd37c37 feat: make AI review verdicts advisory
Removes the separate review check and relies on review labels/comments instead
Marks workflow/tooling failures with review:automation-failed
Updates review guidance to reflect the advisory verdict model
2026-07-22 10:33:25 +03:00
Bohdan Triapitsyn a62731bd6e feat: publish review check on reviewed HEAD
Adds a dedicated `review` check for the exact pull request HEAD
Keeps manual review commands reported separately from the default branch job
Documents the new review check behavior in contributing guidelines
2026-07-22 10:21:11 +03:00
Bohdan Triapitsyn 1c7cdf68e3 feat: add a macOS menu bar toggle for desktop
Adds a General settings switch to show or hide the macOS menu bar item.
Persists the new desktopMacMenuBarEnabled setting and passes tray state into Electron.
Disables tray sync and native tray setup when the menu bar is turned off.
2026-07-22 10:08:58 +03:00
Bohdan Triapitsyn 1c82198289 docs: clarify PR review and handoff requirements
Require reading .github/PULL_REQUEST_TEMPLATE.md alongside AGENTS.md and CONTRIBUTING.md
Tighten guidance for loading matching skills and task-required references before editing
Add PR handoff expectations for concrete evidence and rollback considerations
2026-07-21 23:55:57 +03:00
Bohdan Triapitsyn c4ac55a7dd feat: enforce pull request readiness reviews 2026-07-21 23:50:04 +03:00
Bohdan Triapitsyn 5211d66647 fix(ui): default project sorting to manual 2026-07-21 22:59:42 +03:00
Bohdan Triapitsyn ab97e00ff2 fix(ui): show active assistant model in status 2026-07-21 22:49:16 +03:00
Bohdan Triapitsyn d2efa707ff fix(vscode): detect workspace before runtime registration 2026-07-21 21:24:06 +03:00
Bohdan Triapitsyn a0caec0984 feat(desktop): support remote-only startup
Allow Desktop to skip its in-process OpenChamber server with OPENCHAMBER_SKIP_LOCAL_SERVER=1 while continuing to load the packaged UI shell.

Carry local runtime availability through the boot contract so unavailable or unconfigured remotes enter a remote-only chooser instead of offering broken local recovery actions. The chooser can select saved instances, add a server by URL, or redeem an OpenChamber pairing link over direct or E2EE relay transports.

Keep additional windows, Mini Chat, background startup, and unreachable-host recovery functional without a local origin. Render boot and recovery surfaces with the active theme background rather than exposing the native vibrancy backing.

Document the environment variable and cover serverless boot routing plus malformed pairing imports with focused tests.
2026-07-21 21:11:13 +03:00
Bohdan Triapitsyn 85400459e9 perf: overhaul session loading, caching, and runtime isolation (#2360)
Improve OpenChamber responsiveness under large session workloads while fixing
cache, synchronization, and persistence correctness across runtimes, projects,
directories, and worktrees.

- prioritize selected and visible sessions during bootstrap and defer
  non-critical enrichment work
- reduce redundant message loading, event processing, store publication, and
  hidden sidebar work
- prevent stale session and message requests from overwriting newer
  authoritative state
- preserve existing data when authoritative fetches fail instead of treating
  failures as successful empty responses
- scope session materialization, messages, drafts, queues, todos, pins,
  permissions, folders, tabs, Git state, and pull request data by runtime and
  directory identity
- harden runtime switching, reconnect, cleanup, mutation reconciliation, and
  persisted-state ordering
- preserve live subagent Task linkage when metadata arrives after an older
  message request or while streaming parts are suspended
- coalesce overlapping tail refreshes without losing newer refresh demand
- improve cold-session loading by moving deferrable work out of the critical
  bootstrap path
- isolate URL authentication, mobile credentials, native secrets, and other
  runtime-owned state across endpoint changes
- bound long-lived caches and remove avoidable allocations from event and
  rendering hot paths
- limit virtualization to archive collections where it improves rendering
  without disrupting active sidebar layout
- stabilize session folders, pin ordering, expanded state, and persisted
  sidebar behavior
- open skill files through the same secure editor and outside-workspace grant
  flow used by file navigation, including worktree sessions
- expand regression coverage for stale completions, runtime collisions,
  reconnect behavior, persistence races, authoritative empty results, and
  subagent refresh ordering
- document the updated synchronization, cache ownership, performance, and
  runtime-isolation invariants
2026-07-21 20:52:20 +03:00
Bohdan Triapitsyn 0e47b388d5 feat: scheduled task permission auto-accept and composer-style editor toggles 2026-07-20 23:07:01 +03:00
Bohdan Triapitsyn ac24d321f4 fix: let user message entry animation finish instead of snapping 2026-07-20 21:10:59 +03:00
Bohdan Triapitsyn 841c6639b8 chore: enforce LF line endings via gitattributes 2026-07-20 19:38:02 +03:00
Bohdan Triapitsyn 1e8979d2ef chore: normalize FilesView line endings to LF 2026-07-20 19:26:32 +03:00
Bohdan Triapitsyn d04712ce89 fix: stop stale file focus requests from stealing context panel selection 2026-07-20 19:25:12 +03:00
Bohdan Triapitsyn b7a5f44b7c fix: round meta typography line-heights to whole pixels to stop icon jitter 2026-07-20 17:23:23 +03:00
Bohdan Triapitsyn ca1cf9a3d1 feat: enable React Scan in web HMR dev mode
Adds a new `hmr-react-scan` web dev option in `oc-dev`
Turns on React Scan via `VITE_ENABLE_REACT_SCAN` for that mode
Documents Electron workspace trust so fresh installs fetch the runtime automatically
2026-07-20 12:54:46 +03:00
Bohdan Triapitsyn 70e7c37372 feat: tighten spacing between completed turns and user messages
- Assistant turn bottom padding pb-8 -> pb-2, desktop user message top
  padding pt-6 -> pt-4 (footer-to-bubble gap 60px -> 28px)
- Drop the recap note's -mt-6 that compensated the old large padding
2026-07-19 23:19:02 +03:00
Bohdan Triapitsyn 4be6854ba5 feat: show model in working indicator and fix streaming bottom jitter
- Working indicator shows provider icon and model name with the live
  status (e.g. 'Fable 5 is reading file'), localized via
  chat.statusRow.modelStatus
- Pin auto-follow to the exact fractional scroll maximum and re-pin on
  every passive follow instead of skipping within tolerance
- Round message text line-height to whole pixels so streamed content
  grows on the pixel grid; kills the 1px vertical jitter of
  bottom-anchored rows during streaming
2026-07-19 22:58:28 +03:00
Bohdan Triapitsyn 8e718ee58c feat: merge hidden-user turns and move message metadata to turn footer
- Remove assistant message headers; show provider icon, model, agent,
  thinking variant, duration and time in the turn footer (metadata left,
  hover-revealed actions right)
- Merge turns started by hidden user messages (subagent nudges) into the
  previous turn so Activity, footer and spacing stay continuous
- Treat compaction summary text (info.summary) as justification activity
  in sorted mode and skip it when picking the turn summary
- Interleave activity segments with standalone tool rows so Agent Task
  sits chronologically between activity sections
2026-07-19 22:58:22 +03:00
Bohdan Triapitsyn 1014be696a feat: localize cursor quota credential labels
Use dedicated access and refresh token labels for Cursor quota credentials.
Add localized token placeholder strings across supported settings languages.
2026-07-19 19:15:03 +03:00
Bohdan Triapitsyn 392ca48a7d fix: filter session context by current directory
Loads sessions from the active workspace directory
Fetches session messages using both session ID and directory
Resets expanded raw messages when the directory changes
2026-07-19 10:06:15 +03:00
Bohdan Triapitsyn 3fd6627196 feat: move sessions to new worktrees
Add a root-session action that creates a generated worktree from the session directory's current branch, transfers uncommitted changes, and moves the parent session plus its descendants through OpenCode's control-plane API.

Reuse existing project/worktree topology and quick-create behavior, keep the UI non-blocking, reconcile live and global session state across directories, and roll back partial moves and failed worktree creation safely.

Split worktree bootstrap readiness into directory-created, git-ready, and setup-ready phases across web and VS Code. Session moves wait for Git readiness while existing setup-aware flows continue waiting for full setup completion, and worktree removal is serialized with active bootstrap tasks.

Expose the move only for idle root sessions, show localized progress and explanatory tooltips in the sidebar, and keep pending/ready worktree metadata synchronized with authoritative session attachments to avoid stale setup indicators.

Add coverage for control-plane payloads, session-state migration, bootstrap phase ordering and compatibility, removal races, progress metadata, and fast-ready attachment races.
2026-07-19 00:00:31 +03:00
Bohdan Triapitsyn e9d93a6744 fix: recover worktree bootstrap from stale index.lock
Retries transient index.lock conflicts during worktree population
Removes unchanged stale locks automatically and continues bootstrap
Adds coverage for stale lock recovery
2026-07-18 22:06:25 +03:00
Bohdan Triapitsyn fee6a55bab fix: recover parent sessions during bootstrap
Preserves referenced parents when child sessions arrive before roots
Avoids publishing orphan-only bootstrap snapshots
Adds tests for bootstrap session merging
2026-07-18 21:52:11 +03:00
Bohdan Triapitsyn 3eb5ccd291 fix: apply ghostty patch on clean installs 2026-07-18 10:44:59 +03:00
Bohdan Triapitsyn 27e1775126 release v1.16.2 2026-07-18 10:05:06 +03:00
Bohdan Triapitsyn 61c87feeaf fix: clamp virtual scroll offset and update patch paths
Clamps TanStack virtualizer scroll offsets to valid bounds
Updates patched dependency references to bun-patches
Refreshes ghostty-web patch for invalid codepoint handling
2026-07-18 09:57:25 +03:00
Bohdan Triapitsyn 9c226a5bd4 fix: preserve chat input button overflow during draft toggle
Keeps the button visible state aligned with the draft panel animation
Moves overflow handling to the collapsed state only
2026-07-18 09:31:15 +03:00
Bohdan Triapitsyn 66f3969273 chore: bump @opencode-ai/sdk to 1.18.3
Updates the SDK dependency across web, UI, and VS Code packages.
Refreshes the lockfile and package versions to match the release.
Adds unreleased changelog notes for the current set of user-facing changes.
2026-07-18 01:19:15 +03:00
Bohdan Triapitsyn 72a60f93fd fix: add shadow to chat input elements on mobile for visual consistency
Fix alignment of settings radio options when no description is present
2026-07-18 00:56:32 +03:00
Bohdan Triapitsyn 2af5cd39d1 feat: add subtle shadows to chat input and sidebar
Added a box shadow to the chat input on desktop for depth
Added an inset shadow to the sidebar when open for visual separation
2026-07-18 00:18:28 +03:00
Bohdan Triapitsyn 1b402fcb67 feat: add auto-discover tooltip for project actions and changed icon
Shows a tooltip explaining auto-discover behavior
Updates auto-discover action icons to use scan-2
Adds translated tooltip text for supported locales
2026-07-18 00:06:30 +03:00
Bohdan Triapitsyn d4a8c4d2e1 feat(terminal): refactor runtime and add mobile workspace (#2280)
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
2026-07-17 13:17:21 +03:00
Bohdan Triapitsyn 0202e88eb4 fix(vscode): restore permission auto-accept parity
Add a VS Code-specific foreground permission responder while preserving the server-owned implementation for web, desktop, and mobile runtimes.

Persist the authoritative VS Code policy in extension global state and expose matching GET/PUT bridge routes. Broadcast policy updates to the sidebar, session editor panels, and agent manager so every active webview observes the same explicit per-session policy.

Resolve missing child-session lineage through OpenCode, honor nearest explicit ancestor overrides, deduplicate concurrent requests, retry transient replies, and reconcile pending permissions after enablement, bootstrap, and reconnect. Treat resolved requests as handled and route notification suppression through the same responder outcome.

Keep post-toggle reconciliation failures non-fatal after policy persistence and fail closed when lineage or replies cannot be confirmed. Document that auto-accept intentionally cannot run while every OpenChamber webview is closed or suspended.
2026-07-17 12:59:41 +03:00
Bohdan Triapitsyn 65ed6ba0e6 chore(icons): remove unused video chat icon
Regenerate the shared UI icon sprite from current source usages. The video-chat icon is no longer referenced anywhere under packages/ui/src, so the generator removes its stale SVG path from the generated asset.
2026-07-17 10:33:46 +03:00
Bohdan Triapitsyn 95e3e1cf2e fix(chat): preserve prompt when session creation fails
Keep the new-session draft open until the backend confirms that the session was created successfully. This prevents a failed request from closing the draft and discarding the user's creation context.

Restore the exact submitted composer text after a new-session send failure and persist it as the draft. Only restore when the composer is still empty or unchanged, so text entered while the request is pending is not overwritten.

Add regression coverage that simulates an offline session creation request and verifies that the draft remains open with its title intact.
2026-07-17 10:31:56 +03:00
Bohdan Triapitsyn bd68e303d4 feat(chat): preserve pinned messages across compaction
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.
2026-07-17 10:30:45 +03:00
Bohdan Triapitsyn 53d2dde87a fix: update check for desktop app 2026-07-15 14:02:12 +03:00
Bohdan Triapitsyn 00e002413d fix: resolve configured provider api keys from env and files
Supports {env:NAME} and {file:path} apiKey substitutions in provider config.
Keeps resolved credentials and file contents server-side.
Adds coverage for env and file-based credential resolution.
2026-07-15 12:55:30 +03:00
Bohdan Triapitsyn f45bb05b07 fix: set Google thinking config by Gemini model version
Uses thinkingLevel for Gemini 3 Flash models
Keeps older Gemini Flash models on thinkingBudget: 0
Updates docs and tests for the new Google request payload
2026-07-15 12:45:06 +03:00
Bohdan Triapitsyn 2b5e9a0221 feat: pass selected project when opening new session drafts
New drafts now receive the active project ID from sidebar project actions.
Project-group draft creation also forwards the selected project.
Aligns draft opening behavior across project and session selection flows.
2026-07-15 12:31:35 +03:00
Bohdan Triapitsyn e48a9397f1 feat: surface session goal evaluation model and add diagnostics
Shows the evaluation provider/model used for the latest successful goal audit in the UI.
Persists evaluation model metadata on session goals and covers it in tests.
Adds diagnostic logging for small-model calls and session-goal audit parsing.
2026-07-15 08:56:10 +03:00
Bohdan Triapitsyn 4eac90ad44 fix(chat): decouple input from editor font size
The editor font size setting controls code editors and should not also resize the chat composer. Code and conversational input have different readability and layout requirements, so forcing them to share one size is not appropriate.
2026-07-14 14:45:49 +03:00
Bohdan Triapitsyn d069b02931 chore: remove share opinion sidebar prompt
Delete the share opinion dialog and its sidebar trigger.
Remove the related toast and footer action wiring.
Clean up unused i18n entries in all supported languages.
2026-07-14 14:29:32 +03:00
Bohdan Triapitsyn c1069f08f6 fix(desktop): disable project deep links 2026-07-14 13:35:43 +03:00
Bohdan Triapitsyn fb98edda45 fix: gate session goal audits on live child activity
Re-checks authoritative session status after the quiet window
Skips auditing while a direct child session is still busy or retrying
Retries the quiet window when live status data is unavailable
2026-07-14 10:31:23 +03:00
Bohdan Triapitsyn 4c27f1753d fix(chat): anchor prompt navigator to last turn at chat bottom (#2213)
* fix(chat): anchor prompt navigator to last turn at chat bottom

The scroll spy activates the last turn whose top edge crossed the reading
line (100px below the container top). A final turn short enough to fit
below that line could never become active — sitting at the very bottom of
the chat kept the previous prompt highlighted on the navigator rail.
When the container is scrolled to the bottom (within 8px), force the last
turn active.

* feat(chat): enable prompt navigator by default

Users who already persisted an explicit preference keep their choice.
2026-07-14 10:24:31 +03:00
Bohdan Triapitsyn a9e99a28ea fix: resolve Android APK download URLs for mobile updates
Prefers a real APK asset when the update API points to an AAB
Keeps direct APK links from the API unchanged
Uses the GitHub releases API as a fallback for Android mobile downloads
2026-07-14 09:11:15 +03:00
Bohdan Triapitsyn 5a80638fba release v1.16.1 2026-07-14 01:51:00 +03:00
Bohdan Triapitsyn cd1816f63b fix(chat): make task session rendering authoritative
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.
2026-07-14 01:36:17 +03:00
Bohdan Triapitsyn a1badccddd feat(chat): prompt navigator list preview, prompt filtering, shell status fix (#2211)
* 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.
2026-07-14 00:59:07 +03:00
Bohdan Triapitsyn 68f1c1efe3 docs(agent): streamline guidance and skills
Keep always-on instructions concise and route specialized work through focused skills. Split large skills into progressive references and add dedicated change, desktop, sync, and performance guidance.
2026-07-14 00:45:44 +03:00
Bohdan Triapitsyn b36afbf5ee perf(sidebar): index session ownership and narrow live subscriptions
Replace repeated project-by-session directory matching across sidebar hooks with a shared ownership index that resolves each unique directory once and exposes direct project and folder-scope buckets.

Gate destructive folder reconciliation on authoritative session data and topology readiness, preserve last-known worktrees after discovery failures, and retain nested-project, VS Code, active/archive dedupe, and Windows drive-root semantics.

Narrow cross-directory subscriptions to session and status slices so streaming deltas no longer trigger global aggregation. Reuse a cached session ID index for permission lineage checks instead of rebuilding it on every session switch.

On the reported 15-project, 67-worktree, 14,561-session shape, ownership indexing averages 3.81 ms versus roughly 450 ms for the cache-only hotfix.

Validation: 28 targeted tests, UI type-check, UI lint, and dead-code analysis.
2026-07-13 23:18:12 +03:00
Bohdan Triapitsyn 799904f0f4 fix(chat): rework prompt navigator rail into sliding tape with hover preview (#2185)
* fix(chat): rework prompt navigator rail into sliding tape with hover preview

- Pin the active indicator to the target during programmatic scrolls so the
  scroll spy's intermediate reports don't drag it backwards mid-animation
- Replace the visibility-ratio active-turn picker with a stable reading-line
  rule (last turn whose top is above the line), dropping IntersectionObserver
- Replace the list panel with a Codex-style gutter: the whole strip is one
  hover/click target mapped to the nearest tick, with a per-prompt preview
  card that follows the cursor
- Cap the rail at a fixed window of ticks; hovering the edges carousels
  through the rest, with gradient masks hinting at more content
- Render ticks as a tape that glides to keep the active prompt centered,
  remounting on history prepend to avoid spurious slide animations
- Keep load-earlier as a compact button aligned over the tick column

* fix(chat): shrink navigator gutter when message column sits under it

On narrow windows the centered message column extends under the rail's
full-width invisible hover zone, which swallowed clicks on the right edge
of user bubbles — including the expand/collapse control. Measure the
column against the gutter and switch to a narrow hit zone when they
overlap.

* fix(sync): stop runaway history auto-load on sessions with empty assistant messages

An assistant message fetched with zero parts (e.g. a run aborted before any
output) was stored as absence — indistinguishable from parts that were never
fetched. getSessionMaterializationStatus therefore reported the session as
never renderable, so the ensure-renderable effects (ChatContainer,
ModelControls) retried syncSession forever; each retry refetched the whole
grown window and fired another background prepend, progressively loading the
entire history of large sessions on open.

Commit an explicit empty [] snapshot for assistant messages so fetched-empty
counts as renderable, while non-assistant messages keep the absent
representation and its no-op commit behavior.

Reproduced and verified headless against a real 857-message session: before,
20 message fetches escalating to limit=857; after, one initial page and a
single progressive-mount prepend.
2026-07-13 12:45:23 +03:00
Bohdan Triapitsyn 697b180532 feat: localize quota credentials saved toast
Uses the provider name in the success toast
Adds a shared quotaCredentials.saved message key
Updates translations across supported locales
2026-07-13 10:28:09 +03:00
Bohdan Triapitsyn 3362ebbfa3 release v1.16.0 2026-07-13 02:30:40 +03:00
Bohdan Triapitsyn 6ed2ef750b fix: hide craft-goal starter in VS Code runtime
Omits the craft-goal command from draft starters in VS Code
Prevents the starter from being resolved or pinnable in that runtime
Keeps non-VS Code behavior unchanged
2026-07-13 02:25:18 +03:00
Bohdan Triapitsyn 7253924eb8 feat: add VS Code Insiders to open-in-apps
Recognizes Visual Studio Code Insiders as an available app
Maps the new option to the correct macOS app name
2026-07-13 02:15:00 +03:00
Bohdan Triapitsyn fd66e8c112 fix(files): scope preview defaults to previewable files 2026-07-13 02:07:46 +03:00
Bohdan Triapitsyn 9dd389fe8e feat: group chat visual settings into labeled sections
Adds section headers and tooltip help for the goal settings area
Reorganizes chat settings into Session Assistance, Reasoning, Message Appearance, Tools & Files, and Composer groups
Adds localized labels and search entries for the new section headings
2026-07-13 01:33:19 +03:00
Bohdan Triapitsyn 9b645f0e53 perf: fast relay connect on mobile and desktop + connect splash + edit-safe instances
Relay connect used to serialize a dead LAN probe (up to 8s per stale address
on mobile, 2-4s on desktop) in front of the relay attempt, then paid a second
WebSocket connect + E2EE handshake because the probe tunnel was thrown away.

- mobile probeConnectionCandidates: race the relay probe against the direct
  chain with a 1.5s direct headstart; a live LAN still wins, a dead one no
  longer delays startup
- relay probes adopt their tunnel as the runtime tunnel (adoptRelayTunnel)
  instead of dialing a fresh one — applies to auto-connect, pairing redeem,
  password login, and the desktop host switcher's relay fallback
- relay probe drops the /health round-trip: the E2EE handshake already proves
  the server identity, /auth/session alone proves liveness and auth
- desktop restoreDesktopRelayRuntime: same headstart race; a late direct
  success hot-switches back (stable runtimeKey); startup probe now passes
  expectedServerId so a re-leased LAN address never sees the token
- launch splash shows 'Connecting to device: <label>' with animated dots
  under the (still centered) logo, translated in all locales
- editing a saved instance no longer rebuilds it from the URL field alone:
  the id is passed through, relay/https candidates are preserved, and a
  token-key change migrates the Keychain token instead of orphaning it
2026-07-13 01:29:35 +03:00
Bohdan Triapitsyn 08e4ce5b99 fix(chat): sync subagent prompting in context panel 2026-07-13 01:21:18 +03:00
Bohdan Triapitsyn 7e12a0dcef feat(chat): allow prompting subagent sessions 2026-07-13 01:06:44 +03:00
Bohdan Triapitsyn 04307e163b fix: single relay host per machine via cooperative claim lock
All local instances share the data dir and therefore the relay identity
(serverId), so concurrent relay hosts evicted each other at the relay worker
(4001: Control replaced) and paired devices landed on whichever local process
won last — often a stale dev server, surfacing as 'Unable to reach server'
and devices stuck on relay with 503s on newer endpoints.

- relay/host-lock.js: per-machine claim file (relay-host.lock, {pid}); stale
  claims from dead pids are ignored; unwritable data dir falls back to
  pre-lock behavior
- relay/service.js: start only when the claim is free or ours, otherwise
  'standby' with the holder pid in lastError; 30s watcher takes over when the
  claimant dies and stands down when another process claims; pairing-link
  creation and explicit /relay/enable force-claim (user intent wins)
- mobileConnections.ts: log candidate-refresh skip reasons and the refresh
  result instead of failing silently
2026-07-13 00:36:00 +03:00
Bohdan Triapitsyn e247343423 fix(quota): derive Codex windows from duration 2026-07-12 23:54:07 +03:00
Bohdan Triapitsyn afb368e11b feat: connection candidates refresh + relay identity hardening
Candidates refresh (server + mobile + desktop clients):
- GET /api/client-auth/connection/candidates returns the server's current
  LAN URLs, relay candidate, and serverId for already-paired devices
- /health and /api/version expose serverId so clients can verify a learned
  address belongs to the expected server before sending their bearer token
- mobile: refresh saved candidates over the live transport after every
  connect/wake, hot-switch relay->LAN when a fresh address is reachable;
  serverId gate on direct probes; token no longer sent to /health
- desktop: refresh stored host apiUrl after a relay connect and hot-switch
  back to direct; electron probe verifies serverId before authenticated fetch

Fixes found while debugging a dead pairing:
- settings: strict reader that throws on corrupt/unreadable file instead of
  returning {}; relay signing/encryption key generation is now gated on it,
  so a swallowed read failure can no longer mint a new server identity and
  orphan every paired device (loud log when a keypair IS generated)
- SessionAuthGate: bounded auto-retry for transient session-check failures
  (initial request racing the relay tunnel's first WS attempt, startup 5xx)
2026-07-12 18:09:54 +03:00
Bohdan Triapitsyn 22d5ad3814 fix: mobile goal UX — bottom-sheet dialog, keyboard-safe target button, capacitor safe-top for overlays
- the goal dialog renders as the shared MobileOverlayPanel bottom sheet
  on mobile instead of a centered dialog
- tapping the target button to ARM keeps the soft keyboard open (the next
  message is the objective; same guard as the attachment/mic buttons),
  while opening the manage sheet lets the keyboard close as usual
- capacitor: bottom-sheet overlays cap their height by the keyboard inset
  AND the top safe area — with the keyboard raised while typing inside a
  sheet, 100dvh does not shrink (native resize is off) and the panel could
  slide under the notch/status bar; applies to every MobileOverlayPanel
2026-07-12 17:01:40 +03:00
Bohdan Triapitsyn 8d956f5f9c feat: distill any oversized goal objective, not just plans
The distillation moved from PlanView into setSessionGoal — the shared
choke point for every goal source (composer, fork dialog, plans) — and
into the scheduled-tasks goal creation server-side. Any objective over
5000 chars is distilled into completion criteria by the small model; on a
transient failure a head+tail excerpt keeps the intent (top) and the
acceptance criteria (bottom) with a trim marker, plus a toast. The
working agent always received the full prompt in chat — only the auditor
is bound by the limit.
2026-07-12 16:34:16 +03:00
Bohdan Triapitsyn 19b2a3d0d3 feat: distill oversized plan goals into audit criteria
Plan-goal objectives are capped at 5000 chars for the auditor while the
working agent reads the full plan from its file. Plans over the limit are
now distilled by the small model into completion criteria (end goals +
per-phase verification, no implementation steps), prefixed with a header
pointing back at the plan file so every continuation re-anchors on the
live source of truth. If distillation fails (transient small-model
hiccup), a head+tail excerpt keeps the plan's intent (top) and acceptance
criteria (bottom) with a trim marker between — sacrificing the
implementation middle the agent reads from the file anyway — and a toast
tells the user the objective is degraded.
2026-07-12 16:28:48 +03:00
Bohdan Triapitsyn b09614fd68 refactor(quota): secure managed provider credentials (#2160)
- add shared owner-only credential storage for OpenCode Go, Ollama Cloud, and Cursor
- validate credentials before atomic writes using 0700 directories and 0600 files
- replace provider-specific credential routes with an allowlisted lifecycle API
- stop automatically reading Ollama's legacy cookie file
- stop reading or modifying Cursor's database during regular quota requests
- add explicit one-time Cursor credential import without mutating Cursor storage
- persist refreshed Cursor credentials only in OpenChamber-managed storage
- add Ollama Cloud and Cursor credential controls to provider settings
- preserve OpenCode Go tracking through the shared credential flow
- add VS Code credential management and Cursor quota parity
- reject authentication redirects, enforce request timeouts, and fail on unparseable usage pages
- mask stored secrets in API responses and extend quota security coverage
- update quota provider documentation
2026-07-12 16:21:38 +03:00
Bohdan Triapitsyn 3b92d97795 refactor: simplify sidebar project sorting
Removes recent-project grouping from the sidebar project list
Keeps project ordering based on manual and default sort rules only
Reduces memoized session-derived state in the sidebar
2026-07-12 15:25:07 +03:00
Bohdan Triapitsyn 1c1456892a feat: add sort-desc icon for sidebar project sorting
Replaces the sidebar sort action icon with a dedicated descending sort glyph
Adds the new icon to the shared sprite set
2026-07-12 15:18:17 +03:00
Bohdan Triapitsyn d738d41574 feat: persist permission auto-accept on server (#2158)
Move per-session permission auto-accept policy ownership from the UI to the
OpenChamber server so enabled sessions continue running when clients disconnect
or the server restarts.

- persist explicit per-session policies in OpenChamber settings
- inherit the nearest explicit policy across subagent session hierarchies
- allow child sessions to opt out of an inherited parent policy
- immediately accept matching global and directory-scoped pending requests
- process future requests without requiring a connected UI client
- reconcile pending permissions after startup and event-stream reconnects
- deduplicate concurrent requests and retry transient reply failures
- synchronize policy updates across connected clients
- migrate existing browser-persisted policies to server storage
- suppress auto-accepted permission cards before they enter UI state
- show deduplicated permission toasts for inactive sessions
- preserve foreground-only permission handling in VS Code
- integrate directory-aware notification routing from main
- add coverage for persistence, inheritance, retries, reconciliation, pending
  requests, client hydration, and inactive-session toasts
2026-07-12 15:03:16 +03:00
Bohdan Triapitsyn 3d90eddcaf feat(quota): add OpenCode Go usage tracking (#2155)
* feat(quota): add OpenCode Go usage tracking

* fix(quota): align OpenCode Go VS Code parsing
2026-07-12 14:48:50 +03:00
Bohdan Triapitsyn b4f50e0a01 fix(notifications): handle subagents and session errors (#2156)
Use authoritative session.idle and session.error events for notifications
while retaining legacy message.updated handling for compatibility.

Classify sessions through targeted, directory-aware session lookups instead
of fetching the full session list. Cache confirmed root and parent session
relationships without treating failed lookups as root sessions.

Honor subagent completion settings and templates across the server-driven
web, desktop, and mobile paths, and bring the VS Code webview notification
policy to feature parity.

Use freshly synchronized VS Code settings, retry failed settings syncs,
extract session error messages, and deduplicate authoritative and legacy
completion and error events.
2026-07-12 14:47:57 +03:00
Bohdan Triapitsyn a0bdcae54c feat: add craft-goal session starter and command
Adds /craft-goal autocomplete and chat handling for starting a Goal crafting session.
Introduces new Magic Prompts content and localized labels/descriptions for Goal crafting.
Migrates desktop draft starters to include Craft a Goal once and persists the migration marker.
2026-07-12 10:58:58 +03:00
Bohdan Triapitsyn c9ac8676e7 feat: file-backed goal objectives + compaction accounting fixes
Compaction fixes (observed in a real long run):
- the summary message's zeroed tokens froze the goal counter at its
  pre-compaction value; segments now close with the previously displayed
  total as a continuity floor
- audits and continuations after a summary tail now take execution params
  (provider/model/agent/variant) from the newest non-summary assistant
  turn instead of inheriting agent 'compaction' and the summarize model

File-backed objectives:
- the objective text lives in <data-dir>/goals/<sessionId>.md, keyed by
  session id (one goal per session, a new goal overwrites the file);
  metadata carries only an objectiveFile flag so session.updated fanout
  stays light, and never a path — ids are pattern-validated before any
  filesystem access
- limit raised to 5000 chars, no snapshot field: the UI fetches content
  via PUT/GET/DELETE /api/goals/objective/:sessionId (behind the blanket
  /api auth gate), writes the file before stamping metadata, and falls
  back to an inline objective when the write fails
- the loop reads the file fresh on every tick, so objectives are
  live-editable mid-goal; a missing file falls back to the inline text
- scheduled goal tasks write the objective file server-side; VS Code
  degrades to the audit note (route unavailable there by design)
2026-07-12 02:49:56 +03:00
Bohdan Triapitsyn 2c4b40893c fix(sidebar): keep recent project ids referentially stable 2026-07-12 02:02:42 +03:00
Bohdan Triapitsyn bb45164ae8 feat: session goals - server-driven goal loop with independent small-model audit (#2148)
Arm the target button in the composer and the next prompt becomes a goal:
the server keeps the session working toward it (idle tick -> small-model
audit -> continuation) until the objective is verifiably complete, blocked,
or out of budget — even with the UI closed.

Server (packages/web/server/lib/session-goal):
- event-driven loop on the global SSE hub; goal state lives in
  session.metadata.openchamber.goal (merge-safe patches, stale-write guard
  by goal id), so it survives restarts and syncs to every client for free
- the small-model audit (objective + last assistant turn only, language
  pinned to the objective) is the sole termination authority; blocked needs
  3 consecutive verdicts, audit outages tolerate one unaudited continuation
  then stop the goal as resumable-blocked
- hard stops: optional token budget, auto-continuation cap (Resume grants a
  fresh allowance), turn errors; user abort pauses the goal instead of
  blocking it, and resuming over an aborted tail nudges immediately
- token accounting as a snapshot of the latest turn (input + cache.read +
  output), goal-relative via a creation baseline and segmented across
  compactions; a compaction summary skips the audit and continues
- continuations reuse the session's own provider/model/agent/variant

UI:
- three-mode target button (arm / disarm / manage dialog), informational
  goal strip with inline pause/resume and an Evaluating indicator, sidebar
  state glyph, objective length counter (2000-char server clamp),
  read-only completed goals
- goal entry points: composer (sessions and drafts), start-new-session-
  from-answer dialog, plan implement dialog (plan content becomes the
  objective), scheduled tasks (Run as goal + budget)
- Settings -> Chat -> Goal: feature toggle + default token budget with
  three-layer parity (web server, client persistence, VS Code bridge);
  VS Code renders goal state but hides the entry points (the loop runs in
  the web server only)

Notifications: per-turn "ready" notifications are suppressed while a goal
is active; settling sends one final notification (desktop, web-push, APNs
generic titles with the session name as body) honoring the completion
toggle. Error/question/permission notifications are untouched.

Docs: user guide (session-goals) in all 9 locales + sidebar entry,
scheduled-tasks cross-reference, server module DOCUMENTATION.md.
2026-07-12 01:23:22 +03:00
Bohdan Triapitsyn 82c039117a fix(queue): back off failed queued auto-sends 2026-07-12 01:12:58 +03:00
Bohdan Triapitsyn 72aaa166f7 fix(session): do not block draft creation on auto-accept 2026-07-12 00:54:46 +03:00
Bohdan Triapitsyn 0daad180a1 fix(sidebar): preserve pins after partial session loads 2026-07-12 00:51:36 +03:00
Bohdan Triapitsyn fb173067f5 fix(worktree): refresh changed discovery metadata 2026-07-12 00:49:28 +03:00
Bohdan Triapitsyn 711289a606 fix(chat): retain latest overlapping message data 2026-07-12 00:48:21 +03:00
Bohdan Triapitsyn f214af15fc fix(sidebar): avoid duplicate refresh loads 2026-07-12 00:47:22 +03:00
Bohdan Triapitsyn a8953ad6f9 fix(auth): reject spoofed local host headers 2026-07-12 00:46:41 +03:00
Bohdan Triapitsyn 4f65e01a63 fix(sync): defer incomplete assistant-only pages 2026-07-12 00:45:26 +03:00