跳到內容

開發

npm run check 對擴充功能和頁面做型別檢查,npm test 跑測試套件。頁面是 gui/ 裡的純 TypeScript,由 Vite 建置到 dist/gui;側邊欄外掛是 herdr-plugin/ 裡的純 JavaScript;提示詞是 prompts/ 裡的純 markdown。

終端機視窗
npm install
npm run check # tsc --noEmit for the extension and for the page
npm run gui:build # builds the page into dist/gui (npm test and npm pack do this first)
npm run build:server # bundles the sb server into dist/server (npm pack does this; the build fails on a value import of pi's packages)
npm run server -- status # runs src/server/cli.ts from the checkout through tsx
npm test # node --test, against a fake Herdr and a fake intercom broker, in a temp home of its own per test process (tests/setup.ts)
npm run test:one -- tests/x.test.ts # one file, isolated the same way
npm run gui:dev # the page with hot reload against a demo net; see below
細節

儀表板有它自己的檔案(src/dashboard.ts,預算 162 行),它的渲染是快照的純函式,所以測試不需要終端機就能驅動它。它不畫出來就顯示的東西(標記、列,以及子智慧體的讀法)在 src/netdata.ts 裡,它不含對 pi-tui、typebox 或 pi-coding-agent 的任何值匯入,好讓 server 能載入它;tests/pure-imports.test.ts 走訪匯入圖,並在遇到一個時失敗。瀏覽器檢視的資料與 server(src/net.ts、src/gui.ts)共用 300 行的預算;buildNet 把 session、pane 與工作區變成 JSON 快照,是純函式(並填入可讀 session 檔案的登錄表),而 collectNet 讀取 Herdr 與 intercom,並重用 src/netdata.ts 的子智慧體連結。session 讀取器(src/history.ts)、項目對應(src/items.ts)以及串流與 API 的黏合層(src/watch.ts)以 fixture 檔案測試。

頁面是 gui/ 裡的 vanilla TypeScript,由 Vite(僅為開發相依套件)建置到 dist/gui,隨 npm 套件出貨;dist/ 不提交。頁面依元素 id 比對 DOM,用 transform 與 opacity 上的 CSS 做動畫(地圖的封包是沿著每條線路徑的 transform keyframes,gui/headband.ts 裡的 routePackets;gui/calm.ts 讓不會停的那些休息),而它的重新連線邏輯(gui/stream.ts)以假的串流與假的時鐘測試。地圖的 chunk 包含地圖、標頭、路由器與警示偵測(gui/alerts.ts)。頁面的訊息是 Paraglide 的(gui/messages/<locale>.json,由 npm run gui:i18n 編譯到被忽略的 gui/paraglide/,check、gui:build、gui:dev 與 gui:demo 會先執行它)。

頁面檔案從 gui/sentences.ts 匯入它的 m,絕不從 Paraglide:編譯步驟之後接著 scripts/gui-sentences.mjs,它寫出 gui/paraglide/said/(每則訊息一個模組,所以 tree shaking 不變),而被某個主題的句子包(gui/themes/<view>/sentences.ts)指名的訊息,在該主題顯示時用句子包的用詞說(鴉閣的 zh-TW 句子包在標準說塔台與主塔台的地方說管家與鴉閣,在標準說主智慧體與智慧體的地方,對主智慧體說血僕、對一般智慧體說眷屬;tests/raven-words.test.ts)。主題句子包裡的新訊息不需要其他步驟:下一次 gui:i18n(執行中的 gui:dev 要重啟)就會包好它。

焦點檢視(gui/views.ts 協調 gui/workspace.ts、gui/session.ts 與 gui/dossier.ts)、帶 markdown 渲染器的通訊記錄(gui/chat.ts、gui/markdown.ts),以及覆蓋層的 DOM 與圖磚(gui/layer.ts)在第一次使用時載入。覆蓋層規則(對話框堆疊的 gui/overlay.ts、gui/layer.ts 裡的 createTiles)是純函式,不用瀏覽器就能測試(tests/overlay.test.ts);第 2 與第 3 階段的對話框(ask_user、robot_hand、secret_drop)與 show_doc 文件(gui/doc.ts,它的規則在 tests/doc-page.test.ts 測試)插入同一個堆疊與圖磚。大小預算由 tests/imports.test.ts 檢查:地圖的 chunk ≤ 15 KB(gzip 後 6 KB),延遲載入的 chunk 合計 ≤ 35 KB(12 KB),樣式表 ≤ 22.1 KB(6.1 KB)。

側邊欄外掛是 herdr-plugin/ 裡的純 JavaScript,不從 src/ 匯入任何東西,所以不論 Herdr 在哪裡連結或安裝它,這個資料夾都能運作。tests/netview.test.ts 對一個保有 token 與唯一作用中檢視的假 Herdr,以及一個真實的 Unix socket 驅動它。herdr-reaper/ 裡的 reaper 外掛以同樣的方式建成:它的決定(decide.mjs)是純函式,它的執行(sweep.mjs)以 Herdr、git、狀態儲存與時鐘作為引數,而 tests/reaper.test.ts 對假物件執行它們。

npm run gui:dev 在本機連接埠上以熱重載提供頁面,由一個用虛構名稱、每隔幾秒變動狀態的示範網供應資料。示範包含一個帶有每種聊天項目的 session(開啟任何單位),而 fixture 的工具列(左下)有 drop stream、go silent(沒有訊息、沒有錯誤:45 秒的卡住偵測)、restore,用來檢視斷線的頁面,以及 doc arrives,它讓 billing-main 多顯示一份文件:在它的通訊畫面上它開成一個圖磚,在別處它的徽章往上數。billing-main 列出一份 markdown 計畫與一份 HTML 審閱,後者的表單在示範裡不 post 到任何地方。

要改成把開發頁面指向存活的串流,執行 /boss gui,並以它的 URL 啟動開發 server:GUI_LIVE=http://127.0.0.1:<port>/<token>/ npm run gui:dev。

要在真實的 pi 裡檢查一個 checkout,同時你自己的 sb server 仍在執行(每個狀態資料夾一個),用 --no-extensions 啟動一個暫用的 pi,用 -e 載入 pi-intercom 與你的 provider,再用 -e 載入一個兩行的包裝,它呼叫這個 checkout 的 createStrawBoss({ stateDir: "<scratch dir>", openUrl: async () => {} }),並讓 PI_CODING_AGENT_DIR 與 HOME 指向暫用資料夾,以及一個暫用的 Herdr。它的 /boss gui 於是從這個 checkout 啟動第二個 sb server,記錄在暫用資料夾裡,而且不開啟瀏覽器。

prompt 是 prompts/ 裡單純的 markdown,在 session 啟動時讀取,所以編輯在 /reload 之後生效。