跳到主要內容

用 AI 寫程式的痛:我們做了兩個小工具來解決

用 AI 寫程式最大的問題是什麼?對我們來說,不是模型不夠聰明,而是 不放心 。 LLM token 越來越貴,但大部分都在重複看已經知道的程式碼結構。 Agent 改完程式編譯不過,要來回好幾輪才修好。 工作到一半 context 滿了,重開 session 什麼都不記得了。 有時候改壞了檔案還沒人知道。 這些問題大概不是只有我們遇到。我們的做法是寫兩個小工具來補,一個管 輸入成本 ,一個管 操作安全 。兩者透過 MCP 協定接進 OpenCode,各自只做一件事。 工具一:GraphifyRust — 讓 LLM 不用重看整包程式碼 GraphifyRust 是用 Rust 寫的靜態分析引擎。用 Tree-sitter 解析原始碼,把 function、struct、trait 這些節點抽出來,建成一個有向圖。 AI agent 要改程式時,傳統做法是把整支檔案丟給 LLM。幾百行的檔案可能只有幾段 function 相關,但 LLM 還是得看完所有 import、註解、不相干的邏輯。 Graphify 的 skeleton_extract 只回傳 AST 骨架 — function 名稱、行號、簽名。實際壓縮效果: 檔案 原始 token 骨架 token 節省比例 server.go (BloggerAgent MCP) 1,289 117 90.9% toon.rs (Graphify 核心) 2,132 147 93.1% 骨架不夠用時,用 range mode 精準讀取特定 function。不需要整包丟進去。 選 Rust 的理由很務實:Tree-sitter 的 Rust binding 最成熟。在 110 個檔案、422 條邊的測試專案上,建圖只要 16ms ,比之前 Python 版快 26 倍。節點用 petgraph arena 預分配,減少 heap 碎片。輸出用自訂的 .toon 格式,體積比 JSON 少 60%。 語意搜尋用本機 Qdrant,沒有雲端費用。目前支援 9 種語言:Rust、Python、Go、JavaScript、TypeScript、C、C++、Java、PHP、Swift。 工具二:StateMachineMcp — 永遠不讓壞掉的程...

用 AI 寫程式的痛:我們做了兩個小工具來解決

用 AI 寫程式最大的問題是什麼?對我們來說,不是模型不夠聰明,而是不放心

LLM token 越來越貴,但大部分都在重複看已經知道的程式碼結構。 Agent 改完程式編譯不過,要來回好幾輪才修好。 工作到一半 context 滿了,重開 session 什麼都不記得了。 有時候改壞了檔案還沒人知道。

這些問題大概不是只有我們遇到。我們的做法是寫兩個小工具來補,一個管輸入成本,一個管操作安全。兩者透過 MCP 協定接進 OpenCode,各自只做一件事。

工具一:GraphifyRust — 讓 LLM 不用重看整包程式碼

GraphifyRust 是用 Rust 寫的靜態分析引擎。用 Tree-sitter 解析原始碼,把 function、struct、trait 這些節點抽出來,建成一個有向圖。

AI agent 要改程式時,傳統做法是把整支檔案丟給 LLM。幾百行的檔案可能只有幾段 function 相關,但 LLM 還是得看完所有 import、註解、不相干的邏輯。

Graphify 的 skeleton_extract 只回傳 AST 骨架 — function 名稱、行號、簽名。實際壓縮效果:

檔案 原始 token 骨架 token 節省比例
server.go (BloggerAgent MCP) 1,289 117 90.9%
toon.rs (Graphify 核心) 2,132 147 93.1%

骨架不夠用時,用 range mode 精準讀取特定 function。不需要整包丟進去。

選 Rust 的理由很務實:Tree-sitter 的 Rust binding 最成熟。在 110 個檔案、422 條邊的測試專案上,建圖只要 16ms,比之前 Python 版快 26 倍。節點用 petgraph arena 預分配,減少 heap 碎片。輸出用自訂的 .toon 格式,體積比 JSON 少 60%。

語意搜尋用本機 Qdrant,沒有雲端費用。目前支援 9 種語言:Rust、Python、Go、JavaScript、TypeScript、C、C++、Java、PHP、Swift。

工具二:StateMachineMcp — 永遠不讓壞掉的程式碼進硬碟

StateMachineMcp 是用 Go 寫的 MCP server,概念上就是一個安全閘門:Agent 想改程式碼,必須先通過狀態機檢查。

Phase Gate

每次任務有四個階段:初始化 → 規劃 → 執行 → 驗證 → 完成。執行階段才能改程式碼,規劃階段呼叫 apply_patch 會被擋掉。連續三次改失敗會自動暫停,等人來看。

Double Buffer + Compiler Verify

機制很簡單但很有效:

  1. Agent 送出 patch(精準搜尋區塊 + 取代區塊)。
  2. Patch 先寫到 /tmp/ 的 staging 副本,原始檔案不動。
  3. 自動跑 cargo checktsc --noEmitgo vet
  4. 通過才寫進硬碟,建立 checkpoint。
  5. 失敗就丟掉 staging,原始檔案完好如初。

壞掉的程式碼永遠不會進到檔案系統。聽起來很基本,但沒有這個機制之前,我們被 Agent 改壞過好幾次。

Checkpoint Resume

.opencode/state.json 記錄每次 checkpoint:在哪個階段、改了哪些檔案、compiler 結果。context 滿了要重開 session 時,新 session 載入這個檔案就可以從中斷的地方繼續,不用重跑。

跟 DeepSeek Harness 的關係

後來看到 DeepSeek Harness 的論文,發現他們提出的架構概念跟我們遇到的問題幾乎一樣:

Harness 概念 我們的解法
Session Log(事件溯源) .opencode/state.json checkpoint log
Code Mode(批次工具呼叫) apply_patch + compiler verify
Plugin 系統 MCP 協定
可觀測性 skeleton_extract 90%+ token 壓縮

我們不是先有架構再寫工具,是先有痛才做工具,然後發現這些工具剛好可以拼成一個架構。

Session Log 與長期記憶

Harness 論文把記憶分成兩層,這個區分我們也是實作後才體會到:

  • Session Log:單次任務的執行軌跡。短暫、用完就丟。StateMachineMcp 的 state.json 負責。
  • Vault Memory:跨 session 的持久知識。專案規則、架構決策、設定值。OpenCode 的 ctx_memory 負責。

兩者不能互相取代。Session log 讓任務內可恢復,vault memory 讓任務之間有連續性。

實際成本

這組工具跑在每月約 $10 的 BytePlus 方案上,加上一台有 GPU 的本機機器做 embedding。成本控制的關鍵:

  1. 輸入壓縮:Graphify 把 AST token 減少 90%+。
  2. 本機驗證:StateMachineMcp 攔截編譯錯誤,不用 LLM 來修語法問題。
  3. Checkpoint resume:從 checkpoint 繼續,不重跑。

$10 是實際月費,不是理論上限。

原始碼

兩套工具都放在 GitHub 上,MIT 授權:

如果這些問題你也有遇到,歡迎拿去用,或給我們 feedback。

留言

這個網誌中的熱門文章

有點誇張的準專業機.Minolta Alpha 7 (Dynax 7、Maxxum 7).2000

題外話,去年幫朋友標了這台,遲遲未寫一篇介紹,其實是有私心的,好東西少一點人知道比較不會搶。 上個禮拜因為自己要 幫朋友拍攝一場婚禮 ,無巧不巧原本服役的 707si 掛了,於是跟朋友商借了 Alpha 7 來拍,拍過之後就一直放在身邊,說實在的有點捨不得還,快門聲,手感,強大的性能,實在是有點誇張。 拿 Alpha 7 拍我女兒的時候,因為有 LCD,我女兒會說我要看,而不是問我 把拔這台是底片的嗎 ?讓我解釋半天她也不相信,直指著 LCD 要看照片,很妙,但是個識貨的女孩,一眼就看出這台相機的特點,機背有 LCD。 於 1998 年推出頂級機 Alpha 9 之後,2000 年推出的 Alpha 7 除了快門速度和連拍速度緊挨著機皇而沒有強過頭,卻在準專業定位的 Alpha 7 身上加入多項先進的功能,其中許多 Alpha 9 所沒有的,相當驚人,整理於下: ※ 全新開發之 CDC912 對焦系統,九點寬域對焦,排列為黃金矩陣 ,宣稱為世界首快之 AF 對焦;機背轉盤可選擇對焦點並直接對焦。(Alpha 9 為三點寬域自動對焦) ※ 首見機背大型點矩陣式 LCD 大幅增加人機溝通性能,若採垂直控制拍攝時LCD會隨之轉為垂直。 ※ DMF (Direct Manual Focus) 功能 :透過機身可讓鏡頭全時手動,無須撥動AF/MF鈕 ※ 世界首見 STF (Smooth TransFocus) 特效 ,可使每支鏡頭作出特殊背景鬆濛感,類似Minolta STF 135mm f/2.8[T4.5]的效果 (作用原理:相機自動切換為多重曝光,並於曝光時逐漸縮小光圈葉片)。[Custom 3] ※搭配新一代納入距離編碼器的鏡頭時,Alpha 7 可採 ADI (Advanced Distance Intergration) 測光模式 ,或配合 TTL 4 區閃燈測光。 ※一推出即支援 SAM 超音波馬達鏡頭。(Alpha 9 需要更新韌體) 功能很多很強大,底下就先挑一些比較有意思的設計做介紹。 》十四區蜂巢式測光,LCD 顯示 當同時按下 AE 曝光鎖 (AEL) 與 LCD 顯示選擇鍵 (DISP) 時,會顯示 14 區各分區的相對EV值,與灰色部份比較,白色的為正值,黑色的為負值,以上圖為例,畫面最暗的地方是 –2.3,最亮的地方是 ...

[古典相機] M 系列快門最速.ME MX 合體.Pentax ME Super.1980

Pentax M 系列機身中,快門速度達到 1/2000 秒的,就只有 ME Super 以及需搭配特殊鏡頭 AF 35-70 f2.8 自動對焦的 ME-F 。 為什麼要說 ME Super 是 MX 以及 ME 的合體呢? MX 是只有曝光手動控制, ME 是只有光圈先決,另有幾台 M 系列 1980 年代出的 MG、MV、MV1,也都只有提供光圈先決,除了改變 EV 值外,沒辦法手動調整快門速度,ME Super 是整個 M 系列機身第一台同時可以手動設定快門也能 Auto 快門的機身,或許是因為希望機身維持像 ME 一樣小,所以在快門設定的功能上,並不像其他家是用機頂轉盤的方式 (OM-2 是用機身接環前的轉環),Pentax ME Super 的快門設定是機頂上的兩個鈕,只能在觀景窗內,透過 LED 指示燈顯示所選用的快門速度,同時也會顯示是否 Over 或者 Under。 機身的設計與 ME 幾乎相同,除了機頂右邊的轉盤處加了兩個手動設定快門速度的鈕,其他都相同,寬度和高度就比 ME 多了一點點,真的只有一點點,就各多個 0.5mm,但重量卻比 ME 更輕,猜想是使用了更輕量的機身結構吧,而可搭配的捲片馬達手把也能通用 (ME、ME II)。 MX 與 ME、ME Super 之比較》 機型 生產 體積 (mm) 重量 快門速度 閃燈同步快門 MX 1976-1985 135.8 x 82.5 x 49.3 495g 1 ~ 1/1000, B 1/60 ~ 1, B ME 1976-1980 131 x 82.5 x 49.5 460g 8 ~ 1/1000, B 1/100 ~ 8, B ME Super 1980-1987 131.5 x 83 x 49.5 445g 4 ~ 1/2000, B 1/125 ~ 4, B ...

Nikon D7000 的感光元件 Sony 做的,官方不公開承認,chipworks 拆給你看!

(圖片來源: Teardown of the Nikon D7000 DSLR by chipworks ) Sony IMX071 The Nikon D7000 comes equipped with a DX format (APS-C) sensor fabricated by Sony, the IMX071. With a 16.2 Mp resolution, this is the second highest resolution of any Nikon DSLR, behind the 24 Mp D3X (dpreview.com). This image sensor features a pixel size of 4.8 µm x 4.8 µm (as seen in the Bayer patterned RGB color filters). The sensor displays improvements in pixel layout and process features, as compared to previous generations of Sony DSLR sensors. 有圖有真相,完整拆解請直上: Teardown of the Nikon D7000 DSLR by chipworks