@tekmidian/pai 0.38.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.
Files changed (83) hide show
  1. package/dist/{auto-route-DM7GhJ8y.mjs → auto-route-BlWOWT4z.mjs} +2 -2
  2. package/dist/{auto-route-DM7GhJ8y.mjs.map → auto-route-BlWOWT4z.mjs.map} +1 -1
  3. package/dist/{providers-DUshcB-d.mjs → chain-CTtHligI.mjs} +699 -1405
  4. package/dist/chain-CTtHligI.mjs.map +1 -0
  5. package/dist/cli/index.mjs +4 -3
  6. package/dist/cli/index.mjs.map +1 -1
  7. package/dist/cli/program.mjs +4 -3
  8. package/dist/{clusters-Do4tEGyc.mjs → clusters-wlK0w41E.mjs} +1 -1
  9. package/dist/{clusters-Do4tEGyc.mjs.map → clusters-wlK0w41E.mjs.map} +1 -1
  10. package/dist/daemon/index.mjs +7 -7
  11. package/dist/{daemon-CGg1VCbA.mjs → daemon-CTkN_Vn8.mjs} +25 -25
  12. package/dist/{daemon-CGg1VCbA.mjs.map → daemon-CTkN_Vn8.mjs.map} +1 -1
  13. package/dist/{daemon-DsGGiIJM.mjs → daemon-CmHHmKpg.mjs} +7 -7
  14. package/dist/daemon-mcp/index.mjs +55 -3
  15. package/dist/daemon-mcp/index.mjs.map +1 -1
  16. package/dist/{detector-CMap-9vw.mjs → detector-Bwk_4Pk4.mjs} +1 -1
  17. package/dist/{detector-CMap-9vw.mjs.map → detector-Bwk_4Pk4.mjs.map} +1 -1
  18. package/dist/detector-DO730Zq0.mjs +5 -0
  19. package/dist/{factory-DD2T33C9.mjs → factory-A9x-T2Kg.mjs} +5 -5
  20. package/dist/{factory-DD2T33C9.mjs.map → factory-A9x-T2Kg.mjs.map} +1 -1
  21. package/dist/factory-BD-np0Vd.mjs +3 -0
  22. package/dist/hooks/route-agents-to-worker.mjs +36 -6
  23. package/dist/hooks/route-agents-to-worker.mjs.map +2 -2
  24. package/dist/hooks/worker-proxy.mjs +34 -4
  25. package/dist/hooks/worker-proxy.mjs.map +2 -2
  26. package/dist/hooks/worker-status-line.mjs +100 -9
  27. package/dist/hooks/worker-status-line.mjs.map +4 -4
  28. package/dist/{indexer-backend-Cox9BCo-.mjs → indexer-backend-TG64CCQC.mjs} +1 -1
  29. package/dist/{indexer-backend-Cox9BCo-.mjs.map → indexer-backend-TG64CCQC.mjs.map} +1 -1
  30. package/dist/{latent-ideas-BC1oINZ-.mjs → latent-ideas-B7wq75Pt.mjs} +2 -2
  31. package/dist/{latent-ideas-BC1oINZ-.mjs.map → latent-ideas-B7wq75Pt.mjs.map} +1 -1
  32. package/dist/{link-boost-QFLrJwD6.mjs → link-boost-HkG7JWZR.mjs} +1 -1
  33. package/dist/{link-boost-QFLrJwD6.mjs.map → link-boost-HkG7JWZR.mjs.map} +1 -1
  34. package/dist/{neighborhood-D9MJ1c8f.mjs → neighborhood-lThN-MaQ.mjs} +1 -1
  35. package/dist/{neighborhood-D9MJ1c8f.mjs.map → neighborhood-lThN-MaQ.mjs.map} +1 -1
  36. package/dist/{note-context-d1wT_-GA.mjs → note-context-b6k0mAKi.mjs} +1 -1
  37. package/dist/{note-context-d1wT_-GA.mjs.map → note-context-b6k0mAKi.mjs.map} +1 -1
  38. package/dist/planner-BDI7bE9B.mjs +243 -0
  39. package/dist/planner-BDI7bE9B.mjs.map +1 -0
  40. package/dist/{postgres--BjPtLa0.mjs → postgres-mW1n7Vi1.mjs} +1 -1
  41. package/dist/{postgres--BjPtLa0.mjs.map → postgres-mW1n7Vi1.mjs.map} +1 -1
  42. package/dist/{program-Y0hAiVy8.mjs → program-DXBwJV7h.mjs} +70 -19
  43. package/dist/{program-Y0hAiVy8.mjs.map → program-DXBwJV7h.mjs.map} +1 -1
  44. package/dist/providers-FYkZjn_C.mjs +1405 -0
  45. package/dist/providers-FYkZjn_C.mjs.map +1 -0
  46. package/dist/{query-feedback-BUJxgw5B.mjs → query-feedback-BV4CcxqS.mjs} +1 -1
  47. package/dist/{query-feedback-BUJxgw5B.mjs.map → query-feedback-BV4CcxqS.mjs.map} +1 -1
  48. package/dist/query-feedback-DSVyHtrG.mjs +3 -0
  49. package/dist/router-Bk77E7hj.mjs +3 -0
  50. package/dist/{router-DK_sLsUL.mjs → router-DcHKnEPa.mjs} +1 -1
  51. package/dist/{router-DK_sLsUL.mjs.map → router-DcHKnEPa.mjs.map} +1 -1
  52. package/dist/{sources-Bi7--33T.mjs → sources-kLnQsNrW.mjs} +1 -1
  53. package/dist/{sources-Bi7--33T.mjs.map → sources-kLnQsNrW.mjs.map} +1 -1
  54. package/dist/{sqlite-DtaL1glm.mjs → sqlite-BenGr3UP.mjs} +1 -1
  55. package/dist/{sqlite-DtaL1glm.mjs.map → sqlite-BenGr3UP.mjs.map} +1 -1
  56. package/dist/{state-BY2L6-vX.mjs → state-CAeyOdfq.mjs} +1 -1
  57. package/dist/{state-BY2L6-vX.mjs.map → state-CAeyOdfq.mjs.map} +1 -1
  58. package/dist/{state-8Hm9E4tW.mjs → state-Ca9F_sZc.mjs} +1 -1
  59. package/dist/{themes-BN0a2duq.mjs → themes-BI4GMRP9.mjs} +1 -1
  60. package/dist/{themes-BN0a2duq.mjs.map → themes-BI4GMRP9.mjs.map} +1 -1
  61. package/dist/{tools-CGPqpU3A.mjs → tools-Bp7hj6OW.mjs} +1 -1
  62. package/dist/{tools-y2bJpKom.mjs → tools-DGcB3o_S.mjs} +13 -13
  63. package/dist/{tools-y2bJpKom.mjs.map → tools-DGcB3o_S.mjs.map} +1 -1
  64. package/dist/{trace-h23JCcFD.mjs → trace-bobARFEX.mjs} +1 -1
  65. package/dist/{trace-h23JCcFD.mjs.map → trace-bobARFEX.mjs.map} +1 -1
  66. package/dist/{vault-indexer-DgsPjMgs.mjs → vault-indexer-C3OfXTNF.mjs} +1 -1
  67. package/dist/{vault-indexer-DgsPjMgs.mjs.map → vault-indexer-C3OfXTNF.mjs.map} +1 -1
  68. package/dist/{work-queue-worker-gsKd2LJa.mjs → work-queue-worker-DW8lz-Oo.mjs} +3 -3
  69. package/dist/{work-queue-worker-Dva_v_pI.mjs → work-queue-worker-R7UGIag_.mjs} +3 -3
  70. package/dist/{work-queue-worker-Dva_v_pI.mjs.map → work-queue-worker-R7UGIag_.mjs.map} +1 -1
  71. package/dist/{zettelkasten-vo7psPdT.mjs → zettelkasten-m5QPtb-L.mjs} +3 -3
  72. package/dist/{zettelkasten-vo7psPdT.mjs.map → zettelkasten-m5QPtb-L.mjs.map} +1 -1
  73. package/docs/commands/README.md +4 -0
  74. package/docs/commands/worker.md +56 -0
  75. package/docs/worker.md +89 -1
  76. package/package.json +1 -1
  77. package/src/hooks/ts/pre-tool-use/route-agents-to-worker.ts +2 -2
  78. package/dist/detector-DtLExmHN.mjs +0 -5
  79. package/dist/factory-BXzqRYVZ.mjs +0 -3
  80. package/dist/providers-DUshcB-d.mjs.map +0 -1
  81. package/dist/query-feedback-DhyLOe5S.mjs +0 -3
  82. package/dist/router-1zi8jiNF.mjs +0 -3
  83. /package/dist/{main-resolver-IhZo4pI0.mjs → main-resolver-D6IImXvF.mjs} +0 -0
@@ -150,16 +150,24 @@ var DEFAULT_ROUTING2 = {
150
150
  cooldownMinutes: 30,
151
151
  retryOnQuota: true
152
152
  };
153
+ var DEFAULT_TREE = {
154
+ maxDepth: 2,
155
+ maxChildren: 4
156
+ };
157
+ var DEFAULT_MCP_SETS = {
158
+ desktop: ["clickr"]
159
+ };
153
160
  function defaultWorkersConfig() {
154
161
  return {
155
162
  enabled: false,
156
163
  active: null,
157
164
  providers: {},
158
165
  classes: {},
159
- mcpSets: {},
166
+ mcpSets: { ...DEFAULT_MCP_SETS },
160
167
  pane: { ...DEFAULT_PANE },
161
168
  logDir: DEFAULT_LOG_DIR,
162
- routing: { ...DEFAULT_ROUTING2, order: [] }
169
+ routing: { ...DEFAULT_ROUTING2, order: [] },
170
+ tree: { ...DEFAULT_TREE }
163
171
  };
164
172
  }
165
173
  var WorkersConfigError = class extends Error {
@@ -330,7 +338,7 @@ function parseWorkersConfig(raw) {
330
338
  }
331
339
  }
332
340
  }
333
- const mcpSets = {};
341
+ const mcpSets = { ...DEFAULT_MCP_SETS };
334
342
  if (w.mcpSets !== void 0) {
335
343
  if (typeof w.mcpSets !== "object" || w.mcpSets === null || Array.isArray(w.mcpSets)) {
336
344
  bad(".mcpSets", "must be an object of set name \u2192 [server names]");
@@ -381,6 +389,27 @@ function parseWorkersConfig(raw) {
381
389
  retryOnQuota: r.retryOnQuota === void 0 ? DEFAULT_ROUTING2.retryOnQuota : r.retryOnQuota === true
382
390
  };
383
391
  }
392
+ let tree = { ...DEFAULT_TREE };
393
+ if (w.tree !== void 0) {
394
+ if (typeof w.tree !== "object" || w.tree === null || Array.isArray(w.tree)) {
395
+ bad(".tree", "must be an object");
396
+ }
397
+ const t = w.tree;
398
+ if (t.maxDepth !== void 0) {
399
+ if (typeof t.maxDepth !== "number" || !Number.isInteger(t.maxDepth) || t.maxDepth < 0) {
400
+ bad(".tree.maxDepth", "must be a non-negative integer");
401
+ }
402
+ }
403
+ if (t.maxChildren !== void 0) {
404
+ if (typeof t.maxChildren !== "number" || !Number.isInteger(t.maxChildren) || t.maxChildren < 1) {
405
+ bad(".tree.maxChildren", "must be a positive integer");
406
+ }
407
+ }
408
+ tree = {
409
+ maxDepth: t.maxDepth === void 0 ? DEFAULT_TREE.maxDepth : t.maxDepth,
410
+ maxChildren: t.maxChildren === void 0 ? DEFAULT_TREE.maxChildren : t.maxChildren
411
+ };
412
+ }
384
413
  const active = w.active === void 0 || w.active === null ? null : str(w.active);
385
414
  if (active !== null && active !== "auto" && !(active in providers)) {
386
415
  }
@@ -392,7 +421,8 @@ function parseWorkersConfig(raw) {
392
421
  mcpSets,
393
422
  pane,
394
423
  logDir: str(w.logDir) || d.logDir,
395
- routing
424
+ routing,
425
+ tree
396
426
  };
397
427
  }
398
428
  function readWorkersSection() {
@@ -468,7 +498,44 @@ function workerInScope(worker, term2) {
468
498
  return tabKey(worker.term) === tabKey(term2) && tabKey(term2) !== "";
469
499
  }
470
500
 
501
+ // src/workers/handoff.ts
502
+ import { appendFileSync, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3 } from "node:fs";
503
+ import { dirname, join as join5 } from "node:path";
504
+ function inboxPath(logDir, id) {
505
+ return join5(logDir, `${id}.inbox.jsonl`);
506
+ }
507
+ function readInbox(logDir, id) {
508
+ const path = inboxPath(logDir, id);
509
+ if (!existsSync3(path)) return [];
510
+ const out = [];
511
+ for (const line of readFileSync3(path, "utf8").split("\n")) {
512
+ if (!line.trim()) continue;
513
+ try {
514
+ out.push(JSON.parse(line));
515
+ } catch {
516
+ }
517
+ }
518
+ return out;
519
+ }
520
+
521
+ // src/workers/tree.ts
522
+ function workerDepth(statuses, id) {
523
+ const byId = new Map(statuses.map((s) => [s.id, s]));
524
+ let depth = 0;
525
+ let cur = byId.get(id);
526
+ const seen = /* @__PURE__ */ new Set([id]);
527
+ while (cur?.parent && !seen.has(cur.parent)) {
528
+ seen.add(cur.parent);
529
+ const next = byId.get(cur.parent);
530
+ if (!next) break;
531
+ depth += 1;
532
+ cur = next;
533
+ }
534
+ return depth;
535
+ }
536
+
471
537
  // src/workers/report.ts
538
+ var OPERATOR_MARK = "[operator]";
472
539
  var WORKER_CONTRACT_PROMPT = [
473
540
  "You are a headless implementation worker, run non-interactively by an orchestrating session.",
474
541
  "No narration, no timestamps, no greetings, no summaries of what you read; act, verify, then stop.",
@@ -476,7 +543,20 @@ var WORKER_CONTRACT_PROMPT = [
476
543
  '{"changed":[{"path":"\u2026","summary":"\u2026"}],"commands":["\u2026"],"checks":[{"name":"\u2026","ok":true,"detail":"\u2026"}],"open":["\u2026"],"notes":"one line"}',
477
544
  "changed: files you touched (path + one-line summary). commands: the commands that verify the work.",
478
545
  "checks: each with ok true/false and the evidence in detail. open: what you could not finish, if anything.",
479
- "notes: one line, the headline a reviewer reads first."
546
+ "notes: one line, the headline a reviewer reads first.",
547
+ "",
548
+ `Operator messages: a user turn starting with ${OPERATOR_MARK} was typed by the operator while you`,
549
+ "run (the prompt of a resumed run is the operator's too). Answer it FIRST, in one or two plain lines \u2014",
550
+ "a question gets its answer, an instruction gets one line naming what will change \u2014 then continue the",
551
+ "task you were on.",
552
+ "",
553
+ "Sub-workers: you may start your own workers with `pai worker run --class <class> -p '<prompt>'`",
554
+ "(Bash tool). Your children run on their own provider and report back to you automatically when",
555
+ "they finish. Send a handoff UP instead of doing work yourself when a cheaper provider would",
556
+ "suffice, the task is out of your scope, or a decision is needed:",
557
+ '`pai worker handoff \'{"kind":"proposal","text":"\u2026","data":{\u2026}}\'` (kinds: proposal,',
558
+ "question, blocker; results are sent for you when you finish). Sibling workers are not a",
559
+ "coordination path \u2014 there is no sideways channel; everything goes up to your parent."
480
560
  ].join("\n");
481
561
 
482
562
  // src/workers/render.ts
@@ -504,9 +584,9 @@ function contextMeter(c, s, minPct = 0) {
504
584
  if (pct > 70) return c("yellow", label);
505
585
  return label;
506
586
  }
507
- function renderStatusLine(mine, now = /* @__PURE__ */ new Date(), c = makeColor(true)) {
587
+ function renderStatusLine(mine, now = /* @__PURE__ */ new Date(), c = makeColor(true), all = mine, inbox = {}) {
508
588
  if (!mine.length) return "";
509
- const running = mine.filter((s) => s.state === "running" && alive(s.pid));
589
+ const running = mine.filter((s) => s.state === "running" && alive(s.pid)).sort((a, b) => workerDepth(all, a.id) - workerDepth(all, b.id));
510
590
  const today = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`;
511
591
  const doneToday = mine.filter((s) => s.state !== "running" && s.started.startsWith(today));
512
592
  const ok = doneToday.filter((s) => s.state === "done").length;
@@ -516,7 +596,10 @@ function renderStatusLine(mine, now = /* @__PURE__ */ new Date(), c = makeColor(
516
596
  let head = `${providerTag} \u25B6${running.length}`;
517
597
  const parts = running.slice(0, 3).map((s) => {
518
598
  const meter = contextMeter(c, s, 60);
519
- return `${s.id.slice(-4)} ${s.label.slice(0, 26)} ${ageOf(s.started, now)} \xB7 ${s.last.slice(0, 30)}` + (meter ? ` ${meter}` : "");
599
+ const depth = workerDepth(all, s.id);
600
+ const lead = depth > 0 ? " ".repeat(depth - 1) + "\u21B3 " : "";
601
+ const box = inbox[s.id] ? ` \u25C6${inbox[s.id]}` : "";
602
+ return `${lead}${s.id.slice(-4)} ${s.label.slice(0, 26)} ${ageOf(s.started, now)} \xB7 ${s.last.slice(0, 30)}${box}` + (meter ? ` ${meter}` : "");
520
603
  });
521
604
  if (parts.length) head += " " + parts.join(" | ");
522
605
  if (doneToday.length) head += ` \u2713${ok} \u2717${bad2} today`;
@@ -524,6 +607,14 @@ function renderStatusLine(mine, now = /* @__PURE__ */ new Date(), c = makeColor(
524
607
  }
525
608
 
526
609
  // src/workers/viewer.ts
610
+ function inboxCounts(logDir, statuses) {
611
+ const out = {};
612
+ for (const s of statuses) {
613
+ const n = readInbox(logDir, s.id).length;
614
+ if (n) out[s.id] = n;
615
+ }
616
+ return out;
617
+ }
527
618
  function statusLineOutput(logDir, term2, cwd2, now = /* @__PURE__ */ new Date()) {
528
619
  const statuses = loadStatuses(logDir);
529
620
  const mine = statuses.filter((s) => {
@@ -531,7 +622,7 @@ function statusLineOutput(logDir, term2, cwd2, now = /* @__PURE__ */ new Date())
531
622
  const sameDir = cwd2 && s.cwd.startsWith(cwd2);
532
623
  return sameScope || !term2 && sameDir;
533
624
  });
534
- return renderStatusLine(mine, now);
625
+ return renderStatusLine(mine, now, makeColor(false), statuses, inboxCounts(logDir, mine));
535
626
  }
536
627
 
537
628
  // src/workers/standalone/status-line.ts