@tekmidian/pai 0.61.0 → 0.63.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 (69) hide show
  1. package/dist/{async-CLvuY7b-.mjs → async-DNVWtQl2.mjs} +2 -2
  2. package/dist/{async-CLvuY7b-.mjs.map → async-DNVWtQl2.mjs.map} +1 -1
  3. package/dist/{chain-C5oeyUg4.mjs → chain-CUfE6WYK.mjs} +2 -2
  4. package/dist/{chain-C5oeyUg4.mjs.map → chain-CUfE6WYK.mjs.map} +1 -1
  5. package/dist/cli/index.mjs +11 -11
  6. package/dist/cli/program.mjs +11 -11
  7. package/dist/{context-handover-cache-BdtJZpgv.mjs → context-handover-cache-DFNnlWv2.mjs} +2 -2
  8. package/dist/{context-handover-cache-BdtJZpgv.mjs.map → context-handover-cache-DFNnlWv2.mjs.map} +1 -1
  9. package/dist/daemon/index.mjs +8 -8
  10. package/dist/daemon-C8-uzOuV.mjs +19 -0
  11. package/dist/{daemon-DSsIEqzW.mjs → daemon-Cex3dT9f.mjs} +32 -18
  12. package/dist/{daemon-DSsIEqzW.mjs.map → daemon-Cex3dT9f.mjs.map} +1 -1
  13. package/dist/daemon-mcp/index.mjs +4 -4
  14. package/dist/{factory-EUUhSSoq.mjs → factory-BozZa81q.mjs} +3 -3
  15. package/dist/{factory-EUUhSSoq.mjs.map → factory-BozZa81q.mjs.map} +1 -1
  16. package/dist/{factory-DW7BCJJT.mjs → factory-UO9_DFMN.mjs} +1 -1
  17. package/dist/{fallback-DDbJVaR8.mjs → fallback-ktbR0aR7.mjs} +2 -2
  18. package/dist/{fallback-DDbJVaR8.mjs.map → fallback-ktbR0aR7.mjs.map} +1 -1
  19. package/dist/{helpers-D9WkIf9R.mjs → helpers-Dj-B314s.mjs} +3 -2
  20. package/dist/{helpers-D9WkIf9R.mjs.map → helpers-Dj-B314s.mjs.map} +1 -1
  21. package/dist/hooks/block-sleep-poll.mjs.map +2 -2
  22. package/dist/hooks/load-project-context.mjs +8519 -133
  23. package/dist/hooks/load-project-context.mjs.map +4 -4
  24. package/dist/hooks/security-validator.mjs.map +1 -1
  25. package/dist/hooks/worker-guard.mjs +7859 -0
  26. package/dist/hooks/worker-guard.mjs.map +7 -0
  27. package/dist/hooks/worker-status-line.mjs +101 -8
  28. package/dist/hooks/worker-status-line.mjs.map +4 -4
  29. package/dist/index.mjs +1 -1
  30. package/dist/{indexer-backend-DcDtin1O.mjs → indexer-backend-BN9rpp9O.mjs} +2 -2
  31. package/dist/{main-resolver-DIQ6m_RA.mjs → main-resolver-BIft_FVF.mjs} +3 -3
  32. package/dist/{main-resolver-DIQ6m_RA.mjs.map → main-resolver-BIft_FVF.mjs.map} +1 -1
  33. package/dist/{main-resolver-CxOsxtOr.mjs → main-resolver-C9-poMdi.mjs} +1 -1
  34. package/dist/{planner-D8jAr_sx.mjs → planner-DAQMTMjP.mjs} +4 -4
  35. package/dist/{planner-D8jAr_sx.mjs.map → planner-DAQMTMjP.mjs.map} +1 -1
  36. package/dist/{postgres-nvU5pShF.mjs → postgres-CxD6_Dca.mjs} +3 -3
  37. package/dist/{postgres-nvU5pShF.mjs.map → postgres-CxD6_Dca.mjs.map} +1 -1
  38. package/dist/{program-BTdspOOa.mjs → program-De1GVVM4.mjs} +178 -48
  39. package/dist/program-De1GVVM4.mjs.map +1 -0
  40. package/dist/{run-CxxZKEZw.mjs → run-CZVCCvXE.mjs} +353 -133
  41. package/dist/run-CZVCCvXE.mjs.map +1 -0
  42. package/dist/{session-keepalive-urk--pfa.mjs → session-keepalive-CWGzLBVU.mjs} +2 -2
  43. package/dist/{session-keepalive-urk--pfa.mjs.map → session-keepalive-CWGzLBVU.mjs.map} +1 -1
  44. package/dist/{sqlite-D9p5a4qe.mjs → sqlite-CfKfuggn.mjs} +2 -2
  45. package/dist/{sqlite-D9p5a4qe.mjs.map → sqlite-CfKfuggn.mjs.map} +1 -1
  46. package/dist/{tools-r-7ZG8B5.mjs → tools-B52IvaU6.mjs} +3 -3
  47. package/dist/{tools-qXyHFwNj.mjs → tools-DFdPbX-X.mjs} +2 -2
  48. package/dist/{tools-qXyHFwNj.mjs.map → tools-DFdPbX-X.mjs.map} +1 -1
  49. package/dist/{vault-indexer-DHYBpRZ5.mjs → vault-indexer-mCFus_AM.mjs} +2 -2
  50. package/dist/{vault-indexer-DHYBpRZ5.mjs.map → vault-indexer-mCFus_AM.mjs.map} +1 -1
  51. package/dist/{wakeup-C48hcN6O.mjs → wakeup-DO1O4udw.mjs} +2 -2
  52. package/dist/{wakeup-C48hcN6O.mjs.map → wakeup-DO1O4udw.mjs.map} +1 -1
  53. package/dist/{work-queue-worker-DUvPiwGO.mjs → work-queue-worker-BbrC3I_R.mjs} +2 -2
  54. package/dist/{work-queue-worker-DUvPiwGO.mjs.map → work-queue-worker-BbrC3I_R.mjs.map} +1 -1
  55. package/dist/{work-queue-worker-1_VBfI_k.mjs → work-queue-worker-z-AATZ2t.mjs} +3 -3
  56. package/docs/commands/README.md +4 -0
  57. package/docs/commands/project.md +14 -5
  58. package/docs/commands/projects.md +14 -5
  59. package/docs/commands/worker.md +27 -0
  60. package/package.json +2 -2
  61. package/scripts/build-hooks.mjs +6 -5
  62. package/scripts/build-skill-stubs.mjs +6 -5
  63. package/src/hooks/ts/lib/worker-guard.test.ts +188 -0
  64. package/src/hooks/ts/lib/worker-guard.ts +315 -0
  65. package/src/hooks/ts/pre-tool-use/worker-guard.ts +75 -0
  66. package/src/hooks/ts/session-start/load-project-context.ts +23 -0
  67. package/dist/daemon-MoFF4oeg.mjs +0 -19
  68. package/dist/program-BTdspOOa.mjs.map +0 -1
  69. package/dist/run-CxxZKEZw.mjs.map +0 -1
@@ -8273,16 +8273,20 @@ function expandHome(p) {
8273
8273
  }
8274
8274
 
8275
8275
  // src/workers/paths.ts
8276
+ import { join as join6 } from "node:path";
8276
8277
  function workersLogDir(config) {
8277
8278
  const expanded = expandHome(config.logDir);
8278
8279
  if (config.logDir !== DEFAULT_LOG_DIR) return expanded;
8279
8280
  return resolvePaiFile(paiHomePath("logs", "workers"), [expanded], "pai config migrate --logs");
8280
8281
  }
8282
+ function statusPath(logDir, id) {
8283
+ return join6(logDir, `${id}.status`);
8284
+ }
8281
8285
 
8282
8286
  // src/workers/scope.ts
8283
8287
  import { existsSync as existsSync6, readFileSync as readFileSync6, renameSync as renameSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "node:fs";
8284
8288
  import { homedir as homedir5 } from "node:os";
8285
- import { join as join7 } from "node:path";
8289
+ import { join as join8 } from "node:path";
8286
8290
 
8287
8291
  // src/workers/status.ts
8288
8292
  import { execFileSync } from "node:child_process";
@@ -8295,7 +8299,7 @@ import {
8295
8299
  rmSync,
8296
8300
  writeFileSync as writeFileSync3
8297
8301
  } from "node:fs";
8298
- import { join as join6 } from "node:path";
8302
+ import { join as join7 } from "node:path";
8299
8303
 
8300
8304
  // src/workers/args.ts
8301
8305
  function shortText(s, n) {
@@ -8314,7 +8318,7 @@ function loadStatuses(logDir) {
8314
8318
  for (const name of readdirSync2(logDir).sort()) {
8315
8319
  if (!name.endsWith(".status")) continue;
8316
8320
  try {
8317
- out.push(JSON.parse(readFileSync5(join6(logDir, name), "utf8")));
8321
+ out.push(JSON.parse(readFileSync5(join7(logDir, name), "utf8")));
8318
8322
  } catch {
8319
8323
  }
8320
8324
  }
@@ -8355,7 +8359,7 @@ function ageOf(ts, now = /* @__PURE__ */ new Date()) {
8355
8359
  }
8356
8360
 
8357
8361
  // src/workers/scope.ts
8358
- var AIBROKER_REGISTRY = join7(homedir5(), ".aibroker", "session-names.json");
8362
+ var AIBROKER_REGISTRY = join8(homedir5(), ".aibroker", "session-names.json");
8359
8363
  function tabKey(term2) {
8360
8364
  if (!term2) return "";
8361
8365
  const head = term2.split("p", 1)[0];
@@ -8378,7 +8382,7 @@ function workerInScope(worker, term2) {
8378
8382
  var SPAWNER_SESSION_TTL_MS = 10 * 6e4;
8379
8383
  var SESSION_MAP_PRUNE_MS = 60 * 6e4;
8380
8384
  function sessionMapPath(logDir) {
8381
- return join7(logDir, "claude-session-map.json");
8385
+ return join8(logDir, "claude-session-map.json");
8382
8386
  }
8383
8387
  function recordSessionMapEntry(logDir, cwd2, session, term2, now = Date.now()) {
8384
8388
  if (!cwd2 || !session) return;
@@ -8409,15 +8413,102 @@ function recordSessionMapEntry(logDir, cwd2, session, term2, now = Date.now()) {
8409
8413
  }
8410
8414
  }
8411
8415
 
8412
- // src/workers/agentish.ts
8416
+ // src/workers/pending.ts
8417
+ import { existsSync as existsSync7, readFileSync as readFileSync7, statSync as statSync2, writeFileSync as writeFileSync5 } from "node:fs";
8418
+ import { join as join9 } from "node:path";
8419
+
8420
+ // src/workers/worktree.ts
8413
8421
  import { execFileSync as execFileSync2 } from "node:child_process";
8422
+ function runGit(cwd2, args, env, timeout = 3e4) {
8423
+ try {
8424
+ return execFileSync2("git", ["-C", cwd2, ...args], {
8425
+ encoding: "utf8",
8426
+ timeout,
8427
+ stdio: ["ignore", "pipe", "pipe"],
8428
+ ...env ? { env } : {}
8429
+ }).trim();
8430
+ } catch (e) {
8431
+ const err = e;
8432
+ const why = (typeof err.stderr === "string" ? err.stderr : err.stderr?.toString("utf8")) || err.message || String(e);
8433
+ throw new Error(`git ${args.join(" ")} in ${cwd2}: ${why.trim()}`);
8434
+ }
8435
+ }
8436
+ function git(cwd2, args, timeoutMs) {
8437
+ return runGit(cwd2, args, void 0, timeoutMs);
8438
+ }
8439
+ function uncommittedPaths(wtDir, timeoutMs) {
8440
+ const tracked = git(wtDir, ["diff", "--name-only", "HEAD"], timeoutMs).split("\n").filter(Boolean);
8441
+ const untracked = git(wtDir, ["ls-files", "--others", "--exclude-standard"], timeoutMs).split("\n").filter(Boolean);
8442
+ return [...tracked, ...untracked];
8443
+ }
8444
+
8445
+ // src/workers/pending.ts
8446
+ function toplevel(dir) {
8447
+ try {
8448
+ return git(dir, ["rev-parse", "--show-toplevel"]);
8449
+ } catch {
8450
+ return null;
8451
+ }
8452
+ }
8453
+ function fmtAge(ms) {
8454
+ const h = Math.floor(ms / 36e5);
8455
+ return h >= 48 ? `${Math.floor(h / 24)}d` : h >= 1 ? `${h}h` : `${Math.floor(ms / 6e4)}m`;
8456
+ }
8457
+ function pendingResults(logDir, repoRoot, now = Date.now()) {
8458
+ const want = repoRoot ? toplevel(repoRoot) : null;
8459
+ if (repoRoot && !want) return [];
8460
+ const out = [];
8461
+ for (const st of loadStatuses(logDir)) {
8462
+ if (st.archived || st.merged || isLive(st)) continue;
8463
+ if (!st.worktreeDir || !existsSync7(st.worktreeDir)) continue;
8464
+ const repo = toplevel(st.cwd);
8465
+ if (!repo || want && repo !== want) continue;
8466
+ let commits = 0;
8467
+ let dirty = 0;
8468
+ try {
8469
+ if (st.branch) {
8470
+ commits = git(repo, ["cherry", "HEAD", `refs/heads/${st.branch}`]).split("\n").filter((l) => l.startsWith("+")).length;
8471
+ }
8472
+ dirty = uncommittedPaths(st.worktreeDir).filter((p) => !/(^|\/)node_modules(\/|$)/.test(p)).length;
8473
+ } catch {
8474
+ continue;
8475
+ }
8476
+ if (!commits && !dirty) continue;
8477
+ let ageMs = 0;
8478
+ try {
8479
+ ageMs = Math.max(0, now - statSync2(statusPath(logDir, st.id)).mtimeMs);
8480
+ } catch {
8481
+ }
8482
+ out.push({ id: st.id, label: st.label, repo, ageMs, age: fmtAge(ageMs), commits, dirty });
8483
+ }
8484
+ return out;
8485
+ }
8486
+ function pendingCountCached(logDir, cwd2, ttlMs = 6e4, now = Date.now()) {
8487
+ const file = join9(logDir, "pending-cache.json");
8488
+ let cache = {};
8489
+ try {
8490
+ cache = JSON.parse(readFileSync7(file, "utf8"));
8491
+ } catch {
8492
+ }
8493
+ const hit = cache[cwd2];
8494
+ if (hit && now - hit.at < ttlMs) return hit.n;
8495
+ const n = pendingResults(logDir, cwd2, now).length;
8496
+ try {
8497
+ writeFileSync5(file, JSON.stringify({ ...cache, [cwd2]: { at: now, n } }));
8498
+ } catch {
8499
+ }
8500
+ return n;
8501
+ }
8502
+
8503
+ // src/workers/agentish.ts
8504
+ import { execFileSync as execFileSync3 } from "node:child_process";
8414
8505
  var AG2_SPEC_FALLBACK = "AG2. msg=kind line+k=v lines. kinds T R S Q A X. keys i id g goal o own n forbid d steps p proof u out l limits r res c changes t tests G gate I inst m images # nums w worst x next z note(<200ch). sep |. outcomes + - ~ ? !. @n=path declared once then reused; @n:12=file:line. tests as Name+ Name-. no prose, no articles, never restate, unknown=?. r=+ only if all t +.";
8415
8506
  var AG2_EXTENSIONS_FALLBACK = "y why(\u2264600ch)";
8416
8507
  var cachedSpec = null;
8417
8508
  function ag2Spec() {
8418
8509
  if (cachedSpec) return cachedSpec;
8419
8510
  try {
8420
- const out = execFileSync2("aibroker", ["agentish", "spec"], {
8511
+ const out = execFileSync3("aibroker", ["agentish", "spec"], {
8421
8512
  timeout: 3e3,
8422
8513
  stdio: ["ignore", "pipe", "ignore"],
8423
8514
  encoding: "utf8"
@@ -8599,7 +8690,9 @@ try {
8599
8690
  const { workers } = readWorkersSection();
8600
8691
  const logDir = workersLogDir(workers);
8601
8692
  if (claudeSession) recordSessionMapEntry(logDir, cwd, claudeSession, term);
8602
- const out = statusLineOutput(logDir, term, cwd, claudeSession, /* @__PURE__ */ new Date(), workers.active);
8693
+ let out = statusLineOutput(logDir, term, cwd, claudeSession, /* @__PURE__ */ new Date(), workers.active);
8694
+ const unmerged = pendingCountCached(logDir, cwd);
8695
+ if (unmerged) out = [out, `\u2691${unmerged} unmerged`].filter(Boolean).join(" ");
8603
8696
  if (out) process.stdout.write(out + "\n");
8604
8697
  } catch {
8605
8698
  }