fix(codex-bridge): ship zstd for the agent's Python and refuse to link without it
ci / mobile-link-windows (push) Successful in 44s
ci / approval-gate-windows (push) Successful in 2m32s

Codex compresses request bodies with zstd. The agent venv is Python 3.11, which
has no zstd in its standard library, so every Codex request failed on a fresh
install. The matching zstandard build now ships beside the bridge; the status
endpoint reports ok=false when bodies cannot be read, and the IDE then leaves
Codex's config alone. A running bridge from an older build is replaced, and
"Sync now" makes the bridge re-read the IDE session at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HRDGW1LiKcDUZYUdKBoWYW
This commit is contained in:
2026-10-09 16:27:55 +03:00
co-authored by Claude Opus 5.5
parent dea67fc153
commit b560950f82
13 changed files with 5317 additions and 10 deletions
+17 -1
View File
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'
import { CODEX_BRIDGE_START_BUDGET_MS, type CodexLinkDeps, type CodexLinkPaths, createCodexLink } from './codex-link'
import {
CODEX_LINK_LINE,
CODEX_LINK_REFRESH_URL,
CODEX_LINK_STATUS_URL,
CODEX_LINK_STOP_URL,
codexBridgeArgs,
@@ -21,7 +22,7 @@ const PATHS: CodexLinkPaths = {
const BRIDGE_JSON = `${PATHS.bridgeHome}\\bridge.json`
const BACKUP = `${PATHS.codexConfig}.aiturk-yedek`
const STATUS_OK = { ok: true, surum: '1', ide_durum: 'tamam', ide_model: 7, ozet: true }
const STATUS_OK = { ok: true, surum: '2', ide_durum: 'tamam', ide_model: 7, ozet: true }
const USER_CONFIG = 'model = "gpt-6"\r\n\r\n[features]\r\nweb = true\r\n'
interface World {
@@ -103,6 +104,12 @@ function createWorld(patch: Partial<World> & { files?: Map<string, string> } = {
return null
}
if (method === 'POST' && url === CODEX_LINK_REFRESH_URL) {
world.events.push('refresh')
return world.listening ? STATUS_OK : null
}
if (method === 'POST' && url === CODEX_LINK_STOP_URL) {
world.events.push('stop')
@@ -273,6 +280,15 @@ describe('applyCodexLink', () => {
expect(world.files.get(PATHS.codexConfig)).toBe(`${CODEX_LINK_LINE}\r\n${USER_CONFIG}`)
})
it('asks a running bridge to re-read the IDE session on every apply', async () => {
const { link, world } = createWorld({ listening: true })
await link.apply({ sync: true })
expect(world.events).toContain('refresh')
expect(spawns(world)).toEqual([])
})
it('never overwrites the first backup', async () => {
const { link, world } = createWorld({ listening: true })
world.files.set(BACKUP, 'the original original')