Summary
codex emits structured thread-goal events, but codex-acp forwards them only as free-text agent_message_chunks, so ACP clients can't consume the goal's structured state (status/objective/token budget) — they'd have to regex the prose.
Details
codex 0.142 emits:
thread/goal/updated — goal = { objective, status, tokenBudget }, where status is active | paused | budgetLimited | blocked | usageLimited | complete
thread/goal/cleared
In src/CodexEventHandler.ts, these map to text-only updates:
createThreadGoalUpdatedEvent → { sessionUpdate: "agent_message_chunk", content: { type: "text", text: "Goal updated (active): <objective>" } }
createThreadGoalClearedEvent → { sessionUpdate: "agent_message_chunk", text: "Goal cleared." }
The structured status enum and tokenBudget are dropped. Notably, other thread metadata (name, status, archived) is exposed structurally via createCodexSessionInfoUpdate → session_info_update with _meta.codex. Goal state is the odd one out.
Impact
A client can't reliably detect goal start (active) / end (complete) / clear, or surface the token budget, without parsing localized/format-fragile text.
Suggested fix
Route goal updates through the same structured channel already used for thread status/archived/name, e.g.:
session_info_update with _meta.codex.goal = { objective, status, tokenBudget }
(and a cleared signal on thread/goal/cleared). The human-readable agent_message_chunk can stay for display; the ask is to also expose the structured state so clients can react to the goal lifecycle programmatically.
Summary
codex emits structured thread-goal events, but codex-acp forwards them only as free-text
agent_message_chunks, so ACP clients can't consume the goal's structured state (status/objective/token budget) — they'd have to regex the prose.Details
codex 0.142 emits:
thread/goal/updated—goal = { objective, status, tokenBudget }, wherestatusisactive | paused | budgetLimited | blocked | usageLimited | completethread/goal/clearedIn
src/CodexEventHandler.ts, these map to text-only updates:createThreadGoalUpdatedEvent→{ sessionUpdate: "agent_message_chunk", content: { type: "text", text: "Goal updated (active): <objective>" } }createThreadGoalClearedEvent→{ sessionUpdate: "agent_message_chunk", text: "Goal cleared." }The structured
statusenum andtokenBudgetare dropped. Notably, other thread metadata (name, status, archived) is exposed structurally viacreateCodexSessionInfoUpdate→session_info_updatewith_meta.codex. Goal state is the odd one out.Impact
A client can't reliably detect goal start (
active) / end (complete) / clear, or surface the token budget, without parsing localized/format-fragile text.Suggested fix
Route goal updates through the same structured channel already used for thread status/archived/name, e.g.:
(and a cleared signal on
thread/goal/cleared). The human-readableagent_message_chunkcan stay for display; the ask is to also expose the structured state so clients can react to the goal lifecycle programmatically.