feat: complete web curriculum visuals
86
web/public/course-assets/s01_agent_loop/agent-loop.en.svg
Normal file
@@ -0,0 +1,86 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 530" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="720" height="530" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="720" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Agent Loop — A while Loop Drives the Entire Agent</text>
|
||||
|
||||
<!-- ===== User Input ===== -->
|
||||
<rect x="60" y="80" width="160" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="140" y="102" fill="#1e3a5f" font-size="13" font-weight="600" text-anchor="middle">User Query</text>
|
||||
<text x="140" y="120" fill="#64748b" font-size="11" text-anchor="middle">"Create hello.py for me"</text>
|
||||
|
||||
<!-- Arrow: User → Messages -->
|
||||
<line x1="140" y1="132" x2="140" y2="162" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- ===== Messages ===== -->
|
||||
<rect x="60" y="164" width="160" height="48" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="4,2"/>
|
||||
<text x="140" y="185" fill="#334155" font-size="12" font-weight="500" text-anchor="middle">messages[]</text>
|
||||
<text x="140" y="201" fill="#94a3b8" font-size="10" text-anchor="middle">Accumulated message list</text>
|
||||
|
||||
<!-- Arrow: Messages → LLM -->
|
||||
<line x1="220" y1="188" x2="288" y2="188" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== LLM ===== -->
|
||||
<rect x="290" y="140" width="180" height="96" rx="8" fill="#fff" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="380" y="166" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<line x1="310" y1="176" x2="450" y2="176" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="380" y="194" fill="#475569" font-size="11" text-anchor="middle">Model reads message history</text>
|
||||
<text x="380" y="210" fill="#475569" font-size="11" text-anchor="middle">Decision: Need a tool?</text>
|
||||
<text x="380" y="228" fill="#64748b" font-size="10" text-anchor="middle">Returns stop_reason signal</text>
|
||||
|
||||
<!-- Arrow: LLM → Decision (down) -->
|
||||
<line x1="380" y1="236" x2="380" y2="276" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== Decision Diamond ===== -->
|
||||
<polygon points="380,280 470,316 380,352 290,316" fill="#fff8f0" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="380" y="312" fill="#92400e" font-size="12" font-weight="600" text-anchor="middle">stop_reason</text>
|
||||
<text x="380" y="326" fill="#92400e" font-size="10" text-anchor="middle">== "tool_use"?</text>
|
||||
|
||||
<!-- Arrow: No → End (right) -->
|
||||
<line x1="470" y1="316" x2="540" y2="316" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="505" y="308" fill="#16a34a" font-size="10" font-weight="600" text-anchor="middle">No</text>
|
||||
|
||||
<!-- End Node -->
|
||||
<rect x="542" y="294" width="130" height="44" rx="22" fill="#dcfce7" stroke="#16a34a" stroke-width="2"/>
|
||||
<text x="607" y="313" fill="#166534" font-size="12" font-weight="600" text-anchor="middle">Return Result</text>
|
||||
<text x="607" y="329" fill="#166534" font-size="10" text-anchor="middle">Loop Ends</text>
|
||||
|
||||
<!-- Arrow: Yes → Tool Execution (down) -->
|
||||
<line x1="380" y1="352" x2="380" y2="392" stroke="#d97706" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="395" y="376" fill="#d97706" font-size="10" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ===== Tool Execution ===== -->
|
||||
<rect x="290" y="394" width="180" height="48" rx="8" fill="#fff7ed" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="380" y="415" fill="#92400e" font-size="12" font-weight="600" text-anchor="middle">Execute Tool Call</text>
|
||||
<text x="380" y="432" fill="#92400e" font-size="10" text-anchor="middle">run_bash(command)</text>
|
||||
|
||||
<!-- Arrow: Tool result → Append to messages (loop back) -->
|
||||
<path d="M 290 418 L 40 418 L 40 188 L 58 188" fill="none" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="18" y="375" fill="#92400e" font-size="10" font-weight="500" transform="rotate(-90, 18, 375)">Append tool_result to messages</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="60" y="462" width="600" height="48" rx="6" fill="#f1f5f9"/>
|
||||
<text x="80" y="482" fill="#334155" font-size="10">Core: a</text>
|
||||
<text x="113" y="482" fill="#1e3a5f" font-size="10" font-weight="700" font-family="monospace">while True</text>
|
||||
<text x="186" y="482" fill="#334155" font-size="10">loop. Model calls tool → Execute → Feed back → Ask again. No tool call → Stop.</text>
|
||||
<text x="80" y="500" fill="#64748b" font-size="10">All subsequent chapters layer mechanisms on top of this loop.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
86
web/public/course-assets/s01_agent_loop/agent-loop.ja.svg
Normal file
@@ -0,0 +1,86 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 530" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="720" height="530" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="720" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="31" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Agent Loop — 一つの while ループで Agent 全体を駆動</text>
|
||||
|
||||
<!-- ===== ユーザー入力 ===== -->
|
||||
<rect x="60" y="80" width="160" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="140" y="102" fill="#1e3a5f" font-size="13" font-weight="600" text-anchor="middle">ユーザーの質問</text>
|
||||
<text x="140" y="120" fill="#64748b" font-size="11" text-anchor="middle">"hello.py を作って"</text>
|
||||
|
||||
<!-- 矢印:ユーザー → メッセージリスト -->
|
||||
<line x1="140" y1="132" x2="140" y2="162" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- ===== メッセージリスト ===== -->
|
||||
<rect x="60" y="164" width="160" height="48" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="4,2"/>
|
||||
<text x="140" y="185" fill="#334155" font-size="12" font-weight="500" text-anchor="middle">messages[]</text>
|
||||
<text x="140" y="201" fill="#94a3b8" font-size="10" text-anchor="middle">累積メッセージリスト</text>
|
||||
|
||||
<!-- 矢印:メッセージ → LLM -->
|
||||
<line x1="220" y1="188" x2="288" y2="188" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== LLM ===== -->
|
||||
<rect x="290" y="140" width="180" height="96" rx="8" fill="#fff" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="380" y="166" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">大規模言語モデル (LLM)</text>
|
||||
<line x1="310" y1="176" x2="450" y2="176" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="380" y="194" fill="#475569" font-size="11" text-anchor="middle">モデルがメッセージ履歴を読む</text>
|
||||
<text x="380" y="210" fill="#475569" font-size="11" text-anchor="middle">判断:ツールが必要か?</text>
|
||||
<text x="380" y="228" fill="#64748b" font-size="10" text-anchor="middle">stop_reason シグナルを返す</text>
|
||||
|
||||
<!-- 矢印:LLM → 判定(下) -->
|
||||
<line x1="380" y1="236" x2="380" y2="276" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== 判定ダイヤモンド ===== -->
|
||||
<polygon points="380,280 470,316 380,352 290,316" fill="#fff8f0" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="380" y="312" fill="#92400e" font-size="12" font-weight="600" text-anchor="middle">stop_reason</text>
|
||||
<text x="380" y="326" fill="#92400e" font-size="10" text-anchor="middle">== "tool_use"?</text>
|
||||
|
||||
<!-- 矢印:いいえ → 終了(右) -->
|
||||
<line x1="470" y1="316" x2="540" y2="316" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="505" y="308" fill="#16a34a" font-size="10" font-weight="600" text-anchor="middle">No</text>
|
||||
|
||||
<!-- 終了ノード -->
|
||||
<rect x="542" y="294" width="130" height="44" rx="22" fill="#dcfce7" stroke="#16a34a" stroke-width="2"/>
|
||||
<text x="607" y="313" fill="#166534" font-size="12" font-weight="600" text-anchor="middle">結果を返す</text>
|
||||
<text x="607" y="329" fill="#166534" font-size="10" text-anchor="middle">ループ終了</text>
|
||||
|
||||
<!-- 矢印:はい → ツール実行(下) -->
|
||||
<line x1="380" y1="352" x2="380" y2="392" stroke="#d97706" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="395" y="376" fill="#d97706" font-size="10" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ===== ツール実行 ===== -->
|
||||
<rect x="290" y="394" width="180" height="48" rx="8" fill="#fff7ed" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="380" y="415" fill="#92400e" font-size="12" font-weight="600" text-anchor="middle">ツール呼び出しを実行</text>
|
||||
<text x="380" y="432" fill="#92400e" font-size="10" text-anchor="middle">run_bash(command)</text>
|
||||
|
||||
<!-- 矢印:ツール結果 → メッセージに追加(ループバック) -->
|
||||
<path d="M 290 418 L 40 418 L 40 188 L 58 188" fill="none" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="18" y="375" fill="#92400e" font-size="10" font-weight="500" transform="rotate(-90, 18, 375)">tool_result を messages に追加</text>
|
||||
|
||||
<!-- 凡例 -->
|
||||
<rect x="60" y="462" width="600" height="48" rx="6" fill="#f1f5f9"/>
|
||||
<text x="80" y="482" fill="#334155" font-size="10">核心:一つの</text>
|
||||
<text x="138" y="482" fill="#1e3a5f" font-size="10" font-weight="700" font-family="monospace">while True</text>
|
||||
<text x="210" y="482" fill="#334155" font-size="10">ループ。ツール呼出 → 実行 → 結果を戻す → 再度問う。ツールなし → 停止。</text>
|
||||
<text x="80" y="500" fill="#64748b" font-size="10">以降の全章がこのループの上に仕組みを積み重ねる。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
86
web/public/course-assets/s01_agent_loop/agent-loop.svg
Normal file
@@ -0,0 +1,86 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 530" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="720" height="530" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- 标题 -->
|
||||
<rect x="0" y="0" width="720" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Agent Loop — 一个 while 循环驱动整个 Agent</text>
|
||||
|
||||
<!-- ===== 用户输入 ===== -->
|
||||
<rect x="60" y="80" width="160" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="140" y="102" fill="#1e3a5f" font-size="13" font-weight="600" text-anchor="middle">用户提问</text>
|
||||
<text x="140" y="120" fill="#64748b" font-size="11" text-anchor="middle">"帮我创建 hello.py"</text>
|
||||
|
||||
<!-- 箭头:用户 → 消息列表 -->
|
||||
<line x1="140" y1="132" x2="140" y2="162" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- ===== 消息列表 ===== -->
|
||||
<rect x="60" y="164" width="160" height="48" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="4,2"/>
|
||||
<text x="140" y="185" fill="#334155" font-size="12" font-weight="500" text-anchor="middle">messages[]</text>
|
||||
<text x="140" y="201" fill="#94a3b8" font-size="10" text-anchor="middle">累积式消息列表</text>
|
||||
|
||||
<!-- 箭头:消息列表 → LLM -->
|
||||
<line x1="220" y1="188" x2="288" y2="188" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== LLM ===== -->
|
||||
<rect x="290" y="140" width="180" height="96" rx="8" fill="#fff" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="380" y="166" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">大模型 (LLM)</text>
|
||||
<line x1="310" y1="176" x2="450" y2="176" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="380" y="194" fill="#475569" font-size="11" text-anchor="middle">模型阅读消息历史</text>
|
||||
<text x="380" y="210" fill="#475569" font-size="11" text-anchor="middle">判断:需要工具吗?</text>
|
||||
<text x="380" y="228" fill="#64748b" font-size="10" text-anchor="middle">返回 stop_reason 信号</text>
|
||||
|
||||
<!-- 箭头:LLM → 判断(向下) -->
|
||||
<line x1="380" y1="236" x2="380" y2="276" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== 判断菱形 ===== -->
|
||||
<polygon points="380,280 470,316 380,352 290,316" fill="#fff8f0" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="380" y="312" fill="#92400e" font-size="12" font-weight="600" text-anchor="middle">stop_reason</text>
|
||||
<text x="380" y="326" fill="#92400e" font-size="10" text-anchor="middle">== "tool_use"?</text>
|
||||
|
||||
<!-- 箭头:否 → 结束(向右) -->
|
||||
<line x1="470" y1="316" x2="540" y2="316" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="505" y="308" fill="#16a34a" font-size="10" font-weight="600" text-anchor="middle">否</text>
|
||||
|
||||
<!-- 结束节点 -->
|
||||
<rect x="542" y="294" width="130" height="44" rx="22" fill="#dcfce7" stroke="#16a34a" stroke-width="2"/>
|
||||
<text x="607" y="313" fill="#166534" font-size="12" font-weight="600" text-anchor="middle">返回结果</text>
|
||||
<text x="607" y="329" fill="#166534" font-size="10" text-anchor="middle">循环结束</text>
|
||||
|
||||
<!-- 箭头:是 → 工具执行(向下) -->
|
||||
<line x1="380" y1="352" x2="380" y2="392" stroke="#d97706" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="395" y="376" fill="#d97706" font-size="10" font-weight="600">是</text>
|
||||
|
||||
<!-- ===== 工具执行 ===== -->
|
||||
<rect x="290" y="394" width="180" height="48" rx="8" fill="#fff7ed" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="380" y="415" fill="#92400e" font-size="12" font-weight="600" text-anchor="middle">执行工具调用</text>
|
||||
<text x="380" y="432" fill="#92400e" font-size="10" text-anchor="middle">run_bash(command)</text>
|
||||
|
||||
<!-- 箭头:工具结果 → 追加到消息列表(向左弯回去) -->
|
||||
<path d="M 290 418 L 40 418 L 40 188 L 58 188" fill="none" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="18" y="375" fill="#92400e" font-size="10" font-weight="500" transform="rotate(-90, 18, 375)">追加 tool_result 到 messages</text>
|
||||
|
||||
<!-- 图例 -->
|
||||
<rect x="60" y="462" width="600" height="48" rx="6" fill="#f1f5f9"/>
|
||||
<text x="80" y="482" fill="#334155" font-size="10">核心:一个</text>
|
||||
<text x="148" y="482" fill="#1e3a5f" font-size="10" font-weight="700" font-family="monospace">while True</text>
|
||||
<text x="220" y="482" fill="#334155" font-size="10">循环。模型调工具 → 执行 → 喂回 → 再问。不调工具就停。</text>
|
||||
<text x="80" y="500" fill="#64748b" font-size="10">后续所有章节都在这个循环上叠加机制。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,108 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 500" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="teach" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fef3c7"/><stop offset="100%" stop-color="#fde68a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="cc" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#dcfce7"/><stop offset="100%" stop-color="#bbf7d0"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow-g" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="5" markerHeight="5" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="500" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="760" height="36" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="28" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="24" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Tool Concurrency — Teaching Version vs Claude Code</text>
|
||||
|
||||
<!-- Input tool blocks -->
|
||||
<rect x="180" y="52" width="400" height="28" rx="14" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="380" y="71" fill="#475569" font-size="11" font-weight="600" text-anchor="middle">Model returns 5 tool calls at once</text>
|
||||
|
||||
<rect x="38" y="92" width="100" height="36" rx="4" fill="#dbeafe" stroke="#93c5fd" stroke-width="1"/>
|
||||
<text x="88" y="114" fill="#1e40af" font-size="10" font-weight="600" text-anchor="middle">read A.py</text>
|
||||
|
||||
<rect x="148" y="92" width="100" height="36" rx="4" fill="#dbeafe" stroke="#93c5fd" stroke-width="1"/>
|
||||
<text x="198" y="114" fill="#1e40af" font-size="10" font-weight="600" text-anchor="middle">glob *.py</text>
|
||||
|
||||
<rect x="258" y="92" width="110" height="36" rx="4" fill="#fef3c7" stroke="#fbbf24" stroke-width="1"/>
|
||||
<text x="313" y="114" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">bash "ls -la"</text>
|
||||
|
||||
<rect x="378" y="92" width="100" height="36" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="428" y="114" fill="#991b1b" font-size="10" font-weight="600" text-anchor="middle">write B.py</text>
|
||||
|
||||
<rect x="488" y="92" width="100" height="36" rx="4" fill="#dbeafe" stroke="#93c5fd" stroke-width="1"/>
|
||||
<text x="538" y="114" fill="#1e40af" font-size="10" font-weight="600" text-anchor="middle">read C.py</text>
|
||||
|
||||
<!-- LEFT: Teaching Version -->
|
||||
<rect x="20" y="156" width="350" height="230" rx="8" fill="url(#teach)" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="195" y="180" fill="#92400e" font-size="13" font-weight="700" text-anchor="middle">Teaching: Original Order, One by One</text>
|
||||
|
||||
<rect x="35" y="192" width="320" height="46" rx="4" fill="#fff" stroke="#fbbf24" stroke-width="0.5"/>
|
||||
<text x="46" y="209" fill="#92400e" font-size="9" font-family="monospace">for block in response.content:</text>
|
||||
<text x="46" y="224" fill="#92400e" font-size="9" font-family="monospace"> TOOL_HANDLERS[name](**input)</text>
|
||||
|
||||
<text x="195" y="258" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Result: 5 serial calls, no batches</text>
|
||||
|
||||
<rect x="45" y="270" width="300" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="284" fill="#92400e" font-size="8" font-weight="600">1. read A.py</text>
|
||||
|
||||
<rect x="45" y="294" width="300" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="308" fill="#92400e" font-size="8" font-weight="600">2. glob *.py</text>
|
||||
|
||||
<rect x="45" y="318" width="300" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="332" fill="#92400e" font-size="8" font-weight="600">3. bash "ls -la"</text>
|
||||
|
||||
<rect x="45" y="342" width="145" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="356" fill="#92400e" font-size="8" font-weight="600">4. write B.py</text>
|
||||
|
||||
<rect x="200" y="342" width="145" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="215" y="356" fill="#92400e" font-size="8" font-weight="600">5. read C.py</text>
|
||||
|
||||
<text x="195" y="378" fill="#dc2626" font-size="8" font-weight="600" text-anchor="middle">Teaching focus: tool dispatch first; concurrency omitted</text>
|
||||
|
||||
<!-- RIGHT: Claude Code -->
|
||||
<rect x="390" y="156" width="350" height="230" rx="8" fill="url(#cc)" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="565" y="180" fill="#166534" font-size="13" font-weight="700" text-anchor="middle">Claude Code: isConcurrencySafe(input)</text>
|
||||
|
||||
<rect x="405" y="192" width="320" height="38" rx="4" fill="#fff" stroke="#86efac" stroke-width="0.5"/>
|
||||
<text x="416" y="207" fill="#166534" font-size="9" font-family="monospace">Each tool call judged individually:</text>
|
||||
<text x="416" y="222" fill="#166534" font-size="9" font-family="monospace">tool.isConcurrencySafe(parsedInput) → bool</text>
|
||||
|
||||
<text x="565" y="250" fill="#166534" font-size="10" font-weight="600" text-anchor="middle">Result: 3 batches (by consecutive blocks)</text>
|
||||
|
||||
<rect x="400" y="258" width="155" height="50" rx="4" fill="#dcfce7" stroke="#86efac" stroke-width="1"/>
|
||||
<text x="477" y="276" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">Batch 1</text>
|
||||
<text x="477" y="289" fill="#166534" font-size="8" text-anchor="middle">Concurrent</text>
|
||||
<text x="477" y="302" fill="#166534" font-size="7" text-anchor="middle">read A · glob · bash "ls"</text>
|
||||
|
||||
<line x1="560" y1="283" x2="575" y2="283" stroke="#16a34a" stroke-width="1" marker-end="url(#arrow-g)"/>
|
||||
|
||||
<rect x="580" y="258" width="65" height="50" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="612" y="276" fill="#991b1b" font-size="8" font-weight="600" text-anchor="middle">Batch 2</text>
|
||||
<text x="612" y="289" fill="#991b1b" font-size="8" text-anchor="middle">Serial</text>
|
||||
<text x="612" y="302" fill="#991b1b" font-size="7" text-anchor="middle">write B</text>
|
||||
|
||||
<line x1="650" y1="283" x2="665" y2="283" stroke="#16a34a" stroke-width="1" marker-end="url(#arrow-g)"/>
|
||||
|
||||
<rect x="670" y="258" width="55" height="50" rx="4" fill="#dcfce7" stroke="#86efac" stroke-width="1"/>
|
||||
<text x="697" y="276" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">Batch 3</text>
|
||||
<text x="697" y="289" fill="#166534" font-size="8" text-anchor="middle">Concurrent</text>
|
||||
<text x="697" y="302" fill="#166534" font-size="7" text-anchor="middle">read C</text>
|
||||
|
||||
<text x="565" y="332" fill="#16a34a" font-size="8" font-weight="600" text-anchor="middle">bash "ls" is safe and consecutive, so it stays in Batch 1</text>
|
||||
|
||||
<text x="565" y="366" fill="#16a34a" font-size="9" font-weight="600" text-anchor="middle">✓ Input-dependent safety, not tool-name hardcoding</text>
|
||||
<text x="565" y="380" fill="#16a34a" font-size="9" font-weight="600" text-anchor="middle">✓ Original order preserved; only safe consecutive calls run together</text>
|
||||
|
||||
<!-- Bottom Summary -->
|
||||
<rect x="20" y="402" width="720" height="82" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="40" y="424" fill="#1e3a5f" font-size="12" font-weight="600">Key Difference</text>
|
||||
<text x="40" y="444" fill="#475569" font-size="10">• Teaching: executes response.content in original order, one tool call at a time; no concurrency or batching</text>
|
||||
<text x="40" y="460" fill="#475569" font-size="10">• CC: checks isConcurrencySafe(input), then groups consecutive safe calls into one batch</text>
|
||||
<text x="40" y="476" fill="#475569" font-size="10">• Key difference: teaching focuses on dispatch; CC optimizes safe concurrency while preserving order semantics</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
@@ -0,0 +1,108 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 500" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="teach" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fef3c7"/><stop offset="100%" stop-color="#fde68a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="cc" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#dcfce7"/><stop offset="100%" stop-color="#bbf7d0"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow-g" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="5" markerHeight="5" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="500" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="760" height="36" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="28" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="24" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">ツール並列実行 — 教育版 vs Claude Code</text>
|
||||
|
||||
<!-- 入力ツールブロック -->
|
||||
<rect x="180" y="52" width="400" height="28" rx="14" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="380" y="71" fill="#475569" font-size="11" font-weight="600" text-anchor="middle">モデルが一度に 5 つのツール呼び出しを返す</text>
|
||||
|
||||
<rect x="38" y="92" width="100" height="36" rx="4" fill="#dbeafe" stroke="#93c5fd" stroke-width="1"/>
|
||||
<text x="88" y="114" fill="#1e40af" font-size="10" font-weight="600" text-anchor="middle">read A.py</text>
|
||||
|
||||
<rect x="148" y="92" width="100" height="36" rx="4" fill="#dbeafe" stroke="#93c5fd" stroke-width="1"/>
|
||||
<text x="198" y="114" fill="#1e40af" font-size="10" font-weight="600" text-anchor="middle">glob *.py</text>
|
||||
|
||||
<rect x="258" y="92" width="110" height="36" rx="4" fill="#fef3c7" stroke="#fbbf24" stroke-width="1"/>
|
||||
<text x="313" y="114" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">bash "ls -la"</text>
|
||||
|
||||
<rect x="378" y="92" width="100" height="36" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="428" y="114" fill="#991b1b" font-size="10" font-weight="600" text-anchor="middle">write B.py</text>
|
||||
|
||||
<rect x="488" y="92" width="100" height="36" rx="4" fill="#dbeafe" stroke="#93c5fd" stroke-width="1"/>
|
||||
<text x="538" y="114" fill="#1e40af" font-size="10" font-weight="600" text-anchor="middle">read C.py</text>
|
||||
|
||||
<!-- 左:教育版 -->
|
||||
<rect x="20" y="156" width="350" height="230" rx="8" fill="url(#teach)" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="195" y="180" fill="#92400e" font-size="13" font-weight="700" text-anchor="middle">教育版:元の順序で一つずつ実行</text>
|
||||
|
||||
<rect x="35" y="192" width="320" height="46" rx="4" fill="#fff" stroke="#fbbf24" stroke-width="0.5"/>
|
||||
<text x="46" y="209" fill="#92400e" font-size="9" font-family="monospace">for block in response.content:</text>
|
||||
<text x="46" y="224" fill="#92400e" font-size="9" font-family="monospace"> TOOL_HANDLERS[name](**input)</text>
|
||||
|
||||
<text x="195" y="258" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">結果:5 回の直列呼び出し、batch なし</text>
|
||||
|
||||
<rect x="45" y="270" width="300" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="284" fill="#92400e" font-size="8" font-weight="600">1. read A.py</text>
|
||||
|
||||
<rect x="45" y="294" width="300" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="308" fill="#92400e" font-size="8" font-weight="600">2. glob *.py</text>
|
||||
|
||||
<rect x="45" y="318" width="300" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="332" fill="#92400e" font-size="8" font-weight="600">3. bash "ls -la"</text>
|
||||
|
||||
<rect x="45" y="342" width="145" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="356" fill="#92400e" font-size="8" font-weight="600">4. write B.py</text>
|
||||
|
||||
<rect x="200" y="342" width="145" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="215" y="356" fill="#92400e" font-size="8" font-weight="600">5. read C.py</text>
|
||||
|
||||
<text x="195" y="378" fill="#dc2626" font-size="8" font-weight="600" text-anchor="middle">教育の焦点:まず tool_use 分配を理解し、並列は省略</text>
|
||||
|
||||
<!-- 右:Claude Code -->
|
||||
<rect x="390" y="156" width="350" height="230" rx="8" fill="url(#cc)" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="565" y="180" fill="#166534" font-size="13" font-weight="700" text-anchor="middle">Claude Code:isConcurrencySafe(input)</text>
|
||||
|
||||
<rect x="405" y="192" width="320" height="38" rx="4" fill="#fff" stroke="#86efac" stroke-width="0.5"/>
|
||||
<text x="416" y="207" fill="#166534" font-size="9" font-family="monospace">各ツール呼び出しを個別に判定:</text>
|
||||
<text x="416" y="222" fill="#166534" font-size="9" font-family="monospace">tool.isConcurrencySafe(parsedInput) → bool</text>
|
||||
|
||||
<text x="565" y="250" fill="#166534" font-size="10" font-weight="600" text-anchor="middle">結果:3 バッチ(連続ブロックごと)</text>
|
||||
|
||||
<rect x="400" y="258" width="155" height="50" rx="4" fill="#dcfce7" stroke="#86efac" stroke-width="1"/>
|
||||
<text x="477" y="276" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">Batch 1</text>
|
||||
<text x="477" y="289" fill="#166534" font-size="8" text-anchor="middle">並列</text>
|
||||
<text x="477" y="302" fill="#166534" font-size="7" text-anchor="middle">read A · glob · bash "ls"</text>
|
||||
|
||||
<line x1="560" y1="283" x2="575" y2="283" stroke="#16a34a" stroke-width="1" marker-end="url(#arrow-g)"/>
|
||||
|
||||
<rect x="580" y="258" width="65" height="50" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="612" y="276" fill="#991b1b" font-size="8" font-weight="600" text-anchor="middle">Batch 2</text>
|
||||
<text x="612" y="289" fill="#991b1b" font-size="8" text-anchor="middle">直列</text>
|
||||
<text x="612" y="302" fill="#991b1b" font-size="7" text-anchor="middle">write B</text>
|
||||
|
||||
<line x1="650" y1="283" x2="665" y2="283" stroke="#16a34a" stroke-width="1" marker-end="url(#arrow-g)"/>
|
||||
|
||||
<rect x="670" y="258" width="55" height="50" rx="4" fill="#dcfce7" stroke="#86efac" stroke-width="1"/>
|
||||
<text x="697" y="276" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">Batch 3</text>
|
||||
<text x="697" y="289" fill="#166534" font-size="8" text-anchor="middle">並列</text>
|
||||
<text x="697" y="302" fill="#166534" font-size="7" text-anchor="middle">read C</text>
|
||||
|
||||
<text x="565" y="332" fill="#16a34a" font-size="8" font-weight="600" text-anchor="middle">bash "ls" は安全かつ連続しているため Batch 1 に入る</text>
|
||||
|
||||
<text x="565" y="366" fill="#16a34a" font-size="9" font-weight="600" text-anchor="middle">✓ 入力に基づく安全判定、ツール名ハードコードではない</text>
|
||||
<text x="565" y="380" fill="#16a34a" font-size="9" font-weight="600" text-anchor="middle">✓ 元の順序を保ち、連続する安全呼び出しだけ並列化</text>
|
||||
|
||||
<!-- 下部まとめ -->
|
||||
<rect x="20" y="402" width="720" height="82" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="40" y="424" fill="#1e3a5f" font-size="12" font-weight="600">核心的な違い</text>
|
||||
<text x="40" y="444" fill="#475569" font-size="10">• 教育版:response.content の元の順序で一つずつ実行し、並列処理も batch 化もしない</text>
|
||||
<text x="40" y="460" fill="#475569" font-size="10">• CC:isConcurrencySafe(input) で判定し、連続する安全呼び出しを同じ batch にまとめる</text>
|
||||
<text x="40" y="476" fill="#475569" font-size="10">• 差分の要点:教育版は分配に集中し、CC は順序意味を保ったまま安全な並列を最適化する</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.8 KiB |
108
web/public/course-assets/s02_tool_use/concurrency-comparison.svg
Normal file
@@ -0,0 +1,108 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 500" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="teach" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fef3c7"/><stop offset="100%" stop-color="#fde68a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="cc" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#dcfce7"/><stop offset="100%" stop-color="#bbf7d0"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow-g" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="5" markerHeight="5" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="500" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="760" height="36" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="28" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="24" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Tool Concurrency — 教学版 vs Claude Code</text>
|
||||
|
||||
<!-- Input tool blocks -->
|
||||
<rect x="180" y="52" width="400" height="28" rx="14" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="380" y="71" fill="#475569" font-size="11" font-weight="600" text-anchor="middle">模型一次返回 5 个工具调用</text>
|
||||
|
||||
<rect x="38" y="92" width="100" height="36" rx="4" fill="#dbeafe" stroke="#93c5fd" stroke-width="1"/>
|
||||
<text x="88" y="114" fill="#1e40af" font-size="10" font-weight="600" text-anchor="middle">read A.py</text>
|
||||
|
||||
<rect x="148" y="92" width="100" height="36" rx="4" fill="#dbeafe" stroke="#93c5fd" stroke-width="1"/>
|
||||
<text x="198" y="114" fill="#1e40af" font-size="10" font-weight="600" text-anchor="middle">glob *.py</text>
|
||||
|
||||
<rect x="258" y="92" width="110" height="36" rx="4" fill="#fef3c7" stroke="#fbbf24" stroke-width="1"/>
|
||||
<text x="313" y="114" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">bash "ls -la"</text>
|
||||
|
||||
<rect x="378" y="92" width="100" height="36" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="428" y="114" fill="#991b1b" font-size="10" font-weight="600" text-anchor="middle">write B.py</text>
|
||||
|
||||
<rect x="488" y="92" width="100" height="36" rx="4" fill="#dbeafe" stroke="#93c5fd" stroke-width="1"/>
|
||||
<text x="538" y="114" fill="#1e40af" font-size="10" font-weight="600" text-anchor="middle">read C.py</text>
|
||||
|
||||
<!-- LEFT: Teaching Version -->
|
||||
<rect x="20" y="156" width="350" height="230" rx="8" fill="url(#teach)" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="195" y="180" fill="#92400e" font-size="13" font-weight="700" text-anchor="middle">教学版:按原始顺序逐个执行</text>
|
||||
|
||||
<rect x="35" y="192" width="320" height="46" rx="4" fill="#fff" stroke="#fbbf24" stroke-width="0.5"/>
|
||||
<text x="46" y="209" fill="#92400e" font-size="9" font-family="monospace">for block in response.content:</text>
|
||||
<text x="46" y="224" fill="#92400e" font-size="9" font-family="monospace"> TOOL_HANDLERS[name](**input)</text>
|
||||
|
||||
<text x="195" y="258" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">结果:5 次串行调用,不做 batch</text>
|
||||
|
||||
<rect x="45" y="270" width="300" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="284" fill="#92400e" font-size="8" font-weight="600">1. read A.py</text>
|
||||
|
||||
<rect x="45" y="294" width="300" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="308" fill="#92400e" font-size="8" font-weight="600">2. glob *.py</text>
|
||||
|
||||
<rect x="45" y="318" width="300" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="332" fill="#92400e" font-size="8" font-weight="600">3. bash "ls -la"</text>
|
||||
|
||||
<rect x="45" y="342" width="145" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="60" y="356" fill="#92400e" font-size="8" font-weight="600">4. write B.py</text>
|
||||
|
||||
<rect x="200" y="342" width="145" height="20" rx="4" fill="#fff7ed" stroke="#fbbf24" stroke-width="0.7"/>
|
||||
<text x="215" y="356" fill="#92400e" font-size="8" font-weight="600">5. read C.py</text>
|
||||
|
||||
<text x="195" y="378" fill="#dc2626" font-size="8" font-weight="600" text-anchor="middle">教学重点:先理解 tool_use 分发,暂不引入并发执行</text>
|
||||
|
||||
<!-- RIGHT: Claude Code -->
|
||||
<rect x="390" y="156" width="350" height="230" rx="8" fill="url(#cc)" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="565" y="180" fill="#166534" font-size="13" font-weight="700" text-anchor="middle">Claude Code:isConcurrencySafe(input)</text>
|
||||
|
||||
<rect x="405" y="192" width="320" height="38" rx="4" fill="#fff" stroke="#86efac" stroke-width="0.5"/>
|
||||
<text x="416" y="207" fill="#166534" font-size="9" font-family="monospace">每个工具调用单独判断:</text>
|
||||
<text x="416" y="222" fill="#166534" font-size="9" font-family="monospace">tool.isConcurrencySafe(parsedInput) → bool</text>
|
||||
|
||||
<text x="565" y="250" fill="#166534" font-size="10" font-weight="600" text-anchor="middle">结果:3 个 batch(按连续块分批)</text>
|
||||
|
||||
<rect x="400" y="258" width="155" height="50" rx="4" fill="#dcfce7" stroke="#86efac" stroke-width="1"/>
|
||||
<text x="477" y="276" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">Batch 1</text>
|
||||
<text x="477" y="289" fill="#166534" font-size="8" text-anchor="middle">并发</text>
|
||||
<text x="477" y="302" fill="#166534" font-size="7" text-anchor="middle">read A · glob · bash "ls"</text>
|
||||
|
||||
<line x1="560" y1="283" x2="575" y2="283" stroke="#16a34a" stroke-width="1" marker-end="url(#arrow-g)"/>
|
||||
|
||||
<rect x="580" y="258" width="65" height="50" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="612" y="276" fill="#991b1b" font-size="8" font-weight="600" text-anchor="middle">Batch 2</text>
|
||||
<text x="612" y="289" fill="#991b1b" font-size="8" text-anchor="middle">串行</text>
|
||||
<text x="612" y="302" fill="#991b1b" font-size="7" text-anchor="middle">write B</text>
|
||||
|
||||
<line x1="650" y1="283" x2="665" y2="283" stroke="#16a34a" stroke-width="1" marker-end="url(#arrow-g)"/>
|
||||
|
||||
<rect x="670" y="258" width="55" height="50" rx="4" fill="#dcfce7" stroke="#86efac" stroke-width="1"/>
|
||||
<text x="697" y="276" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">Batch 3</text>
|
||||
<text x="697" y="289" fill="#166534" font-size="8" text-anchor="middle">并发</text>
|
||||
<text x="697" y="302" fill="#166534" font-size="7" text-anchor="middle">read C</text>
|
||||
|
||||
<text x="565" y="332" fill="#16a34a" font-size="8" font-weight="600" text-anchor="middle">bash "ls" 是并发安全调用,且和 read/glob 连续,所以留在 Batch 1</text>
|
||||
|
||||
<text x="565" y="366" fill="#16a34a" font-size="9" font-weight="600" text-anchor="middle">✓ 按输入判断并发安全,不按工具名硬编码</text>
|
||||
<text x="565" y="380" fill="#16a34a" font-size="9" font-weight="600" text-anchor="middle">✓ 保留原始顺序,只在连续安全块内部并发</text>
|
||||
|
||||
<!-- Bottom Summary -->
|
||||
<rect x="20" y="402" width="720" height="82" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="40" y="424" fill="#1e3a5f" font-size="12" font-weight="600">核心差异</text>
|
||||
<text x="40" y="444" fill="#475569" font-size="10">• 教学版:按 response.content 原始顺序逐个执行,不做并发,也不分 batch</text>
|
||||
<text x="40" y="460" fill="#475569" font-size="10">• CC:按 isConcurrencySafe(input) 判断,并把连续的并发安全调用合成同一个 batch</text>
|
||||
<text x="40" y="476" fill="#475569" font-size="10">• 差异重点:教学版聚焦工具分发;CC 在保持顺序语义的同时优化安全并发</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
108
web/public/course-assets/s02_tool_use/tool-dispatch.en.svg
Normal file
@@ -0,0 +1,108 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 560" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-orange" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="720" height="560" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="720" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Tool Use — Loop Unchanged, Just Add Dispatch Mapping</text>
|
||||
|
||||
<!-- ===== s01 (gray, preserved) ===== -->
|
||||
<text x="50" y="76" fill="#94a3b8" font-size="11" font-weight="600">s01 Preserved</text>
|
||||
|
||||
<!-- User Input -->
|
||||
<rect x="60" y="86" width="140" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="130" y="105" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">User Query</text>
|
||||
<text x="130" y="121" fill="#64748b" font-size="10" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- Arrow: User → LLM -->
|
||||
<line x1="200" y1="108" x2="268" y2="108" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="270" y="82" width="150" height="52" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="345" y="104" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="345" y="122" fill="#64748b" font-size="10" text-anchor="middle">stop_reason check</text>
|
||||
|
||||
<!-- Arrow: LLM → Decision -->
|
||||
<line x1="345" y1="134" x2="345" y2="162" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Decision Diamond -->
|
||||
<polygon points="345,166 415,196 345,226 275,196" fill="#fff8f0" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="345" y="194" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">tool_use?</text>
|
||||
|
||||
<!-- No → Return -->
|
||||
<line x1="415" y1="196" x2="475" y2="196" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="445" y="189" fill="#16a34a" font-size="9" font-weight="600">No</text>
|
||||
<rect x="477" y="178" width="100" height="36" rx="18" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="527" y="200" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">Return Result</text>
|
||||
|
||||
<!-- Yes → Next Step -->
|
||||
<line x1="345" y1="226" x2="345" y2="260" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow-orange)"/>
|
||||
<text x="356" y="248" fill="#d97706" font-size="9" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ===== s02 New: TOOL_HANDLERS Dispatch Mapping ===== -->
|
||||
<text x="505" y="282" fill="#d97706" font-size="11" font-weight="600">s02 New</text>
|
||||
|
||||
<!-- Dispatch Mapping Outer Box -->
|
||||
<rect x="195" y="268" width="300" height="200" rx="10" fill="#fff7ed" stroke="#d97706" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="345" y="290" fill="#92400e" font-size="12" font-weight="700" text-anchor="middle">TOOL_HANDLERS Dispatch Mapping</text>
|
||||
|
||||
<!-- Arrow into dispatch mapping -->
|
||||
<line x1="345" y1="260" x2="345" y2="268" stroke="#d97706" stroke-width="1.5"/>
|
||||
|
||||
<!-- bash handler -->
|
||||
<rect x="220" y="300" width="120" height="34" rx="6" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.2"/>
|
||||
<text x="280" y="316" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">bash</text>
|
||||
<text x="280" y="328" fill="#64748b" font-size="9" text-anchor="middle">→ run_bash()</text>
|
||||
|
||||
<!-- read_file handler -->
|
||||
<rect x="360" y="300" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="420" y="316" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">read_file</text>
|
||||
<text x="420" y="328" fill="#64748b" font-size="9" text-anchor="middle">→ run_read()</text>
|
||||
|
||||
<!-- write_file handler -->
|
||||
<rect x="220" y="346" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="280" y="362" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">write_file</text>
|
||||
<text x="280" y="374" fill="#64748b" font-size="9" text-anchor="middle">→ run_write()</text>
|
||||
|
||||
<!-- edit_file handler -->
|
||||
<rect x="360" y="346" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="420" y="362" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">edit_file</text>
|
||||
<text x="420" y="374" fill="#64748b" font-size="9" text-anchor="middle">→ run_edit()</text>
|
||||
|
||||
<!-- glob handler -->
|
||||
<rect x="290" y="392" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="350" y="408" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">glob</text>
|
||||
<text x="350" y="420" fill="#64748b" font-size="9" text-anchor="middle">→ run_glob()</text>
|
||||
|
||||
<!-- Arrow: Dispatch Mapping → Back to Messages -->
|
||||
<path d="M 195 368 L 50 368 L 50 108 L 58 108" fill="none" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow-orange)" stroke-dasharray="6,3"/>
|
||||
<text x="28" y="300" fill="#92400e" font-size="9" font-weight="500" transform="rotate(-90, 28, 300)">Append tool_result to messages</text>
|
||||
|
||||
<!-- ===== Legend ===== -->
|
||||
<rect x="60" y="492" width="600" height="52" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="80" y="508" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="518" fill="#334155" font-size="10">s01 Preserved (loop, LLM, decision — completely unchanged)</text>
|
||||
<rect x="380" y="508" width="12" height="12" rx="2" fill="#ecfdf5" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="400" y="518" fill="#334155" font-size="10">s02 New (5 tools + dispatch mapping)</text>
|
||||
<text x="80" y="536" fill="#64748b" font-size="10">Only 1 line changed in the loop: run_bash() → TOOL_HANDLERS[block.name]()</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.6 KiB |
108
web/public/course-assets/s02_tool_use/tool-dispatch.ja.svg
Normal file
@@ -0,0 +1,108 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 560" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-orange" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="720" height="560" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="720" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="31" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Tool Use — ループ不変、ディスパッチマッピングを追加</text>
|
||||
|
||||
<!-- ===== s01 (灰色、保持部分) ===== -->
|
||||
<text x="50" y="76" fill="#94a3b8" font-size="11" font-weight="600">s01 保持</text>
|
||||
|
||||
<!-- ユーザー入力 -->
|
||||
<rect x="60" y="86" width="140" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="130" y="105" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">ユーザーの質問</text>
|
||||
<text x="130" y="121" fill="#64748b" font-size="10" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- 矢印:ユーザー → LLM -->
|
||||
<line x1="200" y1="108" x2="268" y2="108" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="270" y="82" width="150" height="52" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="345" y="104" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="345" y="122" fill="#64748b" font-size="10" text-anchor="middle">stop_reason 判定</text>
|
||||
|
||||
<!-- 矢印:LLM → 判定 -->
|
||||
<line x1="345" y1="134" x2="345" y2="162" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- 判定ダイヤモンド -->
|
||||
<polygon points="345,166 415,196 345,226 275,196" fill="#fff8f0" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="345" y="194" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">tool_use?</text>
|
||||
|
||||
<!-- いいえ → 返却 -->
|
||||
<line x1="415" y1="196" x2="475" y2="196" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="445" y="189" fill="#16a34a" font-size="9" font-weight="600">No</text>
|
||||
<rect x="477" y="178" width="100" height="36" rx="18" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="527" y="200" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">結果を返す</text>
|
||||
|
||||
<!-- はい → 次のステップ -->
|
||||
<line x1="345" y1="226" x2="345" y2="260" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow-orange)"/>
|
||||
<text x="356" y="248" fill="#d97706" font-size="9" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ===== s02 新規:TOOL_HANDLERS ディスパッチマッピング ===== -->
|
||||
<text x="505" y="282" fill="#d97706" font-size="11" font-weight="600">s02 新規</text>
|
||||
|
||||
<!-- ディスパッチマッピング外枠 -->
|
||||
<rect x="195" y="268" width="300" height="200" rx="10" fill="#fff7ed" stroke="#d97706" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="345" y="290" fill="#92400e" font-size="12" font-weight="700" text-anchor="middle">TOOL_HANDLERS ディスパッチマッピング</text>
|
||||
|
||||
<!-- ディスパッチマッピングへの矢印 -->
|
||||
<line x1="345" y1="260" x2="345" y2="268" stroke="#d97706" stroke-width="1.5"/>
|
||||
|
||||
<!-- bash handler -->
|
||||
<rect x="220" y="300" width="120" height="34" rx="6" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.2"/>
|
||||
<text x="280" y="316" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">bash</text>
|
||||
<text x="280" y="328" fill="#64748b" font-size="9" text-anchor="middle">→ run_bash()</text>
|
||||
|
||||
<!-- read_file handler -->
|
||||
<rect x="360" y="300" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="420" y="316" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">read_file</text>
|
||||
<text x="420" y="328" fill="#64748b" font-size="9" text-anchor="middle">→ run_read()</text>
|
||||
|
||||
<!-- write_file handler -->
|
||||
<rect x="220" y="346" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="280" y="362" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">write_file</text>
|
||||
<text x="280" y="374" fill="#64748b" font-size="9" text-anchor="middle">→ run_write()</text>
|
||||
|
||||
<!-- edit_file handler -->
|
||||
<rect x="360" y="346" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="420" y="362" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">edit_file</text>
|
||||
<text x="420" y="374" fill="#64748b" font-size="9" text-anchor="middle">→ run_edit()</text>
|
||||
|
||||
<!-- glob handler -->
|
||||
<rect x="290" y="392" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="350" y="408" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">glob</text>
|
||||
<text x="350" y="420" fill="#64748b" font-size="9" text-anchor="middle">→ run_glob()</text>
|
||||
|
||||
<!-- 矢印:ディスパッチマッピング → メッセージリストに戻る -->
|
||||
<path d="M 195 368 L 50 368 L 50 108 L 58 108" fill="none" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow-orange)" stroke-dasharray="6,3"/>
|
||||
<text x="28" y="300" fill="#92400e" font-size="9" font-weight="500" transform="rotate(-90, 28, 300)">tool_result を messages に追加</text>
|
||||
|
||||
<!-- ===== 凡例 ===== -->
|
||||
<rect x="60" y="492" width="600" height="52" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="80" y="508" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="518" fill="#334155" font-size="10">s01 保持(ループ、LLM、判定 — 完全に不変)</text>
|
||||
<rect x="380" y="508" width="12" height="12" rx="2" fill="#ecfdf5" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="400" y="518" fill="#334155" font-size="10">s02 新規(5 つのツール + ディスパッチマッピング)</text>
|
||||
<text x="80" y="536" fill="#64748b" font-size="10">ループ内で変更されたのは 1 行だけ:run_bash() → TOOL_HANDLERS[block.name]()</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.9 KiB |
108
web/public/course-assets/s02_tool_use/tool-dispatch.svg
Normal file
@@ -0,0 +1,108 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 560" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-orange" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="720" height="560" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- 标题 -->
|
||||
<rect x="0" y="0" width="720" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Tool Use — 循环不变,只加分发映射</text>
|
||||
|
||||
<!-- ===== s01 (灰色,保留部分) ===== -->
|
||||
<text x="50" y="76" fill="#94a3b8" font-size="11" font-weight="600">s01 保留</text>
|
||||
|
||||
<!-- 用户输入 -->
|
||||
<rect x="60" y="86" width="140" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="130" y="105" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">用户提问</text>
|
||||
<text x="130" y="121" fill="#64748b" font-size="10" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- 箭头:用户 → LLM -->
|
||||
<line x1="200" y1="108" x2="268" y2="108" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="270" y="82" width="150" height="52" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="345" y="104" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">大模型 (LLM)</text>
|
||||
<text x="345" y="122" fill="#64748b" font-size="10" text-anchor="middle">stop_reason 判断</text>
|
||||
|
||||
<!-- 箭头:LLM → 判断 -->
|
||||
<line x1="345" y1="134" x2="345" y2="162" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- 判断菱形 -->
|
||||
<polygon points="345,166 415,196 345,226 275,196" fill="#fff8f0" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="345" y="194" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">tool_use?</text>
|
||||
|
||||
<!-- 否 → 返回 -->
|
||||
<line x1="415" y1="196" x2="475" y2="196" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="445" y="189" fill="#16a34a" font-size="9" font-weight="600">否</text>
|
||||
<rect x="477" y="178" width="100" height="36" rx="18" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="527" y="200" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">返回结果</text>
|
||||
|
||||
<!-- 是 → 下一步 -->
|
||||
<line x1="345" y1="226" x2="345" y2="260" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow-orange)"/>
|
||||
<text x="356" y="248" fill="#d97706" font-size="9" font-weight="600">是</text>
|
||||
|
||||
<!-- ===== s02 新增:TOOL_HANDLERS 分发映射 ===== -->
|
||||
<text x="505" y="282" fill="#d97706" font-size="11" font-weight="600">s02 新增</text>
|
||||
|
||||
<!-- 分发映射外框 -->
|
||||
<rect x="195" y="268" width="300" height="200" rx="10" fill="#fff7ed" stroke="#d97706" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="345" y="290" fill="#92400e" font-size="12" font-weight="700" text-anchor="middle">TOOL_HANDLERS 分发映射</text>
|
||||
|
||||
<!-- 箭头进入分发映射 -->
|
||||
<line x1="345" y1="260" x2="345" y2="268" stroke="#d97706" stroke-width="1.5"/>
|
||||
|
||||
<!-- bash handler -->
|
||||
<rect x="220" y="300" width="120" height="34" rx="6" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.2"/>
|
||||
<text x="280" y="316" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">bash</text>
|
||||
<text x="280" y="328" fill="#64748b" font-size="9" text-anchor="middle">→ run_bash()</text>
|
||||
|
||||
<!-- read_file handler -->
|
||||
<rect x="360" y="300" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="420" y="316" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">read_file</text>
|
||||
<text x="420" y="328" fill="#64748b" font-size="9" text-anchor="middle">→ run_read()</text>
|
||||
|
||||
<!-- write_file handler -->
|
||||
<rect x="220" y="346" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="280" y="362" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">write_file</text>
|
||||
<text x="280" y="374" fill="#64748b" font-size="9" text-anchor="middle">→ run_write()</text>
|
||||
|
||||
<!-- edit_file handler -->
|
||||
<rect x="360" y="346" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="420" y="362" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">edit_file</text>
|
||||
<text x="420" y="374" fill="#64748b" font-size="9" text-anchor="middle">→ run_edit()</text>
|
||||
|
||||
<!-- glob handler -->
|
||||
<rect x="290" y="392" width="120" height="34" rx="6" fill="#ecfdf5" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="350" y="408" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">glob</text>
|
||||
<text x="350" y="420" fill="#64748b" font-size="9" text-anchor="middle">→ run_glob()</text>
|
||||
|
||||
<!-- 箭头:分发映射 → 回到消息列表 -->
|
||||
<path d="M 195 368 L 50 368 L 50 108 L 58 108" fill="none" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow-orange)" stroke-dasharray="6,3"/>
|
||||
<text x="28" y="300" fill="#92400e" font-size="9" font-weight="500" transform="rotate(-90, 28, 300)">tool_result 追加到 messages</text>
|
||||
|
||||
<!-- ===== 图例 ===== -->
|
||||
<rect x="60" y="492" width="600" height="52" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="80" y="508" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="518" fill="#334155" font-size="10">s01 保留(循环、LLM、判断——完全不变)</text>
|
||||
<rect x="380" y="508" width="12" height="12" rx="2" fill="#ecfdf5" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="400" y="518" fill="#334155" font-size="10">s02 新增(5 个工具 + 分发映射)</text>
|
||||
<text x="80" y="536" fill="#64748b" font-size="10">循环里只改了 1 行:run_bash() → TOOL_HANDLERS[block.name]()</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.6 KiB |
@@ -0,0 +1,97 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 320" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="720" height="320" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="720" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Permission — Loop unchanged, a gate before tool execution</text>
|
||||
|
||||
<!-- ===== s02 preserved (gray) ===== -->
|
||||
<text x="50" y="76" fill="#94a3b8" font-size="11" font-weight="600">s02 preserved</text>
|
||||
|
||||
<!-- User input -->
|
||||
<rect x="60" y="88" width="120" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="120" y="113" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- Arrow → LLM -->
|
||||
<line x1="180" y1="108" x2="228" y2="108" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="230" y="84" width="130" height="48" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="295" y="104" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="295" y="122" fill="#64748b" font-size="10" text-anchor="middle">stop_reason?</text>
|
||||
|
||||
<!-- No → return -->
|
||||
<line x1="295" y1="132" x2="295" y2="156" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="308" y="150" fill="#16a34a" font-size="9" font-weight="600">No</text>
|
||||
|
||||
<rect x="240" y="158" width="110" height="32" rx="16" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="295" y="178" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">Return result</text>
|
||||
|
||||
<!-- Yes → next step -->
|
||||
<line x1="360" y1="108" x2="400" y2="108" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="380" y="100" fill="#d97706" font-size="9" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ===== s03 new: Permission check ===== -->
|
||||
<text x="482" y="72" fill="#dc2626" font-size="11" font-weight="600" text-anchor="middle">s03 new</text>
|
||||
|
||||
<!-- Permission check box -->
|
||||
<rect x="402" y="78" width="160" height="120" rx="10" fill="#fef2f2" stroke="#dc2626" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="482" y="100" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">check_permission()</text>
|
||||
|
||||
<!-- Gate 1 -->
|
||||
<rect x="416" y="110" width="132" height="24" rx="4" fill="#fee2e2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="482" y="126" fill="#991b1b" font-size="9" font-weight="600" text-anchor="middle">Gate 1: Deny List</text>
|
||||
|
||||
<!-- Gate 2 -->
|
||||
<rect x="416" y="140" width="132" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="482" y="156" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">Gate 2: Rule Matching</text>
|
||||
|
||||
<!-- Gate 3 -->
|
||||
<rect x="416" y="170" width="132" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="482" y="186" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">Gate 3: User Approval</text>
|
||||
|
||||
<!-- Deny → return deny message -->
|
||||
<path d="M 402 188 L 376 188 L 376 174 L 350 174" fill="none" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="378" y="184" fill="#dc2626" font-size="8" font-weight="600">Deny</text>
|
||||
|
||||
<!-- Pass → tool execution -->
|
||||
<line x1="562" y1="138" x2="598" y2="138" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="575" y="132" fill="#16a34a" font-size="8" font-weight="600">Pass</text>
|
||||
|
||||
<!-- ===== s02 preserved: Tool execution ===== -->
|
||||
<text x="608" y="124" fill="#94a3b8" font-size="9">s02</text>
|
||||
|
||||
<!-- TOOL_HANDLERS -->
|
||||
<rect x="600" y="130" width="100" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="650" y="152" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_</text>
|
||||
<text x="650" y="166" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">HANDLERS</text>
|
||||
<text x="650" y="184" fill="#64748b" font-size="8" text-anchor="middle">bash/read/write/...</text>
|
||||
|
||||
<!-- Arrow: tool results → back to messages -->
|
||||
<path d="M 700 162 L 710 162 L 710 230 L 120 230 L 120 128" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== Legend ===== -->
|
||||
<rect x="60" y="260" width="600" height="44" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="80" y="276" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="286" fill="#334155" font-size="10">s02 preserved (loop, LLM, dispatch — unchanged)</text>
|
||||
<rect x="400" y="276" width="12" height="12" rx="2" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="420" y="286" fill="#334155" font-size="10">s03 new (three-gate permission pipeline)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,97 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 320" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="720" height="320" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="720" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Permission — ループは変更なし、ツール実行前にゲートを追加</text>
|
||||
|
||||
<!-- ===== s02 維持(灰色) ===== -->
|
||||
<text x="50" y="76" fill="#94a3b8" font-size="11" font-weight="600">s02 維持</text>
|
||||
|
||||
<!-- ユーザー入力 -->
|
||||
<rect x="60" y="88" width="120" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="120" y="113" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- 矢印 → LLM -->
|
||||
<line x1="180" y1="108" x2="228" y2="108" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="230" y="84" width="130" height="48" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="295" y="104" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="295" y="122" fill="#64748b" font-size="10" text-anchor="middle">stop_reason?</text>
|
||||
|
||||
<!-- No → 戻る -->
|
||||
<line x1="295" y1="132" x2="295" y2="156" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="308" y="150" fill="#16a34a" font-size="9" font-weight="600">No</text>
|
||||
|
||||
<rect x="240" y="158" width="110" height="32" rx="16" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="295" y="178" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">結果を返す</text>
|
||||
|
||||
<!-- Yes → 次へ -->
|
||||
<line x1="360" y1="108" x2="400" y2="108" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="380" y="100" fill="#d97706" font-size="9" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ===== s03 新規:権限チェック ===== -->
|
||||
<text x="482" y="72" fill="#dc2626" font-size="11" font-weight="600" text-anchor="middle">s03 新規</text>
|
||||
|
||||
<!-- 権限チェック枠 -->
|
||||
<rect x="402" y="78" width="160" height="120" rx="10" fill="#fef2f2" stroke="#dc2626" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="482" y="100" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">check_permission()</text>
|
||||
|
||||
<!-- ゲート 1 -->
|
||||
<rect x="416" y="110" width="132" height="24" rx="4" fill="#fee2e2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="482" y="126" fill="#991b1b" font-size="9" font-weight="600" text-anchor="middle">ゲート 1: 拒否リスト</text>
|
||||
|
||||
<!-- ゲート 2 -->
|
||||
<rect x="416" y="140" width="132" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="482" y="156" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">ゲート 2: ルール照合</text>
|
||||
|
||||
<!-- ゲート 3 -->
|
||||
<rect x="416" y="170" width="132" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="482" y="186" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">ゲート 3: ユーザー承認</text>
|
||||
|
||||
<!-- 拒否 → 拒否メッセージを返す -->
|
||||
<path d="M 402 188 L 376 188 L 376 174 L 350 174" fill="none" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="378" y="184" fill="#dc2626" font-size="8" font-weight="600">拒否</text>
|
||||
|
||||
<!-- 通過 → ツール実行 -->
|
||||
<line x1="562" y1="138" x2="598" y2="138" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="575" y="132" fill="#16a34a" font-size="8" font-weight="600">通過</text>
|
||||
|
||||
<!-- ===== s02 維持:ツール実行 ===== -->
|
||||
<text x="608" y="124" fill="#94a3b8" font-size="9">s02</text>
|
||||
|
||||
<!-- TOOL_HANDLERS -->
|
||||
<rect x="600" y="130" width="100" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="650" y="152" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_</text>
|
||||
<text x="650" y="166" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">HANDLERS</text>
|
||||
<text x="650" y="184" fill="#64748b" font-size="8" text-anchor="middle">bash/read/write/...</text>
|
||||
|
||||
<!-- 矢印:ツール結果 → メッセージリストに戻る -->
|
||||
<path d="M 700 162 L 710 162 L 710 230 L 120 230 L 120 128" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== 凡例 ===== -->
|
||||
<rect x="60" y="260" width="600" height="44" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="80" y="276" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="286" fill="#334155" font-size="10">s02 維持(ループ、LLM、ディスパッチ — 変更なし)</text>
|
||||
<rect x="400" y="276" width="12" height="12" rx="2" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="420" y="286" fill="#334155" font-size="10">s03 新規(3 ゲート権限パイプライン)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
@@ -0,0 +1,97 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 320" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="720" height="320" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- 标题 -->
|
||||
<rect x="0" y="0" width="720" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Permission — 循环不变,工具执行前加一道门</text>
|
||||
|
||||
<!-- ===== s02 保留(灰色) ===== -->
|
||||
<text x="50" y="76" fill="#94a3b8" font-size="11" font-weight="600">s02 保留</text>
|
||||
|
||||
<!-- 用户输入 -->
|
||||
<rect x="60" y="88" width="120" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="120" y="113" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- 箭头 → LLM -->
|
||||
<line x1="180" y1="108" x2="228" y2="108" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="230" y="84" width="130" height="48" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="295" y="104" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="295" y="122" fill="#64748b" font-size="10" text-anchor="middle">stop_reason?</text>
|
||||
|
||||
<!-- 否 → 返回 -->
|
||||
<line x1="295" y1="132" x2="295" y2="156" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="308" y="150" fill="#16a34a" font-size="9" font-weight="600">否</text>
|
||||
|
||||
<rect x="240" y="158" width="110" height="32" rx="16" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="295" y="178" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">返回结果</text>
|
||||
|
||||
<!-- 是 → 下一步 -->
|
||||
<line x1="360" y1="108" x2="400" y2="108" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="380" y="100" fill="#d97706" font-size="9" font-weight="600">是</text>
|
||||
|
||||
<!-- ===== s03 新增:权限检查 ===== -->
|
||||
<text x="482" y="72" fill="#dc2626" font-size="11" font-weight="600" text-anchor="middle">s03 新增</text>
|
||||
|
||||
<!-- 权限检查框 -->
|
||||
<rect x="402" y="78" width="160" height="120" rx="10" fill="#fef2f2" stroke="#dc2626" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="482" y="100" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">check_permission()</text>
|
||||
|
||||
<!-- 闸门 1 -->
|
||||
<rect x="416" y="110" width="132" height="24" rx="4" fill="#fee2e2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="482" y="126" fill="#991b1b" font-size="9" font-weight="600" text-anchor="middle">闸门 1: 拒绝列表</text>
|
||||
|
||||
<!-- 闸门 2 -->
|
||||
<rect x="416" y="140" width="132" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="482" y="156" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">闸门 2: 规则匹配</text>
|
||||
|
||||
<!-- 闸门 3 -->
|
||||
<rect x="416" y="170" width="132" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="482" y="186" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">闸门 3: 用户审批</text>
|
||||
|
||||
<!-- 拒绝 → 返回拒绝信息 -->
|
||||
<path d="M 402 188 L 376 188 L 376 174 L 350 174" fill="none" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="378" y="184" fill="#dc2626" font-size="8" font-weight="600">拒绝</text>
|
||||
|
||||
<!-- 通过 → 工具执行 -->
|
||||
<line x1="562" y1="138" x2="598" y2="138" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="575" y="132" fill="#16a34a" font-size="8" font-weight="600">通过</text>
|
||||
|
||||
<!-- ===== s02 保留:工具执行 ===== -->
|
||||
<text x="608" y="124" fill="#94a3b8" font-size="9">s02</text>
|
||||
|
||||
<!-- TOOL_HANDLERS -->
|
||||
<rect x="600" y="130" width="100" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="650" y="152" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_</text>
|
||||
<text x="650" y="166" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">HANDLERS</text>
|
||||
<text x="650" y="184" fill="#64748b" font-size="8" text-anchor="middle">bash/read/write/...</text>
|
||||
|
||||
<!-- 箭头:工具结果 → 回到消息列表 -->
|
||||
<path d="M 700 162 L 710 162 L 710 230 L 120 230 L 120 128" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== 图例 ===== -->
|
||||
<rect x="60" y="260" width="600" height="44" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="80" y="276" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="286" fill="#334155" font-size="10">s02 保留(循环、LLM、分发——完全不变)</text>
|
||||
<rect x="400" y="276" width="12" height="12" rx="2" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="420" y="286" fill="#334155" font-size="10">s03 新增(三道闸门权限管线)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,61 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 280" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="280" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Permission Pipeline — Three Gates</text>
|
||||
|
||||
<!-- Tool call enters -->
|
||||
<rect x="40" y="62" width="120" height="36" rx="6" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="84" fill="#1e40af" font-size="12" font-weight="600" text-anchor="middle">Tool call enters</text>
|
||||
|
||||
<line x1="160" y1="80" x2="210" y2="80" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Gate 1: Deny list -->
|
||||
<rect x="214" y="56" width="145" height="48" rx="6" fill="#fee2e2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="286" y="76" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">Gate 1: Deny List</text>
|
||||
<text x="286" y="94" fill="#991b1b" font-size="9" text-anchor="middle">rm -rf /, sudo, shutdown</text>
|
||||
|
||||
<line x1="359" y1="80" x2="409" y2="80" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Gate 2: Rule check -->
|
||||
<rect x="413" y="56" width="145" height="48" rx="6" fill="#fef3c7" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="485" y="76" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Gate 2: Rule Matching</text>
|
||||
<text x="485" y="94" fill="#92400e" font-size="9" text-anchor="middle">Write outside ws? Destructive?</text>
|
||||
<text x="485" y="116" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">no match → allow</text>
|
||||
|
||||
<line x1="558" y1="80" x2="608" y2="80" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="583" y="72" fill="#92400e" font-size="8" font-weight="600" text-anchor="middle">match</text>
|
||||
|
||||
<!-- Gate 3: User approval -->
|
||||
<rect x="612" y="56" width="90" height="48" rx="6" fill="#fef3c7" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="657" y="76" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Gate 3</text>
|
||||
<text x="657" y="94" fill="#92400e" font-size="9" text-anchor="middle">User approval</text>
|
||||
<text x="657" y="116" fill="#64748b" font-size="8" font-weight="600" text-anchor="middle">allow / deny</text>
|
||||
|
||||
<!-- Results area -->
|
||||
<rect x="40" y="130" width="662" height="130" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="60" y="152" fill="#1e3a5f" font-size="12" font-weight="600">Three Decisions</text>
|
||||
|
||||
<rect x="60" y="166" width="200" height="42" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="160" y="184" fill="#991b1b" font-size="11" font-weight="600" text-anchor="middle">Deny</text>
|
||||
<text x="160" y="200" fill="#991b1b" font-size="9" text-anchor="middle">Gate 1 hit, or user denied</text>
|
||||
|
||||
<rect x="280" y="166" width="200" height="42" rx="4" fill="#fef3c7" stroke="#fbbf24" stroke-width="0.5"/>
|
||||
<text x="380" y="184" fill="#92400e" font-size="11" font-weight="600" text-anchor="middle">Ask</text>
|
||||
<text x="380" y="200" fill="#92400e" font-size="9" text-anchor="middle">Gate 2 matched, enter Gate 3</text>
|
||||
|
||||
<rect x="500" y="166" width="182" height="42" rx="4" fill="#dcfce7" stroke="#86efac" stroke-width="0.5"/>
|
||||
<text x="591" y="184" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">Allow</text>
|
||||
<text x="591" y="200" fill="#166534" font-size="9" text-anchor="middle">No rule hit, or user approved</text>
|
||||
|
||||
<text x="371" y="248" fill="#64748b" font-size="10" text-anchor="middle">Priority: hard deny → rule matching → if matched ask user; if unmatched allow by default</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
@@ -0,0 +1,61 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 280" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="280" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Permission Pipeline — 3 つのゲート</text>
|
||||
|
||||
<!-- Tool call enters -->
|
||||
<rect x="40" y="62" width="120" height="36" rx="6" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="84" fill="#1e40af" font-size="12" font-weight="600" text-anchor="middle">ツール呼び出し</text>
|
||||
|
||||
<line x1="160" y1="80" x2="210" y2="80" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Gate 1: Deny list -->
|
||||
<rect x="214" y="56" width="145" height="48" rx="6" fill="#fee2e2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="286" y="76" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">ゲート 1: 拒否リスト</text>
|
||||
<text x="286" y="94" fill="#991b1b" font-size="9" text-anchor="middle">rm -rf /, sudo, shutdown</text>
|
||||
|
||||
<line x1="359" y1="80" x2="409" y2="80" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Gate 2: Rule check -->
|
||||
<rect x="413" y="56" width="145" height="48" rx="6" fill="#fef3c7" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="485" y="76" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">ゲート 2: ルール照合</text>
|
||||
<text x="485" y="94" fill="#92400e" font-size="9" text-anchor="middle">ws 外への書き込み?破壊的?</text>
|
||||
<text x="485" y="116" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">不一致 → allow</text>
|
||||
|
||||
<line x1="558" y1="80" x2="608" y2="80" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="583" y="72" fill="#92400e" font-size="8" font-weight="600" text-anchor="middle">一致</text>
|
||||
|
||||
<!-- Gate 3: User approval -->
|
||||
<rect x="612" y="56" width="90" height="48" rx="6" fill="#fef3c7" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="657" y="76" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">ゲート 3</text>
|
||||
<text x="657" y="94" fill="#92400e" font-size="9" text-anchor="middle">ユーザー承認</text>
|
||||
<text x="657" y="116" fill="#64748b" font-size="8" font-weight="600" text-anchor="middle">allow / deny</text>
|
||||
|
||||
<!-- Results area -->
|
||||
<rect x="40" y="130" width="662" height="130" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="60" y="152" fill="#1e3a5f" font-size="12" font-weight="600">3 つの決定</text>
|
||||
|
||||
<rect x="60" y="166" width="200" height="42" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="160" y="184" fill="#991b1b" font-size="11" font-weight="600" text-anchor="middle">拒否 (deny)</text>
|
||||
<text x="160" y="200" fill="#991b1b" font-size="9" text-anchor="middle">ゲート 1 一致、またはユーザー拒否</text>
|
||||
|
||||
<rect x="280" y="166" width="200" height="42" rx="4" fill="#fef3c7" stroke="#fbbf24" stroke-width="0.5"/>
|
||||
<text x="380" y="184" fill="#92400e" font-size="11" font-weight="600" text-anchor="middle">確認 (ask)</text>
|
||||
<text x="380" y="200" fill="#92400e" font-size="9" text-anchor="middle">ゲート 2 一致、ゲート 3 へ</text>
|
||||
|
||||
<rect x="500" y="166" width="182" height="42" rx="4" fill="#dcfce7" stroke="#86efac" stroke-width="0.5"/>
|
||||
<text x="591" y="184" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">許可 (allow)</text>
|
||||
<text x="591" y="200" fill="#166534" font-size="9" text-anchor="middle">ルール不一致、またはユーザー許可</text>
|
||||
|
||||
<text x="371" y="248" fill="#64748b" font-size="10" text-anchor="middle">優先順位:ハード拒否 → ルール照合 → 一致ならユーザー承認、不一致ならデフォルト許可</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,61 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 280" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="280" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Permission Pipeline — 三道闸门</text>
|
||||
|
||||
<!-- Tool call enters -->
|
||||
<rect x="40" y="62" width="120" height="36" rx="6" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="84" fill="#1e40af" font-size="12" font-weight="600" text-anchor="middle">工具调用进入</text>
|
||||
|
||||
<line x1="160" y1="80" x2="210" y2="80" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Gate 1: Deny list -->
|
||||
<rect x="214" y="56" width="145" height="48" rx="6" fill="#fee2e2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="286" y="76" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">闸门 1: 拒绝列表</text>
|
||||
<text x="286" y="94" fill="#991b1b" font-size="9" text-anchor="middle">rm -rf /, sudo, shutdown</text>
|
||||
|
||||
<line x1="359" y1="80" x2="409" y2="80" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Gate 2: Rule check -->
|
||||
<rect x="413" y="56" width="145" height="48" rx="6" fill="#fef3c7" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="485" y="76" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">闸门 2: 规则匹配</text>
|
||||
<text x="485" y="94" fill="#92400e" font-size="9" text-anchor="middle">写工作区外?读敏感路径?</text>
|
||||
<text x="485" y="116" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">未命中 → allow</text>
|
||||
|
||||
<line x1="558" y1="80" x2="608" y2="80" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="583" y="72" fill="#92400e" font-size="8" font-weight="600" text-anchor="middle">命中</text>
|
||||
|
||||
<!-- Gate 3: User approval -->
|
||||
<rect x="612" y="56" width="90" height="48" rx="6" fill="#fef3c7" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="657" y="76" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">闸门 3</text>
|
||||
<text x="657" y="94" fill="#92400e" font-size="9" text-anchor="middle">用户审批</text>
|
||||
<text x="657" y="116" fill="#64748b" font-size="8" font-weight="600" text-anchor="middle">允许 / 拒绝</text>
|
||||
|
||||
<!-- Results area -->
|
||||
<rect x="40" y="130" width="662" height="130" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="60" y="152" fill="#1e3a5f" font-size="12" font-weight="600">三种决策</text>
|
||||
|
||||
<rect x="60" y="166" width="200" height="42" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="160" y="184" fill="#991b1b" font-size="11" font-weight="600" text-anchor="middle">阻止 (deny)</text>
|
||||
<text x="160" y="200" fill="#991b1b" font-size="9" text-anchor="middle">闸门 1 命中,或用户拒绝</text>
|
||||
|
||||
<rect x="280" y="166" width="200" height="42" rx="4" fill="#fef3c7" stroke="#fbbf24" stroke-width="0.5"/>
|
||||
<text x="380" y="184" fill="#92400e" font-size="11" font-weight="600" text-anchor="middle">询问 (ask)</text>
|
||||
<text x="380" y="200" fill="#92400e" font-size="9" text-anchor="middle">闸门 2 命中,进入闸门 3</text>
|
||||
|
||||
<rect x="500" y="166" width="182" height="42" rx="4" fill="#dcfce7" stroke="#86efac" stroke-width="0.5"/>
|
||||
<text x="591" y="184" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">允许 (allow)</text>
|
||||
<text x="591" y="200" fill="#166534" font-size="9" text-anchor="middle">规则未命中,或用户允许</text>
|
||||
|
||||
<text x="371" y="248" fill="#64748b" font-size="10" text-anchor="middle">规则优先:闸门 1 硬拒绝 → 闸门 2 规则匹配 → 命中则用户审批,未命中默认允许</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
100
web/public/course-assets/s04_hooks/hooks-overview.en.svg
Normal file
@@ -0,0 +1,100 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 460" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="800" height="460" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Hooks — Extension Logic Hangs Outside, Loop Unchanged</text>
|
||||
|
||||
<!-- ===== Main Flow Line (y=140 horizontal) ===== -->
|
||||
|
||||
<!-- ① messages[] -->
|
||||
<rect x="40" y="112" width="110" height="56" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="95" y="138" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
<text x="95" y="156" fill="#64748b" font-size="9" text-anchor="middle">(s01 preserved)</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="150" y1="140" x2="198" y2="140" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- ② LLM -->
|
||||
<rect x="200" y="108" width="120" height="64" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="260" y="134" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="260" y="154" fill="#64748b" font-size="10" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- LLM No → Return -->
|
||||
<line x1="260" y1="172" x2="260" y2="200" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="275" y="192" fill="#16a34a" font-size="10" font-weight="600">No</text>
|
||||
<rect x="205" y="202" width="110" height="28" rx="14" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="260" y="220" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">Return Result</text>
|
||||
|
||||
<!-- LLM Yes → PreToolUse -->
|
||||
<line x1="320" y1="140" x2="378" y2="140" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="345" y="132" fill="#d97706" font-size="10" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ③ PreToolUse Hook (s04 new) -->
|
||||
<rect x="380" y="96" width="160" height="88" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="460" y="116" fill="#166534" font-size="11" font-weight="700" text-anchor="middle">trigger_hooks()</text>
|
||||
<text x="460" y="132" fill="#166534" font-size="9" font-weight="600" text-anchor="middle">PreToolUse</text>
|
||||
<rect x="396" y="140" width="128" height="18" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="0.8"/>
|
||||
<text x="460" y="153" fill="#166534" font-size="8" text-anchor="middle">permission_hook · log_hook</text>
|
||||
<text x="460" y="176" fill="#64748b" font-size="8" text-anchor="middle">Teaching: non-None → block</text>
|
||||
|
||||
<!-- PreToolUse Block → branch down -->
|
||||
<line x1="460" y1="184" x2="460" y2="218" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow-red)"/>
|
||||
<rect x="405" y="220" width="110" height="24" rx="12" fill="#fef2f2" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="460" y="236" fill="#991b1b" font-size="10" font-weight="600" text-anchor="middle">Write tool_result</text>
|
||||
|
||||
<!-- PreToolUse Pass → TOOL_HANDLERS -->
|
||||
<line x1="540" y1="140" x2="588" y2="140" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="558" y="132" fill="#16a34a" font-size="9" font-weight="600">Pass</text>
|
||||
|
||||
<!-- ④ TOOL_HANDLERS (s02 preserved) -->
|
||||
<rect x="590" y="108" width="100" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="640" y="134" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_</text>
|
||||
<text x="640" y="148" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">HANDLERS</text>
|
||||
<text x="640" y="164" fill="#64748b" font-size="8" text-anchor="middle">bash/read/...</text>
|
||||
|
||||
<!-- TOOL_HANDLERS → PostToolUse (down) -->
|
||||
<line x1="640" y1="172" x2="640" y2="268" stroke="#16a34a" stroke-width="2"/>
|
||||
<text x="648" y="224" fill="#16a34a" font-size="9" font-weight="600">After exec</text>
|
||||
|
||||
<!-- ⑤ PostToolUse Hook (s04 new) -->
|
||||
<rect x="560" y="270" width="160" height="56" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="640" y="290" fill="#166534" font-size="11" font-weight="700" text-anchor="middle">trigger_hooks()</text>
|
||||
<text x="640" y="306" fill="#166534" font-size="9" font-weight="600" text-anchor="middle">PostToolUse</text>
|
||||
<rect x="576" y="310" width="128" height="12" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="0.8"/>
|
||||
<text x="640" y="320" fill="#166534" font-size="7" text-anchor="middle">large_output_hook</text>
|
||||
|
||||
<!-- ===== Loop: results back to messages ===== -->
|
||||
<path d="M 720 298 L 760 298 L 760 350 L 95 350 L 95 168" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="400" y="370" fill="#64748b" font-size="10" text-anchor="middle">Results appended to messages[], loop continues</text>
|
||||
|
||||
<!-- ===== Bottom Comparison ===== -->
|
||||
<rect x="60" y="396" width="680" height="48" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="100" y="416" fill="#94a3b8" font-size="10" font-weight="600">s03:</text>
|
||||
<text x="130" y="416" fill="#64748b" font-size="10" font-family="monospace">if not check_permission(block): ...</text>
|
||||
<text x="400" y="416" fill="#94a3b8" font-size="10">← every new check requires modifying the loop</text>
|
||||
<text x="100" y="436" fill="#16a34a" font-size="10" font-weight="600">s04:</text>
|
||||
<text x="130" y="436" fill="#16a34a" font-size="10" font-family="monospace">blocked = trigger_hooks("PreToolUse", block)</text>
|
||||
<text x="520" y="436" fill="#16a34a" font-size="10">← add check = register_hook(), loop unchanged</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.6 KiB |
100
web/public/course-assets/s04_hooks/hooks-overview.ja.svg
Normal file
@@ -0,0 +1,100 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 460" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="800" height="460" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Hooks — 拡張ロジックは外側に、ループは一文字も変更しない</text>
|
||||
|
||||
<!-- ===== メインフロー(y=140 水平) ===== -->
|
||||
|
||||
<!-- ① messages[] -->
|
||||
<rect x="40" y="112" width="110" height="56" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="95" y="138" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
<text x="95" y="156" fill="#64748b" font-size="9" text-anchor="middle">(s01 保持)</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="150" y1="140" x2="198" y2="140" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- ② LLM -->
|
||||
<rect x="200" y="108" width="120" height="64" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="260" y="134" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="260" y="154" fill="#64748b" font-size="10" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- LLM No → 返却 -->
|
||||
<line x1="260" y1="172" x2="260" y2="200" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="275" y="192" fill="#16a34a" font-size="10" font-weight="600">No</text>
|
||||
<rect x="205" y="202" width="110" height="28" rx="14" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="260" y="220" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">結果を返す</text>
|
||||
|
||||
<!-- LLM Yes → PreToolUse -->
|
||||
<line x1="320" y1="140" x2="378" y2="140" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="345" y="132" fill="#d97706" font-size="10" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ③ PreToolUse フック(s04 新規) -->
|
||||
<rect x="380" y="96" width="160" height="88" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="460" y="116" fill="#166534" font-size="11" font-weight="700" text-anchor="middle">trigger_hooks()</text>
|
||||
<text x="460" y="132" fill="#166534" font-size="9" font-weight="600" text-anchor="middle">PreToolUse</text>
|
||||
<rect x="396" y="140" width="128" height="18" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="0.8"/>
|
||||
<text x="460" y="153" fill="#166534" font-size="8" text-anchor="middle">permission_hook · log_hook</text>
|
||||
<text x="460" y="176" fill="#64748b" font-size="8" text-anchor="middle">教育版: 非 None → ブロック</text>
|
||||
|
||||
<!-- PreToolUse 中断 → 下に分岐 -->
|
||||
<line x1="460" y1="184" x2="460" y2="218" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow-red)"/>
|
||||
<rect x="405" y="220" width="110" height="24" rx="12" fill="#fef2f2" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="460" y="236" fill="#991b1b" font-size="10" font-weight="600" text-anchor="middle">tool_result に返す</text>
|
||||
|
||||
<!-- PreToolUse 通過 → TOOL_HANDLERS -->
|
||||
<line x1="540" y1="140" x2="588" y2="140" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="558" y="132" fill="#16a34a" font-size="9" font-weight="600">通過</text>
|
||||
|
||||
<!-- ④ TOOL_HANDLERS (s02 保持) -->
|
||||
<rect x="590" y="108" width="100" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="640" y="134" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_</text>
|
||||
<text x="640" y="148" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">HANDLERS</text>
|
||||
<text x="640" y="164" fill="#64748b" font-size="8" text-anchor="middle">bash/read/...</text>
|
||||
|
||||
<!-- TOOL_HANDLERS → PostToolUse (下) -->
|
||||
<line x1="640" y1="172" x2="640" y2="268" stroke="#16a34a" stroke-width="2"/>
|
||||
<text x="648" y="224" fill="#16a34a" font-size="9" font-weight="600">実行後</text>
|
||||
|
||||
<!-- ⑤ PostToolUse フック(s04 新規) -->
|
||||
<rect x="560" y="270" width="160" height="56" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="640" y="290" fill="#166534" font-size="11" font-weight="700" text-anchor="middle">trigger_hooks()</text>
|
||||
<text x="640" y="306" fill="#166534" font-size="9" font-weight="600" text-anchor="middle">PostToolUse</text>
|
||||
<rect x="576" y="310" width="128" height="12" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="0.8"/>
|
||||
<text x="640" y="320" fill="#166534" font-size="7" text-anchor="middle">large_output_hook</text>
|
||||
|
||||
<!-- ===== ループ:結果を messages に戻す ===== -->
|
||||
<path d="M 720 298 L 760 298 L 760 350 L 95 350 L 95 168" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="400" y="370" fill="#64748b" font-size="10" text-anchor="middle">結果を messages[] に追加、ループ継続</text>
|
||||
|
||||
<!-- ===== 下部比較 ===== -->
|
||||
<rect x="60" y="396" width="680" height="48" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="100" y="416" fill="#94a3b8" font-size="10" font-weight="600">s03:</text>
|
||||
<text x="130" y="416" fill="#64748b" font-size="10" font-family="monospace">if not check_permission(block): ...</text>
|
||||
<text x="400" y="416" fill="#94a3b8" font-size="10">← チェックを追加するたびにループを修正</text>
|
||||
<text x="100" y="436" fill="#16a34a" font-size="10" font-weight="600">s04:</text>
|
||||
<text x="130" y="436" fill="#16a34a" font-size="10" font-family="monospace">blocked = trigger_hooks("PreToolUse", block)</text>
|
||||
<text x="520" y="436" fill="#16a34a" font-size="10">← チェック追加 = register_hook()、ループ不変</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
100
web/public/course-assets/s04_hooks/hooks-overview.svg
Normal file
@@ -0,0 +1,100 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 460" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="800" height="460" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- 标题 -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Hooks — 扩展逻辑挂在外面,循环本身一字不改</text>
|
||||
|
||||
<!-- ===== 主流程线(y=140 水平) ===== -->
|
||||
|
||||
<!-- ① messages[] -->
|
||||
<rect x="40" y="112" width="110" height="56" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="95" y="138" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
<text x="95" y="156" fill="#64748b" font-size="9" text-anchor="middle">(s01 保留)</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="150" y1="140" x2="198" y2="140" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- ② LLM -->
|
||||
<rect x="200" y="108" width="120" height="64" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="260" y="134" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="260" y="154" fill="#64748b" font-size="10" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- LLM 否 → 返回 -->
|
||||
<line x1="260" y1="172" x2="260" y2="200" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="275" y="192" fill="#16a34a" font-size="10" font-weight="600">否</text>
|
||||
<rect x="205" y="202" width="110" height="28" rx="14" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="260" y="220" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">返回结果</text>
|
||||
|
||||
<!-- LLM 是 → PreToolUse -->
|
||||
<line x1="320" y1="140" x2="378" y2="140" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="345" y="132" fill="#d97706" font-size="10" font-weight="600">是</text>
|
||||
|
||||
<!-- ③ PreToolUse hook(s04 新增) -->
|
||||
<rect x="380" y="96" width="160" height="88" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="460" y="116" fill="#166534" font-size="11" font-weight="700" text-anchor="middle">trigger_hooks()</text>
|
||||
<text x="460" y="132" fill="#166534" font-size="9" font-weight="600" text-anchor="middle">PreToolUse</text>
|
||||
<rect x="396" y="140" width="128" height="18" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="0.8"/>
|
||||
<text x="460" y="153" fill="#166534" font-size="8" text-anchor="middle">permission_hook · log_hook</text>
|
||||
<text x="460" y="176" fill="#64748b" font-size="8" text-anchor="middle">教学版:非 None → 阻止</text>
|
||||
|
||||
<!-- PreToolUse 阻止 → 向下引出 -->
|
||||
<line x1="460" y1="184" x2="460" y2="218" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow-red)"/>
|
||||
<rect x="405" y="220" width="110" height="24" rx="12" fill="#fef2f2" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="460" y="236" fill="#991b1b" font-size="10" font-weight="600" text-anchor="middle">写入 tool_result</text>
|
||||
|
||||
<!-- PreToolUse 通过 → TOOL_HANDLERS -->
|
||||
<line x1="540" y1="140" x2="588" y2="140" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="558" y="132" fill="#16a34a" font-size="9" font-weight="600">通过</text>
|
||||
|
||||
<!-- ④ TOOL_HANDLERS (s02 保留) -->
|
||||
<rect x="590" y="108" width="100" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="640" y="134" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_</text>
|
||||
<text x="640" y="148" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">HANDLERS</text>
|
||||
<text x="640" y="164" fill="#64748b" font-size="8" text-anchor="middle">bash/read/...</text>
|
||||
|
||||
<!-- TOOL_HANDLERS → PostToolUse (向下) -->
|
||||
<line x1="640" y1="172" x2="640" y2="268" stroke="#16a34a" stroke-width="2"/>
|
||||
<text x="648" y="224" fill="#16a34a" font-size="9" font-weight="600">执行后</text>
|
||||
|
||||
<!-- ⑤ PostToolUse hook(s04 新增) -->
|
||||
<rect x="560" y="270" width="160" height="56" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="640" y="290" fill="#166534" font-size="11" font-weight="700" text-anchor="middle">trigger_hooks()</text>
|
||||
<text x="640" y="306" fill="#166534" font-size="9" font-weight="600" text-anchor="middle">PostToolUse</text>
|
||||
<rect x="576" y="310" width="128" height="12" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="0.8"/>
|
||||
<text x="640" y="320" fill="#166534" font-size="7" text-anchor="middle">large_output_hook</text>
|
||||
|
||||
<!-- ===== 回环:结果回到 messages ===== -->
|
||||
<path d="M 720 298 L 760 298 L 760 350 L 95 350 L 95 168" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="400" y="370" fill="#64748b" font-size="10" text-anchor="middle">结果追加到 messages[],循环继续</text>
|
||||
|
||||
<!-- ===== 底部对比 ===== -->
|
||||
<rect x="60" y="396" width="680" height="48" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="100" y="416" fill="#94a3b8" font-size="10" font-weight="600">s03:</text>
|
||||
<text x="130" y="416" fill="#64748b" font-size="10" font-family="monospace">if not check_permission(block): ...</text>
|
||||
<text x="400" y="416" fill="#94a3b8" font-size="10">← 每加一个检查就要改循环</text>
|
||||
<text x="100" y="436" fill="#16a34a" font-size="10" font-weight="600">s04:</text>
|
||||
<text x="130" y="436" fill="#16a34a" font-size="10" font-family="monospace">blocked = trigger_hooks("PreToolUse", block)</text>
|
||||
<text x="520" y="436" fill="#16a34a" font-size="10">← 加检查 = register_hook(),循环不改</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.6 KiB |
93
web/public/course-assets/s05_todo_write/todo-overview.en.svg
Normal file
@@ -0,0 +1,93 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 420" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="800" height="420" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">TodoWrite — Loop Unchanged, One More Tool Auto-Dispatched</text>
|
||||
|
||||
<!-- ===== s04 Preserved (gray) ===== -->
|
||||
<text x="50" y="76" fill="#94a3b8" font-size="11" font-weight="600">s04 Preserved</text>
|
||||
|
||||
<!-- messages -->
|
||||
<rect x="40" y="90" width="100" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="90" y="117" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="140" y1="112" x2="188" y2="112" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="190" y="86" width="110" height="52" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="245" y="108" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="245" y="126" fill="#64748b" font-size="9" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- No → Return -->
|
||||
<line x1="245" y1="138" x2="245" y2="162" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="258" y="156" fill="#16a34a" font-size="9" font-weight="600">No</text>
|
||||
<rect x="195" y="164" width="100" height="28" rx="14" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="245" y="182" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">Return Result</text>
|
||||
|
||||
<!-- Yes → PreToolUse -->
|
||||
<line x1="300" y1="112" x2="348" y2="112" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="320" y="104" fill="#d97706" font-size="9" font-weight="600">Yes</text>
|
||||
|
||||
<!-- PreToolUse (s04) -->
|
||||
<rect x="350" y="88" width="100" height="48" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="400" y="110" fill="#166534" font-size="9" font-weight="600" text-anchor="middle">trigger_hooks</text>
|
||||
<text x="400" y="124" fill="#166534" font-size="8" text-anchor="middle">PreToolUse</text>
|
||||
|
||||
<!-- → TOOL_HANDLERS -->
|
||||
<line x1="450" y1="112" x2="498" y2="112" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== s05 New: todo_write ===== -->
|
||||
<!-- TOOL_HANDLERS box (expanded, includes todo_write) -->
|
||||
<rect x="500" y="74" width="120" height="140" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="560" y="94" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
|
||||
<!-- s04 preserved tools -->
|
||||
<rect x="512" y="102" width="96" height="22" rx="4" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="560" y="117" fill="#1e3a5f" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
|
||||
<rect x="512" y="130" width="96" height="22" rx="4" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="560" y="145" fill="#1e3a5f" font-size="9" text-anchor="middle">edit · glob</text>
|
||||
|
||||
<!-- s05 new: todo_write -->
|
||||
<rect x="512" y="158" width="96" height="22" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="560" y="173" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">todo_write</text>
|
||||
<text x="560" y="232" fill="#16a34a" font-size="11" font-weight="600" text-anchor="middle">s05 New</text>
|
||||
|
||||
<text x="560" y="196" fill="#64748b" font-size="8" text-anchor="middle">→ in-memory TODO list</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 620 112 L 660 112 L 660 260 L 90 260 L 90 134" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="370" y="280" fill="#64748b" font-size="10" text-anchor="middle">Results appended to messages[], loop continues</text>
|
||||
|
||||
<!-- ===== Nag Reminder ===== -->
|
||||
<rect x="100" y="310" width="600" height="56" rx="8" fill="#fffbeb" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="120" y="332" fill="#92400e" font-size="11" font-weight="700">Nag Reminder</text>
|
||||
<text x="120" y="352" fill="#92400e" font-size="10">Model hasn't called todo_write for 3 rounds → auto-inject <reminder>Update your todos.</reminder></text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="100" y="384" width="600" height="28" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="120" y="392" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="140" y="402" fill="#334155" font-size="10">s04 Preserved (loop, hooks, 5 base tools)</text>
|
||||
<rect x="400" y="392" width="12" height="12" rx="2" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="420" y="402" fill="#334155" font-size="10">s05 New (todo_write + nag reminder)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
93
web/public/course-assets/s05_todo_write/todo-overview.ja.svg
Normal file
@@ -0,0 +1,93 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 420" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="800" height="420" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">TodoWrite — ループ不変、ツール一つ追加で自動ディスパッチ</text>
|
||||
|
||||
<!-- ===== s04 保持(灰色) ===== -->
|
||||
<text x="50" y="76" fill="#94a3b8" font-size="11" font-weight="600">s04 保持</text>
|
||||
|
||||
<!-- messages -->
|
||||
<rect x="40" y="90" width="100" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="90" y="117" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="140" y1="112" x2="188" y2="112" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="190" y="86" width="110" height="52" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="245" y="108" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="245" y="126" fill="#64748b" font-size="9" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- No → 返却 -->
|
||||
<line x1="245" y1="138" x2="245" y2="162" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="258" y="156" fill="#16a34a" font-size="9" font-weight="600">No</text>
|
||||
<rect x="195" y="164" width="100" height="28" rx="14" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="245" y="182" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">結果を返す</text>
|
||||
|
||||
<!-- Yes → PreToolUse -->
|
||||
<line x1="300" y1="112" x2="348" y2="112" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="320" y="104" fill="#d97706" font-size="9" font-weight="600">Yes</text>
|
||||
|
||||
<!-- PreToolUse (s04) -->
|
||||
<rect x="350" y="88" width="100" height="48" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="400" y="110" fill="#166534" font-size="9" font-weight="600" text-anchor="middle">trigger_hooks</text>
|
||||
<text x="400" y="124" fill="#166534" font-size="8" text-anchor="middle">PreToolUse</text>
|
||||
|
||||
<!-- → TOOL_HANDLERS -->
|
||||
<line x1="450" y1="112" x2="498" y2="112" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== s05 新規:todo_write ===== -->
|
||||
<!-- TOOL_HANDLERS 枠(拡大、todo_write を含む) -->
|
||||
<rect x="500" y="74" width="120" height="140" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="560" y="94" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
|
||||
<!-- s04 保持のツール -->
|
||||
<rect x="512" y="102" width="96" height="22" rx="4" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="560" y="117" fill="#1e3a5f" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
|
||||
<rect x="512" y="130" width="96" height="22" rx="4" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="560" y="145" fill="#1e3a5f" font-size="9" text-anchor="middle">edit · glob</text>
|
||||
|
||||
<!-- s05 新規:todo_write -->
|
||||
<rect x="512" y="158" width="96" height="22" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="560" y="173" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">todo_write</text>
|
||||
<text x="560" y="232" fill="#16a34a" font-size="11" font-weight="600" text-anchor="middle">s05 新規</text>
|
||||
|
||||
<text x="560" y="196" fill="#64748b" font-size="8" text-anchor="middle">→ メモリ内 TODO リスト</text>
|
||||
|
||||
<!-- ループバック -->
|
||||
<path d="M 620 112 L 660 112 L 660 260 L 90 260 L 90 134" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="370" y="280" fill="#64748b" font-size="10" text-anchor="middle">結果を messages[] に追加、ループ継続</text>
|
||||
|
||||
<!-- ===== Nag リマインダー ===== -->
|
||||
<rect x="100" y="310" width="600" height="56" rx="8" fill="#fffbeb" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="120" y="332" fill="#92400e" font-size="11" font-weight="700">Nag リマインダー(催促機構)</text>
|
||||
<text x="120" y="352" fill="#92400e" font-size="10">モデルが連続 3 ラウンド todo_write 未呼び出し → 自動注入 <reminder>Update your todos.</reminder></text>
|
||||
|
||||
<!-- 凡例 -->
|
||||
<rect x="100" y="384" width="600" height="28" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="120" y="392" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="140" y="402" fill="#334155" font-size="10">s04 保持(ループ、フック、5 つの基本ツール)</text>
|
||||
<rect x="400" y="392" width="12" height="12" rx="2" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="420" y="402" fill="#334155" font-size="10">s05 新規(todo_write + Nag リマインダー)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
93
web/public/course-assets/s05_todo_write/todo-overview.svg
Normal file
@@ -0,0 +1,93 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 420" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="800" height="420" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- 标题 -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">TodoWrite — 循环不变,多一个工具自动分发</text>
|
||||
|
||||
<!-- ===== s04 保留(灰色) ===== -->
|
||||
<text x="50" y="76" fill="#94a3b8" font-size="11" font-weight="600">s04 保留</text>
|
||||
|
||||
<!-- messages -->
|
||||
<rect x="40" y="90" width="100" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="90" y="117" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="140" y1="112" x2="188" y2="112" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="190" y="86" width="110" height="52" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="245" y="108" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="245" y="126" fill="#64748b" font-size="9" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- 否 → 返回 -->
|
||||
<line x1="245" y1="138" x2="245" y2="162" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="258" y="156" fill="#16a34a" font-size="9" font-weight="600">否</text>
|
||||
<rect x="195" y="164" width="100" height="28" rx="14" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="245" y="182" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">返回结果</text>
|
||||
|
||||
<!-- 是 → PreToolUse -->
|
||||
<line x1="300" y1="112" x2="348" y2="112" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="320" y="104" fill="#d97706" font-size="9" font-weight="600">是</text>
|
||||
|
||||
<!-- PreToolUse (s04) -->
|
||||
<rect x="350" y="88" width="100" height="48" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="400" y="110" fill="#166534" font-size="9" font-weight="600" text-anchor="middle">trigger_hooks</text>
|
||||
<text x="400" y="124" fill="#166534" font-size="8" text-anchor="middle">PreToolUse</text>
|
||||
|
||||
<!-- → TOOL_HANDLERS -->
|
||||
<line x1="450" y1="112" x2="498" y2="112" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== s05 新增:todo_write ===== -->
|
||||
<!-- TOOL_HANDLERS 框(扩大,包含 todo_write) -->
|
||||
<rect x="500" y="74" width="120" height="140" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2" stroke-dasharray="6,3"/>
|
||||
<text x="560" y="94" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
|
||||
<!-- s04 保留的工具 -->
|
||||
<rect x="512" y="102" width="96" height="22" rx="4" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="560" y="117" fill="#1e3a5f" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
|
||||
<rect x="512" y="130" width="96" height="22" rx="4" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="560" y="145" fill="#1e3a5f" font-size="9" text-anchor="middle">edit · glob</text>
|
||||
|
||||
<!-- s05 新增:todo_write -->
|
||||
<rect x="512" y="158" width="96" height="22" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="560" y="173" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">todo_write</text>
|
||||
<text x="560" y="232" fill="#16a34a" font-size="11" font-weight="600" text-anchor="middle">s05 新增</text>
|
||||
|
||||
<text x="560" y="196" fill="#64748b" font-size="8" text-anchor="middle">→ 进程内 TODO 列表</text>
|
||||
|
||||
<!-- 回环 -->
|
||||
<path d="M 620 112 L 660 112 L 660 260 L 90 260 L 90 134" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="370" y="280" fill="#64748b" font-size="10" text-anchor="middle">结果追加到 messages[],循环继续</text>
|
||||
|
||||
<!-- ===== Nag Reminder ===== -->
|
||||
<rect x="100" y="310" width="600" height="56" rx="8" fill="#fffbeb" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="120" y="332" fill="#92400e" font-size="11" font-weight="700">Nag Reminder(催更机制)</text>
|
||||
<text x="120" y="352" fill="#92400e" font-size="10">模型连续 3 轮没调 todo_write → 自动注入 <reminder>Update your todos.</reminder></text>
|
||||
|
||||
<!-- 图例 -->
|
||||
<rect x="100" y="384" width="600" height="28" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="120" y="392" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="140" y="402" fill="#334155" font-size="10">s04 保留(循环、钩子、5 个基础工具)</text>
|
||||
<rect x="400" y="392" width="12" height="12" rx="2" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="420" y="402" fill="#334155" font-size="10">s05 新增(todo_write + nag reminder)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
125
web/public/course-assets/s06_subagent/subagent-overview.en.svg
Normal file
@@ -0,0 +1,125 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 500" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="800" height="500" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Subagent — Independent messages[], All Intermediate Steps Discarded</text>
|
||||
|
||||
<!-- ===== Parent Agent (left) ===== -->
|
||||
<rect x="30" y="68" width="310" height="268" rx="12" fill="#f0f4ff" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="185" y="92" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">Parent Agent</text>
|
||||
|
||||
<!-- messages[] -->
|
||||
<rect x="50" y="100" width="110" height="36" rx="6" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="105" y="123" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="160" y1="118" x2="198" y2="118" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="200" y="96" width="100" height="44" rx="6" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="250" y="123" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">LLM</text>
|
||||
|
||||
<!-- LLM → dispatch -->
|
||||
<line x1="250" y1="140" x2="250" y2="156" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="264" y="152" fill="#64748b" font-size="8">tool_use</text>
|
||||
|
||||
<!-- TOOL_HANDLERS -->
|
||||
<rect x="50" y="158" width="280" height="74" rx="6" fill="#e0e7ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="190" y="176" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
|
||||
<!-- Other tools (gray) -->
|
||||
<rect x="65" y="190" width="115" height="32" rx="4" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="122" y="206" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">Base Tools</text>
|
||||
<text x="122" y="219" fill="#64748b" font-size="8" text-anchor="middle">bash / read / write / ...</text>
|
||||
|
||||
<!-- task → spawn -->
|
||||
<rect x="200" y="193" width="110" height="26" rx="4" fill="#ede9fe" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="255" y="210" fill="#5b21b6" font-size="10" font-weight="600" text-anchor="middle">task → spawn</text>
|
||||
|
||||
<!-- Parent tool_result target -->
|
||||
<rect x="190" y="270" width="120" height="34" rx="5" fill="#dcfce7" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="250" y="291" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">tool_result</text>
|
||||
<path d="M 250 232 L 250 270" fill="none" stroke="#16a34a" stroke-width="1.4" marker-end="url(#arrow-green)"/>
|
||||
<path d="M 190 287 L 42 287 L 42 118 L 50 118" fill="none" stroke="#16a34a" stroke-width="1.2" marker-end="url(#arrow-green)" stroke-dasharray="4,3"/>
|
||||
<text x="110" y="304" fill="#94a3b8" font-size="8" text-anchor="middle">append messages[]</text>
|
||||
<text x="210" y="256" fill="#94a3b8" font-size="8" text-anchor="middle">Normal tool results also append to messages[]</text>
|
||||
|
||||
<!-- ===== Subagent (right) ===== -->
|
||||
<rect x="430" y="68" width="340" height="268" rx="12" fill="#faf5ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="600" y="92" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">Subagent (Fresh Context)</text>
|
||||
|
||||
<!-- fresh messages -->
|
||||
<rect x="450" y="100" width="150" height="36" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="525" y="116" fill="#5b21b6" font-size="10" font-weight="600" text-anchor="middle">messages = [task]</text>
|
||||
<text x="525" y="130" fill="#7c3aed" font-size="8" text-anchor="middle">fresh — no parent history</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="600" y1="118" x2="648" y2="118" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Subagent LLM -->
|
||||
<rect x="650" y="96" width="100" height="44" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="700" y="123" fill="#5b21b6" font-size="12" font-weight="700" text-anchor="middle">LLM</text>
|
||||
|
||||
<!-- own loop -->
|
||||
<rect x="455" y="150" width="300" height="56" rx="8" fill="#ede9fe" stroke="#7c3aed" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="605" y="170" fill="#5b21b6" font-size="10" font-weight="600" text-anchor="middle">Own while loop (max 30 rounds)</text>
|
||||
<text x="605" y="186" fill="#5b21b6" font-size="9" text-anchor="middle">bash · read · write · edit · glob</text>
|
||||
<text x="605" y="198" fill="#94a3b8" font-size="8" text-anchor="middle">No task — recursive spawn forbidden</text>
|
||||
|
||||
<!-- intermediate results → discard -->
|
||||
<rect x="460" y="218" width="290" height="44" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="605" y="238" fill="#64748b" font-size="10" text-anchor="middle">Intermediate 30+ tool calls + results</text>
|
||||
<text x="605" y="254" fill="#dc2626" font-size="10" font-weight="600" text-anchor="middle">All discarded ✗</text>
|
||||
|
||||
<!-- extract only last text -->
|
||||
<rect x="460" y="272" width="290" height="28" rx="6" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="605" y="290" fill="#166534" font-size="10" font-weight="600" text-anchor="middle">✓ Extract only final text → return to Parent</text>
|
||||
|
||||
<!-- ===== dispatch line: Parent → Subagent (top) ===== -->
|
||||
<path d="M 310 206 L 362 206 Q 370 206 370 198 L 370 126 Q 370 118 378 118 L 450 118" fill="none" stroke="#7c3aed" stroke-width="2.5" marker-end="url(#arrow-purple)"/>
|
||||
<rect x="342" y="152" width="80" height="20" rx="4" fill="#faf5ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="382" y="166" fill="#7c3aed" font-size="9" font-weight="700" text-anchor="middle">① task desc</text>
|
||||
|
||||
<!-- ===== return line: Subagent → Parent tool_result ===== -->
|
||||
<path d="M 460 286 L 310 286" fill="none" stroke="#16a34a" stroke-width="2.5" marker-end="url(#arrow-green)"/>
|
||||
<rect x="350" y="268" width="70" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="385" y="282" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">② summary</text>
|
||||
|
||||
<!-- ===== Legend ===== -->
|
||||
<rect x="60" y="370" width="680" height="56" rx="8" fill="#f1f5f9"/>
|
||||
|
||||
<rect x="80" y="384" width="16" height="12" rx="3" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="104" y="394" fill="#334155" font-size="10">s05 Preserved: loop, hooks, todo_write, 6 base tools</text>
|
||||
|
||||
<rect x="80" y="404" width="16" height="12" rx="3" fill="#ede9fe" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="104" y="414" fill="#334155" font-size="10">s06 New: task tool + spawn_subagent() — independent messages[], returns only summary</text>
|
||||
|
||||
<!-- Data flow labels -->
|
||||
<rect x="430" y="440" width="310" height="44" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="445" y="458" fill="#7c3aed" font-size="10" font-weight="600">① Parent → Sub:</text>
|
||||
<text x="580" y="458" fill="#64748b" font-size="10">task description (a short string)</text>
|
||||
<text x="445" y="476" fill="#16a34a" font-size="10" font-weight="600">② Sub → Parent:</text>
|
||||
<text x="580" y="476" fill="#64748b" font-size="10">extract_text() (final conclusion only)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
125
web/public/course-assets/s06_subagent/subagent-overview.ja.svg
Normal file
@@ -0,0 +1,125 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 500" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="800" height="500" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Subagent — 独立した messages[]、中間過程はすべて破棄</text>
|
||||
|
||||
<!-- ===== 親 Agent(左側) ===== -->
|
||||
<rect x="30" y="68" width="310" height="268" rx="12" fill="#f0f4ff" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="185" y="92" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">親 Agent</text>
|
||||
|
||||
<!-- messages[] -->
|
||||
<rect x="50" y="100" width="110" height="36" rx="6" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="105" y="123" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="160" y1="118" x2="198" y2="118" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="200" y="96" width="100" height="44" rx="6" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="250" y="123" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">LLM</text>
|
||||
|
||||
<!-- LLM → ディスパッチ -->
|
||||
<line x1="250" y1="140" x2="250" y2="156" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="264" y="152" fill="#64748b" font-size="8">tool_use</text>
|
||||
|
||||
<!-- TOOL_HANDLERS -->
|
||||
<rect x="50" y="158" width="280" height="74" rx="6" fill="#e0e7ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="190" y="176" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
|
||||
<!-- 他のツール(灰色) -->
|
||||
<rect x="65" y="190" width="115" height="32" rx="4" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="122" y="206" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">基本ツール</text>
|
||||
<text x="122" y="219" fill="#64748b" font-size="8" text-anchor="middle">bash / read / write / ...</text>
|
||||
|
||||
<!-- task → spawn -->
|
||||
<rect x="200" y="193" width="110" height="26" rx="4" fill="#ede9fe" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="255" y="210" fill="#5b21b6" font-size="10" font-weight="600" text-anchor="middle">task → spawn</text>
|
||||
|
||||
<!-- Parent tool_result target -->
|
||||
<rect x="190" y="270" width="120" height="34" rx="5" fill="#dcfce7" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="250" y="291" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">tool_result</text>
|
||||
<path d="M 250 232 L 250 270" fill="none" stroke="#16a34a" stroke-width="1.4" marker-end="url(#arrow-green)"/>
|
||||
<path d="M 190 287 L 42 287 L 42 118 L 50 118" fill="none" stroke="#16a34a" stroke-width="1.2" marker-end="url(#arrow-green)" stroke-dasharray="4,3"/>
|
||||
<text x="110" y="304" fill="#94a3b8" font-size="8" text-anchor="middle">messages[] に追加</text>
|
||||
<text x="210" y="256" fill="#94a3b8" font-size="8" text-anchor="middle">通常ツール結果も messages[] に戻る</text>
|
||||
|
||||
<!-- ===== サブエージェント(右側) ===== -->
|
||||
<rect x="430" y="68" width="340" height="268" rx="12" fill="#faf5ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="600" y="92" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">サブエージェント(新規コンテキスト)</text>
|
||||
|
||||
<!-- 新規 messages -->
|
||||
<rect x="450" y="100" width="150" height="36" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="525" y="116" fill="#5b21b6" font-size="10" font-weight="600" text-anchor="middle">messages = [task]</text>
|
||||
<text x="525" y="130" fill="#7c3aed" font-size="8" text-anchor="middle">新規 — 親の会話を継承しない</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="600" y1="118" x2="648" y2="118" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- サブエージェント LLM -->
|
||||
<rect x="650" y="96" width="100" height="44" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="700" y="123" fill="#5b21b6" font-size="12" font-weight="700" text-anchor="middle">LLM</text>
|
||||
|
||||
<!-- 独自ループ -->
|
||||
<rect x="455" y="150" width="300" height="56" rx="8" fill="#ede9fe" stroke="#7c3aed" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="605" y="170" fill="#5b21b6" font-size="10" font-weight="600" text-anchor="middle">独自の while ループ(最大 30 ラウンド)</text>
|
||||
<text x="605" y="186" fill="#5b21b6" font-size="9" text-anchor="middle">bash · read · write · edit · glob</text>
|
||||
<text x="605" y="198" fill="#94a3b8" font-size="8" text-anchor="middle">task なし — 再帰 spawn 禁止</text>
|
||||
|
||||
<!-- 中間結果 → 破棄 -->
|
||||
<rect x="460" y="218" width="290" height="44" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="605" y="238" fill="#64748b" font-size="10" text-anchor="middle">中間 30+ ラウンドのツール呼び出し + 結果</text>
|
||||
<text x="605" y="254" fill="#dc2626" font-size="10" font-weight="600" text-anchor="middle">すべて破棄 ✗</text>
|
||||
|
||||
<!-- 最後のテキストのみ抽出 -->
|
||||
<rect x="460" y="272" width="290" height="28" rx="6" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="605" y="290" fill="#166534" font-size="10" font-weight="600" text-anchor="middle">✓ 最後のテキストのみ抽出 → 親に返却</text>
|
||||
|
||||
<!-- ===== ディスパッチ線:親 → サブエージェント(上) ===== -->
|
||||
<path d="M 310 206 L 362 206 Q 370 206 370 198 L 370 126 Q 370 118 378 118 L 450 118" fill="none" stroke="#7c3aed" stroke-width="2.5" marker-end="url(#arrow-purple)"/>
|
||||
<rect x="342" y="152" width="80" height="20" rx="4" fill="#faf5ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="382" y="166" fill="#7c3aed" font-size="9" font-weight="700" text-anchor="middle">① task 説明</text>
|
||||
|
||||
<!-- ===== 返却線:サブエージェント → Parent tool_result ===== -->
|
||||
<path d="M 460 286 L 310 286" fill="none" stroke="#16a34a" stroke-width="2.5" marker-end="url(#arrow-green)"/>
|
||||
<rect x="350" y="268" width="70" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="385" y="282" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">② summary</text>
|
||||
|
||||
<!-- ===== 凡例 ===== -->
|
||||
<rect x="60" y="370" width="680" height="56" rx="8" fill="#f1f5f9"/>
|
||||
|
||||
<rect x="80" y="384" width="16" height="12" rx="3" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="104" y="394" fill="#334155" font-size="10">s05 保持:ループ、フック、todo_write、6 つの基本ツール</text>
|
||||
|
||||
<rect x="80" y="404" width="16" height="12" rx="3" fill="#ede9fe" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="104" y="414" fill="#334155" font-size="10">s06 新規:task ツール + spawn_subagent() — 独立 messages[]、要約のみ返却</text>
|
||||
|
||||
<!-- データフローラベル -->
|
||||
<rect x="430" y="440" width="310" height="44" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="445" y="458" fill="#7c3aed" font-size="10" font-weight="600">① 親 → サブ:</text>
|
||||
<text x="580" y="458" fill="#64748b" font-size="10">task description(短い文字列)</text>
|
||||
<text x="445" y="476" fill="#16a34a" font-size="10" font-weight="600">② サブ → 親:</text>
|
||||
<text x="580" y="476" fill="#64748b" font-size="10">extract_text()(最終結論のみ)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.4 KiB |
125
web/public/course-assets/s06_subagent/subagent-overview.svg
Normal file
@@ -0,0 +1,125 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 500" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="800" height="500" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- 标题 -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Subagent — 独立 messages[],中间过程全部丢弃</text>
|
||||
|
||||
<!-- ===== Parent Agent(左侧) ===== -->
|
||||
<rect x="30" y="68" width="310" height="268" rx="12" fill="#f0f4ff" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="185" y="92" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">Parent Agent</text>
|
||||
|
||||
<!-- messages[] -->
|
||||
<rect x="50" y="100" width="110" height="36" rx="6" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="105" y="123" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="160" y1="118" x2="198" y2="118" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="200" y="96" width="100" height="44" rx="6" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="250" y="123" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">LLM</text>
|
||||
|
||||
<!-- LLM → dispatch -->
|
||||
<line x1="250" y1="140" x2="250" y2="156" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="264" y="152" fill="#64748b" font-size="8">tool_use</text>
|
||||
|
||||
<!-- TOOL_HANDLERS -->
|
||||
<rect x="50" y="158" width="280" height="74" rx="6" fill="#e0e7ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="190" y="176" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
|
||||
<!-- 其他工具(灰色) -->
|
||||
<rect x="65" y="190" width="115" height="32" rx="4" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="122" y="206" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">基础工具</text>
|
||||
<text x="122" y="219" fill="#64748b" font-size="8" text-anchor="middle">bash / read / write / ...</text>
|
||||
|
||||
<!-- task → spawn -->
|
||||
<rect x="200" y="193" width="110" height="26" rx="4" fill="#ede9fe" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="255" y="210" fill="#5b21b6" font-size="10" font-weight="600" text-anchor="middle">task → spawn</text>
|
||||
|
||||
<!-- Parent tool_result target -->
|
||||
<rect x="190" y="270" width="120" height="34" rx="5" fill="#dcfce7" stroke="#16a34a" stroke-width="1.2"/>
|
||||
<text x="250" y="291" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">tool_result</text>
|
||||
<path d="M 250 232 L 250 270" fill="none" stroke="#16a34a" stroke-width="1.4" marker-end="url(#arrow-green)"/>
|
||||
<path d="M 190 287 L 42 287 L 42 118 L 50 118" fill="none" stroke="#16a34a" stroke-width="1.2" marker-end="url(#arrow-green)" stroke-dasharray="4,3"/>
|
||||
<text x="110" y="304" fill="#94a3b8" font-size="8" text-anchor="middle">append messages[]</text>
|
||||
<text x="210" y="256" fill="#94a3b8" font-size="8" text-anchor="middle">普通工具结果也回填 messages[]</text>
|
||||
|
||||
<!-- ===== Subagent(右侧) ===== -->
|
||||
<rect x="430" y="68" width="340" height="268" rx="12" fill="#faf5ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="600" y="92" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">Subagent (全新上下文)</text>
|
||||
|
||||
<!-- fresh messages -->
|
||||
<rect x="450" y="100" width="150" height="36" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="525" y="116" fill="#5b21b6" font-size="10" font-weight="600" text-anchor="middle">messages = [task]</text>
|
||||
<text x="525" y="130" fill="#7c3aed" font-size="8" text-anchor="middle">fresh — 不继承父对话</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="600" y1="118" x2="648" y2="118" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Subagent LLM -->
|
||||
<rect x="650" y="96" width="100" height="44" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="700" y="123" fill="#5b21b6" font-size="12" font-weight="700" text-anchor="middle">LLM</text>
|
||||
|
||||
<!-- own loop -->
|
||||
<rect x="455" y="150" width="300" height="56" rx="8" fill="#ede9fe" stroke="#7c3aed" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="605" y="170" fill="#5b21b6" font-size="10" font-weight="600" text-anchor="middle">自己的 while 循环(最多 30 轮)</text>
|
||||
<text x="605" y="186" fill="#5b21b6" font-size="9" text-anchor="middle">bash · read · write · edit · glob</text>
|
||||
<text x="605" y="198" fill="#94a3b8" font-size="8" text-anchor="middle">无 task — 禁止递归 spawn</text>
|
||||
|
||||
<!-- intermediate results → discard -->
|
||||
<rect x="460" y="218" width="290" height="44" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="605" y="238" fill="#64748b" font-size="10" text-anchor="middle">中间 30+ 轮工具调用 + 结果</text>
|
||||
<text x="605" y="254" fill="#dc2626" font-size="10" font-weight="600" text-anchor="middle">全部丢弃 ✗</text>
|
||||
|
||||
<!-- extract only last text -->
|
||||
<rect x="460" y="272" width="290" height="28" rx="6" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="605" y="290" fill="#166534" font-size="10" font-weight="600" text-anchor="middle">✓ 只提取最后一段文本 → 返回给 Parent</text>
|
||||
|
||||
<!-- ===== dispatch 线:Parent → Subagent(走上面) ===== -->
|
||||
<path d="M 310 206 L 362 206 Q 370 206 370 198 L 370 126 Q 370 118 378 118 L 450 118" fill="none" stroke="#7c3aed" stroke-width="2.5" marker-end="url(#arrow-purple)"/>
|
||||
<rect x="342" y="152" width="80" height="20" rx="4" fill="#faf5ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="382" y="166" fill="#7c3aed" font-size="9" font-weight="700" text-anchor="middle">① task 描述</text>
|
||||
|
||||
<!-- ===== return 线:Subagent → Parent tool_result ===== -->
|
||||
<path d="M 460 286 L 310 286" fill="none" stroke="#16a34a" stroke-width="2.5" marker-end="url(#arrow-green)"/>
|
||||
<rect x="350" y="268" width="70" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="385" y="282" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">② summary</text>
|
||||
|
||||
<!-- ===== 图例 ===== -->
|
||||
<rect x="60" y="370" width="680" height="56" rx="8" fill="#f1f5f9"/>
|
||||
|
||||
<rect x="80" y="384" width="16" height="12" rx="3" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="104" y="394" fill="#334155" font-size="10">s05 保留:循环、hook、todo_write、6 个基础工具</text>
|
||||
|
||||
<rect x="80" y="404" width="16" height="12" rx="3" fill="#ede9fe" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="104" y="414" fill="#334155" font-size="10">s06 新增:task 工具 + spawn_subagent() — 独立 messages[],只回传摘要</text>
|
||||
|
||||
<!-- 数据流标注 -->
|
||||
<rect x="430" y="440" width="310" height="44" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="445" y="458" fill="#7c3aed" font-size="10" font-weight="600">① Parent → Sub:</text>
|
||||
<text x="580" y="458" fill="#64748b" font-size="10">task description(一小段文字)</text>
|
||||
<text x="445" y="476" fill="#16a34a" font-size="10" font-weight="600">② Sub → Parent:</text>
|
||||
<text x="580" y="476" fill="#64748b" font-size="10">extract_text()(只有最终结论)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.2 KiB |
110
web/public/course-assets/s07_skill_loading/skill-overview.en.svg
Normal file
@@ -0,0 +1,110 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 380" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="800" height="380" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Skill Loading — catalog at startup, content on demand</text>
|
||||
|
||||
<!-- ===== History preserved ===== -->
|
||||
<text x="50" y="96" fill="#94a3b8" font-size="11" font-weight="600">History preserved</text>
|
||||
|
||||
<!-- messages[] -->
|
||||
<rect x="40" y="108" width="110" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="95" y="135" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="150" y1="130" x2="198" y2="130" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="200" y="106" width="110" height="48" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="255" y="128" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="255" y="146" fill="#64748b" font-size="9" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- No → return -->
|
||||
<line x1="255" y1="154" x2="255" y2="178" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
<text x="268" y="172" fill="#2563eb" font-size="9" font-weight="600">No</text>
|
||||
<rect x="200" y="180" width="110" height="28" rx="14" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="255" y="198" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">Return result</text>
|
||||
|
||||
<!-- Yes → PreToolUse -->
|
||||
<line x1="310" y1="130" x2="348" y2="130" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="325" y="122" fill="#d97706" font-size="9" font-weight="600">Yes</text>
|
||||
|
||||
<!-- PreToolUse (s04) -->
|
||||
<rect x="350" y="108" width="90" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="395" y="128" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">trigger_hooks</text>
|
||||
<text x="395" y="142" fill="#64748b" font-size="8" text-anchor="middle">PreToolUse</text>
|
||||
|
||||
<!-- → TOOL_HANDLERS -->
|
||||
<line x1="440" y1="130" x2="488" y2="130" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== TOOL_HANDLERS ===== -->
|
||||
<rect x="490" y="88" width="120" height="130" rx="10" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="550" y="108" fill="#1e3a5f" font-size="10" font-weight="700" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
|
||||
<!-- s06 tools -->
|
||||
<rect x="500" y="116" width="100" height="18" rx="3" fill="#fff" stroke="#2563eb" stroke-width="0.8"/>
|
||||
<text x="550" y="129" fill="#1e3a5f" font-size="8" text-anchor="middle">bash · read · write</text>
|
||||
<rect x="500" y="138" width="100" height="18" rx="3" fill="#fff" stroke="#2563eb" stroke-width="0.8"/>
|
||||
<text x="550" y="151" fill="#1e3a5f" font-size="8" text-anchor="middle">edit · glob · todo</text>
|
||||
<rect x="500" y="160" width="100" height="18" rx="3" fill="#fff" stroke="#2563eb" stroke-width="0.8"/>
|
||||
<text x="550" y="173" fill="#1e3a5f" font-size="8" text-anchor="middle">task (subagent)</text>
|
||||
|
||||
<rect x="500" y="186" width="100" height="22" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="550" y="201" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">load_skill</text>
|
||||
|
||||
<!-- ===== Loop back ===== -->
|
||||
<path d="M 550 218 L 550 270 L 95 270 L 95 152" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="320" y="290" fill="#64748b" font-size="10" text-anchor="middle">Results appended to messages[], loop continues</text>
|
||||
|
||||
<!-- ===== s07 two-level injection labels (right side) ===== -->
|
||||
|
||||
<text x="710" y="220" fill="#16a34a" font-size="11" font-weight="700" text-anchor="middle">s07 new</text>
|
||||
|
||||
<!-- ① Startup SYSTEM injection -->
|
||||
<rect x="640" y="86" width="140" height="56" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="710" y="106" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">① build_system()</text>
|
||||
<text x="710" y="120" fill="#64748b" font-size="8" text-anchor="middle">Scan skills/ first line at startup</text>
|
||||
<text x="710" y="134" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">→ inject SYSTEM prompt</text>
|
||||
|
||||
<!-- ② Runtime load_skill → tool_result -->
|
||||
<rect x="640" y="148" width="140" height="56" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="710" y="168" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">② load_skill(name)</text>
|
||||
<text x="710" y="182" fill="#64748b" font-size="8" text-anchor="middle">Read full SKILL.md at runtime</text>
|
||||
<text x="710" y="196" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">→ inject tool_result</text>
|
||||
|
||||
<!-- ① → LLM (top connection) -->
|
||||
<path d="M 710 86 L 710 68 L 255 68 L 255 106" fill="none" stroke="#16a34a" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-green)"/>
|
||||
<text x="480" y="64" fill="#166534" font-size="7" font-weight="600">SYSTEM has skill catalog, carried every turn</text>
|
||||
|
||||
<!-- ② → load_skill (short connection) -->
|
||||
<line x1="640" y1="176" x2="600" y2="197" stroke="#16a34a" stroke-width="1.5" stroke-dasharray="4,3"/>
|
||||
|
||||
<!-- ===== Legend ===== -->
|
||||
<rect x="60" y="308" width="680" height="44" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="80" y="322" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="332" fill="#334155" font-size="10">History preserved (loop, hooks, TODO, subagent — unchanged)</text>
|
||||
<rect x="80" y="338" width="12" height="12" rx="2" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="100" y="348" fill="#334155" font-size="10">s07 new (startup catalog in SYSTEM + load_skill tool)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.9 KiB |
110
web/public/course-assets/s07_skill_loading/skill-overview.ja.svg
Normal file
@@ -0,0 +1,110 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 380" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="800" height="380" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Skill Loading — 起動時にカタログ注入、実行時にオンデマンド読み込み</text>
|
||||
|
||||
<!-- ===== 過去章を保持 ===== -->
|
||||
<text x="50" y="96" fill="#94a3b8" font-size="11" font-weight="600">過去章を保持</text>
|
||||
|
||||
<!-- messages[] -->
|
||||
<rect x="40" y="108" width="110" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="95" y="135" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="150" y1="130" x2="198" y2="130" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="200" y="106" width="110" height="48" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="255" y="128" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="255" y="146" fill="#64748b" font-size="9" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- No → 戻る -->
|
||||
<line x1="255" y1="154" x2="255" y2="178" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
<text x="268" y="172" fill="#2563eb" font-size="9" font-weight="600">No</text>
|
||||
<rect x="200" y="180" width="110" height="28" rx="14" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="255" y="198" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">結果を返す</text>
|
||||
|
||||
<!-- Yes → PreToolUse -->
|
||||
<line x1="310" y1="130" x2="348" y2="130" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="325" y="122" fill="#d97706" font-size="9" font-weight="600">Yes</text>
|
||||
|
||||
<!-- PreToolUse (s04) -->
|
||||
<rect x="350" y="108" width="90" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="395" y="128" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">trigger_hooks</text>
|
||||
<text x="395" y="142" fill="#64748b" font-size="8" text-anchor="middle">PreToolUse</text>
|
||||
|
||||
<!-- → TOOL_HANDLERS -->
|
||||
<line x1="440" y1="130" x2="488" y2="130" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== TOOL_HANDLERS ===== -->
|
||||
<rect x="490" y="88" width="120" height="130" rx="10" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="550" y="108" fill="#1e3a5f" font-size="10" font-weight="700" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
|
||||
<!-- s06 ツール -->
|
||||
<rect x="500" y="116" width="100" height="18" rx="3" fill="#fff" stroke="#2563eb" stroke-width="0.8"/>
|
||||
<text x="550" y="129" fill="#1e3a5f" font-size="8" text-anchor="middle">bash · read · write</text>
|
||||
<rect x="500" y="138" width="100" height="18" rx="3" fill="#fff" stroke="#2563eb" stroke-width="0.8"/>
|
||||
<text x="550" y="151" fill="#1e3a5f" font-size="8" text-anchor="middle">edit · glob · todo</text>
|
||||
<rect x="500" y="160" width="100" height="18" rx="3" fill="#fff" stroke="#2563eb" stroke-width="0.8"/>
|
||||
<text x="550" y="173" fill="#1e3a5f" font-size="8" text-anchor="middle">task (subagent)</text>
|
||||
|
||||
<rect x="500" y="186" width="100" height="22" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="550" y="201" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">load_skill</text>
|
||||
|
||||
<!-- ===== ループバック ===== -->
|
||||
<path d="M 550 218 L 550 270 L 95 270 L 95 152" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="320" y="290" fill="#64748b" font-size="10" text-anchor="middle">結果を messages[] に追加、ループ継続</text>
|
||||
|
||||
<!-- ===== s07 2 層注入ラベル(右側) ===== -->
|
||||
|
||||
<text x="710" y="220" fill="#16a34a" font-size="11" font-weight="700" text-anchor="middle">s07 新規</text>
|
||||
|
||||
<!-- ① 起動時 SYSTEM 注入 -->
|
||||
<rect x="640" y="86" width="140" height="56" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="710" y="106" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">① build_system()</text>
|
||||
<text x="710" y="120" fill="#64748b" font-size="8" text-anchor="middle">起動時に skills/ の 1 行目をスキャン</text>
|
||||
<text x="710" y="134" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">→ SYSTEM プロンプトに注入</text>
|
||||
|
||||
<!-- ② 実行時 load_skill → tool_result -->
|
||||
<rect x="640" y="148" width="140" height="56" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="710" y="168" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">② load_skill(name)</text>
|
||||
<text x="710" y="182" fill="#64748b" font-size="8" text-anchor="middle">実行時に完全な SKILL.md を読み取り</text>
|
||||
<text x="710" y="196" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">→ tool_result に注入</text>
|
||||
|
||||
<!-- ① → LLM(上部接続) -->
|
||||
<path d="M 710 86 L 710 68 L 255 68 L 255 106" fill="none" stroke="#16a34a" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-green)"/>
|
||||
<text x="480" y="64" fill="#166534" font-size="7" font-weight="600">SYSTEM にスキルカタログ、毎ターン携帯</text>
|
||||
|
||||
<!-- ② → load_skill(短接続) -->
|
||||
<line x1="640" y1="176" x2="600" y2="197" stroke="#16a34a" stroke-width="1.5" stroke-dasharray="4,3"/>
|
||||
|
||||
<!-- ===== 凡例 ===== -->
|
||||
<rect x="60" y="308" width="680" height="44" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="80" y="322" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="332" fill="#334155" font-size="10">過去章を保持(ループ、フック、TODO、サブ Agent — 変更なし)</text>
|
||||
<rect x="80" y="338" width="12" height="12" rx="2" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="100" y="348" fill="#334155" font-size="10">s07 新規(起動時カタログ注入 SYSTEM + load_skill ツール)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
110
web/public/course-assets/s07_skill_loading/skill-overview.svg
Normal file
@@ -0,0 +1,110 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 380" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="800" height="380" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- 标题 -->
|
||||
<rect x="0" y="0" width="800" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="800" height="8" fill="url(#header)"/>
|
||||
<text x="400" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Skill Loading — 启动时注入目录,运行时按需加载内容</text>
|
||||
|
||||
<!-- ===== 历史章节保留 ===== -->
|
||||
<text x="50" y="96" fill="#94a3b8" font-size="11" font-weight="600">历史章节保留</text>
|
||||
|
||||
<!-- messages[] -->
|
||||
<rect x="40" y="108" width="110" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="95" y="135" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- → LLM -->
|
||||
<line x1="150" y1="130" x2="198" y2="130" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="200" y="106" width="110" height="48" rx="8" fill="#fff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="255" y="128" fill="#1e3a5f" font-size="13" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="255" y="146" fill="#64748b" font-size="9" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- 否 → 返回 -->
|
||||
<line x1="255" y1="154" x2="255" y2="178" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
<text x="268" y="172" fill="#2563eb" font-size="9" font-weight="600">否</text>
|
||||
<rect x="200" y="180" width="110" height="28" rx="14" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="255" y="198" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">返回结果</text>
|
||||
|
||||
<!-- 是 → PreToolUse -->
|
||||
<line x1="310" y1="130" x2="348" y2="130" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="325" y="122" fill="#d97706" font-size="9" font-weight="600">是</text>
|
||||
|
||||
<!-- PreToolUse (s04) -->
|
||||
<rect x="350" y="108" width="90" height="44" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="395" y="128" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">trigger_hooks</text>
|
||||
<text x="395" y="142" fill="#64748b" font-size="8" text-anchor="middle">PreToolUse</text>
|
||||
|
||||
<!-- → TOOL_HANDLERS -->
|
||||
<line x1="440" y1="130" x2="488" y2="130" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== TOOL_HANDLERS ===== -->
|
||||
<rect x="490" y="88" width="120" height="130" rx="10" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="550" y="108" fill="#1e3a5f" font-size="10" font-weight="700" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
|
||||
<!-- s06 工具 -->
|
||||
<rect x="500" y="116" width="100" height="18" rx="3" fill="#fff" stroke="#2563eb" stroke-width="0.8"/>
|
||||
<text x="550" y="129" fill="#1e3a5f" font-size="8" text-anchor="middle">bash · read · write</text>
|
||||
<rect x="500" y="138" width="100" height="18" rx="3" fill="#fff" stroke="#2563eb" stroke-width="0.8"/>
|
||||
<text x="550" y="151" fill="#1e3a5f" font-size="8" text-anchor="middle">edit · glob · todo</text>
|
||||
<rect x="500" y="160" width="100" height="18" rx="3" fill="#fff" stroke="#2563eb" stroke-width="0.8"/>
|
||||
<text x="550" y="173" fill="#1e3a5f" font-size="8" text-anchor="middle">task (subagent)</text>
|
||||
|
||||
<rect x="500" y="186" width="100" height="22" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="550" y="201" fill="#166534" font-size="9" font-weight="700" text-anchor="middle">load_skill</text>
|
||||
|
||||
<!-- ===== 回环 ===== -->
|
||||
<path d="M 550 218 L 550 270 L 95 270 L 95 152" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="320" y="290" fill="#64748b" font-size="10" text-anchor="middle">结果追加到 messages[],循环继续</text>
|
||||
|
||||
<!-- ===== s07 两级注入标注(右侧) ===== -->
|
||||
|
||||
<text x="710" y="220" fill="#16a34a" font-size="11" font-weight="700" text-anchor="middle">s07 新增</text>
|
||||
|
||||
<!-- ① 启动时注入 SYSTEM -->
|
||||
<rect x="640" y="86" width="140" height="56" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="710" y="106" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">① build_system()</text>
|
||||
<text x="710" y="120" fill="#64748b" font-size="8" text-anchor="middle">启动时扫描 skills/ 第一行</text>
|
||||
<text x="710" y="134" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">→ 注入 SYSTEM prompt</text>
|
||||
|
||||
<!-- ② 运行时 load_skill → tool_result -->
|
||||
<rect x="640" y="148" width="140" height="56" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="710" y="168" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">② load_skill(name)</text>
|
||||
<text x="710" y="182" fill="#64748b" font-size="8" text-anchor="middle">运行时读完整 SKILL.md</text>
|
||||
<text x="710" y="196" fill="#166534" font-size="8" font-weight="600" text-anchor="middle">→ 注入 tool_result</text>
|
||||
|
||||
<!-- ① → LLM(顶部连线) -->
|
||||
<path d="M 710 86 L 710 68 L 255 68 L 255 106" fill="none" stroke="#16a34a" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-green)"/>
|
||||
<text x="480" y="64" fill="#166534" font-size="7" font-weight="600">SYSTEM 含技能目录,每轮都带</text>
|
||||
|
||||
<!-- ② → load_skill(短连接线) -->
|
||||
<line x1="640" y1="176" x2="600" y2="197" stroke="#16a34a" stroke-width="1.5" stroke-dasharray="4,3"/>
|
||||
|
||||
<!-- ===== 图例 ===== -->
|
||||
<rect x="60" y="308" width="680" height="44" rx="6" fill="#f1f5f9"/>
|
||||
<rect x="80" y="322" width="12" height="12" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="332" fill="#334155" font-size="10">历史章节保留(循环、钩子、TODO、subagent — 完全不变)</text>
|
||||
<rect x="80" y="338" width="12" height="12" rx="2" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="100" y="348" fill="#334155" font-size="10">s07 新增(启动时目录注入 SYSTEM + load_skill 工具)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.9 KiB |
@@ -0,0 +1,72 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 400" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#991b1b"/><stop offset="100%" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="400" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">L4: autoCompact — LLM Full Summary</text>
|
||||
|
||||
<!-- Trigger Condition -->
|
||||
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">Trigger Condition</text>
|
||||
<text x="140" y="70" fill="#991b1b" font-size="11">All three preprocessing layers have run, estimated tokens > contextWindow - maxOutputTokens - 13_000.</text>
|
||||
<text x="140" y="86" fill="#991b1b" font-size="10">Tries sessionMemoryCompact first (lightweight summary from existing memory), only calls LLM if insufficient.</text>
|
||||
|
||||
<!-- Steps -->
|
||||
<rect x="20" y="106" width="200" height="110" rx="8" fill="#fff" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="120" y="130" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">Step 1: Save transcript</text>
|
||||
<text x="40" y="152" fill="#475569" font-size="10">Write full conversation to .transcripts/</text>
|
||||
<text x="40" y="168" fill="#475569" font-size="10">JSONL format, one message per line</text>
|
||||
<text x="40" y="184" fill="#475569" font-size="10">Filename: transcript_{timestamp}.jsonl</text>
|
||||
<text x="40" y="200" fill="#94a3b8" font-size="9">No data lost, just moved out of active area</text>
|
||||
|
||||
<line x1="225" y1="161" x2="265" y2="161" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="270" y="106" width="200" height="110" rx="8" fill="#fff" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="370" y="130" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">Step 2: LLM generates summary</text>
|
||||
<text x="290" y="152" fill="#475569" font-size="10">Send conversation history to LLM</text>
|
||||
<text x="290" y="166" fill="#475569" font-size="9">Summary must include 9 sections:</text>
|
||||
<text x="290" y="180" fill="#94a3b8" font-size="8">request · concepts · files · errors · resolutions</text>
|
||||
<text x="290" y="192" fill="#94a3b8" font-size="8">user messages · todos · current state · next steps</text>
|
||||
<text x="290" y="206" fill="#94a3b8" font-size="9">Generated only once</text>
|
||||
|
||||
<line x1="475" y1="161" x2="515" y2="161" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="520" y="106" width="180" height="110" rx="8" fill="#fef2f2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="610" y="130" fill="#991b1b" font-size="12" font-weight="700" text-anchor="middle">Step 3: Replace message list</text>
|
||||
<text x="540" y="152" fill="#991b1b" font-size="10">All old messages → 1 summary</text>
|
||||
<text x="540" y="168" fill="#991b1b" font-size="10">Model continues from summary</text>
|
||||
<text x="540" y="184" fill="#991b1b" font-size="10">Includes recently_read file list</text>
|
||||
<text x="540" y="200" fill="#ef4444" font-size="9">⚠ This is an irreversible operation</text>
|
||||
|
||||
<!-- Before/After comparison -->
|
||||
<rect x="20" y="234" width="320" height="94" rx="6" fill="#fff" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="180" y="256" fill="#64748b" font-size="11" font-weight="600" text-anchor="middle">Before messages</text>
|
||||
<rect x="35" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="40" y="276" fill="#475569" font-size="8">user</text>
|
||||
<rect x="92" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="97" y="276" fill="#475569" font-size="8">assistant</text>
|
||||
<rect x="149" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="154" y="276" fill="#475569" font-size="8">user</text>
|
||||
<rect x="206" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="211" y="276" fill="#475569" font-size="8">assistant</text>
|
||||
<rect x="263" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="268" y="276" fill="#475569" font-size="8">user</text>
|
||||
<text x="180" y="318" fill="#94a3b8" font-size="9" text-anchor="middle">~180 messages, occupying 62K tokens</text>
|
||||
|
||||
<line x1="345" y1="281" x2="375" y2="281" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="380" y="234" width="320" height="94" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="540" y="256" fill="#991b1b" font-size="11" font-weight="600" text-anchor="middle">After messages</text>
|
||||
<rect x="395" y="264" width="290" height="32" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="540" y="276" fill="#991b1b" font-size="9" text-anchor="middle">[Compacted] Summary: goal → create hello.py ...</text>
|
||||
<text x="540" y="290" fill="#991b1b" font-size="9" text-anchor="middle">Recent files: hello.py, README.md ...</text>
|
||||
<text x="540" y="318" fill="#94a3b8" font-size="9" text-anchor="middle">~1 message, occupying 1K tokens</text>
|
||||
|
||||
<!-- Circuit breaker -->
|
||||
<rect x="20" y="340" width="680" height="36" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="35" y="362" fill="#475569" font-size="11" font-weight="600">Circuit breaker:</text>
|
||||
<text x="130" y="362" fill="#475569" font-size="10">3 consecutive autocompact failures → stop retrying. Prevents wasting API calls when context is unrecoverable.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
@@ -0,0 +1,72 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 400" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#991b1b"/><stop offset="100%" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="400" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">L4: autoCompact — LLM 完全要約</text>
|
||||
|
||||
<!-- トリガー条件 -->
|
||||
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">トリガー条件</text>
|
||||
<text x="115" y="70" fill="#991b1b" font-size="11">前 3 層の前処理を全て実行後、推定 token > contextWindow - maxOutputTokens - 13_000。</text>
|
||||
<text x="115" y="86" fill="#991b1b" font-size="10">まず sessionMemoryCompact を試行(既存のメモリで軽量要約)、不足時のみ LLM を呼び出し。</text>
|
||||
|
||||
<!-- ステップ -->
|
||||
<rect x="20" y="106" width="200" height="110" rx="8" fill="#fff" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="120" y="130" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">ステップ 1:transcript 保存</text>
|
||||
<text x="40" y="152" fill="#475569" font-size="10">完全な対話を .transcripts/ に書き込み</text>
|
||||
<text x="40" y="168" fill="#475569" font-size="10">JSONL 形式、1 行 1 メッセージ</text>
|
||||
<text x="40" y="184" fill="#475569" font-size="10">ファイル名:transcript_{timestamp}.jsonl</text>
|
||||
<text x="40" y="200" fill="#94a3b8" font-size="9">情報は失われていない、アクティブ領域から移動のみ</text>
|
||||
|
||||
<line x1="225" y1="161" x2="265" y2="161" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="270" y="106" width="200" height="110" rx="8" fill="#fff" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="370" y="130" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">ステップ 2:LLM 要約生成</text>
|
||||
<text x="290" y="152" fill="#475569" font-size="10">対話履歴を LLM に送信</text>
|
||||
<text x="290" y="166" fill="#475569" font-size="9">要約は 9 つのセクションを含む:</text>
|
||||
<text x="290" y="180" fill="#94a3b8" font-size="8">リクエスト・概念・ファイル・エラー・解決</text>
|
||||
<text x="290" y="192" fill="#94a3b8" font-size="8">ユーザーメッセージ・TODO・現在・次ステップ</text>
|
||||
<text x="290" y="206" fill="#94a3b8" font-size="9">1 回のみ生成</text>
|
||||
|
||||
<line x1="475" y1="161" x2="515" y2="161" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="520" y="106" width="180" height="110" rx="8" fill="#fef2f2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="610" y="130" fill="#991b1b" font-size="12" font-weight="700" text-anchor="middle">ステップ 3:メッセージリスト置換</text>
|
||||
<text x="540" y="152" fill="#991b1b" font-size="10">全旧メッセージ → 1 件の要約に</text>
|
||||
<text x="540" y="168" fill="#991b1b" font-size="10">モデルは要約から作業を継続</text>
|
||||
<text x="540" y="184" fill="#991b1b" font-size="10">recently_read ファイルリストを付与</text>
|
||||
<text x="540" y="200" fill="#ef4444" font-size="9">⚠ これは復元不可能な操作</text>
|
||||
|
||||
<!-- 圧縮前/後 比較 -->
|
||||
<rect x="20" y="234" width="320" height="94" rx="6" fill="#fff" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="180" y="256" fill="#64748b" font-size="11" font-weight="600" text-anchor="middle">圧縮前 messages</text>
|
||||
<rect x="35" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="40" y="276" fill="#475569" font-size="8">user</text>
|
||||
<rect x="92" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="97" y="276" fill="#475569" font-size="8">assistant</text>
|
||||
<rect x="149" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="154" y="276" fill="#475569" font-size="8">user</text>
|
||||
<rect x="206" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="211" y="276" fill="#475569" font-size="8">assistant</text>
|
||||
<rect x="263" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="268" y="276" fill="#475569" font-size="8">user</text>
|
||||
<text x="180" y="318" fill="#94a3b8" font-size="9" text-anchor="middle">~180 件のメッセージ、62K トークンを占有</text>
|
||||
|
||||
<line x1="345" y1="281" x2="375" y2="281" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="380" y="234" width="320" height="94" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="540" y="256" fill="#991b1b" font-size="11" font-weight="600" text-anchor="middle">圧縮後 messages</text>
|
||||
<rect x="395" y="264" width="290" height="32" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="540" y="276" fill="#991b1b" font-size="9" text-anchor="middle">[Compacted] 要約:目標 → hello.py を作成 ...</text>
|
||||
<text x="540" y="290" fill="#991b1b" font-size="9" text-anchor="middle">最近のファイル:hello.py, README.md ...</text>
|
||||
<text x="540" y="318" fill="#94a3b8" font-size="9" text-anchor="middle">~1 件のメッセージ、1K トークンを占有</text>
|
||||
|
||||
<!-- サーキットブレーカー -->
|
||||
<rect x="20" y="340" width="680" height="36" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="35" y="362" fill="#475569" font-size="11" font-weight="600">サーキットブレーカー:</text>
|
||||
<text x="145" y="362" fill="#475569" font-size="10">autocompact が連続 3 回失敗 → リトライ停止。コンテキストが復元不可能な場合の API 呼び出しの無駄な反復を防止。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
@@ -0,0 +1,72 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 400" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#991b1b"/><stop offset="100%" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="400" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">L4: autoCompact — LLM 全量摘要</text>
|
||||
|
||||
<!-- 触发条件 -->
|
||||
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">触发条件</text>
|
||||
<text x="105" y="70" fill="#991b1b" font-size="11">前三层预处理全跑完,估算 token > contextWindow - maxOutputTokens - 13_000。</text>
|
||||
<text x="105" y="86" fill="#991b1b" font-size="10">先尝试 sessionMemoryCompact(用已有记忆做轻量摘要),不足才调 LLM。</text>
|
||||
|
||||
<!-- 步骤 -->
|
||||
<rect x="20" y="106" width="200" height="110" rx="8" fill="#fff" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="120" y="130" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">步骤 1:保存 transcript</text>
|
||||
<text x="40" y="152" fill="#475569" font-size="10">完整对话写入 .transcripts/</text>
|
||||
<text x="40" y="168" fill="#475569" font-size="10">JSONL 格式,一行一条消息</text>
|
||||
<text x="40" y="184" fill="#475569" font-size="10">文件名:transcript_{timestamp}.jsonl</text>
|
||||
<text x="40" y="200" fill="#94a3b8" font-size="9">信息没有丢失,只是移出活跃区</text>
|
||||
|
||||
<line x1="225" y1="161" x2="265" y2="161" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="270" y="106" width="200" height="110" rx="8" fill="#fff" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="370" y="130" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">步骤 2:LLM 生成摘要</text>
|
||||
<text x="290" y="152" fill="#475569" font-size="10">把对话历史发给 LLM</text>
|
||||
<text x="290" y="166" fill="#475569" font-size="9">摘要需包含 9 个部分:</text>
|
||||
<text x="290" y="180" fill="#94a3b8" font-size="8">请求·概念·文件·错误·解决</text>
|
||||
<text x="290" y="192" fill="#94a3b8" font-size="8">用户消息·待办·当前·下一步</text>
|
||||
<text x="290" y="206" fill="#94a3b8" font-size="9">只生成一次</text>
|
||||
|
||||
<line x1="475" y1="161" x2="515" y2="161" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="520" y="106" width="180" height="110" rx="8" fill="#fef2f2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="610" y="130" fill="#991b1b" font-size="12" font-weight="700" text-anchor="middle">步骤 3:替换消息列表</text>
|
||||
<text x="540" y="152" fill="#991b1b" font-size="10">所有旧消息 → 1 条摘要</text>
|
||||
<text x="540" y="168" fill="#991b1b" font-size="10">模型从摘要继续工作</text>
|
||||
<text x="540" y="184" fill="#991b1b" font-size="10">附带 recently_read 文件列表</text>
|
||||
<text x="540" y="200" fill="#ef4444" font-size="9">⚠ 这是无法恢复的操作</text>
|
||||
|
||||
<!-- Before/After 对比 -->
|
||||
<rect x="20" y="234" width="320" height="94" rx="6" fill="#fff" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="180" y="256" fill="#64748b" font-size="11" font-weight="600" text-anchor="middle">压缩前 messages</text>
|
||||
<rect x="35" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="40" y="276" fill="#475569" font-size="8">user</text>
|
||||
<rect x="92" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="97" y="276" fill="#475569" font-size="8">assistant</text>
|
||||
<rect x="149" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="154" y="276" fill="#475569" font-size="8">user</text>
|
||||
<rect x="206" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="211" y="276" fill="#475569" font-size="8">assistant</text>
|
||||
<rect x="263" y="264" width="52" height="16" rx="3" fill="#e2e8f0"/><text x="268" y="276" fill="#475569" font-size="8">user</text>
|
||||
<text x="180" y="318" fill="#94a3b8" font-size="9" text-anchor="middle">~180 条消息,占 62K token</text>
|
||||
|
||||
<line x1="345" y1="281" x2="375" y2="281" stroke="#dc2626" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="380" y="234" width="320" height="94" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="540" y="256" fill="#991b1b" font-size="11" font-weight="600" text-anchor="middle">压缩后 messages</text>
|
||||
<rect x="395" y="264" width="290" height="32" rx="4" fill="#fee2e2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="540" y="276" fill="#991b1b" font-size="9" text-anchor="middle">[Compacted] 摘要:目标 → 创建 hello.py ...</text>
|
||||
<text x="540" y="290" fill="#991b1b" font-size="9" text-anchor="middle">最近文件:hello.py, README.md ...</text>
|
||||
<text x="540" y="318" fill="#94a3b8" font-size="9" text-anchor="middle">~1 条消息,占 1K token</text>
|
||||
|
||||
<!-- 熔断器 -->
|
||||
<rect x="20" y="340" width="680" height="36" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="35" y="362" fill="#475569" font-size="11" font-weight="600">熔断器:</text>
|
||||
<text x="95" y="362" fill="#475569" font-size="10">连续 autocompact 失败 3 次 → 停止重试。防止上下文不可恢复时反复浪费 API 调用。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,138 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 820 520" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="820" height="520" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="820" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="820" height="8" fill="url(#header)"/>
|
||||
<text x="410" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Context Compact — Compression Before LLM Call, Three Trigger Modes</text>
|
||||
|
||||
<!-- Labels -->
|
||||
<text x="50" y="74" fill="#94a3b8" font-size="11" font-weight="600">s07 Preserved</text>
|
||||
<text x="180" y="74" fill="#d97706" font-size="11" font-weight="600">s08 New</text>
|
||||
|
||||
<!-- ===== ① messages[] ===== -->
|
||||
<rect x="40" y="132" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="90" y="155" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
<text x="90" y="172" fill="#64748b" font-size="9" text-anchor="middle">(s07 preserved)</text>
|
||||
|
||||
<!-- messages → pipeline entry -->
|
||||
<line x1="140" y1="158" x2="168" y2="158" stroke="#d97706" stroke-width="2" marker-end="url(#arrow-amber)"/>
|
||||
|
||||
<!-- ===== ② Compression Pipeline ===== -->
|
||||
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Compression Pipeline</text>
|
||||
|
||||
<!-- ── ① Every Turn Auto ── -->
|
||||
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
||||
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① Every Turn · Unconditional · 0 API</text>
|
||||
|
||||
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">L3 tool_result_budget</text>
|
||||
|
||||
<rect x="186" y="158" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">L1 snip_compact</text>
|
||||
|
||||
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">L2 micro_compact</text>
|
||||
|
||||
<!-- ↓ → ◇ -->
|
||||
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ◇ Decision Diamond -->
|
||||
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
||||
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">Over threshold?</text>
|
||||
|
||||
<!-- No: right annotation -->
|
||||
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → Pass</text>
|
||||
<text x="306" y="252" fill="#94a3b8" font-size="7">Straight to LLM</text>
|
||||
|
||||
<!-- Yes: below annotation -->
|
||||
<text x="284" y="260" fill="#ea580c" font-size="8" font-weight="600">Yes↓</text>
|
||||
|
||||
<!-- ── ② Conditional Trigger ── -->
|
||||
<rect x="186" y="268" width="168" height="16" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="0.8"/>
|
||||
<text x="270" y="280" fill="#9a3412" font-size="8" font-weight="700" text-anchor="middle">② Conditional · Token Over Threshold · 1 API</text>
|
||||
|
||||
<rect x="186" y="288" width="168" height="24" rx="4" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="270" y="304" fill="#9a3412" font-size="10" font-weight="600" text-anchor="middle">L4 compact_history</text>
|
||||
|
||||
<!-- Pipeline exit → LLM -->
|
||||
<line x1="370" y1="158" x2="438" y2="158" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- ===== ③ LLM ===== -->
|
||||
<rect x="440" y="132" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="490" y="155" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="490" y="172" fill="#64748b" font-size="9" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- LLM No → Return -->
|
||||
<line x1="490" y1="184" x2="490" y2="278" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="502" y="262" fill="#16a34a" font-size="10" font-weight="600">No</text>
|
||||
<rect x="435" y="280" width="110" height="26" rx="13" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="490" y="297" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">Return Result</text>
|
||||
|
||||
<!-- LLM Yes → TOOL_HANDLERS -->
|
||||
<line x1="540" y1="158" x2="578" y2="158" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="554" y="150" fill="#64748b" font-size="10" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ④ TOOL_HANDLERS -->
|
||||
<rect x="580" y="126" width="130" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="645" y="150" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="645" y="166" fill="#64748b" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
<text x="645" y="180" fill="#64748b" font-size="9" text-anchor="middle">task · load_skill · ...</text>
|
||||
|
||||
<!-- LLM API error → emergency compact → retry next turn -->
|
||||
<path d="M 535 184 L 570 216 L 580 228" fill="none" stroke="#dc2626" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-red)"/>
|
||||
<text x="552" y="204" fill="#991b1b" font-size="8" font-weight="600">API error</text>
|
||||
<path d="M 665 266 L 665 340 L 160 340 L 160 142 L 186 142" fill="none" stroke="#dc2626" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-red)"/>
|
||||
<text x="530" y="328" fill="#991b1b" font-size="8" font-weight="600">retry to compression pipeline</text>
|
||||
|
||||
<!-- ===== ③ Emergency Trigger (after LLM API failure) ===== -->
|
||||
<rect x="580" y="210" width="170" height="56" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="665" y="228" fill="#991b1b" font-size="9" font-weight="700" text-anchor="middle">③ Emergency Trigger</text>
|
||||
<text x="665" y="242" fill="#991b1b" font-size="8" text-anchor="middle">API returns prompt_too_long</text>
|
||||
<text x="665" y="256" fill="#991b1b" font-size="8" text-anchor="middle">→ reactive_compact → retry</text>
|
||||
|
||||
<!-- ===== Loop Back ===== -->
|
||||
<path d="M 710 158 L 760 158 L 760 348 L 90 348 L 90 184" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="410" y="366" fill="#64748b" font-size="10" text-anchor="middle">Tool results appended to messages[] → next turn → compress again → LLM</text>
|
||||
|
||||
<!-- ===== Legend ===== -->
|
||||
<rect x="50" y="390" width="720" height="116" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
|
||||
<rect x="70" y="404" width="16" height="12" rx="3" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="94" y="414" fill="#334155" font-size="10">s07 Preserved: loop, hooks, skill loading, sub-agents</text>
|
||||
|
||||
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="94" y="436" fill="#334155" font-size="10">① Every Turn Auto: L3→L1→L2 run unconditionally before each LLM call, 0 API</text>
|
||||
|
||||
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="94" y="458" fill="#334155" font-size="10">② Conditional: after L3/L1/L2, tokens still over threshold → compact_history, 1 API</text>
|
||||
|
||||
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
||||
<text x="94" y="480" fill="#334155" font-size="10">③ Emergency: API returns prompt_too_long → reactive_compact → retry</text>
|
||||
|
||||
<text x="70" y="498" fill="#94a3b8" font-size="9">Three modes with increasing cost: 0 API → 1 API → 1 API + more aggressive trimming</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.0 KiB |
@@ -0,0 +1,138 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 820 520" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="820" height="520" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="820" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="820" height="8" fill="url(#header)"/>
|
||||
<text x="410" y="31" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Context Compact — LLM 呼び出し前に圧縮、3 つのトリガーモード</text>
|
||||
|
||||
<!-- ラベル -->
|
||||
<text x="50" y="74" fill="#94a3b8" font-size="11" font-weight="600">s07 保持</text>
|
||||
<text x="180" y="74" fill="#d97706" font-size="11" font-weight="600">s08 新規</text>
|
||||
|
||||
<!-- ===== ① messages[] ===== -->
|
||||
<rect x="40" y="132" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="90" y="155" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
<text x="90" y="172" fill="#64748b" font-size="9" text-anchor="middle">(s07 保持)</text>
|
||||
|
||||
<!-- messages → パイプライン入口 -->
|
||||
<line x1="140" y1="158" x2="168" y2="158" stroke="#d97706" stroke-width="2" marker-end="url(#arrow-amber)"/>
|
||||
|
||||
<!-- ===== ② 圧縮パイプライン ===== -->
|
||||
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">圧縮パイプライン</text>
|
||||
|
||||
<!-- ── ① 毎ターン自動 ── -->
|
||||
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
||||
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① 毎ターン自動 · 無条件 · 0 API</text>
|
||||
|
||||
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">L3 tool_result_budget</text>
|
||||
|
||||
<rect x="186" y="158" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">L1 snip_compact</text>
|
||||
|
||||
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">L2 micro_compact</text>
|
||||
|
||||
<!-- ↓ → ◇ -->
|
||||
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ◇ 判定ダイヤモンド -->
|
||||
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
||||
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">閾値超過?</text>
|
||||
|
||||
<!-- いいえ:右側注釈 -->
|
||||
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → 通過</text>
|
||||
<text x="306" y="252" fill="#94a3b8" font-size="7">直接 LLM へ</text>
|
||||
|
||||
<!-- はい:下注釈 -->
|
||||
<text x="284" y="260" fill="#ea580c" font-size="8" font-weight="600">Yes↓</text>
|
||||
|
||||
<!-- ── ② 条件トリガー ── -->
|
||||
<rect x="186" y="268" width="168" height="16" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="0.8"/>
|
||||
<text x="270" y="280" fill="#9a3412" font-size="8" font-weight="700" text-anchor="middle">② 条件 · トークン閾値超過 · 1 API</text>
|
||||
|
||||
<rect x="186" y="288" width="168" height="24" rx="4" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="270" y="304" fill="#9a3412" font-size="10" font-weight="600" text-anchor="middle">L4 compact_history</text>
|
||||
|
||||
<!-- パイプライン出口 → LLM -->
|
||||
<line x1="370" y1="158" x2="438" y2="158" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- ===== ③ LLM ===== -->
|
||||
<rect x="440" y="132" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="490" y="155" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="490" y="172" fill="#64748b" font-size="9" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- LLM No → 返却 -->
|
||||
<line x1="490" y1="184" x2="490" y2="278" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="502" y="262" fill="#16a34a" font-size="10" font-weight="600">No</text>
|
||||
<rect x="435" y="280" width="110" height="26" rx="13" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="490" y="297" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">結果を返す</text>
|
||||
|
||||
<!-- LLM Yes → TOOL_HANDLERS -->
|
||||
<line x1="540" y1="158" x2="578" y2="158" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="554" y="150" fill="#64748b" font-size="10" font-weight="600">Yes</text>
|
||||
|
||||
<!-- ④ TOOL_HANDLERS -->
|
||||
<rect x="580" y="126" width="130" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="645" y="150" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="645" y="166" fill="#64748b" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
<text x="645" y="180" fill="#64748b" font-size="9" text-anchor="middle">task · load_skill · ...</text>
|
||||
|
||||
<!-- LLM API 例外 → 緊急圧縮 → 次ターンで再試行 -->
|
||||
<path d="M 535 184 L 570 216 L 580 228" fill="none" stroke="#dc2626" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-red)"/>
|
||||
<text x="552" y="204" fill="#991b1b" font-size="8" font-weight="600">API 例外</text>
|
||||
<path d="M 665 266 L 665 340 L 160 340 L 160 142 L 186 142" fill="none" stroke="#dc2626" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-red)"/>
|
||||
<text x="530" y="328" fill="#991b1b" font-size="8" font-weight="600">圧縮パイプラインへ再試行</text>
|
||||
|
||||
<!-- ===== ③ 緊急トリガー(LLM API 失敗後) ===== -->
|
||||
<rect x="580" y="210" width="170" height="56" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="665" y="228" fill="#991b1b" font-size="9" font-weight="700" text-anchor="middle">③ 緊急トリガー</text>
|
||||
<text x="665" y="242" fill="#991b1b" font-size="8" text-anchor="middle">API が prompt_too_long を返す</text>
|
||||
<text x="665" y="256" fill="#991b1b" font-size="8" text-anchor="middle">→ reactive_compact → リトライ</text>
|
||||
|
||||
<!-- ===== ループバック ===== -->
|
||||
<path d="M 710 158 L 760 158 L 760 348 L 90 348 L 90 184" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="410" y="366" fill="#64748b" font-size="10" text-anchor="middle">ツール結果を messages[] に追加 → 次ターン → 再圧縮 → LLM</text>
|
||||
|
||||
<!-- ===== 凡例 ===== -->
|
||||
<rect x="50" y="390" width="720" height="116" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
|
||||
<rect x="70" y="404" width="16" height="12" rx="3" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="94" y="414" fill="#334155" font-size="10">s07 保持:ループ、フック、スキルロード、サブエージェント</text>
|
||||
|
||||
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="94" y="436" fill="#334155" font-size="10">① 毎ターン自動:L3→L1→L2 が各 LLM 呼び出し前に無条件実行、0 API</text>
|
||||
|
||||
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="94" y="458" fill="#334155" font-size="10">② 条件トリガー:L3/L1/L2 後もトークン超過 → compact_history、1 API</text>
|
||||
|
||||
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
||||
<text x="94" y="480" fill="#334155" font-size="10">③ 緊急トリガー:API が prompt_too_long を返す → reactive_compact → リトライ</text>
|
||||
|
||||
<text x="70" y="498" fill="#94a3b8" font-size="9">3 つのモードはコスト増加:0 API → 1 API → 1 API + より積極的なトリム</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.2 KiB |
@@ -0,0 +1,138 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 820 520" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect width="820" height="520" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- 标题 -->
|
||||
<rect x="0" y="0" width="820" height="48" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="40" width="820" height="8" fill="url(#header)"/>
|
||||
<text x="410" y="31" fill="#fff" font-size="16" font-weight="700" text-anchor="middle">Context Compact — 压缩插在 LLM 调用前,三种触发模式</text>
|
||||
|
||||
<!-- 标签 -->
|
||||
<text x="50" y="74" fill="#94a3b8" font-size="11" font-weight="600">s07 保留</text>
|
||||
<text x="180" y="74" fill="#d97706" font-size="11" font-weight="600">s08 新增</text>
|
||||
|
||||
<!-- ===== ① messages[] ===== -->
|
||||
<rect x="40" y="132" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="90" y="155" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
<text x="90" y="172" fill="#64748b" font-size="9" text-anchor="middle">(s07 保留)</text>
|
||||
|
||||
<!-- messages → 管线入口 -->
|
||||
<line x1="140" y1="158" x2="168" y2="158" stroke="#d97706" stroke-width="2" marker-end="url(#arrow-amber)"/>
|
||||
|
||||
<!-- ===== ② 压缩管线(内部只放标签,不画路径线) ===== -->
|
||||
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
||||
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">压缩管线</text>
|
||||
|
||||
<!-- ── ① 每轮自动 ── -->
|
||||
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
||||
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① 每轮自动 · 无条件 · 0 API</text>
|
||||
|
||||
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">L3 tool_result_budget</text>
|
||||
|
||||
<rect x="186" y="158" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">L1 snip_compact</text>
|
||||
|
||||
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">L2 micro_compact</text>
|
||||
|
||||
<!-- ↓ → ◇ -->
|
||||
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ◇ 判断菱形(紧凑) -->
|
||||
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
||||
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">超阈值?</text>
|
||||
|
||||
<!-- 否:右侧文字标注 -->
|
||||
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">否 → 通过</text>
|
||||
<text x="306" y="252" fill="#94a3b8" font-size="7">直接进 LLM</text>
|
||||
|
||||
<!-- 是:下方文字标注 -->
|
||||
<text x="284" y="260" fill="#ea580c" font-size="8" font-weight="600">是↓</text>
|
||||
|
||||
<!-- ── ② 条件触发 ── -->
|
||||
<rect x="186" y="268" width="168" height="16" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="0.8"/>
|
||||
<text x="270" y="280" fill="#9a3412" font-size="8" font-weight="700" text-anchor="middle">② 条件触发 · token 超阈值 · 1 API</text>
|
||||
|
||||
<rect x="186" y="288" width="168" height="24" rx="4" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="270" y="304" fill="#9a3412" font-size="10" font-weight="600" text-anchor="middle">L4 compact_history</text>
|
||||
|
||||
<!-- 管线出口 → LLM -->
|
||||
<line x1="370" y1="158" x2="438" y2="158" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- ===== ③ LLM ===== -->
|
||||
<rect x="440" y="132" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="490" y="155" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="490" y="172" fill="#64748b" font-size="9" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
|
||||
<!-- LLM 否 → 返回 -->
|
||||
<line x1="490" y1="184" x2="490" y2="278" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="502" y="262" fill="#16a34a" font-size="10" font-weight="600">否</text>
|
||||
<rect x="435" y="280" width="110" height="26" rx="13" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="490" y="297" fill="#166534" font-size="11" font-weight="600" text-anchor="middle">返回结果</text>
|
||||
|
||||
<!-- LLM 是 → TOOL_HANDLERS -->
|
||||
<line x1="540" y1="158" x2="578" y2="158" stroke="#555" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<text x="554" y="150" fill="#64748b" font-size="10" font-weight="600">是</text>
|
||||
|
||||
<!-- ④ TOOL_HANDLERS -->
|
||||
<rect x="580" y="126" width="130" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="645" y="150" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="645" y="166" fill="#64748b" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
<text x="645" y="180" fill="#64748b" font-size="9" text-anchor="middle">task · load_skill · ...</text>
|
||||
|
||||
<!-- LLM API 异常 → 应急压缩 → 下一轮重试 -->
|
||||
<path d="M 535 184 L 570 216 L 580 228" fill="none" stroke="#dc2626" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-red)"/>
|
||||
<text x="552" y="204" fill="#991b1b" font-size="8" font-weight="600">API 异常</text>
|
||||
<path d="M 665 266 L 665 340 L 160 340 L 160 142 L 186 142" fill="none" stroke="#dc2626" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-red)"/>
|
||||
<text x="530" y="328" fill="#991b1b" font-size="8" font-weight="600">重试回到压缩管线</text>
|
||||
|
||||
<!-- ===== ③ 异常触发(LLM API 调用失败后) ===== -->
|
||||
<rect x="580" y="210" width="170" height="56" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="665" y="228" fill="#991b1b" font-size="9" font-weight="700" text-anchor="middle">③ 异常触发</text>
|
||||
<text x="665" y="242" fill="#991b1b" font-size="8" text-anchor="middle">API 返回 prompt_too_long</text>
|
||||
<text x="665" y="256" fill="#991b1b" font-size="8" text-anchor="middle">→ reactive_compact → 重试</text>
|
||||
|
||||
<!-- ===== 回环(y=348 在管线框底 y=334 下方,完全不穿过) ===== -->
|
||||
<path d="M 710 158 L 760 158 L 760 348 L 90 348 L 90 184" fill="none" stroke="#555" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="410" y="366" fill="#64748b" font-size="10" text-anchor="middle">工具结果追加到 messages[] → 下一轮 → 再次压缩 → LLM</text>
|
||||
|
||||
<!-- ===== 图例 ===== -->
|
||||
<rect x="50" y="390" width="720" height="116" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
|
||||
<rect x="70" y="404" width="16" height="12" rx="3" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="94" y="414" fill="#334155" font-size="10">s07 保留:循环、hook、技能加载、子 Agent</text>
|
||||
|
||||
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="94" y="436" fill="#334155" font-size="10">① 每轮自动:L3→L1→L2 在每次 LLM 调用前无条件执行,0 API</text>
|
||||
|
||||
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="94" y="458" fill="#334155" font-size="10">② 条件触发:L3/L1/L2 跑完 token 仍超阈值 → compact_history,1 API</text>
|
||||
|
||||
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
||||
<text x="94" y="480" fill="#334155" font-size="10">③ 异常触发:API 返回 prompt_too_long → reactive_compact → 重试</text>
|
||||
|
||||
<text x="70" y="498" fill="#94a3b8" font-size="9">三种模式的代价递增:0 API → 1 API → 1 API + 更激进的裁剪</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.0 KiB |
@@ -0,0 +1,98 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 590" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="pre" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#dbeafe"/><stop offset="100%" stop-color="#bfdbfe"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="auto" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fecaca"/><stop offset="100%" stop-color="#fca5a5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="emergency" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fed7aa"/><stop offset="100%" stop-color="#fdba74"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow-d" viewBox="0 0 10 10" refX="5" refY="10" markerWidth="6" markerHeight="6" orient="auto">
|
||||
<path d="M 0 0 L 5 10 L 10 0 z" fill="#94a3b8"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="590" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title bar -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Context Compaction — Pre-processing Pipeline + Auto-compact + Emergency Fallback</text>
|
||||
|
||||
<!-- Design principles (left) -->
|
||||
<rect x="20" y="62" width="220" height="80" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="130" y="82" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">Design Principles</text>
|
||||
<text x="130" y="100" fill="#475569" font-size="10" text-anchor="middle">Cheap operations first, expensive later</text>
|
||||
<text x="130" y="116" fill="#475569" font-size="10" text-anchor="middle">Trim text before dropping messages</text>
|
||||
<text x="130" y="132" fill="#475569" font-size="10" text-anchor="middle">Drop messages before calling LLM</text>
|
||||
|
||||
<!-- Cost escalation (right) -->
|
||||
<rect x="530" y="62" width="210" height="80" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="635" y="82" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">Increasing Cost</text>
|
||||
<text x="635" y="104" fill="#475569" font-size="10" text-anchor="middle">Text ops → LLM summary → Emergency trim</text>
|
||||
<text x="635" y="124" fill="#94a3b8" font-size="9" text-anchor="middle">0 API · 0 API · 0 API · 1 API · 1 API</text>
|
||||
|
||||
<!-- ===== Pre-processing pipeline title ===== -->
|
||||
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">Pre-processing Pipeline (execution order: L3 → L1 → L2, before every LLM call, 0 API)</text>
|
||||
|
||||
<!-- L3: toolResultBudget -->
|
||||
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="200" fill="#1e40af" font-size="12" font-weight="600">L3</text>
|
||||
<text x="135" y="200" fill="#1e40af" font-size="13" font-weight="700">toolResultBudget</text>
|
||||
<text x="260" y="200" fill="#1e40af" font-size="11">tool_result total > 200KB → spill largest item</text>
|
||||
<text x="650" y="200" fill="#1e40af" font-size="10" text-anchor="end">keep full content</text>
|
||||
<text x="135" y="218" fill="#2563eb" font-size="9">Trigger: every turn, before microCompact can replace full content</text>
|
||||
|
||||
<!-- Arrow L3→L1 -->
|
||||
<line x1="380" y1="226" x2="380" y2="238" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow-d)"/>
|
||||
|
||||
<!-- L1: snipCompact -->
|
||||
<rect x="80" y="240" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="260" fill="#1e40af" font-size="12" font-weight="600">L1</text>
|
||||
<text x="135" y="260" fill="#1e40af" font-size="13" font-weight="700">snipCompact</text>
|
||||
<text x="260" y="260" fill="#1e40af" font-size="11">messages > 50 → trim middle</text>
|
||||
<text x="650" y="260" fill="#1e40af" font-size="10" text-anchor="end">keep head/tail</text>
|
||||
<text x="135" y="278" fill="#2563eb" font-size="9">Trigger: message count exceeds threshold</text>
|
||||
|
||||
<!-- Arrow L1→L2 -->
|
||||
<line x1="380" y1="286" x2="380" y2="298" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow-d)"/>
|
||||
|
||||
<!-- L2: microCompact -->
|
||||
<rect x="80" y="300" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="320" fill="#1e40af" font-size="12" font-weight="600">L2</text>
|
||||
<text x="135" y="320" fill="#1e40af" font-size="13" font-weight="700">microCompact</text>
|
||||
<text x="260" y="320" fill="#1e40af" font-size="11">old tool_result → placeholder (keep latest 3)</text>
|
||||
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">compact old</text>
|
||||
<text x="135" y="338" fill="#2563eb" font-size="9">Trigger: every turn automatically; tutorial uses text placeholder</text>
|
||||
|
||||
<!-- ===== Auto-compact title ===== -->
|
||||
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">Auto-compact Decision (triggered when pre-processing is insufficient, 1 API call)</text>
|
||||
|
||||
<!-- L4: autoCompact -->
|
||||
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="100" y="412" fill="#991b1b" font-size="12" font-weight="600">L4</text>
|
||||
<text x="135" y="412" fill="#991b1b" font-size="13" font-weight="700">autoCompact</text>
|
||||
<text x="260" y="412" fill="#991b1b" font-size="11">tokens over threshold → LLM summary</text>
|
||||
<text x="650" y="412" fill="#991b1b" font-size="10" text-anchor="end">1 API call</text>
|
||||
<text x="135" y="428" fill="#dc2626" font-size="9">Threshold: contextWindow - maxOutputTokens - 13,000 · Try sessionMemoryCompact first, then LLM</text>
|
||||
<text x="135" y="442" fill="#dc2626" font-size="9">Circuit breaker: stop retrying after 3 consecutive failures</text>
|
||||
|
||||
<!-- ===== Emergency fallback title ===== -->
|
||||
<rect x="20" y="460" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||
<text x="55" y="477" fill="#64748b" font-size="11" font-weight="600">Emergency Fallback (triggered when API still returns prompt_too_long)</text>
|
||||
|
||||
<!-- Emergency: reactiveCompact -->
|
||||
<rect x="80" y="492" width="600" height="62" rx="7" fill="url(#emergency)" stroke="#c2410c" stroke-width="1.5"/>
|
||||
<text x="100" y="512" fill="#9a3412" font-size="12" font-weight="600">Emrg</text>
|
||||
<text x="135" y="512" fill="#9a3412" font-size="13" font-weight="700">reactiveCompact</text>
|
||||
<text x="135" y="528" fill="#9a3412" font-size="10">API returns 413 / prompt_too_long → byte-level trim</text>
|
||||
<text x="135" y="544" fill="#c2410c" font-size="9">Keep last 5 + summary; more aggressive than autoCompact</text>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,98 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 590" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="pre" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#dbeafe"/><stop offset="100%" stop-color="#bfdbfe"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="auto" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fecaca"/><stop offset="100%" stop-color="#fca5a5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="emergency" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fed7aa"/><stop offset="100%" stop-color="#fdba74"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow-d" viewBox="0 0 10 10" refX="5" refY="10" markerWidth="6" markerHeight="6" orient="auto">
|
||||
<path d="M 0 0 L 5 10 L 10 0 z" fill="#94a3b8"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="590" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトルバー -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">コンテキスト圧縮 — 前処理パイプライン + 自動圧縮 + 緊急フォールバック</text>
|
||||
|
||||
<!-- 設計原則(左側) -->
|
||||
<rect x="20" y="62" width="220" height="80" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="130" y="82" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">設計原則</text>
|
||||
<text x="130" y="100" fill="#475569" font-size="10" text-anchor="middle">安価な処理を先に、高価な処理を後に</text>
|
||||
<text x="130" y="116" fill="#475569" font-size="10" text-anchor="middle">テキスト修正 → メッセージ削除の順</text>
|
||||
<text x="130" y="132" fill="#475569" font-size="10" text-anchor="middle">メッセージ削除 → LLM 呼び出しの順</text>
|
||||
|
||||
<!-- コスト増加(右側) -->
|
||||
<rect x="530" y="62" width="210" height="80" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="635" y="82" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">コスト増加</text>
|
||||
<text x="635" y="104" fill="#475569" font-size="10" text-anchor="middle">テキスト操作 → LLM 要約 → 緊急トリム</text>
|
||||
<text x="635" y="124" fill="#94a3b8" font-size="9" text-anchor="middle">0 API · 0 API · 0 API · 1 API · 1 API</text>
|
||||
|
||||
<!-- ===== 前処理パイプラインタイトル ===== -->
|
||||
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">前処理パイプライン(実行順:L3 → L1 → L2、各 LLM 呼び出し前に自動実行、0 API)</text>
|
||||
|
||||
<!-- L3: toolResultBudget -->
|
||||
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="200" fill="#1e40af" font-size="12" font-weight="600">L3</text>
|
||||
<text x="135" y="200" fill="#1e40af" font-size="13" font-weight="700">toolResultBudget</text>
|
||||
<text x="260" y="200" fill="#1e40af" font-size="11">tool_result 合計 > 200KB → 最大項目を退避</text>
|
||||
<text x="650" y="200" fill="#1e40af" font-size="10" text-anchor="end">完全内容を保持</text>
|
||||
<text x="135" y="218" fill="#2563eb" font-size="9">トリガー:毎ターン、microCompact が完全内容を置換する前に実行</text>
|
||||
|
||||
<!-- 矢印 L3→L1 -->
|
||||
<line x1="380" y1="226" x2="380" y2="238" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow-d)"/>
|
||||
|
||||
<!-- L1: snipCompact -->
|
||||
<rect x="80" y="240" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="260" fill="#1e40af" font-size="12" font-weight="600">L1</text>
|
||||
<text x="135" y="260" fill="#1e40af" font-size="13" font-weight="700">snipCompact</text>
|
||||
<text x="260" y="260" fill="#1e40af" font-size="11">メッセージ > 50 → 中間をトリム</text>
|
||||
<text x="650" y="260" fill="#1e40af" font-size="10" text-anchor="end">先頭/末尾保持</text>
|
||||
<text x="135" y="278" fill="#2563eb" font-size="9">トリガー:メッセージ数が閾値を超過</text>
|
||||
|
||||
<!-- 矢印 L1→L2 -->
|
||||
<line x1="380" y1="286" x2="380" y2="298" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow-d)"/>
|
||||
|
||||
<!-- L2: microCompact -->
|
||||
<rect x="80" y="300" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="320" fill="#1e40af" font-size="12" font-weight="600">L2</text>
|
||||
<text x="135" y="320" fill="#1e40af" font-size="13" font-weight="700">microCompact</text>
|
||||
<text x="260" y="320" fill="#1e40af" font-size="11">古い tool_result → プレースホルダー(最新 3 件保持)</text>
|
||||
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">旧結果を圧縮</text>
|
||||
<text x="135" y="338" fill="#2563eb" font-size="9">トリガー:毎ターン自動実行、チュートリアル版はテキストプレースホルダーで模擬</text>
|
||||
|
||||
<!-- ===== 自動圧縮タイトル ===== -->
|
||||
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自動圧縮判定(前処理で不足時にトリガー、1 API 呼び出し)</text>
|
||||
|
||||
<!-- L4: autoCompact -->
|
||||
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="100" y="412" fill="#991b1b" font-size="12" font-weight="600">L4</text>
|
||||
<text x="135" y="412" fill="#991b1b" font-size="13" font-weight="700">autoCompact</text>
|
||||
<text x="260" y="412" fill="#991b1b" font-size="11">トークンが閾値超過 → LLM 全量要約</text>
|
||||
<text x="590" y="412" fill="#991b1b" font-size="10" text-anchor="end">1 API 呼び出し</text>
|
||||
<text x="135" y="428" fill="#dc2626" font-size="9">閾値: contextWindow - maxOutputTokens - 13,000 · sessionMemoryCompact を先に試行、不足時のみ LLM 呼び出し</text>
|
||||
<text x="135" y="442" fill="#dc2626" font-size="9">サーキットブレーカー:連続 3 回失敗後にリトライ停止</text>
|
||||
|
||||
<!-- ===== 緊急フォールバックタイトル ===== -->
|
||||
<rect x="20" y="460" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||
<text x="55" y="477" fill="#64748b" font-size="11" font-weight="600">緊急フォールバック(API が引き続き prompt_too_long を返す場合にトリガー)</text>
|
||||
|
||||
<!-- 緊急: reactiveCompact -->
|
||||
<rect x="80" y="492" width="600" height="62" rx="7" fill="url(#emergency)" stroke="#c2410c" stroke-width="1.5"/>
|
||||
<text x="100" y="512" fill="#9a3412" font-size="12" font-weight="600">緊急</text>
|
||||
<text x="135" y="512" fill="#9a3412" font-size="13" font-weight="700">reactiveCompact</text>
|
||||
<text x="135" y="528" fill="#9a3412" font-size="10">API が 413 / prompt_too_long を返す → バイト単位でトリム</text>
|
||||
<text x="135" y="544" fill="#c2410c" font-size="9">最後の 5 件 + 要約を保持、autoCompact より積極的</text>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,98 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 590" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="pre" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#dbeafe"/><stop offset="100%" stop-color="#bfdbfe"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="auto" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fecaca"/><stop offset="100%" stop-color="#fca5a5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="emergency" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fed7aa"/><stop offset="100%" stop-color="#fdba74"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow-d" viewBox="0 0 10 10" refX="5" refY="10" markerWidth="6" markerHeight="6" orient="auto">
|
||||
<path d="M 0 0 L 5 10 L 10 0 z" fill="#94a3b8"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="590" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">上下文压缩 — 预处理管线 + 自动压缩 + 应急兜底</text>
|
||||
|
||||
<!-- 左侧说明 -->
|
||||
<rect x="20" y="62" width="220" height="80" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="130" y="82" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">设计原则</text>
|
||||
<text x="130" y="100" fill="#475569" font-size="10" text-anchor="middle">便宜的先跑,贵的后跑</text>
|
||||
<text x="130" y="116" fill="#475569" font-size="10" text-anchor="middle">能改文本 → 不删整条</text>
|
||||
<text x="130" y="132" fill="#475569" font-size="10" text-anchor="middle">能删整条 → 不调 LLM</text>
|
||||
|
||||
<!-- 右侧代价箭头 -->
|
||||
<rect x="530" y="62" width="210" height="80" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="635" y="82" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">代价递增</text>
|
||||
<text x="635" y="104" fill="#475569" font-size="10" text-anchor="middle">文本操作 → LLM 摘要 → 应急裁剪</text>
|
||||
<text x="635" y="124" fill="#94a3b8" font-size="9" text-anchor="middle">0 API · 0 API · 0 API · 1 API · 1 API</text>
|
||||
|
||||
<!-- ===== 预处理管线标题 ===== -->
|
||||
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">预处理管线(执行顺序:L3 → L1 → L2,每轮 LLM 调用前自动执行,0 API)</text>
|
||||
|
||||
<!-- L3: toolResultBudget -->
|
||||
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="200" fill="#1e40af" font-size="12" font-weight="600">L3</text>
|
||||
<text x="135" y="200" fill="#1e40af" font-size="13" font-weight="700">toolResultBudget</text>
|
||||
<text x="260" y="200" fill="#1e40af" font-size="11">tool_result 总和 > 200KB → 最大项落盘</text>
|
||||
<text x="650" y="200" fill="#1e40af" font-size="10" text-anchor="end">保留完整内容</text>
|
||||
<text x="135" y="218" fill="#2563eb" font-size="9">触发:每轮自动,必须在 microCompact 之前保留完整内容</text>
|
||||
|
||||
<!-- 箭头 L3→L1 -->
|
||||
<line x1="380" y1="226" x2="380" y2="238" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow-d)"/>
|
||||
|
||||
<!-- L1: snipCompact -->
|
||||
<rect x="80" y="240" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="260" fill="#1e40af" font-size="12" font-weight="600">L1</text>
|
||||
<text x="135" y="260" fill="#1e40af" font-size="13" font-weight="700">snipCompact</text>
|
||||
<text x="260" y="260" fill="#1e40af" font-size="11">消息 > 50 条 → 裁掉中间</text>
|
||||
<text x="650" y="260" fill="#1e40af" font-size="10" text-anchor="end">保留头尾</text>
|
||||
<text x="135" y="278" fill="#2563eb" font-size="9">触发:消息数超过阈值</text>
|
||||
|
||||
<!-- 箭头 L1→L2 -->
|
||||
<line x1="380" y1="286" x2="380" y2="298" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow-d)"/>
|
||||
|
||||
<!-- L2: microCompact -->
|
||||
<rect x="80" y="300" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="100" y="320" fill="#1e40af" font-size="12" font-weight="600">L2</text>
|
||||
<text x="135" y="320" fill="#1e40af" font-size="13" font-weight="700">microCompact</text>
|
||||
<text x="260" y="320" fill="#1e40af" font-size="11">旧 tool_result → 占位符(保留最近 3 条)</text>
|
||||
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">压旧结果</text>
|
||||
<text x="135" y="338" fill="#2563eb" font-size="9">触发:每轮自动,教学版用文本占位符模拟</text>
|
||||
|
||||
<!-- ===== 自动压缩标题 ===== -->
|
||||
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自动压缩决策(预处理不够时触发,1 API 调用)</text>
|
||||
|
||||
<!-- L4: autoCompact -->
|
||||
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="100" y="412" fill="#991b1b" font-size="12" font-weight="600">L4</text>
|
||||
<text x="135" y="412" fill="#991b1b" font-size="13" font-weight="700">autoCompact</text>
|
||||
<text x="260" y="412" fill="#991b1b" font-size="11">token 超阈值 → LLM 全量摘要</text>
|
||||
<text x="590" y="412" fill="#991b1b" font-size="10" text-anchor="end">1 API 调用</text>
|
||||
<text x="135" y="428" fill="#dc2626" font-size="9">阈值: contextWindow - maxOutputTokens - 13,000 · 先尝试 sessionMemoryCompact,不够才调 LLM</text>
|
||||
<text x="135" y="442" fill="#dc2626" font-size="9">熔断:连续失败 3 次后停止重试</text>
|
||||
|
||||
<!-- ===== 应急兜底标题 ===== -->
|
||||
<rect x="20" y="460" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||
<text x="55" y="477" fill="#64748b" font-size="11" font-weight="600">应急兜底(API 仍然返回 prompt_too_long 时触发)</text>
|
||||
|
||||
<!-- 应急: reactiveCompact -->
|
||||
<rect x="80" y="492" width="600" height="62" rx="7" fill="url(#emergency)" stroke="#c2410c" stroke-width="1.5"/>
|
||||
<text x="100" y="512" fill="#9a3412" font-size="12" font-weight="600">应急</text>
|
||||
<text x="135" y="512" fill="#9a3412" font-size="13" font-weight="700">reactiveCompact</text>
|
||||
<text x="135" y="528" fill="#9a3412" font-size="10">API 返回 413 / prompt_too_long → 字节级裁剪</text>
|
||||
<text x="135" y="544" fill="#c2410c" font-size="9">保留最后 5 条 + 摘要,比 autoCompact 更激进</text>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.6 KiB |
@@ -0,0 +1,50 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 356" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="356" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">L3: toolResultBudget — Large Result Persistence</text>
|
||||
|
||||
<!-- Pain Point -->
|
||||
<rect x="20" y="54" width="680" height="42" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="35" y="72" fill="#991b1b" font-size="11" font-weight="600">Pain Point</text>
|
||||
<text x="105" y="72" fill="#991b1b" font-size="11">Model read 30 files in one turn; total tool_result adds up to 500KB, filling the entire context window</text>
|
||||
|
||||
<!-- Before -->
|
||||
<text x="155" y="118" fill="#64748b" font-size="12" font-weight="600" text-anchor="middle">Before</text>
|
||||
<rect x="20" y="128" width="270" height="82" rx="6" fill="#fff" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="35" y="148" fill="#475569" font-size="10" font-family="monospace">tool_result: (78KB) ...</text>
|
||||
<text x="35" y="164" fill="#475569" font-size="10" font-family="monospace">tool_result: (142KB) ...</text>
|
||||
<text x="35" y="180" fill="#475569" font-size="10" font-family="monospace">tool_result: (290KB) ...</text>
|
||||
<text x="155" y="202" fill="#ef4444" font-size="9" font-weight="600" text-anchor="middle">Total 510KB → over budget</text>
|
||||
|
||||
<!-- Arrow -->
|
||||
<line x1="295" y1="163" x2="360" y2="163" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- After -->
|
||||
<text x="485" y="118" fill="#16a34a" font-size="12" font-weight="600" text-anchor="middle">After</text>
|
||||
<rect x="365" y="128" width="335" height="82" rx="6" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="380" y="148" fill="#166534" font-size="10" font-family="monospace">tool_result: <persisted-output></text>
|
||||
<text x="395" y="164" fill="#166534" font-size="9">Full output: .task_outputs/t1.txt</text>
|
||||
<text x="395" y="178" fill="#166534" font-size="9">Preview: (first 2000 chars) ...</text>
|
||||
<text x="532" y="202" fill="#16a34a" font-size="9" font-weight="600" text-anchor="middle">Total 18KB → normal</text>
|
||||
|
||||
<!-- How it works -->
|
||||
<rect x="20" y="214" width="680" height="64" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="35" y="234" fill="#1e3a5f" font-size="11" font-weight="600">How</text>
|
||||
<text x="70" y="234" fill="#475569" font-size="10">1. Sum the size of all tool_result in the latest turn</text>
|
||||
<text x="70" y="250" fill="#475569" font-size="10">2. Over 200KB → sort by size, persist the largest to .task_outputs/tool-results/</text>
|
||||
<text x="70" y="266" fill="#475569" font-size="10">3. Keep only <persisted-output> marker + first 2000 chars preview in context</text>
|
||||
|
||||
<!-- Result summary -->
|
||||
<rect x="20" y="290" width="680" height="36" rx="6" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="35" y="312" fill="#166534" font-size="11">Result: No data lost (full data on disk), context drops from 510KB to ~18KB, 0 API calls</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,50 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 356" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="356" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">L3: toolResultBudget — 大結果の永続化</text>
|
||||
|
||||
<!-- ペインポイント -->
|
||||
<rect x="20" y="54" width="680" height="42" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="35" y="72" fill="#991b1b" font-size="11" font-weight="600">ペインポイント</text>
|
||||
<text x="100" y="72" fill="#991b1b" font-size="11">モデルが一度に 30 ファイルを読み込み、単一ターンの tool_result が合計 500KB に達し、コンテキストウィンドウを圧迫</text>
|
||||
|
||||
<!-- 圧縮前 -->
|
||||
<text x="155" y="118" fill="#64748b" font-size="12" font-weight="600" text-anchor="middle">圧縮前</text>
|
||||
<rect x="20" y="128" width="270" height="82" rx="6" fill="#fff" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="35" y="148" fill="#475569" font-size="10" font-family="monospace">tool_result: (78KB) ...</text>
|
||||
<text x="35" y="164" fill="#475569" font-size="10" font-family="monospace">tool_result: (142KB) ...</text>
|
||||
<text x="35" y="180" fill="#475569" font-size="10" font-family="monospace">tool_result: (290KB) ...</text>
|
||||
<text x="155" y="202" fill="#ef4444" font-size="9" font-weight="600" text-anchor="middle">合計 510KB → 予算超過</text>
|
||||
|
||||
<!-- 矢印 -->
|
||||
<line x1="295" y1="163" x2="360" y2="163" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- 圧縮後 -->
|
||||
<text x="485" y="118" fill="#16a34a" font-size="12" font-weight="600" text-anchor="middle">圧縮後</text>
|
||||
<rect x="365" y="128" width="335" height="82" rx="6" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="380" y="148" fill="#166534" font-size="10" font-family="monospace">tool_result: <persisted-output></text>
|
||||
<text x="395" y="164" fill="#166534" font-size="9">Full output: .task_outputs/t1.txt</text>
|
||||
<text x="395" y="178" fill="#166534" font-size="9">Preview: (先頭 2000 文字) ...</text>
|
||||
<text x="532" y="202" fill="#16a34a" font-size="9" font-weight="600" text-anchor="middle">合計 18KB → 正常</text>
|
||||
|
||||
<!-- 原理説明 -->
|
||||
<rect x="20" y="214" width="680" height="64" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="35" y="234" fill="#1e3a5f" font-size="11" font-weight="600">方法</text>
|
||||
<text x="70" y="234" fill="#475569" font-size="10">1. 最終ターンの全 tool_result の合計サイズを集計</text>
|
||||
<text x="70" y="250" fill="#475569" font-size="10">2. 200KB 超過 → サイズ順にソートし、最大のものから .task_outputs/tool-results/ に永続化</text>
|
||||
<text x="70" y="266" fill="#475569" font-size="10">3. コンテキストには <persisted-output> マーカー + 先頭 2000 文字のプレビューのみ残す</text>
|
||||
|
||||
<!-- 変更サマリー -->
|
||||
<rect x="20" y="290" width="680" height="36" rx="6" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="35" y="312" fill="#166534" font-size="11">結果:情報は失われていない(ディスクに完全なデータあり)、コンテキストは 510KB → ~18KB に削減、0 回 API 呼び出し</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,50 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 356" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="356" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">L3: toolResultBudget — 大结果落盘</text>
|
||||
|
||||
<!-- 痛点 -->
|
||||
<rect x="20" y="54" width="680" height="42" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="35" y="72" fill="#991b1b" font-size="11" font-weight="600">痛点</text>
|
||||
<text x="75" y="72" fill="#991b1b" font-size="11">模型一次读了 30 个文件,单轮 tool_result 加起来 500KB,直接把上下文窗口打满</text>
|
||||
|
||||
<!-- Before -->
|
||||
<text x="155" y="118" fill="#64748b" font-size="12" font-weight="600" text-anchor="middle">压缩前</text>
|
||||
<rect x="20" y="128" width="270" height="82" rx="6" fill="#fff" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="35" y="148" fill="#475569" font-size="10" font-family="monospace">tool_result: (78KB) ...</text>
|
||||
<text x="35" y="164" fill="#475569" font-size="10" font-family="monospace">tool_result: (142KB) ...</text>
|
||||
<text x="35" y="180" fill="#475569" font-size="10" font-family="monospace">tool_result: (290KB) ...</text>
|
||||
<text x="155" y="202" fill="#ef4444" font-size="9" font-weight="600" text-anchor="middle">合计 510KB → 超预算</text>
|
||||
|
||||
<!-- Arrow -->
|
||||
<line x1="295" y1="163" x2="360" y2="163" stroke="#16a34a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- After -->
|
||||
<text x="485" y="118" fill="#16a34a" font-size="12" font-weight="600" text-anchor="middle">压缩后</text>
|
||||
<rect x="365" y="128" width="335" height="82" rx="6" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="380" y="148" fill="#166534" font-size="10" font-family="monospace">tool_result: <persisted-output></text>
|
||||
<text x="395" y="164" fill="#166534" font-size="9">Full output: .task_outputs/t1.txt</text>
|
||||
<text x="395" y="178" fill="#166534" font-size="9">Preview: (前 2000 字符) ...</text>
|
||||
<text x="532" y="202" fill="#16a34a" font-size="9" font-weight="600" text-anchor="middle">合计 18KB → 正常</text>
|
||||
|
||||
<!-- 原理说明 -->
|
||||
<rect x="20" y="214" width="680" height="64" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="35" y="234" fill="#1e3a5f" font-size="11" font-weight="600">怎么做</text>
|
||||
<text x="85" y="234" fill="#475569" font-size="10">1. 统计最后一轮所有 tool_result 的总大小</text>
|
||||
<text x="85" y="250" fill="#475569" font-size="10">2. 超过 200KB → 按大小排序,从最大的开始落盘到 .task_outputs/tool-results/</text>
|
||||
<text x="85" y="266" fill="#475569" font-size="10">3. 上下文里只留 <persisted-output> 标记 + 前 2000 字符预览</text>
|
||||
|
||||
<!-- 变化摘要 -->
|
||||
<rect x="20" y="290" width="680" height="36" rx="6" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="35" y="312" fill="#166534" font-size="11">结果:信息没丢(磁盘有完整数据),上下文从 510KB 降到 ~18KB,0 次 API 调用</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,57 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 300" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ca8a04"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="300" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">L2: microCompact — Old Result Placeholder Replacement</text>
|
||||
|
||||
<!-- Pain Point -->
|
||||
<rect x="20" y="54" width="680" height="36" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">Pain Point</text>
|
||||
<text x="110" y="70" fill="#991b1b" font-size="11">Agent read 10 files in a row; the full content of reads 1-7 is still sitting in context, taking space but no longer useful</text>
|
||||
|
||||
<!-- Before -->
|
||||
<text x="155" y="114" fill="#64748b" font-size="12" font-weight="600" text-anchor="middle">Before (all 10 tool_result complete)</text>
|
||||
<rect x="20" y="122" width="310" height="95" rx="6" fill="#fff" stroke="#94a3b8" stroke-width="1"/>
|
||||
<rect x="30" y="130" width="290" height="10" rx="2" fill="#e2e8f0"/>
|
||||
<text x="38" y="138" fill="#94a3b8" font-size="8" font-family="monospace">Read file A: (full content, 3200 chars)...</text>
|
||||
<rect x="30" y="145" width="290" height="10" rx="2" fill="#e2e8f0"/>
|
||||
<text x="38" y="153" fill="#94a3b8" font-size="8" font-family="monospace">Read file B: (full content, 1800 chars)...</text>
|
||||
<rect x="30" y="160" width="290" height="10" rx="2" fill="#e2e8f0"/>
|
||||
<text x="38" y="168" fill="#94a3b8" font-size="8" font-family="monospace">Read file C: (full content, 4500 chars)...</text>
|
||||
<rect x="30" y="175" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="38" y="183" fill="#92400e" font-size="8" font-family="monospace">Read file J: (full content, 2800 chars)</text>
|
||||
<text x="175" y="212" fill="#ef4444" font-size="9" font-weight="600">7 old results waste ~25K chars</text>
|
||||
|
||||
<!-- Arrow -->
|
||||
<line x1="335" y1="170" x2="375" y2="170" stroke="#ca8a04" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- After -->
|
||||
<text x="535" y="114" fill="#ca8a04" font-size="12" font-weight="600" text-anchor="middle">After (keep only latest 3 complete)</text>
|
||||
<rect x="390" y="122" width="310" height="95" rx="6" fill="#fefce8" stroke="#ca8a04" stroke-width="1"/>
|
||||
<rect x="400" y="130" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="138" fill="#92400e" font-size="8" font-family="monospace">[Earlier result compacted. Re-run if needed.]</text>
|
||||
<rect x="400" y="145" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="153" fill="#92400e" font-size="8" font-family="monospace">[Earlier result compacted. Re-run if needed.]</text>
|
||||
<rect x="400" y="160" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="168" fill="#92400e" font-size="8" font-family="monospace">[Earlier result compacted. Re-run if needed.]</text>
|
||||
<rect x="400" y="175" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="183" fill="#92400e" font-size="8" font-family="monospace">Read file J: (full content, 2800 chars)</text>
|
||||
<text x="545" y="212" fill="#ca8a04" font-size="9" font-weight="600">Keep only latest 3; first 7 become placeholders</text>
|
||||
|
||||
<!-- How -->
|
||||
<rect x="20" y="228" width="680" height="62" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="35" y="248" fill="#1e3a5f" font-size="11" font-weight="600">How (teaching version)</text>
|
||||
<text x="155" y="248" fill="#475569" font-size="10">Iterate through tool_result, keep only latest 3 complete, replace older ones with placeholders.</text>
|
||||
<text x="35" y="264" fill="#1e3a5f" font-size="11" font-weight="600">Real CC</text>
|
||||
<text x="95" y="264" fill="#475569" font-size="10">Clears old results via API cache_edits (without breaking prompt cache prefix), only for COMPACTABLE_TOOLS:</text>
|
||||
<text x="95" y="280" fill="#94a3b8" font-size="9">Read, Bash, Grep, Glob, WebSearch, WebFetch, Edit, Write. Teaching version uses text placeholders to simulate the same effect.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -0,0 +1,57 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 300" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ca8a04"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="300" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">L2: microCompact — 旧結果のプレースホルダー置換</text>
|
||||
|
||||
<!-- ペインポイント -->
|
||||
<rect x="20" y="54" width="680" height="36" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">ペインポイント</text>
|
||||
<text x="115" y="70" fill="#991b1b" font-size="11">Agent が連続で 10 ファイルを読み込み、1〜7 回目の完全なファイル内容がコンテキストに残ったまま、場所を占有しつつ既に不要</text>
|
||||
|
||||
<!-- 圧縮前 -->
|
||||
<text x="155" y="114" fill="#64748b" font-size="12" font-weight="600" text-anchor="middle">圧縮前(10 件の tool_result がすべて完全)</text>
|
||||
<rect x="20" y="122" width="310" height="95" rx="6" fill="#fff" stroke="#94a3b8" stroke-width="1"/>
|
||||
<rect x="30" y="130" width="290" height="10" rx="2" fill="#e2e8f0"/>
|
||||
<text x="38" y="138" fill="#94a3b8" font-size="8" font-family="monospace">Read file A: (完全な内容, 3200 文字)...</text>
|
||||
<rect x="30" y="145" width="290" height="10" rx="2" fill="#e2e8f0"/>
|
||||
<text x="38" y="153" fill="#94a3b8" font-size="8" font-family="monospace">Read file B: (完全な内容, 1800 文字)...</text>
|
||||
<rect x="30" y="160" width="290" height="10" rx="2" fill="#e2e8f0"/>
|
||||
<text x="38" y="168" fill="#94a3b8" font-size="8" font-family="monospace">Read file C: (完全な内容, 4500 文字)...</text>
|
||||
<rect x="30" y="175" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="38" y="183" fill="#92400e" font-size="8" font-family="monospace">Read file J: (完全な内容, 2800 文字)</text>
|
||||
<text x="175" y="212" fill="#ef4444" font-size="9" font-weight="600">7 件の旧結果が ~25K 文字を無駄に占有</text>
|
||||
|
||||
<!-- 矢印 -->
|
||||
<line x1="335" y1="170" x2="375" y2="170" stroke="#ca8a04" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- 圧縮後 -->
|
||||
<text x="535" y="114" fill="#ca8a04" font-size="12" font-weight="600" text-anchor="middle">圧縮後(最新 3 件のみ完全保持)</text>
|
||||
<rect x="390" y="122" width="310" height="95" rx="6" fill="#fefce8" stroke="#ca8a04" stroke-width="1"/>
|
||||
<rect x="400" y="130" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="138" fill="#92400e" font-size="8" font-family="monospace">[Earlier result compacted. Re-run if needed.]</text>
|
||||
<rect x="400" y="145" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="153" fill="#92400e" font-size="8" font-family="monospace">[Earlier result compacted. Re-run if needed.]</text>
|
||||
<rect x="400" y="160" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="168" fill="#92400e" font-size="8" font-family="monospace">[Earlier result compacted. Re-run if needed.]</text>
|
||||
<rect x="400" y="175" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="183" fill="#92400e" font-size="8" font-family="monospace">Read file J: (完全な内容, 2800 文字)</text>
|
||||
<text x="545" y="212" fill="#ca8a04" font-size="9" font-weight="600">最新 3 件のみ保持、前 7 件はプレースホルダー化</text>
|
||||
|
||||
<!-- 原理 -->
|
||||
<rect x="20" y="228" width="680" height="62" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="35" y="248" fill="#1e3a5f" font-size="11" font-weight="600">方法(教学版)</text>
|
||||
<text x="130" y="248" fill="#475569" font-size="10">tool_result を走査し、最新 3 件のみ完全保持、古いものはプレースホルダーに置換。</text>
|
||||
<text x="35" y="264" fill="#1e3a5f" font-size="11" font-weight="600">実際の CC</text>
|
||||
<text x="110" y="264" fill="#475569" font-size="10">API cache_edits で旧結果をクリア(prompt cache プレフィックスを破壊しない)、COMPACTABLE_TOOLS のみ対象:</text>
|
||||
<text x="110" y="280" fill="#94a3b8" font-size="9">Read, Bash, Grep, Glob, WebSearch, WebFetch, Edit, Write。教学版はテキストプレースホルダーで同様の効果を模擬。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
@@ -0,0 +1,57 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 300" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#2563eb"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ca8a04"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="300" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">L2: microCompact — 旧结果占位替换</text>
|
||||
|
||||
<!-- 痛点 -->
|
||||
<rect x="20" y="54" width="680" height="36" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">痛点</text>
|
||||
<text x="75" y="70" fill="#991b1b" font-size="11">Agent 连续读了 10 个文件,第 1-7 次的完整文件内容还躺在上下文里,占着位置但早就没用了</text>
|
||||
|
||||
<!-- Before -->
|
||||
<text x="155" y="114" fill="#64748b" font-size="12" font-weight="600" text-anchor="middle">压缩前(10 条 tool_result 全部完整)</text>
|
||||
<rect x="20" y="122" width="310" height="95" rx="6" fill="#fff" stroke="#94a3b8" stroke-width="1"/>
|
||||
<rect x="30" y="130" width="290" height="10" rx="2" fill="#e2e8f0"/>
|
||||
<text x="38" y="138" fill="#94a3b8" font-size="8" font-family="monospace">Read file A: (完整内容, 3200 字符)...</text>
|
||||
<rect x="30" y="145" width="290" height="10" rx="2" fill="#e2e8f0"/>
|
||||
<text x="38" y="153" fill="#94a3b8" font-size="8" font-family="monospace">Read file B: (完整内容, 1800 字符)...</text>
|
||||
<rect x="30" y="160" width="290" height="10" rx="2" fill="#e2e8f0"/>
|
||||
<text x="38" y="168" fill="#94a3b8" font-size="8" font-family="monospace">Read file C: (完整内容, 4500 字符)...</text>
|
||||
<rect x="30" y="175" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="38" y="183" fill="#92400e" font-size="8" font-family="monospace">Read file J: (完整内容, 2800 字符)</text>
|
||||
<text x="175" y="212" fill="#ef4444" font-size="9" font-weight="600">7 条旧结果白占 ~25K 字符</text>
|
||||
|
||||
<!-- Arrow -->
|
||||
<line x1="335" y1="170" x2="375" y2="170" stroke="#ca8a04" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- After -->
|
||||
<text x="535" y="114" fill="#ca8a04" font-size="12" font-weight="600" text-anchor="middle">压缩后(只保留最近 3 条完整)</text>
|
||||
<rect x="390" y="122" width="310" height="95" rx="6" fill="#fefce8" stroke="#ca8a04" stroke-width="1"/>
|
||||
<rect x="400" y="130" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="138" fill="#92400e" font-size="8" font-family="monospace">[Earlier result compacted. Re-run if needed.]</text>
|
||||
<rect x="400" y="145" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="153" fill="#92400e" font-size="8" font-family="monospace">[Earlier result compacted. Re-run if needed.]</text>
|
||||
<rect x="400" y="160" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="168" fill="#92400e" font-size="8" font-family="monospace">[Earlier result compacted. Re-run if needed.]</text>
|
||||
<rect x="400" y="175" width="290" height="10" rx="2" fill="#fef3c7"/>
|
||||
<text x="408" y="183" fill="#92400e" font-size="8" font-family="monospace">Read file J: (完整内容, 2800 字符)</text>
|
||||
<text x="545" y="212" fill="#ca8a04" font-size="9" font-weight="600">只保留最近 3 条,前 7 条变占位</text>
|
||||
|
||||
<!-- 原理 -->
|
||||
<rect x="20" y="228" width="680" height="62" rx="6" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
|
||||
<text x="35" y="248" fill="#1e3a5f" font-size="11" font-weight="600">怎么做(教学版)</text>
|
||||
<text x="115" y="248" fill="#475569" font-size="10">遍历 tool_result,只保留最近 3 条完整,更旧的替换为占位符。</text>
|
||||
<text x="35" y="264" fill="#1e3a5f" font-size="11" font-weight="600">真实 CC</text>
|
||||
<text x="95" y="264" fill="#475569" font-size="10">通过 API cache_edits 清除旧结果(不破坏 prompt cache 前缀),仅对 COMPACTABLE_TOOLS 生效:</text>
|
||||
<text x="95" y="280" fill="#94a3b8" font-size="9">Read, Bash, Grep, Glob, WebSearch, WebFetch, Edit, Write。教学版用文本占位模拟同样效果。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
104
web/public/course-assets/s09_memory/memory-overview.en.svg
Normal file
@@ -0,0 +1,104 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 430" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#7c3aed"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="430" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Memory — Memory loading, extraction, and consolidation on s08 compression pipeline</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s08 preserved</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#f3e8ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#7c3aed" font-size="10" font-weight="600">s09 new</text>
|
||||
|
||||
<!-- ===== messages[] ===== -->
|
||||
<rect x="30" y="96" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="80" y="126" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- arrow → compression -->
|
||||
<line x1="130" y1="122" x2="152" y2="122" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== Compression pipeline (s08) ===== -->
|
||||
<rect x="155" y="86" width="135" height="72" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="222" y="108" fill="#1e3a5f" font-size="11" font-weight="700" text-anchor="middle">Compression</text>
|
||||
<text x="222" y="124" fill="#64748b" font-size="9" text-anchor="middle">budget → snip → micro</text>
|
||||
<text x="222" y="138" fill="#64748b" font-size="9" text-anchor="middle">→ autoCompact</text>
|
||||
<text x="222" y="152" fill="#94a3b8" font-size="8" text-anchor="middle">(s08)</text>
|
||||
|
||||
<!-- arrow → Loading (purple) -->
|
||||
<line x1="290" y1="122" x2="317" y2="122" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- ===== Loading (s09) ===== -->
|
||||
<rect x="320" y="86" width="120" height="72" rx="8" fill="#f3e8ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="380" y="108" fill="#5b21b6" font-size="11" font-weight="700" text-anchor="middle">Loading</text>
|
||||
<text x="380" y="124" fill="#7c3aed" font-size="9" text-anchor="middle">LLM side-query select</text>
|
||||
<text x="380" y="138" fill="#7c3aed" font-size="9" text-anchor="middle">inject file contents</text>
|
||||
<text x="380" y="152" fill="#a78bfa" font-size="8" text-anchor="middle">≤ 5 items</text>
|
||||
|
||||
<!-- arrow → LLM -->
|
||||
<line x1="440" y1="122" x2="472" y2="122" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== LLM (s08) ===== -->
|
||||
<rect x="475" y="96" width="80" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="515" y="114" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="515" y="132" fill="#64748b" font-size="9" text-anchor="middle">stop_reason</text>
|
||||
<text x="515" y="144" fill="#64748b" font-size="9" text-anchor="middle">=tool_use?</text>
|
||||
|
||||
<!-- LLM → no → return result -->
|
||||
<line x1="515" y1="148" x2="515" y2="178" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="528" y="168" fill="#16a34a" font-size="9" font-weight="600">no, stop</text>
|
||||
<rect x="460" y="180" width="110" height="24" rx="12" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="515" y="196" fill="#166534" font-size="10" font-weight="600" text-anchor="middle">return result</text>
|
||||
|
||||
<!-- LLM → yes → TOOL_HANDLERS -->
|
||||
<line x1="555" y1="122" x2="587" y2="122" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="568" y="114" fill="#64748b" font-size="9" font-weight="600">yes</text>
|
||||
|
||||
<!-- ===== TOOL_HANDLERS (s08) ===== -->
|
||||
<rect x="590" y="88" width="130" height="68" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="655" y="112" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="655" y="128" fill="#64748b" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
<text x="655" y="142" fill="#94a3b8" font-size="8" text-anchor="middle">edit · glob · task</text>
|
||||
|
||||
<!-- ===== Memory Files (s09) ===== -->
|
||||
<rect x="155" y="232" width="430" height="36" rx="6" fill="#faf5ff" stroke="#7c3aed" stroke-width="1.5" stroke-dasharray="4,2"/>
|
||||
<text x="370" y="255" fill="#5b21b6" font-size="11" font-weight="600" text-anchor="middle">.memory/ — MEMORY.md index + *.md files (cross-session persistent)</text>
|
||||
|
||||
<!-- Arrow: Memory Files → Loading -->
|
||||
<path d="M 395 232 L 395 162" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
<text x="408" y="200" fill="#7c3aed" font-size="9">read</text>
|
||||
|
||||
<!-- Arrow: return result → Extraction → Memory Files -->
|
||||
<path d="M 515 204 L 515 232" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
<text x="528" y="222" fill="#7c3aed" font-size="9">Extraction (after each turn)</text>
|
||||
|
||||
<!-- Consolidation note -->
|
||||
<text x="222" y="284" fill="#a78bfa" font-size="9">Consolidation: triggers at ≥ 10 files, dedup·merge·prune</text>
|
||||
|
||||
<!-- ===== Loop back ===== -->
|
||||
<path d="M 720 122 L 748 122 Q 756 122 756 130 L 756 310 Q 756 318 748 318 L 88 318 Q 80 318 80 310 L 80 148" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="400" y="340" fill="#64748b" font-size="10" text-anchor="middle">tool results → messages[] → compress → load memories → LLM → extract after each turn</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="358" width="680" height="56" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="372" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="80" y="382" fill="#475569" font-size="10">s08 preserved: compression pipeline (budget → snip → micro → auto) + emergency trim + loop</text>
|
||||
<rect x="60" y="392" width="12" height="10" rx="2" fill="#f3e8ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="80" y="402" fill="#475569" font-size="10">s09 new: Loading (index in SYSTEM + on-demand inject) + Extraction (after each turn) + Consolidation (threshold)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.0 KiB |
104
web/public/course-assets/s09_memory/memory-overview.ja.svg
Normal file
@@ -0,0 +1,104 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 430" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#7c3aed"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="430" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Memory — s08 圧縮パイプラインに記憶の読み込み・抽出・整理を挿入</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s08 維持</text>
|
||||
<rect x="130" y="56" width="12" height="10" rx="2" fill="#f3e8ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="148" y="66" fill="#7c3aed" font-size="10" font-weight="600">s09 追加</text>
|
||||
|
||||
<!-- ===== messages[] ===== -->
|
||||
<rect x="30" y="96" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="80" y="126" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- arrow → compression -->
|
||||
<line x1="130" y1="122" x2="152" y2="122" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== Compression pipeline (s08) ===== -->
|
||||
<rect x="155" y="86" width="135" height="72" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="222" y="108" fill="#1e3a5f" font-size="11" font-weight="700" text-anchor="middle">圧縮パイプライン</text>
|
||||
<text x="222" y="124" fill="#64748b" font-size="9" text-anchor="middle">budget → snip → micro</text>
|
||||
<text x="222" y="138" fill="#64748b" font-size="9" text-anchor="middle">→ autoCompact</text>
|
||||
<text x="222" y="152" fill="#94a3b8" font-size="8" text-anchor="middle">(s08)</text>
|
||||
|
||||
<!-- arrow → Loading (purple) -->
|
||||
<line x1="290" y1="122" x2="317" y2="122" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- ===== Loading (s09) ===== -->
|
||||
<rect x="320" y="86" width="120" height="72" rx="8" fill="#f3e8ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="380" y="108" fill="#5b21b6" font-size="11" font-weight="700" text-anchor="middle">Loading</text>
|
||||
<text x="380" y="124" fill="#7c3aed" font-size="9" text-anchor="middle">LLM side-query 選択</text>
|
||||
<text x="380" y="138" fill="#7c3aed" font-size="9" text-anchor="middle">ファイル内容を注入</text>
|
||||
<text x="380" y="152" fill="#a78bfa" font-size="8" text-anchor="middle">≤ 5 件</text>
|
||||
|
||||
<!-- arrow → LLM -->
|
||||
<line x1="440" y1="122" x2="472" y2="122" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== LLM (s08) ===== -->
|
||||
<rect x="475" y="96" width="80" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="515" y="114" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="515" y="132" fill="#64748b" font-size="9" text-anchor="middle">stop_reason</text>
|
||||
<text x="515" y="144" fill="#64748b" font-size="9" text-anchor="middle">=tool_use?</text>
|
||||
|
||||
<!-- LLM → no → return result -->
|
||||
<line x1="515" y1="148" x2="515" y2="178" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="528" y="168" fill="#16a34a" font-size="9" font-weight="600">なし、停止</text>
|
||||
<rect x="460" y="180" width="110" height="24" rx="12" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="515" y="196" fill="#166534" font-size="10" font-weight="600" text-anchor="middle">結果を返す</text>
|
||||
|
||||
<!-- LLM → yes → TOOL_HANDLERS -->
|
||||
<line x1="555" y1="122" x2="587" y2="122" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="568" y="114" fill="#64748b" font-size="9" font-weight="600">あり</text>
|
||||
|
||||
<!-- ===== TOOL_HANDLERS (s08) ===== -->
|
||||
<rect x="590" y="88" width="130" height="68" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="655" y="112" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="655" y="128" fill="#64748b" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
<text x="655" y="142" fill="#94a3b8" font-size="8" text-anchor="middle">edit · glob · task</text>
|
||||
|
||||
<!-- ===== Memory Files (s09) ===== -->
|
||||
<rect x="155" y="232" width="430" height="36" rx="6" fill="#faf5ff" stroke="#7c3aed" stroke-width="1.5" stroke-dasharray="4,2"/>
|
||||
<text x="370" y="255" fill="#5b21b6" font-size="11" font-weight="600" text-anchor="middle">.memory/ — MEMORY.md インデックス + *.md ファイル(セッション間永続化)</text>
|
||||
|
||||
<!-- Arrow: Memory Files → Loading -->
|
||||
<path d="M 395 232 L 395 162" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
<text x="408" y="200" fill="#7c3aed" font-size="9">読み込み</text>
|
||||
|
||||
<!-- Arrow: return result → Extraction → Memory Files -->
|
||||
<path d="M 515 204 L 515 232" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
<text x="528" y="222" fill="#7c3aed" font-size="9">Extraction(毎ターン終了後)</text>
|
||||
|
||||
<!-- Consolidation note -->
|
||||
<text x="222" y="284" fill="#a78bfa" font-size="9">Consolidation: ファイル ≥ 10 でトリガー、重複排除・統合・剪定</text>
|
||||
|
||||
<!-- ===== Loop back ===== -->
|
||||
<path d="M 720 122 L 748 122 Q 756 122 756 130 L 756 310 Q 756 318 748 318 L 88 318 Q 80 318 80 310 L 80 148" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="400" y="340" fill="#64748b" font-size="10" text-anchor="middle">ツール結果 → messages[] → 圧縮 → 記憶読み込み → LLM → 毎ターン終了後に抽出</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="358" width="680" height="56" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="372" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="80" y="382" fill="#475569" font-size="10">s08 維持:圧縮パイプライン(budget → snip → micro → auto)+ 緊急トリム + ループ</text>
|
||||
<rect x="60" y="392" width="12" height="10" rx="2" fill="#f3e8ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="80" y="402" fill="#475569" font-size="10">s09 追加:Loading(インデックス常駐 + オンデマンド注入)+ Extraction(毎ターン終了後)+ Consolidation(閾値トリガー)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.2 KiB |
104
web/public/course-assets/s09_memory/memory-overview.svg
Normal file
@@ -0,0 +1,104 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 430" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#7c3aed"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="430" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Memory — 在 s08 压缩管线上,插入记忆加载、提取与整理</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s08 保留</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#f3e8ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#7c3aed" font-size="10" font-weight="600">s09 新增</text>
|
||||
|
||||
<!-- ===== messages[] ===== -->
|
||||
<rect x="30" y="96" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="80" y="126" fill="#1e3a5f" font-size="12" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- arrow → compression -->
|
||||
<line x1="130" y1="122" x2="152" y2="122" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== Compression pipeline (s08) ===== -->
|
||||
<rect x="155" y="86" width="135" height="72" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="222" y="108" fill="#1e3a5f" font-size="11" font-weight="700" text-anchor="middle">压缩管线</text>
|
||||
<text x="222" y="124" fill="#64748b" font-size="9" text-anchor="middle">budget → snip → micro</text>
|
||||
<text x="222" y="138" fill="#64748b" font-size="9" text-anchor="middle">→ autoCompact</text>
|
||||
<text x="222" y="152" fill="#94a3b8" font-size="8" text-anchor="middle">(s08)</text>
|
||||
|
||||
<!-- arrow → Loading (purple) -->
|
||||
<line x1="290" y1="122" x2="317" y2="122" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- ===== Loading (s09) ===== -->
|
||||
<rect x="320" y="86" width="120" height="72" rx="8" fill="#f3e8ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="380" y="108" fill="#5b21b6" font-size="11" font-weight="700" text-anchor="middle">Loading</text>
|
||||
<text x="380" y="124" fill="#7c3aed" font-size="9" text-anchor="middle">LLM side-query 选文件</text>
|
||||
<text x="380" y="138" fill="#7c3aed" font-size="9" text-anchor="middle">注入文件内容</text>
|
||||
<text x="380" y="152" fill="#a78bfa" font-size="8" text-anchor="middle">≤ 5 条</text>
|
||||
|
||||
<!-- arrow → LLM -->
|
||||
<line x1="440" y1="122" x2="472" y2="122" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ===== LLM (s08) ===== -->
|
||||
<rect x="475" y="96" width="80" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="515" y="114" fill="#1e3a5f" font-size="14" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="515" y="132" fill="#64748b" font-size="9" text-anchor="middle">stop_reason</text>
|
||||
<text x="515" y="144" fill="#64748b" font-size="9" text-anchor="middle">=tool_use?</text>
|
||||
|
||||
<!-- LLM → 否 → 返回结果 -->
|
||||
<line x1="515" y1="148" x2="515" y2="178" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="528" y="168" fill="#16a34a" font-size="9" font-weight="600">否,停止</text>
|
||||
<rect x="460" y="180" width="110" height="24" rx="12" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="515" y="196" fill="#166534" font-size="10" font-weight="600" text-anchor="middle">返回结果</text>
|
||||
|
||||
<!-- LLM → 是 → TOOL_HANDLERS -->
|
||||
<line x1="555" y1="122" x2="587" y2="122" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="568" y="114" fill="#64748b" font-size="9" font-weight="600">是</text>
|
||||
|
||||
<!-- ===== TOOL_HANDLERS (s08) ===== -->
|
||||
<rect x="590" y="88" width="130" height="68" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="655" y="112" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="655" y="128" fill="#64748b" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
<text x="655" y="142" fill="#94a3b8" font-size="8" text-anchor="middle">edit · glob · task</text>
|
||||
|
||||
<!-- ===== Memory Files (s09) ===== -->
|
||||
<rect x="155" y="232" width="430" height="36" rx="6" fill="#faf5ff" stroke="#7c3aed" stroke-width="1.5" stroke-dasharray="4,2"/>
|
||||
<text x="370" y="255" fill="#5b21b6" font-size="11" font-weight="600" text-anchor="middle">.memory/ — MEMORY.md 索引 + *.md 文件(跨会话持久化)</text>
|
||||
|
||||
<!-- Arrow: Memory Files → Loading -->
|
||||
<path d="M 395 232 L 395 162" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
<text x="408" y="200" fill="#7c3aed" font-size="9">读取</text>
|
||||
|
||||
<!-- Arrow: 返回结果 → Extraction → Memory Files -->
|
||||
<path d="M 515 204 L 515 232" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
<text x="528" y="222" fill="#7c3aed" font-size="9">Extraction(每轮结束后)</text>
|
||||
|
||||
<!-- Consolidation note -->
|
||||
<text x="222" y="284" fill="#a78bfa" font-size="9">Consolidation: 文件数 ≥ 10 时触发,去重·合并·剪枝</text>
|
||||
|
||||
<!-- ===== Loop back ===== -->
|
||||
<path d="M 720 122 L 748 122 Q 756 122 756 130 L 756 310 Q 756 318 748 318 L 88 318 Q 80 318 80 310 L 80 148" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="400" y="340" fill="#64748b" font-size="10" text-anchor="middle">工具结果追加到 messages[] → 压缩 → 加载记忆 → LLM → 每轮结束后提取</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="358" width="680" height="56" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="372" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="80" y="382" fill="#475569" font-size="10">s08 保留:压缩管线(budget → snip → micro → auto)+ 应急裁剪 + 循环</text>
|
||||
<rect x="60" y="392" width="12" height="10" rx="2" fill="#f3e8ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="80" y="402" fill="#475569" font-size="10">s09 新增:Loading(索引常驻 + 按需注入)+ Extraction(每轮结束后)+ Consolidation(阈值触发)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.0 KiB |
78
web/public/course-assets/s09_memory/memory-subsystems.en.svg
Normal file
@@ -0,0 +1,78 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 380" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#7c3aed"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="380" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Memory System — Store · Load · Extract · Consolidate</text>
|
||||
|
||||
<!-- Storage -->
|
||||
<rect x="40" y="58" width="145" height="80" rx="8" fill="#ede9fe" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="112" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">Storage</text>
|
||||
<line x1="55" y1="90" x2="170" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="55" y="108" fill="#5b21b6" font-size="10">.memory/*.md files</text>
|
||||
<text x="55" y="124" fill="#5b21b6" font-size="10">MEMORY.md index</text>
|
||||
|
||||
<line x1="190" y1="98" x2="218" y2="98" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Loading -->
|
||||
<rect x="222" y="58" width="200" height="80" rx="8" fill="#ede9fe" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="322" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">Load</text>
|
||||
<line x1="237" y1="90" x2="407" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="237" y="108" fill="#5b21b6" font-size="10">Index in SYSTEM (always)</text>
|
||||
<text x="237" y="124" fill="#5b21b6" font-size="10">LLM side-query select files</text>
|
||||
<text x="237" y="134" fill="#a78bfa" font-size="9">≤ 5 items, fallback to keyword</text>
|
||||
|
||||
<line x1="425" y1="98" x2="453" y2="98" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Extraction -->
|
||||
<rect x="457" y="58" width="130" height="80" rx="8" fill="#f3e8ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="522" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">Extract</text>
|
||||
<line x1="472" y1="90" x2="572" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="472" y="108" fill="#5b21b6" font-size="10">After each turn ends</text>
|
||||
<text x="472" y="124" fill="#5b21b6" font-size="10">LLM extracts prefs/constraints</text>
|
||||
<text x="472" y="134" fill="#a78bfa" font-size="9">Check existing, avoid duplicates</text>
|
||||
|
||||
<!-- Consolidation -->
|
||||
<rect x="600" y="58" width="100" height="80" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="650" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">Consolidate</text>
|
||||
<line x1="615" y1="90" x2="685" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="615" y="108" fill="#5b21b6" font-size="10">Triggers at ≥ 10 files</text>
|
||||
<text x="615" y="124" fill="#5b21b6" font-size="10">Dedup · merge · prune</text>
|
||||
<text x="615" y="134" fill="#a78bfa" font-size="9">CC: 3-layer gating</text>
|
||||
|
||||
<!-- Memory Files -->
|
||||
<rect x="40" y="180" width="660" height="36" rx="6" fill="#f8fafc" stroke="#94a3b8" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="370" y="203" fill="#475569" font-size="11" text-anchor="middle">.memory/ — MEMORY.md index + *.md files (YAML frontmatter: name / description / type)</text>
|
||||
|
||||
<!-- Arrow: Storage → Memory Files -->
|
||||
<path d="M 112 138 L 112 174 Q 112 180 118 180" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="120" y="162" fill="#7c3aed" font-size="9">read/write</text>
|
||||
|
||||
<!-- Arrow: Extraction → Memory Files -->
|
||||
<path d="M 522 138 L 522 180" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="536" y="164" fill="#7c3aed" font-size="9">write</text>
|
||||
|
||||
<!-- Arrow: Consolidation → Memory Files -->
|
||||
<path d="M 650 138 L 650 180" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="662" y="164" fill="#7c3aed" font-size="9">overwrite</text>
|
||||
|
||||
<!-- Four types -->
|
||||
<rect x="40" y="240" width="660" height="40" rx="6" fill="#faf5ff" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="60" y="260" fill="#5b21b6" font-size="10" font-weight="600">Four types:</text>
|
||||
<text x="140" y="260" fill="#475569" font-size="10">user (who you are) · feedback (how to work) · project (what's happening) · reference (where to find things)</text>
|
||||
|
||||
<!-- CC source comparison -->
|
||||
<rect x="40" y="296" width="660" height="72" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="316" fill="#5b21b6" font-size="11" font-weight="600">CC Source Comparison</text>
|
||||
<text x="60" y="334" fill="#475569" font-size="10">• Selection: LLM side-query (Sonnet selects), not embedding vector similarity</text>
|
||||
<text x="60" y="350" fill="#475569" font-size="10">• Extraction timing: stop hook (after each turn ends), not after autoCompact</text>
|
||||
<text x="60" y="366" fill="#475569" font-size="10">• Dream consolidation: 3-layer gating (time ≥ 24h + sessions ≥ 5 + file lock), not simple count</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
78
web/public/course-assets/s09_memory/memory-subsystems.ja.svg
Normal file
@@ -0,0 +1,78 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 380" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#7c3aed"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="380" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Memory System — ストレージ · 読み込み · 抽出 · 整理</text>
|
||||
|
||||
<!-- ストレージ -->
|
||||
<rect x="40" y="58" width="145" height="80" rx="8" fill="#ede9fe" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="112" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">ストレージ</text>
|
||||
<line x1="55" y1="90" x2="170" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="55" y="108" fill="#5b21b6" font-size="10">.memory/*.md ファイル</text>
|
||||
<text x="55" y="124" fill="#5b21b6" font-size="10">MEMORY.md インデックス</text>
|
||||
|
||||
<line x1="190" y1="98" x2="218" y2="98" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- 読み込み -->
|
||||
<rect x="222" y="58" width="200" height="80" rx="8" fill="#ede9fe" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="322" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">読み込み</text>
|
||||
<line x1="237" y1="90" x2="407" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="237" y="108" fill="#5b21b6" font-size="10">インデックスを SYSTEM に常駐</text>
|
||||
<text x="237" y="124" fill="#5b21b6" font-size="10">LLM side-query でファイル選択</text>
|
||||
<text x="237" y="134" fill="#a78bfa" font-size="9">≤ 5 件、失敗時はキーワードに降格</text>
|
||||
|
||||
<line x1="425" y1="98" x2="453" y2="98" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- 抽出 -->
|
||||
<rect x="457" y="58" width="130" height="80" rx="8" fill="#f3e8ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="522" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">抽出</text>
|
||||
<line x1="472" y1="90" x2="572" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="472" y="108" fill="#5b21b6" font-size="10">毎ターン終了後にトリガー</text>
|
||||
<text x="472" y="124" fill="#5b21b6" font-size="10">LLM が好み/制約を抽出</text>
|
||||
<text x="472" y="134" fill="#a78bfa" font-size="9">既存を確認、重複回避</text>
|
||||
|
||||
<!-- 整理 -->
|
||||
<rect x="600" y="58" width="100" height="80" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="650" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">整理</text>
|
||||
<line x1="615" y1="90" x2="685" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="615" y="108" fill="#5b21b6" font-size="10">ファイル ≥ 10 でトリガー</text>
|
||||
<text x="615" y="124" fill="#5b21b6" font-size="10">重複排除・統合・剪定</text>
|
||||
<text x="615" y="134" fill="#a78bfa" font-size="9">CC: 3 層ゲート</text>
|
||||
|
||||
<!-- Memory Files -->
|
||||
<rect x="40" y="180" width="660" height="36" rx="6" fill="#f8fafc" stroke="#94a3b8" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="370" y="203" fill="#475569" font-size="11" text-anchor="middle">.memory/ — MEMORY.md インデックス + *.md ファイル(YAML frontmatter: name / description / type)</text>
|
||||
|
||||
<!-- Arrow: ストレージ → Memory Files -->
|
||||
<path d="M 112 138 L 112 174 Q 112 180 118 180" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="120" y="162" fill="#7c3aed" font-size="9">読み/書き</text>
|
||||
|
||||
<!-- Arrow: 抽出 → Memory Files -->
|
||||
<path d="M 522 138 L 522 180" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="536" y="164" fill="#7c3aed" font-size="9">書き込み</text>
|
||||
|
||||
<!-- Arrow: 整理 → Memory Files -->
|
||||
<path d="M 650 138 L 650 180" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="662" y="164" fill="#7c3aed" font-size="9">上書き</text>
|
||||
|
||||
<!-- 4 種類の記憶 -->
|
||||
<rect x="40" y="240" width="660" height="40" rx="6" fill="#faf5ff" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="60" y="260" fill="#5b21b6" font-size="10" font-weight="600">4 種類の記憶:</text>
|
||||
<text x="148" y="260" fill="#475569" font-size="10">user(あなたは誰か)· feedback(どう作業するか)· project(何が起きているか)· reference(どこで探すか)</text>
|
||||
|
||||
<!-- CC ソースコード対照 -->
|
||||
<rect x="40" y="296" width="660" height="72" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="316" fill="#5b21b6" font-size="11" font-weight="600">CC ソースコード対照</text>
|
||||
<text x="60" y="334" fill="#475569" font-size="10">• 記憶選択:LLM side-query(Sonnet が選択)、embedding ベクトル類似度ではない</text>
|
||||
<text x="60" y="350" fill="#475569" font-size="10">• 抽出タイミング:stop hook(毎ターン終了後)、autoCompact 後ではない</text>
|
||||
<text x="60" y="366" fill="#475569" font-size="10">• Dream 整理:3 層ゲート(時間 ≥ 24h + セッション ≥ 5 + ファイルロック)、単純な計数ではない</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
78
web/public/course-assets/s09_memory/memory-subsystems.svg
Normal file
@@ -0,0 +1,78 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 380" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#7c3aed"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="380" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Memory System — 存储 · 加载 · 提取 · 整理</text>
|
||||
|
||||
<!-- 存储 -->
|
||||
<rect x="40" y="58" width="145" height="80" rx="8" fill="#ede9fe" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="112" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">存储</text>
|
||||
<line x1="55" y1="90" x2="170" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="55" y="108" fill="#5b21b6" font-size="10">.memory/*.md 文件</text>
|
||||
<text x="55" y="124" fill="#5b21b6" font-size="10">MEMORY.md 索引</text>
|
||||
|
||||
<line x1="190" y1="98" x2="218" y2="98" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- 加载 -->
|
||||
<rect x="222" y="58" width="200" height="80" rx="8" fill="#ede9fe" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="322" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">加载</text>
|
||||
<line x1="237" y1="90" x2="407" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="237" y="108" fill="#5b21b6" font-size="10">索引常驻 SYSTEM</text>
|
||||
<text x="237" y="124" fill="#5b21b6" font-size="10">LLM side-query 选文件</text>
|
||||
<text x="237" y="134" fill="#a78bfa" font-size="9">≤ 5 条,失败降级到关键词</text>
|
||||
|
||||
<line x1="425" y1="98" x2="453" y2="98" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- 提取 -->
|
||||
<rect x="457" y="58" width="130" height="80" rx="8" fill="#f3e8ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="522" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">提取</text>
|
||||
<line x1="472" y1="90" x2="572" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="472" y="108" fill="#5b21b6" font-size="10">每轮结束后触发</text>
|
||||
<text x="472" y="124" fill="#5b21b6" font-size="10">LLM 提取偏好/约束</text>
|
||||
<text x="472" y="134" fill="#a78bfa" font-size="9">检查已有,避免重复</text>
|
||||
|
||||
<!-- 整理 -->
|
||||
<rect x="600" y="58" width="100" height="80" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="650" y="80" fill="#5b21b6" font-size="13" font-weight="700" text-anchor="middle">整理</text>
|
||||
<line x1="615" y1="90" x2="685" y2="90" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="615" y="108" fill="#5b21b6" font-size="10">文件 ≥ 10 触发</text>
|
||||
<text x="615" y="124" fill="#5b21b6" font-size="10">去重·合并·剪枝</text>
|
||||
<text x="615" y="134" fill="#a78bfa" font-size="9">CC: 三层门控</text>
|
||||
|
||||
<!-- Memory Files -->
|
||||
<rect x="40" y="180" width="660" height="36" rx="6" fill="#f8fafc" stroke="#94a3b8" stroke-width="1" stroke-dasharray="4,2"/>
|
||||
<text x="370" y="203" fill="#475569" font-size="11" text-anchor="middle">.memory/ — MEMORY.md 索引 + *.md 文件(YAML frontmatter: name / description / type)</text>
|
||||
|
||||
<!-- Arrow: 存储 → Memory Files -->
|
||||
<path d="M 112 138 L 112 174 Q 112 180 118 180" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="120" y="162" fill="#7c3aed" font-size="9">写入/读取</text>
|
||||
|
||||
<!-- Arrow: Extraction → Memory Files -->
|
||||
<path d="M 522 138 L 522 180" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="536" y="164" fill="#7c3aed" font-size="9">写入</text>
|
||||
|
||||
<!-- Arrow: 整理 → Memory Files -->
|
||||
<path d="M 650 138 L 650 180" fill="none" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="662" y="164" fill="#7c3aed" font-size="9">覆写</text>
|
||||
|
||||
<!-- 四类记忆 -->
|
||||
<rect x="40" y="240" width="660" height="40" rx="6" fill="#faf5ff" stroke="#c4b5fd" stroke-width="0.5"/>
|
||||
<text x="60" y="260" fill="#5b21b6" font-size="10" font-weight="600">四类记忆:</text>
|
||||
<text x="140" y="260" fill="#475569" font-size="10">user(你是谁)· feedback(怎么做事)· project(正在发生什么)· reference(东西在哪找)</text>
|
||||
|
||||
<!-- CC 源码对照 -->
|
||||
<rect x="40" y="296" width="660" height="72" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="316" fill="#5b21b6" font-size="11" font-weight="600">CC 源码对照</text>
|
||||
<text x="60" y="334" fill="#475569" font-size="10">• 记忆选择:LLM side-query(Sonnet 选),不是 embedding 向量相似度</text>
|
||||
<text x="60" y="350" fill="#475569" font-size="10">• 提取时机:stop hook 中触发(每轮结束后),不是 autoCompact 后</text>
|
||||
<text x="60" y="366" fill="#475569" font-size="10">• Dream 整理:三层门控(时间 ≥ 24h + 会话 ≥ 5 + 文件锁),不是简单计数</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
@@ -0,0 +1,107 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 420" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#059669"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#059669"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="420" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">System Prompt — PROMPT_SECTIONS + On-Demand Assembly + Cache</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s09 Preserved</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#059669" font-size="10" font-weight="600">s10 New</text>
|
||||
|
||||
<!-- ===== Prompt Assembly (green, s10) ===== -->
|
||||
|
||||
<!-- PROMPT_SECTIONS -->
|
||||
<rect x="40" y="82" width="170" height="88" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="125" y="100" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">PROMPT_SECTIONS</text>
|
||||
<text x="55" y="116" fill="#065f46" font-size="9">✓ identity (always)</text>
|
||||
<text x="55" y="130" fill="#065f46" font-size="9">✓ tools (always)</text>
|
||||
<text x="55" y="144" fill="#065f46" font-size="9">✓ workspace (always)</text>
|
||||
<text x="55" y="158" fill="#6b7280" font-size="9">○ memory</text>
|
||||
|
||||
<!-- arrow → assemble -->
|
||||
<line x1="210" y1="126" x2="235" y2="126" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
|
||||
<!-- assemble_system_prompt -->
|
||||
<rect x="238" y="82" width="170" height="88" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="323" y="100" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">assemble_system_prompt</text>
|
||||
<text x="253" y="118" fill="#065f46" font-size="9">Input: context dict</text>
|
||||
<text x="253" y="132" fill="#065f46" font-size="9">Always: identity + tools + workspace</text>
|
||||
<text x="253" y="146" fill="#065f46" font-size="9">On-demand: memory</text>
|
||||
<text x="253" y="160" fill="#6b7280" font-size="9">Output: "\n\n".join(selected)</text>
|
||||
|
||||
<!-- arrow → cache -->
|
||||
<line x1="408" y1="126" x2="433" y2="126" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
|
||||
<!-- get_system_prompt -->
|
||||
<rect x="436" y="82" width="170" height="88" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="521" y="100" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">get_system_prompt</text>
|
||||
<text x="451" y="118" fill="#065f46" font-size="9">json.dumps(context)</text>
|
||||
<text x="451" y="132" fill="#065f46" font-size="9">Hit → return cached</text>
|
||||
<text x="451" y="146" fill="#065f46" font-size="9">Miss → assemble + store</text>
|
||||
<text x="451" y="160" fill="#6b7280" font-size="9">(s10 new)</text>
|
||||
|
||||
<!-- Arrow: cache → LLM -->
|
||||
<path d="M 521 170 L 521 195 L 410 195 L 410 212" fill="none" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="462" y="189" fill="#059669" font-size="9">system=get_system_prompt(context)</text>
|
||||
|
||||
<!-- ===== s09 Agent Loop (blue) ===== -->
|
||||
|
||||
<!-- messages[] -->
|
||||
<rect x="30" y="214" width="100" height="46" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="80" y="241" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- arrow → compression+loading -->
|
||||
<line x1="130" y1="237" x2="155" y2="237" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- compression + loading -->
|
||||
<rect x="158" y="206" width="170" height="62" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="243" y="228" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">Compression + Loading</text>
|
||||
<text x="243" y="242" fill="#64748b" font-size="9" text-anchor="middle">snip → micro → budget → auto</text>
|
||||
<text x="243" y="256" fill="#94a3b8" font-size="8" text-anchor="middle">→ load memory (s09)</text>
|
||||
|
||||
<!-- arrow → LLM -->
|
||||
<line x1="328" y1="237" x2="358" y2="237" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="360" y="214" width="100" height="46" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="410" y="231" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="410" y="246" fill="#64748b" font-size="8" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
<text x="410" y="258" fill="#059669" font-size="8" text-anchor="middle">system assembled</text>
|
||||
|
||||
<!-- arrow → TOOLS -->
|
||||
<line x1="460" y1="237" x2="490" y2="237" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="466" y="229" fill="#64748b" font-size="8">yes</text>
|
||||
|
||||
<!-- TOOL_HANDLERS -->
|
||||
<rect x="493" y="206" width="130" height="62" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="558" y="228" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="558" y="242" fill="#64748b" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
<text x="558" y="256" fill="#94a3b8" font-size="8" text-anchor="middle">(s09 preserved)</text>
|
||||
|
||||
<!-- ===== Loop back ===== -->
|
||||
<path d="M 623 237 L 660 237 L 660 312 L 80 312 L 80 260" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="370" y="328" fill="#64748b" font-size="10" text-anchor="middle">Tool results → messages[] → compress → load memory → assemble prompt → LLM</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="350" width="680" height="56" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="362" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="80" y="372" fill="#475569" font-size="10">s09 Preserved: loop, compression pipeline, memory loading, tool execution</text>
|
||||
<rect x="60" y="382" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="80" y="392" fill="#475569" font-size="10">s10 New: PROMPT_SECTIONS (4 sections) + assemble_system_prompt + get_system_prompt (cache)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
@@ -0,0 +1,107 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 420" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#059669"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#059669"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="420" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">System Prompt — PROMPT_SECTIONS + オンデマンド組み立て + キャッシュ</text>
|
||||
|
||||
<!-- 凡例 -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s09 保持</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#059669" font-size="10" font-weight="600">s10 新規</text>
|
||||
|
||||
<!-- ===== プロンプトアセンブリ(緑、s10) ===== -->
|
||||
|
||||
<!-- PROMPT_SECTIONS -->
|
||||
<rect x="40" y="82" width="170" height="88" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="125" y="100" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">PROMPT_SECTIONS</text>
|
||||
<text x="55" y="116" fill="#065f46" font-size="9">✓ identity (常時)</text>
|
||||
<text x="55" y="130" fill="#065f46" font-size="9">✓ tools (常時)</text>
|
||||
<text x="55" y="144" fill="#065f46" font-size="9">✓ workspace (常時)</text>
|
||||
<text x="55" y="158" fill="#6b7280" font-size="9">○ memory</text>
|
||||
|
||||
<!-- 矢印 → assemble -->
|
||||
<line x1="210" y1="126" x2="235" y2="126" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
|
||||
<!-- assemble_system_prompt -->
|
||||
<rect x="238" y="82" width="170" height="88" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="323" y="100" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">assemble_system_prompt</text>
|
||||
<text x="253" y="118" fill="#065f46" font-size="9">入力: context dict</text>
|
||||
<text x="253" y="132" fill="#065f46" font-size="9">常時: identity + tools + workspace</text>
|
||||
<text x="253" y="146" fill="#065f46" font-size="9">オンデマンド: memory</text>
|
||||
<text x="253" y="160" fill="#6b7280" font-size="9">出力: "\n\n".join(selected)</text>
|
||||
|
||||
<!-- 矢印 → cache -->
|
||||
<line x1="408" y1="126" x2="433" y2="126" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
|
||||
<!-- get_system_prompt -->
|
||||
<rect x="436" y="82" width="170" height="88" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="521" y="100" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">get_system_prompt</text>
|
||||
<text x="451" y="118" fill="#065f46" font-size="9">json.dumps(context)</text>
|
||||
<text x="451" y="132" fill="#065f46" font-size="9">ヒット → キャッシュ返却</text>
|
||||
<text x="451" y="146" fill="#065f46" font-size="9">ミス → assemble + 保存</text>
|
||||
<text x="451" y="160" fill="#6b7280" font-size="9">(s10 新規)</text>
|
||||
|
||||
<!-- 矢印: cache → LLM -->
|
||||
<path d="M 521 170 L 521 195 L 410 195 L 410 212" fill="none" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="462" y="189" fill="#059669" font-size="9">system=get_system_prompt(context)</text>
|
||||
|
||||
<!-- ===== s09 Agent Loop(青) ===== -->
|
||||
|
||||
<!-- messages[] -->
|
||||
<rect x="30" y="214" width="100" height="46" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="80" y="241" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- 矢印 → compression+loading -->
|
||||
<line x1="130" y1="237" x2="155" y2="237" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- 圧縮 + ロード -->
|
||||
<rect x="158" y="206" width="170" height="62" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="243" y="228" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">圧縮 + ロード</text>
|
||||
<text x="243" y="242" fill="#64748b" font-size="9" text-anchor="middle">snip → micro → budget → auto</text>
|
||||
<text x="243" y="256" fill="#94a3b8" font-size="8" text-anchor="middle">→ 記憶ロード (s09)</text>
|
||||
|
||||
<!-- 矢印 → LLM -->
|
||||
<line x1="328" y1="237" x2="358" y2="237" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="360" y="214" width="100" height="46" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="410" y="231" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="410" y="246" fill="#64748b" font-size="8" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
<text x="410" y="258" fill="#059669" font-size="8" text-anchor="middle">system assembled</text>
|
||||
|
||||
<!-- 矢印 → TOOLS -->
|
||||
<line x1="460" y1="237" x2="490" y2="237" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="466" y="229" fill="#64748b" font-size="8">あり</text>
|
||||
|
||||
<!-- TOOL_HANDLERS -->
|
||||
<rect x="493" y="206" width="130" height="62" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="558" y="228" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="558" y="242" fill="#64748b" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
<text x="558" y="256" fill="#94a3b8" font-size="8" text-anchor="middle">(s09 保持)</text>
|
||||
|
||||
<!-- ===== ループバック ===== -->
|
||||
<path d="M 623 237 L 660 237 L 660 312 L 80 312 L 80 260" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="370" y="328" fill="#64748b" font-size="10" text-anchor="middle">ツール結果 → messages[] → 圧縮 → 記憶ロード → プロンプト組み立て → LLM</text>
|
||||
|
||||
<!-- ===== 下部ノート ===== -->
|
||||
<rect x="40" y="350" width="680" height="56" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="362" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="80" y="372" fill="#475569" font-size="10">s09 保持:ループ、圧縮パイプライン、記憶ロード、ツール実行</text>
|
||||
<rect x="60" y="382" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="80" y="392" fill="#475569" font-size="10">s10 新規:PROMPT_SECTIONS(4 セクション)+ assemble_system_prompt + get_system_prompt(キャッシュ)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.9 KiB |
@@ -0,0 +1,107 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 420" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#059669"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#059669"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="420" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">System Prompt — PROMPT_SECTIONS + 按需拼接 + 缓存</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s09 保留</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#059669" font-size="10" font-weight="600">s10 新增</text>
|
||||
|
||||
<!-- ===== Prompt Assembly (green, s10) ===== -->
|
||||
|
||||
<!-- PROMPT_SECTIONS -->
|
||||
<rect x="40" y="82" width="170" height="88" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="125" y="100" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">PROMPT_SECTIONS</text>
|
||||
<text x="55" y="116" fill="#065f46" font-size="9">✓ identity (始终)</text>
|
||||
<text x="55" y="130" fill="#065f46" font-size="9">✓ tools (始终)</text>
|
||||
<text x="55" y="144" fill="#065f46" font-size="9">✓ workspace (始终)</text>
|
||||
<text x="55" y="158" fill="#6b7280" font-size="9">○ memory</text>
|
||||
|
||||
<!-- arrow → assemble -->
|
||||
<line x1="210" y1="126" x2="235" y2="126" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
|
||||
<!-- assemble_system_prompt -->
|
||||
<rect x="238" y="82" width="170" height="88" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="323" y="100" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">assemble_system_prompt</text>
|
||||
<text x="253" y="118" fill="#065f46" font-size="9">输入: context dict</text>
|
||||
<text x="253" y="132" fill="#065f46" font-size="9">始终: identity + tools + workspace</text>
|
||||
<text x="253" y="146" fill="#065f46" font-size="9">按需: memory</text>
|
||||
<text x="253" y="160" fill="#6b7280" font-size="9">输出: "\n\n".join(selected)</text>
|
||||
|
||||
<!-- arrow → cache -->
|
||||
<line x1="408" y1="126" x2="433" y2="126" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
|
||||
<!-- get_system_prompt -->
|
||||
<rect x="436" y="82" width="170" height="88" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="521" y="100" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">get_system_prompt</text>
|
||||
<text x="451" y="118" fill="#065f46" font-size="9">json.dumps(context)</text>
|
||||
<text x="451" y="132" fill="#065f46" font-size="9">命中 → 返回缓存</text>
|
||||
<text x="451" y="146" fill="#065f46" font-size="9">未命中 → assemble + 存</text>
|
||||
<text x="451" y="160" fill="#6b7280" font-size="9">(s10 新增)</text>
|
||||
|
||||
<!-- Arrow: cache → LLM -->
|
||||
<path d="M 521 170 L 521 195 L 410 195 L 410 212" fill="none" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="462" y="189" fill="#059669" font-size="9">system=get_system_prompt(context)</text>
|
||||
|
||||
<!-- ===== s09 Agent Loop (blue) ===== -->
|
||||
|
||||
<!-- messages[] -->
|
||||
<rect x="30" y="214" width="100" height="46" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="80" y="241" fill="#1e3a5f" font-size="11" font-weight="600" text-anchor="middle">messages[]</text>
|
||||
|
||||
<!-- arrow → compression+loading -->
|
||||
<line x1="130" y1="237" x2="155" y2="237" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- compression + loading -->
|
||||
<rect x="158" y="206" width="170" height="62" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="243" y="228" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">压缩 + Loading</text>
|
||||
<text x="243" y="242" fill="#64748b" font-size="9" text-anchor="middle">snip → micro → budget → auto</text>
|
||||
<text x="243" y="256" fill="#94a3b8" font-size="8" text-anchor="middle">→ 加载记忆 (s09)</text>
|
||||
|
||||
<!-- arrow → LLM -->
|
||||
<line x1="328" y1="237" x2="358" y2="237" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- LLM -->
|
||||
<rect x="360" y="214" width="100" height="46" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="410" y="231" fill="#1e3a5f" font-size="12" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="410" y="246" fill="#64748b" font-size="8" text-anchor="middle">stop_reason=tool_use?</text>
|
||||
<text x="410" y="258" fill="#059669" font-size="8" text-anchor="middle">system assembled</text>
|
||||
|
||||
<!-- arrow → TOOLS -->
|
||||
<line x1="460" y1="237" x2="490" y2="237" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<text x="466" y="229" fill="#64748b" font-size="8">是</text>
|
||||
|
||||
<!-- TOOL_HANDLERS -->
|
||||
<rect x="493" y="206" width="130" height="62" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="558" y="228" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="558" y="242" fill="#64748b" font-size="9" text-anchor="middle">bash · read · write</text>
|
||||
<text x="558" y="256" fill="#94a3b8" font-size="8" text-anchor="middle">(s09 保留)</text>
|
||||
|
||||
<!-- ===== Loop back ===== -->
|
||||
<path d="M 623 237 L 660 237 L 660 312 L 80 312 L 80 260" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
<text x="370" y="328" fill="#64748b" font-size="10" text-anchor="middle">工具结果 → messages[] → 压缩 → 加载记忆 → 组装 prompt → LLM</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="350" width="680" height="56" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="362" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="80" y="372" fill="#475569" font-size="10">s09 保留:循环、压缩管线、记忆加载、工具执行</text>
|
||||
<rect x="60" y="382" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="80" y="392" fill="#475569" font-size="10">s10 新增:PROMPT_SECTIONS(4 段)+ assemble_system_prompt + get_system_prompt(缓存)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,98 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 440" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="l1" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fef3c7"/><stop offset="100%" stop-color="#fde68a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="l2" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fed7aa"/><stop offset="100%" stop-color="#fdba74"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="l3" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fecaca"/><stop offset="100%" stop-color="#fca5a5"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="440" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Error Recovery — try/except wrapping LLM calls, three recovery modes</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s10 retained</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#d97706" font-size="10" font-weight="600">s11 new</text>
|
||||
|
||||
<!-- ===== s10 loop (compact) ===== -->
|
||||
<rect x="30" y="92" width="80" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="70" y="116" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="110" y1="112" x2="128" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="131" y="86" width="90" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="176" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt assembly</text>
|
||||
<text x="176" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s10)</text>
|
||||
|
||||
<line x1="221" y1="112" x2="239" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="242" y="86" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="292" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">compress + load</text>
|
||||
<text x="292" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s08-s09)</text>
|
||||
|
||||
<line x1="342" y1="112" x2="360" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- LLM (wrapped in try/except) -->
|
||||
<rect x="363" y="86" width="80" height="52" rx="8" fill="#fef2f2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="403" y="108" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="403" y="122" fill="#dc2626" font-size="8" text-anchor="middle">try/except</text>
|
||||
|
||||
<line x1="443" y1="112" x2="461" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="464" y="86" width="110" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="519" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="519" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">bash · read · write</text>
|
||||
|
||||
<!-- Arrow: LLM → Recovery -->
|
||||
<path d="M 403 138 L 403 178" fill="none" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="415" y="164" fill="#dc2626" font-size="9">error</text>
|
||||
|
||||
<!-- ===== Recovery Section ===== -->
|
||||
<rect x="20" y="182" width="720" height="22" rx="4" fill="#f1f5f9"/>
|
||||
<text x="55" y="197" fill="#64748b" font-size="11" font-weight="600">Error Recovery (classify, recover, retry LLM)</text>
|
||||
|
||||
<!-- Layer 1: max_tokens -->
|
||||
<rect x="40" y="210" width="680" height="48" rx="7" fill="url(#l1)" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="60" y="230" fill="#92400e" font-size="12" font-weight="600">Path 1</text>
|
||||
<text x="112" y="230" fill="#92400e" font-size="11" font-weight="700">max_tokens</text>
|
||||
<text x="200" y="230" fill="#92400e" font-size="11">Output truncated → escalate 8K→64K (once) / continuation prompt (max 3)</text>
|
||||
<text x="200" y="246" fill="#b45309" font-size="9">Trigger: stop_reason == "max_tokens" · Cost: 0-1 API · Recover then continue</text>
|
||||
|
||||
<!-- Layer 2: prompt_too_long -->
|
||||
<rect x="40" y="266" width="680" height="48" rx="7" fill="url(#l2)" stroke="#ea580c" stroke-width="1.5"/>
|
||||
<text x="60" y="286" fill="#9a3412" font-size="12" font-weight="600">Path 2</text>
|
||||
<text x="112" y="286" fill="#9a3412" font-size="11" font-weight="700">prompt_too_long</text>
|
||||
<text x="230" y="286" fill="#9a3412" font-size="11">Context overflow → reactive compact → retry (one chance)</text>
|
||||
<text x="200" y="302" fill="#c2410c" font-size="9">Trigger: API returns 413 · Cost: 1 API · Still over after compact → exit</text>
|
||||
|
||||
<!-- Layer 3: 429/529 -->
|
||||
<rect x="40" y="322" width="680" height="48" rx="7" fill="url(#l3)" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="60" y="342" fill="#991b1b" font-size="12" font-weight="600">Path 3</text>
|
||||
<text x="112" y="342" fill="#991b1b" font-size="11" font-weight="700">429/529</text>
|
||||
<text x="170" y="342" fill="#991b1b" font-size="11">Transient failure → exponential backoff + jitter (max 10) / 3×529 → switch model</text>
|
||||
<text x="200" y="358" fill="#b91c1c" font-size="9">Trigger: RateLimitError / OverloadedError · Formula: min(500×2^n, 32s) + jitter</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="388" width="680" height="40" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="406" fill="#475569" font-size="10">Three most common recovery modes. CC has 13+ reason codes (image_error, aborted_streaming, etc.), each with dedicated handling.</text>
|
||||
<text x="60" y="422" fill="#94a3b8" font-size="9">All paths after recovery → continue back to LLM · Normal flow: tool results → messages → loop</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
@@ -0,0 +1,98 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 440" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="l1" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fef3c7"/><stop offset="100%" stop-color="#fde68a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="l2" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fed7aa"/><stop offset="100%" stop-color="#fdba74"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="l3" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fecaca"/><stop offset="100%" stop-color="#fca5a5"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="440" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Error Recovery — try/except で LLM 呼び出しをラップ、3 つの復旧モード</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s10 維持</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#d97706" font-size="10" font-weight="600">s11 新規</text>
|
||||
|
||||
<!-- ===== s10 loop (compact) ===== -->
|
||||
<rect x="30" y="92" width="80" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="70" y="116" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="110" y1="112" x2="128" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="131" y="86" width="90" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="176" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt assembly</text>
|
||||
<text x="176" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s10)</text>
|
||||
|
||||
<line x1="221" y1="112" x2="239" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="242" y="86" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="292" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">compress + load</text>
|
||||
<text x="292" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s08-s09)</text>
|
||||
|
||||
<line x1="342" y1="112" x2="360" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- LLM (wrapped in try/except) -->
|
||||
<rect x="363" y="86" width="80" height="52" rx="8" fill="#fef2f2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="403" y="108" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="403" y="122" fill="#dc2626" font-size="8" text-anchor="middle">try/except</text>
|
||||
|
||||
<line x1="443" y1="112" x2="461" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="464" y="86" width="110" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="519" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="519" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">bash · read · write</text>
|
||||
|
||||
<!-- Arrow: LLM → Recovery -->
|
||||
<path d="M 403 138 L 403 178" fill="none" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="415" y="164" fill="#dc2626" font-size="9">エラー</text>
|
||||
|
||||
<!-- ===== Recovery Section ===== -->
|
||||
<rect x="20" y="182" width="720" height="22" rx="4" fill="#f1f5f9"/>
|
||||
<text x="55" y="197" fill="#64748b" font-size="11" font-weight="600">エラー復旧(分類処理、復旧後 LLM に戻りリトライ)</text>
|
||||
|
||||
<!-- Layer 1: max_tokens -->
|
||||
<rect x="40" y="210" width="680" height="48" rx="7" fill="url(#l1)" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="60" y="230" fill="#92400e" font-size="12" font-weight="600">パス 1</text>
|
||||
<text x="112" y="230" fill="#92400e" font-size="11" font-weight="700">max_tokens</text>
|
||||
<text x="200" y="230" fill="#92400e" font-size="11">出力が途切れた → 8K→64K に拡張(1 回)/ 続行プロンプト(最大 3 回)</text>
|
||||
<text x="200" y="246" fill="#b45309" font-size="9">トリガー: stop_reason == "max_tokens" · コスト: 0-1 API · 復旧後 continue</text>
|
||||
|
||||
<!-- Layer 2: prompt_too_long -->
|
||||
<rect x="40" y="266" width="680" height="48" rx="7" fill="url(#l2)" stroke="#ea580c" stroke-width="1.5"/>
|
||||
<text x="60" y="286" fill="#9a3412" font-size="12" font-weight="600">パス 2</text>
|
||||
<text x="112" y="286" fill="#9a3412" font-size="11" font-weight="700">prompt_too_long</text>
|
||||
<text x="230" y="286" fill="#9a3412" font-size="11">コンテキスト超過 → reactive compact → リトライ(1 回のみ)</text>
|
||||
<text x="200" y="302" fill="#c2410c" font-size="9">トリガー: API が 413 返却 · コスト: 1 API · 圧縮後も超過 → 終了</text>
|
||||
|
||||
<!-- Layer 3: 429/529 -->
|
||||
<rect x="40" y="322" width="680" height="48" rx="7" fill="url(#l3)" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="60" y="342" fill="#991b1b" font-size="12" font-weight="600">パス 3</text>
|
||||
<text x="112" y="342" fill="#991b1b" font-size="11" font-weight="700">429/529</text>
|
||||
<text x="170" y="342" fill="#991b1b" font-size="11">一時障害 → 指数バックオフ + ジッター(最大 10 回)/ 3 回 529 → モデル切替</text>
|
||||
<text x="200" y="358" fill="#b91c1c" font-size="9">トリガー: RateLimitError / OverloadedError · 式: min(500×2^n, 32s) + jitter</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="388" width="680" height="40" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="406" fill="#475569" font-size="10">最も一般的な 3 つの復旧モード。CC は実際に 13+ の reason code を持ち(image_error, aborted_streaming 等)、それぞれ専用の処理がある。</text>
|
||||
<text x="60" y="422" fill="#94a3b8" font-size="9">全パス復旧後 → continue で LLM に戻る · 正常フロー: ツール結果 → messages → ループ</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,98 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 440" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<linearGradient id="l1" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fef3c7"/><stop offset="100%" stop-color="#fde68a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="l2" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fed7aa"/><stop offset="100%" stop-color="#fdba74"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="l3" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#fecaca"/><stop offset="100%" stop-color="#fca5a5"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="440" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Error Recovery — try/except 包裹 LLM 调用,三种恢复模式</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s10 保留</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#d97706" font-size="10" font-weight="600">s11 新增</text>
|
||||
|
||||
<!-- ===== s10 loop (compact) ===== -->
|
||||
<rect x="30" y="92" width="80" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="70" y="116" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="110" y1="112" x2="128" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="131" y="86" width="90" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="176" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt assembly</text>
|
||||
<text x="176" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s10)</text>
|
||||
|
||||
<line x1="221" y1="112" x2="239" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="242" y="86" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="292" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">compress + load</text>
|
||||
<text x="292" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s08-s09)</text>
|
||||
|
||||
<line x1="342" y1="112" x2="360" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- LLM (wrapped in try/except) -->
|
||||
<rect x="363" y="86" width="80" height="52" rx="8" fill="#fef2f2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="403" y="108" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">LLM</text>
|
||||
<text x="403" y="122" fill="#dc2626" font-size="8" text-anchor="middle">try/except</text>
|
||||
|
||||
<line x1="443" y1="112" x2="461" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="464" y="86" width="110" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="519" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="519" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">bash · read · write</text>
|
||||
|
||||
<!-- Arrow: LLM → Recovery -->
|
||||
<path d="M 403 138 L 403 178" fill="none" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="415" y="164" fill="#dc2626" font-size="9">报错</text>
|
||||
|
||||
<!-- ===== Recovery Section ===== -->
|
||||
<rect x="20" y="182" width="720" height="22" rx="4" fill="#f1f5f9"/>
|
||||
<text x="55" y="197" fill="#64748b" font-size="11" font-weight="600">错误恢复(分类处理,恢复后回到 LLM 重试)</text>
|
||||
|
||||
<!-- Layer 1: max_tokens -->
|
||||
<rect x="40" y="210" width="680" height="48" rx="7" fill="url(#l1)" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="60" y="230" fill="#92400e" font-size="12" font-weight="600">路径 1</text>
|
||||
<text x="112" y="230" fill="#92400e" font-size="11" font-weight="700">max_tokens</text>
|
||||
<text x="200" y="230" fill="#92400e" font-size="11">输出被截断 → 升级 8K→64K(一次)/ 续写提示(最多 3 次)</text>
|
||||
<text x="200" y="246" fill="#b45309" font-size="9">触发: stop_reason == "max_tokens" · 代价: 0-1 API · 恢复后 continue</text>
|
||||
|
||||
<!-- Layer 2: prompt_too_long -->
|
||||
<rect x="40" y="266" width="680" height="48" rx="7" fill="url(#l2)" stroke="#ea580c" stroke-width="1.5"/>
|
||||
<text x="60" y="286" fill="#9a3412" font-size="12" font-weight="600">路径 2</text>
|
||||
<text x="112" y="286" fill="#9a3412" font-size="11" font-weight="700">prompt_too_long</text>
|
||||
<text x="230" y="286" fill="#9a3412" font-size="11">上下文超限 → reactive compact → 重试(一次机会)</text>
|
||||
<text x="200" y="302" fill="#c2410c" font-size="9">触发: API 返回 413 · 代价: 1 API · 压缩过还是超 → 退出</text>
|
||||
|
||||
<!-- Layer 3: 429/529 -->
|
||||
<rect x="40" y="322" width="680" height="48" rx="7" fill="url(#l3)" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="60" y="342" fill="#991b1b" font-size="12" font-weight="600">路径 3</text>
|
||||
<text x="112" y="342" fill="#991b1b" font-size="11" font-weight="700">429/529</text>
|
||||
<text x="170" y="342" fill="#991b1b" font-size="11">临时故障 → 指数退避 + 抖动(最多 10 次)/ 3 次 529 → 切换模型</text>
|
||||
<text x="200" y="358" fill="#b91c1c" font-size="9">触发: RateLimitError / OverloadedError · 公式: min(500×2^n, 32s) + jitter</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="388" width="680" height="40" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="406" fill="#475569" font-size="10">三种最常见的恢复模式。CC 实际有 13+ reason code(image_error、aborted_streaming 等),各有专门处理。</text>
|
||||
<text x="60" y="422" fill="#94a3b8" font-size="9">所有路径恢复后 → continue 回到 LLM · 正常流程: 工具结果 → messages → 循环</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
59
web/public/course-assets/s12_task_system/task-dag.en.svg
Normal file
@@ -0,0 +1,59 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 400" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="dep" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="400" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="#0d9488" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="#0d9488"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Task DAG — Dependency Example: Database → API → Tests → Deploy</text>
|
||||
|
||||
<!-- Row 1: schema (completed) -->
|
||||
<rect x="295" y="70" width="170" height="48" rx="8" fill="#dcfce7" stroke="#16a34a" stroke-width="2"/>
|
||||
<text x="380" y="92" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">✓ schema</text>
|
||||
<text x="380" y="108" fill="#16a34a" font-size="9" text-anchor="middle">completed</text>
|
||||
|
||||
<!-- Arrows: schema → endpoints, schema → docs -->
|
||||
<path d="M 340 118 L 240 162" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
<path d="M 420 118 L 520 162" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
|
||||
<!-- Row 2: endpoints (in_progress), docs (pending) -->
|
||||
<rect x="115" y="164" width="170" height="48" rx="8" fill="#dbeafe" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="200" y="186" fill="#1e40af" font-size="12" font-weight="700" text-anchor="middle">● endpoints</text>
|
||||
<text x="200" y="202" fill="#2563eb" font-size="9" text-anchor="middle">in_progress · owner: agent-1</text>
|
||||
|
||||
<rect x="475" y="164" width="170" height="48" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="560" y="186" fill="#475569" font-size="12" font-weight="700" text-anchor="middle">○ docs</text>
|
||||
<text x="560" y="202" fill="#94a3b8" font-size="9" text-anchor="middle">pending · blockedBy: schema ✓</text>
|
||||
|
||||
<!-- Arrows: endpoints → tests, docs → deploy -->
|
||||
<path d="M 200 212 L 200 262" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
<path d="M 510 212 L 440 262" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
|
||||
<!-- Row 3: tests (pending), deploy (pending) -->
|
||||
<rect x="115" y="264" width="170" height="48" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="200" y="286" fill="#475569" font-size="12" font-weight="700" text-anchor="middle">○ tests</text>
|
||||
<text x="200" y="302" fill="#94a3b8" font-size="9" text-anchor="middle">blockedBy: endpoints ●</text>
|
||||
|
||||
<!-- Arrow: tests → deploy -->
|
||||
<path d="M 285 288 L 375 288" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
|
||||
<rect x="375" y="264" width="170" height="48" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="460" y="286" fill="#475569" font-size="12" font-weight="700" text-anchor="middle">○ deploy</text>
|
||||
<text x="460" y="302" fill="#94a3b8" font-size="9" text-anchor="middle">blockedBy: tests, docs</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="338" width="680" height="46" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="352" width="14" height="12" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="80" y="363" fill="#475569" font-size="10">completed</text>
|
||||
<rect x="160" y="352" width="14" height="12" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="180" y="363" fill="#475569" font-size="10">in_progress</text>
|
||||
<rect x="270" y="352" width="14" height="12" rx="3" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="290" y="363" fill="#475569" font-size="10">pending</text>
|
||||
<text x="370" y="363" fill="#94a3b8" font-size="10">→ blockedBy (arrows = dependency direction)</text>
|
||||
<text x="60" y="378" fill="#94a3b8" font-size="9">docs' blockedBy (schema) is completed → can_start returns True, can be claimed</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
59
web/public/course-assets/s12_task_system/task-dag.ja.svg
Normal file
@@ -0,0 +1,59 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 400" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="dep" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="400" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="#0d9488" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="#0d9488"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Task DAG — 依存関係の例:データベース → API → テスト → デプロイ</text>
|
||||
|
||||
<!-- 行 1: schema(完了) -->
|
||||
<rect x="295" y="70" width="170" height="48" rx="8" fill="#dcfce7" stroke="#16a34a" stroke-width="2"/>
|
||||
<text x="380" y="92" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">✓ schema</text>
|
||||
<text x="380" y="108" fill="#16a34a" font-size="9" text-anchor="middle">completed</text>
|
||||
|
||||
<!-- 矢印: schema → endpoints, schema → docs -->
|
||||
<path d="M 340 118 L 240 162" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
<path d="M 420 118 L 520 162" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
|
||||
<!-- 行 2: endpoints(進行中)、docs(保留中) -->
|
||||
<rect x="115" y="164" width="170" height="48" rx="8" fill="#dbeafe" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="200" y="186" fill="#1e40af" font-size="12" font-weight="700" text-anchor="middle">● endpoints</text>
|
||||
<text x="200" y="202" fill="#2563eb" font-size="9" text-anchor="middle">in_progress · owner: agent-1</text>
|
||||
|
||||
<rect x="475" y="164" width="170" height="48" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="560" y="186" fill="#475569" font-size="12" font-weight="700" text-anchor="middle">○ docs</text>
|
||||
<text x="560" y="202" fill="#94a3b8" font-size="9" text-anchor="middle">pending · blockedBy: schema ✓</text>
|
||||
|
||||
<!-- 矢印: endpoints → tests, docs → deploy -->
|
||||
<path d="M 200 212 L 200 262" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
<path d="M 510 212 L 440 262" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
|
||||
<!-- 行 3: tests(保留中)、deploy(保留中) -->
|
||||
<rect x="115" y="264" width="170" height="48" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="200" y="286" fill="#475569" font-size="12" font-weight="700" text-anchor="middle">○ tests</text>
|
||||
<text x="200" y="302" fill="#94a3b8" font-size="9" text-anchor="middle">blockedBy: endpoints ●</text>
|
||||
|
||||
<!-- 矢印: tests → deploy -->
|
||||
<path d="M 285 288 L 375 288" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
|
||||
<rect x="375" y="264" width="170" height="48" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="460" y="286" fill="#475569" font-size="12" font-weight="700" text-anchor="middle">○ deploy</text>
|
||||
<text x="460" y="302" fill="#94a3b8" font-size="9" text-anchor="middle">blockedBy: tests, docs</text>
|
||||
|
||||
<!-- 凡例 -->
|
||||
<rect x="40" y="338" width="680" height="46" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="352" width="14" height="12" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="80" y="363" fill="#475569" font-size="10">completed</text>
|
||||
<rect x="160" y="352" width="14" height="12" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="180" y="363" fill="#475569" font-size="10">in_progress</text>
|
||||
<rect x="270" y="352" width="14" height="12" rx="3" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="290" y="363" fill="#475569" font-size="10">pending</text>
|
||||
<text x="370" y="363" fill="#94a3b8" font-size="10">→ blockedBy(矢印 = 依存方向)</text>
|
||||
<text x="60" y="378" fill="#94a3b8" font-size="9">docs の blockedBy (schema) は完了済み → can_start が True を返し、claim 可能</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
59
web/public/course-assets/s12_task_system/task-dag.svg
Normal file
@@ -0,0 +1,59 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 400" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<marker id="dep" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="400" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="#0d9488" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="#0d9488"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Task DAG — 依赖关系示例:搭数据库 → API → 测试 → 部署</text>
|
||||
|
||||
<!-- Row 1: schema (completed) -->
|
||||
<rect x="295" y="70" width="170" height="48" rx="8" fill="#dcfce7" stroke="#16a34a" stroke-width="2"/>
|
||||
<text x="380" y="92" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">✓ schema</text>
|
||||
<text x="380" y="108" fill="#16a34a" font-size="9" text-anchor="middle">completed</text>
|
||||
|
||||
<!-- Arrows: schema → endpoints, schema → docs -->
|
||||
<path d="M 340 118 L 240 162" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
<path d="M 420 118 L 520 162" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
|
||||
<!-- Row 2: endpoints (in_progress), docs (pending) -->
|
||||
<rect x="115" y="164" width="170" height="48" rx="8" fill="#dbeafe" stroke="#2563eb" stroke-width="2"/>
|
||||
<text x="200" y="186" fill="#1e40af" font-size="12" font-weight="700" text-anchor="middle">● endpoints</text>
|
||||
<text x="200" y="202" fill="#2563eb" font-size="9" text-anchor="middle">in_progress · owner: agent-1</text>
|
||||
|
||||
<rect x="475" y="164" width="170" height="48" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="560" y="186" fill="#475569" font-size="12" font-weight="700" text-anchor="middle">○ docs</text>
|
||||
<text x="560" y="202" fill="#94a3b8" font-size="9" text-anchor="middle">pending · blockedBy: schema ✓</text>
|
||||
|
||||
<!-- Arrows: endpoints → tests, docs → deploy -->
|
||||
<path d="M 200 212 L 200 262" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
<path d="M 510 212 L 440 262" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
|
||||
<!-- Row 3: tests (pending), deploy (pending) -->
|
||||
<rect x="115" y="264" width="170" height="48" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="200" y="286" fill="#475569" font-size="12" font-weight="700" text-anchor="middle">○ tests</text>
|
||||
<text x="200" y="302" fill="#94a3b8" font-size="9" text-anchor="middle">blockedBy: endpoints ●</text>
|
||||
|
||||
<!-- Arrow: tests → deploy -->
|
||||
<path d="M 285 288 L 375 288" fill="none" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#dep)"/>
|
||||
|
||||
<rect x="375" y="264" width="170" height="48" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.5"/>
|
||||
<text x="460" y="286" fill="#475569" font-size="12" font-weight="700" text-anchor="middle">○ deploy</text>
|
||||
<text x="460" y="302" fill="#94a3b8" font-size="9" text-anchor="middle">blockedBy: tests, docs</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="338" width="680" height="46" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="352" width="14" height="12" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="80" y="363" fill="#475569" font-size="10">completed</text>
|
||||
<rect x="160" y="352" width="14" height="12" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="180" y="363" fill="#475569" font-size="10">in_progress</text>
|
||||
<rect x="270" y="352" width="14" height="12" rx="3" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="290" y="363" fill="#475569" font-size="10">pending</text>
|
||||
<text x="370" y="363" fill="#94a3b8" font-size="10">→ blockedBy(箭头 = 依赖方向)</text>
|
||||
<text x="60" y="378" fill="#94a3b8" font-size="9">docs 的 blockedBy (schema) 已完成 → can_start 返回 True,可被 claim</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,94 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 420" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#0d9488"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-teal" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0d9488"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="420" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Task System — 5 Task Tools + .tasks/ Persistence + blockedBy Dependencies</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s11 Preserved</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#f0fdfa" stroke="#0d9488" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#0d9488" font-size="10" font-weight="600">s12 New</text>
|
||||
|
||||
<!-- ===== s11 loop (compact) ===== -->
|
||||
<rect x="30" y="92" width="80" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="70" y="116" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="110" y1="112" x2="128" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="131" y="86" width="120" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="191" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + compress</text>
|
||||
<text x="191" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s10-s11)</text>
|
||||
|
||||
<line x1="251" y1="112" x2="269" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="272" y="86" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="322" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM (try/except)</text>
|
||||
<text x="322" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s11)</text>
|
||||
|
||||
<line x1="372" y1="112" x2="390" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- TOOLS (expanded) -->
|
||||
<rect x="393" y="80" width="210" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="498" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="408" y="114" fill="#2563eb" font-size="9">bash · read · write</text>
|
||||
<text x="408" y="128" fill="#0d9488" font-size="9" font-weight="600">create_task · list_tasks</text>
|
||||
<text x="408" y="140" fill="#0d9488" font-size="9" font-weight="600">get_task · claim_task · complete_task</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 603 112 L 640 112 L 640 155 L 70 155 L 70 132" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== .tasks/ directory (teal) ===== -->
|
||||
<rect x="40" y="185" width="310" height="76" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-width="2"/>
|
||||
<text x="195" y="205" fill="#134e4a" font-size="11" font-weight="700" text-anchor="middle">.tasks/ — Cross-session Persistence</text>
|
||||
<text x="60" y="222" fill="#0d9488" font-size="9">task_xxx.json · task_yyy.json · task_zzz.json</text>
|
||||
<text x="60" y="238" fill="#6b7280" font-size="8">{id, subject, description, status, owner, blockedBy}</text>
|
||||
<text x="60" y="252" fill="#6b7280" font-size="8">Tutorial ID: timestamp + random | CC: sequential ID + highwatermark</text>
|
||||
|
||||
<!-- Arrow: tools → .tasks/ -->
|
||||
<path d="M 440 144 L 440 165 L 250 165 L 250 185" fill="none" stroke="#0d9488" stroke-width="1.5" marker-end="url(#arrow-teal)"/>
|
||||
<text x="320" y="178" fill="#0d9488" font-size="9">create / save / read</text>
|
||||
|
||||
<!-- ===== Lifecycle (teal) ===== -->
|
||||
<rect x="390" y="185" width="330" height="76" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-width="2"/>
|
||||
<text x="555" y="205" fill="#134e4a" font-size="11" font-weight="700" text-anchor="middle">Dependency Check + Lifecycle</text>
|
||||
<text x="408" y="222" fill="#0d9488" font-size="9">can_start: all blockedBy completed?</text>
|
||||
<text x="408" y="238" fill="#0d9488" font-size="9">claim_task → owner = agent, pending → in_progress</text>
|
||||
<text x="408" y="252" fill="#0d9488" font-size="9">complete_task → completed + unblock downstream</text>
|
||||
|
||||
<!-- ===== State machine ===== -->
|
||||
<rect x="40" y="286" width="680" height="46" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="310" fill="#1e3a5f" font-size="11" font-weight="600">State Machine:</text>
|
||||
<rect x="160" y="298" width="56" height="20" rx="4" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="188" y="312" fill="#475569" font-size="9" text-anchor="middle">pending</text>
|
||||
<line x1="216" y1="308" x2="288" y2="308" stroke="#0d9488" stroke-width="1.5" marker-end="url(#arrow-teal)"/>
|
||||
<text x="252" y="303" fill="#0d9488" font-size="8" font-weight="600" text-anchor="middle">claim</text>
|
||||
<rect x="290" y="298" width="76" height="20" rx="4" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="328" y="312" fill="#1e40af" font-size="9" text-anchor="middle">in_progress</text>
|
||||
<line x1="366" y1="308" x2="458" y2="308" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-teal)"/>
|
||||
<text x="412" y="303" fill="#16a34a" font-size="8" font-weight="600" text-anchor="middle">complete_task</text>
|
||||
<rect x="460" y="298" width="72" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="496" y="312" fill="#166534" font-size="9" text-anchor="middle">completed</text>
|
||||
<text x="548" y="312" fill="#94a3b8" font-size="9">No release rollback; crash → unassign owner</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="352" width="680" height="52" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="366" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="80" y="376" fill="#475569" font-size="10">s11 Preserved: loop, prompt assembly, compression (error recovery independent from task system)</text>
|
||||
<rect x="60" y="384" width="12" height="10" rx="2" fill="#f0fdfa" stroke="#0d9488" stroke-width="1"/>
|
||||
<text x="80" y="394" fill="#475569" font-size="10">s12 New: Task dataclass + 5 tools + .tasks/ persistence + blockedBy dependency graph</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
@@ -0,0 +1,94 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 420" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#0d9488"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-teal" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0d9488"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="420" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Task System — 5 つのタスクツール + .tasks/ 永続化 + blockedBy 依存</text>
|
||||
|
||||
<!-- 凡例 -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s11 保持</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#f0fdfa" stroke="#0d9488" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#0d9488" font-size="10" font-weight="600">s12 新規</text>
|
||||
|
||||
<!-- ===== s11 ループ(コンパクト) ===== -->
|
||||
<rect x="30" y="92" width="80" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="70" y="116" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="110" y1="112" x2="128" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="131" y="86" width="120" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="191" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + compress</text>
|
||||
<text x="191" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s10-s11)</text>
|
||||
|
||||
<line x1="251" y1="112" x2="269" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="272" y="86" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="322" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM (try/except)</text>
|
||||
<text x="322" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s11)</text>
|
||||
|
||||
<line x1="372" y1="112" x2="390" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- ツール(展開) -->
|
||||
<rect x="393" y="80" width="210" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="498" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="408" y="114" fill="#2563eb" font-size="9">bash · read · write</text>
|
||||
<text x="408" y="128" fill="#0d9488" font-size="9" font-weight="600">create_task · list_tasks</text>
|
||||
<text x="408" y="140" fill="#0d9488" font-size="9" font-weight="600">get_task · claim_task · complete_task</text>
|
||||
|
||||
<!-- ループバック -->
|
||||
<path d="M 603 112 L 640 112 L 640 155 L 70 155 L 70 132" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== .tasks/ ディレクトリ(ティール) ===== -->
|
||||
<rect x="40" y="185" width="310" height="76" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-width="2"/>
|
||||
<text x="195" y="205" fill="#134e4a" font-size="11" font-weight="700" text-anchor="middle">.tasks/ — セッション横断永続化</text>
|
||||
<text x="60" y="222" fill="#0d9488" font-size="9">task_xxx.json · task_yyy.json · task_zzz.json</text>
|
||||
<text x="60" y="238" fill="#6b7280" font-size="8">{id, subject, description, status, owner, blockedBy}</text>
|
||||
<text x="60" y="252" fill="#6b7280" font-size="8">チュートリアル ID: timestamp + random | CC: 順次 ID + highwatermark</text>
|
||||
|
||||
<!-- 矢印: tools → .tasks/ -->
|
||||
<path d="M 440 144 L 440 165 L 250 165 L 250 185" fill="none" stroke="#0d9488" stroke-width="1.5" marker-end="url(#arrow-teal)"/>
|
||||
<text x="320" y="178" fill="#0d9488" font-size="9">create / save / read</text>
|
||||
|
||||
<!-- ===== ライフサイクル(ティール) ===== -->
|
||||
<rect x="390" y="185" width="330" height="76" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-width="2"/>
|
||||
<text x="555" y="205" fill="#134e4a" font-size="11" font-weight="700" text-anchor="middle">依存チェック + ライフサイクル</text>
|
||||
<text x="408" y="222" fill="#0d9488" font-size="9">can_start: blockedBy がすべて completed?</text>
|
||||
<text x="408" y="238" fill="#0d9488" font-size="9">claim_task → owner = agent, pending → in_progress</text>
|
||||
<text x="408" y="252" fill="#0d9488" font-size="9">complete_task → completed + 下流をアンロック</text>
|
||||
|
||||
<!-- ===== 状態マシン ===== -->
|
||||
<rect x="40" y="286" width="680" height="46" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="310" fill="#1e3a5f" font-size="11" font-weight="600">状態マシン:</text>
|
||||
<rect x="150" y="298" width="56" height="20" rx="4" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="178" y="312" fill="#475569" font-size="9" text-anchor="middle">pending</text>
|
||||
<line x1="206" y1="308" x2="278" y2="308" stroke="#0d9488" stroke-width="1.5" marker-end="url(#arrow-teal)"/>
|
||||
<text x="242" y="303" fill="#0d9488" font-size="8" font-weight="600" text-anchor="middle">claim</text>
|
||||
<rect x="280" y="298" width="76" height="20" rx="4" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="318" y="312" fill="#1e40af" font-size="9" text-anchor="middle">in_progress</text>
|
||||
<line x1="356" y1="308" x2="448" y2="308" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-teal)"/>
|
||||
<text x="402" y="303" fill="#16a34a" font-size="8" font-weight="600" text-anchor="middle">complete_task</text>
|
||||
<rect x="450" y="298" width="72" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="486" y="312" fill="#166534" font-size="9" text-anchor="middle">completed</text>
|
||||
<text x="538" y="312" fill="#94a3b8" font-size="9">release ロールバックなし、クラッシュ時は unassign で owner クリア</text>
|
||||
|
||||
<!-- ===== 下部ノート ===== -->
|
||||
<rect x="40" y="352" width="680" height="52" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="366" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="80" y="376" fill="#475569" font-size="10">s11 保持:ループ、プロンプト組み立て、圧縮(エラーリカバリとタスクシステムは独立)</text>
|
||||
<rect x="60" y="384" width="12" height="10" rx="2" fill="#f0fdfa" stroke="#0d9488" stroke-width="1"/>
|
||||
<text x="80" y="394" fill="#475569" font-size="10">s12 新規:Task dataclass + 5 ツール + .tasks/ 永続化 + blockedBy 依存グラフ</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.0 KiB |
@@ -0,0 +1,94 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 420" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#0d9488"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-teal" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0d9488"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="420" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Task System — 5 个任务工具 + .tasks/ 持久化 + blockedBy 依赖</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s11 保留</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#f0fdfa" stroke="#0d9488" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#0d9488" font-size="10" font-weight="600">s12 新增</text>
|
||||
|
||||
<!-- ===== s11 loop (compact) ===== -->
|
||||
<rect x="30" y="92" width="80" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="70" y="116" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="110" y1="112" x2="128" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="131" y="86" width="120" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="191" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + compress</text>
|
||||
<text x="191" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s10-s11)</text>
|
||||
|
||||
<line x1="251" y1="112" x2="269" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="272" y="86" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="322" y="108" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM (try/except)</text>
|
||||
<text x="322" y="122" fill="#94a3b8" font-size="8" text-anchor="middle">(s11)</text>
|
||||
|
||||
<line x1="372" y1="112" x2="390" y2="112" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- TOOLS (expanded) -->
|
||||
<rect x="393" y="80" width="210" height="64" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="498" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL_HANDLERS</text>
|
||||
<text x="408" y="114" fill="#2563eb" font-size="9">bash · read · write</text>
|
||||
<text x="408" y="128" fill="#0d9488" font-size="9" font-weight="600">create_task · list_tasks</text>
|
||||
<text x="408" y="140" fill="#0d9488" font-size="9" font-weight="600">get_task · claim_task · complete_task</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 603 112 L 640 112 L 640 155 L 70 155 L 70 132" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== .tasks/ directory (teal) ===== -->
|
||||
<rect x="40" y="185" width="310" height="76" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-width="2"/>
|
||||
<text x="195" y="205" fill="#134e4a" font-size="11" font-weight="700" text-anchor="middle">.tasks/ — 跨会话持久化</text>
|
||||
<text x="60" y="222" fill="#0d9488" font-size="9">task_xxx.json · task_yyy.json · task_zzz.json</text>
|
||||
<text x="60" y="238" fill="#6b7280" font-size="8">{id, subject, description, status, owner, blockedBy}</text>
|
||||
<text x="60" y="252" fill="#6b7280" font-size="8">教学版 ID: timestamp + random | CC: 顺序 ID + highwatermark</text>
|
||||
|
||||
<!-- Arrow: tools → .tasks/ -->
|
||||
<path d="M 440 144 L 440 165 L 250 165 L 250 185" fill="none" stroke="#0d9488" stroke-width="1.5" marker-end="url(#arrow-teal)"/>
|
||||
<text x="320" y="178" fill="#0d9488" font-size="9">create / save / read</text>
|
||||
|
||||
<!-- ===== Lifecycle (teal) ===== -->
|
||||
<rect x="390" y="185" width="330" height="76" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-width="2"/>
|
||||
<text x="555" y="205" fill="#134e4a" font-size="11" font-weight="700" text-anchor="middle">依赖检查 + 生命周期</text>
|
||||
<text x="408" y="222" fill="#0d9488" font-size="9">can_start: blockedBy 全部 completed?</text>
|
||||
<text x="408" y="238" fill="#0d9488" font-size="9">claim_task → owner = agent, pending → in_progress</text>
|
||||
<text x="408" y="252" fill="#0d9488" font-size="9">complete_task → completed + 解锁下游</text>
|
||||
|
||||
<!-- ===== State machine ===== -->
|
||||
<rect x="40" y="286" width="680" height="46" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="310" fill="#1e3a5f" font-size="11" font-weight="600">状态机:</text>
|
||||
<rect x="120" y="298" width="56" height="20" rx="4" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="148" y="312" fill="#475569" font-size="9" text-anchor="middle">pending</text>
|
||||
<line x1="176" y1="308" x2="238" y2="308" stroke="#0d9488" stroke-width="1.5" marker-end="url(#arrow-teal)"/>
|
||||
<text x="207" y="303" fill="#0d9488" font-size="8" font-weight="600" text-anchor="middle">claim</text>
|
||||
<rect x="240" y="298" width="76" height="20" rx="4" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="278" y="312" fill="#1e40af" font-size="9" text-anchor="middle">in_progress</text>
|
||||
<line x1="316" y1="308" x2="408" y2="308" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-teal)"/>
|
||||
<text x="362" y="303" fill="#16a34a" font-size="8" font-weight="600" text-anchor="middle">complete_task</text>
|
||||
<rect x="410" y="298" width="72" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="446" y="312" fill="#166534" font-size="9" text-anchor="middle">completed</text>
|
||||
<text x="500" y="312" fill="#94a3b8" font-size="9">CC 无 release 回退,崩溃时用 unassign 清 owner</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="40" y="352" width="680" height="52" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="60" y="366" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="80" y="376" fill="#475569" font-size="10">s11 保留:循环、prompt 组装、压缩(错误恢复与任务系统独立)</text>
|
||||
<rect x="60" y="384" width="12" height="10" rx="2" fill="#f0fdfa" stroke="#0d9488" stroke-width="1"/>
|
||||
<text x="80" y="394" fill="#475569" font-size="10">s12 新增:Task dataclass + 5 个工具 + .tasks/ 持久化 + blockedBy 依赖图</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,105 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 440" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#ea580c"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-orange" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ea580c"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="440" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Background Tasks — Slow ops to background, Agent keeps thinking</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s12 retained</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#fff7ed" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#ea580c" font-size="10" font-weight="600">s13 new</text>
|
||||
|
||||
<!-- ===== Top: s12 loop (compact) ===== -->
|
||||
<rect x="30" y="86" width="80" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="70" y="110" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="110" y1="106" x2="128" y2="106" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="131" y="80" width="120" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="191" y="102" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + cache</text>
|
||||
<text x="191" y="116" fill="#94a3b8" font-size="8" text-anchor="middle">(s10-s12)</text>
|
||||
|
||||
<line x1="251" y1="106" x2="269" y2="106" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="272" y="80" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="322" y="102" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM call</text>
|
||||
<text x="322" y="116" fill="#94a3b8" font-size="8" text-anchor="middle">(s11 retry)</text>
|
||||
|
||||
<line x1="372" y1="106" x2="390" y2="106" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- TOOL DISPATCH (expanded) -->
|
||||
<rect x="393" y="76" width="210" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="498" y="94" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH</text>
|
||||
<text x="408" y="110" fill="#2563eb" font-size="9">fast? → sync execute (s12)</text>
|
||||
<text x="408" y="124" fill="#ea580c" font-size="9" font-weight="600">slow? → run_in_background ★</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 603 106 L 640 106 L 640 148 L 70 148 L 70 126" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== Background execution (orange) ===== -->
|
||||
<rect x="40" y="172" width="310" height="80" rx="8" fill="#fff7ed" stroke="#ea580c" stroke-width="2"/>
|
||||
<text x="195" y="194" fill="#9a3412" font-size="11" font-weight="700" text-anchor="middle">Background thread execution</text>
|
||||
<text x="60" y="212" fill="#ea580c" font-size="9">run_in_background(tool_use_id, fn, *args)</text>
|
||||
<text x="60" y="226" fill="#6b7280" font-size="8">threading.Thread(target=worker, daemon=True)</text>
|
||||
<text x="60" y="240" fill="#6b7280" font-size="8">result → background_results[id] (threading.Lock protected)</text>
|
||||
|
||||
<!-- Arrow: dispatch → background -->
|
||||
<path d="M 440 136 L 440 158 L 250 158 L 250 172" fill="none" stroke="#ea580c" stroke-width="1.5" marker-end="url(#arrow-orange)"/>
|
||||
<text x="320" y="170" fill="#ea580c" font-size="9">slow op</text>
|
||||
|
||||
<!-- ===== Notification injection (orange) ===== -->
|
||||
<rect x="390" y="172" width="330" height="80" rx="8" fill="#fff7ed" stroke="#ea580c" stroke-width="2"/>
|
||||
<text x="555" y="194" fill="#9a3412" font-size="11" font-weight="700" text-anchor="middle">Notification injection</text>
|
||||
<text x="408" y="212" fill="#ea580c" font-size="9">collect_background_results() check each turn</text>
|
||||
<text x="408" y="226" fill="#6b7280" font-size="8">completed → tool_result inject into messages</text>
|
||||
<text x="408" y="240" fill="#6b7280" font-size="8">pending → "[Running in background...]" placeholder</text>
|
||||
|
||||
<!-- Arrow: background → notification -->
|
||||
<path d="M 350 220 L 390 220" fill="none" stroke="#ea580c" stroke-width="1.5" marker-end="url(#arrow-orange)"/>
|
||||
|
||||
<!-- ===== Slow operation heuristic ===== -->
|
||||
<rect x="40" y="274" width="680" height="48" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="296" fill="#1e3a5f" font-size="11" font-weight="600">Heuristic:</text>
|
||||
<rect x="155" y="284" width="56" height="18" rx="4" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="183" y="297" fill="#16a34a" font-size="9" text-anchor="middle">fast</text>
|
||||
<text x="218" y="297" fill="#475569" font-size="9">read_file · git status · glob</text>
|
||||
<rect x="360" y="284" width="56" height="18" rx="4" fill="#fff7ed" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="388" y="297" fill="#ea580c" font-size="9" text-anchor="middle">slow</text>
|
||||
<text x="423" y="297" fill="#475569" font-size="9">npm install · pip install · pytest (timeout > 30s)</text>
|
||||
|
||||
<!-- ===== Timeline comparison ===== -->
|
||||
<rect x="40" y="340" width="330" height="84" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="205" y="360" fill="#991b1b" font-size="10" font-weight="700" text-anchor="middle">s12 sync blocking</text>
|
||||
<rect x="60" y="370" width="80" height="14" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="381" fill="#1e40af" font-size="8" text-anchor="middle">think</text>
|
||||
<rect x="145" y="370" width="160" height="14" rx="3" fill="#fecaca" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="225" y="381" fill="#991b1b" font-size="8" text-anchor="middle">waiting for bash 3min...</text>
|
||||
<rect x="310" y="370" width="40" height="14" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="330" y="381" fill="#1e40af" font-size="7" text-anchor="middle">continue</text>
|
||||
<text x="60" y="410" fill="#991b1b" font-size="9">Total ~3min, Agent idled for 3 minutes</text>
|
||||
|
||||
<rect x="390" y="340" width="330" height="84" rx="6" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="555" y="360" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">s13 background execution</text>
|
||||
<rect x="410" y="370" width="80" height="14" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="450" y="381" fill="#1e40af" font-size="8" text-anchor="middle">think</text>
|
||||
<rect x="495" y="370" width="100" height="14" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="545" y="381" fill="#166534" font-size="8" text-anchor="middle">keep doing other work</text>
|
||||
<rect x="600" y="370" width="100" height="14" rx="3" fill="#fff7ed" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="650" y="381" fill="#ea580c" font-size="8" text-anchor="middle">notification: result ready</text>
|
||||
<text x="410" y="410" fill="#166534" font-size="9">Total ~3min, but Agent wasn't idle</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1,105 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 440" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#ea580c"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-orange" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ea580c"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="440" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Background Tasks — 遅い操作はバックグラウンドへ、Agent は考え続ける</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s12 維持</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#fff7ed" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#ea580c" font-size="10" font-weight="600">s13 新規</text>
|
||||
|
||||
<!-- ===== Top: s12 loop (compact) ===== -->
|
||||
<rect x="30" y="86" width="80" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="70" y="110" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="110" y1="106" x2="128" y2="106" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="131" y="80" width="120" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="191" y="102" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + cache</text>
|
||||
<text x="191" y="116" fill="#94a3b8" font-size="8" text-anchor="middle">(s10-s12)</text>
|
||||
|
||||
<line x1="251" y1="106" x2="269" y2="106" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="272" y="80" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="322" y="102" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM call</text>
|
||||
<text x="322" y="116" fill="#94a3b8" font-size="8" text-anchor="middle">(s11 retry)</text>
|
||||
|
||||
<line x1="372" y1="106" x2="390" y2="106" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- TOOL DISPATCH (expanded) -->
|
||||
<rect x="393" y="76" width="210" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="498" y="94" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH</text>
|
||||
<text x="408" y="110" fill="#2563eb" font-size="9">fast? → 同期実行 (s12)</text>
|
||||
<text x="408" y="124" fill="#ea580c" font-size="9" font-weight="600">slow? → run_in_background ★</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 603 106 L 640 106 L 640 148 L 70 148 L 70 126" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== Background execution (orange) ===== -->
|
||||
<rect x="40" y="172" width="310" height="80" rx="8" fill="#fff7ed" stroke="#ea580c" stroke-width="2"/>
|
||||
<text x="195" y="194" fill="#9a3412" font-size="11" font-weight="700" text-anchor="middle">バックグラウンドスレッド実行</text>
|
||||
<text x="60" y="212" fill="#ea580c" font-size="9">run_in_background(tool_use_id, fn, *args)</text>
|
||||
<text x="60" y="226" fill="#6b7280" font-size="8">threading.Thread(target=worker, daemon=True)</text>
|
||||
<text x="60" y="240" fill="#6b7280" font-size="8">結果 → background_results[id] (threading.Lock で保護)</text>
|
||||
|
||||
<!-- Arrow: dispatch → background -->
|
||||
<path d="M 440 136 L 440 158 L 250 158 L 250 172" fill="none" stroke="#ea580c" stroke-width="1.5" marker-end="url(#arrow-orange)"/>
|
||||
<text x="320" y="170" fill="#ea580c" font-size="9">slow op</text>
|
||||
|
||||
<!-- ===== Notification injection (orange) ===== -->
|
||||
<rect x="390" y="172" width="330" height="80" rx="8" fill="#fff7ed" stroke="#ea580c" stroke-width="2"/>
|
||||
<text x="555" y="194" fill="#9a3412" font-size="11" font-weight="700" text-anchor="middle">通知注入</text>
|
||||
<text x="408" y="212" fill="#ea580c" font-size="9">collect_background_results() 毎ターン確認</text>
|
||||
<text x="408" y="226" fill="#6b7280" font-size="8">完了 → tool_result を messages に注入</text>
|
||||
<text x="408" y="240" fill="#6b7280" font-size="8">未完了 → "[Running in background...]" プレースホルダー</text>
|
||||
|
||||
<!-- Arrow: background → notification -->
|
||||
<path d="M 350 220 L 390 220" fill="none" stroke="#ea580c" stroke-width="1.5" marker-end="url(#arrow-orange)"/>
|
||||
|
||||
<!-- ===== Slow operation heuristic ===== -->
|
||||
<rect x="40" y="274" width="680" height="48" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="296" fill="#1e3a5f" font-size="11" font-weight="600">ヒューリスティック判定:</text>
|
||||
<rect x="155" y="284" width="56" height="18" rx="4" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="183" y="297" fill="#16a34a" font-size="9" text-anchor="middle">fast</text>
|
||||
<text x="218" y="297" fill="#475569" font-size="9">read_file · git status · glob</text>
|
||||
<rect x="360" y="284" width="56" height="18" rx="4" fill="#fff7ed" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="388" y="297" fill="#ea580c" font-size="9" text-anchor="middle">slow</text>
|
||||
<text x="423" y="297" fill="#475569" font-size="9">npm install · pip install · pytest (timeout > 30s)</text>
|
||||
|
||||
<!-- ===== Timeline comparison ===== -->
|
||||
<rect x="40" y="340" width="330" height="84" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="205" y="360" fill="#991b1b" font-size="10" font-weight="700" text-anchor="middle">s12 同期ブロッキング</text>
|
||||
<rect x="60" y="370" width="80" height="14" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="381" fill="#1e40af" font-size="8" text-anchor="middle">思考</text>
|
||||
<rect x="145" y="370" width="160" height="14" rx="3" fill="#fecaca" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="225" y="381" fill="#991b1b" font-size="8" text-anchor="middle">bash 待ち 3分...</text>
|
||||
<rect x="310" y="370" width="40" height="14" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="330" y="381" fill="#1e40af" font-size="7" text-anchor="middle">継続</text>
|
||||
<text x="60" y="410" fill="#991b1b" font-size="9">合計 ~3分、Agent は3分間待機</text>
|
||||
|
||||
<rect x="390" y="340" width="330" height="84" rx="6" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="555" y="360" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">s13 バックグラウンド実行</text>
|
||||
<rect x="410" y="370" width="80" height="14" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="450" y="381" fill="#1e40af" font-size="8" text-anchor="middle">思考</text>
|
||||
<rect x="495" y="370" width="100" height="14" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="545" y="381" fill="#166534" font-size="8" text-anchor="middle">別の作業を継続</text>
|
||||
<rect x="600" y="370" width="100" height="14" rx="3" fill="#fff7ed" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="650" y="381" fill="#ea580c" font-size="8" text-anchor="middle">通知: 結果完了</text>
|
||||
<text x="410" y="410" fill="#166534" font-size="9">合計 ~3分、Agent は遊ばず</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,105 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 440" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#ea580c"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-orange" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ea580c"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="440" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Background Tasks — 慢操作丢后台,Agent 继续思考</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s12 保留</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#fff7ed" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#ea580c" font-size="10" font-weight="600">s13 新增</text>
|
||||
|
||||
<!-- ===== Top: s12 loop (compact) ===== -->
|
||||
<rect x="30" y="86" width="80" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="70" y="110" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="110" y1="106" x2="128" y2="106" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="131" y="80" width="120" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="191" y="102" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + cache</text>
|
||||
<text x="191" y="116" fill="#94a3b8" font-size="8" text-anchor="middle">(s10-s12)</text>
|
||||
|
||||
<line x1="251" y1="106" x2="269" y2="106" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="272" y="80" width="100" height="52" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="322" y="102" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM call</text>
|
||||
<text x="322" y="116" fill="#94a3b8" font-size="8" text-anchor="middle">(s11 retry)</text>
|
||||
|
||||
<line x1="372" y1="106" x2="390" y2="106" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- TOOL DISPATCH (expanded) -->
|
||||
<rect x="393" y="76" width="210" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="498" y="94" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH</text>
|
||||
<text x="408" y="110" fill="#2563eb" font-size="9">fast? → 同步执行 (s12)</text>
|
||||
<text x="408" y="124" fill="#ea580c" font-size="9" font-weight="600">slow? → run_in_background ★</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 603 106 L 640 106 L 640 148 L 70 148 L 70 126" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== Background execution (orange) ===== -->
|
||||
<rect x="40" y="172" width="310" height="80" rx="8" fill="#fff7ed" stroke="#ea580c" stroke-width="2"/>
|
||||
<text x="195" y="194" fill="#9a3412" font-size="11" font-weight="700" text-anchor="middle">后台线程执行</text>
|
||||
<text x="60" y="212" fill="#ea580c" font-size="9">run_in_background(tool_use_id, fn, *args)</text>
|
||||
<text x="60" y="226" fill="#6b7280" font-size="8">threading.Thread(target=worker, daemon=True)</text>
|
||||
<text x="60" y="240" fill="#6b7280" font-size="8">结果 → background_results[id] (threading.Lock 保护)</text>
|
||||
|
||||
<!-- Arrow: dispatch → background -->
|
||||
<path d="M 440 136 L 440 158 L 250 158 L 250 172" fill="none" stroke="#ea580c" stroke-width="1.5" marker-end="url(#arrow-orange)"/>
|
||||
<text x="320" y="170" fill="#ea580c" font-size="9">slow op</text>
|
||||
|
||||
<!-- ===== Notification injection (orange) ===== -->
|
||||
<rect x="390" y="172" width="330" height="80" rx="8" fill="#fff7ed" stroke="#ea580c" stroke-width="2"/>
|
||||
<text x="555" y="194" fill="#9a3412" font-size="11" font-weight="700" text-anchor="middle">通知注入</text>
|
||||
<text x="408" y="212" fill="#ea580c" font-size="9">collect_background_results() 每轮检查</text>
|
||||
<text x="408" y="226" fill="#6b7280" font-size="8">已完成 → tool_result 注入 messages</text>
|
||||
<text x="408" y="240" fill="#6b7280" font-size="8">未完成 → "[Running in background...]" 占位</text>
|
||||
|
||||
<!-- Arrow: background → notification -->
|
||||
<path d="M 350 220 L 390 220" fill="none" stroke="#ea580c" stroke-width="1.5" marker-end="url(#arrow-orange)"/>
|
||||
|
||||
<!-- ===== Slow operation heuristic ===== -->
|
||||
<rect x="40" y="274" width="680" height="48" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="296" fill="#1e3a5f" font-size="11" font-weight="600">启发式判断:</text>
|
||||
<rect x="155" y="284" width="56" height="18" rx="4" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="183" y="297" fill="#16a34a" font-size="9" text-anchor="middle">fast</text>
|
||||
<text x="218" y="297" fill="#475569" font-size="9">read_file · git status · glob</text>
|
||||
<rect x="360" y="284" width="56" height="18" rx="4" fill="#fff7ed" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="388" y="297" fill="#ea580c" font-size="9" text-anchor="middle">slow</text>
|
||||
<text x="423" y="297" fill="#475569" font-size="9">npm install · pip install · pytest (timeout > 30s)</text>
|
||||
|
||||
<!-- ===== Timeline comparison ===== -->
|
||||
<rect x="40" y="340" width="330" height="84" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="205" y="360" fill="#991b1b" font-size="10" font-weight="700" text-anchor="middle">s12 同步阻塞</text>
|
||||
<rect x="60" y="370" width="80" height="14" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="381" fill="#1e40af" font-size="8" text-anchor="middle">思考</text>
|
||||
<rect x="145" y="370" width="160" height="14" rx="3" fill="#fecaca" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="225" y="381" fill="#991b1b" font-size="8" text-anchor="middle">等 bash 3 分钟...</text>
|
||||
<rect x="310" y="370" width="40" height="14" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="330" y="381" fill="#1e40af" font-size="7" text-anchor="middle">继续</text>
|
||||
<text x="60" y="410" fill="#991b1b" font-size="9">总耗时 ~3min,Agent 空 etc. 等了 3 分钟</text>
|
||||
|
||||
<rect x="390" y="340" width="330" height="84" rx="6" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="555" y="360" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">s13 后台执行</text>
|
||||
<rect x="410" y="370" width="80" height="14" rx="3" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="450" y="381" fill="#1e40af" font-size="8" text-anchor="middle">思考</text>
|
||||
<rect x="495" y="370" width="100" height="14" rx="3" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="545" y="381" fill="#166534" font-size="8" text-anchor="middle">继续做别的事</text>
|
||||
<rect x="600" y="370" width="100" height="14" rx="3" fill="#fff7ed" stroke="#ea580c" stroke-width="1"/>
|
||||
<text x="650" y="381" fill="#ea580c" font-size="8" text-anchor="middle">通知: 结果来了</text>
|
||||
<text x="410" y="410" fill="#166534" font-size="9">总耗时 ~3min,但 Agent 没闲着</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1,125 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 480" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#4f46e5"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-indigo" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4f46e5"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="480" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Cron Scheduler — Independent scheduler thread + cron_queue injection point</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f8fafc" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#64748b" font-size="10" font-weight="600">s10-s13 retained</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#4f46e5" font-size="10" font-weight="600">s14 new</text>
|
||||
|
||||
<!-- ===== Row 1: Full Agent Loop Chain ===== -->
|
||||
|
||||
<!-- consume_cron_queue (s14 new, indigo) -->
|
||||
<rect x="30" y="100" width="95" height="48" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="77" y="120" fill="#312e81" font-size="9" font-weight="700" text-anchor="middle">consume</text>
|
||||
<text x="77" y="134" fill="#312e81" font-size="9" font-weight="700" text-anchor="middle">cron_queue</text>
|
||||
<text x="77" y="144" fill="#94a3b8" font-size="7" text-anchor="middle">★ s14 injection</text>
|
||||
|
||||
<line x1="125" y1="124" x2="143" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- messages (s10) -->
|
||||
<rect x="146" y="100" width="80" height="48" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="186" y="128" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="226" y1="124" x2="244" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- prompt + cache (s10) -->
|
||||
<rect x="247" y="94" width="115" height="60" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="304" y="116" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + cache</text>
|
||||
<text x="304" y="130" fill="#94a3b8" font-size="8" text-anchor="middle">assemble_system_prompt</text>
|
||||
<text x="304" y="142" fill="#94a3b8" font-size="8" text-anchor="middle">(s10)</text>
|
||||
|
||||
<line x1="362" y1="124" x2="380" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- LLM call (s11 retry) -->
|
||||
<rect x="383" y="94" width="100" height="60" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="433" y="116" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM (try/except)</text>
|
||||
<text x="433" y="130" fill="#94a3b8" font-size="8" text-anchor="middle">with_retry</text>
|
||||
<text x="433" y="142" fill="#94a3b8" font-size="8" text-anchor="middle">(s11)</text>
|
||||
|
||||
<line x1="483" y1="124" x2="501" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- TOOL DISPATCH (expanded) -->
|
||||
<rect x="504" y="88" width="220" height="72" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="614" y="106" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH</text>
|
||||
<text x="519" y="122" fill="#2563eb" font-size="8">fast → sync (bash, read, write)</text>
|
||||
<text x="519" y="134" fill="#ea580c" font-size="8">slow → background thread (s13)</text>
|
||||
<text x="519" y="146" fill="#4f46e5" font-size="8" font-weight="600">cron → schedule_cron, list, cancel (s14)</text>
|
||||
<text x="519" y="156" fill="#2563eb" font-size="8">task → create, list, claim, complete (s12)</text>
|
||||
|
||||
<!-- Loop back arrow -->
|
||||
<path d="M 724 124 L 748 124 L 748 170 L 77 170 L 77 148" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
<text x="400" y="183" fill="#94a3b8" font-size="9" text-anchor="middle">loop back: tool_results → next turn</text>
|
||||
|
||||
<!-- ===== Row 2: Cron Scheduler Thread (indigo) ===== -->
|
||||
<rect x="30" y="206" width="250" height="90" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="155" y="226" fill="#312e81" font-size="11" font-weight="700" text-anchor="middle">cron_scheduler_loop (daemon thread)</text>
|
||||
<text x="48" y="244" fill="#4f46e5" font-size="9">time.sleep(1) → cron_matches(job.cron, now)</text>
|
||||
<text x="48" y="258" fill="#4f46e5" font-size="9">match → cron_queue.append(job)</text>
|
||||
<text x="48" y="272" fill="#6b7280" font-size="8">minute_marker prevents double-fire per minute</text>
|
||||
<text x="48" y="286" fill="#6b7280" font-size="8">one-shot jobs auto-delete after firing</text>
|
||||
|
||||
<!-- Arrow: scheduler → cron_queue -->
|
||||
<path d="M 155 296 L 155 330" fill="none" stroke="#4f46e5" stroke-width="1.5" marker-end="url(#arrow-indigo)"/>
|
||||
|
||||
<!-- cron_queue (indigo) -->
|
||||
<rect x="60" y="333" width="200" height="38" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="160" y="352" fill="#312e81" font-size="10" font-weight="700" text-anchor="middle">cron_queue</text>
|
||||
<text x="160" y="364" fill="#4f46e5" font-size="8" text-anchor="middle">cron_lock · scheduler writes · loop reads</text>
|
||||
|
||||
<!-- Arrow: cron_queue → consume_cron_queue (connects to top row) -->
|
||||
<path d="M 77 333 L 77 318 L 18 318 L 18 124 L 30 124" fill="none" stroke="#4f46e5" stroke-width="2" marker-end="url(#arrow-indigo)"/>
|
||||
<text x="95" y="313" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">next agent_loop consumes</text>
|
||||
|
||||
<!-- ===== Row 2 Right: CronJob + Storage ===== -->
|
||||
<rect x="320" y="206" width="410" height="90" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="525" y="226" fill="#312e81" font-size="11" font-weight="700" text-anchor="middle">CronJob + Persistence</text>
|
||||
<text x="338" y="244" fill="#4f46e5" font-size="9" font-weight="600">CronJob dataclass:</text>
|
||||
<text x="455" y="244" fill="#6b7280" font-size="8">id, cron, prompt, recurring, durable</text>
|
||||
<text x="338" y="260" fill="#4f46e5" font-size="9" font-weight="600">Durable → .scheduled_tasks.json</text>
|
||||
<text x="560" y="260" fill="#6b7280" font-size="8">restored via load_durable_jobs after restart</text>
|
||||
<text x="338" y="276" fill="#4f46e5" font-size="9" font-weight="600">Session-only → memory only</text>
|
||||
<text x="530" y="276" fill="#6b7280" font-size="8">lost when process exits</text>
|
||||
<text x="338" y="292" fill="#ef4444" font-size="9" font-weight="600">⚠ Process exit = scheduler stops (not OS-level crontab)</text>
|
||||
|
||||
<!-- ===== Row 3: 5-field cron reference ===== -->
|
||||
<rect x="30" y="390" width="700" height="76" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="412" fill="#1e3a5f" font-size="11" font-weight="600">5-field Cron Expression</text>
|
||||
<rect x="60" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="86" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="118" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="144" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="176" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="202" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="234" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="260" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="292" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="318" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<text x="60" y="455" fill="#94a3b8" font-size="8">min</text>
|
||||
<text x="130" y="455" fill="#94a3b8" font-size="8">hour</text>
|
||||
<text x="194" y="455" fill="#94a3b8" font-size="8">day</text>
|
||||
<text x="254" y="455" fill="#94a3b8" font-size="8">month</text>
|
||||
<text x="310" y="455" fill="#94a3b8" font-size="8">dow</text>
|
||||
|
||||
<text x="380" y="434" fill="#475569" font-size="9">*/5 * * * * → every 5 minutes</text>
|
||||
<text x="380" y="450" fill="#475569" font-size="9">0 9 * * 1-5 → weekdays 9:00</text>
|
||||
<text x="560" y="434" fill="#475569" font-size="9">0 9 * * * → daily 9:00</text>
|
||||
<text x="560" y="450" fill="#475569" font-size="9">Supports: *, */N, N, N-M, N,M,...</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
@@ -0,0 +1,125 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 480" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#4f46e5"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-indigo" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4f46e5"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="480" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Cron Scheduler — 独立スケジューラスレッド + cron_queue 注入ポイント</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f8fafc" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#64748b" font-size="10" font-weight="600">s10-s13 維持</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#4f46e5" font-size="10" font-weight="600">s14 新規</text>
|
||||
|
||||
<!-- ===== Row 1: Full Agent Loop Chain ===== -->
|
||||
|
||||
<!-- consume_cron_queue (s14 new, indigo) -->
|
||||
<rect x="30" y="100" width="95" height="48" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="77" y="120" fill="#312e81" font-size="9" font-weight="700" text-anchor="middle">consume</text>
|
||||
<text x="77" y="134" fill="#312e81" font-size="9" font-weight="700" text-anchor="middle">cron_queue</text>
|
||||
<text x="77" y="144" fill="#94a3b8" font-size="7" text-anchor="middle">★ s14 注入点</text>
|
||||
|
||||
<line x1="125" y1="124" x2="143" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- messages (s10) -->
|
||||
<rect x="146" y="100" width="80" height="48" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="186" y="128" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="226" y1="124" x2="244" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- prompt + cache (s10) -->
|
||||
<rect x="247" y="94" width="115" height="60" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="304" y="116" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + cache</text>
|
||||
<text x="304" y="130" fill="#94a3b8" font-size="8" text-anchor="middle">assemble_system_prompt</text>
|
||||
<text x="304" y="142" fill="#94a3b8" font-size="8" text-anchor="middle">(s10)</text>
|
||||
|
||||
<line x1="362" y1="124" x2="380" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- LLM call (s11 retry) -->
|
||||
<rect x="383" y="94" width="100" height="60" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="433" y="116" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM (try/except)</text>
|
||||
<text x="433" y="130" fill="#94a3b8" font-size="8" text-anchor="middle">with_retry</text>
|
||||
<text x="433" y="142" fill="#94a3b8" font-size="8" text-anchor="middle">(s11)</text>
|
||||
|
||||
<line x1="483" y1="124" x2="501" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- TOOL DISPATCH (expanded) -->
|
||||
<rect x="504" y="88" width="220" height="72" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="614" y="106" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH</text>
|
||||
<text x="519" y="122" fill="#2563eb" font-size="8">fast → sync (bash, read, write)</text>
|
||||
<text x="519" y="134" fill="#ea580c" font-size="8">slow → background thread (s13)</text>
|
||||
<text x="519" y="146" fill="#4f46e5" font-size="8" font-weight="600">cron → schedule_cron, list, cancel (s14)</text>
|
||||
<text x="519" y="156" fill="#2563eb" font-size="8">task → create, list, claim, complete (s12)</text>
|
||||
|
||||
<!-- Loop back arrow -->
|
||||
<path d="M 724 124 L 748 124 L 748 170 L 77 170 L 77 148" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
<text x="400" y="183" fill="#94a3b8" font-size="9" text-anchor="middle">loop back: tool_results → next turn</text>
|
||||
|
||||
<!-- ===== Row 2: Cron Scheduler Thread (indigo) ===== -->
|
||||
<rect x="30" y="206" width="250" height="90" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="155" y="226" fill="#312e81" font-size="11" font-weight="700" text-anchor="middle">cron_scheduler_loop (daemon スレッド)</text>
|
||||
<text x="48" y="244" fill="#4f46e5" font-size="9">time.sleep(1) → cron_matches(job.cron, now)</text>
|
||||
<text x="48" y="258" fill="#4f46e5" font-size="9">マッチ → cron_queue.append(job)</text>
|
||||
<text x="48" y="272" fill="#6b7280" font-size="8">minute_marker で同一分の重複発火を防止</text>
|
||||
<text x="48" y="286" fill="#6b7280" font-size="8">一度きりのタスクは発火後自動削除</text>
|
||||
|
||||
<!-- Arrow: scheduler → cron_queue -->
|
||||
<path d="M 155 296 L 155 330" fill="none" stroke="#4f46e5" stroke-width="1.5" marker-end="url(#arrow-indigo)"/>
|
||||
|
||||
<!-- cron_queue (indigo) -->
|
||||
<rect x="60" y="333" width="200" height="38" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="160" y="352" fill="#312e81" font-size="10" font-weight="700" text-anchor="middle">cron_queue</text>
|
||||
<text x="160" y="364" fill="#4f46e5" font-size="8" text-anchor="middle">cron_lock · スケジューラ書込 · loop 読込</text>
|
||||
|
||||
<!-- Arrow: cron_queue → consume_cron_queue (connects to top row) -->
|
||||
<path d="M 77 333 L 77 318 L 18 318 L 18 124 L 30 124" fill="none" stroke="#4f46e5" stroke-width="2" marker-end="url(#arrow-indigo)"/>
|
||||
<text x="80" y="313" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">次の agent_loop が消費</text>
|
||||
|
||||
<!-- ===== Row 2 Right: CronJob + Storage ===== -->
|
||||
<rect x="320" y="206" width="410" height="90" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="525" y="226" fill="#312e81" font-size="11" font-weight="700" text-anchor="middle">CronJob + 永続化</text>
|
||||
<text x="338" y="244" fill="#4f46e5" font-size="9" font-weight="600">CronJob dataclass:</text>
|
||||
<text x="455" y="244" fill="#6b7280" font-size="8">id, cron, prompt, recurring, durable</text>
|
||||
<text x="338" y="260" fill="#4f46e5" font-size="9" font-weight="600">Durable → .scheduled_tasks.json</text>
|
||||
<text x="560" y="260" fill="#6b7280" font-size="8">再起動後 load_durable_jobs で復元</text>
|
||||
<text x="338" y="276" fill="#4f46e5" font-size="9" font-weight="600">Session-only → メモリのみ</text>
|
||||
<text x="530" y="276" fill="#6b7280" font-size="8">プロセス終了で消失</text>
|
||||
<text x="338" y="292" fill="#ef4444" font-size="9" font-weight="600">⚠ プロセス終了 = スケジューラ停止(OS レベルの crontab ではない)</text>
|
||||
|
||||
<!-- ===== Row 3: 5-field cron reference ===== -->
|
||||
<rect x="30" y="390" width="700" height="76" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="412" fill="#1e3a5f" font-size="11" font-weight="600">5 フィールド Cron 式</text>
|
||||
<rect x="60" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="86" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="118" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="144" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="176" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="202" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="234" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="260" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="292" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="318" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<text x="60" y="455" fill="#94a3b8" font-size="8">分</text>
|
||||
<text x="130" y="455" fill="#94a3b8" font-size="8">時</text>
|
||||
<text x="194" y="455" fill="#94a3b8" font-size="8">日</text>
|
||||
<text x="254" y="455" fill="#94a3b8" font-size="8">月</text>
|
||||
<text x="310" y="455" fill="#94a3b8" font-size="8">曜日</text>
|
||||
|
||||
<text x="380" y="434" fill="#475569" font-size="9">*/5 * * * * → 5 分ごと</text>
|
||||
<text x="380" y="450" fill="#475569" font-size="9">0 9 * * 1-5 → 平日 9:00</text>
|
||||
<text x="560" y="434" fill="#475569" font-size="9">0 9 * * * → 毎日 9:00</text>
|
||||
<text x="560" y="450" fill="#475569" font-size="9">対応: *, */N, N, N-M, N,M,...</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.9 KiB |
@@ -0,0 +1,125 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 480" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#4f46e5"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-indigo" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4f46e5"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="480" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Cron Scheduler — 独立调度线程 + cron_queue 注入点</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f8fafc" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#64748b" font-size="10" font-weight="600">s10-s13 保留</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#4f46e5" font-size="10" font-weight="600">s14 新增</text>
|
||||
|
||||
<!-- ===== Row 1: Full Agent Loop Chain ===== -->
|
||||
|
||||
<!-- consume_cron_queue (s14 new, indigo) -->
|
||||
<rect x="30" y="100" width="95" height="48" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="77" y="120" fill="#312e81" font-size="9" font-weight="700" text-anchor="middle">consume</text>
|
||||
<text x="77" y="134" fill="#312e81" font-size="9" font-weight="700" text-anchor="middle">cron_queue</text>
|
||||
<text x="77" y="144" fill="#94a3b8" font-size="7" text-anchor="middle">★ s14 注入点</text>
|
||||
|
||||
<line x1="125" y1="124" x2="143" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- messages (s10) -->
|
||||
<rect x="146" y="100" width="80" height="48" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="186" y="128" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="226" y1="124" x2="244" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- prompt + cache (s10) -->
|
||||
<rect x="247" y="94" width="115" height="60" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="304" y="116" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + cache</text>
|
||||
<text x="304" y="130" fill="#94a3b8" font-size="8" text-anchor="middle">assemble_system_prompt</text>
|
||||
<text x="304" y="142" fill="#94a3b8" font-size="8" text-anchor="middle">(s10)</text>
|
||||
|
||||
<line x1="362" y1="124" x2="380" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- LLM call (s11 retry) -->
|
||||
<rect x="383" y="94" width="100" height="60" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="433" y="116" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM (try/except)</text>
|
||||
<text x="433" y="130" fill="#94a3b8" font-size="8" text-anchor="middle">with_retry</text>
|
||||
<text x="433" y="142" fill="#94a3b8" font-size="8" text-anchor="middle">(s11)</text>
|
||||
|
||||
<line x1="483" y1="124" x2="501" y2="124" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- TOOL DISPATCH (expanded) -->
|
||||
<rect x="504" y="88" width="220" height="72" rx="8" fill="#f8fafc" stroke="#94a3b8" stroke-width="1.2"/>
|
||||
<text x="614" y="106" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH</text>
|
||||
<text x="519" y="122" fill="#2563eb" font-size="8">fast → sync (bash, read, write)</text>
|
||||
<text x="519" y="134" fill="#ea580c" font-size="8">slow → background thread (s13)</text>
|
||||
<text x="519" y="146" fill="#4f46e5" font-size="8" font-weight="600">cron → schedule_cron, list, cancel (s14)</text>
|
||||
<text x="519" y="156" fill="#2563eb" font-size="8">task → create, list, claim, complete (s12)</text>
|
||||
|
||||
<!-- Loop back arrow -->
|
||||
<path d="M 724 124 L 748 124 L 748 170 L 77 170 L 77 148" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
<text x="400" y="183" fill="#94a3b8" font-size="9" text-anchor="middle">loop back: tool_results → next turn</text>
|
||||
|
||||
<!-- ===== Row 2: Cron Scheduler Thread (indigo) ===== -->
|
||||
<rect x="30" y="206" width="250" height="90" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="155" y="226" fill="#312e81" font-size="11" font-weight="700" text-anchor="middle">cron_scheduler_loop(独立 daemon 线程)</text>
|
||||
<text x="48" y="244" fill="#4f46e5" font-size="9">time.sleep(1) → cron_matches(job.cron, now)</text>
|
||||
<text x="48" y="258" fill="#4f46e5" font-size="9">匹配 → cron_queue.append(job)</text>
|
||||
<text x="48" y="272" fill="#6b7280" font-size="8">minute_marker 防同分钟重复触发</text>
|
||||
<text x="48" y="286" fill="#6b7280" font-size="8">一次性任务触发后自动删除</text>
|
||||
|
||||
<!-- Arrow: scheduler → cron_queue -->
|
||||
<path d="M 155 296 L 155 330" fill="none" stroke="#4f46e5" stroke-width="1.5" marker-end="url(#arrow-indigo)"/>
|
||||
|
||||
<!-- cron_queue (indigo) -->
|
||||
<rect x="60" y="333" width="200" height="38" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="160" y="352" fill="#312e81" font-size="10" font-weight="700" text-anchor="middle">cron_queue</text>
|
||||
<text x="160" y="364" fill="#4f46e5" font-size="8" text-anchor="middle">cron_lock 保护 · 调度线程写 · agent_loop 读</text>
|
||||
|
||||
<!-- Arrow: cron_queue → consume_cron_queue (connects to top row) -->
|
||||
<path d="M 77 333 L 77 318 L 18 318 L 18 124 L 30 124" fill="none" stroke="#4f46e5" stroke-width="2" marker-end="url(#arrow-indigo)"/>
|
||||
<text x="72" y="313" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">下次 agent_loop 消费</text>
|
||||
|
||||
<!-- ===== Row 2 Right: CronJob + Storage ===== -->
|
||||
<rect x="320" y="206" width="410" height="90" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="2"/>
|
||||
<text x="525" y="226" fill="#312e81" font-size="11" font-weight="700" text-anchor="middle">CronJob + 持久化</text>
|
||||
<text x="338" y="244" fill="#4f46e5" font-size="9" font-weight="600">CronJob dataclass:</text>
|
||||
<text x="455" y="244" fill="#6b7280" font-size="8">id, cron, prompt, recurring, durable</text>
|
||||
<text x="338" y="260" fill="#4f46e5" font-size="9" font-weight="600">Durable → .scheduled_tasks.json</text>
|
||||
<text x="560" y="260" fill="#6b7280" font-size="8">重启后 load_durable_jobs 恢复</text>
|
||||
<text x="338" y="276" fill="#4f46e5" font-size="9" font-weight="600">Session-only → 内存 only</text>
|
||||
<text x="530" y="276" fill="#6b7280" font-size="8">进程关闭即丢</text>
|
||||
<text x="338" y="292" fill="#ef4444" font-size="9" font-weight="600">⚠ 进程关闭 = 调度停止(不是 OS 级 crontab)</text>
|
||||
|
||||
<!-- ===== Row 3: 5-field cron reference ===== -->
|
||||
<rect x="30" y="390" width="700" height="76" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="60" y="412" fill="#1e3a5f" font-size="11" font-weight="600">五段式 Cron 表达式</text>
|
||||
<rect x="60" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="86" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="118" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="144" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="176" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="202" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="234" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="260" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<rect x="292" y="422" width="52" height="16" rx="3" fill="#eef2ff" stroke="#4f46e5" stroke-width="1"/>
|
||||
<text x="318" y="434" fill="#4f46e5" font-size="9" text-anchor="middle">*</text>
|
||||
<text x="60" y="455" fill="#94a3b8" font-size="8">分钟</text>
|
||||
<text x="130" y="455" fill="#94a3b8" font-size="8">小时</text>
|
||||
<text x="194" y="455" fill="#94a3b8" font-size="8">日</text>
|
||||
<text x="254" y="455" fill="#94a3b8" font-size="8">月</text>
|
||||
<text x="310" y="455" fill="#94a3b8" font-size="8">星期</text>
|
||||
|
||||
<text x="380" y="434" fill="#475569" font-size="9">*/5 * * * * → 每 5 分钟</text>
|
||||
<text x="380" y="450" fill="#475569" font-size="9">0 9 * * 1-5 → 工作日 9:00</text>
|
||||
<text x="560" y="434" fill="#475569" font-size="9">0 9 * * * → 每天 9:00</text>
|
||||
<text x="560" y="450" fill="#475569" font-size="9">支持: *, */N, N, N-M, N,M,...</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
@@ -0,0 +1,120 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 470" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#0891b2"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0891b2"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="470" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Agent Teams — Lead Loop + Teammate Threads + MessageBus</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s10-s14 Preserved</text>
|
||||
<rect x="180" y="56" width="12" height="10" rx="2" fill="#ecfeff" stroke="#0891b2" stroke-width="1"/>
|
||||
<text x="198" y="66" fill="#0891b2" font-size="10" font-weight="600">s15 New</text>
|
||||
<rect x="280" y="56" width="12" height="10" rx="2" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="298" y="66" fill="#16a34a" font-size="10" font-weight="600">Teammate</text>
|
||||
<rect x="395" y="56" width="12" height="10" rx="2" fill="#fffbeb" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="413" y="66" fill="#d97706" font-size="10" font-weight="600">Real CC detail</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Agent Loop ===== -->
|
||||
<rect x="28" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="63" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">cron_queue</text>
|
||||
|
||||
<line x1="98" y1="110" x2="112" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="115" y="90" width="72" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="151" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="187" y1="110" x2="201" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="204" y="86" width="86" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="247" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + cache</text>
|
||||
|
||||
<line x1="290" y1="110" x2="304" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="307" y="86" width="74" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="344" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM call</text>
|
||||
|
||||
<line x1="381" y1="110" x2="395" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="398" y="80" width="336" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="566" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH</text>
|
||||
<text x="414" y="114" fill="#2563eb" font-size="8">bash · read · write · task(4) · cron(3)</text>
|
||||
<text x="414" y="128" fill="#0891b2" font-size="8" font-weight="700">★ spawn_teammate · send_message · check_inbox</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 63 150 L 63 130" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== Spawn arrow: TOOLS bottom → MessageBus top ===== -->
|
||||
<line x1="560" y1="140" x2="560" y2="178" stroke="#0891b2" stroke-width="2" marker-end="url(#arrow-cyan)"/>
|
||||
<rect x="543" y="152" width="38" height="14" rx="3" fill="#ecfeff"/>
|
||||
<text x="562" y="163" fill="#0891b2" font-size="8" font-weight="600" text-anchor="middle">spawn</text>
|
||||
|
||||
<!-- ===== Row 2: MessageBus ===== -->
|
||||
<rect x="60" y="178" width="640" height="34" rx="17" fill="#ecfeff" stroke="#0891b2" stroke-width="2"/>
|
||||
<text x="380" y="200" fill="#0e7490" font-size="11" font-weight="700" text-anchor="middle">MessageBus (.mailboxes/*.jsonl)</text>
|
||||
|
||||
<!-- ===== Row 3: Teammates ===== -->
|
||||
<line x1="170" y1="212" x2="170" y2="248" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<line x1="380" y1="212" x2="380" y2="248" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<line x1="590" y1="212" x2="590" y2="248" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="124" y="226" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="334" y="226" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="544" y="226" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
|
||||
<line x1="200" y1="248" x2="200" y2="212" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="410" y1="248" x2="410" y2="212" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="620" y1="248" x2="620" y2="212" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="214" y="241" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="424" y="241" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="634" y="241" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
|
||||
<rect x="60" y="248" width="220" height="66" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="170" y="268" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Teammate: alice (Backend)</text>
|
||||
<text x="75" y="284" fill="#16a34a" font-size="8">inbox → LLM → bash/read/write/send</text>
|
||||
<text x="75" y="298" fill="#6b7280" font-size="8">Max 10 rounds → summary → BUS.send</text>
|
||||
|
||||
<rect x="270" y="248" width="220" height="66" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="380" y="268" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Teammate: bob (Frontend)</text>
|
||||
<text x="285" y="284" fill="#16a34a" font-size="8">Independent agent_loop, shared client</text>
|
||||
<text x="285" y="298" fill="#6b7280" font-size="8">Thread(daemon=True)</text>
|
||||
|
||||
<rect x="480" y="248" width="220" height="66" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="590" y="268" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Teammate: charlie (QA)</text>
|
||||
<text x="495" y="284" fill="#16a34a" font-size="8">Cannot spawn other teammates</text>
|
||||
<text x="495" y="298" fill="#6b7280" font-size="8">spawn → work → summary</text>
|
||||
|
||||
<!-- ===== Row 4: Permission bubbling (real CC detail) ===== -->
|
||||
<path d="M 60 360 L 10 360 L 10 195 L 60 195" fill="none" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow-amber)" stroke-dasharray="5,3"/>
|
||||
<rect x="20" y="318" width="126" height="18" rx="4" fill="#fffbeb" stroke="#f59e0b" stroke-width="1"/>
|
||||
<text x="83" y="331" fill="#d97706" font-size="10" font-weight="700" text-anchor="middle">permission_request</text>
|
||||
|
||||
<rect x="60" y="340" width="640" height="50" rx="6" fill="#fffbeb" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="380" y="360" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Permission Bubbling (real CC; omitted in teaching code)</text>
|
||||
<text x="80" y="378" fill="#78716c" font-size="9">① Teammate needs approval → MessageBus sends permission_request ② Lead receives → user approval → approve/deny</text>
|
||||
|
||||
<!-- ===== Row 5: Bottom notes ===== -->
|
||||
<rect x="60" y="410" width="640" height="44" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="80" y="424" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="434" fill="#475569" font-size="10">s10-s14: prompt assembly, error recovery, task graph, background threads, cron scheduling</text>
|
||||
<rect x="80" y="440" width="12" height="10" rx="2" fill="#ecfeff" stroke="#0891b2" stroke-width="1"/>
|
||||
<text x="100" y="450" fill="#475569" font-size="10">s15: MessageBus + spawn_teammate_thread + send_message + check_inbox (permission bubbling is a real CC detail)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
@@ -0,0 +1,120 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 470" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#0891b2"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0891b2"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="470" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- タイトル -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Agent Teams — Lead ループ + チームメイトスレッド + MessageBus</text>
|
||||
|
||||
<!-- 凡例 -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s10-s14 保持</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#ecfeff" stroke="#0891b2" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#0891b2" font-size="10" font-weight="600">s15 新規</text>
|
||||
<rect x="260" y="56" width="12" height="10" rx="2" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="278" y="66" fill="#16a34a" font-size="10" font-weight="600">チームメイト</text>
|
||||
<rect x="390" y="56" width="12" height="10" rx="2" fill="#fffbeb" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="408" y="66" fill="#d97706" font-size="10" font-weight="600">真实 CC 補足</text>
|
||||
|
||||
<!-- ===== 行 1: Lead Agent ループ ===== -->
|
||||
<rect x="28" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="63" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">cron_queue</text>
|
||||
|
||||
<line x1="98" y1="110" x2="112" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="115" y="90" width="72" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="151" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="187" y1="110" x2="201" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="204" y="86" width="86" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="247" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + cache</text>
|
||||
|
||||
<line x1="290" y1="110" x2="304" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="307" y="86" width="74" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="344" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM call</text>
|
||||
|
||||
<line x1="381" y1="110" x2="395" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="398" y="80" width="336" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="566" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH</text>
|
||||
<text x="414" y="114" fill="#2563eb" font-size="8">bash · read · write · task(4) · cron(3)</text>
|
||||
<text x="414" y="128" fill="#0891b2" font-size="8" font-weight="700">★ spawn_teammate · send_message · check_inbox</text>
|
||||
|
||||
<!-- ループバック -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 63 150 L 63 130" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== spawn 矢印 ===== -->
|
||||
<line x1="560" y1="140" x2="560" y2="178" stroke="#0891b2" stroke-width="2" marker-end="url(#arrow-cyan)"/>
|
||||
<rect x="543" y="152" width="38" height="14" rx="3" fill="#ecfeff"/>
|
||||
<text x="562" y="163" fill="#0891b2" font-size="8" font-weight="600" text-anchor="middle">spawn</text>
|
||||
|
||||
<!-- ===== 行 2: MessageBus ===== -->
|
||||
<rect x="60" y="178" width="640" height="34" rx="17" fill="#ecfeff" stroke="#0891b2" stroke-width="2"/>
|
||||
<text x="380" y="200" fill="#0e7490" font-size="11" font-weight="700" text-anchor="middle">MessageBus (.mailboxes/*.jsonl)</text>
|
||||
|
||||
<!-- ===== 行 3: チームメイト ===== -->
|
||||
<line x1="170" y1="212" x2="170" y2="248" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<line x1="380" y1="212" x2="380" y2="248" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<line x1="590" y1="212" x2="590" y2="248" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="124" y="226" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="334" y="226" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="544" y="226" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
|
||||
<line x1="200" y1="248" x2="200" y2="212" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="410" y1="248" x2="410" y2="212" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="620" y1="248" x2="620" y2="212" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="214" y="241" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="424" y="241" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="634" y="241" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
|
||||
<rect x="60" y="248" width="220" height="66" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="170" y="268" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">チームメイト: alice (Backend)</text>
|
||||
<text x="75" y="284" fill="#16a34a" font-size="8">inbox → LLM → bash/read/write/send</text>
|
||||
<text x="75" y="298" fill="#6b7280" font-size="8">最大 10 ラウンド → summary → BUS.send</text>
|
||||
|
||||
<rect x="270" y="248" width="220" height="66" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="380" y="268" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">チームメイト: bob (Frontend)</text>
|
||||
<text x="285" y="284" fill="#16a34a" font-size="8">独立 agent_loop、共有 client</text>
|
||||
<text x="285" y="298" fill="#6b7280" font-size="8">Thread(daemon=True)</text>
|
||||
|
||||
<rect x="480" y="248" width="220" height="66" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="590" y="268" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">チームメイト: charlie (QA)</text>
|
||||
<text x="495" y="284" fill="#16a34a" font-size="8">他のチームメイトを spawn 不可</text>
|
||||
<text x="495" y="298" fill="#6b7280" font-size="8">spawn → work → summary</text>
|
||||
|
||||
<!-- ===== 行 4: 権限バブリング(real CC detail) ===== -->
|
||||
<path d="M 60 360 L 10 360 L 10 195 L 60 195" fill="none" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow-amber)" stroke-dasharray="5,3"/>
|
||||
<rect x="20" y="318" width="126" height="18" rx="4" fill="#fffbeb" stroke="#f59e0b" stroke-width="1"/>
|
||||
<text x="83" y="331" fill="#d97706" font-size="10" font-weight="700" text-anchor="middle">permission_request</text>
|
||||
|
||||
<rect x="60" y="340" width="640" height="50" rx="6" fill="#fffbeb" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="380" y="360" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">権限バブリング(真实 CC、教学版は省略)</text>
|
||||
<text x="80" y="378" fill="#78716c" font-size="9">① 承認が必要 → MessageBus が permission_request 送信 ② Lead が受信 → ユーザー承認 → approve/deny</text>
|
||||
|
||||
<!-- ===== 行 5: 下部ノート ===== -->
|
||||
<rect x="60" y="410" width="640" height="44" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="80" y="424" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="434" fill="#475569" font-size="10">s10-s14:プロンプト組み立て、エラーリカバリ、タスクグラフ、バックグラウンドスレッド、cron</text>
|
||||
<rect x="80" y="440" width="12" height="10" rx="2" fill="#ecfeff" stroke="#0891b2" stroke-width="1"/>
|
||||
<text x="100" y="450" fill="#475569" font-size="10">s15:MessageBus + spawn_teammate_thread + send_message + check_inbox(権限バブリングは真实 CC 補足)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.9 KiB |
@@ -0,0 +1,132 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 470" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#0891b2"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0891b2"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="470" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Agent Teams — Lead Loop + Teammate Threads + MessageBus</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s10-s14 保留</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#ecfeff" stroke="#0891b2" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#0891b2" font-size="10" font-weight="600">s15 新增</text>
|
||||
<rect x="270" y="56" width="12" height="10" rx="2" fill="#f0fdf4" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="288" y="66" fill="#16a34a" font-size="10" font-weight="600">Teammate</text>
|
||||
<rect x="390" y="56" width="12" height="10" rx="2" fill="#fffbeb" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="408" y="66" fill="#d97706" font-size="10" font-weight="600">真实 CC 补充</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Agent Loop ===== -->
|
||||
<!-- Boxes at y=90..130 (h=40), prompt/LLM at y=86..134 (h=48), TOOLS at y=80..140 (h=60) -->
|
||||
|
||||
<rect x="28" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="63" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">cron_queue</text>
|
||||
|
||||
<line x1="98" y1="110" x2="112" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="115" y="90" width="72" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="151" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="187" y1="110" x2="201" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="204" y="86" width="86" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="247" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt + cache</text>
|
||||
|
||||
<line x1="290" y1="110" x2="304" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="307" y="86" width="74" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="344" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM call</text>
|
||||
|
||||
<line x1="381" y1="110" x2="395" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="398" y="80" width="336" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="566" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH</text>
|
||||
<text x="414" y="114" fill="#2563eb" font-size="8">bash · read · write · task(4) · cron(3)</text>
|
||||
<text x="414" y="128" fill="#0891b2" font-size="8" font-weight="700">★ spawn_teammate · send_message · check_inbox</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 63 150 L 63 130" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)" stroke-dasharray="6,3"/>
|
||||
|
||||
<!-- ===== Spawn arrow: TOOLS bottom → MessageBus top ===== -->
|
||||
<!-- TOOLS bottom: y=140, Bus top: y=178 -->
|
||||
<line x1="560" y1="140" x2="560" y2="178" stroke="#0891b2" stroke-width="2" marker-end="url(#arrow-cyan)"/>
|
||||
<rect x="543" y="152" width="38" height="14" rx="3" fill="#ecfeff"/>
|
||||
<text x="562" y="163" fill="#0891b2" font-size="8" font-weight="600" text-anchor="middle">spawn</text>
|
||||
|
||||
<!-- ===== Row 2: MessageBus ===== -->
|
||||
<!-- y=178..212 (h=34) -->
|
||||
<rect x="60" y="178" width="640" height="34" rx="17" fill="#ecfeff" stroke="#0891b2" stroke-width="2"/>
|
||||
<text x="380" y="200" fill="#0e7490" font-size="11" font-weight="700" text-anchor="middle">MessageBus (.mailboxes/*.jsonl)</text>
|
||||
|
||||
<!-- ===== Row 3: Teammates ===== -->
|
||||
<!-- Bus bottom: y=212, Teammate top: y=248 (gap=36) -->
|
||||
|
||||
<!-- Bus → Teammate: incoming arrows (solid green) -->
|
||||
<line x1="170" y1="212" x2="170" y2="248" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<line x1="380" y1="212" x2="380" y2="248" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<line x1="590" y1="212" x2="590" y2="248" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="124" y="226" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="334" y="226" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="544" y="226" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
|
||||
<!-- Teammate → Bus: send_message (dashed cyan, offset 30px right) -->
|
||||
<line x1="200" y1="248" x2="200" y2="212" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="410" y1="248" x2="410" y2="212" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="620" y1="248" x2="620" y2="212" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="214" y="241" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="424" y="241" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="634" y="241" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
|
||||
<!-- alice: x=60..280, y=248..314 -->
|
||||
<rect x="60" y="248" width="220" height="66" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="170" y="268" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Teammate: alice (Backend)</text>
|
||||
<text x="75" y="284" fill="#16a34a" font-size="8">inbox → LLM → bash/read/write/send</text>
|
||||
<text x="75" y="298" fill="#6b7280" font-size="8">最多 10 轮 → summary → BUS.send</text>
|
||||
|
||||
<!-- bob: x=270..490, y=248..314 -->
|
||||
<rect x="270" y="248" width="220" height="66" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="380" y="268" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Teammate: bob (Frontend)</text>
|
||||
<text x="285" y="284" fill="#16a34a" font-size="8">独立 agent_loop,共享 client</text>
|
||||
<text x="285" y="298" fill="#6b7280" font-size="8">Thread(daemon=True)</text>
|
||||
|
||||
<!-- charlie: x=480..700, y=248..314 -->
|
||||
<rect x="480" y="248" width="220" height="66" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="590" y="268" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Teammate: charlie (QA)</text>
|
||||
<text x="495" y="284" fill="#16a34a" font-size="8">不能 spawn 其他 teammate</text>
|
||||
<text x="495" y="298" fill="#6b7280" font-size="8">spawn → work → summary</text>
|
||||
|
||||
<!-- ===== Row 4: Permission bubbling (real CC detail) ===== -->
|
||||
<!-- Permission request goes through MessageBus, then Lead check_inbox handles it. -->
|
||||
<path d="M 60 360 L 10 360 L 10 195 L 60 195" fill="none" stroke="#d97706" stroke-width="1.5" marker-end="url(#arrow-amber)" stroke-dasharray="5,3"/>
|
||||
<rect x="20" y="318" width="126" height="18" rx="4" fill="#fffbeb" stroke="#f59e0b" stroke-width="1"/>
|
||||
<text x="83" y="331" fill="#d97706" font-size="10" font-weight="700" text-anchor="middle">permission_request</text>
|
||||
|
||||
<rect x="60" y="340" width="640" height="50" rx="6" fill="#fffbeb" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="380" y="360" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">权限冒泡(真实 CC,教学版省略)</text>
|
||||
<text x="80" y="378" fill="#78716c" font-size="9">① 队友需审批 → MessageBus 发送 permission_request ② Lead 收到 → 用户审批 → 回复 approve/deny</text>
|
||||
|
||||
<!-- ===== Row 5: Bottom notes ===== -->
|
||||
<rect x="60" y="410" width="640" height="44" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="80" y="424" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="100" y="434" fill="#475569" font-size="10">s10-s14: prompt 组装、错误恢复、任务图、后台线程、cron 调度</text>
|
||||
<rect x="80" y="440" width="12" height="10" rx="2" fill="#ecfeff" stroke="#0891b2" stroke-width="1"/>
|
||||
<text x="100" y="450" fill="#475569" font-size="10">s15: MessageBus + spawn_teammate_thread + send_message + check_inbox(权限冒泡见真实 CC 补充)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.3 KiB |
@@ -0,0 +1,65 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 296" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#0891b2"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0891b2"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="296" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Team Topology — Lead ↔ MessageBus ↔ Teammates</text>
|
||||
|
||||
<!-- Lead -->
|
||||
<rect x="260" y="58" width="200" height="68" rx="8" fill="#ecfeff" stroke="#0891b2" stroke-width="2"/>
|
||||
<text x="360" y="82" fill="#0e7490" font-size="13" font-weight="700" text-anchor="middle">Lead Agent</text>
|
||||
<text x="360" y="100" fill="#0e7490" font-size="10" text-anchor="middle">Main loop + spawn + inbox handling</text>
|
||||
<text x="360" y="116" fill="#0e7490" font-size="10" text-anchor="middle">check_inbox receives teammate messages</text>
|
||||
|
||||
<!-- Message Bus -->
|
||||
<rect x="80" y="150" width="560" height="26" rx="13" fill="#fef3c7" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="360" y="168" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Message Bus (.mailboxes/*.jsonl)</text>
|
||||
|
||||
<!-- Teammates -->
|
||||
<rect x="40" y="214" width="180" height="60" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="130" y="238" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">Alice (Backend)</text>
|
||||
<text x="130" y="254" fill="#166534" font-size="9" text-anchor="middle">own loop → inbox → work → reply</text>
|
||||
|
||||
<rect x="270" y="214" width="180" height="60" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="360" y="238" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">Bob (Frontend)</text>
|
||||
<text x="360" y="254" fill="#166534" font-size="9" text-anchor="middle">own loop → inbox → work → reply</text>
|
||||
|
||||
<rect x="500" y="214" width="180" height="60" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="590" y="238" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">Charlie (QA)</text>
|
||||
<text x="590" y="254" fill="#166534" font-size="9" text-anchor="middle">own loop → inbox → work → reply</text>
|
||||
|
||||
<!-- Lead ↔ Bus -->
|
||||
<line x1="330" y1="126" x2="330" y2="150" stroke="#0891b2" stroke-width="1.5" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="300" y="142" fill="#0891b2" font-size="7">send</text>
|
||||
<line x1="390" y1="150" x2="390" y2="126" stroke="#0891b2" stroke-width="1.5" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="398" y="142" fill="#0891b2" font-size="7">inbox</text>
|
||||
|
||||
<!-- Bus → Teammates -->
|
||||
<line x1="120" y1="176" x2="120" y2="214" stroke="#555" stroke-width="1" marker-end="url(#arrow)"/>
|
||||
<line x1="350" y1="176" x2="350" y2="214" stroke="#555" stroke-width="1" marker-end="url(#arrow)"/>
|
||||
<line x1="570" y1="176" x2="570" y2="214" stroke="#555" stroke-width="1" marker-end="url(#arrow)"/>
|
||||
<text x="82" y="195" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="312" y="195" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="532" y="195" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<line x1="140" y1="214" x2="140" y2="176" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="370" y1="214" x2="370" y2="176" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="590" y1="214" x2="590" y2="176" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="145" y="203" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="375" y="203" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="595" y="203" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1,65 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 296" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#0891b2"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0891b2"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="296" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Team Topology — Lead ↔ MessageBus ↔ チームメイト</text>
|
||||
|
||||
<!-- Lead -->
|
||||
<rect x="260" y="58" width="200" height="68" rx="8" fill="#ecfeff" stroke="#0891b2" stroke-width="2"/>
|
||||
<text x="360" y="82" fill="#0e7490" font-size="13" font-weight="700" text-anchor="middle">Lead Agent</text>
|
||||
<text x="360" y="100" fill="#0e7490" font-size="10" text-anchor="middle">メインループ + spawn + inbox 処理</text>
|
||||
<text x="360" y="116" fill="#0e7490" font-size="10" text-anchor="middle">check_inbox でチームメイトのメッセージ受信</text>
|
||||
|
||||
<!-- Message Bus -->
|
||||
<rect x="80" y="150" width="560" height="26" rx="13" fill="#fef3c7" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="360" y="168" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Message Bus (.mailboxes/*.jsonl)</text>
|
||||
|
||||
<!-- チームメイト -->
|
||||
<rect x="40" y="214" width="180" height="60" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="130" y="238" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">Alice (Backend)</text>
|
||||
<text x="130" y="254" fill="#166534" font-size="9" text-anchor="middle">独立 loop → inbox → 作業 → 返信</text>
|
||||
|
||||
<rect x="270" y="214" width="180" height="60" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="360" y="238" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">Bob (Frontend)</text>
|
||||
<text x="360" y="254" fill="#166534" font-size="9" text-anchor="middle">独立 loop → inbox → 作業 → 返信</text>
|
||||
|
||||
<rect x="500" y="214" width="180" height="60" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="590" y="238" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">Charlie (QA)</text>
|
||||
<text x="590" y="254" fill="#166534" font-size="9" text-anchor="middle">独立 loop → inbox → 作業 → 返信</text>
|
||||
|
||||
<!-- Lead ↔ Bus -->
|
||||
<line x1="330" y1="126" x2="330" y2="150" stroke="#0891b2" stroke-width="1.5" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="300" y="142" fill="#0891b2" font-size="7">send</text>
|
||||
<line x1="390" y1="150" x2="390" y2="126" stroke="#0891b2" stroke-width="1.5" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="398" y="142" fill="#0891b2" font-size="7">inbox</text>
|
||||
|
||||
<!-- Bus → チームメイト -->
|
||||
<line x1="120" y1="176" x2="120" y2="214" stroke="#555" stroke-width="1" marker-end="url(#arrow)"/>
|
||||
<line x1="350" y1="176" x2="350" y2="214" stroke="#555" stroke-width="1" marker-end="url(#arrow)"/>
|
||||
<line x1="570" y1="176" x2="570" y2="214" stroke="#555" stroke-width="1" marker-end="url(#arrow)"/>
|
||||
<text x="82" y="195" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="312" y="195" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="532" y="195" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<line x1="140" y1="214" x2="140" y2="176" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="370" y1="214" x2="370" y2="176" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="590" y1="214" x2="590" y2="176" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="145" y="203" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="375" y="203" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="595" y="203" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
72
web/public/course-assets/s15_agent_teams/team-topology.svg
Normal file
@@ -0,0 +1,72 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 296" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#0891b2"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0891b2"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber-left" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 10 0 L 0 5 L 10 10 z" fill="#d97706"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="720" height="296" fill="#fafbfc" rx="8"/>
|
||||
<rect x="0" y="0" width="720" height="38" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="30" width="720" height="8" fill="url(#header)"/>
|
||||
<text x="360" y="25" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Team Topology — Lead ↔ MessageBus ↔ Teammates</text>
|
||||
|
||||
<!-- Lead: x=260..460, y=58..126 -->
|
||||
<rect x="260" y="58" width="200" height="68" rx="8" fill="#ecfeff" stroke="#0891b2" stroke-width="2"/>
|
||||
<text x="360" y="82" fill="#0e7490" font-size="13" font-weight="700" text-anchor="middle">Lead Agent</text>
|
||||
<text x="360" y="100" fill="#0e7490" font-size="10" text-anchor="middle">主循环 + spawn + inbox 处理</text>
|
||||
<text x="360" y="116" fill="#0e7490" font-size="10" text-anchor="middle">check_inbox 接收队友消息</text>
|
||||
|
||||
<!-- Message Bus: x=80..640, y=150..176 (26px tall) -->
|
||||
<rect x="80" y="150" width="560" height="26" rx="13" fill="#fef3c7" stroke="#d97706" stroke-width="1.5"/>
|
||||
<text x="360" y="168" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Message Bus (.mailboxes/*.jsonl)</text>
|
||||
|
||||
<!-- Teammates: y=214..274 (60px tall) -->
|
||||
<rect x="40" y="214" width="180" height="60" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="130" y="238" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">Alice (Backend)</text>
|
||||
<text x="130" y="254" fill="#166534" font-size="9" text-anchor="middle">独立 loop → inbox → 干活 → 回复</text>
|
||||
|
||||
<rect x="270" y="214" width="180" height="60" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="360" y="238" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">Bob (Frontend)</text>
|
||||
<text x="360" y="254" fill="#166534" font-size="9" text-anchor="middle">独立 loop → inbox → 干活 → 回复</text>
|
||||
|
||||
<rect x="500" y="214" width="180" height="60" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="590" y="238" fill="#166534" font-size="12" font-weight="700" text-anchor="middle">Charlie (QA)</text>
|
||||
<text x="590" y="254" fill="#166534" font-size="9" text-anchor="middle">独立 loop → inbox → 干活 → 回复</text>
|
||||
|
||||
<!-- ===== Lead ↔ Bus (gap: 126→150 = 24px) ===== -->
|
||||
<!-- Lead → Bus (send/spawn): x=330 -->
|
||||
<line x1="330" y1="126" x2="330" y2="150" stroke="#0891b2" stroke-width="1.5" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="300" y="142" fill="#0891b2" font-size="7">send</text>
|
||||
<!-- Bus → Lead (inbox delivery): x=390 -->
|
||||
<line x1="390" y1="150" x2="390" y2="126" stroke="#0891b2" stroke-width="1.5" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="398" y="142" fill="#0891b2" font-size="7">inbox</text>
|
||||
|
||||
<!-- ===== Bus → Teammates (gap: 176→214 = 38px) ===== -->
|
||||
<!-- Incoming (solid): from Bus bottom to Teammate top -->
|
||||
<line x1="120" y1="176" x2="120" y2="214" stroke="#555" stroke-width="1" marker-end="url(#arrow)"/>
|
||||
<line x1="350" y1="176" x2="350" y2="214" stroke="#555" stroke-width="1" marker-end="url(#arrow)"/>
|
||||
<line x1="570" y1="176" x2="570" y2="214" stroke="#555" stroke-width="1" marker-end="url(#arrow)"/>
|
||||
<text x="82" y="195" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="312" y="195" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<text x="532" y="195" fill="#16a34a" font-size="9" font-weight="600">receive</text>
|
||||
<!-- Outgoing / send_message back (dashed, offset 20px right) -->
|
||||
<line x1="140" y1="214" x2="140" y2="176" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="370" y1="214" x2="370" y2="176" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<line x1="590" y1="214" x2="590" y2="176" stroke="#0891b2" stroke-width="1" stroke-dasharray="4,2" marker-end="url(#arrow-cyan)"/>
|
||||
<text x="145" y="203" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="375" y="203" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
<text x="595" y="203" fill="#0891b2" font-size="9" font-weight="600">send</text>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
@@ -0,0 +1,143 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 500" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#7c3aed"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0891b2"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="500" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Team Protocols — Request-Response + request_id Correlation + State Machine</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s15 Preserved</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#7c3aed" font-size="10" font-weight="600">s16 New</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="80" width="356" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH (core tool set)</text>
|
||||
<text x="394" y="114" fill="#2563eb" font-size="8">bash · read · write · task(4) · spawn · send · inbox</text>
|
||||
<text x="394" y="128" fill="#7c3aed" font-size="8" font-weight="700">★ request_shutdown · request_plan · review_plan</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- ===== Row 2: Protocol Flow (purple) — request_id lifecycle ===== -->
|
||||
<rect x="30" y="176" width="700" height="100" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="380" y="196" fill="#4c1d95" font-size="11" font-weight="700" text-anchor="middle">Request-Response Protocol Flow (request_id throughout)</text>
|
||||
|
||||
<!-- Step 1: Send request -->
|
||||
<rect x="50" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="115" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">① Lead sends request</text>
|
||||
<text x="115" y="240" fill="#6b7280" font-size="7" text-anchor="middle">BUS.send("shutdown_request"</text>
|
||||
<text x="115" y="252" fill="#6b7280" font-size="7" text-anchor="middle">metadata={request_id})</text>
|
||||
|
||||
<line x1="180" y1="234" x2="206" y2="234" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Step 2: Teammate receives & dispatches -->
|
||||
<rect x="209" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="274" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">② Teammate receives</text>
|
||||
<text x="274" y="240" fill="#6b7280" font-size="7" text-anchor="middle">dispatch_by_type(inbox)</text>
|
||||
<text x="274" y="252" fill="#6b7280" font-size="7" text-anchor="middle">→ handler(type, metadata)</text>
|
||||
|
||||
<line x1="339" y1="234" x2="365" y2="234" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Step 3: Teammate processes & responds -->
|
||||
<rect x="368" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="433" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">③ Teammate responds</text>
|
||||
<text x="433" y="240" fill="#6b7280" font-size="7" text-anchor="middle">BUS.send("shutdown_response"</text>
|
||||
<text x="433" y="252" fill="#6b7280" font-size="7" text-anchor="middle">same request_id + approve)</text>
|
||||
|
||||
<line x1="498" y1="234" x2="524" y2="234" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Step 4: Lead receives response -->
|
||||
<rect x="527" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="592" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">④ Lead receives</text>
|
||||
<text x="592" y="240" fill="#6b7280" font-size="7" text-anchor="middle">match_response(request_id)</text>
|
||||
<text x="592" y="252" fill="#6b7280" font-size="7" text-anchor="middle">→ resolve/reject callback</text>
|
||||
|
||||
<!-- ===== Row 3: State Machine + Storage ===== -->
|
||||
<!-- State Machine -->
|
||||
<rect x="30" y="296" width="340" height="85" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="200" y="316" fill="#4c1d95" font-size="10" font-weight="700" text-anchor="middle">State Machine (same for both protocols)</text>
|
||||
|
||||
<rect x="55" y="330" width="58" height="20" rx="4" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="84" y="344" fill="#475569" font-size="9" text-anchor="middle">pending</text>
|
||||
|
||||
<line x1="113" y1="340" x2="192" y2="340" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="152" y="335" fill="#16a34a" font-size="8" font-weight="600" text-anchor="middle">approve</text>
|
||||
|
||||
<rect x="192" y="330" width="62" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="223" y="344" fill="#166534" font-size="9" text-anchor="middle">approved</text>
|
||||
|
||||
<path d="M 84 350 L 84 368 L 128 368" fill="none" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="76" y="362" fill="#dc2626" font-size="8" font-weight="600" text-anchor="end">reject</text>
|
||||
|
||||
<rect x="128" y="358" width="60" height="20" rx="4" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="158" y="372" fill="#991b1b" font-size="9" text-anchor="middle">rejected</text>
|
||||
|
||||
<!-- pending_requests storage -->
|
||||
<rect x="400" y="296" width="330" height="85" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="565" y="316" fill="#4c1d95" font-size="10" font-weight="700" text-anchor="middle">pending_requests Storage</text>
|
||||
<text x="420" y="336" fill="#7c3aed" font-size="9">pending_requests: dict[str, ProtocolState]</text>
|
||||
<text x="420" y="352" fill="#6b7280" font-size="8">request_id → {type, sender, status, created_at}</text>
|
||||
<text x="420" y="368" fill="#6b7280" font-size="8">match_response: find request by request_id</text>
|
||||
|
||||
<!-- ===== Row 4: Two protocols use same machine ===== -->
|
||||
<rect x="30" y="396" width="700" height="48" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="55" y="416" fill="#1e3a5f" font-size="10" font-weight="600">Two protocols, one mechanism:</text>
|
||||
<rect x="230" y="406" width="130" height="18" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="295" y="419" fill="#92400e" font-size="9" text-anchor="middle">shutdown_request</text>
|
||||
<text x="368" y="419" fill="#475569" font-size="10">and</text>
|
||||
<rect x="390" y="406" width="140" height="18" rx="4" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="460" y="419" fill="#1e40af" font-size="9" text-anchor="middle">plan_approval_request</text>
|
||||
<text x="540" y="419" fill="#475569" font-size="10">share the same pending→approved/rejected FSM</text>
|
||||
<text x="55" y="436" fill="#6b7280" font-size="8">New protocol type = new msg_type, no new state machine. request_id links request and response.</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="30" y="460" width="700" height="28" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="470" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="480" fill="#475569" font-size="10">s15: MessageBus + spawn_teammate + inbox</text>
|
||||
<rect x="310" y="470" width="12" height="10" rx="2" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="330" y="480" fill="#475569" font-size="10">s16: request_id protocol + dispatch + pending_requests + state machine</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,141 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 500" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#7c3aed"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0891b2"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="500" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Team Protocols — リクエスト・レスポンス + request_id 紐付け + 状態機械</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s15 保持</text>
|
||||
<rect x="130" y="56" width="12" height="10" rx="2" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="148" y="66" fill="#7c3aed" font-size="10" font-weight="600">s16 新規</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="80" width="356" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH(コアツールセット)</text>
|
||||
<text x="394" y="114" fill="#2563eb" font-size="8">bash · read · write · task(4) · spawn · send · inbox</text>
|
||||
<text x="394" y="128" fill="#7c3aed" font-size="8" font-weight="700">★ request_shutdown · request_plan · review_plan</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- ===== Row 2: Protocol Flow ===== -->
|
||||
<rect x="30" y="176" width="700" height="100" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="380" y="196" fill="#4c1d95" font-size="11" font-weight="700" text-anchor="middle">リクエスト・レスポンスプロトコルフロー(request_id が全チェーンを貫通)</text>
|
||||
|
||||
<!-- Step 1 -->
|
||||
<rect x="50" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="115" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">① Lead が要求送信</text>
|
||||
<text x="115" y="240" fill="#6b7280" font-size="7" text-anchor="middle">BUS.send("shutdown_request"</text>
|
||||
<text x="115" y="252" fill="#6b7280" font-size="7" text-anchor="middle">metadata={request_id})</text>
|
||||
|
||||
<line x1="180" y1="234" x2="206" y2="234" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<rect x="209" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="274" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">② チームメイト受信</text>
|
||||
<text x="274" y="240" fill="#6b7280" font-size="7" text-anchor="middle">dispatch_by_type(inbox)</text>
|
||||
<text x="274" y="252" fill="#6b7280" font-size="7" text-anchor="middle">→ handler(type, metadata)</text>
|
||||
|
||||
<line x1="339" y1="234" x2="365" y2="234" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<rect x="368" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="433" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">③ チームメイト応答</text>
|
||||
<text x="433" y="240" fill="#6b7280" font-size="7" text-anchor="middle">BUS.send("shutdown_response"</text>
|
||||
<text x="433" y="252" fill="#6b7280" font-size="7" text-anchor="middle">同じ request_id + approve)</text>
|
||||
|
||||
<line x1="498" y1="234" x2="524" y2="234" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<rect x="527" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="592" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">④ Lead 応答受信</text>
|
||||
<text x="592" y="240" fill="#6b7280" font-size="7" text-anchor="middle">match_response(request_id)</text>
|
||||
<text x="592" y="252" fill="#6b7280" font-size="7" text-anchor="middle">→ resolve/reject callback</text>
|
||||
|
||||
<!-- ===== Row 3: State Machine + Storage ===== -->
|
||||
<rect x="30" y="296" width="340" height="85" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="200" y="316" fill="#4c1d95" font-size="10" font-weight="700" text-anchor="middle">状態機械(2 つのプロトコルで共通)</text>
|
||||
|
||||
<rect x="55" y="330" width="58" height="20" rx="4" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="84" y="344" fill="#475569" font-size="9" text-anchor="middle">pending</text>
|
||||
|
||||
<line x1="113" y1="340" x2="192" y2="340" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="152" y="335" fill="#16a34a" font-size="8" font-weight="600" text-anchor="middle">approve</text>
|
||||
|
||||
<rect x="192" y="330" width="62" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="223" y="344" fill="#166534" font-size="9" text-anchor="middle">approved</text>
|
||||
|
||||
<path d="M 84 350 L 84 368 L 128 368" fill="none" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="76" y="362" fill="#dc2626" font-size="8" font-weight="600" text-anchor="end">reject</text>
|
||||
|
||||
<rect x="128" y="358" width="60" height="20" rx="4" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="158" y="372" fill="#991b1b" font-size="9" text-anchor="middle">rejected</text>
|
||||
|
||||
<rect x="400" y="296" width="330" height="85" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="565" y="316" fill="#4c1d95" font-size="10" font-weight="700" text-anchor="middle">pending_requests ストレージ</text>
|
||||
<text x="420" y="336" fill="#7c3aed" font-size="9">pending_requests: dict[str, ProtocolState]</text>
|
||||
<text x="420" y="352" fill="#6b7280" font-size="8">request_id → {type, sender, status, created_at}</text>
|
||||
<text x="420" y="368" fill="#6b7280" font-size="8">match_response: request_id で要求を検索</text>
|
||||
|
||||
<!-- ===== Row 4 ===== -->
|
||||
<rect x="30" y="396" width="700" height="48" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="55" y="416" fill="#1e3a5f" font-size="10" font-weight="600">2 つのプロトコル、1 つの仕組み:</text>
|
||||
<rect x="230" y="406" width="130" height="18" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="295" y="419" fill="#92400e" font-size="9" text-anchor="middle">shutdown_request</text>
|
||||
<text x="368" y="419" fill="#475569" font-size="10">と</text>
|
||||
<rect x="390" y="406" width="140" height="18" rx="4" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="460" y="419" fill="#1e40af" font-size="9" text-anchor="middle">plan_approval_request</text>
|
||||
<text x="540" y="419" fill="#475569" font-size="10">が pending→approved/rejected 状態機械を共有</text>
|
||||
<text x="55" y="436" fill="#6b7280" font-size="8">新しいプロトコルタイプ = 新しい msg_type、新しい状態機械は不要。request_id が要求と応答を紐付け。</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="30" y="460" width="700" height="28" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="470" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="480" fill="#475569" font-size="10">s15: MessageBus + spawn_teammate + inbox</text>
|
||||
<rect x="310" y="470" width="12" height="10" rx="2" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="330" y="480" fill="#475569" font-size="10">s16: request_id プロトコル + dispatch + pending_requests + 状態機械</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.9 KiB |
@@ -0,0 +1,148 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 500" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#7c3aed"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-cyan" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0891b2"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="500" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Team Protocols — 请求-响应协议 + request_id 关联 + 状态机</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s15 保留</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#7c3aed" font-size="10" font-weight="600">s16 新增</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="80" width="356" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH(核心工具集)</text>
|
||||
<text x="394" y="114" fill="#2563eb" font-size="8">bash · read · write · task(4) · spawn · send · inbox</text>
|
||||
<text x="394" y="128" fill="#7c3aed" font-size="8" font-weight="700">★ request_shutdown · request_plan · review_plan</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- ===== Row 2: Protocol Flow (purple) — request_id lifecycle ===== -->
|
||||
<rect x="30" y="176" width="700" height="100" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="2"/>
|
||||
<text x="380" y="196" fill="#4c1d95" font-size="11" font-weight="700" text-anchor="middle">请求-响应协议流程(request_id 贯穿)</text>
|
||||
|
||||
<!-- Step 1: Send request -->
|
||||
<rect x="50" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="115" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">① Lead 发请求</text>
|
||||
<text x="115" y="240" fill="#6b7280" font-size="7" text-anchor="middle">BUS.send("shutdown_request"</text>
|
||||
<text x="115" y="252" fill="#6b7280" font-size="7" text-anchor="middle">metadata={request_id})</text>
|
||||
|
||||
<line x1="180" y1="234" x2="206" y2="234" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Step 2: Teammate receives & dispatches -->
|
||||
<rect x="209" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="274" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">② 队友收到</text>
|
||||
<text x="274" y="240" fill="#6b7280" font-size="7" text-anchor="middle">dispatch_by_type(inbox)</text>
|
||||
<text x="274" y="252" fill="#6b7280" font-size="7" text-anchor="middle">→ handler(type, metadata)</text>
|
||||
|
||||
<line x1="339" y1="234" x2="365" y2="234" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Step 3: Teammate processes & responds -->
|
||||
<rect x="368" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="433" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">③ 队友回复</text>
|
||||
<text x="433" y="240" fill="#6b7280" font-size="7" text-anchor="middle">BUS.send("shutdown_response"</text>
|
||||
<text x="433" y="252" fill="#6b7280" font-size="7" text-anchor="middle">同 request_id + approve)</text>
|
||||
|
||||
<line x1="498" y1="234" x2="524" y2="234" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Step 4: Lead receives response -->
|
||||
<rect x="527" y="208" width="130" height="52" rx="6" fill="#fff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="592" y="226" fill="#7c3aed" font-size="9" font-weight="600" text-anchor="middle">④ Lead 收响应</text>
|
||||
<text x="592" y="240" fill="#6b7280" font-size="7" text-anchor="middle">match_response(request_id)</text>
|
||||
<text x="592" y="252" fill="#6b7280" font-size="7" text-anchor="middle">→ resolve/reject callback</text>
|
||||
|
||||
<!-- ===== Row 3: State Machine + Storage ===== -->
|
||||
<!-- State Machine -->
|
||||
<rect x="30" y="296" width="340" height="85" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="200" y="316" fill="#4c1d95" font-size="10" font-weight="700" text-anchor="middle">状态机(同一套,两种协议)</text>
|
||||
|
||||
<!-- pending box: center (84, 340), right edge x=113, bottom y=350 -->
|
||||
<rect x="55" y="330" width="58" height="20" rx="4" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1"/>
|
||||
<text x="84" y="344" fill="#475569" font-size="9" text-anchor="middle">pending</text>
|
||||
|
||||
<!-- approve: line from pending right (113,340) to approved left (192,340) -->
|
||||
<line x1="113" y1="340" x2="192" y2="340" stroke="#16a34a" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="152" y="335" fill="#16a34a" font-size="8" font-weight="600" text-anchor="middle">approve</text>
|
||||
|
||||
<!-- approved box: left edge x=192 -->
|
||||
<rect x="192" y="330" width="62" height="20" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1"/>
|
||||
<text x="223" y="344" fill="#166534" font-size="9" text-anchor="middle">approved</text>
|
||||
|
||||
<!-- reject: path from pending bottom (84,350) down to (84,368) then right to rejected left (128,368) -->
|
||||
<path d="M 84 350 L 84 368 L 128 368" fill="none" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="76" y="362" fill="#dc2626" font-size="8" font-weight="600" text-anchor="end">reject</text>
|
||||
|
||||
<!-- rejected box: left edge x=128, top y=358 -->
|
||||
<rect x="128" y="358" width="60" height="20" rx="4" fill="#fef2f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="158" y="372" fill="#991b1b" font-size="9" text-anchor="middle">rejected</text>
|
||||
|
||||
<!-- pending_requests storage -->
|
||||
<rect x="400" y="296" width="330" height="85" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.5"/>
|
||||
<text x="565" y="316" fill="#4c1d95" font-size="10" font-weight="700" text-anchor="middle">pending_requests 存储</text>
|
||||
<text x="420" y="336" fill="#7c3aed" font-size="9">pending_requests: dict[str, ProtocolState]</text>
|
||||
<text x="420" y="352" fill="#6b7280" font-size="8">request_id → {type, sender, status, created_at}</text>
|
||||
<text x="420" y="368" fill="#6b7280" font-size="8">match_response: 按 request_id 找回对应请求</text>
|
||||
|
||||
<!-- ===== Row 4: Two protocols use same machine ===== -->
|
||||
<rect x="30" y="396" width="700" height="48" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<text x="55" y="416" fill="#1e3a5f" font-size="10" font-weight="600">两种协议,同一套机制:</text>
|
||||
<rect x="230" y="406" width="130" height="18" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="295" y="419" fill="#92400e" font-size="9" text-anchor="middle">shutdown_request</text>
|
||||
<text x="368" y="419" fill="#475569" font-size="10">和</text>
|
||||
<rect x="390" y="406" width="140" height="18" rx="4" fill="#dbeafe" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="460" y="419" fill="#1e40af" font-size="9" text-anchor="middle">plan_approval_request</text>
|
||||
<text x="540" y="419" fill="#475569" font-size="10">共用 pending→approved/rejected 状态机</text>
|
||||
<text x="55" y="436" fill="#6b7280" font-size="8">新增协议类型 = 新的 msg_type,不需要新状态机。request_id 关联请求和响应。</text>
|
||||
|
||||
<!-- ===== Bottom notes ===== -->
|
||||
<rect x="30" y="460" width="700" height="28" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="470" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="480" fill="#475569" font-size="10">s15: MessageBus + spawn_teammate + inbox</text>
|
||||
<rect x="310" y="470" width="12" height="10" rx="2" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1"/>
|
||||
<text x="330" y="480" fill="#475569" font-size="10">s16: request_id 协议 + dispatch + pending_requests + 状态机</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,109 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 470" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#059669"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#059669"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="470" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Autonomous Agents — Idle Loop + Auto-Claim + WORK/IDLE Lifecycle</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s16 Preserved</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#059669" font-size="10" font-weight="600">s17 New</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop (s16 preserved) ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="80" width="356" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH (all s16 preserved)</text>
|
||||
<text x="394" y="114" fill="#2563eb" font-size="8">bash · read · write · task(4) · send · inbox</text>
|
||||
<text x="394" y="128" fill="#7c3aed" font-size="8" font-weight="700">★ request_shutdown · request_plan · review_plan</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- Connector: preserved inner loop is wrapped by the s17 lifecycle -->
|
||||
<path d="M 326 134 L 326 160 L 170 160 L 170 210" fill="none" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<text x="248" y="156" fill="#059669" font-size="8" font-weight="600" text-anchor="middle">same inner LLM/tool loop inside WORK</text>
|
||||
|
||||
<!-- ===== Row 2: Teammate Lifecycle (s17 new) ===== -->
|
||||
<rect x="30" y="172" width="700" height="195" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="380" y="194" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">Teammate Lifecycle (s17 new: WORK → IDLE → SHUTDOWN)</text>
|
||||
|
||||
<!-- WORK box -->
|
||||
<rect x="55" y="210" width="230" height="100" rx="6" fill="#fff" stroke="#059669" stroke-width="1.5"/>
|
||||
<text x="170" y="230" fill="#059669" font-size="10" font-weight="700" text-anchor="middle">WORK Phase</text>
|
||||
<text x="70" y="248" fill="#374151" font-size="8">inner loop: inbox → LLM → bash / read / write</text>
|
||||
<text x="70" y="262" fill="#374151" font-size="8">stop_reason == tool_use → loop</text>
|
||||
<text x="70" y="276" fill="#374151" font-size="8">stop_reason != tool_use → IDLE</text>
|
||||
<text x="70" y="298" fill="#6b7280" font-size="7">Max 10 rounds / interruptible by shutdown_request</text>
|
||||
|
||||
<!-- Arrow: WORK → IDLE -->
|
||||
<line x1="285" y1="260" x2="415" y2="260" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="350" y="253" fill="#059669" font-size="8" font-weight="600" text-anchor="middle">task done</text>
|
||||
|
||||
<!-- Arrow: IDLE → WORK (curved, above) -->
|
||||
<path d="M 415 232 C 375 200, 320 200, 285 232" fill="none" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<text x="350" y="208" fill="#059669" font-size="8" font-weight="600" text-anchor="middle">work found</text>
|
||||
|
||||
<!-- IDLE box -->
|
||||
<rect x="418" y="210" width="295" height="100" rx="6" fill="#fff" stroke="#059669" stroke-width="1.5"/>
|
||||
<text x="565" y="230" fill="#059669" font-size="10" font-weight="700" text-anchor="middle">IDLE Phase (poll every 5s)</text>
|
||||
<text x="433" y="248" fill="#374151" font-size="8">├ Check inbox → has message → back to WORK</text>
|
||||
<text x="433" y="264" fill="#374151" font-size="8">├ scan_unclaimed_tasks → claim → back to WORK</text>
|
||||
<text x="433" y="280" fill="#374151" font-size="8">└ 60s timeout → SHUTDOWN ↓</text>
|
||||
<text x="433" y="298" fill="#6b7280" font-size="7">idle_poll() + claim_task()</text>
|
||||
|
||||
<!-- SHUTDOWN box -->
|
||||
<rect x="515" y="335" width="130" height="24" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="580" y="351" fill="#991b1b" font-size="9" font-weight="700" text-anchor="middle">SHUTDOWN</text>
|
||||
|
||||
<!-- Arrow: IDLE → SHUTDOWN -->
|
||||
<line x1="580" y1="310" x2="580" y2="335" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="598" y="326" fill="#dc2626" font-size="7">60s timeout</text>
|
||||
|
||||
<!-- ===== Row 3: Bottom notes ===== -->
|
||||
<rect x="30" y="388" width="700" height="42" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="400" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="410" fill="#475569" font-size="10">s16: MessageBus + protocols + request_shutdown + plan approval</text>
|
||||
<rect x="50" y="414" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="70" y="424" fill="#475569" font-size="10">s17: idle_poll + scan_unclaimed_tasks + auto_claim + identity re-injection</text>
|
||||
|
||||
<!-- ===== Row 4: Autonomous note ===== -->
|
||||
<rect x="30" y="442" width="700" height="22" rx="4" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="380" y="457" fill="#065f46" font-size="9" text-anchor="middle">Lead tools unchanged (14) · Teammate tools 5 → 8 (+3 task tools) · Teammates self-claim, Lead only creates tasks</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1,109 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 470" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#059669"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#059669"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="470" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Autonomous Agents — アイドルポーリング + 自動認領 + WORK/IDLE ライフサイクル</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s16 保持</text>
|
||||
<rect x="130" y="56" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="148" y="66" fill="#059669" font-size="10" font-weight="600">s17 新規</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="80" width="356" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH(s16 全保持)</text>
|
||||
<text x="394" y="114" fill="#2563eb" font-size="8">bash · read · write · task(4) · send · inbox</text>
|
||||
<text x="394" y="128" fill="#7c3aed" font-size="8" font-weight="700">★ request_shutdown · request_plan · review_plan</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- Connector: preserved inner loop is wrapped by the s17 lifecycle -->
|
||||
<path d="M 326 134 L 326 160 L 170 160 L 170 210" fill="none" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<text x="248" y="156" fill="#059669" font-size="8" font-weight="600" text-anchor="middle">同じ内側 LLM/tool loop を WORK に入れる</text>
|
||||
|
||||
<!-- ===== Row 2: Teammate Lifecycle ===== -->
|
||||
<rect x="30" y="172" width="700" height="195" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="380" y="194" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">チームメイトライフサイクル(s17 新規:WORK → IDLE → SHUTDOWN)</text>
|
||||
|
||||
<!-- WORK box -->
|
||||
<rect x="55" y="210" width="230" height="100" rx="6" fill="#fff" stroke="#059669" stroke-width="1.5"/>
|
||||
<text x="170" y="230" fill="#059669" font-size="10" font-weight="700" text-anchor="middle">WORK フェーズ</text>
|
||||
<text x="70" y="248" fill="#374151" font-size="8">内側ループ:inbox → LLM → bash / read / write</text>
|
||||
<text x="70" y="262" fill="#374151" font-size="8">stop_reason == tool_use → ループ</text>
|
||||
<text x="70" y="276" fill="#374151" font-size="8">stop_reason != tool_use → IDLE</text>
|
||||
<text x="70" y="298" fill="#6b7280" font-size="7">最大 10 ラウンド / shutdown_request で中断可能</text>
|
||||
|
||||
<!-- Arrow: WORK → IDLE -->
|
||||
<line x1="285" y1="260" x2="415" y2="260" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="350" y="253" fill="#059669" font-size="8" font-weight="600" text-anchor="middle">タスク完了</text>
|
||||
|
||||
<!-- Arrow: IDLE → WORK -->
|
||||
<path d="M 415 232 C 375 200, 320 200, 285 232" fill="none" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<text x="350" y="208" fill="#059669" font-size="8" font-weight="600" text-anchor="middle">仕事を発見</text>
|
||||
|
||||
<!-- IDLE box -->
|
||||
<rect x="418" y="210" width="295" height="100" rx="6" fill="#fff" stroke="#059669" stroke-width="1.5"/>
|
||||
<text x="565" y="230" fill="#059669" font-size="10" font-weight="700" text-anchor="middle">IDLE フェーズ(5 秒ごとにポーリング)</text>
|
||||
<text x="433" y="248" fill="#374151" font-size="8">├ inbox チェック → メッセージあり → WORK に戻る</text>
|
||||
<text x="433" y="264" fill="#374151" font-size="8">├ scan_unclaimed_tasks → 認領 → WORK に戻る</text>
|
||||
<text x="433" y="280" fill="#374151" font-size="8">└ 60 秒タイムアウト → SHUTDOWN ↓</text>
|
||||
<text x="433" y="298" fill="#6b7280" font-size="7">idle_poll() + claim_task()</text>
|
||||
|
||||
<!-- SHUTDOWN box -->
|
||||
<rect x="515" y="335" width="130" height="24" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="580" y="351" fill="#991b1b" font-size="9" font-weight="700" text-anchor="middle">SHUTDOWN</text>
|
||||
|
||||
<!-- Arrow: IDLE → SHUTDOWN -->
|
||||
<line x1="580" y1="310" x2="580" y2="335" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="598" y="326" fill="#dc2626" font-size="7">60 秒タイムアウト</text>
|
||||
|
||||
<!-- ===== Row 3: Bottom notes ===== -->
|
||||
<rect x="30" y="388" width="700" height="42" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="400" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="410" fill="#475569" font-size="10">s16: MessageBus + protocols + request_shutdown + plan approval</text>
|
||||
<rect x="50" y="414" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="70" y="424" fill="#475569" font-size="10">s17: idle_poll + scan_unclaimed_tasks + auto_claim + identity re-injection</text>
|
||||
|
||||
<!-- ===== Row 4 ===== -->
|
||||
<rect x="30" y="442" width="700" height="22" rx="4" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="380" y="457" fill="#065f46" font-size="9" text-anchor="middle">Lead ツール不変(14) · チームメイトツール 5 → 8(+3 task tools) · チームメイトが自己認領、Lead はタスク作成のみ</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,109 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 470" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#059669"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#059669"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="470" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Autonomous Agents — 空闲循环 + 自动认领 + WORK/IDLE 生命周期</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s16 保留</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#059669" font-size="10" font-weight="600">s17 新增</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop (s16 preserved) ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="80" width="356" height="60" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="98" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH (s16 全保留)</text>
|
||||
<text x="394" y="114" fill="#2563eb" font-size="8">bash · read · write · task(4) · send · inbox</text>
|
||||
<text x="394" y="128" fill="#7c3aed" font-size="8" font-weight="700">★ request_shutdown · request_plan · review_plan</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- Connector: preserved inner loop is wrapped by the s17 lifecycle -->
|
||||
<path d="M 326 134 L 326 160 L 170 160 L 170 210" fill="none" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<text x="248" y="156" fill="#059669" font-size="8" font-weight="600" text-anchor="middle">同一个内层 LLM/tool loop 放进 WORK</text>
|
||||
|
||||
<!-- ===== Row 2: Teammate Lifecycle (s17 new) ===== -->
|
||||
<rect x="30" y="172" width="700" height="195" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="2"/>
|
||||
<text x="380" y="194" fill="#065f46" font-size="11" font-weight="700" text-anchor="middle">队友生命周期(s17 新增:WORK → IDLE → SHUTDOWN)</text>
|
||||
|
||||
<!-- WORK box -->
|
||||
<rect x="55" y="210" width="230" height="100" rx="6" fill="#fff" stroke="#059669" stroke-width="1.5"/>
|
||||
<text x="170" y="230" fill="#059669" font-size="10" font-weight="700" text-anchor="middle">WORK 阶段</text>
|
||||
<text x="70" y="248" fill="#374151" font-size="8">内层循环:inbox → LLM → bash / read / write</text>
|
||||
<text x="70" y="262" fill="#374151" font-size="8">stop_reason == tool_use → loop</text>
|
||||
<text x="70" y="276" fill="#374151" font-size="8">stop_reason != tool_use → IDLE</text>
|
||||
<text x="70" y="298" fill="#6b7280" font-size="7">最多 10 轮 / 可被 shutdown_request 中断</text>
|
||||
|
||||
<!-- Arrow: WORK → IDLE -->
|
||||
<line x1="285" y1="260" x2="415" y2="260" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)"/>
|
||||
<text x="350" y="253" fill="#059669" font-size="8" font-weight="600" text-anchor="middle">任务完成</text>
|
||||
|
||||
<!-- Arrow: IDLE → WORK (curved, above) -->
|
||||
<path d="M 415 232 C 375 200, 320 200, 285 232" fill="none" stroke="#059669" stroke-width="1.5" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<text x="350" y="208" fill="#059669" font-size="8" font-weight="600" text-anchor="middle">发现新任务</text>
|
||||
|
||||
<!-- IDLE box -->
|
||||
<rect x="418" y="210" width="295" height="100" rx="6" fill="#fff" stroke="#059669" stroke-width="1.5"/>
|
||||
<text x="565" y="230" fill="#059669" font-size="10" font-weight="700" text-anchor="middle">IDLE 阶段(每 5s 轮询)</text>
|
||||
<text x="433" y="248" fill="#374151" font-size="8">├ 检查 inbox → 有消息 → 回 WORK</text>
|
||||
<text x="433" y="264" fill="#374151" font-size="8">├ scan_unclaimed_tasks → 认领 → 回 WORK</text>
|
||||
<text x="433" y="280" fill="#374151" font-size="8">└ 60s 超时 → SHUTDOWN ↓</text>
|
||||
<text x="433" y="298" fill="#6b7280" font-size="7">idle_poll() + claim_task()</text>
|
||||
|
||||
<!-- SHUTDOWN box -->
|
||||
<rect x="515" y="335" width="130" height="24" rx="6" fill="#fef2f2" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="580" y="351" fill="#991b1b" font-size="9" font-weight="700" text-anchor="middle">SHUTDOWN</text>
|
||||
|
||||
<!-- Arrow: IDLE → SHUTDOWN -->
|
||||
<line x1="580" y1="310" x2="580" y2="335" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-red)"/>
|
||||
<text x="598" y="326" fill="#dc2626" font-size="7">60s 超时</text>
|
||||
|
||||
<!-- ===== Row 3: Bottom notes ===== -->
|
||||
<rect x="30" y="388" width="700" height="42" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="400" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="410" fill="#475569" font-size="10">s16: MessageBus + protocols + request_shutdown + plan approval</text>
|
||||
<rect x="50" y="414" width="12" height="10" rx="2" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="70" y="424" fill="#475569" font-size="10">s17: idle_poll + scan_unclaimed_tasks + auto_claim + identity re-injection</text>
|
||||
|
||||
<!-- ===== Row 4: Autonomous note ===== -->
|
||||
<rect x="30" y="442" width="700" height="22" rx="4" fill="#ecfdf5" stroke="#059669" stroke-width="1"/>
|
||||
<text x="380" y="457" fill="#065f46" font-size="9" text-anchor="middle">Lead 工具不变(14) · 队友工具 5 → 8(+3 task tools) · 队友自主认领,Lead 只创建任务</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1,103 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 450" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#b45309"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#b45309"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="450" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Worktree Isolation — Git Worktree + Task-Directory Binding + Event Log</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s17 Preserved</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#fffbeb" stroke="#b45309" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#b45309" font-size="10" font-weight="600">s18 New</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop (s17 preserved) ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="76" width="356" height="70" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="94" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH (s17 + s18)</text>
|
||||
<text x="394" y="110" fill="#2563eb" font-size="8">bash · read · write · task(4) · send · inbox</text>
|
||||
<text x="394" y="123" fill="#7c3aed" font-size="8" font-weight="700">request_shutdown · request_plan · review_plan</text>
|
||||
<text x="394" y="136" fill="#b45309" font-size="8" font-weight="700">★ create_worktree · remove_worktree · keep_worktree</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- ===== Row 2: Worktree Topology (s18 new) ===== -->
|
||||
<rect x="30" y="172" width="700" height="215" rx="8" fill="#fffbeb" stroke="#b45309" stroke-width="2"/>
|
||||
<text x="380" y="194" fill="#78350f" font-size="11" font-weight="700" text-anchor="middle">Worktree Isolation (s18 new: each task gets its own directory + branch)</text>
|
||||
|
||||
<!-- Main repo box -->
|
||||
<rect x="230" y="208" width="300" height="36" rx="6" fill="#fff" stroke="#b45309" stroke-width="1.5"/>
|
||||
<text x="380" y="231" fill="#78350f" font-size="10" font-weight="600" text-anchor="middle">Main repo (.tasks/ + .worktrees/ + .mailboxes/)</text>
|
||||
|
||||
<!-- Arrow: Main repo → Worktree 1 (Alice) -->
|
||||
<line x1="310" y1="244" x2="178" y2="272" stroke="#b45309" stroke-width="1.5" marker-end="url(#arrow-amber)"/>
|
||||
<text x="200" y="262" fill="#b45309" font-size="7" font-weight="600" transform="rotate(-12 200 262)">create + bind</text>
|
||||
|
||||
<!-- Arrow: Main repo → Worktree 2 (Bob) -->
|
||||
<line x1="450" y1="244" x2="582" y2="272" stroke="#b45309" stroke-width="1.5" marker-end="url(#arrow-amber)"/>
|
||||
<text x="530" y="252" fill="#b45309" font-size="7" font-weight="600" transform="rotate(12 530 252)">create + bind</text>
|
||||
|
||||
<!-- Worktree 1: Alice -->
|
||||
<rect x="50" y="275" width="255" height="78" rx="6" fill="#fff" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="177" y="294" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Alice: .worktrees/auth/</text>
|
||||
<text x="65" y="310" fill="#374151" font-size="8">branch: wt/auth-refactor</text>
|
||||
<text x="65" y="324" fill="#374151" font-size="8">Task: Refactor auth module</text>
|
||||
<text x="65" y="344" fill="#16a34a" font-size="8" font-weight="600">✓ Isolated, no impact on Bob or main repo</text>
|
||||
|
||||
<!-- Worktree 2: Bob -->
|
||||
<rect x="455" y="275" width="255" height="78" rx="6" fill="#fff" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="582" y="294" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Bob: .worktrees/ui/</text>
|
||||
<text x="470" y="310" fill="#374151" font-size="8">branch: wt/ui-login</text>
|
||||
<text x="470" y="324" fill="#374151" font-size="8">Task: Refactor UI login page</text>
|
||||
<text x="470" y="344" fill="#16a34a" font-size="8" font-weight="600">✓ Isolated, no impact on Alice or main repo</text>
|
||||
|
||||
<!-- Event log + Lifecycle -->
|
||||
<rect x="50" y="362" width="310" height="20" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="205" y="376" fill="#92400e" font-size="8" text-anchor="middle">Event log: .worktrees/events.jsonl → create / remove / keep</text>
|
||||
|
||||
<rect x="400" y="362" width="310" height="20" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="555" y="376" fill="#92400e" font-size="8" text-anchor="middle">Cleanup: keep (preserve branch for review) / remove (delete + mark done)</text>
|
||||
|
||||
<!-- ===== Row 3: Bottom notes ===== -->
|
||||
<rect x="30" y="400" width="700" height="42" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="412" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="422" fill="#475569" font-size="10">s17: idle_poll + auto_claim + protocols + WORK/IDLE lifecycle</text>
|
||||
<rect x="50" y="426" width="12" height="10" rx="2" fill="#fffbeb" stroke="#b45309" stroke-width="1"/>
|
||||
<text x="70" y="436" fill="#475569" font-size="10">s18: create_worktree + bind_task + remove/keep + events.jsonl (Lead 14→17)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,103 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 450" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#b45309"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#b45309"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="450" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">Worktree Isolation — Git Worktree + タスク・ディレクトリ紐付け + イベントログ</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s17 保持</text>
|
||||
<rect x="130" y="56" width="12" height="10" rx="2" fill="#fffbeb" stroke="#b45309" stroke-width="1"/>
|
||||
<text x="148" y="66" fill="#b45309" font-size="10" font-weight="600">s18 新規</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="76" width="356" height="70" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="94" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH(s17 + s18)</text>
|
||||
<text x="394" y="110" fill="#2563eb" font-size="8">bash · read · write · task(4) · send · inbox</text>
|
||||
<text x="394" y="123" fill="#7c3aed" font-size="8" font-weight="700">request_shutdown · request_plan · review_plan</text>
|
||||
<text x="394" y="136" fill="#b45309" font-size="8" font-weight="700">★ create_worktree · remove_worktree · keep_worktree</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- ===== Row 2: Worktree Topology ===== -->
|
||||
<rect x="30" y="172" width="700" height="215" rx="8" fill="#fffbeb" stroke="#b45309" stroke-width="2"/>
|
||||
<text x="380" y="194" fill="#78350f" font-size="11" font-weight="700" text-anchor="middle">Worktree 隔離(s18 新規:各タスクに独立ディレクトリ + 独立ブランチ)</text>
|
||||
|
||||
<!-- Main repo box -->
|
||||
<rect x="230" y="208" width="300" height="36" rx="6" fill="#fff" stroke="#b45309" stroke-width="1.5"/>
|
||||
<text x="380" y="231" fill="#78350f" font-size="10" font-weight="600" text-anchor="middle">メインリポジトリ(.tasks/ + .worktrees/ + .mailboxes/)</text>
|
||||
|
||||
<!-- Arrow: Main repo → Worktree 1 (Alice) -->
|
||||
<line x1="310" y1="244" x2="178" y2="272" stroke="#b45309" stroke-width="1.5" marker-end="url(#arrow-amber)"/>
|
||||
<text x="200" y="262" fill="#b45309" font-size="7" font-weight="600" transform="rotate(-12 200 262)">create + bind</text>
|
||||
|
||||
<!-- Arrow: Main repo → Worktree 2 (Bob) -->
|
||||
<line x1="450" y1="244" x2="582" y2="272" stroke="#b45309" stroke-width="1.5" marker-end="url(#arrow-amber)"/>
|
||||
<text x="530" y="252" fill="#b45309" font-size="7" font-weight="600" transform="rotate(12 530 252)">create + bind</text>
|
||||
|
||||
<!-- Worktree 1: Alice -->
|
||||
<rect x="50" y="275" width="255" height="78" rx="6" fill="#fff" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="177" y="294" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Alice: .worktrees/auth/</text>
|
||||
<text x="65" y="310" fill="#374151" font-size="8">branch: wt/auth-refactor</text>
|
||||
<text x="65" y="324" fill="#374151" font-size="8">Task: 認証モジュールのリファクタリング</text>
|
||||
<text x="65" y="344" fill="#16a34a" font-size="8" font-weight="600">✓ 隔離、Bob とメインリポジトリに影響なし</text>
|
||||
|
||||
<!-- Worktree 2: Bob -->
|
||||
<rect x="455" y="275" width="255" height="78" rx="6" fill="#fff" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="582" y="294" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Bob: .worktrees/ui/</text>
|
||||
<text x="470" y="310" fill="#374151" font-size="8">branch: wt/ui-login</text>
|
||||
<text x="470" y="324" fill="#374151" font-size="8">Task: UI ログインページのリファクタリング</text>
|
||||
<text x="470" y="344" fill="#16a34a" font-size="8" font-weight="600">✓ 隔離、Alice とメインリポジトリに影響なし</text>
|
||||
|
||||
<!-- Event log + Lifecycle -->
|
||||
<rect x="50" y="362" width="310" height="20" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="205" y="376" fill="#92400e" font-size="8" text-anchor="middle">イベントログ: .worktrees/events.jsonl → create / remove / keep</text>
|
||||
|
||||
<rect x="400" y="362" width="310" height="20" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="555" y="376" fill="#92400e" font-size="8" text-anchor="middle">片付け: keep(ブランチ保持 review)/ remove(削除+完了マーク)</text>
|
||||
|
||||
<!-- ===== Row 3: Bottom notes ===== -->
|
||||
<rect x="30" y="400" width="700" height="42" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="412" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="422" fill="#475569" font-size="10">s17: idle_poll + auto_claim + protocols + WORK/IDLE ライフサイクル</text>
|
||||
<rect x="50" y="426" width="12" height="10" rx="2" fill="#fffbeb" stroke="#b45309" stroke-width="1"/>
|
||||
<text x="70" y="436" fill="#475569" font-size="10">s18: create_worktree + bind_task + remove/keep + events.jsonl(Lead 14→17)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.2 KiB |
@@ -0,0 +1,103 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 450" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#b45309"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-amber" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#b45309"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#16a34a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="450" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">Worktree Isolation — Git Worktree + 任务-目录绑定 + 事件日志</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s17 保留</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#fffbeb" stroke="#b45309" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#b45309" font-size="10" font-weight="600">s18 新增</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop (s17 preserved) ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="76" width="356" height="70" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="94" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH (s17 + s18)</text>
|
||||
<text x="394" y="110" fill="#2563eb" font-size="8">bash · read · write · task(4) · send · inbox</text>
|
||||
<text x="394" y="123" fill="#7c3aed" font-size="8" font-weight="700">request_shutdown · request_plan · review_plan</text>
|
||||
<text x="394" y="136" fill="#b45309" font-size="8" font-weight="700">★ create_worktree · remove_worktree · keep_worktree</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- ===== Row 2: Worktree Topology (s18 new) ===== -->
|
||||
<rect x="30" y="172" width="700" height="215" rx="8" fill="#fffbeb" stroke="#b45309" stroke-width="2"/>
|
||||
<text x="380" y="194" fill="#78350f" font-size="11" font-weight="700" text-anchor="middle">Worktree 隔离(s18 新增:每个任务独立目录 + 独立分支)</text>
|
||||
|
||||
<!-- Main repo box -->
|
||||
<rect x="230" y="208" width="300" height="36" rx="6" fill="#fff" stroke="#b45309" stroke-width="1.5"/>
|
||||
<text x="380" y="231" fill="#78350f" font-size="10" font-weight="600" text-anchor="middle">主仓库 (.tasks/ + .worktrees/ + .mailboxes/)</text>
|
||||
|
||||
<!-- Arrow: Main repo → Worktree 1 (Alice) -->
|
||||
<line x1="310" y1="244" x2="178" y2="272" stroke="#b45309" stroke-width="1.5" marker-end="url(#arrow-amber)"/>
|
||||
<text x="200" y="262" fill="#b45309" font-size="7" font-weight="600" transform="rotate(-12 200 262)">create + bind</text>
|
||||
|
||||
<!-- Arrow: Main repo → Worktree 2 (Bob) -->
|
||||
<line x1="450" y1="244" x2="582" y2="272" stroke="#b45309" stroke-width="1.5" marker-end="url(#arrow-amber)"/>
|
||||
<text x="530" y="252" fill="#b45309" font-size="7" font-weight="600" transform="rotate(12 530 252)">create + bind</text>
|
||||
|
||||
<!-- Worktree 1: Alice -->
|
||||
<rect x="50" y="275" width="255" height="78" rx="6" fill="#fff" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="177" y="294" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Alice: .worktrees/auth/</text>
|
||||
<text x="65" y="310" fill="#374151" font-size="8">branch: wt/auth-refactor</text>
|
||||
<text x="65" y="324" fill="#374151" font-size="8">Task: 重构认证模块</text>
|
||||
<text x="65" y="344" fill="#16a34a" font-size="8" font-weight="600">✓ 隔离,不影响 Bob 和主仓库</text>
|
||||
|
||||
<!-- Worktree 2: Bob -->
|
||||
<rect x="455" y="275" width="255" height="78" rx="6" fill="#fff" stroke="#16a34a" stroke-width="1.5"/>
|
||||
<text x="582" y="294" fill="#166534" font-size="10" font-weight="700" text-anchor="middle">Bob: .worktrees/ui/</text>
|
||||
<text x="470" y="310" fill="#374151" font-size="8">branch: wt/ui-login</text>
|
||||
<text x="470" y="324" fill="#374151" font-size="8">Task: 重构 UI 登录页</text>
|
||||
<text x="470" y="344" fill="#16a34a" font-size="8" font-weight="600">✓ 隔离,不影响 Alice 和主仓库</text>
|
||||
|
||||
<!-- Event log + Lifecycle -->
|
||||
<rect x="50" y="362" width="310" height="20" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="205" y="376" fill="#92400e" font-size="8" text-anchor="middle">事件日志: .worktrees/events.jsonl → create / remove / keep</text>
|
||||
|
||||
<rect x="400" y="362" width="310" height="20" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="555" y="376" fill="#92400e" font-size="8" text-anchor="middle">收尾: keep (保留分支 review) / remove (删除+标记完成)</text>
|
||||
|
||||
<!-- ===== Row 3: Bottom notes ===== -->
|
||||
<rect x="30" y="400" width="700" height="42" rx="6" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="412" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="422" fill="#475569" font-size="10">s17: idle_poll + auto_claim + protocols + WORK/IDLE lifecycle</text>
|
||||
<rect x="50" y="426" width="12" height="10" rx="2" fill="#fffbeb" stroke="#b45309" stroke-width="1"/>
|
||||
<text x="70" y="436" fill="#475569" font-size="10">s18: create_worktree + bind_task + remove/keep + events.jsonl (Lead 14→17)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
112
web/public/course-assets/s19_mcp_plugin/mcp-architecture.en.svg
Normal file
@@ -0,0 +1,112 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 460" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-rose" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<marker id="arrow-rose-left" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 10 0 L 0 5 L 10 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="460" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">MCP Plugin — Standard Protocol + External Tool Integration + Tool Pool Assembly</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s18 Preserved</text>
|
||||
<rect x="160" y="56" width="12" height="10" rx="2" fill="#fff1f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="178" y="66" fill="#dc2626" font-size="10" font-weight="600">s19 New</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop (s18 preserved) ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="76" width="356" height="72" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="94" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH (Lead 18 tools)</text>
|
||||
<text x="394" y="109" fill="#2563eb" font-size="7.5">bash · read · write · task(4) · send · inbox</text>
|
||||
<text x="394" y="121" fill="#7c3aed" font-size="7.5" font-weight="700">request_shutdown · request_plan · review_plan</text>
|
||||
<text x="394" y="133" fill="#b45309" font-size="7.5" font-weight="700">create_worktree · remove_worktree · keep_worktree</text>
|
||||
<text x="394" y="145" fill="#dc2626" font-size="7.5" font-weight="700">★ connect_mcp + dynamic mcp__server__tool tools</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- ===== Row 2: MCP Architecture (s19 new) ===== -->
|
||||
<rect x="30" y="172" width="700" height="215" rx="8" fill="#fff1f2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="380" y="194" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">MCP Architecture (s19 new: standard protocol + external tools dynamic integration)</text>
|
||||
|
||||
<!-- Agent Side -->
|
||||
<rect x="50" y="210" width="255" height="140" rx="6" fill="#fff" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="177" y="230" fill="#991b1b" font-size="10" font-weight="700" text-anchor="middle">Agent Side (MCPClient)</text>
|
||||
|
||||
<rect x="65" y="240" width="225" height="24" rx="4" fill="#fef2f2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="177" y="256" fill="#475569" font-size="8" text-anchor="middle">connect_mcp → discover → register tools</text>
|
||||
|
||||
<rect x="65" y="272" width="225" height="24" rx="4" fill="#fef2f2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="177" y="288" fill="#475569" font-size="8" text-anchor="middle">assemble_tool_pool assembles builtin + mcp</text>
|
||||
|
||||
<rect x="65" y="304" width="225" height="24" rx="4" fill="#fef2f2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="177" y="320" fill="#475569" font-size="8" text-anchor="middle">call_tool("mcp__docs__search", ...)</text>
|
||||
|
||||
<!-- Communication arrows -->
|
||||
<line x1="305" y1="262" x2="435" y2="262" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-rose)"/>
|
||||
<text x="370" y="256" fill="#dc2626" font-size="7" font-weight="600" text-anchor="middle">tools/list</text>
|
||||
|
||||
<line x1="435" y1="296" x2="305" y2="296" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-rose)"/>
|
||||
<text x="370" y="312" fill="#dc2626" font-size="7" font-weight="600" text-anchor="middle">tools/call + response</text>
|
||||
|
||||
<!-- MCP Servers -->
|
||||
<rect x="438" y="210" width="275" height="140" rx="6" fill="#fff" stroke="#ca8a04" stroke-width="1.5"/>
|
||||
<text x="575" y="230" fill="#854d0e" font-size="10" font-weight="700" text-anchor="middle">MCP Servers (External Services)</text>
|
||||
|
||||
<rect x="453" y="240" width="245" height="28" rx="4" fill="#fefce8" stroke="#facc15" stroke-width="0.5"/>
|
||||
<text x="575" y="258" fill="#854d0e" font-size="9" font-weight="600" text-anchor="middle">docs server: search · get_version</text>
|
||||
|
||||
<rect x="453" y="276" width="245" height="28" rx="4" fill="#fefce8" stroke="#facc15" stroke-width="0.5"/>
|
||||
<text x="575" y="294" fill="#854d0e" font-size="9" font-weight="600" text-anchor="middle">deploy server: trigger · status</text>
|
||||
|
||||
<rect x="453" y="312" width="245" height="28" rx="4" fill="#fefce8" stroke="#facc15" stroke-width="0.5"/>
|
||||
<text x="575" y="330" fill="#854d0e" font-size="9" font-weight="600" text-anchor="middle">Any language, just needs stdio JSON-RPC</text>
|
||||
|
||||
<!-- Naming convention -->
|
||||
<rect x="50" y="360" width="660" height="20" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="380" y="374" fill="#92400e" font-size="8" text-anchor="middle">Tool naming: mcp__{server}__{tool} → e.g. mcp__docs__search · mcp__deploy__trigger · prevents name collisions across servers</text>
|
||||
|
||||
<!-- ===== Row 3: Bottom notes ===== -->
|
||||
<rect x="30" y="400" width="700" height="22" rx="4" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="408" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="418" fill="#475569" font-size="10">s18: worktree + events + protocols (Lead 17)</text>
|
||||
<rect x="420" y="408" width="12" height="10" rx="2" fill="#fff1f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="440" y="418" fill="#475569" font-size="10">s19: MCP + dynamic tools (Lead 18)</text>
|
||||
|
||||
<!-- ===== Final note ===== -->
|
||||
<rect x="30" y="430" width="700" height="22" rx="4" fill="#fff1f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="380" y="444" fill="#991b1b" font-size="9" font-weight="600" text-anchor="middle">Next: s20 combines tools, permissions, teams, worktrees, MCP, and more into one while True loop.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.8 KiB |
112
web/public/course-assets/s19_mcp_plugin/mcp-architecture.ja.svg
Normal file
@@ -0,0 +1,112 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 460" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-rose" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<marker id="arrow-rose-left" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 10 0 L 0 5 L 10 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="460" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="14" font-weight="700" text-anchor="middle">MCP Plugin — 標準プロトコル + 外部ツール接続 + ツールプール組み立て</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s18 保持</text>
|
||||
<rect x="130" y="56" width="12" height="10" rx="2" fill="#fff1f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="148" y="66" fill="#dc2626" font-size="10" font-weight="600">s19 新規</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="76" width="356" height="72" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="94" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH(Lead 18 tools)</text>
|
||||
<text x="394" y="109" fill="#2563eb" font-size="7.5">bash · read · write · task(4) · send · inbox</text>
|
||||
<text x="394" y="121" fill="#7c3aed" font-size="7.5" font-weight="700">request_shutdown · request_plan · review_plan</text>
|
||||
<text x="394" y="133" fill="#b45309" font-size="7.5" font-weight="700">create_worktree · remove_worktree · keep_worktree</text>
|
||||
<text x="394" y="145" fill="#dc2626" font-size="7.5" font-weight="700">★ connect_mcp + 動的 mcp__server__tool ツール</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- ===== Row 2: MCP Architecture ===== -->
|
||||
<rect x="30" y="172" width="700" height="215" rx="8" fill="#fff1f2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="380" y="194" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">MCP アーキテクチャ(s19 新規:標準プロトコル + 外部ツール動的統合)</text>
|
||||
|
||||
<!-- Agent Side -->
|
||||
<rect x="50" y="210" width="255" height="140" rx="6" fill="#fff" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="177" y="230" fill="#991b1b" font-size="10" font-weight="700" text-anchor="middle">Agent 側(MCPClient)</text>
|
||||
|
||||
<rect x="65" y="240" width="225" height="24" rx="4" fill="#fef2f2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="177" y="256" fill="#475569" font-size="8" text-anchor="middle">connect_mcp → discover → ツール登録</text>
|
||||
|
||||
<rect x="65" y="272" width="225" height="24" rx="4" fill="#fef2f2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="177" y="288" fill="#475569" font-size="8" text-anchor="middle">assemble_tool_pool builtin + mcp 組み立て</text>
|
||||
|
||||
<rect x="65" y="304" width="225" height="24" rx="4" fill="#fef2f2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="177" y="320" fill="#475569" font-size="8" text-anchor="middle">call_tool("mcp__docs__search", ...)</text>
|
||||
|
||||
<!-- Communication arrows -->
|
||||
<line x1="305" y1="262" x2="435" y2="262" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-rose)"/>
|
||||
<text x="370" y="256" fill="#dc2626" font-size="7" font-weight="600" text-anchor="middle">tools/list</text>
|
||||
|
||||
<line x1="435" y1="296" x2="305" y2="296" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-rose)"/>
|
||||
<text x="370" y="312" fill="#dc2626" font-size="7" font-weight="600" text-anchor="middle">tools/call + response</text>
|
||||
|
||||
<!-- MCP Servers -->
|
||||
<rect x="438" y="210" width="275" height="140" rx="6" fill="#fff" stroke="#ca8a04" stroke-width="1.5"/>
|
||||
<text x="575" y="230" fill="#854d0e" font-size="10" font-weight="700" text-anchor="middle">MCP Servers(外部サービス)</text>
|
||||
|
||||
<rect x="453" y="240" width="245" height="28" rx="4" fill="#fefce8" stroke="#facc15" stroke-width="0.5"/>
|
||||
<text x="575" y="258" fill="#854d0e" font-size="9" font-weight="600" text-anchor="middle">docs server: search · get_version</text>
|
||||
|
||||
<rect x="453" y="276" width="245" height="28" rx="4" fill="#fefce8" stroke="#facc15" stroke-width="0.5"/>
|
||||
<text x="575" y="294" fill="#854d0e" font-size="9" font-weight="600" text-anchor="middle">deploy server: trigger · status</text>
|
||||
|
||||
<rect x="453" y="312" width="245" height="28" rx="4" fill="#fefce8" stroke="#facc15" stroke-width="0.5"/>
|
||||
<text x="575" y="330" fill="#854d0e" font-size="9" font-weight="600" text-anchor="middle">任意言語実装、stdio JSON-RPC のみ必要</text>
|
||||
|
||||
<!-- Naming convention -->
|
||||
<rect x="50" y="360" width="660" height="20" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="380" y="374" fill="#92400e" font-size="8" text-anchor="middle">ツール命名: mcp__{server}__{tool} → 例: mcp__docs__search · mcp__deploy__trigger · サーバー間の名前衝突を防止</text>
|
||||
|
||||
<!-- ===== Row 3: Bottom notes ===== -->
|
||||
<rect x="30" y="400" width="700" height="22" rx="4" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="408" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="418" fill="#475569" font-size="10">s18: worktree + events + protocols(Lead 17)</text>
|
||||
<rect x="420" y="408" width="12" height="10" rx="2" fill="#fff1f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="440" y="418" fill="#475569" font-size="10">s19: MCP + dynamic tools(Lead 18)</text>
|
||||
|
||||
<!-- ===== Final note ===== -->
|
||||
<rect x="30" y="430" width="700" height="22" rx="4" fill="#fff1f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="380" y="444" fill="#991b1b" font-size="9" font-weight="600" text-anchor="middle">次の s20:tools、permissions、teams、worktree、MCP などを 1 つの while True ループに統合。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.8 KiB |
112
web/public/course-assets/s19_mcp_plugin/mcp-architecture.svg
Normal file
@@ -0,0 +1,112 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 460" font-family="system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/><stop offset="100%" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="arrow-rose" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
<marker id="arrow-rose-left" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
||||
<path d="M 10 0 L 0 5 L 10 10 z" fill="#dc2626"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="760" height="460" fill="#fafbfc" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<rect x="0" y="0" width="760" height="44" fill="url(#header)" rx="8"/>
|
||||
<rect x="0" y="36" width="760" height="8" fill="url(#header)"/>
|
||||
<text x="380" y="28" fill="#fff" font-size="15" font-weight="700" text-anchor="middle">MCP Plugin — 标准协议 + 外部工具接入 + 工具池组装</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="40" y="56" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="58" y="66" fill="#2563eb" font-size="10" font-weight="600">s18 保留</text>
|
||||
<rect x="140" y="56" width="12" height="10" rx="2" fill="#fff1f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="158" y="66" fill="#dc2626" font-size="10" font-weight="600">s19 新增</text>
|
||||
|
||||
<!-- ===== Row 1: Lead Loop (s18 preserved) ===== -->
|
||||
<rect x="20" y="90" width="70" height="40" rx="8" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/>
|
||||
<text x="55" y="114" fill="#4f46e5" font-size="8" font-weight="600" text-anchor="middle">turn</text>
|
||||
|
||||
<line x1="90" y1="110" x2="104" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="107" y="90" width="70" height="40" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="142" y="114" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">messages</text>
|
||||
|
||||
<line x1="177" y1="110" x2="191" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="194" y="86" width="80" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="234" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">prompt</text>
|
||||
|
||||
<line x1="274" y1="110" x2="288" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="291" y="86" width="70" height="48" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="326" y="114" fill="#1e3a5f" font-size="9" font-weight="600" text-anchor="middle">LLM</text>
|
||||
|
||||
<line x1="361" y1="110" x2="375" y2="110" stroke="#555" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="378" y="76" width="356" height="72" rx="8" fill="#f0f4ff" stroke="#2563eb" stroke-width="1.5"/>
|
||||
<text x="556" y="94" fill="#1e3a5f" font-size="10" font-weight="600" text-anchor="middle">TOOL DISPATCH (Lead 18 tools)</text>
|
||||
<text x="394" y="109" fill="#2563eb" font-size="7.5">bash · read · write · task(4) · send · inbox</text>
|
||||
<text x="394" y="121" fill="#7c3aed" font-size="7.5" font-weight="700">request_shutdown · request_plan · review_plan</text>
|
||||
<text x="394" y="133" fill="#b45309" font-size="7.5" font-weight="700">create_worktree · remove_worktree · keep_worktree</text>
|
||||
<text x="394" y="145" fill="#dc2626" font-size="7.5" font-weight="700">★ connect_mcp + 动态 mcp__server__tool 工具</text>
|
||||
|
||||
<!-- Loop back -->
|
||||
<path d="M 734 110 L 748 110 L 748 150 L 55 150 L 55 130" fill="none" stroke="#94a3b8" stroke-width="1" marker-end="url(#arrow)" stroke-dasharray="5,4"/>
|
||||
|
||||
<!-- ===== Row 2: MCP Architecture (s19 new) ===== -->
|
||||
<rect x="30" y="172" width="700" height="215" rx="8" fill="#fff1f2" stroke="#dc2626" stroke-width="2"/>
|
||||
<text x="380" y="194" fill="#991b1b" font-size="11" font-weight="700" text-anchor="middle">MCP 架构(s19 新增:标准协议 + 外部工具动态接入)</text>
|
||||
|
||||
<!-- Agent Side -->
|
||||
<rect x="50" y="210" width="255" height="140" rx="6" fill="#fff" stroke="#dc2626" stroke-width="1.5"/>
|
||||
<text x="177" y="230" fill="#991b1b" font-size="10" font-weight="700" text-anchor="middle">Agent Side (MCPClient)</text>
|
||||
|
||||
<rect x="65" y="240" width="225" height="24" rx="4" fill="#fef2f2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="177" y="256" fill="#475569" font-size="8" text-anchor="middle">connect_mcp → discover → 注册工具</text>
|
||||
|
||||
<rect x="65" y="272" width="225" height="24" rx="4" fill="#fef2f2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="177" y="288" fill="#475569" font-size="8" text-anchor="middle">assemble_tool_pool 组装 builtin + mcp</text>
|
||||
|
||||
<rect x="65" y="304" width="225" height="24" rx="4" fill="#fef2f2" stroke="#fca5a5" stroke-width="0.5"/>
|
||||
<text x="177" y="320" fill="#475569" font-size="8" text-anchor="middle">call_tool("mcp__docs__search", ...)</text>
|
||||
|
||||
<!-- Communication arrows -->
|
||||
<line x1="305" y1="262" x2="435" y2="262" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-rose)"/>
|
||||
<text x="370" y="256" fill="#dc2626" font-size="7" font-weight="600" text-anchor="middle">tools/list</text>
|
||||
|
||||
<line x1="435" y1="296" x2="305" y2="296" stroke="#dc2626" stroke-width="1.5" marker-end="url(#arrow-rose)"/>
|
||||
<text x="370" y="312" fill="#dc2626" font-size="7" font-weight="600" text-anchor="middle">tools/call + response</text>
|
||||
|
||||
<!-- MCP Servers -->
|
||||
<rect x="438" y="210" width="275" height="140" rx="6" fill="#fff" stroke="#ca8a04" stroke-width="1.5"/>
|
||||
<text x="575" y="230" fill="#854d0e" font-size="10" font-weight="700" text-anchor="middle">MCP Servers (外部服务)</text>
|
||||
|
||||
<rect x="453" y="240" width="245" height="28" rx="4" fill="#fefce8" stroke="#facc15" stroke-width="0.5"/>
|
||||
<text x="575" y="258" fill="#854d0e" font-size="9" font-weight="600" text-anchor="middle">docs server: search · get_version</text>
|
||||
|
||||
<rect x="453" y="276" width="245" height="28" rx="4" fill="#fefce8" stroke="#facc15" stroke-width="0.5"/>
|
||||
<text x="575" y="294" fill="#854d0e" font-size="9" font-weight="600" text-anchor="middle">deploy server: trigger · status</text>
|
||||
|
||||
<rect x="453" y="312" width="245" height="28" rx="4" fill="#fefce8" stroke="#facc15" stroke-width="0.5"/>
|
||||
<text x="575" y="330" fill="#854d0e" font-size="9" font-weight="600" text-anchor="middle">任意语言实现,只需 stdio JSON-RPC</text>
|
||||
|
||||
<!-- Naming convention -->
|
||||
<rect x="50" y="360" width="660" height="20" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="380" y="374" fill="#92400e" font-size="8" text-anchor="middle">工具命名: mcp__{server}__{tool} → 例: mcp__docs__search · mcp__deploy__trigger · 避免不同 server 的工具名冲突</text>
|
||||
|
||||
<!-- ===== Row 3: Bottom notes ===== -->
|
||||
<rect x="30" y="400" width="700" height="22" rx="4" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1"/>
|
||||
<rect x="50" y="408" width="12" height="10" rx="2" fill="#f0f4ff" stroke="#2563eb" stroke-width="1"/>
|
||||
<text x="70" y="418" fill="#475569" font-size="10">s18: worktree + events + protocols (Lead 17)</text>
|
||||
<rect x="420" y="408" width="12" height="10" rx="2" fill="#fff1f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="440" y="418" fill="#475569" font-size="10">s19: MCP + dynamic tools (Lead 18)</text>
|
||||
|
||||
<!-- ===== Final note ===== -->
|
||||
<rect x="30" y="430" width="700" height="22" rx="4" fill="#fff1f2" stroke="#dc2626" stroke-width="1"/>
|
||||
<text x="380" y="444" fill="#991b1b" font-size="9" font-weight="600" text-anchor="middle">下一章 s20:把工具、权限、团队、worktree、MCP 等机制合回同一个 while True 循环。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
@@ -0,0 +1,85 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 920 620" font-family="'Noto Sans CJK SC', 'Droid Sans Fallback', system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#0f766e"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#475569"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#059669"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-orange" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ea580c"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="920" height="620" rx="8" fill="#fafbfc"/>
|
||||
<rect x="0" y="0" width="920" height="46" rx="8" fill="url(#header)"/>
|
||||
<rect x="0" y="38" width="920" height="8" fill="url(#header)"/>
|
||||
<text x="460" y="29" text-anchor="middle" fill="#fff" font-size="17" font-weight="700">s20 Comprehensive Agent — Every Mechanism Around One Loop</text>
|
||||
<rect x="40" y="76" width="840" height="212" rx="8" fill="#eef2ff" stroke="#2563eb" stroke-width="1.8"/>
|
||||
<text x="460" y="101" text-anchor="middle" fill="#1e3a8a" font-size="13" font-weight="700">Core Agent Loop</text>
|
||||
<rect x="70" y="128" width="110" height="48" rx="7" fill="#fff" stroke="#2563eb" stroke-width="1.4"/>
|
||||
<text x="125" y="157" text-anchor="middle" fill="#1e3a5f" font-size="11" font-weight="700">messages[]</text>
|
||||
<line x1="180" y1="152" x2="222" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<rect x="225" y="118" width="150" height="68" rx="7" fill="#ecfdf5" stroke="#059669" stroke-width="1.6"/>
|
||||
<text x="300" y="140" text-anchor="middle" fill="#065f46" font-size="11" font-weight="700">Before LLM</text>
|
||||
<text x="240" y="158" fill="#047857" font-size="8.5">cron/background injection</text>
|
||||
<text x="240" y="171" fill="#047857" font-size="8.5">compact + memory + prompt</text>
|
||||
<line x1="375" y1="152" x2="417" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<rect x="420" y="118" width="110" height="68" rx="7" fill="#fff" stroke="#2563eb" stroke-width="1.4"/>
|
||||
<text x="475" y="146" text-anchor="middle" fill="#1e3a5f" font-size="12" font-weight="700">LLM</text>
|
||||
<text x="475" y="164" text-anchor="middle" fill="#64748b" font-size="8.5">stop_reason=tool_use?</text>
|
||||
<line x1="530" y1="152" x2="572" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<rect x="575" y="118" width="150" height="68" rx="7" fill="#fff7ed" stroke="#ea580c" stroke-width="1.6"/>
|
||||
<text x="650" y="140" text-anchor="middle" fill="#9a3412" font-size="11" font-weight="700">Before Tools</text>
|
||||
<text x="590" y="158" fill="#c2410c" font-size="8.5">PreToolUse hooks</text>
|
||||
<text x="590" y="171" fill="#c2410c" font-size="8.5">permission pipeline</text>
|
||||
<line x1="725" y1="152" x2="767" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<rect x="770" y="118" width="80" height="68" rx="7" fill="#fff" stroke="#2563eb" stroke-width="1.4"/>
|
||||
<text x="810" y="147" text-anchor="middle" fill="#1e3a5f" font-size="10" font-weight="700">handlers</text>
|
||||
<text x="810" y="164" text-anchor="middle" fill="#64748b" font-size="8">builtin + MCP</text>
|
||||
<path d="M 810 186 L 810 244 L 125 244 L 125 176" fill="none" stroke="#475569" stroke-width="1.4" stroke-dasharray="6,4" marker-end="url(#arrow)"/>
|
||||
<text x="460" y="263" text-anchor="middle" fill="#64748b" font-size="9">tool_result / task_notification → messages[] → next turn</text>
|
||||
<rect x="40" y="318" width="190" height="104" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="1.4"/>
|
||||
<text x="135" y="341" text-anchor="middle" fill="#065f46" font-size="11" font-weight="700">Context & Knowledge</text>
|
||||
<text x="58" y="362" fill="#047857" font-size="9">s07 skills + load_skill</text>
|
||||
<text x="58" y="377" fill="#047857" font-size="9">s09 memory selection</text>
|
||||
<text x="58" y="392" fill="#047857" font-size="9">s10 prompt sections</text>
|
||||
<text x="58" y="407" fill="#047857" font-size="9">s08 compact pipeline</text>
|
||||
<path d="M 230 350 L 282 186" fill="none" stroke="#059669" stroke-width="1.3" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<rect x="260" y="318" width="190" height="104" rx="8" fill="#fff7ed" stroke="#ea580c" stroke-width="1.4"/>
|
||||
<text x="355" y="341" text-anchor="middle" fill="#9a3412" font-size="11" font-weight="700">Governance</text>
|
||||
<text x="278" y="362" fill="#c2410c" font-size="9">s03 permission</text>
|
||||
<text x="278" y="377" fill="#c2410c" font-size="9">s04 hooks</text>
|
||||
<text x="278" y="392" fill="#c2410c" font-size="9">s11 retry / fallback</text>
|
||||
<text x="278" y="407" fill="#c2410c" font-size="9">Stop hooks</text>
|
||||
<path d="M 450 350 L 592 186" fill="none" stroke="#ea580c" stroke-width="1.3" marker-end="url(#arrow-orange)" stroke-dasharray="5,3"/>
|
||||
<rect x="480" y="318" width="190" height="104" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.4"/>
|
||||
<text x="575" y="341" text-anchor="middle" fill="#5b21b6" font-size="11" font-weight="700">Durable Work</text>
|
||||
<text x="498" y="362" fill="#6d28d9" font-size="9">s05 todo_write</text>
|
||||
<text x="498" y="377" fill="#6d28d9" font-size="9">s12 task graph</text>
|
||||
<text x="498" y="392" fill="#6d28d9" font-size="9">s13 background</text>
|
||||
<text x="498" y="407" fill="#6d28d9" font-size="9">s14 cron scheduler</text>
|
||||
<path d="M 575 318 L 575 188" fill="none" stroke="#7c3aed" stroke-width="1.3" marker-end="url(#arrow-purple)" stroke-dasharray="5,3"/>
|
||||
<rect x="700" y="318" width="180" height="104" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-width="1.4"/>
|
||||
<text x="790" y="341" text-anchor="middle" fill="#0f766e" font-size="11" font-weight="700">Teams & Plugins</text>
|
||||
<text x="718" y="362" fill="#0f766e" font-size="9">s06 subagent</text>
|
||||
<text x="718" y="377" fill="#0f766e" font-size="9">s15-s17 team protocols</text>
|
||||
<text x="718" y="392" fill="#0f766e" font-size="9">s18 worktree isolation</text>
|
||||
<text x="718" y="407" fill="#0f766e" font-size="9">s19 MCP tools</text>
|
||||
<path d="M 790 318 L 790 188" fill="none" stroke="#0d9488" stroke-width="1.3" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<rect x="70" y="462" width="780" height="112" rx="8" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.2"/>
|
||||
<text x="460" y="487" text-anchor="middle" fill="#1e293b" font-size="12" font-weight="700">TOOL POOL: 27 builtins + dynamic mcp__server__tool</text>
|
||||
<text x="95" y="512" fill="#334155" font-size="9">file/shell: bash · read · write · edit · glob</text>
|
||||
<text x="95" y="530" fill="#334155" font-size="9">single-agent: todo_write · task · load_skill · compact</text>
|
||||
<text x="95" y="548" fill="#334155" font-size="9">durable work: task tools · cron tools</text>
|
||||
<text x="510" y="512" fill="#334155" font-size="9">team: spawn_teammate · send_message · check_inbox</text>
|
||||
<text x="510" y="530" fill="#334155" font-size="9">protocol: request_shutdown · request_plan · review_plan</text>
|
||||
<text x="510" y="548" fill="#334155" font-size="9">isolation/plugin: worktree tools · connect_mcp</text>
|
||||
<path d="M 850 518 L 890 518 L 890 152 L 850 152" fill="none" stroke="#475569" stroke-width="1.2" marker-end="url(#arrow)" stroke-dasharray="4,4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,85 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 920 620" font-family="'Noto Sans CJK JP', 'Noto Sans CJK SC', 'Droid Sans Fallback', system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#0f766e"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#475569"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#059669"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-orange" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ea580c"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="920" height="620" rx="8" fill="#fafbfc"/>
|
||||
<rect x="0" y="0" width="920" height="46" rx="8" fill="url(#header)"/>
|
||||
<rect x="0" y="38" width="920" height="8" fill="url(#header)"/>
|
||||
<text x="460" y="29" text-anchor="middle" fill="#fff" font-size="17" font-weight="700">s20 Comprehensive Agent — すべての仕組みを 1 つのループへ</text>
|
||||
<rect x="40" y="76" width="840" height="212" rx="8" fill="#eef2ff" stroke="#2563eb" stroke-width="1.8"/>
|
||||
<text x="460" y="101" text-anchor="middle" fill="#1e3a8a" font-size="13" font-weight="700">Core Agent Loop</text>
|
||||
<rect x="70" y="128" width="110" height="48" rx="7" fill="#fff" stroke="#2563eb" stroke-width="1.4"/>
|
||||
<text x="125" y="157" text-anchor="middle" fill="#1e3a5f" font-size="11" font-weight="700">messages[]</text>
|
||||
<line x1="180" y1="152" x2="222" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<rect x="225" y="118" width="150" height="68" rx="7" fill="#ecfdf5" stroke="#059669" stroke-width="1.6"/>
|
||||
<text x="300" y="140" text-anchor="middle" fill="#065f46" font-size="11" font-weight="700">LLM 前</text>
|
||||
<text x="240" y="158" fill="#047857" font-size="8.5">cron/background 注入</text>
|
||||
<text x="240" y="171" fill="#047857" font-size="8.5">compact + memory + prompt</text>
|
||||
<line x1="375" y1="152" x2="417" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<rect x="420" y="118" width="110" height="68" rx="7" fill="#fff" stroke="#2563eb" stroke-width="1.4"/>
|
||||
<text x="475" y="146" text-anchor="middle" fill="#1e3a5f" font-size="12" font-weight="700">LLM</text>
|
||||
<text x="475" y="164" text-anchor="middle" fill="#64748b" font-size="8.5">stop_reason=tool_use?</text>
|
||||
<line x1="530" y1="152" x2="572" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<rect x="575" y="118" width="150" height="68" rx="7" fill="#fff7ed" stroke="#ea580c" stroke-width="1.6"/>
|
||||
<text x="650" y="140" text-anchor="middle" fill="#9a3412" font-size="11" font-weight="700">Tool 前</text>
|
||||
<text x="590" y="158" fill="#c2410c" font-size="8.5">PreToolUse hooks</text>
|
||||
<text x="590" y="171" fill="#c2410c" font-size="8.5">permission pipeline</text>
|
||||
<line x1="725" y1="152" x2="767" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
<rect x="770" y="118" width="80" height="68" rx="7" fill="#fff" stroke="#2563eb" stroke-width="1.4"/>
|
||||
<text x="810" y="147" text-anchor="middle" fill="#1e3a5f" font-size="10" font-weight="700">handlers</text>
|
||||
<text x="810" y="164" text-anchor="middle" fill="#64748b" font-size="8">builtin + MCP</text>
|
||||
<path d="M 810 186 L 810 244 L 125 244 L 125 176" fill="none" stroke="#475569" stroke-width="1.4" stroke-dasharray="6,4" marker-end="url(#arrow)"/>
|
||||
<text x="460" y="263" text-anchor="middle" fill="#64748b" font-size="9">tool_result / task_notification → messages[] → 次のターン</text>
|
||||
<rect x="40" y="318" width="190" height="104" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="1.4"/>
|
||||
<text x="135" y="341" text-anchor="middle" fill="#065f46" font-size="11" font-weight="700">Context / Knowledge</text>
|
||||
<text x="58" y="362" fill="#047857" font-size="9">s07 skills + load_skill</text>
|
||||
<text x="58" y="377" fill="#047857" font-size="9">s09 memory selection</text>
|
||||
<text x="58" y="392" fill="#047857" font-size="9">s10 prompt sections</text>
|
||||
<text x="58" y="407" fill="#047857" font-size="9">s08 compact pipeline</text>
|
||||
<path d="M 230 350 L 282 186" fill="none" stroke="#059669" stroke-width="1.3" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<rect x="260" y="318" width="190" height="104" rx="8" fill="#fff7ed" stroke="#ea580c" stroke-width="1.4"/>
|
||||
<text x="355" y="341" text-anchor="middle" fill="#9a3412" font-size="11" font-weight="700">Governance</text>
|
||||
<text x="278" y="362" fill="#c2410c" font-size="9">s03 permission</text>
|
||||
<text x="278" y="377" fill="#c2410c" font-size="9">s04 hooks</text>
|
||||
<text x="278" y="392" fill="#c2410c" font-size="9">s11 retry / fallback</text>
|
||||
<text x="278" y="407" fill="#c2410c" font-size="9">Stop hooks</text>
|
||||
<path d="M 450 350 L 592 186" fill="none" stroke="#ea580c" stroke-width="1.3" marker-end="url(#arrow-orange)" stroke-dasharray="5,3"/>
|
||||
<rect x="480" y="318" width="190" height="104" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.4"/>
|
||||
<text x="575" y="341" text-anchor="middle" fill="#5b21b6" font-size="11" font-weight="700">Durable Work</text>
|
||||
<text x="498" y="362" fill="#6d28d9" font-size="9">s05 todo_write</text>
|
||||
<text x="498" y="377" fill="#6d28d9" font-size="9">s12 task graph</text>
|
||||
<text x="498" y="392" fill="#6d28d9" font-size="9">s13 background</text>
|
||||
<text x="498" y="407" fill="#6d28d9" font-size="9">s14 cron scheduler</text>
|
||||
<path d="M 575 318 L 575 188" fill="none" stroke="#7c3aed" stroke-width="1.3" marker-end="url(#arrow-purple)" stroke-dasharray="5,3"/>
|
||||
<rect x="700" y="318" width="180" height="104" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-width="1.4"/>
|
||||
<text x="790" y="341" text-anchor="middle" fill="#0f766e" font-size="11" font-weight="700">Teams / Plugins</text>
|
||||
<text x="718" y="362" fill="#0f766e" font-size="9">s06 subagent</text>
|
||||
<text x="718" y="377" fill="#0f766e" font-size="9">s15-s17 team protocols</text>
|
||||
<text x="718" y="392" fill="#0f766e" font-size="9">s18 worktree isolation</text>
|
||||
<text x="718" y="407" fill="#0f766e" font-size="9">s19 MCP tools</text>
|
||||
<path d="M 790 318 L 790 188" fill="none" stroke="#0d9488" stroke-width="1.3" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
<rect x="70" y="462" width="780" height="112" rx="8" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.2"/>
|
||||
<text x="460" y="487" text-anchor="middle" fill="#1e293b" font-size="12" font-weight="700">TOOL POOL: 27 builtins + dynamic mcp__server__tool</text>
|
||||
<text x="95" y="512" fill="#334155" font-size="9">file/shell: bash · read · write · edit · glob</text>
|
||||
<text x="95" y="530" fill="#334155" font-size="9">single-agent: todo_write · task · load_skill · compact</text>
|
||||
<text x="95" y="548" fill="#334155" font-size="9">durable work: task tools · cron tools</text>
|
||||
<text x="510" y="512" fill="#334155" font-size="9">team: spawn_teammate · send_message · check_inbox</text>
|
||||
<text x="510" y="530" fill="#334155" font-size="9">protocol: request_shutdown · request_plan · review_plan</text>
|
||||
<text x="510" y="548" fill="#334155" font-size="9">isolation/plugin: worktree tools · connect_mcp</text>
|
||||
<path d="M 850 518 L 890 518 L 890 152 L 850 152" fill="none" stroke="#475569" stroke-width="1.2" marker-end="url(#arrow)" stroke-dasharray="4,4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
@@ -0,0 +1,105 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 920 620" font-family="'Noto Sans CJK SC', 'Droid Sans Fallback', system-ui, -apple-system, sans-serif">
|
||||
<defs>
|
||||
<linearGradient id="header" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1e3a5f"/>
|
||||
<stop offset="100%" stop-color="#0f766e"/>
|
||||
</linearGradient>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#475569"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#059669"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c3aed"/>
|
||||
</marker>
|
||||
<marker id="arrow-orange" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ea580c"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<rect width="920" height="620" rx="8" fill="#fafbfc"/>
|
||||
<rect x="0" y="0" width="920" height="46" rx="8" fill="url(#header)"/>
|
||||
<rect x="0" y="38" width="920" height="8" fill="url(#header)"/>
|
||||
<text x="460" y="29" text-anchor="middle" fill="#fff" font-size="17" font-weight="700">s20 Comprehensive Agent — 全部机制挂在同一个循环上</text>
|
||||
|
||||
<!-- Main loop band -->
|
||||
<rect x="40" y="76" width="840" height="212" rx="8" fill="#eef2ff" stroke="#2563eb" stroke-width="1.8"/>
|
||||
<text x="460" y="101" text-anchor="middle" fill="#1e3a8a" font-size="13" font-weight="700">核心 Agent Loop</text>
|
||||
|
||||
<rect x="70" y="128" width="110" height="48" rx="7" fill="#fff" stroke="#2563eb" stroke-width="1.4"/>
|
||||
<text x="125" y="157" text-anchor="middle" fill="#1e3a5f" font-size="11" font-weight="700">messages[]</text>
|
||||
|
||||
<line x1="180" y1="152" x2="222" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="225" y="118" width="150" height="68" rx="7" fill="#ecfdf5" stroke="#059669" stroke-width="1.6"/>
|
||||
<text x="300" y="140" text-anchor="middle" fill="#065f46" font-size="11" font-weight="700">LLM 前处理</text>
|
||||
<text x="240" y="158" fill="#047857" font-size="8.5">cron / background 注入</text>
|
||||
<text x="240" y="171" fill="#047857" font-size="8.5">compact + memory + prompt</text>
|
||||
|
||||
<line x1="375" y1="152" x2="417" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="420" y="118" width="110" height="68" rx="7" fill="#fff" stroke="#2563eb" stroke-width="1.4"/>
|
||||
<text x="475" y="146" text-anchor="middle" fill="#1e3a5f" font-size="12" font-weight="700">LLM</text>
|
||||
<text x="475" y="164" text-anchor="middle" fill="#64748b" font-size="8.5">stop_reason=tool_use?</text>
|
||||
|
||||
<line x1="530" y1="152" x2="572" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="575" y="118" width="150" height="68" rx="7" fill="#fff7ed" stroke="#ea580c" stroke-width="1.6"/>
|
||||
<text x="650" y="140" text-anchor="middle" fill="#9a3412" font-size="11" font-weight="700">工具前闸门</text>
|
||||
<text x="590" y="158" fill="#c2410c" font-size="8.5">PreToolUse hooks</text>
|
||||
<text x="590" y="171" fill="#c2410c" font-size="8.5">permission pipeline</text>
|
||||
|
||||
<line x1="725" y1="152" x2="767" y2="152" stroke="#475569" stroke-width="1.5" marker-end="url(#arrow)"/>
|
||||
|
||||
<rect x="770" y="118" width="80" height="68" rx="7" fill="#fff" stroke="#2563eb" stroke-width="1.4"/>
|
||||
<text x="810" y="147" text-anchor="middle" fill="#1e3a5f" font-size="10" font-weight="700">handlers</text>
|
||||
<text x="810" y="164" text-anchor="middle" fill="#64748b" font-size="8">builtin + MCP</text>
|
||||
|
||||
<path d="M 810 186 L 810 244 L 125 244 L 125 176" fill="none" stroke="#475569" stroke-width="1.4" stroke-dasharray="6,4" marker-end="url(#arrow)"/>
|
||||
<text x="460" y="263" text-anchor="middle" fill="#64748b" font-size="9">tool_result / task_notification → messages[] → 下一轮</text>
|
||||
|
||||
<!-- Top sidecars -->
|
||||
<rect x="40" y="318" width="190" height="104" rx="8" fill="#ecfdf5" stroke="#059669" stroke-width="1.4"/>
|
||||
<text x="135" y="341" text-anchor="middle" fill="#065f46" font-size="11" font-weight="700">上下文与知识</text>
|
||||
<text x="58" y="362" fill="#047857" font-size="9">s07 skills catalog + load_skill</text>
|
||||
<text x="58" y="377" fill="#047857" font-size="9">s09 memory selection</text>
|
||||
<text x="58" y="392" fill="#047857" font-size="9">s10 prompt sections</text>
|
||||
<text x="58" y="407" fill="#047857" font-size="9">s08 compact pipeline</text>
|
||||
<path d="M 230 350 L 282 186" fill="none" stroke="#059669" stroke-width="1.3" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
|
||||
<rect x="260" y="318" width="190" height="104" rx="8" fill="#fff7ed" stroke="#ea580c" stroke-width="1.4"/>
|
||||
<text x="355" y="341" text-anchor="middle" fill="#9a3412" font-size="11" font-weight="700">治理与扩展点</text>
|
||||
<text x="278" y="362" fill="#c2410c" font-size="9">s03 permission</text>
|
||||
<text x="278" y="377" fill="#c2410c" font-size="9">s04 hooks</text>
|
||||
<text x="278" y="392" fill="#c2410c" font-size="9">s11 retry / fallback</text>
|
||||
<text x="278" y="407" fill="#c2410c" font-size="9">Stop hooks</text>
|
||||
<path d="M 450 350 L 592 186" fill="none" stroke="#ea580c" stroke-width="1.3" marker-end="url(#arrow-orange)" stroke-dasharray="5,3"/>
|
||||
|
||||
<rect x="480" y="318" width="190" height="104" rx="8" fill="#f5f3ff" stroke="#7c3aed" stroke-width="1.4"/>
|
||||
<text x="575" y="341" text-anchor="middle" fill="#5b21b6" font-size="11" font-weight="700">持久工作</text>
|
||||
<text x="498" y="362" fill="#6d28d9" font-size="9">s05 todo_write</text>
|
||||
<text x="498" y="377" fill="#6d28d9" font-size="9">s12 task graph</text>
|
||||
<text x="498" y="392" fill="#6d28d9" font-size="9">s13 background</text>
|
||||
<text x="498" y="407" fill="#6d28d9" font-size="9">s14 cron scheduler</text>
|
||||
<path d="M 575 318 L 575 188" fill="none" stroke="#7c3aed" stroke-width="1.3" marker-end="url(#arrow-purple)" stroke-dasharray="5,3"/>
|
||||
|
||||
<rect x="700" y="318" width="180" height="104" rx="8" fill="#f0fdfa" stroke="#0d9488" stroke-width="1.4"/>
|
||||
<text x="790" y="341" text-anchor="middle" fill="#0f766e" font-size="11" font-weight="700">团队与插件</text>
|
||||
<text x="718" y="362" fill="#0f766e" font-size="9">s06 subagent</text>
|
||||
<text x="718" y="377" fill="#0f766e" font-size="9">s15-s17 team protocols</text>
|
||||
<text x="718" y="392" fill="#0f766e" font-size="9">s18 worktree isolation</text>
|
||||
<text x="718" y="407" fill="#0f766e" font-size="9">s19 MCP tools</text>
|
||||
<path d="M 790 318 L 790 188" fill="none" stroke="#0d9488" stroke-width="1.3" marker-end="url(#arrow-green)" stroke-dasharray="5,3"/>
|
||||
|
||||
<!-- Tool pool -->
|
||||
<rect x="70" y="462" width="780" height="112" rx="8" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.2"/>
|
||||
<text x="460" y="487" text-anchor="middle" fill="#1e293b" font-size="12" font-weight="700">TOOL POOL: 27 builtins + dynamic mcp__server__tool</text>
|
||||
<text x="95" y="512" fill="#334155" font-size="9">file/shell: bash · read · write · edit · glob</text>
|
||||
<text x="95" y="530" fill="#334155" font-size="9">single-agent: todo_write · task · load_skill · compact</text>
|
||||
<text x="95" y="548" fill="#334155" font-size="9">durable work: create/list/get/claim/complete_task · schedule/list/cancel_cron</text>
|
||||
<text x="510" y="512" fill="#334155" font-size="9">team: spawn_teammate · send_message · check_inbox</text>
|
||||
<text x="510" y="530" fill="#334155" font-size="9">protocol: request_shutdown · request_plan · review_plan</text>
|
||||
<text x="510" y="548" fill="#334155" font-size="9">isolation/plugin: create/remove/keep_worktree · connect_mcp</text>
|
||||
<path d="M 850 518 L 890 518 L 890 152 L 850 152" fill="none" stroke="#475569" stroke-width="1.2" marker-end="url(#arrow)" stroke-dasharray="4,4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.8 KiB |
@@ -5,31 +5,58 @@ import type {
|
||||
VersionDiff,
|
||||
DocContent,
|
||||
VersionIndex,
|
||||
ChapterImage,
|
||||
} from "../src/types/agent-data";
|
||||
import { VERSION_META, VERSION_ORDER, LEARNING_PATH } from "../src/lib/constants";
|
||||
|
||||
// Resolve paths relative to this script's location (web/scripts/)
|
||||
const WEB_DIR = path.resolve(__dirname, "..");
|
||||
const REPO_ROOT = path.resolve(WEB_DIR, "..");
|
||||
const AGENTS_DIR = path.join(REPO_ROOT, "agents");
|
||||
const DOCS_DIR = path.join(REPO_ROOT, "docs");
|
||||
const LEGACY_AGENTS_DIR = path.join(REPO_ROOT, "agents");
|
||||
const LEGACY_DOCS_DIR = path.join(REPO_ROOT, "docs");
|
||||
const OUT_DIR = path.join(WEB_DIR, "src", "data", "generated");
|
||||
const PUBLIC_DIR = path.join(WEB_DIR, "public");
|
||||
const COURSE_ASSETS_DIR = path.join(PUBLIC_DIR, "course-assets");
|
||||
|
||||
// Map python filenames to version IDs
|
||||
// s01_agent_loop.py -> s01
|
||||
// s02_tools.py -> s02
|
||||
// s_full.py -> s_full (reference agent, typically skipped)
|
||||
function filenameToVersionId(filename: string): string | null {
|
||||
const base = path.basename(filename, ".py");
|
||||
if (base === "s_full") return null;
|
||||
if (base === "__init__") return null;
|
||||
type Locale = "en" | "zh" | "ja";
|
||||
|
||||
const match = base.match(/^(s\d+[a-c]?)_/);
|
||||
if (!match) return null;
|
||||
return match[1];
|
||||
interface ChapterSource {
|
||||
id: string;
|
||||
dirName: string;
|
||||
dirPath: string;
|
||||
codePath: string;
|
||||
}
|
||||
|
||||
function dirToVersionId(dirName: string): string | null {
|
||||
const match = dirName.match(/^(s\d{2})_/);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
function filenameToVersionId(filename: string): string | null {
|
||||
const base = path.basename(filename, ".py");
|
||||
if (base === "s_full" || base === "__init__") return null;
|
||||
|
||||
const match = base.match(/^(s\d+[a-c]?)_/);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
function listRootChapters(): ChapterSource[] {
|
||||
return fs
|
||||
.readdirSync(REPO_ROOT, { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.map((entry) => entry.name)
|
||||
.filter((name) => /^s\d{2}_/.test(name))
|
||||
.sort()
|
||||
.map((dirName) => {
|
||||
const id = dirToVersionId(dirName);
|
||||
if (!id) return null;
|
||||
const dirPath = path.join(REPO_ROOT, dirName);
|
||||
const codePath = path.join(dirPath, "code.py");
|
||||
if (!fs.existsSync(codePath)) return null;
|
||||
return { id, dirName, dirPath, codePath };
|
||||
})
|
||||
.filter((chapter): chapter is ChapterSource => chapter !== null);
|
||||
}
|
||||
|
||||
// Extract classes from Python source
|
||||
function extractClasses(
|
||||
lines: string[]
|
||||
): { name: string; startLine: number; endLine: number }[] {
|
||||
@@ -37,29 +64,31 @@ function extractClasses(
|
||||
const classPattern = /^class\s+(\w+)/;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const m = lines[i].match(classPattern);
|
||||
if (m) {
|
||||
const name = m[1];
|
||||
const startLine = i + 1;
|
||||
// Find end of class: next class/function at indent 0, or EOF
|
||||
let endLine = lines.length;
|
||||
for (let j = i + 1; j < lines.length; j++) {
|
||||
if (
|
||||
lines[j].match(/^class\s/) ||
|
||||
lines[j].match(/^def\s/) ||
|
||||
(lines[j].match(/^\S/) && lines[j].trim() !== "" && !lines[j].startsWith("#") && !lines[j].startsWith("@"))
|
||||
) {
|
||||
endLine = j;
|
||||
break;
|
||||
}
|
||||
const match = lines[i].match(classPattern);
|
||||
if (!match) continue;
|
||||
|
||||
const name = match[1];
|
||||
const startLine = i + 1;
|
||||
let endLine = lines.length;
|
||||
for (let j = i + 1; j < lines.length; j++) {
|
||||
if (
|
||||
lines[j].match(/^class\s/) ||
|
||||
lines[j].match(/^def\s/) ||
|
||||
(lines[j].match(/^\S/) &&
|
||||
lines[j].trim() !== "" &&
|
||||
!lines[j].startsWith("#") &&
|
||||
!lines[j].startsWith("@"))
|
||||
) {
|
||||
endLine = j;
|
||||
break;
|
||||
}
|
||||
classes.push({ name, startLine, endLine });
|
||||
}
|
||||
classes.push({ name, startLine, endLine });
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
// Extract top-level functions from Python source
|
||||
function extractFunctions(
|
||||
lines: string[]
|
||||
): { name: string; signature: string; startLine: number }[] {
|
||||
@@ -67,31 +96,28 @@ function extractFunctions(
|
||||
const funcPattern = /^def\s+(\w+)\((.*?)\)/;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const m = lines[i].match(funcPattern);
|
||||
if (m) {
|
||||
functions.push({
|
||||
name: m[1],
|
||||
signature: `def ${m[1]}(${m[2]})`,
|
||||
startLine: i + 1,
|
||||
});
|
||||
}
|
||||
const match = lines[i].match(funcPattern);
|
||||
if (!match) continue;
|
||||
functions.push({
|
||||
name: match[1],
|
||||
signature: `def ${match[1]}(${match[2]})`,
|
||||
startLine: i + 1,
|
||||
});
|
||||
}
|
||||
|
||||
return functions;
|
||||
}
|
||||
|
||||
// Extract tool names from Python source
|
||||
// Looks for "name": "tool_name" patterns in dict literals
|
||||
function extractTools(source: string): string[] {
|
||||
const toolPattern = /"name"\s*:\s*"(\w+)"/g;
|
||||
const toolPattern = /"name"\s*:\s*"([\w-]+)"/g;
|
||||
const tools = new Set<string>();
|
||||
let m;
|
||||
while ((m = toolPattern.exec(source)) !== null) {
|
||||
tools.add(m[1]);
|
||||
let match;
|
||||
while ((match = toolPattern.exec(source)) !== null) {
|
||||
tools.add(match[1]);
|
||||
}
|
||||
return Array.from(tools);
|
||||
}
|
||||
|
||||
// Count non-blank, non-comment lines
|
||||
function countLoc(lines: string[]): number {
|
||||
return lines.filter((line) => {
|
||||
const trimmed = line.trim();
|
||||
@@ -99,181 +125,287 @@ function countLoc(lines: string[]): number {
|
||||
}).length;
|
||||
}
|
||||
|
||||
// Detect locale from subdirectory path
|
||||
// docs/en/s01-the-agent-loop.md -> "en"
|
||||
// docs/zh/s01-the-agent-loop.md -> "zh"
|
||||
// docs/ja/s01-the-agent-loop.md -> "ja"
|
||||
function detectLocale(relPath: string): "en" | "zh" | "ja" {
|
||||
function detectLocale(relPath: string): Locale {
|
||||
if (relPath.startsWith("zh/") || relPath.startsWith("zh\\")) return "zh";
|
||||
if (relPath.startsWith("ja/") || relPath.startsWith("ja\\")) return "ja";
|
||||
return "en";
|
||||
}
|
||||
|
||||
// Extract version from doc filename (e.g., "s01-the-agent-loop.md" -> "s01")
|
||||
function extractDocVersion(filename: string): string | null {
|
||||
const m = filename.match(/^(s\d+[a-c]?)-/);
|
||||
return m ? m[1] : null;
|
||||
const match = filename.match(/^(s\d+[a-c]?)-/);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
// Main extraction
|
||||
function main() {
|
||||
console.log("Extracting content from agents and docs...");
|
||||
console.log(` Repo root: ${REPO_ROOT}`);
|
||||
console.log(` Agents dir: ${AGENTS_DIR}`);
|
||||
console.log(` Docs dir: ${DOCS_DIR}`);
|
||||
function titleFromMarkdown(content: string, fallback: string): string {
|
||||
const titleMatch = content.match(/^#\s+(.+)$/m);
|
||||
return titleMatch ? titleMatch[1] : fallback;
|
||||
}
|
||||
|
||||
// Skip extraction if source directories don't exist (e.g. Vercel build).
|
||||
// Pre-committed generated data will be used instead.
|
||||
if (!fs.existsSync(AGENTS_DIR)) {
|
||||
console.log(" Agents directory not found, skipping extraction.");
|
||||
console.log(" Using pre-committed generated data.");
|
||||
return;
|
||||
}
|
||||
function cleanCourseAssets() {
|
||||
fs.rmSync(COURSE_ASSETS_DIR, { recursive: true, force: true });
|
||||
fs.mkdirSync(COURSE_ASSETS_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
// 1. Read all agent files
|
||||
const agentFiles = fs
|
||||
.readdirSync(AGENTS_DIR)
|
||||
.filter((f) => f.startsWith("s") && f.endsWith(".py"));
|
||||
function copyChapterAssets(chapter: ChapterSource): ChapterImage[] {
|
||||
const imagesDir = path.join(chapter.dirPath, "images");
|
||||
if (!fs.existsSync(imagesDir)) return [];
|
||||
|
||||
console.log(` Found ${agentFiles.length} agent files`);
|
||||
const outDir = path.join(COURSE_ASSETS_DIR, chapter.dirName);
|
||||
fs.mkdirSync(outDir, { recursive: true });
|
||||
fs.cpSync(imagesDir, outDir, { recursive: true });
|
||||
|
||||
const versions: AgentVersion[] = [];
|
||||
return fs
|
||||
.readdirSync(imagesDir)
|
||||
.filter((filename) => filename.endsWith(".svg"))
|
||||
.filter((filename) => !filename.includes(".en.") && !filename.includes(".ja."))
|
||||
.sort()
|
||||
.map((filename) => ({
|
||||
src: `/course-assets/${chapter.dirName}/${filename}`,
|
||||
alt: filename.replace(/\.svg$/, "").replace(/-/g, " "),
|
||||
}));
|
||||
}
|
||||
|
||||
for (const filename of agentFiles) {
|
||||
const versionId = filenameToVersionId(filename);
|
||||
if (!versionId) {
|
||||
console.warn(` Skipping ${filename}: could not determine version ID`);
|
||||
continue;
|
||||
}
|
||||
function localeReadmeName(locale: Locale): string {
|
||||
if (locale === "zh") return "README.md";
|
||||
return `README.${locale}.md`;
|
||||
}
|
||||
|
||||
const filePath = path.join(AGENTS_DIR, filename);
|
||||
const source = fs.readFileSync(filePath, "utf-8");
|
||||
const lines = source.split("\n");
|
||||
function rewriteChapterMarkdown(
|
||||
content: string,
|
||||
chapter: ChapterSource,
|
||||
locale: Locale
|
||||
): string {
|
||||
let next = content;
|
||||
|
||||
const meta = VERSION_META[versionId];
|
||||
const classes = extractClasses(lines);
|
||||
const functions = extractFunctions(lines);
|
||||
const tools = extractTools(source);
|
||||
const loc = countLoc(lines);
|
||||
|
||||
versions.push({
|
||||
id: versionId,
|
||||
filename,
|
||||
title: meta?.title ?? versionId,
|
||||
subtitle: meta?.subtitle ?? "",
|
||||
loc,
|
||||
tools,
|
||||
newTools: [], // computed after all versions are loaded
|
||||
coreAddition: meta?.coreAddition ?? "",
|
||||
keyInsight: meta?.keyInsight ?? "",
|
||||
classes,
|
||||
functions,
|
||||
layer: meta?.layer ?? "tools",
|
||||
source,
|
||||
});
|
||||
}
|
||||
|
||||
// Sort versions according to VERSION_ORDER
|
||||
const orderMap = new Map(VERSION_ORDER.map((v, i) => [v, i]));
|
||||
versions.sort(
|
||||
(a, b) => (orderMap.get(a.id as any) ?? 99) - (orderMap.get(b.id as any) ?? 99)
|
||||
next = next.replace(
|
||||
/^\[中文\]\(README\.md\)\s*.\s*\[English\]\(README\.en\.md\)\s*.\s*\[日本語\]\(README\.ja\.md\)\n\n?/m,
|
||||
""
|
||||
);
|
||||
|
||||
// 2. Compute newTools for each version
|
||||
for (let i = 0; i < versions.length; i++) {
|
||||
const prev = i > 0 ? new Set(versions[i - 1].tools) : new Set<string>();
|
||||
versions[i].newTools = versions[i].tools.filter((t) => !prev.has(t));
|
||||
next = next.replace(
|
||||
/(!\[[^\]]*\]\()images\/([^)]+)(\))/g,
|
||||
`$1/course-assets/${chapter.dirName}/$2$3`
|
||||
);
|
||||
|
||||
next = next.replace(
|
||||
/\]\(\.\.\/(s\d{2}_[^)\/]+)\/?\)/g,
|
||||
(_match, dirName) => {
|
||||
const id = dirToVersionId(dirName);
|
||||
return id ? `](/${locale}/${id})` : `](../${dirName}/)`;
|
||||
}
|
||||
);
|
||||
|
||||
next = next.replace(
|
||||
/\]\(\.\/(s\d{2}_[^)\/]+)\/?\)/g,
|
||||
(_match, dirName) => {
|
||||
const id = dirToVersionId(dirName);
|
||||
return id ? `](/${locale}/${id})` : `](./${dirName}/)`;
|
||||
}
|
||||
);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
function buildRootVersions(chapters: ChapterSource[]): AgentVersion[] {
|
||||
return chapters.map((chapter) => {
|
||||
const source = fs.readFileSync(chapter.codePath, "utf-8");
|
||||
const lines = source.split("\n");
|
||||
const meta = VERSION_META[chapter.id];
|
||||
|
||||
return {
|
||||
id: chapter.id,
|
||||
filename: `${chapter.dirName}/code.py`,
|
||||
title: meta?.title ?? chapter.id,
|
||||
subtitle: meta?.subtitle ?? "",
|
||||
loc: countLoc(lines),
|
||||
tools: extractTools(source),
|
||||
newTools: [] as string[],
|
||||
coreAddition: meta?.coreAddition ?? "",
|
||||
keyInsight: meta?.keyInsight ?? "",
|
||||
classes: extractClasses(lines),
|
||||
functions: extractFunctions(lines),
|
||||
layer: meta?.layer ?? "tools",
|
||||
source,
|
||||
images: copyChapterAssets(chapter),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function buildLegacyVersions(): AgentVersion[] {
|
||||
if (!fs.existsSync(LEGACY_AGENTS_DIR)) return [];
|
||||
|
||||
const agentFiles = fs
|
||||
.readdirSync(LEGACY_AGENTS_DIR)
|
||||
.filter((filename) => filename.startsWith("s") && filename.endsWith(".py"));
|
||||
|
||||
const versions = agentFiles
|
||||
.map((filename) => {
|
||||
const id = filenameToVersionId(filename);
|
||||
if (!id) return null;
|
||||
|
||||
const filePath = path.join(LEGACY_AGENTS_DIR, filename);
|
||||
const source = fs.readFileSync(filePath, "utf-8");
|
||||
const lines = source.split("\n");
|
||||
const meta = VERSION_META[id];
|
||||
|
||||
return {
|
||||
id,
|
||||
filename,
|
||||
title: meta?.title ?? id,
|
||||
subtitle: meta?.subtitle ?? "",
|
||||
loc: countLoc(lines),
|
||||
tools: extractTools(source),
|
||||
newTools: [] as string[],
|
||||
coreAddition: meta?.coreAddition ?? "",
|
||||
keyInsight: meta?.keyInsight ?? "",
|
||||
classes: extractClasses(lines),
|
||||
functions: extractFunctions(lines),
|
||||
layer: meta?.layer ?? "tools",
|
||||
source,
|
||||
images: [] as ChapterImage[],
|
||||
};
|
||||
})
|
||||
.filter((version): version is AgentVersion => version !== null);
|
||||
|
||||
return versions;
|
||||
}
|
||||
|
||||
function buildRootDocs(chapters: ChapterSource[]): DocContent[] {
|
||||
const docs: DocContent[] = [];
|
||||
const locales: Locale[] = ["en", "zh", "ja"];
|
||||
|
||||
for (const chapter of chapters) {
|
||||
for (const locale of locales) {
|
||||
const filename = localeReadmeName(locale);
|
||||
const filePath = path.join(chapter.dirPath, filename);
|
||||
if (!fs.existsSync(filePath)) continue;
|
||||
|
||||
const raw = fs.readFileSync(filePath, "utf-8");
|
||||
const content = rewriteChapterMarkdown(raw, chapter, locale);
|
||||
docs.push({
|
||||
version: chapter.id,
|
||||
locale,
|
||||
title: titleFromMarkdown(content, filename),
|
||||
content,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Compute diffs between adjacent versions in LEARNING_PATH
|
||||
return docs;
|
||||
}
|
||||
|
||||
function buildLegacyDocs(): DocContent[] {
|
||||
const docs: DocContent[] = [];
|
||||
if (!fs.existsSync(LEGACY_DOCS_DIR)) return docs;
|
||||
|
||||
const localeDirs: Locale[] = ["en", "zh", "ja"];
|
||||
for (const locale of localeDirs) {
|
||||
const localeDir = path.join(LEGACY_DOCS_DIR, locale);
|
||||
if (!fs.existsSync(localeDir)) continue;
|
||||
|
||||
const docFiles = fs.readdirSync(localeDir).filter((f) => f.endsWith(".md"));
|
||||
for (const filename of docFiles) {
|
||||
const version = extractDocVersion(filename);
|
||||
if (!version) continue;
|
||||
|
||||
const relPath = path.join(locale, filename);
|
||||
const filePath = path.join(LEGACY_DOCS_DIR, relPath);
|
||||
const content = fs.readFileSync(filePath, "utf-8");
|
||||
docs.push({
|
||||
version,
|
||||
locale: detectLocale(relPath),
|
||||
title: titleFromMarkdown(content, filename),
|
||||
content,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return docs;
|
||||
}
|
||||
|
||||
function computeNewTools(versions: AgentVersion[]) {
|
||||
for (let i = 0; i < versions.length; i++) {
|
||||
const prev = i > 0 ? new Set(versions[i - 1].tools) : new Set<string>();
|
||||
versions[i].newTools = versions[i].tools.filter((tool) => !prev.has(tool));
|
||||
}
|
||||
}
|
||||
|
||||
function buildDiffs(versions: AgentVersion[]): VersionDiff[] {
|
||||
const diffs: VersionDiff[] = [];
|
||||
const versionMap = new Map(versions.map((v) => [v.id, v]));
|
||||
const versionMap = new Map(versions.map((version) => [version.id, version]));
|
||||
|
||||
for (let i = 1; i < LEARNING_PATH.length; i++) {
|
||||
const fromId = LEARNING_PATH[i - 1];
|
||||
const toId = LEARNING_PATH[i];
|
||||
const fromVer = versionMap.get(fromId);
|
||||
const toVer = versionMap.get(toId);
|
||||
|
||||
if (!fromVer || !toVer) continue;
|
||||
|
||||
const fromClassNames = new Set(fromVer.classes.map((c) => c.name));
|
||||
const fromFuncNames = new Set(fromVer.functions.map((f) => f.name));
|
||||
const fromClassNames = new Set(fromVer.classes.map((cls) => cls.name));
|
||||
const fromFuncNames = new Set(fromVer.functions.map((fn) => fn.name));
|
||||
const fromToolNames = new Set(fromVer.tools);
|
||||
|
||||
diffs.push({
|
||||
from: fromId,
|
||||
to: toId,
|
||||
newClasses: toVer.classes
|
||||
.map((c) => c.name)
|
||||
.filter((n) => !fromClassNames.has(n)),
|
||||
.map((cls) => cls.name)
|
||||
.filter((name) => !fromClassNames.has(name)),
|
||||
newFunctions: toVer.functions
|
||||
.map((f) => f.name)
|
||||
.filter((n) => !fromFuncNames.has(n)),
|
||||
newTools: toVer.tools.filter((t) => !fromToolNames.has(t)),
|
||||
.map((fn) => fn.name)
|
||||
.filter((name) => !fromFuncNames.has(name)),
|
||||
newTools: toVer.tools.filter((tool) => !fromToolNames.has(tool)),
|
||||
locDelta: toVer.loc - fromVer.loc,
|
||||
});
|
||||
}
|
||||
|
||||
// 4. Read doc files from locale subdirectories (en/, zh/, ja/)
|
||||
const docs: DocContent[] = [];
|
||||
return diffs;
|
||||
}
|
||||
|
||||
if (fs.existsSync(DOCS_DIR)) {
|
||||
const localeDirs = ["en", "zh", "ja"];
|
||||
let totalDocFiles = 0;
|
||||
function sortVersions(versions: AgentVersion[]) {
|
||||
const orderMap = new Map(VERSION_ORDER.map((id, index) => [id, index]));
|
||||
versions.sort(
|
||||
(a, b) => (orderMap.get(a.id as any) ?? 99) - (orderMap.get(b.id as any) ?? 99)
|
||||
);
|
||||
}
|
||||
|
||||
for (const locale of localeDirs) {
|
||||
const localeDir = path.join(DOCS_DIR, locale);
|
||||
if (!fs.existsSync(localeDir)) continue;
|
||||
function main() {
|
||||
console.log("Extracting course content...");
|
||||
console.log(` Repo root: ${REPO_ROOT}`);
|
||||
|
||||
const docFiles = fs
|
||||
.readdirSync(localeDir)
|
||||
.filter((f) => f.endsWith(".md"));
|
||||
cleanCourseAssets();
|
||||
|
||||
totalDocFiles += docFiles.length;
|
||||
const rootChapters = listRootChapters();
|
||||
const useRootTrack = rootChapters.length > 0;
|
||||
|
||||
for (const filename of docFiles) {
|
||||
const version = extractDocVersion(filename);
|
||||
if (!version) {
|
||||
console.warn(` Skipping doc ${locale}/${filename}: could not determine version`);
|
||||
continue;
|
||||
}
|
||||
console.log(
|
||||
useRootTrack
|
||||
? ` Source: root chapter folders (${rootChapters.length})`
|
||||
: " Source: legacy agents/docs folders"
|
||||
);
|
||||
|
||||
const filePath = path.join(localeDir, filename);
|
||||
const content = fs.readFileSync(filePath, "utf-8");
|
||||
const versions = useRootTrack
|
||||
? buildRootVersions(rootChapters)
|
||||
: buildLegacyVersions();
|
||||
const docs = useRootTrack ? buildRootDocs(rootChapters) : buildLegacyDocs();
|
||||
|
||||
const titleMatch = content.match(/^#\s+(.+)$/m);
|
||||
const title = titleMatch ? titleMatch[1] : filename;
|
||||
sortVersions(versions);
|
||||
computeNewTools(versions);
|
||||
const diffs = buildDiffs(versions);
|
||||
|
||||
docs.push({ version, locale: locale as "en" | "zh" | "ja", title, content });
|
||||
}
|
||||
}
|
||||
|
||||
console.log(` Found ${totalDocFiles} doc files across ${localeDirs.length} locales`);
|
||||
} else {
|
||||
console.warn(` Docs directory not found: ${DOCS_DIR}`);
|
||||
}
|
||||
|
||||
// 5. Write output
|
||||
fs.mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
const index: VersionIndex = { versions, diffs };
|
||||
const indexPath = path.join(OUT_DIR, "versions.json");
|
||||
fs.writeFileSync(indexPath, JSON.stringify(index, null, 2));
|
||||
console.log(` Wrote ${indexPath}`);
|
||||
fs.writeFileSync(path.join(OUT_DIR, "versions.json"), JSON.stringify(index, null, 2));
|
||||
fs.writeFileSync(path.join(OUT_DIR, "docs.json"), JSON.stringify(docs, null, 2));
|
||||
|
||||
const docsPath = path.join(OUT_DIR, "docs.json");
|
||||
fs.writeFileSync(docsPath, JSON.stringify(docs, null, 2));
|
||||
console.log(` Wrote ${docsPath}`);
|
||||
|
||||
// Summary
|
||||
console.log("\nExtraction complete:");
|
||||
console.log(` ${versions.length} versions`);
|
||||
console.log(` ${diffs.length} diffs`);
|
||||
console.log(` ${docs.length} docs`);
|
||||
for (const v of versions) {
|
||||
for (const version of versions) {
|
||||
console.log(
|
||||
` ${v.id}: ${v.loc} LOC, ${v.tools.length} tools, ${v.classes.length} classes, ${v.functions.length} functions`
|
||||
` ${version.id}: ${version.loc} LOC, ${version.tools.length} tools, ${version.classes.length} classes, ${version.functions.length} functions`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,11 @@ body {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.prose-custom {
|
||||
max-width: 100%;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
pre, code {
|
||||
font-size: 11px;
|
||||
@@ -188,6 +193,7 @@ body {
|
||||
.prose-custom pre {
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
border-radius: 0.75rem;
|
||||
@@ -200,6 +206,11 @@ body {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
}
|
||||
|
||||
.prose-custom pre code {
|
||||
display: block;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.prose-custom pre.code-block {
|
||||
padding-top: 2.25rem;
|
||||
}
|
||||
@@ -368,10 +379,18 @@ body {
|
||||
|
||||
/* -- Tables -- */
|
||||
|
||||
.prose-custom table {
|
||||
width: 100%;
|
||||
.prose-custom .table-scroll {
|
||||
max-width: 100%;
|
||||
margin-top: 1.25rem;
|
||||
margin-bottom: 1.25rem;
|
||||
overflow-x: auto;
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.prose-custom table {
|
||||
width: 100%;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
font-size: 0.8125rem;
|
||||
|
||||
@@ -16,6 +16,10 @@ const CLASS_DESCRIPTIONS: Record<string, string> = {
|
||||
TeammateManager: "Multi-agent team lifecycle and coordination",
|
||||
Teammate: "Individual agent identity and state tracking",
|
||||
SharedBoard: "Cross-agent shared state coordination",
|
||||
CronJob: "Durable recurring job definition",
|
||||
ProtocolState: "Pending team protocol requests and response matching",
|
||||
MCPClient: "External tool discovery and invocation client",
|
||||
RecoveryState: "Retry, fallback, and continuation state",
|
||||
};
|
||||
|
||||
interface ArchDiagramProps {
|
||||
@@ -68,29 +72,23 @@ function getLayerColorClasses(versionId: string): {
|
||||
}
|
||||
}
|
||||
|
||||
function collectClassesUpTo(
|
||||
function collectClassesForVersion(
|
||||
targetId: string
|
||||
): { name: string; introducedIn: string }[] {
|
||||
const { versions, diffs } = versionsData;
|
||||
const order = versions.map((v) => v.id);
|
||||
const targetIdx = order.indexOf(targetId);
|
||||
if (targetIdx < 0) return [];
|
||||
const targetIndex = versionsData.versions.findIndex((v) => v.id === targetId);
|
||||
const version = targetIndex >= 0 ? versionsData.versions[targetIndex] : undefined;
|
||||
|
||||
const result: { name: string; introducedIn: string }[] = [];
|
||||
const seen = new Set<string>();
|
||||
|
||||
for (let i = 0; i <= targetIdx; i++) {
|
||||
const v = versions[i];
|
||||
if (!v.classes) continue;
|
||||
for (const cls of v.classes) {
|
||||
if (!seen.has(cls.name)) {
|
||||
seen.add(cls.name);
|
||||
result.push({ name: cls.name, introducedIn: v.id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return (
|
||||
version?.classes?.map((cls) => ({
|
||||
name: cls.name,
|
||||
introducedIn:
|
||||
versionsData.versions
|
||||
.slice(0, targetIndex + 1)
|
||||
.find((candidate) =>
|
||||
candidate.classes?.some((candidateCls) => candidateCls.name === cls.name)
|
||||
)?.id ?? targetId,
|
||||
})) ?? []
|
||||
);
|
||||
}
|
||||
|
||||
function getNewClassNames(version: string): Set<string> {
|
||||
@@ -103,7 +101,7 @@ function getNewClassNames(version: string): Set<string> {
|
||||
}
|
||||
|
||||
export function ArchDiagram({ version }: ArchDiagramProps) {
|
||||
const allClasses = collectClassesUpTo(version);
|
||||
const allClasses = collectClassesForVersion(version);
|
||||
const newClassNames = getNewClassNames(version);
|
||||
const versionData = versionsData.versions.find((v) => v.id === version);
|
||||
const tools = versionData?.tools ?? [];
|
||||
|
||||
@@ -18,6 +18,14 @@ import s09Annotations from "@/data/annotations/s09.json";
|
||||
import s10Annotations from "@/data/annotations/s10.json";
|
||||
import s11Annotations from "@/data/annotations/s11.json";
|
||||
import s12Annotations from "@/data/annotations/s12.json";
|
||||
import s13Annotations from "@/data/annotations/s13.json";
|
||||
import s14Annotations from "@/data/annotations/s14.json";
|
||||
import s15Annotations from "@/data/annotations/s15.json";
|
||||
import s16Annotations from "@/data/annotations/s16.json";
|
||||
import s17Annotations from "@/data/annotations/s17.json";
|
||||
import s18Annotations from "@/data/annotations/s18.json";
|
||||
import s19Annotations from "@/data/annotations/s19.json";
|
||||
import s20Annotations from "@/data/annotations/s20.json";
|
||||
|
||||
interface Decision {
|
||||
id: string;
|
||||
@@ -46,6 +54,14 @@ const ANNOTATIONS: Record<string, AnnotationFile> = {
|
||||
s10: s10Annotations as AnnotationFile,
|
||||
s11: s11Annotations as AnnotationFile,
|
||||
s12: s12Annotations as AnnotationFile,
|
||||
s13: s13Annotations as AnnotationFile,
|
||||
s14: s14Annotations as AnnotationFile,
|
||||
s15: s15Annotations as AnnotationFile,
|
||||
s16: s16Annotations as AnnotationFile,
|
||||
s17: s17Annotations as AnnotationFile,
|
||||
s18: s18Annotations as AnnotationFile,
|
||||
s19: s19Annotations as AnnotationFile,
|
||||
s20: s20Annotations as AnnotationFile,
|
||||
};
|
||||
|
||||
interface DesignDecisionsProps {
|
||||
@@ -124,7 +140,14 @@ export function DesignDecisions({ version }: DesignDecisionsProps) {
|
||||
|
||||
const annotations = ANNOTATIONS[version];
|
||||
if (!annotations || annotations.decisions.length === 0) {
|
||||
return null;
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-xl font-semibold">{t("design_decisions")}</h2>
|
||||
<div className="rounded-xl border border-dashed border-[var(--color-border)] bg-[var(--color-bg)] p-6 text-sm text-[var(--color-text-secondary)]">
|
||||
Design decisions are not available for this lesson yet.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -6,8 +6,9 @@ import { getFlowForVersion } from "@/data/execution-flows";
|
||||
import type { FlowNode, FlowEdge } from "@/types/agent-data";
|
||||
|
||||
const NODE_WIDTH = 140;
|
||||
const NODE_HEIGHT = 40;
|
||||
const DIAMOND_SIZE = 50;
|
||||
const NODE_HEIGHT = 44;
|
||||
const DIAMOND_WIDTH = 92;
|
||||
const DIAMOND_HEIGHT = 64;
|
||||
|
||||
const LAYER_COLORS: Record<string, string> = {
|
||||
start: "#3B82F6",
|
||||
@@ -17,39 +18,207 @@ const LAYER_COLORS: Record<string, string> = {
|
||||
end: "#EF4444",
|
||||
};
|
||||
|
||||
function getNodeCenter(node: FlowNode): { cx: number; cy: number } {
|
||||
return { cx: node.x, cy: node.y };
|
||||
function getNodeLines(node: FlowNode): string[] {
|
||||
const maxChars = node.type === "decision" ? 12 : 18;
|
||||
return node.label.split("\n").flatMap((line) => {
|
||||
if (line.length <= maxChars) return [line];
|
||||
|
||||
const parts = line.split(/(\s+\/\s+|\s+|_)/).filter(Boolean);
|
||||
const chunks: string[] = [];
|
||||
let current = "";
|
||||
|
||||
for (const part of parts) {
|
||||
const next = `${current}${part}`;
|
||||
if (current && next.trim().length > maxChars) {
|
||||
chunks.push(current.trim());
|
||||
current = part.trimStart();
|
||||
} else {
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
if (current.trim()) chunks.push(current.trim());
|
||||
return chunks.length ? chunks : [line];
|
||||
});
|
||||
}
|
||||
|
||||
function estimateTextWidth(line: string, fontSize: number): number {
|
||||
return line.length * fontSize * 0.62;
|
||||
}
|
||||
|
||||
function getNodeMetrics(node: FlowNode) {
|
||||
const lines = getNodeLines(node);
|
||||
const longest = Math.max(...lines.map((line) => estimateTextWidth(line, 11)), 0);
|
||||
|
||||
if (node.type === "decision") {
|
||||
return {
|
||||
lines,
|
||||
width: Math.max(DIAMOND_WIDTH, longest + 54),
|
||||
height: Math.max(DIAMOND_HEIGHT, lines.length * 15 + 42),
|
||||
};
|
||||
}
|
||||
|
||||
if (node.type === "start" || node.type === "end") {
|
||||
return {
|
||||
lines,
|
||||
width: Math.max(NODE_WIDTH, longest + 34),
|
||||
height: Math.max(NODE_HEIGHT, lines.length * 15 + 24),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
lines,
|
||||
width: Math.max(NODE_WIDTH, longest + 30),
|
||||
height: Math.max(NODE_HEIGHT, lines.length * 15 + 24),
|
||||
};
|
||||
}
|
||||
|
||||
function getNodeBounds(node: FlowNode) {
|
||||
const metrics = getNodeMetrics(node);
|
||||
const halfW = metrics.width / 2;
|
||||
const halfH = metrics.height / 2;
|
||||
|
||||
return {
|
||||
cx: node.x,
|
||||
cy: node.y,
|
||||
left: node.x - halfW,
|
||||
right: node.x + halfW,
|
||||
top: node.y - halfH,
|
||||
bottom: node.y + halfH,
|
||||
};
|
||||
}
|
||||
|
||||
const LOOP_RAIL_X = -48;
|
||||
const RIGHT_LOOP_RAIL_X = 576;
|
||||
const FLOW_CENTER_X = 300;
|
||||
const LOOP_PAD = 28;
|
||||
const LOOP_BACK_DX_LIMIT = 360;
|
||||
const LOOP_BACK_DY_LIMIT = 70;
|
||||
|
||||
type LoopSide = "left" | "right";
|
||||
|
||||
function getLoopSide(start: ReturnType<typeof getNodeBounds>, end: ReturnType<typeof getNodeBounds>): LoopSide {
|
||||
return (start.cx + end.cx) / 2 > FLOW_CENTER_X ? "right" : "left";
|
||||
}
|
||||
|
||||
function getLoopRailX(
|
||||
start: ReturnType<typeof getNodeBounds>,
|
||||
end: ReturnType<typeof getNodeBounds>,
|
||||
side = getLoopSide(start, end),
|
||||
) {
|
||||
if (side === "right") {
|
||||
return Math.max(RIGHT_LOOP_RAIL_X, start.right + LOOP_PAD, end.right + LOOP_PAD);
|
||||
}
|
||||
|
||||
return Math.min(LOOP_RAIL_X, start.left - LOOP_PAD, end.left - LOOP_PAD);
|
||||
}
|
||||
|
||||
function isLoopBack(start: ReturnType<typeof getNodeBounds>, end: ReturnType<typeof getNodeBounds>) {
|
||||
const dx = end.cx - start.cx;
|
||||
const dy = end.cy - start.cy;
|
||||
return dy < -LOOP_BACK_DY_LIMIT && Math.abs(dx) <= LOOP_BACK_DX_LIMIT;
|
||||
}
|
||||
|
||||
function shouldUseStepRoute(start: ReturnType<typeof getNodeBounds>, end: ReturnType<typeof getNodeBounds>) {
|
||||
const dx = end.cx - start.cx;
|
||||
const dy = end.cy - start.cy;
|
||||
return dy > 28 && Math.abs(dx) > 44 && end.top > start.bottom;
|
||||
}
|
||||
|
||||
function getStepBusY(start: ReturnType<typeof getNodeBounds>, end: ReturnType<typeof getNodeBounds>) {
|
||||
const room = end.top - start.bottom;
|
||||
return Math.min(end.top - 16, start.bottom + Math.max(18, room * 0.35));
|
||||
}
|
||||
|
||||
function getEdgePath(from: FlowNode, to: FlowNode): string {
|
||||
const { cx: x1, cy: y1 } = getNodeCenter(from);
|
||||
const { cx: x2, cy: y2 } = getNodeCenter(to);
|
||||
const start = getNodeBounds(from);
|
||||
const end = getNodeBounds(to);
|
||||
const dx = end.cx - start.cx;
|
||||
const dy = end.cy - start.cy;
|
||||
|
||||
const halfH = from.type === "decision" ? DIAMOND_SIZE / 2 : NODE_HEIGHT / 2;
|
||||
const halfHTo = to.type === "decision" ? DIAMOND_SIZE / 2 : NODE_HEIGHT / 2;
|
||||
|
||||
if (Math.abs(x1 - x2) < 10) {
|
||||
const startY = y1 + halfH;
|
||||
const endY = y2 - halfHTo;
|
||||
return `M ${x1} ${startY} L ${x2} ${endY}`;
|
||||
if (isLoopBack(start, end)) {
|
||||
const side = getLoopSide(start, end);
|
||||
const railX = getLoopRailX(start, end, side);
|
||||
const startX = side === "right" ? start.right : start.left;
|
||||
const endX = side === "right" ? end.right : end.left;
|
||||
const midY = (start.cy + end.cy) / 2;
|
||||
return `M ${startX} ${start.cy} C ${railX} ${start.cy}, ${railX} ${midY}, ${railX} ${midY} C ${railX} ${end.cy}, ${endX} ${end.cy}, ${endX} ${end.cy}`;
|
||||
}
|
||||
|
||||
const startY = y1 + halfH;
|
||||
const endY = y2 - halfHTo;
|
||||
const midY = (startY + endY) / 2;
|
||||
return `M ${x1} ${startY} L ${x1} ${midY} L ${x2} ${midY} L ${x2} ${endY}`;
|
||||
if (Math.abs(dx) < 10) {
|
||||
if (dy >= 0) {
|
||||
return `M ${start.cx} ${start.bottom} L ${end.cx} ${end.top}`;
|
||||
}
|
||||
return `M ${start.cx} ${start.top} L ${end.cx} ${end.bottom}`;
|
||||
}
|
||||
|
||||
if (Math.abs(dy) < 10) {
|
||||
const startX = dx > 0 ? start.right : start.left;
|
||||
const endX = dx > 0 ? end.left : end.right;
|
||||
const midX = (startX + endX) / 2;
|
||||
return `M ${startX} ${start.cy} C ${midX} ${start.cy}, ${midX} ${end.cy}, ${endX} ${end.cy}`;
|
||||
}
|
||||
|
||||
if (shouldUseStepRoute(start, end)) {
|
||||
const busY = getStepBusY(start, end);
|
||||
return `M ${start.cx} ${start.bottom} L ${start.cx} ${busY} L ${end.cx} ${busY} L ${end.cx} ${end.top}`;
|
||||
}
|
||||
|
||||
if (Math.abs(dx) > 70) {
|
||||
const startX = dx > 0 ? start.right : start.left;
|
||||
const endX = dx > 0 ? end.left : end.right;
|
||||
const control = Math.max(56, Math.abs(dx) * 0.45);
|
||||
return `M ${startX} ${start.cy} C ${startX + (dx > 0 ? control : -control)} ${start.cy}, ${endX - (dx > 0 ? control : -control)} ${end.cy}, ${endX} ${end.cy}`;
|
||||
}
|
||||
|
||||
const startY = dy > 0 ? start.bottom : start.top;
|
||||
const endY = dy > 0 ? end.top : end.bottom;
|
||||
const controlDistance = Math.max(44, Math.abs(endY - startY) * 0.42);
|
||||
const controlY1 = startY + (endY > startY ? controlDistance : -controlDistance);
|
||||
const controlY2 = endY - (endY > startY ? controlDistance : -controlDistance);
|
||||
|
||||
return `M ${start.cx} ${startY} C ${start.cx} ${controlY1}, ${end.cx} ${controlY2}, ${end.cx} ${endY}`;
|
||||
}
|
||||
|
||||
function getEdgeLabelPosition(from: FlowNode, to: FlowNode): { x: number; y: number } {
|
||||
const start = getNodeBounds(from);
|
||||
const end = getNodeBounds(to);
|
||||
const dx = end.cx - start.cx;
|
||||
const dy = end.cy - start.cy;
|
||||
|
||||
if (isLoopBack(start, end)) {
|
||||
const side = getLoopSide(start, end);
|
||||
return {
|
||||
x: getLoopRailX(start, end, side) + (side === "right" ? -24 : 24),
|
||||
y: (start.cy + end.cy) / 2 - 6,
|
||||
};
|
||||
}
|
||||
|
||||
if (Math.abs(dy) < 10) {
|
||||
return { x: (start.cx + end.cx) / 2, y: start.cy - 12 };
|
||||
}
|
||||
|
||||
if (shouldUseStepRoute(start, end)) {
|
||||
return { x: (start.cx + end.cx) / 2, y: getStepBusY(start, end) - 8 };
|
||||
}
|
||||
|
||||
return {
|
||||
x: (start.cx + end.cx) / 2 + (dx > 0 ? 18 : -18),
|
||||
y: (start.bottom + end.top) / 2 - 8,
|
||||
};
|
||||
}
|
||||
|
||||
function NodeShape({ node }: { node: FlowNode }) {
|
||||
const color = LAYER_COLORS[node.type];
|
||||
const lines = node.label.split("\n");
|
||||
const { lines, width, height } = getNodeMetrics(node);
|
||||
|
||||
if (node.type === "decision") {
|
||||
const half = DIAMOND_SIZE / 2;
|
||||
const halfW = width / 2;
|
||||
const halfH = height / 2;
|
||||
return (
|
||||
<g>
|
||||
<polygon
|
||||
points={`${node.x},${node.y - half} ${node.x + half},${node.y} ${node.x},${node.y + half} ${node.x - half},${node.y}`}
|
||||
points={`${node.x},${node.y - halfH} ${node.x + halfW},${node.y} ${node.x},${node.y + halfH} ${node.x - halfW},${node.y}`}
|
||||
fill="none"
|
||||
stroke={color}
|
||||
strokeWidth={2}
|
||||
@@ -58,10 +227,10 @@ function NodeShape({ node }: { node: FlowNode }) {
|
||||
<text
|
||||
key={i}
|
||||
x={node.x}
|
||||
y={node.y + (i - (lines.length - 1) / 2) * 12}
|
||||
y={node.y + (i - (lines.length - 1) / 2) * 13}
|
||||
textAnchor="middle"
|
||||
dominantBaseline="central"
|
||||
fontSize={10}
|
||||
fontSize={lines.length > 2 ? 9 : 10}
|
||||
fontFamily="monospace"
|
||||
fill="currentColor"
|
||||
>
|
||||
@@ -76,27 +245,30 @@ function NodeShape({ node }: { node: FlowNode }) {
|
||||
return (
|
||||
<g>
|
||||
<rect
|
||||
x={node.x - NODE_WIDTH / 2}
|
||||
y={node.y - NODE_HEIGHT / 2}
|
||||
width={NODE_WIDTH}
|
||||
height={NODE_HEIGHT}
|
||||
rx={NODE_HEIGHT / 2}
|
||||
x={node.x - width / 2}
|
||||
y={node.y - height / 2}
|
||||
width={width}
|
||||
height={height}
|
||||
rx={height / 2}
|
||||
fill="none"
|
||||
stroke={color}
|
||||
strokeWidth={2}
|
||||
/>
|
||||
<text
|
||||
x={node.x}
|
||||
y={node.y}
|
||||
textAnchor="middle"
|
||||
dominantBaseline="central"
|
||||
fontSize={12}
|
||||
fontWeight={600}
|
||||
fontFamily="monospace"
|
||||
fill="currentColor"
|
||||
>
|
||||
{node.label}
|
||||
</text>
|
||||
{lines.map((line, i) => (
|
||||
<text
|
||||
key={i}
|
||||
x={node.x}
|
||||
y={node.y + (i - (lines.length - 1) / 2) * 14}
|
||||
textAnchor="middle"
|
||||
dominantBaseline="central"
|
||||
fontSize={12}
|
||||
fontWeight={600}
|
||||
fontFamily="monospace"
|
||||
fill="currentColor"
|
||||
>
|
||||
{line}
|
||||
</text>
|
||||
))}
|
||||
</g>
|
||||
);
|
||||
}
|
||||
@@ -105,10 +277,10 @@ function NodeShape({ node }: { node: FlowNode }) {
|
||||
return (
|
||||
<g>
|
||||
<rect
|
||||
x={node.x - NODE_WIDTH / 2}
|
||||
y={node.y - NODE_HEIGHT / 2}
|
||||
width={NODE_WIDTH}
|
||||
height={NODE_HEIGHT}
|
||||
x={node.x - width / 2}
|
||||
y={node.y - height / 2}
|
||||
width={width}
|
||||
height={height}
|
||||
rx={4}
|
||||
fill="none"
|
||||
stroke={color}
|
||||
@@ -147,12 +319,14 @@ function EdgePath({
|
||||
if (!from || !to) return null;
|
||||
|
||||
const d = getEdgePath(from, to);
|
||||
const midX = (from.x + to.x) / 2;
|
||||
const midY = (from.y + to.y) / 2;
|
||||
const label = getEdgeLabelPosition(from, to);
|
||||
|
||||
return (
|
||||
<g>
|
||||
<motion.path
|
||||
data-edge-from={edge.from}
|
||||
data-edge-to={edge.to}
|
||||
data-edge-label={edge.label ?? ""}
|
||||
d={d}
|
||||
fill="none"
|
||||
stroke="var(--color-text-secondary)"
|
||||
@@ -164,10 +338,15 @@ function EdgePath({
|
||||
/>
|
||||
{edge.label && (
|
||||
<motion.text
|
||||
x={midX + 8}
|
||||
y={midY - 4}
|
||||
x={label.x}
|
||||
y={label.y}
|
||||
textAnchor="middle"
|
||||
fontSize={10}
|
||||
fill="var(--color-text-secondary)"
|
||||
stroke="var(--color-bg)"
|
||||
strokeWidth={5}
|
||||
strokeLinejoin="round"
|
||||
paintOrder="stroke"
|
||||
fontFamily="monospace"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
@@ -191,15 +370,24 @@ export function ExecutionFlow({ version }: ExecutionFlowProps) {
|
||||
setFlow(getFlowForVersion(version));
|
||||
}, [version]);
|
||||
|
||||
if (!flow) return null;
|
||||
if (!flow) {
|
||||
return (
|
||||
<div className="rounded-xl border border-dashed border-[var(--color-border)] bg-[var(--color-bg)] p-6 text-sm text-[var(--color-text-secondary)]">
|
||||
Execution flow is not available for this lesson yet.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const maxY = Math.max(...flow.nodes.map((n) => n.y)) + 50;
|
||||
const bounds = flow.nodes.map(getNodeBounds);
|
||||
const minX = Math.min(-40, ...bounds.map((b) => b.left)) - 24;
|
||||
const maxX = Math.max(700, ...bounds.map((b) => b.right)) + 24;
|
||||
const maxY = Math.max(...bounds.map((b) => b.bottom)) + 50;
|
||||
|
||||
return (
|
||||
<div className="overflow-x-auto rounded-xl border border-[var(--color-border)] bg-[var(--color-bg)] p-4">
|
||||
<svg
|
||||
viewBox={`0 0 600 ${maxY}`}
|
||||
className="mx-auto w-full max-w-[600px]"
|
||||
viewBox={`${minX} 0 ${maxX - minX} ${maxY}`}
|
||||
className="mx-auto w-full max-w-[720px]"
|
||||
style={{ minHeight: 300 }}
|
||||
>
|
||||
<defs>
|
||||
@@ -219,12 +407,14 @@ export function ExecutionFlow({ version }: ExecutionFlowProps) {
|
||||
</defs>
|
||||
|
||||
{flow.edges.map((edge, i) => (
|
||||
<EdgePath key={`${edge.from}-${edge.to}`} edge={edge} nodes={flow.nodes} index={i} />
|
||||
<EdgePath key={`${edge.from}-${edge.to}-${i}`} edge={edge} nodes={flow.nodes} index={i} />
|
||||
))}
|
||||
|
||||
{flow.nodes.map((node, i) => (
|
||||
<motion.g
|
||||
key={node.id}
|
||||
data-node-id={node.id}
|
||||
data-node-label={node.label}
|
||||
initial={{ opacity: 0, y: -10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: i * 0.06, duration: 0.3 }}
|
||||
|
||||
@@ -40,6 +40,10 @@ function postProcessHtml(html: string): string {
|
||||
'<pre class="ascii-diagram"><code$1>'
|
||||
);
|
||||
|
||||
// Keep wide Markdown tables inside the prose column on small screens.
|
||||
html = html.replace(/<table>/g, '<div class="table-scroll"><table>');
|
||||
html = html.replace(/<\/table>/g, '</table></div>');
|
||||
|
||||
// Mark the first blockquote as hero callout
|
||||
html = html.replace(
|
||||
/<blockquote>/,
|
||||
|
||||
@@ -21,6 +21,14 @@ const scenarioModules: Record<string, () => Promise<{ default: Scenario }>> = {
|
||||
s10: () => import("@/data/scenarios/s10.json") as Promise<{ default: Scenario }>,
|
||||
s11: () => import("@/data/scenarios/s11.json") as Promise<{ default: Scenario }>,
|
||||
s12: () => import("@/data/scenarios/s12.json") as Promise<{ default: Scenario }>,
|
||||
s13: () => import("@/data/scenarios/s13.json") as Promise<{ default: Scenario }>,
|
||||
s14: () => import("@/data/scenarios/s14.json") as Promise<{ default: Scenario }>,
|
||||
s15: () => import("@/data/scenarios/s15.json") as Promise<{ default: Scenario }>,
|
||||
s16: () => import("@/data/scenarios/s16.json") as Promise<{ default: Scenario }>,
|
||||
s17: () => import("@/data/scenarios/s17.json") as Promise<{ default: Scenario }>,
|
||||
s18: () => import("@/data/scenarios/s18.json") as Promise<{ default: Scenario }>,
|
||||
s19: () => import("@/data/scenarios/s19.json") as Promise<{ default: Scenario }>,
|
||||
s20: () => import("@/data/scenarios/s20.json") as Promise<{ default: Scenario }>,
|
||||
};
|
||||
|
||||
interface AgentLoopSimulatorProps {
|
||||
@@ -33,10 +41,27 @@ export function AgentLoopSimulator({ version }: AgentLoopSimulatorProps) {
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const loader = scenarioModules[version];
|
||||
if (loader) {
|
||||
loader().then((mod) => setScenario(mod.default));
|
||||
setScenario(null);
|
||||
|
||||
if (!loader) {
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}
|
||||
|
||||
loader()
|
||||
.then((mod) => {
|
||||
if (!cancelled) setScenario(mod.default);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) setScenario(null);
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [version]);
|
||||
|
||||
const sim = useSimulator(scenario?.steps ?? []);
|
||||
@@ -50,7 +75,16 @@ export function AgentLoopSimulator({ version }: AgentLoopSimulatorProps) {
|
||||
}
|
||||
}, [sim.visibleSteps.length]);
|
||||
|
||||
if (!scenario) return null;
|
||||
if (!scenario) {
|
||||
return (
|
||||
<section>
|
||||
<h2 className="mb-2 text-xl font-semibold">{t("simulator")}</h2>
|
||||
<div className="rounded-xl border border-dashed border-[var(--color-border)] bg-[var(--color-bg)] p-6 text-sm text-[var(--color-text-secondary)]">
|
||||
Simulator scenario is not available for this lesson yet.
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<section>
|
||||
|
||||
@@ -9,16 +9,24 @@ const visualizations: Record<
|
||||
> = {
|
||||
s01: lazy(() => import("./s01-agent-loop")),
|
||||
s02: lazy(() => import("./s02-tool-dispatch")),
|
||||
s03: lazy(() => import("./s03-todo-write")),
|
||||
s04: lazy(() => import("./s04-subagent")),
|
||||
s05: lazy(() => import("./s05-skill-loading")),
|
||||
s06: lazy(() => import("./s06-context-compact")),
|
||||
s07: lazy(() => import("./s07-task-system")),
|
||||
s08: lazy(() => import("./s08-background-tasks")),
|
||||
s09: lazy(() => import("./s09-agent-teams")),
|
||||
s10: lazy(() => import("./s10-team-protocols")),
|
||||
s11: lazy(() => import("./s11-autonomous-agents")),
|
||||
s12: lazy(() => import("./s12-worktree-task-isolation")),
|
||||
s03: lazy(() => import("./s03-permission")),
|
||||
s04: lazy(() => import("./s04-hooks")),
|
||||
s05: lazy(() => import("./s03-todo-write")),
|
||||
s06: lazy(() => import("./s04-subagent")),
|
||||
s07: lazy(() => import("./s05-skill-loading")),
|
||||
s08: lazy(() => import("./s06-context-compact")),
|
||||
s09: lazy(() => import("./s09-memory")),
|
||||
s10: lazy(() => import("./s10-system-prompt")),
|
||||
s11: lazy(() => import("./s11-error-recovery")),
|
||||
s12: lazy(() => import("./s07-task-system")),
|
||||
s13: lazy(() => import("./s08-background-tasks")),
|
||||
s14: lazy(() => import("./s14-cron-scheduler")),
|
||||
s15: lazy(() => import("./s09-agent-teams")),
|
||||
s16: lazy(() => import("./s10-team-protocols")),
|
||||
s17: lazy(() => import("./s11-autonomous-agents")),
|
||||
s18: lazy(() => import("./s12-worktree-task-isolation")),
|
||||
s19: lazy(() => import("./s19-mcp-tools")),
|
||||
s20: lazy(() => import("./s20-comprehensive")),
|
||||
};
|
||||
|
||||
export function SessionVisualization({ version }: { version: string }) {
|
||||
|
||||
386
web/src/components/visualizations/s03-permission.tsx
Normal file
@@ -0,0 +1,386 @@
|
||||
"use client";
|
||||
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { CheckCircle2, ClipboardCheck, OctagonAlert, PlayCircle, ShieldAlert, ShieldCheck, UserCheck } from "lucide-react";
|
||||
import { StepControls } from "@/components/visualizations/shared/step-controls";
|
||||
import { useSteppedVisualization } from "@/hooks/useSteppedVisualization";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const STEPS = [
|
||||
{
|
||||
title: "Three Requests, Three Routes",
|
||||
desc: "Permission is a router: safe calls run, risky calls ask, forbidden calls stop.",
|
||||
mode: "overview",
|
||||
},
|
||||
{
|
||||
title: "Allow: Safe Read Runs Immediately",
|
||||
desc: "A read-only file request passes policy and reaches the handler without a user ticket.",
|
||||
mode: "allow",
|
||||
},
|
||||
{
|
||||
title: "Ask: Risky Local Delete Becomes a Ticket",
|
||||
desc: "A local delete command is not forbidden, but it must pause for explicit confirmation.",
|
||||
mode: "ask",
|
||||
},
|
||||
{
|
||||
title: "Approved Ask: Handler Runs After Yes",
|
||||
desc: "The same risky request executes only after the user approves this exact action.",
|
||||
mode: "ask-approved",
|
||||
},
|
||||
{
|
||||
title: "Deny: Forbidden Pattern Stops Early",
|
||||
desc: "A root-level sudo delete is blocked before any handler can touch the machine.",
|
||||
mode: "deny",
|
||||
},
|
||||
{
|
||||
title: "One Permission Desk, Three Outcomes",
|
||||
desc: "The harness keeps allow, ask, and deny decisions outside the model, then returns the decision to the loop.",
|
||||
mode: "summary",
|
||||
},
|
||||
] as const;
|
||||
|
||||
const REQUESTS = [
|
||||
{
|
||||
id: "allow",
|
||||
tool: "read_file",
|
||||
command: "README.md",
|
||||
result: "allow",
|
||||
detail: "read-only workspace file",
|
||||
tone: "emerald",
|
||||
},
|
||||
{
|
||||
id: "ask",
|
||||
tool: "bash",
|
||||
command: "rm -rf ./tmp/build-cache",
|
||||
result: "ask",
|
||||
detail: "local destructive command",
|
||||
tone: "amber",
|
||||
},
|
||||
{
|
||||
id: "deny",
|
||||
tool: "bash",
|
||||
command: "sudo rm -rf /",
|
||||
result: "deny",
|
||||
detail: "forbidden root delete",
|
||||
tone: "red",
|
||||
},
|
||||
] as const;
|
||||
|
||||
function toneClass(tone: "emerald" | "amber" | "red" | "blue" | "zinc") {
|
||||
if (tone === "emerald") return "border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900 dark:bg-emerald-950/40 dark:text-emerald-200";
|
||||
if (tone === "amber") return "border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900 dark:bg-amber-950/40 dark:text-amber-200";
|
||||
if (tone === "red") return "border-red-200 bg-red-50 text-red-800 dark:border-red-900 dark:bg-red-950/40 dark:text-red-200";
|
||||
if (tone === "blue") return "border-blue-200 bg-blue-50 text-blue-800 dark:border-blue-900 dark:bg-blue-950/40 dark:text-blue-200";
|
||||
return "border-zinc-200 bg-white text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200";
|
||||
}
|
||||
|
||||
function Surface({
|
||||
title,
|
||||
icon,
|
||||
active,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
icon: React.ReactNode;
|
||||
active: boolean;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"min-w-0 rounded-lg border p-4 transition-colors",
|
||||
active
|
||||
? "border-red-300 bg-red-50 dark:border-red-900 dark:bg-red-950/30"
|
||||
: "border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900"
|
||||
)}
|
||||
>
|
||||
<div className="mb-4 flex items-center gap-3 text-lg font-semibold text-zinc-900 dark:text-zinc-100">
|
||||
<span
|
||||
className={cn(
|
||||
"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg",
|
||||
active
|
||||
? "bg-red-500 text-white"
|
||||
: "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300"
|
||||
)}
|
||||
>
|
||||
{icon}
|
||||
</span>
|
||||
{title}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
type StepMode = (typeof STEPS)[number]["mode"];
|
||||
type RequestId = (typeof REQUESTS)[number]["id"];
|
||||
|
||||
function activeRequestId(mode: StepMode): RequestId | null {
|
||||
if (mode === "allow") return "allow";
|
||||
if (mode === "ask" || mode === "ask-approved") return "ask";
|
||||
if (mode === "deny") return "deny";
|
||||
return null;
|
||||
}
|
||||
|
||||
function RequestCard({
|
||||
request,
|
||||
active,
|
||||
muted,
|
||||
}: {
|
||||
request: (typeof REQUESTS)[number];
|
||||
active: boolean;
|
||||
muted: boolean;
|
||||
}) {
|
||||
return (
|
||||
<motion.div
|
||||
layout
|
||||
animate={active ? { y: -1 } : { y: 0 }}
|
||||
className={cn(
|
||||
"min-w-0 rounded-xl border p-4 shadow-sm",
|
||||
active ? toneClass(request.tone) : "border-zinc-200 bg-white text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200",
|
||||
muted && "opacity-45"
|
||||
)}
|
||||
>
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div className="min-w-0 text-sm font-semibold">tool request</div>
|
||||
<span className="shrink-0 rounded-full bg-white/70 px-2 py-1 font-mono text-xs font-semibold dark:bg-zinc-950/30">
|
||||
{request.tool}
|
||||
</span>
|
||||
</div>
|
||||
<code className="block min-w-0 rounded-lg bg-zinc-950 p-3 font-mono text-xs leading-relaxed text-zinc-100 whitespace-pre-wrap break-words">
|
||||
{request.command}
|
||||
</code>
|
||||
<div className="mt-3 flex items-center justify-between gap-3 text-sm">
|
||||
<span className="min-w-0 text-pretty opacity-80">{request.detail}</span>
|
||||
<span className="shrink-0 rounded bg-white/75 px-2 py-1 font-semibold dark:bg-zinc-950/30">
|
||||
{request.result}
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
function CheckRow({
|
||||
label,
|
||||
detail,
|
||||
status,
|
||||
active,
|
||||
}: {
|
||||
label: string;
|
||||
detail: string;
|
||||
status: "waiting" | "pass" | "allow" | "ask" | "approved" | "deny" | "skip";
|
||||
active: boolean;
|
||||
}) {
|
||||
const icon =
|
||||
status === "deny" ? <OctagonAlert size={16} /> : status === "pass" || status === "allow" ? <CheckCircle2 size={16} /> : status === "ask" ? <ShieldAlert size={16} /> : status === "approved" ? <UserCheck size={16} /> : <ClipboardCheck size={16} />;
|
||||
const tone = status === "deny" ? "red" : status === "pass" || status === "allow" || status === "approved" ? "emerald" : status === "ask" ? "amber" : "zinc";
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
layout
|
||||
initial={{ opacity: 0, y: 8 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className={cn(
|
||||
"rounded-lg border p-3",
|
||||
active ? toneClass(tone) : "border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900"
|
||||
)}
|
||||
>
|
||||
<div className="mb-1 flex items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-2 text-sm font-semibold">
|
||||
{icon}
|
||||
{label}
|
||||
</div>
|
||||
<span className="shrink-0 rounded bg-white/70 px-2 py-0.5 text-[11px] font-semibold dark:bg-zinc-950/30">
|
||||
{status}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs leading-relaxed opacity-80">{detail}</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
function PermissionDesk({ mode }: { mode: StepMode }) {
|
||||
if (mode === "overview" || mode === "summary") {
|
||||
return (
|
||||
<div className="grid gap-2">
|
||||
<CheckRow label="Safe read" detail="No write, no shell, no approval needed." status="allow" active={mode === "overview"} />
|
||||
<CheckRow label="Risky local change" detail="May be useful, but requires a human yes." status="ask" active={mode === "overview"} />
|
||||
<CheckRow label="Forbidden pattern" detail="Root delete and sudo never reach handlers." status="deny" active={mode === "overview"} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (mode === "allow") {
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<CheckRow label="Gate 1: hard deny" detail="No sudo, no root path, no forbidden pattern." status="pass" active={false} />
|
||||
<CheckRow label="Gate 2: allow rule" detail="Read-only workspace file can run immediately." status="allow" active />
|
||||
<CheckRow label="Gate 3: user approval" detail="Skipped because this call is already safe." status="skip" active={false} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (mode === "deny") {
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<CheckRow label="Gate 1: hard deny" detail="sudo + root delete is blocked immediately." status="deny" active />
|
||||
<CheckRow label="Gate 2: risk rule" detail="Skipped because hard deny already decided." status="skip" active={false} />
|
||||
<CheckRow label="Gate 3: user approval" detail="Skipped because the user cannot approve forbidden actions." status="skip" active={false} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<CheckRow label="Gate 1: hard deny" detail="Local project path is not globally forbidden." status="pass" active={false} />
|
||||
<CheckRow label="Gate 2: risk rule" detail="Deleting files needs an explicit approval ticket." status="ask" active={mode === "ask"} />
|
||||
<CheckRow label="Gate 3: user approval" detail="The tool waits until this request is approved." status={mode === "ask-approved" ? "approved" : "waiting"} active={mode === "ask-approved"} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function CodeLine({ label, value }: { label: string; value: string }) {
|
||||
return (
|
||||
<div className="min-w-0 rounded-lg bg-white/70 p-2 dark:bg-zinc-950/30">
|
||||
<div className="mb-1 text-[11px] font-semibold uppercase tracking-wide opacity-70">{label}</div>
|
||||
<code className="block min-w-0 whitespace-pre-wrap break-words font-mono text-xs leading-relaxed">{value}</code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Outcome({ mode }: { mode: StepMode }) {
|
||||
if (mode === "overview") {
|
||||
return <div className="rounded-lg border border-dashed border-zinc-300 px-4 py-8 text-center text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400">select a request route</div>;
|
||||
}
|
||||
|
||||
if (mode === "allow") {
|
||||
return (
|
||||
<motion.div initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} className={cn("space-y-3 rounded-xl border p-4", toneClass("emerald"))}>
|
||||
<div className="flex items-center gap-2 text-base font-semibold">
|
||||
<PlayCircle size={17} />
|
||||
Handler runs now
|
||||
</div>
|
||||
<CodeLine label="handler" value="read_file" />
|
||||
<CodeLine label="args" value='path: "README.md"' />
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
if (mode === "ask") {
|
||||
return (
|
||||
<motion.div initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} className={cn("rounded-xl border p-4", toneClass("amber"))}>
|
||||
<div className="mb-2 flex items-center gap-2 text-base font-semibold">
|
||||
<UserCheck size={17} />
|
||||
Approval ticket
|
||||
</div>
|
||||
<div className="text-sm leading-relaxed">"Allow deleting local build cache?"</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
if (mode === "ask-approved") {
|
||||
return (
|
||||
<motion.div initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} className={cn("space-y-3 rounded-xl border p-4", toneClass("blue"))}>
|
||||
<div className="flex items-center gap-2 text-base font-semibold">
|
||||
<PlayCircle size={17} />
|
||||
Handler runs after approval
|
||||
</div>
|
||||
<CodeLine label="handler" value="bash" />
|
||||
<CodeLine label="args" value="rm -rf ./tmp/build-cache" />
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
if (mode === "deny") {
|
||||
return (
|
||||
<motion.div initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} className={cn("rounded-xl border p-4", toneClass("red"))}>
|
||||
<div className="mb-2 flex items-center gap-2 text-base font-semibold">
|
||||
<OctagonAlert size={17} />
|
||||
Blocked before handler
|
||||
</div>
|
||||
<div className="text-sm leading-relaxed">No tool execution, no user prompt, no filesystem touch.</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.div initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} className="space-y-2">
|
||||
{REQUESTS.map((request) => (
|
||||
<div key={request.id} className={cn("rounded-lg border p-3", toneClass(request.tone))}>
|
||||
<div className="mb-1 flex items-center gap-2 text-sm font-semibold">
|
||||
{request.result === "deny" ? <OctagonAlert size={15} /> : request.result === "ask" ? <ShieldAlert size={15} /> : <ShieldCheck size={15} />}
|
||||
{request.result}
|
||||
</div>
|
||||
<div className="text-xs leading-relaxed opacity-80">{request.detail}</div>
|
||||
</div>
|
||||
))}
|
||||
<div className={cn("rounded-xl border p-4", toneClass("emerald"))}>
|
||||
<div className="mb-2 flex items-center gap-2 text-base font-semibold">
|
||||
<ShieldCheck size={17} />
|
||||
decision returned to loop
|
||||
</div>
|
||||
<div className="text-sm leading-relaxed">Permission stays outside the model, but the loop still receives a normal tool_result or blocked result.</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function PermissionVisualization({ title }: { title?: string }) {
|
||||
const vis = useSteppedVisualization({ totalSteps: STEPS.length, autoPlayInterval: 2500 });
|
||||
const step = vis.currentStep;
|
||||
const current = STEPS[step];
|
||||
const mode = current.mode;
|
||||
const activeId = activeRequestId(mode);
|
||||
|
||||
return (
|
||||
<section className="min-h-[500px] space-y-4">
|
||||
<h2 className="text-xl font-semibold text-zinc-900 dark:text-zinc-100">
|
||||
{title || "Permission Desk"}
|
||||
</h2>
|
||||
|
||||
<div className="rounded-lg border border-zinc-200 bg-white p-4 dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<div className="grid gap-3 lg:grid-cols-[1fr_1.1fr_0.95fr]">
|
||||
<Surface title="Tool requests" icon={<OctagonAlert size={20} />} active={mode === "overview" || activeId !== null}>
|
||||
<div className="space-y-2">
|
||||
{REQUESTS.map((request) => (
|
||||
<RequestCard
|
||||
key={request.id}
|
||||
request={request}
|
||||
active={activeId === request.id || (mode === "overview" && step === 0)}
|
||||
muted={activeId !== null && activeId !== request.id}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Surface>
|
||||
|
||||
<Surface title="Permission desk" icon={<ShieldCheck size={20} />} active={mode !== "overview"}>
|
||||
<PermissionDesk mode={mode} />
|
||||
</Surface>
|
||||
|
||||
<Surface title="Outcome" icon={<PlayCircle size={20} />} active={mode !== "overview"}>
|
||||
<AnimatePresence mode="wait">
|
||||
<Outcome key={mode} mode={mode} />
|
||||
</AnimatePresence>
|
||||
</Surface>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 rounded-lg border border-zinc-200 bg-zinc-50 px-4 py-3 text-sm leading-relaxed text-zinc-600 dark:border-zinc-700 dark:bg-zinc-800/70 dark:text-zinc-300">
|
||||
Beginner rule: the model proposes tools; the runtime routes each request to allow, ask, or deny before execution.
|
||||
</div>
|
||||
|
||||
<StepControls
|
||||
className="mt-4"
|
||||
currentStep={vis.currentStep}
|
||||
totalSteps={vis.totalSteps}
|
||||
onPrev={vis.prev}
|
||||
onNext={vis.next}
|
||||
onReset={vis.reset}
|
||||
isPlaying={vis.isPlaying}
|
||||
onToggleAutoPlay={vis.toggleAutoPlay}
|
||||
stepTitle={current.title}
|
||||
stepDescription={current.desc}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -99,12 +99,12 @@ function KanbanColumn({
|
||||
headerBg: string;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex min-h-[280px] flex-1 flex-col rounded-lg border border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<div className="min-w-0 flex min-h-[220px] flex-col rounded-lg border border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 sm:min-h-[280px]">
|
||||
<div
|
||||
className={`rounded-t-lg px-3 py-2 text-center text-xs font-bold uppercase tracking-wider ${headerBg}`}
|
||||
className={`flex items-center justify-center gap-1 rounded-t-lg px-3 py-2 text-center text-xs font-bold uppercase tracking-wider ${headerBg}`}
|
||||
>
|
||||
{title}
|
||||
<span className={`ml-1.5 inline-flex h-5 w-5 items-center justify-center rounded-full text-[10px] font-bold ${accentClass}`}>
|
||||
<span className="min-w-0 break-words">{title}</span>
|
||||
<span className={`inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-[10px] font-bold ${accentClass}`}>
|
||||
{tasks.length}
|
||||
</span>
|
||||
</div>
|
||||
@@ -147,19 +147,19 @@ function TaskCard({ task }: { task: Task }) {
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.8 }}
|
||||
transition={{ type: "spring", stiffness: 400, damping: 30 }}
|
||||
className={`rounded-md border p-2.5 ${borderStyles[task.status]}`}
|
||||
className={`min-w-0 rounded-md border p-2.5 ${borderStyles[task.status]}`}
|
||||
>
|
||||
<div className="mb-1.5 flex items-center justify-between">
|
||||
<div className="mb-1.5 flex min-w-0 items-center justify-between gap-2">
|
||||
<span className="font-mono text-[10px] text-zinc-400 dark:text-zinc-500">
|
||||
#{task.id}
|
||||
</span>
|
||||
<span
|
||||
className={`rounded-full px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${statusStyles[task.status]}`}
|
||||
className={`shrink-0 rounded-full px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${statusStyles[task.status]}`}
|
||||
>
|
||||
{task.status.replace("_", " ")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
|
||||
<div className="break-words text-xs font-medium leading-snug text-zinc-700 dark:text-zinc-300">
|
||||
{task.label}
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -264,7 +264,7 @@ export default function TodoWrite({ title }: { title?: string }) {
|
||||
</div>
|
||||
|
||||
{/* Kanban board */}
|
||||
<div className="flex gap-3">
|
||||
<div className="grid gap-3 sm:grid-cols-3">
|
||||
<KanbanColumn
|
||||
title="Pending"
|
||||
tasks={pendingTasks}
|
||||
|
||||
269
web/src/components/visualizations/s04-hooks.tsx
Normal file
@@ -0,0 +1,269 @@
|
||||
"use client";
|
||||
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { ClipboardList, FileSearch, LogOut, PlugZap, RadioTower, ScrollText, Wrench } from "lucide-react";
|
||||
import { StepControls } from "@/components/visualizations/shared/step-controls";
|
||||
import { useSteppedVisualization } from "@/hooks/useSteppedVisualization";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type HookId = "UserPromptSubmit" | "PreToolUse" | "PostToolUse" | "Stop";
|
||||
|
||||
const HOOKS: {
|
||||
id: HookId;
|
||||
when: string;
|
||||
callbacks: string[];
|
||||
color: "blue" | "amber" | "emerald" | "zinc";
|
||||
}[] = [
|
||||
{
|
||||
id: "UserPromptSubmit",
|
||||
when: "after input, before LLM",
|
||||
callbacks: ["context_inject_hook"],
|
||||
color: "blue",
|
||||
},
|
||||
{
|
||||
id: "PreToolUse",
|
||||
when: "after tool_use, before handler",
|
||||
callbacks: ["permission_hook", "log_hook"],
|
||||
color: "amber",
|
||||
},
|
||||
{
|
||||
id: "PostToolUse",
|
||||
when: "after handler, before next turn",
|
||||
callbacks: ["large_output_hook"],
|
||||
color: "emerald",
|
||||
},
|
||||
{
|
||||
id: "Stop",
|
||||
when: "before final output",
|
||||
callbacks: ["summary_hook"],
|
||||
color: "zinc",
|
||||
},
|
||||
];
|
||||
|
||||
const STEPS = [
|
||||
{
|
||||
title: "Hooks Are Registered Outside the Loop",
|
||||
desc: "The loop only knows event names; callback behavior lives in the registry.",
|
||||
active: null,
|
||||
},
|
||||
{
|
||||
title: "UserPromptSubmit",
|
||||
desc: "Input hooks can log, validate, or inject context before the model sees the prompt.",
|
||||
active: "UserPromptSubmit" as HookId,
|
||||
},
|
||||
{
|
||||
title: "The Core Loop Still Chooses a Tool",
|
||||
desc: "Calling the model and receiving tool_use remains the same as before.",
|
||||
active: null,
|
||||
},
|
||||
{
|
||||
title: "PreToolUse",
|
||||
desc: "Permission and logging hooks run before the handler touches the workspace.",
|
||||
active: "PreToolUse" as HookId,
|
||||
},
|
||||
{
|
||||
title: "PostToolUse",
|
||||
desc: "Result hooks inspect output or trigger side effects after execution.",
|
||||
active: "PostToolUse" as HookId,
|
||||
},
|
||||
{
|
||||
title: "Stop",
|
||||
desc: "Cleanup and summary hooks run when the model stops asking for tools.",
|
||||
active: "Stop" as HookId,
|
||||
},
|
||||
] as const;
|
||||
|
||||
function toneClass(tone: "blue" | "amber" | "emerald" | "zinc", active = true) {
|
||||
if (!active) return "border-zinc-200 bg-white text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200";
|
||||
if (tone === "blue") return "border-blue-200 bg-blue-50 text-blue-800 dark:border-blue-900 dark:bg-blue-950/40 dark:text-blue-200";
|
||||
if (tone === "amber") return "border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900 dark:bg-amber-950/40 dark:text-amber-200";
|
||||
if (tone === "emerald") return "border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900 dark:bg-emerald-950/40 dark:text-emerald-200";
|
||||
return "border-zinc-200 bg-zinc-50 text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-200";
|
||||
}
|
||||
|
||||
function Surface({
|
||||
title,
|
||||
icon,
|
||||
active,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
icon: React.ReactNode;
|
||||
active: boolean;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"min-w-0 rounded-lg border p-4 transition-colors",
|
||||
active
|
||||
? "border-emerald-300 bg-emerald-50 dark:border-emerald-900 dark:bg-emerald-950/30"
|
||||
: "border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900"
|
||||
)}
|
||||
>
|
||||
<div className="mb-4 flex items-center gap-3 text-lg font-semibold text-zinc-900 dark:text-zinc-100">
|
||||
<span
|
||||
className={cn(
|
||||
"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg",
|
||||
active
|
||||
? "bg-emerald-500 text-white"
|
||||
: "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300"
|
||||
)}
|
||||
>
|
||||
{icon}
|
||||
</span>
|
||||
{title}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function HookCard({
|
||||
hook,
|
||||
active,
|
||||
}: {
|
||||
hook: (typeof HOOKS)[number];
|
||||
active: boolean;
|
||||
}) {
|
||||
return (
|
||||
<motion.div
|
||||
layout
|
||||
animate={active ? { y: [0, -2, 0] } : { y: 0 }}
|
||||
transition={{ duration: 0.8, repeat: active ? Infinity : 0 }}
|
||||
className={cn("rounded-lg border p-3", toneClass(hook.color, active))}
|
||||
>
|
||||
<div className="mb-1 flex min-w-0 items-center justify-between gap-2">
|
||||
<div className="min-w-0 truncate font-mono text-sm font-semibold">{hook.id}</div>
|
||||
{active && <PlugZap size={16} className="shrink-0" />}
|
||||
</div>
|
||||
<div className="mb-3 text-xs leading-relaxed opacity-80">{hook.when}</div>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{hook.callbacks.map((callback) => (
|
||||
<span key={callback} className="rounded bg-white/70 px-2 py-1 font-mono text-[11px] dark:bg-zinc-950/30">
|
||||
{callback}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
function TurnCard({ step }: { step: number }) {
|
||||
const state =
|
||||
step <= 1
|
||||
? { title: "User input", body: "Read README.md and summarize it.", icon: <ScrollText size={18} /> }
|
||||
: step === 2
|
||||
? { title: "LLM chooses tool", body: "tool_use: read_file({ path: 'README.md' })", icon: <Wrench size={18} /> }
|
||||
: step === 3
|
||||
? { title: "Tool waits at pre-hook", body: "permission_hook + log_hook inspect the call.", icon: <FileSearch size={18} /> }
|
||||
: step === 4
|
||||
? { title: "Handler returned output", body: "large_output_hook checks result size.", icon: <ClipboardList size={18} /> }
|
||||
: { title: "No more tool_use", body: "summary_hook records final session stats.", icon: <LogOut size={18} /> };
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
key={state.title}
|
||||
initial={{ opacity: 0, y: 8 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="rounded-xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-700 dark:bg-zinc-900"
|
||||
>
|
||||
<div className="mb-2 flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100">
|
||||
{state.icon}
|
||||
{state.title}
|
||||
</div>
|
||||
<div className="rounded-lg bg-zinc-50 p-3 font-mono text-xs leading-relaxed text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300">
|
||||
{state.body}
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
function AuditLog({ step }: { step: number }) {
|
||||
const items = [
|
||||
"[registry] four hook slots registered",
|
||||
"[UserPromptSubmit] working directory logged",
|
||||
"[loop] model returned read_file tool_use",
|
||||
"[PreToolUse] permission allowed; tool call logged",
|
||||
"[PostToolUse] output size checked",
|
||||
"[Stop] session used 1 tool call",
|
||||
].slice(0, step + 1);
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<AnimatePresence mode="popLayout">
|
||||
{items.map((item) => (
|
||||
<motion.div
|
||||
key={item}
|
||||
layout
|
||||
initial={{ opacity: 0, x: 8 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
exit={{ opacity: 0, x: -8 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className="rounded-lg border border-zinc-200 bg-white px-3 py-2 font-mono text-xs text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200"
|
||||
>
|
||||
{item}
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function HooksVisualization({ title }: { title?: string }) {
|
||||
const vis = useSteppedVisualization({ totalSteps: STEPS.length, autoPlayInterval: 2500 });
|
||||
const step = vis.currentStep;
|
||||
const current = STEPS[step];
|
||||
const activeHook = current.active;
|
||||
|
||||
return (
|
||||
<section className="min-h-[500px] space-y-4">
|
||||
<h2 className="text-xl font-semibold text-zinc-900 dark:text-zinc-100">
|
||||
{title || "Hook Workbench"}
|
||||
</h2>
|
||||
|
||||
<div className="rounded-lg border border-zinc-200 bg-white p-4 dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<div className="mb-4 rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm leading-relaxed text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950/30 dark:text-emerald-200">
|
||||
The loop stays boring on purpose: it calls <span className="font-mono">trigger_hooks(event)</span>, and the registry decides what extra logic runs.
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 xl:grid-cols-[1.15fr_0.85fr]">
|
||||
<Surface title="Hook registry" icon={<RadioTower size={20} />} active={step === 0 || activeHook !== null}>
|
||||
<div className="grid gap-2 sm:grid-cols-2">
|
||||
{HOOKS.map((hook) => (
|
||||
<HookCard key={hook.id} hook={hook} active={activeHook === hook.id} />
|
||||
))}
|
||||
</div>
|
||||
</Surface>
|
||||
|
||||
<Surface title="This turn" icon={<ScrollText size={20} />} active={step >= 1}>
|
||||
<div className="space-y-3">
|
||||
<TurnCard step={step} />
|
||||
<div className="rounded-lg border border-zinc-200 bg-zinc-50 p-3 dark:border-zinc-700 dark:bg-zinc-800/70">
|
||||
<div className="mb-2 text-sm font-semibold text-zinc-800 dark:text-zinc-100">Audit log</div>
|
||||
<AuditLog step={step} />
|
||||
</div>
|
||||
</div>
|
||||
</Surface>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 rounded-lg border border-zinc-200 bg-zinc-50 px-4 py-3 text-sm leading-relaxed text-zinc-600 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300">
|
||||
Beginner rule: adding behavior means registering a callback, not editing the core model-tool-result loop.
|
||||
</div>
|
||||
|
||||
<StepControls
|
||||
className="mt-4"
|
||||
currentStep={vis.currentStep}
|
||||
totalSteps={vis.totalSteps}
|
||||
onPrev={vis.prev}
|
||||
onNext={vis.next}
|
||||
onReset={vis.reset}
|
||||
isPlaying={vis.isPlaying}
|
||||
onToggleAutoPlay={vis.toggleAutoPlay}
|
||||
stepTitle={current.title}
|
||||
stepDescription={current.desc}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -193,6 +193,36 @@ const STEPS = [
|
||||
},
|
||||
];
|
||||
|
||||
const COMPRESSION_LAYERS = [
|
||||
{
|
||||
label: "Micro",
|
||||
full: "MICRO-COMPACT",
|
||||
trigger: "old tool_result",
|
||||
action: "shrink bulky outputs",
|
||||
step: 3,
|
||||
classes:
|
||||
"border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900 dark:bg-amber-950/30 dark:text-amber-200",
|
||||
},
|
||||
{
|
||||
label: "Auto",
|
||||
full: "AUTO-COMPACT",
|
||||
trigger: "token threshold",
|
||||
action: "summarize the conversation",
|
||||
step: 5,
|
||||
classes:
|
||||
"border-blue-200 bg-blue-50 text-blue-800 dark:border-blue-900 dark:bg-blue-950/30 dark:text-blue-200",
|
||||
},
|
||||
{
|
||||
label: "Manual",
|
||||
full: "/compact",
|
||||
trigger: "user command",
|
||||
action: "keep one compact summary",
|
||||
step: 6,
|
||||
classes:
|
||||
"border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900 dark:bg-emerald-950/30 dark:text-emerald-200",
|
||||
},
|
||||
];
|
||||
|
||||
export default function ContextCompact({ title }: { title?: string }) {
|
||||
const {
|
||||
currentStep,
|
||||
@@ -222,17 +252,17 @@ export default function ContextCompact({ title }: { title?: string }) {
|
||||
</h2>
|
||||
|
||||
<div
|
||||
className="rounded-lg border border-zinc-200 bg-white p-6 dark:border-zinc-700 dark:bg-zinc-900"
|
||||
className="rounded-lg border border-zinc-200 bg-white p-4 dark:border-zinc-700 dark:bg-zinc-900 sm:p-6"
|
||||
style={{ minHeight: 500 }}
|
||||
>
|
||||
<div className="flex gap-6">
|
||||
<div className="grid gap-5 lg:grid-cols-[140px_1fr]">
|
||||
{/* Token Window (tall vertical bar on the left) */}
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="min-w-0 flex flex-col items-center">
|
||||
<div className="mb-2 font-mono text-[10px] font-semibold text-zinc-500 dark:text-zinc-400">
|
||||
Context Window
|
||||
</div>
|
||||
<div
|
||||
className="relative w-24 overflow-hidden rounded-xl border-2 border-zinc-300 bg-zinc-50 dark:border-zinc-600 dark:bg-zinc-800"
|
||||
className="relative w-20 max-w-full overflow-hidden rounded-xl border-2 border-zinc-300 bg-zinc-50 dark:border-zinc-600 dark:bg-zinc-800 sm:w-24"
|
||||
style={{ height: WINDOW_HEIGHT }}
|
||||
>
|
||||
{/* Blocks stacked from bottom up */}
|
||||
@@ -293,14 +323,14 @@ export default function ContextCompact({ title }: { title?: string }) {
|
||||
</div>
|
||||
|
||||
{/* Right side: state display and compression stage */}
|
||||
<div className="flex flex-1 flex-col justify-between">
|
||||
<div className="min-w-0">
|
||||
{/* Top: horizontal token bar */}
|
||||
<div>
|
||||
<div className="mb-1 flex items-center justify-between">
|
||||
<div className="mb-1 flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between">
|
||||
<span className="text-xs text-zinc-500 dark:text-zinc-400">
|
||||
Token usage
|
||||
</span>
|
||||
<span className="font-mono text-xs text-zinc-500">
|
||||
<span className="break-words font-mono text-xs text-zinc-500 dark:text-zinc-400">
|
||||
{state.tokenCount.toLocaleString()} / {MAX_TOKENS.toLocaleString()}
|
||||
</span>
|
||||
</div>
|
||||
@@ -314,7 +344,7 @@ export default function ContextCompact({ title }: { title?: string }) {
|
||||
</div>
|
||||
|
||||
{/* Message type legend */}
|
||||
<div className="mt-4 flex items-center gap-4">
|
||||
<div className="mt-4 flex flex-wrap items-center gap-3">
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="h-3 w-3 rounded bg-blue-500" />
|
||||
<span className="text-[10px] text-zinc-500 dark:text-zinc-400">user</span>
|
||||
@@ -329,6 +359,37 @@ export default function ContextCompact({ title }: { title?: string }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 grid gap-2 sm:grid-cols-3">
|
||||
{COMPRESSION_LAYERS.map((layer) => {
|
||||
const reached = currentStep >= layer.step;
|
||||
const active = state.compressionLabel === layer.full;
|
||||
return (
|
||||
<motion.div
|
||||
key={layer.full}
|
||||
layout
|
||||
animate={active ? { y: [0, -2, 0] } : { y: 0 }}
|
||||
transition={{ duration: 0.8, repeat: active ? Infinity : 0 }}
|
||||
className={`min-w-0 rounded-lg border p-3 transition-colors ${
|
||||
reached
|
||||
? layer.classes
|
||||
: "border-zinc-200 bg-zinc-50 text-zinc-500 dark:border-zinc-700 dark:bg-zinc-800/70 dark:text-zinc-400"
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="text-sm font-semibold">{layer.label}</span>
|
||||
<span className="rounded bg-white/70 px-1.5 py-0.5 font-mono text-[10px] dark:bg-zinc-900/60">
|
||||
{reached ? "used" : "waiting"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 space-y-1 text-[11px] leading-snug">
|
||||
<div className="break-words font-mono">{layer.trigger}</div>
|
||||
<div className="break-words opacity-80">{layer.action}</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Highlight old tool_results at step 2 */}
|
||||
<AnimatePresence>
|
||||
{currentStep === 2 && (
|
||||
@@ -336,12 +397,12 @@ export default function ContextCompact({ title }: { title?: string }) {
|
||||
initial={{ opacity: 0, y: 8 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="mt-3 rounded border border-amber-300 bg-amber-50 px-3 py-2 dark:border-amber-700 dark:bg-amber-900/20"
|
||||
className="mt-3 rounded-lg border border-amber-300 bg-amber-50 px-3 py-2 dark:border-amber-700 dark:bg-amber-900/20"
|
||||
>
|
||||
<div className="text-xs font-semibold text-amber-700 dark:text-amber-300">
|
||||
tool_results are the largest blocks
|
||||
</div>
|
||||
<div className="text-[11px] text-amber-600 dark:text-amber-400">
|
||||
<div className="text-[11px] leading-snug text-amber-600 dark:text-amber-400">
|
||||
File contents, command outputs, search results -- each one is thousands of tokens.
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -374,7 +435,7 @@ export default function ContextCompact({ title }: { title?: string }) {
|
||||
}`}>
|
||||
{state.compressionLabel}
|
||||
</div>
|
||||
<div className={`mt-1 text-xs ${
|
||||
<div className={`mt-1 text-xs leading-snug ${
|
||||
currentStep === 3
|
||||
? "text-amber-500 dark:text-amber-400"
|
||||
: currentStep === 5
|
||||
@@ -396,35 +457,21 @@ export default function ContextCompact({ title }: { title?: string }) {
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4 }}
|
||||
className="mt-4 space-y-2"
|
||||
className="mt-4 grid gap-2"
|
||||
>
|
||||
<div className="flex items-center gap-2 rounded bg-amber-50 px-3 py-1.5 dark:bg-amber-900/10">
|
||||
<div className="h-2 w-2 rounded-full bg-amber-500" />
|
||||
<span className="text-xs text-amber-700 dark:text-amber-300">
|
||||
Stage 1: Micro -- shrink old tool_results
|
||||
</span>
|
||||
<span className="ml-auto font-mono text-[10px] text-amber-500">
|
||||
automatic
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 rounded bg-blue-50 px-3 py-1.5 dark:bg-blue-900/10">
|
||||
<div className="h-2 w-2 rounded-full bg-blue-500" />
|
||||
<span className="text-xs text-blue-700 dark:text-blue-300">
|
||||
Stage 2: Auto -- summarize entire conversation
|
||||
</span>
|
||||
<span className="ml-auto font-mono text-[10px] text-blue-500">
|
||||
at threshold
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 rounded bg-emerald-50 px-3 py-1.5 dark:bg-emerald-900/10">
|
||||
<div className="h-2 w-2 rounded-full bg-emerald-500" />
|
||||
<span className="text-xs text-emerald-700 dark:text-emerald-300">
|
||||
Stage 3: /compact -- user-triggered, deepest compression
|
||||
</span>
|
||||
<span className="ml-auto font-mono text-[10px] text-emerald-500">
|
||||
manual
|
||||
</span>
|
||||
</div>
|
||||
{COMPRESSION_LAYERS.map((layer, index) => (
|
||||
<div
|
||||
key={`summary-${layer.full}`}
|
||||
className={`flex flex-col gap-1 rounded px-3 py-2 sm:flex-row sm:items-center sm:justify-between ${layer.classes}`}
|
||||
>
|
||||
<span className="break-words text-xs">
|
||||
Stage {index + 1}: {layer.label} -- {layer.action}
|
||||
</span>
|
||||
<span className="shrink-0 font-mono text-[10px] opacity-80">
|
||||
{layer.trigger}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,494 +1,214 @@
|
||||
"use client";
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { useSteppedVisualization } from "@/hooks/useSteppedVisualization";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { CheckCircle2, ClipboardList, FileJson, LockKeyhole, PlayCircle } from "lucide-react";
|
||||
import { StepControls } from "@/components/visualizations/shared/step-controls";
|
||||
import { useDarkMode, useSvgPalette } from "@/hooks/useDarkMode";
|
||||
import { useSteppedVisualization } from "@/hooks/useSteppedVisualization";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type TaskStatus = "pending" | "in_progress" | "completed" | "blocked";
|
||||
type Status = "blocked" | "ready" | "active" | "done";
|
||||
|
||||
interface TaskNode {
|
||||
interface TaskCard {
|
||||
id: string;
|
||||
label: string;
|
||||
x: number;
|
||||
y: number;
|
||||
deps: string[];
|
||||
}
|
||||
|
||||
interface StepInfo {
|
||||
title: string;
|
||||
description: string;
|
||||
blockers: string[];
|
||||
status: Status;
|
||||
}
|
||||
|
||||
const TASKS: TaskNode[] = [
|
||||
{ id: "T1", label: "T1: Setup DB", x: 80, y: 160, deps: [] },
|
||||
{ id: "T2", label: "T2: API routes", x: 280, y: 80, deps: ["T1"] },
|
||||
{ id: "T3", label: "T3: Auth module", x: 280, y: 240, deps: ["T1"] },
|
||||
{ id: "T4", label: "T4: Integration", x: 480, y: 160, deps: ["T2", "T3"] },
|
||||
{ id: "T5", label: "T5: Deploy", x: 650, y: 160, deps: ["T4"] },
|
||||
const STEPS = [
|
||||
{
|
||||
title: "Tasks Become Files",
|
||||
desc: "The agent writes work as task cards on disk, so the plan survives compaction and restarts.",
|
||||
},
|
||||
{
|
||||
title: "Find the First Ready Card",
|
||||
desc: "A task with no blockers is ready immediately. Everything else waits visibly.",
|
||||
},
|
||||
{
|
||||
title: "Work One Card",
|
||||
desc: "The active task is not just text in the model's head; it has a durable status.",
|
||||
},
|
||||
{
|
||||
title: "Completion Unlocks Dependents",
|
||||
desc: "When T1 is done, the cards that depended on T1 become ready.",
|
||||
},
|
||||
{
|
||||
title: "Parallel Ready Work",
|
||||
desc: "T2 and T3 can run independently, while T4 still waits for both.",
|
||||
},
|
||||
{
|
||||
title: "All Blockers Cleared",
|
||||
desc: "Once T2 and T3 are done, T4 moves from waiting to active.",
|
||||
},
|
||||
{
|
||||
title: "Board Resolved",
|
||||
desc: "Every card reaches done. The dependency idea is visible without drawing a graph.",
|
||||
},
|
||||
] as const;
|
||||
|
||||
const BASE_TASKS = [
|
||||
{ id: "T1", title: "Set up database", blockers: [] },
|
||||
{ id: "T2", title: "Add API routes", blockers: ["T1"] },
|
||||
{ id: "T3", title: "Build auth module", blockers: ["T1"] },
|
||||
{ id: "T4", title: "Integration pass", blockers: ["T2", "T3"] },
|
||||
{ id: "T5", title: "Deploy", blockers: ["T4"] },
|
||||
];
|
||||
|
||||
const NODE_W = 140;
|
||||
const NODE_H = 50;
|
||||
|
||||
const STEP_INFO: StepInfo[] = [
|
||||
{
|
||||
title: "File-Based Tasks",
|
||||
description:
|
||||
"Tasks are stored in JSON files on disk. They survive context compaction -- unlike in-memory state.",
|
||||
},
|
||||
{
|
||||
title: "Start T1",
|
||||
description:
|
||||
"Tasks without dependencies can start immediately. T1 has no blockers.",
|
||||
},
|
||||
{
|
||||
title: "T1 Complete",
|
||||
description: "Completing T1 unblocks its dependents: T2 and T3.",
|
||||
},
|
||||
{
|
||||
title: "Parallel Work",
|
||||
description:
|
||||
"T2 and T3 have no dependency on each other. Both can run simultaneously.",
|
||||
},
|
||||
{
|
||||
title: "Partial Unblock",
|
||||
description:
|
||||
"T4 depends on BOTH T2 and T3. It waits for all blockers to complete.",
|
||||
},
|
||||
{
|
||||
title: "Fully Unblocked",
|
||||
description: "All blockers resolved. T4 can now proceed.",
|
||||
},
|
||||
{
|
||||
title: "Graph Resolved",
|
||||
description:
|
||||
"The entire dependency graph is resolved. File-based persistence means this works across context compressions.",
|
||||
},
|
||||
];
|
||||
|
||||
function getTaskStatus(taskId: string, step: number): TaskStatus {
|
||||
const statusMap: Record<string, TaskStatus[]> = {
|
||||
T1: [
|
||||
"pending",
|
||||
"in_progress",
|
||||
"completed",
|
||||
"completed",
|
||||
"completed",
|
||||
"completed",
|
||||
"completed",
|
||||
],
|
||||
T2: [
|
||||
"pending",
|
||||
"pending",
|
||||
"pending",
|
||||
"in_progress",
|
||||
"completed",
|
||||
"completed",
|
||||
"completed",
|
||||
],
|
||||
T3: [
|
||||
"pending",
|
||||
"pending",
|
||||
"pending",
|
||||
"in_progress",
|
||||
"in_progress",
|
||||
"completed",
|
||||
"completed",
|
||||
],
|
||||
T4: [
|
||||
"pending",
|
||||
"pending",
|
||||
"pending",
|
||||
"pending",
|
||||
"blocked",
|
||||
"in_progress",
|
||||
"completed",
|
||||
],
|
||||
T5: [
|
||||
"pending",
|
||||
"pending",
|
||||
"pending",
|
||||
"pending",
|
||||
"pending",
|
||||
"pending",
|
||||
"completed",
|
||||
],
|
||||
function taskStatus(id: string, step: number): Status {
|
||||
const table: Record<string, Status[]> = {
|
||||
T1: ["ready", "ready", "active", "done", "done", "done", "done"],
|
||||
T2: ["blocked", "blocked", "blocked", "ready", "active", "done", "done"],
|
||||
T3: ["blocked", "blocked", "blocked", "ready", "active", "done", "done"],
|
||||
T4: ["blocked", "blocked", "blocked", "blocked", "blocked", "active", "done"],
|
||||
T5: ["blocked", "blocked", "blocked", "blocked", "blocked", "blocked", "done"],
|
||||
};
|
||||
return statusMap[taskId]?.[step] ?? "pending";
|
||||
return table[id]?.[step] ?? "blocked";
|
||||
}
|
||||
|
||||
function isEdgeActive(fromId: string, toId: string, step: number): boolean {
|
||||
const fromStatus = getTaskStatus(fromId, step);
|
||||
const toStatus = getTaskStatus(toId, step);
|
||||
function getTasks(step: number): TaskCard[] {
|
||||
return BASE_TASKS.map((task) => ({ ...task, status: taskStatus(task.id, step) }));
|
||||
}
|
||||
|
||||
function statusClass(status: Status): string {
|
||||
if (status === "done") return "border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900 dark:bg-emerald-950/40 dark:text-emerald-200";
|
||||
if (status === "active") return "border-blue-200 bg-blue-50 text-blue-800 dark:border-blue-900 dark:bg-blue-950/40 dark:text-blue-200";
|
||||
if (status === "ready") return "border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900 dark:bg-amber-950/40 dark:text-amber-200";
|
||||
return "border-zinc-200 bg-zinc-50 text-zinc-600 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300";
|
||||
}
|
||||
|
||||
function statusIcon(status: Status) {
|
||||
if (status === "done") return <CheckCircle2 size={15} />;
|
||||
if (status === "active") return <PlayCircle size={15} />;
|
||||
if (status === "ready") return <ClipboardList size={15} />;
|
||||
return <LockKeyhole size={15} />;
|
||||
}
|
||||
|
||||
function TaskCardView({ task }: { task: TaskCard }) {
|
||||
return (
|
||||
fromStatus === "completed" &&
|
||||
(toStatus === "in_progress" || toStatus === "completed")
|
||||
<motion.div
|
||||
layout
|
||||
initial={{ opacity: 0, y: 8 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.97 }}
|
||||
transition={{ duration: 0.22 }}
|
||||
className={cn("rounded-md border p-3 shadow-sm", statusClass(task.status))}
|
||||
>
|
||||
<div className="mb-2 flex items-center justify-between gap-2">
|
||||
<div className="font-mono text-xs font-semibold">{task.id}</div>
|
||||
<div className="flex items-center gap-1 text-[11px] font-semibold">
|
||||
{statusIcon(task.status)}
|
||||
{task.status}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm font-semibold leading-snug">{task.title}</div>
|
||||
<div className="mt-2 flex flex-wrap gap-1">
|
||||
{task.blockers.length === 0 ? (
|
||||
<span className="rounded bg-white/70 px-1.5 py-0.5 text-[10px] dark:bg-zinc-950/30">
|
||||
no blockers
|
||||
</span>
|
||||
) : (
|
||||
task.blockers.map((blocker) => (
|
||||
<span key={blocker} className="rounded bg-white/70 px-1.5 py-0.5 font-mono text-[10px] dark:bg-zinc-950/30">
|
||||
waits for {blocker}
|
||||
</span>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
function getStatusColor(status: TaskStatus) {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return {
|
||||
fill: "#e2e8f0",
|
||||
darkFill: "#27272a",
|
||||
stroke: "#cbd5e1",
|
||||
darkStroke: "#3f3f46",
|
||||
text: "#475569",
|
||||
darkText: "#d4d4d8",
|
||||
};
|
||||
case "in_progress":
|
||||
return {
|
||||
fill: "#fef3c7",
|
||||
darkFill: "#451a0340",
|
||||
stroke: "#f59e0b",
|
||||
darkStroke: "#d97706",
|
||||
text: "#b45309",
|
||||
darkText: "#fbbf24",
|
||||
};
|
||||
case "completed":
|
||||
return {
|
||||
fill: "#d1fae5",
|
||||
darkFill: "#06402740",
|
||||
stroke: "#10b981",
|
||||
darkStroke: "#059669",
|
||||
text: "#047857",
|
||||
darkText: "#34d399",
|
||||
};
|
||||
case "blocked":
|
||||
return {
|
||||
fill: "#fecaca",
|
||||
darkFill: "#45050540",
|
||||
stroke: "#ef4444",
|
||||
darkStroke: "#dc2626",
|
||||
text: "#dc2626",
|
||||
darkText: "#f87171",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getStatusLabel(status: TaskStatus): string {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return "pending";
|
||||
case "in_progress":
|
||||
return "in_progress";
|
||||
case "completed":
|
||||
return "done";
|
||||
case "blocked":
|
||||
return "blocked";
|
||||
}
|
||||
}
|
||||
|
||||
function buildCurvePath(
|
||||
x1: number,
|
||||
y1: number,
|
||||
x2: number,
|
||||
y2: number
|
||||
): string {
|
||||
const midX = (x1 + x2) / 2;
|
||||
return `M ${x1} ${y1} C ${midX} ${y1}, ${midX} ${y2}, ${x2} ${y2}`;
|
||||
function Lane({
|
||||
title,
|
||||
subtitle,
|
||||
tasks,
|
||||
}: {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
tasks: TaskCard[];
|
||||
}) {
|
||||
return (
|
||||
<div className="rounded-lg border border-zinc-200 bg-white p-3 dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<div className="mb-3">
|
||||
<div className="text-sm font-semibold text-zinc-800 dark:text-zinc-100">{title}</div>
|
||||
<div className="text-[11px] text-zinc-500 dark:text-zinc-400">{subtitle}</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<AnimatePresence mode="popLayout">
|
||||
{tasks.length > 0 ? (
|
||||
tasks.map((task) => <TaskCardView key={`${task.id}-${task.status}`} task={task} />)
|
||||
) : (
|
||||
<motion.div
|
||||
key="empty"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="rounded-md border border-dashed border-zinc-300 px-3 py-6 text-center text-xs text-zinc-500 dark:border-zinc-700 dark:text-zinc-400"
|
||||
>
|
||||
empty
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function TaskSystem({ title }: { title?: string }) {
|
||||
const {
|
||||
currentStep,
|
||||
totalSteps,
|
||||
next,
|
||||
prev,
|
||||
reset,
|
||||
isPlaying,
|
||||
toggleAutoPlay,
|
||||
} = useSteppedVisualization({ totalSteps: 7, autoPlayInterval: 2500 });
|
||||
const vis = useSteppedVisualization({ totalSteps: STEPS.length, autoPlayInterval: 2500 });
|
||||
const step = vis.currentStep;
|
||||
const tasks = getTasks(step);
|
||||
const current = STEPS[step];
|
||||
|
||||
const isDark = useDarkMode();
|
||||
const palette = useSvgPalette();
|
||||
|
||||
const edges = useMemo(() => {
|
||||
const result: {
|
||||
fromId: string;
|
||||
toId: string;
|
||||
x1: number;
|
||||
y1: number;
|
||||
x2: number;
|
||||
y2: number;
|
||||
}[] = [];
|
||||
for (const task of TASKS) {
|
||||
for (const depId of task.deps) {
|
||||
const dep = TASKS.find((t) => t.id === depId);
|
||||
if (!dep) continue;
|
||||
result.push({
|
||||
fromId: dep.id,
|
||||
toId: task.id,
|
||||
x1: dep.x + NODE_W,
|
||||
y1: dep.y + NODE_H / 2,
|
||||
x2: task.x,
|
||||
y2: task.y + NODE_H / 2,
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, []);
|
||||
|
||||
const stepInfo = STEP_INFO[currentStep];
|
||||
const blocked = tasks.filter((task) => task.status === "blocked");
|
||||
const ready = tasks.filter((task) => task.status === "ready");
|
||||
const active = tasks.filter((task) => task.status === "active");
|
||||
const done = tasks.filter((task) => task.status === "done");
|
||||
|
||||
return (
|
||||
<section className="min-h-[500px] space-y-4">
|
||||
<h2 className="text-xl font-semibold text-zinc-900 dark:text-zinc-100">
|
||||
{title || "Task Dependency Graph"}
|
||||
{title || "Task Board Dependencies"}
|
||||
</h2>
|
||||
|
||||
<div className="rounded-lg border border-zinc-200 bg-white p-4 dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<svg viewBox="0 0 800 340" className="w-full" aria-label="Task DAG">
|
||||
<defs>
|
||||
<marker
|
||||
id="arrowGray"
|
||||
viewBox="0 0 10 10"
|
||||
refX="9"
|
||||
refY="5"
|
||||
markerWidth="6"
|
||||
markerHeight="6"
|
||||
orient="auto-start-reverse"
|
||||
>
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill={palette.arrowFill} />
|
||||
</marker>
|
||||
<marker
|
||||
id="arrowGreen"
|
||||
viewBox="0 0 10 10"
|
||||
refX="9"
|
||||
refY="5"
|
||||
markerWidth="6"
|
||||
markerHeight="6"
|
||||
orient="auto-start-reverse"
|
||||
>
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#10b981" />
|
||||
</marker>
|
||||
<marker
|
||||
id="arrowRed"
|
||||
viewBox="0 0 10 10"
|
||||
refX="9"
|
||||
refY="5"
|
||||
markerWidth="6"
|
||||
markerHeight="6"
|
||||
orient="auto-start-reverse"
|
||||
>
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ef4444" />
|
||||
</marker>
|
||||
<filter id="glowAmber" x="-30%" y="-30%" width="160%" height="160%">
|
||||
<feGaussianBlur stdDeviation="4" result="blur" />
|
||||
<feFlood floodColor="#f59e0b" floodOpacity="0.4" result="color" />
|
||||
<feComposite in="color" in2="blur" operator="in" result="glow" />
|
||||
<feMerge>
|
||||
<feMergeNode in="glow" />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<filter
|
||||
id="glowGreen"
|
||||
x="-30%"
|
||||
y="-30%"
|
||||
width="160%"
|
||||
height="160%"
|
||||
>
|
||||
<feGaussianBlur stdDeviation="3" result="blur" />
|
||||
<feFlood floodColor="#10b981" floodOpacity="0.3" result="color" />
|
||||
<feComposite in="color" in2="blur" operator="in" result="glow" />
|
||||
<feMerge>
|
||||
<feMergeNode in="glow" />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
{/* Dependency edges */}
|
||||
{edges.map(({ fromId, toId, x1, y1, x2, y2 }) => {
|
||||
const active = isEdgeActive(fromId, toId, currentStep);
|
||||
const toStatus = getTaskStatus(toId, currentStep);
|
||||
const isBlocked = toStatus === "blocked";
|
||||
let markerEnd = "url(#arrowGray)";
|
||||
let strokeColor = palette.arrowFill;
|
||||
if (active) {
|
||||
markerEnd = "url(#arrowGreen)";
|
||||
strokeColor = "#10b981";
|
||||
} else if (isBlocked) {
|
||||
markerEnd = "url(#arrowRed)";
|
||||
strokeColor = "#ef4444";
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.path
|
||||
key={`${fromId}-${toId}`}
|
||||
d={buildCurvePath(x1, y1, x2, y2)}
|
||||
fill="none"
|
||||
markerEnd={markerEnd}
|
||||
animate={{
|
||||
stroke: strokeColor,
|
||||
strokeWidth: active ? 2.5 : 1.5,
|
||||
strokeDasharray: isBlocked ? "6 4" : "none",
|
||||
}}
|
||||
transition={{ duration: 0.5 }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Task nodes */}
|
||||
{TASKS.map((task) => {
|
||||
const status = getTaskStatus(task.id, currentStep);
|
||||
const colors = getStatusColor(status);
|
||||
const statusLabel = getStatusLabel(status);
|
||||
const isActive = status === "in_progress";
|
||||
const isComplete = status === "completed";
|
||||
|
||||
let filterAttr: string | undefined;
|
||||
if (isActive) filterAttr = "url(#glowAmber)";
|
||||
else if (isComplete) filterAttr = "url(#glowGreen)";
|
||||
|
||||
return (
|
||||
<g key={task.id} filter={filterAttr}>
|
||||
<motion.rect
|
||||
x={task.x}
|
||||
y={task.y}
|
||||
width={NODE_W}
|
||||
height={NODE_H}
|
||||
rx={8}
|
||||
animate={{
|
||||
fill: isDark ? colors.darkFill : colors.fill,
|
||||
stroke: isDark ? colors.darkStroke : colors.stroke,
|
||||
}}
|
||||
strokeWidth={isActive ? 2 : 1.5}
|
||||
transition={{ duration: 0.4 }}
|
||||
/>
|
||||
<text
|
||||
x={task.x + NODE_W / 2}
|
||||
y={task.y + 20}
|
||||
textAnchor="middle"
|
||||
dominantBaseline="middle"
|
||||
fontSize="11"
|
||||
fontWeight="600"
|
||||
fill={isDark ? colors.darkText : colors.text}
|
||||
>
|
||||
{task.label}
|
||||
</text>
|
||||
<text
|
||||
x={task.x + NODE_W / 2}
|
||||
y={task.y + 38}
|
||||
textAnchor="middle"
|
||||
dominantBaseline="middle"
|
||||
fontSize="9"
|
||||
fontFamily="monospace"
|
||||
fill={isDark ? colors.darkText : colors.text}
|
||||
opacity={0.8}
|
||||
>
|
||||
{statusLabel}
|
||||
</text>
|
||||
</g>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Blocked annotation for T4 at step 4 */}
|
||||
{currentStep === 4 && (
|
||||
<motion.g
|
||||
initial={{ opacity: 0, y: 5 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.4 }}
|
||||
>
|
||||
<rect
|
||||
x={445}
|
||||
y={118}
|
||||
width={170}
|
||||
height={22}
|
||||
rx={4}
|
||||
fill={isDark ? "#451a03" : "#fef2f2"}
|
||||
stroke={isDark ? "#dc2626" : "#fca5a5"}
|
||||
strokeWidth={1}
|
||||
/>
|
||||
<text
|
||||
x={530}
|
||||
y={132}
|
||||
textAnchor="middle"
|
||||
dominantBaseline="middle"
|
||||
fontSize="9"
|
||||
fontFamily="monospace"
|
||||
fill={isDark ? "#f87171" : "#dc2626"}
|
||||
>
|
||||
Blocked: waiting on T3
|
||||
</text>
|
||||
</motion.g>
|
||||
)}
|
||||
</svg>
|
||||
|
||||
{/* File persistence indicator */}
|
||||
<div className="mt-3 flex items-center gap-2 rounded-md border border-zinc-200 bg-zinc-50 px-3 py-2 dark:border-zinc-700 dark:bg-zinc-800/60">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
className="h-5 w-5 flex-shrink-0 text-zinc-400 dark:text-zinc-500"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M3.75 9.776c.112-.017.227-.026.344-.026h15.812c.117 0 .232.009.344.026m-16.5 0a2.25 2.25 0 0 0-1.883 2.542l.857 6a2.25 2.25 0 0 0 2.227 1.932H19.05a2.25 2.25 0 0 0 2.227-1.932l.857-6a2.25 2.25 0 0 0-1.883-2.542m-16.5 0V6A2.25 2.25 0 0 1 6 3.75h3.879a1.5 1.5 0 0 1 1.06.44l2.122 2.12a1.5 1.5 0 0 0 1.06.44H18A2.25 2.25 0 0 1 20.25 9v.776"
|
||||
/>
|
||||
</svg>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-mono text-xs font-medium text-zinc-600 dark:text-zinc-300">
|
||||
.tasks/tasks.json
|
||||
</span>
|
||||
<span className="text-[10px] text-zinc-400 dark:text-zinc-500">
|
||||
Persisted to disk -- survives context compaction
|
||||
</span>
|
||||
<div className="mb-4 flex flex-col gap-3 rounded-lg border border-zinc-200 bg-zinc-50 p-3 dark:border-zinc-700 dark:bg-zinc-800/70 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="flex items-center gap-2 text-sm font-semibold text-zinc-800 dark:text-zinc-100">
|
||||
<FileJson size={16} />
|
||||
.tasks board
|
||||
</div>
|
||||
<motion.div
|
||||
className="ml-auto h-2 w-2 rounded-full bg-emerald-500"
|
||||
animate={{ opacity: [1, 0.3, 1] }}
|
||||
transition={{ repeat: Infinity, duration: 2 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Legend */}
|
||||
<div className="mt-3 flex flex-wrap items-center gap-4">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="h-3 w-3 rounded bg-zinc-300 dark:bg-zinc-600" />
|
||||
<span className="text-[10px] text-zinc-500 dark:text-zinc-400">
|
||||
pending
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="h-3 w-3 rounded bg-amber-400 dark:bg-amber-600" />
|
||||
<span className="text-[10px] text-zinc-500 dark:text-zinc-400">
|
||||
in_progress
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="h-3 w-3 rounded bg-emerald-400 dark:bg-emerald-600" />
|
||||
<span className="text-[10px] text-zinc-500 dark:text-zinc-400">
|
||||
completed
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="h-3 w-3 rounded bg-red-400 dark:bg-red-600" />
|
||||
<span className="text-[10px] text-zinc-500 dark:text-zinc-400">
|
||||
blocked
|
||||
</span>
|
||||
<div className="grid grid-cols-4 gap-2 text-center text-xs">
|
||||
<div className="rounded bg-zinc-100 px-2 py-1 dark:bg-zinc-900">{blocked.length} blocked</div>
|
||||
<div className="rounded bg-amber-100 px-2 py-1 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300">{ready.length} ready</div>
|
||||
<div className="rounded bg-blue-100 px-2 py-1 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300">{active.length} active</div>
|
||||
<div className="rounded bg-emerald-100 px-2 py-1 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300">{done.length} done</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 lg:grid-cols-4">
|
||||
<Lane title="Waiting" subtitle="blocked by another card" tasks={blocked} />
|
||||
<Lane title="Ready" subtitle="can be claimed now" tasks={ready} />
|
||||
<Lane title="Working" subtitle="currently in progress" tasks={active} />
|
||||
<Lane title="Done" subtitle="unlocks dependents" tasks={done} />
|
||||
</div>
|
||||
|
||||
<div className="mt-4 rounded-md border border-blue-200 bg-blue-50 px-3 py-2 text-xs leading-relaxed text-blue-800 dark:border-blue-900 dark:bg-blue-950/30 dark:text-blue-200">
|
||||
A dependency is not an arrow students must trace. It is a visible blocker badge on the card.
|
||||
</div>
|
||||
|
||||
<StepControls
|
||||
className="mt-4"
|
||||
currentStep={vis.currentStep}
|
||||
totalSteps={vis.totalSteps}
|
||||
onPrev={vis.prev}
|
||||
onNext={vis.next}
|
||||
onReset={vis.reset}
|
||||
isPlaying={vis.isPlaying}
|
||||
onToggleAutoPlay={vis.toggleAutoPlay}
|
||||
stepTitle={current.title}
|
||||
stepDescription={current.desc}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<StepControls
|
||||
currentStep={currentStep}
|
||||
totalSteps={totalSteps}
|
||||
onPrev={prev}
|
||||
onNext={next}
|
||||
onReset={reset}
|
||||
isPlaying={isPlaying}
|
||||
onToggleAutoPlay={toggleAutoPlay}
|
||||
stepTitle={stepInfo.title}
|
||||
stepDescription={stepInfo.description}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||