Commit Graph

1073 Commits

Author SHA1 Message Date
camy-x
83a4913aa4 fix(claude): accept newer patch releases as native clients (#5820) 2026-09-20 19:15:51 +08:00
Luis Pater
42c9680eee feat(executor): support duplex streaming for codex websockets
- Implement `streamCodexDuplex` to handle bidirectional WebSocket interactions for Codex
- Support steering continuations (`response.steer`) and queued creations (`response.create`, `response.append`)
- Preserve response settings and state transitions across steering updates and automatic successors
- Isolate connection-level failures with `codexDuplexConnectionError` to prevent unnecessary credential cooldowns

Closes: #5968
2026-09-20 00:02:10 +08:00
Luis Pater
c93978c4ea fix(schema): normalize true boolean subschemas and strip unsupported keywords
- Normalize boolean `true` subschemas across root, properties, items, definitions, and dependencies into empty object schemas `{}`
- Include `dependencies` in schema definition traversal and normalization
- Strip unsupported schema keywords including `additionalItems`, `unevaluatedProperties`, `unevaluatedItems`, and `contentSchema`

Closes: #3551
2026-09-19 03:07:33 +08:00
Luis Pater
b6d1f050af fix(executor): buffer post-tool text to order devin tool calls before assistant response
- Buffer text deltas arriving after tool calls in streaming execution and flush them after closing active tool slots
- Prioritize tool call deltas over content text deltas during Connect frame processing
- Separate pre-tool and post-tool text parts in non-streaming responses to preserve step ordering
- Correct thought step index resolution when closing thoughts during content chunk emission

Closes: #5951
2026-09-19 02:41:17 +08:00
Luis Pater
22392c537d fix(executor): restore hybrid passthrough mcp tool names in claude oauth
- Track declared passthrough MCP tools in `claudeMCPAliasResolver`
- Recover hybrid tool names when the model prepends a virtual server prefix or replaces the caller's server with the virtual server
- Ensure client-tool alias matches take precedence over passthrough recovery and reject ambiguous passthrough tool matches

Closes: #5949
2026-09-19 02:13:11 +08:00
Luis Pater
690f4f3116 feat(executor): support use-max-completion-tokens for openai compatibility models
- Add `use-max-completion-tokens` setting to OpenAI compatibility model configuration
- Provide token normalization between `max_tokens` and `max_completion_tokens` based on model preference

Closes: #5939
2026-09-19 01:54:05 +08:00
Luis Pater
f86a33f721 fix(executor): restrict claude advisor tool check to server tool use
- Only detect `server_tool_use` for advisor tool invocations in Claude conversation history
- Prevent client-side tools named `advisor` using standard `tool_use` from improperly triggering advisor cloaking restrictions

Closes: #5934
2026-09-18 23:32:00 +08:00
Luis Pater
81d6ba7746 fix(codex): preserve reasoning content and IDs for compat models in responses
- Resolve model `is_compat` status via model info, config index, or model entries in Codex executor
- Skip wiping `reasoning.content` and stripping reasoning IDs during Responses sanitization when `is_compat` is enabled
- Pass resolved compat flag across standard, streaming, compact, and WebSocket Codex request flows

Closes: #5930
2026-09-18 23:02:54 +08:00
Luis Pater
e84e248c51 fix(executor): record expected Devin upstream model and bound stream observer memory
- Set expected upstream model for Devin in both streaming and non-streaming paths to avoid false positive substitution warnings on intentional mappings
- Account for line overhead and enforce max lines per stream event in StreamResponseModelObserver, dropping overflowed events until the event boundary
- Add unit tests for Devin intentional mappings and stream observer bounded memory behavior
2026-09-18 22:08:35 +08:00
Luis Pater
cde7d57e44 fix(executor): robust response model observability across meta, kimi, and openai-compat streams
- observe response model from terminal sourceEvent in Meta non-stream multi-event SSE responses
- record expected upstream model in UsageReporter to prevent false substitution warnings on Kimi canonical mappings
- use bounded stream observer to extract response models across image stream chunk boundaries
- add regression tests for Meta SSE non-stream, Kimi model mappings, and chunked image streams
2026-09-18 21:53:19 +08:00
Luis Pater
f8467f07dc fix(executor): record authentic Devin and Gemini Interactions response models
- Devin: extract authentic upstream model name from parsed Usage.ModelName
  instead of synthesized interactions JSON or binary Connect frames. Keep
  response model empty when upstream does not report one.
- Gemini: support interaction.model and event_type terminal semantics
  in response model extractors for Gemini Interactions streaming.
- Add unit tests for Devin and Gemini Interactions response model observability.
2026-09-18 21:32:59 +08:00
Luis Pater
e9463ff5a7 feat(executor): extend response model recording and substitution warnings to all providers 2026-09-18 21:22:43 +08:00
Luis Pater
cd5af08e31 Merge pull request #5928 from Viggo95/feat/codex-response-model-observability 2026-09-18 21:05:35 +08:00
Luis Pater
cc545cbf90 fix(openai): align tool call messages and preserve ordering on ambiguous outputs
- Add `AlignOpenAIToolCallMessages` to reorder tool results immediately after the matching assistant tool calls while preserving original content and numeric precision.
- Prevent deferred message reordering and call ID guessing when tool outputs are incomplete, duplicate, or missing IDs.
- Normalize translated requests after applying summary configuration in Codex multi-agent execution.

Closes: #5925
2026-09-18 12:32:21 +08:00
Viggo95
25f40d8cf8 feat(codex): record upstream response model and warn on silent model substitution
Codex upstreams can silently serve a different model than the one requested
(HTTP 200, with response.model naming the substitute). The proxy kept no record
of it: nothing logged, nothing reported, only the pass-through response body.

- Add Record.ResponseModel to sdk/cliproxy/usage, aligned with the existing
  ResponseServiceTier field, and emit it from the redis usage queue as the
  optional response_model payload field alongside response_service_tier. Only
  the record for the requested model carries it: additional-model records
  (image generation tool usage) describe a side model the upstream response
  never refers to, and would otherwise look like a substitution downstream.
- Add internal/runtime/executor/helps/response_model.go with
  extractCodexResponseModelEvent (SSE frames and raw JSON, restricted to the events
  that embed the authoritative response object, rejecting non-string and
  oversized upstream model names) and IsCodexModelSubstituted (both sides
  trimmed, lower-cased and stripped of thinking suffixes, dated aliases such as
  gpt-5.6-terra-2026-05-13 accepted in either direction).
- UsageReporter records the served model on the event path and emits the WARN
  when the attempt publishes its usage record, so no logging work happens
  before the first event is forwarded. Repeats are throttled per
  (auth id, requested model, served model) with a 10 minute window, because on
  an affected credential every request is substituted and an unthrottled
  warning would mirror the whole request volume into the logs. The credential
  is labelled auth_index=<index> only: codex credential file names embed the
  account e-mail, which must not be written to the logs at request rate.

Coverage, by entry point. The served model is observed on the HTTP streaming
path (both the bootstrap-buffered handshake and the streaming goroutine), the
HTTP non-streaming Execute loop, the websocket streaming and non-streaming
paths, and the two /responses-shaped image entry points. The remaining codex
entry points cannot report it and are therefore left alone: executeCompact
(/responses/compact answers with a compaction object that has no event type and
no response.model), the two direct image endpoints (/images/generations and
/images/edits answer in the Images API shape and stream image_generation.*
events), and CountTokens (counts locally with tiktoken, never reaching an
upstream).

TokenAccountingSchemaVersion is not bumped: it versions the token accounting
contract (token breakdown semantics), and this change only adds an optional
non-token field that leaves existing consumers and all token math untouched.

Note: response_model ships with the usage record and is the counting source;
the WARN is a throttled alerting signal and must not be used to count
substitutions.

Tests: table-driven unit tests for both helpers over real model ids, reporter
tests covering the published record, the single throttled warning, the absence
of account identifiers in it, concurrent observation and publishing under
-race, the throttle window and its entry bound, an executor-level guard for the
observeCodexTokenEvent wiring and the per-model records, plus a redisqueue
payload assertion for response_model. gofmt, go vet, go test -race on the
touched packages and go test ./... are clean.
2026-09-18 12:31:52 +08:00
Luis Pater
660a5800e7 fix(xai): restore aliased client web search tool name in responses
- Restore client-defined `web_search` tool names from their alias across SSE, websocket, and buffered execution responses.
- Preserve namespaced tool calls when matching and restoring tool names.

Closes: #5923
2026-09-18 09:57:06 +08:00
Luis Pater
1cce932573 fix(claude): skip retry-after header on overage-only rejections
- Skip parsing the `Retry-After` header when a rate limit rejection is overage-only to prevent global credential cooldowns.
- Allow exponential backoff to handle model recovery while keeping shared subscription windows available for other models.

Closes: #5920
2026-09-18 09:15:48 +08:00
Luis Pater
c616193a6c fix(xai): unify forced hosted tool choice normalization
- Generalize forced hosted tool choice handling across both image generation and web search.
- Normalize forced web search tool choices to string mode and isolate the target tool in the tools list.
- Strip hosted web search from mixed `allowed_tools` definitions.
- Skip native `x_search` injection when a hosted tool is exclusively required.

Closes: #5916
2026-09-18 02:20:41 +08:00
Luis Pater
44eaef0009 feat(claude): support model-level cooling and scope overage rate limits
- Add `claude.model-level-cooling` configuration to scope rate limit cooldowns to the requested model.
- Treat overage-only and spend cap rejections as model-scoped when shared subscription windows remain healthy.
- Propagate model-level cooling settings into streaming, token counting, and direct execution error classifiers.

Closes: #5915
2026-09-18 01:55:36 +08:00
Luis Pater
b6fe4f20c4 fix(devin): handle orphaned tool results and normalize function result payloads
- Match tool results against pending tool calls and downgrade unmatched results to user messages.
- Prevent downgraded orphaned tool results from consuming images intended for user turns.
- Unwrap protocol wrapper envelopes and extract structured text parts while preserving arbitrary business JSON.
- Provide a placeholder for empty or whitespace-only tool results.

Closes: #5911
2026-09-18 01:34:38 +08:00
Luis Pater
9e10db53ad fix(devin): aggregate tool calls by id and track cache write tokens
- Track and aggregate tool calls by call ID instead of slot index in streaming and buffered execution.
- Support raw arguments from invalid JSON fields for custom tool calls.
- Parse usage field 4 as cache write tokens instead of adding to prompt tokens.
- Align client metadata with the default client name and drop deprecated tag 28.

Closes: #5910
2026-09-18 01:04:43 +08:00
Luis Pater
64c9433fd2 fix(devin): support images in tool results
- Extract and attach images from tool results to corresponding tool prompts by call ID.
- Preserve structured business JSON and raw objects in function result content.
- Prepend image headers to tool prompt content when images are present.

Closes: #5893
2026-09-17 20:00:46 +08:00
Luis Pater
8c664b2fed Merge pull request #5896 from router-for-me/translator
feat(translator): preserve model metadata in requests
2026-09-17 13:52:35 +08:00
Luis Pater
ad088a8795 fix(devin): filter automation update tools and sanitize tool descriptions
- Filter out `automation_update` tools and sanitize tool descriptions in Devin wire requests and logs.
- Strip additional Codex prompt directives from system messages.
- Support `children` field fallback when collecting namespace tools.
2026-09-17 13:51:26 +08:00
hkfires
a9e92b8145 feat(translator): preserve model metadata in requests 2026-09-17 13:10:47 +08:00
Luis Pater
311efcb3a2 test(executor): use metaUserAgent constant in meta executor test
Closes: #5885
2026-09-17 10:01:49 +08:00
Luis Pater
c4982e846e fix(executor): strip relayed tool result images for text-only models
- Replace tool image placeholders with omission markers for compatibility with text-only upstream models.
- Strip synthetic image relay notices and image parts from user messages.

Closes: #5884
2026-09-17 09:57:13 +08:00
Luis Pater
c2bb91d2cb fix(devin): buffer content deltas to handle late thinking signatures
- Buffer content and tool call deltas while thinking is active so late-arriving thinking signatures can be attached before closing thinking blocks.
- Ensure pending actions and open steps are properly flushed and closed on stream completion or trailer errors.

Closes: #5873
2026-09-17 04:49:55 +08:00
Luis Pater
4613cfd44e Merge pull request #5870 from avabbbb/fix/devin-high-demand-rate-limit
fix(devin): classify high-demand errors as rate limits
2026-09-17 03:59:25 +08:00
Luis Pater
7fcbdf8896 feat(translator): enhance web search streaming and citation mapping in OpenAI Responses
- Add incremental merging for Gemini `groundingMetadata` with chunk index remapping and query deduplication.
- Implement rune offset mapping across multipart messages for accurate `url_citation` annotations.
- Manage full streaming lifecycle for web search calls, emitting `searching`, `completed`, and output item done events.
- Stream incremental citation annotations via `response.output_text.annotation.added` events.
- Support `web_search_preview_2025_03_11` as a recognized web search tool type.
2026-09-17 03:51:48 +08:00
Luis Pater
8c6d4dcde8 Merge pull request #5862 from sususu98/feat/antigravity-websearch
feat(antigravity): support web search translation and URL resolution in OpenAI Responses
2026-09-16 20:21:46 +08:00
Luis Pater
7c32971b91 fix(executor): prevent stream failure on client disconnect after claude completion
- Break stream scan loops immediately when upstream completion is reached.
- Skip scanner error handling and cancellation checks when `upstreamCompleted` is true.

Closes: #5866
2026-09-16 20:00:27 +08:00
Luis Pater
44f8343f30 Merge pull request #5867 from avabbbb/fix/devin-swe-1-6-slow
fix(devin): support swe-1-6-slow model variant
2026-09-16 19:36:05 +08:00
bekkilove
d44901f91c fix(devin): classify high-demand errors as rate limits
Devin upstream occasionally encodes transient capacity failures using
Connect code permission_denied with message containing 'high demand'.
CPA's ParseDevinTrailerError currently maps every permission_denied to
HTTP 403. The auth cooldown manager interprets 403 as a 30-minute model
permission cooldown, keeping a recovered model locally unavailable.

This fix narrowly reclassifies the observed high-demand variant as
HTTP 429 (Too Many Requests), so it enters the quota/retry cooldown
path instead of the long permission denial path. Genuine
permission_denied errors (model access denied, plan entitlement denied,
etc.) remain HTTP 403.

Tests: 4 new cases in TestParseDevinTrailerError covering transient
high-demand (429), genuine permission error (403), resource_exhausted
unchanged (429), and case-insensitive matching. All existing tests
pass with no regressions.
2026-09-16 19:24:08 +08:00
sususu
ef63d2e7fa feat(antigravity): support web search translation and URL resolution in OpenAI Responses
- Add bidirectional web search translation between OpenAI Responses API and Gemini/Antigravity
- Map Responses web_search tool to Antigravity web_search requestType envelope and googleSearch
- Map Google groundingMetadata to Responses web_search_call output item and url_citation annotations
- Buffer streaming text deltas while awaiting groundingMetadata so web_search_call strictly precedes message in SSE events and response.completed.output
- Derive search stream mode from effective translated request (requestRawJSON) to accurately support model aliases and rewrites
- Calculate streaming and non-streaming URL citation Unicode character (rune) offsets on full accumulated text, eliminating multi-byte CJK truncation and clamping
- Prioritize models.json native_capabilities.web_search explicit false as absolute veto before checking dynamic Antigravity probe capability
- Isolate Antigravity web search gating to Antigravity-specific model capabilities
- Suppress native googleSearch in Antigravity chat fallback when tools are mixed with function declarations
- Support Responses allowed_tools tool_choice containing web search and concatenate multi-part text queries
- Resolve Vertex Search grounding redirect URLs to target destination URLs in Antigravity executor
- Add comprehensive unit test coverage for stream/non-stream translation, late grounding, CJK offsets, model aliases, mixed tools, allowed_tools, and URL resolution
2026-09-16 16:56:31 +08:00
bekkilove
dea4ce8aeb fix(devin): support swe-1-6-slow model variant 2026-09-16 16:49:49 +08:00
Luis Pater
6f908cbcff feat(translator): enhance finish reason handling and tool call translations
- Refine finish reason assignment logic in OpenAI interactions to account for incomplete states (`length`, `content_filter`) and tool call indices.
- Implement changes to normalize tool call indexing to ensure contiguous 0-based indexing.
- Add `status` and `incomplete_details` fields to OpenAI response payloads for enriched status handling.
- Improve logic for handling `generation_config` fields during interactions request conversion.
- Add robust defaulting for missing usage metrics in response payloads.
- Ensure comprehensive test coverage for all enhanced scenarios.

Closes: #5851
2026-09-16 10:24:47 +08:00
sususu
f51d3ae93b fix(interactions): strip invalid id from function_result and redundant call_id from function_call
- Remove unexpected id parameter from function_result in Claude and OpenAI Chat Interactions request translators to comply with Google Interactions API schema and fix HTTP 400 (Unknown parameter 'id' at 'input[N]').
- Remove redundant call_id parameter from function_call in Claude Interactions request translator to match schema requirements.
- Propagate is_error flag between Claude tool_result and Interactions function_result.
- Align Devin executor to prioritize call_id for function_result steps.
- Add regression tests covering parameter schemas and end-to-end executor request generation.

Closes: #5828
2026-09-16 00:31:31 +08:00
Luis Pater
65348b9594 feat(executor): add native Meta (Muse Code) provider integration
- Introduced `MetaExecutor` to support native Meta (Muse Code) API operations, including `Execute`, `ExecuteStream`, and `CountTokens`.
- Added logic to handle Meta-specific `responses` endpoint, including request preparation, enriched authentication, header management, and response translation.
- Implemented token counting functionality with custom `CountTokens` logic.
- Updated `meta_executor` to process streamed and non-streamed responses, maintaining compatibility with the Codex schema.
- Added utility functions to handle events, errors, and enriched metadata common to Meta API requests.
- Extended `models.json` to include Meta's updated configuration with additional thinking levels like "minimal" and "max."
- Introduced comprehensive tests to validate Meta-specific execution, streaming, header assignments, and response formatting.
2026-09-15 18:12:49 +08:00
Luis Pater
42ca5d3412 Merge PR #5502 feat/meta-provider into cpa/muse
Bring in native Meta (Muse Code) provider support while keeping the
existing Devin integration and original Meta commit history.
2026-09-15 12:05:40 +08:00
Luis Pater
7bbfeaf8a7 feat(executor): promote reasoning content as summary and sanitize inputs
- Introduce `promoteOpenAIResponsesReasoningTextToSummary` to move `reasoning_text` parts from content to summary when the summary is empty.
- Clear `reasoning.content` to comply with Codex schema constraints (`maxItems: 0`).
- Implement safeguards for handling cleartext reasoning, preserving valid encrypted content, and stripping invalid `encrypted_content`.
- Add comprehensive tests to validate behavior for promoting reasoning texts, preserving existing summaries, and ensuring sanitization rules.

Closes: #5825
2026-09-15 03:42:08 +08:00
Luis Pater
1fac8cc0c8 feat(executor): strip unsupported id fields from Gemini interactions payload
- Introduce `sanitizeGeminiInteractionsUnsupportedInputIDs` to remove `id` fields from Gemini interactions `input` and `content` items.
- Update execution logic to apply the sanitization process before upstreaming payloads.
- Add tests to ensure payloads are correctly sanitized and validate `call_id` pairing for Gemini interactions.

Closes: #5828
2026-09-15 02:21:45 +08:00
sususu
6e307553f4 feat(codex): add optional time ceiling for stream bootstrap buffering
- Add `stream-bootstrap-timeout` configuration (defaulting to 0/unlimited, recommended 20s behind reverse proxies) to bound how long early handshake or trickled events may hold response headers.
- Release stream buffering into normal in-stream delivery once the time budget is exhausted on both SSE and WebSocket executors.
- Deliver post-timeout overload and status-bearing errors in-stream rather than triggering credential failover, preventing latency doubling on long reasoning turns.
- Provide thread-safe mock clock test harness and comprehensive unit tests covering timeout release, unlimited default, disabled ceilings, and post-timeout error delivery.
2026-09-14 14:25:45 +08:00
sususu98
bb20fa2d5e Merge pull request #5724 from Viggo95/fix/codex-bootstrap-buffer-noncontent-events
fix(codex): keep bootstrap buffer open for events that carry no output
2026-09-14 12:27:00 +08:00
Luis Pater
c1cb0c5de1 fix(translator): preserve html characters in tool arguments and fix devin sequential tool calls
- Introduce `SetStringWithoutHTMLEscape` to prevent escaping of HTML characters (`<`, `>`, `&`) in tool call arguments and argument deltas across translators.
- Handle sequential tool calls in Devin executor that share the same stream index but have distinct tool call IDs.
2026-09-14 11:04:08 +08:00
sususu
5f56ce928e fix(devin): trigger dimension group fallback if any usage metric is zero 2026-09-14 09:37:29 +08:00
sususu
4c331bb953 fix(devin): unwrap repeated field 28 groups, merge partial field 7 usage, and harden APICall escaping 2026-09-14 09:32:05 +08:00
sususu
0719520f2a feat(api-call): support $TOKEN$ replacement in request body data 2026-09-14 09:20:03 +08:00
sususu
b4749cb204 fix(devin): parse field 8 header submessages, accumulate field 4 prompt tokens, and add field 28 usage fallback 2026-09-14 09:19:51 +08:00
sususu
30b2ac8996 refactor(devin): deduplicate auth credentials extraction, filter sparse tool calls, and optimize model lookup 2026-09-13 23:34:43 +08:00