@tekmidian/pai 0.49.0 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/{aibroker-client-D5NT0S1N.mjs → aibroker-client-Bu72yPKj.mjs} +1 -1
  2. package/dist/{aibroker-client-Bn9SnGMa.mjs → aibroker-client-CDIXmq-e.mjs} +1 -1
  3. package/dist/{aibroker-client-Bn9SnGMa.mjs.map → aibroker-client-CDIXmq-e.mjs.map} +1 -1
  4. package/dist/{chain-CNSa0A3G.mjs → chain-BBbVbWVv.mjs} +4 -4
  5. package/dist/{chain-CNSa0A3G.mjs.map → chain-BBbVbWVv.mjs.map} +1 -1
  6. package/dist/cli/index.mjs +14 -14
  7. package/dist/cli/program.mjs +14 -14
  8. package/dist/config-Bn9jpblO.mjs +653 -0
  9. package/dist/config-Bn9jpblO.mjs.map +1 -0
  10. package/dist/{config-DxMZjpvY.mjs → config-DYXARgk8.mjs} +180 -151
  11. package/dist/config-DYXARgk8.mjs.map +1 -0
  12. package/dist/config-RjeVGJ7K.mjs +3 -0
  13. package/dist/{context-handover-cache-B9NKSjwR.mjs → context-handover-cache-yOuK9RIk.mjs} +5 -5
  14. package/dist/{context-handover-cache-B9NKSjwR.mjs.map → context-handover-cache-yOuK9RIk.mjs.map} +1 -1
  15. package/dist/daemon/index.mjs +13 -12
  16. package/dist/daemon/index.mjs.map +1 -1
  17. package/dist/{daemon-DZ4Q0jrs.mjs → daemon-CBTQYtHF.mjs} +49 -30
  18. package/dist/daemon-CBTQYtHF.mjs.map +1 -0
  19. package/dist/daemon-Vf7pHnjR.mjs +25 -0
  20. package/dist/daemon-mcp/index.mjs +186 -23
  21. package/dist/daemon-mcp/index.mjs.map +1 -1
  22. package/dist/factory-Ba8j9K7q.mjs +3 -0
  23. package/dist/{factory-DNYAqjH0.mjs → factory-Bt7TWQje.mjs} +3 -3
  24. package/dist/{factory-DNYAqjH0.mjs.map → factory-Bt7TWQje.mjs.map} +1 -1
  25. package/dist/{fallback-IeR2FrFn.mjs → fallback-CIGspCSi.mjs} +260 -10
  26. package/dist/fallback-CIGspCSi.mjs.map +1 -0
  27. package/dist/hooks/capture-all-events.mjs +80 -8
  28. package/dist/hooks/capture-all-events.mjs.map +4 -4
  29. package/dist/hooks/context-compression-hook.mjs +54 -39
  30. package/dist/hooks/context-compression-hook.mjs.map +4 -4
  31. package/dist/hooks/post-compact-inject.mjs +54 -39
  32. package/dist/hooks/post-compact-inject.mjs.map +4 -4
  33. package/dist/hooks/route-agents-to-worker.mjs +204 -109
  34. package/dist/hooks/route-agents-to-worker.mjs.map +4 -4
  35. package/dist/hooks/whisper-rules.mjs +7613 -9
  36. package/dist/hooks/whisper-rules.mjs.map +4 -4
  37. package/dist/hooks/worker-proxy.mjs +204 -109
  38. package/dist/hooks/worker-proxy.mjs.map +4 -4
  39. package/dist/hooks/worker-status-line.mjs +211 -116
  40. package/dist/hooks/worker-status-line.mjs.map +4 -4
  41. package/dist/hooks/worker-supervision.mjs +208 -113
  42. package/dist/hooks/worker-supervision.mjs.map +4 -4
  43. package/dist/{kg-entity-BSjM5xZh.mjs → kg-entity-BSW7ra8i.mjs} +1 -1
  44. package/dist/{kg-entity-BSjM5xZh.mjs.map → kg-entity-BSW7ra8i.mjs.map} +1 -1
  45. package/dist/main-resolver-BTastpp4.mjs +7 -0
  46. package/dist/{main-resolver-DvYu9jbl.mjs → main-resolver-BmZPCmgj.mjs} +3 -3
  47. package/dist/{main-resolver-DvYu9jbl.mjs.map → main-resolver-BmZPCmgj.mjs.map} +1 -1
  48. package/dist/{planner-Cn8HmT7l.mjs → planner-BiH9msqq.mjs} +6 -6
  49. package/dist/{planner-Cn8HmT7l.mjs.map → planner-BiH9msqq.mjs.map} +1 -1
  50. package/dist/{program-D9-wfmkZ.mjs → program-BX67-4I2.mjs} +233 -277
  51. package/dist/program-BX67-4I2.mjs.map +1 -0
  52. package/dist/query-feedback-Bm6XvCmg.mjs +3 -0
  53. package/dist/{query-feedback-CYyOGi3y.mjs → query-feedback-CTs_jx6i.mjs} +1 -1
  54. package/dist/{query-feedback-CYyOGi3y.mjs.map → query-feedback-CTs_jx6i.mjs.map} +1 -1
  55. package/dist/{run-Cls0YGgV.mjs → run-TChOnMO_.mjs} +1388 -1183
  56. package/dist/run-TChOnMO_.mjs.map +1 -0
  57. package/dist/{server-Ch99xt5K.mjs → server-R9UkCn3v.mjs} +42 -3
  58. package/dist/server-R9UkCn3v.mjs.map +1 -0
  59. package/dist/session-keepalive-BuG3wvik.mjs +579 -0
  60. package/dist/session-keepalive-BuG3wvik.mjs.map +1 -0
  61. package/dist/skills/VaultContext/SKILL.md +1 -1
  62. package/dist/{state-DnYGRmS7.mjs → state-Ca0ltLgI.mjs} +1 -1
  63. package/dist/{state-PJrgfDLW.mjs → state-DwrsOoMi.mjs} +1 -1
  64. package/dist/{state-PJrgfDLW.mjs.map → state-DwrsOoMi.mjs.map} +1 -1
  65. package/dist/{tools-B77WHeVZ.mjs → tools-BEqiJt_j.mjs} +13 -13
  66. package/dist/{tools-B77WHeVZ.mjs.map → tools-BEqiJt_j.mjs.map} +1 -1
  67. package/dist/{tools-NnR_n-Ja.mjs → tools-BwsOTmjh.mjs} +2 -2
  68. package/dist/{wakeup-UrhiW-KU.mjs → wakeup-Yk5lQ0jb.mjs} +1 -1
  69. package/dist/{wakeup-UrhiW-KU.mjs.map → wakeup-Yk5lQ0jb.mjs.map} +1 -1
  70. package/dist/{work-queue-worker-BA5IDBwQ.mjs → work-queue-worker-B9zVWImP.mjs} +3 -3
  71. package/dist/{work-queue-worker-BA5IDBwQ.mjs.map → work-queue-worker-B9zVWImP.mjs.map} +1 -1
  72. package/dist/work-queue-worker-D-DnQ7oh.mjs +14 -0
  73. package/dist/{zettelkasten-BBjA7GcP.mjs → zettelkasten-DezbXghl.mjs} +2 -2
  74. package/dist/{zettelkasten-BBjA7GcP.mjs.map → zettelkasten-DezbXghl.mjs.map} +1 -1
  75. package/docs/cache-keepalive.md +138 -0
  76. package/docs/commands/README.md +7 -0
  77. package/docs/commands/config.md +84 -0
  78. package/docs/commands/daemon.md +6 -0
  79. package/docs/commands/worker.md +37 -2
  80. package/docs/config.md +171 -0
  81. package/docs/model-catalogue.md +502 -0
  82. package/docs/provider-independence-details.md +1 -1
  83. package/docs/task-bus.md +1 -1
  84. package/docs/worker.md +33 -5
  85. package/docs/workers-config.md +105 -12
  86. package/package.json +1 -1
  87. package/src/hooks/ts/capture-all-events.test.ts +71 -0
  88. package/src/hooks/ts/capture-all-events.ts +10 -3
  89. package/src/hooks/ts/user-prompt/whisper-rules.test.ts +56 -1
  90. package/src/hooks/ts/user-prompt/whisper-rules.ts +24 -0
  91. package/statusline-command.sh +81 -6
  92. package/dist/config-DCu8THKi.mjs +0 -228
  93. package/dist/config-DCu8THKi.mjs.map +0 -1
  94. package/dist/config-DeqFqa1N.mjs +0 -3
  95. package/dist/config-DxMZjpvY.mjs.map +0 -1
  96. package/dist/daemon-CYpVy_Dw.mjs +0 -24
  97. package/dist/daemon-DZ4Q0jrs.mjs.map +0 -1
  98. package/dist/factory-47Qf_df7.mjs +0 -3
  99. package/dist/fallback-IeR2FrFn.mjs.map +0 -1
  100. package/dist/indexer-C5Le7XE7.mjs +0 -1
  101. package/dist/main-resolver-CnfnWa8C.mjs +0 -7
  102. package/dist/program-D9-wfmkZ.mjs.map +0 -1
  103. package/dist/query-feedback-C7rSfiXU.mjs +0 -3
  104. package/dist/run-Cls0YGgV.mjs.map +0 -1
  105. package/dist/server-Ch99xt5K.mjs.map +0 -1
  106. package/dist/work-queue-worker-DLM2wlqM.mjs +0 -14
@@ -0,0 +1,502 @@
1
+ # Model catalogue for PAI providers (2026-09-20)
2
+
3
+ Every row below was checked against the provider's own docs/pricing page via
4
+ WebFetch, or — where the official page didn't render a usable table for the
5
+ fetch summarizer, or officially wasn't reachable — against a WebSearch
6
+ synthesis of third-party trackers, marked "3rd-party" in the Source column.
7
+ Anything neither source confirmed is UNKNOWN. Prices are list/pay-as-you-go,
8
+ USD, as of today; providers change these often — re-check before relying on
9
+ a number for billing.
10
+
11
+ Context on what PAI can run today (verified in this worktree, not assumed):
12
+
13
+ - `WorkerProtocol` is `"anthropic" | "openai"` (`src/workers/config.ts:37`).
14
+ `"openai"` runs through PAI's local proxy (`src/workers/proxy/`), which
15
+ translates Anthropic Messages ⇄ OpenAI Chat Completions — **not** the
16
+ Responses API.
17
+ - `MODEL_CAPABILITIES` is the closed set `["default", "fast", "image"]`
18
+ (`src/workers/config.ts:261`). There is **no** open-set `models: {…,
19
+ vision, longcontext, reasoning}` and **no** top-level `capabilities:`
20
+ preference map in this codebase today — the spec's mention of both is
21
+ forward-looking (a parallel worker's WIP), not current state. The nearest
22
+ existing equivalents are `tags:` (`code, vision, image-gen, long-context,
23
+ fast, reasoning` — routing filters, not model ids) and `classes.<name>` /
24
+ `classes.<name>.requireTags`.
25
+ - There is **no `image` engine**. `WorkerEngine` is `"claude" | "codex"`
26
+ only (`src/workers/config.ts:40`). A provider's `models.image` id is real
27
+ config (`glm.models.image: example-paint` is already set in the live
28
+ `workers.yaml`) but nothing in `run.ts` treats it specially: the "image"
29
+ class just launches Claude Code or Codex with `--model <that id>` over the
30
+ normal chat protocol. **No code path calls an images-generation endpoint**
31
+ (`POST {url}/images/generations` or equivalent). Until that engine lands,
32
+ none of the image-generation APIs in §1.11 are reachable through
33
+ `pai worker run` — see §2 and §5.
34
+
35
+ ## 1. Provider families
36
+
37
+ ### 1.1 Anthropic
38
+
39
+ Source: https://platform.claude.com/docs/en/models/overview (redirects from
40
+ docs.anthropic.com; fetched verbatim).
41
+
42
+ | Model id | For | Context | Max output | Input / Output per 1M | Protocol | Base URL | Notes |
43
+ |---|---|---|---|---|---|---|---|
44
+ | `claude-fable-5-1` | reasoning, longcontext | 1M | 128K | $10 / $50 | anthropic | api.anthropic.com | Adaptive thinking always on; knowledge cutoff Jun 2026 |
45
+ | `claude-opus-5` | default (complex) | 1M | 128K | $5 / $25 | anthropic | api.anthropic.com | |
46
+ | `claude-sonnet-5` | default | 1M | 128K | $2 / $10 | anthropic | api.anthropic.com | PAI's `NATIVE_ANTHROPIC_MODELS.default` |
47
+ | `claude-haiku-4-5-20251001` | fast | 200K | 64K | $1 / $5 | anthropic | api.anthropic.com | PAI's `NATIVE_ANTHROPIC_MODELS.fast`; vision on all four |
48
+
49
+ All four: text+image input, vision, tool use, native to PAI's `protocol:
50
+ "anthropic"` — no proxy, no translation, this is what `ANTHROPIC_NATIVE`
51
+ already runs on.
52
+
53
+ ### 1.2 OpenAI
54
+
55
+ Sources: https://developers.openai.com/api/docs/models (redirects from
56
+ platform.openai.com/docs/models; WebFetch, some entries cross-checked by
57
+ WebSearch since the fetch summarizer produced a couple of clearly-fabricated
58
+ codenames on the first pass — see caveat below) and
59
+ https://developers.openai.com/api/docs/models/gpt-6-astra (fetched directly,
60
+ verbatim numbers).
61
+
62
+ | Model id | For | Context | Max output | Input / Output per 1M | Protocol | Base URL | Notes |
63
+ |---|---|---|---|---|---|---|---|
64
+ | `gpt-6-astra` | default (flagship) | 1.05M | 128K | $10 / $50 | openai-chat *(Chat Completions listed "Supported") / openai-responses for tool calling* | api.openai.com/v1 | Tool calling requires the Responses API per OpenAI's own migration guide — a plain chat run works over Chat Completions, but PAI workers that use tools would lose them through the proxy today |
65
+ | `gpt-5.1` | default (legacy) | 400K | 128K | UNKNOWN (legacy pricing page not fetched) | openai-chat | api.openai.com/v1 | Still listed, "previous flagship" |
66
+ | `gpt-5-mini` | fast | 272K–400K (sources disagree) | 128K | $0.25 / $2.00 | openai-chat | api.openai.com/v1 | 3rd-party cross-check |
67
+ | `gpt-5-nano` | fast | 272K–400K (sources disagree) | 128K | $0.05 / $0.40 | openai-chat | api.openai.com/v1 | 3rd-party cross-check |
68
+ | `gpt-image-2` (snapshot `gpt-image-2-2026-04-21`) | image | n/a | n/a | ~$0.006 / $0.053 / $0.211 per 1024×1024 image at low/med/high quality (metered as output image tokens, not a flat per-image price) | images-api | api.openai.com/v1/images/generations | 3rd-party; current flagship image model, replaces `gpt-image-1.5` |
69
+ | `gpt-image-1-mini` | image | n/a | n/a | ~$0.005 / $0.011 / $0.036 per image (low/med/high, 1024×1024) | images-api | api.openai.com/v1/images/generations | 3rd-party |
70
+
71
+ **Caveat on this table:** the first WebFetch against `developers.openai.com/api/docs/models`
72
+ returned model ids (`gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`,
73
+ `gpt-daybreak-red-latest`, `gpt-daybreak-blue-latest`) that could not be
74
+ corroborated by a follow-up WebSearch and read as fabricated by the
75
+ page-summarizing model — they are **not** included above. `gpt-6-astra` and
76
+ the GPT-5.x ids *were* corroborated independently (direct fetch of its own
77
+ model page, plus multiple WebSearch hits referencing it as "the current
78
+ flagship" and giving matching numbers), so those are kept. Treat any OpenAI
79
+ model id not in the table above, that you see in a single search result, as
80
+ unverified until you load its own `/docs/models/<id>` page directly.
81
+
82
+ ### 1.3 Google Gemini
83
+
84
+ Sources: https://ai.google.dev/gemini-api/docs/models (WebFetch),
85
+ https://ai.google.dev/gemini-api/docs/pricing (WebFetch, verbatim numbers),
86
+ WebSearch cross-check against ai.google.dev/gemini-api/docs/gemini-3 and
87
+ OpenRouter listings.
88
+
89
+ | Model id | For | Context | Vision | Input / Output per 1M | Protocol | Base URL | Notes |
90
+ |---|---|---|---|---|---|---|---|
91
+ | `gemini-3-pro-preview` | default | 1,048,576 | yes | UNKNOWN (deprecated, shut down 2026-03-09) | openai-chat *(via compat layer)* or native REST | generativelanguage.googleapis.com | Superseded by `gemini-3.1-pro-preview` |
92
+ | `gemini-3.5-flash` | default/fast | 1,048,576 | yes | $1.50 / $9.00 | openai-chat or native REST | generativelanguage.googleapis.com | |
93
+ | `gemini-3.5-flash-lite` | fast | 1,048,576 | yes | $0.30 / $2.50 | openai-chat or native REST | generativelanguage.googleapis.com | text/image/video/audio input |
94
+ | `gemini-3.8-flash` | default/fast | UNKNOWN | yes | $0.75 / $3.75 (promo through 2026-12-31, then $1.50/$7.50) | openai-chat or native REST | generativelanguage.googleapis.com | Latest in the 3.x Flash line per docs |
95
+ | `gemini-3.1-flash-image` ("Nano Banana 2") | image | UNKNOWN | yes (image in/out) | $0.50/1M input; image output ≈$0.045/0.5K-px image, $0.067/1K-px image | images-api-ish *(REST `generateContent`, not OpenAI images schema)* | generativelanguage.googleapis.com | Real Google-used nickname; verified by 2 independent WebSearch results |
96
+ | `gemini-3.1-flash-lite-image` ("Nano Banana 2 Lite") | image | UNKNOWN | yes | $0.25/1M input; ≈$0.0336/1K-px image output | images-api-ish | generativelanguage.googleapis.com | |
97
+
98
+ Google publishes an OpenAI-compatibility shim
99
+ (`https://generativelanguage.googleapis.com/v1beta/openai/`) documented on
100
+ the same models page, which is why the Chat-family entries above list
101
+ `openai-chat` as usable — PAI's proxy targets exactly that shape.
102
+
103
+ ### 1.4 xAI (Grok)
104
+
105
+ Source: https://docs.x.ai/docs/models (WebFetch; ids like
106
+ `grok-4.20-0309-reasoning` look unusual but xAI does use dated build
107
+ suffixes — not independently cross-checked, flagged accordingly).
108
+
109
+ | Model id | For | Context | Input / Output per 1M | Protocol | Base URL | Notes |
110
+ |---|---|---|---|---|---|---|
111
+ | `grok-4.6` | default | 500K | $2.00–4.00 / $6.00–12.00 (tiered past 200K prompt) | openai-chat | api.x.ai/v1 | Docs recommend this as default |
112
+ | `grok-4.3` | longcontext | 1M | $1.25–2.50 / $2.50–5.00 | openai-chat | api.x.ai/v1 | UNVERIFIED beyond single fetch |
113
+ | `grok-build-0.1` | fast/coding | 256K | $1.00–2.00 / $2.00–4.00 | openai-chat | api.x.ai/v1 | UNVERIFIED beyond single fetch |
114
+ | `grok-imagine-image-2.0` | image | n/a | $0.04/image | images-api (xAI-specific schema, not OpenAI images) | api.x.ai/v1 | UNVERIFIED beyond single fetch |
115
+
116
+ xAI's API is documented as OpenAI-Chat-Completions-shaped for the text
117
+ models (this is well-established from xAI's long-standing SDK compat, not
118
+ just this fetch).
119
+
120
+ ### 1.5 Mistral
121
+
122
+ Sources: https://docs.mistral.ai/getting-started/models/models_overview/,
123
+ https://mistral.ai/pricing, https://mistral.ai/pricing/api — none of the
124
+ three rendered a full table for the fetch tool; numbers below are the
125
+ fragments the fetches did surface, explicitly marked incomplete.
126
+
127
+ | Model id | For | Context | Input / Output per 1M | Protocol | Base URL | Notes |
128
+ |---|---|---|---|---|---|---|
129
+ | `mistral-large-latest` (Large 3) | default | UNKNOWN | $0.5 / $1.5 | openai-chat | api.mistral.ai/v1 | Exact API id string not confirmed — page named the model "Mistral Large 3", not its API slug |
130
+ | `mistral-medium-latest` (Medium 3.5) | default | UNKNOWN | $1.5 / $7.5 | openai-chat | api.mistral.ai/v1 | Same caveat |
131
+ | `mistral-small-latest` (Small 4) | fast | UNKNOWN | $0.15 / $0.6 | openai-chat | api.mistral.ai/v1 | Same caveat |
132
+ | `codestral-latest` | coding | UNKNOWN | $0.3 / $0.9 | openai-chat | api.mistral.ai/v1 | Same caveat |
133
+ | `ministral-3b-latest` / `ministral-8b-latest` | fast | UNKNOWN | $0.1/$0.1, $0.15/$0.15 | openai-chat | api.mistral.ai/v1 | Same caveat |
134
+
135
+ Mistral's La Plateforme API id strings could not be confirmed from the pages
136
+ fetched (they showed marketing names, not `models/list`-style ids); before
137
+ using any of these, hit `GET https://api.mistral.ai/v1/models` to get exact
138
+ ids. Everything else (pricing, context) is UNKNOWN or from the fragment
139
+ above — do not treat this row group as fully verified.
140
+
141
+ ### 1.6 DeepSeek
142
+
143
+ Source: https://api-docs.deepseek.com/quick_start/pricing (WebFetch,
144
+ verbatim).
145
+
146
+ | Model id | For | Context | Max output | Input / Output per 1M | Vision | Protocol | Base URL |
147
+ |---|---|---|---|---|---|---|---|
148
+ | `deepseek-flash` | default/fast | 1M | 384K | $0.15 / $0.60 (off-peak; peak hours 01:00–04:00 & 06:00–10:00 UTC Mon–Fri double the rate) | yes | openai-chat | api.deepseek.com |
149
+ | `deepseek-v4-pro` | default (reasoning) | 1M | 384K | $0.66 / $1.98 (off-peak) | no | openai-chat | api.deepseek.com |
150
+
151
+ Docs explicitly say both accept "OpenAI Format" requests — this is a clean
152
+ `protocol: openai` target for PAI's proxy.
153
+
154
+ ### 1.7 Zhipu / Z.ai (GLM)
155
+
156
+ Sources: https://docs.z.ai/api-reference/llm/chat-completion (WebFetch)
157
+ cross-checked by WebSearch against OpenRouter/Requesty/Together listings.
158
+ The live `workers.yaml` in this environment already configures `glm` (real
159
+ key present — not reproduced here) against Z.ai's **Anthropic-compatible**
160
+ endpoint, confirming the second protocol row is real, not just documented.
161
+
162
+ | Model id | For | Context | Max output | Input / Output per 1M | Protocol | Base URL |
163
+ |---|---|---|---|---|---|---|
164
+ | `glm-5.3` | default | 1,048,576 | 128K | $1.40 / $4.40 ($0.26 cached input) | anthropic **or** openai-chat | `https://api.z.ai/api/anthropic` (anthropic) or `https://api.z.ai/api/paas/v4` (openai-chat, `POST /chat/completions`) |
165
+ | `glm-5.3-flash` | fast | UNKNOWN | 128K | UNKNOWN | anthropic or openai-chat | same |
166
+ | `glm-5.2` | default (prior) | 1,048,576 | 131,072 | ~$0.49–1.56 depending on host (Z.ai direct cheapest) | anthropic or openai-chat | same |
167
+ | `glm-4.6v` / `glm-4.5v` | vision | UNKNOWN | UNKNOWN | UNKNOWN | anthropic or openai-chat | same |
168
+
169
+ This is the one family already proven end-to-end: 284 of 495 recorded
170
+ worker runs in this environment's ledger used `provider: glm` — see §5.
171
+
172
+ ### 1.8 Moonshot (Kimi)
173
+
174
+ Sources: https://platform.moonshot.ai/docs/pricing → redirects to
175
+ https://platform.kimi.ai/docs/pricing (WebFetch). The live `workers.yaml`
176
+ configures `kimi` against `https://api.kimi.ai/coding/` (an
177
+ Anthropic-compatible endpoint distinct from the general Moonshot platform
178
+ API below — confirmed by the live config using `protocol: anthropic`
179
+ implicitly, i.e. no `protocol:`/`upstream_url` set for it).
180
+
181
+ | Model id | For | Context | Input / Output per 1M | Protocol | Base URL |
182
+ |---|---|---|---|---|---|
183
+ | `kimi-k3` | default | 1,048,576 | $3.00 / $15.00 ($0.30 cached input) | anthropic (coding endpoint) or openai-chat (general platform) | `https://api.kimi.ai/coding/` (anthropic) or `https://api.moonshot.ai/v1` (openai-chat) |
184
+ | `kimi-k2.7-code` | default (cheaper) | 262,144 | $0.95 / $4.00 | openai-chat | api.moonshot.ai/v1 |
185
+ | `kimi-k2.7-code-highspeed` | fast | 262,144 | $1.90 / $8.00 | openai-chat | api.moonshot.ai/v1 |
186
+ | `kimi-k2.6` | default (older) | 262,144 | $0.95 / $4.00 | openai-chat | api.moonshot.ai/v1 |
187
+
188
+ 12 of 495 recorded runs in this environment used `provider: kimi` — see §5.
189
+ The fetched doc didn't state explicitly which of the two base URLs is
190
+ OpenAI- vs Anthropic-shaped; the live config's usage (no `protocol:` field
191
+ = defaults to `"anthropic"`) is the confirmation for the coding endpoint.
192
+
193
+ ### 1.9 Alibaba Qwen (DashScope / Model Studio)
194
+
195
+ Source: WebSearch synthesis (official docs page
196
+ https://www.alibabacloud.com/help/en/model-studio/qwen-api-via-dashscope
197
+ was found but not directly fetched — 3rd-party pricing trackers used for
198
+ numbers).
199
+
200
+ | Model id | For | Context | Input / Output per 1M | Protocol | Base URL | Notes |
201
+ |---|---|---|---|---|---|---|
202
+ | `qwen3.8-max` | default (flagship) | 1M | $2.00 / $6.00 ($0.25 cached) | anthropic, openai-chat, or DashScope-native (all three documented) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` (openai-chat) | GA 2026-08-03; multi-region (Beijing/Singapore/Tokyo/Frankfurt/Virginia) |
203
+ | `qwen3-max` | default (prior) | 262K | $0.78–3.00 (tiered) / up to $3.90 | same three | same | |
204
+ | `qwen3.5-plus` | default (mid) | 256K (rate doubles above) | $0.40 / $2.40 | same | same | |
205
+ | `qwen3.5-flash` | fast | UNKNOWN | $0.10 / $0.40 | same | same | |
206
+
207
+ The "OpenAI-, Anthropic-, and DashScope-compatible endpoints" claim came up
208
+ independently in the WebSearch synthesis for `qwen3.8-max`; if accurate,
209
+ Qwen could run with `protocol: anthropic` (no proxy) exactly like GLM/Kimi —
210
+ worth confirming with one live `curl` before configuring it that way, since
211
+ it wasn't checked against the primary doc page directly.
212
+
213
+ ### 1.10 Meta Llama via hosted APIs
214
+
215
+ Sources: https://console.groq.com/docs/models (WebFetch, verbatim ids),
216
+ WebSearch synthesis for Together AI / Fireworks AI (official model-list
217
+ pages didn't render Llama ids for the fetch tool; numbers are 3rd-party).
218
+
219
+ | Model id | Host | Context | Input / Output per 1M | Protocol | Base URL | Notes |
220
+ |---|---|---|---|---|---|---|
221
+ | `llama-3.1-8b-instant` | Groq | 131,072 | UNKNOWN (moved to enterprise-only per one 3rd-party source, unconfirmed) | openai-chat | api.groq.com/openai/v1 | |
222
+ | `llama-3.3-70b-versatile` | Groq | 131,072 | UNKNOWN (same caveat) | openai-chat | api.groq.com/openai/v1 | |
223
+ | `openai/gpt-oss-120b` | Groq | 131,072 | $0.15 / $0.60 (3rd-party) | openai-chat | api.groq.com/openai/v1 | Not a Llama model, but Groq's current cheap/fast default per one source |
224
+ | `meta-llama/Llama-3.3-70B-Instruct-Turbo` | Together AI | UNKNOWN | ~$1.04/$1.04 (3rd-party, rising from ~$0.88 mid-2026) | openai-chat | api.together.xyz/v1 | Exact id not directly confirmed on together.ai/models fetch — verify via their `/models` list endpoint |
225
+ | Llama 3.1 70B–class | Fireworks AI | UNKNOWN | ~$0.90/$0.90 flat for >16B models (3rd-party) | openai-chat | api.fireworks.ai/inference/v1 | Exact id not confirmed |
226
+
227
+ All three (Groq, Together, Fireworks) are documented OpenAI-Chat-Completions
228
+ compatible — this family is the cleanest `protocol: openai` fit once ids are
229
+ confirmed against each provider's `/v1/models` endpoint.
230
+
231
+ ### 1.11 Image-generation APIs
232
+
233
+ | Provider | Model id | Price | API shape | Base URL | Source |
234
+ |---|---|---|---|---|---|
235
+ | OpenAI | `gpt-image-2` | see §1.2 | `POST /v1/images/generations` (OpenAI images schema) | api.openai.com | WebSearch, multiple corroborating |
236
+ | Google | `gemini-3.1-flash-image` | see §1.3 | `POST /v1beta/models/{model}:generateContent` (Gemini schema, image parts in/out — **not** the OpenAI images schema) | generativelanguage.googleapis.com | WebFetch pricing page |
237
+ | Black Forest Labs | `flux-2-pro`, `flux-2-klein-4b`, `flux-2-klein-9b`, `flux-2-flex`, `flux-2-max` | $0.014–$0.07/megapixel, credit-based (1 credit = $0.01) | BFL-specific REST, async job polling | api.bfl.ai | WebSearch (docs.bfl.ml, bfl.ai/pricing) |
238
+ | Stability AI | Stable Image Ultra / Core / SD3.5 (Medium/Large/Flash/Large-Turbo) | $0.025–$0.08/image, credit-based (1 credit = $0.01) | Stability REST (`POST /v2beta/stable-image/generate/...`) | api.stability.ai | WebSearch (official pricing page returned only a title to the fetch tool) |
239
+ | Ideogram | `ideogram-4.0`, `ideogram-3.0`, `ideogram-p-image` | $0.02–$0.10/image by version/quality tier | Ideogram REST | api.ideogram.ai | WebSearch |
240
+ | Recraft | Recraft V3 / V4 (Styles Pro, Styles Vector) | $0.04 raster / $0.08 vector / $0.10–$0.055 for style variants | Recraft REST, API-unit billed | external.api.recraft.ai | WebSearch |
241
+ | Replicate (gateway) | e.g. `black-forest-labs/flux-1.1-pro`, `ideogram-ai/ideogram-v3-quality` | pass-through per-model, e.g. $0.04 and $0.09/image respectively | Replicate REST (`POST /v1/predictions`), async | api.replicate.com | WebFetch (replicate.com/pricing) |
242
+
243
+ None of these speak the OpenAI Chat Completions or Messages protocol —
244
+ they're all their own REST job/response shapes (some sync, some async
245
+ job-polling). PAI's proxy translates Anthropic↔OpenAI-chat; it does not
246
+ translate to any of these images schemas, and there is no `engine: image`
247
+ runner today (see the note at the top of this document and §2/§5).
248
+
249
+ ## 2. What PAI can use today, with a small change, or not at all
250
+
251
+ **Usable today, unchanged** (`protocol: anthropic`, no proxy, no engine
252
+ work):
253
+ - Anthropic (native, already the default)
254
+ - Z.ai GLM via `https://api.z.ai/api/anthropic` — proven live (§1.7, §5)
255
+ - Moonshot Kimi via `https://api.kimi.ai/coding/` — proven live (§1.8, §5)
256
+ - Alibaba Qwen, *if* its Anthropic-compatible endpoint holds up under a real
257
+ `curl` test (claimed in 3rd-party sources, not confirmed against Alibaba's
258
+ own doc page — do one `pai worker providers test` before trusting it)
259
+
260
+ **Usable today through `protocol: openai` (the existing proxy), unchanged**,
261
+ provided the provider's tool-calling still works over Chat Completions
262
+ (untested end-to-end — see §5):
263
+ - DeepSeek (`api.deepseek.com`, docs say "OpenAI Format" explicitly)
264
+ - Z.ai GLM's OpenAI-compatible endpoint (`/api/paas/v4`) as an alternative
265
+ to the Anthropic one
266
+ - Moonshot's general platform endpoint (`api.moonshot.ai/v1`)
267
+ - xAI Grok (`api.x.ai/v1`)
268
+ - Groq, Together AI, Fireworks AI (Llama and others)
269
+ - OpenAI itself, for models that don't require the Responses API for tool
270
+ calls (`gpt-5.1`, `gpt-5-mini`, `gpt-5-nano`); `gpt-6-astra` would lose
271
+ tool-calling through Chat Completions per OpenAI's own docs
272
+ - Google Gemini via its documented OpenAI-compatibility shim
273
+ (`.../v1beta/openai/`)
274
+ - Mistral, once exact model ids are confirmed via `GET /v1/models`
275
+
276
+ **Needs a small change:**
277
+ - **Codex CLI providers** (`engine: codex`) already exist as a config
278
+ option (`WorkerEngine`, `src/workers/config.ts:40`) — no OpenAI-Responses
279
+ work needed for a ChatGPT-plan provider, just `pai worker providers add
280
+ <name> --engine codex`.
281
+ - **OpenAI Responses-only models** (`gpt-6-astra` with tools, and any future
282
+ model that drops Chat Completions tool support) need the proxy's
283
+ translator (`src/workers/proxy/translate.ts`) extended to speak Responses
284
+ as well as Chat Completions — real work, not config.
285
+
286
+ **Cannot be used at all today:**
287
+ - Every image-generation API in §1.11 (OpenAI images, Google Imagen/Nano
288
+ Banana, Flux, Stability, Ideogram, Recraft, Replicate) — none speak
289
+ Anthropic Messages or OpenAI Chat Completions, and no `engine: image` (or
290
+ equivalent images-job runner) exists in this codebase to call them. A
291
+ provider's `models.image` field is accepted by config validation today,
292
+ but nothing consumes it as an image request — it's just the id `run.ts`
293
+ passes to `--model` on a normal chat run, which will simply fail (or
294
+ silently run as a chat model, if the id also happens to answer chat) on
295
+ a real image-only endpoint.
296
+
297
+ ## 3. `workers.yaml` snippets
298
+
299
+ All of these are commented out and use placeholder key files under
300
+ `~/.claude/pai/keys/<name>` (the on-disk field is `key_file`; `keysDir()` in
301
+ `src/workers/config.ts:1050` resolves to `paiHomePath("keys")`, i.e.
302
+ `~/.claude/pai/keys`). Every snippet below was validated to parse without
303
+ throwing via `readWorkersYaml()` against a temp file — see §3 validation
304
+ output. None of this was written into the live `~/.claude/pai/workers.yaml`.
305
+
306
+ ```yaml
307
+ # --- OpenAI, via the PAI proxy (protocol: openai) ---
308
+ # providers:
309
+ # openai:
310
+ # protocol: openai
311
+ # upstream_url: "https://api.openai.com/v1"
312
+ # key_file: "~/.claude/pai/keys/openai"
313
+ # models:
314
+ # default: gpt-5.1 # gpt-6-astra needs Responses API for tools — see docs/model-catalogue.md §2
315
+ # fast: gpt-5-mini
316
+ # tier: 4
317
+
318
+ # --- Google Gemini, via its OpenAI-compatibility shim ---
319
+ # providers:
320
+ # gemini:
321
+ # protocol: openai
322
+ # upstream_url: "https://generativelanguage.googleapis.com/v1beta/openai"
323
+ # key_file: "~/.claude/pai/keys/gemini"
324
+ # models:
325
+ # default: gemini-3.5-flash
326
+ # fast: gemini-3.5-flash-lite
327
+ # tags: [vision, long-context]
328
+ # tier: 2
329
+
330
+ # --- xAI Grok ---
331
+ # providers:
332
+ # xai:
333
+ # protocol: openai
334
+ # upstream_url: "https://api.x.ai/v1"
335
+ # key_file: "~/.claude/pai/keys/xai"
336
+ # models:
337
+ # default: grok-4.6
338
+ # fast: grok-build-0.1
339
+ # tier: 3
340
+
341
+ # --- Mistral (confirm exact model ids via GET /v1/models before use) ---
342
+ # providers:
343
+ # mistral:
344
+ # protocol: openai
345
+ # upstream_url: "https://api.mistral.ai/v1"
346
+ # key_file: "~/.claude/pai/keys/mistral"
347
+ # models:
348
+ # default: mistral-large-latest
349
+ # fast: mistral-small-latest
350
+ # tier: 2
351
+
352
+ # --- DeepSeek ---
353
+ # providers:
354
+ # deepseek:
355
+ # protocol: openai
356
+ # upstream_url: "https://api.deepseek.com"
357
+ # key_file: "~/.claude/pai/keys/deepseek"
358
+ # models:
359
+ # default: deepseek-v4-pro
360
+ # fast: deepseek-flash
361
+ # tier: 1
362
+
363
+ # --- Zhipu / Z.ai GLM (native anthropic — same shape as the live glm provider) ---
364
+ # providers:
365
+ # glm2:
366
+ # url: "https://api.z.ai/api/anthropic"
367
+ # key_file: "~/.claude/pai/keys/glm2"
368
+ # models:
369
+ # default: glm-5.3
370
+ # fast: glm-5.3-flash
371
+ # tier: 2
372
+
373
+ # --- Moonshot Kimi (native anthropic, coding endpoint — same shape as the live kimi provider) ---
374
+ # providers:
375
+ # kimi2:
376
+ # url: "https://api.kimi.ai/coding/"
377
+ # key_file: "~/.claude/pai/keys/kimi2"
378
+ # models:
379
+ # default: kimi-k3
380
+ # tier: 3
381
+
382
+ # --- Alibaba Qwen (verify anthropic-compatible endpoint before relying on this) ---
383
+ # providers:
384
+ # qwen:
385
+ # protocol: openai
386
+ # upstream_url: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
387
+ # key_file: "~/.claude/pai/keys/qwen"
388
+ # models:
389
+ # default: qwen3.8-max
390
+ # fast: qwen3.5-flash
391
+ # tier: 3
392
+
393
+ # --- Meta Llama via Groq ---
394
+ # providers:
395
+ # groq:
396
+ # protocol: openai
397
+ # upstream_url: "https://api.groq.com/openai/v1"
398
+ # key_file: "~/.claude/pai/keys/groq"
399
+ # models:
400
+ # default: openai/gpt-oss-120b
401
+ # fast: llama-3.1-8b-instant
402
+ # tier: 1
403
+
404
+ # --- Preference example: today's mechanism (classes, not a capabilities: map) ---
405
+ # No top-level `capabilities:` block exists yet (see docs/model-catalogue.md).
406
+ # The current equivalent of "prefer an image provider for image, Claude for
407
+ # everything else" is per-class routing:
408
+ # classes:
409
+ # image: glm2/image # once an image engine exists — see §2, §5
410
+ # implement: anthropic
411
+ # draft: anthropic
412
+ ```
413
+
414
+ ### Validation
415
+
416
+ Ran a temp vitest (`src/workers/model-catalogue-snippets.test.ts`, added on
417
+ this branch) that writes each uncommented provider block above into an
418
+ isolated `workers.yaml` (via `PAI_WORKERS_YAML`) and calls
419
+ `readWorkersYaml()` from `src/workers/workers-config.ts`, asserting it does
420
+ not throw and that `data.providers.<name>.protocol` /
421
+ `.upstreamUrl` match what's intended. Output:
422
+
423
+ ```
424
+ $ bunx vitest run src/workers/model-catalogue-snippets.test.ts
425
+
426
+ RUN v4.0.18 <worktree>
427
+
428
+ ✓ src/workers/model-catalogue-snippets.test.ts (9 tests) 11ms
429
+
430
+ Test Files 1 passed (1)
431
+ Tests 9 passed (9)
432
+ Start at 18:49:03
433
+ Duration 208ms (transform 83ms, setup 21ms, import 96ms, tests 11ms, environment 0ms)
434
+ ```
435
+
436
+ All 9 snippets (`openai`, `gemini`, `xai`, `mistral`, `deepseek`, `glm2`,
437
+ `kimi2`, `qwen`, `groq`) parsed without a `WorkersConfigError` and reported
438
+ the expected `protocol`/`upstream_url`. Re-run with the command above to
439
+ reproduce (run `bun install` first if `node_modules` is missing).
440
+
441
+ ## 4. How to add one (today's real CLI, verified against `--help`)
442
+
443
+ ```
444
+ # 1. Save the key
445
+ mkdir -p ~/.claude/pai/keys && chmod 700 ~/.claude/pai/keys
446
+ printf '%s' 'sk-...' > ~/.claude/pai/keys/deepseek && chmod 600 ~/.claude/pai/keys/deepseek
447
+
448
+ # 2. Add the provider (flags confirmed via `pai worker providers add --help`)
449
+ pai worker providers add deepseek \
450
+ --protocol openai --upstream-url https://api.deepseek.com \
451
+ --key-file ~/.claude/pai/keys/deepseek \
452
+ --model deepseek-v4-pro --fast-model deepseek-flash \
453
+ --cost-tier 1
454
+
455
+ # 3. Set the model per capability (no `pai worker model image ...` shorthand
456
+ # beyond what `model` already does — capabilities are default/fast/image)
457
+ pai worker model image example-paint --provider deepseek # only meaningful once an image engine exists — see §2
458
+
459
+ # 4. Point a class at it (there is no `pai worker capability image <name>` —
460
+ # that command doesn't exist; classes are the current mechanism)
461
+ # Edit workers.yaml: classes.image: deepseek/image
462
+ # or: pai worker classes # to see current routing, then edit by hand
463
+
464
+ # 5. Run against it
465
+ pai worker run --provider deepseek -p "…" --allowedTools 'Read,Edit,Bash'
466
+ # or, once a class points at it:
467
+ pai worker run --class image -p "…"
468
+ ```
469
+
470
+ `pai worker model` and `pai worker classes` are real (`pai worker model
471
+ --help`, `pai worker --help`); `pai worker capability` is **not** a command
472
+ in this codebase — the task's suggested walkthrough
473
+ (`pai worker capability image <name>`) doesn't exist yet, so step 4 above
474
+ uses what does.
475
+
476
+ ## 5. State of the OpenAI-protocol path
477
+
478
+ Fact, not assumption, gathered from this environment's own ledger and test
479
+ suite:
480
+
481
+ - **495 recorded worker runs** in `~/.claude/pai/logs/workers/*.status`
482
+ (this machine's ledger) break down as `anthropic`: 199, `glm`: 284,
483
+ `kimi`: 12. **Zero** used a provider with `protocol: "openai"` — `glm` and
484
+ `kimi` are both configured in the live `workers.yaml` against
485
+ Anthropic-compatible endpoints (`api.z.ai/api/anthropic`,
486
+ `api.kimi.ai/coding/`), not through the proxy.
487
+ - `src/workers/proxy/server.test.ts` and `translate.test.ts` (36 test cases
488
+ total) exercise the Anthropic↔OpenAI translation and the proxy's HTTP
489
+ server exclusively against an in-process mock upstream
490
+ (`server.test.ts:96` "non-streaming: translates both directions ... passes
491
+ the keyFile token upstream" spins up a local fake server, not a real
492
+ OpenAI-compatible API).
493
+ - No file under `docs/`, no CHANGELOG entry, and no `.status`/`.jsonl`
494
+ ledger line names a provider with `upstream_url` set that actually ran.
495
+
496
+ **Conclusion:** the `protocol: openai` proxy path is implemented and unit-
497
+ tested against synthetic upstreams, but as of 2026-09-20 no worker run in
498
+ this environment's history has completed through it against a real
499
+ OpenAI-Chat-Completions provider. The first live use of any provider in
500
+ §1.2–§1.6, §1.9, §1.10 above (all `openai-chat` protocol) would be this
501
+ codebase's first real exercise of that path — worth a `pai worker providers
502
+ test <name>` smoke run before depending on it for real work.
@@ -194,7 +194,7 @@ session, context intact; returns the new worker id. Not for running workers.
194
194
  Providers, model roles and class routing live in `~/.claude/pai/workers.yaml`
195
195
  (the primary, hand-editable mechanism — see **docs/workers-config.md**).
196
196
  Everything else worker-related still lives in the `workers` section of
197
- `~/.claude/pai/config.json` (`readWorkersSection` / `writeWorkersSection`,
197
+ `~/.claude/pai/config.yaml` (or `config.json` until you run `pai config yaml`) (`readWorkersSection` / `writeWorkersSection`,
198
198
  `src/workers/config.ts:619`); every sentence and tool above writes it
199
199
  atomically — no hand-editing.
200
200
 
package/docs/task-bus.md CHANGED
@@ -46,7 +46,7 @@ Todoist → Settings → Integrations → Developer → API token.
46
46
 
47
47
  ### 2. Configure
48
48
 
49
- In `~/.claude/pai/config.json`:
49
+ In `~/.claude/pai/config.yaml` (or `config.json` until you run `pai config yaml`):
50
50
 
51
51
  ```jsonc
52
52
  {
package/docs/worker.md CHANGED
@@ -67,7 +67,7 @@ annotated example, how to add a provider, the load order, and
67
67
  `pai worker config migrate` for configs still on the old JSON shape or an
68
68
  old `workers.yaml` location). Everything else worker-related (pane, log
69
69
  dir, routing cooldown, cache-keepalive cadence, fallback) stays in
70
- `~/.claude/pai/config.json`'s `workers` section.
70
+ `~/.claude/pai/config.yaml` (or `config.json` until you run `pai config yaml`)'s `workers` section.
71
71
 
72
72
  Quick summary of workers.yaml:
73
73
 
@@ -215,6 +215,27 @@ so it is unavailable for codex workers (their thread id is kept, but
215
215
  `pai worker resume` refuses with an explanation). `providers test` reports
216
216
  `codex not installed` (exit 0) when the CLI is missing.
217
217
 
218
+ ## The image engine
219
+
220
+ Claude cannot generate images; a provider that can sets `engine: "image"`
221
+ and `--capability image` runs it directly instead of spawning any process:
222
+
223
+ ```
224
+ pai worker providers add pictures --engine image \
225
+ --url https://api.example.com/v1 --key sk-… --model example-image-model
226
+ pai worker model image example-image-model --provider pictures
227
+ pai worker run --capability image -p "a red circle on white" --out ./circle.png
228
+ ```
229
+
230
+ This POSTs `{model, prompt, size, n: 1, response_format: "b64_json"}` to
231
+ `{url}/images/generations`, decodes the PNG, and writes it — no worktree, no
232
+ MCP, no follow pane. `--capability` (alias `--for`) picks the provider by
233
+ capability instead of by class/`--provider`; see `docs/workers-config.md`'s
234
+ "Capabilities" section for the full resolution order, `pai worker
235
+ capability` (cross-provider preference) vs. `pai worker model` (one
236
+ provider's own model ids), and what happens with no image provider
237
+ configured.
238
+
218
239
  ## Daily use
219
240
 
220
241
  ```
@@ -236,8 +257,11 @@ pai worker log [all|tail|<id>] # raw streams + routing ledger
236
257
  ```
237
258
 
238
259
  Classes pick the provider for a task class: `--class implement|research|spotcheck|…`
239
- (`--role` still works as its alias). `--no-pane` suppresses the iTerm follow
240
- pane; `--provider <name>` bypasses classes entirely. If you bring your own
260
+ (`--role` still works as its alias). `--capability <name>` (alias `--for`)
261
+ picks the provider by capability instead — e.g. `--capability image` runs
262
+ the configured image engine (above) regardless of the active provider or
263
+ class. `--no-pane` suppresses the iTerm follow pane; `--provider <name>`
264
+ bypasses classes and capabilities entirely. If you bring your own
241
265
  `--append-system-prompt`, the worker contract below is added alongside it, not
242
266
  instead.
243
267
 
@@ -282,7 +306,11 @@ to the pai commands (`pai worker install` moves any previous versions to
282
306
 
283
307
  ## Routing
284
308
 
285
- A run resolves its provider as: `--provider` > `--class` > `active`.
309
+ A run resolves its provider as: `--provider` > `--capability`/a class implying
310
+ one > `--class` > `active`. `--capability` (and a class whose implied
311
+ capability is not `default` and names no provider of its own, e.g. `image`)
312
+ resolves cross-provider through `capabilities:` instead of this chain — see
313
+ `docs/workers-config.md`'s "Capabilities" section.
286
314
 
287
315
  With `active: "auto"`, providers are tried in `routing.order` (or the class's
288
316
  own `order`), skipping:
@@ -318,7 +346,7 @@ What `on` does:
318
346
  `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1`.
319
347
  - Pins the top-level `model` key to the provider's default model.
320
348
  - Saves the replaced values under `workers.fallback.saved` in
321
- `~/.claude/pai/config.json` and writes a `FALLBACK-ACTIVE.md` note into the
349
+ `~/.claude/pai/config.yaml` (or `config.json` until you run `pai config yaml`) and writes a `FALLBACK-ACTIVE.md` note into the
322
350
  workers log dir telling running sessions what to do.
323
351
 
324
352
  Notes: