Commit Graph

3975 Commits

Author SHA1 Message Date
diegosouzapw
e63fbed64b fix(combo): no-auth OpenCode combos use oc/ prefix, not opencode/ (#2901)
The no-auth OpenCode provider has id "opencode" and alias "oc". The combo
builder built qualifiedModel from the provider id ("opencode/big-pickle"), but
parseModel("opencode/...") resolves to the opencode-zen api-key tier via a
manual ALIAS_TO_PROVIDER_ID override — not the no-auth "opencode" provider.
"oc/<model>" resolves correctly.

Rewrite qualifiedModel to the provider alias for no-auth providers (only when
the alias differs from the id), keeping providerId for getModelIsHidden. Aligned
the route test that previously asserted the buggy "opencode/" prefix.

Closes #2901
2026-05-31 01:20:57 -03:00
Diego Rodrigues de Sa e Souza
bafcf72be7 Merge PR 2970 into release/v3.8.8
fix(translator): drop Codex image_generation tool in Responses→Chat (#2950)
2026-05-31 01:08:19 -03:00
diegosouzapw
b5d03ed3f2 fix(translator): drop Codex image_generation tool in Responses→Chat (#2950)
Codex Desktop injects an image_generation hosted tool into every Responses API
request (even text-only ones). The tool-type validator threw
unsupportedFeature() (400) for it, breaking every Codex Desktop request.

Mirror the tool_search handling: add IMAGE_GENERATION_TOOL_TYPES, allow it past
the validator guard, and drop it from the tools array before forwarding to Chat
Completions.

Closes #2950
2026-05-31 01:05:13 -03:00
Diego Rodrigues de Sa e Souza
bc6332310d Merge PR 2969 into release/v3.8.8
fix(providers): route Copilot Claude/Gemini via chat/completions (#2911)
2026-05-31 01:01:32 -03:00
diegosouzapw
f14722315d fix(providers): route Copilot Claude/Gemini via chat/completions (#2911)
The github provider has format:"openai" (baseUrl .../chat/completions) plus a
separate responsesBaseUrl (.../responses); a model only uses the Responses API
when it sets targetFormat:"openai-responses". GitHub Copilot's Responses API
does not serve Claude/Gemini models, so claude-opus-4.7, claude-opus-4-5-20251101,
gemini-3.1-pro-preview and gemini-3-flash-preview failed with [400]. The working
claude-opus-4.6 carries no targetFormat and uses chat/completions.

Drop targetFormat:"openai-responses" from those four Claude/Gemini entries so
they use the provider default. Native OpenAI gpt-* models (and oswe-vscode-prime)
keep the Responses API.

Closes #2911
2026-05-31 00:56:41 -03:00
Diego Rodrigues de Sa e Souza
f6d68a7bf3 Merge PR 2967 into release/v3.8.8
fix(routing): replay reasoning_content for OpenCode big-pickle (#2900)
2026-05-31 00:44:49 -03:00
diegosouzapw
672398e86f fix(routing): replay reasoning_content for OpenCode big-pickle (#2900)
big-pickle's OpenCode/Zen upstream runs DeepSeek thinking mode, but the model
id reveals no DeepSeek signal, so requiresReasoningReplay (called with
allowLegacyFallback:false) never triggered. Follow-up/tool-use turns failed
with [400] 'The reasoning_content in the thinking mode must be passed back to
the API'. Note: requiresReasoningReplay does not consume supportsReasoning, so
the registry flag alone would not have fixed it.

Add RegistryModel.interleavedField (mirrors models.dev interleaved_field),
declare interleavedField:'reasoning_content' (+ supportsReasoning:true) on
big-pickle in both opencode and opencode-zen, and surface the registry value
in getResolvedModelCapabilities so requiresReasoningReplay returns true.

Closes #2900
2026-05-31 00:41:46 -03:00
Diego Rodrigues de Sa e Souza
5c340ea813 Merge PR 2966 into release/v3.8.8
fix(db): resolve 077 migration version collision blocking getDbInstance
2026-05-31 00:36:18 -03:00
diegosouzapw
d5b163558d fix(db): resolve 077 migration version collision blocking getDbInstance
077_api_key_stream_default_mode.sql and 077_quota_pools.sql both claimed
prefix 077, so getMigrationFiles() threw a version-collision error and
getDbInstance() failed at every startup (app would not boot; all DB-touching
unit tests were red on release/v3.8.8).

Renumber the dependency-free, idempotent quota_pools migration 077 -> 085
(no other migration references quota_pools/quota_allocations), keep the
non-idempotent api_key_stream_default_mode ALTER at 077, add a retroactive
isSchemaAlreadyApplied guard (case 085) for DBs that already applied it under
077, and add a regression test enforcing unique migration prefixes.
2026-05-31 00:33:51 -03:00
terence71-glitch
e2ad12d090 fix(proxy): show registry provider proxies in dashboard (#2963)
Integrated into release/v3.8.8
2026-05-30 22:14:53 -03:00
diegosouzapw
4536aabe23 Merge PR 2959 into release/v3.8.8 2026-05-30 22:02:49 -03:00
diegosouzapw
ff255c4582 Merge PR 2958 into release/v3.8.8 2026-05-30 22:02:09 -03:00
diegosouzapw
c90bed0043 Merge PR 2957 into release/v3.8.8 2026-05-30 22:01:07 -03:00
diegosouzapw
fa4bd6c68c Merge PR 2951 into release/v3.8.8 2026-05-30 22:01:04 -03:00
diegosouzapw
4e51bc686c Merge PR 2946 into release/v3.8.8 2026-05-30 22:00:41 -03:00
diegosouzapw
1a9b2bfd85 Merge PR 2943 into release/v3.8.8 2026-05-30 22:00:38 -03:00
diegosouzapw
266c145ee4 Merge PR 2940 into release/v3.8.8 2026-05-30 22:00:34 -03:00
diegosouzapw
8dafe78d79 Merge PR 2938 into release/v3.8.8 2026-05-30 22:00:31 -03:00
diegosouzapw
606b7092b6 Merge PR 2937 into release/v3.8.8 2026-05-30 22:00:29 -03:00
diegosouzapw
cf3600de11 Merge PR 2931 into release/v3.8.8 2026-05-30 22:00:20 -03:00
diegosouzapw
856603ecb7 Merge PR 2927 into release/v3.8.8 2026-05-30 21:59:50 -03:00
Raxxoor
3dd4a3b6f8 fix(antigravity): avoid visible signatureless tool history (#2927)
Integrated into release/v3.8.8
2026-05-30 21:59:20 -03:00
diegosouzapw
ba340f18a5 Merge branch 'fix/nextcloud-json-stream-default' into release/v3.8.8 2026-05-30 21:19:50 -03:00
diegosouzapw
e7870132db Merge release/v3.8.8 2026-05-30 21:19:17 -03:00
Diego Rodrigues de Sa e Souza
697946381d fix(auth): prevent Codex multi-account refresh_token family revocation (#2941)
Integrated into release/v3.8.8
2026-05-30 21:18:33 -03:00
Diego Rodrigues de Sa e Souza
2fb5979118 fix(dashboard): v3.8.8 screen fixes — agent-bridge SSR + audit/logs/memory/playground (#2944)
Integrated into release/v3.8.8
2026-05-30 21:18:25 -03:00
Paijo
7a0e803c01 feat: add Qwen Web (chat.qwen.ai) cookie provider (#2947)
Integrated into release/v3.8.8
2026-05-30 21:18:16 -03:00
terence71-glitch
52503064a8 fix(skills): avoid Claude assistant tool_result blocks (#2956)
Integrated into release/v3.8.8
2026-05-30 21:18:08 -03:00
terence71-glitch
187bc509bb fix(sse): bypass web-search fallback on Claude -> Claude passthrough (#2960)
Integrated into release/v3.8.8
2026-05-30 21:17:52 -03:00
Brandon Bennett
8dff29c760 docs: update CHANGELOG and MCP-SERVER.md for scope fix and Notion context source 2026-05-30 19:33:50 -04:00
Brandon Bennett
58eb093a2e docs: update CHANGELOG and MCP-SERVER.md for scope fix and Notion context source 2026-05-30 19:33:49 -04:00
Brandon Bennett
8cd77b0f49 feat(notion): add Notion MCP context source with 6 tools, dashboard tab, and 20 tests 2026-05-30 19:11:58 -04:00
Brandon Bennett
0c9345f75e fix: move enforceScopes guard before MCP_TOOL_MAP lookup, add scopes to all dynamic tool definitions
- Move !enforceScopes guard before MCP_TOOL_MAP lookup in evaluateToolScopes()
- Add inlineScopes parameter for dynamic tool scope resolution
- Add scopes to all 33 dynamic tool definitions across 5 tool files
- Wire toolDef.scopes through withScopeEnforcement in server.ts
- Preserves existing behavior: tool_definition_missing returned when
  enforceScopes=true and no scopes found anywhere
2026-05-30 19:11:52 -04:00
ReqX
ff7a9069f0 fix(routing): add agy to executor map so it uses AntigravityExecutor
The agy provider was registered in providerRegistry.ts with
executor: "antigravity" but the executor map in executors/index.ts
only had an "antigravity" entry. getExecutor("agy") fell through to
DefaultExecutor, which returned undefined for baseUrl (agy only has
baseUrls), causing fetch(undefined) → TypeError: Cannot read properties
of undefined (reading 'toString').

Closes diegosouzapw/OmniRoute#2932
2026-05-30 22:01:00 +00:00
soyelmismo
a91f352fde test: add unit tests for CPU leak fixes and registry changes
5 new test files covering all 13 changed production files:
- estimateSizeFast.test.ts: 16 tests for fast size estimator (circular ref
  protection, early exit, nested structures, Map safety)
- eviction-guards-apiKeyRotator.test.ts: 5 tests for Map eviction guards
  (!has() check prevents evicting existing keys on update)
- eviction-guards-codexQuotaFetcher.test.ts: 4 tests for connectionRegistry
  and quotaCache eviction guards
- rateLimitManager-idle-eviction.test.ts: 6 tests for idle limiter cleanup,
  limiterLastUsed tracking, and shutdown behavior
- registry-direct-exports.test.ts: 20 tests verifying all 8 registries export
  plain objects (no Proxy traps, no lazy getters, mutable entries)

Extract estimateSizeFast/isSmallEnoughForSemanticCache into standalone
open-sse/utils/estimateSize.ts to make them testable without importing
the entire chatCore.ts dependency tree.
2026-05-30 14:02:27 -05:00
soyelmismo
6cdf69e077 fix: address Kilo Code review feedback on PR #2951
- estimateSizeFast: add WeakSet cycle detection to prevent infinite
  loop on circular object references
- trace(): wrap JSON.stringify(extra) in try-catch to handle BigInt,
  circular refs, or other non-serializable values gracefully
- Registry API change (Comment 3): verified all callers already use
  new getter functions — no broken call sites
2026-05-30 13:34:57 -05:00
soyelmismo
b4c0ce6519 fix: address Gemini Code Review feedback on PR #2951
- Add !has(key) guard before eviction to avoid evicting entries
  that are about to be updated (combo.ts, apiKeyRotator.ts,
  codexQuotaFetcher.ts)
- Use optional chaining for provider?.toUpperCase() null safety
- Replace Object.values() with for-in in estimateSizeFast hot path
2026-05-30 13:03:02 -05:00
Jan Leon
664a606bfb fix(dashboard/api-manager): scroll to key name error in create modal 2026-05-30 18:54:26 +02:00
Jan Leon
99d673fe5b feat(stream): add per-key JSON stream default mode 2026-05-30 18:33:47 +02:00
oyi77
d698e957fb fix: combo credential resolution ignores target.providerId — prefer combo target's providerId over model-inferred provider
Root cause: model string provider prefix (e.g. "xiaomi" from
"xiaomi/mimo-v2-flash") differs from the credential DB provider ID
(e.g. "opengate") when a combo target has a custom providerId. The
pre-selection and execution flows both looked up credentials using the
model-inferred provider, which didn't match any DB entry.

Fix A (chat.ts): checkModelAvailable now uses target.providerId when
available, falling back to modelInfo.provider.

Fix B (chat.ts): handleSingleModelChat now accepts runtimeOptions.providerId
and preferentially uses it for credential lookup instead of re-resolving
the provider from the model string.

Fix C (model.ts): add "xiaomi" alias for "xiaomi-mimo" so direct
(non-combo) model requests to xiaomi/mimo-* also resolve correctly.
2026-05-30 22:21:29 +07:00
NomenAK
dd6104ea38 test(cliproxyapi): update executor test for the broadened tool-name cloak
The CPA executor now cloaks non-Claude-Code tool names (not just mcp_*), so the
prior "does not rewrite non-mcp_ tool names" assertion no longer holds:
my_tool is aliased to MyTool and restored on the response via _toolNameMap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 15:00:01 +00:00
NomenAK
a1e0bc7469 fix(claude): harden tool cloak + schema sanitizer (adversarial review round)
Addresses confirmed findings from an adversarial review of the prior commits:

- schema sanitizer: a truncation placeholder in a SCALAR annotation keyword
  (description/title/pattern/format) was coerced to {}, which is itself invalid
  draft-2020-12 and re-triggered the exact "input_schema is invalid" 400 the
  sanitizer exists to prevent. Placeholders are now only coerced to {} in
  subschema-expecting positions; scalar keywords are left untouched.
- schema sanitizer: numeric-string coercion is folded into
  stripInvalidSchemaConstructs so it also covers contains / propertyNames /
  additionalItems (which coerceSchemaNumericFields never visited).
- schema sanitizer: stop stripping the valid `default` keyword on the Claude
  native/passthrough surface (the #1782 default-strip is a translator concern;
  tool schemas here were previously forwarded verbatim). sanitizeClaudeToolSchema
  is now a single stripInvalidSchemaConstructs pass.
- tool-name cloak: consult TOOL_RENAME_MAP / EXTRA_TOOL_RENAME_MAP before the
  generic PascalCase fallback, so the CLIProxyAPI path uses the established
  fingerprint-evasion aliases (subagents->SubDispatch, session_status->CheckStatus,
  webfetch->WebFetch, ...) identically to the native path instead of weaker
  first-letter casing.
- kill-switch: CLAUDE_DISABLE_TOOL_NAME_CLOAK is now honoured inside
  cloakThirdPartyToolNames, so BOTH the native and CLIProxyAPI executor paths
  respect it (previously only base.ts did); .env.example + ENVIRONMENT.md updated.

Regression tests added for each. Verified end-to-end through the live CPA path:
mixture_of_agents, subagents, and a tool carrying placeholder descriptions and
`default` values all return 200 with original names restored on the response.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 14:35:53 +00:00
Jan Leon
31a734966c test(reasoning-cache): authenticate reasoning cache API route requests 2026-05-30 16:19:12 +02:00
Jan Leon
ce039778da test(chatcore): avoid pending metadata race in upstream timeout test 2026-05-30 16:13:30 +02:00
Jan Leon
27e56f6bb2 test(chatcore): wait longer for upstream timeout metadata 2026-05-30 16:07:53 +02:00
NomenAK
23dad7d93d fix(claude): apply tool cloak + schema sanitize on the CLIProxyAPI executor path
The native Claude OAuth guard in executors/base.ts is bypassed when
`upstream_proxy_config.mode = cliproxyapi` routes the request through the
CliproxyAPI executor — it has its own execute()/transformRequest() and never
reaches BaseExecutor.execute(), so the cloak/sanitizer never ran for that
(common) deployment. Wire the same guards into
CliproxyapiExecutor.transformRequest (Anthropic-shape branch), composing with
the existing bisected `mcp_*` reserved-namespace rewrite:

- sanitizeClaudeToolSchemas() on transformed.tools.
- cloakThirdPartyToolNames() with skip = mcp-reserved, so applyMcpToolNameRewrite
  keeps authority over `mcp_*` (its bisected `Mcp_X` form) and the two reverse
  maps stay disjoint / single-hop. Both merge into the non-enumerable
  _toolNameMap the response stream already uses to restore the caller's names.

cloakThirdPartyToolNames is now non-mutating (clones changed entries) to respect
transformRequest's no-input-mutation contract, and takes an optional `skip`
predicate.

Verified end-to-end through the live CPA path: a real ~100-tool harness payload
that returned the "out of extra usage" placeholder now returns 200 with original
tool names restored on the response stream; `mcp_*` tools and genuine PascalCase
Claude Code tools are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 13:59:36 +00:00
Jan Leon
57aff12781 fix(stream): default Nextcloud integration to JSON 2026-05-30 15:59:23 +02:00
NomenAK
3b2d075402 fix(claude): address tool-cloak PR review — preserve boolean schemas, null-guards, docs
Follow-up commit on PR #2943 review:

- Preserve boolean schemas in `sanitizeClaudeToolSchemas` (Gemini Code Assist,
  high severity). `additionalProperties: false` is the canonical JSON Schema
  lock-down for object tools; the previous coercion silently turned it into the
  permissive `{}`, which would invite models to hallucinate extra arguments
  during tool calling. Same rule now applies to per-property boolean schemas
  under `properties`. Placeholder strings still get the permissive `{}` slot —
  booleans get preserved verbatim.

- Defensive null guards in `cloakThirdPartyToolNames` for `tools[]` and
  `messages[]` entries that might be `null`/`undefined`. Prevents a runtime
  `TypeError` if a malformed payload reaches the cloak.

- Document `CLAUDE_DISABLE_TOOL_NAME_CLOAK` in `.env.example` and
  `docs/reference/ENVIRONMENT.md` (env/docs contract was failing in CI).

- Regression tests covering all of the above (5 boolean preservation cases,
  2 null-tolerance cases).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 13:30:04 +00:00
diegosouzapw
468354f8ff clean 2026-05-30 10:06:02 -03:00
soyelmismo
31e11aa8d8 perf: extract optimizations from perf/cpu-optimization-chat-completions
Extract 3 high-value CPU/RAM optimizations from perf branch:

1. estimateSizeFast() — fast object-tree size estimator replacing
   JSON.stringify().length in isSmallEnoughForSemanticCache(). Walks
   object tree with a stack, zero string allocation, early exit at 256KB.

2. Consolidate settings reads — move getCachedSettings() to a single
   early read in handleChatCore(), eliminating a redundant second read
   200 lines later. Also removes the isDetailedLoggingEnabled() wrapper
   call (reads settings internally) in favor of direct field check.

3. Registry Proxy→direct export — convert 8 registries from lazy
   Proxy+getOrCreate pattern to simple exported const objects. Eliminates
   Proxy trap overhead on every provider property access during routing.
   Affected: audio, embedding, image, moderation, music, rerank, search,
   video registries (-451 lines of Proxy boilerplate).

These changes are independent of the CPU leak fix (limiter eviction)
and complement it by reducing per-request CPU overhead.
2026-05-30 07:59:04 -05:00