Commit Graph
690 Commits
Author SHA1 Message Date
Iuliia Ivashko 20cda28cac fix(opencode): name the release when upgrading OpenCode
Since opencode 1.18.x, `POST /global/upgrade` requires a `target` semver in
the body. OpenChamber sent an empty object, so every "Update OpenCode" click
came back 400. The rejection arrives as `{name, data:{message}}`, which has
no `error` field, so the user was left with the bare status text: "Bad
Request".

Resolve the target from the latest release — the same lookup the upgrade
prompt already uses to decide there is anything to offer — and fail with an
explicit code when it cannot be resolved, rather than sending a body opencode
is guaranteed to reject. Read the upstream rejection message so a refused
upgrade explains itself.

The VS Code extension carries its own copy of this flow and had the same two
defects; both are fixed there.

fixes #3121
2026-08-28 18:48:27 +03:00
Iuliia Ivashko 01b3e3346f fix(git): check out a local tracking branch when a remote branch is picked 2026-08-28 15:45:43 +03:00
Bohdan Triapitsyn 06263a5c2b Merge pull request #3064 from fitzgpt/feat/i18n-turkish
feat(i18n): add Turkish (tr) locale
2026-08-28 11:33:52 +03:00
fitzgpt 83c2c7dc76 feat(i18n): add Turkish (tr) locale 2026-08-28 02:27:31 +03:00
Bohdan Triapitsyn b8465ae133 fix: harden and de-slop the merged contribution batch
Follow-ups promised on merge, plus review findings on the batch itself:

- chat: task-tool output now respects the 512KiB render cap; quick-open
  icon is visible at rest on coarse pointers and reachable by keyboard
  (row keydown no longer swallows inner-button Enter/Space); composer
  inline-code decoration drops the metric-shifting padding; a btw fork
  send carries only the boundary instruction, never the promotion notice
- sync: cascade revert/unrevert aborts busy descendants, busy state is
  read from every child store at the moment of use; rule 9 documents
  redo clearing all descendant revert markers
- electron: renderer recovery keeps memory-eviction (a valid
  render-process-gone reason) and both windows share one
  attachRendererRecovery helper
- vscode: process registry is a thin re-export of the web module
  (provider-env-aliases precedent) with ordered register/unregister
  writes and an awaited close
- server/cli: managed-process registry takes injectable deps (fixes the
  unreaped-orphans ReferenceError), corrupt settings errors name the
  file, getWorktrees test restores console.warn
- tests: module-mock harnesses removed (AgentsSidebar, SettingsView
  mobile focus — behaviors stay live but uncovered, accepted trade),
  QuestionMarkdown asserts rendered DOM
- i18n: German gains the debug-panel request keys, Japanese/German drop
  removed worktree keys, Ukrainian unit spacing fixed
- changelog: Copilot AI Credits entries (main + VS Code)
2026-08-28 02:08:09 +03:00
Bohdan Triapitsyn 98567cd6e0 Merge main 2026-08-28 01:27:32 +03:00
Bohdan Triapitsyn feba432407 Merge pull request #2784 from herjarsa/fix/silence-worktree-warning-for-non-git-dirs
fix(git): silence getWorktrees warning when directory is not a repo
2026-08-28 01:23:51 +03:00
Bohdan Triapitsyn 5854f43ca1 Merge pull request #2907 from jakoss/github-usage-rework
Align GitHub Copilot quota usage with AI credits
2026-08-28 01:23:40 +03:00
Bohdan Triapitsyn 0596af5761 Merge pull request #3000 from mpeter/fix/anthropic-small-model-base-url
fix(small-model): route anthropic provider through configured baseURL
2026-08-28 01:23:22 +03:00
Bohdan Triapitsyn d49ff426ab Merge pull request #2844 from sergiofspedro/fix/windows-port-release
fix: kill orphaned process on Windows before OpenCode restart
2026-08-28 01:23:04 +03:00
Bohdan Triapitsyn 285c63e238 Merge pull request #1946 from divyam234/fix/theme-runtime-symlink-themes
fix: load symlinked custom themes
2026-08-28 01:22:52 +03:00
Bohdan Triapitsyn 27be3f3193 Merge pull request #3038 from colinmollenhour/bug/Fix-External-OpenCode-Host-Recovery
fix(opencode): preserve external host during recovery
2026-08-28 01:22:23 +03:00
Bohdan Triapitsyn ef51b95749 Merge pull request #2171 from greghaynes/clever-heron
fix(web): shorten PWA install app name
2026-08-27 23:15:26 +03:00
Bohdan Triapitsyn fb9306745e Merge pull request #2774 from IngTian/fix/omit-thinking-config-non-reasoning
fix(small-model): omit thinkingConfig for non-reasoning Google models
2026-08-27 23:14:53 +03:00
Bohdan Triapitsyn af1706c6a7 Merge pull request #2995 from bashrusakh/fix/2763-opencode-binary
fix(server): keep env-provided OPENCODE_BINARY when settings clear the override
2026-08-27 23:14:10 +03:00
Bohdan Triapitsyn 50d97a78e5 Merge pull request #3051 from pascalandr/fix/3046-editor-font-size-persistence
fix(settings): persist editor font size
2026-08-27 23:14:04 +03:00
Bohdan Triapitsyn a2f55df211 Merge pull request #3066 from gaojunran/fix/branch-base-created-from-head
fix(git): don't treat bare HEAD as a branch diff base
2026-08-27 23:13:50 +03:00
Bohdan Triapitsyn 8d98ba3826 Merge pull request #3104 from fitzgpt/fix/non-ascii-directory-header
fix(server): percent-encode non-ASCII directory headers to OpenCode
2026-08-27 23:13:44 +03:00
Jakub Syty 22bd738180 Merge branch 'openchamber:main' into github-usage-rework 2026-08-27 10:06:53 +02:00
Ayoub Achour 61741e58c4 fix(tunnels): update cloudflared download link 2026-08-27 04:10:09 +01:00
Colin Mollenhour 2428d88907 fix(opencode): preserve external host during recovery 2026-08-27 01:10:06 +00:00
Bohdan Triapitsyn c4df01f707 chore(quota): drop the Command Code usage provider
Command Code's official API has no usage endpoints; the old usage source
was the unofficial studio API reached through a now-archived plugin, so
the tile could only ever fail for officially configured users. Removed
across server, shared UI, and the VS Code extension; the provider logo
fallback stays — it serves the model picker, not usage.
2026-08-26 19:29:04 +03:00
Bohdan Triapitsyn edec60faff fix(github): stop fork remotes from claiming the local branch's PR badge
PR-status source candidates were every configured remote, so a checkout
carrying contributor forks matched a fork's closed PR whose head merely
shared the branch name — a fork's 'main' surfaced on the local main in the
git and work-status panels. Only the ranked-first remote (the one the
branch pushes to) and its fork network are PR sources now; other remotes
remain search targets but their owner:branch heads no longer count.
2026-08-26 18:40:34 +03:00
Alexandre Reyes Martins 8ea94a119f fix: restore baseline validation (#3142) 2026-08-26 17:15:49 +03:00
Jakub Syty c3cb9ca157 Merge remote-tracking branch 'origin/github-usage-rework' into github-usage-rework 2026-08-26 14:00:20 +02:00
Jakub Syty 06a72fed3b Merge branch 'openchamber:main' into github-usage-rework 2026-08-26 13:58:58 +02:00
Jakub Syty 1459b4b360 Adjust for unlimited plan option 2026-08-26 13:58:31 +02:00
Matt Peter 56b5e9971f fix(small-model): don't double up /v1 in Anthropic baseURL override
Match @ai-sdk/anthropic exactly: baseURL is the full API prefix, so
/messages is appended as-is instead of unconditionally inserting /v1,
which broke configs where the baseURL already ends in /v1 (the common
form OpenCode itself passes to @ai-sdk/anthropic).

Addresses review feedback from @btriapitsyn on PR #3000.
2026-08-25 09:42:28 -04:00
Matt Peter f459206e4a fix(small-model): route anthropic provider through configured baseURL
The Anthropic small-model dispatch (session-assist recap/suggestion,
walkthrough, etc.) hardcoded https://api.anthropic.com/v1/messages,
ignoring provider.anthropic.options.baseURL — the same override every
other provider branch already respects. Any setup routing the anthropic
provider through a local proxy (e.g. Meridian for Claude Max / Vertex)
had the small-model call bypass the proxy and hit the real Anthropic API
with whatever placeholder credential the proxy config uses, failing with
401 invalid x-api-key on every call.
2026-08-25 09:42:28 -04:00
fitzgpt 89cfbd1b9a docs(server): note the encoded directory header in markdown image grants 2026-08-24 16:22:58 +03:00
Bohdan Triapitsyn 2f27f0ec4b fix(terminal): reconcile tabs with server sessions and keep shown terminals alive
The tab list lived only in per-tab sessionStorage, so a new browser
tab, another device, or cleared storage showed an empty terminal
sidebar while PTYs kept running server-side, and orphans leaked until
the idle sweep. Add GET /api/terminal/sessions and adopt unknown
server sessions into the local tab projection (additive only; a failed
listing changes nothing).

The idle sweep also reaped terminals in background tabs because only
the active tab holds a WebSocket attachment. Add POST
/api/terminal/touch and have open clients periodically refresh
activity for every session their tabs reference.
2026-08-24 14:30:00 +03:00
Bohdan Triapitsyn 97edd033f9 fix(relay): stop bystander instances from capturing the relay host
Two mitigations for local multi-instance contention over the shared relay
identity:

- A standby instance now waits a 2-minute grace period after the host claim
  frees before taking over, so a cleanly restarting host (app update or
  relaunch) — which reclaims at boot with no wait — always wins the restart
  window instead of stranding paired devices on another process.
- Dev instances never host the relay passively: dev scripts set
  OPENCHAMBER_RELAY_HOST=off and the Electron dev shell is detected via
  OPENCHAMBER_ELECTRON_DEV. Explicit enable/pairing on such an instance still
  force-claims; OPENCHAMBER_RELAY_HOST=on overrides.
2026-08-24 14:03:18 +03:00
Bohdan Triapitsyn 3aa45805bc fix(devices): keep the existing device name on re-pair and re-login
A dedupe-keyed client re-mint (QR rescan, password/passkey re-login) replaces
the stored record, which also reset the operator-visible name to the app's
hardcoded default ('OpenChamber Mobile'). The app-reported name is now only a
fallback: an explicit pairing label wins, otherwise the replaced record's
label is kept, and the default applies only to a first-ever pairing.
2026-08-24 14:03:18 +03:00
fitzgpt d6a5192fba fix(server): percent-encode non-ASCII directory headers to OpenCode 2026-08-24 02:21:35 +03:00
Bohdan Triapitsyn 2740c7b3a2 feat(projects): pin a thinking level next to a project's model
A project could pin the model new chats start on, but not the level to
run it at: the default cascade dropped any variant as soon as a project
model won, and only ever considered the global one — which belongs to
the global model.

Projects now carry `defaultVariant` alongside `defaultModel`, stored and
sanitized only next to that model, and the cascade passes it through.
Both controls sit in one "Defaults for new chats" group laid out like the
Sessions defaults, and the level appears only for models that offer them.
2026-08-22 20:31:31 +03:00
Bohdan Triapitsyn fcbe2c0414 fix(settings): clean up orphaned temp files and harden atomic writes 2026-08-22 11:55:38 +03:00
gaojunran a498d1935d fix(git): don't treat bare HEAD as a branch diff base
git switch -c / git checkout -b from the current branch record
'branch: Created from HEAD' in the reflog, but parseBranchCreationSource
only rejected 'HEAD@{...}' (detached start) and raw commit hashes. The
bare HEAD passed through, so getBranchBase returned { base: 'HEAD' }
and the branch scope computed diffs against HEAD itself, which is empty
when the service is checked out on that branch and wrong otherwise.

Treat bare HEAD like HEAD@{...}: no named source is recorded, so return
null and let the UI ask the user to pick a base.
2026-08-22 11:44:23 +08:00
Bohdan Triapitsyn 23928d342c feat(dictation): transcribe after recording instead of live
Parakeet is an offline model trained on whole utterances, so re-decoding
the growing buffer to animate a live transcript cost O(n^2) work for a
result the final decode replaced. Sessions now decode once per committed
segment, and the composer shows a scrolling waveform of the mic level
instead of running text.

Long dictations split at a pause once past 60s (hard cap 90s) instead of
on a blind 15s timer, so cuts no longer land mid-word. Committed segments
decode while the user is still speaking: a 185s dictation returns 4.1s
after stop instead of 11.0s, with identical text (816 vs 817 words).

Also fixes two ways the stream manager could silently drop transcribed
audio. It now counts the commits it issued instead of trusting the
session's echoed events, so a commit still in flight when the client
finishes can no longer be left out of the final text. And segment
byte/peak accounting is reset where the commit is issued rather than when
the event arrives, which could mistake the tail of a dictation for
silence and clear it.
2026-08-22 01:10:19 +03:00
Bohdan Triapitsyn 0d50253efa refactor(integrations): retire unavailable options
Remove retired Command Code, Discord, and Telegram integration entries, search targets, and documentation. Keep Command Code provider usage and logo support available through normalized provider ID aliases.
2026-08-22 01:10:19 +03:00
Bohdan Triapitsyn 0b01f5ae2d feat(diff): add branch scope to context panel diff view
Show every change on the current branch relative to its base in the
Changed/Staged/Last turn dropdown. The base comes from the branch's
reflog record or an explicit per-branch user choice (persisted), never
a main/master guess; when git has no record the user picks a base once
from a searchable branch list.

- server: GET /api/git/branch-base (reflog-derived base),
  GET /api/git/range-files (name-status -z with rename/copy
  destination paths and -C copy detection)
- shared UI: optional getBranchBase/getGitRangeFiles runtime APIs
  with boundary parsing; persisted per-branch overrides keyed by
  runtime+directory+branch
- DiffView: branch scope with confirmed-unavailability coercion of
  persisted tabs (detached HEAD, default-branch checkout, metadata
  settled without a default), range-invalidated diff cache guarded
  against stale completions, bounded branch-metadata retry, read-only
  diff actions in branch scope; hidden in VS Code
- helper module branchDiffScope.ts with tests for coercion,
  availability, race conditions, and retry exhaustion
2026-08-22 01:10:19 +03:00
Tom Rochette a79ae57ae5 fix(ui): scope file-reference stat probes to the session directory (#3022)
* test: add regression test for stat directory scoping (#3019)

* fix: scope file-reference stat probes to the session directory (#3019)

The /api/fs/stat probe sent by the markdown renderer carried no
directory hint, so the server resolved the workspace from
settings.lastDirectory. When the browsed directory differs from the
session directory the stat returns 400 and the renderer treats it as
file-does-not-exist, silently disabling file-reference links.

Send effectiveDirectory as x-opencode-directory on the probe and
qualify the stat cache key by directory so a rejection under one
directory cannot leak into another. The probe logic moves from
MarkdownRendererImpl into fileReferenceStat with unit coverage.
2026-08-21 16:48:32 +03:00
Bohdan Triapitsyn b879cf323f feat(sidebar): add single-project display mode 2026-08-21 16:25:51 +03:00
Pascal André ac41d4e8c9 fix(settings): persist editor font size 2026-08-21 11:57:59 +02:00
Bohdan Triapitsyn 9e87d7fdb9 feat(chats): add managed projectless chat sessions
Create projectless chat sessions under a managed, date-scoped Chats directory and clean abandoned or deleted session folders.

Add Chats to sidebar state, startup cache, shared context, and Electron Mini Chat while keeping VS Code project-only. Resolve managed chat directories to one server-side memory owner and document the runtime contracts.
2026-08-21 12:12:40 +03:00
Jakub Syty a3d20512a0 Refactor application architecture and shared functionality 2026-08-21 10:59:47 +02:00
Bohdan Triapitsyn 3613127e2d fix(quota): support z.ai credit limits 2026-08-20 19:09:13 +03:00
Bohdan Triapitsyn 647a949369 feat(providers): support custom API protocols 2026-08-20 18:39:13 +03:00
Bohdan Triapitsyn 1ed3f1f575 feat(skills): curated GitHub catalog redesign (#3016)
* feat(skills): remove ClawHub catalog integration

Drop the ClawHub registry as a skills catalog source across web server,
shared UI, VS Code, docs, and locales. The catalog now serves git-based
sources only: the curated Anthropic repo and user-defined repositories.
Also removes the now-unused adm-zip dependency.

* feat(skills): redesign catalog around curated GitHub repositories

Replace the single-source dropdown with a card grid of curated GitHub
repositories (Anthropic, OpenAI, Cursor pstack/skills, Matt Pocock) plus
user-defined sources. Source cards show skill counts, GitHub stars, and
last-updated time; a global search covers all loaded sources.

Server: curated sources gain GitHub repo metadata (stars, pushed_at)
fetched best-effort with a 3-hour in-memory and on-disk cache; scans
run through a concurrency-limited, deduplicated cache with 3-hour TTL
persisted across restarts. Refresh still bypasses the cache.

Shared UI: source cards, global search with clear button, per-skill
GitHub links, install/installed states. VS Code curated list updated
to match. All new copy translated across 12 locales.

* fix(skills): address catalog review findings

- GitHub metadata fetch timeout drops to 1.5s (under the catalog
  client's 3s deadline) and failed lookups cache briefly (5 min) so
  repeated catalog loads do not re-hit a failing API.
- Disk cache files are written with owner-only permissions (0o600);
  rename preserves the mode.
- loadSource deduplicates concurrent in-flight requests per source and
  the shared isLoadingSource flag now clears only when the last active
  source load finishes.
2026-08-20 01:40:10 +03:00
Bohdan Triapitsyn 6a09c63392 feat(small-model): resolve plugin-registered providers from the running OpenCode
Plugin providers are registered from a plugin's `config` hook and credentialed
from its `auth` loader, both inside the running OpenCode process. Nothing about
them reaches `opencode.json` or `auth.json`, so resolution that only reads files
could not see them: selecting such a model failed with "has no known API base
URL" while the same model worked in chat (#2666).

`GET /provider` is where that state is visible. A new `runtime-providers`
module keeps one cached snapshot of it and reports, per provider, the
credential and endpoint OpenCode itself resolved. Credential resolution becomes
config -> runtime -> auth.json, and endpoint resolution config -> openai default
-> runtime -> models.dev catalog.

Providers with a dedicated wire format (Copilot, ChatGPT-plan OpenAI, Anthropic,
Google) are excluded from the runtime credential: for them OpenCode reports an
OAuth access token that their real transport does not accept.

opencode zen is excluded when the user has no zen login. OpenCode then reports
the sentinel `apiKey: "public"` and trims its catalog to free models that run on
its own infrastructure; the sentinel is never read as a credential.

Claude Code stays refused for background actions even when a plugin publishes an
OpenAI-compatible endpoint for it, because that endpoint is a facade over the
Claude Agent SDK and spawns the CLI per request.

No capability probe. Asking `GET /models` does identify a plugin whose protocol
lives in its own `fetch`, but measured across the 166 providers with an `api`
URL in the models.dev catalog it also denies six that work and simply have no
`/models` route. A provider that vanishes from the picker explains nothing,
while one that fails on use says why, so availability stops at credential and
endpoint.

The same list drives the Small Model and Changes Walkthrough pickers.

Validated against a real OpenCode with four plugin providers loaded: offered
providers went from 3 to 7, zen and Claude Code stayed out, and a generation
through a plugin-backed model that previously failed now returns.
2026-08-20 00:47:34 +03:00
Serhii Dziupin 14d7a0ca9b fix: settle busy sessions after managed OpenCode restart (#3002)
* fix: reconcile busy sessions after managed OpenCode restart

Forced health-check restarts previously rebound the event stream without
settling in-flight turns, so sessions stayed busy with no terminal state.
Interrupt those sessions, classify health failures, and retain bounded
process diagnostics for post-restart diagnosis.

Fixes #2943

Co-authored-by: serkraser <serkraser@gmail.com>

* fix: surface interrupted chats after OpenCode restart

Complete unfinished assistant turns as aborted once the session is
authoritatively idle, and show a persistent toast so users can continue
instead of remaining silently stranded.

Fixes #2943

Co-authored-by: serkraser <serkraser@gmail.com>

* fix: redact Basic auth credentials in restart diagnostics

The key/value sanitizer stopped at whitespace, so Authorization: Basic
credentials survived in stderr tails and health snapshots. Redact the
scheme token before that rule runs.

Co-authored-by: serkraser <serkraser@gmail.com>
2026-08-19 11:53:30 +03:00