feat(executor): add Devin (Codeium Cascade) provider - #180
Open
jroth1111 wants to merge 5 commits into
Open
Conversation
Add a new Devin executor that talks to the Codeium Cascade backend
(server.codeium.com) using the Connect-RPC protocol, impersonating the
Devin CLI (chisel). This enables CLIProxyAPIPlus to serve Devin's free
models (GLM-5.2 High, SWE-1.7, SWE-1.6) through the standard OpenAI
chat completions API.
The executor implements the ProviderExecutor interface with:
- OpenAI chat completion → Devin GetChatMessage protobuf translation
- Connect-RPC framing (uncompressed, flag 0x00) matching the Devin CLI
- Streaming response parsing (7-frame: init, thinking, text, finish,
usage, display stats, trailer) with OpenAI SSE conversion
- Non-streaming mode that collects stream chunks into a single response
- Basic auth header (Basic <token>-<token>) matching the CLI pattern
- Session token normalization (devin-session-token$ prefix)
- Deterministic attestation field (f) generation
- Caller overrides for maxTokens, temperature, and topP
Auth is configured via a JSON file in the auth directory with:
{"type": "devin", "devin_session_token": "<token>"}
Models are registered statically in models.json with 6 free Devin
models. The executor is registered in service_executors.go and included
in the baseline executor auths.
Wire format verified against the Devin CLI v3000.4.25 via mitmproxy:
- Metadata fields match (ideName, extensionName, ideType, version, os, f)
- Completion config defaults match (maxTokens=128000, temperature=1.0,
topK=40, topP=0.95, maxNewlines=400)
- Request fields match (requestType=CASCADE, plannerMode=DEFAULT)
- HTTP headers match (authorization, content-type, connect-protocol-version)
All 15 unit tests pass covering protobuf encoding/decoding, Connect
frame parsing, OpenAI request parsing, Devin request building, and
OpenAI response/SSE generation.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…l registration - Register Devin models in service_models.go switch (case "devin") so the /v1/models endpoint lists them when a Devin auth file is loaded. - Return raw JSON from buildOpenAIStreamChunk (no "data: " prefix or "\n\n" suffix) since the proxy's SSE handler wraps each chunk itself. Remove the manual "data: [DONE]" sentinel for the same reason. - Fix JSON structure: usage was appended after the root object's closing brace; move it inside before closing. - Only include usage in stream chunks when token counts are non-zero (the Devin server sends zero-valued usage in every frame). - Fix Execute() (non-streaming) to parse OpenAI JSON chunks from ExecuteStream() instead of calling parseGetChatMessageResponse() (which expects raw protobuf). Use gjson to extract content, reasoning, finish_reason, usage, and tool_calls from each chunk. - Change default max_tokens from 128000 to 64000 to match the Devin CLI. - Update unit tests for the new max_tokens default. Verified end-to-end: both streaming and non-streaming chat completions return correct content, reasoning, finish_reason, and usage. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Fresh mitmproxy capture of the Devin CLI (v3000.4.25) confirms the CLI sends max_tokens=128000 in the CompletionConfiguration, not 64000. Reverted the previous change. Verified via side-by-side mitmproxy comparison of CLI vs proxy requests: - Metadata (field 1, 990 bytes): identical structure - Configuration (field 8): identical (128000, 400, 1.0, 40, 0.95) - request_type=5, planner_mode=1, cascade_id, chat_model_uid: all match - Response frame structure matches (field 1/3/4/5/7/9/12/17) Tested all 6 models (glm-5-2, glm-5-2-1m, glm-5-2-max, swe-1-7, swe-1-7-medium, swe-1-6) with streaming, non-streaming, system prompts, and multi-turn conversations. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Non-streaming assembly: tool call arguments arrive as fragments across multiple stream chunks (first chunk has id+name, subsequent chunks have argument pieces with empty id/name). Merge fragments into the last tool call instead of treating each as a separate entry. Add docs/devin.md with usage examples including tool calling and multi-turn tool results. Verified tool calling end-to-end: - Non-streaming: single merged tool call with complete arguments - Streaming: fragments accumulate correctly - Multi-turn: model correctly uses tool results in follow-up response Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Tests cover: - Tool definition encoding (name, description, json_schema_string) - Tool call encoding (id, name, arguments_json) - Non-streaming response with multiple tool calls - Streaming SSE chunk with tool call deltas All 19 Devin unit tests pass. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
server.codeium.com) using the Connect-RPC protocol, impersonating the Devin CLI (chisel)Implementation
New files
internal/runtime/executor/devin_protobuf.goprotowire(no codegen needed)internal/runtime/executor/devin_executor.goProviderExecutor— OpenAI → Devin translation, Connect-RPC framing, streaming response parsing, tool call fragment merginginternal/runtime/executor/devin_executor_test.godocs/devin.mdModified files
sdk/cliproxy/service_executors.goDevinExecutorin the provider switch + baseline authssdk/cliproxy/service_models.goregisterModelsForAuthWithCacheswitchinternal/registry/model_definitions.goDevinfield tostaticModelsJSON+GetDevinModels()internal/registry/models/models.jsonHow it works
GetChatMessageRequestprotobufpromptfield (field 2)chat_message_prompts(field 3, repeated)tools(field 10, repeated) asChatToolDefinitiontemperature,max_tokens,top_p→CompletionConfiguration(field 8)0x00, uncompressed)Content-Type: application/connect+proto,Connect-Protocol-Version: 1,Authorization: Basic <token>-<token>,User-Agent: "",Accept-Encoding: identityGetChatMessageResponseprotobuf → OpenAI SSE chunks (raw JSON; the proxy's SSE handler wraps each chunk withdata: %s\n\n)ExecuteStream()and assembles a singlechat.completionresponse, merging fragmented tool call argumentsChatToolDefinition(field 10). Response tool call deltas (delta_tool_calls, field 6) are converted to OpenAI'stool_callsformat. Multi-turn tool results are encoded asChatMessagePromptwithsource=TOOLandtool_call_id.Auth configuration
Create a JSON file in the auth directory (e.g.,
auths/devin.json):{ "type": "devin", "devin_session_token": "devin-session-token$eyJhbGci..." }The token is the same session token used by the Devin CLI (found in
~/.local/share/devin/credentials.toml).Metadata identity (matching Devin CLI)
ide_namedevin-cliextension_version/ide_version3000.4.25extension_name/ide_typechisellocaleenosdarwinf(attestation)Completion config defaults
max_tokensmax_tokenstemperaturetemperaturetop_ptop_ptop_kmax_newlinesWire format verification
Side-by-side comparison of the Devin CLI (v3000.4.25) and CLIProxyAPIPlus requests captured via mitmproxy:
Request comparison (field-by-field)
*The CLI sends a system prompt by default; the proxy only sends one when the OpenAI request includes a system message.
Response comparison
Both the CLI and proxy responses use the same Connect frame structure with identical field layout:
Tool calling validation (mitmproxy)
Captured a complete 3-turn tool calling flow via mitmproxy:
Turn 1 (1898 bytes request, 12562 bytes response):
run_command({"command": "ls"})— 5 frames (id+name, then arg fragments)edit_file({"path": "hello.txt", "content": "Hello World"})— 10 framesTurn 2 (2088 bytes request):
ChatMessagePromptwithsource=TOOLandtool_call_idTurn 3 (2343 bytes request):
End-to-end test results
All 6 models tested with streaming, non-streaming, system prompts, multi-turn, and tool calling:
Test plan
go build -o test-output ./cmd/server && rm test-outputsucceedsgo test -v -run TestDevin ./internal/runtime/executor/— 19 pass, 0 failgofmt -w .— all files formattedGenerated with Devin