Commit Graph

1020 Commits

Author SHA1 Message Date
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
sususu
9d190f309c feat(devin): integrate global signature detector for cross-provider signature detection 2026-09-13 23:34:43 +08:00
sususu
fb2c1c1afa fix(devin): transport reuse, interleaved stream steps, strings.Builder panic, and updater URL 2026-09-13 23:34:43 +08:00
sususu
926450e87b fix(devin): dynamic catalog-driven chat_model_uid resolution and effort clamping 2026-09-13 23:34:43 +08:00
sususu
1604cb0334 fix(devin): normalize upstream internal errors to 502 Bad Gateway 2026-09-13 23:34:43 +08:00
sususu
98b106f0e8 fix(devin): store transient quota metrics strictly in Quota.Signals and keep Metadata static 2026-09-13 23:34:43 +08:00
sususu
6a239f5715 fix(devin): propagate stream chunk errors, fix truncated protobuf infinite loop, respect ctx roundtripper, and limit auth response body reads 2026-09-13 23:34:43 +08:00
sususu
86de823daa perf(devin): cache Devin HTTP transports per proxy URL to reuse connection pools 2026-09-13 23:34:43 +08:00
sususu
6df8f32278 perf(devin): eliminate O(K^2) tool call argument string allocations using strings.Builder 2026-09-13 23:34:43 +08:00
sususu
6c7d2d57f7 perf(devin): cache sensitive word regex matcher, preallocate request bytes and frame decompression buffer 2026-09-13 23:34:43 +08:00
sususu
5d0c77cf3f fix(devin): enforce Connect-RPC EOS trailer invariant, validate frame flag, and bind OAuth callback to ctx 2026-09-13 23:34:43 +08:00
sususu
50dd582641 fix(devin): update streaming tool call step metadata if arriving in subsequent frames 2026-09-13 23:34:43 +08:00
sususu
d754298a8b fix(devin): bound tool call indices against OOM, set Refresh timeout, and check manual callback state 2026-09-13 23:34:43 +08:00
sususu
2f2f9b4381 fix(devin): guard against reopening thought step on late-arriving signatures 2026-09-13 23:34:43 +08:00
sususu
a5ea971f35 fix(devin): sort streaming tool call stop events and normalize prompt CRLF 2026-09-13 23:34:43 +08:00
sususu
f1f5506c0b fix(devin): align wire protocol, harden streaming, and resolve multi-turn tool/signature parity
- Wire parity: align Connect-RPC Sentry-Trace, User-Agent suppression, float32 double pattern, and dynamic 732-char hex device fingerprint
- Session ordinal & cache: implement process-scoped Field 15.2 with bounded LRU (5000 entries) and Field 15.4=14 user boundary; prioritize stable session_id over previous_interaction_id to preserve prompt caching
- Streaming robustness: unblock hung TCP reads on client cancellation via context watcher; accurately propagate stream read errors and trailer errors instead of swallowing truncated frames
- Thought signature & reasoning: emit raw delta signatures directly in active thought steps; eliminate redundant tail base64 re-encoding; ensure 1:1 assistant signature and thinking alignment across multi-turn history
- Tool call de-multiplexing: route parallel tool calls by tc.Index in both streaming step events and non-streaming aggregations
- Security & transport: escape OAuth callback error HTML against reflected XSS, enforce strict state validation, and isolate Devin HTTP transport with tr.Clone()
2026-09-13 23:34:43 +08:00
sususu
85ddf3aeb5 fix(devin): calculate total_input_tokens and total_tokens correctly 2026-09-13 23:34:43 +08:00
sususu
bf06746d42 feat(devin): map model aliases and swe-1-7/haiku/sonnet/gpt-4-1 UIDs 2026-09-13 23:34:43 +08:00
sususu
ca664c6ede feat(devin): clamp maxTokens to model MaxCompletionTokens 2026-09-13 23:34:43 +08:00
sususu
2683ec201d feat(cmd): add fetch_devin_models CLI tool for dynamic model catalog extraction 2026-09-13 23:34:43 +08:00
sususu
469aa3678f feat(devin): parse protobuf timestamp and harden partial failure logging 2026-09-13 23:34:43 +08:00
sususu
16cb6c0b02 feat(devin): add symmetric decoded upstream response in request log 2026-09-13 23:34:43 +08:00
sususu
59df75d20c docs(devin): update DevinExecutor comment with verbatim reconstructed cloud system prompt 2026-09-13 23:34:43 +08:00
sususu
0c2351bb89 feat(devin): support none thinking level for glm-5-2 2026-09-13 23:34:43 +08:00
sususu
308e5ad3b1 feat(devin): add deepseek-v4-flash and deepseek-v4-1-flash models 2026-09-13 23:34:43 +08:00
sususu
8a3770710e docs(devin): document cloud-side system instructions baseline in DevinExecutor 2026-09-13 23:34:43 +08:00
sususu
2caab7dbf9 feat(devin): enhance request-log with intermediate interactions and decoded upstream body 2026-09-13 23:34:43 +08:00
sususu
ea2f29feec feat(devin): add devin/gemini-3-8-flash and devin/grok-4-6 model definitions and signature recognition
- Register static model definitions for devin/gemini-3-8-flash (1M context, Google) and devin/grok-4-6 (500k context, xAI).
- Support gemini38Efforts (low/medium/high) and grok46Efforts (low/medium/high/xhigh) in ResolveDevinChatModelUID, supporting both colon and parenthesis suffix parsing.
- Recognize Gemini Tink thought signatures (AY-prefix / 0x01 Tink header) in detectSignatureType and parseSignatureBytes.
- Add unit tests for both models in registry and devin_models.
2026-09-13 23:34:43 +08:00
sususu
5b8e3821b1 fix(devin): strip system prompt lines matching configured sensitive words to evade unicode normalization bypass 2026-09-13 23:34:43 +08:00
sususu
7b5741c639 feat(devin): support credential quota and seat status query via GetUserStatus
- Implement Connect-RPC GetUserStatus serialization and response parsing in internal/auth/devin/user_status.go.
- Extract user email, plan, username, user_id, team_id, org_id, daily/weekly quota percentages, and reset timestamps.
- Wire user status into DevinExecutor.Refresh to update auth metadata and Quota.Signals.
- Add devin to ProviderSupportsQuotaObservation so CPA management endpoints surface quota observations.
- Enrich Devin OAuth login flow with user status, email, and quota information, and add CSRF state verification.
- Support base_url override in DevinAuthService for mock testing and custom gateways.
2026-09-13 23:34:43 +08:00
sususu
c0b76c2d09 refactor(devin): keep sensitive words strictly external in config.yaml without hardcoding 2026-09-13 23:34:43 +08:00
sususu
c0b86059c4 fix(devin): sanitize claude subagent identity and emoji directives to prevent content policy 403 2026-09-13 23:34:43 +08:00
sususu
d115fe2c45 refactor(devin): align sensitive-words with antigravity to config.yaml only 2026-09-13 23:34:43 +08:00
sususu
1b6948513d feat(devin): support sensitive-words in auth json metadata and attributes 2026-09-13 23:34:43 +08:00
sususu
f5247e496f fix(devin): restrict sensitive word obfuscation strictly to system prompt only 2026-09-13 23:34:43 +08:00
sususu
02fd1bde78 feat(devin): restrict glm-5-2 to free tier, remove static swe-1-7-lightning, and harden cloak 2026-09-13 23:34:43 +08:00
sususu
eed249072d feat(devin): prefix all Devin model IDs with devin/ namespace 2026-09-13 23:34:43 +08:00
sususu
cbe800aa28 feat(devin): bind upstream session_id and cascade_id to CPA canonical session 2026-09-13 23:34:43 +08:00
sususu
f94752762b feat(devin): add Devin/Cognition provider integration and CLI OAuth
Implement the full Devin/Cognition Connect-RPC provider support across all CPA endpoints (/v1/chat/completions, /v1/messages, /v1/responses), complete with binary protobuf wire framing, streaming tools/arguments delta handling, thinking/reasoning replay, and CLI OAuth authentication.

Key highlights:
- Wire Protocol & Streaming:
  * Implemented Connect-RPC uncompressed 5-byte framing (0x00 + 4-byte length + protobuf) for ApiServerService/GetChatMessage.
  * Implemented Devin protobuf encoder/decoder in internal/runtime/executor/helps/devin_wire.go, including ClientMetadata, prompts, tools, completion_config, and multimodal image handling (Prompt Field #10).
  * Stream frame consumption via interactions protocol, correctly mapping arguments_delta and tracking multiple sequential tool calls (currentToolCallActive).
  * Streaming thought summary and sealed.v1 signature deltas targeting the thinking step.

- Model Registration & Thinking Clamping:
  * Registered static fallback models in model_definitions.go (swe-2, claude-fable-5-1, gpt-6-astra, swe-1-7-lightning, glm-5-2, glm-5-3).
  * Configured ThinkingSupport with discrete levels per model family.
  * Implemented CPA-standard nearest-neighbor clamping for thinking levels (minimal/low -> medium, xhigh -> max for swe-2).
  * Mapped thinking effort to Devin upstream model UID (e.g. swe-2-medium, swe-2-high, swe-2-max).

- Sensitive Words & System Prompt Sanitization:
  * Added devin.sensitive-words configuration in internal/config/config_types.go and config.go, matching Antigravity conventions.
  * Supported zero-width space (\u200b) obfuscation in prompts, tools, and system instructions via SensitiveWordMatcher.
  * Stripped Claude Code billing headers (x-anthropic-billing-header:) and CLI identity signatures from system instructions and tool descriptions to avoid upstream content filter rejections.

- Signature Compatibility:
  * Added SignatureProviderSWE = "swe" recognizing sealed.v1.* reasoning signatures in internal/signature/provider_compatibility.go.
  * Propagated reasoning.encrypted_content on Responses API and thinking.signature on Messages API.

- Authentication:
  * Implemented Devin PKCE OAuth flow with loopback callback server and headless manual token/code paste (--no-browser).
  * Registered Devin authenticator in SDK and CLI (-devin-login flag).
  * Integrated with management OAuth session endpoints and credentials manager.
2026-09-13 23:34:43 +08:00
Luis Pater
94d6eb535e docs(config): document payload filter examples for codex tools
- Add example payload filter rules in `config.example.yaml` for stripping tools from both flat and nested `additional_tools` Codex request payloads.

Closes: #5792
2026-09-13 22:12:28 +08:00
Luis Pater
f702bc1ac2 feat(codex): preserve native fidelity for responses-lite requests
- Detect native responses-lite requests via headers and client metadata.
- Skip instructions normalization and synthetic session cloaking for native requests.
- Preserve upstream completion output during websocket response forwarding.

Closes: #5780
2026-09-13 15:05:03 +08:00
Luis Pater
e696ea47c5 feat(codex): forward X-Codex-Turn-State header in executor requests
- Ensure `X-Codex-Turn-State` is preserved and forwarded from incoming client requests.

Closes: #5778
2026-09-13 14:42:26 +08:00
Viggo95
cb73cd9936 fix(codex): buffer keepalive and empty item announcements during codex bootstrap
The bootstrap buffer released the stream on the first frame outside the
handshake allow-list. Upstream sends `keepalive` heartbeats and
`response.output_item.added` before the first token, so the downstream headers
were committed while nothing had been produced, and an overload rejection
arriving afterwards could no longer be retried on another credential.

Extend the allow-list with `keepalive`, and with `response.output_item.added`,
`response.content_part.added` and `response.reasoning_summary_part.added` when
they announce something that is still empty. `response.output_item.added` is
accepted only for `message`, `reasoning`, `function_call` and `custom_tool_call`
items, and only while their content, summary, arguments or input is empty: every
other item type stands for a server-side operation that may already be running -
a `web_search_call` is announced with status "in_progress" and its `searching`
event follows immediately - and failing the attempt over after one would run
that operation again on another credential. Part announcements are matched on a
closed list of textual part types for the same reason.

The list stays closed. "Nothing has happened yet" cannot be derived from the
absence of a TTFT token, because TTFT deliberately ignores server-side tool
traffic such as `response.shell_call_output_content.delta` and its `.done`
counterpart, so an unrecognised frame, an unrecognised item type and an
unrecognised part type all release the stream exactly as before.

Holding those frames also required fixing the bound on how much may be held.
codexBootstrapMaxBufferedEvents was enforced with len(bufferedChunks), and a
chunk count bounds only the downstream formats that render every upstream frame:
the OpenAI Chat Completions and Gemini translators return zero chunks for a frame
they do not recognise, which is true of every frame added here. Count frames read
from the upstream instead, and cap what a bootstrap accumulates over the upstream
frames and the chunks they translate into. The SSE scanner walks physical lines
and an event can arrive as one line (": keepalive"), two, or three
(event:/data:/blank), so the frame budget is sized for the widest framing rather
than derived from any separator. The websocket loop counts a message as soon as
it is read, before the branches that skip non-text and whitespace-only messages,
so a peer sending only frames the loop skips cannot hold the downstream headers
open; the message that exhausts the budget is still processed and delivered
rather than dropped. Both caps are checked before a frame is admitted, so one
oversized frame cannot be taken on the strength of an empty buffer. This widens
the window where one frame rendered one chunk - the websocket path effectively
moves from 16 frames to 48.

An empty `response.incomplete` seen while buffering is now delivered in-stream
instead of failing the attempt over, matching the websocket executor and the
documented contract that only overload and rate-limit rejections trigger
failover.

`isCodexHandshakeMetadataEvent` is renamed to `isCodexBootstrapBufferableEvent`
because the list is no longer only handshake metadata. Both config doc sites
describe what is held, that heartbeats are held too, that SSE also holds the
lines around a `data:` frame, and that the hold is bounded by frames and bytes
rather than by wall-clock time.
2026-09-12 22:27:44 +08:00
Luis Pater
d9b8fdb77f fix(claude): forward unmanaged caller betas on direct anthropic requests
- Define a managed Claude beta set to distinguish proxy-governed betas from caller extensions.
- Forward unmanaged caller betas on direct Anthropic endpoints to support newer client features.

Closes: #5738
2026-09-11 23:44:21 +08:00