@marcoscale98/pi-extensible-workflows 5.14.1-fork.1 → 5.19.1-fork.1

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 (94) hide show
  1. package/CHANGELOG.md +135 -0
  2. package/dist/src/agent-execution.js +114 -87
  3. package/dist/src/background-widget.d.ts +61 -0
  4. package/dist/src/background-widget.js +23 -16
  5. package/dist/src/decoders.js +28 -1
  6. package/dist/src/execution.d.ts +4 -2
  7. package/dist/src/execution.js +43 -2
  8. package/dist/src/host-delivery.js +1 -0
  9. package/dist/src/host-navigator.d.ts +18 -0
  10. package/dist/src/host-navigator.js +71 -13
  11. package/dist/src/host-recovery.d.ts +5 -2
  12. package/dist/src/host-recovery.js +3 -3
  13. package/dist/src/host-view.d.ts +21 -1
  14. package/dist/src/host-view.js +138 -47
  15. package/dist/src/host.d.ts +2 -2
  16. package/dist/src/host.js +246 -60
  17. package/dist/src/index.d.ts +3 -1
  18. package/dist/src/index.js +1346 -622
  19. package/dist/src/index.js.map +3 -3
  20. package/dist/src/paths.d.ts +2 -0
  21. package/dist/src/paths.js +2 -0
  22. package/dist/src/registry.js +3 -2
  23. package/dist/src/roles.d.ts +70 -0
  24. package/dist/src/roles.js +326 -0
  25. package/dist/src/script-tools.d.ts +27 -0
  26. package/dist/src/script-tools.js +87 -0
  27. package/dist/src/settings.d.ts +26 -0
  28. package/dist/src/settings.js +277 -0
  29. package/dist/src/trajectory.d.ts +39 -4
  30. package/dist/src/trajectory.js +82 -5
  31. package/dist/src/types.d.ts +30 -3
  32. package/dist/src/types.js +1 -1
  33. package/dist/src/utils.d.ts +21 -1
  34. package/dist/src/utils.js +40 -0
  35. package/dist/src/validation.d.ts +10 -17
  36. package/dist/src/validation.js +29 -458
  37. package/dist/starter/index.js +0 -2
  38. package/dist/starter/index.js.map +1 -1
  39. package/dist/starter/review-loop.d.ts +0 -13
  40. package/dist/starter/review-loop.js +0 -2
  41. package/dist/subagents/index.js +1344 -798
  42. package/dist/subagents/index.js.map +3 -3
  43. package/dist/subagents/src/contracts.d.ts +49 -29
  44. package/dist/subagents/src/contracts.js +18 -7
  45. package/dist/subagents/src/index.d.ts +1 -1
  46. package/dist/subagents/src/index.js +15 -7
  47. package/dist/subagents/src/manager.js +32 -13
  48. package/dist/subagents/src/navigator.js +396 -247
  49. package/dist/subagents/src/view.d.ts +24 -2
  50. package/dist/subagents/src/view.js +107 -80
  51. package/dist/trajectory/assets/index.html +370 -232
  52. package/dist/trajectory/assets/prism.min.js +13 -0
  53. package/dist/trajectory/index.js +445 -277
  54. package/dist/trajectory/index.js.map +3 -3
  55. package/dist/trajectory/src/assets/index.html +370 -232
  56. package/dist/trajectory/src/assets/prism.min.js +13 -0
  57. package/dist/trajectory/src/export.js +4 -2
  58. package/dist/trajectory/src/index.d.ts +2 -0
  59. package/dist/trajectory/src/index.js +151 -60
  60. package/dist/trajectory/src/server.js +138 -11
  61. package/dist/trajectory/src/server.js.map +2 -2
  62. package/package.json +7 -6
  63. package/skills/pi-extensible-workflows/SKILL.md +2 -0
  64. package/src/agent-execution.ts +110 -80
  65. package/src/background-widget.ts +26 -19
  66. package/src/decoders.ts +22 -1
  67. package/src/execution.ts +41 -4
  68. package/src/host-delivery.ts +1 -0
  69. package/src/host-navigator.ts +58 -14
  70. package/src/host-recovery.ts +8 -7
  71. package/src/host-view.ts +116 -42
  72. package/src/host.ts +223 -55
  73. package/src/index.ts +3 -1
  74. package/src/paths.ts +3 -0
  75. package/src/registry.ts +3 -2
  76. package/src/roles.ts +327 -0
  77. package/src/script-tools.ts +76 -0
  78. package/src/settings.ts +224 -0
  79. package/src/trajectory.ts +97 -9
  80. package/src/types.ts +12 -5
  81. package/src/utils.ts +36 -1
  82. package/src/validation.ts +30 -356
  83. package/starter/review-loop.ts +0 -2
  84. package/subagents/README.md +3 -3
  85. package/subagents/src/contracts.ts +22 -7
  86. package/subagents/src/index.ts +18 -7
  87. package/subagents/src/manager.ts +31 -13
  88. package/subagents/src/navigator.ts +336 -180
  89. package/subagents/src/view.ts +108 -76
  90. package/trajectory/src/assets/index.html +370 -232
  91. package/trajectory/src/assets/prism.min.js +13 -0
  92. package/trajectory/src/export.ts +4 -2
  93. package/trajectory/src/index.ts +124 -47
  94. package/trajectory/src/server.ts +114 -14
@@ -24,6 +24,7 @@ export declare const SUBAGENTS_RUN_PARAMETERS: Type.TObject<{
24
24
  }>;
25
25
  export declare const SUBAGENTS_INSPECT_PARAMETERS: Type.TObject<{
26
26
  id: Type.TOptional<Type.TString>;
27
+ scope: Type.TOptional<Type.TUnion<[Type.TLiteral<"session">, Type.TLiteral<"all">]>>;
27
28
  }>;
28
29
  export declare const SUBAGENTS_ID_PARAMETERS: Type.TObject<{
29
30
  id: Type.TString;
@@ -38,36 +39,51 @@ export declare const SUBAGENTS_STOP_PARAMETERS: Type.TObject<{
38
39
  export declare const SUBAGENTS_RETRY_PARAMETERS: Type.TObject<{
39
40
  id: Type.TString;
40
41
  }>;
41
- export declare const SUBAGENTS_TOOL_SCHEMAS: {
42
- readonly subagents_run: Type.TObject<{
43
- prompt: Type.TString;
44
- mode: Type.TOptional<Type.TUnion<[Type.TLiteral<"background">, Type.TLiteral<"foreground">]>>;
45
- label: Type.TOptional<Type.TString>;
46
- model: Type.TOptional<Type.TString>;
47
- tools: Type.TOptional<Type.TArray<Type.TString>>;
48
- skills: Type.TOptional<Type.TArray<Type.TString>>;
49
- extensions: Type.TOptional<Type.TArray<Type.TString>>;
50
- contextFiles: Type.TOptional<Type.TArray<Type.TString>>;
51
- role: Type.TOptional<Type.TString>;
52
- worktree: Type.TOptional<Type.TString>;
53
- outputSchema: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
54
- retries: Type.TOptional<Type.TInteger>;
55
- timeoutMs: Type.TOptional<Type.TUnion<[Type.TInteger, Type.TNull]>>;
56
- }>;
57
- readonly subagents_inspect: Type.TObject<{
58
- id: Type.TOptional<Type.TString>;
59
- }>;
60
- readonly subagents_steer: Type.TObject<{
61
- id: Type.TString;
42
+ export declare const SUBAGENT_STATUS_OUTPUT: Type.TObject<{
43
+ id: Type.TString;
44
+ state: Type.TString;
45
+ sessionId: Type.TOptional<Type.TString>;
46
+ startedAt: Type.TOptional<Type.TNumber>;
47
+ finishedAt: Type.TOptional<Type.TNumber>;
48
+ attempts: Type.TOptional<Type.TNumber>;
49
+ attemptDetails: Type.TOptional<Type.TArray<Type.TUnknown>>;
50
+ worktree: Type.TOptional<Type.TObject<{
51
+ path: Type.TString;
52
+ branch: Type.TString;
53
+ }>>;
54
+ error: Type.TOptional<Type.TObject<{
55
+ code: Type.TString;
62
56
  message: Type.TString;
63
- }>;
64
- readonly subagents_stop: Type.TObject<{
65
- id: Type.TString;
66
- }>;
67
- readonly subagents_retry: Type.TObject<{
68
- id: Type.TString;
69
- }>;
70
- };
57
+ }>>;
58
+ progress: Type.TOptional<Type.TUnknown>;
59
+ value: Type.TOptional<Type.TUnknown>;
60
+ }>;
61
+ export declare const SUBAGENTS_INSPECT_OUTPUT: Type.TUnion<[Type.TObject<{
62
+ id: Type.TString;
63
+ state: Type.TString;
64
+ sessionId: Type.TOptional<Type.TString>;
65
+ startedAt: Type.TOptional<Type.TNumber>;
66
+ finishedAt: Type.TOptional<Type.TNumber>;
67
+ attempts: Type.TOptional<Type.TNumber>;
68
+ attemptDetails: Type.TOptional<Type.TArray<Type.TUnknown>>;
69
+ worktree: Type.TOptional<Type.TObject<{
70
+ path: Type.TString;
71
+ branch: Type.TString;
72
+ }>>;
73
+ error: Type.TOptional<Type.TObject<{
74
+ code: Type.TString;
75
+ message: Type.TString;
76
+ }>>;
77
+ progress: Type.TOptional<Type.TUnknown>;
78
+ value: Type.TOptional<Type.TUnknown>;
79
+ }>, Type.TArray<Type.TObject<{
80
+ id: Type.TString;
81
+ state: Type.TString;
82
+ }>>]>;
83
+ export declare const SUBAGENTS_STEER_OUTPUT: Type.TObject<{
84
+ id: Type.TString;
85
+ accepted: Type.TBoolean;
86
+ }>;
71
87
  export type SubagentRunRequest = Static<typeof SUBAGENTS_RUN_PARAMETERS>;
72
88
  export declare function normalizeSubagentRunRequest(value: unknown): SubagentRunRequest;
73
89
  export type SubagentInspectRequest = Static<typeof SUBAGENTS_INSPECT_PARAMETERS>;
@@ -115,6 +131,8 @@ export interface SubagentManagerContext {
115
131
  readonly extensionContext: ExtensionContext;
116
132
  readonly waitForForeground?: boolean;
117
133
  readonly includeAttemptMetadata?: boolean;
134
+ /** Adds the live progress and activity of an active run; tool results leave streamed activity out. */
135
+ readonly includeActivity?: boolean;
118
136
  }
119
137
  export interface SubagentAttemptActionData {
120
138
  readonly attempt: AgentAttemptSummary;
@@ -159,6 +177,8 @@ export interface SubagentManager {
159
177
  steer(request: Readonly<SubagentSteerRequest>, context: Readonly<SubagentManagerContext>): Promise<unknown>;
160
178
  stop(request: Readonly<SubagentIdRequest>, context: Readonly<SubagentManagerContext>): Promise<unknown>;
161
179
  retry(request: Readonly<SubagentIdRequest>, context: Readonly<SubagentManagerContext>): Promise<unknown>;
180
+ /** Removes a settled run record; used by the /subagents navigator only. */
181
+ delete?(request: Readonly<SubagentIdRequest>, context: Readonly<SubagentManagerContext>): Promise<unknown>;
162
182
  getAttemptActionData?(id: string): Readonly<SubagentAttemptActionData> | undefined;
163
183
  dispose?(): Promise<void>;
164
184
  }
@@ -33,6 +33,7 @@ export const SUBAGENTS_RUN_PARAMETERS = Type.Object({
33
33
  }, { additionalProperties: false });
34
34
  export const SUBAGENTS_INSPECT_PARAMETERS = Type.Object({
35
35
  id: Type.Optional(Type.String({ description: "Subagent ID; omit to list ordered run summaries" })),
36
+ scope: Type.Optional(Type.Union([Type.Literal("session"), Type.Literal("all")], { description: "List scope when id is omitted: session (default) lists runs from the current Pi session; all lists every stored run" })),
36
37
  }, { additionalProperties: false });
37
38
  export const SUBAGENTS_ID_PARAMETERS = Type.Object({
38
39
  id: Type.String({ description: "Subagent ID" }),
@@ -47,13 +48,23 @@ export const SUBAGENTS_STOP_PARAMETERS = Type.Object({
47
48
  export const SUBAGENTS_RETRY_PARAMETERS = Type.Object({
48
49
  id: Type.String({ description: "Failed or stopped subagent ID to retry" }),
49
50
  }, { additionalProperties: false });
50
- export const SUBAGENTS_TOOL_SCHEMAS = {
51
- subagents_run: SUBAGENTS_RUN_PARAMETERS,
52
- subagents_inspect: SUBAGENTS_INSPECT_PARAMETERS,
53
- subagents_steer: SUBAGENTS_STEER_PARAMETERS,
54
- subagents_stop: SUBAGENTS_STOP_PARAMETERS,
55
- subagents_retry: SUBAGENTS_RETRY_PARAMETERS,
56
- };
51
+ // Structured results codemode scripts receive instead of the JSON text; nested records stay loose so they cannot drift from persistence.
52
+ export const SUBAGENT_STATUS_OUTPUT = Type.Object({
53
+ id: Type.String(),
54
+ state: Type.String(),
55
+ sessionId: Type.Optional(Type.String()),
56
+ startedAt: Type.Optional(Type.Number()),
57
+ finishedAt: Type.Optional(Type.Number()),
58
+ attempts: Type.Optional(Type.Number()),
59
+ attemptDetails: Type.Optional(Type.Array(Type.Unknown())),
60
+ worktree: Type.Optional(Type.Object({ path: Type.String(), branch: Type.String() })),
61
+ error: Type.Optional(Type.Object({ code: Type.String(), message: Type.String() })),
62
+ progress: Type.Optional(Type.Unknown()),
63
+ value: Type.Optional(Type.Unknown()),
64
+ });
65
+ // One run when id is given, otherwise the ordered run summaries; the summaries stay short in the codemode description.
66
+ export const SUBAGENTS_INSPECT_OUTPUT = Type.Union([SUBAGENT_STATUS_OUTPUT, Type.Array(Type.Object({ id: Type.String(), state: Type.String() }))]);
67
+ export const SUBAGENTS_STEER_OUTPUT = Type.Object({ id: Type.String(), accepted: Type.Boolean() });
57
68
  export function normalizeSubagentRunRequest(value) {
58
69
  if (!Value.Check(SUBAGENTS_RUN_PARAMETERS, value))
59
70
  throw new WorkflowError("INVALID_METADATA", "Invalid subagents_run parameters");
@@ -5,7 +5,7 @@ export { attemptValue, statusValue, subagentErrorValue } from "./decode.js";
5
5
  export { createSubagentManager, createUnavailableSubagentManager } from "./manager.js";
6
6
  export { createRunStoreWorktreeAdapter, defaultWorktreeHome } from "./worktree.js";
7
7
  export type { SubagentWorktreeAdapter, SubagentWorktreeContext, SubagentWorktreeHandle, SubagentWorktreeRunStore } from "./worktree.js";
8
- type SubagentsExtensionAPI = Pick<ExtensionAPI, "registerTool"> & Partial<Pick<ExtensionAPI, "getActiveTools" | "on" | "sendMessage" | "registerCommand">>;
8
+ type SubagentsExtensionAPI = Pick<ExtensionAPI, "registerTool"> & Partial<Pick<ExtensionAPI, "getActiveTools" | "getAllTools" | "on" | "sendMessage" | "registerCommand" | "appendEntry" | "registerEntryRenderer">>;
9
9
  export declare function createSubagentTools(manager: SubagentManager): readonly ToolDefinition[];
10
10
  export declare function createSubagentsExtension(options?: SubagentsExtensionOptions, activeTools?: () => readonly string[], notify?: (notification: SubagentNotification) => void | Promise<void>, onStatus?: (status: Readonly<SubagentStatus>, request: Readonly<SubagentRunRequest>) => void, onResourceWarning?: (message: string) => void): SubagentsExtension;
11
11
  export declare function registerSubagentsExtension(pi: SubagentsExtensionAPI, options?: SubagentsExtensionOptions): SubagentsExtension;
@@ -1,12 +1,12 @@
1
1
  import { join } from "node:path";
2
2
  import { defineTool, getAgentDir } from "@earendil-works/pi-coding-agent";
3
3
  import { Value } from "typebox/value";
4
- import { WorkflowError, loadingRegistry } from "../../src/index.js";
4
+ import { WorkflowError, loadCodemodeToolsSetting, loadingRegistry, reachableTools, workflowToolExposure } from "../../src/index.js";
5
5
  import { clearSubagentManager, setSubagentManager } from "../../src/subagent-manager-handle.js";
6
6
  import { createSubagentManager } from "./manager.js";
7
7
  import { registerSubagentNavigator } from "./navigator.js";
8
8
  import { createSubagentBackgroundWidget, renderSubagentCall, renderSubagentControlCall, renderSubagentControlResult, renderSubagentInspectCall, renderSubagentInspectResult, renderSubagentResult } from "./view.js";
9
- import { normalizeSubagentRunRequest, SUBAGENTS_ID_PARAMETERS, SUBAGENTS_INSPECT_PARAMETERS, SUBAGENTS_RETRY_PARAMETERS, SUBAGENTS_RUN_PARAMETERS, SUBAGENTS_STEER_PARAMETERS, SUBAGENTS_STOP_PARAMETERS, } from "./contracts.js";
9
+ import { normalizeSubagentRunRequest, SUBAGENT_STATUS_OUTPUT, SUBAGENTS_ID_PARAMETERS, SUBAGENTS_INSPECT_OUTPUT, SUBAGENTS_INSPECT_PARAMETERS, SUBAGENTS_RETRY_PARAMETERS, SUBAGENTS_RUN_PARAMETERS, SUBAGENTS_STEER_OUTPUT, SUBAGENTS_STEER_PARAMETERS, SUBAGENTS_STOP_PARAMETERS, } from "./contracts.js";
10
10
  export * from "./contracts.js";
11
11
  export { attemptValue, statusValue, subagentErrorValue } from "./decode.js";
12
12
  export { createSubagentManager, createUnavailableSubagentManager } from "./manager.js";
@@ -41,7 +41,7 @@ function serialize(value) {
41
41
  }
42
42
  }
43
43
  function toolResult(value) {
44
- return { content: [{ type: "text", text: serialize(value) }], details: value };
44
+ return { content: [{ type: "text", text: serialize(value) }], details: value, structuredContent: value };
45
45
  }
46
46
  function managerContext(toolCallId, signal, onUpdate, context) {
47
47
  return {
@@ -63,6 +63,7 @@ export function createSubagentTools(manager) {
63
63
  "Do not poll a running ID; use subagents_inspect({ id }) when you need its current status or terminal result.",
64
64
  ],
65
65
  parameters: SUBAGENTS_RUN_PARAMETERS,
66
+ outputSchema: SUBAGENT_STATUS_OUTPUT,
66
67
  async execute(toolCallId, params, signal, onUpdate, context) {
67
68
  return toolResult(await manager.run(validateSubagentRunRequest(params), managerContext(toolCallId, signal, onUpdate, context)));
68
69
  },
@@ -72,8 +73,9 @@ export function createSubagentTools(manager) {
72
73
  defineTool({
73
74
  name: "subagents_inspect",
74
75
  label: "Subagents Inspect",
75
- description: "Inspect durable subagent runs. Omit id for ordered run summaries, or provide id for detailed status, progress, activity, accounting, tool calls, timestamps, worktree metadata, and a terminal value or error when available.",
76
+ description: "Inspect durable subagent runs. Omit id for ordered run summaries of the current session (scope all for every session), or provide id for detailed status, progress, activity, accounting, tool calls, timestamps, worktree metadata, and a terminal value or error when available.",
76
77
  parameters: SUBAGENTS_INSPECT_PARAMETERS,
78
+ outputSchema: SUBAGENTS_INSPECT_OUTPUT,
77
79
  async execute(toolCallId, params, signal, onUpdate, context) {
78
80
  return toolResult(await manager.inspect(validateSubagentInspectRequest(params), managerContext(toolCallId, signal, onUpdate, context)));
79
81
  },
@@ -85,6 +87,7 @@ export function createSubagentTools(manager) {
85
87
  label: "Subagents Steer",
86
88
  description: "Send a message to a running subagent. The message is queued safely if its steering handler is not ready; settled runs cannot be steered.",
87
89
  parameters: SUBAGENTS_STEER_PARAMETERS,
90
+ outputSchema: SUBAGENTS_STEER_OUTPUT,
88
91
  async execute(toolCallId, params, signal, onUpdate, context) {
89
92
  return toolResult(await manager.steer(validateSubagentSteerRequest(params), managerContext(toolCallId, signal, onUpdate, context)));
90
93
  },
@@ -96,6 +99,7 @@ export function createSubagentTools(manager) {
96
99
  label: "Subagents Stop",
97
100
  description: "Stop one running subagent, abort its active session, persist state \"stopped\", and clean its worktree without affecting sibling runs.",
98
101
  parameters: SUBAGENTS_STOP_PARAMETERS,
102
+ outputSchema: SUBAGENT_STATUS_OUTPUT,
99
103
  async execute(toolCallId, params, signal, onUpdate, context) {
100
104
  return toolResult(await manager.stop(validateSubagentIdRequest(params, "subagents_stop"), managerContext(toolCallId, signal, onUpdate, context)));
101
105
  },
@@ -107,6 +111,7 @@ export function createSubagentTools(manager) {
107
111
  label: "Subagents Retry",
108
112
  description: "Start a fresh run from a failed or stopped subagent's persisted request. The new run gets a new ID and preserves its original background or foreground mode.",
109
113
  parameters: SUBAGENTS_RETRY_PARAMETERS,
114
+ outputSchema: SUBAGENT_STATUS_OUTPUT,
110
115
  async execute(toolCallId, params, signal, onUpdate, context) {
111
116
  return toolResult(await manager.retry(validateSubagentIdRequest(params, "subagents_retry"), managerContext(toolCallId, signal, onUpdate, context)));
112
117
  },
@@ -145,7 +150,8 @@ export function createSubagentsExtension(options = {}, activeTools, notify, onSt
145
150
  }
146
151
  export function registerSubagentsExtension(pi, options = {}) {
147
152
  const getActiveTools = pi.getActiveTools;
148
- const activeTools = getActiveTools === undefined ? undefined : () => getActiveTools.call(pi);
153
+ const getAllTools = pi.getAllTools;
154
+ const activeTools = getActiveTools === undefined ? undefined : () => reachableTools({ getActiveTools: () => getActiveTools.call(pi), ...(getAllTools === undefined ? {} : { getAllTools: () => getAllTools.call(pi) }) });
149
155
  const sendMessage = pi.sendMessage;
150
156
  const notify = sendMessage === undefined ? undefined : (notification) => {
151
157
  sendMessage.call(pi, { customType: "subagents", content: notificationContent(notification), display: true, details: notification }, { deliverAs: "steer", triggerTurn: true });
@@ -153,11 +159,13 @@ export function registerSubagentsExtension(pi, options = {}) {
153
159
  const onResourceWarning = sendMessage === undefined ? undefined : (message) => {
154
160
  sendMessage.call(pi, { customType: "subagents", content: `Warning: ${message}`, display: true }, { deliverAs: "steer" });
155
161
  };
156
- const widget = createSubagentBackgroundWidget();
162
+ const appendEntry = pi.appendEntry;
163
+ const widget = createSubagentBackgroundWidget({ ...(appendEntry === undefined ? {} : { appendEntry: (customType, data) => { appendEntry.call(pi, customType, data); } }), ...(pi.registerEntryRenderer === undefined ? {} : { registerEntryRenderer: pi.registerEntryRenderer.bind(pi) }) });
157
164
  const extension = createSubagentsExtension(options, activeTools, notify, (status, request) => { widget.update(status, request); const registry = loadingRegistry(); if (typeof registry.observeSubagentStatus === "function")
158
165
  registry.observeSubagentStatus(status, request); }, onResourceWarning);
166
+ const codemodeTools = loadCodemodeToolsSetting(options.managerDependencies?.agentDir);
159
167
  for (const tool of extension.tools)
160
- pi.registerTool(tool);
168
+ pi.registerTool({ ...tool, ...workflowToolExposure(tool.name, codemodeTools) });
161
169
  if (pi.registerCommand !== undefined)
162
170
  registerSubagentNavigator(pi.registerCommand.bind(pi), extension.manager, storageDirectory(options), options.clipboard);
163
171
  if (pi.on !== undefined) {
@@ -2,8 +2,9 @@ import { randomUUID } from "node:crypto";
2
2
  import { chmod, link, mkdir, open, readFile, readdir, rename, rm, stat } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  import { getAgentDir } from "@earendil-works/pi-coding-agent";
5
- import { addAccounting, deepFreeze, errorCode, errorText, finiteNumber, isNodeError, isThinkingLevel, jsonValue, object, loadAgentDefinitions, loadingRegistry, localAgentTransport, resolveAgentResourcePolicy, resolveWorkflowSettings, roleNameOf, sanitizeDisplayText, sumAccounting, structuralPath, validateModelAliasAvailability, WorkflowAgentExecutor, WorkflowError, workflowProjectSettingsPath, workflowSettingsPath, SerialLane, } from "../../src/index.js";
5
+ import { addAccounting, deepFreeze, errorCode, errorText, finiteNumber, isNodeError, isThinkingLevel, jsonValue, object, loadingRegistry, localAgentTransport, resolveAgentResourcePolicy, resolveWorkflowSettings, roleNameOf, sanitizeDisplayText, sumAccounting, structuralPath, validateModelAliasAvailability, WorkflowAgentExecutor, WorkflowError, workflowProjectSettingsPath, workflowSettingsPath, SerialLane, } from "../../src/index.js";
6
6
  import { decodeAgentDefinition, decodeWorkflowExtensions } from "../../src/decoders.js";
7
+ import { loadAgentDefinitions } from "../../src/roles.js";
7
8
  import { atomicJson, json as readJson, processAlive } from "../../src/persistence.js";
8
9
  import { accountingValue, activityValue, legacyAccountingValue, worktreeValue } from "./decode.js";
9
10
  import { SUBAGENT_ATTEMPT_DETAILS_LIMIT, SUBAGENT_MAX_RETRIES, SUBAGENT_SYSTEM_PROMPT_LIMIT, SUBAGENTS_TOOL_NAMES, normalizeSubagentRunRequest, } from "./contracts.js";
@@ -1144,8 +1145,9 @@ class PersistentSubagentManager {
1144
1145
  if (request.id !== undefined) {
1145
1146
  const id = checkedId({ id: request.id });
1146
1147
  const active = this.activeRuns.get(id);
1147
- const status = active ? persistedStatus(active) : this.terminalSummaries.get(id) ?? await loadPersistedStatus(storageDirectory(this.dependencies), id);
1148
- const inspection = publicStatus(status, context.includeAttemptMetadata === true);
1148
+ const includeActivity = context.includeActivity === true;
1149
+ const status = active ? includeActivity ? liveStatus(active) : persistedStatus(active) : this.terminalSummaries.get(id) ?? await loadPersistedStatus(storageDirectory(this.dependencies), id);
1150
+ const inspection = publicStatus(status, context.includeAttemptMetadata === true, includeActivity);
1149
1151
  if (status.state === "completed")
1150
1152
  return { ...inspection, value: await loadPersistedResult(storageDirectory(this.dependencies), id) };
1151
1153
  if (status.state === "failed") {
@@ -1154,9 +1156,9 @@ class PersistentSubagentManager {
1154
1156
  }
1155
1157
  return inspection;
1156
1158
  }
1157
- return this.inspectList();
1159
+ return this.inspectList(request.scope === "all" ? undefined : context.extensionContext.sessionManager.getSessionId());
1158
1160
  }
1159
- async inspectList() {
1161
+ async inspectList(sessionId) {
1160
1162
  const root = storageDirectory(this.dependencies);
1161
1163
  await secureDirectory(root);
1162
1164
  const entries = await readdir(root, { withFileTypes: true });
@@ -1170,7 +1172,7 @@ class PersistentSubagentManager {
1170
1172
  try {
1171
1173
  const active = this.activeRuns.get(entry.name);
1172
1174
  const status = publicStatus(active ? persistedStatus(active) : this.terminalSummaries.get(entry.name) ?? await loadPersistedStatus(root, entry.name, false));
1173
- if (status.startedAt === undefined)
1175
+ if (status.startedAt === undefined || (sessionId !== undefined && status.sessionId !== sessionId))
1174
1176
  continue;
1175
1177
  statuses.push({ status, startedAt: status.startedAt });
1176
1178
  }
@@ -1208,6 +1210,21 @@ class PersistentSubagentManager {
1208
1210
  await this.stopRun(run, false);
1209
1211
  return publicStatus(persistedStatus(run));
1210
1212
  }
1213
+ /** Removes a settled record for the /subagents navigator, as /workflow deletes a terminal run; not a model tool. */
1214
+ async delete(request) {
1215
+ const id = checkedId(request);
1216
+ await this.ensureInitialized();
1217
+ const root = storageDirectory(this.dependencies);
1218
+ const status = this.activeRuns.has(id) ? undefined : this.terminalSummaries.get(id) ?? await loadPersistedStatus(root, id, false);
1219
+ if (status === undefined || status.state === "running")
1220
+ throw new WorkflowError("RUN_OWNED", `Stop subagent ${id} before deleting it`);
1221
+ // Retained worktree metadata means cleanup failed, and the record holds what a later cleanup needs.
1222
+ if (status.worktree !== undefined)
1223
+ throw new WorkflowError("WORKTREE_FAILED", `Subagent ${id} still has a worktree to clean up`);
1224
+ await rm(runDirectory(root, id), { recursive: true, force: true });
1225
+ this.terminalSummaries.delete(id);
1226
+ return { id, deleted: true };
1227
+ }
1211
1228
  async dispose() {
1212
1229
  if (this.disposePromise)
1213
1230
  return this.disposePromise;
@@ -1405,9 +1422,10 @@ class PersistentSubagentManager {
1405
1422
  run.disposed = true;
1406
1423
  this.clearSteering(run);
1407
1424
  await this.cleanupSessions(run, true);
1408
- const worktreeCleaned = await this.cleanupWorktree(run);
1409
- if (worktreeCleaned)
1410
- await enqueueWrite(run, () => atomicJson(statusPath(run.directory), persistedStatus(run)));
1425
+ await this.cleanupWorktree(run);
1426
+ // A run that settled just before disposal may not have written its terminal status yet: finishTerminal returns early
1427
+ // once the run is disposed. Left as "running" under this live process, the next manager here would never reconcile it.
1428
+ await enqueueWrite(run, () => atomicJson(statusPath(run.directory), persistedStatus(run)));
1411
1429
  this.resolveTerminal(run);
1412
1430
  this.removeLiveRun(run);
1413
1431
  }
@@ -1627,10 +1645,11 @@ export function createSubagentManager(dependencies = {}) {
1627
1645
  return {
1628
1646
  run: (request, context) => manager.run(request, context),
1629
1647
  inspect: (request, context) => manager.inspect(request, context),
1630
- getAttemptActionData: (id) => manager.getAttemptActionData?.(id),
1631
- steer: (request, context) => manager.steer(request, context),
1632
- stop: (request, context) => manager.stop(request, context),
1648
+ getAttemptActionData: (id) => manager.getAttemptActionData(id),
1649
+ steer: (request) => manager.steer(request),
1650
+ stop: (request) => manager.stop(request),
1633
1651
  retry: (request, context) => manager.retry(request, context),
1634
- dispose: async () => { await manager.dispose?.(); },
1652
+ delete: (request) => manager.delete(request),
1653
+ dispose: async () => { await manager.dispose(); },
1635
1654
  };
1636
1655
  }