@tekmidian/pai 0.37.0 → 0.38.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.
@@ -1,41 +1,63 @@
1
1
  ---
2
2
  name: Worker
3
- description: "Run, watch and route subagent workers on configured providers. USE WHEN delegating subagent work, checking on running workers, or managing worker providers."
3
+ description: "Run, watch and route subagent workers on configured providers. USE WHEN delegating subagent work, checking on running workers, or managing worker providers/classes from chat."
4
4
  ---
5
5
 
6
6
  ## Worker Skill
7
7
 
8
- USE WHEN delegating subagent work, checking on running workers, or managing worker providers.
8
+ USE WHEN delegating subagent work, checking on running workers, or managing worker providers/classes from chat.
9
9
 
10
10
  ### Delegating
11
11
 
12
12
  The Agent tool is denied when workers are on — delegate with Bash instead:
13
13
 
14
14
  ```
15
- pai worker run --label "short task label" --role research \\
15
+ pai worker run --label "short task label" --class research \\
16
16
  -p '<full, self-contained task spec>' \\
17
17
  --allowedTools 'Read,Edit,Write,Bash,Grep,Glob' --output-format json
18
18
  ```
19
19
 
20
20
  - Always run in background (run_in_background: true) and with a timeout.
21
- - Roles: implement (default quality), research (web: add WebSearch,WebFetch), spotcheck (cheap/fast model).
21
+ - Classes: draft (spec writing), plan, implement (default quality), review,
22
+ research (web: add WebSearch,WebFetch), spotcheck (cheap/fast model), simple,
23
+ complex, image. `--role` still works as an alias of `--class`.
24
+ - Anything larger than a one-file change goes through a chain:
25
+ `pai worker run --chain draft,implement …` — the draft stage turns the brief
26
+ into a spec file, implement runs with it, `--chain draft,implement,review`
27
+ adds a review pass. `--class spotcheck` for verification runs.
22
28
  - The answer is in the `result` field of the JSON it prints. Review the diff yourself.
23
29
  - `--no-pane` suppresses the iTerm follow pane; panes open automatically otherwise.
24
- - Panes run under the `pai-worker` dynamic profile (default profile's font
25
- family at `workers.pane.fontSize`, default 13); `pai worker pane <id> --check`
26
- reports the pane plus that profile's path, existence and font.
30
+ - `--agent <name>` runs a definition from ~/.claude/agents/<name>.md (the agent
31
+ library runs on workers: body becomes the system prompt, tools the allowlist,
32
+ model the class).
27
33
 
28
34
  ### Watching
29
35
 
30
- - `worker_ps` — running + last finished workers.
36
+ - `worker_ps` — running + last finished workers (chains show as trees).
31
37
  - `worker_replay` with id — the transcript of one worker.
32
38
  - CLI equivalents: `pai worker ps`, `pai worker follow <id>`.
33
39
 
34
40
  ### Routing
35
41
 
36
42
  - `worker_status` — on/off, active provider, providers, run tally.
37
- - `worker_providers` — list/add/remove/use/enable/disable/test. Adding needs
38
- name, base_url, model and a key (key file path, or a raw key which is
39
- parked in ~/.config/pai/keys/<name>, mode 0600).
40
- - `worker_roles` list/set/unset role provider[/fast].
43
+ - `worker_providers` — list/add/update/remove/use/enable/disable/test. Adding
44
+ needs name, base_url, model and a key (key file path, or a raw key which is
45
+ parked in ~/.config/pai/keys/<name>, mode 0600). update changes cost_tier
46
+ (1 cheapest 5 most expensive) and tags (code, vision, image-gen,
47
+ long-context, fast, reasoning).
48
+ - `worker_classes` — list/set/unset class → provider[/fast], or constraints
49
+ only (max_cost_tier, require_tags) so auto-routing picks a qualifying provider.
50
+ - `worker_run` — start a worker or chain from chat; returns the id immediately.
41
51
  - `worker_toggle` — off makes Agent subagents run on Anthropic again.
52
+
53
+ ### Preferences from chat (map the phrase, use the tool, never mention files)
54
+
55
+ - "use <provider> for image generation" / "route research to <provider>" →
56
+ worker_classes set <class>=<provider>. One line back.
57
+ - "prefer the flash model for simple tasks" / "cheap only for drafts" →
58
+ worker_classes set simple|draft=<provider>/fast (or a max_cost_tier). One line.
59
+ - "reviews should use a reasoning model" → worker_classes set review with
60
+ require_tags ["reasoning"] (drop the pin if one exists). One line.
61
+ - "what handles reviews" / "show the routing table" → worker_classes list
62
+ (plus worker_status for providers). One or two lines.
63
+ - Never tell the user to edit a config file — the tools do it.
@@ -190,6 +190,10 @@ Generated man pages for every `pai` command area. Read any page in the terminal
190
190
  | `pai topic check <context>` | Check whether context text has drifted to a different project. |
191
191
  | `pai update` | Update PAI from GitHub (git pull + rebuild + daemon restart). Preserves local customizations. |
192
192
  | `pai worker` | Run subagents on configured worker providers: run, ps, follow, replay, |
193
+ | `pai worker classes` | Classes: which provider serves draft / implement / review / … |
194
+ | `pai worker classes list` | List classes and their targets (default action) |
195
+ | `pai worker classes set <class> [target]` | Point a class at a provider (or provider/fast), or give only constraints: |
196
+ | `pai worker classes unset <class>` | Remove a class (runs then use the active provider) |
193
197
  | `pai worker follow [id]` | Live transcript of one worker, or of this session's running workers |
194
198
  | `pai worker install` | Migrate: Agent hook in settings.json, ~/.local/bin glm* shims, old script cleanup |
195
199
  | `pai worker log [what]` | all = ledger, tail = last ledger lines, <id> = raw event stream, none = list |
@@ -198,20 +202,17 @@ Generated man pages for every `pai` command area. Read any page in the terminal
198
202
  | `pai worker on` | Route Agent-tool subagents to workers (default when a provider exists) |
199
203
  | `pai worker pane [id]` | Open the follow pane for a worker (or one shared pane for this session) |
200
204
  | `pai worker providers` | Providers: list (default), add, remove, use, enable, disable, test |
201
- | `pai worker providers add <name>` | Add a provider; the first one also turns workers on and seeds roles. |
205
+ | `pai worker providers add <name>` | Add a provider; the first one also turns workers on and seeds classes. |
202
206
  | `pai worker providers disable <name>` | Disable a provider (auto-routing skips it; --provider still works) |
203
207
  | `pai worker providers enable <name>` | Enable a provider (also clears its cooldown) |
204
- | `pai worker providers remove <name>` | Remove a provider and any roles pointing at it |
208
+ | `pai worker providers remove <name>` | Remove a provider and any classes pointing at it |
205
209
  | `pai worker providers test [name]` | One-word pong probe through a provider (default: the active one) |
206
- | `pai worker providers use <name>` | Make this provider the active one for runs without --provider/--role |
210
+ | `pai worker providers update <name>` | Change cost tier and tags of a provider (routing constraints use these) |
211
+ | `pai worker providers use <name>` | Make this provider the active one for runs without --provider/--class |
207
212
  | `pai worker proxy [stop]` | The local Anthropic↔OpenAI proxy (loopback only); started on demand by `run`, |
208
213
  | `pai worker ps` | List workers of this session (RUNNING + FINISHED); --all for every worker |
209
214
  | `pai worker replay <id>` | Print the transcript of one finished or running worker |
210
215
  | `pai worker resume <id> <text>` | Continue a finished worker on the same provider: claude --resume <session> |
211
- | `pai worker roles` | Roles: which provider serves implement / research / spotcheck |
212
- | `pai worker roles list` | List roles and their providers (default action) |
213
- | `pai worker roles set <role> <provider[/alias]>` | Point a role at a provider, optionally its fast model (e.g. glm/fast) |
214
- | `pai worker roles unset <role>` | Remove a role (runs then use the active provider) |
215
216
  | `pai worker run [args...]` | Run one claude-code worker through the configured provider. |
216
217
  | `pai worker say <id> <text>` | Send one message to a running worker (forwarded to its open stdin) |
217
218
  | `pai worker status-line [term] [cwd]` | One-line worker summary for a status bar (empty when none in scope). |
@@ -32,7 +32,7 @@ pai worker <subcommand> [options]
32
32
  | [`pai worker off`](#pai-worker-off) | Stop routing: Agent tool runs on Anthropic again |
33
33
  | [`pai worker install`](#pai-worker-install) | Migrate: Agent hook in settings.json, ~/.local/bin glm* shims, old script cleanup |
34
34
  | [`pai worker providers`](#pai-worker-providers) | Providers: list (default), add, remove, use, enable, disable, test |
35
- | [`pai worker roles`](#pai-worker-roles) | Roles: which provider serves implement / research / spotcheck |
35
+ | [`pai worker classes`](#pai-worker-classes) | Classes: which provider serves draft / implement / review / |
36
36
 
37
37
  ### pai worker run [args...]
38
38
 
@@ -40,6 +40,8 @@ Run one claude-code worker through the configured provider.
40
40
 
41
41
  Unknown options are passed to claude verbatim (e.g. -p, --allowedTools);
42
42
  --output-format/--verbose are handled here.
43
+ --chain draft,implement[,review] runs a spec-first pipeline;
44
+ --agent <name> runs an agent definition from ~/.claude/agents.
43
45
 
44
46
  **Arguments**
45
47
 
@@ -52,7 +54,10 @@ Unknown options are passed to claude verbatim (e.g. -p, --allowedTools);
52
54
  | Option | Description | Default |
53
55
  |--------|-------------|---------|
54
56
  | `--provider <name>` | Provider to run on (default: active, else routing order) | |
55
- | `--role <role>` | Use the provider of this role (implement, research, spotcheck, ) | |
57
+ | `--class <name>` | Use the provider of this class (draft, implement, review, research, spotcheck, simple, complex, image) | |
58
+ | `--role <name>` | Alias of --class (roles were renamed to classes) | |
59
+ | `--chain <stages>` | Comma-separated stage classes, e.g. draft,implement or draft,implement,review | |
60
+ | `--agent <name>` | Run the agent definition ~/.claude/agents/<name>.md on a worker | |
56
61
  | `--model <model>` | Override the provider's model for this run | |
57
62
  | `--label <text>` | Short task label shown in ps / follow / status line | |
58
63
  | `--mcp <names>` | MCP servers/sets this worker may use (comma-separated; see `pai worker mcp`) | |
@@ -124,7 +129,7 @@ Open the follow pane for a worker (or one shared pane for this session)
124
129
 
125
130
  | Option | Description | Default |
126
131
  |--------|-------------|---------|
127
- | `--check` | Only report whether the pane is open, plus the profile file's path and font | |
132
+ | `--check` | Only report whether the pane is open, plus the profile file's path, font, and the hosting window's bounds | |
128
133
 
129
134
 
130
135
  ### pai worker log [what]
@@ -235,7 +240,7 @@ Providers: list (default), add, remove, use, enable, disable, test
235
240
 
236
241
  ### pai worker providers add <name>
237
242
 
238
- Add a provider; the first one also turns workers on and seeds roles.
243
+ Add a provider; the first one also turns workers on and seeds classes.
239
244
 
240
245
  Example: pai worker providers add glm --base-url https://…/anthropic \
241
246
  --key-file ~/.config/zai/api_key --model glm-5.3 --fast-model glm-5.3-flash
@@ -263,11 +268,31 @@ Codex (ChatGPT plan): --engine codex — runs through the Codex CLI.
263
268
  | `--engine <engine>` | claude (default) or codex — codex runs `codex exec --json` | |
264
269
  | `--context-window <tokens>` | Context window for the meter (default 200000; init event overrides) | |
265
270
  | `--quota-probe <url>` | URL whose JSON first number is the quota percent (0-100) | |
271
+ | `--cost-tier <1-5>` | Cost tier 1 (cheapest) … 5 (most expensive; default 3) | |
272
+ | `--tags <tags>` | Capability tags, comma-separated (from: code, vision, image-gen, long-context, fast, reasoning) | `` |
273
+
274
+
275
+ ### pai worker providers update <name>
276
+
277
+ Change cost tier and tags of a provider (routing constraints use these)
278
+
279
+ **Arguments**
280
+
281
+ | Argument | Kind |
282
+ |----------|------|
283
+ | `<name>` | required |
284
+
285
+ **Options**
286
+
287
+ | Option | Description | Default |
288
+ |--------|-------------|---------|
289
+ | `--cost-tier <1-5>` | Cost tier 1 (cheapest) … 5 (most expensive) | |
290
+ | `--tags <tags>` | Capability tags, comma-separated (from: code, vision, image-gen, long-context, fast, reasoning); --tags '' clears | `` |
266
291
 
267
292
 
268
293
  ### pai worker providers remove <name>
269
294
 
270
- Remove a provider and any roles pointing at it
295
+ Remove a provider and any classes pointing at it
271
296
 
272
297
  **Arguments**
273
298
 
@@ -278,7 +303,7 @@ Remove a provider and any roles pointing at it
278
303
 
279
304
  ### pai worker providers use <name>
280
305
 
281
- Make this provider the active one for runs without --provider/--role
306
+ Make this provider the active one for runs without --provider/--class
282
307
 
283
308
  **Arguments**
284
309
 
@@ -320,37 +345,49 @@ One-word pong probe through a provider (default: the active one)
320
345
  | `[name]` | optional |
321
346
 
322
347
 
323
- ### pai worker roles
348
+ ### pai worker classes
349
+
350
+ Classes: which provider serves draft / implement / review / …
324
351
 
325
- Roles: which provider serves implement / research / spotcheck
326
352
 
353
+ ### pai worker classes list
327
354
 
328
- ### pai worker roles list
355
+ List classes and their targets (default action)
329
356
 
330
- List roles and their providers (default action)
331
357
 
358
+ ### pai worker classes set <class> [target]
332
359
 
333
- ### pai worker roles set <role> <provider[/alias]>
360
+ Point a class at a provider (or provider/fast), or give only constraints:
334
361
 
335
- Point a role at a provider, optionally its fast model (e.g. glm/fast)
362
+ classes set research --max-cost-tier 2 --require-tags long-context,reasoning
336
363
 
337
364
  **Arguments**
338
365
 
339
366
  | Argument | Kind |
340
367
  |----------|------|
341
- | `<role>` | required |
342
- | `<provider[/alias]>` | required |
368
+ | `<class>` | required |
369
+ | `[target]` | optional |
370
+
371
+ **Options**
372
+
373
+ | Option | Description | Default |
374
+ |--------|-------------|---------|
375
+ | `--provider <name>` | Pin the class to this provider (object form) | |
376
+ | `--mcp <names>` | MCP servers/sets for runs of this class (comma-separated) | |
377
+ | `--max-cost-tier <1-5>` | Auto-routing considers only providers up to this cost tier | |
378
+ | `--require-tags <tags>` | Auto-routing needs these tags (comma-separated) | |
379
+ | `--order <providers>` | Per-class routing order overriding workers.routing.order (comma-separated) | |
343
380
 
344
381
 
345
- ### pai worker roles unset <role>
382
+ ### pai worker classes unset <class>
346
383
 
347
- Remove a role (runs then use the active provider)
384
+ Remove a class (runs then use the active provider)
348
385
 
349
386
  **Arguments**
350
387
 
351
388
  | Argument | Kind |
352
389
  |----------|------|
353
- | `<role>` | required |
390
+ | `<class>` | required |
354
391
 
355
392
 
356
393
  ## See also
package/docs/worker.md CHANGED
@@ -32,22 +32,26 @@ main session (Anthropic) workers (configured provider)
32
32
  "keyFile": "~/.config/zai/api_key",
33
33
  "models": { "default": "glm-5.3", "fast": "glm-5.3-flash" },
34
34
  "env": { "API_TIMEOUT_MS": "3000000" },
35
- "contextWindow": 200000
35
+ "contextWindow": 200000,
36
+ "costTier": 2,
37
+ "tags": ["code", "long-context"]
36
38
  },
37
39
  "oai": {
38
40
  "protocol": "openai",
39
41
  "upstreamUrl": "https://api.openai.com/v1",
40
42
  "keyFile": "~/.config/pai/keys/oai",
41
- "models": { "default": "gpt-5.2", "fast": "gpt-5.2-mini" }
43
+ "models": { "default": "gpt-5.2", "fast": "gpt-5.2-mini" },
44
+ "costTier": 4,
45
+ "tags": ["reasoning", "vision"]
42
46
  },
43
47
  "codexprov": {
44
48
  "engine": "codex",
45
49
  "models": { "default": "gpt-5.2-codex" }
46
50
  }
47
51
  },
48
- "roles": {
52
+ "classes": {
49
53
  "implement": "glm",
50
- "research": "glm",
54
+ "research": { "maxCostTier": 2, "requireTags": ["long-context"] },
51
55
  "spotcheck": "glm/fast",
52
56
  "docs": { "provider": "glm", "mcp": ["office"] }
53
57
  },
@@ -70,8 +74,12 @@ main session (Anthropic) workers (configured provider)
70
74
  Code (see below).
71
75
  - `contextWindow` overrides the context-meter window when the endpoint's
72
76
  init event does not announce one (default 200 000).
73
- - A role target is `"provider[/model]"` or an object with `provider` and a
74
- `mcp` allowlist applied on top of `--mcp`.
77
+ - `costTier` (1 cheapest 5 most expensive, default 3) and `tags` (from:
78
+ `code`, `vision`, `image-gen`, `long-context`, `fast`, `reasoning`) describe
79
+ a provider; classes use them to constrain routing (next section).
80
+ - A class target is `"provider[/model]"` or an object with `provider` and a
81
+ `mcp` allowlist applied on top of `--mcp`, or an object with only routing
82
+ constraints (`maxCostTier`, `requireTags`, `order`).
75
83
 
76
84
  Or add one from the CLI:
77
85
 
@@ -80,19 +88,64 @@ pai worker providers add glm \
80
88
  --base-url https://api.z.ai/api/anthropic \
81
89
  --key-file ~/.config/zai/api_key \
82
90
  --model glm-5.3 --fast-model glm-5.3-flash \
83
- --env API_TIMEOUT_MS=3000000
91
+ --env API_TIMEOUT_MS=3000000 \
92
+ --cost-tier 2 --tags code,long-context
84
93
  pai worker providers add oai \
85
94
  --upstream-url https://api.openai.com/v1 \
86
95
  --key-file ~/.config/pai/keys/oai --model gpt-5.2
96
+ pai worker providers update glm --cost-tier 1 # tiers/tags change later
87
97
  ```
88
98
 
89
99
  The first provider also sets `enabled: true`, makes itself active and seeds
90
- the three roles. Then:
100
+ the nine classes. Then:
91
101
 
92
102
  ```
93
103
  pai worker install # Agent hook in settings.json + glm* shims + cleanup
94
104
  ```
95
105
 
106
+ ## Task classes
107
+
108
+ Roles were renamed to **classes** — task classes pick the provider for a kind
109
+ of work. The nine standard classes: `draft`, `plan`, `implement`, `review`,
110
+ `research`, `spotcheck`, `simple`, `complex`, `image` (any other name can be
111
+ defined too). Configs with the old `roles` key keep parsing; the key migrates
112
+ to `classes` on the first write.
113
+
114
+ ```
115
+ pai worker classes # list
116
+ pai worker classes set implement glm # pin a provider
117
+ pai worker classes set spotcheck glm/fast # …its fast model
118
+ pai worker classes set research --max-cost-tier 2 --require-tags long-context
119
+ pai worker classes unset research
120
+ ```
121
+
122
+ Every provider carries a **cost tier** (1 cheapest … 5 most expensive,
123
+ default 3) and **tags** (`code`, `vision`, `image-gen`, `long-context`,
124
+ `fast`, `reasoning`). A class resolves its provider as:
125
+
126
+ 1. `--provider` (explicit flag) wins;
127
+ 2. else the class mapping when it pins a provider;
128
+ 3. else auto-routing (see below) restricted to providers within the class's
129
+ `maxCostTier` and carrying all its `requireTags`;
130
+ 4. nothing qualifies → the run fails with a message listing why every
131
+ provider was excluded.
132
+
133
+ `classes.<name>.order` overrides `routing.order` for that class. Cooldown and
134
+ quota logic is unchanged.
135
+
136
+ ### Preferences from chat
137
+
138
+ The Worker skill maps phrases onto the MCP tools — the answer is one or two
139
+ lines, and the user is never told to edit a file:
140
+
141
+ - "use X for image generation" / "route research to kimi" →
142
+ `worker_classes set <class>=<provider>`
143
+ - "prefer the flash model for simple tasks" / "cheap only for drafts" →
144
+ `worker_classes set simple|draft=<provider>/fast` (or `max_cost_tier`)
145
+ - "reviews should use a reasoning model" → `worker_classes set review` with
146
+ `require_tags: ["reasoning"]`
147
+ - "what handles reviews" / "show the routing table" → `worker_classes list`
148
+
96
149
  ## The proxy (OpenAI-protocol providers)
97
150
 
98
151
  A provider with `protocol: "openai"` cannot be talked to by Claude Code
@@ -135,6 +188,8 @@ so it is unavailable for codex workers (their thread id is kept, but
135
188
  pai worker run --label "fix black buttons" -p '<task spec>' \
136
189
  --allowedTools 'Read,Edit,Write,Bash,Grep,Glob' --output-format json \
137
190
  --mcp office
191
+ pai worker run --chain draft,implement -p '<brief>' # spec-first (below)
192
+ pai worker run --agent engineer -p '<task>' # agent library (below)
138
193
  pai worker ps # this session's workers
139
194
  pai worker follow [id] # live transcript (type to talk to it)
140
195
  pai worker replay <id> # transcript of one worker
@@ -145,10 +200,46 @@ pai worker proxy [--port N|stop] # the translating proxy, by hand
145
200
  pai worker log [all|tail|<id>] # raw streams + routing ledger
146
201
  ```
147
202
 
148
- Roles pick the provider for a task class: `--role implement|research|spotcheck`.
149
- `--no-pane` suppresses the iTerm follow pane; `--provider <name>` bypasses
150
- roles entirely. If you bring your own `--append-system-prompt`, the worker
151
- contract below is added alongside it, not instead.
203
+ Classes pick the provider for a task class: `--class implement|research|spotcheck|…`
204
+ (`--role` still works as its alias). `--no-pane` suppresses the iTerm follow
205
+ pane; `--provider <name>` bypasses classes entirely. If you bring your own
206
+ `--append-system-prompt`, the worker contract below is added alongside it, not
207
+ instead.
208
+
209
+ ## Chains (draft → implement → review)
210
+
211
+ ```
212
+ pai worker run --chain draft,implement -p '<brief>'
213
+ pai worker run --chain draft,implement,review -p '<brief>' # + review pass
214
+ ```
215
+
216
+ - The **draft** class turns the brief into a full spec file under
217
+ `<logDir>/specs/<chain id>.md` — goal, constraints, files likely touched,
218
+ acceptance checks, verification commands. It reads the repository first and
219
+ implements nothing.
220
+ - **implement** (or any other stage class) runs with that spec as its prompt
221
+ and the original brief attached.
222
+ - **review** reads the spec and the working-tree diff and produces the
223
+ structured report.
224
+ - Each stage is its own worker: own id, own pane, `parent` set to the chain
225
+ id — `ps` shows the chain as a tree.
226
+ - A stage that fails stops the chain (the exit code is the first failing
227
+ stage's); a draft that produces no spec stops it with a message telling the
228
+ caller to write the spec and re-run without the draft stage.
229
+ - `--class` alongside `--chain` overrides the class of every stage; `--label`
230
+ names the chain (stages render as `<label> · <stage>`).
231
+
232
+ ## Agent definitions as workers
233
+
234
+ `pai worker run --agent <name>` loads `~/.claude/agents/<name>.md` and runs it
235
+ on a worker: the front matter's `model` maps to a class (haiku→simple,
236
+ sonnet→implement, opus→complex — `--class` overrides), `tools` becomes
237
+ `--allowedTools`, and the body is passed via `--append-system-prompt` (your
238
+ own flags on the command line still win). The label defaults to
239
+ `<agent>: <first 50 chars of prompt>`.
240
+
241
+ The agent library therefore runs on workers, not on the orchestrator's
242
+ Anthropic account — same hooks, same classes, same `ps`/`follow`/`replay`.
152
243
 
153
244
  The old habits keep working: `glm`, `glm-run`, `glm-ps`, `glm-log` are shims
154
245
  to the pai commands (`pai worker install` moves any previous versions to
@@ -156,13 +247,19 @@ to the pai commands (`pai worker install` moves any previous versions to
156
247
 
157
248
  ## Routing
158
249
 
159
- A run resolves its provider as: `--provider` > `--role` > `active`.
250
+ A run resolves its provider as: `--provider` > `--class` > `active`.
160
251
 
161
- With `active: "auto"`, providers are tried in `routing.order`, skipping:
252
+ With `active: "auto"`, providers are tried in `routing.order` (or the class's
253
+ own `order`), skipping:
162
254
 
163
255
  - disabled providers,
164
256
  - providers in a cooldown (set for `cooldownMinutes` after a quota failure),
165
- - providers whose `quotaProbe` URL reports ≥ `quotaSkipAt` (default 95).
257
+ - providers whose `quotaProbe` URL reports ≥ `quotaSkipAt` (default 95),
258
+ - providers above the class's `maxCostTier` or missing one of its
259
+ `requireTags`.
260
+
261
+ Nothing qualifying fails the run with the exclusion reason of every provider
262
+ in the order.
166
263
 
167
264
  A quota failure before the first tool call is re-run on the next provider and
168
265
  logged as `WORKER-REROUTE`. `pai worker providers enable <name>` clears a
@@ -213,9 +310,30 @@ stdin closes two seconds later unless another message arrives — after that
213
310
 
214
311
  `pai worker resume <id> "<text>"` continues the same Claude session (the id
215
312
  recorded from the init event) on the same provider, labelled `↩ <original>`,
216
- and prints a fresh worker id with `--print-id`. A pane running `follow` reads
217
- its own stdin the same way: type to say while it runs, or to resume after it
218
- finished.
313
+ and prints a fresh worker id with `--print-id`.
314
+
315
+ A `follow <id>` pane on a TTY is a chat, not a tail: the transcript lives in
316
+ a scroll region that ends two rows above the pane's bottom, the last two rows
317
+ are fixed — the prompt row (`› `, full readline editing: arrows, backspace,
318
+ Ctrl-A/E, Ctrl-U) and the ticker row — and every transcript line is inserted
319
+ above them with a save-cursor / restore-cursor write, so the cursor never
320
+ leaves the prompt. Enter sends the line: said to the worker while it runs,
321
+ `resume`d into the same session once it has finished (the pane follows the
322
+ fresh run id and keeps the chat). The sent line is echoed into the transcript
323
+ as a `»` row with its time gutter, exactly once — the mirrored `operator`
324
+ event is swallowed. `/help` lists the commands:
325
+
326
+ | key | action |
327
+ | --- | --- |
328
+ | `/quit` | close the pane |
329
+ | `/resume <text>` | resume the finished worker with `<text>` |
330
+ | `/status` | one-line worker status |
331
+ | anything else | a message — said, or resumed |
332
+
333
+ Ctrl-C on an empty prompt leaves the pane, on a draft it clears the prompt;
334
+ Ctrl-D leaves. The auto-exit countdown never fires while the prompt holds
335
+ unsent text. Without a TTY (piped output) the pane keeps the plain scrolling
336
+ behaviour — no prompt row, no ticker, stdin still the operator channel.
219
337
 
220
338
  ### Context meter
221
339
 
@@ -239,7 +357,7 @@ pai worker run --mcp office … # a set, or names: --mcp memory,github
239
357
  `--mcp` takes server names and/or `mcpSets` names (comma-separated,
240
358
  repeatable); the filtered config is written from `~/.claude.json`'s
241
359
  `mcpServers` to `<logDir>/<id>.mcp.json` and passed with
242
- `--strict-mcp-config --mcp-config`. Role targets may add `"mcp": ["office"]`
360
+ `--strict-mcp-config --mcp-config`. Class targets may add `"mcp": ["office"]`
243
361
  on top. An unknown name fails fast, listing what exists;
244
362
  `pai worker mcp list` shows servers and sets. A caller-provided
245
363
  `--mcp-config` always wins; MCP is chosen at launch, not mid-run.
@@ -263,6 +381,17 @@ separator when the day changes) and, on a TTY, a liveness line
263
381
  erased before the next event. `replay` shows a finished transcript with the
264
382
  same gutter.
265
383
 
384
+ The pane wraps rows itself at the terminal width (re-read on resize, so a
385
+ narrower pane re-wraps what arrives after the resize): breaks on whitespace
386
+ where it can, hard-wraps a long token otherwise, never splits an ANSI escape
387
+ (it measures printable columns, not string length), and carries diff colours
388
+ onto every continuation row. Each continuation row carries a blank-time
389
+ gutter with the `│` bar kept — the bar runs unbroken down the pane and no
390
+ content ever lands left of it. In the chat layout the transcript scrolls
391
+ inside an ANSI scroll region (`ESC[1;rows-2r`, reset on exit and re-set on
392
+ resize) so the prompt and ticker rows stay fixed; piped output keeps the
393
+ terminal's own wrapping instead.
394
+
266
395
  The pane command is `exec pai worker follow …` so the pane holds exactly one
267
396
  process — signals reach the follow directly, and when the worker finishes
268
397
  the pane counts down its `auto-exit` (default 60 s, `pane.autoExitSecs`).
@@ -288,12 +417,14 @@ background instead. Decisions are ledgered (`DENIED-ANTHROPIC-AGENT`,
288
417
 
289
418
  ## MCP tools
290
419
 
291
- `worker_status`, `worker_providers` (list/add/remove/use/enable/disable/test),
292
- `worker_roles`, `worker_toggle`, `worker_ps`, `worker_replay`,
293
- `worker_say` (message a running worker), `worker_resume` (continue a
294
- finished one) the same library the CLI calls. `worker_providers add`
295
- accepts a raw `key`, parks it in `~/.config/pai/keys/<name>` (mode 0600) and
296
- stores only the path.
420
+ `worker_status`, `worker_providers`
421
+ (list/add/update/remove/use/enable/disable/test `update` changes
422
+ `cost_tier`/`tags`), `worker_classes` (list/set/unset), `worker_run` (start a
423
+ worker or chain from chat, returns the id immediately), `worker_toggle`,
424
+ `worker_ps`, `worker_replay`, `worker_say` (message a running worker),
425
+ `worker_resume` (continue a finished one) — the same library the CLI calls.
426
+ `worker_providers add` accepts a raw `key`, parks it in
427
+ `~/.config/pai/keys/<name>` (mode 0600) and stores only the path.
297
428
 
298
429
  ## Status line
299
430
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekmidian/pai",
3
- "version": "0.37.0",
3
+ "version": "0.38.0",
4
4
  "description": "PAI Knowledge OS — Personal AI Infrastructure with federated memory and project management",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",