Commit Graph
961 Commits
Author SHA1 Message Date
Alex Kutas 49f0a9e62f OPE-296: Add linear integration for starting sessions from issues (#3235)
* feat(linear): start sessions from Linear issues
Authorize a Linear workspace on this OpenChamber server, map teams to
projects, attach an issue from chat, start a session or worktree from an
issue, and post started/completed/failed comments that open the session.
Hidden in VS Code.

* feat(linear): connect more than one Linear workspace

Store each OAuth grant on this OpenChamber server and keep one current, so Settings can add and switch workspaces without dropping the others. Project mapping is per workspace. Remove the Linear button next to New Chat; start-from-issue stays on New Worktree.

* feat(linear): add a right-hand issues panel

Browse and filter issues in the rail, open a card to change status or start a session, and collapse search plus most filters to icons on a narrow panel.

* feat(linear): open issues in the rail and filter by Linear status

The rail icon only shows after Linear is connected. Clicking a Linear row on work status opens the panel. Status options match the card, including Done, Canceled, and Duplicate. The Integrations experimental warning sits under Third-party integrations.

* fix(linear): use stable OAuth callback broker

* fix(chat): preview Linear issue attachments

The context switch missed linear-issue, so tsc treated the preview helpers as incomplete.

* fix(ui): restore Linear i18n parity and the #2903 sync harness

Turkish was missing the Linear dictionaries, and the subagent test still wrapped only SyncContext after reads moved to SyncRuntimeContext.

* fix(linear): drop changelog hunks and close review races

Keep changelogs out of this PR, restore CodeMirror ranges, ignore stale Linear list pages, and leave a persisted Linear tab open until auth has actually resolved.

* fix(linear): tint active issue filters and clear them in one click

* fix(markdown): read escaped brackets as text, not display math

`\[...\]` is display math in LaTeX and an escaped bracket pair in
CommonMark. The block tokenizer claimed every `\[`, so prose like
`[title \[Bug\] more](url)` was handed to KaTeX: "Bug" rendered as a
centered formula and the block token split the paragraph, tearing the
link into three pieces. Linear, GitHub and any other source that escapes
brackets the way CommonMark requires hit this.

Display math now has to own its line — `\[` starts one and `\]` ends
one. A formula on its own line still renders; `\[` mid-sentence stays an
escape, which is what CommonMark says it is and what prose almost always
means. Inline `\(...\)` keeps the same ambiguity, but inline math is
legitimately mid-sentence, so there is no position to judge it by.

Covered by regression tests, including the verbatim comment body that
surfaced this.

* feat(linear): make session status comments opt-in and public-only

A status comment lands in a Linear workspace the whole team reads, and
the link it carried pointed at whatever origin started the session —
usually loopback or a LAN address. Everyone but its author got a dead
link, and nobody had agreed to the comments in the first place.

Comments are now off until the user turns them on in Settings ->
Integrations -> Linear, and the check lives on the server: the event hub
posts completed and failure without going through the interface, so a
client-side gate would not hold. When the resolved origin is not
publicly reachable the server posts nothing at all rather than a link
only its author can open; `isPublicSessionOrigin` rejects loopback,
private LAN, carrier-grade NAT, link-local and single-label hosts. The
desktop deep-link origin is gone with it, since no one else can follow
one either.

The comment body also dropped the session title. It repeated the issue
the comment already sits on, and issue titles routinely carry brackets
("[Bug] ...") that broke the markdown link. The body is now one short
link, and `sessionTitle` is gone from the route, client and types.

Also caps the dedupe file at the newest 500 sessions; it grew forever.

* fix(linear): match the pull request panel and clear review findings

Comments in the Linear panel now render as the same avatar timeline the
pull request panel uses, with the shared time-format preference instead
of a raw locale string. Comment authors carry `avatarUrl`, which the
GraphQL selection was not requesting.

Review findings from the same pass:

- `status-runtime.js` hand-rolled `typeof` narrowing and failed the
  vendored anti-slop lint; it now parses through `parse.js` like every
  other file in the module.
- `useLinearAuthStore` turned any failed request into `connected: false`
  with `hasChecked: true`. Since the rail icon, the composer entry and
  the worktree option all gate on `connected === true`, one network blip
  hid Linear for the rest of the session, and Settings only re-checked
  when it had never checked. It now keeps the last known status and
  leaves `hasChecked` false so the next caller retries.
- `LinearIssuesView` (1096 lines) was a static import in `ContextPanel`,
  shipping in the main bundle although its rail icon stays hidden until
  a workspace is connected. It is lazy now, like `GitView`.
- Dropped dead code: the unused port helpers left over from the loopback
  callback, two re-exported default values nothing read, and a redundant
  export in `linkedIssues`.
- Integrations is no longer badged beta.
2026-08-30 02:18:40 +03:00
Bohdan Triapitsyn 9963e6e3b7 release v1.21.1 2026-08-29 13:20:21 +03:00
Bohdan Triapitsyn 8aba30ac43 revert: stop forwarding the Small Model override into the managed OpenCode config
Reverts #2687. In real use the injected small_model behaves poorly with
OpenCode: its internal small-model consumers and OpenChamber's own small
model are different things and must stay configured separately.
2026-08-29 01:14:02 +03:00
Bohdan Triapitsyn 48bcac1758 fix: harden and de-slop the merged sidebar/chat/settings batch
Post-merge follow-ups for #2740 #2735 #2734 #2690 #2676 #2738 #2684
#2689 #2733 #2739 #2462 #2687 #2736 #2618 #2697, plus three regressions
found while reviewing them:

- ctrl/cmd+digit while typing no longer switches session tabs (#2503 was
  still open in practice: the guard only covered the mod+alt surface binding)
- Shiki template-call sanitizer now covers every bundled grammar, including
  the js/ts aliases and embedding grammars; timed-out highlight requests are
  memoized and no longer cancel unrelated in-flight requests
- settings flush on suspend uses keepalive and also fires on Capacitor
  appStateChange; keeps the selected model persisted across mode switches
- remote-only branches fetch before checkout; range helpers fail clearly
- git status invalidation now fires for runtime adapters too
- settings number inputs and select triggers size in ch so they scale with
  the interface font
- recent-activity timestamps tick from one list-level ticker
- Markdown preview find goes through the shared find_in_file keybind with
  containment, no longer counts its own bar, and debounces observer runs
- #2676 reverted; #2524 fixed by fading the sticky header's own background
  instead of overlaying the content below it
- sticky group headers in the model picker and sidebar render again
  (oc-sticky-fade-scroller class restored after 9b9d7069c)
- project switcher names are left-aligned again (wrapper lost in 26dbc2f30)
- tool card quick-open icon is always visible and opens the same line as the
  expanded card's button
- tautological tests replaced or removed; new oxlint findings fixed
2026-08-29 01:06:43 +03:00
Bohdan Triapitsyn 3e0a9622aa refactor(server): own the requested project directory in the runtime
Drop the canonical-containment 403 guard and the extra realpath(base) the
read routes (stat/read/raw/serve) had gained. Every workspace resolution
returns insideWorkspace: true and outside-file grants use
base = dirname(canonicalPath), so the guard could never fire; the flag had
no remaining reader and is gone with it. The read routes are back to the
single realpath(resolved.resolved) they had before.

Move the lexical-base fallback out of the inline header parsing in
routes.js. x-opencode-directory decoding belongs to
project-directory-runtime, so resolveProjectDirectory now also returns
requestedDirectory, the pre-realpath candidate that validated.
resolveWorkspacePathFromContext retries against it when the canonical base
rejects a path, which keeps files under a symlinked project root
addressable without a second copy of the header/query parsing.
2026-08-29 00:53:06 +03:00
Bohdan Triapitsyn 55ae41bde2 Merge remote-tracking branch 'origin/main' into port-2872 2026-08-29 00:48:36 +03:00
Bohdan Triapitsyn 2a5a25d5a2 fix(small-model): harden configured headers 2026-08-28 23:50:04 +03:00
Dmitrii 3903cb53b1 fix(small-model): send configured provider headers (#3214)
readProviderConfig read only options.baseURL and options.apiKey, and the
OpenAI-compatible dispatch hardcoded a bearer token, so provider
options.headers never reached the request. OpenCode sends those headers on
every chat turn, which left the small model authenticating differently from
the request path against the same URL.

Providers behind a gateway that authenticates on its own header, such as the
Ocp-Apim-Subscription-Key default of Azure API Management, answered 401 for
walkthroughs, session goal audits, titles and commit summaries while the same
model worked in chat.

Read options.headers alongside the API key, resolve {env:...} and {file:...}
in the values with the existing resolveConfigApiKey, and merge them into the
request after the bearer default so a gateway whose header is the credential
can override it.

Closes #3213
2026-08-28 23:46:05 +03:00
Bohdan Triapitsyn ac1881fab7 fix(server): forward Small Model override to managed OpenCode config
The Small Model override chosen in Settings never reached the managed
OpenCode process config, so OpenCode's own title/summary generation
kept using its fallback chain instead of the user's explicit choice
and sessions stayed untitled.

Merge main into this branch to pick up the includeWeb/includeMemory
flags added to prepareManagedOpenCodeEnv, and re-apply the Small
Model injection on top of that current env shape in
getManagedOpenCodeEnv (server/index.js).

Closes #2497
2026-08-28 23:45:04 +03:00
Bohdan Triapitsyn 9e5890729c fix(git): include remote-only branches from ls-remote in branch lists (#2735)
fix(git): include remote-only branches from ls-remote in branch lists
2026-08-28 23:40:58 +03:00
Bohdan Triapitsyn 1151c40f13 fix(server): bound login-shell probes so a slow rc file cannot stall startup
Merge main and reduce the change to the defect that reproduces: the server's
synchronous login-shell probes (env snapshot and command -v for opencode,
node, bun) ran with no timeout, so a slow or interactive rc file held startup
until it returned — on macOS that is what made a brew-installed opencode look
undetected from a Dock launch. Every probe now carries the same 5s bound the
Electron shell probe already uses and falls through on overrun; the known
install locations already include both Homebrew prefixes.

The non-login command -v fast path and the reproduction script are dropped:
a plain sh inherits the same PATH the resolver has already walked.

Closes #1720
2026-08-28 23:23:16 +03:00
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
Bohdan Triapitsyn f551f4e784 Merge pull request #3205 from openchamber/fix/branch-selector-remote-checkout
fix(git): check out a local tracking branch when a remote branch is picked
2026-08-28 16:21:40 +03:00
Bohdan Triapitsyn 5871c36875 chore: bump @opencode-ai/sdk to 1.18.25 2026-08-28 16:01:07 +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
herjarsa 256722eeea fix(server): drop /api/fs/list hunk per btriapitsyn review
Main already returns entry paths under the requested (lexical) directory,
fixed separately. Re-applying the original LIST hunk introduced two
regressions: shadowing of outer 'let requestedPath' inside the try block,
and the gitignore filter comparing lexical entry paths against
'ignoredPaths' built from the canonical realpath.

This commit drops the LIST hunk and the two list tests that accompanied
it. The read-family fixes (stat/read/raw/serve) stay — those were the
actual symlink resolve-before-containment fix and are not affected by
the LIST regressions.

Refs btriapitsyn on #2872 (2026-08-27).
2026-08-28 09:41:31 +02: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 e205452223 Merge pull request #2771 from shijie152/fix/relay-key-atomic-settings
fix(cli): atomic settings writes and gate relay key regeneration in connect-url
2026-08-28 01:24:30 +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 bfcd1830f0 Merge pull request #1727 from HAHH9527/fix/windows-schtasks-tr-261-char-limit
fix(cli): externalize Windows startup PowerShell to .ps1 wrapper (schtasks /TR 261-char limit)
2026-08-28 01:22:57 +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 64f3f46d93 Merge pull request #1957 from bketelsen/fix/sw-notificationclick-focus
fix(pwa): focus existing window on notification click
2026-08-27 23:15:39 +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 8598f3a37c release v1.21.0 2026-08-26 23:15:55 +03:00
Bohdan Triapitsyn cb18f8c9af chore: bump @opencode-ai/sdk to 1.18.23 2026-08-26 19:46:23 +03: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 841eca5720 feat(surface): switch app shells when the viewport crosses the phone threshold
The mobile-vs-desktop surface is stamped once at boot, so a browser
window narrowed past the phone threshold kept the desktop shell (and
its legacy squeezed layout) until a manual reload. A viewport watcher
now reloads into the other shell once the resize settles — the same
mechanism the old Settings toggle used. Fixed shells (Capacitor,
desktop, VS Code) and ?surface= overrides never switch.

With the new mobile app reachable this way, the old/new mobile layout
preference is gone: phones always get the mobile app.
2026-08-24 16:08:04 +03:00