13-codex-json-node-graph
flowchart TD
classDef decision fill:#fff7e6,stroke:#c47f00,stroke-width:1px,color:#2f2100;
classDef terminal fill:#f4f4f5,stroke:#a1a1aa,color:#18181b;
subgraph UI["User / UI"]
direction TB
U0["User/UI | 用户输入<br/>{"issue":"ACME-42", "text":"验证码过期时移动端没有 toast,接口返回 TOKEN_EXPIRED,帮我修一下。"}"]
D0{"输入类型?"}
U1["User/UI | 评论请求<br/>{"issue_id":"iss_42", "content":"验证码过期...", "parent_id":null}"]
U2["User/UI | 回复请求<br/>{"issue_id":"iss_42", "content":"继续检查移动端...", "parent_id":"cmt_parent"}"]
end
subgraph SERVER["Multica Server"]
direction TB
S1["Server | comment 落库<br/>{"id":"cmt_501", "issue_id":"iss_42", "author_type":"member", "parent_id":null, "content":"验证码过期..."}"]
D1{"有显式 @Agent?"}
D2{"parent_id 为空?"}
R1["Server | @ 路由结果<br/>{"target_agent":"@Agent", "source":"mention"}"]
R2["Server | 评论默认路由<br/>{"target_agent":"agt_codesmith", "source":"issue_assignee"}"]
R3["Server | 回复线程路由<br/>{"target_agent":"agt_codesmith", "source":"thread_or_assignee_rule"}"]
D3{"触发 Agent?"}
D4{"已有 queued/dispatched task?"}
S2["Server | 不新建 task<br/>{"comment_saved":true, "new_task":false, "reason":"coalesce_into_pending_task"}"]
S3["Server | queued task<br/>{"id":"task_9001", "agent_id":"agt_codesmith", "runtime_id":"rt_codex_01", "trigger_comment_id":"cmt_501", "status":"queued"}"]
S4["Server | claim response<br/>{"task_id":"task_9001", "trigger_comment":"验证码过期...", "prior_session_id":"codex-thread-abc", "auth_token":"mat_task_token"}"]
S5["Server | task_message<br/>{"task_id":"task_9001", "type":"tool_use", "tool":"exec_command", "input":"multica issue get ACME-42 --output json"}"]
S6["Server | Agent 评论<br/>{"id":"cmt_777", "author_type":"agent", "parent_id":"cmt_501", "content":"已定位并修复 TOKEN_EXPIRED toast。"}"]
D8{"Agent 已主动评论?"}
S7["Server | 兜底评论<br/>{"author_type":"agent", "parent_id":"cmt_501", "content":"<final output>"}"]
S8["Server | task completed<br/>{"id":"task_9001", "status":"completed", "session_id":"codex-thread-abc", "work_dir":".../workdir"}"]
S9["Server | task failed/cancelled<br/>{"id":"task_9001", "status":"failed|cancelled", "reason":"<classified_reason>"}"]
end
subgraph DAEMON["Daemon / codexBackend"]
direction TB
M0["Daemon | execenv<br/>{"workdir":".../task_9001/workdir", "CODEX_HOME":".../task_9001/codex-home", "MULTICA_TOKEN":"mat_task_token"}"]
M1["Daemon | wrapped prompt<br/>{"issue_id":"ACME-42", "trigger_comment_id":"cmt_501", "prompt":"[NEW COMMENT] 验证码过期...; run multica issue get; reply --parent cmt_501"}"]
D5{"有 prior_session_id?"}
M2["codexBackend | thread/resume<br/>{"method":"thread/resume", "threadId":"codex-thread-abc", "cwd":".../workdir"}"]
D6{"resume 可恢复失败?"}
M3["codexBackend | thread/start<br/>{"method":"thread/start", "cwd":".../workdir", "persistExtendedHistory":true}"]
M4["codexBackend | turn/start<br/>{"method":"turn/start", "threadId":"codex-thread-abc", "input.text":"<wrapped prompt>"}"]
M5["Daemon | agent.Result<br/>{"status":"completed", "output":"已定位并修复...", "session_id":"codex-thread-abc", "usage":"12000/1800"}"]
end
subgraph CODEX["Codex app-server / multica CLI"]
direction TB
C0["Codex | app-server<br/>{"process":"codex app-server --listen stdio://", "transport":"JSON-RPC over stdio"}"]
C1["Codex | tool event<br/>{"method":"item/started", "type":"commandExecution", "command":"multica issue get ACME-42 --output json"}"]
C2["Codex | reply command<br/>{"command":"multica issue comment add ACME-42 --parent cmt_501 --content-file ./reply.md"}"]
C3["multica CLI | API 写回<br/>{"api":"POST issue comment", "parent_id":"cmt_501", "content_file":"reply.md"}"]
C4["Codex | turn/completed<br/>{"status":"completed|failed|cancelled", "threadId":"codex-thread-abc", "usage":{"in":12000, "out":1800}}"]
D7{"turn status completed?"}
end
U0 -- "点击发送" --> D0
D0 -- "评论:parent_id=null" --> U1
D0 -- "回复:parent_id=comment_id" --> U2
U1 -- "POST /comments" --> S1
U2 -- "POST /comments" --> S1
S1 -- "解析 mention" --> D1
D1 -- "是:强路由" --> R1
D1 -- "否" --> D2
D2 -- "是:评论场景" --> R2
D2 -- "否:回复场景" --> R3
R1 -- "得到 target_agent" --> D3
R2 -- "得到 target_agent" --> D3
R3 -- "得到 target_agent 或 null" --> D3
D3 -- "否:只保留 comment" --> S2
D3 -- "是" --> D4
D4 -- "是:合并唤醒信号" --> S2
D4 -- "否:enqueue" --> S3
S3 -- "daemon claim runtime" --> S4
S4 -- "claim response" --> M0
M0 -- "InjectRuntimeConfig + env" --> M1
M1 -- "spawn process" --> C0
C0 -- "initialize / initialized" --> D5
D5 -- "是" --> M2
D5 -- "否" --> M3
M2 -- "thread/resume" --> D6
D6 -- "否:resume 成功" --> M4
D6 -- "是:fallback fresh thread" --> M3
M3 -- "thread/start" --> M4
M4 -- "JSON-RPC turn/start" --> C1
C1 -- "emit item event" --> S5
C1 -- "Codex 决定回复" --> C2
C2 -- "执行 multica CLI" --> C3
C3 -- "POST comment API" --> S6
C1 -- "继续执行/修改/测试" --> C4
C4 --> D7
D7 -- "否" --> S9
D7 -- "是" --> M5
M5 -- "report usage + complete task" --> D8
D8 -- "是:不补评论" --> S8
D8 -- "否:用 final output 补评论" --> S7
S7 -- "create fallback comment" --> S8
class D0,D1,D2,D3,D4,D5,D6,D7,D8 decision;
class S2,S8,S9 terminal;
This post is licensed under CC BY 4.0 by the author.