进程工具(T-05):exec(单发)、exec_command / write_stdin(有状态会话)。
移植自 OpenAI Codex CLI(Apache-2.0,Copyright 2025 OpenAI;见模块根 THIRD-PARTY-NOTICES.md),经 Keelson
Process/* 转写:
两个协议,宿主接沙箱的缝:
IExecBackend(起进程):缺省 local-backend(ProcessBuilder);argv-prefix-backend 一行把每条命令包进
bwrap … / firejail … / ssh host …。会话只经它。ICommandRunner(单发跑完再返回):缺省 backend-runner;可在这里做「沙箱里失败 → 问人 → 重跑」的编排。
Keelson.Agent.Sandbox 不移植。不做 PTY(会话是管道,stdin 可写)。进程工具(T-05):exec(单发)、exec_command / write_stdin(有状态会话)。
移植自 OpenAI Codex CLI(Apache-2.0,Copyright 2025 OpenAI;见模块根 THIRD-PARTY-NOTICES.md),经 Keelson
`Process/*` 转写:
- HeadTailBuffer ← codex-rs/core/src/unified_exec/head_tail_buffer.rs(头尾各半、中间丢弃并计数);
- 单发执行 ← codex-rs/core/src/exec.rs(时限 10 s、超时退出码 124、128 + 信号、杀后排空 2 s);
- 固定环境 ← unified_exec/process_manager.rs 的 UNIFIED_EXEC_ENV(不带 CODEX_CI);
- 会话 ← unified_exec/{mod.rs, process_manager.rs}(yield 250–30000 ms、空轮询 ≥ 5000 ms、64 个会话、
最近 8 个不驱逐、先驱逐已退出的、\u0003 中断);
- 结果文本 ← core/src/tools/context.rs 与 core/src/tools/mod.rs(format_exec_output_for_model)。
两个协议,宿主接沙箱的缝:
- `IExecBackend`(起进程):缺省 `local-backend`(ProcessBuilder);`argv-prefix-backend` 一行把每条命令包进
`bwrap …` / `firejail …` / `ssh host …`。会话只经它。
- `ICommandRunner`(单发跑完再返回):缺省 `backend-runner`;可在这里做「沙箱里失败 → 问人 → 重跑」的编排。
Keelson.Agent.Sandbox 不移植。不做 PTY(会话是管道,stdin 可写)。(argv-prefix-backend base prefix)把每条命令包进前缀再交给 base:(argv-prefix-backend (local-backend) ["bwrap" "--ro-bind" "/" "/" …])。
把每条命令包进前缀再交给 base:`(argv-prefix-backend (local-backend) ["bwrap" "--ro-bind" "/" "/" …])`。
(close-sessions! w)结束工作区的全部会话(宿主在会话结束时调)。
结束工作区的全部会话(宿主在会话结束时调)。
(exec {:as args3096
:or {workdir nil timeout_ms nil}
:keys [command workdir timeout_ms]})运行一条命令并回它的输出。command 是 argv,原样交给 execvp(),不自动套 shell:要 shell 就写 ["bash", "-lc", "…"]。总是设 workdir,除非确有必要不要用 cd。缺省时限 10 秒(timeout_ms 可调),超时退出码 124;stdin 关闭。
运行一条命令并回它的输出。command 是 argv,原样交给 execvp(),不自动套 shell:要 shell 就写 ["bash", "-lc", "…"]。总是设 workdir,除非确有必要不要用 cd。缺省时限 10 秒(timeout_ms 可调),超时退出码 124;stdin 关闭。
(exec-command* w
{:keys [cmd workdir yield_time_ms max_output_tokens shell
login]})(exec-text {:keys [exit-code timed-out? duration-ms output]} max-bytes)Codex format_exec_output_for_model:退出码 / 耗时 / 截断改变了行数时总行数 / 输出(头尾截断)。
Codex format_exec_output_for_model:退出码 / 耗时 / 截断改变了行数时总行数 / 输出(头尾截断)。
(exec_command
{:as args3189
:or {workdir nil yield_time_ms nil max_output_tokens nil shell nil login nil}
:keys [cmd workdir yield_time_ms max_output_tokens shell login]})经 shell 运行一条命令,等至多 yield_time_ms:跑完了回退出码;还在跑就回一个会话 ID,之后用 write_stdin 写输入或轮询输出。适合长时间运行或交互式命令(dev server、REPL、tail -f)。
经 shell 运行一条命令,等至多 yield_time_ms:跑完了回退出码;还在跑就回一个会话 ID,之后用 write_stdin 写输入或轮询输出。适合长时间运行或交互式命令(dev server、REPL、tail -f)。
进程工具给子进程加的固定环境(Codex UNIFIED_EXEC_ENV):关颜色、哑终端、UTF-8 区域、分页器换成 cat—— 模型读的是纯文本,交互式分页器会让命令挂住。
进程工具给子进程加的固定环境(Codex UNIFIED_EXEC_ENV):关颜色、哑终端、UTF-8 区域、分页器换成 cat—— 模型读的是纯文本,交互式分页器会让命令挂住。
(head-tail-buffer max-bytes)有上限的输出缓冲:头、尾各占一半预算(奇数时尾多一字节)。不是线程安全的。
有上限的输出缓冲:头、尾各占一半预算(奇数时尾多一字节)。不是线程安全的。
(run-command runner req)单发跑完:req {:argv :cwd :env :timeout-ms :output-bytes} ⇒ {:exit-code :timed-out? :duration-ms :output bytes :omitted :stdout :stderr}。
单发跑完:req {:argv :cwd :env :timeout-ms :output-bytes}
⇒ {:exit-code :timed-out? :duration-ms :output bytes :omitted :stdout :stderr}。(start-process backend req)req {:argv [..] :cwd ".."|nil :env {k v|nil}}(env 叠加在继承环境之上,nil 值 = 删除)⇒ java.lang.Process。
req {:argv [..] :cwd ".."|nil :env {k v|nil}}(env 叠加在继承环境之上,nil 值 = 删除)⇒ java.lang.Process。
(omitted b)因上限从中间丢掉的字节数。
因上限从中间丢掉的字节数。
(push! b bytes off len)追加一段:先填头,填满后进尾,尾超预算丢最老的。
追加一段:先填头,填满后进尾,尾超预算丢最老的。
(to-bytes b)(to-bytes b marker-fn)留着的输出:头 + 尾;给了 marker-fn 且有省略时头尾之间插一行 (marker-fn omitted)。
留着的输出:头 + 尾;给了 marker-fn 且有省略时头尾之间插一行 (marker-fn omitted)。
(total b)见过的全部字节(含丢掉的)。
见过的全部字节(含丢掉的)。
(local-backend)本机 ProcessBuilder 后端(不带沙箱:宿主须显式选它)。
本机 ProcessBuilder 后端(**不带沙箱**:宿主须显式选它)。
(prune-candidate meta protected)驱逐谁(Codex process_id_to_prune_from_meta):按最近使用排,最近的 protected 个不动; 其余按最久没用排,先挑已退出的,没有就挑最久没用的。meta: [{:id :last-used :exited?}]
驱逐谁(Codex process_id_to_prune_from_meta):按最近使用排,最近的 protected 个不动;
其余按最久没用排,先挑已退出的,没有就挑最久没用的。meta: [{:id :last-used :exited?}](run-on-backend backend {:keys [argv cwd env timeout-ms output-bytes]})单发执行的本体:起进程、关 stdin(读 stdin 的命令立即见 EOF 而不是挂住)、收输出; 超时 ⇒ 杀进程树、再等至多 2 s 收尾、退出码 124。
单发执行的本体:起进程、关 stdin(读 stdin 的命令立即见 EOF 而不是挂住)、收输出; 超时 ⇒ 杀进程树、再等至多 2 s 收尾、退出码 124。
(truncate-text s max-bytes)按 UTF-8 字节头尾截断文本(中间插省略标记)。
按 UTF-8 字节头尾截断文本(中间插省略标记)。
(write_stdin {:as args3195
:or {chars nil yield_time_ms nil max_output_tokens nil}
:keys [session_id chars yield_time_ms max_output_tokens]})往 exec_command 开的会话写 stdin 并收一段输出。chars 为空串 = 只轮询不写(至少等 5000 ms);"\u0003" = 发中断(Ctrl-C)。
往 exec_command 开的会话写 stdin 并收一段输出。chars 为空串 = 只轮询不写(至少等 5000 ms);"\u0003" = 发中断(Ctrl-C)。
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |