Commit Graph
3456 Commits
Author SHA1 Message Date
Sérgio Pedro d06329bca1 chore: retry review again after second CI timeout mid-review 2026-08-12 11:04:19 +01:00
Sérgio Pedro cc4792a7e0 chore: retry review after prior run hit CI timeout mid-review (582s, no verdict posted) 2026-08-12 10:56:20 +01:00
Sérgio Pedro ced65062c8 fix: kill orphaned process on Windows before OpenCode restart
killProcessOnPort() was a no-op on win32 (POSIX-only, via lsof/kill),
so a restart could leave the old OpenCode process holding the port
while a new instance spawned on a different one. That's a plausible
contributor to a chronic pattern seen in production logs: repeated
"OpenCode process exited, restarting" cycles and hundreds of
ECONNRESET/proxy errors over multiple days on Windows.

Give killProcessOnPort a real Windows branch: parse `netstat -ano`
for PIDs listening on the target port, filter out our own pid, and
force-kill each via `taskkill /PID <pid> /F` (no /T -- we don't own
that process, so only the listener itself is killed, not any
children it may have).

waitForPortRelease()'s existing soft-fail-and-warn behavior is left
untouched -- it's a deliberate safety net for any platform where the
port doesn't free up in time, not just Windows, and the restart
already rebinds event-stream readers to the actual resulting port via
onOpenCodeRestarted.
2026-08-12 10:19:29 +01:00
Bohdan Triapitsyn 9e43b9ae46 fix(pairing): include the request origin as a direct candidate in pairing links
Creating a device key while the UI is open through a public https domain
(reverse proxy) dropped that domain from the QR payload whenever the
dialog passed a preferred LAN URL, leaving only the local IP and relay
as transports. Carry the non-loopback request origin as an additional
direct candidate (priority 20, between LAN and relay) so paired devices
can keep using the same domain on any network.
2026-08-12 10:36:59 +03:00
Bohdan Triapitsyn 069d9ad5c9 feat: cap subagent list height in work status panel
Limits the expanded subagents list to eight rows
Adds independent scrolling so other sections stay visible
Documents the new subagents panel behavior
2026-08-12 02:10:27 +03:00
Bohdan Triapitsyn 5917325d49 feat: switch OpenCode Go usage to API
OpenCode Go now reads quota usage with a bearer API key from OpenCode auth.json
Removes the old workspace ID and browser cookie credential flow
Deletes legacy OpenCode Go credential files during upgrade
2026-08-12 01:49:22 +03:00
Bohdan Triapitsyn d1224213ca docs: add changelog authoring guidance
Adds a dedicated skill for drafting user-facing unreleased changelog entries.
Covers both the main app changelog and the VS Code extension changelog.
Updates agent guidance to route changelog work to the new skill.
2026-08-12 01:23:57 +03:00
pablogonzalez b8df186822 feat(desktop): upgrade Electron to 43.3 for Linux frameless rounded corners (#2765)
* feat(desktop): upgrade Electron to 43.3 for Linux frameless rounded corners

- electron ^41.2.1 -> ^43.3.0 (electron/electron#51459/#52111: rounded
  corners for frameless windows on Linux, default-on; disable via
  roundedCorners: false)
- @electron/rebuild ^3.7.0 -> ^4.2.0 to build native modules against
  the new Electron ABI
- pin node-abi to 4.33.0 via root overrides so @electron/rebuild (and
  electron-builder's internal rebuild) can resolve Electron 43's ABI
- README: Electron 43 ships its own fixed extractor (extract-zip 2.0.1
  Node-24 unpack bug no longer applies; ensure-electron remains a
  safety net for interrupted/wrong-arch installs)

* chore: re-trigger pr-review after adding visual evidence

* fix(desktop): scope node-abi to Electron rebuild tooling

* chore: re-trigger pr-review after dependency fix

* chore: re-trigger pr-review with drag evidence

* chore: retry pr-review after evidence confirmation
2026-08-11 17:25:32 +03:00
Bohdan Triapitsyn 22b3665077 feat: show work status on draft sessions and resolve project worktrees
Keeps the work status panel aligned to the draft's target directory
Resolves project labels for sibling worktrees using shared session-directory logic
Adds coverage for resolving a worktree back to its registered project
2026-08-11 17:00:23 +03:00
Bohdan Triapitsyn a20b87e984 fix(work-status): label project details clearly 2026-08-11 17:00:23 +03:00
Serhii DziupinandSerhii Dziupin c3c47e8956 perf(ui): tighten Shiki highlight caches and parallelize fences
Use content fingerprints instead of full source as cache keys, record
entry sizes once (no TextEncoder/JSON.stringify on get/evict), and
highlight multiple markdown fences concurrently.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-11 13:23:43 +00:00
Andrea VandChangeHow 454119ac25 fix(ui): mount only the active session chat iframe (#2816)
* fix(ui): mount only the active session chat iframe

* repro(ui): mount-all-persisted session-chat iframes (#2815)

Adds a regression-style reproduction for issue #2815: ContextPanel
renders one full-application iframe for every chat tab (inactive tabs
are only hidden via the Tailwind 'hidden' class, never unmounted), so a
reload restores all persisted session-chat tabs from the ui-store and
mounts N embedded OpenChamber apps in one browser tab.

The test reads the real ContextPanel.tsx render block, drives the real
useUIStore with the issue's persisted scenario (11 tabs, 8 read-only
session-chat tabs), and models the render block with the real
buildEmbeddedSessionChatURL helper, showing 8 live src iframes (7
hidden but loaded).

* test(ui): adapt issue 2815 reproduction for active chat

* fix(ui): unmount session chat when panel closes

---------

Co-authored-by: ChangeHow <23733347+ChangeHow@users.noreply.github.com>
2026-08-11 16:11:25 +03:00
Bohdan Triapitsyn b55152db6f fix(usage): refresh work status quotas automatically 2026-08-11 12:58:36 +03:00
Dawnfz-Lenfeng 5b8ff22d35 fix(ui): always show /init command in autocomplete
The /init command was only offered in the autocomplete when the current session had no messages yet, and it was filtered out entirely once any message existed. Since the underlying session.command endpoint works in any session, keep /init available whenever a session exists so AGENTS.md setup stays reachable mid-conversation.
2026-08-11 17:45:15 +08:00
ChangeHow 99e254acf3 fix(ui): prevent code line numbers from wrapping (#2719) 2026-08-11 10:49:01 +03:00
Bohdan Triapitsyn a0207e3857 test: cover work-status empty panel recovery 2026-08-10 23:31:58 +03:00
Aaron Hogue 02872ff9d3 fix: keep work-status panel reachable when all sections are hidden (#2805)
* fix: keep work-status panel reachable when all sections are hidden

When every section was unchecked in the Panel Sections dialog, the panel
went transparent and inert, making the settings gear icon unreachable.
The only recovery was knowing to toggle the panel off and on from the
header, which still rendered the same empty/inert state.

Changes:
- Panel stays interactive (not inert) when visible, even with zero
  rendered sections. This matches how other panels in the app use inert
  only for visually-collapsed (width/height = 0) states.
- Empty state shows 'No sections selected' with a link to reopen the
  sections dialog, matching the centered text-muted-foreground pattern
  used by the file tree, review panel, and home page empty states.
- Sections dialog gains a 'Show all' link (visible whenever any section
  is hidden) and a warning when all sections are unchecked, matching the
  keybinds settings 'Reset to defaults' pattern.
- Added i18n keys to all 10 locale files (English fallback).

Fixes #2804

* Round 1: fix interactive guard for fresh-mount; translate i18n keys

Address openchamber-bot review findings:

1. (blocker) Replace English fallback strings in all 10 non-English
   locale files with real translations per locale-ui-patterns guidance.

2. (non-blocker) Restore the renderedSections > 0 guard for the
   transient no-data-on-mount state so the panel doesn't flash a bare
   bordered card. The interactive condition is now:
     visible && (renderedSections > 0 || allSectionsHidden)
   Empty-state rendering is gated on allSectionsHidden alone (not
   renderedSections === 0) so it works correctly on fresh mount when
   all sections were already hidden in persisted settings.

Validation:
  tsc --noEmit: 0 errors
  bun test work-status: 34 pass, 0 fail

* Round 2: use .every() guard, dedup chooseLabel key, add tests

1. Replace >= length check with areAllWorkStatusSectionsHidden() helper
   that uses .every() — stale section ids left in persisted settings
   from a future removal can no longer inflate the count.

2. Remove duplicate chooseLabel i18n key from all 11 locales — the
   empty-state link now reuses the existing sections.open key.

3. Add 6 focused tests for areAllWorkStatusSectionsHidden covering
   empty, null/undefined, partial, full, stale-id, and stale+full.

Validation:
  tsc --noEmit: 0 errors
  bun test work-status: 40 pass (6 new), 0 fail
2026-08-10 23:28:50 +03:00
Bohdan Triapitsyn 59d988deda release v1.18.2 2026-08-10 20:57:44 +03:00
Bohdan Triapitsyn fb286653f1 fix: adjust model picker scroll shadows 2026-08-10 20:55:39 +03:00
Bohdan Triapitsyn 75978cf188 fix(mcp): reliable OAuth across runtimes and honest pre-restart UI
MCP authorization was broken in several stacked ways. The browser return
leg landed on the SPA behind the auth gate, so the system browser saw a
login page instead of finishing; the pending-context store silently
saved nothing because its route had no JSON body parser; and the
callback-URL config write started deferring behind Apply & Restart, so
authorization ran against a runtime without the URL and dead-ended on
OpenCode's loopback listener.

The return leg is now completed entirely server-side by an
unauthenticated GET /mcp/oauth/callback that only forwards a code whose
state matches a parked context. Desktop with the local server and VS
Code switch to OpenCode's native flow over its fixed loopback port —
no config writes or restarts at all, with a one-time cleanup of the
previously written callback URL — and its completion signal drives the
page instead of blind status polling. Remote, hosted-web, and mobile
keep the server-callback flow, applying a queued callback-URL write
immediately since authorization cannot wait for a manual restart.

Also: a server queued behind Apply & Restart now shows an Awaiting
restart badge and explanation instead of connect/reauthorize buttons
that can only fail, and Reauthorize is offered only while the server is
actually connected.
2026-08-10 20:23:45 +03:00
Bohdan Triapitsyn 3feee346da fix: replace glass dialog styling with solid background
Dialogs and settings window now use the standard background color
Removed dialog from the glass utility styles
Preserves existing glass effects for other surfaces
2026-08-10 18:49:45 +03:00
Serhii DziupinandSerhii Dziupin 6ab12fdb61 fix(ui): stop sustained Shiki re-highlight of unchanged markdown
Content-address the markdown HTML cache and memoize Shiki worker/client
results so remounts and long sessions no longer re-tokenize stable code
blocks (openchamber/openchamber#2769).

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-10 13:50:20 +00:00
Bohdan Triapitsyn b1d121a47e chore: reorder project changelog entry 2026-08-10 16:12:16 +03:00
Bohdan Triapitsyn f9595cb80b fix(projects): open draft after adding project 2026-08-10 16:10:03 +03:00
Bohdan Triapitsyn bd4e7668fb chore: update changelog entries for recent UI and chat fixes 2026-08-10 15:30:56 +03:00
Bohdan Triapitsyn e5eab8c8be style: soften diff action container shadow 2026-08-10 15:10:37 +03:00
Bohdan Triapitsyn 1738707f22 fix(relay): keep relay host alive for devices that actually use it
Relay demand now counts the authoritative transport signal: a request
arriving through the tunnel permanently marks the client usesRelay, and
hasActiveRelayClients also accepts lastTransport === 'relay'. Store read
failures no longer masquerade as no demand, so reconcile can't persist
enabled=false and sever paired devices on a transient error.
2026-08-10 15:10:37 +03:00
Bohdan Triapitsyn 5e26390ad2 fix: make the composer caret more visible
Thickens the CodeMirror cursor to 2px
Adds a slight vertical scale so the caret stands out above glyphs
Covers the new cursor styling with a test
2026-08-10 15:10:37 +03:00
Bohdan Triapitsyn 2c30af5807 refactor: remove macOS vibrancy support and unify glass surfaces
Drops the macOS vibrancy toggle, IPC, and related settings copy
Updates dialogs, popovers, tooltips, and dropdowns to use shared glass styles
Adds sticky header fade behavior to model picker and sidebar lists
2026-08-10 15:10:37 +03:00
Bohdan Triapitsyn 90a16d1d44 fix(chat): refresh work status from git hints 2026-08-10 15:10:36 +03:00
Bohdan Triapitsyn dfa7b45dd0 fix(mobile): recover pending questions after cold start 2026-08-10 15:10:36 +03:00
Rajat Asthana 2efbbcee33 Merge branch 'openchamber:main' into fix/shell-command-entry-caret 2026-08-10 14:53:43 +05:30
RyderAsking 0b2b697aa5 fix(chat): prevent shell prefix from corrupting input 2026-08-10 09:22:56 +00:00
Serhii Dziupin 87f2d21054 chore: remove terminal debug screenshots 2026-08-10 10:14:46 +03:00
Serhii Dziupin f8b841c922 chore: remove PR evidence screenshots for rail badge background 2026-08-10 10:14:00 +03:00
Serhii DziupinandUbuntu 2d96454fc9 fix(i18n): shorten pending-restart applying label across locales (#2791)
Co-authored-by: Ubuntu <ubuntu@watcher.tail9db222.ts.net>
2026-08-10 09:51:31 +03:00
Serhii Dziupin 5e6d1f8b01 fix(ui): restore rail badge background via surface theme tokens (#2790)
* fix(ui): expose surface.* tokens so bg-surface-muted renders

* docs: add PR evidence screenshots for rail badge background
2026-08-10 08:23:06 +03:00
herjarsa 629bf40d83 fix(git): silence getWorktrees warning when directory is not a repo
`getWorktrees` logs a warn-level line every time the managed OpenCode
process or any other caller passes a directory that is not inside a
git repository. The OpenChamber desktop main.log fills with hundreds
of these "Failed to list worktrees, returning empty list: fatal: not
a git repository ..." entries over a normal session.

The empty-list fallback is already correct (worktrees are an optional
feature), but the warning is noise that hides real git failures. Use
the existing `isNotGitRepositoryError` helper to suppress the warn
specifically for the "not a git repository" case and keep the
warning for genuine failures (lock contention, permission errors,
corrupt repos, etc.).
2026-08-10 00:20:12 +02:00
Bohdan Triapitsyn 4e7eb81036 chore: ignore /tmp directory 2026-08-09 22:46:31 +03:00
Bohdan Triapitsyn e13b4526c6 feat(tasks): manage markdown loops from scheduled tasks 2026-08-09 21:43:16 +03:00
Bohdan Triapitsyn ce6912fe40 fix(tasks): sync markdown loops when listing tasks 2026-08-09 20:32:30 +03:00
Bohdan Triapitsyn a7f1d7d89e chore: added unreleased changes 2026-08-09 20:07:40 +03:00
Bohdan Triapitsyn f8b33be5eb chore: bump @opencode-ai/sdk to 1.18.15 2026-08-09 20:03:06 +03:00
Bohdan Triapitsyn 121685e564 revert: restore auto-hiding overlay scrollbars 2026-08-09 19:53:49 +03:00
Bohdan Triapitsyn f4743ea060 feat(chat): work-status panel, and MCP auth and settings fixes (#2776)
Adds a work-status panel beside the transcript. Context fill, model and
cost, todos, running subagents and the permission requests blocking
them, branch and working-tree state, MCP servers, pinned messages and
context sources were scattered across the header, the composer and the
context panel — a blocked subagent was reported nowhere at all. The
panel reads them from live channels rather than persisted history, and
becomes an overlay where the chat is too narrow to seat a column.

It is on by default, including for existing installs. Because it now
carries these readouts, the desktop header and composer drop the ones it
duplicates: todo and changed-files chips, usage and MCP tabs. VS Code
and mobile keep theirs — neither hosts the panel.

Fixes MCP authorization, which was broken from the panel, invalidated by
a directory switch through a redirect URI that encoded the working
directory, and left the desktop app in the background because browsers
will not follow a custom-protocol link without a user gesture. The
settings page no longer asks the user to understand the MCP spec before
adding a server: one field takes the command or the link, with the kind
inferred and a visible override, and client-registration fields appear
only when a server actually asks for its own credentials.

Also: skills load from the panel instead of only when the composer's
slash autocomplete opens; the header button names the current instance
rather than falling through to the word "Instance" for relay hosts.

Three new optional UI settings keys, all migrated. No change to stored
MCP server configuration.
2026-08-09 19:30:25 +03:00
Floze 901d34bc5f fix: keep GitHub settings mounted during refresh 2026-08-09 15:41:58 +04:00
Zeying Tian 0bbbcd6445 fix(small-model): omit thinkingConfig for non-reasoning Google models 2026-08-09 03:10:31 -04:00
quiz152 95338dbbb1 test(cli): deterministic torn-write regression coverage; document module
Address the openchamber-ai review's non-blocking notes:

- Concurrency evidence: the torn-write test now injects a slow, chunked
  writeFile (one open handle, file grows prefix->full) so a torn read is
  deterministically observable in the 30ms window. A companion test runs the
  naive direct writer under the same load and asserts torn reads ARE produced,
  proving the atomicity test can actually fail on the pre-fix writer.
- Windows fallback comment: no longer claims the copyFile fallback is atomic;
  it is called out as a last resort confined to Windows.
- Module map: document cli-settings-accessors.js in bin/lib/DOCUMENTATION.md.
2026-08-09 11:39:42 +08:00
quiz152 7a165fd0bb fix(cli): atomic settings writes and gate relay key regeneration in connect-url
The CLI's settings accessors wrote settings.json directly with writeFile and
read it leniently, with no strict-reader gate on relay identity. Running
'openchamber connect-url' while the desktop app is up could:
  - tear the file for a concurrent reader in the app, tripping the relay
    service's read and mapping it to {} (first-run);
  - then regenerate the relay signing/encryption keys, changing serverId and
    orphaning every paired device and push binding.

Move the accessors into a dedicated module that mirrors the settings
runtime's guarantees: atomic tmp+rename writes (with the Windows fallback)
so no reader can observe a partial file, and a strict reader that throws on
corrupt/unreadable payloads so identity regeneration is gated exactly like
the server runtime. Wire the strict reader into the CLI relay identity path.

Adds unit tests covering atomic writes under concurrent readers, strict-read
behavior, and that a corrupt settings file makes getRelayIdentity fail
instead of minting a replacement keypair.
2026-08-09 11:16:30 +08:00
Bohdan Triapitsyn 493a618efc perf(terminal): relax transport keepalive from 20s to 45s
The ping has no pong-timeout on either side — it exists only to keep
intermediaries from idling out the socket. 45s stays safely under the
relay host-data idle reaper (90s) and common proxy read timeouts (60s),
while halving the events that wake the relay Durable Object during an
open session.
2026-08-08 17:26:59 +03:00