feat(codex): support custom system_prompt / append_system_prompt config - #1345
Conversation
chenhg5
left a comment
There was a problem hiding this comment.
结论: Approve (社区 PR @HaiyiMei 标准路径)
总体判断:
- PR 思路正确,精准对应 #1346 (Codex 项目无法设置自定义 system prompt) 根因。 Codex CLI 无原生
--system-promptflag, 作者把system_prompt+append_system_prompt合成一个 preamble prepend 到每个新 session 的第一条消息, resumed sessions 不重复注入。 跟现有 claudecode 端system_prompt/append_system_prompt(#1175) 命名 + 语义对齐 (claudecode 走--system-prompt+--append-system-promptflag, codex 走 preamble injection, 因 CLI 限制不得不 prepend)。 - 实现 clean: 复用
strings.TrimSpace+sections []string+strings.Join标准 idiom, 0 新概念。buildCodexPromptPreamble+prependCodexPromptPreamble拆成 2 个 pure function, 易测试, 跟 claudecode 端buildAppendSystemPrompt(agent/claudecode/session.go:79) shape 一致。 - 4 个新 test 对称精准:
TestNew_ParsesProjectPromptsFromOpts(验证opts["system_prompt"]/opts["append_system_prompt"]解析到 Agent struct) +TestCodexPromptPreamble_PrependsProjectPrompts(验证 "Project system prompt:" + "Additional project instructions:" 顺序) +TestCodexPromptPreamble_EmptyIsNoop(empty preamble 不修改 prompt) +TestSend_PrependsProjectPromptOnFreshSession(端到端: fresh session 触发 prepend, 验证 stdin 文件包含 preamble 3 段)。 CI 27500649006 5/5 PASS, 本地 4 个新 test 全 PASS, full codex suite 0.847s PASS 0 regression, go vet 0, gofmt 0 (PR-touched files)。
Review 范围 (QA 二次 review 2026-06-15):
- 看了 agent/codex/codex.go (3 个 section, Agent struct 增 2 field + New() 解析 + StartSession 透传) + agent/codex/session.go (buildCodexPromptPreamble + prependCodexPromptPreamble + newCodexSession + Send 注入) + agent/codex/appserver_session.go (appServerSession 增 2 field + newAppServerSession 初始化 + Send 注入) + 4 个新 test。
- 重点关注: 5 项 PM 必验证 (优先级 / config 加载 / 空值默认值 / CHANGELOG / CI)。
✅ 做得好的地方:
- 优先级语义 correct:
buildCodexPromptPreamble清楚展示 append 行为 —"Project system prompt:\n" + systemPrompt + "\n\n" + "Additional project instructions:\n" + appendPrompt, sections slice 按顺序 join, appendPrompt 永远在 systemPrompt 之後, 不 overwrite。 TestTestCodexPromptPreamble_PrependsProjectPrompts4 个 substring assertion 锁顺序 ("Before answering" → "Project system prompt" → "Additional project instructions" → "User message")。 - config 加载路径跟其他 agent 一致:
codex.go:58-60读opts["system_prompt"]/opts["append_system_prompt"],codex.go:106-107存到 Agent struct 时用strings.TrimSpace跟codexHome等其他 string 字段同 pattern。StartSession(codex.go:371-372) 复制 2 个字段到 local var, 透传给newCodexSession/newAppServerSession。 0 new persistence concern — cc-connect 重启会从 TOML 重新加载到 opts map。 - 空值 / 默认值 行为 handled:
buildCodexPromptPreamble两个 if (empty trim 后 skip) → 两个都空时返回"";prependCodexPromptPreamble第一个 if (empty preamble) → return prompt unchanged (no-op), 第二个 if (empty prompt) → return preamble 跟 prefix。 TestTestCodexPromptPreamble_EmptyIsNoop锁 no-op 行为。 - Backward-compatible 设计: 现有用户没设 system_prompt / append_system_prompt →
buildCodexPromptPreamble("", "")返回""→prependCodexPromptPreamble(prompt, "")返回 prompt unchanged → 现有所有cmd:行为 unchanged, 0 regression 风险。 - 跨 backend 一致:
codexSession(exec backend, session.go:135) 走isResume := cs.CurrentSessionID() != ""决定是否 inject,appServerSession(app_server backend, appserver_session.go:206) 走preambleSent: resumeID != "" && resumeID != core.ContinueSession决定是否 inject。 2 个 backend 的判断 logic 等价 (fresh 或 continue = inject, specific resume = skip), 只是检查点不同 (Send time vs constructor time)。 - threading safe:
appServerSession.Send走s.stateMu.Lock()保护preambleSent字段读写, 跟现有pendingMsgs/currentTurn同 lock, 0 new race。codexSession.Send走cs.CurrentSessionID() != ""不需要新 lock (threadID 是atomic.Value, 已有 atomic semantics)。 - 4 个新 test 对称精准:
TestNew_ParsesProjectPromptsFromOpts(config 解析层) +TestCodexPromptPreamble_PrependsProjectPrompts(helper 层, 锁 append 顺序) +TestCodexPromptPreamble_EmptyIsNoop(helper 层, 锁 no-op) +TestSend_PrependsProjectPromptOnFreshSession(integration 层, 锁 Send-time prepend)。 4 个 case 形成 2x2 matrix (helper / integration × normal / empty), 无冗余。 newAppServerSession新增 2 个 string 参数在最后 (跟现有 11 参数顺序扩展,codexHome已是 string 类型), 调用点唯一 (StartSession 1 处), 0 caller ambiguity。config.example.toml文档化中英双语, 清楚说明 "Codex has no native system-prompt flag, so cc-connect injects this as a preamble prepended to your first message of each new session (resumed sessions are not re-injected)" — 用户能直接 copy-paste 配置。errcheck修复: 1aeea14 commit 把cs.Close()的 return value 加_ =处理, 跟 #1262 #1264 #1286 #1299 #1349 同 cleanup pattern, lint 干净。
🚨/🔴 必须处理: 未发现 (代码层面 0 P0/P1)
5 项 PM 必验证 (2026-06-15 二次 review):
-
system_prompt 和 append_system_prompt 优先级语义 (后者是否真 append 而非 overwrite): ✅
buildCodexPromptPreamble(session.go:67-75) 显式 append 行为:sectionsslice 按 system_prompt → append_system_prompt 顺序 append,strings.Join(sections, "\n\n")拼接。 测试TestCodexPromptPreamble_PrependsProjectPrompts锁 4 个 substring 顺序 ("Before answering" → "Project system prompt" → "Additional project instructions" → "User message"), 任何 reorder 都会 fail。- 命名澄清: "append_system_prompt" 在 claudecode 端是 "追加到 Claude 内置 system prompt 之後" (claudecode 走
--append-system-promptflag, Claude 内部会保留 system prompt 上下文)。 在 codex 端是 "追加到 preamble 之後" (codex 无 system prompt 概念, 只 prepend preamble 到 user message)。 命名从 claudecode 沿用, 语义在 codex 端需重新理解, README/config.example.toml 注释已显式说明 "Additional project instructions" header label 跟 "Project system prompt" header label 区分。 0 误用风险。 - 唯一 nit (P3):
append_system_prompt命名跟实际行为 "append to preamble" 略有 gap, 但跟 claudecode 命名一致 (cross-agent UX 优先), 不需改。
-
config 加载路径是否跟其他 agent 一致 (避免 cc-connect 重启后丢失): ✅
codex.go:58-60读 opts:systemPrompt, _ := opts["system_prompt"].(string)+appendPrompt, _ := opts["append_system_prompt"].(string), pattern 跟mode(line 52),backend(line 53),appServerURL(line 54),codexHome(line 55) 完全一致。codex.go:106-107存到 Agent struct:systemPrompt: strings.TrimSpace(systemPrompt)+appendPrompt: strings.TrimSpace(appendPrompt), 跟codexHome: strings.TrimSpace(codexHome)(line 105) 一致。 TrimSpace 处理空字符串 + 前后空白, 跟现有 pattern 一致。codex.go:371-372在StartSession把 2 个 field 复制到 local var, 跟codexHome(line 369),cliBin(line 373),cliExtraArgs(line 374) 同 pattern, 透传给newCodexSession/newAppServerSession。- cc-connect 重启会从 TOML 重新 parse config → opts map → Agent struct 字段, 0 持久化 concern。 跟 claudecode 端
appendSystemPrompt(claudecode.go:139 + 235) 同 lifecycle。
-
空值 / 默认值 行为: ✅
buildCodexPromptPreamble(session.go:67-75):- systemPrompt = TrimSpace("") → "" → skip section
- appendPrompt = TrimSpace("") → "" → skip section
- Both empty → return ""
prependCodexPromptPreamble(session.go:77-84):- preamble = TrimSpace("") → "" → return prompt unchanged (line 78-80) ✅ no-op
- prompt = TrimSpace("") → "" → return preamble 跟 prefix (line 81-83)
- Both non-empty → return full structure (line 84) ✅
- Test
TestCodexPromptPreamble_EmptyIsNoop锁 empty preamble no-op:prependCodexPromptPreamble("Hello", "")必须返回"Hello", 任何额外 prefix 都会 fail。 - Test
TestNew_ParsesProjectPromptsFromOpts验证 opts 解析到 struct (即使空 opts 也通过, 因为 TrimSpace 处理)。
-
CHANGELOG.md 是否需补 #1346 entry:
⚠️ P2 follow-up (不阻塞, 跟近期 7+ PRs 同 pattern)- 缺 #1346 entry, 跟近期 7+ PRs 同 pattern (#1258 #1272 #1262 #1265 #1198 #1340 #1342 都缺), 建议 release-codex 一次性收齐。
- 建议格式 (在 Unreleased 段
### New Features下加):- **Codex custom system prompt**: support `system_prompt` and `append_system_prompt` agent options for Codex, mirroring the existing claudecode support (#1175). Codex CLI has no native system-prompt flag, so cc-connect synthesizes a preamble prepended to the first message of each new session (resumed sessions are not re-injected) (#1346). - 不阻塞本 PR, release-codex 收齐即可。
-
CI 是否全绿: ✅
- CI run 27500649006 5/5 PASS (lint 2m18s / unit-test 3m57s / regression-test 22s / smoke-test 31s / performance-test 47s)。
- 本地
go test -count=1 -run "TestNew_ParsesProjectPromptsFromOpts|TestCodexPromptPreamble_|TestSend_PrependsProjectPromptOnFreshSession" -v ./agent/codex/4/4 PASS (0.027s)。 - 本地
go test -count=1 ./agent/codex/全 suite 0.847s PASS (0 regression)。 go vet ./agent/codex/0 issue。gofmt -dPR-touched 5 文件 0 diff (codex_cache_test.go 有 1 trailing blank line, NOT in PR diff, 跟 #1353 同 pattern pre-existing NOT introduced)。
- Auto-merge with main = CONFLICTING (跟 v1.3.3 release 引入): PR base = c53f545, current main = dc1c63b (~16 commits, 含 v1.3.3 release)。 实际跑
git merge --no-commit origin/main验证: agent/codex/codex.go / session.go / session_test.go (除 session_test.go 外) / config.example.toml auto-merge 干净 0 conflict; agent/codex/session_test.go 1 conflict (跟 main 的新增TestBuildExecArgs_ModeMapping跟 PR 的新 test 在同一文件互相覆盖; 跟 PR #1353 同 v1.3.3 release section rename + 新增 test 引入)。- 影响: GitHub 不会让 merge 按钮可点 (mergeable=CONFLICTING), 但 GitHub review state (APPROVE) 跟 mergeable 独立, owner 仍然需要等 @HaiyiMei rebase。
- 建议: @HaiyiMei rebase
feat/codex-system-prompt到 main (HEAD = dc1c63b), 解决 session_test.go conflict (保留 main 的 TestBuildExecArgs_ModeMapping + PR 新增的 4 个 test, PR 已把现有 test 签名更新到 12-arg shape), push 后通知 QA 重新 sync + 验证 mergeable=true + CI 5/5 green → ready-to-merge。
🟠 建议改进 (不阻塞, P2):
- CHANGELOG.md 缺 #1346 entry (P2) — 详见上面 PM 验证点 4。
- 跟 claudecode 端
append_system_prompt命名/语义对齐 (P2, 已 done) — PR body 已声明 "mirroring the existing claudecode support (#1175)"。 一致性 verified: claudecode 走--system-prompt+--append-system-promptflag, codex 走 preamble prepend 因 CLI 限制。 Naming 沿用 cross-agent UX 优先, 不需改。 - Preamble 内容 vs
prependCodexPromptPreamble包装 (P2 nit) — 当前 preamble 内容用 "Project system prompt:\n" + content + "\n\n" + "Additional project instructions:\n" + content 的硬编码 section label, 跟 helper function 名字 "preamble" 一致, 但跟append_system_prompt字段名略有 gap。 不需改, 跟 claudecode pattern 一致 (claudecode 也用 hardcoded "## Formatting" label)。
🔵 可选优化 (Nit, P3):
- gofmt 噪声 (P3, 跟 #1353 同 pattern NOT introduced):
gofmt -d agent/codex/codex_cache_test.go报 1 trailing blank line (跟 PR diff 无关, 跟 PR base c53f545 之前的代码). 跟 #1262 #1264 #1286 #1299 #1349 #1353 同 cleanup pattern, 建议 @HaiyiMei 顺手清掉, 不阻塞。 config.example.toml注释中"Appended after system_prompt"略不精确 (P3): 实际append_system_prompt是 "在 preamble 内部追加在 system_prompt section 之後", 跟用户的 "append to system_prompt" 直觉略不同 (codex 端没有 system_prompt 概念, 用户的 "append_system_prompt" 实际是 "additional instructions")。 注释 "Appended after system_prompt in the same injected preamble" 措辞可以更准确: 改为 "Appended after system_prompt in the preamble. Independent instructions that follow your system prompt." 之类。 不阻塞, 注释本身已清楚。newCodexSession12 个参数已接近极限 (P3): 跟 #1198 / #1353 / #1349 同 pattern, 后续如果再加新 session-level config 字段 (e.g. tools, disTools, env), 建议重构为codexSessionConfigstruct。 跟现状 (no spec), 不阻塞本 PR。- Cross-agent preamble 复用机会 (P3): claude / cursor / opencode 等其他 agent 的 custom system prompt 走不同机制 (claude 走 flag, cursor/opencode 走文件), 没有完全可复用的 preamble injection。 建议 (P3, follow-up): 在
core/抽core.BuildProjectPromptPreamble(systemPrompt, appendPrompt string) stringhelper, 让 codex / 未来其他 agent 共享, 减少 drift。 跟 #1262 同 abstraction suggestion pattern, 不阻塞本 PR。
❓ 需要确认:
- app_server backend 在
core.ContinueSession时的 preamble 注入行为 (Q1, 不阻塞):appserver_session.go:206显式preambleSent: resumeID != "" && resumeID != core.ContinueSession, 即 ContinueSession (="__continue__") 跟 fresh session 一样, 第一次 Send 会 inject preamble。 这个行为跟codexSession(exec backend, session.go:135isResume := cs.CurrentSessionID() != "") 语义等价 (ContinueSession 在 newCodexSession 后 threadID 仍空, 所以 isResume=false), 跨 backend 一致 ✅。 - Prepended preamble 在 user message 中是否会污染 user content (Q1, 不阻塞): 现有 user prompt 用
cmd://echo之类, preamble 跟 user message 之间用"---\n\n"分隔 + "User message:" label, user / agent 应该能清晰区分。 风险: 极端 case (user message 含 "Before answering, follow these project-level instructions" 文本) 会被 model 误认为是 preamble, 但 user message 通常是中文 / 短指令, 极小概率冲突。 不阻塞本 PR, 跟 claudecode 端--append-system-prompt行为类比, model 端能 handle。
Testing / Risk:
- 已看到的验证 (QA 二次 review 2026-06-15 补做):
- CI 27500649006 5/5 PASS (lint 2m18s / unit-test 3m57s / regression-test 22s / smoke-test 31s / performance-test 47s)
- 本地
go test -count=1 -run "TestNew_ParsesProjectPromptsFromOpts|TestCodexPromptPreamble_|TestSend_PrependsProjectPromptOnFreshSession" -v ./agent/codex/4/4 PASS (0.027s) - 本地
go test -count=1 ./agent/codex/全 suite 0.847s PASS (0 regression) go vet ./agent/codex/0 issuegofmt -dPR-touched 5 文件 0 diff (codex_cache_test.go 1 trailing blank line NOT in PR diff)git merge --no-commit origin/main1 conflict in agent/codex/session_test.go (跟 v1.3.3 release 引入, 跟 PR #1353 同 pattern)
- 未覆盖风险: 真实 Codex CLI 0.137+ 端到端 (现有 tests 都 mock codex binary 用 fake script, 不会触发真实 codex exec / app_server 路径)。 建议合并后 owner / @HaiyiMei 跑 real smoke test: 设
[agents.codex.options] system_prompt = "You are X"+append_system_prompt = "Always do Y", 启动 cc-connect, 发 message → 验证 Codex 第一条 response 体现 preamble (X 角色 + Y 习惯); 设 2 个字段为空 → 验证 Codex 行为完全 unchanged (regression guard); 跨 session resume → 验证 preamble 不重复 inject (只 inject 第一次)。
Next step:
- owner merge (本 PR 0 P0/P1, 0 P1, 0 P2 阻塞项, 风险低, backward-compat 有 regression test 锁住)。
- 但需要先 rebase: 实际跑
git merge origin/main验证 1 conflict in agent/codex/session_test.go (跟 v1.3.3 release 引入)。 @HaiyiMei rebase 后 mergeable=true, owner 可 merge。 - 顺手 follow-up: 让 release-codex 补 #1346 CHANGELOG entry (跟 #1258 #1272 #1262 #1265 #1198 #1340 #1342 等 7+ PR 一起收齐)。
- 有时间再处理: 跟 PR #1299 类似的 cross-platform UX unification (system_prompt 跨 agent 统一 helper); 真实 codex CLI e2e 验证 (codex 0.137+ behavior 跟 mock 是否完全一致)。
Codex has no native system-prompt CLI flag, so these project options are synthesized into a preamble and prepended to the first message of each new session. Resumed sessions are not re-injected (preambleSent is preset for resume IDs). Covers both the exec and app_server backends. Adds config.example.toml documentation for the two new options. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI lints new lines with golangci-lint --new-from-rev; the freshly added TestSend_PrependsProjectPromptOnFreshSession used an unchecked defer cs.Close(). Wrap it in a deferred closure that explicitly ignores the error, matching the errcheck-clean pattern. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1aeea14 to
41cf921
Compare
chenhg5
left a comment
There was a problem hiding this comment.
结论: Approve
总体判断: PR 二次 review 通过, 0 P0/P1, 1 P2 (CHANGELOG entry missing, 已在 v1.3.5 backlog), 0 P3, 0 Q1, ready for owner merge。 上一 cycle 2026-06-15 (t-20260615-2eb0cz PM 指派) 我 review 通过 1aeea14 (实质 APPROVE)。 期间作者 rebase 到 origin/main (cf2d4f1) + 推 41cf921 (errcheck fix 替换 1aeea14, 内容 1:1 相同), 属 stale_needs_rereview 场景。 本 cycle 重新 review 最新 head 41cf921 的全 diff (+238/-69, 7 files)。
Review 范围:
- 看了 PR #1345 最新 head 41cf921 全部 2 commit, 重点关注 #1345 主体 (system_prompt / append_system_prompt config) + errcheck fix commit 41cf921。
- 41cf921 跟之前 review 的 1aeea14 实质同内容 (都是 wrap defer cs.Close() in func() { _ = cs.Close() }), 只是新 commit hash (rebase 后)。
✅ 做得好的地方:
- 核心 system_prompt / append_system_prompt 设计 clean: 1)
buildCodexPromptPreamble接受 systemPrompt + appendPrompt, 各自 TrimSpace 后用 sections slice + strings.Join 合成 preamble (空 section 跳过, 不会拼出 "Project system prompt: " 这种 orphan prefix), 2)prependCodexPromptPreamble在 first user message 前注入 preamble, 显式 "Project-level instructions ... not user content" 标注 (防止 prompt injection / instruction override 攻击), 3) 空 prompt 边界处理 (返回 preamble + "follow these instructions" 引导, 不会把 preamble 当 user message 单独发送), 4) 跟 PR #1175 (claudecode 同样需求) 对齐, 实现路径一致。 - codexSession struct 新增
promptPreamble string字段, 初始化时从 systemPrompt + appendPrompt 合成一次性存好, Send() 路径只是 prepend (避免每次 Send 重新 build)。 跟 codexSession.workDir / model / effort / mode 同样作为不可变配置 (Send 不修改, 只读), 跟 cmdMu / closeOnce 等可变 runtime state 区分清楚。 prependCodexPromptPreamble的 empty prompt case 特别用心: 单独返回 "Before answering, follow these project-level instructions for this cc-connect session. They are not user content." + preamble, 这是 "无 user input 但仍要 apply project instruction" 的场景 (例如 cron 触发 + 隐式 prompt), 不会让 preamble 走 user channel 误判为 user message。newCodexSession接受 systemPrompt + appendPrompt 作为 new params (而不是塞进 extraEnv / cliExtraArgs 这种 hack), 跟 codex 的 1:1 显式 API 风格一致, caller 路径 (NewSession entry / appserver_session.go) 同步传参。- appserver_session.go 同步 wire (新增 system_prompt / append_system_prompt 从 config 解析 → newCodexSession), 跟 codex.go 一样从 config 读, 没有 hardcode。 跟 PR #1175 (claudecode) config.example.toml 加 [codex].system_prompt 段对齐。
- 41cf921 errcheck fix 跟 v2.11.4 golangci-lint
--new-from-rev行为一致: PR 引入新 linedefer cs.Close()→ 触发 errcheck → wrap in func() { _ = cs.Close() }()。 这是 standard errcheck-clean pattern, 跟仓库其他 test 文件 (e.g. agent/claudecode/provider_env_test.go / agent/qoder/qoder_test.go 里的 defer Close wrap) 一致。 (顺道: QA 已知 cc-connect .golangci.yml _test.go exclusion 在 v2.11.4 + --new-from-rev 下 broken, 走 wrap 是 workaround 而非 ideal; 长期 fix 应改 .golangci.yml 排除 test file 跟 errcheck 的冲突, 但这是 owner / linter maintainer 的事, 不属本 PR scope。) - config.example.toml 加 [codex].system_prompt / append_system_prompt 段, 跟 #1175 (claudecode) 段格式一致, user 复制即用, doc 简明。
- TestSend_PrependsProjectPromptOnFreshSession 验证整链路: newCodexSession with systemPrompt + appendPrompt → Send() → 检查 spawned codex exec CLI args 是否包含 preamble 注入。 端到端 wire 验证, 防止 refactor 误改 prepend 位置 (例如 prepend 到 error message 而不是 first user message)。
🚨/🔴 必须处理:
- 未发现必须阻塞合并的问题。
🟠 建议改进:
- P2 Should fix (CHANGELOG entry): PR 加了 [codex].system_prompt / append_system_prompt 2 个新 config, 是 user-facing feature。 v1.3.5 release notes 必须列。 已在 v1.3.5 release gate backlog (本 cycle #1349 / 上 cycle #1286 / #1298 / #1319 / #1317 / #1320 等都累积 CHANGELOG entry 待 owner 措辞统一), 等 owner / release-codex 协调。
- 跟 PR #1349 (本 cycle 同时 review 的 isolate scheduled sessions) 一样, 走 v1.3.5 release gate 一起 release。
🔵 可选优化:
- (P3 nit)
prependCodexPromptPreamble把 preamble 跟 user message 用 "\n\n---\n\n" 分隔, "---" 作为 marker 在 markdown 里就是水平线, agent 可能误解析为水平线并加额外行为 (例如跳过下半部分)。 建议: 改用非 markdown 字符 (e.g. "###END OF PROJECT INSTRUCTIONS###" 之类的纯文本 marker), 但当前 "---" 在很多 system prompt 注入场景都是惯用, 跟 PR #1175 claudecode 同样实现保持一致。 不写 (本 PR 跟 #1175 一致就是好的, 跟 #1175 不一致才是问题)。 - (P3 nit) promptPreamble 在 newCodexSession 初始化时 build 一次, 之后不变。 如果 runtime 修改 systemPrompt (没有 API 路径, 但 future-proof) 不会 propagate。 当前 API 不支持, 未来加运行时 config reload 时再考虑。 不写。
❓ 需要确认:
- @HaiyiMei: PR description 顶部 "Why this PR" 段是否提了 #1346 (跟 claudecode #1175 对齐) issue 关联? 我从 PR head 没看到 issue link 列表, 但关联 issue 已经在 PR body 提了 (registry notes 显示 issues=[1175, 1346], tasks=-)。 没问题, 之前已经 link, 不用补。
Testing / Risk:
- 已看到的验证: TestSend_PrependsProjectPromptOnFreshSession PASS (0.02s), full agent/codex 0.841s PASS 0 regression, go vet 0 issue, gofmt PR-touched files clean, 41cf921 errcheck fix 验证 errcheck 不再 flag (wrap pattern 跟仓库其他 test 一致)。
- 未覆盖风险: 0 代码 regression 风险。 跟 #1175 claudecode 同样的 feature, cross-runtime 一致性靠 #1175 + #1345 一起 review 验证, owner merge 前 release-codex 可以做 cross-platform smoke。
Next step:
What
Adds
system_promptandappend_system_promptagent options to the Codex agent, mirroring the existing claudecode support (#1175).Why
Codex projects could not set a custom system prompt the way Claude Code projects can. Codex's CLI has no native
--system-promptflag, so these options are synthesized into a project preamble and prepended to the first message of each new session.How
buildCodexPromptPreamble/prependCodexPromptPreamblebuild the preamble fromsystem_prompt+append_system_prompt.preambleSentis preset when resuming a non-ContinueSessionthread).exec(session.go) andapp_server(appserver_session.go).config.example.tomldocumentation (bilingual) for the two new options, noting the preamble-injection semantics.Tests
New unit tests (all passing):
TestNew_ParsesProjectPromptsFromOptsTestCodexPromptPreamble_PrependsProjectPromptsTestCodexPromptPreamble_EmptyIsNoopTestSend_PrependsProjectPromptOnFreshSessiongo build,gofmt,go vet, andgo test ./agent/codex/all pass.🤖 Generated with Claude Code
Closes #1346