Commit graph

178 commits

Author SHA1 Message Date
musistudio
240cd73c1c Merge branch 'dev/3.1' into dev/docs
# Conflicts:
#	docs/src/content/docs/en/configuration/profiles.md
#	docs/src/content/docs/zh/configuration/profiles.md
2026-08-06 14:16:12 +08:00
musi
3c71252de1 Add interactive docs demos 2026-08-06 14:10:32 +08:00
musistudio
89081a2082 Preserve target-provider slash model routing 2026-08-06 14:07:56 +08:00
musistudio
94674ba2e6 Add web content JSON provider account connectors 2026-08-06 11:36:11 +08:00
musistudio
df42fe8683 Propagate provider context for Fusion model discovery 2026-08-05 20:06:58 +08:00
musistudio
0fd7bf755f Merge dev/3.1 into main for v3.0.19
# Conflicts:
#	packages/ui/src/pages/home/components/network-logs.tsx
2026-08-05 18:56:16 +08:00
musistudio
0e1d9f4c05 Add Codex multi-agent bridge and provider model descriptions 2026-08-05 16:24:36 +08:00
musistudio
561c2d813c Add local agent auth provider hook support 2026-08-04 15:34:47 +08:00
musistudio
4cba6b51a8 Apply provider capability routing per upstream attempt 2026-08-04 10:21:51 +08:00
musi
7a51e892cc
Merge pull request #1622 from jesieleo/fix/codex-oauth-live-credentials
fix(codex): 同步本地登录的最新 OAuth 凭据
2026-08-03 13:20:24 +08:00
pacocartones
174ab41849 fix(gateway): compare API keys in constant time
The gateway API key authorizer matched the presented token against every
configured key with `item.key === token`, a variable-time string
comparison that returns on the first differing byte. The repository
already avoids that shape for its other secrets: context-archive.ts,
management-server.ts and media/service.ts each compare tokens through a
local timingSafeEqual helper with a length guard.

Route the gateway API key lookup through the same helper shape so all
secret comparisons behave identically. The length guard is kept so a
token of a different length is rejected rather than making
timingSafeEqual throw.

Behaviour is unchanged: valid keys authorize, unknown keys still return
401 "Invalid API key.", expired keys still return 401 "API key is
expired.", and the refresh-on-miss reload path is preserved.
2026-08-02 19:41:27 +02:00
jesieleo
c86e86038a fix(codex): refresh OAuth credentials from local login 2026-08-02 12:46:00 +08:00
ezra-quemuel
24a4861aa6 fix(config): translate top-level provider protocol into a capability
Local-agent login imports (Codex API et al.) declare the provider protocol
at the top level of the payload (protocol: "openai_responses") and carry no
capabilities array. parseProviders dropped that field, so the saved provider
ended up with neither protocol nor capabilities and the gateway fell back to
the default openai_chat_completions adapter. For Responses-only backends
(chatgpt.com/backend-api/codex) every request then 404s against a
non-existent /chat/completions route.

Synthesize a single capability from the top-level protocol (and the
provider's base URL) when no explicit capabilities are configured, reusing
the existing protocol normalization used for capability items. Explicit
capabilities still win. Fixes #1619.
2026-07-31 17:24:39 -07:00
musistudio
ccf63088ea Fix Bot Gateway stdio runner handling in Electron 2026-07-31 17:25:33 +08:00
musistudio
6a3509dbb2 Merge dev/3.1 into main for v3.0.18 2026-07-31 15:37:47 +08:00
musistudio
3f566d991a Preserve API keys across provider probes 2026-07-31 14:50:19 +08:00
musistudio
39a5712ae7 Prepare Claude App VM storage before launch 2026-07-31 11:55:10 +08:00
musi
2bceead04b
Merge pull request #1605 from ShiroKSH/fix/abort-retry-backoff
fix(gateway): abort retry backoff on disconnect
2026-07-30 17:33:09 +08:00
musistudio
571aa63602 Show request and trace costs in agent observability 2026-07-30 17:32:34 +08:00
musistudio
7b6a14301c Refine subagent model extraction and add detection tests 2026-07-30 15:29:56 +08:00
musistudio
e778687774 Show partial agent session failures in observability UI 2026-07-30 15:25:50 +08:00
ShiroKSH
7fcdeef78a fix(gateway): restore retry executor 2026-07-29 16:00:33 +03:00
ShiroKSH
546719003c fix(gateway): abort retry backoff on disconnect 2026-07-29 15:58:35 +03:00
Matteo Antoci
70d31ab47e fix(claude-code): never resolve a token from inside mcpOAuth
Review on #1604: preferring `claudeAiOauth` was not enough. A record holding
only `mcpOAuth` entries still produced a token, because the fallback ran a
recursive `findOauthTokenSet()` over the whole record and `mcpOAuth`
per-plugin records carry their own `accessToken`. That imports a plugin
token as a Claude Code provider and recreates the 401 the change was meant
to avoid. It also short-circuited the plaintext-file fallback, so a usable
`~/.claude/.credentials.json` was ignored in favour of the plugin token.

Restrict both lookups to root-level token fields instead of reordering the
recursive search. Root-level excludes *any* nested container, so a future
sibling of `mcpOAuth` cannot reintroduce the hole, and the pre-`claudeAiOauth`
layout that kept tokens at the record root still resolves.

Extract `readOauthTokenSetFields()` out of `findOauthTokenSet()` in shared.ts
rather than duplicating the field list. `findOauthTokenSet()` keeps its
behaviour, so codex/grok/kimi/opencode/zcode are unaffected.

Apply the same restriction to the credentials-file path: Claude Code writes
that file with the identical record shape, mcpOAuth included, so the hazard
was present there too.

Adds the two regression tests from the review verbatim.

Refs #1601, #1567
2026-07-29 14:34:09 +02:00
musistudio
e9bbf9dbb0 Synchronize legacy profiles with global profile state 2026-07-29 20:25:49 +08:00
musistudio
ea501e95f3 Fix deck-stage captures and Windows SDK path resolution 2026-07-29 19:04:41 +08:00
Matteo Antoci
519b92d406 fix(claude-code): look up the keychain item by account
Claude Code >= 2.1 writes its credential item under the current $USER and
leaves any pre-2.1 item (account "unknown") in place on the *same* service
name, `Claude Code-credentials`. `security find-generic-password -s <svc> -w`
with no `-a` matches an arbitrary one of them, so CCR read the stale legacy
item: the read exits 0, the JSON parses, and it carries only `mcpOAuth`.
`findOauthTokenSet()` then correctly returns undefined and the candidate is
silently dropped by the `status !== "missing"` filter in service.ts.

Resolve the item through tiered candidates, evaluated lazily so the normal
case stays at one `security` call:

1. the expected service name, derived the way Claude Code derives it
   (`Claude Code${oauthSuffix}-credentials${configSuffix}`, where
   configSuffix is `-${sha256(NFC(configDir)).slice(0, 8)}` once
   CLAUDE_CONFIG_DIR / CLAUDE_SECURESTORAGE_CONFIG_DIR is set), read under
   the current account;
2. `security dump-keychain` enumeration, newest-modified first, for items
   under another account or a config dir this process cannot reconstruct.
   Without `-d` that prints item metadata only: it never decrypts a
   password and never prompts;
3. the previous accountless read, as a last resort.

Prefer an explicit top-level `claudeAiOauth` across every candidate and fall
back to the recursive search only if none has one. `mcpOAuth` holds
per-plugin OAuth records that also carry `accessToken`, and key order puts
it first, so a recursive match could import an MCP plugin token as an
Anthropic provider that then 401s on every request.

Surface diagnostics instead of swallowing them: capture `security` stderr
rather than discarding it via `stdio: ["ignore","pipe","ignore"]`, and
return a `locked` candidate naming the reason when login state exists but
yields no token, so it survives the `status !== "missing"` filter. Treat
errSecItemNotFound (exit 44) as absence rather than an error, so a machine
with no Claude Code login still reports `missing`.

Also fix the file fallback: continue past a credentials file that holds no
token instead of returning it, and check the secure-storage config dir,
which the env vars above can relocate away from ~/.claude.

Refs #1601, #1567
2026-07-29 11:53:30 +02:00
musistudio
58523a1b04 Improve gateway runtime compatibility and child error diagnostics 2026-07-29 17:06:21 +08:00
musi
8f0b2d91e5 Refactor routing architecture and update project structure 2026-07-29 09:30:04 +08:00
musistudio
6dff43dd15 Allow authenticated RPC requests from any origin 2026-07-28 20:09:19 +08:00
musistudio
c0e4dba2c3 Expose model output limits in OpenCode configuration 2026-07-28 20:05:21 +08:00
musistudio
6cfd3f226f Expand core functionality and update related components 2026-07-28 17:44:49 +08:00
musistudio
d305f87e67 Cap imported Codex GPT-5 context windows 2026-07-28 15:15:14 +08:00
musistudio
755b00f829 Update Infistar referral links 2026-07-28 15:02:25 +08:00
musistudio
2c89b212ef Merge branch 'main' into dev/3.1
# Conflicts:
#	packages/core/test/unit/gateway/upstream-header-sanitizer.test.mjs
2026-07-28 09:54:13 +08:00
musi
d2867bd4a4
Merge pull request #1594 from jesieleo/fix/strip-forwarded-provider-headers
fix(gateway): 修复 HTTPS 自定义供应商请求 502
2026-07-28 08:43:10 +08:00
musi
d3cd06b6fe
Merge pull request #1591 from jesieleo/fix/electron-profile-status-jank
fix(electron): 修复从CCR启动ZCode导致CCR Electron界面卡顿的问题
2026-07-28 08:33:03 +08:00
jesieleo
1b7971f8d2 fix(gateway): strip inbound proxy headers from providers 2026-07-28 00:37:11 +08:00
musistudio
5df6a7a3f8 Rewrite Anthropic upstream URLs for selected providers 2026-07-27 20:14:34 +08:00
musi
6971be8e87 Unify config storage and gateway bootstrap 2026-07-27 16:51:03 +08:00
jesieleo
8ea1cd6e19 fix(electron): 避免运行状态轮询阻塞界面 2026-07-27 14:09:02 +08:00
jesieleo
74fa35f374 fix(zcode): resolve Fusion model context windows 2026-07-27 12:58:14 +08:00
jesieleo
237b4924b7 fix(zcode): use model catalog context windows 2026-07-27 08:56:52 +08:00
musi
7c4a877c99 feat: support Kilo Code profiles 2026-07-26 22:09:24 +08:00
musistudio
fa5559435f Merge remote-tracking branch 'origin/dev/3.1' into codex/claude-design-profile
# Conflicts:
#	.test-dist/core/runtime/request-log-worker.js
#	.test-dist/core/test/integration/gateway/gateway-client-disconnect.test.js
#	.test-dist/core/test/integration/gateway/gateway-virtual-models.test.js
#	.test-dist/core/test/integration/mcp/grok-media-service.test.js
#	.test-dist/core/test/integration/mcp/local-ai-gateway-media-live.test.js
#	.test-dist/core/test/integration/observability/request-log-pricing-transaction.test.js
#	.test-dist/core/test/integration/observability/request-log-runtime.test.js
#	.test-dist/core/test/integration/observability/request-log-store.test.js
#	.test-dist/core/test/integration/plugins/plugin-service.test.js
#	.test-dist/core/test/integration/profiles/profile-service.test.js
#	.test-dist/core/test/integration/usage/usage-store.test.js
#	.test-dist/core/test/unit/agents/bot-gateway-env.test.js
#	.test-dist/core/test/unit/agents/claude-app-gateway-models.test.js
#	.test-dist/core/test/unit/agents/claude-app-launch.test.js
#	.test-dist/core/test/unit/agents/claude-environment.test.js
#	.test-dist/core/test/unit/agents/codex-app-model-catalog.test.js
#	.test-dist/core/test/unit/agents/codex-media-preview-bridge.test.js
#	.test-dist/core/test/unit/agents/codex-model-catalog.test.js
#	.test-dist/core/test/unit/agents/local-agent-provider-codex.test.js
#	.test-dist/core/test/unit/agents/local-agent-provider-grok.test.js
#	.test-dist/core/test/unit/agents/local-agent-provider-kimi.test.js
#	.test-dist/core/test/unit/agents/opencode-profile-config.test.js
#	.test-dist/core/test/unit/agents/provider-model-metadata.test.js
#	.test-dist/core/test/unit/config/config-env-interpolation.test.js
#	.test-dist/core/test/unit/config/theme-preference.test.js
#	.test-dist/core/test/unit/gateway/codex-patch-bridge.test.js
#	.test-dist/core/test/unit/gateway/gateway-billing-sync.test.js
#	.test-dist/core/test/unit/gateway/gateway-claude-code-oauth.test.js
#	.test-dist/core/test/unit/gateway/gateway-media-config.test.js
#	.test-dist/core/test/unit/gateway/gateway-runtime-change.test.js
#	.test-dist/core/test/unit/gateway/gateway-status.test.js
#	.test-dist/core/test/unit/gateway/router-builtins.test.js
#	.test-dist/core/test/unit/gateway/routing-architecture.test.js
#	.test-dist/core/test/unit/mcp/toolhub-browser-automation-config.test.js
#	.test-dist/core/test/unit/models/pricing-service.test.js
#	.test-dist/core/test/unit/observability/raw-trace-sync.test.js
#	.test-dist/core/test/unit/profiles/ccr-cli-runtime.test.js
#	.test-dist/core/test/unit/profiles/profile-app-process-detection.test.js
#	.test-dist/core/test/unit/profiles/profile-launch-core.test.js
#	.test-dist/core/test/unit/profiles/windows-ccr-launcher.test.js
#	.test-dist/core/test/unit/providers/credential-pool.test.js
#	.test-dist/core/test/unit/providers/provider-account-service.test.js
#	.test-dist/core/test/unit/providers/provider-model-catalog.test.js
#	.test-dist/core/test/unit/providers/provider-preset-utils.test.js
#	.test-dist/core/test/unit/providers/provider-probe.test.js
#	.test-dist/core/test/unit/proxy/proxy-upstream.test.js
#	.test-dist/core/test/unit/routing/route-script-runtime.test.js
#	.test-dist/core/test/unit/web/web-management-server.test.js
#	.test-dist/ui/test/component/components.test.js
#	.test-dist/ui/test/component/layout.test.js
#	.test-dist/ui/test/component/overview-components.test.js
#	.test-dist/ui/test/component/profiles.test.js
#	.test-dist/ui/test/component/tray-components.test.js
#	.test-dist/ui/test/integration/providers.test.js
#	.test-dist/ui/test/unit/mcp-server-config.test.js
#	.test-dist/ui/test/unit/model-selector-format.test.js
#	.test-dist/ui/test/unit/routing.test.js
#	.test-dist/ui/test/unit/usage-activity.test.js
#	.test-dist/ui/test/unit/usage-format.test.js
#	.test-dist/ui/test/unit/virtual-models.test.js
#	README.md
#	README_zh.md
2026-07-26 18:17:48 +08:00
musistudio
31c14ea82e feat: bundle Claude Design for desktop app 2026-07-26 18:09:01 +08:00
musi
211552a68b Merge remote-tracking branch 'origin/main' into dev/3.1
# Conflicts:
#	README.md
#	README_zh.md
2026-07-25 22:49:30 +08:00
musistudio
3d576d2730 Update project implementation 2026-07-25 22:40:01 +08:00
musi
00f5d6e4e5 fix cache ratio token accounting 2026-07-25 22:12:04 +08:00
musi
01488216fe Merge remote-tracking branch 'origin/dev/3.1' into dev/3.1 2026-07-25 20:01:11 +08:00