Commit Graph
882 Commits
Author SHA1 Message Date
bot-hermes 1f03b83db1 fix(walkthrough): thread directory into GitLab diff client and fix tests
- Add directory parameter to getGitLabMergeRequestDiff for per-project
  API base URL override resolution
- Mock getGitLabAuth/getEffectiveProviderApiBaseUrl in walkthrough tests
- Update auth-check test to mock null auth instead of null client
2026-08-18 20:47:36 +00:00
bot-hermes 4ce02ee569 fix: address bot review findings
- Add codeberg.org to deriveLinkedIssueProvider built-in Gitea check
- Fix Gitea PR review prompt: !N → #N (GitLab vs Gitea syntax)
- Update gitlab.mdx: remove 'read-only' claim (write support ships)
- Gate walkthrough Gitea PR source (server can't fulfill yet)
- Thread per-project API base URL override into walkthrough GitLab diff
- Stop following cross-origin redirects in GitLab/Gitea clients (auth leak prevention)
2026-08-18 20:35:46 +00:00
bot-hermes 707991665a Merge remote-tracking branch 'origin/main' into feat/gitlab-issues-mrs
# Conflicts:
#	packages/ui/src/components/chat/work-status/WorkStatusContextSection.tsx
#	packages/ui/src/lib/i18n/messages/de.ts
#	packages/ui/src/lib/i18n/messages/en.ts
#	packages/ui/src/lib/i18n/messages/es.ts
#	packages/ui/src/lib/i18n/messages/fr.ts
#	packages/ui/src/lib/i18n/messages/ja.ts
#	packages/ui/src/lib/i18n/messages/ko.ts
#	packages/ui/src/lib/i18n/messages/pl.ts
#	packages/ui/src/lib/i18n/messages/pt-BR.ts
#	packages/ui/src/lib/i18n/messages/uk.ts
#	packages/ui/src/lib/i18n/messages/zh-CN.ts
#	packages/ui/src/lib/i18n/messages/zh-TW.ts
#	packages/web/server/lib/opencode/settings-helpers.js
2026-08-18 20:22:15 +00:00
Bohdan Triapitsyn b754ccbf63 Merge remote-tracking branch 'origin/main' 2026-08-18 21:38:20 +03:00
Bohdan Triapitsyn 423f5b9652 feat(files): upload files with drag and drop 2026-08-18 21:24:53 +03:00
Bohdan Triapitsyn 1efc7fb570 fix(fs): open files through workspace symlinks 2026-08-18 19:15:11 +03:00
Bohdan Triapitsyn 3326ad0ea8 fix(quota): coalesce provider usage refreshes 2026-08-18 19:13:58 +03:00
Bohdan Triapitsyn 84e940a9e4 fix(mobile): bypass ngrok browser interstitial 2026-08-18 19:12:02 +03:00
Serhii DziupinandSerhii Dziupin 9832c0a4a8 fix(git): handle worktrees from forked PRs safely (#2693)
* fix(git): create worktrees from forked PRs via refs/pull/<n>/head fallback

A worktree created from a linked GitHub PR whose head branch lives in a fork
failed when the fork's head repository was missing (deleted fork) or
unfetchable (auth, network): the dialog threw 'PR head repository URL is
unavailable' before any git command ran, and the server had no fallback to
refs/pull/<n>/head, which GitHub serves on the base repository.

- NewWorktreeDialog: when pr.headRepo is absent, send a prRef config
  (refs/pull/<n>/head from origin) instead of throwing; the fork config now
  also carries prRef so the server can fall back when the fork fetch fails.
- git service: fetchPullRequestHeadRef fetches refs/pull/<n>/head into
  refs/remotes/<remote>/pr-<n>-head (same refspec shape as
  fetchRemoteBranchRef) and both validateWorktreeCreate and
  attachGitWorktreeToCandidate fall back to it when the fork path fails;
  fallback worktrees get --no-track and no upstream config because a PR ref
  is not pushable. When both paths fail the original fork error surfaces.
- Focused tests cover the prRef-only path and the fork-unreachable fallback.

Fixes #2422

* fix(git): harden PR worktree fallback against stale fork refs (#12)

After a fork fetch fails, resolve immediately from refs/pull/<n>/head
instead of accepting a cached remotes/<fork>/<branch> tracking ref.
Match the PR base repository by URL (not a hardcoded origin remote),
store fetched PR heads under refs/openchamber/pull/<n>/head, and share
one existing-mode resolver between validate and create.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* fix(git): make PR head SHA authoritative and namespace private refs

Reuse local/remote branches for linked PRs only when their tip matches
pr.headSha; otherwise fall through to fork fetch / refs/pull. Store PR
heads under refs/openchamber/github/<owner>/<repo>/pull/<n>/head, prefer
HTTPS for direct base-repo fallback, and surface composite fork+fallback
errors when both paths fail.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* test(ui): assert validate/create forward deleted-fork PR payload fields

Guards the dialog wiring regression where validate omitted prRef while
create included it, by asserting worktreeManager forwards prRef,
prBaseRepoUrl, and related fields for deleted-fork configs.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* refactor(git): always checkout linked PRs from refs/pull/<n>/head

Move PR worktree resolution to the server. The UI now sends only
pullRequest identity (number + baseRepoUrl + optional head fields);
the server always fetches the authoritative PR head and best-effort
configures fork upstream afterward.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* refactor(ui): drop PrWorktreeConfig; send PR identity only

Delete the prWorktreeConfig module. NewWorktreeDialog maps linked PRs
straight to pullRequest identity, skips upstream defaults for that path,
and leaves checkout + optional fork tracking to the server.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* refactor(git): linked PRs are {number, baseRepoUrl} only

Drop fork upstream / tracking and head/base owner-repo fields from the
linked-PR worktree path. Fetch refs/pull/<n>/head, create --no-track, done.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* fix(git): meet #2422 Must/Should without refs/pull fallback

Linked PRs send fork identity only; the server provisions pr-<owner>,
fetches the head branch, and fails clearly when the fork is missing or
unreachable. Local reuse requires a matching headSha. Prefer HTTPS for
headRepoUrl. Do not write upstream tracking when the upstream ref was
never fetched.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* fix(git): drop invalid upstream fallback and PR branch collisions

Remove setBranchTrackingFallback: if upstream fetch fails, leave tracking
unset. When a linked PR's head branch already exists locally with a
different tip, create pr-<number> instead of git worktree add -b on the
colliding name.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* fix(git): strip PR worktree create back to fork-remote provision (#15)

Keep the original ensureRemoteName/Url path for linked fork PRs, prefer
HTTPS clone URLs, fail clearly when the fork is unreachable, and leave
upstream tracking unset when the upstream ref was never fetched.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>


Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-18 16:56:55 +03:00
Bohdan Triapitsyn 17d08c0395 feat(quota): add Command Code usage tracking 2026-08-18 16:24:02 +03:00
Bohdan Triapitsyn 34e8a24b20 feat(knowledge): rebuild the project notes panel as Project knowledge (#2973)
The panel stored notes, todos and plans inside one shared JSON file that
six unrelated domains also wrote to, synchronised itself through window
CustomEvents, and could only read plans. It is now Project knowledge:
server-owned storage with explicit routes, a store with rollback, a
section sidebar, plans that open and edit in place, and search across
all of it.

Notes and plans the user pins travel with every message sent in that
project. Pinning is project state, not an attachment to one message, so
it holds until unpinned and the work status panel names what is riding
along and can detach it.

Agent memory is added alongside, in two scopes: what is true about the
user, and what is true about this codebase. The split is not cosmetic —
a wrong project fact costs one project and is noticed, while a wrong
global fact quietly shapes every session everywhere and the user has no
code to check it against. It stays separate from notes so an agent
mistake cannot land in what the user wrote. Sessions receive an index of
titles only; bodies are read on demand, because an index carrying full
text grows until it crowds out the conversation.

Deciding what a session must be told, and whether it has been told, now
lives on the server. The client owned it before, which meant sessions
started without a UI — scheduled tasks, sessions the agent dispatches —
received nothing at all, and a tab's record of what it had sent outlived
the conversation: after compaction the agent no longer held the block
while the tab went on believing it did. What was delivered is recorded
in the session's own metadata, and compaction restores it through the
runtime that already restores pinned messages, in the same turn.

Agent memory ships dark behind OPENCHAMBER_MEMORY_ENABLE: unset, there
is no tool, no routes, no session index, no settings row and no panel
tab. Absent rather than switched off, so nothing invites turning on a
feature that has not been announced. Pinned notes and plans are
unaffected and ship as normal.
2026-08-18 02:59:04 +03:00
Aaron Hogue 7611076436 fix(proxy): reuse upstream connections for OpenCode API requests (#2916)
* fix(proxy): reuse upstream connections for OpenCode API requests

`createProxyMiddleware` was constructed without an `agent`, so `http-proxy`
fell back to `agent: false`. That disables connection pooling and forces
`Connection: close` on every proxied request, consuming one ephemeral port
per request.

Measured against a real `opencode serve` instance, 200 sequential requests
through the proxy created 201 TIME_WAIT entries (1.005 ports/request). With
a keep-alive agent the same load creates 0.

On macOS the ephemeral range is 16,384 ports and TIME_WAIT lasts 30s, so
sustained traffic around 546 req/sec exhausts the pool — after which every
process on the host fails to open outbound connections with EADDRNOTAVAIL.

`maxSockets: Infinity` preserves the unbounded concurrency of `agent: false`,
so this changes connection reuse only, not request throughput.

Partially addresses #2915.

* fix(proxy): derive proxy agent class from the target scheme

Addresses review feedback on #2916. The first commit created an
unconditional `http.Agent`, which regresses external OpenCode servers
configured over https via `OPENCODE_HOST` (accepted by env-config.js).

http-proxy dispatches through `https.request` when the target protocol is
`https:` (http-proxy/lib/http-proxy/passes/web-incoming.js:126), and
`http.Agent#createConnection` is plain `net.createConnection` — so an
http.Agent would open a plaintext socket to a TLS port and fail every
proxied request. `agent: false` previously worked for both schemes.

`createOpenCodeProxyAgent(target)` now returns an `https.Agent` for https
targets and an `http.Agent` otherwise, derived once from
`resolveProxyTarget()` at registration so the single shared instance is
preserved across `apiProxy` and `interactiveOAuthProxy`.

Guarded in both test layers, verified to fail when the selection is
reverted to an unconditional http.Agent. `https.Agent` extends
`http.Agent`, so the http cases assert `not.toBeInstanceOf(https.Agent)`.

* Round 2: fix: resolve the proxy agent lazily so cold starts honor https

Addresses the round-2 blocker on #2916. Deriving the agent class at
registration is too early: startup-pipeline-runtime.js calls setupProxy()
(line 104) before bootstrapOpenCodeAtStartup() (line 141), so on a fresh
process state.openCodePort is null, buildOpenCodeUrl() throws
(network-runtime.js:86-88), and resolveProxyTarget() returns the http
loopback fallback. An external server configured via OPENCODE_HOST=https://
only appears on state.openCodeBaseUrl after bootstrap, so it was still
getting a plain http.Agent — the regression the previous commit intended
to fix.

`agent` is now a getter backed by a per-scheme memoizing resolver.
http-proxy-middleware rebuilds per-request options with
`Object.assign({}, this.proxyOptions)` in prepareProxyRequest, which invokes
getters, so resolution happens at request time while still yielding one
shared pool per scheme.

Tests now model the production ordering — registration while the port is
null and buildOpenCodeUrl throws, then an https base URL appearing after
bootstrap — and fail against the eager implementation. A behavioral test
pins the http-proxy-middleware option re-read the fix depends on, so a
library change that froze options would fail loudly instead of silently
regressing https targets.

The resolver is module-private; `bun run dead-code` flagged it as an
unused export when it was exported.

* Round 3: docs(changelog): note upstream connection reuse under [Unreleased]

Repo precedent adds [Unreleased] bullets for comparable proxy/stability
fixes (1.18.4 Stability, 1.9.3 Reliability/Proxy). Non-blocker raised in
review on #2916.

* Round 3: docs(changelog): use repo-standard 'behavior' spelling

* Round 4: docs(changelog): don't imply a restart is the only recovery

The ephemeral port pool drains on its own once the exhausting traffic
stops (TIME_WAIT expiry), so a restart is sufficient but not necessary.
Optional nit raised in review on #2916.

* Round 5: fix: construct the proxy agent through one factory; widen the pool

Review found the https branch was mutation-uncovered: the resolver
re-implemented agent construction inline instead of calling the exported
`createOpenCodeProxyAgent(target)`, so replacing its https branch with
`new https.Agent()` — dropping OPENCODE_AGENT_OPTIONS, and with it
keep-alive — left the entire suite green. Since `createOpenCodeProxyAgent`
also had no production callers, its four tests were pinning dead code.
Delegating collapses both: the factory is now the single construction
path, and the mutation fails 2 tests including the live resolver path.

Also from review:

- maxFreeSockets 32 -> 256 (Node's own default). The lower cap evicted
  pooled sockets under concurrency, reintroducing the churn this agent
  exists to prevent: at 64 concurrent requests it left 303 sockets in
  TIME_WAIT versus 0 at 256.
- Added `timeout` to OPENCODE_AGENT_OPTIONS. Free-socket eviction is
  governed by agent.options.timeout, which was unset, so idle sockets
  persisted until the peer closed them. `keepAliveMsecs` is the TCP probe
  delay, not the idle lifetime.
- resolveProxyTarget() now checks openCodePort before calling
  buildOpenCodeUrl instead of relying on it throwing. The port is nulled
  on several runtime paths (health-check failure, failed restart), so a
  degraded OpenCode made every proxied request pay for a thrown-and-caught
  exception — and the getter added a second call per request.
- Test fixtures use :4096 rather than :443; WHATWG URL elides the default
  port, so parseInt('') is NaN and env-config rejects that host. The
  fixtures modeled a state that cannot reach production.
- The getter-read assertion is now exact (0 at construction, 1, then 2)
  rather than >= 2, which would have passed if the getter were read twice
  at construction and never per-request.
- listen() rejects on 'error' and servers start inside try/finally, so a
  bind failure fails the test instead of hanging to timeout.
2026-08-17 23:44:38 +03:00
Serhii Dziupin 6d6ece6856 fix(config): fail closed when config content yields no JSON value
Treating every undefined parse as empty config let a file that is not JSON
at all (YAML, plain text) read as {}, so a later write would back it up and
replace it - the same data loss this fix is meant to prevent. Only a
comment-only parse, where ValueExpected is the sole error, counts as empty.
2026-08-17 16:44:17 +03:00
Serhii Dziupin 07f8264e72 merge: resolve changelog conflicts with main
Keep main's reordered Unreleased lists and add the config-wipe fix bullet
at the top of both changelogs.
2026-08-17 16:29:08 +03:00
bot-hermes 45437a4221 feat(web,ui): per-project forced git provider and settings gating
Adds a per-project forced provider (github|gitlab|gitea) on top of the
per-project API base URL overrides: stored under gitProviders.provider in
projects/<projectId>.json, sanitized server-side, and winning over remote-host
detection both in useGitProvider and in server repo resolution
(parseGitLabRemoteUrl/parseGiteaRemoteUrl accept any host when the provider
is forced). The Projects settings page replaces the three always-visible URL
fields with a provider selector (auto-detect + the three forges) and one URL
override for the active provider. Global provider override fields on the
GitHub/GitLab/Gitea settings tabs now render only once an account is
connected, and Settings search availability matches that gating.

Also fixes the useConfigStore/useDirectoryStore circular-import TDZ in the
bundled chunk via the window-registered store handle and defers the directory
subscription to a microtask; fixes the Gitea PR merge payload (Do carries the
merge-style string enum, not a boolean + MergeMethod); and adds a documented
Gitea client live-test harness (scripts/gitea-live-test.ts + client.d.ts).
2026-08-17 09:57:54 +00:00
bot-hermes 66edc74fac feat(web,ui): per-project git provider API base URL overrides
Per provider (github|gitlab|gitea) a project override stored in
~/.config/openchamber/projects/<projectId>.json under gitProviders wins
over the global settings.json value (precedence: project override > global
> built-in default). Server forge routes resolve the override per request
directory (worktree-aware via git-common-dir + containment + path fallback,
60s TTL cache); the override host is also accepted for remote parsing and
client detection. New GET/PUT /api/projects/:projectId/git-providers route;
client openchamberConfig preserves the server-owned gitProviders key;
Projects page gains a Git provider API base URLs section; detection store
hydrates per-project overrides (memory-only, server-authoritative).
2026-08-17 09:57:54 +00:00
bot-hermes 697925ee0d feat(web,ui): built-in codeberg.org gitea host and provider detectUrls 2026-08-17 09:56:59 +00:00
bot-hermes 0fc857959e feat(web,ui): per-provider git forge API base URL and detection URLs
Configure a default API base URL per git provider (github/gitlab/gitea)
in settings.json gitProviders, with GitHub Enterprise support (Octokit
baseUrl + device-flow web origin derived from the API base), and replace
the client-side custom-domains list with server-persisted detection URL
chips (SSH/HTTPS forms normalized to hosts). The configured API base host
auto-counts as a detection host. Settings round-trip through the existing
/api/config/settings sanitizer; the UI store hydrates from server settings
with a one-time localStorage migration.
2026-08-17 09:55:11 +00:00
bot-hermes 66adb65377 test(web): gitea issue creation — wire api coverage, module docs, section comment
The Gitea create-issue path (server route, client, wire api, facade, UI
button/dialog) landed with the forge user-lookup work; close the remaining
verification/documentation gaps:

- wire: gitea.test.ts covers issueCreate (POST /api/gitea/issues/create,
  full/optional body, error throw)
- docs: DOCUMENTATION.md lists createIssue client method and the
  POST /repos/{owner}/{repo}/issues endpoint (labels as names)
- ui: fix stale 'read-only by design' JSDoc in GiteaIssuesSection — creation
  is offered here and the detail view provides edit/close/reopen
2026-08-16 16:29:25 +00:00
bot-hermes 3b3799f79e fix(web): optional fs stat outside workspace returns exists:false
Graceful probe: an optional stat of a config/backup path outside the active
workspace now reports exists:false instead of 400, so boot-time probes don't
surface console errors for a check that was never mandatory.
2026-08-16 16:29:25 +00:00
bot-hermes 3800c84948 feat(ui): forge user lookup — assignee combobox, @-mentions, repo-scoped user search
Repo-scoped assignable-user search for GitHub, GitLab, and Gitea, surfaced as
an assignee combobox in the metadata editor and @-mention autocomplete in
forge comment/reply/review surfaces.

- server: GET /api/{provider}/users/search (assignees / project members),
  query + directory/override repo resolution, 429 -> 503, connected:false
  degradation; GitLab assignee writes resolve login -> ID server-side
- wire: searchUsers (+ searchLabels/milestones/branches/tags) on the three
  API clients with tests
- facade: userSearch capability (all three), searchUsers adapters,
  mapGithubAssignee/mapGitlabMember/mapGiteaAssignee -> ForgeUser
- ui: ForgeLookupCombobox (keyboard nav, debounced 30s-TTL cache,
  connected-only caching), ForgeMentionTextarea (@ token parsing, caret
  restore), free-text fallback when lookup is unavailable; i18n in 12 locales
- extras sharing the same infrastructure: GitLab create-issue dialog and
  label/milestone/branch/tag lookups in the metadata editor
2026-08-16 16:29:25 +00:00
bot-hermes 8f5cfdcd62 feat(ui): forge write operations — comments, replies, close/reopen, edit, reviews, draft, metadata
- server: write routes for all three providers (issue/PR comments, inline review-comment replies, issue/MR updates w/ labels-assignees-milestone, review submit, draft toggle)
- ui: ForgeProvider gains six write ops; shared action components (composer, thread reply, state/review/draft/metadata/edit) wired into ForgeEntityDetailView and GitHub PR Overview
2026-08-16 16:29:24 +00:00
bot-hermes 92f0eced34 feat(ui): rich forge entity views — commits, files/diff, timeline, checks, metadata chips
- server: new read routes for PR/MR commits, timeline, reviews, commit-statuses across github/gitlab/gitea; enrich PR/issue summaries with labels/assignees/milestone/commentsCount
- ui: forge facade gains getCommits/getTimeline/getChecks; shared ForgeEntityDetailView + section components; mounted into PR/MR views and issue sections
2026-08-16 16:29:24 +00:00
bot-hermes ca91fd7e2d feat(gitea): add Gitea/Forgejo as a git provider
Full parity with the existing GitLab provider:
- Server module packages/web/server/lib/gitea (auth/client/repo/routes + docs + tests)
  with Gitea REST v1 API, PAT + base URL auth, multi-account storage
- Shared GiteaAPI types and web API client
- Provider detection generalized with user-configurable custom domains
  per provider (github/gitlab/gitea), additive with built-in defaults
  (github.com, gitlab.com) and connected-account hosts; precedence
  github -> gitlab -> gitea
- Gitea PR view, issues section, pickers, integration dialog, branch
  PR status helper, settings UI (PAT + base URL + custom domains)
- Magic prompts (gitea.pr.review, gitea.issue.review) and full 11-locale
  i18n parity
2026-08-16 16:27:49 +00:00
bot-hermes d5dea0c004 feat(ui): branch selectors in the GitLab merge request create form 2026-08-16 16:27:48 +00:00
bot-hermes 28d992ac78 feat(web): create, update and merge GitLab merge requests 2026-08-16 16:23:39 +00:00
bot-hermes b8a0aa0242 feat(web): resolve walkthrough diffs for GitLab merge requests 2026-08-16 16:23:38 +00:00
bot-hermes 267db3fb9d feat(web): filter GitLab merge requests by source branch 2026-08-16 16:23:36 +00:00
bot-hermes d798b3f479 feat(web): add GitLab issues/MRs server module
Add a server-side GitLab integration mirroring the GitHub module:
- auth.js: PAT auth storage with multi-account support and configurable
  base URL (gitlab.com default, self-hosted instances supported)
- client.js: raw-fetch GitLab REST v4 client with per-request timeout,
  ETag conditional-GET cache, own rate-limit cooldown, pagination, and
  single-follow redirect handling
- repo.js: GitLab remote URL parser + directory resolution
- routes.js: read-only /api/gitlab/* routes (auth, issues, MRs, branches)
- index.js + DOCUMENTATION.md + unit tests for auth, client, repo, routes
- Wire registerGitLabRoutes into feature-routes-runtime
2026-08-16 15:42:26 +00:00
bot-hermes b5ddb6f3a1 feat(web): add GitLab API client wrapper and types 2026-08-16 15:42:26 +00:00
Bohdan Triapitsyn 58c190f0b1 fix(web): use Vitest timers in PR status tests 2026-08-16 17:30:45 +03:00
Bohdan Triapitsyn 268f9ea9f2 fix(github): keep merged PRs as branch history instead of hiding them
Branch status resolves an open PR across the whole fork network first, so a
merged fork PR can never hide an open upstream PR for the same head. Only when
no target has an open PR does the branch's newest closed/merged PR come back,
as history.

The panel shows that history as a compact note and offers creating the next PR
below it, instead of either sticking on a terminal PR or going blank after a
merge. Terminal associations stay persisted for reload continuity but are never
treated as authority: they revalidate on the discovery cadence and on focus.

History is looked up only for the branch's own remote and name, and remembered
per repo+branch, so the extra lookup cannot exhaust the route's resolve budget.
The checks summary and merge-permission lookup are skipped for a closed or
merged PR, where neither is actionable.
2026-08-15 17:56:55 +03:00
Bohdan Triapitsyn 9032dfa5c0 fix(ui): show project names exactly as the folder is named
Auto-derived project labels were title-cased, turning .ssh into .Ssh and
opencode-claude into Opencode Claude. Show the folder name verbatim in the
sidebar, window title, settings selector and notification templates, and
migrate persisted legacy labels back to the folder name (manual renames
are preserved).
2026-08-15 10:16:31 +03:00
Cursor Agentandserkraser 6751c7dc7a fix(config): isolate plugin list reads from a broken JSONC layer
Plugin listing still called readConfigFile per layer, so one unparseable
project file made GET /api/config/plugins and VS Code listPluginEntries
fail. Reuse readConfigLayer isolation and pin comment-only empty parse
in the VS Code suite.

Co-authored-by: serkraser <serkraser@gmail.com>
2026-08-15 06:30:36 +00:00
Cursor Agentandserkraser 8b086343fd merge: resolve changelog conflicts with main
Keep both Unreleased bullets: the config-wipe Settings fix and the
stale merged-PR Git panel fix from main.

Co-authored-by: serkraser <serkraser@gmail.com>
2026-08-15 05:30:54 +00:00
Cursor Agentandserkraser 35563dd78d fix(config): isolate broken JSONC layers and treat comment-only as empty
Address review findings on the #2923 fail-closed parse fix:

- Comment-only files produce ValueExpected with no JSON value; treat that
  as empty config instead of INVALID_JSONC. Partial object trees still throw.
- readConfigLayers no longer lets one unparseable layer abort valid sibling
  layers. Mutations still fail closed on the custom/user write target.

Co-authored-by: serkraser <serkraser@gmail.com>
2026-08-15 05:13:32 +00:00
Serhii Dziupin 8c91c82b62 Merge pull request #2929 from openchamber/feat/fix-stale-merged-pr-status-3a1e 2026-08-15 08:07:14 +03:00
Serhii Dziupin 11a136bba8 Merge pull request #2913 from Gautam0507/fix/2803-session-retention-persist 2026-08-15 08:05:48 +03:00
Cursor Agentandserkraser 13cbbc76d7 test(github): cover persist, hydrate, and complete open-list misses
Add store persist/hydrate regressions for terminal branch associations
and a server test that a complete empty open list does not query closed
PRs. Inline the open-only matcher state so the next repo target can win.

Co-authored-by: serkraser <serkraser@gmail.com>
2026-08-15 04:27:52 +00:00
Serhii DziupinandSerhii Dziupin 962b016cbd fix(github): stop stale merged PRs from sticking in branch status
Branch PR status now resolves open PRs only, revalidates closed/merged
associations on a discovery cadence, and clears authoritative empty
results so the panel can self-heal without a manual refresh.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-15 04:27:02 +00:00
Cursor Agentandserkraser 4cc090130c fix(config): refuse partial JSONC parses that wipe opencode.jsonc
jsonc-parser was returning truncated trees (often only `$schema`) when
configs contained JSON5-style unquoted keys. Config mutations then backed
up and overwrote the full file with that stub. Check parse errors on read
and refuse to overwrite unparseable files on write in web and VS Code.

Fixes #2923

Co-authored-by: serkraser <serkraser@gmail.com>
2026-08-15 04:25:40 +00:00
Serhii Dziupin 11537de734 Merge pull request #2924 from makeittech/feat/fix-clawhub-label-typo-5c30
Fix ClawHub display name typo in Skills Catalog (#2895)
2026-08-15 06:43:56 +03:00
Bohdan Triapitsyn d353638f39 fix: integrate Claude CLI provider state 2026-08-15 01:59:26 +03:00
Gautam0507 b15b20fe08 fix(settings): persist sessionRetentionAction through the settings sanitizer 2026-08-15 00:39:36 +05:30
Serhii DziupinandSerhii Dziupin a216b6871f Fix ClawHub display name typo in Skills Catalog (#2895)
The Skills Catalog source dropdown showed "ClawdHub"; the registry brands
itself as ClawHub. Update curated/fallback labels across web, UI, and VS Code,
align docs, and add regression tests.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-14 18:49:31 +00:00
Bohdan Triapitsyn 72cd861eb8 fix(quota): match the Claude Code integration provider to Claude quota
The opencode-claude integration registers its provider as `claude-code`, which
never matched the `claude` quota provider, so the collapsed Usage section in
the work status panel showed no limit for a model from that integration.

Claude windows also reported no duration, leaving the headline to fall back to
whichever row came first instead of the limit that runs out soonest. The
session and weekly windows now carry their length; extra usage stays without
one because it is a monthly spend cap.
2026-08-14 21:07:55 +03:00
Bohdan Triapitsyn b77a30cd88 feat(quota): read Claude plan limits from the Claude Code login
Claude quota only worked when the user had signed into Anthropic through
OpenCode. Credentials are now discovered from Claude Code itself first: the
macOS Keychain entry, then the Linux/WSL credentials file (honouring
CLAUDE_CONFIG_DIR), then OpenCode auth.json, then CLAUDE_CODE_OAUTH_TOKEN.

All sources stay read-only and the OAuth token is never refreshed: Anthropic
allows one live refresh token per client_id, so refreshing here would sign the
user out of Claude Code. Credentials are re-read per request instead, and an
expired token reports that Claude Code needs a sign-in rather than a bare 401.

Usage is now read from the limits[] array, so model-scoped weekly limits work
again after Anthropic stopped populating seven_day_sonnet/seven_day_opus, and
new limit kinds no longer need a code change. Adds extra-usage spend and the
plan name, and holds the last good values through Anthropic's 429s with a
cooldown and an account-keyed cache.
2026-08-14 20:49:59 +03:00
Bohdan Triapitsyn 3f266232f9 release v1.18.4 2026-08-14 17:48:03 +03:00
Bohdan Triapitsyn 12b5857b3f fix(markdown): align image gallery authorization 2026-08-14 17:27:07 +03:00
ChangeHow 90780258cd fix(markdown): correct image gallery rendering (#2894) 2026-08-14 17:10:36 +03:00