@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.
- package/dist/{aibroker-client-D5NT0S1N.mjs → aibroker-client-Bu72yPKj.mjs} +1 -1
- package/dist/{aibroker-client-Bn9SnGMa.mjs → aibroker-client-CDIXmq-e.mjs} +1 -1
- package/dist/{aibroker-client-Bn9SnGMa.mjs.map → aibroker-client-CDIXmq-e.mjs.map} +1 -1
- package/dist/{chain-CNSa0A3G.mjs → chain-BBbVbWVv.mjs} +4 -4
- package/dist/{chain-CNSa0A3G.mjs.map → chain-BBbVbWVv.mjs.map} +1 -1
- package/dist/cli/index.mjs +14 -14
- package/dist/cli/program.mjs +14 -14
- package/dist/config-Bn9jpblO.mjs +653 -0
- package/dist/config-Bn9jpblO.mjs.map +1 -0
- package/dist/{config-DxMZjpvY.mjs → config-DYXARgk8.mjs} +180 -151
- package/dist/config-DYXARgk8.mjs.map +1 -0
- package/dist/config-RjeVGJ7K.mjs +3 -0
- package/dist/{context-handover-cache-B9NKSjwR.mjs → context-handover-cache-yOuK9RIk.mjs} +5 -5
- package/dist/{context-handover-cache-B9NKSjwR.mjs.map → context-handover-cache-yOuK9RIk.mjs.map} +1 -1
- package/dist/daemon/index.mjs +13 -12
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/{daemon-DZ4Q0jrs.mjs → daemon-CBTQYtHF.mjs} +49 -30
- package/dist/daemon-CBTQYtHF.mjs.map +1 -0
- package/dist/daemon-Vf7pHnjR.mjs +25 -0
- package/dist/daemon-mcp/index.mjs +186 -23
- package/dist/daemon-mcp/index.mjs.map +1 -1
- package/dist/factory-Ba8j9K7q.mjs +3 -0
- package/dist/{factory-DNYAqjH0.mjs → factory-Bt7TWQje.mjs} +3 -3
- package/dist/{factory-DNYAqjH0.mjs.map → factory-Bt7TWQje.mjs.map} +1 -1
- package/dist/{fallback-IeR2FrFn.mjs → fallback-CIGspCSi.mjs} +260 -10
- package/dist/fallback-CIGspCSi.mjs.map +1 -0
- package/dist/hooks/capture-all-events.mjs +80 -8
- package/dist/hooks/capture-all-events.mjs.map +4 -4
- package/dist/hooks/context-compression-hook.mjs +54 -39
- package/dist/hooks/context-compression-hook.mjs.map +4 -4
- package/dist/hooks/post-compact-inject.mjs +54 -39
- package/dist/hooks/post-compact-inject.mjs.map +4 -4
- package/dist/hooks/route-agents-to-worker.mjs +204 -109
- package/dist/hooks/route-agents-to-worker.mjs.map +4 -4
- package/dist/hooks/whisper-rules.mjs +7613 -9
- package/dist/hooks/whisper-rules.mjs.map +4 -4
- package/dist/hooks/worker-proxy.mjs +204 -109
- package/dist/hooks/worker-proxy.mjs.map +4 -4
- package/dist/hooks/worker-status-line.mjs +211 -116
- package/dist/hooks/worker-status-line.mjs.map +4 -4
- package/dist/hooks/worker-supervision.mjs +208 -113
- package/dist/hooks/worker-supervision.mjs.map +4 -4
- package/dist/{kg-entity-BSjM5xZh.mjs → kg-entity-BSW7ra8i.mjs} +1 -1
- package/dist/{kg-entity-BSjM5xZh.mjs.map → kg-entity-BSW7ra8i.mjs.map} +1 -1
- package/dist/main-resolver-BTastpp4.mjs +7 -0
- package/dist/{main-resolver-DvYu9jbl.mjs → main-resolver-BmZPCmgj.mjs} +3 -3
- package/dist/{main-resolver-DvYu9jbl.mjs.map → main-resolver-BmZPCmgj.mjs.map} +1 -1
- package/dist/{planner-Cn8HmT7l.mjs → planner-BiH9msqq.mjs} +6 -6
- package/dist/{planner-Cn8HmT7l.mjs.map → planner-BiH9msqq.mjs.map} +1 -1
- package/dist/{program-D9-wfmkZ.mjs → program-BX67-4I2.mjs} +233 -277
- package/dist/program-BX67-4I2.mjs.map +1 -0
- package/dist/query-feedback-Bm6XvCmg.mjs +3 -0
- package/dist/{query-feedback-CYyOGi3y.mjs → query-feedback-CTs_jx6i.mjs} +1 -1
- package/dist/{query-feedback-CYyOGi3y.mjs.map → query-feedback-CTs_jx6i.mjs.map} +1 -1
- package/dist/{run-Cls0YGgV.mjs → run-TChOnMO_.mjs} +1388 -1183
- package/dist/run-TChOnMO_.mjs.map +1 -0
- package/dist/{server-Ch99xt5K.mjs → server-R9UkCn3v.mjs} +42 -3
- package/dist/server-R9UkCn3v.mjs.map +1 -0
- package/dist/session-keepalive-BuG3wvik.mjs +579 -0
- package/dist/session-keepalive-BuG3wvik.mjs.map +1 -0
- package/dist/skills/VaultContext/SKILL.md +1 -1
- package/dist/{state-DnYGRmS7.mjs → state-Ca0ltLgI.mjs} +1 -1
- package/dist/{state-PJrgfDLW.mjs → state-DwrsOoMi.mjs} +1 -1
- package/dist/{state-PJrgfDLW.mjs.map → state-DwrsOoMi.mjs.map} +1 -1
- package/dist/{tools-B77WHeVZ.mjs → tools-BEqiJt_j.mjs} +13 -13
- package/dist/{tools-B77WHeVZ.mjs.map → tools-BEqiJt_j.mjs.map} +1 -1
- package/dist/{tools-NnR_n-Ja.mjs → tools-BwsOTmjh.mjs} +2 -2
- package/dist/{wakeup-UrhiW-KU.mjs → wakeup-Yk5lQ0jb.mjs} +1 -1
- package/dist/{wakeup-UrhiW-KU.mjs.map → wakeup-Yk5lQ0jb.mjs.map} +1 -1
- package/dist/{work-queue-worker-BA5IDBwQ.mjs → work-queue-worker-B9zVWImP.mjs} +3 -3
- package/dist/{work-queue-worker-BA5IDBwQ.mjs.map → work-queue-worker-B9zVWImP.mjs.map} +1 -1
- package/dist/work-queue-worker-D-DnQ7oh.mjs +14 -0
- package/dist/{zettelkasten-BBjA7GcP.mjs → zettelkasten-DezbXghl.mjs} +2 -2
- package/dist/{zettelkasten-BBjA7GcP.mjs.map → zettelkasten-DezbXghl.mjs.map} +1 -1
- package/docs/cache-keepalive.md +138 -0
- package/docs/commands/README.md +7 -0
- package/docs/commands/config.md +84 -0
- package/docs/commands/daemon.md +6 -0
- package/docs/commands/worker.md +37 -2
- package/docs/config.md +171 -0
- package/docs/model-catalogue.md +502 -0
- package/docs/provider-independence-details.md +1 -1
- package/docs/task-bus.md +1 -1
- package/docs/worker.md +33 -5
- package/docs/workers-config.md +105 -12
- package/package.json +1 -1
- package/src/hooks/ts/capture-all-events.test.ts +71 -0
- package/src/hooks/ts/capture-all-events.ts +10 -3
- package/src/hooks/ts/user-prompt/whisper-rules.test.ts +56 -1
- package/src/hooks/ts/user-prompt/whisper-rules.ts +24 -0
- package/statusline-command.sh +81 -6
- package/dist/config-DCu8THKi.mjs +0 -228
- package/dist/config-DCu8THKi.mjs.map +0 -1
- package/dist/config-DeqFqa1N.mjs +0 -3
- package/dist/config-DxMZjpvY.mjs.map +0 -1
- package/dist/daemon-CYpVy_Dw.mjs +0 -24
- package/dist/daemon-DZ4Q0jrs.mjs.map +0 -1
- package/dist/factory-47Qf_df7.mjs +0 -3
- package/dist/fallback-IeR2FrFn.mjs.map +0 -1
- package/dist/indexer-C5Le7XE7.mjs +0 -1
- package/dist/main-resolver-CnfnWa8C.mjs +0 -7
- package/dist/program-D9-wfmkZ.mjs.map +0 -1
- package/dist/query-feedback-C7rSfiXU.mjs +0 -3
- package/dist/run-Cls0YGgV.mjs.map +0 -1
- package/dist/server-Ch99xt5K.mjs.map +0 -1
- package/dist/work-queue-worker-DLM2wlqM.mjs +0 -14
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "../db-Ddns80yf.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { p as MainConfigError, s as loadConfig } from "../config-Bn9jpblO.mjs";
|
|
4
|
+
import { C as readWorkersSection, c as MODEL_CAPABILITIES, n as CAPABILITY_NAME_RE } from "../config-DYXARgk8.mjs";
|
|
5
|
+
import { B as setWorkerLabel, E as ledgerSummary, F as loadStatuses, P as loadStatus, c as handoffFromInside, k as alive, l as readInbox, n as runWorker, r as testProvider, u as sayToWorker } from "../run-TChOnMO_.mjs";
|
|
6
6
|
import { t as PaiClient } from "../ipc-client-C6NryMMb.mjs";
|
|
7
|
-
import { _ as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { A as getConfigValueOp, C as psOutput, D as resolveSpecPath, E as readSpecPrompt, M as setConfigValueOp, N as unsetConfigValueOp, O as MainConfigOpsError, _ as setWorkersEnabled, a as addProvider, b as updateProvider, c as describeModels, d as removeProvider, f as resolveProviderName, g as setProviderModel, h as setProviderEnabled, i as fallbackStatusText, j as listConfigOp, l as describeProviders, m as setClass, n as fallbackOn, o as classTargetText, p as setCapabilityPreference, r as fallbackStatus, s as describeCapabilities, t as fallbackOff, u as modelPrefsText, v as unsetCapabilityPreference, w as replayOutput, x as useProvider, y as unsetClass } from "../fallback-CIGspCSi.mjs";
|
|
8
|
+
import { g as ledgerPath, y as workersLogDir } from "../server-R9UkCn3v.mjs";
|
|
9
|
+
import { t as runChain } from "../chain-BBbVbWVv.mjs";
|
|
10
10
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
11
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
12
12
|
|
|
@@ -3839,7 +3839,7 @@ USE WHEN user says 'load vault context', 'brief me from Obsidian', 'morning brie
|
|
|
3839
3839
|
|
|
3840
3840
|
Reads: daily note → open TODOs → PAI index (active projects) → HOME.md (focus areas) → recent insights. Synthesizes into morning briefing with Suggested First Action.
|
|
3841
3841
|
|
|
3842
|
-
All vault skills work with the vault configured in \`~/.claude/pai/config.
|
|
3842
|
+
All vault skills work with the vault configured in \`~/.claude/pai/config.yaml\` (\`vaultPath\` key, or \`config.json\` until you run \`pai config yaml\`).`
|
|
3843
3843
|
};
|
|
3844
3844
|
|
|
3845
3845
|
//#endregion
|
|
@@ -4709,7 +4709,7 @@ User
|
|
|
4709
4709
|
| Memory | \${PAI_DIR}/projects/*/Notes/ | Session notes, todos |
|
|
4710
4710
|
| Skills | ~/.claude/Skills/ | Workflow instructions |
|
|
4711
4711
|
| History | \${PAI_HOME}/History/ | Automated capture |
|
|
4712
|
-
| Config | ~/.claude/pai/ | Agent preferences (config.
|
|
4712
|
+
| Config | ~/.claude/pai/ | Agent preferences (config.yaml, workers.yaml, etc.) |
|
|
4713
4713
|
|
|
4714
4714
|
## Two-Tier MCP Strategy
|
|
4715
4715
|
|
|
@@ -5441,6 +5441,7 @@ const workerRunShape = {
|
|
|
5441
5441
|
specPath: string().min(1).optional().describe("Path to a file (or \"-\" for stdin) whose contents become the prompt. Mutually exclusive with prompt."),
|
|
5442
5442
|
chain: string().optional().describe("Comma-separated stages, e.g. draft,implement or draft,implement,review."),
|
|
5443
5443
|
class: string().optional().describe("Task class (draft, implement, review, research, spotcheck, simple, complex, image)."),
|
|
5444
|
+
capability: string().optional().describe("Run on whichever provider serves this capability instead of the active one — e.g. \"image\" runs an engine=image provider directly (POSTs the prompt, writes a PNG under the worker's log dir) instead of spawning claude. Wins over class."),
|
|
5444
5445
|
label: string().min(1).describe("Short task label shown in worker_ps / the status line and worker pane."),
|
|
5445
5446
|
cwd: string().optional().describe("Working directory (default: here)."),
|
|
5446
5447
|
allowed_tools: string().optional().describe("Comma-separated tool allowlist passed to the worker."),
|
|
@@ -5471,11 +5472,11 @@ function resolveWorkerRunPrompt(args, cwd) {
|
|
|
5471
5472
|
* handler, index.ts registers it. The mutations themselves live in
|
|
5472
5473
|
* src/workers/providers.ts, shared with the `pai worker model` CLI.
|
|
5473
5474
|
*/
|
|
5474
|
-
const text = (s) => ({ content: [{
|
|
5475
|
+
const text$2 = (s) => ({ content: [{
|
|
5475
5476
|
type: "text",
|
|
5476
5477
|
text: s
|
|
5477
5478
|
}] });
|
|
5478
|
-
const error = (e) => ({
|
|
5479
|
+
const error$1 = (e) => ({
|
|
5479
5480
|
content: [{
|
|
5480
5481
|
type: "text",
|
|
5481
5482
|
text: e instanceof Error ? e.message : String(e)
|
|
@@ -5490,22 +5491,128 @@ const error = (e) => ({
|
|
|
5490
5491
|
function workerModel(args, configPath) {
|
|
5491
5492
|
try {
|
|
5492
5493
|
const action = args.action ?? "get";
|
|
5493
|
-
if (action !== "get" && action !== "set") return error(/* @__PURE__ */ new Error(`unknown action "${String(action)}" (expected: get, set)`));
|
|
5494
|
-
if (args.capability !== void 0 && args.slot !== void 0 && args.capability !== args.slot) return error(/* @__PURE__ */ new Error(`capability "${args.capability}" and slot "${args.slot}" disagree — pass one`));
|
|
5494
|
+
if (action !== "get" && action !== "set") return error$1(/* @__PURE__ */ new Error(`unknown action "${String(action)}" (expected: get, set)`));
|
|
5495
|
+
if (args.capability !== void 0 && args.slot !== void 0 && args.capability !== args.slot) return error$1(/* @__PURE__ */ new Error(`capability "${args.capability}" and slot "${args.slot}" disagree — pass one`));
|
|
5495
5496
|
const capability = args.capability ?? args.slot ?? "default";
|
|
5496
5497
|
const { workers } = readWorkersSection(configPath);
|
|
5497
5498
|
if (action === "get") {
|
|
5498
5499
|
if (args.provider) {
|
|
5499
5500
|
const name = resolveProviderName(workers, args.provider);
|
|
5500
5501
|
const p = workers.providers[name];
|
|
5501
|
-
return p ? text(`${name} ${modelPrefsText(p)}`) : error(/* @__PURE__ */ new Error(`no provider named "${args.provider}"`));
|
|
5502
|
+
return p ? text$2(`${name} ${modelPrefsText(p)}`) : error$1(/* @__PURE__ */ new Error(`no provider named "${args.provider}"`));
|
|
5502
5503
|
}
|
|
5503
|
-
return text(describeModels(workers).join("\n"));
|
|
5504
|
+
return text$2(describeModels(workers).join("\n"));
|
|
5504
5505
|
}
|
|
5505
|
-
if (!args.model || !args.model.trim()) return error(/* @__PURE__ */ new Error("set needs a non-empty model id"));
|
|
5506
|
+
if (!args.model || !args.model.trim()) return error$1(/* @__PURE__ */ new Error("set needs a non-empty model id"));
|
|
5506
5507
|
const name = resolveProviderName(workers, args.provider);
|
|
5507
5508
|
const p = setProviderModel(name, capability, args.model, configPath).providers[name];
|
|
5508
|
-
return text(`${name} ${capability} model: ${p?.models[capability] ?? "?"}`);
|
|
5509
|
+
return text$2(`${name} ${capability} model: ${p?.models[capability] ?? "?"}`);
|
|
5510
|
+
} catch (e) {
|
|
5511
|
+
return error$1(e);
|
|
5512
|
+
}
|
|
5513
|
+
}
|
|
5514
|
+
|
|
5515
|
+
//#endregion
|
|
5516
|
+
//#region src/daemon-mcp/tools/config.ts
|
|
5517
|
+
/**
|
|
5518
|
+
* MCP handlers for config_list/config_get/config_set/config_unset — thin
|
|
5519
|
+
* wrappers around src/config/main-config-ops.ts, the same functions
|
|
5520
|
+
* src/cli/commands/config.ts calls, so masking and validation cannot drift
|
|
5521
|
+
* between the CLI and MCP surfaces.
|
|
5522
|
+
*/
|
|
5523
|
+
function text$1(s) {
|
|
5524
|
+
return { content: [{
|
|
5525
|
+
type: "text",
|
|
5526
|
+
text: s
|
|
5527
|
+
}] };
|
|
5528
|
+
}
|
|
5529
|
+
function errorText(e) {
|
|
5530
|
+
return {
|
|
5531
|
+
content: [{
|
|
5532
|
+
type: "text",
|
|
5533
|
+
text: e instanceof MainConfigOpsError || e instanceof MainConfigError ? e.message : e instanceof Error ? e.message : String(e)
|
|
5534
|
+
}],
|
|
5535
|
+
isError: true
|
|
5536
|
+
};
|
|
5537
|
+
}
|
|
5538
|
+
function configList(args) {
|
|
5539
|
+
try {
|
|
5540
|
+
const r = listConfigOp({ all: args.all });
|
|
5541
|
+
return text$1(args.json ? JSON.stringify(r.data, null, 2) : r.yaml.trimEnd());
|
|
5542
|
+
} catch (e) {
|
|
5543
|
+
return errorText(e);
|
|
5544
|
+
}
|
|
5545
|
+
}
|
|
5546
|
+
function configGet(args) {
|
|
5547
|
+
try {
|
|
5548
|
+
const r = getConfigValueOp(args.path);
|
|
5549
|
+
if (!r.found) return errorText(/* @__PURE__ */ new Error(`Not set: ${args.path}`));
|
|
5550
|
+
return text$1(typeof r.value === "object" ? JSON.stringify(r.value, null, 2) : String(r.value));
|
|
5551
|
+
} catch (e) {
|
|
5552
|
+
return errorText(e);
|
|
5553
|
+
}
|
|
5554
|
+
}
|
|
5555
|
+
function configSet(args) {
|
|
5556
|
+
try {
|
|
5557
|
+
const r = setConfigValueOp(args.path, args.value, { force: args.force });
|
|
5558
|
+
const lines = [];
|
|
5559
|
+
if (r.yamlCreated) lines.push(`created ${r.yamlPath}`);
|
|
5560
|
+
lines.push(`Set ${args.path} = ${typeof r.value === "object" ? JSON.stringify(r.value) : String(r.value)}`);
|
|
5561
|
+
return text$1(lines.join("\n"));
|
|
5562
|
+
} catch (e) {
|
|
5563
|
+
return errorText(e);
|
|
5564
|
+
}
|
|
5565
|
+
}
|
|
5566
|
+
function configUnset(args) {
|
|
5567
|
+
try {
|
|
5568
|
+
return text$1(unsetConfigValueOp(args.path).existed ? `Unset ${args.path}` : `${args.path} was not set`);
|
|
5569
|
+
} catch (e) {
|
|
5570
|
+
return errorText(e);
|
|
5571
|
+
}
|
|
5572
|
+
}
|
|
5573
|
+
|
|
5574
|
+
//#endregion
|
|
5575
|
+
//#region src/daemon-mcp/tools/worker-capability.ts
|
|
5576
|
+
/**
|
|
5577
|
+
* worker_capability — the MCP tool behind cross-provider capability
|
|
5578
|
+
* preference (the config behind `pai worker capability`).
|
|
5579
|
+
*
|
|
5580
|
+
* Extracted like worker-model.ts: index.ts starts its transport on import,
|
|
5581
|
+
* so its inline handlers cannot be imported by tests. The mutations
|
|
5582
|
+
* themselves live in src/workers/providers.ts, shared with the CLI.
|
|
5583
|
+
*/
|
|
5584
|
+
const text = (s) => ({ content: [{
|
|
5585
|
+
type: "text",
|
|
5586
|
+
text: s
|
|
5587
|
+
}] });
|
|
5588
|
+
const error = (e) => ({
|
|
5589
|
+
content: [{
|
|
5590
|
+
type: "text",
|
|
5591
|
+
text: e instanceof Error ? e.message : String(e)
|
|
5592
|
+
}],
|
|
5593
|
+
isError: true
|
|
5594
|
+
});
|
|
5595
|
+
/**
|
|
5596
|
+
* list (default): every capability preference and what it resolves to right
|
|
5597
|
+
* now. set: which provider(s) serve a capability, first usable one wins.
|
|
5598
|
+
* unset: remove a preference.
|
|
5599
|
+
*/
|
|
5600
|
+
function workerCapability(args, configPath) {
|
|
5601
|
+
try {
|
|
5602
|
+
const action = args.action ?? "list";
|
|
5603
|
+
if (action === "list") {
|
|
5604
|
+
const { workers } = readWorkersSection(configPath);
|
|
5605
|
+
return text(describeCapabilities(workers).join("\n"));
|
|
5606
|
+
}
|
|
5607
|
+
if (!args.capability) return error(/* @__PURE__ */ new Error(`capability is required for action "${action}"`));
|
|
5608
|
+
if (action === "unset") {
|
|
5609
|
+
unsetCapabilityPreference(args.capability, configPath);
|
|
5610
|
+
return text(`removed the capability preference for "${args.capability}"`);
|
|
5611
|
+
}
|
|
5612
|
+
if (action !== "set") return error(/* @__PURE__ */ new Error(`unknown action "${String(action)}" (expected: list, set, unset)`));
|
|
5613
|
+
if (!args.providers || !args.providers.length) return error(/* @__PURE__ */ new Error("set needs a non-empty providers list"));
|
|
5614
|
+
const workers = setCapabilityPreference(args.capability, args.providers, configPath);
|
|
5615
|
+
return text(describeCapabilities(workers).find((l) => l.startsWith(`${args.capability}:`)) ?? `${args.capability}: [${workers.capabilities[args.capability]?.join(", ")}]`);
|
|
5509
5616
|
} catch (e) {
|
|
5510
5617
|
return error(e);
|
|
5511
5618
|
}
|
|
@@ -5636,7 +5743,7 @@ async function startShim() {
|
|
|
5636
5743
|
"",
|
|
5637
5744
|
"Recency boost optionally down-weights older results (recency_boost=90 means scores halve every 90 days).",
|
|
5638
5745
|
"",
|
|
5639
|
-
"Defaults come from ~/.claude/pai/config.
|
|
5746
|
+
"Defaults come from ~/.claude/pai/config.yaml (search section). Per-call parameters override config defaults.",
|
|
5640
5747
|
"",
|
|
5641
5748
|
"Returns ranked snippets with project slug, file path, line range, and score.",
|
|
5642
5749
|
"Higher score = more relevant.",
|
|
@@ -5898,7 +6005,9 @@ async function startShim() {
|
|
|
5898
6005
|
" base_url (anthropic protocol) or upstream_url (protocol=openai, runs",
|
|
5899
6006
|
" through the local PAI proxy). A raw key is written to",
|
|
5900
6007
|
" ~/.claude/pai/keys/<name> (mode 0600); only the path lands in the config.",
|
|
5901
|
-
" engine=codex runs the Codex CLI instead of Claude Code
|
|
6008
|
+
" engine=codex runs the Codex CLI instead of Claude Code; engine=image POSTs",
|
|
6009
|
+
" straight to {base_url}/images/generations instead of spawning a process —",
|
|
6010
|
+
" pair it with a worker_capability image preference to run it.",
|
|
5902
6011
|
"action=update changes cost_tier / tags of an existing provider.",
|
|
5903
6012
|
"action=test runs a one-word pong probe through the provider",
|
|
5904
6013
|
" (reports 'codex not installed' when that engine's CLI is missing)."
|
|
@@ -5917,7 +6026,11 @@ async function startShim() {
|
|
|
5917
6026
|
base_url: string().optional().describe("Anthropic-compatible API base URL (add)."),
|
|
5918
6027
|
upstream_url: string().optional().describe("Chat Completions base URL (add, protocol=openai)."),
|
|
5919
6028
|
protocol: _enum(["anthropic", "openai"]).optional().describe("Protocol (add). Default: anthropic."),
|
|
5920
|
-
engine: _enum([
|
|
6029
|
+
engine: _enum([
|
|
6030
|
+
"claude",
|
|
6031
|
+
"codex",
|
|
6032
|
+
"image"
|
|
6033
|
+
]).optional().describe("Runner engine (add). Default: claude."),
|
|
5921
6034
|
context_window: number().int().positive().optional().describe("Context window for the meter (add). No default: unset hides the meter unless the init event announces one."),
|
|
5922
6035
|
key_file: string().optional().describe("File holding the API token, 0600 (add)."),
|
|
5923
6036
|
key: string().optional().describe("Raw API token (add) — parked in ~/.claude/pai/keys/<name>."),
|
|
@@ -6086,14 +6199,34 @@ async function startShim() {
|
|
|
6086
6199
|
"",
|
|
6087
6200
|
"action=get (default): the model ids of one provider (provider given,",
|
|
6088
6201
|
"default: the active one) or of every provider when provider is omitted.",
|
|
6089
|
-
"action=set needs model; capability picks which one
|
|
6202
|
+
"action=set needs model; capability picks which one — the set is open",
|
|
6203
|
+
`(well-known: ${MODEL_CAPABILITIES.join(", ")}; any other ^[a-z][a-z0-9-]*$ name works too).`
|
|
6090
6204
|
].join("\n"), {
|
|
6091
6205
|
action: _enum(["get", "set"]).optional().describe("Default: get."),
|
|
6092
6206
|
provider: string().optional().describe("Provider to read or change (default: the active one)."),
|
|
6093
|
-
capability:
|
|
6207
|
+
capability: string().regex(CAPABILITY_NAME_RE).optional().describe(`Which model capability to set (open set; well-known: ${MODEL_CAPABILITIES.join(", ")}). Default: default.`),
|
|
6094
6208
|
slot: _enum(["default", "fast"]).optional().describe("Deprecated pre-capability alias of `capability`."),
|
|
6095
6209
|
model: string().optional().describe("The new model id (required for set).")
|
|
6096
6210
|
}, async (args) => workerModel(args));
|
|
6211
|
+
server.tool("worker_capability", [
|
|
6212
|
+
"Which provider(s) serve a capability across the whole config (the",
|
|
6213
|
+
"config behind `pai worker capability`) — distinct from worker_model,",
|
|
6214
|
+
"which sets a model id on one provider's own table.",
|
|
6215
|
+
"",
|
|
6216
|
+
"action=list (default): every preference and what it resolves to now.",
|
|
6217
|
+
"action=set needs capability, providers (first usable one wins).",
|
|
6218
|
+
"action=unset needs capability. E.g. set capability=image,",
|
|
6219
|
+
"providers=[\"pictures\"] to run worker_run with capability=image against",
|
|
6220
|
+
"an engine=image provider named \"pictures\"."
|
|
6221
|
+
].join("\n"), {
|
|
6222
|
+
action: _enum([
|
|
6223
|
+
"list",
|
|
6224
|
+
"set",
|
|
6225
|
+
"unset"
|
|
6226
|
+
]).optional().describe("Default: list."),
|
|
6227
|
+
capability: string().optional().describe("Capability name, e.g. image (required for set, unset)."),
|
|
6228
|
+
providers: array(string()).optional().describe("Preference list, first usable one wins (required for set).")
|
|
6229
|
+
}, async (args) => workerCapability(args));
|
|
6097
6230
|
server.tool("worker_run", [
|
|
6098
6231
|
"Start a worker (or a chain) and return its id immediately.",
|
|
6099
6232
|
"",
|
|
@@ -6101,8 +6234,9 @@ async function startShim() {
|
|
|
6101
6234
|
"exactly one of prompt/specPath (the -p value, or a file/stdin '-' to read",
|
|
6102
6235
|
"it from — avoids quoting long prompts through JSON-RPC). chain (e.g.",
|
|
6103
6236
|
"\"draft,implement\") runs spec-first stages, class picks the provider",
|
|
6104
|
-
"(default: active)
|
|
6105
|
-
"
|
|
6237
|
+
"(default: active); capability=image runs an engine=image provider",
|
|
6238
|
+
"directly instead, writing a PNG rather than spawning claude.",
|
|
6239
|
+
"Check on it with worker_ps / worker_replay, talk to it with worker_say."
|
|
6106
6240
|
].join("\n"), workerRunShape, async (args) => {
|
|
6107
6241
|
try {
|
|
6108
6242
|
const cwd = args.cwd ?? process.cwd();
|
|
@@ -6139,6 +6273,7 @@ async function startShim() {
|
|
|
6139
6273
|
});
|
|
6140
6274
|
return runWorker({
|
|
6141
6275
|
className: args.class,
|
|
6276
|
+
capabilityFlag: args.capability,
|
|
6142
6277
|
label: args.label,
|
|
6143
6278
|
noPane: false,
|
|
6144
6279
|
mcpFlag: args.mcp,
|
|
@@ -6283,6 +6418,34 @@ async function startShim() {
|
|
|
6283
6418
|
return workerError(e);
|
|
6284
6419
|
}
|
|
6285
6420
|
});
|
|
6421
|
+
server.tool("config_list", [
|
|
6422
|
+
"Print the main PAI config as YAML (or JSON). Secrets (key/token/secret/",
|
|
6423
|
+
"password fields, and postgres.connectionString) are always masked to",
|
|
6424
|
+
"****<last4>. Defaults to only what the file explicitly sets; all=true",
|
|
6425
|
+
"includes every built-in default value too."
|
|
6426
|
+
].join("\n"), {
|
|
6427
|
+
all: boolean().optional().describe("Include every default value, not just what the file sets. Default: false."),
|
|
6428
|
+
json: boolean().optional().describe("Return JSON instead of YAML. Default: false.")
|
|
6429
|
+
}, async (args) => configList(args));
|
|
6430
|
+
server.tool("config_get", [
|
|
6431
|
+
"Read one config value by dotted path (e.g. search.recencyBoostDays).",
|
|
6432
|
+
"Resolves against the defaults-merged effective config, so a value never",
|
|
6433
|
+
"set in the file still answers with its built-in default. Masked",
|
|
6434
|
+
"(****<last4>) if the path looks like a secret."
|
|
6435
|
+
].join("\n"), { path: string().min(1).describe("Dotted config path, e.g. search.recencyBoostDays.") }, async (args) => configGet(args));
|
|
6436
|
+
server.tool("config_set", [
|
|
6437
|
+
"Write one config value by dotted path. WRITES THE FILE: creates",
|
|
6438
|
+
"config.yaml on first use (converting config.json if it exists), then",
|
|
6439
|
+
"writes comment-preserving. Value parsing: true/false, null, numbers,",
|
|
6440
|
+
"[...] / {...} as JSON, else a plain string. Refuses an unknown",
|
|
6441
|
+
"top-level key or a value whose type disagrees with the built-in",
|
|
6442
|
+
"default unless force=true."
|
|
6443
|
+
].join("\n"), {
|
|
6444
|
+
path: string().min(1).describe("Dotted config path, e.g. search.recencyBoostDays."),
|
|
6445
|
+
value: string().describe("Value to set, as a string (parsed per the rules above)."),
|
|
6446
|
+
force: boolean().optional().describe("Allow an unknown top-level key or a type mismatch. Default: false.")
|
|
6447
|
+
}, async (args) => configSet(args));
|
|
6448
|
+
server.tool("config_unset", ["Remove one config value by dotted path, WRITING THE FILE — reverting it", "to the built-in default. No-ops when the path was never explicitly set."].join("\n"), { path: string().min(1).describe("Dotted config path, e.g. search.recencyBoostDays.") }, async (args) => configUnset(args));
|
|
6286
6449
|
const transport = new StdioServerTransport();
|
|
6287
6450
|
await server.connect(transport);
|
|
6288
6451
|
}
|