devinx — Claude Code on Cognition SWE-2 via cliproxyapi (setup guide) A developer published a setup guide for a Python shim that exposes Cognition's SWE-2 and SWE-1.x coding models through an OpenAI-compatible API, letting tools like Claude Code call them via CLIProxyAPI. The shim translates OpenAI chat completion requests into Cognition's Connect-RPC GetChatMessage calls against server.codeium.com, authenticating with the Devin CLI's stored credential. | | /usr/bin/env python3 | | | """OpenAI-compatible shim in front of Cognition's Connect-RPC GetChatMessage. | | | | | | Serves POST /v1/chat/completions stream + non-stream and GET /v1/models by | | | translating to exa.api server pb.ApiServerService/GetChatMessage against | | | server.codeium.com, authenticated with the Devin CLI's stored credential. | | | Runs behind CLIProxyAPI as an openai-compatibility upstream. | | | """ | | | import glob | | | import gzip | | | import json | | | import os | | | import re | | | import struct | | | import threading | | | import time | | | import uuid | | | from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer | | | | | | import requests | | | from google.protobuf import descriptor pb2, descriptor pool, message factory | | | from google.protobuf import timestamp pb2, duration pb2, any pb2, struct pb2 | | | from google.protobuf import wrappers pb2, empty pb2, field mask pb2, type pb2 | | | from google.protobuf import source context pb2, api pb2 | | | | | | HERE = os.path.dirname os.path.abspath file | | | UPSTREAM = "https://server.codeium.com" | | | AUTH PATH = "/exa.auth pb.AuthService/GetUserJwt" | | | CHAT PATH = "/exa.api server pb.ApiServerService/GetChatMessage" | | | IDE NAME = "windsurf" | | | IDE VERSION = "3.51.3" | | | EXT VERSION = "1.48.2" | | | SESSION PREFIX = "devin-session-token$" | | | STOP PATTERNS = "<\|user\| ", "<\|bot\| ", "<\|context request\| ", "<\|endoftext\| ", "<\|end of turn\| " | | | | | | MODELS = | | | "swe-2-max", "swe-2-high", "swe-2-medium", | | | "swe-1-7", "swe-1-7-medium", "swe-1-7-lightning", "swe-1-7-lightning-medium", | | | "swe-1-6", "swe-1-6-fast", | | | | | | | | | SRC USER, SRC SYSTEM, SRC TOOL = 1, 2, 4 | | | REQ CASCADE, PLANNER DEFAULT = 5, 1 | | | CACHE EPHEMERAL = 1 | | | STOP MAX TOKENS = 3 | | | | | | pool = descriptor pool.DescriptorPool | | | for m in timestamp pb2, duration pb2, any pb2, struct pb2, descriptor pb2, | | | wrappers pb2, empty pb2, field mask pb2, type pb2, source context pb2, api pb2 : | | | fd = descriptor pb2.FileDescriptorProto | | | fd.ParseFromString m.DESCRIPTOR.serialized pb | | | try: | | | pool.Add fd | | | except Exception: | | | pass | | | fdps = {} | | | for p in glob.glob os.path.join HERE, " .fdp" : | | | fd = descriptor pb2.FileDescriptorProto | | | fd.ParseFromString open p, "rb" .read | | | fdps fd.name = fd | | | added = set | | | for in range 40 : | | | for name, fd in fdps.items : | | | if name in added: | | | continue | | | try: | | | pool.Add fd | | | added.add name | | | except Exception: | | | pass | | | | | | | | | def msg name : | | | return message factory.GetMessageClass pool.FindMessageTypeByName name | | | | | | | | | GetUserJwtRequest = msg "exa.auth pb.GetUserJwtRequest" | | | GetUserJwtResponse = msg "exa.auth pb.GetUserJwtResponse" | | | GetChatMessageRequest = msg "exa.api server pb.GetChatMessageRequest" | | | GetChatMessageResponse = msg "exa.api server pb.GetChatMessageResponse" | | | | | | | | | def load key : | | | if os.environ.get "DEVIN SHIM API KEY" : | | | return os.environ "DEVIN SHIM API KEY" | | | Prefer the shim's own login created via XDG DATA HOME=~/devin-shim/data | | | devin auth login ; fall back to the Devin CLI's credential. | | | for cred in os.path.expanduser "~/devin-shim/data/devin/credentials.toml" , | | | os.path.expanduser "~/.local/share/devin/credentials.toml" : | | | if not os.path.exists cred : | | | continue | | | for line in open cred : | | | if line.startswith "windsurf api key" : | | | return line.split '"' 1 | | | raise RuntimeError "no devin credential found" | | | | | | | | | API KEY = load key | | | if not API KEY.startswith SESSION PREFIX : | | | API KEY = SESSION PREFIX + API KEY | | | | | | jwt lock = threading.Lock | | | jwt = {"token": None, "exp": 0.0, "base": None} | | | | | | | | | def metadata jwt="" : | | | return { | | | "api key": API KEY, | | | "user jwt": jwt, | | | "ide name": IDE NAME, | | | "ide version": IDE VERSION, | | | "extension name": "windsurf", | | | "extension version": EXT VERSION, | | | "locale": "en", | | | "session id": str uuid.uuid4 , | | | "request id": uuid.uuid4 .int & 2 63 - 1 , | | | } | | | | | | | | | def jwt expiry token : | | | try: | | | import base64 | | | payload = token.split "." 1 | | | payload += "=" -len payload % 4 | | | return json.loads base64.urlsafe b64decode payload .get "exp", 0 | | | except Exception: | | | return 0.0 | | | | | | | | | def get jwt force=False : | | | with jwt lock: | | | now = time.time | | | if not force and jwt "token" and jwt "exp" - 60 now: | | | return jwt "token" , jwt "base" | | | req = GetUserJwtRequest metadata= metadata | | | r = requests.post UPSTREAM + AUTH PATH, data=req.SerializeToString , | | | headers={"content-type": "application/proto", | | | "connect-protocol-version": "1"}, timeout=30 | | | r.raise for status | | | resp = GetUserJwtResponse | | | try: | | | resp.ParseFromString r.content | | | except Exception: | | | resp.ParseFromString gzip.decompress r.content | | | if not resp.user jwt: | | | raise RuntimeError "GetUserJwt returned empty jwt" | | | jwt "token" = resp.user jwt | | | jwt "exp" = jwt expiry resp.user jwt or now + 3300 | | | jwt "base" = resp.custom api server url.strip or None | | | return jwt "token" , jwt "base" | | | | | | | | | def text of content : | | | if isinstance content, str : | | | return content | | | out = | | | for part in content or : | | | if part.get "type" == "text": | | | out.append part.get "text", "" | | | return "".join out | | | | | | | | | Cognition's input classifier rejects these Claude Code system-prompt blocks | | | competitor identity, security-policy vocabulary, product marketing + URLs . | | | Rewrite them to neutral equivalents; behavior instructions are unchanged. | | | SYS REWRITES = | | | re.compile r"You are ?:a ?Claude ^. \." , "You are a coding agent." , | | | re.compile r"IMPORTANT: Assist with authorized security testing. ? ?=\n\s \n\|\Z ", re.S , | | | "Assist with authorized security testing and defensive security work; refuse harmful or destructive requests." , | | | re.compile r"\n?\s -?\s Claude Code is available ^\n " , "" , | | | re.compile r"- For clear communication with the user the assistant MUST avoid using emojis\." , | | | "- For clear communication with the user, avoid emojis." , | | | | | | | | | | | | def scrub system text : | | | for rx, rep in SYS REWRITES: | | | text = rx.sub rep, text | | | return text | | | | | | | | | TaskOutput's shipped description trips the same classifier in combination | | | per-line fragments pass . It is deprecated upstream; send a short equivalent. | | | TOOL DESC REWRITES = { | | | "TaskOutput": "Get the output of a running or completed background task shell, agent, or remote session by task id.", | | | } | | | | | | | | | def images of content : | | | if isinstance content, str or not content: | | | return | | | out = | | | for part in content or : | | | if part.get "type" == "image url": | | | url = part.get "image url", {} .get "url", "" | | | if url.startswith "data:" : | | | mime, , b64 = url 5: .partition ";base64," | | | out.append {"base64 data": b64, "mime type": mime or "image/png"} | | | return out | | | | | | | | | def build request body : | | | system parts, prompts = , | | | cascade id = str uuid.uuid4 | | | for i, m in enumerate body.get "messages", : | | | role = m.get "role" | | | mid = str uuid.uuid5 uuid.NAMESPACE URL, f"{cascade id}\0{i}\0{role}" | | | if role in "system", "developer" : | | | system parts.append scrub system text of m.get "content" | | | elif role == "user": | | | prompts.append {"message id": mid, "source": SRC USER, | | | "prompt": text of m.get "content" , | | | "images": images of m.get "content" } | | | elif role == "assistant": | | | tcs = {"id": tc.get "id", "" , "name": tc.get "function", {} .get "name", "" , | | | "arguments json": tc.get "function", {} .get "arguments", "" } | | | for tc in m.get "tool calls" or | | | text = text of m.get "content" | | | thinking = m.get "reasoning content" or "" | | | prompts.append {"message id": mid, "source": SRC SYSTEM, "prompt": text, | | | "thinking": thinking, "tool calls": tcs} | | | elif role == "tool": | | | prompts.append {"message id": mid, "source": SRC TOOL, | | | "tool call id": m.get "tool call id", "" , | | | "prompt": text of m.get "content" , | | | "images": images of m.get "content" } | | | tools = {"name": t "function" "name" , | | | "description": TOOL DESC REWRITES.get t "function" "name" , | | | t "function" .get "description", "" , | | | "json schema string": json.dumps t "function" .get "parameters" or {} , | | | "strict": bool t "function" .get "strict" } | | | for t in body.get "tools" or if t.get "type" == "function" | | | tc = body.get "tool choice" | | | tool choice = {"option name": "auto"} | | | if isinstance tc, str and tc in "auto", "required", "none" : | | | tool choice = {"option name": tc} | | | elif isinstance tc, dict : | | | fn = tc.get "function" or {} .get "name" | | | if fn: | | | tool choice = {"tool name": fn} | | | stops = list STOP PATTERNS | | | stop = body.get "stop" | | | stops += stop if isinstance stop, str else list stop or | | | conf = {"num completions": 1, "max newlines": 200, "top k": 50, | | | "stop patterns": stops, "fim eot prob threshold": 1} | | | conf "max tokens" = int body.get "max completion tokens" or body.get "max tokens" or 64000 | | | if body.get "temperature" is not None: | | | conf "temperature" = conf "first temperature" = float body "temperature" | | | else: | | | conf "temperature" = conf "first temperature" = 0.4 | | | if body.get "top p" is not None: | | | conf "top p" = float body "top p" | | | else: | | | conf "top p" = 1 | | | model = body.get "model", "swe-2-max" | | | if "/" in model: | | | model = model.rsplit "/", 1 -1 | | | return GetChatMessageRequest | | | metadata= metadata get jwt 0 , | | | prompt="\n\n".join p for p in system parts if p , | | | chat message prompts=prompts, | | | chat model uid=model, | | | request type=REQ CASCADE, | | | planner mode=PLANNER DEFAULT, | | | tool choice=tool choice, | | | system prompt cache options={"type": CACHE EPHEMERAL}, | | | disable parallel tool calls=False, | | | cascade id=cascade id, | | | execution id=str uuid.uuid4 , | | | configuration=conf, | | | tools=tools, | | | , model | | | | | | | | | def chat stream req : | | | """Yield GetChatMessageResponse, None per frame or None, error str on trailer error.""" | | | jwt, base = get jwt | | | req.metadata.user jwt = jwt | | | body = req.SerializeToString | | | for attempt in range 2 : | | | gz = gzip.compress body | | | frame = bytes 1 + struct.pack " I", len gz + gz | | | r = requests.post base or UPSTREAM + CHAT PATH, data=frame, | | | headers={"content-type": "application/connect+proto", | | | "connect-protocol-version": "1", | | | "connect-content-encoding": "gzip", | | | "connect-accept-encoding": "gzip", | | | "user-agent": "connect-go/1.18.1 go1.26.3 "}, | | | timeout=600, stream=True | | | if r.status code == 200: | | | break | | | if r.status code in 401, 403 and attempt == 0: | | | jwt, base = get jwt force=True | | | req.metadata.user jwt = jwt | | | body = req.SerializeToString | | | continue | | | yield None, f"upstream {r.status code}: {r.text :400 }" | | | return | | | buf = b"" | | | for chunk in r.iter content 65536 : | | | buf += chunk | | | while len buf = 5: | | | flag = buf 0 | | | ln = struct.unpack " I", buf 1:5 0 | | | if len buf < 5 + ln: | | | break | | | payload = buf 5:5 + ln | | | buf = buf 5 + ln: | | | if flag & 2: | | | trailer = gzip.decompress payload if flag & 1 else payload | | | try: | | | err = json.loads trailer .get "error" or {} | | | except Exception: | | | err = {} | | | if err.get "message" : | | | yield None, f"{err.get 'code', 'error' }: {err 'message' }" | | | continue | | | raw = gzip.decompress payload if flag & 1 else payload | | | msg = GetChatMessageResponse | | | msg.ParseFromString raw | | | yield msg, None | | | | | | | | | def openai chunk model, delta=None, finish=None, usage=None : | | | ch = {"index": 0} | | | if delta is not None: | | | ch "delta" = delta | | | if finish: | | | ch "finish reason" = finish | | | out = {"id": "chatcmpl-devin", "object": "chat.completion.chunk", | | | "created": int time.time , "model": model, "choices": ch } | | | if usage: | | | out "usage" = usage | | | return out | | | | | | | | | def sse obj : | | | return f"data: {json.dumps obj }\n\n".encode | | | | | | | | | def run chat body, wfile : | | | """Translate one OpenAI chat.completions call; returns final msg dict, usage, error .""" | | | try: | | | req, model = build request body | | | except Exception as e: | | | return None, None, f"request build: {e}" | | | stream = bool body.get "stream" | | | w = wfile if stream else None | | | headers sent = False | | | Cognition's input classifier denies borderline payloads nondeterministically | | | same body observed pass/fail . Retry while nothing reached the client. | | | for attempt in range 3 : | | | if attempt: | | | req, model = build request body | | | if w and not headers sent: | | | w.write b"HTTP/1.1 200 OK\r\ncontent-type: text/event-stream\r\n" | | | b"cache-control: no-cache\r\nconnection: close\r\n\r\n" | | | w.flush | | | w.write sse openai chunk model, delta={"role": "assistant"} | | | w.flush | | | headers sent = True | | | text, thinking = , | | | tool blocks = {} id - {"name":..., "json":...} | | | tool order = | | | usage = {} | | | stop = 0 | | | err = None | | | emitted = False | | | for msg, e in chat stream req : | | | if e: | | | err = e | | | break | | | if msg.delta text: | | | text.append msg.delta text | | | if w: | | | emitted = True | | | w.write sse openai chunk model, delta={"content": msg.delta text} | | | w.flush | | | if msg.delta thinking: | | | thinking.append msg.delta thinking | | | if w: | | | emitted = True | | | w.write sse openai chunk model, delta={"reasoning content": msg.delta thinking} | | | w.flush | | | for tc in msg.delta tool calls: | | | tid = tc.id or tool order -1 if tool order else "" | | | if not tid: | | | continue | | | if tid not in tool blocks: | | | tool blocks tid = {"name": tc.name, "json": ""} | | | tool order.append tid | | | if w: | | | emitted = True | | | idx = tool order.index tid | | | w.write sse openai chunk model, delta={"tool calls": | | | {"index": idx, "id": tid, "type": "function", | | | "function": {"name": tc.name, "arguments": ""}} } | | | w.flush | | | if tc.name: | | | tool blocks tid "name" = tc.name | | | if tc.arguments json: | | | prev = tool blocks tid "json" | | | acc = tc.arguments json if tc.arguments json.startswith prev else prev + tc.arguments json | | | delta = acc len prev : | | | tool blocks tid "json" = acc | | | if w and delta: | | | emitted = True | | | idx = tool order.index tid | | | w.write sse openai chunk model, delta={"tool calls": | | | {"index": idx, "function": {"arguments": delta}} } | | | w.flush | | | if msg.usage.input tokens: | | | usage = {"prompt tokens": int msg.usage.input tokens , | | | "completion tokens": int msg.usage.output tokens , | | | "total tokens": int msg.usage.input tokens + msg.usage.output tokens } | | | stop = msg.stop reason | | | if err and not emitted and attempt < 2 and "permission denied" in err: | | | print f"upstream permission denied, retrying attempt {attempt + 2}/3 ", flush=True | | | continue | | | break | | | if err: | | | if w: | | | w.write sse {"error": {"message": err, "type": "upstream error"}} | | | w.write b"data: DONE \n\n" | | | w.flush | | | return None, None, err | | | finish = "tool calls" if tool blocks else "stop" | | | if not tool blocks and stop == STOP MAX TOKENS: | | | finish = "length" | | | if w: | | | final = openai chunk model, delta={}, finish=finish, | | | usage=usage if body.get "stream options" or {} .get "include usage" else None | | | w.write sse final | | | w.write b"data: DONE \n\n" | | | w.flush | | | return None, None, None | | | msg out = {"role": "assistant", "content": "".join text } | | | if thinking: | | | msg out "reasoning content" = "".join thinking | | | if tool blocks: | | | msg out "tool calls" = | | | {"id": tid, "type": "function", | | | "function": {"name": b "name" , "arguments": b "json" }} | | | for tid, b in tid, tool blocks tid for tid in tool order | | | msg out "content" = msg out "content" or None | | | resp = {"id": "chatcmpl-devin", "object": "chat.completion", | | | "created": int time.time , "model": model, | | | "choices": {"index": 0, "message": msg out, "finish reason": finish} } | | | if usage: | | | resp "usage" = usage | | | return resp, usage, None | | | | | | | | | class Handler BaseHTTPRequestHandler : | | | protocol version = "HTTP/1.1" | | | | | | def log message self, fmt, args : | | | print f"{self.address string } {fmt % args}", flush=True | | | | | | def json self, code, obj : | | | data = json.dumps obj .encode | | | self.send response code | | | self.send header "content-type", "application/json" | | | self.send header "content-length", str len data | | | self.end headers | | | self.wfile.write data | | | | | | def do GET self : | | | if self.path.split "?" 0 in "/v1/models", "/models" : | | | self. json 200, {"object": "list", "data": | | | {"id": m, "object": "model", "created": 0, "owned by": "devin"} for m in MODELS } | | | else: | | | self. json 404, {"error": {"message": "not found", "type": "invalid request error"}} | | | | | | def do POST self : | | | path = self.path.split "?" 0 | | | if path not in "/v1/chat/completions", "/chat/completions" : | | | self. json 404, {"error": {"message": "not found", "type": "invalid request error"}} | | | return | | | try: | | | raw = self.rfile.read int self.headers.get "content-length", 0 | | | if os.environ.get "DEVIN SHIM DUMP" : | | | with open os.environ "DEVIN SHIM DUMP" + f".{time.time ns }.json", "wb" as fh: | | | fh.write raw | | | body = json.loads raw | | | except Exception as e: | | | self. json 400, {"error": {"message": f"bad json: {e}", "type": "invalid request error"}} | | | return | | | if body.get "stream" : | | | run chat owns the raw socket from here | | | resp, , err = run chat body, self.wfile | | | if err: | | | return | | | return | | | resp, , err = run chat body, None | | | if err: | | | self. json 502, {"error": {"message": err, "type": "upstream error"}} | | | else: | | | self. json 200, resp | | | | | | | | | if name == " main ": | | | port = int os.environ.get "DEVIN SHIM PORT", "8321" | | | print f"devin-shim listening on 127.0.0.1:{port}", flush=True | | | ThreadingHTTPServer "127.0.0.1", port , Handler .serve forever |