pi-subagents 0.40.0 → 0.42.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 (121) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +54 -1879
  3. package/agents/oracle.md +1 -0
  4. package/inspector-runner.mjs +11 -0
  5. package/package.json +13 -5
  6. package/prompts/parallel-context-build.md +1 -1
  7. package/prompts/parallel-handoff-plan.md +1 -1
  8. package/prompts/review-loop.md +1 -1
  9. package/skills/pi-subagents/SKILL.md +9 -7
  10. package/skills/pi-subagents/references/constraints-and-recipes.md +24 -32
  11. package/skills/pi-subagents/references/execution-controls.md +99 -97
  12. package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  13. package/skills/pi-subagents/references/prompting-and-roles.md +23 -30
  14. package/src/agents/agent-management.ts +155 -65
  15. package/src/agents/agent-serializer.ts +19 -0
  16. package/src/agents/agents.ts +154 -71
  17. package/src/agents/chain-serializer.ts +10 -7
  18. package/src/agents/frontmatter.ts +5 -3
  19. package/src/agents/identity.ts +1 -1
  20. package/src/agents/proactive-skills.ts +13 -10
  21. package/src/agents/skills.ts +23 -6
  22. package/src/api/control-channel.ts +4 -0
  23. package/src/api/delegation.ts +26 -194
  24. package/src/api/external-runs.ts +129 -0
  25. package/src/api/intercom-bridge.ts +3 -0
  26. package/src/api/pi-args.ts +5 -0
  27. package/src/api/preflight.ts +3 -3
  28. package/src/api/shared-types.ts +19 -0
  29. package/src/extension/config.ts +10 -0
  30. package/src/extension/control-notices.ts +5 -39
  31. package/src/extension/doctor.ts +10 -9
  32. package/src/extension/fanout-child.ts +7 -4
  33. package/src/extension/index.ts +232 -68
  34. package/src/extension/rpc.ts +18 -12
  35. package/src/extension/schemas.ts +48 -37
  36. package/src/extension/tool-description.ts +36 -86
  37. package/src/inspectors/herdr/actions.ts +229 -0
  38. package/src/inspectors/herdr/client.ts +130 -0
  39. package/src/inspectors/herdr/inspector-runner.ts +141 -0
  40. package/src/inspectors/herdr/project-panes.ts +154 -0
  41. package/src/integrations/herdr-status.ts +330 -0
  42. package/src/intercom/intercom-bridge.ts +3 -2
  43. package/src/intercom/result-intercom.ts +5 -1
  44. package/src/missions/actions.ts +374 -0
  45. package/src/missions/lifecycle.ts +314 -0
  46. package/src/missions/store.ts +442 -0
  47. package/src/missions/types.ts +135 -0
  48. package/src/policy/authority.ts +46 -0
  49. package/src/profiles/profiles.ts +29 -3
  50. package/src/runs/background/async-execution.ts +110 -50
  51. package/src/runs/background/async-job-tracker.ts +27 -4
  52. package/src/runs/background/async-resume.ts +6 -6
  53. package/src/runs/background/async-status.ts +29 -1
  54. package/src/runs/background/auto-drain.ts +3 -3
  55. package/src/runs/background/chain-append.ts +3 -2
  56. package/src/runs/background/control-channel.ts +9 -7
  57. package/src/runs/background/fleet-view.ts +3 -4
  58. package/src/runs/background/notify.ts +2 -1
  59. package/src/runs/background/process-terminal.ts +5 -5
  60. package/src/runs/background/result-watcher.ts +13 -5
  61. package/src/runs/background/run-id-resolver.ts +3 -3
  62. package/src/runs/background/run-status.ts +35 -8
  63. package/src/runs/background/scheduled-runs.ts +602 -375
  64. package/src/runs/background/stale-run-reconciler.ts +3 -3
  65. package/src/runs/background/subagent-runner.ts +608 -445
  66. package/src/runs/background/subagent-wait.ts +50 -9
  67. package/src/runs/background/wait-subscriptions.ts +253 -0
  68. package/src/runs/background/wait-tool.ts +12 -4
  69. package/src/runs/foreground/async-steering-action.ts +3 -3
  70. package/src/runs/foreground/chain-clarify.ts +8 -4
  71. package/src/runs/foreground/chain-execution.ts +56 -30
  72. package/src/runs/foreground/execution.ts +34 -9
  73. package/src/runs/foreground/subagent-executor.ts +1036 -274
  74. package/src/runs/shared/acceptance.ts +28 -6
  75. package/src/runs/shared/child-protocol.ts +302 -22
  76. package/src/runs/shared/dynamic-fanout.ts +1 -1
  77. package/src/runs/shared/external-cli-runner.ts +130 -0
  78. package/src/runs/shared/long-running-guard.ts +42 -1
  79. package/src/runs/shared/mcp-direct-tool-allowlist.ts +2 -0
  80. package/src/runs/shared/nested-events.ts +59 -5
  81. package/src/runs/shared/nested-render.ts +9 -4
  82. package/src/runs/shared/parallel-handoff.ts +86 -2
  83. package/src/runs/shared/parallel-utils.ts +11 -2
  84. package/src/runs/shared/permissions.ts +95 -0
  85. package/src/runs/shared/pi-args.ts +468 -109
  86. package/src/runs/shared/pi-spawn.ts +11 -1
  87. package/src/runs/shared/run-history.ts +1 -1
  88. package/src/runs/shared/subagent-prompt-runtime.ts +36 -5
  89. package/src/runs/shared/subagent-startup-retry.ts +5 -2
  90. package/src/runs/shared/turn-budget.ts +6 -6
  91. package/src/runs/shared/worktree.ts +122 -12
  92. package/src/shared/accessible-dir.ts +29 -7
  93. package/src/shared/artifacts.ts +143 -1
  94. package/src/shared/fork-context.ts +3 -2
  95. package/src/shared/launch-contract.ts +1 -0
  96. package/src/shared/settings.ts +10 -0
  97. package/src/shared/types.ts +156 -14
  98. package/src/shared/utils.ts +8 -6
  99. package/src/slash/delegation-adapters.ts +32 -194
  100. package/src/slash/delegation-request.ts +43 -126
  101. package/src/slash/prompt-template-bridge.ts +158 -205
  102. package/src/slash/prompt-workflows.ts +21 -57
  103. package/src/slash/slash-bridge.ts +14 -0
  104. package/src/slash/slash-commands.ts +31 -632
  105. package/src/slash/subagents-admin.ts +18 -14
  106. package/src/tui/fleet-status.ts +156 -21
  107. package/src/tui/fleet-transcript.ts +110 -5
  108. package/src/tui/fleet.ts +57 -25
  109. package/src/tui/render.ts +368 -152
  110. package/src/types/pi-runtime-compat.d.ts +8 -0
  111. package/src/watchdog/lsp-diagnostics.ts +12 -7
  112. package/src/watchdog/model-selection.ts +2 -2
  113. package/src/watchdog/permission-arbiter.ts +145 -0
  114. package/src/watchdog/register-child.ts +1 -1
  115. package/src/watchdog/register-main.ts +1 -1
  116. package/src/watchdog/review.ts +4 -1
  117. package/src/watchdog/runtime.ts +3 -2
  118. package/src/workflows/chat-progress.ts +140 -0
  119. package/src/workflows/scripted-workflow.ts +415 -0
  120. package/agents/advisor.md +0 -73
  121. package/src/extension/chain-validation.ts +0 -181
@@ -4,7 +4,6 @@ import { fileURLToPath } from "node:url";
4
4
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
5
5
  import { parseFrontmatter } from "../agents/frontmatter.ts";
6
6
  import type { SubagentParamsLike } from "../runs/foreground/subagent-executor.ts";
7
- import type { ChainStep } from "../shared/settings.ts";
8
7
  import { getAgentDir, getProjectConfigDir } from "../shared/utils.ts";
9
8
 
10
9
  interface PromptWorkflow {
@@ -17,7 +16,6 @@ interface PromptWorkflow {
17
16
  model?: string;
18
17
  skill?: string | string[] | false;
19
18
  cwd?: string;
20
- worktree?: boolean;
21
19
  chain?: string;
22
20
  }
23
21
 
@@ -111,7 +109,6 @@ function loadPromptWorkflow(filePath: string): PromptWorkflow | undefined {
111
109
  ...(model ? { model } : {}),
112
110
  ...(skill !== undefined ? { skill } : {}),
113
111
  ...(cwd ? { cwd } : {}),
114
- ...(booleanField(frontmatter, "worktree") === true ? { worktree: true } : {}),
115
112
  ...(chain ? { chain } : {}),
116
113
  };
117
114
  }
@@ -171,12 +168,11 @@ function substituteArgs(template: string, args: string[]): string {
171
168
  .replace(/\$(\d+)/g, (_match, index: string) => args[Number(index) - 1] ?? "");
172
169
  }
173
170
 
174
- function parseRuntimeOptions(words: string[]): { args: string[]; agentOverride?: string; fork?: boolean; fresh?: boolean; worktree?: boolean; bg?: boolean } {
171
+ function parseRuntimeOptions(words: string[]): { args: string[]; agentOverride?: string; fork?: boolean; fresh?: boolean; bg?: boolean } {
175
172
  const args: string[] = [];
176
173
  let agentOverride: string | undefined;
177
174
  let fork = false;
178
175
  let fresh = false;
179
- let worktree = false;
180
176
  let bg = false;
181
177
  for (let i = 0; i < words.length; i++) {
182
178
  const word = words[i]!;
@@ -188,10 +184,6 @@ function parseRuntimeOptions(words: string[]): { args: string[]; agentOverride?:
188
184
  fresh = true;
189
185
  continue;
190
186
  }
191
- if (word === "--worktree") {
192
- worktree = true;
193
- continue;
194
- }
195
187
  if (word === "--bg" || word === "--async") {
196
188
  bg = true;
197
189
  continue;
@@ -207,14 +199,9 @@ function parseRuntimeOptions(words: string[]): { args: string[]; agentOverride?:
207
199
  }
208
200
  args.push(word);
209
201
  }
210
- return { args, agentOverride, fork, fresh, worktree, bg };
202
+ return { args, agentOverride, fork, fresh, bg };
211
203
  }
212
204
 
213
- function splitChainDeclaration(input: string): { declaration: string; argsText: string } {
214
- const delimiter = input.indexOf(" -- ");
215
- if (delimiter === -1) return { declaration: input.trim(), argsText: "" };
216
- return { declaration: input.slice(0, delimiter).trim(), argsText: input.slice(delimiter + 4).trim() };
217
- }
218
205
 
219
206
  function splitPromptChain(input: string): string[] {
220
207
  return input.split(" -> ").map((part) => part.trim()).filter(Boolean);
@@ -232,20 +219,25 @@ function workflowParams(workflow: PromptWorkflow, args: string[], runtime: Retur
232
219
  ...(workflow.model ? { model: workflow.model } : {}),
233
220
  ...(workflow.skill !== undefined ? { skill: workflow.skill } : {}),
234
221
  ...(workflow.cwd ? { cwd: workflow.cwd } : {}),
235
- ...(runtime.worktree || workflow.worktree ? { worktree: true } : {}),
236
222
  ...(runtime.bg ? { async: true } : {}),
237
223
  };
238
224
  }
239
225
 
240
- function workflowChainStep(workflow: PromptWorkflow, args: string[], runtime: ReturnType<typeof parseRuntimeOptions>): ChainStep {
241
- const params = workflowParams(workflow, args, runtime);
242
- return {
243
- agent: params.agent ?? "delegate",
244
- task: params.task,
245
- ...(params.model ? { model: params.model } : {}),
246
- ...(params.skill !== undefined ? { skill: params.skill } : {}),
247
- ...(params.cwd ? { cwd: params.cwd } : {}),
248
- };
226
+ function promptWorkflowScript(workflows: PromptWorkflow[], args: string[], runtime: ReturnType<typeof parseRuntimeOptions>): string {
227
+ const launches = workflows.map((workflow, index) => {
228
+ const params = workflowParams(workflow, args, runtime);
229
+ const task = params.task ?? "";
230
+ const child = {
231
+ agent: params.agent ?? "delegate",
232
+ task,
233
+ ...(params.model ? { model: params.model } : {}),
234
+ ...(params.skill !== undefined ? { skill: params.skill } : {}),
235
+ ...(params.cwd ? { cwd: params.cwd } : {}),
236
+ ...(params.context ? { context: params.context } : {}),
237
+ };
238
+ return `const step${index} = await runs.run(${JSON.stringify(`prompt-${index + 1}-${workflow.name}`)}, { ...${JSON.stringify(child)}, task: ${JSON.stringify(task)}.replaceAll("{previous}", previous) });\nprevious = step${index}.output;`;
239
+ });
240
+ return `let previous = "";\n${launches.join("\n")}\nreturn previous;`;
249
241
  }
250
242
 
251
243
  function findWorkflow(workflows: PromptWorkflow[], name: string): PromptWorkflow | undefined {
@@ -273,7 +265,7 @@ export function registerPromptWorkflowCommands(input: {
273
265
  const name = words.shift();
274
266
  const workflows = discoverPromptWorkflows(ctx.cwd);
275
267
  if (!name || name === "list") {
276
- pi.sendMessage({ content: formatWorkflowList(workflows), display: true });
268
+ pi.sendMessage({ content: formatWorkflowList(workflows), display: true } as Parameters<typeof pi.sendMessage>[0]);
277
269
  return;
278
270
  }
279
271
  const workflow = findWorkflow(workflows, name);
@@ -284,13 +276,12 @@ export function registerPromptWorkflowCommands(input: {
284
276
  const runtime = parseRuntimeOptions(words);
285
277
  try {
286
278
  if (workflow.chain) {
287
- const chainNames = splitPromptChain(workflow.chain);
288
- const chain = chainNames.map((stepName) => {
279
+ const chain = splitPromptChain(workflow.chain).map((stepName) => {
289
280
  const step = findWorkflow(workflows, stepName);
290
281
  if (!step) throw new Error(`Unknown prompt workflow in chain '${workflow.name}': ${stepName}`);
291
- return workflowChainStep(step, runtime.args, runtime);
282
+ return step;
292
283
  });
293
- await run({ chain, task: runtime.args.join(" "), clarify: false, agentScope: "both", ...(runtime.bg ? { async: true } : {}) }, ctx);
284
+ await run({ workflowScript: promptWorkflowScript(chain, runtime.args, runtime), clarify: false, agentScope: "both", ...(runtime.bg ? { async: true } : {}) }, ctx);
294
285
  return;
295
286
  }
296
287
  await run(workflowParams(workflow, runtime.args, runtime), ctx);
@@ -300,31 +291,4 @@ export function registerPromptWorkflowCommands(input: {
300
291
  },
301
292
  });
302
293
 
303
- pi.registerCommand("chain-prompts", {
304
- description: "Run prompt templates as a native subagent chain: /chain-prompts analyze -> fix -- args",
305
- handler: async (rawArgs, ctx) => {
306
- const { declaration, argsText } = splitChainDeclaration(rawArgs);
307
- const workflows = discoverPromptWorkflows(ctx.cwd);
308
- if (!declaration || declaration === "list") {
309
- pi.sendMessage({ content: formatWorkflowList(workflows), display: true });
310
- return;
311
- }
312
- const runtime = parseRuntimeOptions(shellWords(argsText));
313
- const names = splitPromptChain(declaration);
314
- if (names.length === 0) {
315
- ctx.ui.notify("Usage: /chain-prompts prompt-a -> prompt-b -- args", "error");
316
- return;
317
- }
318
- try {
319
- const chain = names.map((name) => {
320
- const workflow = findWorkflow(workflows, name);
321
- if (!workflow) throw new Error(`Unknown prompt workflow: ${name}`);
322
- return workflowChainStep(workflow, runtime.args, runtime);
323
- });
324
- await run({ chain, task: runtime.args.join(" "), clarify: false, agentScope: "both", ...(runtime.bg ? { async: true } : {}) }, ctx);
325
- } catch (error) {
326
- ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
327
- }
328
- },
329
- });
330
294
  }
@@ -78,6 +78,20 @@ export function registerSlashSubagentBridge(options: SlashBridgeOptions): {
78
78
  const request = data as Partial<SlashSubagentRequest>;
79
79
  if (typeof request.requestId !== "string" || !request.params) return;
80
80
  const { requestId, params } = request as SlashSubagentRequest;
81
+ if (params.tasks !== undefined || params.chain !== undefined || params.concurrency !== undefined || params.worktree !== undefined || params.chainDir !== undefined) {
82
+ const message = "Legacy slash-event chain and parallel inputs were removed; use workflowScript.";
83
+ options.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, {
84
+ requestId,
85
+ result: {
86
+ content: [{ type: "text", text: message }],
87
+ isError: true,
88
+ details: { mode: "management", results: [] },
89
+ },
90
+ isError: true,
91
+ errorText: message,
92
+ } satisfies SlashSubagentResponse);
93
+ return;
94
+ }
81
95
 
82
96
  const ctx = request.ctx ?? options.getContext();
83
97
  if (!ctx) {