OMP agent loop:為什麼需要兩層 while?外層的「停了就再被 steering 打醒」在做什麼
omp 的 runLoopBody 用雙層 while:內層跑 model call → tool call 的核心節奏;外層在 agent 本想停下時,排空 queued steering / follow-up / asides,決定要不要再跑一輪。這設計解決了「使用者在 model 跑時打字」與「背景任務悄悄塞訊息」的交付時機問題。
逐段讀 oh-my-pi(OMP)原始碼:streaming、rulebook、slash/custom tools、memory 與 task hub 等內部設計。
omp 的 runLoopBody 用雙層 while:內層跑 model call → tool call 的核心節奏;外層在 agent 本想停下時,排空 queued steering / follow-up / asides,決定要不要再跑一輪。這設計解決了「使用者在 model 跑時打字」與「背景任務悄悄塞訊息」的交付時機問題。
omp 用 StablePrefix 凍結 system prompt + tool specs,用 AppendOnlyLog 讓 messages 只增不改,配合 digest-based 的 longestStablePrefix 算法,在 prune/shake/steering 重寫歷史時,只重送 divergence point 之後的尾巴。這讓 Anthropic/DeepSeek 的 prompt cache 命中率最大化,解決了舊版每輪強制 ~40k token re-prefill 的問題(issue #3406)。
omp 不只有一種 compaction:context-full 走 LLM 摘要、可疊代、失敗對半重切預算;snapcompact 不呼叫 LLM,把歷史壓成 PNG 讓 vision model 讀,解決無 API key / 低延遲 / 視覺模型便宜場景;branch summary 在 `/tree` 切分支時摘要被離開的段落;shake 純機械式把 tool-result 大段文字換成 placeholder,給 summary 太重、prune 不夠的緊急手動場景。四種策略分工明確,由 session maintenance 自動編排或使用者手動觸發。
omp 的審批解析器 resolveApproval 按「工具宣告 → 使用者覆寫 → 模式門檻」三層決策。未宣告 approval、或格式錯誤的工具,預設降級為 exec(fail-closed)。三層分工:工具自己宣告 tier + 可選 policy/override/reason;使用者用 tools.approval.<tool> 覆寫;模式(always-ask/write/yolo)決定自動通過哪些 tier。關鍵鐵律:tool-side deny 與 user-side deny 永遠不可被模式跨越;yolo 中 override: true 不會強迫 prompt,但 policy: deny 仍生效。
omp bash 工具的審批引擎把命令用共享 shell tokenizer 切成段(依 `;` `&&` `||` `|` `&` newline、subshell),deny/prompt 規則對**每段**分別匹配 glob,任一段命中即觸發;allow 規則要求**整行匹配**且**無 shell control syntax**,防止 `cd x && rm -rf /` 此類惡意段溜過去。CRITICAL_BASH_PATTERNS 硬編碼 45 個危險命令正則(`rm -rf /`、`chmod -R 777 /`、`curl | bash`、`kill -9 1` 等),優先於使用者 pattern 生效。設計權衡:allow 嚴格是為了安全,deny/prompt 寬鬆是為了可用性。
OMP 用 hashline 格式取代傳統 line-number patch:以 4-hex content hash + N* syntactic block locator 定位,消除 whitespace drift;noop-loop-guard 在同一 session、同一 canonical path、同一 input hash 連續 3 次 no-op 時直接拋 ToolError,打破模型「以為 anchor 錯、把 payload 變大再試」的 182/205 次重試死循環(issue #2081)。
OMP 把 60+ 個 provider 的 routing、compat、thinking、quota 等政策全部寫在 KDL(taxonomy/classes/providers/runtime),編譯成 rules.json 再由 runtime engine 解析。這樣做的核心理由:分層所有權、編譯期驗證、規則優先級解決——三件事若用 TS 硬編碼會散在各處、難以驗證、優先級靠人眼。
OMP 把所有 provider 特有的 wire 行為寫進 KDL 規則樹,靜態編譯成 JSON 再由 cascade resolver 套用,避免 TS 程式碼被無數 if-else 污染,並能在 CI 捕捉衝突。
omp 用 append-only JSONL 存 session,entry 帶 id/parentId 組成 tree,leaf pointer 決定 active path。/tree 用 TreeSelectorComponent 導航,navigateTree() 切 leaf 時可選擇摘要被離開的分支(branch_summary)、自動處理 checkpoint/rewind、支援 Claude/Codex foreign session import。fork 複製整個 session 檔並繼承 providerPromptCacheKey,resume/switchSession 以 captureState/rollback 保證原子切換。
OMP 將 hooks、skills、MCP、marketplace 整合為統一的擴展面:hooks 併入 extension runner 統一事件匯流排、skills 依 description 進行語意觸發、MCP 採 250ms 快速啟動閘 + deferred fallback、marketplace 採雙 scope 並相容 Claude Code catalog 格式。
OMP 自建 TUI 引擎而非用 React/Ink,核心是 differential rendering(只重繪變化行)、explicit history contract、composer 多模輸入與 keybindings 系統;本文從原始碼層面解析其架構決策與實作細節。
OMP 將效能敏感、正確性要求高、需確定性的子系統(grep、AST、PTY、隔離、檔案走訪)下沉到 6 個 Rust crate,再透過 pi-natives 統一暴露 N-API 介面;binding 契約由 napi-rs 自動生成 TS 宣告,再經 gen-enums.ts 產出 runtime enum 物件與顯式 ESM exports。
omp collab 以 host 為權威、guest 從不互聯的 hub 拓撲,透過 AES-256-GCM 封裝 JSON frame、4-byte envelope、snapshot-chunk 分片,實現零中繼可見的即時協作;guest 權限靠 16-byte write token 在 link 內綁定,host 用 timing-safe comparison 驗證。
OMP 的 metaharness 不是單純跑分工具,而是為了在硬體隔離的 microVM 裡、統一 auth gateway、可對照 baseline 的實驗級基礎設施。
14 篇拆完,回到總覽:append-only context、compaction 分工、審批三層、KDL rule tree、session tree 是最值得借鏡的五件;snapcompact、metaharness 自製基建屬於過度工程;looplane 短期不該自建完整 provider catalog、完整 TUI、完整 collab。兩者哲學差異:omp = batteries-included in-process,looplane = minimal + 外部 runtime。
OMP 的 Agent stream 不只是把 token 往終端機吐:它把 agent、turn、message、tool execution 分成不同層級的事件。理解這個事件契約,才能在 UI 顯示增量文字、工具進度與錯誤,同時不把暫存中的 partial message 誤當成已提交的對話。