{"id":1628,"date":"2026-04-26T15:48:27","date_gmt":"2026-04-26T07:48:27","guid":{"rendered":"https:\/\/blog.shangwendada.top\/?p=1628"},"modified":"2026-04-26T17:52:03","modified_gmt":"2026-04-26T09:52:03","slug":"codex-main-runtime-%e6%9e%b6%e6%9e%84%e6%b7%b1%e6%8b%86%ef%bc%9a%e8%ae%b0%e5%bf%86%e3%80%81%e5%8e%8b%e7%bc%a9%e3%80%81%e5%b9%b6%e8%a1%8c%e6%89%a7%e8%a1%8c%e4%b8%8e%e5%8d%a1%e6%ad%bb%e8%af%86%e5%88%ab","status":"publish","type":"post","link":"https:\/\/blog.shangwendada.top\/index.php\/2026\/04\/26\/codex-main-runtime-%e6%9e%b6%e6%9e%84%e6%b7%b1%e6%8b%86%ef%bc%9a%e8%ae%b0%e5%bf%86%e3%80%81%e5%8e%8b%e7%bc%a9%e3%80%81%e5%b9%b6%e8%a1%8c%e6%89%a7%e8%a1%8c%e4%b8%8e%e5%8d%a1%e6%ad%bb%e8%af%86%e5%88%ab\/","title":{"rendered":"codex-main Runtime \u67b6\u6784\u6df1\u62c6\uff1a\u8bb0\u5fc6\u3001\u538b\u7f29\u3001\u5e76\u884c\u6267\u884c\u4e0e\u5361\u6b7b\u8bc6\u522b"},"content":{"rendered":"<h1>codex-main Runtime \u67b6\u6784\u6df1\u62c6\uff1a\u8bb0\u5fc6\u3001\u538b\u7f29\u3001\u5e76\u884c\u6267\u884c\u4e0e\u5361\u6b7b\u8bc6\u522b<\/h1>\n<p>\u672c\u6587\u9762\u5411 AppCheckMaster \u7684 APK \u5b89\u5168\u5ba1\u8ba1\u5de5\u4f5c\u6d41\uff0c\u62c6\u89e3 <code>backend\/codex-main<\/code> \u5982\u4f55\u628a\u4e00\u6b21\u201c\u7f16\u7801\/\u5ba1\u8ba1\u4efb\u52a1\u201d\u53d8\u6210\u53ef\u6301\u7eed\u3001\u591a\u8f6e\u3001\u53ef\u538b\u7f29\u3001\u53ef\u5e76\u884c\u3001\u53ef\u6062\u590d\u7684 runtime\u3002<\/p>\n<p>\u91cd\u70b9\u56de\u7b54\u56db\u4e2a\u95ee\u9898\uff1a<\/p>\n<ul>\n<li>codex-main \u5982\u4f55\u5904\u7406\u201c\u8bb0\u5fc6\u201d\uff1a\u5f53\u524d\u7ebf\u7a0b\u5386\u53f2\u3001\u957f\u671f memories\u3001\u5916\u90e8\u4e0a\u4e0b\u6587\u6c61\u67d3\u4e0e\u5f15\u7528\u56de\u6536\u3002<\/li>\n<li>codex-main \u5982\u4f55\u505a\u201c\u538b\u7f29\u201d\uff1a\u4ec0\u4e48\u65f6\u5019\u538b\u7f29\u3001\u538b\u7f29\u540e\u5982\u4f55\u66ff\u6362\u5386\u53f2\u3001\u4e3a\u4ec0\u4e48\u8981\u91cd\u7f6e\u6a21\u578b\u8fde\u63a5\u3002<\/li>\n<li>codex-main \u5982\u4f55\u505a\u201c\u5e76\u884c\u6267\u884c\u201d\uff1a\u6a21\u578b\u534f\u8bae\u91cc\u7684\u5e76\u884c\u5de5\u5177\u8c03\u7528\u5982\u4f55\u843d\u5230 runtime \u7684\u5e76\u884c\u95f8\u95e8\u3002<\/li>\n<li>codex-main \u5982\u4f55\u8bc6\u522b\u201c\u957f\u547d\u4ee4\/\u5361\u6b7b\u201d\uff1a\u666e\u901a shell \u8d85\u65f6\u3001\u8f93\u51fa\u7ba1\u9053\u5361\u6b7b\u3001\u957f\u9a7b\u8fdb\u7a0b yield \u4e0e\u540e\u53f0\u4f1a\u8bdd\u3002<\/li>\n<\/ul>\n<p>\u672c\u6587\u6240\u6709\u67b6\u6784\u56fe\u548c\u65f6\u5e8f\u56fe\u90fd\u4f7f\u7528 Mermaid \u4ee3\u7801\u5757\u3002\u53ea\u8981 Markdown \u6e32\u67d3\u5668\u652f\u6301 Mermaid\uff0c\u56fe\u7247\u5c31\u53ef\u4ee5\u76f4\u63a5\u6e32\u67d3\uff0c\u4e0d\u4f9d\u8d56\u989d\u5916\u56fe\u7247\u8d44\u6e90\u3002<\/p>\n<hr \/>\n<h2>0. \u603b\u89c8\uff1acodex-main \u662f\u4e00\u4e2a turn runtime<\/h2>\n<p>codex-main \u7684\u6838\u5fc3\u4e0d\u662f\u201c\u53d1\u4e00\u6761 prompt \u7ed9\u6a21\u578b\u201d\uff0c\u800c\u662f\u4e00\u4e2a\u56f4\u7ed5 <strong>turn<\/strong> \u8fd0\u884c\u7684 runtime\uff1a<\/p>\n<ul>\n<li><code>Session<\/code> \u6301\u6709\u7ebf\u7a0b\u7ea7\u72b6\u6001\uff0c\u4f8b\u5982\u5386\u53f2\u3001\u914d\u7f6e\u3001\u5de5\u5177\u6ce8\u518c\u3001\u5ba1\u6279\u72b6\u6001\u3001\u957f\u671f\u8bb0\u5fc6\u5f00\u5173\u3002<\/li>\n<li><code>TurnContext<\/code> \u6301\u6709\u672c\u8f6e\u8bf7\u6c42\u7684\u4e0a\u4e0b\u6587\uff0c\u4f8b\u5982\u6a21\u578b\u4fe1\u606f\u3001\u5de5\u5177\u96c6\u5408\u3001sandbox\u3001\u5ba1\u6279\u7b56\u7565\u3002<\/li>\n<li><code>ModelClientSession<\/code> \u6301\u6709\u672c\u8f6e\u6a21\u578b\u8fde\u63a5\u72b6\u6001\uff0c\u4f8b\u5982 WebSocket \u8fde\u63a5\u3001<code>previous_response_id<\/code>\u3001<code>x-codex-turn-state<\/code>\u3002<\/li>\n<li><code>ContextManager<\/code> \u6301\u6709\u77ed\u671f\u5bf9\u8bdd\u5386\u53f2\uff0c\u5e76\u8d1f\u8d23\u9001\u5165\u6a21\u578b\u524d\u7684\u5386\u53f2\u5f52\u4e00\u5316\u3002<\/li>\n<li><code>ToolCallRuntime<\/code> \u8d1f\u8d23\u628a\u6a21\u578b\u8f93\u51fa\u7684\u5de5\u5177\u8c03\u7528\u5e76\u884c\u6216\u4e32\u884c\u6267\u884c\u3002<\/li>\n<li><code>Compact<\/code> \u8d1f\u8d23\u5728\u4e0a\u4e0b\u6587\u53d8\u957f\u65f6\uff0c\u628a\u65e7\u5386\u53f2\u53d8\u6210\u6458\u8981\u6216\u8fdc\u7aef compact \u540e\u7684\u65b0\u5386\u53f2\u3002<\/li>\n<li><code>Memories<\/code> \u8d1f\u8d23\u8de8\u7ebf\u7a0b\u957f\u671f\u8bb0\u5fc6\u7684\u540e\u53f0\u62bd\u53d6\u3001\u5408\u5e76\u3001\u5f15\u7528\u4e0e\u6c61\u67d3\u63a7\u5236\u3002<\/li>\n<li><code>UnifiedExec<\/code> \u8d1f\u8d23\u957f\u547d\u4ee4\u3001\u4ea4\u4e92\u5f0f\u547d\u4ee4\u3001\u540e\u53f0\u547d\u4ee4\u7684\u751f\u547d\u5468\u671f\u3002<\/li>\n<\/ul>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189321020.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189321020.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/p>\n<p>\u4e00\u4e2a\u5f88\u5b9e\u7528\u7684\u7406\u89e3\u65b9\u5f0f\u662f\uff1a<\/p>\n<blockquote>\n<p>turn \u662f\u6700\u5c0f\u8c03\u5ea6\u5355\u5143\uff0chistory \u662f\u6a21\u578b\u8f93\u5165\u7684\u4e8b\u5b9e\u6765\u6e90\uff0ctool runtime \u662f\u526f\u4f5c\u7528\u6267\u884c\u5c42\uff0ccompact\/memories \u662f\u4e0a\u4e0b\u6587\u751f\u547d\u652f\u6301\u7cfb\u7edf\u3002<\/p>\n<\/blockquote>\n<hr \/>\n<h2>1. \u4e00\u6b21\u7f16\u7801\u4efb\u52a1\u7684\u4e3b\u94fe\u8def<\/h2>\n<p>\u4e00\u6b21\u7f16\u7801\u6216\u5b89\u5168\u5ba1\u8ba1\u4efb\u52a1\u8fdb\u5165 codex-main \u540e\uff0c\u5927\u81f4\u7ecf\u5386\u8fd9\u4e9b\u6b65\u9aa4\uff1a<\/p>\n<ol>\n<li>\u6784\u5efa <code>TurnContext<\/code>\uff0c\u51b3\u5b9a\u672c\u8f6e\u7528\u4ec0\u4e48\u6a21\u578b\u3001\u4ec0\u4e48\u5de5\u5177\u3001\u4ec0\u4e48 sandbox\u3001\u4ec0\u4e48\u5ba1\u6279\u7b56\u7565\u3002<\/li>\n<li>\u4ece <code>ContextManager<\/code> \u53d6\u51fa\u6a21\u578b\u53ef\u89c1\u5386\u53f2\uff0c\u5e76\u505a\u5f52\u4e00\u5316\u3002<\/li>\n<li>\u8fdb\u5165 <code>ModelClientSession.stream(...)<\/code>\uff0c\u4f18\u5148\u4f7f\u7528 WebSocket\uff0c\u5fc5\u8981\u65f6\u56de\u9000 HTTP SSE\u3002<\/li>\n<li>\u6a21\u578b\u6d41\u5f0f\u8fd4\u56de response item\u3002<\/li>\n<li>\u666e\u901a\u6587\u672c\u5199\u5165\u5386\u53f2\u5e76\u53d1\u7ed9\u524d\u7aef\u3002<\/li>\n<li>\u5de5\u5177\u8c03\u7528\u4ea4\u7ed9 <code>ToolRouter<\/code> \u89e3\u6790\uff0c\u518d\u4ea4\u7ed9 <code>ToolCallRuntime<\/code> \u6267\u884c\u3002<\/li>\n<li>\u5de5\u5177\u8f93\u51fa\u56de\u5199\u5386\u53f2\u3002<\/li>\n<li>\u5982\u679c\u9700\u8981 follow-up\uff0c\u518d\u5e26\u7740\u5de5\u5177\u7ed3\u679c\u7ee7\u7eed\u91c7\u6837\u3002<\/li>\n<li>\u5982\u679c token \u89e6\u9876\u6216\u6a21\u578b\u5207\u6362\u5bfc\u81f4\u4e0a\u4e0b\u6587\u4e0d\u8db3\uff0c\u89e6\u53d1 compact\u3002<\/li>\n<li>\u672c\u8f6e\u7ed3\u675f\u540e\uff0cruntime \u6301\u4e45\u5316\u72b6\u6001\uff0c\u5e76\u628a\u53ef\u7528\u4fe1\u606f\u63d0\u4f9b\u7ed9\u540e\u7eed turn\u3002<\/li>\n<\/ol>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777197111037.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777197111037.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/p>\n<h3>\u5173\u952e\u4ee3\u7801\u8282\u9009\uff1aturn \u8d1f\u8d23\u4e32\u8d77\u6240\u6709 runtime \u80fd\u529b<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/session\/turn.rs<\/code><\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\uff1a\u91c7\u6837\u524d\u5148\u5224\u65ad\u662f\u5426\u9700\u8981\u538b\u7f29\u3002\nlet auto_compact_limit = turn_context\n    .model_info\n    .auto_compact_token_limit()\n    .unwrap_or(i64::MAX);\n\nlet compacted = run_pre_sampling_compact(&amp;sess, &amp;turn_context).await;\nif compacted {\n    client_session.reset_websocket_session();\n}<\/code><\/pre>\n<p>\u8fd9\u6bb5\u903b\u8f91\u8bf4\u660e\uff1a\u538b\u7f29\u4e0d\u662f\u6a21\u578b\u63d0\u793a\u8bcd\u91cc\u7684\u201c\u81ea\u89c9\u884c\u4e3a\u201d\uff0c\u800c\u662f runtime \u5728\u91c7\u6837\u524d\u4e3b\u52a8\u6267\u884c\u7684\u4e0a\u4e0b\u6587\u7ef4\u62a4\u52a8\u4f5c\u3002\u538b\u7f29\u540e\u8981\u91cd\u7f6e WebSocket\uff0c\u56e0\u4e3a\u5386\u53f2\u88ab\u6539\u5199\uff0c\u65e7\u7684 <code>previous_response_id<\/code> \/ \u589e\u91cf\u4e0a\u4e0b\u6587\u4e0d\u518d\u53ef\u9760\u3002<\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\uff1a\u628a\u5386\u53f2\u8f6c\u6210\u6a21\u578b\u8f93\u5165\u3002\nlet input = sess\n    .clone_history()\n    .await\n    .for_prompt(&amp;turn_context.model_info.input_modalities);<\/code><\/pre>\n<p>\u8fd9\u91cc\u4f53\u73b0\u4e86 codex-main \u7684\u4e00\u4e2a\u91cd\u8981\u8bbe\u8ba1\uff1a\u6a21\u578b\u8f93\u5165\u4e0d\u662f\u4ece\u7ec8\u7aef transcript \u62fc\u51fa\u6765\u7684\uff0c\u800c\u662f\u4ece runtime-owned history \u6295\u5f71\u51fa\u6765\u7684\u3002<\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\uff1a\u5de5\u5177\u8f93\u51fa\u540e\uff0c\u5982\u679c\u8fd8\u9700\u8981\u6a21\u578b\u7ee7\u7eed\u63a8\u7406\uff0c\u5c31\u7ee7\u7eed\u4e00\u8f6e\u91c7\u6837\u3002\nif token_limit_reached &amp;&amp; needs_follow_up {\n    run_auto_compact(\n        sess.clone(),\n        turn_context.clone(),\n        client_session.clone(),\n        auto_compact_limit,\n        InitialContextInjection::BeforeLastUserMessage,\n        CompactReason::ContextLimit,\n        CompactTrigger::MidTurn,\n    )\n    .await?;\n\n    client_session.reset_websocket_session();\n    continue;\n}<\/code><\/pre>\n<p>\u8fd9\u6bb5\u662f\u201c\u7f16\u7801\u4efb\u52a1\u4e0d\u4f1a\u56e0\u4e3a\u4e2d\u9014\u4e0a\u4e0b\u6587\u6ee1\u4e86\u5c31\u6b7b\u6389\u201d\u7684\u5173\u952e\u3002\u6a21\u578b\u521a\u8c03\u7528\u5b8c\u5de5\u5177\u3001\u8fd8\u9700\u8981\u770b\u7ed3\u679c\u7ee7\u7eed\u505a\u4e8b\u65f6\uff0c\u5982\u679c\u4e0a\u4e0b\u6587\u89e6\u9876\uff0cruntime \u4f1a\u5148 compact\uff0c\u518d\u7ee7\u7eed follow-up\u3002<\/p>\n<hr \/>\n<h2>2. \u8bb0\u5fc6\u7cfb\u7edf\uff1a\u77ed\u671f\u5386\u53f2 + \u957f\u671f memories<\/h2>\n<p>codex-main \u7684\u201c\u8bb0\u5fc6\u201d\u5206\u4e24\u5c42\uff1a<\/p>\n<ul>\n<li><strong>\u77ed\u671f\u5386\u53f2<\/strong>\uff1a\u5f53\u524d\u7ebf\u7a0b\u7684 <code>ResponseItem<\/code> \u5217\u8868\uff0c\u7531 <code>ContextManager<\/code> \u7ba1\u7406\u3002\u5b83\u51b3\u5b9a\u4e0b\u4e00\u6b21\u6a21\u578b\u5230\u5e95\u80fd\u770b\u5230\u4ec0\u4e48\u3002<\/li>\n<li><strong>\u957f\u671f memories<\/strong>\uff1a\u8de8\u7ebf\u7a0b\u540e\u53f0\u62bd\u53d6\u548c\u5408\u5e76\u7684\u8bb0\u5fc6\uff0c\u7531 <code>memories<\/code> pipeline \u548c state DB \u7ba1\u7406\u3002\u5b83\u89e3\u51b3\u201c\u53e6\u4e00\u4e2a\u4f1a\u8bdd\u91cc\u5b66\u5230\u7684\u504f\u597d\u3001\u9879\u76ee\u4e8b\u5b9e\u3001\u5de5\u4f5c\u65b9\u5f0f\u5982\u4f55\u590d\u7528\u201d\u7684\u95ee\u9898\u3002<\/li>\n<\/ul>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189385243.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189385243.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/p>\n<h3>2.1 \u77ed\u671f\u5386\u53f2\uff1aContextManager \u662f\u6a21\u578b\u8f93\u5165\u7684\u4e8b\u5b9e\u6765\u6e90<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/context_manager\/history.rs<\/code><\/p>\n<pre><code class=\"language-rust\">pub(crate) struct ContextManager {\n    \/\/\/ Items are stored oldest first.\n    items: Vec&lt;ResponseItem&gt;,\n    \/\/\/ Incremented any time history is rewritten, for example compaction.\n    history_version: u64,\n    token_info: Option&lt;TokenUsageInfo&gt;,\n    reference_context_item: Option&lt;TurnContextItem&gt;,\n}<\/code><\/pre>\n<p>\u5b57\u6bb5\u89e3\u91ca\uff1a<\/p>\n<ul>\n<li><code>items<\/code>\uff1a\u6a21\u578b\u53ef\u89c1\u5386\u53f2\u7684\u539f\u59cb\u6761\u76ee\uff0c\u6309\u65f6\u95f4\u4ece\u65e7\u5230\u65b0\u4fdd\u5b58\u3002<\/li>\n<li><code>history_version<\/code>\uff1a\u5386\u53f2\u88ab\u91cd\u5199\u65f6\u9012\u589e\uff0c\u4f8b\u5982 compact\u3001rollback\u3002\u5b83\u8ba9\u5176\u4ed6\u7ec4\u4ef6\u77e5\u9053\u201c\u4e4b\u524d\u770b\u5230\u7684\u5386\u53f2\u5feb\u7167\u5df2\u7ecf\u8fc7\u671f\u201d\u3002<\/li>\n<li><code>token_info<\/code>\uff1a\u6700\u8fd1\u4e00\u6b21 token \u4f30\u7b97\u6216\u5b9e\u9645\u4f7f\u7528\u60c5\u51b5\uff0c\u7528\u4e8e\u5224\u65ad\u662f\u5426\u9700\u8981 compact\u3002<\/li>\n<li><code>reference_context_item<\/code>\uff1a\u538b\u7f29\u540e\u4fdd\u7559\u7684\u4e0a\u4e0b\u6587\u57fa\u7ebf\uff0c\u7528\u4e8e\u907f\u514d\u628a\u65e7 context \u91cd\u590d\u6ce8\u5165\u3002<\/li>\n<\/ul>\n<pre><code class=\"language-rust\">pub(crate) fn for_prompt(mut self, input_modalities: &amp;[InputModality]) -&gt; Vec&lt;ResponseItem&gt; {\n    self.normalize_history(input_modalities);\n    self.items\n        .retain(|item| !matches!(item, ResponseItem::GhostSnapshot { .. }));\n    self.items\n}<\/code><\/pre>\n<p><code>for_prompt()<\/code> \u662f\u77ed\u671f\u8bb0\u5fc6\u8fdb\u5165\u6a21\u578b\u524d\u7684\u6700\u540e\u4e00\u9053\u95e8\u3002\u5b83\u505a\u4e24\u4ef6\u4e8b\uff1a<\/p>\n<ul>\n<li>\u8c03\u7528 <code>normalize_history(...)<\/code> \u4fee\u6b63\u5386\u53f2\u7ed3\u6784\uff0c\u4f8b\u5982\u79fb\u9664\u6ca1\u6709\u5bf9\u5e94\u8c03\u7528\u7684 orphan tool output\u3002<\/li>\n<li>\u79fb\u9664 <code>GhostSnapshot<\/code> \u8fd9\u7c7b runtime \u5185\u90e8\u8f85\u52a9\u9879\uff0c\u907f\u514d\u6c61\u67d3\u6a21\u578b\u4e0a\u4e0b\u6587\u3002<\/li>\n<\/ul>\n<pre><code class=\"language-rust\">fn normalize_history(&amp;mut self, input_modalities: &amp;[InputModality]) {\n    \/\/ \u7cbe\u7b80\u8bf4\u660e\uff1a\u4fdd\u8bc1 tool call \u4e0e tool output \u6210\u5bf9\u5b58\u5728\uff1b\n    \/\/ \u5982\u679c\u6a21\u578b\u4e0d\u652f\u6301\u56fe\u7247\u8f93\u5165\uff0c\u5219\u5265\u79bb\u56fe\u7247\u5185\u5bb9\uff1b\n    \/\/ \u79fb\u9664\u4e0d\u5e94\u66b4\u9732\u7ed9\u6a21\u578b\u7684\u5185\u90e8\u6761\u76ee\u3002\n}<\/code><\/pre>\n<p>\u8fd9\u4e00\u6b65\u5f88\u91cd\u8981\u3002\u5b89\u5168\u5ba1\u8ba1\u4efb\u52a1\u7ecf\u5e38\u4f1a\u8c03\u7528 shell\u3001\u79fb\u52a8\u7aef\u3001Frida\u3001MCP\u3001\u56fe\u7247\u67e5\u770b\u7b49\u5de5\u5177\uff0c\u5982\u679c\u5386\u53f2\u6ca1\u6709\u89c4\u8303\u5316\uff0c\u6a21\u578b\u53ef\u80fd\u770b\u5230\u201c\u5b64\u513f\u5de5\u5177\u8f93\u51fa\u201d\u6216\u4e0d\u652f\u6301\u7684\u8f93\u5165\u6a21\u6001\uff0c\u5bfc\u81f4\u534f\u8bae\u9519\u8bef\u6216\u63a8\u7406\u504f\u79fb\u3002<\/p>\n<h3>2.2 \u957f\u671f memories\uff1a\u4e24\u9636\u6bb5\u540e\u53f0\u7ba1\u7ebf<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<\/p>\n<ul>\n<li><code>backend\/codex-main\/codex-rs\/core\/src\/memories\/README.md<\/code><\/li>\n<li><code>backend\/codex-main\/codex-rs\/core\/src\/memories\/mod.rs<\/code><\/li>\n<li><code>backend\/codex-main\/codex-rs\/state\/src\/runtime\/memories.rs<\/code><\/li>\n<\/ul>\n<p>memories pipeline \u5728 root session \u542f\u52a8\u65f6\u8fd0\u884c\uff0c\u4f46\u6709\u51e0\u4e2a\u524d\u7f6e\u6761\u4ef6\uff1a<\/p>\n<ul>\n<li>\u4e0d\u662f ephemeral session\u3002<\/li>\n<li>\u4e0d\u662f sub-agent\u3002<\/li>\n<li>\u914d\u7f6e\u542f\u7528\u4e86 memory\u3002<\/li>\n<li>state DB \u53ef\u7528\u3002<\/li>\n<li>\u7ebf\u7a0b\u6ca1\u6709\u88ab\u5916\u90e8\u4e0a\u4e0b\u6587\u6c61\u67d3\u5230\u9700\u8981\u7981\u7528 memory \u7684\u72b6\u6001\u3002<\/li>\n<\/ul>\n<p>\u6838\u5fc3\u4e24\u9636\u6bb5\u5982\u4e0b\uff1a<\/p>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189413928.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189413928.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><br \/>\n\u4ee3\u7801\u8282\u9009\uff1a<\/p>\n<pre><code class=\"language-rust\">\/\/ core\/src\/memories\/mod.rs\uff0c\u7cbe\u7b80\u8282\u9009\u3002\nmod phase_one {\n    pub const MODEL: &amp;str = &quot;gpt-5.4-mini&quot;;\n    pub const CONCURRENCY_LIMIT: usize = 8;\n}\n\nmod phase_two {\n    pub const MODEL: &amp;str = &quot;gpt-5.4&quot;;\n    pub const JOB_HEARTBEAT_SECONDS: u64 = 90;\n}<\/code><\/pre>\n<p>\u8bbe\u8ba1\u542b\u4e49\uff1a<\/p>\n<ul>\n<li>Phase 1 \u662f\u5927\u91cf\u5c0f\u4efb\u52a1\uff0c\u9002\u5408\u7528\u66f4\u8f7b\u6a21\u578b\u5e76\u53d1\u62bd\u53d6\u3002<\/li>\n<li>Phase 2 \u662f\u5168\u5c40\u5408\u5e76\uff0c\u5f71\u54cd\u957f\u671f\u8bb0\u5fc6\u8d28\u91cf\uff0c\u4f7f\u7528\u66f4\u5f3a\u6a21\u578b\u5e76\u901a\u8fc7 global lock \u4fdd\u8bc1\u53ea\u6709\u4e00\u4e2a\u5408\u5e76\u8005\u3002<\/li>\n<li><code>JOB_HEARTBEAT_SECONDS<\/code> \u548c lease \u673a\u5236\u8ba9\u540e\u53f0\u4efb\u52a1\u4e0d\u4f1a\u56e0\u4e3a\u8fdb\u7a0b\u5d29\u6e83\u6c38\u4e45\u5360\u9501\u3002<\/li>\n<\/ul>\n<pre><code class=\"language-rust\">\/\/ state\/src\/runtime\/memories.rs\uff0c\u7cbe\u7b80\u8282\u9009\u3002\npub fn claim_stage1_jobs_for_startup(...) {\n    \/\/ \u8fc7\u6ee4\u5f53\u524d\u7ebf\u7a0b\u3001\u7981\u7528 memory \u7684\u7ebf\u7a0b\u3001\u592a\u65b0\u7684\u7ebf\u7a0b\u3001\u5df2\u5904\u7406\u4e14\u672a\u8fc7\u671f\u7684\u7ebf\u7a0b\u3002\n    \/\/ \u6309 updated_at \u6392\u5e8f\uff0c\u63a7\u5236 scan_limit\uff0c\u518d\u9886\u53d6 job lease\u3002\n}<\/code><\/pre>\n<p>\u8fd9\u4f53\u73b0\u4e86\u957f\u671f\u8bb0\u5fc6\u7684\u4e00\u4e2a\u4f18\u5316\u539f\u5219\uff1a<\/p>\n<blockquote>\n<p>\u4e0d\u91cd\u65b0\u603b\u7ed3\u6240\u6709\u5386\u53f2\uff0c\u53ea\u603b\u7ed3\u201c\u503c\u5f97\u66f4\u65b0\u201d\u7684 rollout\uff0c\u5e76\u901a\u8fc7 lease \u907f\u514d\u91cd\u590d\u5de5\u4f5c\u3002<\/p>\n<\/blockquote>\n<h3>2.3 \u5916\u90e8\u4e0a\u4e0b\u6587\u6c61\u67d3\uff1amemory \u4e0d\u662f\u65e0\u6761\u4ef6\u5b66\u4e60<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<\/p>\n<ul>\n<li><code>backend\/codex-main\/codex-rs\/core\/src\/mcp_tool_call.rs<\/code><\/li>\n<li><code>backend\/codex-main\/codex-rs\/core\/src\/stream_events_utils.rs<\/code><\/li>\n<\/ul>\n<p>\u5f53\u7ebf\u7a0b\u4f7f\u7528\u4e86\u5916\u90e8 MCP \u4e0a\u4e0b\u6587\uff0cruntime \u53ef\u80fd\u628a\u5f53\u524d\u7ebf\u7a0b\u6807\u8bb0\u4e3a memory polluted\uff1a<\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\u3002\nif config.memory.disable_on_external_context {\n    mark_thread_memory_mode_polluted(...).await;\n}<\/code><\/pre>\n<p>\u8fd9\u5bf9\u5b89\u5168\u5ba1\u8ba1\u5c24\u5176\u91cd\u8981\u3002MCP \u53ef\u80fd\u8bfb\u53d6\u5916\u90e8\u7cfb\u7edf\u3001\u79c1\u6709\u8d44\u6e90\u6216\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u5982\u679c\u65e0\u8111\u5199\u8fdb\u957f\u671f memory\uff0c\u4f1a\u6c61\u67d3\u540e\u7eed\u9879\u76ee\u548c\u540e\u7eed\u5ba1\u8ba1\u3002<\/p>\n<h3>2.4 memory citation\uff1a\u957f\u671f\u8bb0\u5fc6\u4e5f\u8981\u53ef\u8ffd\u8e2a<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/memories\/citations.rs<\/code><\/p>\n<p>\u6a21\u578b\u5f15\u7528 memory \u65f6\u4f1a\u4ea7\u751f memory citation\u3002runtime \u4f1a\u89e3\u6790 citation\uff0c\u8bb0\u5f55\u54ea\u4e9b stage1 output \u88ab\u4f7f\u7528\u8fc7\u3002\u8fd9\u6837 Phase 2 \u53ef\u4ee5\u6839\u636e\u4f7f\u7528\u9891\u7387\u3001\u6700\u8fd1\u4f7f\u7528\u65f6\u95f4\u3001\u8fc7\u671f\u7b56\u7565\u9009\u62e9\u5408\u5e76\u8f93\u5165\u3002<\/p>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189450402.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189450402.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/p>\n<p>\u6548\u679c\uff1a<\/p>\n<ul>\n<li>\u7ecf\u5e38\u88ab\u5f15\u7528\u7684\u8bb0\u5fc6\u66f4\u5bb9\u6613\u4fdd\u7559\u3002<\/li>\n<li>\u957f\u671f\u672a\u4f7f\u7528\u7684\u8bb0\u5fc6\u66f4\u5bb9\u6613\u88ab\u6dd8\u6c70\u3002<\/li>\n<li>\u5408\u5e76\u8f93\u5165\u4e0d\u662f\u65e0\u9650\u589e\u957f\uff0c\u800c\u662f\u5e26\u4f7f\u7528\u53cd\u9988\u7684\u53d7\u63a7\u96c6\u5408\u3002<\/li>\n<\/ul>\n<hr \/>\n<h2>3. \u538b\u7f29\u7cfb\u7edf\uff1a\u4e0a\u4e0b\u6587\u751f\u547d\u652f\u6301<\/h2>\n<p>codex-main \u7684\u538b\u7f29\u4e0d\u662f\u7b80\u5355\u201c\u603b\u7ed3\u4e00\u4e0b\u804a\u5929\u8bb0\u5f55\u201d\u3002\u5b83\u6709\u660e\u786e\u89e6\u53d1\u70b9\u3001\u5386\u53f2\u66ff\u6362\u7b56\u7565\u3001\u534f\u8bae\u91cd\u7f6e\u52a8\u4f5c\u3002<\/p>\n<p>\u89e6\u53d1\u70b9\u4e3b\u8981\u6709\u56db\u7c7b\uff1a<\/p>\n<ul>\n<li><strong>Pre-turn compact<\/strong>\uff1a\u91c7\u6837\u524d\u53d1\u73b0 token \u4f7f\u7528\u8d85\u8fc7 auto compact limit\u3002<\/li>\n<li><strong>Mid-turn compact<\/strong>\uff1a\u5de5\u5177\u8c03\u7528\u540e\u4ecd\u9700 follow-up\uff0c\u4f46 token limit \u5df2\u89e6\u9876\u3002<\/li>\n<li><strong>Model downshift compact<\/strong>\uff1a\u5207\u5230\u4e0a\u4e0b\u6587\u66f4\u5c0f\u7684\u6a21\u578b\u524d\uff0c\u53d1\u73b0\u5f53\u524d\u5386\u53f2\u592a\u5927\u3002<\/li>\n<li><strong>Manual compact<\/strong>\uff1a\u7528\u6237\u6216\u4e0a\u5c42\u663e\u5f0f\u89e6\u53d1\u3002<\/li>\n<\/ul>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189473813.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189473813.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/p>\n<h3>3.1 \u672c\u5730 compact\uff1a\u6a21\u578b\u81ea\u5df1\u603b\u7ed3\u5386\u53f2<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/compact.rs<\/code><\/p>\n<pre><code class=\"language-rust\">pub enum InitialContextInjection {\n    DoNotInject,\n    BeforeLastUserMessage,\n}<\/code><\/pre>\n<p><code>InitialContextInjection<\/code> \u7684\u542b\u4e49\uff1a<\/p>\n<ul>\n<li><code>DoNotInject<\/code>\uff1apre-turn \u6216 manual compact \u65f6\uff0c\u4e0d\u9700\u8981\u628a initial context \u63d2\u56de\u7528\u6237\u6d88\u606f\u524d\u3002<\/li>\n<li><code>BeforeLastUserMessage<\/code>\uff1amid-turn compact \u65f6\uff0c\u9700\u8981\u628a compact \u540e\u7684\u4e0a\u4e0b\u6587\u63d2\u5230\u6700\u540e\u4e00\u6761\u7528\u6237\u6d88\u606f\u524d\u3002\u8fd9\u6837\u6a21\u578b\u7ee7\u7eed follow-up \u65f6\uff0c\u4ecd\u80fd\u770b\u5230\u201c\u7528\u6237\u521a\u624d\u8981\u505a\u4ec0\u4e48\u201d\u3002<\/li>\n<\/ul>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\uff1acompact \u671f\u95f4\u590d\u7528\u540c\u4e00\u4e2a client session\u3002\nlet client_session = model_client.create_session();\n\nloop {\n    let turn_input = build_compact_prompt(history);\n    let stream = client_session.stream(&amp;turn_input).await?;\n\n    if context_too_large {\n        history.remove_first_item();\n        continue;\n    }\n\n    break;\n}<\/code><\/pre>\n<p>\u8fd9\u91cc\u6709\u4e00\u4e2a\u4e0d\u660e\u663e\u4f46\u5f88\u5173\u952e\u7684\u7f13\u5b58\u4f18\u5316\uff1a<\/p>\n<blockquote>\n<p>compact \u8fc7\u7a0b\u4e2d\u5982\u679c\u4e0a\u4e0b\u6587\u4ecd\u7136\u592a\u5927\uff0c\u4f18\u5148\u5220\u9664\u6700\u8001\u7684 history item\uff0c\u800c\u4e0d\u662f\u91cd\u5199\u6700\u8fd1\u4e0a\u4e0b\u6587\u3002\u8fd9\u6837\u80fd\u5c3d\u91cf\u4fdd\u7559 prompt cache \u524d\u7f00\u548c\u6700\u65b0\u4efb\u52a1\u8bed\u4e49\u3002<\/p>\n<\/blockquote>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\uff1a\u751f\u6210 summary \u540e\u66ff\u6362\u5386\u53f2\u3002\nlet compacted_item = CompactedItem {\n    message: summary_text.clone(),\n    replacement_history: Some(new_history.clone()),\n};\n\nsess.replace_compacted_history(\n    new_history,\n    reference_context_item,\n    compacted_item,\n)\n.await;\n\nclient_session.reset_websocket_session();\nsess.recompute_token_usage(&amp;turn_context).await;<\/code><\/pre>\n<p>\u538b\u7f29\u540e\u7684\u884c\u4e3a\u4e0d\u662f\u201c\u8ffd\u52a0\u4e00\u6761\u603b\u7ed3\u201d\uff0c\u800c\u662f\u201c\u7528\u65b0\u5386\u53f2\u66ff\u6362\u65e7\u5386\u53f2\u201d\u3002\u8fd9\u80fd\u907f\u514d\u65e7\u4e0a\u4e0b\u6587\u7ee7\u7eed\u5360 token\uff0c\u4e5f\u8ba9\u540e\u7eed token \u4f30\u7b97\u53d8\u51c6\u786e\u3002<\/p>\n<h3>3.2 \u8fdc\u7aef compact\uff1a\u7531 provider \u539f\u751f\u538b\u7f29\u5386\u53f2<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/compact_remote.rs<\/code><\/p>\n<p>\u5f53 provider \u652f\u6301 remote compaction\uff0cruntime \u4f1a\u8d70\u8fdc\u7aef compact endpoint\uff1a<\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\u3002\nif provider.supports_remote_compaction {\n    model_client\n        .compact_conversation_history(history, ...)\n        .await?;\n}<\/code><\/pre>\n<p>\u8fdc\u7aef compact \u7684\u7ed3\u679c\u8fd8\u8981\u7ecf\u8fc7\u8fc7\u6ee4\uff1a<\/p>\n<pre><code class=\"language-rust\">fn should_keep_compacted_history_item(item: &amp;ResponseItem) -&gt; bool {\n    \/\/ \u4fdd\u7559 assistant\u3001compaction item\u3001\u5fc5\u8981 warning \/ summary user message\u3002\n    \/\/ \u4e22\u5f03 developer message \u548c\u9648\u65e7\u91cd\u590d context\u3002\n}<\/code><\/pre>\n<p>\u4e3a\u4ec0\u4e48\u8981\u8fc7\u6ee4\uff1f<\/p>\n<ul>\n<li>provider \u8fd4\u56de\u7684\u662f\u201c\u538b\u7f29\u540e\u7684\u5bf9\u8bdd\u5386\u53f2\u201d\uff0c\u4f46\u5e76\u4e0d\u4ee3\u8868\u6bcf\u4e2a\u6761\u76ee\u90fd\u9002\u5408\u91cd\u65b0\u6ce8\u5165\u3002<\/li>\n<li>developer message\u3001\u9648\u65e7 context\u3001\u91cd\u590d baseline \u90fd\u53ef\u80fd\u7834\u574f runtime \u5bf9\u4e0a\u4e0b\u6587\u7684\u6240\u6709\u6743\u3002<\/li>\n<li>\u8fc7\u6ee4\u540e\u518d <code>replace_compacted_history(...)<\/code>\uff0c\u786e\u4fdd\u5386\u53f2\u4ecd\u7b26\u5408 codex-main \u7684\u534f\u8bae\u4e0d\u53d8\u91cf\u3002<\/li>\n<\/ul>\n<h3>3.3 \u538b\u7f29\u540e\u7684\u534f\u8bae\u91cd\u7f6e<\/h3>\n<p>\u538b\u7f29\u4f1a\u91cd\u5199 history\uff0c\u56e0\u6b64\u5fc5\u987b\u91cd\u7f6e\u6a21\u578b\u8fde\u63a5\u72b6\u6001\uff1a<\/p>\n<pre><code class=\"language-rust\">client_session.reset_websocket_session();<\/code><\/pre>\n<p>\u539f\u56e0\uff1a<\/p>\n<ul>\n<li>WebSocket \u589e\u91cf\u8bf7\u6c42\u4f9d\u8d56 <code>previous_response_id<\/code>\u3002<\/li>\n<li><code>previous_response_id<\/code> \u6697\u542b\u201c\u670d\u52a1\u7aef\u8fd8\u8bb0\u5f97\u4e0a\u4e00\u8f6e\u4e0a\u4e0b\u6587\u201d\u3002<\/li>\n<li>compact \u540e\u672c\u5730\u5386\u53f2\u5df2\u7ecf\u53d8\u6210\u65b0\u6295\u5f71\uff0c\u7ee7\u7eed\u590d\u7528\u65e7\u589e\u91cf\u72b6\u6001\u53ef\u80fd\u9020\u6210\u670d\u52a1\u7aef\u4e0a\u4e0b\u6587\u4e0e\u672c\u5730\u4e0a\u4e0b\u6587\u4e0d\u4e00\u81f4\u3002<\/li>\n<\/ul>\n<p>\u8fd9\u662f codex-main \u5728\u201c\u7f13\u5b58\u547d\u4e2d\u201d\u548c\u201c\u6b63\u786e\u6027\u201d\u4e4b\u95f4\u7684\u53d6\u820d\uff1a\u80fd\u590d\u7528\u65f6\u5c3d\u91cf\u590d\u7528\uff0c\u4e00\u65e6 history rewrite\uff0c\u5c31\u4e3b\u52a8\u65ad\u5f00\u589e\u91cf\u94fe\u8def\u3002<\/p>\n<hr \/>\n<h2>4. \u6a21\u578b\u534f\u8bae\u4e0e\u7f13\u5b58\u547d\u4e2d<\/h2>\n<p>codex-main \u5bf9 Responses API \u7684\u4f7f\u7528\u6709\u51e0\u4e2a\u4e13\u95e8\u670d\u52a1\u4e8e\u7a33\u5b9a\u6027\u548c\u7f13\u5b58\u547d\u4e2d\u7684\u8bbe\u8ba1\uff1a<\/p>\n<ul>\n<li><code>prompt_cache_key<\/code>\uff1a\u901a\u5e38\u4f7f\u7528 conversation id\uff0c\u8ba9\u540c\u4e00\u7ebf\u7a0b\u547d\u4e2d\u670d\u52a1\u7aef prompt cache\u3002<\/li>\n<li><code>previous_response_id<\/code>\uff1aWebSocket \u589e\u91cf\u8bf7\u6c42\u53ea\u53d1\u9001\u65b0\u589e item\uff0c\u51cf\u5c11\u91cd\u590d\u4f20\u8f93\u3002<\/li>\n<li><code>x-codex-turn-state<\/code>\uff1a\u670d\u52a1\u7aef\u8fd4\u56de\u540e\uff0c\u540e\u7eed\u8bf7\u6c42\u5e26\u56de\uff0c\u5e2e\u52a9\u540c\u4e00 turn \u7684 sticky routing\u3002<\/li>\n<li><code>enable_request_compression<\/code>\uff1a\u8bf7\u6c42\u4f53\u538b\u7f29\uff0c\u964d\u4f4e\u957f\u4e0a\u4e0b\u6587\u4f20\u8f93\u6210\u672c\u3002<\/li>\n<li><code>prewarm_websocket<\/code>\uff1a\u63d0\u524d\u5efa\u7acb WebSocket \u5e76\u7528 <code>generate=false<\/code> \u9884\u70ed\uff0c\u964d\u4f4e\u4e0b\u4e00\u6b21\u771f\u5b9e\u91c7\u6837\u5ef6\u8fdf\u3002<\/li>\n<\/ul>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189508565.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189508565.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/p>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/client.rs<\/code><\/p>\n<pre><code class=\"language-rust\">pub struct ModelClientSession {\n    client: ModelClient,\n    websocket_session: Mutex&lt;Option&lt;WebsocketSession&gt;&gt;,\n    cache_websocket_session_on_drop: bool,\n    turn_state: OnceLock&lt;String&gt;,\n}<\/code><\/pre>\n<p>\u5b57\u6bb5\u89e3\u91ca\uff1a<\/p>\n<ul>\n<li><code>websocket_session<\/code>\uff1a\u5f53\u524d turn \u53ef\u590d\u7528\u7684 WebSocket \u8fde\u63a5\u3002<\/li>\n<li><code>cache_websocket_session_on_drop<\/code>\uff1a\u672c\u8f6e\u7ed3\u675f\u65f6\u662f\u5426\u628a\u8fde\u63a5\u653e\u56de client state\uff0c\u4f9b\u4e0b\u4e00\u8f6e\u590d\u7528\u3002<\/li>\n<li><code>turn_state<\/code>\uff1a\u4ece\u54cd\u5e94\u5934 <code>x-codex-turn-state<\/code> \u8bfb\u5230\u7684\u670d\u52a1\u7aef\u72b6\u6001\uff0c\u7528\u4e8e\u540c\u4e00 turn \u7684\u8bf7\u6c42\u9ecf\u6027\u3002<\/li>\n<\/ul>\n<pre><code class=\"language-rust\">fn build_responses_headers(&amp;self, ...) -&gt; HeaderMap {\n    let mut headers = HeaderMap::new();\n\n    if let Some(turn_state) = self.turn_state.get() {\n        headers.insert(&quot;x-codex-turn-state&quot;, turn_state.parse()?);\n    }\n\n    headers\n}<\/code><\/pre>\n<p><code>turn_state<\/code> \u4e0d\u662f\u6a21\u578b\u8bb0\u5fc6\uff0c\u800c\u662f\u534f\u8bae\u5c42\u7684\u670d\u52a1\u7aef\u8def\u7531\/\u72b6\u6001\u63d0\u793a\u3002\u5b83\u7684\u751f\u547d\u5468\u671f\u5e94\u8be5\u6bd4 thread memory \u77ed\u5f97\u591a\uff0c\u4e3b\u8981\u670d\u52a1\u4e8e\u540c\u4e00 turn \u5185\u7684\u8fde\u7eed\u8bf7\u6c42\u3002<\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\u3002\nrequest.prompt_cache_key = Some(conversation_id);\nrequest.parallel_tool_calls = prompt.parallel_tool_calls;\nrequest.previous_response_id = websocket_session.last_response_id();<\/code><\/pre>\n<p>\u8fd9\u51e0\u4e2a\u5b57\u6bb5\u628a\u6a21\u578b\u534f\u8bae\u548c runtime \u5bf9\u9f50\u8d77\u6765\uff1a<\/p>\n<ul>\n<li>cache key \u7a33\u5b9a\uff0c\u624d\u80fd\u547d\u4e2d\u957f prompt \u524d\u7f00\u7f13\u5b58\u3002<\/li>\n<li>previous response id \u5b58\u5728\uff0c\u624d\u80fd\u8d70\u589e\u91cf\u8f93\u5165\u3002<\/li>\n<li>parallel tool calls \u6253\u5f00\uff0c\u6a21\u578b\u624d\u53ef\u4ee5\u5728\u540c\u4e00\u8f6e\u8f93\u51fa\u591a\u4e2a\u53ef\u5e76\u53d1\u5de5\u5177\u8c03\u7528\u3002<\/li>\n<\/ul>\n<h3>\u7f13\u5b58\u547d\u4e2d\u4f18\u5316\u603b\u7ed3<\/h3>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189527897.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189527897.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/p>\n<hr \/>\n<h2>5. \u5e76\u884c\u6267\u884c\uff1a\u6a21\u578b\u5e76\u884c\u8c03\u7528\u5230 runtime \u5e76\u884c\u95f8\u95e8<\/h2>\n<p>codex-main \u7684\u5e76\u884c\u4e0d\u662f\u201c\u6240\u6709\u5de5\u5177\u90fd\u968f\u4fbf\u5e76\u53d1\u201d\u3002\u5b83\u5206\u4e09\u5c42\u63a7\u5236\uff1a<\/p>\n<ol>\n<li>\u6a21\u578b\u534f\u8bae\u5c42\uff1a\u8bf7\u6c42\u91cc\u5141\u8bb8 <code>parallel_tool_calls<\/code>\u3002<\/li>\n<li>\u8def\u7531\u5c42\uff1a<code>ToolRouter<\/code> \u5224\u65ad\u67d0\u4e2a\u5de5\u5177\u662f\u5426\u652f\u6301\u5e76\u884c\u3002<\/li>\n<li>runtime \u5c42\uff1a<code>ToolCallRuntime<\/code> \u7528\u8bfb\u5199\u9501\u5b9e\u73b0\u201c\u5e76\u884c\u5b89\u5168\u5de5\u5177\u53ef\u4e00\u8d77\u8dd1\uff0c\u975e\u5e76\u884c\u5de5\u5177\u72ec\u5360\u201d\u3002<br \/>\n<div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189542053.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189542053.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/li>\n<\/ol>\n<h3>5.1 \u6a21\u578b\u534f\u8bae\u6253\u5f00 parallel tool calls<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<\/p>\n<ul>\n<li><code>backend\/codex-main\/codex-rs\/core\/src\/client_common.rs<\/code><\/li>\n<li><code>backend\/codex-main\/codex-rs\/core\/src\/client.rs<\/code><\/li>\n<\/ul>\n<pre><code class=\"language-rust\">pub struct Prompt {\n    pub input: Vec&lt;ResponseItem&gt;,\n    pub tools: Vec&lt;Tool&gt;,\n    pub parallel_tool_calls: bool,\n}<\/code><\/pre>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\u3002\nrequest.parallel_tool_calls = prompt.parallel_tool_calls;<\/code><\/pre>\n<p>\u8fd9\u4e2a\u5b57\u6bb5\u53ea\u662f\u544a\u8bc9\u6a21\u578b\u201c\u4f60\u53ef\u4ee5\u5e76\u884c\u89c4\u5212\u5de5\u5177\u8c03\u7528\u201d\u3002\u771f\u6b63\u80fd\u5426\u5e76\u53d1\u6267\u884c\uff0c\u8fd8\u8981\u770b runtime\u3002<\/p>\n<h3>5.2 stream_events_utils \u628a\u6a21\u578b item \u53d8\u6210\u5de5\u5177 future<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/stream_events_utils.rs<\/code><\/p>\n<pre><code class=\"language-rust\">pub(crate) struct OutputItemResult {\n    pub needs_follow_up: bool,\n    pub tool_future: Option&lt;BoxFuture&lt;&#039;static, ToolCallOutput&gt;&gt;,\n}<\/code><\/pre>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\u3002\nlet call = ctx.tool_router.build_tool_call(response_item)?;\nrecord_completed_response_item(...).await;\n\nlet cancellation_token = ctx.cancellation_token.child_token();\nlet tool_future = ctx\n    .tool_runtime\n    .clone()\n    .handle_tool_call(call, cancellation_token);\n\nOutputItemResult {\n    needs_follow_up: true,\n    tool_future: Some(tool_future),\n}<\/code><\/pre>\n<p>\u542b\u4e49\uff1a<\/p>\n<ul>\n<li>\u6a21\u578b\u4e00\u65e6\u8f93\u51fa\u5de5\u5177\u8c03\u7528\uff0cruntime \u5148\u628a\u8fd9\u6761 tool call \u8bb0\u5f55\u8fdb history\u3002<\/li>\n<li>\u7136\u540e\u628a\u5de5\u5177\u8c03\u7528\u5305\u88c5\u6210 future\u3002<\/li>\n<li><code>needs_follow_up = true<\/code> \u8868\u793a\u5de5\u5177\u8f93\u51fa\u56de\u5199\u540e\uff0c\u6a21\u578b\u8fd8\u9700\u8981\u7ee7\u7eed\u770b\u7ed3\u679c\u5e76\u63a8\u7406\u3002<\/li>\n<\/ul>\n<h3>5.3 ToolCallRuntime \u7684\u8bfb\u5199\u9501\u5e76\u884c\u6a21\u578b<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/tools\/parallel.rs<\/code><\/p>\n<pre><code class=\"language-rust\">pub(crate) struct ToolCallRuntime {\n    router: Arc&lt;ToolRouter&gt;,\n    session: Arc&lt;Session&gt;,\n    turn_context: Arc&lt;TurnContext&gt;,\n    tracker: SharedTurnDiffTracker,\n    parallel_execution: Arc&lt;RwLock&lt;()&gt;&gt;,\n}<\/code><\/pre>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\uff1a\u5e76\u884c\u5b89\u5168\u5de5\u5177\u62ff\u8bfb\u9501\uff0c\u72ec\u5360\u5de5\u5177\u62ff\u5199\u9501\u3002\nlet supports_parallel = self.router.tool_supports_parallel(&amp;call);\n\nlet _guard = if supports_parallel {\n    Either::Left(lock.read().await)\n} else {\n    Either::Right(lock.write().await)\n};\n\nrouter\n    .dispatch_tool_call_with_code_mode_result(...)\n    .await<\/code><\/pre>\n<p>\u8fd9\u6bb5\u662f\u5e76\u884c\u6267\u884c\u7684\u6838\u5fc3\uff1a<\/p>\n<ul>\n<li>\u652f\u6301\u5e76\u884c\u7684\u5de5\u5177\u62ff read lock\uff0c\u591a\u4e2a read lock \u53ef\u540c\u65f6\u5b58\u5728\u3002<\/li>\n<li>\u4e0d\u652f\u6301\u5e76\u884c\u7684\u5de5\u5177\u62ff write lock\uff0cwrite lock \u4f1a\u7b49\u5f85\u6240\u6709 read lock \u7ed3\u675f\uff0c\u4e5f\u4f1a\u963b\u6b62\u5176\u4ed6 read\/write lock\u3002<\/li>\n<li>\u56e0\u6b64\uff0cruntime \u53ef\u4ee5\u5e76\u53d1\u6267\u884c\u201c\u53ea\u8bfb\u3001\u72ec\u7acb\u3001\u5b89\u5168\u201d\u7684\u5de5\u5177\uff0c\u540c\u65f6\u4fdd\u8bc1 mutating \u6216\u9ad8\u98ce\u9669\u5de5\u5177\u4e32\u884c\u3002<\/li>\n<\/ul>\n<h3>5.4 ToolRegistry \u8d1f\u8d23\u6700\u7ec8\u6267\u884c\u548c\u526f\u4f5c\u7528\u95e8\u63a7<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/tools\/registry.rs<\/code><\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\u3002\nlet is_mutating = handler.is_mutating(&amp;call, context).await?;\n\nif is_mutating {\n    turn.tool_call_gate.wait_ready().await;\n}\n\nlet output = handler.handle(call, context).await;<\/code><\/pre>\n<p>\u8fd9\u5c42\u89e3\u51b3\u7684\u662f\u53e6\u4e00\u4e2a\u95ee\u9898\uff1a\u5373\u4f7f\u5de5\u5177\u652f\u6301\u5e76\u884c\uff0c\u771f\u6b63\u6267\u884c\u524d\u4ecd\u8981\u5224\u65ad\u662f\u5426 mutating\u3001\u662f\u5426\u9700\u8981\u7b49\u5f85\u5ba1\u6279\u3001\u662f\u5426\u8981\u8dd1 pre\/post hook\u3001\u662f\u5426\u8981\u5199 telemetry\u3002<\/p>\n<h3>5.5 \u4e3a\u4ec0\u4e48\u5b89\u5168\u5ba1\u8ba1\u91cc\u8fd9\u5f88\u91cd\u8981<\/h3>\n<p>\u5b89\u5168\u5ba1\u8ba1\u4efb\u52a1\u91cc\u6709\u5f88\u591a\u5929\u7136\u9002\u5408\u5e76\u884c\u7684\u5de5\u4f5c\uff1a<\/p>\n<ul>\n<li>\u591a\u6587\u4ef6\u4ee3\u7801\u9605\u8bfb\u3002<\/li>\n<li>\u591a\u89c4\u5219\u9759\u6001\u5339\u914d\u3002<\/li>\n<li>\u591a\u4e2a\u53ea\u8bfb shell \u67e5\u8be2\u3002<\/li>\n<li>\u591a\u4e2a MCP resource \u8bfb\u53d6\u3002<\/li>\n<li>\u591a\u4e2a APK \u53cd\u7f16\u8bd1\u4ea7\u7269\u7d22\u5f15\u68c0\u7d22\u3002<\/li>\n<\/ul>\n<p>\u4f46\u4e5f\u6709\u5f88\u591a\u5fc5\u987b\u4e32\u884c\u6216\u72ec\u5360\u7684\u5de5\u4f5c\uff1a<\/p>\n<ul>\n<li>\u4fee\u6539\u6587\u4ef6\u3002<\/li>\n<li>\u5220\u9664\u4e34\u65f6\u76ee\u5f55\u3002<\/li>\n<li>\u5b89\u88c5\/\u5378\u8f7d APK\u3002<\/li>\n<li>\u542f\u505c Frida server\u3002<\/li>\n<li>\u6539\u53d8\u8bbe\u5907\u524d\u53f0 app \u72b6\u6001\u3002<\/li>\n<\/ul>\n<p>codex-main \u7684\u8bfb\u5199\u9501\u5e76\u884c\u6a21\u578b\u6b63\u597d\u9002\u5408 AppCheckMaster\uff1a\u8ba9\u201c\u8bfb\u53d6\u548c\u5206\u6790\u201d\u5c3d\u91cf\u5e76\u53d1\uff0c\u8ba9\u201c\u526f\u4f5c\u7528\u548c\u8bbe\u5907\u72b6\u6001\u53d8\u5316\u201d\u4fdd\u6301\u53d7\u63a7\u3002<\/p>\n<hr \/>\n<h2>6. \u957f\u547d\u4ee4\u4e0e\u5361\u6b7b\u8bc6\u522b<\/h2>\n<p>codex-main \u5bf9\u201c\u547d\u4ee4\u5361\u6b7b\u201d\u7684\u5904\u7406\u5206\u4e24\u5957\u673a\u5236\uff1a<\/p>\n<ul>\n<li>\u666e\u901a <code>shell<\/code> \/ <code>shell_command<\/code>\uff1a\u4e00\u6b21\u6027\u547d\u4ee4\uff0c\u4f7f\u7528 timeout\u3001kill process group\u3001IO drain timeout\u3001\u8f93\u51fa\u4e0a\u9650\u3002<\/li>\n<li><code>unified_exec<\/code>\uff1a\u957f\u547d\u4ee4\u6216\u4ea4\u4e92\u5f0f\u547d\u4ee4\uff0c\u4f7f\u7528 yield time\u3001\u540e\u53f0 process id\u3001\u72b6\u6001\u673a\u3001\u8f93\u51fa\u901a\u77e5\u3001\u540e\u7eed wait\/write_stdin\u3002<\/li>\n<\/ul>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189576026.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189576026.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/p>\n<h3>6.1 \u666e\u901a shell\uff1atimeout \u4e0d\u662f\u552f\u4e00\u9632\u7ebf<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/exec.rs<\/code><\/p>\n<p>\u5173\u952e\u5e38\u91cf\uff1a<\/p>\n<pre><code class=\"language-rust\">pub const DEFAULT_EXEC_COMMAND_TIMEOUT_MS: u64 = 10_000;\npub const EXEC_TIMEOUT_EXIT_CODE: i32 = 124;\nconst IO_DRAIN_TIMEOUT_MS: u64 = 2_000;\nconst MAX_EXEC_OUTPUT_DELTAS_PER_CALL: usize = 10_000;<\/code><\/pre>\n<p>\u89e3\u91ca\uff1a<\/p>\n<ul>\n<li>\u9ed8\u8ba4\u547d\u4ee4 10 \u79d2\u8d85\u65f6\u3002<\/li>\n<li>\u8d85\u65f6\u9000\u51fa\u7801\u6309 shell \u4e60\u60ef\u7528 <code>124<\/code>\u3002<\/li>\n<li>kill \u540e\u6700\u591a\u7b49 2 \u79d2 drain stdout\/stderr\uff0c\u9632\u6b62\u8f93\u51fa\u7ba1\u9053\u6c38\u8fdc\u4e0d\u5173\u95ed\u3002<\/li>\n<li>\u5355\u6b21\u5de5\u5177\u8c03\u7528\u6700\u591a\u53d1\u9001 10000 \u4e2a output delta\uff0c\u907f\u514d\u6d41\u5f0f\u8f93\u51fa\u5237\u7206\u4e8b\u4ef6\u901a\u9053\u3002<\/li>\n<\/ul>\n<pre><code class=\"language-rust\">pub enum ExecExpiration {\n    Timeout(Duration),\n    DefaultTimeout,\n    Cancellation(CancellationToken),\n}<\/code><\/pre>\n<p><code>ExecExpiration<\/code> \u628a\u4e09\u7c7b\u7ec8\u6b62\u6761\u4ef6\u62bd\u8c61\u6210\u4e00\u4e2a\u7b49\u5f85\u5bf9\u8c61\uff1a<\/p>\n<ul>\n<li>\u7528\u6237\u663e\u5f0f <code>timeout_ms<\/code>\u3002<\/li>\n<li>\u9ed8\u8ba4 timeout\u3002<\/li>\n<li>\u4e0a\u5c42\u53d6\u6d88 token\uff0c\u4f8b\u5982\u7528\u6237\u4e2d\u65ad turn\u3002<\/li>\n<\/ul>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\uff1a\u7b49\u5f85\u5b50\u8fdb\u7a0b\u3001\u8d85\u65f6\u6216 ctrl-c\u3002\nlet (exit_status, timed_out) = tokio::select! {\n    status_result = child.wait() =&gt; {\n        (status_result?, false)\n    }\n    _ = &amp;mut expiration_wait =&gt; {\n        kill_child_process_group(&amp;mut child)?;\n        child.start_kill()?;\n        (ExitStatus::from_raw(EXEC_TIMEOUT_EXIT_CODE), true)\n    }\n    _ = ctrl_c() =&gt; {\n        kill_child_process_group(&amp;mut child)?;\n        child.start_kill()?;\n        (ExitStatus::from_raw(1), false)\n    }\n};<\/code><\/pre>\n<p>\u8fd9\u89e3\u51b3\u201c\u547d\u4ee4\u672c\u8eab\u4e0d\u9000\u51fa\u201d\u7684\u95ee\u9898\u3002\u4f46\u8fd8\u6709\u4e00\u4e2a\u66f4\u9690\u853d\u7684\u95ee\u9898\uff1a\u547d\u4ee4\u88ab kill \u540e\uff0cstdout\/stderr pipe \u53ef\u80fd\u4ecd\u4e0d\u5173\u95ed\u3002<\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\uff1akill \u540e\u8bfb\u53d6\u4efb\u52a1\u4e5f\u4e0d\u80fd\u65e0\u9650\u7b49\u3002\nmatch tokio::time::timeout(\n    capture_policy.io_drain_timeout(),\n    &amp;mut *output_handle,\n)\n.await\n{\n    Ok(output) =&gt; output?,\n    Err(_) =&gt; {\n        output_handle.abort();\n        StreamOutput::default()\n    }\n}<\/code><\/pre>\n<p>\u4e3a\u4ec0\u4e48\u9700\u8981 IO drain timeout\uff1f<\/p>\n<p>\u6709\u4e9b\u547d\u4ee4\u4f1a\u521b\u5efa\u5b59\u8fdb\u7a0b\uff0c\u5b59\u8fdb\u7a0b\u7ee7\u627f stdout\/stderr\u3002\u7236\u8fdb\u7a0b\u88ab kill \u540e\uff0cpipe \u4ecd\u7136\u88ab\u5b59\u8fdb\u7a0b\u6301\u6709\uff0c\u8bfb\u53d6\u4efb\u52a1\u4f1a\u4e00\u76f4\u7b49 EOF\u3002\u5982\u679c\u6ca1\u6709 drain timeout\uff0cagent \u4f1a\u8868\u73b0\u5f97\u50cf\u201c\u660e\u660e kill \u4e86\u547d\u4ee4\u4f46\u81ea\u5df1\u5361\u4f4f\u4e86\u201d\u3002<\/p>\n<h3>6.2 \u8f93\u51fa\u8bfb\u53d6\uff1a\u65e2\u8981\u9632\u7206\uff0c\u4e5f\u8981\u9632\u80cc\u538b<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/exec.rs<\/code><\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\u3002\nwhile let Ok(bytes_read) = reader.read(&amp;mut buf).await {\n    if bytes_read == 0 {\n        break;\n    }\n\n    maybe_emit_output_delta(&amp;buf[..bytes_read]).await;\n    append_capped(&amp;mut captured_output, &amp;buf[..bytes_read], output_cap);\n}<\/code><\/pre>\n<p>\u8f93\u51fa\u5904\u7406\u6709\u4e24\u6761\u7ebf\uff1a<\/p>\n<ul>\n<li>\u6d41\u5f0f delta \u53d1\u7ed9\u524d\u7aef\uff0c\u5e2e\u52a9\u7528\u6237\u770b\u5230\u547d\u4ee4\u8fd8\u6d3b\u7740\u3002<\/li>\n<li>\u672c\u5730 capped buffer \u4fdd\u7559\u5934\u5c3e\u6216\u9650\u5b9a\u5927\u5c0f\uff0c\u907f\u514d\u5de8\u5927\u65e5\u5fd7\u628a\u4e0a\u4e0b\u6587\u548c\u5185\u5b58\u6253\u7206\u3002<\/li>\n<\/ul>\n<p>\u5373\u4f7f\u8f93\u51fa\u8d85\u8fc7 cap\uff0cruntime \u4ecd\u4f1a\u7ee7\u7eed drain pipe\uff0c\u9632\u6b62\u5b50\u8fdb\u7a0b\u56e0\u4e3a stdout\/stderr pipe \u5199\u6ee1\u800c\u963b\u585e\u3002<\/p>\n<h3>6.3 unified_exec\uff1a\u957f\u547d\u4ee4\u4e0d\u7b49\u4e8e\u5361\u6b7b<\/h3>\n<p>\u666e\u901a shell \u9002\u5408 <code>rg<\/code>\u3001<code>git status<\/code>\u3001<code>cargo test<\/code> \u8fd9\u7c7b\u5e94\u8be5\u7ed3\u675f\u7684\u547d\u4ee4\u3002\u957f\u547d\u4ee4\u5219\u4e0d\u540c\uff0c\u4f8b\u5982\uff1a<\/p>\n<ul>\n<li>\u542f\u52a8 dev server\u3002<\/li>\n<li>\u8dd1\u6301\u7eed\u65e5\u5fd7 tail\u3002<\/li>\n<li>\u957f\u65f6\u95f4 fuzz \/ scan\u3002<\/li>\n<li>\u4ea4\u4e92\u5f0f shell\u3002<\/li>\n<li>\u79fb\u52a8\u7aef\u5b9e\u65f6\u76d1\u63a7\u3002<\/li>\n<\/ul>\n<p>\u8fd9\u4e9b\u547d\u4ee4\u201c\u6ca1\u7ed3\u675f\u201d\u4e0d\u4e00\u5b9a\u662f\u5361\u6b7b\uff0c\u6240\u4ee5 unified_exec \u91c7\u7528 yield \u6a21\u578b\u3002<\/p>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<\/p>\n<ul>\n<li><code>backend\/codex-main\/codex-rs\/core\/src\/tools\/handlers\/unified_exec.rs<\/code><\/li>\n<li><code>backend\/codex-main\/codex-rs\/core\/src\/unified_exec\/process_manager.rs<\/code><\/li>\n<li><code>backend\/codex-main\/codex-rs\/core\/src\/unified_exec\/process.rs<\/code><\/li>\n<\/ul>\n<pre><code class=\"language-rust\">pub struct ExecCommandArgs {\n    pub cmd: Vec&lt;String&gt;,\n    pub yield_time_ms: Option&lt;u64&gt;,\n    pub max_output_tokens: Option&lt;u64&gt;,\n    pub sandbox_permissions: Option&lt;SandboxPermissions&gt;,\n    pub timeout_ms: Option&lt;u64&gt;,\n}<\/code><\/pre>\n<p><code>yield_time_ms<\/code> \u662f unified_exec \u7684\u5173\u952e\u3002\u5b83\u4e0d\u662f\u547d\u4ee4\u603b\u8d85\u65f6\uff0c\u800c\u662f\u201c\u672c\u6b21\u5de5\u5177\u8c03\u7528\u6700\u591a\u7b49\u591a\u4e45\u518d\u628a\u63a7\u5236\u6743\u8fd8\u7ed9\u6a21\u578b\u201d\u3002<\/p>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189610110.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/blog.shangwendada.top\/wp-content\/uploads\/2026\/04\/image-1777189610110.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"file\" \/><\/div><\/p>\n<p><code>collect_output_until_deadline(...)<\/code> \u4f1a\u7b49\u5f85\u8fd9\u4e9b\u4e8b\u4ef6\u4e4b\u4e00\uff1a<\/p>\n<ul>\n<li>\u6709\u65b0\u8f93\u51fa\u5230\u8fbe\u3002<\/li>\n<li>\u8fdb\u7a0b\u9000\u51fa\u3002<\/li>\n<li>\u8f93\u51fa\u5173\u95ed\u3002<\/li>\n<li>cancellation token \u89e6\u53d1\u3002<\/li>\n<li>\u5230\u8fbe\u672c\u6b21 yield deadline\u3002<\/li>\n<\/ul>\n<p>\u5b83\u4e0d\u662f sleep \u8f6e\u8be2\uff0c\u800c\u662f\u901a\u8fc7 <code>Notify<\/code> \u548c\u72b6\u6001 watch \u88ab\u52a8\u5524\u9192\uff0c\u907f\u514d CPU \u5fd9\u7b49\u3002<\/p>\n<h3>6.4 ProcessManager \u9632\u6b62\u540e\u53f0\u8fdb\u7a0b\u65e0\u9650\u5806\u79ef<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/unified_exec\/process_manager.rs<\/code><\/p>\n<pre><code class=\"language-rust\">\/\/ \u7cbe\u7b80\u8282\u9009\u3002\nfn prune_processes_if_needed(&amp;mut self) {\n    \/\/ \u4fdd\u62a4\u6700\u8fd1\u7684\u82e5\u5e72\u8fdb\u7a0b\uff1b\n    \/\/ \u4f18\u5148\u6e05\u7406\u5df2\u9000\u51fa\u7684 LRU\uff1b\n    \/\/ \u5982\u679c\u4ecd\u8d85\u9650\uff0c\u518d\u6e05\u7406\u6700\u4e45\u672a\u4f7f\u7528\u7684\u8fdb\u7a0b\u3002\n}<\/code><\/pre>\n<p>\u957f\u547d\u4ee4\u80fd\u540e\u53f0\u8fd0\u884c\uff0c\u5c31\u5fc5\u987b\u6709\u540e\u53f0\u8d44\u6e90\u56de\u6536\u3002\u5426\u5219\u4e00\u6b21\u5ba1\u8ba1\u91cc\u542f\u52a8\u591a\u4e2a\u626b\u63cf\u3001tail\u3001server\uff0c\u5f88\u5bb9\u6613\u628a runtime \u62d6\u6b7b\u3002<\/p>\n<h3>6.5 ProcessState\uff1a\u533a\u5206\u9000\u51fa\u3001\u5931\u8d25\u3001\u4ecd\u8fd0\u884c<\/h3>\n<p>\u6e90\u7801\u4f4d\u7f6e\uff1a<code>backend\/codex-main\/codex-rs\/core\/src\/unified_exec\/process_state.rs<\/code><\/p>\n<pre><code class=\"language-rust\">pub struct ProcessState {\n    pub has_exited: bool,\n    pub exit_code: Option&lt;i32&gt;,\n    pub failure_message: Option&lt;String&gt;,\n}<\/code><\/pre>\n<p>\u72b6\u6001\u89e3\u91ca\uff1a<\/p>\n<ul>\n<li><code>has_exited = false<\/code>\uff1a\u8fdb\u7a0b\u4ecd\u5728\u8fd0\u884c\uff0c\u8fd4\u56de partial output \u4e0d\u4ee3\u8868\u5931\u8d25\u3002<\/li>\n<li><code>has_exited = true, exit_code = Some(code)<\/code>\uff1a\u6b63\u5e38\u62ff\u5230\u9000\u51fa\u7801\u3002<\/li>\n<li><code>failure_message = Some(...)<\/code>\uff1aruntime \u5c42\u6267\u884c\u5931\u8d25\uff0c\u4f8b\u5982 exec server \u9519\u8bef\u3001\u8f93\u51fa\u6d41\u5f02\u5e38\u3002<\/li>\n<\/ul>\n<p>\u8fd9\u8ba9\u6a21\u578b\u53ef\u4ee5\u505a\u6b63\u786e\u51b3\u7b56\uff1a<\/p>\n<ul>\n<li>\u547d\u4ee4\u6ca1\u7ed3\u675f\u4f46\u6709 <code>process_id<\/code>\uff1a\u53ef\u4ee5 wait\u3002<\/li>\n<li>\u8f93\u51fa\u91cc\u63d0\u793a\u9700\u8981\u8f93\u5165\uff1a\u53ef\u4ee5 write_stdin\u3002<\/li>\n<li>\u660e\u786e\u5931\u8d25\uff1a\u6362\u7b56\u7565\u6216\u62a5\u544a\u9519\u8bef\u3002<\/li>\n<li>\u8d85\u65f6\u6216\u65e0\u8f93\u51fa\uff1a\u53ef\u4ee5 terminate \u6216\u6539\u7528\u66f4\u7a84\u547d\u4ee4\u3002<\/li>\n<\/ul>\n<hr \/>\n<h2>7. \u957f\u547d\u4ee4\u201c\u5361\u6b7b\u201d\u7684\u8bc6\u522b\u7b56\u7565\u603b\u7ed3<\/h2>\n<p>codex-main \u6ca1\u6709\u53ea\u9760\u4e00\u4e2a\u201c\u8d85\u65f6\u79d2\u8868\u201d\u5224\u65ad\u5361\u6b7b\uff0c\u800c\u662f\u6309\u547d\u4ee4\u7c7b\u578b\u5206\u5c42\uff1a<\/p>\n<table>\n<thead>\n<tr>\n<th>\u573a\u666f<\/th>\n<th>\u673a\u5236<\/th>\n<th>\u4f18\u5316\u7ed3\u679c<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u666e\u901a\u547d\u4ee4\u4e0d\u9000\u51fa<\/td>\n<td><code>ExecExpiration<\/code> + <code>tokio::select!<\/code><\/td>\n<td>\u5230\u70b9 kill\uff0c\u4e0d\u963b\u585e turn<\/td>\n<\/tr>\n<tr>\n<td>\u5b50\u8fdb\u7a0b\/\u5b59\u8fdb\u7a0b\u5bfc\u81f4 pipe \u4e0d\u5173\u95ed<\/td>\n<td><code>IO_DRAIN_TIMEOUT_MS<\/code><\/td>\n<td>kill \u540e\u6700\u591a drain \u4e00\u5c0f\u6bb5\u65f6\u95f4\uff0c\u907f\u514d agent \u81ea\u5df1\u6302\u6b7b<\/td>\n<\/tr>\n<tr>\n<td>\u8f93\u51fa\u8fc7\u5927<\/td>\n<td>output cap + delta cap<\/td>\n<td>\u9632\u6b62\u5185\u5b58\u3001\u4e8b\u4ef6\u6d41\u3001\u6a21\u578b\u4e0a\u4e0b\u6587\u7206\u70b8<\/td>\n<\/tr>\n<tr>\n<td>\u8f93\u51fa\u5f88\u5feb<\/td>\n<td>\u6301\u7eed drain pipe<\/td>\n<td>\u9632\u6b62 stdout\/stderr \u80cc\u538b\u5bfc\u81f4\u8fdb\u7a0b\u5047\u6b7b<\/td>\n<\/tr>\n<tr>\n<td>\u957f\u9a7b\u8fdb\u7a0b<\/td>\n<td>unified_exec <code>yield_time_ms<\/code><\/td>\n<td>\u5230\u70b9\u8fd4\u56de partial output\uff0c\u8fdb\u7a0b\u540e\u53f0\u7ee7\u7eed<\/td>\n<\/tr>\n<tr>\n<td>\u4ea4\u4e92\u5f0f\u547d\u4ee4<\/td>\n<td><code>write_stdin<\/code> + process id<\/td>\n<td>\u6a21\u578b\u53ef\u4ee5\u7ee7\u7eed\u5582\u8f93\u5165\uff0c\u800c\u4e0d\u662f\u91cd\u542f\u547d\u4ee4<\/td>\n<\/tr>\n<tr>\n<td>\u540e\u53f0\u8fdb\u7a0b\u8fc7\u591a<\/td>\n<td>LRU prune<\/td>\n<td>\u63a7\u5236\u8d44\u6e90\u5360\u7528<\/td>\n<\/tr>\n<tr>\n<td>\u7528\u6237\u4e2d\u65ad<\/td>\n<td>cancellation token<\/td>\n<td>\u5de5\u5177 future \u8fd4\u56de aborted output<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h2>8. \u6e90\u7801\u8c03\u7528\u94fe\u7d22\u5f15<\/h2>\n<h3>8.1 \u4e00\u6b21 turn \u7684\u4e3b\u8c03\u7528\u94fe<\/h3>\n<pre><code class=\"language-text\">Session \/ CodexThread\n  -&gt; session\/turn.rs::run_turn\n    -&gt; run_pre_sampling_compact\n    -&gt; ContextManager::for_prompt\n    -&gt; ModelClientSession::stream\n      -&gt; WebSocket stream or HTTP SSE stream\n    -&gt; stream_events_utils::handle_output_item_done\n      -&gt; ToolRouter::build_tool_call\n      -&gt; ToolCallRuntime::handle_tool_call\n      -&gt; ToolRegistry::dispatch_any\n    -&gt; drain_in_flight\n    -&gt; maybe run_auto_compact if token limit reached<\/code><\/pre>\n<h3>8.2 \u77ed\u671f\u5386\u53f2\u8c03\u7528\u94fe<\/h3>\n<pre><code class=\"language-text\">ContextManager\n  -&gt; items: Vec&lt;ResponseItem&gt;\n  -&gt; normalize_history\n  -&gt; for_prompt\n  -&gt; estimate_token_count_with_base_instructions\n  -&gt; replace_compacted_history \/ rollback<\/code><\/pre>\n<h3>9.3 \u957f\u671f memories \u8c03\u7528\u94fe<\/h3>\n<pre><code class=\"language-text\">Session startup\n  -&gt; memories::pipeline\n    -&gt; state::runtime::memories::claim_stage1_jobs_for_startup\n    -&gt; memory_trace::build_memories_from_trace_files\n      -&gt; ModelClient::summarize_memories\n    -&gt; record_stage1_output_usage\n    -&gt; get_phase2_input_selection\n    -&gt; phase2 global consolidation<\/code><\/pre>\n<h3>8.4 compact \u8c03\u7528\u94fe<\/h3>\n<pre><code class=\"language-text\">session\/turn.rs\n  -&gt; run_pre_sampling_compact\n  -&gt; maybe_run_previous_model_inline_compact\n  -&gt; run_auto_compact\n    -&gt; compact_remote::run_inline_remote_auto_compact_task\n    -&gt; compact::run_inline_auto_compact_task\n      -&gt; run_compact_task_inner\n      -&gt; Session::replace_compacted_history\n      -&gt; ModelClientSession::reset_websocket_session<\/code><\/pre>\n<h3>8.5 \u5e76\u884c\u5de5\u5177\u8c03\u7528\u94fe<\/h3>\n<pre><code class=\"language-text\">Responses API stream\n  -&gt; response.output_item.done\n  -&gt; stream_events_utils::handle_output_item_done\n  -&gt; ToolRouter::build_tool_call\n  -&gt; ToolCallRuntime::handle_tool_call\n    -&gt; tool_supports_parallel\n    -&gt; RwLock read\/write gate\n    -&gt; ToolRouter::dispatch_tool_call_with_code_mode_result\n    -&gt; ToolRegistry::dispatch_any\n    -&gt; specific handler<\/code><\/pre>\n<h3>8.6 \u666e\u901a shell \u9632\u5361\u6b7b\u8c03\u7528\u94fe<\/h3>\n<pre><code class=\"language-text\">ShellHandler\n  -&gt; process_exec_tool_call\n  -&gt; exec\n  -&gt; spawn_child_async\n  -&gt; consume_output\n    -&gt; tokio::select!(child.wait, expiration, ctrl-c)\n    -&gt; kill_child_process_group on timeout\n    -&gt; read_output stdout\/stderr\n    -&gt; IO drain timeout<\/code><\/pre>\n<h3>8.7 unified_exec \u957f\u547d\u4ee4\u8c03\u7528\u94fe<\/h3>\n<pre><code class=\"language-text\">UnifiedExecHandler\n  -&gt; ProcessManager::allocate_process_id\n  -&gt; ProcessManager::exec_command\n    -&gt; UnifiedExecProcess::spawn\n    -&gt; HeadTailBuffer\n    -&gt; Notify output waiters\n    -&gt; collect_output_until_deadline\n    -&gt; return partial output + process_id\n  -&gt; wait \/ write_stdin \/ terminate<\/code><\/pre>\n<hr \/>\n<h2>9. \u540d\u8bcd\u901f\u67e5<\/h2>\n<table>\n<thead>\n<tr>\n<th>\u540d\u8bcd<\/th>\n<th>\u542b\u4e49<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>turn<\/code><\/td>\n<td>\u4e00\u6b21\u7528\u6237\u8f93\u5165\u5230\u6a21\u578b\u5b8c\u6210\u54cd\u5e94\u7684 runtime \u8c03\u5ea6\u5468\u671f\u3002\u5185\u90e8\u53ef\u80fd\u5305\u542b\u591a\u6b21\u6a21\u578b\u91c7\u6837\u548c\u591a\u4e2a\u5de5\u5177\u8c03\u7528\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>Session<\/code><\/td>\n<td>\u7ebf\u7a0b\u7ea7\u8fd0\u884c\u72b6\u6001\uff0c\u62e5\u6709 history\u3001\u914d\u7f6e\u3001\u5de5\u5177\u3001\u5ba1\u6279\u3001memory \u72b6\u6001\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>TurnContext<\/code><\/td>\n<td>\u672c\u8f6e\u4e0d\u53ef\u6216\u5c11\u7684\u4e0a\u4e0b\u6587\u5feb\u7167\uff0c\u4f8b\u5982\u6a21\u578b\u3001\u5de5\u5177\u3001sandbox\u3001\u5ba1\u6279\u7b56\u7565\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>ContextManager<\/code><\/td>\n<td>\u5f53\u524d\u7ebf\u7a0b\u77ed\u671f\u5386\u53f2\u7684 owner\uff0c\u8d1f\u8d23\u5f52\u4e00\u5316\u548c\u6295\u5f71\u4e3a\u6a21\u578b\u8f93\u5165\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>ResponseItem<\/code><\/td>\n<td>Responses API \u7684\u7edf\u4e00\u5386\u53f2\u6761\u76ee\uff0c\u5305\u62ec\u7528\u6237\u6d88\u606f\u3001\u52a9\u624b\u6d88\u606f\u3001\u5de5\u5177\u8c03\u7528\u3001\u5de5\u5177\u8f93\u51fa\u7b49\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>history_version<\/code><\/td>\n<td>history \u88ab\u91cd\u5199\u540e\u7684\u7248\u672c\u53f7\uff0ccompact\/rollback \u7b49\u4f1a\u9012\u589e\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>reference_context_item<\/code><\/td>\n<td>compact \u540e\u4fdd\u7559\u7684\u4e0a\u4e0b\u6587\u57fa\u7ebf\uff0c\u907f\u514d\u91cd\u590d\u6ce8\u5165\u65e7\u4e0a\u4e0b\u6587\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>ModelClientSession<\/code><\/td>\n<td>\u672c\u8f6e\u6a21\u578b\u534f\u8bae\u4f1a\u8bdd\uff0c\u7ba1\u7406 WebSocket\u3001<code>previous_response_id<\/code>\u3001<code>turn_state<\/code>\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>turn_state<\/code><\/td>\n<td>\u670d\u52a1\u7aef\u901a\u8fc7 <code>x-codex-turn-state<\/code> \u8fd4\u56de\u7684\u77ed\u751f\u547d\u5468\u671f\u534f\u8bae\u72b6\u6001\uff0c\u7528\u4e8e\u540c\u4e00 turn \u7684\u8bf7\u6c42\u9ecf\u6027\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>prompt_cache_key<\/code><\/td>\n<td>\u63d0\u793a\u7f13\u5b58 key\uff0c\u901a\u5e38\u6309 conversation id \u7a33\u5b9a\u8bbe\u7f6e\uff0c\u5e2e\u52a9\u670d\u52a1\u7aef cache \u547d\u4e2d\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>previous_response_id<\/code><\/td>\n<td>WebSocket \u589e\u91cf\u8bf7\u6c42\u7684\u951a\u70b9\uff0c\u8ba9\u4e0b\u4e00\u6b21\u53ea\u53d1\u9001\u65b0\u589e item\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>parallel_tool_calls<\/code><\/td>\n<td>\u6a21\u578b\u534f\u8bae\u5b57\u6bb5\uff0c\u5141\u8bb8\u6a21\u578b\u5728\u540c\u4e00\u8f6e\u89c4\u5212\u591a\u4e2a\u5de5\u5177\u8c03\u7528\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>ToolRouter<\/code><\/td>\n<td>\u628a\u6a21\u578b\u8f93\u51fa item \u89e3\u6790\u6210\u5177\u4f53\u5de5\u5177\u8c03\u7528\uff0c\u5e76\u5224\u65ad\u5de5\u5177\u5c5e\u6027\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>ToolCallRuntime<\/code><\/td>\n<td>\u5de5\u5177\u8c03\u7528\u6267\u884c runtime\uff0c\u7528\u8bfb\u5199\u9501\u63a7\u5236\u5e76\u884c\u4e0e\u72ec\u5360\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>ToolRegistry<\/code><\/td>\n<td>\u5de5\u5177 handler \u6ce8\u518c\u3001mutating \u5224\u65ad\u3001hook\u3001telemetry \u548c\u6700\u7ec8 dispatch\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>Compact<\/code><\/td>\n<td>\u538b\u7f29\u5386\u53f2\u7684 runtime \u673a\u5236\uff0c\u5305\u62ec\u672c\u5730\u603b\u7ed3\u548c\u8fdc\u7aef provider compact\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>InitialContextInjection<\/code><\/td>\n<td>compact \u540e initial context \u7684\u63d2\u5165\u7b56\u7565\uff0cmid-turn \u65f6\u5e38\u7528 <code>BeforeLastUserMessage<\/code>\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>Memory polluted<\/code><\/td>\n<td>\u5f53\u524d\u7ebf\u7a0b\u56e0\u5916\u90e8\u4e0a\u4e0b\u6587\u7b49\u539f\u56e0\u4e0d\u9002\u5408\u5199\u5165\u957f\u671f memory\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>ExecExpiration<\/code><\/td>\n<td>\u666e\u901a\u547d\u4ee4\u7684\u7ed3\u675f\u6761\u4ef6\u62bd\u8c61\uff0c\u5305\u62ec\u8d85\u65f6\u3001\u9ed8\u8ba4\u8d85\u65f6\u3001\u53d6\u6d88\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>IO_DRAIN_TIMEOUT_MS<\/code><\/td>\n<td>kill \u540e\u7b49\u5f85 stdout\/stderr drain \u7684\u4e0a\u9650\uff0c\u9632\u6b62 pipe \u4e0d\u5173\u95ed\u5bfc\u81f4 runtime \u5361\u4f4f\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>unified_exec<\/code><\/td>\n<td>\u957f\u547d\u4ee4\/\u4ea4\u4e92\u5f0f\u547d\u4ee4 runtime\uff0c\u652f\u6301\u540e\u53f0 process\u3001partial output\u3001wait\/write_stdin\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>yield_time_ms<\/code><\/td>\n<td>unified_exec \u5355\u6b21\u5de5\u5177\u8c03\u7528\u7b49\u5f85\u8f93\u51fa\u7684\u65f6\u95f4\u4e0a\u9650\uff0c\u4e0d\u7b49\u540c\u4e8e\u547d\u4ee4\u603b\u8d85\u65f6\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>HeadTailBuffer<\/code><\/td>\n<td>\u957f\u8f93\u51fa\u4fdd\u7559\u7ed3\u6784\uff0c\u907f\u514d\u65e0\u9650\u65e5\u5fd7\u5360\u6ee1\u5185\u5b58\uff0c\u540c\u65f6\u4fdd\u7559\u6709\u7528\u5934\u5c3e\u4fe1\u606f\u3002<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n","protected":false},"excerpt":{"rendered":"<p>codex-main Runtime \u67b6\u6784\u6df1\u62c6\uff1a\u8bb0\u5fc6\u3001\u538b\u7f29\u3001\u5e76\u884c\u6267\u884c\u4e0e\u5361\u6b7b\u8bc6\u522b \u672c\u6587\u9762\u5411 AppCheckMa [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1628","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/posts\/1628","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/comments?post=1628"}],"version-history":[{"count":2,"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/posts\/1628\/revisions"}],"predecessor-version":[{"id":1642,"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/posts\/1628\/revisions\/1642"}],"wp:attachment":[{"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/media?parent=1628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/categories?post=1628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.shangwendada.top\/index.php\/wp-json\/wp\/v2\/tags?post=1628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}