Commit Graph
324 Commits
Author SHA1 Message Date
Bohdan Triapitsyn bbc297202e fix: use opencode skills as source of truth 2026-05-17 14:51:25 +03:00
Erman HAVUÇandBohdan Triapitsyn e1977bbe63 feat(ui): collapsible thinking blocks with merged per-turn view and user toggle (#1273)
* feat: add collapsible reasoning traces with animated labels

* feat(ui): redesign reasoning blocks with merged collapsible Thought view

- Replace per-part reasoning blocks with a single merged block per turn
  (VSCode Copilot pattern), controlled by new `groupReasoningBlocks` store flag
- `ReasoningTimelineBlock` redesigned: chevron toggle, summary preview on
  collapsed header, 'Thinking'/'Justification' label when expanded, BusyDots
  while streaming, auto-scroll to bottom during live streaming
- Short texts (< 120 chars) render inline without a toggle
- Summary now strips markdown and truncates at a word boundary with ellipsis
- New `MergedReasoningPart` component merges all reasoning parts for a message
  into one block at the position of the first reasoning part
- `defaultExpanded` prop lets callers override initial expand state
- Remove `.thinking-dot` CSS animation (replaced by BusyDots component)
- Fix reasoning markdown font-size: use `--text-markdown` instead of `--text-meta`

* refactor(ui): scope working phrases inside useAssistantStatus and simplify reasoning status

- Move WORKING_PHRASES array and getRandomWorkingPhrase() inside the hook
  so they are no longer exported (were only consumed by ReasoningPart which
  no longer needs them)
- Change the 'reasoning' activity status text from a random working phrase
  to the deterministic string 'thinking' — matches the new UI label

* test(ui): expand ReasoningPart tests for new collapsible and summary behavior

- Update baseline test to use text long enough to trigger the collapsible
  path (short texts now render inline) and assert on the correct aria markup
- Add test for 'Justification' label when pre-expanded via defaultExpanded
- Add test for 'Thinking' label for the thinking variant when expanded
- Add test verifying summary is a word-boundary-truncated excerpt ending with
  an ellipsis character

* i18n: rename 'Reasoning Traces' to 'Thinking Blocks' and add thought key

- Rename settings label from 'Show Reasoning Traces' → 'Show Thinking Blocks'
  across all supported locales (en, es, ko, pl, pt-BR, uk, zh-CN)
- Add `chat.reasoningTrace.thought` key to all locales (used by merged
  reasoning block header in completed state)

* feat(ui): add collapsibleThinkingBlocks setting with full persistence wiring

- New boolean store field `collapsibleThinkingBlocks` (default true) with
  `setCollapsibleThinkingBlocks` action; persisted to localStorage
- Threaded through DesktopSettings, SettingsPayload (API types), desktop
  persistence (sanitize + apply), web appearance persistence, appearance
  auto-save watcher, and server-side settings-helpers sanitize/format
- Server defaults to true when the field is absent in formatSettingsResponse
- MessageBody reads the flag: false → render reasoning as plain AssistantTextPart;
  true → existing collapsible/merged block path

* feat(settings): expose Collapsible Reasoning Blocks toggle in visual settings

Add a checkbox under the 'Show Thinking Blocks' row (visible only when
showReasoningTraces is enabled) that toggles the collapsibleThinkingBlocks
preference. Follows the existing toggle pattern: div role=button, keyboard
handler for Enter/Space, Checkbox primitive, aria-pressed attribute.

* i18n: revert showReasoningTraces label rename and add collapsibleThinkingBlocks strings

- Revert 'Show Reasoning Traces' → 'Show Thinking Blocks' rename (the
  collapsibleThinkingBlocks toggle is now a separate control, so the parent
  label stays as 'Reasoning Traces' for clarity)
- Add `collapsibleThinkingBlocks` / `collapsibleThinkingBlocksAria` strings
  across all seven supported locales (en, es, ko, pl, pt-BR, uk, zh-CN)

* test(server): add settings-helpers coverage for collapsibleThinkingBlocks

- Verify sanitizeSettingsUpdate accepts boolean true/false and rejects
  non-boolean values (string, number)
- Verify formatSettingsResponse forwards the value correctly for both true
  and false, and defaults to true when the field is absent

* fix(ui): respect defaultExpanded prop and remove dead alwaysShowActions from ReasoningTimelineBlock

The useEffect on [isStreaming] was firing on mount and immediately calling
setIsExpanded(false) (since isStreaming is false for completed blocks),
overriding any defaultExpanded={true} passed by callers. The fix uses a
prevIsStreamingRef so the effect only collapses the block on a true→false
transition and is a no-op on initial mount.

Also removes alwaysShowActions from ReasoningTimelineBlockProps — the new
header design always shows the chevron, making the prop obsolete. The prop
was already absent from the component destructuring (a dead type entry) and
was silently ignored at runtime. Removed it from ReasoningPartProps,
MergedReasoningPartProps, and the two call-sites in MessageBody as well.

* chore: remove unused reasoningpresentation module and test

* fix(ui): polish collapsible reasoning block UI

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-16 17:20:16 +03:00
Bohdan Triapitsyn b79a40adce fix: proxy absolute same-origin preview requests
Fixes Preview backend calls built from window.location.origin
Routes same-origin fetch, XHR, EventSource, and WebSocket requests through the preview proxy
Keeps local full-stack apps working inside the Preview panel
2026-05-15 14:44:35 +03:00
Bohdan Triapitsyn 34fde831eb fix: make daemon startup ready handoff reliable
Wait longer for slow daemon startup
Fail cleanly when ready handoff does not complete
Avoid orphaned daemon processes after startup timeout
2026-05-14 15:00:25 +03:00
Bohdan Triapitsyn a12be061e3 feat: add OpenCode update and in-app Browser features 2026-05-14 14:45:04 +03:00
Bohdan Triapitsyn ef85c63336 fix: voice input in Electron - local Whisper STT + network error handling
- Add local Whisper STT via Transformers.js with Web Worker (no UI freeze)
- Default sttProvider to 'local' in Electron (browser STT unavailable)
- Fix infinite toast loop: stop auto-restart on network errors
- Add retry limit with exponential backoff for transient STT errors
- Append voice transcript to input field (append-inline), not replace
- Add model catalog with download/load button in Voice Settings
2026-05-14 01:19:52 +03:00
Bohdan Triapitsyn 7fb5ad0f48 fix: check window focus before summarization to avoid wasted Zen API calls
When notificationMode is 'hidden-only', the isWindowFocused check now
happens before summarization and template resolution, not after. This
prevents costly Zen API calls for notifications that would be skipped
anyway, and eliminates stale notifications arriving after the user has
already read the response and switched away.
2026-05-13 17:43:08 +03:00
a2c88f0142 Sync speech recognition settings across devices (#1217)
* fix: sync STT settings across devices
Persist speech recognition preferences through shared OpenChamber settings so mobile and desktop stay in sync.

* fix bot review

* fix(voice): sync transcribe-on-stop setting

---------

Co-authored-by: Konstantin Zolin <kzolin@alfabank.ru>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-13 15:45:03 +03:00
11e5ab93a9 fix(quota): guard remaining usage percent (#1242)
* fix(quota): guard remaining usage percent

* test(quota): cover non-finite usage percents

* fix(ui): clean up virtual scroll frame

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-13 14:51:46 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 1e1a7e02b7 test(opencode): restore missing PATH cleanly (#1243)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-13 10:35:32 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez d66e077b99 fix(pwa): include root-scoped session shortcuts (#1244)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-13 10:35:12 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez f01391dd72 fix(opencode): broadcast activity idle after cooldown (#1249)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-13 10:32:30 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 05c5683ecb fix(scheduled-tasks): skip scheduling after stop (#1251)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-13 10:32:16 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez c005c59186 fix(quota): accept epoch reset timestamps (#1241)
* fix(quota): accept epoch reset timestamps

* fix(quota): format epoch reset windows

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-13 10:30:42 +03:00
kjhqandartac f059bc8dd6 fix: remove GitHub hardcoding and generalize for non-GitHub git providers (#1216)
* fix: remove GitHub hardcoding and generalize for non-GitHub git providers

* fix: guard SSH path extraction against missing colon separator

---------

Co-authored-by: artac <artac@artacs-MacBook-Pro.local>
2026-05-13 10:19:31 +03:00
644050824e fix(terminal): reject file cwd values (#1204)
* fix(terminal): reject file cwd values

* test(terminal): remove stale cwd access mock

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-12 11:30:10 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 89630af98d fix(settings): constrain plan path remapping (#1203)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:12:17 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 1f6cea50ed fix(tasks): preserve timestamps when listing (#1198)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:10:56 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 51356b4195 fix(projects): use fallback icon MIME (#1197)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:10:39 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 51e1967f68 fix(sessions): isolate folder save temp files (#1195)
* fix(sessions): isolate folder save temp files

* fix(sessions): remove failed save temp files

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:10:06 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 222d1b7f51 fix(tts): clamp generated summaries (#1187)
* fix(tts): clamp generated summaries

* fix(tts): preserve non-finite summary limits

* test(tts): stub fetch without vitest globals

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:06:21 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez b944bd812c fix(quota): ignore invalid reset timestamps (#1182)
* fix(quota): ignore invalid reset timestamps

* fix(quota): guard reset-after timestamps

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:05:22 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 323347f50e fix(terminal): preserve UTF-8 replay chunks (#1181)
* fix(terminal): preserve UTF-8 replay chunks

* fix(terminal): avoid replay trim prepends

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:05:03 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 2a9c7e6bca fix(event-stream): clean up reconnect delay listeners (#1180)
* fix(event-stream): clean up reconnect delay listeners

* test(event-stream): clarify listener count

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:04:46 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 7721c2fe10 fix(event-stream): isolate subscriber failures (#1235)
* fix(event-stream): isolate subscriber failures

* fix(event-stream): handle async subscriber failures

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:02:04 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez df12c3a2b5 fix(terminal): make SSE cleanup idempotent (#1234)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:01:47 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 060a5311ef fix(terminal): remove upgrade listener on shutdown (#1233)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:01:31 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez eeabc304bd fix(opencode): clear server close timeout (#1224)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:00:45 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 4cbee27383 fix(opencode): clear readiness probe timers (#1226)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 11:00:31 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 0cfa37932e fix(updates): compare prerelease versions correctly (#1220)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 10:57:47 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez eb3f0e7f72 test(opencode): avoid duplicate WSL env assertion (#1212)
* test(opencode): avoid duplicate WSL env assertion

* test(opencode): assert WSL rejection directly

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 10:57:39 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 614e9bbfbf test(opencode): restore PATH after lifecycle tests (#1210)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 10:57:14 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 733e1e2d21 fix(pwa): keep scoped shortcuts isolated (#1205)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-12 10:55:31 +03:00
Wenqiang.Xu 3716deb16c fix: use platform-aware UTF-8 locale fallback for PTY (#1137)
C.UTF-8 does not exist on macOS, causing the terminal to fall back
to ASCII encoding when LANG is unset. Use en_US.UTF-8 on macOS and
C.UTF-8 on Linux. Also set LC_CTYPE with the platform-appropriate
value (UTF-8 on macOS, C.UTF-8 on Linux) for additional safety.
2026-05-08 16:19:24 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 4a79af3fb7 fix(event-stream): cancel unavailable upstream bodies (#1142)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-08 15:14:39 +03:00
Isaac Sanchez-HawkinsandIsaac Sanchez 4b65a16b12 fix(git): load sandbox db dependency in esm (#1140)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
2026-05-08 15:09:52 +03:00
zerone0xandBohdan Triapitsyn 3fbcdbc3dc fix(quota): stop showing misleading OpenRouter percentages (#1127)
* fix(quota): stop showing misleading OpenRouter percentages

Fixes #1085

* fix(quota): clean up OpenRouter credit labels

---------
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-07 23:39:53 +03:00
Bohdan Triapitsyn 585e2a55f1 fix: suppress inherited subagent notifications
Subagent completion notifications respect notification settings
Permission auto-accept now suppresses notifications for known child sessions
Server notification checks use OpenCode session parent semantics
2026-05-07 23:03:46 +03:00
Wenqiang.Xu cb8ea5e6c5 fix: set LANG env for PTY to support UTF-8/Unicode in terminal (#1129) 2026-05-07 23:03:09 +03:00
Bohdan Triapitsyn d764ad6872 feat: add repository cloning to project setup
Add project can clone repositories into a chosen folder
Command palette now opens the add project flow
Clone flow supports selecting Git identities
2026-05-07 01:10:17 +03:00
Bohdan Triapitsyn fd3557e5c3 feat: improve preview proxy behavior
Sort dev-server false positive preview errors
Improves preview URL rewriting and navigation handling
Syncs app theme into preview iFrames
2026-05-07 00:02:01 +03:00
82b36e5080 fix: align session status parsing and vscode reconnect reconcile (#1125)
* fix: align session status parsing and vscode reconnect reconcile

* fix vscode session status fallback and reconcile cleanup safety

---------

Co-authored-by: vhqtvn <8930337+vhqtvn@users.noreply.github.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-06 19:45:31 +03:00
Bohdan Triapitsyn b18886598c fix: validate configured OpenCode binary (#1120)
* Validate configured OpenCode binary

* fix: keep WSL OpenCode startup failures retryable

Avoids misclassifying transient WSL resolution failures as invalid binary config
Adds regression coverage for WSL strict-mode handling
Cleans up temporary test directories
Fix for #1119 issue
2026-05-06 02:06:16 +03:00
Bohdan Triapitsyn 6a749ed259 fix: suppress expected missing directory logs
Stops noisy stack traces for missing directory probes
Preserves existing 404 behavior for absent directories
2026-05-06 01:51:14 +03:00
Bohdan Triapitsyn 93267927ff feat: add git stash management
Add a Stashes dialog with create, apply, pop, and drop actions
Include untracked files automatically when stashing
Show file counts for current changes and stash entries
2026-05-05 23:39:20 +03:00
Bohdan Triapitsyn c80c2b62a8 feat: add one-click git sync button
Combine fetch, pull with rebase, and push into one sync action
Keep remote dropdown focused on safe fetch actions
Block sync when uncommitted changes would conflict with rebase
2026-05-05 20:45:31 +03:00
Bohdan Triapitsyn 6dd322ddbe fix: reduce local server status overhead 2026-05-05 18:47:00 +03:00
962ee41bba fix(ui): add opt-in mobile keyboard resize mode and stabilize touch terminal input (#1107)
* fix(ui): add opt-in mobile keyboard resize mode

* fix(ui): stabilize touch terminal input and tab layout

* fix(ui): narrow touch terminal handling to mobile and tablet

* fix(ui): refine touch terminal input handling

* fix(ui): re-key terminal viewport on session id

* fix(ui): avoid touch-laptop terminal overlay regression

* fix(ui): hide ghostty system caret surfaces

* fix(settings): normalize mobile keyboard mode sanitization

* fix(ui): honor terminal quick keys toggle on mobile

* fix(ui): gate mobile keyboard resize mode on iOS

---------

Co-authored-by: vhqtvn <8930337+vhqtvn@users.noreply.github.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-05 12:26:34 +03:00
Shyamalan KannanandBohdan Triapitsyn a9ee499ae4 fix: add concurrency controls for multiple sessions using the same provider (#1069)
* fix: add concurrency controls for multiple sessions using the same provider

Adds OS-inspired scheduling primitives (from HiveMind/AIMD research) to prevent
concurrent sessions from the same provider from experiencing slowdowns, random
stops, and cascading failures.

Server-side:
- Health check skips OpenCode restart when sessions are actively busy — a busy
  server under concurrent load can fail the health check timeout without being
  dead. Staleness guard forces restart if unhealthy+busy persists >2 minutes.
- Upstream SSE stall timeout scaled from 20s to 60s to avoid unnecessary
  reconnections when multiple sessions are waiting for LLM responses.

Client-side (HiveMind primitives, arXiv:2604.17111):
- Transparent retry with exponential backoff (1s→2s→4s, max 32s) for
  429/502/503/504 errors — the #1 most effective primitive from the paper.
- Circuit breaker: opens after 3 consecutive retryable errors, cooldown
  doubles each trip (30s→60s→120s, capped 128s), matching TCP AIMD.
- Per-provider session tracking with TTL eviction (1h idle sweep).
- Fetch-level retry gated on AbortError/TypeError only (not DNS failures).

Refs github-code-review skill findings (all 8 issues resolved).

* fix: use definite assignment assertion for response variable

Fixes TS2454: Variable 'response' is used before being assigned
in strict mode. The for-loop body always assigns it on every path
that reaches the post-loop code, but TS can't prove that.

* fix: add cleanupSession to error paths and remove unreachable code

P1 fixes (Greptile review):
- cleanupSession called on fetch error throw path
- cleanupSession called on non-retryable HTTP error throw path
- Removed unreachable post-loop code (loop always terminates via return or throw)

Adds explicit post-loop throw to satisfy TypeScript strict return check.

* fix: address Greptile review feedback on concurrent session controls

Removes client-side session tracking that leaked on normal completion paths.

The session tracking was redundant — the server-side health check already reads from

sessionRuntime.getSessionActivitySnapshot() for busy-session detection.

Changes:

- Remove activeSessions Set and all session-tracking functions from provider-tracker

- Remove trackSessionStarted/cleanupSession calls from client.ts

- Remove unreachable (response as Response) block after retry loop

- Make upstreamStallTimeoutMs conditional: 60s when >1 sessions, 20s otherwise

Refs #1069

* fix: enforce dynamic concurrency safeguards

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-01 14:57:31 +03:00
pasta-paulandBohdan Triapitsyn 1991736ebf fix(server): prevent streaming hang during long agent sessions (#1088)
* fix(server): increase WS buffer/replay limits and add backpressure warning

During long-running agent sessions (e.g. ultrawork loops with many tool
calls), the browser WebSocket client can briefly fall behind the server.
When the outbound buffer exceeds the limit, the server force-disconnects
with close code 1013, and the small replay buffer (512 events) is
insufficient to recover all missed events — leaving the UI permanently
stalled.

Changes:
- Raise MESSAGE_STREAM_WS_MAX_BUFFERED_BYTES from 4 MB to 16 MB to
  tolerate larger bursts without disconnecting
- Add MESSAGE_STREAM_WS_BACKPRESSURE_WARN_BYTES (12 MB) threshold that
  sends a one-shot "backpressure" frame to the client before the hard
  disconnect, giving it a chance to shed low-priority updates
- Raise MESSAGE_STREAM_GLOBAL_REPLAY_LIMIT from 512 to 2048 so more
  events survive brief reconnection gaps
- Add tests for the backpressure warning behavior (emit, dedup, reset)

* fix(ui): batch event flushes under backpressure

---------
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-01 13:25:19 +03:00