@tekmidian/pai 0.37.0 → 0.39.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.
- package/dist/{auto-route-DM7GhJ8y.mjs → auto-route-BlWOWT4z.mjs} +2 -2
- package/dist/{auto-route-DM7GhJ8y.mjs.map → auto-route-BlWOWT4z.mjs.map} +1 -1
- package/dist/{providers-sXcK5bDZ.mjs → chain-CTtHligI.mjs} +1040 -782
- package/dist/chain-CTtHligI.mjs.map +1 -0
- package/dist/cli/index.mjs +4 -3
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/program.mjs +4 -3
- package/dist/{clusters-Do4tEGyc.mjs → clusters-wlK0w41E.mjs} +1 -1
- package/dist/{clusters-Do4tEGyc.mjs.map → clusters-wlK0w41E.mjs.map} +1 -1
- package/dist/daemon/index.mjs +7 -7
- package/dist/{daemon-CGg1VCbA.mjs → daemon-CTkN_Vn8.mjs} +25 -25
- package/dist/{daemon-CGg1VCbA.mjs.map → daemon-CTkN_Vn8.mjs.map} +1 -1
- package/dist/{daemon-DsGGiIJM.mjs → daemon-CmHHmKpg.mjs} +7 -7
- package/dist/daemon-mcp/index.mjs +207 -34
- package/dist/daemon-mcp/index.mjs.map +1 -1
- package/dist/{detector-CMap-9vw.mjs → detector-Bwk_4Pk4.mjs} +1 -1
- package/dist/{detector-CMap-9vw.mjs.map → detector-Bwk_4Pk4.mjs.map} +1 -1
- package/dist/detector-DO730Zq0.mjs +5 -0
- package/dist/{factory-DD2T33C9.mjs → factory-A9x-T2Kg.mjs} +5 -5
- package/dist/{factory-DD2T33C9.mjs.map → factory-A9x-T2Kg.mjs.map} +1 -1
- package/dist/factory-BD-np0Vd.mjs +3 -0
- package/dist/hooks/route-agents-to-worker.mjs +112 -20
- package/dist/hooks/route-agents-to-worker.mjs.map +2 -2
- package/dist/hooks/worker-proxy.mjs +110 -18
- package/dist/hooks/worker-proxy.mjs.map +2 -2
- package/dist/hooks/worker-status-line.mjs +176 -23
- package/dist/hooks/worker-status-line.mjs.map +4 -4
- package/dist/{indexer-backend-Cox9BCo-.mjs → indexer-backend-TG64CCQC.mjs} +1 -1
- package/dist/{indexer-backend-Cox9BCo-.mjs.map → indexer-backend-TG64CCQC.mjs.map} +1 -1
- package/dist/{latent-ideas-BC1oINZ-.mjs → latent-ideas-B7wq75Pt.mjs} +2 -2
- package/dist/{latent-ideas-BC1oINZ-.mjs.map → latent-ideas-B7wq75Pt.mjs.map} +1 -1
- package/dist/{link-boost-QFLrJwD6.mjs → link-boost-HkG7JWZR.mjs} +1 -1
- package/dist/{link-boost-QFLrJwD6.mjs.map → link-boost-HkG7JWZR.mjs.map} +1 -1
- package/dist/{neighborhood-D9MJ1c8f.mjs → neighborhood-lThN-MaQ.mjs} +1 -1
- package/dist/{neighborhood-D9MJ1c8f.mjs.map → neighborhood-lThN-MaQ.mjs.map} +1 -1
- package/dist/{note-context-d1wT_-GA.mjs → note-context-b6k0mAKi.mjs} +1 -1
- package/dist/{note-context-d1wT_-GA.mjs.map → note-context-b6k0mAKi.mjs.map} +1 -1
- package/dist/planner-BDI7bE9B.mjs +243 -0
- package/dist/planner-BDI7bE9B.mjs.map +1 -0
- package/dist/{postgres--BjPtLa0.mjs → postgres-mW1n7Vi1.mjs} +1 -1
- package/dist/{postgres--BjPtLa0.mjs.map → postgres-mW1n7Vi1.mjs.map} +1 -1
- package/dist/{program-CEIHn_Ma.mjs → program-DXBwJV7h.mjs} +274 -65
- package/dist/program-DXBwJV7h.mjs.map +1 -0
- package/dist/providers-FYkZjn_C.mjs +1405 -0
- package/dist/providers-FYkZjn_C.mjs.map +1 -0
- package/dist/{query-feedback-BUJxgw5B.mjs → query-feedback-BV4CcxqS.mjs} +1 -1
- package/dist/{query-feedback-BUJxgw5B.mjs.map → query-feedback-BV4CcxqS.mjs.map} +1 -1
- package/dist/query-feedback-DSVyHtrG.mjs +3 -0
- package/dist/router-Bk77E7hj.mjs +3 -0
- package/dist/{router-DK_sLsUL.mjs → router-DcHKnEPa.mjs} +1 -1
- package/dist/{router-DK_sLsUL.mjs.map → router-DcHKnEPa.mjs.map} +1 -1
- package/dist/skills/Worker/SKILL.md +34 -12
- package/dist/{sources-Bi7--33T.mjs → sources-kLnQsNrW.mjs} +1 -1
- package/dist/{sources-Bi7--33T.mjs.map → sources-kLnQsNrW.mjs.map} +1 -1
- package/dist/{sqlite-DtaL1glm.mjs → sqlite-BenGr3UP.mjs} +1 -1
- package/dist/{sqlite-DtaL1glm.mjs.map → sqlite-BenGr3UP.mjs.map} +1 -1
- package/dist/{state-BY2L6-vX.mjs → state-CAeyOdfq.mjs} +1 -1
- package/dist/{state-BY2L6-vX.mjs.map → state-CAeyOdfq.mjs.map} +1 -1
- package/dist/{state-8Hm9E4tW.mjs → state-Ca9F_sZc.mjs} +1 -1
- package/dist/{themes-BN0a2duq.mjs → themes-BI4GMRP9.mjs} +1 -1
- package/dist/{themes-BN0a2duq.mjs.map → themes-BI4GMRP9.mjs.map} +1 -1
- package/dist/{tools-CGPqpU3A.mjs → tools-Bp7hj6OW.mjs} +1 -1
- package/dist/{tools-y2bJpKom.mjs → tools-DGcB3o_S.mjs} +13 -13
- package/dist/{tools-y2bJpKom.mjs.map → tools-DGcB3o_S.mjs.map} +1 -1
- package/dist/{trace-h23JCcFD.mjs → trace-bobARFEX.mjs} +1 -1
- package/dist/{trace-h23JCcFD.mjs.map → trace-bobARFEX.mjs.map} +1 -1
- package/dist/{vault-indexer-DgsPjMgs.mjs → vault-indexer-C3OfXTNF.mjs} +1 -1
- package/dist/{vault-indexer-DgsPjMgs.mjs.map → vault-indexer-C3OfXTNF.mjs.map} +1 -1
- package/dist/{work-queue-worker-gsKd2LJa.mjs → work-queue-worker-DW8lz-Oo.mjs} +3 -3
- package/dist/{work-queue-worker-Dva_v_pI.mjs → work-queue-worker-R7UGIag_.mjs} +3 -3
- package/dist/{work-queue-worker-Dva_v_pI.mjs.map → work-queue-worker-R7UGIag_.mjs.map} +1 -1
- package/dist/{zettelkasten-vo7psPdT.mjs → zettelkasten-m5QPtb-L.mjs} +3 -3
- package/dist/{zettelkasten-vo7psPdT.mjs.map → zettelkasten-m5QPtb-L.mjs.map} +1 -1
- package/docs/commands/README.md +12 -7
- package/docs/commands/worker.md +110 -17
- package/docs/worker.md +244 -25
- package/package.json +1 -1
- package/src/hooks/ts/pre-tool-use/route-agents-to-worker.ts +2 -2
- package/dist/detector-DtLExmHN.mjs +0 -5
- package/dist/factory-BXzqRYVZ.mjs +0 -3
- package/dist/program-CEIHn_Ma.mjs.map +0 -1
- package/dist/providers-sXcK5bDZ.mjs.map +0 -1
- package/dist/query-feedback-DhyLOe5S.mjs +0 -3
- package/dist/router-1zi8jiNF.mjs +0 -3
- /package/dist/{main-resolver-IhZo4pI0.mjs → main-resolver-D6IImXvF.mjs} +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as PaiClient } from "../ipc-client-BmypMNYk.mjs";
|
|
3
3
|
import { o as loadConfig } from "../config-B64vFg14.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { B as workersLogDir, F as ledgerSummary, J as readWorkersSection, M as loadStatuses, a as testProvider, g as sayToWorker, h as readInbox, i as runWorker, j as loadStatus, k as alive, m as handoffFromInside, t as runChain, z as ledgerPath } from "../chain-CTtHligI.mjs";
|
|
5
|
+
import { a as setClass, c as unsetClass, f as psOutput, i as removeProvider, l as updateProvider, n as classTargetText, o as setProviderEnabled, p as replayOutput, r as describeProviders, s as setWorkersEnabled, t as addProvider, u as useProvider } from "../providers-FYkZjn_C.mjs";
|
|
5
6
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
8
|
|
|
@@ -1220,6 +1221,10 @@ const $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
|
|
|
1220
1221
|
return payload;
|
|
1221
1222
|
};
|
|
1222
1223
|
});
|
|
1224
|
+
const $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
1225
|
+
$ZodType.init(inst, def);
|
|
1226
|
+
inst._zod.parse = (payload) => payload;
|
|
1227
|
+
});
|
|
1223
1228
|
function handleArrayResult(result, final, index) {
|
|
1224
1229
|
if (result.issues.length) final.issues.push(...prefixIssues(index, result.issues));
|
|
1225
1230
|
final.value[index] = result.value;
|
|
@@ -2084,6 +2089,10 @@ function _boolean(Class, params) {
|
|
|
2084
2089
|
});
|
|
2085
2090
|
}
|
|
2086
2091
|
/* @__NO_SIDE_EFFECTS__ */
|
|
2092
|
+
function _unknown(Class) {
|
|
2093
|
+
return new Class({ type: "unknown" });
|
|
2094
|
+
}
|
|
2095
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
2087
2096
|
function _lt(value, params) {
|
|
2088
2097
|
return new $ZodCheckLessThan({
|
|
2089
2098
|
check: "less_than",
|
|
@@ -2646,6 +2655,7 @@ const numberProcessor = (schema, ctx, _json, _params) => {
|
|
|
2646
2655
|
const booleanProcessor = (_schema, _ctx, json, _params) => {
|
|
2647
2656
|
json.type = "boolean";
|
|
2648
2657
|
};
|
|
2658
|
+
const unknownProcessor = (_schema, _ctx, _json, _params) => {};
|
|
2649
2659
|
const enumProcessor = (schema, _ctx, json, _params) => {
|
|
2650
2660
|
const def = schema._zod.def;
|
|
2651
2661
|
const values = getEnumValues(def.entries);
|
|
@@ -3133,6 +3143,14 @@ const ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
|
|
|
3133
3143
|
function boolean(params) {
|
|
3134
3144
|
return _boolean(ZodBoolean, params);
|
|
3135
3145
|
}
|
|
3146
|
+
const ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
3147
|
+
$ZodUnknown.init(inst, def);
|
|
3148
|
+
ZodType.init(inst, def);
|
|
3149
|
+
inst._zod.processJSONSchema = (ctx, json, params) => unknownProcessor(inst, ctx, json, params);
|
|
3150
|
+
});
|
|
3151
|
+
function unknown() {
|
|
3152
|
+
return _unknown(ZodUnknown);
|
|
3153
|
+
}
|
|
3136
3154
|
const ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
|
|
3137
3155
|
$ZodArray.init(inst, def);
|
|
3138
3156
|
ZodType.init(inst, def);
|
|
@@ -4524,40 +4542,62 @@ const worker = {
|
|
|
4524
4542
|
description: "Run, watch and route subagent workers on configured providers",
|
|
4525
4543
|
content: `## Worker Skill
|
|
4526
4544
|
|
|
4527
|
-
USE WHEN delegating subagent work, checking on running workers, or managing worker providers.
|
|
4545
|
+
USE WHEN delegating subagent work, checking on running workers, or managing worker providers/classes from chat.
|
|
4528
4546
|
|
|
4529
4547
|
### Delegating
|
|
4530
4548
|
|
|
4531
4549
|
The Agent tool is denied when workers are on — delegate with Bash instead:
|
|
4532
4550
|
|
|
4533
4551
|
\`\`\`
|
|
4534
|
-
pai worker run --label "short task label" --
|
|
4552
|
+
pai worker run --label "short task label" --class research \\
|
|
4535
4553
|
-p '<full, self-contained task spec>' \\
|
|
4536
4554
|
--allowedTools 'Read,Edit,Write,Bash,Grep,Glob' --output-format json
|
|
4537
4555
|
\`\`\`
|
|
4538
4556
|
|
|
4539
4557
|
- Always run in background (run_in_background: true) and with a timeout.
|
|
4540
|
-
-
|
|
4558
|
+
- Classes: draft (spec writing), plan, implement (default quality), review,
|
|
4559
|
+
research (web: add WebSearch,WebFetch), spotcheck (cheap/fast model), simple,
|
|
4560
|
+
complex, image. \`--role\` still works as an alias of \`--class\`.
|
|
4561
|
+
- Anything larger than a one-file change goes through a chain:
|
|
4562
|
+
\`pai worker run --chain draft,implement …\` — the draft stage turns the brief
|
|
4563
|
+
into a spec file, implement runs with it, \`--chain draft,implement,review\`
|
|
4564
|
+
adds a review pass. \`--class spotcheck\` for verification runs.
|
|
4541
4565
|
- The answer is in the \`result\` field of the JSON it prints. Review the diff yourself.
|
|
4542
4566
|
- \`--no-pane\` suppresses the iTerm follow pane; panes open automatically otherwise.
|
|
4543
|
-
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4567
|
+
- \`--agent <name>\` runs a definition from ~/.claude/agents/<name>.md (the agent
|
|
4568
|
+
library runs on workers: body becomes the system prompt, tools the allowlist,
|
|
4569
|
+
model the class).
|
|
4546
4570
|
|
|
4547
4571
|
### Watching
|
|
4548
4572
|
|
|
4549
|
-
- \`worker_ps\` — running + last finished workers.
|
|
4573
|
+
- \`worker_ps\` — running + last finished workers (chains show as trees).
|
|
4550
4574
|
- \`worker_replay\` with id — the transcript of one worker.
|
|
4551
4575
|
- CLI equivalents: \`pai worker ps\`, \`pai worker follow <id>\`.
|
|
4552
4576
|
|
|
4553
4577
|
### Routing
|
|
4554
4578
|
|
|
4555
4579
|
- \`worker_status\` — on/off, active provider, providers, run tally.
|
|
4556
|
-
- \`worker_providers\` — list/add/remove/use/enable/disable/test. Adding
|
|
4557
|
-
name, base_url, model and a key (key file path, or a raw key which is
|
|
4558
|
-
parked in ~/.config/pai/keys/<name>, mode 0600).
|
|
4559
|
-
|
|
4560
|
-
-
|
|
4580
|
+
- \`worker_providers\` — list/add/update/remove/use/enable/disable/test. Adding
|
|
4581
|
+
needs name, base_url, model and a key (key file path, or a raw key which is
|
|
4582
|
+
parked in ~/.config/pai/keys/<name>, mode 0600). update changes cost_tier
|
|
4583
|
+
(1 cheapest … 5 most expensive) and tags (code, vision, image-gen,
|
|
4584
|
+
long-context, fast, reasoning).
|
|
4585
|
+
- \`worker_classes\` — list/set/unset class → provider[/fast], or constraints
|
|
4586
|
+
only (max_cost_tier, require_tags) so auto-routing picks a qualifying provider.
|
|
4587
|
+
- \`worker_run\` — start a worker or chain from chat; returns the id immediately.
|
|
4588
|
+
- \`worker_toggle\` — off makes Agent subagents run on Anthropic again.
|
|
4589
|
+
|
|
4590
|
+
### Preferences from chat (map the phrase, use the tool, never mention files)
|
|
4591
|
+
|
|
4592
|
+
- "use <provider> for image generation" / "route research to <provider>" →
|
|
4593
|
+
worker_classes set <class>=<provider>. One line back.
|
|
4594
|
+
- "prefer the flash model for simple tasks" / "cheap only for drafts" →
|
|
4595
|
+
worker_classes set simple|draft=<provider>/fast (or a max_cost_tier). One line.
|
|
4596
|
+
- "reviews should use a reasoning model" → worker_classes set review with
|
|
4597
|
+
require_tags ["reasoning"] (drop the pin if one exists). One line.
|
|
4598
|
+
- "what handles reviews" / "show the routing table" → worker_classes list
|
|
4599
|
+
(plus worker_status for providers). One or two lines.
|
|
4600
|
+
- Never tell the user to edit a config file — the tools do it.`
|
|
4561
4601
|
};
|
|
4562
4602
|
|
|
4563
4603
|
//#endregion
|
|
@@ -5718,7 +5758,8 @@ async function startShim() {
|
|
|
5718
5758
|
});
|
|
5719
5759
|
server.tool("worker_status", [
|
|
5720
5760
|
"Show the worker system state: on/off, active provider, configured providers,",
|
|
5721
|
-
"roles,
|
|
5761
|
+
"roles, today's run tally from the ledger, and the running workers with",
|
|
5762
|
+
"their inbox counts (◆N = handoffs waiting).",
|
|
5722
5763
|
"",
|
|
5723
5764
|
"Use this before delegating with `pai worker run` to see what routing will choose."
|
|
5724
5765
|
].join("\n"), {}, async () => {
|
|
@@ -5726,32 +5767,42 @@ async function startShim() {
|
|
|
5726
5767
|
const { workers } = readWorkersSection();
|
|
5727
5768
|
const s = ledgerSummary(ledgerPath(workersLogDir(workers)), "all", 10);
|
|
5728
5769
|
const tally = s ? [`runs ${s.scope}: ${s.started} started, ${s.endedOk} ok, ${s.endedFailed} failed`, `agent hook: ${s.denied} denied, ${s.allowed} allowed, ${s.reroutes} reroutes`] : ["no runs recorded yet"];
|
|
5770
|
+
const logDir = workersLogDir(workers);
|
|
5771
|
+
const running = loadStatuses(logDir).filter((w) => w.state === "running" && alive(w.pid));
|
|
5772
|
+
const runningLines = running.length ? [
|
|
5773
|
+
"",
|
|
5774
|
+
`running (${running.length}):`,
|
|
5775
|
+
...running.map((w) => ` ${w.id} ${w.label}${w.parent ? ` (sub-worker of ${w.parent})` : ""} · ${w.last}` + (readInbox(logDir, w.id).length ? ` · ◆${readInbox(logDir, w.id).length}` : ""))
|
|
5776
|
+
] : [];
|
|
5729
5777
|
return workerText([
|
|
5730
5778
|
`workers: ${workers.enabled ? "on" : "off"}`,
|
|
5731
5779
|
`active provider: ${workers.active ?? "(none)"}`,
|
|
5732
5780
|
...describeProviders(workers),
|
|
5733
5781
|
"",
|
|
5734
|
-
...tally
|
|
5782
|
+
...tally,
|
|
5783
|
+
...runningLines
|
|
5735
5784
|
].join("\n"));
|
|
5736
5785
|
} catch (e) {
|
|
5737
5786
|
return workerError(e);
|
|
5738
5787
|
}
|
|
5739
5788
|
});
|
|
5740
5789
|
server.tool("worker_providers", [
|
|
5741
|
-
"Manage worker providers (list, add, remove, use, enable, disable, test).",
|
|
5790
|
+
"Manage worker providers (list, add, update, remove, use, enable, disable, test).",
|
|
5742
5791
|
"",
|
|
5743
|
-
"action=list (default) shows providers,
|
|
5792
|
+
"action=list (default) shows providers (with cost tier and tags), classes and routing.",
|
|
5744
5793
|
"action=add needs name, model — and either key_file or key, plus:",
|
|
5745
5794
|
" base_url (anthropic protocol) or upstream_url (protocol=openai, runs",
|
|
5746
5795
|
" through the local PAI proxy). A raw key is written to",
|
|
5747
5796
|
" ~/.config/pai/keys/<name> (mode 0600); only the path lands in the config.",
|
|
5748
5797
|
" engine=codex runs the Codex CLI instead of Claude Code.",
|
|
5798
|
+
"action=update changes cost_tier / tags of an existing provider.",
|
|
5749
5799
|
"action=test runs a one-word pong probe through the provider",
|
|
5750
5800
|
" (reports 'codex not installed' when that engine's CLI is missing)."
|
|
5751
5801
|
].join("\n"), {
|
|
5752
5802
|
action: _enum([
|
|
5753
5803
|
"list",
|
|
5754
5804
|
"add",
|
|
5805
|
+
"update",
|
|
5755
5806
|
"remove",
|
|
5756
5807
|
"use",
|
|
5757
5808
|
"enable",
|
|
@@ -5770,12 +5821,29 @@ async function startShim() {
|
|
|
5770
5821
|
fast_model: string().optional().describe("Cheaper model for spotchecks (add, optional)."),
|
|
5771
5822
|
env: record(string(), string()).optional().describe("Extra env for runs (add, optional)."),
|
|
5772
5823
|
note: string().optional().describe("Human note shown in listings (add, optional)."),
|
|
5773
|
-
quota_probe: string().optional().describe("URL whose JSON first number is the quota percent (add, optional).")
|
|
5824
|
+
quota_probe: string().optional().describe("URL whose JSON first number is the quota percent (add, optional)."),
|
|
5825
|
+
cost_tier: number().int().min(1).max(5).optional().describe("Cost tier 1 (cheapest) … 5 (most expensive). Default 3. (add, update)"),
|
|
5826
|
+
tags: array(_enum([
|
|
5827
|
+
"code",
|
|
5828
|
+
"vision",
|
|
5829
|
+
"image-gen",
|
|
5830
|
+
"long-context",
|
|
5831
|
+
"fast",
|
|
5832
|
+
"reasoning"
|
|
5833
|
+
])).optional().describe("Capability tags (add, update).")
|
|
5774
5834
|
}, async (args) => {
|
|
5775
5835
|
try {
|
|
5776
5836
|
const action = args.action ?? "list";
|
|
5777
5837
|
if (action === "list") return workerText(describeProviders(readWorkersSection().workers).join("\n"));
|
|
5778
5838
|
if (!args.name) return workerError(/* @__PURE__ */ new Error("name is required for this action"));
|
|
5839
|
+
if (action === "update") {
|
|
5840
|
+
if (args.cost_tier === void 0 && args.tags === void 0) return workerError(/* @__PURE__ */ new Error("update needs cost_tier and/or tags"));
|
|
5841
|
+
updateProvider(args.name, {
|
|
5842
|
+
...args.cost_tier !== void 0 ? { costTier: args.cost_tier } : {},
|
|
5843
|
+
...args.tags !== void 0 ? { tags: args.tags } : {}
|
|
5844
|
+
});
|
|
5845
|
+
return workerText([`provider ${args.name} updated`, ...describeProviders(readWorkersSection().workers)].join("\n"));
|
|
5846
|
+
}
|
|
5779
5847
|
if (action === "add") {
|
|
5780
5848
|
if (!args.model) return workerError(/* @__PURE__ */ new Error("add needs model"));
|
|
5781
5849
|
if (args.protocol !== "openai" && !args.base_url) return workerError(/* @__PURE__ */ new Error("add needs base_url (only protocol=openai goes without it)"));
|
|
@@ -5792,7 +5860,9 @@ async function startShim() {
|
|
|
5792
5860
|
...args.upstream_url ? { upstreamUrl: args.upstream_url } : {},
|
|
5793
5861
|
...args.engine ? { engine: args.engine } : {},
|
|
5794
5862
|
...args.context_window ? { contextWindow: args.context_window } : {},
|
|
5795
|
-
...args.quota_probe ? { quotaProbe: args.quota_probe } : {}
|
|
5863
|
+
...args.quota_probe ? { quotaProbe: args.quota_probe } : {},
|
|
5864
|
+
...args.cost_tier !== void 0 ? { costTier: args.cost_tier } : {},
|
|
5865
|
+
...args.tags?.length ? { tags: args.tags } : {}
|
|
5796
5866
|
});
|
|
5797
5867
|
return workerText([`provider ${args.name} added; active: ${workers.active ?? "(none)"}; workers ${workers.enabled ? "on" : "off"}`, ...describeProviders(workers)].join("\n"));
|
|
5798
5868
|
}
|
|
@@ -5818,37 +5888,140 @@ async function startShim() {
|
|
|
5818
5888
|
return workerError(e);
|
|
5819
5889
|
}
|
|
5820
5890
|
});
|
|
5821
|
-
server.tool("
|
|
5822
|
-
"Manage worker
|
|
5891
|
+
server.tool("worker_classes", [
|
|
5892
|
+
"Manage worker classes (list, set, unset).",
|
|
5823
5893
|
"",
|
|
5824
|
-
"A
|
|
5894
|
+
"A class maps a task class to a provider, optionally its fast model:",
|
|
5825
5895
|
"implement=glm, research=glm, spotcheck=glm/fast.",
|
|
5826
|
-
"
|
|
5896
|
+
"set can instead give routing constraints only (max_cost_tier,",
|
|
5897
|
+
"require_tags) — auto-routing then picks a qualifying provider.",
|
|
5898
|
+
"Runs pick the provider via --class first, then the active provider."
|
|
5827
5899
|
].join("\n"), {
|
|
5828
5900
|
action: _enum([
|
|
5829
5901
|
"list",
|
|
5830
5902
|
"set",
|
|
5831
5903
|
"unset"
|
|
5832
5904
|
]).optional().describe("Default: list."),
|
|
5833
|
-
|
|
5834
|
-
target: string().optional().describe("Provider or provider/fast (set).")
|
|
5905
|
+
class: string().optional().describe("Class name (set/unset), e.g. implement, spotcheck."),
|
|
5906
|
+
target: string().optional().describe("Provider or provider/fast (set)."),
|
|
5907
|
+
max_cost_tier: number().int().min(1).max(5).optional().describe("Auto-routing considers only providers up to this cost tier (set)."),
|
|
5908
|
+
require_tags: array(_enum([
|
|
5909
|
+
"code",
|
|
5910
|
+
"vision",
|
|
5911
|
+
"image-gen",
|
|
5912
|
+
"long-context",
|
|
5913
|
+
"fast",
|
|
5914
|
+
"reasoning"
|
|
5915
|
+
])).optional().describe("Auto-routing needs these tags (set).")
|
|
5835
5916
|
}, async (args) => {
|
|
5836
5917
|
try {
|
|
5837
5918
|
const action = args.action ?? "list";
|
|
5838
5919
|
if (action === "list") {
|
|
5839
5920
|
const { workers } = readWorkersSection();
|
|
5840
|
-
const entries = Object.entries(workers.
|
|
5841
|
-
|
|
5842
|
-
return workerText(entries.length ? entries.map(([r, t]) => `${r}: ${text(t)}`).join("\n") : "no roles set");
|
|
5921
|
+
const entries = Object.entries(workers.classes);
|
|
5922
|
+
return workerText(entries.length ? entries.map(([cls, t]) => `${cls}: ${classTargetText(t)}`).join("\n") : "no classes set");
|
|
5843
5923
|
}
|
|
5844
|
-
if (!args.
|
|
5924
|
+
if (!args.class) return workerError(/* @__PURE__ */ new Error("class is required for this action"));
|
|
5845
5925
|
if (action === "set") {
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5926
|
+
const hasConstraints = args.max_cost_tier !== void 0 || args.require_tags !== void 0;
|
|
5927
|
+
if (!args.target && !hasConstraints) return workerError(/* @__PURE__ */ new Error("set needs target provider[/fast] and/or max_cost_tier/require_tags"));
|
|
5928
|
+
const target = args.target !== void 0 && !hasConstraints ? args.target : {
|
|
5929
|
+
...args.target ? { provider: args.target.split("/")[0] } : {},
|
|
5930
|
+
...args.max_cost_tier !== void 0 ? { maxCostTier: args.max_cost_tier } : {},
|
|
5931
|
+
...args.require_tags !== void 0 ? { requireTags: args.require_tags } : {}
|
|
5932
|
+
};
|
|
5933
|
+
setClass(args.class, target);
|
|
5934
|
+
return workerText(`class ${args.class} → ${classTargetText(target)}`);
|
|
5849
5935
|
}
|
|
5850
|
-
|
|
5851
|
-
return workerText(`
|
|
5936
|
+
unsetClass(args.class);
|
|
5937
|
+
return workerText(`class ${args.class} removed`);
|
|
5938
|
+
} catch (e) {
|
|
5939
|
+
return workerError(e);
|
|
5940
|
+
}
|
|
5941
|
+
});
|
|
5942
|
+
server.tool("worker_run", [
|
|
5943
|
+
"Start a worker (or a chain) and return its id immediately.",
|
|
5944
|
+
"",
|
|
5945
|
+
"This is the chat-side face of `pai worker run`: prompt is required,",
|
|
5946
|
+
"chain (e.g. \"draft,implement\") runs spec-first stages, class picks the",
|
|
5947
|
+
"provider (default: active). Check on it with worker_ps / worker_replay,",
|
|
5948
|
+
"talk to it with worker_say."
|
|
5949
|
+
].join("\n"), {
|
|
5950
|
+
prompt: string().min(1).describe("The task (the -p value)."),
|
|
5951
|
+
chain: string().optional().describe("Comma-separated stages, e.g. draft,implement or draft,implement,review."),
|
|
5952
|
+
class: string().optional().describe("Task class (draft, implement, review, research, spotcheck, simple, complex, image)."),
|
|
5953
|
+
label: string().optional().describe("Short task label shown in worker_ps."),
|
|
5954
|
+
cwd: string().optional().describe("Working directory (default: here)."),
|
|
5955
|
+
allowed_tools: string().optional().describe("Comma-separated tool allowlist passed to the worker."),
|
|
5956
|
+
mcp: string().optional().describe("MCP servers/sets the worker may use (comma-separated).")
|
|
5957
|
+
}, async (args) => {
|
|
5958
|
+
try {
|
|
5959
|
+
const claudeArgs = [
|
|
5960
|
+
"-p",
|
|
5961
|
+
args.prompt,
|
|
5962
|
+
...args.allowed_tools ? ["--allowedTools", args.allowed_tools] : []
|
|
5963
|
+
];
|
|
5964
|
+
let startedIdResolve;
|
|
5965
|
+
let startupFailure = null;
|
|
5966
|
+
const idArrived = new Promise((resolve) => {
|
|
5967
|
+
startedIdResolve = resolve;
|
|
5968
|
+
});
|
|
5969
|
+
const background = async () => {
|
|
5970
|
+
if (args.chain) return runChain({
|
|
5971
|
+
stages: args.chain.split(","),
|
|
5972
|
+
className: args.class,
|
|
5973
|
+
label: args.label,
|
|
5974
|
+
noPane: false,
|
|
5975
|
+
mcpFlag: args.mcp,
|
|
5976
|
+
brief: args.prompt,
|
|
5977
|
+
claudeArgs,
|
|
5978
|
+
...args.cwd ? { cwd: args.cwd } : {},
|
|
5979
|
+
onChainStart: (id) => startedIdResolve(id),
|
|
5980
|
+
quiet: true
|
|
5981
|
+
});
|
|
5982
|
+
return runWorker({
|
|
5983
|
+
className: args.class,
|
|
5984
|
+
label: args.label,
|
|
5985
|
+
noPane: false,
|
|
5986
|
+
mcpFlag: args.mcp,
|
|
5987
|
+
claudeArgs,
|
|
5988
|
+
...args.cwd ? { cwd: args.cwd } : {},
|
|
5989
|
+
onWorkerStart: (wid) => startedIdResolve(wid),
|
|
5990
|
+
quiet: true
|
|
5991
|
+
});
|
|
5992
|
+
};
|
|
5993
|
+
background().catch((e) => {
|
|
5994
|
+
startupFailure = e;
|
|
5995
|
+
startedIdResolve("");
|
|
5996
|
+
});
|
|
5997
|
+
const id = await Promise.race([idArrived, new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("worker did not start within 15s")), 15e3))]);
|
|
5998
|
+
if (!id) return workerError(startupFailure ?? /* @__PURE__ */ new Error("worker failed to start"));
|
|
5999
|
+
return workerText(`${id} started${args.chain ? ` (chain: ${args.chain})` : ""} — check on it with worker_ps, worker_replay, worker_say`);
|
|
6000
|
+
} catch (e) {
|
|
6001
|
+
return workerError(e);
|
|
6002
|
+
}
|
|
6003
|
+
});
|
|
6004
|
+
server.tool("worker_handoff", [
|
|
6005
|
+
"From inside a worker: send a handoff up to the parent worker.",
|
|
6006
|
+
"",
|
|
6007
|
+
"kind: proposal (do this instead of me), question, blocker, or result",
|
|
6008
|
+
"(results are sent for you when you finish — only send one yourself for",
|
|
6009
|
+
"mid-run findings). The handoff lands in the parent's inbox and is said to",
|
|
6010
|
+
"it when it is still running. Outside a worker this fails — there is no",
|
|
6011
|
+
"sideways or downward path."
|
|
6012
|
+
].join("\n"), {
|
|
6013
|
+
kind: _enum([
|
|
6014
|
+
"proposal",
|
|
6015
|
+
"result",
|
|
6016
|
+
"question",
|
|
6017
|
+
"blocker"
|
|
6018
|
+
]).describe("What the handoff carries."),
|
|
6019
|
+
text: string().min(1).describe("The message body, one paragraph."),
|
|
6020
|
+
data: record(string(), unknown()).optional().describe("Structured payload (optional).")
|
|
6021
|
+
}, async (args) => {
|
|
6022
|
+
try {
|
|
6023
|
+
const h = await handoffFromInside(workersLogDir(readWorkersSection().workers), process.env, args);
|
|
6024
|
+
return workerText(`ok → ${h.to} (${h.kind}); the parent sees it in its inbox`);
|
|
5852
6025
|
} catch (e) {
|
|
5853
6026
|
return workerError(e);
|
|
5854
6027
|
}
|