pi-subagents 0.75.0 → 0.76.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 (137) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/docs/agents.md +1 -1
  3. package/docs/configuration.md +4 -2
  4. package/docs/extension-api.md +1 -1
  5. package/docs/missions.md +12 -2
  6. package/docs/tool-reference.md +21 -6
  7. package/docs/workflows.md +1 -1
  8. package/package.json +2 -1
  9. package/src/agents/agent-memory.js +3 -3
  10. package/src/agents/agent-memory.js.map +1 -1
  11. package/src/agents/agent-serializer.d.ts.map +1 -1
  12. package/src/agents/agent-serializer.js +8 -1
  13. package/src/agents/agent-serializer.js.map +1 -1
  14. package/src/agents/agents.d.ts.map +1 -1
  15. package/src/agents/agents.js +101 -121
  16. package/src/agents/agents.js.map +1 -1
  17. package/src/extension/index.d.ts.map +1 -1
  18. package/src/extension/index.js +37 -4
  19. package/src/extension/index.js.map +1 -1
  20. package/src/extension/reply-workflow-script.d.ts.map +1 -1
  21. package/src/extension/reply-workflow-script.js +20 -11
  22. package/src/extension/reply-workflow-script.js.map +1 -1
  23. package/src/extension/schemas.d.ts +1 -1
  24. package/src/extension/schemas.js +8 -8
  25. package/src/extension/schemas.js.map +1 -1
  26. package/src/extension/tool-description.js +1 -1
  27. package/src/extension/tool-description.js.map +1 -1
  28. package/src/intercom/result-intercom.d.ts.map +1 -1
  29. package/src/intercom/result-intercom.js +2 -1
  30. package/src/intercom/result-intercom.js.map +1 -1
  31. package/src/profiles/profiles.d.ts.map +1 -1
  32. package/src/profiles/profiles.js +25 -22
  33. package/src/profiles/profiles.js.map +1 -1
  34. package/src/runs/background/active-async-capacity.d.ts +15 -1
  35. package/src/runs/background/active-async-capacity.d.ts.map +1 -1
  36. package/src/runs/background/active-async-capacity.js +51 -6
  37. package/src/runs/background/active-async-capacity.js.map +1 -1
  38. package/src/runs/background/async-job-tracker.d.ts +3 -2
  39. package/src/runs/background/async-job-tracker.d.ts.map +1 -1
  40. package/src/runs/background/async-job-tracker.js +2 -1
  41. package/src/runs/background/async-job-tracker.js.map +1 -1
  42. package/src/runs/background/calendar-schedule.d.ts +27 -0
  43. package/src/runs/background/calendar-schedule.d.ts.map +1 -0
  44. package/src/runs/background/calendar-schedule.js +94 -0
  45. package/src/runs/background/calendar-schedule.js.map +1 -0
  46. package/src/runs/background/notify.d.ts +6 -0
  47. package/src/runs/background/notify.d.ts.map +1 -1
  48. package/src/runs/background/notify.js +24 -4
  49. package/src/runs/background/notify.js.map +1 -1
  50. package/src/runs/background/result-watcher.d.ts +5 -1
  51. package/src/runs/background/result-watcher.d.ts.map +1 -1
  52. package/src/runs/background/result-watcher.js +44 -7
  53. package/src/runs/background/result-watcher.js.map +1 -1
  54. package/src/runs/background/run-child-session.d.ts +2 -0
  55. package/src/runs/background/run-child-session.d.ts.map +1 -1
  56. package/src/runs/background/run-child-session.js +12 -1
  57. package/src/runs/background/run-child-session.js.map +1 -1
  58. package/src/runs/background/scheduled-runs.d.ts +3 -1
  59. package/src/runs/background/scheduled-runs.d.ts.map +1 -1
  60. package/src/runs/background/scheduled-runs.js +184 -47
  61. package/src/runs/background/scheduled-runs.js.map +1 -1
  62. package/src/runs/background/subagent-runner.d.ts +1 -0
  63. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  64. package/src/runs/background/subagent-runner.js +14 -6
  65. package/src/runs/background/subagent-runner.js.map +1 -1
  66. package/src/runs/background/wait-completions.d.ts.map +1 -1
  67. package/src/runs/background/wait-completions.js +1 -0
  68. package/src/runs/background/wait-completions.js.map +1 -1
  69. package/src/runs/background/workflow-terminal-proof.d.ts +14 -1
  70. package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -1
  71. package/src/runs/background/workflow-terminal-proof.js +41 -28
  72. package/src/runs/background/workflow-terminal-proof.js.map +1 -1
  73. package/src/runs/foreground/execution.d.ts.map +1 -1
  74. package/src/runs/foreground/execution.js +23 -3
  75. package/src/runs/foreground/execution.js.map +1 -1
  76. package/src/runs/foreground/foreground-history.d.ts.map +1 -1
  77. package/src/runs/foreground/foreground-history.js +1 -0
  78. package/src/runs/foreground/foreground-history.js.map +1 -1
  79. package/src/runs/foreground/subagent-executor.d.ts +1 -1
  80. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  81. package/src/runs/foreground/subagent-executor.js +44 -6
  82. package/src/runs/foreground/subagent-executor.js.map +1 -1
  83. package/src/runs/shared/child-session.d.ts.map +1 -1
  84. package/src/runs/shared/child-session.js +10 -2
  85. package/src/runs/shared/child-session.js.map +1 -1
  86. package/src/runs/shared/mcp-direct-tool-allowlist.d.ts.map +1 -1
  87. package/src/runs/shared/mcp-direct-tool-allowlist.js +5 -3
  88. package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
  89. package/src/runs/shared/parallel-handoff.d.ts +10 -4
  90. package/src/runs/shared/parallel-handoff.d.ts.map +1 -1
  91. package/src/runs/shared/parallel-handoff.js +53 -6
  92. package/src/runs/shared/parallel-handoff.js.map +1 -1
  93. package/src/runs/shared/partial-output.d.ts +18 -0
  94. package/src/runs/shared/partial-output.d.ts.map +1 -0
  95. package/src/runs/shared/partial-output.js +29 -0
  96. package/src/runs/shared/partial-output.js.map +1 -0
  97. package/src/runs/shared/worktree-cleanup-apply.d.ts +37 -0
  98. package/src/runs/shared/worktree-cleanup-apply.d.ts.map +1 -0
  99. package/src/runs/shared/worktree-cleanup-apply.js +179 -0
  100. package/src/runs/shared/worktree-cleanup-apply.js.map +1 -0
  101. package/src/runs/shared/worktree-cleanup-plan.d.ts +7 -0
  102. package/src/runs/shared/worktree-cleanup-plan.d.ts.map +1 -1
  103. package/src/runs/shared/worktree-cleanup-plan.js +41 -19
  104. package/src/runs/shared/worktree-cleanup-plan.js.map +1 -1
  105. package/src/runs/shared/worktree-lock.d.ts +6 -0
  106. package/src/runs/shared/worktree-lock.d.ts.map +1 -0
  107. package/src/runs/shared/worktree-lock.js +41 -0
  108. package/src/runs/shared/worktree-lock.js.map +1 -0
  109. package/src/runs/shared/worktree.d.ts +3 -0
  110. package/src/runs/shared/worktree.d.ts.map +1 -1
  111. package/src/runs/shared/worktree.js +9 -1
  112. package/src/runs/shared/worktree.js.map +1 -1
  113. package/src/shared/file-lease.d.ts +5 -0
  114. package/src/shared/file-lease.d.ts.map +1 -0
  115. package/src/shared/file-lease.js +101 -0
  116. package/src/shared/file-lease.js.map +1 -0
  117. package/src/shared/settings-file-lease.d.ts +5 -0
  118. package/src/shared/settings-file-lease.d.ts.map +1 -0
  119. package/src/shared/settings-file-lease.js +39 -0
  120. package/src/shared/settings-file-lease.js.map +1 -0
  121. package/src/shared/types.d.ts +10 -0
  122. package/src/shared/types.d.ts.map +1 -1
  123. package/src/shared/types.js.map +1 -1
  124. package/src/tui/render.d.ts.map +1 -1
  125. package/src/tui/render.js +7 -2
  126. package/src/tui/render.js.map +1 -1
  127. package/src/watchdog/diff-tool.js +2 -2
  128. package/src/watchdog/diff-tool.js.map +1 -1
  129. package/src/watchdog/register-main.js +1 -2
  130. package/src/watchdog/register-main.js.map +1 -1
  131. package/src/watchdog/runtime.d.ts +3 -3
  132. package/src/watchdog/runtime.d.ts.map +1 -1
  133. package/src/watchdog/runtime.js +7 -3
  134. package/src/watchdog/runtime.js.map +1 -1
  135. package/src/watchdog/settings.d.ts.map +1 -1
  136. package/src/watchdog/settings.js +22 -17
  137. package/src/watchdog/settings.js.map +1 -1
@@ -8,6 +8,7 @@ import * as os from "node:os";
8
8
  import * as path from "node:path";
9
9
  import { fileURLToPath } from "node:url";
10
10
  import { createAtomicJsonWriter } from "../shared/atomic-json.js";
11
+ import { resolveSettingsWriteTarget, withSettingsFileLease } from "../shared/settings-file-lease.js";
11
12
  import { CODE_OWNED_EXTERNAL_CLI_ADAPTER_LABEL, isCodeOwnedExternalCliAdapterId, parseExternalCliCapabilityNarrowing, validateCodeOwnedProfileRunner } from "../runs/shared/external-cli-contract.js";
12
13
  import { isClaudeCodeAdapterId } from "../runs/shared/claude-code-adapter.js";
13
14
  import { getAgentDir, getProjectConfigDir } from "../shared/utils.js";
@@ -688,35 +689,6 @@ function writeSettingsFile(filePath, settings) {
688
689
  });
689
690
  writeAtomicSettings(targetPath, settings);
690
691
  }
691
- function resolveSettingsWriteTarget(filePath) {
692
- let targetPath = filePath;
693
- for (;;) {
694
- try {
695
- return fs.realpathSync.native(targetPath);
696
- }
697
- catch (error) {
698
- if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
699
- throw error;
700
- // A trailing separator requires a directory; it cannot name a new settings file.
701
- if (targetPath.endsWith("/") || targetPath.endsWith(path.sep))
702
- throw error;
703
- }
704
- // A missing target is allowed only when its physical parent already exists.
705
- const parentPath = fs.realpathSync.native(path.dirname(targetPath));
706
- const unresolvedPath = path.join(parentPath, path.basename(targetPath));
707
- let linkText;
708
- try {
709
- linkText = fs.readlinkSync(unresolvedPath);
710
- }
711
- catch (error) {
712
- if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
713
- throw error;
714
- return unresolvedPath;
715
- }
716
- // Keep link text intact so the filesystem follows directory links before "..".
717
- targetPath = path.isAbsolute(linkText) ? linkText : `${parentPath}${path.sep}${linkText}`;
718
- }
719
- }
720
692
  function parseOverrideStringArrayOrFalse(value, meta) {
721
693
  if (value === undefined)
722
694
  return undefined;
@@ -1487,18 +1459,20 @@ export function saveBuiltinAgentOverride(cwd, name, scope, override) {
1487
1459
  const filePath = scope === "project" ? getProjectAgentSettingsPath(cwd) : getUserAgentSettingsPath();
1488
1460
  if (!filePath)
1489
1461
  throw new Error("Project override is not available here. No project config root was found.");
1490
- const settings = readSettingsFileStrict(filePath);
1491
- const subagents = settings.subagents && typeof settings.subagents === "object" && !Array.isArray(settings.subagents)
1492
- ? { ...settings.subagents }
1493
- : {};
1494
- const agentOverrides = subagents.agentOverrides && typeof subagents.agentOverrides === "object" && !Array.isArray(subagents.agentOverrides)
1495
- ? { ...subagents.agentOverrides }
1496
- : {};
1497
- agentOverrides[name] = cloneOverrideValue(override);
1498
- subagents.agentOverrides = agentOverrides;
1499
- settings.subagents = subagents;
1500
- writeSettingsFile(filePath, settings);
1501
- return filePath;
1462
+ return withSettingsFileLease(filePath, () => {
1463
+ const settings = readSettingsFileStrict(filePath);
1464
+ const subagents = settings.subagents && typeof settings.subagents === "object" && !Array.isArray(settings.subagents)
1465
+ ? { ...settings.subagents }
1466
+ : {};
1467
+ const agentOverrides = subagents.agentOverrides && typeof subagents.agentOverrides === "object" && !Array.isArray(subagents.agentOverrides)
1468
+ ? { ...subagents.agentOverrides }
1469
+ : {};
1470
+ agentOverrides[name] = cloneOverrideValue(override);
1471
+ subagents.agentOverrides = agentOverrides;
1472
+ settings.subagents = subagents;
1473
+ writeSettingsFile(filePath, settings);
1474
+ return filePath;
1475
+ });
1502
1476
  }
1503
1477
  export function removeBuiltinAgentOverride(cwd, name, scope, options) {
1504
1478
  const filePath = scope === "project" ? getProjectAgentSettingsPath(cwd) : getUserAgentSettingsPath();
@@ -1506,55 +1480,59 @@ export function removeBuiltinAgentOverride(cwd, name, scope, options) {
1506
1480
  throw new Error("Project override is not available here. No project config root was found.");
1507
1481
  if (!fs.existsSync(filePath))
1508
1482
  return { path: filePath, removed: false, machinePreserved: false };
1509
- const settings = readSettingsFileStrict(filePath);
1510
- const subagents = settings.subagents;
1511
- if (!subagents || typeof subagents !== "object" || Array.isArray(subagents))
1512
- return { path: filePath, removed: false, machinePreserved: false };
1513
- const nextSubagents = { ...subagents };
1514
- const agentOverrides = nextSubagents.agentOverrides;
1515
- if (!agentOverrides || typeof agentOverrides !== "object" || Array.isArray(agentOverrides))
1516
- return { path: filePath, removed: false, machinePreserved: false };
1517
- const nextOverrides = { ...agentOverrides };
1518
- const current = nextOverrides[name];
1519
- if (!Object.prototype.hasOwnProperty.call(nextOverrides, name))
1520
- return { path: filePath, removed: false, machinePreserved: false };
1521
- const configuredMachine = current && typeof current === "object" && !Array.isArray(current) ? current.machine : undefined;
1522
- const machine = configuredMachine === false || (typeof configuredMachine === "string" && configuredMachine.trim()) ? configuredMachine : undefined;
1523
- if (options?.preserveMachine && machine !== undefined)
1524
- nextOverrides[name] = { machine };
1525
- else
1526
- delete nextOverrides[name];
1527
- if (Object.keys(nextOverrides).length > 0)
1528
- nextSubagents.agentOverrides = nextOverrides;
1529
- else
1530
- delete nextSubagents.agentOverrides;
1531
- if (Object.keys(nextSubagents).length > 0)
1532
- settings.subagents = nextSubagents;
1533
- else
1534
- delete settings.subagents;
1535
- writeSettingsFile(filePath, settings);
1536
- return { path: filePath, removed: true, machinePreserved: options?.preserveMachine === true && machine !== undefined };
1483
+ return withSettingsFileLease(filePath, () => {
1484
+ const settings = readSettingsFileStrict(filePath);
1485
+ const subagents = settings.subagents;
1486
+ if (!subagents || typeof subagents !== "object" || Array.isArray(subagents))
1487
+ return { path: filePath, removed: false, machinePreserved: false };
1488
+ const nextSubagents = { ...subagents };
1489
+ const agentOverrides = nextSubagents.agentOverrides;
1490
+ if (!agentOverrides || typeof agentOverrides !== "object" || Array.isArray(agentOverrides))
1491
+ return { path: filePath, removed: false, machinePreserved: false };
1492
+ const nextOverrides = { ...agentOverrides };
1493
+ const current = nextOverrides[name];
1494
+ if (!Object.prototype.hasOwnProperty.call(nextOverrides, name))
1495
+ return { path: filePath, removed: false, machinePreserved: false };
1496
+ const configuredMachine = current && typeof current === "object" && !Array.isArray(current) ? current.machine : undefined;
1497
+ const machine = configuredMachine === false || (typeof configuredMachine === "string" && configuredMachine.trim()) ? configuredMachine : undefined;
1498
+ if (options?.preserveMachine && machine !== undefined)
1499
+ nextOverrides[name] = { machine };
1500
+ else
1501
+ delete nextOverrides[name];
1502
+ if (Object.keys(nextOverrides).length > 0)
1503
+ nextSubagents.agentOverrides = nextOverrides;
1504
+ else
1505
+ delete nextSubagents.agentOverrides;
1506
+ if (Object.keys(nextSubagents).length > 0)
1507
+ settings.subagents = nextSubagents;
1508
+ else
1509
+ delete settings.subagents;
1510
+ writeSettingsFile(filePath, settings);
1511
+ return { path: filePath, removed: true, machinePreserved: options?.preserveMachine === true && machine !== undefined };
1512
+ });
1537
1513
  }
1538
1514
  export function mergeBuiltinAgentOverride(cwd, name, scope, fields) {
1539
1515
  const filePath = scope === "project" ? getProjectAgentSettingsPath(cwd) : getUserAgentSettingsPath();
1540
1516
  if (!filePath)
1541
1517
  throw new Error("Project override is not available here. No project config root was found.");
1542
- const settings = readSettingsFileStrict(filePath);
1543
- const subagents = settings.subagents && typeof settings.subagents === "object" && !Array.isArray(settings.subagents)
1544
- ? { ...settings.subagents }
1545
- : {};
1546
- const agentOverrides = subagents.agentOverrides && typeof subagents.agentOverrides === "object" && !Array.isArray(subagents.agentOverrides)
1547
- ? { ...subagents.agentOverrides }
1548
- : {};
1549
- const existing = agentOverrides[name];
1550
- const base = existing && typeof existing === "object" && !Array.isArray(existing)
1551
- ? existing
1552
- : {};
1553
- agentOverrides[name] = { ...base, ...cloneOverrideValue(fields) };
1554
- subagents.agentOverrides = agentOverrides;
1555
- settings.subagents = subagents;
1556
- writeSettingsFile(filePath, settings);
1557
- return filePath;
1518
+ return withSettingsFileLease(filePath, () => {
1519
+ const settings = readSettingsFileStrict(filePath);
1520
+ const subagents = settings.subagents && typeof settings.subagents === "object" && !Array.isArray(settings.subagents)
1521
+ ? { ...settings.subagents }
1522
+ : {};
1523
+ const agentOverrides = subagents.agentOverrides && typeof subagents.agentOverrides === "object" && !Array.isArray(subagents.agentOverrides)
1524
+ ? { ...subagents.agentOverrides }
1525
+ : {};
1526
+ const existing = agentOverrides[name];
1527
+ const base = existing && typeof existing === "object" && !Array.isArray(existing)
1528
+ ? existing
1529
+ : {};
1530
+ agentOverrides[name] = { ...base, ...cloneOverrideValue(fields) };
1531
+ subagents.agentOverrides = agentOverrides;
1532
+ settings.subagents = subagents;
1533
+ writeSettingsFile(filePath, settings);
1534
+ return filePath;
1535
+ });
1558
1536
  }
1559
1537
  export function removeBuiltinAgentOverrideFields(cwd, name, scope, fields) {
1560
1538
  const filePath = scope === "project" ? getProjectAgentSettingsPath(cwd) : getUserAgentSettingsPath();
@@ -1562,44 +1540,46 @@ export function removeBuiltinAgentOverrideFields(cwd, name, scope, fields) {
1562
1540
  throw new Error("Project override is not available here. No project config root was found.");
1563
1541
  if (!fs.existsSync(filePath))
1564
1542
  return { path: filePath, removed: false };
1565
- const settings = readSettingsFileStrict(filePath);
1566
- const subagents = settings.subagents;
1567
- if (!subagents || typeof subagents !== "object" || Array.isArray(subagents))
1568
- return { path: filePath, removed: false };
1569
- const agentOverrides = subagents.agentOverrides;
1570
- if (!agentOverrides || typeof agentOverrides !== "object" || Array.isArray(agentOverrides))
1571
- return { path: filePath, removed: false };
1572
- const entry = agentOverrides[name];
1573
- if (!entry || typeof entry !== "object" || Array.isArray(entry))
1574
- return { path: filePath, removed: false };
1575
- const nextEntry = { ...entry };
1576
- let removed = false;
1577
- for (const field of fields) {
1578
- if (Object.prototype.hasOwnProperty.call(nextEntry, field)) {
1579
- delete nextEntry[field];
1580
- removed = true;
1543
+ return withSettingsFileLease(filePath, () => {
1544
+ const settings = readSettingsFileStrict(filePath);
1545
+ const subagents = settings.subagents;
1546
+ if (!subagents || typeof subagents !== "object" || Array.isArray(subagents))
1547
+ return { path: filePath, removed: false };
1548
+ const agentOverrides = subagents.agentOverrides;
1549
+ if (!agentOverrides || typeof agentOverrides !== "object" || Array.isArray(agentOverrides))
1550
+ return { path: filePath, removed: false };
1551
+ const entry = agentOverrides[name];
1552
+ if (!entry || typeof entry !== "object" || Array.isArray(entry))
1553
+ return { path: filePath, removed: false };
1554
+ const nextEntry = { ...entry };
1555
+ let removed = false;
1556
+ for (const field of fields) {
1557
+ if (Object.prototype.hasOwnProperty.call(nextEntry, field)) {
1558
+ delete nextEntry[field];
1559
+ removed = true;
1560
+ }
1581
1561
  }
1582
- }
1583
- if (!removed)
1584
- return { path: filePath, removed: false };
1585
- const nextSubagents = { ...subagents };
1586
- if (Object.keys(nextEntry).length > 0) {
1587
- nextSubagents.agentOverrides[name] = nextEntry;
1588
- }
1589
- else {
1590
- const nextOverrides = { ...agentOverrides };
1591
- delete nextOverrides[name];
1592
- if (Object.keys(nextOverrides).length > 0)
1593
- nextSubagents.agentOverrides = nextOverrides;
1562
+ if (!removed)
1563
+ return { path: filePath, removed: false };
1564
+ const nextSubagents = { ...subagents };
1565
+ if (Object.keys(nextEntry).length > 0) {
1566
+ nextSubagents.agentOverrides[name] = nextEntry;
1567
+ }
1568
+ else {
1569
+ const nextOverrides = { ...agentOverrides };
1570
+ delete nextOverrides[name];
1571
+ if (Object.keys(nextOverrides).length > 0)
1572
+ nextSubagents.agentOverrides = nextOverrides;
1573
+ else
1574
+ delete nextSubagents.agentOverrides;
1575
+ }
1576
+ if (Object.keys(nextSubagents).length > 0)
1577
+ settings.subagents = nextSubagents;
1594
1578
  else
1595
- delete nextSubagents.agentOverrides;
1596
- }
1597
- if (Object.keys(nextSubagents).length > 0)
1598
- settings.subagents = nextSubagents;
1599
- else
1600
- delete settings.subagents;
1601
- writeSettingsFile(filePath, settings);
1602
- return { path: filePath, removed: true };
1579
+ delete settings.subagents;
1580
+ writeSettingsFile(filePath, settings);
1581
+ return { path: filePath, removed: true };
1582
+ });
1603
1583
  }
1604
1584
  const DISCOVERY_PRUNED_DIR_NAMES = new Set([".git", "node_modules", ".pi", "sync-backups"]);
1605
1585
  function isDiscoveryNestedProjectRoot(dir) {