Commit Graph
844 Commits
Author SHA1 Message Date
Serhii Dziupin 746e0d4abd Merge pull request #2617 from openchamber/feat/unexpected-message-content-edbc
fix(walkthrough): replace raw provider-login error with a readiness blocker
2026-08-04 17:33:48 +03:00
Cursor AgentandSerhii Dziupin 460675f57e Merge origin/main into deferred OpenCode restart branch.
Adopt main's providerAuth helpers (OAuth index preservation, OAuth-only API
key hiding, always-load auth methods) while keeping deferred Apply & Restart
for provider mutations.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-04 13:29:46 +00:00
Cursor AgentandSerhii Dziupin 65a1eec782 fix(ui): keep manual model override after delegated subtask completes
Synthetic subagent-completion nudges were treated as the latest user model
choice and rehydrated the agent default, while setAgent preferred the agent
pin over the session override. Skip synthetic prompts for restore, preserve
manual selection-store overrides, and prefer session agent models in setAgent.

Closes openchamber/openchamber#2404

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-04 12:46:48 +00:00
Cursor AgentandSerhii Dziupin 35f17e9e96 fix(walkthrough): hide unauthenticated models and disable Generate
Do not present a provider without a login as the selected walkthrough
model, and grey out Generate when readiness is false instead of showing
a login-error blocker or raw auth banner.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-04 12:22:54 +00:00
Cursor AgentandSerhii Dziupin 29420a7e7e fix(ui): rename large paste toast to Large text detected
Use clearer toast title copy across all locales.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-04 12:15:01 +00:00
Cursor AgentandSerhii Dziupin 471d0a8ecb fix(ui): neaten large text paste toast
Drop the grey description and info icon, and widen the toast so the
title and two actions sit on one clean row.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-04 11:57:38 +00:00
Cursor AgentandSerhii Dziupin ef11ab5b14 feat(ui): attach large text pastes as virtual files
Offer to turn sufficiently large plain-text clipboard pastes into
pasted-context-N.txt attachments instead of inserting them into the
composer, with ask/attach/inline composer settings.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-04 11:38:02 +00:00
Cursor AgentandSerhii Dziupin 2b67be0a07 fix(ui): prevent shiki template-call OOM on backtick JS
Neutralize the catastrophic TextMate template-call lookahead when loading
JS/TS grammars in the markdown Shiki worker, and terminate hung highlight
requests after 5s so unbounded Oniguruma WASM matching cannot OOM the
renderer (openchamber/openchamber#2587).

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-04 11:35:42 +00:00
Cursor AgentandSerhii Dziupin abb396e080 fix(walkthrough): block unauthenticated providers with a friendly refusal
When the walkthrough small model resolves to a provider with no usable
login, readiness was still ready and generate returned a raw 500 message.
Refuse up front with no-provider-login and surface a blocker instead.

Closes openchamber/openchamber#2607

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-04 11:29:58 +00:00
Serhii Dziupin f47110c66f Merge pull request #2616 from makeittech/feat/restore-archived-sessions-2346
feat: add restore/unarchive for archived sessions
2026-08-04 13:41:00 +03:00
Serhii Dziupin 932d224916 feat: add german translations for session restore 2026-08-04 13:29:03 +03:00
Serhii Dziupin 577aca0437 feat: add restore/unarchive for archived sessions
Archived sessions had no way back to the active list: the only available
action was "Delete permanently". Add restore per session (sidebar context
menu, Archive page row) and in bulk (sidebar selection bar).

The OpenCode server cannot clear time.archived over HTTP — session.update
only applies the field for a finite number, so an omitted key is a no-op
and null is silently ignored (verified against opencode 1.18.12). Restore
therefore writes time.archived = 0: every client-side reader classifies
archive state by truthiness, so 0 reads as active in the UI, the event
reducer, and the OpenCode app/TUI.

The server's time_archived IS NULL list filter still excludes such rows,
so the global session cache no longer issues an archived:false request
for its active list. Full and per-directory loads now fetch once with
the inclusive flag and split client-side via splitGlobalSessionsByArchived,
which also halves per-directory refresh requests. Directory bootstrap
keeps the server filter because live child stores must not hold archived
sessions; a restored session re-enters its live store through the
authoritative session.updated event.

unarchiveSession/unarchiveSessions follow the archiveSession contract:
wait for server confirmation before reconciling stores, runtime-guard
every reconciliation, preserve partial batch results, and fail loudly
when the server keeps the session archived instead of toasting a
successful no-op.

Closes #2346
2026-08-04 13:21:04 +03:00
Serhii Dziupin 397b9840b7 Merge pull request #2595 from openchamber/feat/ctrl-l-add-selection-to-chat-58c2
feat(ui): Ctrl/Cmd+L adds selected text to chat
2026-08-04 11:33:51 +03:00
Bohdan Triapitsyn 540d2ae46a fix(sync): render sessions in worktrees created while the client is running #2603 2026-08-04 02:05:29 +03:00
Bohdan Triapitsyn 3aeca4893e docs(sync): correct the ownership precedence the fix inverted
Review found the owning documentation still describing the behaviour this
branch replaced, in one case stacked directly above the new docstring saying
the opposite. Holding a session proves containment, not ownership, so every
text that called store membership the authoritative mapping was actively
misleading for the module whose wrong answer misroutes every send.

Corrected in the module docstring, the resolution module's precedence
description, the sync-refs helper it points at, and the sync DOCUMENTATION.md
table and rules.

The debug report built its authoritative value membership-first, so for exactly
the scenario this branch fixes it reported the parent directory and could raise
a source-disagreement alert while routing was in fact correct. It now uses the
same record-first order as the resolver.

The CLI timeout comment claimed the wait and provisioning windows were additive
while the code took the larger of the two. The server provisions the worktree
inside session creation, before it waits for the session to go idle, so they do
run in sequence: the windows are now summed and the tests pin both cases.
2026-08-04 01:50:14 +03:00
Bohdan Triapitsyn baeefe1ae5 fix(i18n): add German download label 2026-08-04 01:37:48 +03:00
Bohdan Triapitsyn a7b61506dc style: adjust openchamber dark theme colors
Softens the dark surface and syntax background tones
Updates foreground, selection, and cursor contrast
Keeps markdown, chat, and tool text aligned with the new palette
2026-08-04 01:37:03 +03:00
Bohdan Triapitsyn 1684e6f660 fix(files): hide desktop-only reveal action in browser clients #2597
fix(files): hide desktop-only reveal action in browser clients
2026-08-04 01:35:57 +03:00
Bohdan Triapitsyn 12a7d83dd1 Merge remote-tracking branch 'origin/main' into performance-improvements 2026-08-03 23:40:41 +03:00
Bohdan Triapitsyn fe38f7a56b fix: treat lost relay sends as ambiguous instead of failed
A prompt whose response is lost after the request left the client may
already be running server-side. The relay tunnel reported those failures
as plain text errors ("stream aborted by host", "relay keepalive
timeout"), which matched none of the patterns in isAmbiguousSendFailure,
so an accepted prompt was rolled back and the message queue re-sent it —
two independent AI responses for one user message (#2425). Direct
connections never hit the path.

Transports now tag dispatched-but-unconfirmed failures and the classifier
reads the tag before falling back to status/text heuristics. Confirmation
waits for the connection to actually return (bounded) and retries with
backoff instead of two attempts 150ms apart over the just-broken tunnel.
2026-08-03 23:09:43 +03:00
Bohdan Triapitsyn 1cc5cfedbb feat: add DeepSeek quota provider #2594 2026-08-03 18:37:31 +03:00
Cursor AgentandSerhii Dziupin 682c42df8f fix(ui): harden Ctrl+L selection capture and menu delivery
Cover CodeMirror and DOM capture paths in tests, collapse text-control
selections after capture, and deliver the desktop Edit-menu action over
a single IPC channel so append cannot double-fire.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 14:24:22 +00:00
Serhii DziupinandClaude Sonnet 5 f02969548a fix(files): hide desktop-only reveal action and label download in browser clients
Reveal-in-file-manager was always offered whenever the server exposed
revealPath, including in a plain browser tab where there is no local
file manager to reveal into. Gate it behind a new isBrowserClientRuntime
check (web platform, no Electron shell) and relabel the save action to
"Download" for that case, since it triggers a browser-style file
download rather than an in-place save.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 17:11:41 +03:00
Cursor AgentandSerhii Dziupin ead9aad33b Merge origin/main into deferred OpenCode restart branch.
Resolve ProvidersPage and lifecycle conflicts with custom providers and
AppImage ARGV0 stripping. Address review follow-ups: OAuth index helper +
tests, single auth-methods load trigger, shared Google env-alias module with
VS Code parity coverage, and deferred restart for custom provider upsert.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 13:57:05 +00:00
Bohdan Triapitsyn 107fe45248 perf(runtime): cache the derived runtime key
`getRuntimeKey` keys caches, stores, and persisted state across the whole UI,
so it runs on store reads, event handling, and render paths. Until the runtime
endpoint is explicitly initialised, every call re-derived the key by trimming
two injected globals and constructing three URL objects.

In a streaming capture this made `readInjectedLocalOrigin` the single most
expensive application function: 315 ms of self time, 12% of all main-thread
busy time. After the change it does not appear in the profile at all, and the
same capture went from two long tasks to none, with the longest task dropping
from 210 ms to 47 ms.

The key depends only on the active API base URL and two injected globals, and
`switchRuntimeEndpoint` writes the injected API base URL at runtime, so the
cache is validated against the raw untrimmed values rather than memoised
outright. That comparison allocates nothing and still recomputes as soon as any
input changes. Tests cover both directions, including an operation-count
assertion that repeated calls construct no URLs.

The streaming profiler also reports output-normalised metrics, because response
length varies between runs and makes per-second totals incomparable.
2026-08-03 15:31:22 +03:00
Serhii Dziupin 9289dea4a0 Merge pull request #2586 from openchamber/feat/skill-renaming-content-preservation-c1d5
fix(skills): preserve SKILL.md content when renaming
2026-08-03 15:04:48 +03:00
Cursor AgentandSerhii Dziupin 3ad3f21024 feat(ui): add Ctrl/Cmd+L to send selected text to chat
Bind mod+l to append the current selection into the chat composer
(Cursor-style), and move session sidebar toggle to mod+alt+l so desktop
menus stay in sync. Closes #208.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 12:04:35 +00:00
Howon Lee 2dd3bbfe8e feat: add DeepSeek quota provider 2026-08-03 20:46:32 +09:00
Bohdan Triapitsyn 7d311d99c9 feat: add custom/other OpenAI-compatible LLM providers #2571 2026-08-03 13:21:45 +03:00
Cursor AgentandSerhii Dziupin 5b9a8c4bef merge(main): resolve skills.test.js import conflict
Keep both discoverSkills from main and renameSkill from this branch.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 09:55:56 +00:00
Cursor AgentandSerhii Dziupin 3cb02439ea Add German pendingRestart locale keys after main merge.
de.settings.ts came from main without Apply & Restart strings;
add translations so i18n key parity stays intact.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 09:52:24 +00:00
Bohdan Triapitsyn 2c52240f8e fix(sync): route sessions by server-confirmed directory, unstick queued sends
Session directory resolution had no precedence contract: the selection-time
directory short-circuited every lookup, and a persisted runtime value was
consulted before the authoritative record. A worktree session selected before
its directory store bootstrapped kept the active-directory fallback, and that
guess was persisted, so it survived reloads and restarts.

Directory resolution now lives in one module and orders sources by whether the
server confirmed the path, not by whether the value is local or synced:
authoritative (the child store that holds the session) > server-confirmed
selection > worktree attachment/metadata (the requested path, pre-canonical) >
remembered. A guessed selection is no longer persisted, remembered, or ranked.
Chips read the same resolution the composer used, so queue keys cannot diverge.

Queued auto-send could strand an item indefinitely: backoff, missing send
configuration, and the recent-abort window all returned without scheduling a
wake-up, so the queue only retried when an unrelated status or directory change
re-ran the effect. A retry scheduler now wakes it at the earliest known time.

A rejected send rolls the optimistic message back while the composer stays
silent for transport failures, which makes it indistinguishable from nothing
happening. Failures are now recorded to a bounded in-memory log surfaced in the
About diagnostics report, alongside a directory-resolution breakdown, plus
__opencodeDebug.diagnoseSessionDirectory() and getRecentSendFailures().

Prompted by a report of worktree prompting silently failing. That failure was
not reproduced locally, so the diagnostics are what will identify it.
2026-08-03 12:51:12 +03:00
Serhii Dziupin 94c9ac3153 Merge pull request #2592 from openchamber/terminal-open-debug
fix(terminal): start PTY before viewport mounts without dropping output or replies
2026-08-03 12:50:19 +03:00
Serhii Dziupin 88937ade72 fix(terminal): start PTY before viewport mounts without dropping output or startup replies
Terminal creation no longer waits for the Ghostty viewport to report its
size: it starts the PTY immediately with a container/font-derived
provisional size (falling back to 80x24), then resizes once the real
viewport dimensions are known, with a dedupe guard while sizing settles.

Starting the shell earlier means it can emit device/theme queries before
a browser terminal is attached to answer them, so the server now answers
primary device attribute queries itself (Fish blocks ~10s on this at
startup) and bun-pty buffers output emitted before a data subscriber
attaches. Also fixes a few WebSocket transport reconnect races surfaced
by session creation now overlapping renderer setup.
2026-08-03 12:29:32 +03:00
Cursor AgentandSerhii Dziupin c070b9c53b Merge origin/main into deferred OpenCode restart branch.
Resolve skills store conflicts by keeping repository-local directory
resolution from main and deferred-restart handling from this branch.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 09:26:57 +00:00
Cursor AgentandSerhii Dziupin ebf1b027cc fix(i18n): add German strings for custom LLM providers
Merge of main brought the de locale without the custom-provider keys
added on this branch, which broke the UI build type cast to I18nDictionary.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 08:56:23 +00:00
Cursor AgentandSerhii Dziupin 0cde9e9413 Fix deferred restart review findings.
Drop phantom pending records when provider disconnect removes nothing
and when Behavior AGENTS.md payloads are not deferred. Clear the Apply
badge after external OpenCode manual-restart guidance. Align skills and
commands save toasts with deferred restart feedback, and fix French
OpenCode elision.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 08:56:05 +00:00
Cursor AgentandSerhii Dziupin bfea13ef1d fix(skills): harden rename to managed roots and cover failures
Restrict in-place skill rename to managed skill directories, require
frontmatter name to match before moving, roll back/reject with tests,
hide rename in the UI for unmanaged paths, and drop unused toast keys.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 08:54:29 +00:00
Cursor AgentandSerhii Dziupin 094fb4fc40 merge main to pick up German locale for custom provider keys
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 08:53:06 +00:00
Cursor AgentandSerhii Dziupin 72b0d9b90f Shorten Apply & Restart action label
Drop OpenCode from the Settings footer apply button and confirm title so
the action fits the narrow nav and stays concise.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 07:35:31 +00:00
Cursor AgentandSerhii Dziupin 096f2fa52c Move Apply & Restart into Settings footer with confirm
Replace the top-right pending CTA with a primary footer action that
replaces Reload OpenCode when changes are pending, and warn that running
chats will stop unless the user opts out of the confirmation.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 07:25:10 +00:00
Cursor AgentandSerhii Dziupin f0591515fd fix(skills): preserve SKILL.md content when renaming
Rename skills by moving the skill directory and updating frontmatter
name instead of recreate-with-stub-description, which wiped the body
and supporting files.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 07:02:24 +00:00
Cursor AgentandSerhii Dziupin 57819dd164 Accumulate OpenCode settings restarts behind Apply & Restart
Defer OpenCode reloads after settings mutations, track pending changes,
and expose a top-right Apply & Restart OpenCode action with a counter so
sessions stay available until the user explicitly applies.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-03 06:56:38 +00:00
Bohdan Triapitsyn 82c540b9a3 feat(i18n): complete German localization 2026-08-03 02:26:52 +03:00
Bohdan Triapitsyn b7b4c089de Merge remote-tracking branch 'origin/main' into feat/german-locale 2026-08-03 01:57:04 +03:00
Bohdan Triapitsyn 1d17cb87b3 feat(walkthrough): write walkthroughs in the reader's language
A guided explanation is only useful in a language the reader reads, so the
panel header gets a language picker alongside the model one, defaulting to
the interface language. Like the model, it is request state rather than a
setting: the language travels with the read and the generation, and the one
a walkthrough was written in is stored with it, so reopening a review
describes what is there instead of what a fresh one would be.

Only prose is translated. Hunk aliases resolve back to hunk ids and
icon/importance are validated against fixed English values, so a translated
one would be dropped by the normalizer — silently losing an anchor or a
style. Identifiers and paths stay as they appear in the code.

The language is part of the cache key, and a read now asks the cache for the
exact request it was given before falling back to the pointer. Without that
the panel answered a request to switch languages with the text it already
had, leaving the other language unused in the cache.

Alongside it:

- The answer budget is derived from the resolved model instead of a flat 24k.
  That number was the same for a 64k-context model and for one that admits to
  384k output tokens, and on the latter it was the only reason generation
  failed: the model spent the whole allowance reasoning and returned nothing.
  It is now min(96k, max(24k, a quarter of the context)) capped by the
  catalog's output limit, decided once so the input reserve and the request
  cannot drift apart.
- A read no longer offers Cancel. It is a few hundred milliseconds of git with
  nothing to cancel, and the button flickered on every model or language
  change. When the panel is showing a fallback, a banner names what is on
  screen versus what was asked for — only once the read has settled.
- The header keeps one 32px control height and drops its labels below 680px
  instead of squeezing them to two letters and an ellipsis.

Docs and module documentation updated in every locale.
2026-08-03 01:27:27 +03:00
Bohdan Triapitsyn 0d83ebfeba fix(ui): align context surface icons 2026-08-02 23:23:04 +03:00
Bohdan Triapitsyn 17c2d5ec36 fix(ui): keep diff refreshes targeted 2026-08-02 21:46:22 +03:00
Bohdan Triapitsyn 89399ec1c2 fix(ui): simplify walkthrough action label 2026-08-02 21:17:39 +03:00
Bohdan Triapitsyn 9d48d5d02b fix(git): clean up in-progress merge/rebase banner
Use the real status-warning tokens (--status-warning-bg did not exist, so
the card rendered without a fill), drop the decorative icons, and fold the
conflict count into the title as a single full-message key per locale.
The operation description now wraps instead of truncating, and both the
conflict and ready-to-continue states share the same action layout.
2026-08-02 20:27:05 +03:00