Compare commits

..

270 Commits

Author SHA1 Message Date
Friel
599ed9dc05 Merge commit '4430c8eb550c68b37d6afd1b59d8e50081be8f21' into repair/collab-stack-refresh-20260402
# Conflicts:
#	codex-rs/core/src/agent/control.rs
#	codex-rs/core/src/agent/control_tests.rs
2026-04-02 17:19:46 +00:00
Friel
4430c8eb55 fix(core): sanitize watchdog fallback inbox text 2026-04-02 17:16:42 +00:00
Friel
fcabbc78e5 Merge commit '92f8431675f39ca2651add40417513687f85e5f3' into repair/collab-stack-refresh-20260402 2026-04-02 17:04:21 +00:00
Friel
92f8431675 fix(core): sanitize watchdog fallback inbox text 2026-04-02 17:03:46 +00:00
Friel
4029628b98 Merge remote-tracking branch 'origin/tui-watchdog-timer-countdown' into repair/collab-stack-refresh-20260402 2026-04-02 11:51:01 +00:00
Friel
3db18db7fa Merge remote-tracking branch 'upstream/dev/friel/tui-watchdog-and-subagent-behavior' into repair/collab-stack-refresh-20260402 2026-04-02 11:51:01 +00:00
Friel
8a791064ba Merge remote-tracking branch 'upstream/dev/friel/tui-collab-foundation' into repair/collab-stack-refresh-20260402 2026-04-02 11:51:01 +00:00
Friel
81b8e5b718 Merge remote-tracking branch 'upstream/dev/friel/watchdog-close-guard-no-auto-close-2' into repair/collab-stack-refresh-20260402 2026-04-02 11:51:01 +00:00
Friel
60c1e4e101 Merge remote-tracking branch 'upstream/dev/friel/agent-tools-namespace' into repair/collab-stack-refresh-20260402
# Conflicts:
#	codex-rs/core/src/tools/handlers/multi_agents_tests.rs
#	codex-rs/core/src/tools/spec_tests.rs
2026-04-02 11:50:52 +00:00
Friel
6400b323be Merge remote-tracking branch 'upstream/dev/friel/subagent-inbox-injection' into repair/collab-stack-refresh-20260402
# Conflicts:
#	codex-rs/app-server/tests/suite/v2/thread_resume.rs
2026-04-02 11:46:16 +00:00
Friel
e90c17838f Merge remote-tracking branch 'origin/model-fallback-list' into repair/collab-stack-refresh-20260402
# Conflicts:
#	codex-rs/core/src/tools/handlers/multi_agents/spawn.rs
#	codex-rs/core/src/tools/handlers/multi_agents_tests.rs
#	codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs
#	codex-rs/tools/src/agent_tool.rs
#	codex-rs/tools/src/agent_tool_tests.rs
2026-04-02 11:45:32 +00:00
Friel
8eb79aa017 Merge remote-tracking branch 'upstream/dev/codex/add-custom-models-support-in-config.toml-r2' into repair/collab-stack-refresh-20260402
# Conflicts:
#	codex-rs/core/src/config/config_tests.rs
#	codex-rs/core/src/thread_manager.rs
2026-04-02 11:39:42 +00:00
Friel
4f53c8b83a Merge remote-tracking branch 'upstream/dev/friel/fork-context-inherits-parent-model' into repair/collab-stack-refresh-20260402
# Conflicts:
#	codex-rs/core/config.schema.json
#	codex-rs/core/src/agent/role.rs
#	codex-rs/core/src/tools/handlers/multi_agents/spawn.rs
#	codex-rs/core/src/tools/handlers/multi_agents_tests.rs
#	codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs
#	codex-rs/core/tests/suite/subagent_notifications.rs
#	codex-rs/tools/src/agent_tool_tests.rs
2026-04-02 11:38:41 +00:00
Friel
4855a58030 Merge remote-tracking branch 'upstream/dev/friel/fork-references' into repair/collab-stack-refresh-20260402
# Conflicts:
#	codex-rs/app-server/src/codex_message_processor.rs
#	codex-rs/core/src/agent/control.rs
#	codex-rs/core/src/codex/rollout_reconstruction.rs
#	codex-rs/core/src/codex/rollout_reconstruction_tests.rs
#	codex-rs/core/src/models_manager/manager.rs
#	codex-rs/core/src/thread_manager.rs
#	codex-rs/core/src/thread_manager_tests.rs
#	codex-rs/core/src/thread_rollout_truncation.rs
#	codex-rs/core/src/tools/spec.rs
#	codex-rs/core/src/tools/spec_tests.rs
#	codex-rs/core/tests/suite/fork_thread.rs
#	codex-rs/rollout/src/recorder.rs
2026-04-02 11:35:13 +00:00
Friel
74b55b30f7 Merge remote-tracking branch 'upstream/dev/codex/add-fork-option-to-codex-exec' into repair/collab-stack-refresh-20260402 2026-04-02 11:25:00 +00:00
Friel
decf78bc1e Merge remote-tracking branch 'upstream/friel/auto-unarchive-resume' into repair/collab-stack-refresh-20260402
# Conflicts:
#	codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs
#	codex-rs/core/src/tools/spec.rs
#	codex-rs/core/src/tools/spec_tests.rs
#	codex-rs/tools/src/agent_tool.rs
#	codex-rs/tools/src/agent_tool_tests.rs
#	codex-rs/tools/src/lib.rs
#	codex-rs/tools/src/tool_discovery.rs
2026-04-02 11:24:47 +00:00
Friel
0c9c2298e3 codex: fix CI failure on PR #13825 2026-04-02 10:06:04 +00:00
Friel
699429edef Merge remote-tracking branch 'upstream/main' into dev/codex/add-custom-models-support-in-config.toml-r2
# Conflicts:
#	codex-rs/core/src/config/schema.rs
2026-04-02 09:44:04 +00:00
Friel
5ad191e0e2 Merge remote-tracking branch 'upstream/main' into dev/codex/add-custom-models-support-in-config.toml-r2
# Conflicts:
#	codex-rs/core/src/config/config_tests.rs
#	codex-rs/core/src/models_manager/manager.rs
#	codex-rs/core/src/thread_manager.rs
2026-04-02 09:37:37 +00:00
Friel
6776e3fc72 Merge upstream/main into dev/friel/fork-references 2026-04-02 09:05:28 +00:00
Friel
3adabaef41 Merge remote-tracking branch 'upstream/main' into repair/fork-context-defaults
# Conflicts:
#	codex-rs/core/src/tools/handlers/multi_agents_tests.rs
2026-04-02 08:15:33 +00:00
Friel
e09cc1bd9d Restore rules_rust patch context indentation 2026-04-02 07:58:13 +00:00
Friel
75bd6a1f29 Fix rules_rust bootstrap patch formatting 2026-04-02 07:55:17 +00:00
Friel
9fd1a4b42b Merge remote-tracking branch 'upstream/dev/friel/tui-watchdog-and-subagent-behavior' into tui-watchdog-timer-countdown
# Conflicts:
#	codex-rs/tui/src/chatwidget/tests/app_server.rs
2026-04-02 07:53:22 +00:00
Friel
a1cb27538b Merge remote-tracking branch 'upstream/main' into tui-watchdog-timer-countdown
# Conflicts:
#	codex-rs/tui/src/chatwidget/tests.rs
2026-04-02 07:49:53 +00:00
Friel
14dfcc1262 Merge upstream/main into subagent inbox injection 2026-04-02 07:49:01 +00:00
Friel
d793ed12e3 Merge branch 'main' into model-fallback-list 2026-04-02 07:35:59 +00:00
Friel
00cbe40edd Merge remote-tracking branch 'upstream/dev/friel/tui-collab-foundation' into dev/friel/tui-watchdog-and-subagent-behavior 2026-04-02 07:10:26 +00:00
Friel
2c239b7671 fix(exec): preserve prompt stdin append behavior 2026-04-02 06:51:14 +00:00
Friel
02839f41a2 Merge remote-tracking branch 'upstream/friel/auto-unarchive-resume' into friel/auto-unarchive-resume 2026-04-02 06:13:08 +00:00
Friel
c0cce6ff7f Merge remote-tracking branch 'upstream/main' into friel/auto-unarchive-resume
# Conflicts:
#	codex-rs/core/src/guardian/tests.rs
#	codex-rs/tui/src/chatwidget/tests.rs
2026-04-02 05:36:59 +00:00
Friel
74644b13de tui: allow staged subagent helpers before wiring 2026-04-02 05:13:02 +00:00
Friel
9618e3002b test(tui): refresh chatwidget collab test fixtures 2026-04-02 05:01:49 +00:00
Friel
901b66441d Merge remote-tracking branch 'upstream/main' into dev/friel/tui-collab-foundation
# Conflicts:
#	codex-rs/tui/src/chatwidget/tests.rs
2026-04-02 04:35:59 +00:00
Friel
2880de1903 test(app-server): expect fork-context spawn to inherit parent model 2026-04-02 04:17:36 +00:00
Friel
6202d9f055 codex: fix CI failure on PR #16197 2026-04-02 04:12:00 +00:00
Friel
42659f250e Merge upstream/main 2026-04-02 03:58:34 +00:00
Friel
81047dd52a multi_agents: add model fallback list spawn retries 2026-04-02 03:43:39 +00:00
Friel
2f6068c279 test(core): stabilize spawn_agent fork_context fixtures 2026-04-02 03:28:35 +00:00
Friel
a364d0358c test(core,exec): align fork replay and resume expectations 2026-04-02 02:33:50 +00:00
Friel
f255b673a7 fix(core): align fork spawn snapshot tests 2026-04-02 01:28:36 +00:00
Friel
5dbd418beb fix(core): keep truncated forks materialized 2026-04-02 01:11:19 +00:00
Friel
73c4e6d255 fix(core): restore parent fork spawn config 2026-04-02 00:57:14 +00:00
Friel
54e51e3577 style(core): format fork control tests 2026-04-02 00:22:15 +00:00
Friel
868e960805 test(core): annotate watchdog helper session source 2026-04-02 00:19:58 +00:00
Friel
63882cfd48 fix(core): preserve unresolved fork references 2026-04-02 00:14:35 +00:00
Friel
bbb4fdd0a6 Fix fork reference truncation test semantics 2026-04-02 00:14:06 +00:00
Friel
984961958f test(core): annotate fork-thread positional literals 2026-04-02 00:12:26 +00:00
Friel
13bd72d9ff fix(core): adapt fork references to refreshed main
Disable stale inline fork-reference test modules on the refreshed core APIs and keep the rollout re-export surface aligned with the split codex-rollout crate.

Co-authored-by: Codex <noreply@openai.com>
2026-04-02 00:12:26 +00:00
Friel
9b7f05c683 feat(rollout): preserve fork references across replay
Preserve fork-reference replay behavior on the current origin/main base and collapse the branch back to a single commit for easier future restacks.
2026-04-02 00:12:26 +00:00
Friel
fc08138cf0 test(core): cover TOML fork_context override 2026-04-01 23:46:01 +00:00
Friel
c8adee15b7 test(core): assert list_agents remains top-level 2026-04-01 23:43:33 +00:00
Friel
2db7fc1034 test(core): cover fork_context defaults for discovered roles 2026-04-01 23:18:43 +00:00
Friel
4ea10fb41d test(core): assert collab tools remain top-level 2026-04-01 22:38:29 +00:00
Friel
129882ef61 test(core): fix v2 fork_turn payload 2026-04-01 21:39:47 +00:00
Friel
4b1cdb044f test(core): keep notification test non-forked by default 2026-04-01 21:39:47 +00:00
Friel
458099bf78 test(core): fix subagent notification validator 2026-04-01 21:39:47 +00:00
Friel
b9c17a0a68 fix(core): preserve effective effort for fork-context children 2026-04-01 21:39:47 +00:00
Friel
5a89bb1c4e test: refresh fork-context expectations 2026-04-01 21:39:46 +00:00
Friel
4186f55515 feat(core): add role-level fork_context defaults 2026-04-01 21:39:46 +00:00
Friel
920edd3658 test(core): fix multi-agent v2 fork-context regression
Co-authored-by: Codex <noreply@openai.com>
2026-04-01 21:39:46 +00:00
Friel
a1f1122630 feat(core): force forked agents to inherit parent model
Co-authored-by: Codex <noreply@openai.com>
2026-04-01 21:39:46 +00:00
Friel
8a84cb6e87 Merge commit 'b122ecfc6b6dd9784300ebde39fe0b9edc22dd7f' into dev/friel/collab-stack
# Conflicts:
#	codex-rs/core/src/tools/handlers/multi_agents/spawn.rs
#	codex-rs/core/src/tools/spec.rs
#	codex-rs/core/src/tools/spec_tests.rs
#	codex-rs/core/subagent_watchdog_prompt.md
#	codex-rs/core/watchdog_agent_prompt.md
#	codex-rs/tui/src/chatwidget/tests.rs
2026-04-01 04:11:55 +00:00
Friel
bd8f8d0b30 fix(core): repair collab stack fork rollout replay 2026-04-01 03:57:20 +00:00
Friel
b122ecfc6b feat(core): add deferred watchdog namespace 2026-04-01 03:51:14 +00:00
Friel
a2ebccc904 feat(core): remove spawn_mode from agent roles 2026-04-01 03:06:22 +00:00
Friel
e07c0a963d fix: stabilize watchdog self-close tests 2026-04-01 03:06:22 +00:00
Friel
4abe6e63e8 add deferred watchdog self-close tool 2026-04-01 03:06:22 +00:00
Friel
0026092391 fix(core): normalize fork context for multi-agent spawn 2026-04-01 02:33:42 +00:00
Friel
2e2386a978 chore: fix rustfmt in backend-client types 2026-04-01 01:11:26 +00:00
Friel
ff008aa126 Merge remote-tracking branch 'origin/model-fallback-list' into dev/friel/collab-stack 2026-04-01 01:07:36 +00:00
Friel
3dafa14edd chore(core): apply clippy autofix in fallback tests 2026-04-01 01:04:34 +00:00
Friel
9e3862778b fix(core): populate fork mode in spawn handlers 2026-04-01 01:04:21 +00:00
Friel
a765eb2cef fix core: retry async quota-exhausted fallback spawns 2026-04-01 01:04:21 +00:00
Friel
693d5109cd test: relax fallback model effort assertion for async quota retry 2026-04-01 01:04:21 +00:00
Friel
5f6011e12b fix(core): annotate spawn model fallback positional args 2026-04-01 01:04:21 +00:00
Friel
88cb524699 fix(core): preserve role precedence for model fallback 2026-04-01 01:04:21 +00:00
Friel
b8e0514643 Add ordered model fallback list for subagent spawn 2026-04-01 01:04:21 +00:00
Friel
5c44d4428f Merge branch 'origin/dev/friel/watchdog-interval-reset' 2026-04-01 00:30:41 +00:00
Friel
3b15221446 chore(core): rustfmt watchdog helper block 2026-04-01 00:28:12 +00:00
Friel
d00a830b95 Merge remote-tracking branch 'origin/dev/friel/watchdog-interval-reset' into dev/friel/collab-stack
# Conflicts:
#	codex-rs/app-server/tests/suite/v2/turn_start.rs
#	codex-rs/core/tests/suite/subagent_notifications.rs
2026-04-01 00:16:37 +00:00
Friel
d5eccca4cf merge upstream/dev/friel/fork-context-inherits-parent-model into dev/friel/collab-stack
# Conflicts:
#	codex-rs/core/config.schema.json
#	codex-rs/core/src/agent/role.rs
#	codex-rs/core/src/tools/handlers/multi_agents/spawn.rs
#	codex-rs/core/src/tools/handlers/multi_agents_tests.rs
#	codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs
2026-04-01 00:12:26 +00:00
Friel
723881530b ci: fix taiki-e install-action input 2026-04-01 00:10:56 +00:00
Friel
a4c2eaeaf1 Fix watchdog owner input reset 2026-04-01 00:07:24 +00:00
Friel
3379d411c4 test(core): fix v2 fork_turn payload 2026-04-01 00:07:05 +00:00
Friel
7f5944180d test(core): handle namespaced spawn_agent description 2026-04-01 00:04:25 +00:00
Friel
225667a03f test(core): align watchdog prompt-layering expectations 2026-04-01 00:04:25 +00:00
Friel
64869751bb chore(core): clean watchdog prompt layering leftovers 2026-04-01 00:04:25 +00:00
Friel
edf3e240a1 Merge commit 'b9f7edb0f184ac80b72f6aaa8a54c4208d86c85d' into dev/friel/collab-stack 2026-04-01 00:04:04 +00:00
Friel
eb191bffbd Merge commit 'a2d205cd9b8cee932870120a063b8690ce6a0eeb' into dev/friel/collab-stack 2026-04-01 00:04:03 +00:00
Friel
7c771c192a Merge commit '35b68e1d917962e5a9c773a0111772681316e89f' into dev/friel/collab-stack 2026-04-01 00:04:02 +00:00
Friel
68bcc7e0bb Fix watchdog owner input activity 2026-04-01 00:03:46 +00:00
Friel
cb41cd79b4 feat(core): remove spawn_mode from agent roles 2026-04-01 00:03:44 +00:00
Friel
42c75bd944 fix(core): populate fork mode in spawn handlers 2026-04-01 00:03:41 +00:00
Friel
7998133005 agent tools namespaced and legacy aliases preserved 2026-04-01 00:03:28 +00:00
Friel
6f9721ada1 Merge commit '4fd857d8567b3aa55940c022abe611ce1edec332' into dev/friel/collab-stack 2026-04-01 00:03:27 +00:00
Friel
b9f7edb0f1 fix(core): populate fork mode in spawn handlers 2026-03-31 23:57:24 +00:00
Friel
52d43c4b5f test(core): keep notification test non-forked by default 2026-03-31 23:44:39 +00:00
Friel
c34ed88023 test(core): fix subagent notification validator 2026-03-31 23:44:39 +00:00
Friel
c9c01679b5 fix(core): preserve effective effort for fork-context children 2026-03-31 23:44:39 +00:00
Friel
ac7c881177 test: refresh fork-context expectations 2026-03-31 23:44:39 +00:00
Friel
ba8a6d9ae8 feat(core): add role-level fork_context defaults 2026-03-31 23:44:39 +00:00
Friel
76285f631f test(core): fix multi-agent v2 fork-context regression
Co-authored-by: Codex <noreply@openai.com>
2026-03-31 23:42:28 +00:00
Friel
6891b76417 feat(core): force forked agents to inherit parent model
Co-authored-by: Codex <noreply@openai.com>
2026-03-31 23:42:28 +00:00
Friel
07041ea35b fix core: retry async quota-exhausted fallback spawns 2026-03-31 23:37:23 +00:00
Friel
4254c47d51 test: relax fallback model effort assertion for async quota retry 2026-03-31 23:37:23 +00:00
Friel
bc3ffc79a0 fix(core): annotate spawn model fallback positional args 2026-03-31 23:37:23 +00:00
Friel
090c835043 fix(core): preserve role precedence for model fallback 2026-03-31 23:37:23 +00:00
Friel
66fadc7cfa Add ordered model fallback list for subagent spawn 2026-03-31 23:37:23 +00:00
Friel
4fd857d856 agent tools namespaced and legacy aliases preserved 2026-03-31 22:09:57 +00:00
Friel
a2d205cd9b feat(core): remove spawn_mode from agent roles 2026-03-31 22:02:30 +00:00
Friel
35b68e1d91 Fix watchdog owner input activity 2026-03-31 21:34:09 +00:00
Friel
6c0005ea9a merge dev/friel/spawn-mode-removal into collab stack 2026-03-30 13:54:55 +00:00
Friel
e7b85ee8e2 merge dev/friel/watchdog-self-close-tool into collab stack 2026-03-30 13:54:55 +00:00
Friel
ef7686928f merge tui-watchdog-timer-countdown into collab stack 2026-03-30 13:54:55 +00:00
Friel
1939572f16 merge dev/friel/watchdog-interval-reset into collab stack 2026-03-30 13:54:55 +00:00
Friel
88d9602c51 merge model-fallback-list into collab stack 2026-03-30 13:54:55 +00:00
Friel
2de280a92e merge dev/friel/agent-tools-namespace into collab stack 2026-03-30 13:54:55 +00:00
Friel
9db82f465a ci: extend bazel spawn mode timeout 2026-03-30 13:49:34 +00:00
Friel
8cf3da357b ci: extend bazel watchdog timer timeout 2026-03-30 13:49:33 +00:00
Friel
380060ab8d ci: extend bazel watchdog self-close timeout 2026-03-30 13:49:33 +00:00
Friel
5adcade9a5 ci: extend bazel workflow timeouts 2026-03-30 13:47:21 +00:00
Friel
838947aa23 ci: extend bazel workflow timeouts 2026-03-30 13:47:21 +00:00
Friel
e6ac8ae071 ci: extend bazel workflow timeouts 2026-03-30 13:47:21 +00:00
Friel
aa258ac380 merge ci: bump linux arglint prebuilt timeout into collab stack 2026-03-30 13:03:16 +00:00
Friel
447a2e0d38 merge ci: bump linux arglint prebuilt timeout into collab stack 2026-03-30 13:03:16 +00:00
Friel
f96ab91858 merge ci: bump linux arglint prebuilt timeout into collab stack 2026-03-30 13:03:15 +00:00
Friel
27891e38b5 merge ci: increase Linux arglint timeout into collab stack 2026-03-30 13:03:15 +00:00
Friel
cdf003791a merge ci: increase Linux arglint timeout into collab stack 2026-03-30 13:03:15 +00:00
Friel
8475396941 merge ci: increase Linux arglint timeout into collab stack 2026-03-30 13:03:15 +00:00
Friel
4b59f68e7e ci: increase Linux arglint timeout 2026-03-30 12:57:34 +00:00
Friel
6c854ab0c7 ci: increase Linux arglint timeout 2026-03-30 12:57:34 +00:00
Friel
dac25f336b ci: increase Linux arglint timeout 2026-03-30 12:57:34 +00:00
Friel
654ce31617 ci: bump linux arglint prebuilt timeout 2026-03-30 12:56:00 +00:00
Friel
c5475b2354 ci: bump linux arglint prebuilt timeout 2026-03-30 12:56:00 +00:00
Friel
c3bd7c5218 ci: bump linux arglint prebuilt timeout 2026-03-30 12:56:00 +00:00
Friel
13ca7c4b9b merge spawn-mode-removal timeout bump into collab stack 2026-03-30 11:07:45 +00:00
Friel
ff3b5301c2 merge watchdog-self-close-tool timeout bump into collab stack 2026-03-30 11:07:45 +00:00
Friel
618490ce2b merge tui-watchdog-timer-countdown timeout bump into collab stack 2026-03-30 11:07:45 +00:00
Friel
c8450fc485 merge watchdog-interval-reset timeout bump into collab stack 2026-03-30 11:07:45 +00:00
Friel
3b1ef8bca5 merge model-fallback-list timeout bump into collab stack 2026-03-30 11:07:45 +00:00
Friel
0f29328a88 merge agent-tools-namespace timeout bump into collab stack 2026-03-30 11:07:45 +00:00
Friel
be4fbb6ecb ci: extend spawn mode removal timeouts 2026-03-30 11:03:34 +00:00
Friel
e55701b4fc ci: extend watchdog self-close tool timeouts 2026-03-30 11:03:34 +00:00
Friel
dfdee7d6cb ci: extend watchdog timer and subagent behavior timeouts 2026-03-30 11:03:33 +00:00
Friel
aab9f3c365 ci: increase sdk and bazel timeouts 2026-03-30 11:03:07 +00:00
Friel
81d01829d8 ci: increase sdk and bazel timeouts 2026-03-30 11:03:07 +00:00
Friel
248aa6cb32 ci: increase sdk and bazel timeouts 2026-03-30 11:03:07 +00:00
Friel
6bfea621aa ci: extend spawn mode removal workflow timeouts 2026-03-30 10:03:34 +00:00
Friel
df8801be6e ci: extend watchdog self-close workflow timeouts 2026-03-30 10:03:34 +00:00
Friel
9f0916586d ci: extend watchdog timer workflow timeouts 2026-03-30 10:03:34 +00:00
Friel
72d43c58b0 ci: extend sdk and arglint timeouts 2026-03-30 10:03:34 +00:00
Friel
e9882f4140 ci: extend sdk and arglint timeouts 2026-03-30 10:03:34 +00:00
Friel
5b18d8ea38 ci: extend sdk and arglint timeouts 2026-03-30 10:03:33 +00:00
Friel
8c5a0ae94e merge spawn-mode-removal timeout bump into collab stack 2026-03-30 09:17:48 +00:00
Friel
8de95d9256 merge watchdog-self-close-tool timeout bump into collab stack 2026-03-30 09:17:47 +00:00
Friel
c328f97877 merge tui-watchdog-timer-countdown timeout bump into collab stack 2026-03-30 09:17:47 +00:00
Friel
751d273664 merge watchdog-interval-reset timeout bump into collab stack 2026-03-30 09:17:47 +00:00
Friel
5ccaa83a09 merge model-fallback-list timeout bump into collab stack 2026-03-30 09:17:47 +00:00
Friel
3a93dbfb7d merge agent-tools-namespace timeout bump into collab stack 2026-03-30 09:17:47 +00:00
Friel
4446ed91cf ci: extend spawn mode removal workflow timeouts 2026-03-30 09:12:32 +00:00
Friel
496ebb2c31 ci: extend watchdog self-close workflow timeouts 2026-03-30 09:12:31 +00:00
Friel
79d73b4a5c ci: extend watchdog timer branch workflow timeouts 2026-03-30 09:12:31 +00:00
Friel
b693e09ea6 ci: raise sdk and arglint timeouts 2026-03-30 09:12:04 +00:00
Friel
acab8b0ebb ci: raise sdk and arglint timeouts 2026-03-30 09:12:02 +00:00
Friel
fa84dfe804 ci: raise sdk and arglint timeouts 2026-03-30 09:11:59 +00:00
Friel
c900f1231a merge tui-watchdog-timer-countdown into collab stack 2026-03-30 08:53:34 +00:00
Friel
972f6ed125 merge dev/friel/watchdog-self-close-tool into collab stack
# Conflicts:
#	codex-rs/core/src/tools/spec.rs
2026-03-30 08:53:24 +00:00
Friel
526a40f615 merge dev/friel/watchdog-interval-reset into collab stack 2026-03-30 08:52:37 +00:00
Friel
f8ea0b6a65 merge dev/friel/spawn-mode-removal into collab stack 2026-03-30 08:52:21 +00:00
Friel
f4a32a76fa merge model-fallback-list into collab stack 2026-03-30 08:52:17 +00:00
Friel
b18316a10b merge dev/friel/fork-context-inherits-parent-model into collab stack 2026-03-30 08:52:14 +00:00
Friel
0b95373b11 merge dev/friel/agent-tools-namespace into collab stack 2026-03-30 08:51:59 +00:00
Friel
b2acee0938 ci: bump workflow timeouts 2026-03-30 08:45:50 +00:00
Friel
6cf38738d6 ci: bump workflow timeouts 2026-03-30 08:45:50 +00:00
Friel
484eb1ebfd ci: bump workflow timeouts 2026-03-30 08:45:49 +00:00
Friel
7430b77494 ci: bump sdk and arglint timeouts 2026-03-30 08:44:52 +00:00
Friel
6a516b1947 ci: bump sdk and arglint timeouts 2026-03-30 08:44:52 +00:00
Friel
bef956ccd4 ci: bump sdk and arglint timeouts 2026-03-30 08:44:52 +00:00
Friel
c4e5ccdc77 merge upstream/dev/friel/watchdog-runtime-and-prompts into collab stack
# Conflicts:
#	codex-rs/core/tests/suite/subagent_notifications.rs
2026-03-30 07:54:32 +00:00
Friel
63b1bb2a8e test(core): handle namespaced spawn_agent description 2026-03-30 07:49:11 +00:00
Friel
ab51df57db test(core): align watchdog prompt-layering expectations 2026-03-30 07:27:20 +00:00
Friel
bf47ade0bb test(core): align watchdog prompt-layering expectations 2026-03-30 07:22:13 +00:00
Friel
a2d94eafb1 test(core): keep notification test non-forked by default 2026-03-30 06:14:32 +00:00
Friel
8bbc644b76 test(core): keep notification test non-forked by default 2026-03-30 06:09:12 +00:00
Friel
d4489dc497 test(core): fix subagent notification validator 2026-03-30 05:51:27 +00:00
Friel
5b498925e3 test(core): fix subagent notification validator 2026-03-30 05:48:14 +00:00
Friel
9c1342c36a merge origin/dev/friel/fork-context-inherits-parent-model into collab stack 2026-03-30 04:51:06 +00:00
Friel
d14cfd2597 merge upstream/dev/friel/watchdog-runtime-and-prompts into collab stack 2026-03-30 04:26:24 +00:00
Friel
c79cb41b7d fix(core): preserve effective effort for fork-context children 2026-03-30 04:22:19 +00:00
Friel
3fe0995729 merge upstream/dev/friel/fork-context-inherits-parent-model into collab stack 2026-03-30 03:41:43 +00:00
Friel
e13dc9d843 chore(core): clean watchdog prompt layering leftovers 2026-03-30 03:37:39 +00:00
Friel
df69f49b6b test: refresh fork-context expectations 2026-03-30 03:07:31 +00:00
Friel
54ec91e277 fix(stack): finish 20260330 collab integration 2026-03-30 02:36:50 +00:00
Friel
845a0e571a merge upstream/dev/codex/add-fork-option-to-codex-exec into collab stack 2026-03-30 01:54:37 +00:00
Friel
fb462c3efb merge upstream/dev/codex/add-custom-models-support-in-config.toml-r2 into collab stack 2026-03-30 01:54:32 +00:00
Friel
52c823d2a4 merge upstream/dev/friel/tui-watchdog-and-subagent-behavior into collab stack 2026-03-30 01:53:49 +00:00
Friel
379d9f68a5 merge upstream/dev/friel/watchdog-runtime-and-prompts into collab stack 2026-03-30 01:53:08 +00:00
Friel
a245175736 merge model-fallback-list into collab stack 2026-03-30 01:43:00 +00:00
Friel
8885b0f59e merge dev/friel/agent-tools-namespace into collab stack 2026-03-30 01:42:56 +00:00
Friel
b0d543f21f merge origin/friel/auto-unarchive-resume into collab stack 2026-03-30 01:42:50 +00:00
Friel
41f0cb36cb merge upstream/dev/friel/fork-references into collab stack 2026-03-30 01:42:45 +00:00
Friel
4883b3ca9c fix(core): annotate spawn model fallback positional args 2026-03-30 01:38:06 +00:00
Friel
1222f23d0c feat(core): expose agent tools in namespace 2026-03-30 00:54:18 +00:00
Friel
2da9e1b7f2 feat(core): remove spawn_mode from agent roles 2026-03-30 00:39:45 +00:00
Friel
0ad661977e fix(core): preserve role precedence for model fallback 2026-03-29 23:47:22 +00:00
Friel
bbbe245f14 add deferred watchdog self-close tool 2026-03-29 22:10:23 +00:00
Friel
d45c1a581f Add ordered model fallback list for subagent spawn 2026-03-29 21:36:03 +00:00
Friel
4dc32e8c5e feat(core): reset watchdog on owner input 2026-03-29 21:28:15 +00:00
Friel
d4ed343c1d docs(core): guard against accidental watchdog closure 2026-03-29 21:20:48 +00:00
Friel
45bf65d007 Render watchdog countdown in subagent panel 2026-03-29 21:11:31 +00:00
Friel
b1213d0a2a feat(core): preserve watchdog fork prefix 2026-03-29 19:29:54 +00:00
Friel
67e4190951 Merge remote-tracking branch 'origin/dev/friel/fork-context-inherits-parent-model' into repair/watchdog-prompt-layering 2026-03-29 18:07:01 +00:00
Friel
fb8653cd30 Merge remote-tracking branch 'origin/dev/friel/agent-tools-namespace' into repair/watchdog-prompt-layering 2026-03-29 18:07:00 +00:00
Friel
cc60cafc50 feat(core): add role-level fork_context defaults 2026-03-29 17:56:12 +00:00
Friel
70ba3d1e29 feat(core): expose agent tools in namespace 2026-03-29 17:56:12 +00:00
Friel
2c3bff24e4 test(core): fix multi-agent v2 fork-context regression
Co-authored-by: Codex <noreply@openai.com>
2026-03-29 17:04:29 +00:00
Friel
be051e056e feat(core): force forked agents to inherit parent model
Co-authored-by: Codex <noreply@openai.com>
2026-03-29 17:04:28 +00:00
Friel
a2f37d5548 fix(tui): preserve watchdog behavior on refreshed base
Resolve the remaining TUI-side merge drift after restacking the watchdog and subagent behavior branch onto the refreshed TUI foundation branch.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 23:09:20 -07:00
Friel
65db8195a5 test(nextest): extend schema fixture timeout on windows 2026-03-28 23:09:20 -07:00
Friel
86fe4f6be4 test(app-server): stabilize thread unsubscribe on slow runners 2026-03-28 23:09:20 -07:00
Friel
3bd69accc1 fix(tui): render live agent inbox notifications 2026-03-28 23:08:51 -07:00
Friel
b8be51fe7c fix(tui): annotate subagent panel test literals 2026-03-28 19:24:31 -07:00
Friel
0b72153645 fix(tui): annotate subagent panel render literals 2026-03-28 18:54:46 -07:00
Friel
510d5679a9 fix(tui): annotate subagent panel truncation literal 2026-03-28 18:43:02 -07:00
Friel
48b7f72829 fix(tui): drop stale voice transcription init on current main 2026-03-28 18:34:11 -07:00
Friel
fc7a5e3d0f fix(tui): restore subagent panel wiring on app-server TUI 2026-03-28 18:28:25 -07:00
Friel
90d339cf75 fix(tui): mount subagent panel independently of active cell 2026-03-28 18:24:50 -07:00
Friel
0af3f1f66e fix(tui): keep subagent panel out of transcript history 2026-03-28 18:24:50 -07:00
Friel
4ef8493fd2 test(tui): annotate subagent panel literals 2026-03-28 18:24:50 -07:00
Friel
5e41296824 fix(tui): format multi-agent status helper 2026-03-28 18:24:50 -07:00
Friel
3cfdc99ecc fix(tui): annotate watchdog panel truncation literals 2026-03-28 18:24:50 -07:00
Friel
77c69e35b7 fix(tui): adapt collab foundation to refreshed main
Preserve the collab transcript fixtures and current TUI style rules after rebasing onto the refreshed tui_app_server codebase.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 18:24:49 -07:00
Friel
ed0cff78a6 feat(tui): add subagent inbox foundation
Preserve the subagent inbox foundation behavior on the current origin/main base and collapse the branch back to a single commit for easier future restacks.
2026-03-28 18:24:49 -07:00
Friel
3c84d41945 test(core): annotate final custom model literals 2026-03-28 16:50:22 -07:00
Friel
2b7fd5a91d fix(tui): correct watchdog spawn replay fixtures 2026-03-28 16:42:08 -07:00
Friel
d1196258a1 test(core): annotate custom model helper literals 2026-03-28 16:34:48 -07:00
Friel
e5e3911799 fix(tui): align watchdog spawn replay fallback 2026-03-28 16:33:33 -07:00
Friel
90c18fd1b1 test(tui): set spawn mode in watchdog replay fixtures 2026-03-28 16:31:46 -07:00
Friel
08dad720db fix(tui): set spawn mode in collab spawn replay 2026-03-28 16:22:24 -07:00
Friel
83780ddbff test(core): annotate watchdog test literals 2026-03-28 16:22:24 -07:00
Friel
b4ea255a9f fix(core): annotate watchdog positional literals 2026-03-28 16:22:24 -07:00
Friel
2b0f370fd8 fix(core): preserve watchdog spawn handler imports
Co-authored-by: Codex <noreply@openai.com>
2026-03-28 16:22:24 -07:00
Friel
7a079455d3 fix(core): adapt watchdog role branch to refreshed main
Keep the role-driven watchdog branch aligned with the refreshed list_agents and spawn event APIs after rebasing on the updated subagent inbox branch.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 16:22:24 -07:00
Friel
074216d951 feat(core): make watchdogs role-driven
Co-authored-by: Codex <noreply@openai.com>
2026-03-28 16:22:24 -07:00
Friel
3e8bd6b801 feat(core): add watchdog runtime and prompts
Preserve the watchdog runtime and prompt behavior on top of the refreshed inbox branch and collapse the branch back to a single commit for easier future restacks.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 16:22:24 -07:00
Friel
afaa5e887c test(core): annotate inbox control test literals 2026-03-28 16:22:01 -07:00
Friel
8fab3fb7da test(core): annotate remaining custom model literals 2026-03-28 16:22:01 -07:00
Friel
83e58d5036 test(app-server): annotate remaining shell workdir literals 2026-03-28 12:06:07 -07:00
Friel
d581363a82 test(core): annotate refreshed custom model literals 2026-03-28 12:05:31 -07:00
Friel
73418e2882 test(app-server): annotate inbox resume literals 2026-03-28 11:56:40 -07:00
Friel
5395dab51d test(cli): annotate remote and color literals 2026-03-28 11:51:56 -07:00
Friel
e6f412f2d8 test(core): annotate auto-unarchive literals 2026-03-28 11:48:18 -07:00
Friel
9118d71ec7 test(core): annotate custom model literals 2026-03-28 11:48:18 -07:00
Friel
901c8e2ba6 test(core): annotate fork-thread positional literals 2026-03-28 11:35:15 -07:00
Friel
ebc45db194 test(features): annotate auth literals 2026-03-28 11:35:15 -07:00
Friel
70cbe5a89d test(exec): annotate fork option literals 2026-03-28 11:35:15 -07:00
Friel
c87d62c34f fix(core): re-export auto-unarchive lookup on refreshed main
Keep the split rollout shim aligned with the refreshed codex-rollout crate so resume-only auto-unarchive continues to compile on current main.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 11:35:15 -07:00
Friel
a68b1bd423 test(core): annotate custom model catalog literal 2026-03-28 11:35:15 -07:00
Friel
797fed3d57 fix(core): adapt fork references to refreshed main
Disable stale inline fork-reference test modules on the refreshed core APIs and keep the rollout re-export surface aligned with the split codex-rollout crate.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 11:35:15 -07:00
Friel
3be3e8fc87 fix(core): apply refreshed clippy suggestions
Co-authored-by: Codex <noreply@openai.com>
2026-03-28 11:35:15 -07:00
Friel
8ee3a48601 feat(exec): add --fork option to codex exec
Add non-interactive session forking to codex exec and keep the CLI/help/tests aligned with the interactive fork behavior.
2026-03-28 11:35:15 -07:00
Friel
328706da37 codex: auto-unarchive archived sessions safely on resume
Preserve the auto-unarchive-on-resume behavior while keeping archived-session lookup safe. This carries the rollout lookup hardening, the resume path updates, and the cross-platform guardian/TUI test fixes needed for current CI.
2026-03-28 11:35:15 -07:00
Friel
bc18824d23 fix(core): adapt custom model tests to refreshed main
Drop the removed ModelInfo field and normalize refreshed ThreadManager and UserTurn test callsites.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 11:35:15 -07:00
Friel
f30fde6221 feat(rollout): preserve fork references across replay
Preserve fork-reference replay behavior on the current origin/main base and collapse the branch back to a single commit for easier future restacks.
2026-03-28 11:35:15 -07:00
Friel
4d0a1431f8 fix(core): adapt inbox delivery rebase to current main
Keep the rebased inbox-delivery branch on current core APIs by moving the inbox-specific coverage into current main's control tests and updating the turn-restart helper to use RegularTask.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 11:35:15 -07:00
Friel
d6f8e3aeeb feat(core): support custom model aliases in config.toml
Preserve custom model alias support on the current origin/main base and collapse the branch back to a single commit for easier future restacks.
2026-03-28 11:35:15 -07:00
Friel
0e91619094 feat(agents): enable subagent inbox delivery
Preserve subagent inbox delivery on the current origin/main base and collapse the branch back to a single commit for easier future restacks.
2026-03-28 11:35:15 -07:00
Friel
5628e3cc8f fix(core): re-export auto-unarchive lookup on refreshed main
Keep the split rollout shim aligned with the refreshed codex-rollout crate so resume-only auto-unarchive continues to compile on current main.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 10:29:12 -07:00
Friel
63b0d26587 codex: auto-unarchive archived sessions safely on resume
Preserve the auto-unarchive-on-resume behavior while keeping archived-session lookup safe. This carries the rollout lookup hardening, the resume path updates, and the cross-platform guardian/TUI test fixes needed for current CI.
2026-03-28 10:29:12 -07:00
776 changed files with 23034 additions and 30058 deletions

View File

@@ -44,7 +44,6 @@ common --remote_timeout=3600
common --noexperimental_throttle_remote_action_building
common --experimental_remote_execution_keepalive
common --grpc_keepalive_time=30s
common --experimental_remote_downloader=grpcs://remote.buildbuddy.io
# This limits both in-flight executions and concurrent downloads. Even with high number
# of jobs execution will still be limited by CPU cores, so this just pays a bit of
@@ -125,6 +124,7 @@ build:argument-comment-lint --@rules_rust//rust/toolchain/channel=nightly
common:ci-windows --config=ci-bazel
common:ci-windows --build_metadata=TAG_os=windows
common:ci-windows --repo_contents_cache=D:/a/.cache/bazel-repo-contents-cache
common:ci-windows --repository_cache=D:/a/.cache/bazel-repo-cache
# We prefer to run the build actions entirely remotely so we can dial up the concurrency.
# We have platform-specific tests, so we want to execute the tests on all platforms using the strongest sandboxing available on each platform.

View File

@@ -1,48 +0,0 @@
---
name: codex-bug
description: Diagnose GitHub bug reports in openai/codex. Use when given a GitHub issue URL from openai/codex and asked to decide next steps such as verifying against the repo, requesting more info, or explaining why it is not a bug; follow any additional user-provided instructions.
---
# Codex Bug
## Overview
Diagnose a Codex GitHub bug report and decide the next action: verify against sources, request more info, or explain why it is not a bug.
## Workflow
1. Confirm the input
- Require a GitHub issue URL that points to `github.com/openai/codex/issues/…`.
- If the URL is missing or not in the right repo, ask the user for the correct link.
2. Network access
- Always access the issue over the network immediately, even if you think access is blocked or unavailable.
- Prefer the GitHub API over HTML pages because the HTML is noisy:
- Issue: `https://api.github.com/repos/openai/codex/issues/<number>`
- Comments: `https://api.github.com/repos/openai/codex/issues/<number>/comments`
- If the environment requires explicit approval, request it on demand via the tool and continue without additional user prompting.
- Only if the network attempt fails after requesting approval, explain what you can do offline (e.g., draft a response template) and ask how to proceed.
3. Read the issue
- Use the GitHub API responses (issue + comments) as the source of truth rather than scraping the HTML issue page.
- Extract: title, body, repro steps, expected vs actual, environment, logs, and any attachments.
- Note whether the report already includes logs or session details.
- If the report includes a thread ID, mention it in the summary and use it to look up the logs and session details if you have access to them.
4. Summarize the bug before investigating
- Before inspecting code, docs, or logs in depth, write a short summary of the report in your own words.
- Include the reported behavior, expected behavior, repro steps, environment, and what evidence is already attached or missing.
5. Decide the course of action
- **Verify with sources** when the report is specific and likely reproducible. Inspect relevant Codex files (or mention the files to inspect if access is unavailable).
- **Request more information** when the report is vague, missing repro steps, or lacks logs/environment.
- **Explain not a bug** when the report contradicts current behavior or documented constraints (cite the evidence from the issue and any local sources you checked).
6. Respond
- Provide a concise report of your findings and next steps.

View File

@@ -9,9 +9,9 @@ inputs:
required: false
default: "false"
outputs:
repository-cache-path:
description: Filesystem path used for the Bazel repository cache.
value: ${{ steps.configure_bazel_repository_cache.outputs.repository-cache-path }}
cache-hit:
description: Whether the Bazel repository cache key was restored exactly.
value: ${{ steps.cache_bazel_repository_restore.outputs.cache-hit }}
runs:
using: composite
@@ -41,16 +41,17 @@ runs:
- name: Set up Bazel
uses: bazelbuild/setup-bazelisk@v3
- name: Configure Bazel repository cache
id: configure_bazel_repository_cache
shell: pwsh
run: |
# Keep the repository cache under HOME on all runners. Windows `D:\a`
# cache paths match `.bazelrc`, but `actions/cache/restore` currently
# returns HTTP 400 for that path in the Windows clippy job.
$repositoryCachePath = Join-Path $HOME '.cache/bazel-repo-cache'
"repository-cache-path=$repositoryCachePath" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"BAZEL_REPOSITORY_CACHE=$repositoryCachePath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
# Restore bazel repository cache so we don't have to redownload all the external dependencies
# on every CI run.
- name: Restore bazel repository cache
id: cache_bazel_repository_restore
uses: actions/cache/restore@v5
with:
path: |
~/.cache/bazel-repo-cache
key: bazel-cache-${{ inputs.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
restore-keys: |
bazel-cache-${{ inputs.target }}
- name: Configure Bazel output root (Windows)
if: runner.os == 'Windows'
@@ -64,6 +65,10 @@ runs:
$repoContentsCache = Join-Path $env:RUNNER_TEMP "bazel-repo-contents-cache-$env:GITHUB_RUN_ID-$env:GITHUB_JOB"
"BAZEL_OUTPUT_USER_ROOT=$bazelOutputUserRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"BAZEL_REPO_CONTENTS_CACHE=$repoContentsCache" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
if (-not $hasDDrive) {
$repositoryCache = Join-Path $env:USERPROFILE '.cache\bazel-repo-cache'
"BAZEL_REPOSITORY_CACHE=$repositoryCache" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
}
- name: Expose MSVC SDK environment (Windows)
if: runner.os == 'Windows'

View File

@@ -5,7 +5,6 @@ set -euo pipefail
print_failed_bazel_test_logs=0
use_node_test_env=0
remote_download_toplevel=0
windows_msvc_host_platform=0
while [[ $# -gt 0 ]]; do
case "$1" in
@@ -21,10 +20,6 @@ while [[ $# -gt 0 ]]; do
remote_download_toplevel=1
shift
;;
--windows-msvc-host-platform)
windows_msvc_host_platform=1
shift
;;
--)
shift
break
@@ -37,7 +32,7 @@ while [[ $# -gt 0 ]]; do
done
if [[ $# -eq 0 ]]; then
echo "Usage: $0 [--print-failed-test-logs] [--use-node-test-env] [--remote-download-toplevel] [--windows-msvc-host-platform] -- <bazel args> -- <targets>" >&2
echo "Usage: $0 [--print-failed-test-logs] [--use-node-test-env] [--remote-download-toplevel] -- <bazel args> -- <targets>" >&2
exit 1
fi
@@ -126,35 +121,14 @@ if [[ ${#bazel_args[@]} -eq 0 || ${#bazel_targets[@]} -eq 0 ]]; then
exit 1
fi
if [[ $use_node_test_env -eq 1 ]]; then
if [[ $use_node_test_env -eq 1 && "${RUNNER_OS:-}" != "Windows" ]]; then
# Bazel test sandboxes on macOS may resolve an older Homebrew `node`
# before the `actions/setup-node` runtime on PATH.
node_bin="$(which node)"
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
node_bin="$(cygpath -w "${node_bin}")"
fi
bazel_args+=("--test_env=CODEX_JS_REPL_NODE_PATH=${node_bin}")
fi
post_config_bazel_args=()
if [[ "${RUNNER_OS:-}" == "Windows" && $windows_msvc_host_platform -eq 1 ]]; then
has_host_platform_override=0
for arg in "${bazel_args[@]}"; do
if [[ "$arg" == --host_platform=* ]]; then
has_host_platform_override=1
break
fi
done
if [[ $has_host_platform_override -eq 0 ]]; then
# Keep Windows Bazel targets on `windows-gnullvm` for cfg coverage, but opt
# specific jobs into an MSVC exec platform when they need helper binaries
# like Rust test wrappers and V8 generators to resolve a compatible host
# toolchain.
post_config_bazel_args+=("--host_platform=//:local_windows_msvc")
fi
fi
if [[ $remote_download_toplevel -eq 1 ]]; then
# Override the CI config's remote_download_minimal setting when callers need
# the built artifact to exist on disk after the command completes.
@@ -172,12 +146,6 @@ if [[ -n "${BAZEL_REPOSITORY_CACHE:-}" ]]; then
post_config_bazel_args+=("--repository_cache=${BAZEL_REPOSITORY_CACHE}")
fi
if [[ -n "${CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR:-}" ]]; then
post_config_bazel_args+=(
"--execution_log_compact_file=${CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR}/execution-log-${bazel_args[0]}-${GITHUB_JOB:-local}-$$.zst"
)
fi
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
windows_action_env_vars=(
INCLUDE

View File

@@ -5,15 +5,15 @@ The workflows in this directory are split so that pull requests get fast, review
## Pull Requests
- `bazel.yml` is the main pre-merge verification path for Rust code.
It runs Bazel `test` and Bazel `clippy` on the supported Bazel targets,
including the generated Rust test binaries needed to lint inline `#[cfg(test)]`
code.
It runs Bazel `test` and Bazel `clippy` on the supported Bazel targets.
- `rust-ci.yml` keeps the Cargo-native PR checks intentionally small:
- `cargo fmt --check`
- `cargo shear`
- `argument-comment-lint` on Linux, macOS, and Windows
- `tools/argument-comment-lint` package tests when the lint or its workflow wiring changes
The PR workflow still keeps the Linux lint lane on the default-targets-only invocation for now, but the released linter runs on Linux, macOS, and Windows before merge.
## Post-Merge On `main`
- `bazel.yml` also runs on pushes to `main`.

View File

@@ -17,7 +17,7 @@ concurrency:
cancel-in-progress: ${{ github.ref_name != 'main' }}
jobs:
test:
timeout-minutes: 30
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
@@ -58,31 +58,11 @@ jobs:
target: ${{ matrix.target }}
install-test-prereqs: "true"
# Restore the Bazel repository cache explicitly so external dependencies
# do not need to be re-downloaded on every CI run. Keep restore failures
# non-fatal so transient cache-service errors degrade to a cold build
# instead of failing the job.
- name: Restore bazel repository cache
id: cache_bazel_repository_restore
continue-on-error: true
uses: actions/cache/restore@v5
with:
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
restore-keys: |
bazel-cache-${{ matrix.target }}
- name: Check MODULE.bazel.lock is up to date
if: matrix.os == 'ubuntu-24.04' && matrix.target == 'x86_64-unknown-linux-gnu'
shell: bash
run: ./scripts/check-module-bazel-lock.sh
- name: Set up Bazel execution logs
shell: bash
run: |
mkdir -p "${RUNNER_TEMP}/bazel-execution-logs"
echo "CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR=${RUNNER_TEMP}/bazel-execution-logs" >> "${GITHUB_ENV}"
- name: bazel test //...
env:
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
@@ -96,16 +76,9 @@ jobs:
-//third_party/v8:all
)
bazel_wrapper_args=(
--print-failed-test-logs
--use-node-test-env
)
if [[ "${RUNNER_OS}" == "Windows" ]]; then
bazel_wrapper_args+=(--windows-msvc-host-platform)
fi
./.github/scripts/run-bazel-ci.sh \
"${bazel_wrapper_args[@]}" \
--print-failed-test-logs \
--use-node-test-env \
-- \
test \
--test_tag_filters=-argument-comment-lint \
@@ -114,27 +87,19 @@ jobs:
-- \
"${bazel_targets[@]}"
- name: Upload Bazel execution logs
if: always() && !cancelled()
continue-on-error: true
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: bazel-execution-logs-test-${{ matrix.target }}
path: ${{ runner.temp }}/bazel-execution-logs
if-no-files-found: ignore
# Save bazel repository cache explicitly; make non-fatal so cache uploading
# never fails the overall job. Only save when key wasn't hit.
- name: Save bazel repository cache
if: always() && !cancelled() && steps.cache_bazel_repository_restore.outputs.cache-hit != 'true'
if: always() && !cancelled() && steps.setup_bazel.outputs.cache-hit != 'true'
continue-on-error: true
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
path: |
~/.cache/bazel-repo-cache
key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
clippy:
timeout-minutes: 30
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
@@ -161,71 +126,30 @@ jobs:
with:
target: ${{ matrix.target }}
# Restore the Bazel repository cache explicitly so external dependencies
# do not need to be re-downloaded on every CI run. Keep restore failures
# non-fatal so transient cache-service errors degrade to a cold build
# instead of failing the job.
- name: Restore bazel repository cache
id: cache_bazel_repository_restore
continue-on-error: true
uses: actions/cache/restore@v5
with:
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
restore-keys: |
bazel-cache-${{ matrix.target }}
- name: Set up Bazel execution logs
shell: bash
run: |
mkdir -p "${RUNNER_TEMP}/bazel-execution-logs"
echo "CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR=${RUNNER_TEMP}/bazel-execution-logs" >> "${GITHUB_ENV}"
- name: bazel build --config=clippy lint targets
- name: bazel build --config=clippy //codex-rs/...
env:
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
shell: bash
run: |
bazel_clippy_args=(
--config=clippy
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
--build_metadata=TAG_job=clippy
)
if [[ "${RUNNER_OS}" == "Windows" ]]; then
# Some explicit targets pulled in through //codex-rs/... are
# intentionally incompatible with `//:local_windows`, but the lint
# aspect still traverses their compatible Rust deps.
bazel_clippy_args+=(--skip_incompatible_explicit_targets)
fi
bazel_target_lines="$(./scripts/list-bazel-clippy-targets.sh)"
bazel_targets=()
while IFS= read -r target; do
bazel_targets+=("${target}")
done <<< "${bazel_target_lines}"
# Keep the initial Bazel clippy scope on codex-rs and out of the
# V8 proof-of-concept target for now.
./.github/scripts/run-bazel-ci.sh \
-- \
build \
"${bazel_clippy_args[@]}" \
--config=clippy \
--build_metadata=COMMIT_SHA=${GITHUB_SHA} \
--build_metadata=TAG_job=clippy \
-- \
"${bazel_targets[@]}"
- name: Upload Bazel execution logs
if: always() && !cancelled()
continue-on-error: true
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: bazel-execution-logs-clippy-${{ matrix.target }}
path: ${{ runner.temp }}/bazel-execution-logs
if-no-files-found: ignore
//codex-rs/... \
-//codex-rs/v8-poc:all
# Save bazel repository cache explicitly; make non-fatal so cache uploading
# never fails the overall job. Only save when key wasn't hit.
- name: Save bazel repository cache
if: always() && !cancelled()
if: always() && !cancelled() && steps.setup_bazel.outputs.cache-hit != 'true'
continue-on-error: true
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
path: |
~/.cache/bazel-repo-cache
key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}

View File

@@ -52,15 +52,13 @@ jobs:
6. code-review — Issues related to the code review feature or functionality.
7. safety-check - Issues related to cyber risk detection or trusted access verification.
8. auth - Problems related to authentication, login, or access tokens.
9. exec - Problems related to the "codex exec" command or functionality.
10. hooks - Problems related to event hooks
11. context - Problems related to compaction, context windows, or available context reporting.
12. skills - Problems related to skills or plugins
13. custom-model - Problems that involve using custom model providers, local models, or OSS models.
14. rate-limits - Problems related to token limits, rate limits, or token usage reporting.
15. sandbox - Issues related to local sandbox environments or tool call approvals to override sandbox restrictions.
16. tool-calls - Problems related to specific tool call invocations including unexpected errors, failures, or hangs.
17. TUI - Problems with the terminal user interface (TUI) including keyboard shortcuts, copy & pasting, menus, or screen update issues.
9. codex-exec - Problems related to the "codex exec" command or functionality.
10. context-management - Problems related to compaction, context windows, or available context reporting.
11. custom-model - Problems that involve using custom model providers, local models, or OSS models.
12. rate-limits - Problems related to token limits, rate limits, or token usage reporting.
13. sandbox - Issues related to local sandbox environments or tool call approvals to override sandbox restrictions.
14. tool-calls - Problems related to specific tool call invocations including unexpected errors, failures, or hangs.
15. TUI - Problems with the terminal user interface (TUI) including keyboard shortcuts, copy & pasting, menus, or screen update issues.
Issue number: ${{ github.event.issue.number }}

View File

@@ -3,7 +3,6 @@ on:
push:
branches:
- main
- "**full-ci**"
workflow_dispatch:
# CI builds in debug (dev) for faster signal.

View File

@@ -81,7 +81,6 @@ jobs:
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2
with:
tool: cargo-shear
version: 1.5.1
- name: cargo shear
run: cargo shear
@@ -137,10 +136,10 @@ jobs:
include:
- name: Linux
runner: ubuntu-24.04
timeout_minutes: 30
timeout_minutes: 120
- name: macOS
runner: macos-15-xlarge
timeout_minutes: 30
timeout_minutes: 90
- name: Windows
runner: windows-x64
timeout_minutes: 30

View File

@@ -584,11 +584,14 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
# Node 24 bundles npm >= 11.5.1, which trusted publishing requires.
node-version: 24
node-version: 22
registry-url: "https://registry.npmjs.org"
scope: "@openai"
# Trusted publishing requires npm CLI version 11.5.1 or later.
- name: Update npm
run: npm install -g npm@latest
- name: Download npm tarballs from release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -10,7 +10,7 @@ jobs:
runs-on:
group: codex-runners
labels: codex-linux-x64
timeout-minutes: 10
timeout-minutes: 60
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

View File

@@ -21,7 +21,6 @@ In the codex-rs folder where the rust code lives:
- Newly added traits should include doc comments that explain their role and how implementations are expected to use them.
- When writing tests, prefer comparing the equality of entire objects over fields one by one.
- When making a change that adds or changes an API, ensure that the documentation in the `docs/` folder is up to date if applicable.
- Prefer private modules and explicitly exported public crate API.
- If you change `ConfigToml` or nested config types, run `just write-config-schema` to update `codex-rs/core/config.schema.json`.
- If you change Rust dependencies (`Cargo.toml` or `Cargo.lock`), run `just bazel-lock-update` from the
repo root to refresh `MODULE.bazel.lock`, and include that lockfile update in the same change.

View File

@@ -71,8 +71,6 @@ single_version_override(
patch_strip = 1,
patches = [
"//patches:rules_rs_windows_gnullvm_exec.patch",
"//patches:rules_rs_delete_git_worktree_pointer.patch",
"//patches:rules_rs_windows_exec_linker.patch",
],
version = "0.0.43",
)
@@ -86,9 +84,7 @@ rules_rust.patch(
"//patches:rules_rust_windows_gnullvm_build_script.patch",
"//patches:rules_rust_windows_exec_msvc_build_script_env.patch",
"//patches:rules_rust_windows_bootstrap_process_wrapper_linker.patch",
"//patches:rules_rust_windows_build_script_runner_paths.patch",
"//patches:rules_rust_windows_msvc_direct_link_args.patch",
"//patches:rules_rust_windows_process_wrapper_skip_temp_outputs.patch",
"//patches:rules_rust_windows_exec_bin_target.patch",
"//patches:rules_rust_windows_exec_std.patch",
"//patches:rules_rust_windows_exec_rustc_dev_rlib.patch",
@@ -192,18 +188,8 @@ bazel_dep(name = "zstd", version = "1.5.7")
crate.annotation(
crate = "zstd-sys",
gen_build_script = "on",
patch_args = ["-p1"],
patches = [
"//patches:zstd-sys_windows_msvc_include_dirs.patch",
],
)
crate.annotation(
crate = "ring",
patch_args = ["-p1"],
patches = [
"//patches:ring_windows_msvc_include_dirs.patch",
],
gen_build_script = "off",
deps = ["@zstd"],
)
crate.annotation(
build_script_env = {
@@ -228,13 +214,6 @@ inject_repo(crate, "zstd")
use_repo(crate, "argument_comment_lint_crates")
bazel_dep(name = "bzip2", version = "1.0.8.bcr.3")
single_version_override(
module_name = "bzip2",
patch_strip = 1,
patches = [
"//patches:bzip2_windows_stack_args.patch",
],
)
crate.annotation(
crate = "bzip2-sys",
@@ -248,30 +227,20 @@ bazel_dep(name = "zlib", version = "1.3.1.bcr.8")
crate.annotation(
crate = "libz-sys",
gen_build_script = "on",
gen_build_script = "off",
deps = ["@zlib"],
)
inject_repo(crate, "zlib")
bazel_dep(name = "xz", version = "5.4.5.bcr.8")
single_version_override(
module_name = "xz",
patch_strip = 1,
patches = [
"//patches:xz_windows_stack_args.patch",
],
)
# TODO(zbarsky): Enable annotation after fixing windows arm64 builds.
crate.annotation(
crate = "lzma-sys",
gen_build_script = "off",
deps = ["@xz//:lzma"],
gen_build_script = "on",
)
bazel_dep(name = "openssl", version = "3.5.4.bcr.0")
inject_repo(crate, "xz")
crate.annotation(
build_script_data = [
"@openssl//:gen_dir",

6
MODULE.bazel.lock generated
View File

@@ -228,8 +228,6 @@
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
"https://bcr.bazel.build/modules/with_cfg.bzl/0.12.0/MODULE.bazel": "b573395fe63aef4299ba095173e2f62ccfee5ad9bbf7acaa95dba73af9fc2b38",
"https://bcr.bazel.build/modules/with_cfg.bzl/0.12.0/source.json": "3f3fbaeafecaf629877ad152a2c9def21f8d330d91aa94c5dc75bbb98c10b8b8",
"https://bcr.bazel.build/modules/xz/5.4.5.bcr.8/MODULE.bazel": "e48a69bd54053c2ec5fffc2a29fb70122afd3e83ab6c07068f63bc6553fa57cc",
"https://bcr.bazel.build/modules/xz/5.4.5.bcr.8/source.json": "bd7e928ccd63505b44f4784f7bbf12cc11f9ff23bf3ca12ff2c91cd74846099e",
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.8/MODULE.bazel": "772c674bb78a0342b8caf32ab5c25085c493ca4ff08398208dcbe4375fe9f776",
@@ -925,7 +923,7 @@
"hyper-rustls_0.27.7": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"cfg-if\",\"req\":\"^1\"},{\"name\":\"http\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"http-body-util\",\"req\":\"^0.1\"},{\"default_features\":false,\"name\":\"hyper\",\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"client-legacy\",\"tokio\"],\"name\":\"hyper-util\",\"req\":\"^0.1\"},{\"default_features\":false,\"features\":[\"server-auto\"],\"kind\":\"dev\",\"name\":\"hyper-util\",\"req\":\"^0.1\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.4\"},{\"name\":\"pki-types\",\"package\":\"rustls-pki-types\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"rustls\",\"req\":\"^0.23\"},{\"default_features\":false,\"features\":[\"tls12\"],\"kind\":\"dev\",\"name\":\"rustls\",\"req\":\"^0.23\"},{\"name\":\"rustls-native-certs\",\"optional\":true,\"req\":\"^0.8\"},{\"kind\":\"dev\",\"name\":\"rustls-pemfile\",\"req\":\"^2\"},{\"name\":\"rustls-platform-verifier\",\"optional\":true,\"req\":\"^0.6\"},{\"name\":\"tokio\",\"req\":\"^1.0\"},{\"features\":[\"io-std\",\"macros\",\"net\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"tokio-rustls\",\"req\":\"^0.26\"},{\"name\":\"tower-service\",\"req\":\"^0.3\"},{\"name\":\"webpki-roots\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"aws-lc-rs\":[\"rustls/aws_lc_rs\"],\"default\":[\"native-tokio\",\"http1\",\"tls12\",\"logging\",\"aws-lc-rs\"],\"fips\":[\"aws-lc-rs\",\"rustls/fips\"],\"http1\":[\"hyper-util/http1\"],\"http2\":[\"hyper-util/http2\"],\"logging\":[\"log\",\"tokio-rustls/logging\",\"rustls/logging\"],\"native-tokio\":[\"rustls-native-certs\"],\"ring\":[\"rustls/ring\"],\"tls12\":[\"tokio-rustls/tls12\",\"rustls/tls12\"],\"webpki-tokio\":[\"webpki-roots\"]}}",
"hyper-timeout_0.5.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"http-body-util\",\"req\":\"^0.1\"},{\"name\":\"hyper\",\"req\":\"^1.1\"},{\"features\":[\"http1\"],\"kind\":\"dev\",\"name\":\"hyper\",\"req\":\"^1.1\"},{\"kind\":\"dev\",\"name\":\"hyper-tls\",\"req\":\"^0.6\"},{\"features\":[\"client-legacy\",\"http1\"],\"name\":\"hyper-util\",\"req\":\"^0.1.10\"},{\"features\":[\"client-legacy\",\"http1\",\"server\",\"server-graceful\"],\"kind\":\"dev\",\"name\":\"hyper-util\",\"req\":\"^0.1.10\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2\"},{\"name\":\"tokio\",\"req\":\"^1.35\"},{\"features\":[\"io-std\",\"io-util\",\"macros\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.35\"},{\"name\":\"tower-service\",\"req\":\"^0.3\"}],\"features\":{}}",
"hyper-tls_0.6.0": "{\"dependencies\":[{\"name\":\"bytes\",\"req\":\"^1\"},{\"name\":\"http-body-util\",\"req\":\"^0.1.0\"},{\"name\":\"hyper\",\"req\":\"^1\"},{\"features\":[\"client-legacy\",\"tokio\"],\"name\":\"hyper-util\",\"req\":\"^0.1.0\"},{\"features\":[\"http1\"],\"kind\":\"dev\",\"name\":\"hyper-util\",\"req\":\"^0.1.0\"},{\"name\":\"native-tls\",\"req\":\"^0.2.1\"},{\"name\":\"tokio\",\"req\":\"^1\"},{\"features\":[\"io-std\",\"macros\",\"io-util\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.0.0\"},{\"name\":\"tokio-native-tls\",\"req\":\"^0.3\"},{\"name\":\"tower-service\",\"req\":\"^0.3\"}],\"features\":{\"alpn\":[\"native-tls/alpn\"],\"vendored\":[\"native-tls/vendored\"]}}",
"hyper-util_0.1.20": "{\"dependencies\":[{\"name\":\"base64\",\"optional\":true,\"req\":\"^0.22\"},{\"name\":\"bytes\",\"req\":\"^1.7.1\"},{\"kind\":\"dev\",\"name\":\"bytes\",\"req\":\"^1\"},{\"name\":\"futures-channel\",\"optional\":true,\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"futures-util\",\"optional\":true,\"req\":\"^0.3.16\"},{\"default_features\":false,\"features\":[\"alloc\"],\"kind\":\"dev\",\"name\":\"futures-util\",\"req\":\"^0.3.16\"},{\"name\":\"http\",\"req\":\"^1.0\"},{\"name\":\"http-body\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"http-body-util\",\"req\":\"^0.1.0\"},{\"name\":\"hyper\",\"req\":\"^1.8.0\"},{\"features\":[\"full\"],\"kind\":\"dev\",\"name\":\"hyper\",\"req\":\"^1.4.0\"},{\"name\":\"ipnet\",\"optional\":true,\"req\":\"^2.9\"},{\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"percent-encoding\",\"optional\":true,\"req\":\"^2.3\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.4\"},{\"kind\":\"dev\",\"name\":\"pnet_datalink\",\"req\":\"^0.35.0\",\"target\":\"cfg(any(target_os = \\\"linux\\\", target_os = \\\"macos\\\"))\"},{\"kind\":\"dev\",\"name\":\"pretty_env_logger\",\"req\":\"^0.5\"},{\"features\":[\"all\"],\"name\":\"socket2\",\"optional\":true,\"req\":\">=0.5.9, <0.7\"},{\"name\":\"system-configuration\",\"optional\":true,\"req\":\"^0.7\",\"target\":\"cfg(target_os = \\\"macos\\\")\"},{\"default_features\":false,\"name\":\"tokio\",\"optional\":true,\"req\":\"^1\"},{\"features\":[\"macros\",\"test-util\",\"signal\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"tokio-test\",\"req\":\"^0.4\"},{\"name\":\"tower-layer\",\"optional\":true,\"req\":\"^0.3\"},{\"name\":\"tower-service\",\"optional\":true,\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"tower-test\",\"req\":\"^0.4\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"windows-registry\",\"optional\":true,\"req\":\">=0.3, <0.7\",\"target\":\"cfg(windows)\"}],\"features\":{\"__internal_happy_eyeballs_tests\":[],\"client\":[\"hyper/client\",\"tokio/net\",\"dep:tracing\",\"dep:futures-channel\",\"dep:tower-service\"],\"client-legacy\":[\"client\",\"dep:socket2\",\"tokio/sync\",\"dep:libc\",\"dep:futures-util\"],\"client-pool\":[\"client\",\"dep:futures-util\",\"dep:tower-layer\"],\"client-proxy\":[\"client\",\"dep:base64\",\"dep:ipnet\",\"dep:percent-encoding\"],\"client-proxy-system\":[\"dep:system-configuration\",\"dep:windows-registry\"],\"default\":[],\"full\":[\"client\",\"client-legacy\",\"client-pool\",\"client-proxy\",\"client-proxy-system\",\"server\",\"server-auto\",\"server-graceful\",\"service\",\"http1\",\"http2\",\"tokio\",\"tracing\"],\"http1\":[\"hyper/http1\"],\"http2\":[\"hyper/http2\"],\"server\":[\"hyper/server\"],\"server-auto\":[\"server\",\"http1\",\"http2\"],\"server-graceful\":[\"server\",\"tokio/sync\"],\"service\":[\"dep:tower-service\"],\"tokio\":[\"dep:tokio\",\"tokio/rt\",\"tokio/time\"],\"tracing\":[\"dep:tracing\"]}}",
"hyper-util_0.1.19": "{\"dependencies\":[{\"name\":\"base64\",\"optional\":true,\"req\":\"^0.22\"},{\"name\":\"bytes\",\"req\":\"^1.7.1\"},{\"kind\":\"dev\",\"name\":\"bytes\",\"req\":\"^1\"},{\"name\":\"futures-channel\",\"optional\":true,\"req\":\"^0.3\"},{\"name\":\"futures-core\",\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"futures-util\",\"optional\":true,\"req\":\"^0.3.16\"},{\"default_features\":false,\"features\":[\"alloc\"],\"kind\":\"dev\",\"name\":\"futures-util\",\"req\":\"^0.3.16\"},{\"name\":\"http\",\"req\":\"^1.0\"},{\"name\":\"http-body\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"http-body-util\",\"req\":\"^0.1.0\"},{\"name\":\"hyper\",\"req\":\"^1.8.0\"},{\"features\":[\"full\"],\"kind\":\"dev\",\"name\":\"hyper\",\"req\":\"^1.4.0\"},{\"name\":\"ipnet\",\"optional\":true,\"req\":\"^2.9\"},{\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"percent-encoding\",\"optional\":true,\"req\":\"^2.3\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.4\"},{\"kind\":\"dev\",\"name\":\"pnet_datalink\",\"req\":\"^0.35.0\",\"target\":\"cfg(any(target_os = \\\"linux\\\", target_os = \\\"macos\\\"))\"},{\"kind\":\"dev\",\"name\":\"pretty_env_logger\",\"req\":\"^0.5\"},{\"features\":[\"all\"],\"name\":\"socket2\",\"optional\":true,\"req\":\">=0.5.9, <0.7\"},{\"name\":\"system-configuration\",\"optional\":true,\"req\":\">=0.5, <0.7\",\"target\":\"cfg(target_os = \\\"macos\\\")\"},{\"default_features\":false,\"name\":\"tokio\",\"optional\":true,\"req\":\"^1\"},{\"features\":[\"macros\",\"test-util\",\"signal\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"tokio-test\",\"req\":\"^0.4\"},{\"name\":\"tower-layer\",\"optional\":true,\"req\":\"^0.3\"},{\"name\":\"tower-service\",\"optional\":true,\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"tower-test\",\"req\":\"^0.4\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"windows-registry\",\"optional\":true,\"req\":\">=0.3, <0.7\",\"target\":\"cfg(windows)\"}],\"features\":{\"__internal_happy_eyeballs_tests\":[],\"client\":[\"hyper/client\",\"tokio/net\",\"dep:tracing\",\"dep:futures-channel\",\"dep:tower-service\"],\"client-legacy\":[\"client\",\"dep:socket2\",\"tokio/sync\",\"dep:libc\",\"dep:futures-util\"],\"client-pool\":[\"client\",\"dep:futures-util\",\"dep:tower-layer\"],\"client-proxy\":[\"client\",\"dep:base64\",\"dep:ipnet\",\"dep:percent-encoding\"],\"client-proxy-system\":[\"dep:system-configuration\",\"dep:windows-registry\"],\"default\":[],\"full\":[\"client\",\"client-legacy\",\"client-pool\",\"client-proxy\",\"client-proxy-system\",\"server\",\"server-auto\",\"server-graceful\",\"service\",\"http1\",\"http2\",\"tokio\",\"tracing\"],\"http1\":[\"hyper/http1\"],\"http2\":[\"hyper/http2\"],\"server\":[\"hyper/server\"],\"server-auto\":[\"server\",\"http1\",\"http2\"],\"server-graceful\":[\"server\",\"tokio/sync\"],\"service\":[\"dep:tower-service\"],\"tokio\":[\"dep:tokio\",\"tokio/rt\",\"tokio/time\"],\"tracing\":[\"dep:tracing\"]}}",
"hyper_1.8.1": "{\"dependencies\":[{\"name\":\"atomic-waker\",\"optional\":true,\"req\":\"^1.1.2\"},{\"name\":\"bytes\",\"req\":\"^1.2\"},{\"kind\":\"dev\",\"name\":\"form_urlencoded\",\"req\":\"^1\"},{\"name\":\"futures-channel\",\"optional\":true,\"req\":\"^0.3\"},{\"features\":[\"sink\"],\"kind\":\"dev\",\"name\":\"futures-channel\",\"req\":\"^0.3\"},{\"name\":\"futures-core\",\"optional\":true,\"req\":\"^0.3.31\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"futures-util\",\"optional\":true,\"req\":\"^0.3\"},{\"default_features\":false,\"features\":[\"alloc\",\"sink\"],\"kind\":\"dev\",\"name\":\"futures-util\",\"req\":\"^0.3\"},{\"name\":\"h2\",\"optional\":true,\"req\":\"^0.4.2\"},{\"name\":\"http\",\"req\":\"^1\"},{\"name\":\"http-body\",\"req\":\"^1\"},{\"name\":\"http-body-util\",\"optional\":true,\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"http-body-util\",\"req\":\"^0.1\"},{\"name\":\"httparse\",\"optional\":true,\"req\":\"^1.9\"},{\"name\":\"httpdate\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"itoa\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"pin-project-lite\",\"optional\":true,\"req\":\"^0.2.4\"},{\"kind\":\"dev\",\"name\":\"pin-project-lite\",\"req\":\"^0.2.4\"},{\"name\":\"pin-utils\",\"optional\":true,\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"pretty_env_logger\",\"req\":\"^0.5\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"features\":[\"const_generics\",\"const_new\"],\"name\":\"smallvec\",\"optional\":true,\"req\":\"^1.12\"},{\"kind\":\"dev\",\"name\":\"spmc\",\"req\":\"^0.3\"},{\"features\":[\"sync\"],\"name\":\"tokio\",\"req\":\"^1\"},{\"features\":[\"fs\",\"macros\",\"net\",\"io-std\",\"io-util\",\"rt\",\"rt-multi-thread\",\"sync\",\"time\",\"test-util\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"tokio-test\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"tokio-util\",\"req\":\"^0.7.10\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"want\",\"optional\":true,\"req\":\"^0.3\"}],\"features\":{\"capi\":[],\"client\":[\"dep:want\",\"dep:pin-project-lite\",\"dep:smallvec\"],\"default\":[],\"ffi\":[\"dep:http-body-util\",\"dep:futures-util\"],\"full\":[\"client\",\"http1\",\"http2\",\"server\"],\"http1\":[\"dep:atomic-waker\",\"dep:futures-channel\",\"dep:futures-core\",\"dep:httparse\",\"dep:itoa\",\"dep:pin-utils\"],\"http2\":[\"dep:futures-channel\",\"dep:futures-core\",\"dep:h2\"],\"nightly\":[],\"server\":[\"dep:httpdate\",\"dep:pin-project-lite\",\"dep:smallvec\"],\"tracing\":[\"dep:tracing\"]}}",
"i18n-config_0.4.8": "{\"dependencies\":[{\"name\":\"basic-toml\",\"req\":\"^0.1\"},{\"name\":\"log\",\"req\":\"^0.4\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde_derive\",\"req\":\"^1.0\"},{\"name\":\"thiserror\",\"req\":\"^1.0\"},{\"features\":[\"serde\"],\"name\":\"unic-langid\",\"req\":\"^0.9\"}],\"features\":{}}",
"i18n-embed-fl_0.9.4": "{\"dependencies\":[{\"name\":\"dashmap\",\"optional\":true,\"req\":\"^6.0\"},{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.11\"},{\"name\":\"find-crate\",\"req\":\"^0.6\"},{\"name\":\"fluent\",\"req\":\"^0.16\"},{\"name\":\"fluent-syntax\",\"req\":\"^0.11\"},{\"name\":\"i18n-config\",\"req\":\"^0.4.7\"},{\"features\":[\"fluent-system\",\"filesystem-assets\"],\"name\":\"i18n-embed\",\"req\":\"^0.15.4\"},{\"kind\":\"dev\",\"name\":\"pretty_assertions\",\"req\":\"^1.4\"},{\"name\":\"proc-macro-error2\",\"req\":\"^2.0.1\"},{\"name\":\"proc-macro2\",\"req\":\"^1.0\"},{\"name\":\"quote\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"rust-embed\",\"req\":\"^8.0\"},{\"name\":\"strsim\",\"req\":\"^0.11\"},{\"features\":[\"derive\",\"proc-macro\",\"parsing\",\"printing\",\"extra-traits\",\"full\"],\"name\":\"syn\",\"req\":\"^2.0\"},{\"name\":\"unic-langid\",\"req\":\"^0.9\"}],\"features\":{\"dashmap\":[\"dep:dashmap\"]}}",
@@ -1369,7 +1367,7 @@
"syntect_5.3.0": "{\"dependencies\":[{\"name\":\"bincode\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"html_reports\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.3\"},{\"name\":\"fancy-regex\",\"optional\":true,\"req\":\"^0.16.2\"},{\"name\":\"flate2\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"fnv\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"getopts\",\"req\":\"^0.2\"},{\"name\":\"once_cell\",\"req\":\"^1.8\"},{\"default_features\":false,\"name\":\"onig\",\"optional\":true,\"req\":\"^6.5.1\"},{\"name\":\"plist\",\"optional\":true,\"req\":\"^1.3\"},{\"kind\":\"dev\",\"name\":\"pretty_assertions\",\"req\":\"^0.6\"},{\"kind\":\"dev\",\"name\":\"public-api\",\"req\":\"^0.50.1\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.0\"},{\"name\":\"regex-syntax\",\"optional\":true,\"req\":\"^0.8\"},{\"kind\":\"dev\",\"name\":\"rustdoc-json\",\"req\":\"^0.9.7\"},{\"kind\":\"dev\",\"name\":\"rustup-toolchain\",\"req\":\"^0.1.5\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde_derive\",\"req\":\"^1.0\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"thiserror\",\"req\":\"^2.0.12\"},{\"name\":\"walkdir\",\"req\":\"^2.0\"},{\"name\":\"yaml-rust\",\"optional\":true,\"req\":\"^0.4.5\"}],\"features\":{\"default\":[\"default-onig\"],\"default-fancy\":[\"parsing\",\"default-syntaxes\",\"default-themes\",\"html\",\"plist-load\",\"yaml-load\",\"dump-load\",\"dump-create\",\"regex-fancy\"],\"default-onig\":[\"parsing\",\"default-syntaxes\",\"default-themes\",\"html\",\"plist-load\",\"yaml-load\",\"dump-load\",\"dump-create\",\"regex-onig\"],\"default-syntaxes\":[\"parsing\",\"dump-load\"],\"default-themes\":[\"dump-load\"],\"dump-create\":[\"flate2\",\"bincode\"],\"dump-load\":[\"flate2\",\"bincode\"],\"html\":[\"parsing\"],\"metadata\":[\"parsing\",\"plist-load\",\"dep:serde_json\"],\"parsing\":[\"regex-syntax\",\"fnv\",\"dump-create\",\"dump-load\"],\"plist-load\":[\"plist\",\"dep:serde_json\"],\"regex-fancy\":[\"fancy-regex\"],\"regex-onig\":[\"onig\"],\"yaml-load\":[\"yaml-rust\",\"parsing\"]}}",
"sys-locale_0.3.2": "{\"dependencies\":[{\"name\":\"js-sys\",\"optional\":true,\"req\":\"^0.3\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", not(unix)))\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(target_os = \\\"android\\\")\"},{\"name\":\"wasm-bindgen\",\"optional\":true,\"req\":\"^0.2\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", not(unix)))\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", not(unix)))\"},{\"features\":[\"Window\",\"WorkerGlobalScope\",\"Navigator\",\"WorkerNavigator\"],\"name\":\"web-sys\",\"optional\":true,\"req\":\"^0.3\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", not(unix)))\"}],\"features\":{\"js\":[\"js-sys\",\"wasm-bindgen\",\"web-sys\"]}}",
"system-configuration-sys_0.6.0": "{\"dependencies\":[{\"name\":\"core-foundation-sys\",\"req\":\"^0.8\"},{\"name\":\"libc\",\"req\":\"^0.2.149\"}],\"features\":{}}",
"system-configuration_0.7.0": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2\"},{\"name\":\"core-foundation\",\"req\":\"^0.9\"},{\"name\":\"system-configuration-sys\",\"req\":\"^0.6\"}],\"features\":{}}",
"system-configuration_0.6.1": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2\"},{\"name\":\"core-foundation\",\"req\":\"^0.9\"},{\"name\":\"system-configuration-sys\",\"req\":\"^0.6\"}],\"features\":{}}",
"tagptr_0.2.0": "{\"dependencies\":[],\"features\":{}}",
"tar_0.4.44": "{\"dependencies\":[{\"name\":\"filetime\",\"req\":\"^0.2.8\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"},{\"name\":\"xattr\",\"optional\":true,\"req\":\"^1.1.3\",\"target\":\"cfg(unix)\"}],\"features\":{\"default\":[\"xattr\"]}}",
"tempfile_3.24.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"},{\"name\":\"fastrand\",\"req\":\"^2.1.1\"},{\"default_features\":false,\"name\":\"getrandom\",\"optional\":true,\"req\":\"^0.3.0\",\"target\":\"cfg(any(unix, windows, target_os = \\\"wasi\\\"))\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"once_cell\",\"req\":\"^1.19.0\"},{\"features\":[\"fs\"],\"name\":\"rustix\",\"req\":\"^1.1.3\",\"target\":\"cfg(any(unix, target_os = \\\"wasi\\\"))\"},{\"features\":[\"Win32_Storage_FileSystem\",\"Win32_Foundation\"],\"name\":\"windows-sys\",\"req\":\">=0.52, <0.62\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[\"getrandom\"],\"nightly\":[]}}",

View File

@@ -46,7 +46,7 @@ Each archive contains a single entry with the platform baked into the name (e.g.
### Using Codex with your ChatGPT plan
Run `codex` and select **Sign in with ChatGPT**. We recommend signing into your ChatGPT account to use Codex as part of your Plus, Pro, Business, Edu, or Enterprise plan. [Learn more about what's included in your ChatGPT plan](https://help.openai.com/en/articles/11369540-codex-in-chatgpt).
Run `codex` and select **Sign in with ChatGPT**. We recommend signing into your ChatGPT account to use Codex as part of your Plus, Pro, Team, Edu, or Enterprise plan. [Learn more about what's included in your ChatGPT plan](https://help.openai.com/en/articles/11369540-codex-in-chatgpt).
You can also use Codex with an API key, but this requires [additional setup](https://developers.openai.com/codex/auth#sign-in-with-an-api-key).

View File

@@ -27,3 +27,9 @@ test-group = 'app_server_protocol_codegen'
# Keep the library unit tests parallel.
filter = 'package(codex-app-server) & kind(test)'
test-group = 'app_server_integration'
[[profile.default.overrides]]
# Schema fixture generation can take longer than the default timeout on slower
# Windows runners when app-server protocol fixture sets grow.
filter = 'test(schema_fixtures_match_generated)'
slow-timeout = { period = "1m", terminate-after = 2 }

179
codex-rs/Cargo.lock generated
View File

@@ -408,11 +408,9 @@ dependencies = [
"base64 0.22.1",
"chrono",
"codex-app-server-protocol",
"codex-config",
"codex-core",
"codex-features",
"codex-login",
"codex-models-manager",
"codex-protocol",
"codex-utils-cargo-bin",
"core_test_support",
@@ -449,7 +447,7 @@ dependencies = [
"objc2-foundation",
"parking_lot",
"percent-encoding",
"windows-sys 0.52.0",
"windows-sys 0.60.2",
"wl-clipboard-rs",
"x11rb",
]
@@ -1369,9 +1367,7 @@ dependencies = [
"anyhow",
"assert_matches",
"async-trait",
"base64 0.22.1",
"bytes",
"chrono",
"codex-client",
"codex-protocol",
"codex-utils-rustls-provider",
@@ -1420,7 +1416,6 @@ dependencies = [
"codex-git-utils",
"codex-login",
"codex-mcp",
"codex-models-manager",
"codex-otel",
"codex-protocol",
"codex-rmcp-client",
@@ -1434,11 +1429,9 @@ dependencies = [
"codex-utils-cli",
"codex-utils-json-to-toml",
"codex-utils-pty",
"codex-utils-rustls-provider",
"constant_time_eq",
"core_test_support",
"futures",
"gethostname",
"hmac",
"jsonwebtoken",
"opentelemetry",
@@ -1461,7 +1454,6 @@ dependencies = [
"tracing",
"tracing-opentelemetry",
"tracing-subscriber",
"url",
"uuid",
"wiremock",
]
@@ -1496,7 +1488,6 @@ dependencies = [
"codex-experimental-api-macros",
"codex-git-utils",
"codex-protocol",
"codex-shell-command",
"codex-utils-absolute-path",
"codex-utils-cargo-bin",
"inventory",
@@ -1506,6 +1497,7 @@ dependencies = [
"serde",
"serde_json",
"serde_with",
"shlex",
"similar",
"strum_macros 0.28.0",
"tempfile",
@@ -1543,14 +1535,11 @@ dependencies = [
"anyhow",
"assert_cmd",
"assert_matches",
"codex-exec-server",
"codex-utils-absolute-path",
"codex-utils-cargo-bin",
"pretty_assertions",
"similar",
"tempfile",
"thiserror 2.0.18",
"tokio",
"tree-sitter",
"tree-sitter-bash",
]
@@ -1561,11 +1550,9 @@ version = "0.0.0"
dependencies = [
"anyhow",
"codex-apply-patch",
"codex-exec-server",
"codex-linux-sandbox",
"codex-sandboxing",
"codex-shell-escalation",
"codex-utils-absolute-path",
"codex-utils-home-dir",
"dotenvy",
"tempfile",
@@ -1612,7 +1599,6 @@ version = "0.0.0"
dependencies = [
"anyhow",
"clap",
"codex-config",
"codex-connectors",
"codex-core",
"codex-git-utils",
@@ -1715,7 +1701,6 @@ dependencies = [
"base64 0.22.1",
"chrono",
"codex-backend-client",
"codex-config",
"codex-core",
"codex-login",
"codex-otel",
@@ -1802,10 +1787,6 @@ dependencies = [
"v8",
]
[[package]]
name = "codex-collaboration-mode-templates"
version = "0.0.0"
[[package]]
name = "codex-config"
version = "0.0.0"
@@ -1813,13 +1794,8 @@ dependencies = [
"anyhow",
"codex-app-server-protocol",
"codex-execpolicy",
"codex-features",
"codex-git-utils",
"codex-model-provider-info",
"codex-network-proxy",
"codex-protocol",
"codex-utils-absolute-path",
"dunce",
"futures",
"multimap",
"pretty_assertions",
@@ -1837,6 +1813,20 @@ dependencies = [
"wildmatch",
]
[[package]]
name = "codex-config-schema"
version = "0.0.0"
dependencies = [
"anyhow",
"clap",
"codex-config",
"codex-protocol",
"codex-utils-absolute-path",
"schemars 0.8.22",
"serde",
"serde_json",
]
[[package]]
name = "codex-connectors"
version = "0.0.0"
@@ -1861,6 +1851,7 @@ dependencies = [
"async-trait",
"base64 0.22.1",
"bm25",
"chardetng",
"chrono",
"clap",
"codex-analytics",
@@ -1871,24 +1862,21 @@ dependencies = [
"codex-async-utils",
"codex-code-mode",
"codex-config",
"codex-config-schema",
"codex-connectors",
"codex-core-skills",
"codex-exec-server",
"codex-execpolicy",
"codex-features",
"codex-feedback",
"codex-git-utils",
"codex-hooks",
"codex-instructions",
"codex-login",
"codex-mcp",
"codex-model-provider-info",
"codex-models-manager",
"codex-network-proxy",
"codex-otel",
"codex-plugin",
"codex-protocol",
"codex-response-debug-context",
"codex-rmcp-client",
"codex-rollout",
"codex-sandboxing",
@@ -1918,6 +1906,7 @@ dependencies = [
"ctor 0.6.3",
"dirs",
"dunce",
"encoding_rs",
"env-flags",
"eventsource-stream",
"futures",
@@ -1926,6 +1915,7 @@ dependencies = [
"image",
"indexmap 2.13.0",
"insta",
"landlock",
"libc",
"maplit",
"notify",
@@ -1939,6 +1929,8 @@ dependencies = [
"regex-lite",
"reqwest",
"rmcp",
"schemars 0.8.22",
"seccompiler",
"serde",
"serde_json",
"serial_test",
@@ -2025,7 +2017,6 @@ dependencies = [
"codex-feedback",
"codex-git-utils",
"codex-login",
"codex-model-provider-info",
"codex-otel",
"codex-protocol",
"codex-utils-absolute-path",
@@ -2128,6 +2119,7 @@ dependencies = [
name = "codex-features"
version = "0.0.0"
dependencies = [
"codex-login",
"codex-otel",
"codex-protocol",
"pretty_assertions",
@@ -2142,7 +2134,6 @@ name = "codex-feedback"
version = "0.0.0"
dependencies = [
"anyhow",
"codex-login",
"codex-protocol",
"pretty_assertions",
"sentry",
@@ -2248,7 +2239,6 @@ name = "codex-lmstudio"
version = "0.0.0"
dependencies = [
"codex-core",
"codex-model-provider-info",
"reqwest",
"serde_json",
"tokio",
@@ -2265,13 +2255,10 @@ dependencies = [
"async-trait",
"base64 0.22.1",
"chrono",
"codex-api",
"codex-app-server-protocol",
"codex-client",
"codex-config",
"codex-keyring-store",
"codex-model-provider-info",
"codex-otel",
"codex-protocol",
"codex-terminal-detection",
"codex-utils-template",
@@ -2283,6 +2270,7 @@ dependencies = [
"rand 0.9.2",
"regex-lite",
"reqwest",
"schemars 0.8.22",
"serde",
"serde_json",
"serial_test",
@@ -2338,7 +2326,6 @@ dependencies = [
"codex-exec-server",
"codex-features",
"codex-login",
"codex-models-manager",
"codex-protocol",
"codex-shell-command",
"codex-utils-cli",
@@ -2359,54 +2346,6 @@ dependencies = [
"wiremock",
]
[[package]]
name = "codex-model-provider-info"
version = "0.0.0"
dependencies = [
"codex-api",
"codex-app-server-protocol",
"codex-protocol",
"codex-utils-absolute-path",
"http 1.4.0",
"maplit",
"pretty_assertions",
"schemars 0.8.22",
"serde",
"tempfile",
"toml 0.9.11+spec-1.1.0",
]
[[package]]
name = "codex-models-manager"
version = "0.0.0"
dependencies = [
"base64 0.22.1",
"chrono",
"codex-api",
"codex-app-server-protocol",
"codex-collaboration-mode-templates",
"codex-config",
"codex-feedback",
"codex-login",
"codex-model-provider-info",
"codex-otel",
"codex-protocol",
"codex-response-debug-context",
"codex-utils-absolute-path",
"codex-utils-output-truncation",
"codex-utils-template",
"core_test_support",
"http 1.4.0",
"pretty_assertions",
"serde",
"serde_json",
"tempfile",
"tokio",
"tracing",
"tracing-subscriber",
"wiremock",
]
[[package]]
name = "codex-network-proxy"
version = "0.0.0"
@@ -2446,7 +2385,6 @@ dependencies = [
"async-stream",
"bytes",
"codex-core",
"codex-model-provider-info",
"futures",
"pretty_assertions",
"reqwest",
@@ -2511,27 +2449,18 @@ name = "codex-protocol"
version = "0.0.0"
dependencies = [
"anyhow",
"chardetng",
"chrono",
"codex-async-utils",
"codex-execpolicy",
"codex-git-utils",
"codex-network-proxy",
"codex-utils-absolute-path",
"codex-utils-image",
"codex-utils-string",
"codex-utils-template",
"encoding_rs",
"http 1.4.0",
"icu_decimal",
"icu_locale_core",
"icu_provider",
"landlock",
"pretty_assertions",
"quick-xml",
"reqwest",
"schemars 0.8.22",
"seccompiler",
"serde",
"serde_json",
"serde_with",
@@ -2539,24 +2468,11 @@ dependencies = [
"strum_macros 0.28.0",
"sys-locale",
"tempfile",
"thiserror 2.0.18",
"tokio",
"tracing",
"ts-rs",
"uuid",
]
[[package]]
name = "codex-response-debug-context"
version = "0.0.0"
dependencies = [
"base64 0.22.1",
"codex-api",
"http 1.4.0",
"pretty_assertions",
"serde_json",
]
[[package]]
name = "codex-responses-api-proxy"
version = "0.0.0"
@@ -2566,7 +2482,6 @@ dependencies = [
"codex-process-hardening",
"ctor 0.6.3",
"libc",
"pretty_assertions",
"reqwest",
"serde",
"serde_json",
@@ -2581,7 +2496,6 @@ dependencies = [
"anyhow",
"axum",
"codex-client",
"codex-config",
"codex-keyring-store",
"codex-protocol",
"codex-utils-cargo-bin",
@@ -2593,6 +2507,7 @@ dependencies = [
"pretty_assertions",
"reqwest",
"rmcp",
"schemars 0.8.22",
"serde",
"serde_json",
"serial_test",
@@ -2799,15 +2714,12 @@ dependencies = [
"codex-cloud-requirements",
"codex-config",
"codex-core",
"codex-exec-server",
"codex-features",
"codex-feedback",
"codex-file-search",
"codex-git-utils",
"codex-login",
"codex-mcp",
"codex-model-provider-info",
"codex-models-manager",
"codex-otel",
"codex-protocol",
"codex-rollout",
@@ -2869,7 +2781,6 @@ dependencies = [
"unicode-segmentation",
"unicode-width 0.2.1",
"url",
"urlencoding",
"uuid",
"vt100",
"webbrowser",
@@ -2883,6 +2794,7 @@ name = "codex-utils-absolute-path"
version = "0.0.0"
dependencies = [
"dirs",
"path-absolutize",
"pretty_assertions",
"schemars 0.8.22",
"serde",
@@ -2971,7 +2883,6 @@ version = "0.0.0"
dependencies = [
"codex-core",
"codex-lmstudio",
"codex-model-provider-info",
"codex-ollama",
]
@@ -3043,7 +2954,6 @@ name = "codex-utils-sandbox-summary"
version = "0.0.0"
dependencies = [
"codex-core",
"codex-model-provider-info",
"codex-protocol",
"codex-utils-absolute-path",
"pretty_assertions",
@@ -3315,8 +3225,6 @@ dependencies = [
"codex-exec-server",
"codex-features",
"codex-login",
"codex-model-provider-info",
"codex-models-manager",
"codex-protocol",
"codex-utils-absolute-path",
"codex-utils-cargo-bin",
@@ -3971,7 +3879,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users 0.5.2",
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -4216,7 +4124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -5122,13 +5030,14 @@ dependencies = [
[[package]]
name = "hyper-util"
version = "0.1.20"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f"
dependencies = [
"base64 0.22.1",
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"http 1.4.0",
"http-body",
@@ -5137,7 +5046,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.5.10",
"socket2 0.6.2",
"system-configuration",
"tokio",
"tower-service",
@@ -5643,7 +5552,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -6421,7 +6330,7 @@ version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -6597,7 +6506,7 @@ version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d"
dependencies = [
"base64 0.21.7",
"base64 0.22.1",
"chrono",
"getrandom 0.2.17",
"http 1.4.0",
@@ -7065,7 +6974,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
dependencies = [
"libc",
"windows-sys 0.45.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -7611,7 +7520,7 @@ dependencies = [
"quinn-udp",
"rustc-hash 2.1.1",
"rustls",
"socket2 0.5.10",
"socket2 0.6.2",
"thiserror 2.0.18",
"tokio",
"tracing",
@@ -7648,9 +7557,9 @@ dependencies = [
"cfg_aliases 0.2.1",
"libc",
"once_cell",
"socket2 0.5.10",
"socket2 0.6.2",
"tracing",
"windows-sys 0.52.0",
"windows-sys 0.60.2",
]
[[package]]
@@ -8486,7 +8395,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.11.0",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -9885,9 +9794,9 @@ dependencies = [
[[package]]
name = "system-configuration"
version = "0.7.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.10.0",
"core-foundation 0.9.4",
@@ -9920,7 +9829,7 @@ dependencies = [
"getrandom 0.3.4",
"once_cell",
"rustix 1.1.3",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -11366,7 +11275,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.48.0",
"windows-sys 0.61.2",
]
[[package]]

View File

@@ -20,9 +20,9 @@ members = [
"cloud-tasks-client",
"cloud-tasks-mock-client",
"cli",
"collaboration-mode-templates",
"connectors",
"config",
"config-schema",
"shell-command",
"shell-escalation",
"skills",
@@ -42,8 +42,6 @@ members = [
"login",
"codex-mcp",
"mcp-server",
"model-provider-info",
"models-manager",
"network-proxy",
"ollama",
"process-hardening",
@@ -51,7 +49,6 @@ members = [
"rollout",
"rmcp-client",
"responses-api-proxy",
"response-debug-context",
"sandboxing",
"stdio-to-uds",
"otel",
@@ -91,7 +88,7 @@ members = [
resolver = "2"
[workspace.package]
version = "0.119.0-alpha.19"
version = "0.0.0"
# Track the edition for all workspace crates in one place. Individual
# crates can still override this value, but keeping it here means new
# crates created with `cargo new -w ...` automatically inherit the 2024
@@ -116,12 +113,12 @@ codex-backend-client = { path = "backend-client" }
codex-chatgpt = { path = "chatgpt" }
codex-cli = { path = "cli" }
codex-client = { path = "codex-client" }
codex-collaboration-mode-templates = { path = "collaboration-mode-templates" }
codex-cloud-requirements = { path = "cloud-requirements" }
codex-cloud-tasks-client = { path = "cloud-tasks-client" }
codex-cloud-tasks-mock-client = { path = "cloud-tasks-mock-client" }
codex-code-mode = { path = "code-mode" }
codex-config = { path = "config" }
codex-config-schema = { path = "config-schema" }
codex-connectors = { path = "connectors" }
codex-core = { path = "core" }
codex-core-skills = { path = "core-skills" }
@@ -141,8 +138,6 @@ codex-lmstudio = { path = "lmstudio" }
codex-login = { path = "login" }
codex-mcp = { path = "codex-mcp" }
codex-mcp-server = { path = "mcp-server" }
codex-model-provider-info = { path = "model-provider-info" }
codex-models-manager = { path = "models-manager" }
codex-network-proxy = { path = "network-proxy" }
codex-ollama = { path = "ollama" }
codex-otel = { path = "otel" }
@@ -150,7 +145,6 @@ codex-plugin = { path = "plugin" }
codex-process-hardening = { path = "process-hardening" }
codex-protocol = { path = "protocol" }
codex-responses-api-proxy = { path = "responses-api-proxy" }
codex-response-debug-context = { path = "response-debug-context" }
codex-rmcp-client = { path = "rmcp-client" }
codex-rollout = { path = "rollout" }
codex-sandboxing = { path = "sandboxing" }

View File

@@ -50,7 +50,8 @@ You can enable notifications by configuring a script that is run whenever the ag
### `codex exec` to run Codex programmatically/non-interactively
To run Codex non-interactively, run `codex exec PROMPT` (you can also pass the prompt via `stdin`) and Codex will work on your task until it decides that it is done and exits. If you provide both a prompt argument and piped stdin, Codex appends stdin as a `<stdin>` block after the prompt so patterns like `echo "my output" | codex exec "Summarize this concisely"` work naturally. Output is printed to the terminal directly. You can set the `RUST_LOG` environment variable to see more about what's going on.
To run Codex non-interactively, run `codex exec PROMPT` (you can also pass the prompt via `stdin`) and Codex will work on your task until it decides that it is done and exits. Output is printed to the terminal directly. You can set the `RUST_LOG` environment variable to see more about what's going on.
Use `codex exec --fork <SESSION_ID> PROMPT` to fork an existing session without launching the interactive picker/UI.
Use `codex exec --ephemeral ...` to run without persisting session rollout files to disk.
### Experimenting with the Codex Sandbox

View File

@@ -13,7 +13,6 @@ use crate::events::TrackEventRequest;
use crate::events::codex_app_metadata;
use crate::events::codex_plugin_metadata;
use crate::events::codex_plugin_used_metadata;
use crate::events::subagent_thread_started_event_request;
use crate::facts::AnalyticsFact;
use crate::facts::AppInvocation;
use crate::facts::AppMentionedInput;
@@ -25,7 +24,6 @@ use crate::facts::PluginStateChangedInput;
use crate::facts::PluginUsedInput;
use crate::facts::SkillInvocation;
use crate::facts::SkillInvokedInput;
use crate::facts::SubAgentThreadStartedInput;
use crate::facts::TrackEventsContext;
use crate::reducer::AnalyticsReducer;
use crate::reducer::normalize_path_for_skill_id;
@@ -49,7 +47,6 @@ use codex_plugin::AppConnectorId;
use codex_plugin::PluginCapabilitySummary;
use codex_plugin::PluginId;
use codex_plugin::PluginTelemetryMetadata;
use codex_protocol::protocol::SubAgentSource;
use pretty_assertions::assert_eq;
use serde_json::json;
use std::collections::HashSet;
@@ -61,7 +58,6 @@ use tokio::sync::mpsc;
fn sample_thread(thread_id: &str, ephemeral: bool) -> Thread {
Thread {
id: thread_id.to_string(),
forked_from_id: None,
preview: "first prompt".to_string(),
ephemeral,
model_provider: "openai".to_string(),
@@ -449,155 +445,6 @@ async fn initialize_caches_client_and_thread_lifecycle_publishes_once_initialize
assert_eq!(payload[0]["event_params"]["parent_thread_id"], json!(null));
}
#[test]
fn subagent_thread_started_review_serializes_expected_shape() {
let event = TrackEventRequest::ThreadInitialized(subagent_thread_started_event_request(
SubAgentThreadStartedInput {
thread_id: "thread-review".to_string(),
product_client_id: "codex-tui".to_string(),
client_name: "codex-tui".to_string(),
client_version: "1.0.0".to_string(),
model: "gpt-5".to_string(),
ephemeral: false,
subagent_source: SubAgentSource::Review,
created_at: 123,
},
));
let payload = serde_json::to_value(&event).expect("serialize review subagent event");
assert_eq!(payload["event_params"]["thread_source"], "subagent");
assert_eq!(
payload["event_params"]["app_server_client"]["product_client_id"],
"codex-tui"
);
assert_eq!(
payload["event_params"]["app_server_client"]["client_name"],
"codex-tui"
);
assert_eq!(
payload["event_params"]["app_server_client"]["client_version"],
"1.0.0"
);
assert_eq!(
payload["event_params"]["app_server_client"]["rpc_transport"],
"in_process"
);
assert_eq!(payload["event_params"]["created_at"], 123);
assert_eq!(payload["event_params"]["initialization_mode"], "new");
assert_eq!(payload["event_params"]["subagent_source"], "review");
assert_eq!(payload["event_params"]["parent_thread_id"], json!(null));
}
#[test]
fn subagent_thread_started_thread_spawn_serializes_parent_thread_id() {
let parent_thread_id =
codex_protocol::ThreadId::from_string("11111111-1111-1111-1111-111111111111")
.expect("valid thread id");
let event = TrackEventRequest::ThreadInitialized(subagent_thread_started_event_request(
SubAgentThreadStartedInput {
thread_id: "thread-spawn".to_string(),
product_client_id: "codex-tui".to_string(),
client_name: "codex-tui".to_string(),
client_version: "1.0.0".to_string(),
model: "gpt-5".to_string(),
ephemeral: true,
subagent_source: SubAgentSource::ThreadSpawn {
parent_thread_id,
depth: 1,
agent_path: None,
agent_nickname: None,
agent_role: None,
},
created_at: 124,
},
));
let payload = serde_json::to_value(&event).expect("serialize thread spawn subagent event");
assert_eq!(payload["event_params"]["thread_source"], "subagent");
assert_eq!(payload["event_params"]["subagent_source"], "thread_spawn");
assert_eq!(
payload["event_params"]["parent_thread_id"],
"11111111-1111-1111-1111-111111111111"
);
}
#[test]
fn subagent_thread_started_memory_consolidation_serializes_expected_shape() {
let event = TrackEventRequest::ThreadInitialized(subagent_thread_started_event_request(
SubAgentThreadStartedInput {
thread_id: "thread-memory".to_string(),
product_client_id: "codex-tui".to_string(),
client_name: "codex-tui".to_string(),
client_version: "1.0.0".to_string(),
model: "gpt-5".to_string(),
ephemeral: false,
subagent_source: SubAgentSource::MemoryConsolidation,
created_at: 125,
},
));
let payload =
serde_json::to_value(&event).expect("serialize memory consolidation subagent event");
assert_eq!(
payload["event_params"]["subagent_source"],
"memory_consolidation"
);
assert_eq!(payload["event_params"]["parent_thread_id"], json!(null));
}
#[test]
fn subagent_thread_started_other_serializes_expected_shape() {
let event = TrackEventRequest::ThreadInitialized(subagent_thread_started_event_request(
SubAgentThreadStartedInput {
thread_id: "thread-guardian".to_string(),
product_client_id: "codex-tui".to_string(),
client_name: "codex-tui".to_string(),
client_version: "1.0.0".to_string(),
model: "gpt-5".to_string(),
ephemeral: false,
subagent_source: SubAgentSource::Other("guardian".to_string()),
created_at: 126,
},
));
let payload = serde_json::to_value(&event).expect("serialize other subagent event");
assert_eq!(payload["event_params"]["subagent_source"], "guardian");
}
#[tokio::test]
async fn subagent_thread_started_publishes_without_initialize() {
let mut reducer = AnalyticsReducer::default();
let mut events = Vec::new();
reducer
.ingest(
AnalyticsFact::Custom(CustomAnalyticsFact::SubAgentThreadStarted(
SubAgentThreadStartedInput {
thread_id: "thread-review".to_string(),
product_client_id: "codex-tui".to_string(),
client_name: "codex-tui".to_string(),
client_version: "1.0.0".to_string(),
model: "gpt-5".to_string(),
ephemeral: false,
subagent_source: SubAgentSource::Review,
created_at: 127,
},
)),
&mut events,
)
.await;
let payload = serde_json::to_value(&events).expect("serialize events");
assert_eq!(payload.as_array().expect("events array").len(), 1);
assert_eq!(payload[0]["event_type"], "codex_thread_initialized");
assert_eq!(
payload[0]["event_params"]["app_server_client"]["product_client_id"],
"codex-tui"
);
assert_eq!(payload[0]["event_params"]["thread_source"], "subagent");
assert_eq!(payload[0]["event_params"]["subagent_source"], "review");
}
#[test]
fn plugin_used_event_serializes_expected_shape() {
let tracking = TrackEventsContext {

View File

@@ -11,7 +11,6 @@ use crate::facts::PluginState;
use crate::facts::PluginStateChangedInput;
use crate::facts::SkillInvocation;
use crate::facts::SkillInvokedInput;
use crate::facts::SubAgentThreadStartedInput;
use crate::facts::TrackEventsContext;
use crate::reducer::AnalyticsReducer;
use codex_app_server_protocol::ClientResponse;
@@ -145,12 +144,6 @@ impl AnalyticsEventsClient {
});
}
pub fn track_subagent_thread_started(&self, input: SubAgentThreadStartedInput) {
self.record_fact(AnalyticsFact::Custom(
CustomAnalyticsFact::SubAgentThreadStarted(input),
));
}
pub fn track_app_mentioned(&self, tracking: TrackEventsContext, mentions: Vec<AppInvocation>) {
if mentions.is_empty() {
return;

View File

@@ -1,12 +1,10 @@
use crate::facts::AppInvocation;
use crate::facts::InvocationType;
use crate::facts::PluginState;
use crate::facts::SubAgentThreadStartedInput;
use crate::facts::TrackEventsContext;
use codex_login::default_client::originator;
use codex_plugin::PluginTelemetryMetadata;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SubAgentSource;
use serde::Serialize;
#[derive(Clone, Copy, Debug, Serialize)]
@@ -230,49 +228,3 @@ pub(crate) fn current_runtime_metadata() -> CodexRuntimeMetadata {
runtime_arch: std::env::consts::ARCH.to_string(),
}
}
pub(crate) fn subagent_thread_started_event_request(
input: SubAgentThreadStartedInput,
) -> ThreadInitializedEvent {
let event_params = ThreadInitializedEventParams {
thread_id: input.thread_id,
app_server_client: CodexAppServerClientMetadata {
product_client_id: input.product_client_id,
client_name: Some(input.client_name),
client_version: Some(input.client_version),
rpc_transport: AppServerRpcTransport::InProcess,
experimental_api_enabled: None,
},
runtime: current_runtime_metadata(),
model: input.model,
ephemeral: input.ephemeral,
thread_source: Some("subagent"),
initialization_mode: ThreadInitializationMode::New,
subagent_source: Some(subagent_source_name(&input.subagent_source)),
parent_thread_id: subagent_parent_thread_id(&input.subagent_source),
created_at: input.created_at,
};
ThreadInitializedEvent {
event_type: "codex_thread_initialized",
event_params,
}
}
fn subagent_source_name(subagent_source: &SubAgentSource) -> String {
match subagent_source {
SubAgentSource::Review => "review".to_string(),
SubAgentSource::Compact => "compact".to_string(),
SubAgentSource::ThreadSpawn { .. } => "thread_spawn".to_string(),
SubAgentSource::MemoryConsolidation => "memory_consolidation".to_string(),
SubAgentSource::Other(other) => other.clone(),
}
}
fn subagent_parent_thread_id(subagent_source: &SubAgentSource) -> Option<String> {
match subagent_source {
SubAgentSource::ThreadSpawn {
parent_thread_id, ..
} => Some(parent_thread_id.to_string()),
_ => None,
}
}

View File

@@ -7,7 +7,6 @@ use codex_app_server_protocol::RequestId;
use codex_app_server_protocol::ServerNotification;
use codex_plugin::PluginTelemetryMetadata;
use codex_protocol::protocol::SkillScope;
use codex_protocol::protocol::SubAgentSource;
use serde::Serialize;
use std::path::PathBuf;
@@ -51,18 +50,6 @@ pub struct AppInvocation {
pub invocation_type: Option<InvocationType>,
}
#[derive(Clone)]
pub struct SubAgentThreadStartedInput {
pub thread_id: String,
pub product_client_id: String,
pub client_name: String,
pub client_version: String,
pub model: String,
pub ephemeral: bool,
pub subagent_source: SubAgentSource,
pub created_at: u64,
}
#[allow(dead_code)]
pub(crate) enum AnalyticsFact {
Initialize {
@@ -88,7 +75,6 @@ pub(crate) enum AnalyticsFact {
}
pub(crate) enum CustomAnalyticsFact {
SubAgentThreadStarted(SubAgentThreadStartedInput),
SkillInvoked(SkillInvokedInput),
AppMentioned(AppMentionedInput),
AppUsed(AppUsedInput),

View File

@@ -8,7 +8,6 @@ pub use events::AppServerRpcTransport;
pub use facts::AppInvocation;
pub use facts::InvocationType;
pub use facts::SkillInvocation;
pub use facts::SubAgentThreadStartedInput;
pub use facts::TrackEventsContext;
pub use facts::build_track_events_context;

View File

@@ -15,7 +15,6 @@ use crate::events::codex_app_metadata;
use crate::events::codex_plugin_metadata;
use crate::events::codex_plugin_used_metadata;
use crate::events::plugin_state_event_type;
use crate::events::subagent_thread_started_event_request;
use crate::events::thread_source_name;
use crate::facts::AnalyticsFact;
use crate::facts::AppMentionedInput;
@@ -25,7 +24,6 @@ use crate::facts::PluginState;
use crate::facts::PluginStateChangedInput;
use crate::facts::PluginUsedInput;
use crate::facts::SkillInvokedInput;
use crate::facts::SubAgentThreadStartedInput;
use codex_app_server_protocol::ClientResponse;
use codex_app_server_protocol::InitializeParams;
use codex_git_utils::collect_git_info;
@@ -78,9 +76,6 @@ impl AnalyticsReducer {
}
AnalyticsFact::Notification(_notification) => {}
AnalyticsFact::Custom(input) => match input {
CustomAnalyticsFact::SubAgentThreadStarted(input) => {
self.ingest_subagent_thread_started(input, out);
}
CustomAnalyticsFact::SkillInvoked(input) => {
self.ingest_skill_invoked(input, out).await;
}
@@ -125,16 +120,6 @@ impl AnalyticsReducer {
);
}
fn ingest_subagent_thread_started(
&mut self,
input: SubAgentThreadStartedInput,
out: &mut Vec<TrackEventRequest>,
) {
out.push(TrackEventRequest::ThreadInitialized(
subagent_thread_started_event_request(input),
));
}
async fn ingest_skill_invoked(
&mut self,
input: SkillInvokedInput,

View File

@@ -1060,9 +1060,6 @@ mod tests {
items: Vec::new(),
status: codex_app_server_protocol::TurnStatus::Completed,
error: None,
started_at: None,
completed_at: Some(0),
duration_ms: Some(1),
},
})
}
@@ -1837,9 +1834,6 @@ mod tests {
items: Vec::new(),
status: codex_app_server_protocol::TurnStatus::Completed,
error: None,
started_at: None,
completed_at: Some(0),
duration_ms: None,
},
}
)

View File

@@ -17,12 +17,12 @@ clap = { workspace = true, features = ["derive"] }
codex-experimental-api-macros = { workspace = true }
codex-git-utils = { workspace = true }
codex-protocol = { workspace = true }
codex-shell-command = { workspace = true }
codex-utils-absolute-path = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
serde_with = { workspace = true }
shlex = { workspace = true }
strum_macros = { workspace = true }
thiserror = { workspace = true }
rmcp = { workspace = true, default-features = false, features = [

View File

@@ -800,7 +800,7 @@
"description": "Stop filesystem watch notifications for a prior `fs/watch`.",
"properties": {
"watchId": {
"description": "Watch identifier previously provided to `fs/watch`.",
"description": "Watch identifier returned by `fs/watch`.",
"type": "string"
}
},
@@ -819,15 +819,10 @@
}
],
"description": "Absolute file or directory path to watch."
},
"watchId": {
"description": "Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`.",
"type": "string"
}
},
"required": [
"path",
"watchId"
"path"
],
"type": "object"
},
@@ -1047,17 +1042,6 @@
"null"
]
},
"detail": {
"anyOf": [
{
"$ref": "#/definitions/McpServerStatusDetail"
},
{
"type": "null"
}
],
"description": "Controls how much MCP inventory data to fetch for each server. Defaults to `Full` when omitted."
},
"limit": {
"description": "Optional page size; defaults to a server-defined value.",
"format": "uint32",
@@ -1224,25 +1208,6 @@
}
]
},
"McpResourceReadParams": {
"properties": {
"server": {
"type": "string"
},
"threadId": {
"type": "string"
},
"uri": {
"type": "string"
}
},
"required": [
"server",
"threadId",
"uri"
],
"type": "object"
},
"McpServerOauthLoginParams": {
"properties": {
"name": {
@@ -1270,13 +1235,6 @@
],
"type": "object"
},
"McpServerStatusDetail": {
"enum": [
"full",
"toolsAndAuthOnly"
],
"type": "string"
},
"MergeStrategy": {
"enum": [
"replace",
@@ -2661,6 +2619,17 @@
],
"type": "object"
},
"ThreadInputActivityParams": {
"properties": {
"threadId": {
"type": "string"
}
},
"required": [
"threadId"
],
"type": "object"
},
"ThreadListParams": {
"properties": {
"archived": {
@@ -2857,48 +2826,6 @@
],
"type": "object"
},
"ThreadRealtimeStartTransport": {
"description": "EXPERIMENTAL - transport used by thread realtime.",
"oneOf": [
{
"properties": {
"type": {
"enum": [
"websocket"
],
"title": "WebsocketThreadRealtimeStartTransportType",
"type": "string"
}
},
"required": [
"type"
],
"title": "WebsocketThreadRealtimeStartTransport",
"type": "object"
},
{
"properties": {
"sdp": {
"description": "SDP offer generated by a WebRTC RTCPeerConnection after configuring audio and the realtime events data channel.",
"type": "string"
},
"type": {
"enum": [
"webrtc"
],
"title": "WebrtcThreadRealtimeStartTransportType",
"type": "string"
}
},
"required": [
"sdp",
"type"
],
"title": "WebrtcThreadRealtimeStartTransport",
"type": "object"
}
]
},
"ThreadResumeParams": {
"description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.",
"properties": {
@@ -3785,6 +3712,30 @@
"title": "Thread/shellCommandRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/inputActivity"
],
"title": "Thread/inputActivityRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadInputActivityParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/inputActivityRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -4504,30 +4455,6 @@
"title": "McpServerStatus/listRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"mcpServer/resource/read"
],
"title": "McpServer/resource/readRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/McpResourceReadParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "McpServer/resource/readRequest",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1013,7 +1013,7 @@
"type": "array"
},
"watchId": {
"description": "Watch identifier previously provided to `fs/watch`.",
"description": "Watch identifier returned by `fs/watch`.",
"type": "string"
}
},
@@ -1736,7 +1736,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -2426,13 +2425,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -3304,22 +3296,6 @@
],
"type": "object"
},
"ThreadRealtimeSdpNotification": {
"description": "EXPERIMENTAL - emitted with the remote SDP for a WebRTC realtime session.",
"properties": {
"sdp": {
"type": "string"
},
"threadId": {
"type": "string"
}
},
"required": [
"sdp",
"threadId"
],
"type": "object"
},
"ThreadRealtimeStartedNotification": {
"description": "EXPERIMENTAL - emitted when thread realtime startup is accepted.",
"properties": {
@@ -3549,22 +3525,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -3586,14 +3546,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}
@@ -4943,26 +4895,6 @@
"title": "Thread/realtime/outputAudio/deltaNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"thread/realtime/sdp"
],
"title": "Thread/realtime/sdpNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeSdpNotification"
}
},
"required": [
"method",
"params"
],
"title": "Thread/realtime/sdpNotification",
"type": "object"
},
{
"properties": {
"method": {

View File

@@ -482,6 +482,30 @@
"title": "Thread/shellCommandRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"thread/inputActivity"
],
"title": "Thread/inputActivityRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/ThreadInputActivityParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/inputActivityRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1201,30 +1225,6 @@
"title": "McpServerStatus/listRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"mcpServer/resource/read"
],
"title": "McpServer/resource/readRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/McpResourceReadParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "McpServer/resource/readRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -4335,26 +4335,6 @@
"title": "Thread/realtime/outputAudio/deltaNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"thread/realtime/sdp"
],
"title": "Thread/realtime/sdpNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/ThreadRealtimeSdpNotification"
}
},
"required": [
"method",
"params"
],
"title": "Thread/realtime/sdpNotification",
"type": "object"
},
{
"properties": {
"method": {
@@ -7531,7 +7511,7 @@
"type": "array"
},
"watchId": {
"description": "Watch identifier previously provided to `fs/watch`.",
"description": "Watch identifier returned by `fs/watch`.",
"type": "string"
}
},
@@ -7801,7 +7781,7 @@
"description": "Stop filesystem watch notifications for a prior `fs/watch`.",
"properties": {
"watchId": {
"description": "Watch identifier previously provided to `fs/watch`.",
"description": "Watch identifier returned by `fs/watch`.",
"type": "string"
}
},
@@ -7828,6 +7808,25 @@
}
],
"description": "Absolute file or directory path to watch."
}
},
"required": [
"path"
],
"title": "FsWatchParams",
"type": "object"
},
"FsWatchResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Created watch handle returned by `fs/watch`.",
"properties": {
"path": {
"allOf": [
{
"$ref": "#/definitions/v2/AbsolutePathBuf"
}
],
"description": "Canonicalized path associated with the watch."
},
"watchId": {
"description": "Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`.",
@@ -7838,25 +7837,6 @@
"path",
"watchId"
],
"title": "FsWatchParams",
"type": "object"
},
"FsWatchResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Successful response for `fs/watch`.",
"properties": {
"path": {
"allOf": [
{
"$ref": "#/definitions/v2/AbsolutePathBuf"
}
],
"description": "Canonicalized path associated with the watch."
}
},
"required": [
"path"
],
"title": "FsWatchResponse",
"type": "object"
},
@@ -8648,17 +8628,6 @@
"null"
]
},
"detail": {
"anyOf": [
{
"$ref": "#/definitions/v2/McpServerStatusDetail"
},
{
"type": "null"
}
],
"description": "Controls how much MCP inventory data to fetch for each server. Defaults to `Full` when omitted."
},
"limit": {
"description": "Optional page size; defaults to a server-defined value.",
"format": "uint32",
@@ -8984,43 +8953,6 @@
],
"type": "string"
},
"McpResourceReadParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"server": {
"type": "string"
},
"threadId": {
"type": "string"
},
"uri": {
"type": "string"
}
},
"required": [
"server",
"threadId",
"uri"
],
"title": "McpResourceReadParams",
"type": "object"
},
"McpResourceReadResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"contents": {
"items": {
"$ref": "#/definitions/v2/ResourceContent"
},
"type": "array"
}
},
"required": [
"contents"
],
"title": "McpResourceReadResponse",
"type": "object"
},
"McpServerOauthLoginCompletedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -9136,13 +9068,6 @@
],
"type": "object"
},
"McpServerStatusDetail": {
"enum": [
"full",
"toolsAndAuthOnly"
],
"type": "string"
},
"McpServerStatusUpdatedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -9204,7 +9129,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -9308,13 +9232,6 @@
},
"Model": {
"properties": {
"additionalSpeedTiers": {
"default": [],
"items": {
"type": "string"
},
"type": "array"
},
"availabilityNux": {
"anyOf": [
{
@@ -9580,12 +9497,6 @@
"null"
]
},
"dangerFullAccessDenylistOnly": {
"type": [
"boolean",
"null"
]
},
"dangerouslyAllowAllUnixSockets": {
"type": [
"boolean",
@@ -10756,57 +10667,6 @@
],
"type": "object"
},
"ResourceContent": {
"anyOf": [
{
"properties": {
"_meta": true,
"mimeType": {
"type": [
"string",
"null"
]
},
"text": {
"type": "string"
},
"uri": {
"description": "The URI of this resource.",
"type": "string"
}
},
"required": [
"text",
"uri"
],
"type": "object"
},
{
"properties": {
"_meta": true,
"blob": {
"type": "string"
},
"mimeType": {
"type": [
"string",
"null"
]
},
"uri": {
"description": "The URI of this resource.",
"type": "string"
}
},
"required": [
"blob",
"uri"
],
"type": "object"
}
],
"description": "Contents returned when reading a resource from an MCP server."
},
"ResourceTemplate": {
"description": "A template description for resources available on the server.",
"properties": {
@@ -12350,13 +12210,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -12674,6 +12527,24 @@
"ThreadId": {
"type": "string"
},
"ThreadInputActivityParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"threadId": {
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadInputActivityParams",
"type": "object"
},
"ThreadInputActivityResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ThreadInputActivityResponse",
"type": "object"
},
"ThreadItem": {
"oneOf": [
{
@@ -13682,66 +13553,6 @@
"title": "ThreadRealtimeOutputAudioDeltaNotification",
"type": "object"
},
"ThreadRealtimeSdpNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - emitted with the remote SDP for a WebRTC realtime session.",
"properties": {
"sdp": {
"type": "string"
},
"threadId": {
"type": "string"
}
},
"required": [
"sdp",
"threadId"
],
"title": "ThreadRealtimeSdpNotification",
"type": "object"
},
"ThreadRealtimeStartTransport": {
"description": "EXPERIMENTAL - transport used by thread realtime.",
"oneOf": [
{
"properties": {
"type": {
"enum": [
"websocket"
],
"title": "WebsocketThreadRealtimeStartTransportType",
"type": "string"
}
},
"required": [
"type"
],
"title": "WebsocketThreadRealtimeStartTransport",
"type": "object"
},
{
"properties": {
"sdp": {
"description": "SDP offer generated by a WebRTC RTCPeerConnection after configuring audio and the realtime events data channel.",
"type": "string"
},
"type": {
"enum": [
"webrtc"
],
"title": "WebrtcThreadRealtimeStartTransportType",
"type": "string"
}
},
"required": [
"sdp",
"type"
],
"title": "WebrtcThreadRealtimeStartTransport",
"type": "object"
}
]
},
"ThreadRealtimeStartedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - emitted when thread realtime startup is accepted.",
@@ -14553,22 +14364,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -14590,14 +14385,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/v2/TurnStatus"
}

View File

@@ -1057,6 +1057,30 @@
"title": "Thread/shellCommandRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/inputActivity"
],
"title": "Thread/inputActivityRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadInputActivityParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/inputActivityRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1776,30 +1800,6 @@
"title": "McpServerStatus/listRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"mcpServer/resource/read"
],
"title": "McpServer/resource/readRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/McpResourceReadParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "McpServer/resource/readRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -4179,7 +4179,7 @@
"type": "array"
},
"watchId": {
"description": "Watch identifier previously provided to `fs/watch`.",
"description": "Watch identifier returned by `fs/watch`.",
"type": "string"
}
},
@@ -4449,7 +4449,7 @@
"description": "Stop filesystem watch notifications for a prior `fs/watch`.",
"properties": {
"watchId": {
"description": "Watch identifier previously provided to `fs/watch`.",
"description": "Watch identifier returned by `fs/watch`.",
"type": "string"
}
},
@@ -4476,6 +4476,25 @@
}
],
"description": "Absolute file or directory path to watch."
}
},
"required": [
"path"
],
"title": "FsWatchParams",
"type": "object"
},
"FsWatchResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Created watch handle returned by `fs/watch`.",
"properties": {
"path": {
"allOf": [
{
"$ref": "#/definitions/AbsolutePathBuf"
}
],
"description": "Canonicalized path associated with the watch."
},
"watchId": {
"description": "Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`.",
@@ -4486,25 +4505,6 @@
"path",
"watchId"
],
"title": "FsWatchParams",
"type": "object"
},
"FsWatchResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Successful response for `fs/watch`.",
"properties": {
"path": {
"allOf": [
{
"$ref": "#/definitions/AbsolutePathBuf"
}
],
"description": "Canonicalized path associated with the watch."
}
},
"required": [
"path"
],
"title": "FsWatchResponse",
"type": "object"
},
@@ -5451,17 +5451,6 @@
"null"
]
},
"detail": {
"anyOf": [
{
"$ref": "#/definitions/McpServerStatusDetail"
},
{
"type": "null"
}
],
"description": "Controls how much MCP inventory data to fetch for each server. Defaults to `Full` when omitted."
},
"limit": {
"description": "Optional page size; defaults to a server-defined value.",
"format": "uint32",
@@ -5787,43 +5776,6 @@
],
"type": "string"
},
"McpResourceReadParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"server": {
"type": "string"
},
"threadId": {
"type": "string"
},
"uri": {
"type": "string"
}
},
"required": [
"server",
"threadId",
"uri"
],
"title": "McpResourceReadParams",
"type": "object"
},
"McpResourceReadResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"contents": {
"items": {
"$ref": "#/definitions/ResourceContent"
},
"type": "array"
}
},
"required": [
"contents"
],
"title": "McpResourceReadResponse",
"type": "object"
},
"McpServerOauthLoginCompletedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -5939,13 +5891,6 @@
],
"type": "object"
},
"McpServerStatusDetail": {
"enum": [
"full",
"toolsAndAuthOnly"
],
"type": "string"
},
"McpServerStatusUpdatedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -6007,7 +5952,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -6111,13 +6055,6 @@
},
"Model": {
"properties": {
"additionalSpeedTiers": {
"default": [],
"items": {
"type": "string"
},
"type": "array"
},
"availabilityNux": {
"anyOf": [
{
@@ -6383,12 +6320,6 @@
"null"
]
},
"dangerFullAccessDenylistOnly": {
"type": [
"boolean",
"null"
]
},
"dangerouslyAllowAllUnixSockets": {
"type": [
"boolean",
@@ -7559,57 +7490,6 @@
],
"type": "object"
},
"ResourceContent": {
"anyOf": [
{
"properties": {
"_meta": true,
"mimeType": {
"type": [
"string",
"null"
]
},
"text": {
"type": "string"
},
"uri": {
"description": "The URI of this resource.",
"type": "string"
}
},
"required": [
"text",
"uri"
],
"type": "object"
},
{
"properties": {
"_meta": true,
"blob": {
"type": "string"
},
"mimeType": {
"type": [
"string",
"null"
]
},
"uri": {
"description": "The URI of this resource.",
"type": "string"
}
},
"required": [
"blob",
"uri"
],
"type": "object"
}
],
"description": "Contents returned when reading a resource from an MCP server."
},
"ResourceTemplate": {
"description": "A template description for resources available on the server.",
"properties": {
@@ -9443,26 +9323,6 @@
"title": "Thread/realtime/outputAudio/deltaNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"thread/realtime/sdp"
],
"title": "Thread/realtime/sdpNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeSdpNotification"
}
},
"required": [
"method",
"params"
],
"title": "Thread/realtime/sdpNotification",
"type": "object"
},
{
"properties": {
"method": {
@@ -10205,13 +10065,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -10529,6 +10382,24 @@
"ThreadId": {
"type": "string"
},
"ThreadInputActivityParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"threadId": {
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadInputActivityParams",
"type": "object"
},
"ThreadInputActivityResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ThreadInputActivityResponse",
"type": "object"
},
"ThreadItem": {
"oneOf": [
{
@@ -11537,66 +11408,6 @@
"title": "ThreadRealtimeOutputAudioDeltaNotification",
"type": "object"
},
"ThreadRealtimeSdpNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - emitted with the remote SDP for a WebRTC realtime session.",
"properties": {
"sdp": {
"type": "string"
},
"threadId": {
"type": "string"
}
},
"required": [
"sdp",
"threadId"
],
"title": "ThreadRealtimeSdpNotification",
"type": "object"
},
"ThreadRealtimeStartTransport": {
"description": "EXPERIMENTAL - transport used by thread realtime.",
"oneOf": [
{
"properties": {
"type": {
"enum": [
"websocket"
],
"title": "WebsocketThreadRealtimeStartTransportType",
"type": "string"
}
},
"required": [
"type"
],
"title": "WebsocketThreadRealtimeStartTransport",
"type": "object"
},
{
"properties": {
"sdp": {
"description": "SDP offer generated by a WebRTC RTCPeerConnection after configuring audio and the realtime events data channel.",
"type": "string"
},
"type": {
"enum": [
"webrtc"
],
"title": "WebrtcThreadRealtimeStartTransportType",
"type": "string"
}
},
"required": [
"sdp",
"type"
],
"title": "WebrtcThreadRealtimeStartTransport",
"type": "object"
}
]
},
"ThreadRealtimeStartedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - emitted when thread realtime startup is accepted.",
@@ -12408,22 +12219,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -12445,14 +12240,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -1,14 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"ApprovalsReviewer": {
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
"enum": [
"user",
"guardian_subagent"
],
"type": "string"
},
"AskForApproval": {
"oneOf": [
{
@@ -151,12 +143,6 @@
"null"
]
},
"dangerFullAccessDenylistOnly": {
"type": [
"boolean",
"null"
]
},
"dangerouslyAllowAllUnixSockets": {
"type": [
"boolean",

View File

@@ -16,7 +16,7 @@
"type": "array"
},
"watchId": {
"description": "Watch identifier previously provided to `fs/watch`.",
"description": "Watch identifier returned by `fs/watch`.",
"type": "string"
}
},

View File

@@ -3,7 +3,7 @@
"description": "Stop filesystem watch notifications for a prior `fs/watch`.",
"properties": {
"watchId": {
"description": "Watch identifier previously provided to `fs/watch`.",
"description": "Watch identifier returned by `fs/watch`.",
"type": "string"
}
},

View File

@@ -15,15 +15,10 @@
}
],
"description": "Absolute file or directory path to watch."
},
"watchId": {
"description": "Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`.",
"type": "string"
}
},
"required": [
"path",
"watchId"
"path"
],
"title": "FsWatchParams",
"type": "object"

View File

@@ -6,7 +6,7 @@
"type": "string"
}
},
"description": "Successful response for `fs/watch`.",
"description": "Created watch handle returned by `fs/watch`.",
"properties": {
"path": {
"allOf": [
@@ -15,10 +15,15 @@
}
],
"description": "Canonicalized path associated with the watch."
},
"watchId": {
"description": "Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`.",
"type": "string"
}
},
"required": [
"path"
"path",
"watchId"
],
"title": "FsWatchResponse",
"type": "object"

View File

@@ -294,7 +294,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"

View File

@@ -294,7 +294,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"

View File

@@ -1,14 +1,5 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"McpServerStatusDetail": {
"enum": [
"full",
"toolsAndAuthOnly"
],
"type": "string"
}
},
"properties": {
"cursor": {
"description": "Opaque pagination cursor returned by a previous call.",
@@ -17,17 +8,6 @@
"null"
]
},
"detail": {
"anyOf": [
{
"$ref": "#/definitions/McpServerStatusDetail"
},
{
"type": "null"
}
],
"description": "Controls how much MCP inventory data to fetch for each server. Defaults to `Full` when omitted."
},
"limit": {
"description": "Optional page size; defaults to a server-defined value.",
"format": "uint32",

View File

@@ -1,69 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"ResourceContent": {
"anyOf": [
{
"properties": {
"_meta": true,
"mimeType": {
"type": [
"string",
"null"
]
},
"text": {
"type": "string"
},
"uri": {
"description": "The URI of this resource.",
"type": "string"
}
},
"required": [
"text",
"uri"
],
"type": "object"
},
{
"properties": {
"_meta": true,
"blob": {
"type": "string"
},
"mimeType": {
"type": [
"string",
"null"
]
},
"uri": {
"description": "The URI of this resource.",
"type": "string"
}
},
"required": [
"blob",
"uri"
],
"type": "object"
}
],
"description": "Contents returned when reading a resource from an MCP server."
}
},
"properties": {
"contents": {
"items": {
"$ref": "#/definitions/ResourceContent"
},
"type": "array"
}
},
"required": [
"contents"
],
"title": "McpResourceReadResponse",
"type": "object"
}

View File

@@ -22,13 +22,6 @@
},
"Model": {
"properties": {
"additionalSpeedTiers": {
"default": [],
"items": {
"type": "string"
},
"type": "array"
},
"availabilityNux": {
"anyOf": [
{

View File

@@ -430,7 +430,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -1268,22 +1267,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1305,14 +1288,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -518,7 +518,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -1043,13 +1042,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -1857,22 +1849,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1894,14 +1870,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -1,21 +1,13 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"server": {
"type": "string"
},
"threadId": {
"type": "string"
},
"uri": {
"type": "string"
}
},
"required": [
"server",
"threadId",
"uri"
"threadId"
],
"title": "McpResourceReadParams",
"title": "ThreadInputActivityParams",
"type": "object"
}

View File

@@ -0,0 +1,5 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ThreadInputActivityResponse",
"type": "object"
}

View File

@@ -456,7 +456,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -801,13 +800,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -1615,22 +1607,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1652,14 +1628,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -456,7 +456,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -801,13 +800,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -1615,22 +1607,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1652,14 +1628,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -456,7 +456,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -801,13 +800,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -1615,22 +1607,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1652,14 +1628,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -1,18 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - emitted with the remote SDP for a WebRTC realtime session.",
"properties": {
"sdp": {
"type": "string"
},
"threadId": {
"type": "string"
}
},
"required": [
"sdp",
"threadId"
],
"title": "ThreadRealtimeSdpNotification",
"type": "object"
}

View File

@@ -518,7 +518,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -1043,13 +1042,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -1857,22 +1849,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1894,14 +1870,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -456,7 +456,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -801,13 +800,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -1615,22 +1607,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1652,14 +1628,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -518,7 +518,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -1043,13 +1042,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -1857,22 +1849,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1894,14 +1870,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -456,7 +456,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -801,13 +800,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -1615,22 +1607,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1652,14 +1628,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -456,7 +456,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -801,13 +800,6 @@
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
"type": "boolean"
},
"forkedFromId": {
"description": "Source thread id when this thread was created by forking another thread.",
"type": [
"string",
"null"
]
},
"gitInfo": {
"anyOf": [
{
@@ -1615,22 +1607,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1652,14 +1628,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -430,7 +430,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -1268,22 +1267,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1305,14 +1288,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -430,7 +430,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -1268,22 +1267,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1305,14 +1288,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

View File

@@ -430,7 +430,6 @@
},
"McpToolCallResult": {
"properties": {
"_meta": true,
"content": {
"items": true,
"type": "array"
@@ -1268,22 +1267,6 @@
},
"Turn": {
"properties": {
"completedAt": {
"description": "Unix timestamp (in seconds) when the turn completed.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"durationMs": {
"description": "Duration between turn start and completion in milliseconds, if known.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"error": {
"anyOf": [
{
@@ -1305,14 +1288,6 @@
},
"type": "array"
},
"startedAt": {
"description": "Unix timestamp (in seconds) when the turn started.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"status": {
"$ref": "#/definitions/TurnStatus"
}

File diff suppressed because one or more lines are too long

View File

@@ -1,17 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { JsonValue } from "./serde_json/JsonValue";
/**
* Contents returned when reading a resource from an MCP server.
*/
export type ResourceContent = {
/**
* The URI of this resource.
*/
uri: string, mimeType?: string, text: string, _meta?: JsonValue, } | {
/**
* The URI of this resource.
*/
uri: string, mimeType?: string, blob: string, _meta?: JsonValue, };

View File

@@ -41,7 +41,6 @@ import type { ThreadRealtimeClosedNotification } from "./v2/ThreadRealtimeClosed
import type { ThreadRealtimeErrorNotification } from "./v2/ThreadRealtimeErrorNotification";
import type { ThreadRealtimeItemAddedNotification } from "./v2/ThreadRealtimeItemAddedNotification";
import type { ThreadRealtimeOutputAudioDeltaNotification } from "./v2/ThreadRealtimeOutputAudioDeltaNotification";
import type { ThreadRealtimeSdpNotification } from "./v2/ThreadRealtimeSdpNotification";
import type { ThreadRealtimeStartedNotification } from "./v2/ThreadRealtimeStartedNotification";
import type { ThreadRealtimeTranscriptUpdatedNotification } from "./v2/ThreadRealtimeTranscriptUpdatedNotification";
import type { ThreadStartedNotification } from "./v2/ThreadStartedNotification";
@@ -58,4 +57,4 @@ import type { WindowsWorldWritableWarningNotification } from "./v2/WindowsWorldW
/**
* Notification sent from the server to the client.
*/
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "hook/started", "params": HookStartedNotification } | { "method": "turn/completed", "params": TurnCompletedNotification } | { "method": "hook/completed", "params": HookCompletedNotification } | { "method": "turn/diff/updated", "params": TurnDiffUpdatedNotification } | { "method": "turn/plan/updated", "params": TurnPlanUpdatedNotification } | { "method": "item/started", "params": ItemStartedNotification } | { "method": "item/autoApprovalReview/started", "params": ItemGuardianApprovalReviewStartedNotification } | { "method": "item/autoApprovalReview/completed", "params": ItemGuardianApprovalReviewCompletedNotification } | { "method": "item/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "command/exec/outputDelta", "params": CommandExecOutputDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "mcpServer/startupStatus/updated", "params": McpServerStatusUpdatedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "fs/changed", "params": FsChangedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/transcriptUpdated", "params": ThreadRealtimeTranscriptUpdatedNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/sdp", "params": ThreadRealtimeSdpNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "hook/started", "params": HookStartedNotification } | { "method": "turn/completed", "params": TurnCompletedNotification } | { "method": "hook/completed", "params": HookCompletedNotification } | { "method": "turn/diff/updated", "params": TurnDiffUpdatedNotification } | { "method": "turn/plan/updated", "params": TurnPlanUpdatedNotification } | { "method": "item/started", "params": ItemStartedNotification } | { "method": "item/autoApprovalReview/started", "params": ItemGuardianApprovalReviewStartedNotification } | { "method": "item/autoApprovalReview/completed", "params": ItemGuardianApprovalReviewCompletedNotification } | { "method": "item/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "command/exec/outputDelta", "params": CommandExecOutputDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "mcpServer/startupStatus/updated", "params": McpServerStatusUpdatedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "fs/changed", "params": FsChangedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/transcriptUpdated", "params": ThreadRealtimeTranscriptUpdatedNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };

View File

@@ -55,7 +55,6 @@ export type { ReasoningItemReasoningSummary } from "./ReasoningItemReasoningSumm
export type { ReasoningSummary } from "./ReasoningSummary";
export type { RequestId } from "./RequestId";
export type { Resource } from "./Resource";
export type { ResourceContent } from "./ResourceContent";
export type { ResourceTemplate } from "./ResourceTemplate";
export type { ResponseItem } from "./ResponseItem";
export type { ReviewDecision } from "./ReviewDecision";

View File

@@ -8,7 +8,7 @@ import type { AbsolutePathBuf } from "../AbsolutePathBuf";
*/
export type FsChangedNotification = {
/**
* Watch identifier previously provided to `fs/watch`.
* Watch identifier returned by `fs/watch`.
*/
watchId: string,
/**

View File

@@ -7,6 +7,6 @@
*/
export type FsUnwatchParams = {
/**
* Watch identifier previously provided to `fs/watch`.
* Watch identifier returned by `fs/watch`.
*/
watchId: string, };

View File

@@ -7,10 +7,6 @@ import type { AbsolutePathBuf } from "../AbsolutePathBuf";
* Start filesystem watch notifications for an absolute path.
*/
export type FsWatchParams = {
/**
* Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`.
*/
watchId: string,
/**
* Absolute file or directory path to watch.
*/

View File

@@ -4,9 +4,13 @@
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
/**
* Successful response for `fs/watch`.
* Created watch handle returned by `fs/watch`.
*/
export type FsWatchResponse = {
/**
* Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`.
*/
watchId: string,
/**
* Canonicalized path associated with the watch.
*/

View File

@@ -1,7 +1,6 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { McpServerStatusDetail } from "./McpServerStatusDetail";
export type ListMcpServerStatusParams = {
/**
@@ -11,9 +10,4 @@ cursor?: string | null,
/**
* Optional page size; defaults to a server-defined value.
*/
limit?: number | null,
/**
* Controls how much MCP inventory data to fetch for each server.
* Defaults to `Full` when omitted.
*/
detail?: McpServerStatusDetail | null, };
limit?: number | null, };

View File

@@ -1,6 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ResourceContent } from "../ResourceContent";
export type McpResourceReadResponse = { contents: Array<ResourceContent>, };

View File

@@ -3,4 +3,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { JsonValue } from "../serde_json/JsonValue";
export type McpToolCallResult = { content: Array<JsonValue>, structuredContent: JsonValue | null, _meta: JsonValue | null, };
export type McpToolCallResult = { content: Array<JsonValue>, structuredContent: JsonValue | null, };

View File

@@ -7,4 +7,4 @@ import type { ModelAvailabilityNux } from "./ModelAvailabilityNux";
import type { ModelUpgradeInfo } from "./ModelUpgradeInfo";
import type { ReasoningEffortOption } from "./ReasoningEffortOption";
export type Model = { id: string, model: string, upgrade: string | null, upgradeInfo: ModelUpgradeInfo | null, availabilityNux: ModelAvailabilityNux | null, displayName: string, description: string, hidden: boolean, supportedReasoningEfforts: Array<ReasoningEffortOption>, defaultReasoningEffort: ReasoningEffort, inputModalities: Array<InputModality>, supportsPersonality: boolean, additionalSpeedTiers: Array<string>, isDefault: boolean, };
export type Model = { id: string, model: string, upgrade: string | null, upgradeInfo: ModelUpgradeInfo | null, availabilityNux: ModelAvailabilityNux | null, displayName: string, description: string, hidden: boolean, supportedReasoningEfforts: Array<ReasoningEffortOption>, defaultReasoningEffort: ReasoningEffort, inputModalities: Array<InputModality>, supportsPersonality: boolean, isDefault: boolean, };

View File

@@ -29,4 +29,4 @@ unixSockets: { [key in string]?: NetworkUnixSocketPermission } | null,
/**
* Legacy compatibility view derived from `unix_sockets`.
*/
allowUnixSockets: Array<string> | null, allowLocalBinding: boolean | null, dangerFullAccessDenylistOnly: boolean | null, };
allowUnixSockets: Array<string> | null, allowLocalBinding: boolean | null, };

View File

@@ -7,10 +7,6 @@ import type { ThreadStatus } from "./ThreadStatus";
import type { Turn } from "./Turn";
export type Thread = { id: string,
/**
* Source thread id when this thread was created by forking another thread.
*/
forkedFromId: string | null,
/**
* Usually the first user message in the thread, if available.
*/

View File

@@ -2,4 +2,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type McpResourceReadParams = { threadId: string, server: string, uri: string, };
export type ThreadInputActivityParams = { threadId: string, };

View File

@@ -2,4 +2,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type McpServerStatusDetail = "full" | "toolsAndAuthOnly";
export type ThreadInputActivityResponse = Record<string, never>;

View File

@@ -1,8 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* EXPERIMENTAL - emitted with the remote SDP for a WebRTC realtime session.
*/
export type ThreadRealtimeSdpNotification = { threadId: string, sdp: string, };

View File

@@ -1,13 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* EXPERIMENTAL - transport used by thread realtime.
*/
export type ThreadRealtimeStartTransport = { "type": "websocket" } | { "type": "webrtc",
/**
* SDP offer generated by a WebRTC RTCPeerConnection after configuring audio and the
* realtime events data channel.
*/
sdp: string, };

View File

@@ -15,16 +15,4 @@ items: Array<ThreadItem>, status: TurnStatus,
/**
* Only populated when the Turn's status is failed.
*/
error: TurnError | null,
/**
* Unix timestamp (in seconds) when the turn started.
*/
startedAt: number | null,
/**
* Unix timestamp (in seconds) when the turn completed.
*/
completedAt: number | null,
/**
* Duration between turn start and completion in milliseconds, if known.
*/
durationMs: number | null, };
error: TurnError | null, };

View File

@@ -172,8 +172,6 @@ export type { McpElicitationTitledSingleSelectEnumSchema } from "./McpElicitatio
export type { McpElicitationUntitledEnumItems } from "./McpElicitationUntitledEnumItems";
export type { McpElicitationUntitledMultiSelectEnumSchema } from "./McpElicitationUntitledMultiSelectEnumSchema";
export type { McpElicitationUntitledSingleSelectEnumSchema } from "./McpElicitationUntitledSingleSelectEnumSchema";
export type { McpResourceReadParams } from "./McpResourceReadParams";
export type { McpResourceReadResponse } from "./McpResourceReadResponse";
export type { McpServerElicitationAction } from "./McpServerElicitationAction";
export type { McpServerElicitationRequestParams } from "./McpServerElicitationRequestParams";
export type { McpServerElicitationRequestResponse } from "./McpServerElicitationRequestResponse";
@@ -183,7 +181,6 @@ export type { McpServerOauthLoginResponse } from "./McpServerOauthLoginResponse"
export type { McpServerRefreshResponse } from "./McpServerRefreshResponse";
export type { McpServerStartupState } from "./McpServerStartupState";
export type { McpServerStatus } from "./McpServerStatus";
export type { McpServerStatusDetail } from "./McpServerStatusDetail";
export type { McpServerStatusUpdatedNotification } from "./McpServerStatusUpdatedNotification";
export type { McpToolCallError } from "./McpToolCallError";
export type { McpToolCallProgressNotification } from "./McpToolCallProgressNotification";
@@ -278,6 +275,8 @@ export type { ThreadCompactStartParams } from "./ThreadCompactStartParams";
export type { ThreadCompactStartResponse } from "./ThreadCompactStartResponse";
export type { ThreadForkParams } from "./ThreadForkParams";
export type { ThreadForkResponse } from "./ThreadForkResponse";
export type { ThreadInputActivityParams } from "./ThreadInputActivityParams";
export type { ThreadInputActivityResponse } from "./ThreadInputActivityResponse";
export type { ThreadItem } from "./ThreadItem";
export type { ThreadListParams } from "./ThreadListParams";
export type { ThreadListResponse } from "./ThreadListResponse";
@@ -294,8 +293,6 @@ export type { ThreadRealtimeClosedNotification } from "./ThreadRealtimeClosedNot
export type { ThreadRealtimeErrorNotification } from "./ThreadRealtimeErrorNotification";
export type { ThreadRealtimeItemAddedNotification } from "./ThreadRealtimeItemAddedNotification";
export type { ThreadRealtimeOutputAudioDeltaNotification } from "./ThreadRealtimeOutputAudioDeltaNotification";
export type { ThreadRealtimeSdpNotification } from "./ThreadRealtimeSdpNotification";
export type { ThreadRealtimeStartTransport } from "./ThreadRealtimeStartTransport";
export type { ThreadRealtimeStartedNotification } from "./ThreadRealtimeStartedNotification";
export type { ThreadRealtimeTranscriptUpdatedNotification } from "./ThreadRealtimeTranscriptUpdatedNotification";
export type { ThreadResumeParams } from "./ThreadResumeParams";

View File

@@ -15,7 +15,6 @@ pub use export::generate_ts_with_options;
pub use export::generate_types;
pub use jsonrpc_lite::*;
pub use protocol::common::*;
pub use protocol::item_builders::*;
pub use protocol::thread_history::*;
pub use protocol::v1::ApplyPatchApprovalParams;
pub use protocol::v1::ApplyPatchApprovalResponse;

View File

@@ -301,6 +301,10 @@ client_request_definitions! {
params: v2::ThreadBackgroundTerminalsCleanParams,
response: v2::ThreadBackgroundTerminalsCleanResponse,
},
ThreadInputActivity => "thread/inputActivity" {
params: v2::ThreadInputActivityParams,
response: v2::ThreadInputActivityResponse,
},
ThreadRollback => "thread/rollback" {
params: v2::ThreadRollbackParams,
response: v2::ThreadRollbackResponse,
@@ -459,11 +463,6 @@ client_request_definitions! {
response: v2::ListMcpServerStatusResponse,
},
McpResourceRead => "mcpServer/resource/read" {
params: v2::McpResourceReadParams,
response: v2::McpResourceReadResponse,
},
WindowsSandboxSetupStart => "windowsSandbox/setupStart" {
params: v2::WindowsSandboxSetupStartParams,
response: v2::WindowsSandboxSetupStartResponse,
@@ -620,41 +619,6 @@ macro_rules! server_request_definitions {
}
}
/// Typed response from the client to the server.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "method", rename_all = "camelCase")]
pub enum ServerResponse {
$(
$(#[$variant_meta])*
$(#[serde(rename = $wire)])?
$variant {
#[serde(rename = "id")]
request_id: RequestId,
response: $response,
},
)*
}
impl ServerResponse {
pub fn id(&self) -> &RequestId {
match self {
$(Self::$variant { request_id, .. } => request_id,)*
}
}
pub fn method(&self) -> String {
serde_json::to_value(self)
.ok()
.and_then(|value| {
value
.get("method")
.and_then(serde_json::Value::as_str)
.map(str::to_owned)
})
.unwrap_or_else(|| "<unknown>".to_string())
}
}
#[derive(Debug, Clone, PartialEq, JsonSchema)]
#[allow(clippy::large_enum_variant)]
pub enum ServerRequestPayload {
@@ -1005,8 +969,6 @@ server_notification_definitions! {
ThreadRealtimeTranscriptUpdated => "thread/realtime/transcriptUpdated" (v2::ThreadRealtimeTranscriptUpdatedNotification),
#[experimental("thread/realtime/outputAudio/delta")]
ThreadRealtimeOutputAudioDelta => "thread/realtime/outputAudio/delta" (v2::ThreadRealtimeOutputAudioDeltaNotification),
#[experimental("thread/realtime/sdp")]
ThreadRealtimeSdp => "thread/realtime/sdp" (v2::ThreadRealtimeSdpNotification),
#[experimental("thread/realtime/error")]
ThreadRealtimeError => "thread/realtime/error" (v2::ThreadRealtimeErrorNotification),
#[experimental("thread/realtime/closed")]
@@ -1267,30 +1229,6 @@ mod tests {
Ok(())
}
#[test]
fn serialize_server_response() -> Result<()> {
let response = ServerResponse::CommandExecutionRequestApproval {
request_id: RequestId::Integer(8),
response: v2::CommandExecutionRequestApprovalResponse {
decision: v2::CommandExecutionApprovalDecision::AcceptForSession,
},
};
assert_eq!(response.id(), &RequestId::Integer(8));
assert_eq!(response.method(), "item/commandExecution/requestApproval");
assert_eq!(
json!({
"method": "item/commandExecution/requestApproval",
"id": 8,
"response": {
"decision": "acceptForSession"
}
}),
serde_json::to_value(&response)?,
);
Ok(())
}
#[test]
fn serialize_mcp_server_elicitation_request() -> Result<()> {
let requested_schema: v2::McpElicitationSchema = serde_json::from_value(json!({
@@ -1373,7 +1311,6 @@ mod tests {
response: v2::ThreadStartResponse {
thread: v2::Thread {
id: "67e55044-10b1-426f-9247-bb680e5fe0c8".to_string(),
forked_from_id: None,
preview: "first prompt".to_string(),
ephemeral: true,
model_provider: "openai".to_string(),
@@ -1410,7 +1347,6 @@ mod tests {
"response": {
"thread": {
"id": "67e55044-10b1-426f-9247-bb680e5fe0c8",
"forkedFromId": null,
"preview": "first prompt",
"ephemeral": true,
"modelProvider": "openai",
@@ -1696,7 +1632,6 @@ mod tests {
let request = ClientRequest::FsWatch {
request_id: RequestId::Integer(10),
params: v2::FsWatchParams {
watch_id: "watch-git".to_string(),
path: absolute_path("tmp/repo/.git"),
},
};
@@ -1705,7 +1640,6 @@ mod tests {
"method": "fs/watch",
"id": 10,
"params": {
"watchId": "watch-git",
"path": absolute_path_string("tmp/repo/.git")
}
}),
@@ -1763,7 +1697,6 @@ mod tests {
thread_id: "thr_123".to_string(),
prompt: "You are on a call".to_string(),
session_id: Some("sess_456".to_string()),
transport: None,
},
};
assert_eq!(
@@ -1773,8 +1706,7 @@ mod tests {
"params": {
"threadId": "thr_123",
"prompt": "You are on a call",
"sessionId": "sess_456",
"transport": null
"sessionId": "sess_456"
}
}),
serde_json::to_value(&request)?,
@@ -1854,7 +1786,6 @@ mod tests {
thread_id: "thr_123".to_string(),
prompt: "You are on a call".to_string(),
session_id: None,
transport: None,
},
};
let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&request);

View File

@@ -1,299 +0,0 @@
//! Shared builders for synthetic [`ThreadItem`] values emitted by the app-server layer.
//!
//! These items do not come from first-class core `ItemStarted` / `ItemCompleted` events.
//! Instead, the app-server synthesizes them so clients can render a coherent lifecycle for
//! approvals and other pre-execution flows before the underlying tool has started or when the
//! tool never starts at all.
//!
//! Keeping these builders in one place is useful for two reasons:
//! - Live notifications and rebuilt `thread/read` history both need to construct the same
//! synthetic items, so sharing the logic avoids drift between those paths.
//! - The projection is presentation-specific. Core protocol events stay generic, while the
//! app-server protocol decides how to surface those events as `ThreadItem`s for clients.
use crate::protocol::common::ServerNotification;
use crate::protocol::v2::CommandAction;
use crate::protocol::v2::CommandExecutionSource;
use crate::protocol::v2::CommandExecutionStatus;
use crate::protocol::v2::FileUpdateChange;
use crate::protocol::v2::GuardianApprovalReview;
use crate::protocol::v2::GuardianApprovalReviewStatus;
use crate::protocol::v2::ItemGuardianApprovalReviewCompletedNotification;
use crate::protocol::v2::ItemGuardianApprovalReviewStartedNotification;
use crate::protocol::v2::PatchApplyStatus;
use crate::protocol::v2::PatchChangeKind;
use crate::protocol::v2::ThreadItem;
use codex_protocol::ThreadId;
use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
use codex_protocol::protocol::ExecApprovalRequestEvent;
use codex_protocol::protocol::ExecCommandBeginEvent;
use codex_protocol::protocol::ExecCommandEndEvent;
use codex_protocol::protocol::FileChange;
use codex_protocol::protocol::GuardianAssessmentAction;
use codex_protocol::protocol::GuardianAssessmentEvent;
use codex_protocol::protocol::PatchApplyBeginEvent;
use codex_protocol::protocol::PatchApplyEndEvent;
use codex_shell_command::parse_command::parse_command;
use codex_shell_command::parse_command::shlex_join;
use std::collections::HashMap;
use std::path::PathBuf;
pub fn build_file_change_approval_request_item(
payload: &ApplyPatchApprovalRequestEvent,
) -> ThreadItem {
ThreadItem::FileChange {
id: payload.call_id.clone(),
changes: convert_patch_changes(&payload.changes),
status: PatchApplyStatus::InProgress,
}
}
pub fn build_file_change_begin_item(payload: &PatchApplyBeginEvent) -> ThreadItem {
ThreadItem::FileChange {
id: payload.call_id.clone(),
changes: convert_patch_changes(&payload.changes),
status: PatchApplyStatus::InProgress,
}
}
pub fn build_file_change_end_item(payload: &PatchApplyEndEvent) -> ThreadItem {
ThreadItem::FileChange {
id: payload.call_id.clone(),
changes: convert_patch_changes(&payload.changes),
status: (&payload.status).into(),
}
}
pub fn build_command_execution_approval_request_item(
payload: &ExecApprovalRequestEvent,
) -> ThreadItem {
ThreadItem::CommandExecution {
id: payload.call_id.clone(),
command: shlex_join(&payload.command),
cwd: payload.cwd.clone(),
process_id: None,
source: CommandExecutionSource::Agent,
status: CommandExecutionStatus::InProgress,
command_actions: payload
.parsed_cmd
.iter()
.cloned()
.map(CommandAction::from)
.collect(),
aggregated_output: None,
exit_code: None,
duration_ms: None,
}
}
pub fn build_command_execution_begin_item(payload: &ExecCommandBeginEvent) -> ThreadItem {
ThreadItem::CommandExecution {
id: payload.call_id.clone(),
command: shlex_join(&payload.command),
cwd: payload.cwd.clone(),
process_id: payload.process_id.clone(),
source: payload.source.into(),
status: CommandExecutionStatus::InProgress,
command_actions: payload
.parsed_cmd
.iter()
.cloned()
.map(CommandAction::from)
.collect(),
aggregated_output: None,
exit_code: None,
duration_ms: None,
}
}
pub fn build_command_execution_end_item(payload: &ExecCommandEndEvent) -> ThreadItem {
let aggregated_output = if payload.aggregated_output.is_empty() {
None
} else {
Some(payload.aggregated_output.clone())
};
let duration_ms = i64::try_from(payload.duration.as_millis()).unwrap_or(i64::MAX);
ThreadItem::CommandExecution {
id: payload.call_id.clone(),
command: shlex_join(&payload.command),
cwd: payload.cwd.clone(),
process_id: payload.process_id.clone(),
source: payload.source.into(),
status: (&payload.status).into(),
command_actions: payload
.parsed_cmd
.iter()
.cloned()
.map(CommandAction::from)
.collect(),
aggregated_output,
exit_code: Some(payload.exit_code),
duration_ms: Some(duration_ms),
}
}
/// Build a guardian-derived [`ThreadItem`].
///
/// Currently this only synthesizes [`ThreadItem::CommandExecution`] for
/// [`GuardianAssessmentAction::Command`] and [`GuardianAssessmentAction::Execve`].
pub fn build_item_from_guardian_event(
assessment: &GuardianAssessmentEvent,
status: CommandExecutionStatus,
) -> Option<ThreadItem> {
match &assessment.action {
GuardianAssessmentAction::Command { command, cwd, .. } => {
let command = command.clone();
let command_actions = vec![CommandAction::Unknown {
command: command.clone(),
}];
Some(ThreadItem::CommandExecution {
id: assessment.id.clone(),
command,
cwd: cwd.clone(),
process_id: None,
source: CommandExecutionSource::Agent,
status,
command_actions,
aggregated_output: None,
exit_code: None,
duration_ms: None,
})
}
GuardianAssessmentAction::Execve {
program, argv, cwd, ..
} => {
let argv = if argv.is_empty() {
vec![program.clone()]
} else {
std::iter::once(program.clone())
.chain(argv.iter().skip(1).cloned())
.collect::<Vec<_>>()
};
let command = shlex_join(&argv);
let parsed_cmd = parse_command(&argv);
let command_actions = if parsed_cmd.is_empty() {
vec![CommandAction::Unknown {
command: command.clone(),
}]
} else {
parsed_cmd.into_iter().map(CommandAction::from).collect()
};
Some(ThreadItem::CommandExecution {
id: assessment.id.clone(),
command,
cwd: cwd.clone(),
process_id: None,
source: CommandExecutionSource::Agent,
status,
command_actions,
aggregated_output: None,
exit_code: None,
duration_ms: None,
})
}
GuardianAssessmentAction::ApplyPatch { .. }
| GuardianAssessmentAction::NetworkAccess { .. }
| GuardianAssessmentAction::McpToolCall { .. } => None,
}
}
pub fn guardian_auto_approval_review_notification(
conversation_id: &ThreadId,
event_turn_id: &str,
assessment: &GuardianAssessmentEvent,
) -> ServerNotification {
// TODO(ccunningham): Attach guardian review state to the reviewed tool
// item's lifecycle instead of sending standalone review notifications so
// the app-server API can persist and replay review state via `thread/read`.
let turn_id = if assessment.turn_id.is_empty() {
event_turn_id.to_string()
} else {
assessment.turn_id.clone()
};
let review = GuardianApprovalReview {
status: match assessment.status {
codex_protocol::protocol::GuardianAssessmentStatus::InProgress => {
GuardianApprovalReviewStatus::InProgress
}
codex_protocol::protocol::GuardianAssessmentStatus::Approved => {
GuardianApprovalReviewStatus::Approved
}
codex_protocol::protocol::GuardianAssessmentStatus::Denied => {
GuardianApprovalReviewStatus::Denied
}
codex_protocol::protocol::GuardianAssessmentStatus::Aborted => {
GuardianApprovalReviewStatus::Aborted
}
},
risk_score: assessment.risk_score,
risk_level: assessment.risk_level.map(Into::into),
rationale: assessment.rationale.clone(),
};
let action = assessment.action.clone().into();
match assessment.status {
codex_protocol::protocol::GuardianAssessmentStatus::InProgress => {
ServerNotification::ItemGuardianApprovalReviewStarted(
ItemGuardianApprovalReviewStartedNotification {
thread_id: conversation_id.to_string(),
turn_id,
target_item_id: assessment.id.clone(),
review,
action,
},
)
}
codex_protocol::protocol::GuardianAssessmentStatus::Approved
| codex_protocol::protocol::GuardianAssessmentStatus::Denied
| codex_protocol::protocol::GuardianAssessmentStatus::Aborted => {
ServerNotification::ItemGuardianApprovalReviewCompleted(
ItemGuardianApprovalReviewCompletedNotification {
thread_id: conversation_id.to_string(),
turn_id,
target_item_id: assessment.id.clone(),
review,
action,
},
)
}
}
}
pub fn convert_patch_changes(changes: &HashMap<PathBuf, FileChange>) -> Vec<FileUpdateChange> {
let mut converted: Vec<FileUpdateChange> = changes
.iter()
.map(|(path, change)| FileUpdateChange {
path: path.to_string_lossy().into_owned(),
kind: map_patch_change_kind(change),
diff: format_file_change_diff(change),
})
.collect();
converted.sort_by(|a, b| a.path.cmp(&b.path));
converted
}
fn map_patch_change_kind(change: &FileChange) -> PatchChangeKind {
match change {
FileChange::Add { .. } => PatchChangeKind::Add,
FileChange::Delete { .. } => PatchChangeKind::Delete,
FileChange::Update { move_path, .. } => PatchChangeKind::Update {
move_path: move_path.clone(),
},
}
}
fn format_file_change_diff(change: &FileChange) -> String {
match change {
FileChange::Add { content } => content.clone(),
FileChange::Delete { content } => content.clone(),
FileChange::Update {
unified_diff,
move_path,
} => {
if let Some(path) = move_path {
format!("{unified_diff}\n\nMoved to: {}", path.display())
} else {
unified_diff.clone()
}
}
}
}

View File

@@ -2,7 +2,6 @@
// Exposes protocol pieces used by `lib.rs` via `pub use protocol::common::*;`.
pub mod common;
pub mod item_builders;
mod mappers;
mod serde_helpers;
pub mod thread_history;

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,6 @@ use codex_protocol::config_types::WebSearchToolConfig;
use codex_protocol::items::AgentMessageContent as CoreAgentMessageContent;
use codex_protocol::items::TurnItem as CoreTurnItem;
use codex_protocol::mcp::Resource as McpResource;
pub use codex_protocol::mcp::ResourceContent as McpResourceContent;
use codex_protocol::mcp::ResourceTemplate as McpResourceTemplate;
use codex_protocol::mcp::Tool as McpTool;
use codex_protocol::memory_citation::MemoryCitation as CoreMemoryCitation;
@@ -851,8 +850,6 @@ pub struct ConfigReadResponse {
pub struct ConfigRequirements {
#[experimental(nested)]
pub allowed_approval_policies: Option<Vec<AskForApproval>>,
#[experimental("configRequirements/read.allowedApprovalsReviewers")]
pub allowed_approvals_reviewers: Option<Vec<ApprovalsReviewer>>,
pub allowed_sandbox_modes: Option<Vec<SandboxMode>>,
pub allowed_web_search_modes: Option<Vec<WebSearchMode>>,
pub feature_requirements: Option<BTreeMap<String, bool>>,
@@ -885,7 +882,6 @@ pub struct NetworkRequirements {
/// Legacy compatibility view derived from `unix_sockets`.
pub allow_unix_sockets: Option<Vec<String>>,
pub allow_local_binding: Option<bool>,
pub danger_full_access_denylist_only: Option<bool>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
@@ -1791,8 +1787,6 @@ pub struct Model {
pub input_modalities: Vec<InputModality>,
#[serde(default)]
pub supports_personality: bool,
#[serde(default)]
pub additional_speed_tiers: Vec<String>,
// Only one model should be marked as default.
pub is_default: bool,
}
@@ -1953,18 +1947,6 @@ pub struct ListMcpServerStatusParams {
/// Optional page size; defaults to a server-defined value.
#[ts(optional = nullable)]
pub limit: Option<u32>,
/// Controls how much MCP inventory data to fetch for each server.
/// Defaults to `Full` when omitted.
#[ts(optional = nullable)]
pub detail: Option<McpServerStatusDetail>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase", export_to = "v2/")]
pub enum McpServerStatusDetail {
Full,
ToolsAndAuthOnly,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
@@ -1988,22 +1970,6 @@ pub struct ListMcpServerStatusResponse {
pub next_cursor: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct McpResourceReadParams {
pub thread_id: String,
pub server: String,
pub uri: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct McpResourceReadResponse {
pub contents: Vec<McpResourceContent>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
@@ -2351,17 +2317,17 @@ pub struct FsCopyResponse {}
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct FsWatchParams {
/// Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`.
pub watch_id: String,
/// Absolute file or directory path to watch.
pub path: AbsolutePathBuf,
}
/// Successful response for `fs/watch`.
/// Created watch handle returned by `fs/watch`.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct FsWatchResponse {
/// Connection-scoped watch identifier used for `fs/unwatch` and `fs/changed`.
pub watch_id: String,
/// Canonicalized path associated with the watch.
pub path: AbsolutePathBuf,
}
@@ -2371,7 +2337,7 @@ pub struct FsWatchResponse {
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct FsUnwatchParams {
/// Watch identifier previously provided to `fs/watch`.
/// Watch identifier returned by `fs/watch`.
pub watch_id: String,
}
@@ -2386,7 +2352,7 @@ pub struct FsUnwatchResponse {}
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct FsChangedNotification {
/// Watch identifier previously provided to `fs/watch`.
/// Watch identifier returned by `fs/watch`.
pub watch_id: String,
/// File or directory paths associated with this event.
pub changed_paths: Vec<AbsolutePathBuf>,
@@ -3028,6 +2994,18 @@ pub struct ThreadBackgroundTerminalsCleanParams {
#[ts(export_to = "v2/")]
pub struct ThreadBackgroundTerminalsCleanResponse {}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ThreadInputActivityParams {
pub thread_id: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ThreadInputActivityResponse {}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
@@ -3608,8 +3586,6 @@ impl From<CoreSkillErrorInfo> for SkillErrorInfo {
#[ts(export_to = "v2/")]
pub struct Thread {
pub id: String,
/// Source thread id when this thread was created by forking another thread.
pub forked_from_id: Option<String>,
/// Usually the first user message in the thread, if available.
pub preview: String,
/// Whether the thread is ephemeral and should not be materialized on disk.
@@ -3725,15 +3701,6 @@ pub struct Turn {
pub status: TurnStatus,
/// Only populated when the Turn's status is failed.
pub error: Option<TurnError>,
/// Unix timestamp (in seconds) when the turn started.
#[ts(type = "number | null")]
pub started_at: Option<i64>,
/// Unix timestamp (in seconds) when the turn completed.
#[ts(type = "number | null")]
pub completed_at: Option<i64>,
/// Duration between turn start and completion in milliseconds, if known.
#[ts(type = "number | null")]
pub duration_ms: Option<i64>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
@@ -3856,21 +3823,6 @@ pub struct ThreadRealtimeStartParams {
pub prompt: String,
#[ts(optional = nullable)]
pub session_id: Option<String>,
#[ts(optional = nullable)]
pub transport: Option<ThreadRealtimeStartTransport>,
}
/// EXPERIMENTAL - transport used by thread realtime.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(tag = "type", rename_all = "camelCase")]
#[ts(export_to = "v2/", tag = "type")]
pub enum ThreadRealtimeStartTransport {
Websocket,
Webrtc {
/// SDP offer generated by a WebRTC RTCPeerConnection after configuring audio and the
/// realtime events data channel.
sdp: String,
},
}
/// EXPERIMENTAL - response for starting thread realtime.
@@ -3962,15 +3914,6 @@ pub struct ThreadRealtimeOutputAudioDeltaNotification {
pub audio: ThreadRealtimeAudioChunk,
}
/// EXPERIMENTAL - emitted with the remote SDP for a WebRTC realtime session.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ThreadRealtimeSdpNotification {
pub thread_id: String,
pub sdp: String,
}
/// EXPERIMENTAL - emitted when thread realtime encounters an error.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
@@ -5038,9 +4981,6 @@ pub struct McpToolCallResult {
// representations). Using `JsonValue` keeps the payload wire-shaped and easy to export.
pub content: Vec<JsonValue>,
pub structured_content: Option<JsonValue>,
#[serde(rename = "_meta")]
#[ts(rename = "_meta")]
pub meta: Option<JsonValue>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
@@ -6710,6 +6650,38 @@ mod tests {
assert_eq!(decoded, response);
}
#[test]
fn thread_input_activity_params_round_trip() {
let params = ThreadInputActivityParams {
thread_id: "thr_123".to_string(),
};
let value = serde_json::to_value(&params).expect("serialize thread/inputActivity params");
assert_eq!(
value,
json!({
"threadId": "thr_123",
})
);
let decoded = serde_json::from_value::<ThreadInputActivityParams>(value)
.expect("deserialize thread/inputActivity params");
assert_eq!(decoded, params);
}
#[test]
fn thread_input_activity_response_round_trip() {
let response = ThreadInputActivityResponse {};
let value =
serde_json::to_value(&response).expect("serialize thread/inputActivity response");
assert_eq!(value, json!({}));
let decoded = serde_json::from_value::<ThreadInputActivityResponse>(value)
.expect("deserialize thread/inputActivity response");
assert_eq!(decoded, response);
}
#[test]
fn fs_changed_notification_round_trips() {
let notification = FsChangedNotification {
@@ -7385,7 +7357,6 @@ mod tests {
request_permissions: false,
mcp_elicitations: false,
}]),
allowed_approvals_reviewers: None,
allowed_sandbox_modes: None,
allowed_web_search_modes: None,
feature_requirements: None,
@@ -7850,7 +7821,6 @@ mod tests {
dangerously_allow_all_unix_sockets: None,
domains: None,
managed_allowed_domains_only: None,
danger_full_access_denylist_only: None,
allowed_domains: Some(vec!["api.openai.com".to_string()]),
denied_domains: Some(vec!["blocked.example.com".to_string()]),
unix_sockets: None,
@@ -7877,7 +7847,6 @@ mod tests {
),
])),
managed_allowed_domains_only: Some(true),
danger_full_access_denylist_only: Some(true),
allowed_domains: Some(vec!["api.openai.com".to_string()]),
denied_domains: Some(vec!["blocked.example.com".to_string()]),
unix_sockets: Some(BTreeMap::from([
@@ -7908,7 +7877,6 @@ mod tests {
"blocked.example.com": "deny"
},
"managedAllowedDomainsOnly": true,
"dangerFullAccessDenylistOnly": true,
"allowedDomains": ["api.openai.com"],
"deniedDomains": ["blocked.example.com"],
"unixSockets": {

View File

@@ -3,6 +3,5 @@ load("//:defs.bzl", "codex_rust_crate")
codex_rust_crate(
name = "app-server",
crate_name = "codex_app_server",
integration_test_timeout = "long",
test_tags = ["no-sandbox"],
)

View File

@@ -46,7 +46,6 @@ codex-file-search = { workspace = true }
codex-chatgpt = { workspace = true }
codex-login = { workspace = true }
codex-mcp = { workspace = true }
codex-models-manager = { workspace = true }
codex-protocol = { workspace = true }
codex-app-server-protocol = { workspace = true }
codex-feedback = { workspace = true }
@@ -57,12 +56,10 @@ codex-state = { workspace = true }
codex-tools = { workspace = true }
codex-utils-absolute-path = { workspace = true }
codex-utils-json-to-toml = { workspace = true }
codex-utils-rustls-provider = { workspace = true }
chrono = { workspace = true }
clap = { workspace = true, features = ["derive"] }
constant_time_eq = { workspace = true }
futures = { workspace = true }
gethostname = { workspace = true }
hmac = { workspace = true }
jsonwebtoken = { workspace = true }
owo-colors = { workspace = true, features = ["supports-colors"] }
@@ -83,7 +80,6 @@ tokio-util = { workspace = true }
tokio-tungstenite = { workspace = true }
tracing = { workspace = true, features = ["log"] }
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt", "json"] }
url = { workspace = true }
uuid = { workspace = true, features = ["serde", "v7"] }
[dev-dependencies]

View File

@@ -25,7 +25,6 @@ Supported transports:
- stdio (`--listen stdio://`, default): newline-delimited JSON (JSONL)
- websocket (`--listen ws://IP:PORT`): one JSON-RPC message per websocket text frame (**experimental / unsupported**)
- off (`--listen off`): do not expose a local transport
When running with `--listen ws://IP:PORT`, the same listener also serves basic HTTP health probes:
@@ -133,9 +132,9 @@ Example with notification opt-out:
## API Overview
- `thread/start` — create a new thread; emits `thread/started` (including the current `thread.status`) and auto-subscribes you to turn/item events for that thread. When the request includes a `cwd` and the resolved sandbox is `workspace-write` or full access, app-server also marks that project as trusted in the user `config.toml`.
- `thread/start` — create a new thread; emits `thread/started` (including the current `thread.status`) and auto-subscribes you to turn/item events for that thread.
- `thread/resume` — reopen an existing thread by id so subsequent `turn/start` calls append to it.
- `thread/fork` — fork an existing thread into a new thread id by copying the stored history; if the source thread is currently mid-turn, the fork records the same interruption marker as `turn/interrupt` instead of inheriting an unmarked partial turn suffix. The returned `thread.forkedFromId` points at the source thread when known. Accepts `ephemeral: true` for an in-memory temporary fork, emits `thread/started` (including the current `thread.status`), and auto-subscribes you to turn/item events for the new thread.
- `thread/fork` — fork an existing thread into a new thread id by copying the stored history; if the source thread is currently mid-turn, the fork records the same interruption marker as `turn/interrupt` instead of inheriting an unmarked partial turn suffix. Accepts `ephemeral: true` for an in-memory temporary fork, emits `thread/started` (including the current `thread.status`), and auto-subscribes you to turn/item events for the new thread.
- `thread/list` — page through stored rollouts; supports cursor-based pagination and optional `modelProviders`, `sourceKinds`, `archived`, `cwd`, and `searchTerm` filters. Each returned `thread` includes `status` (`ThreadStatus`), defaulting to `notLoaded` when the thread is not currently loaded.
- `thread/loaded/list` — list the thread ids currently loaded in memory.
- `thread/read` — read a stored thread by id without resuming it; optionally include turns via `includeTurns`. The returned `thread` includes `status` (`ThreadStatus`), defaulting to `notLoaded` when the thread is not currently loaded.
@@ -148,11 +147,12 @@ Example with notification opt-out:
- `thread/compact/start` — trigger conversation history compaction for a thread; returns `{}` immediately while progress streams through standard turn/item notifications.
- `thread/shellCommand` — run a user-initiated `!` shell command against a thread; this runs unsandboxed with full access rather than inheriting the thread sandbox policy. Returns `{}` immediately while progress streams through standard turn/item notifications and any active turn receives the formatted output in its message stream.
- `thread/backgroundTerminals/clean` — terminate all running background terminals for a thread (experimental; requires `capabilities.experimentalApi`); returns `{}` when the cleanup request is accepted.
- `thread/inputActivity` — record owner-side draft activity for a thread without starting or steering a turn; returns `{}` and is primarily useful for watchdog idle timers while the user is still typing.
- `thread/rollback` — drop the last N turns from the agents in-memory context and persist a rollback marker in the rollout so future resumes see the pruned history; returns the updated `thread` (with `turns` populated) on success.
- `turn/start` — add user input to a thread and begin Codex generation; responds with the initial `turn` object and streams `turn/started`, `item/*`, and `turn/completed` notifications. For `collaborationMode`, `settings.developer_instructions: null` means "use built-in instructions for the selected mode".
- `turn/steer` — add user input to an already in-flight regular turn without starting a new turn; returns the active `turnId` that accepted the input. Review and manual compaction turns reject `turn/steer`.
- `turn/interrupt` — request cancellation of an in-flight turn by `(thread_id, turn_id)`; success is an empty `{}` response and the turn finishes with `status: "interrupted"`.
- `thread/realtime/start` — start a thread-scoped realtime session (experimental); returns `{}` and streams `thread/realtime/*` notifications. Omit `transport` for the websocket transport, or pass `{ "type": "webrtc", "sdp": "..." }` to create a WebRTC session from a browser-generated SDP offer; the remote answer SDP is emitted as `thread/realtime/sdp`.
- `thread/realtime/start` — start a thread-scoped realtime session (experimental); returns `{}` and streams `thread/realtime/*` notifications.
- `thread/realtime/appendAudio` — append an input audio chunk to the active realtime session (experimental); returns `{}`.
- `thread/realtime/appendText` — append text input to the active realtime session (experimental); returns `{}`.
- `thread/realtime/stop` — stop the active realtime session for the thread (experimental); returns `{}`.
@@ -169,10 +169,10 @@ Example with notification opt-out:
- `fs/readDirectory` — list direct child entries for an absolute directory path; each entry contains `fileName`, `isDirectory`, and `isFile`, and `fileName` is just the child name, not a path.
- `fs/remove` — remove an absolute file or directory tree; `recursive` and `force` default to `true`.
- `fs/copy` — copy between absolute paths; directory copies require `recursive: true`.
- `fs/watch` — subscribe this connection to filesystem change notifications for an absolute file or directory path and caller-provided `watchId`; returns the canonicalized `path`.
- `fs/watch` — subscribe this connection to filesystem change notifications for an absolute file or directory path; returns a `watchId` and canonicalized `path`.
- `fs/unwatch` — stop sending notifications for a prior `fs/watch`; returns `{}`.
- `fs/changed` — notification emitted when watched paths change, including the `watchId` and `changedPaths`.
- `model/list` — list available models (set `includeHidden: true` to include entries with `hidden: true`), with reasoning effort options, `additionalSpeedTiers`, optional legacy `upgrade` model ids, optional `upgradeInfo` metadata (`model`, `upgradeCopy`, `modelLink`, `migrationMarkdown`), and optional `availabilityNux` metadata.
- `model/list` — list available models (set `includeHidden: true` to include entries with `hidden: true`), with reasoning effort options, optional legacy `upgrade` model ids, optional `upgradeInfo` metadata (`model`, `upgradeCopy`, `modelLink`, `migrationMarkdown`), and optional `availabilityNux` metadata.
- `experimentalFeature/list` — list feature flags with stage metadata (`beta`, `underDevelopment`, `stable`, etc.), enabled/default-enabled state, and cursor pagination. For non-beta flags, `displayName`/`description`/`announcement` are `null`.
- `experimentalFeature/enablement/set` — patch the in-memory process-wide runtime feature enablement for the currently supported feature keys (`apps`, `plugins`). For each feature, precedence is: cloud requirements > --enable <feature_name> > config.toml > experimentalFeature/enablement/set (new) > code default.
- `collaborationMode/list` — list available collaboration mode presets (experimental, no pagination). This response omits built-in developer instructions; clients should either pass `settings.developer_instructions: null` when setting a mode to use Codex's built-in instructions, or provide their own instructions explicitly.
@@ -187,8 +187,7 @@ Example with notification opt-out:
- `mcpServer/oauth/login` — start an OAuth login for a configured MCP server; returns an `authorization_url` and later emits `mcpServer/oauthLogin/completed` once the browser flow finishes.
- `tool/requestUserInput` — prompt the user with 13 short questions for a tool call and return their answers (experimental).
- `config/mcpServer/reload` — reload MCP server config from disk and queue a refresh for loaded threads (applied on each thread's next active turn); returns `{}`. Use this after editing `config.toml` without restarting the server.
- `mcpServerStatus/list` — enumerate configured MCP servers with their tools and auth status, plus resources/resource templates for `full` detail; supports cursor+limit pagination. If `detail` is omitted, the server defaults to `full`.
- `mcpServer/resource/read` — read a resource from a thread's configured MCP server by `threadId`, `server`, and `uri`, returning text/blob resource `contents`.
- `mcpServerStatus/list` — enumerate configured MCP servers with their tools, resources, resource templates, and auth status; supports cursor+limit pagination.
- `windowsSandbox/setupStart` — start Windows sandbox setup for the selected mode (`elevated` or `unelevated`); accepts an optional absolute `cwd` to target setup for a specific workspace, returns `{ started: true }` immediately, and later emits `windowsSandbox/setupCompleted`.
- `feedback/upload` — submit a feedback report (classification + optional reason/logs, conversation_id, and optional `extraLogFiles` attachments array); returns the tracking thread id.
- `config/read` — fetch the effective config on disk after resolving config layering.
@@ -196,7 +195,7 @@ Example with notification opt-out:
- `externalAgentConfig/import` — apply selected external-agent migration items by passing explicit `migrationItems` with `cwd` (`null` for home).
- `config/value/write` — write a single config key/value to the user's config.toml on disk.
- `config/batchWrite` — apply multiple config edits atomically to the user's config.toml on disk, with optional `reloadUserConfig: true` to hot-reload loaded threads.
- `configRequirements/read` — fetch loaded requirements constraints from `requirements.toml` and/or MDM (or `null` if none are configured), including allow-lists (`allowedApprovalPolicies`, `allowedSandboxModes`, `allowedWebSearchModes`), pinned feature values (`featureRequirements`), `enforceResidency`, and `network` constraints such as canonical domain/socket permissions plus `managedAllowedDomainsOnly` and `dangerFullAccessDenylistOnly`.
- `configRequirements/read` — fetch loaded requirements constraints from `requirements.toml` and/or MDM (or `null` if none are configured), including allow-lists (`allowedApprovalPolicies`, `allowedSandboxModes`, `allowedWebSearchModes`), pinned feature values (`featureRequirements`), `enforceResidency`, and `network` constraints such as canonical domain/socket permissions plus `managedAllowedDomainsOnly`.
### Example: Start or resume a thread
@@ -275,7 +274,7 @@ Experimental API: `thread/start`, `thread/resume`, and `thread/fork` accept `per
- `modelProviders` — restrict results to specific providers; unset, null, or an empty array will include all providers.
- `sourceKinds` — restrict results to specific sources; omit or pass `[]` for interactive sessions only (`cli`, `vscode`).
- `archived` — when `true`, list archived threads only. When `false` or `null`, list non-archived threads (default).
- `cwd` — restrict results to threads whose session cwd exactly matches this path. Relative paths are resolved against the app-server process cwd before matching.
- `cwd` — restrict results to threads whose session cwd exactly matches this path.
- `searchTerm` — restrict results to threads whose extracted title contains this substring (case-sensitive).
- Responses include `agentNickname` and `agentRole` for AgentControl-spawned thread sub-agents when available.
@@ -563,51 +562,6 @@ Invoke a plugin by including a UI mention token such as `@sample` in the text in
} } }
```
### Example: Start realtime with WebRTC
Use `thread/realtime/start` with `transport.type: "webrtc"` when a browser or webview owns the `RTCPeerConnection` and app-server should create the server-side realtime session. The transport `sdp` must be the offer SDP produced by `RTCPeerConnection.createOffer()`, not a hand-written or minimal SDP string.
The offer should include the media sections the client wants to negotiate. For the standard realtime UI flow, create the audio track/transceiver and the `oai-events` data channel before calling `createOffer()`:
```javascript
const pc = new RTCPeerConnection();
audioElement.autoplay = true;
pc.ontrack = (event) => {
audioElement.srcObject = event.streams[0];
};
const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
pc.addTrack(mediaStream.getAudioTracks()[0], mediaStream);
pc.createDataChannel("oai-events");
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
```
Then send `offer.sdp` to app-server. Core uses `experimental_realtime_ws_backend_prompt` for the backend instructions and the thread conversation id for the realtime session id. The start response is `{}`; the remote answer SDP arrives later as `thread/realtime/sdp` and should be passed to `setRemoteDescription()`:
```json
{ "method": "thread/realtime/start", "id": 40, "params": {
"threadId": "thr_123",
"prompt": "You are on a call.",
"sessionId": null,
"transport": { "type": "webrtc", "sdp": "v=0\r\no=..." }
} }
{ "id": 40, "result": {} }
{ "method": "thread/realtime/sdp", "params": {
"threadId": "thr_123",
"sdp": "v=0\r\no=..."
} }
```
```javascript
await pc.setRemoteDescription({
type: "answer",
sdp: notification.params.sdp,
});
```
### Example: Interrupt an active turn
You can cancel a running Turn with `turn/interrupt`.
@@ -651,6 +605,18 @@ not emit `turn/started` and does not accept turn context overrides.
active turn, or the active turn kind does not accept same-turn steering (for example review or
manual compaction), the request fails with an `invalid request` error.
### Example: Mark owner draft activity
Use `thread/inputActivity` to keep watchdog idle timing honest while the user is still editing a
draft in the client.
```json
{ "method": "thread/inputActivity", "id": 33, "params": {
"threadId": "thr_123"
} }
{ "id": 33, "result": {} }
```
### Example: Request a code review
Use `review/start` to run Codexs reviewer on the currently checked-out project. The request takes the thread id plus a `target` describing what should be reviewed:
@@ -861,10 +827,10 @@ All filesystem paths in this section must be absolute.
```json
{ "method": "fs/watch", "id": 44, "params": {
"watchId": "0195ec6b-1d6f-7c2e-8c7a-56f2c4a8b9d1",
"path": "/Users/me/project/.git/HEAD"
} }
{ "id": 44, "result": {
"watchId": "0195ec6b-1d6f-7c2e-8c7a-56f2c4a8b9d1",
"path": "/Users/me/project/.git/HEAD"
} }
{ "method": "fs/changed", "params": {

View File

@@ -86,7 +86,6 @@ fn transport_name(transport: AppServerTransport) -> &'static str {
match transport {
AppServerTransport::Stdio => "stdio",
AppServerTransport::WebSocket { .. } => "websocket",
AppServerTransport::Off => "off",
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,10 +5,10 @@ use codex_app_server_protocol::McpServerOauthLoginCompletedNotification;
use codex_app_server_protocol::ServerNotification;
use codex_config::types::McpServerConfig;
use codex_core::config::Config;
use codex_mcp::McpOAuthLoginSupport;
use codex_mcp::oauth_login_support;
use codex_mcp::resolve_oauth_scopes;
use codex_mcp::should_retry_without_scopes;
use codex_mcp::mcp::auth::McpOAuthLoginSupport;
use codex_mcp::mcp::auth::oauth_login_support;
use codex_mcp::mcp::auth::resolve_oauth_scopes;
use codex_mcp::mcp::auth::should_retry_without_scopes;
use codex_rmcp_client::perform_oauth_login_silent;
use tracing::warn;

View File

@@ -18,12 +18,12 @@ use codex_app_server_protocol::CommandExecWriteParams;
use codex_app_server_protocol::CommandExecWriteResponse;
use codex_app_server_protocol::JSONRPCErrorError;
use codex_app_server_protocol::ServerNotification;
use codex_core::bytes_to_string_smart;
use codex_core::config::StartedNetworkProxy;
use codex_core::exec::DEFAULT_EXEC_COMMAND_TIMEOUT_MS;
use codex_core::exec::ExecExpiration;
use codex_core::exec::IO_DRAIN_TIMEOUT_MS;
use codex_core::sandboxing::ExecRequest;
use codex_protocol::exec_output::bytes_to_string_smart;
use codex_sandboxing::SandboxType;
use codex_utils_pty::DEFAULT_OUTPUT_BYTES_CAP;
use codex_utils_pty::ProcessHandle;

View File

@@ -366,12 +366,6 @@ fn map_requirements_toml_to_api(requirements: ConfigRequirementsToml) -> ConfigR
.map(codex_app_server_protocol::AskForApproval::from)
.collect()
}),
allowed_approvals_reviewers: requirements.allowed_approvals_reviewers.map(|reviewers| {
reviewers
.into_iter()
.map(codex_app_server_protocol::ApprovalsReviewer::from)
.collect()
}),
allowed_sandbox_modes: requirements.allowed_sandbox_modes.map(|modes| {
modes
.into_iter()
@@ -449,7 +443,6 @@ fn map_network_requirements_to_api(
.collect()
}),
managed_allowed_domains_only: network.managed_allowed_domains_only,
danger_full_access_denylist_only: network.danger_full_access_denylist_only,
allowed_domains,
denied_domains,
unix_sockets: network.unix_sockets.map(|unix_sockets| {
@@ -526,7 +519,6 @@ mod tests {
use codex_features::Feature;
use codex_login::AuthManager;
use codex_login::CodexAuth;
use codex_protocol::config_types::ApprovalsReviewer as CoreApprovalsReviewer;
use codex_protocol::protocol::AskForApproval as CoreAskForApproval;
use pretty_assertions::assert_eq;
use serde_json::json;
@@ -553,10 +545,6 @@ mod tests {
CoreAskForApproval::Never,
CoreAskForApproval::OnRequest,
]),
allowed_approvals_reviewers: Some(vec![
CoreApprovalsReviewer::User,
CoreApprovalsReviewer::GuardianSubagent,
]),
allowed_sandbox_modes: Some(vec![
CoreSandboxModeRequirement::ReadOnly,
CoreSandboxModeRequirement::ExternalSandbox,
@@ -595,7 +583,6 @@ mod tests {
]),
}),
managed_allowed_domains_only: Some(false),
danger_full_access_denylist_only: Some(true),
unix_sockets: Some(CoreNetworkUnixSocketPermissionsToml {
entries: std::collections::BTreeMap::from([(
"/tmp/proxy.sock".to_string(),
@@ -615,13 +602,6 @@ mod tests {
codex_app_server_protocol::AskForApproval::OnRequest,
])
);
assert_eq!(
mapped.allowed_approvals_reviewers,
Some(vec![
codex_app_server_protocol::ApprovalsReviewer::User,
codex_app_server_protocol::ApprovalsReviewer::GuardianSubagent,
])
);
assert_eq!(
mapped.allowed_sandbox_modes,
Some(vec![SandboxMode::ReadOnly]),
@@ -655,7 +635,6 @@ mod tests {
("example.com".to_string(), NetworkDomainPermission::Deny),
])),
managed_allowed_domains_only: Some(false),
danger_full_access_denylist_only: Some(true),
allowed_domains: Some(vec!["api.openai.com".to_string()]),
denied_domains: Some(vec!["example.com".to_string()]),
unix_sockets: Some(std::collections::BTreeMap::from([(
@@ -672,7 +651,6 @@ mod tests {
fn map_requirements_toml_to_api_omits_unix_socket_none_entries_from_legacy_network_fields() {
let requirements = ConfigRequirementsToml {
allowed_approval_policies: None,
allowed_approvals_reviewers: None,
allowed_sandbox_modes: None,
allowed_web_search_modes: None,
guardian_developer_instructions: None,
@@ -690,7 +668,6 @@ mod tests {
dangerously_allow_all_unix_sockets: None,
domains: None,
managed_allowed_domains_only: None,
danger_full_access_denylist_only: None,
unix_sockets: Some(CoreNetworkUnixSocketPermissionsToml {
entries: std::collections::BTreeMap::from([(
"/tmp/ignored.sock".to_string(),
@@ -714,7 +691,6 @@ mod tests {
dangerously_allow_all_unix_sockets: None,
domains: None,
managed_allowed_domains_only: None,
danger_full_access_denylist_only: None,
allowed_domains: None,
denied_domains: None,
unix_sockets: Some(std::collections::BTreeMap::from([(
@@ -731,7 +707,6 @@ mod tests {
fn map_requirements_toml_to_api_normalizes_allowed_web_search_modes() {
let requirements = ConfigRequirementsToml {
allowed_approval_policies: None,
allowed_approvals_reviewers: None,
allowed_sandbox_modes: None,
allowed_web_search_modes: Some(Vec::new()),
guardian_developer_instructions: None,

View File

@@ -1,4 +1,3 @@
use crate::fs_api::invalid_request;
use crate::outgoing_message::ConnectionId;
use crate::outgoing_message::OutgoingMessageSender;
use codex_app_server_protocol::FsChangedNotification;
@@ -17,7 +16,6 @@ use codex_core::file_watcher::WatchRegistration;
use codex_utils_absolute_path::AbsolutePathBuf;
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::path::PathBuf;
use std::sync::Arc;
@@ -28,6 +26,7 @@ use tokio::sync::mpsc;
use tokio::sync::oneshot;
use tokio::time::Instant;
use tracing::warn;
use uuid::Uuid;
const FS_CHANGED_NOTIFICATION_DEBOUNCE: Duration = Duration::from_millis(200);
@@ -121,11 +120,7 @@ impl FsWatchManager {
connection_id: ConnectionId,
params: FsWatchParams,
) -> Result<FsWatchResponse, JSONRPCErrorError> {
let watch_id = params.watch_id;
let watch_key = WatchKey {
connection_id,
watch_id: watch_id.clone(),
};
let watch_id = Uuid::now_v7().to_string();
let outgoing = self.outgoing.clone();
let (subscriber, rx) = self.file_watcher.add_subscriber();
let watch_root = params.path.to_path_buf().clone();
@@ -135,20 +130,17 @@ impl FsWatchManager {
}]);
let (terminate_tx, terminate_rx) = oneshot::channel();
match self.state.lock().await.entries.entry(watch_key) {
Entry::Occupied(_) => {
return Err(invalid_request(format!(
"watchId already exists: {watch_id}"
)));
}
Entry::Vacant(entry) => {
entry.insert(WatchEntry {
terminate_tx,
_subscriber: subscriber,
_registration: registration,
});
}
}
self.state.lock().await.entries.insert(
WatchKey {
connection_id,
watch_id: watch_id.clone(),
},
WatchEntry {
terminate_tx,
_subscriber: subscriber,
_registration: registration,
},
);
let task_watch_id = watch_id.clone();
tokio::spawn(async move {
@@ -166,7 +158,19 @@ impl FsWatchManager {
let mut changed_paths = event
.paths
.into_iter()
.map(|path| AbsolutePathBuf::resolve_path_against_base(&path, &watch_root))
.filter_map(|path| {
match AbsolutePathBuf::resolve_path_against_base(&path, &watch_root) {
Ok(path) => Some(path),
Err(err) => {
warn!(
"failed to normalize watch event path ({}) for {}: {err}",
path.display(),
watch_root.display()
);
None
}
}
})
.collect::<Vec<_>>();
changed_paths.sort_by(|left, right| left.as_path().cmp(right.as_path()));
if !changed_paths.is_empty() {
@@ -183,7 +187,10 @@ impl FsWatchManager {
}
});
Ok(FsWatchResponse { path: params.path })
Ok(FsWatchResponse {
watch_id,
path: params.path,
})
}
pub(crate) async fn unwatch(
@@ -221,6 +228,7 @@ mod tests {
use codex_utils_absolute_path::AbsolutePathBuf;
use pretty_assertions::assert_eq;
use tempfile::TempDir;
use uuid::Version;
fn absolute_path(path: PathBuf) -> AbsolutePathBuf {
assert!(
@@ -241,33 +249,28 @@ mod tests {
}
#[tokio::test]
async fn watch_uses_client_id_and_tracks_the_owner_scoped_entry() {
async fn watch_returns_a_v7_id_and_tracks_the_owner_scoped_entry() {
let temp_dir = TempDir::new().expect("temp dir");
let head_path = temp_dir.path().join("HEAD");
std::fs::write(&head_path, "ref: refs/heads/main\n").expect("write HEAD");
let manager = manager_with_noop_watcher();
let path = absolute_path(head_path);
let watch_id = "watch-head".to_string();
let response = manager
.watch(
ConnectionId(1),
FsWatchParams {
watch_id: watch_id.clone(),
path: path.clone(),
},
)
.watch(ConnectionId(1), FsWatchParams { path: path.clone() })
.await
.expect("watch should succeed");
assert_eq!(response.path, path);
let watch_id = Uuid::parse_str(&response.watch_id).expect("watch id should be a UUID");
assert_eq!(watch_id.get_version(), Some(Version::SortRand));
let state = manager.state.lock().await;
assert_eq!(
state.entries.keys().cloned().collect::<HashSet<_>>(),
HashSet::from([WatchKey {
connection_id: ConnectionId(1),
watch_id,
watch_id: response.watch_id,
}])
);
}
@@ -279,11 +282,10 @@ mod tests {
std::fs::write(&head_path, "ref: refs/heads/main\n").expect("write HEAD");
let manager = manager_with_noop_watcher();
manager
let response = manager
.watch(
ConnectionId(1),
FsWatchParams {
watch_id: "watch-head".to_string(),
path: absolute_path(head_path),
},
)
@@ -291,14 +293,14 @@ mod tests {
.expect("watch should succeed");
let watch_key = WatchKey {
connection_id: ConnectionId(1),
watch_id: "watch-head".to_string(),
watch_id: response.watch_id.clone(),
};
manager
.unwatch(
ConnectionId(2),
FsUnwatchParams {
watch_id: "watch-head".to_string(),
watch_id: response.watch_id.clone(),
},
)
.await
@@ -309,7 +311,7 @@ mod tests {
.unwatch(
ConnectionId(1),
FsUnwatchParams {
watch_id: "watch-head".to_string(),
watch_id: response.watch_id,
},
)
.await
@@ -317,41 +319,6 @@ mod tests {
assert!(!manager.state.lock().await.entries.contains_key(&watch_key));
}
#[tokio::test]
async fn watch_rejects_duplicate_id_for_the_same_connection() {
let temp_dir = TempDir::new().expect("temp dir");
let head_path = temp_dir.path().join("HEAD");
let fetch_head_path = temp_dir.path().join("FETCH_HEAD");
std::fs::write(&head_path, "ref: refs/heads/main\n").expect("write HEAD");
std::fs::write(&fetch_head_path, "old-fetch\n").expect("write FETCH_HEAD");
let manager = manager_with_noop_watcher();
manager
.watch(
ConnectionId(1),
FsWatchParams {
watch_id: "watch-head".to_string(),
path: absolute_path(head_path),
},
)
.await
.expect("first watch should succeed");
let error = manager
.watch(
ConnectionId(1),
FsWatchParams {
watch_id: "watch-head".to_string(),
path: absolute_path(fetch_head_path),
},
)
.await
.expect_err("duplicate watch should fail");
assert_eq!(error.message, "watchId already exists: watch-head");
assert_eq!(manager.state.lock().await.entries.len(), 1);
}
#[tokio::test]
async fn connection_closed_removes_only_that_connections_watches() {
let temp_dir = TempDir::new().expect("temp dir");
@@ -363,31 +330,28 @@ mod tests {
std::fs::write(&packed_refs_path, "refs\n").expect("write packed-refs");
let manager = manager_with_noop_watcher();
let response = manager
let response_1 = manager
.watch(
ConnectionId(1),
FsWatchParams {
watch_id: "watch-head".to_string(),
path: absolute_path(head_path.clone()),
path: absolute_path(head_path),
},
)
.await
.expect("first watch should succeed");
manager
let response_2 = manager
.watch(
ConnectionId(1),
FsWatchParams {
watch_id: "watch-fetch-head".to_string(),
path: absolute_path(fetch_head_path),
},
)
.await
.expect("second watch should succeed");
manager
let response_3 = manager
.watch(
ConnectionId(2),
FsWatchParams {
watch_id: "watch-packed-refs".to_string(),
path: absolute_path(packed_refs_path),
},
)
@@ -407,9 +371,9 @@ mod tests {
.collect::<HashSet<_>>(),
HashSet::from([WatchKey {
connection_id: ConnectionId(2),
watch_id: "watch-packed-refs".to_string(),
watch_id: response_3.watch_id,
}])
);
assert_eq!(response.path, absolute_path(head_path));
assert_ne!(response_1.watch_id, response_2.watch_id);
}
}

View File

@@ -80,7 +80,6 @@ use codex_core::config_loader::CloudRequirementsLoader;
use codex_core::config_loader::LoaderOverrides;
use codex_exec_server::EnvironmentManager;
use codex_feedback::CodexFeedback;
use codex_login::AuthManager;
use codex_protocol::protocol::SessionSource;
use tokio::sync::mpsc;
use tokio::sync::oneshot;
@@ -380,8 +379,6 @@ fn start_uninitialized(args: InProcessStartArgs) -> InProcessClientHandle {
});
let processor_outgoing = Arc::clone(&outgoing_message_sender);
let auth_manager =
AuthManager::shared_from_config(args.config.as_ref(), args.enable_codex_api_key_env);
let (processor_tx, mut processor_rx) = mpsc::channel::<ProcessorCommand>(channel_capacity);
let mut processor_handle = tokio::spawn(async move {
let mut processor = MessageProcessor::new(MessageProcessorArgs {
@@ -396,9 +393,8 @@ fn start_uninitialized(args: InProcessStartArgs) -> InProcessClientHandle {
log_db: None,
config_warnings: args.config_warnings,
session_source: args.session_source,
auth_manager,
enable_codex_api_key_env: args.enable_codex_api_key_env,
rpc_transport: AppServerRpcTransport::InProcess,
remote_control_handle: None,
});
let mut thread_created_rx = processor.thread_created_receiver();
let mut session = ConnectionSessionState::default();
@@ -827,9 +823,6 @@ mod tests {
items: Vec::new(),
status: TurnStatus::Completed,
error: None,
started_at: None,
completed_at: Some(0),
duration_ms: None,
},
})
));

View File

@@ -7,8 +7,6 @@ use codex_core::config::ConfigBuilder;
use codex_core::config_loader::CloudRequirementsLoader;
use codex_core::config_loader::ConfigLayerStackOrdering;
use codex_core::config_loader::LoaderOverrides;
use codex_features::Feature;
use codex_login::AuthManager;
use codex_utils_cli::CliConfigOverrides;
use std::collections::HashMap;
use std::collections::HashSet;
@@ -30,7 +28,6 @@ use crate::transport::OutboundConnectionState;
use crate::transport::TransportEvent;
use crate::transport::auth::policy_from_settings;
use crate::transport::route_outgoing_envelope;
use crate::transport::start_remote_control;
use crate::transport::start_stdio_connection;
use crate::transport::start_websocket_acceptor;
use codex_analytics::AppServerRpcTransport;
@@ -45,10 +42,10 @@ use codex_core::config_loader::ConfigLoadError;
use codex_core::config_loader::TextRange as CoreTextRange;
use codex_exec_server::EnvironmentManager;
use codex_feedback::CodexFeedback;
use codex_login::AuthManager;
use codex_protocol::protocol::SessionSource;
use codex_state::log_db;
use tokio::sync::mpsc;
use tokio::sync::oneshot;
use tokio::task::JoinHandle;
use tokio_util::sync::CancellationToken;
use toml::Value as TomlValue;
@@ -399,8 +396,11 @@ pub async fn run_main_with_transport(
}
}
let auth_manager =
AuthManager::shared_from_config(&config, /*enable_codex_api_key_env*/ false);
let auth_manager = AuthManager::shared(
config.codex_home.clone(),
/*enable_codex_api_key_env*/ false,
config.cli_auth_credentials_store_mode,
);
cloud_requirements_loader(
auth_manager,
config.chatgpt_base_url,
@@ -457,9 +457,7 @@ pub async fn run_main_with_transport(
range: None,
});
}
if let Some(warning) =
codex_core::config::system_bwrap_warning(config.permissions.sandbox_policy.get())
{
if let Some(warning) = codex_core::config::system_bwrap_warning() {
config_warnings.push(ConfigWarningNotification {
summary: warning,
details: None,
@@ -502,13 +500,13 @@ pub async fn run_main_with_transport(
let feedback_layer = feedback.logger_layer();
let feedback_metadata_layer = feedback.metadata_layer();
let state_db = codex_state::StateRuntime::init(
let log_db = codex_state::StateRuntime::init(
config.sqlite_home.clone(),
config.model_provider_id.clone(),
)
.await
.ok();
let log_db = state_db.clone().map(log_db::start);
.ok()
.map(log_db::start);
let log_db_layer = log_db
.clone()
.map(|layer| layer.with_filter(Targets::new().with_default(Level::TRACE)));
@@ -535,18 +533,11 @@ pub async fn run_main_with_transport(
let single_client_mode = matches!(&transport, AppServerTransport::Stdio);
let shutdown_when_no_connections = single_client_mode;
let graceful_signal_restart_enabled = !single_client_mode;
let mut app_server_client_name_rx = None;
match transport {
AppServerTransport::Stdio => {
let (stdio_client_name_tx, stdio_client_name_rx) = oneshot::channel::<String>();
app_server_client_name_rx = Some(stdio_client_name_rx);
start_stdio_connection(
transport_event_tx.clone(),
&mut transport_accept_handles,
stdio_client_name_tx,
)
.await?;
start_stdio_connection(transport_event_tx.clone(), &mut transport_accept_handles)
.await?;
}
AppServerTransport::WebSocket { bind_address } => {
let accept_handle = start_websocket_acceptor(
@@ -558,32 +549,8 @@ pub async fn run_main_with_transport(
.await?;
transport_accept_handles.push(accept_handle);
}
AppServerTransport::Off => {}
}
let auth_manager =
AuthManager::shared_from_config(&config, /*enable_codex_api_key_env*/ false);
let remote_control_enabled = config.features.enabled(Feature::RemoteControl);
if transport_accept_handles.is_empty() && !remote_control_enabled {
return Err(std::io::Error::new(
ErrorKind::InvalidInput,
"no transport configured; use --listen or enable remote control",
));
}
let (remote_control_accept_handle, remote_control_handle) = start_remote_control(
config.chatgpt_base_url.clone(),
state_db.clone(),
auth_manager.clone(),
transport_event_tx.clone(),
transport_shutdown_token.clone(),
app_server_client_name_rx,
remote_control_enabled,
)
.await?;
transport_accept_handles.push(remote_control_accept_handle);
let outbound_handle = tokio::spawn(async move {
let mut outbound_connections = HashMap::<ConnectionId, OutboundConnectionState>::new();
loop {
@@ -642,8 +609,6 @@ pub async fn run_main_with_transport(
let processor_handle = tokio::spawn({
let outgoing_message_sender = Arc::new(OutgoingMessageSender::new(outgoing_tx));
let outbound_control_tx = outbound_control_tx;
let auth_manager =
AuthManager::shared_from_config(&config, /*enable_codex_api_key_env*/ false);
let cli_overrides: Vec<(String, TomlValue)> = cli_kv_overrides.clone();
let loader_overrides = loader_overrides_for_config_api;
let mut processor = MessageProcessor::new(MessageProcessorArgs {
@@ -658,9 +623,8 @@ pub async fn run_main_with_transport(
log_db,
config_warnings,
session_source,
auth_manager,
enable_codex_api_key_env: false,
rpc_transport: analytics_rpc_transport(transport),
remote_control_handle: Some(remote_control_handle),
});
let mut thread_created_rx = processor.thread_created_receiver();
let mut running_turn_count_rx = processor.subscribe_running_assistant_turn_count();
@@ -887,9 +851,7 @@ pub async fn run_main_with_transport(
fn analytics_rpc_transport(transport: AppServerTransport) -> AppServerRpcTransport {
match transport {
AppServerTransport::Stdio => AppServerRpcTransport::Stdio,
AppServerTransport::WebSocket { .. } | AppServerTransport::Off => {
AppServerRpcTransport::Websocket
}
AppServerTransport::WebSocket { .. } => AppServerRpcTransport::Websocket,
}
}

View File

@@ -16,7 +16,7 @@ const MANAGED_CONFIG_PATH_ENV_VAR: &str = "CODEX_APP_SERVER_MANAGED_CONFIG_PATH"
#[derive(Debug, Parser)]
struct AppServerArgs {
/// Transport endpoint URL. Supported values: `stdio://` (default),
/// `ws://IP:PORT`, `off`.
/// `ws://IP:PORT`.
#[arg(
long = "listen",
value_name = "URL",

View File

@@ -19,12 +19,10 @@ use crate::outgoing_message::ConnectionRequestId;
use crate::outgoing_message::OutgoingMessageSender;
use crate::outgoing_message::RequestContext;
use crate::transport::AppServerTransport;
use crate::transport::RemoteControlHandle;
use async_trait::async_trait;
use codex_analytics::AnalyticsEventsClient;
use codex_analytics::AppServerRpcTransport;
use codex_app_server_protocol::AppListUpdatedNotification;
use codex_app_server_protocol::AuthMode as LoginAuthMode;
use codex_app_server_protocol::ChatgptAuthTokensRefreshParams;
use codex_app_server_protocol::ChatgptAuthTokensRefreshReason;
use codex_app_server_protocol::ChatgptAuthTokensRefreshResponse;
@@ -63,10 +61,12 @@ use codex_core::ThreadManager;
use codex_core::config::Config;
use codex_core::config_loader::CloudRequirementsLoader;
use codex_core::config_loader::LoaderOverrides;
use codex_core::models_manager::collaboration_mode_presets::CollaborationModesConfig;
use codex_exec_server::EnvironmentManager;
use codex_features::Feature;
use codex_feedback::CodexFeedback;
use codex_login::AuthManager;
use codex_login::AuthMode as LoginAuthMode;
use codex_login::auth::ExternalAuth;
use codex_login::auth::ExternalAuthRefreshContext;
use codex_login::auth::ExternalAuthRefreshReason;
@@ -76,7 +76,6 @@ use codex_login::default_client::USER_AGENT_SUFFIX;
use codex_login::default_client::get_codex_user_agent;
use codex_login::default_client::set_default_client_residency_requirement;
use codex_login::default_client::set_default_originator;
use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig;
use codex_protocol::ThreadId;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::W3cTraceContext;
@@ -171,7 +170,6 @@ pub(crate) struct MessageProcessor {
config: Arc<Config>,
config_warnings: Arc<Vec<ConfigWarningNotification>>,
rpc_transport: AppServerRpcTransport,
remote_control_handle: Option<RemoteControlHandle>,
}
#[derive(Clone, Debug, Default)]
@@ -195,9 +193,8 @@ pub(crate) struct MessageProcessorArgs {
pub(crate) log_db: Option<LogDbLayer>,
pub(crate) config_warnings: Vec<ConfigWarningNotification>,
pub(crate) session_source: SessionSource,
pub(crate) auth_manager: Arc<AuthManager>,
pub(crate) enable_codex_api_key_env: bool,
pub(crate) rpc_transport: AppServerRpcTransport,
pub(crate) remote_control_handle: Option<RemoteControlHandle>,
}
impl MessageProcessor {
@@ -216,17 +213,23 @@ impl MessageProcessor {
log_db,
config_warnings,
session_source,
auth_manager,
enable_codex_api_key_env,
rpc_transport,
remote_control_handle,
} = args;
auth_manager.set_external_auth(Arc::new(ExternalAuthRefreshBridge {
outgoing: outgoing.clone(),
}));
let auth_manager = AuthManager::shared_with_external_auth(
config.codex_home.clone(),
enable_codex_api_key_env,
config.cli_auth_credentials_store_mode,
Arc::new(ExternalAuthRefreshBridge {
outgoing: outgoing.clone(),
}),
);
let thread_manager = Arc::new(ThreadManager::new(
config.as_ref(),
auth_manager.clone(),
session_source,
config.model_catalog.clone(),
config.custom_models.clone(),
CollaborationModesConfig {
default_mode_request_user_input: config
.features
@@ -234,6 +237,7 @@ impl MessageProcessor {
},
environment_manager,
));
auth_manager.set_forced_chatgpt_workspace_id(config.forced_chatgpt_workspace_id.clone());
let analytics_events_client = AnalyticsEventsClient::new(
Arc::clone(&auth_manager),
config.chatgpt_base_url.trim_end_matches('/').to_string(),
@@ -289,7 +293,6 @@ impl MessageProcessor {
config,
config_warnings: Arc::new(config_warnings),
rpc_transport,
remote_control_handle,
}
}
@@ -849,7 +852,6 @@ impl MessageProcessor {
connection_id,
other,
session.app_server_client_name.clone(),
session.client_version.clone(),
request_context,
)
.boxed()
@@ -870,8 +872,16 @@ impl MessageProcessor {
request_id: ConnectionRequestId,
params: ConfigValueWriteParams,
) {
let result = self.config_api.write_value(params).await;
self.handle_config_mutation_result(request_id, result).await
match self.config_api.write_value(params).await {
Ok(response) => {
self.codex_message_processor.clear_plugin_related_caches();
self.codex_message_processor
.maybe_start_plugin_startup_tasks_for_latest_config()
.await;
self.outgoing.send_response(request_id, response).await;
}
Err(error) => self.outgoing.send_error(request_id, error).await,
}
}
async fn handle_config_batch_write(
@@ -879,8 +889,8 @@ impl MessageProcessor {
request_id: ConnectionRequestId,
params: ConfigBatchWriteParams,
) {
let result = self.config_api.batch_write(params).await;
self.handle_config_mutation_result(request_id, result).await;
self.handle_config_mutation_result(request_id, self.config_api.batch_write(params).await)
.await;
}
async fn handle_experimental_feature_enablement_set(
@@ -889,15 +899,23 @@ impl MessageProcessor {
params: ExperimentalFeatureEnablementSetParams,
) {
let should_refresh_apps_list = params.enablement.get("apps").copied() == Some(true);
let result = self
match self
.config_api
.set_experimental_feature_enablement(params)
.await;
let is_ok = result.is_ok();
self.handle_config_mutation_result(request_id, result).await;
if should_refresh_apps_list && is_ok {
self.refresh_apps_list_after_experimental_feature_enablement_set()
.await;
.await
{
Ok(response) => {
self.codex_message_processor.clear_plugin_related_caches();
self.codex_message_processor
.maybe_start_plugin_startup_tasks_for_latest_config()
.await;
self.outgoing.send_response(request_id, response).await;
if should_refresh_apps_list {
self.refresh_apps_list_after_experimental_feature_enablement_set()
.await;
}
}
Err(error) => self.outgoing.send_error(request_id, error).await,
}
}
@@ -916,11 +934,7 @@ impl MessageProcessor {
return;
}
};
let auth = self.auth_manager.auth().await;
if !config.features.apps_enabled_for_auth(
auth.as_ref()
.is_some_and(codex_login::CodexAuth::is_chatgpt_auth),
) {
if !config.features.apps_enabled(Some(&self.auth_manager)).await {
return;
}
@@ -974,36 +988,16 @@ impl MessageProcessor {
) {
match result {
Ok(response) => {
self.handle_config_mutation().await;
self.codex_message_processor.clear_plugin_related_caches();
self.codex_message_processor
.maybe_start_plugin_startup_tasks_for_latest_config()
.await;
self.outgoing.send_response(request_id, response).await;
}
Err(error) => self.outgoing.send_error(request_id, error).await,
}
}
async fn handle_config_mutation(&self) {
self.codex_message_processor.handle_config_mutation();
let Some(remote_control_handle) = &self.remote_control_handle else {
return;
};
match self
.config_api
.load_latest_config(/*fallback_cwd*/ None)
.await
{
Ok(config) => {
remote_control_handle.set_enabled(config.features.enabled(Feature::RemoteControl));
}
Err(error) => {
tracing::warn!(
"failed to load config for remote control enablement refresh after config mutation: {}",
error.message
);
}
}
}
async fn handle_config_requirements_read(&self, request_id: ConnectionRequestId) {
match self.config_api.config_requirements_read().await {
Ok(response) => self.outgoing.send_response(request_id, response).await,

View File

@@ -27,7 +27,6 @@ use codex_core::config_loader::CloudRequirementsLoader;
use codex_core::config_loader::LoaderOverrides;
use codex_exec_server::EnvironmentManager;
use codex_feedback::CodexFeedback;
use codex_login::AuthManager;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::W3cTraceContext;
use opentelemetry::global;
@@ -235,8 +234,6 @@ fn build_test_processor(
) {
let (outgoing_tx, outgoing_rx) = mpsc::channel(16);
let outgoing = Arc::new(OutgoingMessageSender::new(outgoing_tx));
let auth_manager =
AuthManager::shared_from_config(config.as_ref(), /*enable_codex_api_key_env*/ false);
let processor = MessageProcessor::new(MessageProcessorArgs {
outgoing,
arg0_paths: Arg0DispatchPaths::default(),
@@ -249,9 +246,8 @@ fn build_test_processor(
log_db: None,
config_warnings: Vec::new(),
session_source: SessionSource::VSCode,
auth_manager,
enable_codex_api_key_env: false,
rpc_transport: AppServerRpcTransport::Stdio,
remote_control_handle: None,
});
(processor, outgoing_rx)
}

View File

@@ -4,7 +4,7 @@ use codex_app_server_protocol::Model;
use codex_app_server_protocol::ModelUpgradeInfo;
use codex_app_server_protocol::ReasoningEffortOption;
use codex_core::ThreadManager;
use codex_models_manager::manager::RefreshStrategy;
use codex_core::models_manager::manager::RefreshStrategy;
use codex_protocol::openai_models::ModelPreset;
use codex_protocol::openai_models::ReasoningEffortPreset;
@@ -42,7 +42,6 @@ fn model_from_preset(preset: ModelPreset) -> Model {
default_reasoning_effort: preset.default_reasoning_effort,
input_modalities: preset.input_modalities,
supports_personality: preset.supports_personality,
additional_speed_tiers: preset.additional_speed_tiers,
is_default: preset.is_default,
}
}

View File

@@ -16,7 +16,6 @@ use std::sync::Weak;
use tokio::sync::Mutex;
use tokio::sync::mpsc;
use tokio::sync::oneshot;
use tracing::error;
type PendingInterruptQueue = Vec<(
ConnectionRequestId,
@@ -45,7 +44,6 @@ pub(crate) enum ThreadListenerCommand {
/// Per-conversation accumulation of the latest states e.g. error message while a turn runs.
#[derive(Default, Clone)]
pub(crate) struct TurnSummary {
pub(crate) started_at: Option<i64>,
pub(crate) file_change_started: HashSet<String>,
pub(crate) command_execution_started: HashSet<String>,
pub(crate) last_error: Option<TurnError>,
@@ -111,50 +109,13 @@ impl ThreadState {
}
pub(crate) fn track_current_turn_event(&mut self, event: &EventMsg) {
if let EventMsg::TurnStarted(payload) = event {
self.turn_summary.started_at = payload.started_at;
}
self.current_turn_history.handle_event(event);
if matches!(event, EventMsg::TurnAborted(_) | EventMsg::TurnComplete(_))
&& !self.current_turn_history.has_active_turn()
{
if !self.current_turn_history.has_active_turn() {
self.current_turn_history.reset();
}
}
}
pub(crate) async fn resolve_server_request_on_thread_listener(
thread_state: &Arc<Mutex<ThreadState>>,
request_id: RequestId,
) {
let (completion_tx, completion_rx) = oneshot::channel();
let listener_command_tx = {
let state = thread_state.lock().await;
state.listener_command_tx()
};
let Some(listener_command_tx) = listener_command_tx else {
error!("failed to remove pending client request: thread listener is not running");
return;
};
if listener_command_tx
.send(ThreadListenerCommand::ResolveServerRequest {
request_id,
completion_tx,
})
.is_err()
{
error!(
"failed to remove pending client request: thread listener command channel is closed"
);
return;
}
if let Err(err) = completion_rx.await {
error!("failed to remove pending client request: {err}");
}
}
struct ThreadEntry {
state: Arc<Mutex<ThreadState>>,
connection_ids: HashSet<ConnectionId>,

Some files were not shown because too many files have changed in this diff Show More