iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0
AI 自動化

用 AI Agent 打造你的產品使用手冊產線系列 第 27 篇

[Day 27] 把產線包成 npm 套件

  • 分享至 

  • xImage
  •  

老實說,一開始我覺得範例專案原本的架構就夠用了:runner、manifest、正文、被拍的 Demo App 全部放在同一個 repo,指令也都是 npm run manual 這種只在範例專案裡才有意義的寫法,反正能跑就好。

但從 i18n 名稱比對、多語同步,一路做到影片與 App 內導覽,中間改了不少東西,很多「只有 Demo App 才成立」的假設也跟著越積越多。後來再想了想,既然最終目標是讓別的產品也能用這條產線,最自然的形式就是包成一個 npm package,讓別人 npm install 就能用。要做到這件事,原本的架構就得調整。

所以最後這組番外篇來處理發布。今天先把工具從專案裡抽出來,變成一個 CLI:auto-manual-gen;接下來兩天,再把「怎麼用它」的知識打包成 Claude Code plugin。

這篇同時也是一份使用說明。如果你是直接跳到這一篇,搭配範例專案應該就能知道這條產線能做什麼、該怎麼用,細節則可以回頭翻對應的那一天。

為什麼要重構

要包成套件,原本的架構有幾個地方過不去:

問題 重構後
所有路徑都以 runner 這支檔案為基準,一旦被裝進 node_modules/,就會在錯的資料夾裡找 manifest 使用者的檔案從目前目錄往上找 manual.yaml;工具自己附帶的檔案 (腳本、樣式、schema) 則以套件位置為基準
跟產品有關的東西散在程式碼與 config.json 裡,有些甚至寫死成 Demo App 的檔名 全部集中到 manual.yaml,套件的程式碼裡不再出現任何 Demo App 的檔名
怎麼啟動 App 是寫死的 沿用 Day 07 的 AppDriver,內建 Electron 與 Web,其他情況讓使用者自己寫 driver
失敗一律 process.exit(1),CI 與 agent 分不出是誰的問題 exit code 分成內容、用法、環境三種,每個指令都支援 --json
Word 轉 PDF、TTS 只能在 Windows 上跑,發布後就會變成「在 macOS 上壞掉」的 issue 當成選用能力,缺了只在用到時失敗,由 doctor 回報

重構後的範例專案還是同一個 repo,但裡面分成了兩部分:

auto-manual-gen/
├── packages/auto-manual-gen/   # 產線本體,就是發布到 npm 的那個套件
├── manual.yaml                 # ← 以下是「一個使用 auto-manual-gen 的手冊專案」
├── manifest/  docs/  agent/  templates/
└── apps/demo-stream-app/       # 被拍的 Demo App

範例專案透過 npm workspace 依賴 auto-manual-gen,用法跟別人 npm install -D auto-manual-gen 完全一樣,原本的 npm run manual 也還在,只是現在轉給的是 auto-manual-gen run。

要特別說明的是,Demo App 依然留在 repo 裡,沒有拆出去。這純粹是為了 demo 方便:clone 下來就有東西可以拍,不用另外準備一個 App。實際用在自己的產品上時,結構會剛好反過來,下一節會看到。

手上已經有產品,怎麼用?

假設你手上已經有一個產品 (Web 或 Electron),想幫它做一本手冊,該怎麼做?

讓我們先看一下整體是怎麼運作的,安裝的部分先跳過,後面再說明。

三個角色

這條產線裡有三個角色,各自負責不同的事:

  • CLI 負責「做」:開 App、照 manifest 操作、截圖畫框、產出 Word / PDF / 影片。同一份 manifest,誰跑結果都一樣。
  • agent 負責「寫」:manifest 與正文。它用 CLI 探勘畫面、驗證、試跑,看錯誤訊息自己修。
  • 人負責「決定」與「確認」:手冊要寫什麼、提供產品知識、確認最後拍出來的東西對不對。

整個流程如下:

有幾個地方要特別說明:

  • 前提是 App 要有 data-testid。這條產線的每一步都靠 testid 定位,CLI 沒辦法替你的 App 加上去。不過不需要一開始就全部補齊,第 3 步寫到哪一章,probe 發現缺了哪個,agent 再補哪個就好。因為這是在改產品程式碼,第 4 步一定要經過 review。
  • 第 2 步決定手冊寫得好不好。功能的正式名稱、哪個畫面要先登入、哪個元件會延遲出現,這些都是產品知識。agent 可以先起草,但只有人能確認對不對。
  • run 成功不代表拍對了。它只保證流程跑得通,畫面對不對、框有沒有框在對的元件上、有沒有拍到敏感資料,都要人看過。比起逐行讀 manifest,把時間花在截圖與正文上更值得,格式上的錯誤 validate 已經擋掉大部分了。
  • 第 6 步是長期最省力的地方。UI 改版改到 testid,CI 的 run 會失敗,--json 的錯誤裡已經附上候選的 testid,agent 拿它去修,人只要 review 那個 PR。

專案架構

手冊專案建議直接放在產品 repo 的子目錄 (e.g. manual/)。manifest 依賴的是產品的 testid,UI 跟 manifest 放在一起,才能在同一個 PR 裡一起改、一起在 CI 驗證,不會等到下次有人跑手冊才發現壞掉:

my-electron-app/
├── package.json          # devDependencies 加上 auto-manual-gen、playwright
├── src/ ...              # 產品本身,元件上有 data-testid
└── manual/               # 手冊專案,manual.yaml 在哪,根目錄就在哪
    ├── manual.yaml       # 專案共用的設定,進版控
    ├── config.json       # 個人設定,不進版控
    ├── manifest/         # 操作步驟 (agent 寫、人 review)
    ├── docs/             # 正文 (agent 寫、人 review)
    └── screenshots/  output/   # CLI 產出,不進版控

跟範例專案剛好相反:範例專案是手冊專案在最外層、App 在 apps/ 底下;真實產品則是 App 在最外層,手冊專案縮進子目錄。

CLI 是從目前目錄往上找 manual.yaml,所以指令要在 manual/ 裡執行。可以在產品的 package.json 包一層 "manual": "cd manual && auto-manual-gen",之後在根目錄用 npm run manual -- run 就好。

manual.yaml:跟產品有關的都在這裡

manual.yaml 原本就存在 (Day 14 的 profile 與 bootstrap),現在它多了一個身分:它在哪裡,手冊專案的根目錄就在哪裡。以上面的結構為例,大概會長這樣:

# yaml-language-server: $schema=../node_modules/auto-manual-gen/schema/v1/manual.json
profile: my-electron-app
title: { zh-Hant: MyApp 使用手冊, en: MyApp User Manual }
version: 'v1.0.0'
locales: [zh-Hant, en]

bootstrap:
  viewport: { width: 1600, height: 900, deviceScaleFactor: 2 }
  localeKey: locale     # App 從哪個 localStorage key 讀語言
  ready: app-root       # 這個 testid 出現才算開機完成
  clock: '2025-09-01T09:00:00'
  disableAnimations: true

app:
  mode: electron
  electron: { projectDir: .., build: npm run build }

text:
  messages: ../src/renderer/locales/{locale}.json
tour:
  output: ../src/renderer/help/tours.json

所有路徑都以 manual.yaml 所在的目錄為基準。config.json 則是一人一份,只能覆寫 app,例如自己機器上的 dev server 剛好開在別的 port。

如果 App 的啟動方式比較特別 (e.g. 要先登入 SSO、要先用 docker compose 把後端跑起來),可以改用 mode: custom,指向自己寫的 driver:

app:
  mode: custom
  custom: { driver: ./driver.mjs }

driver 模組只要 default export 一個回傳 AppDriver 的函式就好,套件也有匯出內建的 WebDriver、ElectronDriver,可以包一層再用。

開頭那行 yaml-language-server 指向套件裡附帶的 schema (路徑相對於這個檔案,manual/ 往上一層才是 node_modules/),有裝 YAML 擴充套件的 VS Code 就會即時補全、把錯的欄位標紅;manifest 也一樣,換成 schema/v1/manifest.json 就好。validate 用的是同一份 schema,不會有「編輯器說對、validate 說錯」的情況。

指令一覽

用到的就是這個系列一路做過來的那些事,只是現在每一件都是一個指令:

指令 做什麼 詳見
probe 列出畫面上可見且有 data-testid 的元件,寫 manifest 前先探勘 Day 16–17
validate 不開瀏覽器,驗證 manifest 與正文 (引用、保護區、名稱出處) Day 16、19
run 依 manifest 驅動 App、截圖、畫框標號;一章一次開機,可以只重跑一章 Day 08–15
build 合併正文與截圖,產出 Word / HTML / PDF Day 20–21
sync 主語言改了哪幾段、譯文要重翻哪幾段 Day 22–23
video 同一份 manifest 錄成附字幕、旁白的教學影片 Day 24–25
tour 同一份 manifest 轉成 App 內導覽 Day 26
init / doctor 建立骨架 / 檢查環境 下一節

每個欄位、每個動詞的說明都整理在套件的 README,那份文件明天也會直接變成 agent 的上下文。

agent 光靠 README 與 --help 就能呼叫這些指令;但要寫出好的手冊,還需要工作流程、寫作規範與產品知識,這些 README 裡沒有。怎麼把它們打包給 agent,是明天 plugin 的主題。

怎麼安裝

第一次導入時,先在產品 repo 裡建立 manual/,接著在 App 跑起來的狀態下:

npm install -D auto-manual-gen playwright
npx playwright install chromium

npx auto-manual-gen init --url http://localhost:5173
npx auto-manual-gen run

這裡假設套件已經在 registry 上;如果同事給你的是打包好的 .tgz,把 auto-manual-gen 換成檔案路徑就好,最後一節會說明。

init 會在目前的目錄產生一份最小可跑的骨架:manual.yaml、config.example.json、一章只截首頁一張圖的 manifest/10-overview.yaml 與對應的正文,並把 screenshots/、output/、*.webm、*.mp4 補進 .gitignore。接著跑 run,就能拿到 screenshots/zh-Hant/overview-01.png。

如果要拍的是 Electron,改用 --mode electron,並用 --app-dir 指向 App 的目錄 (有 package.json 與 main 的那一層):

npx auto-manual-gen init --mode electron --app-dir ..

產生的 manual.yaml 會是 projectDir: ..,並預設在開機前先跑一次 npm run build,手冊要拍的是打包後的樣子。

如果跑不起來,或是換到同事的電腦上,可以先跑一次 npx auto-manual-gen doctor。它會列出 Node、Playwright、Chromium 這些必要的東西有沒有裝好,以及 pandoc、ffmpeg 這類選用工具缺了哪些、會影響哪個指令。

注意 init 不會產生 UI-MAP.md、QUIRKS.md。那些是產品本身的知識,沒辦法事先寫好,也就是流程第 2 步要人補上的部分,明天會再提到。

打包與分享

前面的安裝指令,都假設 npm install auto-manual-gen 裝得到東西。但這條產線不一定要上架到公開的 npm,更常見的情況是:在公司裡做好了,想 甩鍋 交接給別人,或是讓別人也可以自己使用。

打包

在套件的目錄裡先編譯,再打包:

cd packages/auto-manual-gen
npm run build
npm pack

npm pack 會產出一個 auto-manual-gen-0.1.0.tgz,這就是 npm publish 實際上傳的那個檔案。不管最後要不要上架,打包出來的東西都是同一份。

分享

方法一:直接給 .tgz。最簡單,不需要任何基礎設施。建議把檔案放進產品 repo (e.g. vendor/),再從路徑安裝:

npm install -D ./vendor/auto-manual-gen-0.1.0.tgz playwright

package.json 會記成 "auto-manual-gen": "file:vendor/auto-manual-gen-0.1.0.tgz"。檔案跟著 repo 走,其他同事 clone 下來 npm install 就有了;如果把 .tgz 放在自己電腦或共用槽上,別人的 npm install 就會因為找不到檔案而失敗。

缺點是更新要靠人:出了新版,就得換掉 .tgz、改路徑,再請大家重新安裝。

方法二:發布到公司內部的 npm registry。如果有兩個以上的產品在用,或是會持續更新,就值得放上 registry。Verdaccio、Azure Artifacts 都能當內部 registry (GitHub Packages、GitLab 也可以,但套件名稱要改成有 scope 的 @your-org/auto-manual-gen,.npmrc 也要改成只把這個 scope 指過去)。發布的人:

npm login --registry https://npm.example.internal/
npm publish --registry https://npm.example.internal/

使用的產品 repo 加一個 .npmrc,指向公司的 registry (內部 registry 通常會代理公開的 npm,其他套件照樣裝得到):

registry=https://npm.example.internal/

之後就跟前面一樣,npm install -D auto-manual-gen playwright 就好,更新也只要 npm update auto-manual-gen。不過要注意,npm update 只會在 package.json 記錄的版本範圍內升級:現在的版本是 0.1.0,記下來的範圍是 ^0.1.0,只涵蓋 0.1.x。出了 0.2.0,就要明確指定 npm install -D auto-manual-gen@0.2.0。

至於要不要上架到公開的 npm,我的建議是在公司內部就好XD

不管是哪一種,只要有人依賴這個套件,就要清楚哪些東西改了會讓別人壞掉:CLI 的指令與參數、manual.yaml 與 manifest 的 schema。這些有不相容的變更,就升主版號;還在 0.x 的時候,慣例是改升 minor (0.1 → 0.2),這也是為什麼 npm update 不會自動跨過去。

小結

今天把產線從範例專案裡抽了出來,變成 auto-manual-gen 這個 CLI:

  • 為了包成 npm package,跟產品有關的設定都集中到 manual.yaml,它在哪裡,手冊專案的根目錄就在哪裡。
  • 用在自己的產品時,手冊專案放在產品 repo 的 manual/ 子目錄;CLI 負責做,agent 負責寫,人負責決定與確認。
  • npm pack 打包後,可以直接給同事 .tgz,或發布到公司內部的 registry。

CLI 準備好了,人跟 CI 都能用。明天處理最後一種使用者:AI agent,把「怎麼用這套工具」打包成 Claude Code plugin。


上一篇
[Day 26] 操作導覽
下一篇
[Day 28] 把產線打包給 agent 1:從 skills 到 Claude Code plugin
系列文
用 AI Agent 打造你的產品使用手冊產線 共 29 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言