Commit Graph
3363 Commits
Author SHA1 Message Date
Andrea VandBohdan Triapitsyn a005215458 feat(chat): remember JSON output view mode (#3072)
* feat(chat): remember JSON output view mode

* perf(chat): skip JSON preference reads for text output

* fix(chat): persist JSON view in UI settings

* fix(chat): round-trip JSON view preference

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-09-05 18:27:38 +03:00
Ibrahim Khan 3a96c7ce64 fix(cli): warn when systemd user lingering is disabled (#1855) 2026-09-05 18:12:43 +03:00
Bohdan Triapitsyn 391ea57731 docs: update unreleased changelog title 2026-09-05 17:58:04 +03:00
Matt Visnovsky a0f7e08e88 fix(sessions): restore archived worktree sessions (#3325)
* fix(sessions): restore archived worktree sessions

* fix(sessions): re-move worktree restore roots stranded by a failed move
2026-09-05 17:51:51 +03:00
Bohdan Triapitsyn fe9119abb5 docs(changelog): VS Code notes for the next release, no banner in the extension changelog
Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 17:29:32 +03:00
Bohdan Triapitsyn 08d5d766cf docs(skills): rename changelog-authoring to update-changelog
Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 17:17:40 +03:00
Bohdan Triapitsyn 3d2bcf7ed6 chore(changelog): retire CHANGELOG.md as a dependency
The update dialog (server and desktop) now reads changelog/index.json and
renders title, intro and groups; the release workflow builds the GitHub
Release body and name from changelog/<version>.md; oc-dev, the issue-intake
agent, AGENTS.md and the changelog skill no longer point at the file.

CHANGELOG.md stays as a legacy copy for installs up to 1.22.1, which fetch
it for update notes. The generator refreshes it while it exists and never
recreates it, so deleting it after 2026-09-19 retires it for good.

Generated outputs hold released versions only, so editing unreleased.md
never makes them stale: agents write that file and nothing else, and
oc-dev create-release does the generation.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 17:02:28 +03:00
Bohdan Triapitsyn c3ae9b1d91 docs(changelog): title the unreleased notes
Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 16:46:07 +03:00
Bohdan Triapitsyn a1bc1368ae docs(changelog): title every release and require one
Every release file now carries a title: two to six plain words naming the
change a user would remember it for. The generator refuses a release without
one, promote carries the title from unreleased.md, and the unreleased
template opens with a title line. The changelog-authoring skill and the
format README describe how to write it.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 16:45:29 +03:00
Bohdan Triapitsyn 475dc5ecb1 docs(changelog): title 1.22.1 after its OpenCode Go highlight
The grouped notes put the OpenCode Go header change under Improvements, so
the site's headline fallback (first bold bullet) picked Message queue. The
explicit title keeps the release's most important change on the index.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 16:27:45 +03:00
Bohdan Triapitsyn fe662874df fix(ui): show changelog groups as labels in the update dialog
Release notes now carry New, Improvements, Fixes, and Misc headings.
Inside the update dialog they render as small uppercase labels over
their lists instead of full-size document headings.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 16:17:29 +03:00
Bohdan Triapitsyn 9f78de9e89 docs(changelog): rewrite the last thirty releases for readers
Releases 1.13.1 through 1.22.1 are regrouped by what each change is
(New, Improvements, Fixes, Misc) and reworded in the voice the
changelog-authoring skill asks for: one or two plain sentences per
bullet, the symptom or the capability named, no mechanism. Packed
bullets were split, every fact and every contributor credit kept.
Older releases keep the mechanical grouping.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 15:58:34 +03:00
Bohdan Triapitsyn d9b9c8edab feat(changelog): one source file per release, generated outputs
Release notes now live in changelog/<version>.md (front matter with
version and date, then ## App and ## VS Code sections grouped into
New, Improvements, Fixes, Misc) plus changelog/unreleased.md for what
has not shipped. `bun run changelog:build` renders CHANGELOG.md,
packages/vscode/CHANGELOG.md, and changelog/index.json from them;
`changelog:check` fails when the outputs are behind and runs in CI and
in release:prepare. `oc-dev create-release` promotes unreleased.md to
the versioned file dated today and rebuilds.

The existing history was split mechanically: every bullet kept, sorted
into groups by keyword, five hand-typed headers with one-digit days
normalised to YYYY-MM-DD (the update dialog matched none of them). The
generated files keep today's release headers, which the update dialog,
the release workflow, and the website match by regex.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 15:58:23 +03:00
Bohdan Triapitsyn bc2513f410 docs(changelog): group release notes and rewrite the authoring skill
Release sections now carry New, Improvements, Fixes, and Misc groups,
and the bullets are written for a user who never opened the code: one
or two plain sentences naming what they see. The changelog-authoring
skill makes that shape the primary rule, with a worked example, a
five-second reader test, and checks per bullet.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 15:45:22 +03:00
Bohdan Triapitsyn c3a83b3181 fix(vscode): default to the VS Code display language before a saved locale
The splash and the UI bundle both started in English on a fresh install
even when VS Code ran in a supported language, because only OpenChamber's
own saved locale was consulted. The HTML now exposes VS Code's display
language; the splash and detectInitialLocale use it until the user picks
a locale, which still wins.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 15:08:15 +03:00
Bohdan Triapitsyn 319cf9f17a fix(mobile): label the pill's running-state action as queue
While a turn runs, the collapsed pill showed a plain Send button for a
draft that the expanded composer shows as Queue with a rotated icon, and
the pill routed it through the primary action. The pill now queues, with
the same label and icon as the expanded composer.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 15:08:15 +03:00
Bohdan Triapitsyn 1e0d7abb6e fix(sidebar): poll project actions only while one is running
The sidebar indicator kept the terminal listing loop going for as long as
the sidebar was visible, in every client, whether or not anything was
running. It now lists once on mount, to pick up runs another client
started, and keeps the loop only while a project action is known to be
running anywhere; an idle sidebar costs no polling.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 15:08:15 +03:00
Bohdan Triapitsyn f4eaa70eaa fix(docker): ship patched dependencies in the runtime image
The runtime stage copied node_modules from the deps stage, but patch-package
runs in the builder stage, so a patched server-side dependency reached the
image unpatched; only the bundled dist carried the fix. Both node_modules
copies now come from builder.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 15:08:15 +03:00
Bohdan Triapitsyn 99c9f99a3d test(vscode): assert bundle keys by presence
The bundle files are parsed as string maps, so a missing key is the only
failure the test can see; checking presence says that directly.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 14:50:08 +03:00
Bohdan Triapitsyn 03e14b61cd fix(terminal): key project action state by one canonical directory
The terminal store keyed its directories by trimming trailing slashes,
while the new sidebar activity indicator and the whole-server session
grouping keyed the same folder with the project-action normalizer, which
also rewrites backslashes. On Windows that split one project into two
namespaces: the sidebar reconciled server sessions under "C:/repo" while
the terminal panel and the project actions button worked under "C:\repo",
so the running-action indicator never lit up, adopted tabs were duplicated
and a stop recorded in one namespace did not guard reconciliation in the
other. The project actions button also read the store map directly with a
path normalized somewhere else, missing its own directory entry.

All terminal directory keys now come from normalizeTerminalDirectory in
lib/pathNormalization, and store reads go through getDirectoryState.
2026-09-05 14:48:25 +03:00
Bohdan Triapitsyn 74b8c77d49 fix(chat): keep the diff preview bound off a surrogate pair
The 256 KiB budget for an oversized tool diff preview counts UTF-16 units, so
the cut can land between the two halves of an astral character - an emoji in a
patched string, for instance. The preview then ended in a lone surrogate that
renders as the replacement glyph.

Step back one unit when the boundary splits a pair.
2026-09-05 14:48:17 +03:00
Bohdan Triapitsyn e24d2b2cbd fix(ui): guard the remaining comment inputs against IME composition
The IME fix covered the diff/file comment input and the browser annotation
overlay, but two other places where a user writes a comment still acted on
the Enter that confirms an IME candidate: the chat quote comment in the text
selection menu, and the in-place comment editor on a composer context chip.
Confirming a candidate there attached or committed the half-typed reading and
closed the input. Escape, which abandons a candidate, had the same problem.

Both handlers now return early on a composing keystroke, and a single test
asserts the guard across every comment input so the next one added does not
quietly skip it.
2026-09-05 14:48:17 +03:00
Bohdan Triapitsyn 904334de88 fix(vscode): compare workspace folders through the shared path helper
The add-folder dedup normalized the drive letter to uppercase on one side and compared it with Uri.fsPath, which VS Code lowercases again. On Windows an already-open folder therefore never matched and was re-added. Uses pathsEqualWithNormalizedDriveLetter so both sides normalize.
2026-09-05 14:47:10 +03:00
Bohdan Triapitsyn 6c3e51956a fix(vscode): complete the Turkish extension bundles
The inline-comment feature added its manifest and runtime strings to English and French only, so Turkish users saw English command titles, thread labels and warnings. Adds the ten missing keys and a test that fails whenever a locale bundle drifts from the English key set or its placeholders.
2026-09-05 14:47:10 +03:00
Bohdan Triapitsyn 9eb8a92169 fix(cli): probe bun.exe under BUN_INSTALL on Windows
isBunInstalled() spawned <BUN_INSTALL>/bin/bun, which does not exist on
Windows where the installer ships bun.exe. spawnSync adds no extension to
an explicit path, so the probe failed and the CLI quietly started the
server under Node even with Bun installed. The probe now names bun.exe
on win32.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 14:46:06 +03:00
Bohdan Triapitsyn 65019492e5 fix(sync): guard child-session discovery against overlapping pulls
Child discovery now pages through the whole session list, so one pull can
take longer than the 15s watchdog interval. Two overlapping pulls each read
the store before either commits, so both appended the same newly found child
and the directory store ended up with duplicate rows. Keep one pull per
directory in flight, mirroring the status-poll guard.
2026-09-05 14:45:35 +03:00
Bohdan Triapitsyn f02dfbd4cb fix(web): tidy the XDG config root resolution
The web server read XDG_CONFIG_HOME through a redundant typeof guard on a
value that is already string|undefined, which tripped the anti-slop lint on
its own new line and diverged from the VS Code helper. Both now read the
same way. The VS Code provider test also still hard-coded ~/.config/opencode,
so it silently stopped asserting whenever XDG_CONFIG_HOME was set; it now
uses the shared constant, like the web test already does.
2026-09-05 14:45:20 +03:00
Bohdan Triapitsyn e43541d38b fix(tooling): resolve Bun in the full dev launcher
dev-web-full.mjs is started by node and spawned bare `bun`, so on Windows
machines where npm exposes only bun.cmd both children died with ENOENT and
`dev:web:full` never started. It now uses the resolver dev-web-hmr.mjs got,
and hides the console window like the other Node-spawned children.
2026-09-05 14:45:20 +03:00
Bohdan Triapitsyn ac23e23db7 docs(providers): name the supported adapters in the web module doc
The web route accepts the OpenAI Chat Completions, OpenAI Responses and
Anthropic Messages adapters, but the module doc still described the write
path as OpenAI-compatible only. The VS Code doc already names all three.
2026-09-05 14:44:55 +03:00
Bohdan Triapitsyn b7a63af1b9 test(providers): cover legacy alias migration with several entries
The legacy `providers` block is deleted whole when its last entry migrates
to `provider`. Nothing covered the case where other legacy entries remain,
so a regression there would silently drop unrelated providers. Adds the
case to both the web server and VS Code parity suites.
2026-09-05 14:44:55 +03:00
Bohdan Triapitsyn 671dce7213 fix(vscode): send an editor comment to the sidebar chat instead of opening a tab
A comment went to the active session tab, and when there was none it opened
a new one, even while the user was chatting in the sidebar. That is not how
the other capture flows behave. The comment now takes the same route as
Add to Context: the active session tab when one exists, otherwise the
sidebar, revealed if it is closed.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 14:25:00 +03:00
Bohdan Triapitsyn 60a4dccb32 fix(vscode): file an editor comment under the session it was delivered to
A comment written with no session tab open opens one, and that panel knows
its directory long before it has loaded the session list and selected its
session. The webview filed the draft on the first snapshot that had a
directory, with the session key falling back to "draft" because no session
was current yet. The panel's composer reads the session's key, so the chip
never appeared, while the editor thread saw the draft in the store snapshot
and reported it attached.

A session panel now stamps its session on every comment it delivers, and
the webview waits until it actually shows that session before filing. The
sidebar files on its current session or an open new-session draft, and no
longer falls back to "draft" merely because nothing is selected yet. The
resolver is a pure module with tests.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 14:18:51 +03:00
Bohdan Triapitsyn 4f1f9e6650 feat(sidebar): show running project actions by directory 2026-09-05 14:12:07 +03:00
Bohdan Triapitsyn 7a3244bab2 test(web): remove two timing races that hung CI for a minute each
Both failures showed up as "Test timed out in 30000ms" followed by "Hook
timed out in 30000ms" on loaded PR runners, in files nobody had touched.

relay host-client: the scripted client dialed its WebSocket before awaiting
its WebCrypto setup and only then attached the open/message listeners. On a
loaded runner the loopback socket opened while key generation was still
queued on the threadpool, the open event found no listener, no hello was
sent, and the client waited forever. The socket is now dialed after the key
material is ready, in the same tick as the listeners. The fake relay also
terminates leftover sockets on stop so a failure is reported once, not
twice.

walkthrough routes: each test slept 20 ms and assumed the request had
reached the route by then. The tests now wait until the service has been
asked to generate one more time than before the request, and afterEach
closes idle keep-alive connections so server.close() cannot hang on a
response a failed test never received.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 12:40:07 +03:00
Felipe GenéandBohdan Triapitsyn a12b9be443 feat(chat): Comments and review in VS Code, like the OpenChamber desktop app (#1724)
* feat(chat): render code comments as cards instead of fenced text

* fix(vscode): route Add Comment to the active session editor panel

* fix(chat): persist queued inline comments and tighten file-chip path matching

* feat(vscode): comment on code from the editor

* fix(chat): keep attached context in the message and broadcast comment removal

* fix(vscode): hold every pending comment and gate both entry points on the workspace

* fix(vscode): let only the owning surface decide its comment threads

* fix(vscode): drop a comment removed while its delivery was still in flight

* test(vscode): cover the in-flight comment removal guard

* test(vscode): cover comment removal reaching every chat surface

* fix(vscode): give up on a comment the chat never confirmed holding

* fix(vscode): retract a comment everywhere before reporting it discarded

* fix(chat): preserve queued comment cards

* fix: preserve inline comment context across send paths

* fix(chat): preserve command routing with context

* fix(chat): keep unavailable actions on normal send path

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-09-05 12:28:17 +03:00
Bohdan Triapitsyn d323b51a0a fix(queue): deliver a queued slash command with context as a prompt
OpenCode's command route accepts file parts only. The server queue was
attaching captured context as text parts to POST /session/:id/command, so
a slash command queued with a comment, quote, or PR diff was rejected with
400 and retried forever.

A command queued without context still takes the command route with its
files. One queued with context now takes the prompt route the way the
composer does: the command's template is expanded with its arguments, a
skill keeps its text and gets the explicit skill-invocation instruction,
and the context rides along.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 12:27:55 +03:00
Bohdan Triapitsyn 0b39efb0ae chore: bump @opencode-ai/sdk to 1.18.29 2026-09-05 12:11:20 +03:00
Bohdan Triapitsyn d37ce34a2e fix(terminal): reconcile project action executions across clients (#3362) 2026-09-05 12:05:39 +03:00
Matt Visnovsky 4e0eed717d fix: Project action terminal lifecycle (#3287)
* fix(terminal): make command sessions own action lifecycle

* fix(ui): reconcile project action terminal state

* feat(ui): show running project actions in terminal tabs

* feat(ui): run project actions from linked worktrees

* fix(ui): guard project action reconciliation

* fix(ui): scope project action preview fallback

* fix(ui): default project actions to worktrees

* fix(ui): reveal project action terminals

* fix(ui): retain terminal output after snapshot replay

* fix(ui): restore running action terminals on revisit
2026-09-05 12:04:36 +03:00
Bohdan Triapitsyn 58dfc789a2 fix(queue): clear the queue card after the last queued message is sent
When the server delivered the last item of a session's queue it deleted
the session entry and broadcast the update with an empty directory. The
UI keys its projection by directory, could not build the key, and dropped
the event, so the delivered message stayed in the "Queued messages" card
until the next full hydration.

The server now remembers a session's directory beyond the emptying of its
queue so that broadcast names it. The UI additionally treats an empty
session without a directory as "this session's queue is done" for every
projection keyed under that session id, which covers clients talking to
an older server.

Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
2026-09-05 11:21:39 +03:00
Bohdan Triapitsyn 7c9fdd1ee5 fix: complete goal resume and comment input follow-ups (#3361) 2026-09-05 10:53:34 +03:00
ChangeHow f3f844463b fix(ui): preserve IME composition in comment inputs (#3228)
Thanks for extending the existing IME handling to comment inputs and documenting the browser-event checks. We will also protect the annotation Escape handlers from cancelling composition.
2026-09-05 10:49:05 +03:00
ChangeHow df7e018e60 fix(chat): size markdown table columns by content (#3268)
Thanks for fixing the cramped table columns and covering the streaming-to-settled transition. The content-sized layout and horizontal scrolling look ready to merge.
2026-09-05 10:46:22 +03:00
Leonidandalvins82 c5086e0250 fix(session-goal): bound length recovery after truncation (#3278)
Thanks to alvins82 for tracing the truncation failure and to bashrusakh for adding bounded recovery and error precedence. We will finish the explicit Resume behavior in the same batch.

Closes #3255

Co-authored-by: alvins82 <alvins82@gmail.com>
2026-09-05 10:46:18 +03:00
ChangeHow 47e2049427 fix(ui): show send action in collapsed mobile composer (#3247)
Thanks for refining the action placement. This keeps New chat available while idle and preserves Abort while a response is running. We will finish the repository-specific cleanup in the same batch.
2026-09-05 10:46:13 +03:00
Leonid c8d8d4a384 fix(sync): paginate child session discovery to avoid >200 truncation (#3271)
Thanks for fixing the child-session discovery cutoff and covering the paginated discovery path with a provider-level regression test.
2026-09-05 10:46:09 +03:00
Bohdan Triapitsyn 260bfe666b fix: complete config path and review follow-ups (#3348) 2026-09-05 02:19:59 +03:00
tdoherty 0543b954c3 fix(web): honor XDG_CONFIG_HOME for OpenCode paths (#3305)
Closes #3304. Thanks for consolidating the global OpenCode paths. VS Code path parity and effective-path display follow-ups are maintainer-owned.
2026-09-05 02:14:26 +03:00
fitzgpt 64f9f3aba7 feat(vscode): localize loading splash and dev-server status for Turkish (#3303)
Thanks for filling in the Turkish bootstrap messages. Glossary and evidence-text follow-ups are maintainer-owned.
2026-09-05 02:14:21 +03:00
Leonid ec86d738e2 fix(vscode): stop gating list-derived permission auto-accept on the V2 preflight (#3318)
Thanks for fixing both permission reconciliation paths. The fetchPermission documentation follow-up is maintainer-owned; #3259 remains open.
2026-09-05 02:14:17 +03:00