Files
shared/skills/models/SKILL.md
T

198 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: models
description: 查詢目前可用哪些模型並依 spec-model 的固定標籤體系標註(能力等級/成本/延遲/上下文/用途/可用性),維護 `~/.claude/jsc/models.json` 快取,並依任務類型推薦模型或檢查當前模型是否符合指定模型。提供 `--refresh`(重跑探測與 smoke test 並重寫快取)、`--task <analysis|implement|review|summary|persona>`(依對映表推薦模型+一行理由+次選)、`--check <model>`(比對指定模型與當前模型,不符則依強制切換規則輸出錯誤並回非零狀態)、`--json`(結構化輸出)四個參數,預設模式讀快取(過期或不存在則自動探測)輸出模型 × 標籤表格。當使用者問現在有哪些模型可用、要幫某個任務選模型、要檢查目前模型對不對、要重新驗證模型可用性、或提到 `models` skill、模型標籤、模型快取、`~/.claude/jsc/models.json` 時觸發。不適用於:切換模型本身(使用者自行執行 `/model`)、產生指定模型的 wiki TODO(用 `/jsc-shared:todo-wiki`,它會呼叫本 skill 取推薦)、與模型選型無關的一般查詢。
argument-hint: "[--refresh] [--task <analysis|implement|review|summary|persona>] [--check <model>] [--json]"
---
# models — 取得可用模型並加上標籤
依 `/jsc-shared:spec-model` 的標籤體系與來源優先序,查詢目前帳號/CLI 可用的模型、標註標籤、維護快取,並提供任務推薦與模型檢查兩種決策輔助。**本 skill 是 spec-model 的唯一可執行入口**——其他 skill(如 `/jsc-shared:todo-wiki`、`worklog --tune`)需要模型清單或推薦時,一律呼叫本 skill,不得自行重寫探測或推薦邏輯。
| 模式 | 用途 | 是否重跑探測 |
| --- | --- | --- |
| 預設(無參數) | 輸出模型 × 標籤表格 | 快取有效才不跑;過期或不存在才自動探測 |
| `--refresh` | 強制重跑探測+smoke test,重寫快取 | 一律重跑 |
| `--task <type>` | 依任務對映表推薦模型 | 沿用當前有效快取(無效才先探測) |
| `--check <model>` | 檢查指定模型與當前模型是否一致 | 沿用當前有效快取(無效才先探測) |
`--json` 可疊加在任一模式上,改變輸出格式,不改變邏輯。
---
## 共用規範(必要前置)
先載入 `/jsc-shared:spec-preflight` 並依其流程處理;載入不到即代表 shared plugin 未安裝,
依該 spec 詢問使用者是否安裝 `https://gitea.jsc.idv.tw/plugins/shared.git`,不安裝則中斷本 skill。
本 skill 需要的規範:`spec-model`、`spec-output`、`spec-execution`、`spec-time-log`、`spec-skill-invocation`
`spec-model` 是本 skill 的行為本體(標籤體系、任務對映表、來源優先序、快取設計、強制切換規則五節),下文只描述**本 skill 如何呼叫這五節**,不重抄內容;標籤字彙、對映表、來源優先序、快取欄位、錯誤訊息格式如與本檔敘述有出入,一律以 `spec-model` 當次實際載入到的內容為準。
---
## 參數
| 參數 | 說明 | 預設 |
| --- | --- | --- |
| `--refresh` | 忽略快取新鮮度,強制依 spec-model 第三節重跑探測與 smoke test,重寫快取 | 不帶則只在快取過期/不存在時才探測 |
| `--task <analysis\|implement\|review\|summary\|persona>` | 依 spec-model 第二節對映表推薦模型 | 不帶則不做推薦,走預設表格輸出 |
| `--check <model>` | 指定模型 id 或別名,比對當前模型 | 不帶則不做檢查 |
| `--json` | 輸出結構化 JSON 取代 Markdown 表格/文字 | 不帶則輸出 Markdown |
**參數互斥與優先序**:`--refresh` 是修飾詞,可與任何模式並存(一律先重跑探測,再往下做該模式的動作)。`--check` 與 `--task` 同時出現時,兩者語意不同不建議並用;若使用者仍同時帶入,以 `--check` 為主要動作、`--task` 的推薦結果附帶輸出,並在回報開頭註明「同時指定 `--check` 與 `--task`,本次以 `--check` 的判定結果為準」。都未帶時走預設模式(表格輸出)。
---
## 快取
路徑與欄位固定依 `spec-model` 第四節:`~/.claude/jsc/models.json`,每筆 `{ id, aliases[], tags[], context, pricing, verified_at, verdict, reason }`,`verified_at` 超過 30 天視為過期。
- **讀取**:優先用助理的檔案讀取工具(Claude Code 為 Read)直接讀取並解析 JSON;shell 環境改用 `python3 -c "import json,sys; ..."` 解析,避免依賴 `jq`(是否安裝因環境而異)。
- **寫入**:優先用助理的檔案寫入工具(Write/Edit)整份覆寫,確保 UTF-8 無 BOM(依 `spec-output`);shell 環境改用 `python3` 組字典後 `json.dump(..., ensure_ascii=False, indent=2)` 寫檔,不用字串拼接手刻 JSON(容易漏跳脫字元)。
- **目錄不存在**:`~/.claude/jsc/` 不存在時,寫入前先建立(`mkdir -p ~/.claude/jsc`)。
- **`reason` 欄位一併記錄來源**:因快取欄位固定、不得新增欄位,「這筆是怎麼判定出來的」寫進 `reason`,格式建議:`<來源層次摘要(CLI 自陳 --help/使用痕跡 stats-cache.json/claude-api skill 文件)> + <smoke test 結果摘要或「未能於此 CLI 驗證」>`。輸出表格的「來源」欄直接取這裡的內容,不另外judge。
- **內容邊界**:只准存模型中繼資料七個欄位,**絕不寫入任何工作內容、對話內容、專案路徑、議題內容或個資**——寫入前逐筆檢查是否越界。
---
## 預設模式(無參數)
1. 檢查快取檔是否存在;不存在 → 視同過期,走步驟 3。
2. 存在則讀出每筆 `verified_at`,與目前時間(`TZ='Asia/Taipei' date +'%Y/%m/%d %H:%M:%S'`)比對,**任一筆超過 30 天** → 整份快取視為過期,走步驟 3;全部未過期 → 直接跳到步驟 4 用現有內容輸出。
3. **自動探測**(等同 `--refresh` 的探測部分,見下節「探測與 smoke test 流程」),完成後覆寫快取,再進入步驟 4。
4. **輸出模型 × 標籤表格**(Markdown,依 `/jsc-shared:spec-output`):
| 模型 id | 別名 | 標籤 | 上下文 | 定價 | verified_at | 判定 | 來源/理由 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `claude-sonnet-5` | `sonnet` | `#均衡實作` `#實作` `#中成本` `#標準上下文` `#本機可用` | 200k | (查證當下定價) | 2026/08/11 10:00:00 | 本機可用 | CLI 自陳 + smoke test 通過 |
(表格內容為格式示意,實際筆數與標籤依當次快取內容輸出,不得照抄範例值。)
5. `--json` 時改輸出:
```json
{
"cache_path": "~/.claude/jsc/models.json",
"generated_at": "2026/08/11 10:00:00",
"models": [
{ "id": "...", "aliases": ["..."], "tags": ["..."], "context": 200000,
"pricing": "...", "verified_at": "2026/08/11 10:00:00", "verdict": "本機可用", "reason": "..." }
]
}
```
---
## `--refresh`:探測與 smoke test 流程
不論快取是否有效都執行本節,完成後整份覆寫快取。依 `spec-model` 第三節,**前一項可取得就不往下**,但仍要把後續層次能補充的候選都納入再統一做 smoke test:
1. **`claude-api` skill**:以 Skill 工具載入,取得當下模型 id/定價/上下文長度清單,**不憑記憶、不援引本檔或過去對話中的舊數字**。這是候選清單與 `pricing`/`context` 欄位的權威來源。
2. **CLI 自陳**:Claude Code 執行 `claude --help`,解析 `--model` 說明列出的別名(如 `sonnet`/`opus`/`fable` 等,實際內容以當次輸出為準);非 Claude Code 助理依自身列出指令(`codex`、`opencode`、`agy`、`copilot` 各自對應指令),取不到就不強行湊數。
3. **使用痕跡(僅 Claude Code)**:讀 `~/.claude/stats-cache.json` 的 `dailyModelTokens`/`modelUsage` 等欄位,把出現過的模型 id 併入候選清單(只補充候選,不代表現在仍可用)。
4. **Smoke test**(所有候選逐一跑,Claude Code 專屬做法;其他助理見下節「非 Claude Code 助理」):
```bash
CLAUDE_CODE_CHILD_SESSION=1 timeout 45 claude -p 'OK' --model <id>
```
stderr/stdout 出現 `is not a model this version of Claude Code recognizes` 或 `There's an issue with the selected model` → 該筆 `verdict = 不可用`;正常回應 → `verdict = 本機可用`;因不在此 CLI 驗證範圍(例如純文件記載、非本帳號方案)而無法判定 → `verdict = 未驗證`。
⚠️ 每個候選都要帶 `CLAUDE_CODE_CHILD_SESSION=1`,避免觸發巢狀 session 與 SessionStart hook。
5. **貼標籤**:依 spec-model 第一節標籤字彙表,對每個候選同時判斷能力等級、成本(依步驟 1 查到的定價分三段,不憑記憶)、延遲、上下文(`context ≥ 1,000,000` 記 `#長上下文`,否則 `#標準上下文`)、用途(可多個)、可用性(步驟 4 的判定結果)。
6. **寫回快取**:`verified_at` 取本次完成時間,`reason` 依上節「`reason` 欄位一併記錄來源」的格式寫入,整份以 `models.json` 覆寫(不是逐筆 append,避免殘留已下架模型的舊紀錄;若某模型本次探測不到但快取內既有記錄,先詢問是否移除或保留標記為 `#不可用`,不擅自沉默刪除)。
7. 完成後照預設模式步驟 4/5 輸出表格。
---
## `--task <analysis|implement|review|summary|persona>`
1. 確保快取有效(無效先走上節探測流程)。
2. 依 `spec-model` 第二節對映表,把參數值對應到任務類型與必要/加分標籤:
| 參數值 | 對映任務類型 | 必要標籤 | 加分標籤 |
| --- | --- | --- | --- |
| `analysis` | 需求分析/拆 TODO/架構決策 | `#深度推理` `#分析` `#本機可用` | `#長上下文` |
| `implement` | 依清單實作/規格落地 | `#均衡實作` `#實作` `#本機可用` | `#中成本` |
| `review` | code review/findings 判讀 | `#深度推理` `#審查` `#本機可用` | — |
| `summary` | 逐輪摘要(worklog)/分類 | `#輕量快速` `#摘要` `#延遲敏感可用` `#低成本` | — |
| `persona` | 人格對話 | `#對話人格` `#本機可用` | `#延遲敏感可用` |
參數值不在上表 → 回報「不支援的任務類型 `<值>`,可用值:analysis/implement/review/summary/persona」並停止,不猜測近似值。
3. 篩出快取中**同時具備全部必要標籤**的模型;都不具備 → 回報「目前快取內沒有符合『<必要標籤>』的模型,建議先執行 `--refresh` 重新探測」並停止。
4. 候選排序:加分標籤命中數較多者優先;仍並列則 `verified_at` 較新者優先。
5. 輸出**推薦 id + 一行理由 + 次選**:
```
推薦:<id>(<alias>)—— <一行理由,說明命中哪些必要標籤與加分標籤>
次選:<id2>(<alias2>)—— <一行理由>(若只有一個候選則省略此行並註明「無其他候選」)
```
6. `--json` 時改輸出:
```json
{
"task": "implement",
"required_tags": ["#均衡實作", "#實作", "#本機可用"],
"bonus_tags": ["#中成本"],
"recommended": { "id": "...", "alias": "...", "reason": "..." },
"alternatives": [ { "id": "...", "alias": "...", "reason": "..." } ]
}
```
---
## `--check <model>`
用於判斷「當前執行者的模型」是否等於指定模型,供其他 skill(例如開啟帶 `model:` frontmatter 清單檔時)呼叫,行為依 `spec-model` 第五節:
1. 確保快取有效(無效先走探測流程),在快取的 `id`/`aliases[]` 中解析 `<model>`(可傳 id 或別名);快取查不到 → 仍照字面值往下比對,並在輸出中註明「快取未收錄此模型,僅做字面比對」。
2. 取得「當前模型」:**Claude Code 沒有環境變數可讀當前模型 id**,以 agent 對自身系統提示所述的 exact model id 自我回報為準;自我回報不確定時,請使用者執行 `/status` 確認後再比對,**不得用猜的**。
3. 比對指定模型(含別名)與當前模型:
- **相符** → 輸出 `[時間][模型檢查][INF]: 當前模型 <current-id> 符合指定的 <model>(<alias>)。`(時間格式依 `/jsc-shared:spec-time-log`),視為成功結束。
- **不符** → 依 spec-model 第五節格式輸出並停止,**不得自行降級或升級頂替,不得先做一部分**:
```
[yyyy/MM/dd HH:mm:ss][模型檢查][ERR]: 本清單/本 skill 指定 <model>(<alias>),當前模型為 <current-model-id>。
請執行 /model <alias> 切換後重新載入,本次不進行任何修改。
```
**回非零狀態**:本 skill 以 agent 對話形式執行時沒有 process exit code 可回傳,以上述 `[ERR]` 行本身作為失敗訊號——呼叫方(其他 skill 或以 headless 模式呼叫本 skill 的腳本)應以輸出是否含 `[模型檢查][ERR]` 判定失敗;若未來新增腳本化實作(例如 `shared/scripts/lib` 的參考實作),該腳本須以 `exit 1` 對應此狀態。
4. `--json` 時改輸出:
```json
{
"check_model": "sonnet",
"resolved_id": "claude-sonnet-5",
"current_model": "claude-opus-5",
"match": false,
"message": "[2026/08/11 10:00:00][模型檢查][ERR]: 本清單/本 skill 指定 sonnet(claude-sonnet-5),當前模型為 claude-opus-5。請執行 /model sonnet 切換後重新載入,本次不進行任何修改。",
"exit_status": 1
}
```
相符時 `match: true`、`exit_status: 0`,`message` 改為 INF 那行。
---
## 非 Claude Code 助理
`claude-api` skill(來源優先序第 1 層)與 `~/.claude/stats-cache.json` 使用痕跡(第 3 層)都是 Claude Code 專屬,其他 CLI(Codex/OpenCode/Antigravity/GitHub Copilot)不可取得,**只能做到**:
- **CLI 自陳**(第 2 層):各自的模型列出指令(例如 `codex` 的設定/說明輸出、`opencode models`、`agy` 對應指令、`copilot` 對應指令),取得到就以此作為候選與別名來源。
- **smoke test**(第 4 層):以該 CLI 自己的無互動單輪呼叫方式驗證候選模型可用性(例如 `codex exec`、`opencode run`、`agy -p`、`copilot -p` 等一次性呼叫,回應正常記 `#本機可用`、明確報錯記 `#不可用`),需在該助理環境下能否比照 Claude Code smoke test 的無害單輪呼叫方式自行判斷;判斷不出對應方式就不勉強跑。
無法取得 `pricing`/`context`(需要 `claude-api` skill 才查得到的欄位)時,**不得憑記憶填入**,該筆欄位留空或標註「未知(無法在此 CLI 取得)」;無法完成第 2、4 層探測的模型,**整批標 `#未驗證`**,`reason` 寫「僅文件記載,未能於此 CLI 驗證」。
**不得中斷**:不論第 1、3 層缺失、或第 2、4 層部分候選探測失敗,都要照常完成本次模式並輸出結果,缺失的部分如實標註,不視為錯誤而中止整個 skill。
---
## 呼叫方式
依 `/jsc-shared:spec-skill-invocation` 的統一呼叫方式,本 skill 的實際參數格式與範例:
| 助理 | 呼叫 |
| --- | --- |
| Claude Code / Antigravity | `/jsc-shared:models`、`/jsc-shared:models --refresh`、`/jsc-shared:models --task implement`、`/jsc-shared:models --check sonnet`、`/jsc-shared:models --task analysis --json` |
| Codex | `$models --task review`,或用 `/skills` 選單 |
| OpenCode | 依本 skill 的 description 自動觸發,或以自然語言描述「幫我查現在有哪些模型可用」等同預設模式 |