@fitchmultz/pi-subagents 0.0.0-stage → 0.44.5

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 (347) hide show
  1. package/CHANGELOG.md +1654 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1533 -2
  4. package/agents/context-builder.md +97 -0
  5. package/agents/debugger.md +51 -0
  6. package/agents/delegate.md +13 -0
  7. package/agents/fixer.md +37 -0
  8. package/agents/oracle.md +71 -0
  9. package/agents/planner.md +72 -0
  10. package/agents/researcher.md +51 -0
  11. package/agents/reviewer-claude.md +69 -0
  12. package/agents/reviewer-gpt.md +68 -0
  13. package/agents/reviewer-ponytail.md +82 -0
  14. package/agents/reviewer-security.md +81 -0
  15. package/agents/reviewer.md +69 -0
  16. package/agents/scout.md +66 -0
  17. package/agents/ui-designer.md +51 -0
  18. package/agents/watcher.md +26 -0
  19. package/agents/worker.md +46 -0
  20. package/agents/writer.md +36 -0
  21. package/dist/agents/agent-management.js +923 -0
  22. package/dist/agents/agent-scope.js +7 -0
  23. package/dist/agents/agent-selection.js +20 -0
  24. package/dist/agents/agent-serializer.js +100 -0
  25. package/dist/agents/agents.js +752 -0
  26. package/dist/agents/chain-serializer.js +367 -0
  27. package/dist/agents/frontmatter.js +21 -0
  28. package/dist/agents/identity.js +29 -0
  29. package/dist/agents/skills.js +570 -0
  30. package/dist/extension/build-info.js +1 -0
  31. package/dist/extension/compact-tools.js +112 -0
  32. package/dist/extension/config.js +22 -0
  33. package/dist/extension/control-notices.js +29 -0
  34. package/dist/extension/doctor.js +143 -0
  35. package/dist/extension/fanout-child.js +326 -0
  36. package/dist/extension/index.js +577 -0
  37. package/dist/extension/schemas.js +416 -0
  38. package/dist/extension/tool-input.js +20 -0
  39. package/dist/extension/tool-result.js +14 -0
  40. package/dist/history/canonical-result.js +81 -0
  41. package/dist/history/database.js +72 -0
  42. package/dist/history/index.js +199 -0
  43. package/dist/history/ingest.js +468 -0
  44. package/dist/history/queries.js +350 -0
  45. package/dist/history/store.js +216 -0
  46. package/dist/history/types.js +4 -0
  47. package/dist/history/worker.js +466 -0
  48. package/dist/intercom/intercom-bridge.js +112 -0
  49. package/dist/intercom/live-intercom.js +94 -0
  50. package/dist/intercom/result-intercom.js +373 -0
  51. package/dist/pi-intercom/agent-dir.js +10 -0
  52. package/dist/pi-intercom/bridge.js +750 -0
  53. package/dist/pi-intercom/broker/broker.js +426 -0
  54. package/dist/pi-intercom/broker/client.js +492 -0
  55. package/dist/pi-intercom/broker/framing.js +65 -0
  56. package/dist/pi-intercom/broker/paths.js +42 -0
  57. package/dist/pi-intercom/broker/pid.js +66 -0
  58. package/dist/pi-intercom/broker/spawn.js +221 -0
  59. package/dist/pi-intercom/config.js +102 -0
  60. package/dist/pi-intercom/index.js +2942 -0
  61. package/dist/pi-intercom/reply-tracker.js +182 -0
  62. package/dist/pi-intercom/session-targets.js +128 -0
  63. package/dist/pi-intercom/subagent-live-events.js +132 -0
  64. package/dist/pi-intercom/topics.js +157 -0
  65. package/dist/pi-intercom/types.js +163 -0
  66. package/dist/pi-intercom/ui/compose.js +269 -0
  67. package/dist/pi-intercom/ui/inline-message.js +80 -0
  68. package/dist/pi-intercom/ui/session-list.js +124 -0
  69. package/dist/runs/background/async-control.js +95 -0
  70. package/dist/runs/background/async-execution.js +676 -0
  71. package/dist/runs/background/async-job-tracker.js +383 -0
  72. package/dist/runs/background/async-result-file.js +58 -0
  73. package/dist/runs/background/async-resume.js +305 -0
  74. package/dist/runs/background/async-status.js +442 -0
  75. package/dist/runs/background/completion-dedupe.js +69 -0
  76. package/dist/runs/background/completion-delivery.js +245 -0
  77. package/dist/runs/background/notify.js +71 -0
  78. package/dist/runs/background/parallel-groups.js +55 -0
  79. package/dist/runs/background/result-watcher.js +426 -0
  80. package/dist/runs/background/run-id-resolver.js +64 -0
  81. package/dist/runs/background/run-status.js +382 -0
  82. package/dist/runs/background/stale-run-reconciler.js +335 -0
  83. package/dist/runs/background/subagent-runner-launcher.js +55 -0
  84. package/dist/runs/background/subagent-runner.js +1872 -0
  85. package/dist/runs/background/top-level-async.js +5 -0
  86. package/dist/runs/foreground/chain-clarify.js +1152 -0
  87. package/dist/runs/foreground/clarify-invocation.js +72 -0
  88. package/dist/runs/foreground/execution-input.js +423 -0
  89. package/dist/runs/foreground/foreground-control.js +817 -0
  90. package/dist/runs/foreground/question-control.js +88 -0
  91. package/dist/runs/foreground/run-async-path.js +205 -0
  92. package/dist/runs/foreground/subagent-executor.js +442 -0
  93. package/dist/runs/foreground/subagent-params.js +165 -0
  94. package/dist/runs/foreground/wait-run.js +141 -0
  95. package/dist/runs/shared/acceptance-contract.js +253 -0
  96. package/dist/runs/shared/acceptance-evaluation.js +256 -0
  97. package/dist/runs/shared/acceptance-finalization.js +280 -0
  98. package/dist/runs/shared/acceptance-reports.js +147 -0
  99. package/dist/runs/shared/acceptance.js +4 -0
  100. package/dist/runs/shared/chain-outputs.js +110 -0
  101. package/dist/runs/shared/child-attempt.js +693 -0
  102. package/dist/runs/shared/child-execution-cwd.js +96 -0
  103. package/dist/runs/shared/child-observations.js +114 -0
  104. package/dist/runs/shared/claude-code.js +199 -0
  105. package/dist/runs/shared/completion-guard.js +31 -0
  106. package/dist/runs/shared/dynamic-fanout.js +274 -0
  107. package/dist/runs/shared/history-index.js +72 -0
  108. package/dist/runs/shared/mcp-direct-tool-allowlist.js +334 -0
  109. package/dist/runs/shared/model-fallback.js +185 -0
  110. package/dist/runs/shared/mutating-tool-guard.js +170 -0
  111. package/dist/runs/shared/native-finalization.js +101 -0
  112. package/dist/runs/shared/native-usage.js +153 -0
  113. package/dist/runs/shared/nested-events.js +700 -0
  114. package/dist/runs/shared/nested-path.js +48 -0
  115. package/dist/runs/shared/nested-render.js +108 -0
  116. package/dist/runs/shared/parallel-utils.js +61 -0
  117. package/dist/runs/shared/parent-receipts.js +68 -0
  118. package/dist/runs/shared/parent-usage.js +121 -0
  119. package/dist/runs/shared/pi-args.js +310 -0
  120. package/dist/runs/shared/pi-spawn.js +52 -0
  121. package/dist/runs/shared/run-history-queries.js +45 -0
  122. package/dist/runs/shared/run-history.js +110 -0
  123. package/dist/runs/shared/run-id-ambiguity.js +4 -0
  124. package/dist/runs/shared/run-records.js +679 -0
  125. package/dist/runs/shared/session-cwd-preload.js +33 -0
  126. package/dist/runs/shared/single-output.js +222 -0
  127. package/dist/runs/shared/streaming-text.js +15 -0
  128. package/dist/runs/shared/structured-output.js +55 -0
  129. package/dist/runs/shared/subagent-control.js +179 -0
  130. package/dist/runs/shared/subagent-prompt-runtime.js +197 -0
  131. package/dist/runs/shared/subagent-tool-loop-guard.js +66 -0
  132. package/dist/runs/shared/supervisor-questions.js +350 -0
  133. package/dist/runs/shared/workflow-graph.js +214 -0
  134. package/dist/runs/shared/workflow-policy.js +84 -0
  135. package/dist/runs/shared/worktree.js +525 -0
  136. package/dist/shared/agent-context-policy.js +126 -0
  137. package/dist/shared/artifacts.js +96 -0
  138. package/dist/shared/atomic-json.js +13 -0
  139. package/dist/shared/cooperative.js +20 -0
  140. package/dist/shared/execution-cwd.js +14 -0
  141. package/dist/shared/file-coalescer.js +21 -0
  142. package/dist/shared/fork-context.js +49 -0
  143. package/dist/shared/formatters.js +85 -0
  144. package/dist/shared/journal-reader.js +407 -0
  145. package/dist/shared/lazy-tools.js +32 -0
  146. package/dist/shared/model-info.js +68 -0
  147. package/dist/shared/native-session.js +15 -0
  148. package/dist/shared/native-tui.js +18 -0
  149. package/dist/shared/native-typebox.js +20 -0
  150. package/dist/shared/post-exit-stdio-guard.js +197 -0
  151. package/dist/shared/prompt-sections.js +8 -0
  152. package/dist/shared/session-entries.js +52 -0
  153. package/dist/shared/session-identity.js +14 -0
  154. package/dist/shared/settings.js +254 -0
  155. package/dist/shared/status-format.js +111 -0
  156. package/dist/shared/temp-root.js +114 -0
  157. package/dist/shared/types.js +207 -0
  158. package/dist/shared/ui-mode.js +3 -0
  159. package/dist/shared/utils.js +334 -0
  160. package/dist/slash/prompt-template-bridge.js +298 -0
  161. package/dist/slash/slash-bridge.js +116 -0
  162. package/dist/slash/slash-commands.js +607 -0
  163. package/dist/slash/slash-live-state.js +246 -0
  164. package/dist/tui/action-hints.js +75 -0
  165. package/dist/tui/agent-history.js +197 -0
  166. package/dist/tui/agent-view.js +1656 -0
  167. package/dist/tui/render.js +1515 -0
  168. package/docs/intercom-bridge.md +212 -0
  169. package/docs/intercom.md +581 -0
  170. package/docs/performance.md +121 -0
  171. package/package.json +102 -4
  172. package/prompts/gather-context-and-clarify.md +14 -0
  173. package/prompts/parallel-cleanup.md +62 -0
  174. package/prompts/parallel-context-build.md +56 -0
  175. package/prompts/parallel-handoff-plan.md +62 -0
  176. package/prompts/parallel-research.md +51 -0
  177. package/prompts/parallel-review.md +59 -0
  178. package/prompts/review-loop.md +42 -0
  179. package/scripts/build.mjs +134 -0
  180. package/scripts/check-compat.mjs +48 -0
  181. package/scripts/compat-host.mjs +19 -0
  182. package/scripts/intercom-bridge-credentials.mjs +143 -0
  183. package/scripts/intercom-remote.mjs +103 -0
  184. package/scripts/linux-smoke.sh +51 -0
  185. package/scripts/local-install-smoke.mjs +66 -0
  186. package/scripts/native-package-smoke.mjs +82 -0
  187. package/scripts/package-smoke.mjs +209 -0
  188. package/scripts/prepare.mjs +67 -0
  189. package/scripts/real-pi-smoke.mjs +415 -0
  190. package/scripts/run-tests.mjs +149 -0
  191. package/skills/pi-intercom/SKILL.md +113 -0
  192. package/skills/pi-intercom/evals/evals.json +29 -0
  193. package/skills/pi-intercom/evals/trigger-evals.json +47 -0
  194. package/skills/pi-intercom/references/peer-sessions.md +69 -0
  195. package/skills/pi-subagents/SKILL.md +76 -0
  196. package/skills/pi-subagents/evals/evals.json +29 -0
  197. package/skills/pi-subagents/evals/trigger-evals.json +42 -0
  198. package/skills/pi-subagents/references/full-orchestration-guide.md +863 -0
  199. package/src/agents/agent-management.ts +813 -0
  200. package/src/agents/agent-scope.ts +7 -0
  201. package/src/agents/agent-selection.ts +23 -0
  202. package/src/agents/agent-serializer.ts +99 -0
  203. package/src/agents/agents.ts +916 -0
  204. package/src/agents/chain-serializer.ts +329 -0
  205. package/src/agents/frontmatter.ts +21 -0
  206. package/src/agents/identity.ts +30 -0
  207. package/src/agents/skills.ts +637 -0
  208. package/src/extension/build-info.ts +2 -0
  209. package/src/extension/compact-tools.ts +114 -0
  210. package/src/extension/config.ts +23 -0
  211. package/src/extension/control-notices.ts +47 -0
  212. package/src/extension/doctor.ts +171 -0
  213. package/src/extension/fanout-child.ts +312 -0
  214. package/src/extension/index.ts +649 -0
  215. package/src/extension/schemas.ts +444 -0
  216. package/src/extension/tool-input.ts +19 -0
  217. package/src/extension/tool-result.ts +16 -0
  218. package/src/history/canonical-result.ts +62 -0
  219. package/src/history/database.ts +59 -0
  220. package/src/history/index.ts +156 -0
  221. package/src/history/ingest.ts +349 -0
  222. package/src/history/queries.ts +241 -0
  223. package/src/history/store.ts +203 -0
  224. package/src/history/types.ts +166 -0
  225. package/src/history/worker.ts +321 -0
  226. package/src/intercom/intercom-bridge.ts +123 -0
  227. package/src/intercom/live-intercom.ts +104 -0
  228. package/src/intercom/result-intercom.ts +429 -0
  229. package/src/pi-intercom/agent-dir.ts +9 -0
  230. package/src/pi-intercom/bridge.ts +668 -0
  231. package/src/pi-intercom/broker/broker.ts +463 -0
  232. package/src/pi-intercom/broker/client.ts +558 -0
  233. package/src/pi-intercom/broker/framing.ts +77 -0
  234. package/src/pi-intercom/broker/paths.ts +47 -0
  235. package/src/pi-intercom/broker/pid.ts +59 -0
  236. package/src/pi-intercom/broker/spawn.ts +248 -0
  237. package/src/pi-intercom/config.ts +142 -0
  238. package/src/pi-intercom/index.ts +2929 -0
  239. package/src/pi-intercom/reply-tracker.ts +211 -0
  240. package/src/pi-intercom/session-targets.ts +172 -0
  241. package/src/pi-intercom/subagent-live-events.ts +133 -0
  242. package/src/pi-intercom/topics.ts +125 -0
  243. package/src/pi-intercom/types.ts +271 -0
  244. package/src/pi-intercom/ui/compose.ts +289 -0
  245. package/src/pi-intercom/ui/inline-message.ts +92 -0
  246. package/src/pi-intercom/ui/session-list.ts +139 -0
  247. package/src/runs/background/async-control.ts +89 -0
  248. package/src/runs/background/async-execution.ts +850 -0
  249. package/src/runs/background/async-job-tracker.ts +385 -0
  250. package/src/runs/background/async-result-file.ts +62 -0
  251. package/src/runs/background/async-resume.ts +333 -0
  252. package/src/runs/background/async-status.ts +481 -0
  253. package/src/runs/background/completion-dedupe.ts +79 -0
  254. package/src/runs/background/completion-delivery.ts +195 -0
  255. package/src/runs/background/notify.ts +123 -0
  256. package/src/runs/background/parallel-groups.ts +53 -0
  257. package/src/runs/background/result-watcher.ts +423 -0
  258. package/src/runs/background/run-id-resolver.ts +69 -0
  259. package/src/runs/background/run-status.ts +384 -0
  260. package/src/runs/background/stale-run-reconciler.ts +369 -0
  261. package/src/runs/background/subagent-runner-launcher.ts +56 -0
  262. package/src/runs/background/subagent-runner.ts +2053 -0
  263. package/src/runs/background/top-level-async.ts +13 -0
  264. package/src/runs/foreground/chain-clarify.ts +1340 -0
  265. package/src/runs/foreground/clarify-invocation.ts +77 -0
  266. package/src/runs/foreground/execution-input.ts +467 -0
  267. package/src/runs/foreground/foreground-control.ts +821 -0
  268. package/src/runs/foreground/question-control.ts +82 -0
  269. package/src/runs/foreground/run-async-path.ts +243 -0
  270. package/src/runs/foreground/subagent-executor.ts +501 -0
  271. package/src/runs/foreground/subagent-params.ts +320 -0
  272. package/src/runs/foreground/wait-run.ts +124 -0
  273. package/src/runs/shared/acceptance-contract.ts +257 -0
  274. package/src/runs/shared/acceptance-evaluation.ts +275 -0
  275. package/src/runs/shared/acceptance-finalization.ts +353 -0
  276. package/src/runs/shared/acceptance-reports.ts +152 -0
  277. package/src/runs/shared/acceptance.ts +33 -0
  278. package/src/runs/shared/chain-outputs.ts +114 -0
  279. package/src/runs/shared/child-attempt.ts +623 -0
  280. package/src/runs/shared/child-execution-cwd.ts +91 -0
  281. package/src/runs/shared/child-observations.ts +99 -0
  282. package/src/runs/shared/claude-code.ts +243 -0
  283. package/src/runs/shared/completion-guard.ts +35 -0
  284. package/src/runs/shared/dynamic-fanout.ts +295 -0
  285. package/src/runs/shared/history-index.ts +69 -0
  286. package/src/runs/shared/mcp-direct-tool-allowlist.ts +376 -0
  287. package/src/runs/shared/model-fallback.ts +219 -0
  288. package/src/runs/shared/mutating-tool-guard.ts +194 -0
  289. package/src/runs/shared/native-finalization.ts +128 -0
  290. package/src/runs/shared/native-usage.ts +113 -0
  291. package/src/runs/shared/nested-events.ts +752 -0
  292. package/src/runs/shared/nested-path.ts +52 -0
  293. package/src/runs/shared/nested-render.ts +119 -0
  294. package/src/runs/shared/parallel-utils.ts +153 -0
  295. package/src/runs/shared/parent-receipts.ts +59 -0
  296. package/src/runs/shared/parent-usage.ts +121 -0
  297. package/src/runs/shared/pi-args.ts +350 -0
  298. package/src/runs/shared/pi-spawn.ts +52 -0
  299. package/src/runs/shared/run-history-queries.ts +44 -0
  300. package/src/runs/shared/run-history.ts +100 -0
  301. package/src/runs/shared/run-id-ambiguity.ts +4 -0
  302. package/src/runs/shared/run-records.ts +607 -0
  303. package/src/runs/shared/session-cwd-preload.ts +27 -0
  304. package/src/runs/shared/single-output.ts +267 -0
  305. package/src/runs/shared/streaming-text.ts +18 -0
  306. package/src/runs/shared/structured-output.ts +68 -0
  307. package/src/runs/shared/subagent-control.ts +219 -0
  308. package/src/runs/shared/subagent-prompt-runtime.ts +201 -0
  309. package/src/runs/shared/subagent-tool-loop-guard.ts +89 -0
  310. package/src/runs/shared/supervisor-questions.ts +415 -0
  311. package/src/runs/shared/workflow-graph.ts +220 -0
  312. package/src/runs/shared/workflow-policy.ts +125 -0
  313. package/src/runs/shared/worktree.ts +635 -0
  314. package/src/shared/agent-context-policy.ts +184 -0
  315. package/src/shared/artifacts.ts +95 -0
  316. package/src/shared/atomic-json.ts +16 -0
  317. package/src/shared/cooperative.ts +21 -0
  318. package/src/shared/execution-cwd.ts +14 -0
  319. package/src/shared/file-coalescer.ts +29 -0
  320. package/src/shared/fork-context.ts +68 -0
  321. package/src/shared/formatters.ts +84 -0
  322. package/src/shared/journal-reader.ts +333 -0
  323. package/src/shared/lazy-tools.ts +36 -0
  324. package/src/shared/model-info.ts +81 -0
  325. package/src/shared/native-session.ts +8 -0
  326. package/src/shared/native-tui.ts +10 -0
  327. package/src/shared/native-typebox.ts +14 -0
  328. package/src/shared/post-exit-stdio-guard.ts +204 -0
  329. package/src/shared/prompt-sections.ts +10 -0
  330. package/src/shared/session-entries.ts +49 -0
  331. package/src/shared/session-identity.ts +18 -0
  332. package/src/shared/settings.ts +384 -0
  333. package/src/shared/status-format.ts +123 -0
  334. package/src/shared/temp-root.ts +107 -0
  335. package/src/shared/types.ts +1260 -0
  336. package/src/shared/ui-mode.ts +5 -0
  337. package/src/shared/utils.ts +342 -0
  338. package/src/slash/prompt-template-bridge.ts +408 -0
  339. package/src/slash/slash-bridge.ts +178 -0
  340. package/src/slash/slash-commands.ts +617 -0
  341. package/src/slash/slash-live-state.ts +292 -0
  342. package/src/tui/action-hints.ts +69 -0
  343. package/src/tui/agent-history.ts +210 -0
  344. package/src/tui/agent-view.ts +1323 -0
  345. package/src/tui/render.ts +1550 -0
  346. package/tsconfig.build.json +12 -0
  347. package/tsconfig.json +19 -0
@@ -0,0 +1,1260 @@
1
+ /**
2
+ * Type definitions for the subagent extension
3
+ */
4
+
5
+ import * as os from "node:os";
6
+ import * as path from "node:path";
7
+ import type { Message, Usage as NativeUsage } from "@earendil-works/pi-ai";
8
+ import type { FSWatcher } from "node:fs";
9
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
10
+ import type { AgentToolResult } from "@earendil-works/pi-agent-core";
11
+ import type { SubagentHistoryIndex } from "../history/index.ts";
12
+
13
+ // ============================================================================
14
+ // Basic Types
15
+ // ============================================================================
16
+
17
+ export interface MaxOutputConfig {
18
+ bytes?: number;
19
+ lines?: number;
20
+ }
21
+
22
+ export type OutputMode = "inline" | "file-only";
23
+
24
+ export type JsonSchemaObject = Record<string, unknown>;
25
+
26
+ export interface ChainOutputMapEntry {
27
+ text: string;
28
+ structured?: unknown;
29
+ agent: string;
30
+ stepIndex: number;
31
+ }
32
+
33
+ export type ChainOutputMap = Record<string, ChainOutputMapEntry>;
34
+
35
+ export type WorkflowNodeStatus = "pending" | "running" | "completed" | "complete" | "failed" | "blocked" | "paused" | "detached" | "timed-out";
36
+
37
+ export interface WorkflowGraphNode {
38
+ id: string;
39
+ kind: "step" | "parallel-group" | "dynamic-parallel-group" | "agent";
40
+ agent?: string;
41
+ phase?: string;
42
+ label: string;
43
+ status: WorkflowNodeStatus;
44
+ flatIndex?: number;
45
+ stepIndex?: number;
46
+ children?: WorkflowGraphNode[];
47
+ dynamic?: {
48
+ sourceOutput: string;
49
+ sourcePath: string;
50
+ itemName: string;
51
+ maxItems?: number;
52
+ collectAs?: string;
53
+ };
54
+ itemKey?: string;
55
+ outputName?: string;
56
+ structured?: boolean;
57
+ acceptanceStatus?: AcceptanceLedgerStatus;
58
+ error?: string;
59
+ }
60
+
61
+ export interface WorkflowGraphSnapshot {
62
+ runId: string;
63
+ mode: "chain" | "parallel" | "single";
64
+ phases: Array<{ title: string; nodeIds: string[] }>;
65
+ nodes: WorkflowGraphNode[];
66
+ currentNodeId?: string;
67
+ }
68
+
69
+ export interface SavedOutputReference {
70
+ path: string;
71
+ bytes: number;
72
+ lines: number;
73
+ message: string;
74
+ }
75
+
76
+ interface TruncationResult {
77
+ text: string;
78
+ truncated: boolean;
79
+ originalBytes?: number;
80
+ originalLines?: number;
81
+ artifactPath?: string;
82
+ }
83
+
84
+ export interface UsageContribution {
85
+ id: string;
86
+ /** Native tool and summary usage may not carry model attribution. */
87
+ provider?: string;
88
+ model?: string;
89
+ usage: NativeUsage;
90
+ }
91
+
92
+ export interface Usage {
93
+ contributions?: UsageContribution[];
94
+ input: number;
95
+ output: number;
96
+ cacheRead: number;
97
+ cacheWrite: number;
98
+ cost: number;
99
+ turns: number;
100
+ }
101
+
102
+ export interface TokenUsage {
103
+ input: number;
104
+ output: number;
105
+ total: number;
106
+ }
107
+
108
+ export type ActivityState = "needs_attention";
109
+ export type ControlEventType = "needs_attention";
110
+ export type ControlNotificationChannel = "event" | "async" | "intercom";
111
+
112
+ export interface ControlConfig {
113
+ enabled?: boolean;
114
+ needsAttentionAfterMs?: number;
115
+ failedToolAttemptsBeforeAttention?: number;
116
+ notifyOn?: ControlEventType[];
117
+ notifyChannels?: ControlNotificationChannel[];
118
+ }
119
+
120
+ export interface ResolvedControlConfig {
121
+ enabled: boolean;
122
+ needsAttentionAfterMs: number;
123
+ failedToolAttemptsBeforeAttention: number;
124
+ notifyOn: ControlEventType[];
125
+ notifyChannels: ControlNotificationChannel[];
126
+ }
127
+
128
+ export interface ControlEvent {
129
+ type: ControlEventType;
130
+ from?: ActivityState;
131
+ to: ActivityState;
132
+ ts: number;
133
+ agent: string;
134
+ index?: number;
135
+ runId: string;
136
+ message: string;
137
+ reason?: "idle" | "completion_guard" | "tool_failures";
138
+ turns?: number;
139
+ tokens?: number;
140
+ toolCount?: number;
141
+ currentTool?: string;
142
+ currentToolDurationMs?: number;
143
+ currentPath?: string;
144
+ elapsedMs?: number;
145
+ recentFailureSummary?: string;
146
+ supervisorQuestion?: { questionId: string; state: "awaiting_input" | "answer_pending"; answer?: string };
147
+ }
148
+
149
+ export type SubagentResultStatus = "completed" | "failed" | "blocked" | "paused" | "detached" | "timed-out";
150
+ export type SubagentRunMode = "single" | "parallel" | "chain";
151
+
152
+ export type PublicNestedStepSummary = Pick<
153
+ NestedStepSummary,
154
+ "agent" | "status" | "sessionFile" | "activityState" | "lastActivityAt" | "currentTool" | "currentToolStartedAt" | "currentPath" | "turnCount" | "toolCount" | "startedAt" | "endedAt" | "error"
155
+ > & {
156
+ children?: PublicNestedRunSummary[];
157
+ };
158
+
159
+ export type PublicNestedRunSummary = Pick<
160
+ NestedRunSummary,
161
+ "id" | "parentRunId" | "parentStepIndex" | "parentAgent" | "depth" | "path" | "asyncDir" | "sessionId" | "sessionFile" | "intercomTarget" | "ownerIntercomTarget" | "leafIntercomTarget" | "ownerState" | "mode" | "state" | "agent" | "agents" | "currentStep" | "chainStepCount" | "parallelGroups" | "activityState" | "lastActivityAt" | "currentTool" | "currentToolStartedAt" | "currentPath" | "turnCount" | "toolCount" | "totalTokens" | "startedAt" | "endedAt" | "lastUpdate" | "error"
162
+ > & {
163
+ steps?: PublicNestedStepSummary[];
164
+ children?: PublicNestedRunSummary[];
165
+ };
166
+
167
+ export interface SubagentResultIntercomChild {
168
+ agent: string;
169
+ status: SubagentResultStatus;
170
+ summary: string;
171
+ index?: number;
172
+ artifactPath?: string;
173
+ metadataPath?: string;
174
+ sessionPath?: string;
175
+ intercomTarget?: string;
176
+ children?: PublicNestedRunSummary[];
177
+ }
178
+
179
+ export interface SubagentResultIntercomPayload {
180
+ completionId?: string;
181
+ to: string;
182
+ message: string;
183
+ requestId?: string;
184
+ runId: string;
185
+ mode: SubagentRunMode;
186
+ status: SubagentResultStatus;
187
+ summary: string;
188
+ error?: string;
189
+ source: "foreground" | "async";
190
+ children: SubagentResultIntercomChild[];
191
+ resultPath?: string;
192
+ asyncId?: string;
193
+ asyncDir?: string;
194
+ chainSteps?: number;
195
+ agent?: string;
196
+ index?: number;
197
+ artifactPath?: string;
198
+ sessionPath?: string;
199
+ }
200
+
201
+ // ============================================================================
202
+ // Progress Tracking
203
+ // ============================================================================
204
+
205
+ export interface AgentProgress {
206
+ index: number;
207
+ agent: string;
208
+ status: "pending" | "running" | "completed" | "complete" | "failed" | "blocked" | "paused" | "detached" | "timed-out";
209
+ model?: string;
210
+ thinking?: string;
211
+ /** Display boundary: earlier native history belongs to a previous attempt. */
212
+ modelStartedAt?: number;
213
+ activityState?: ActivityState;
214
+ task: string;
215
+ skills?: string[];
216
+ lastActivityAt?: number;
217
+ currentTool?: string;
218
+ currentToolArgs?: string;
219
+ currentToolStartedAt?: number;
220
+ currentPath?: string;
221
+ streamingText?: string;
222
+ recentTools: Array<{ tool: string; args: string; endMs: number }>;
223
+ recentOutput: string[];
224
+ toolCount: number;
225
+ turnCount?: number;
226
+ tokens: number;
227
+ durationMs: number;
228
+ error?: string;
229
+ failedTool?: string;
230
+ }
231
+
232
+ export interface ToolCallSummary {
233
+ text: string;
234
+ expandedText: string;
235
+ }
236
+
237
+ interface ProgressSummary extends Partial<Pick<AgentProgress,
238
+ "index" | "agent" | "status" | "activityState" | "task" | "skills" | "lastActivityAt" | "currentTool" | "currentToolArgs" | "currentToolStartedAt" | "currentPath" | "recentTools" | "recentOutput" | "turnCount" | "error" | "failedTool"
239
+ >> {
240
+ toolCount: number;
241
+ tokens: number;
242
+ durationMs: number;
243
+ }
244
+
245
+ // ============================================================================
246
+ // Results
247
+ // ============================================================================
248
+
249
+ export interface ModelAttempt {
250
+ accounting?: { state: "complete" | "incomplete"; error?: string };
251
+ model: string;
252
+ success: boolean;
253
+ exitCode?: number | null;
254
+ error?: string;
255
+ usage?: Usage;
256
+ }
257
+
258
+ export type AcceptanceProvenanceLevel = "none" | "attested" | "checked" | "verified";
259
+
260
+ export type AcceptanceEvidenceKind =
261
+ | "changed-files"
262
+ | "tests-added"
263
+ | "commands-run"
264
+ | "validation-output"
265
+ | "residual-risks"
266
+ | "no-staged-files"
267
+ | "diff-summary"
268
+ | "review-findings"
269
+ | "manual-notes";
270
+
271
+ export interface AcceptanceGate {
272
+ id: string;
273
+ must: string;
274
+ evidence?: AcceptanceEvidenceKind[];
275
+ severity?: "required" | "recommended";
276
+ }
277
+
278
+ export interface AcceptanceVerifyCommand {
279
+ id: string;
280
+ command: string;
281
+ timeoutMs?: number;
282
+ cwd?: string;
283
+ env?: Record<string, string>;
284
+ allowFailure?: boolean;
285
+ }
286
+
287
+ export interface AcceptanceConfig {
288
+ criteria?: Array<string | AcceptanceGate>;
289
+ evidence?: AcceptanceEvidenceKind[];
290
+ verify?: AcceptanceVerifyCommand[];
291
+ stopRules?: string[];
292
+ maxFinalizationTurns?: number;
293
+ }
294
+
295
+ export type AcceptanceInput = AcceptanceConfig;
296
+
297
+ export interface ResolvedAcceptanceGate extends AcceptanceGate {
298
+ id: string;
299
+ must: string;
300
+ evidence: AcceptanceEvidenceKind[];
301
+ severity: "required" | "recommended";
302
+ }
303
+
304
+ export interface ResolvedAcceptanceConfig {
305
+ level: AcceptanceProvenanceLevel;
306
+ explicit: boolean;
307
+ inferredReason: string[];
308
+ criteria: ResolvedAcceptanceGate[];
309
+ evidence: AcceptanceEvidenceKind[];
310
+ verify: AcceptanceVerifyCommand[];
311
+ stopRules: string[];
312
+ finalization: {
313
+ mode: "none" | "self-review-loop";
314
+ maxTurns: number;
315
+ };
316
+ }
317
+
318
+ export interface AcceptanceReport {
319
+ criteriaSatisfied?: Array<{
320
+ id?: string;
321
+ status: "satisfied" | "not-satisfied" | "not-applicable" | "blocked";
322
+ evidence: string;
323
+ humanAction?: string;
324
+ }>;
325
+ changedFiles?: string[];
326
+ testsAddedOrUpdated?: string[];
327
+ commandsRun?: Array<{
328
+ command: string;
329
+ result: "passed" | "failed" | "not-run";
330
+ summary: string;
331
+ }>;
332
+ validationOutput?: string[];
333
+ residualRisks?: string[];
334
+ noStagedFiles?: boolean;
335
+ diffSummary?: string;
336
+ reviewFindings?: Array<string | Record<string, unknown>>;
337
+ manualNotes?: string;
338
+ notes?: string;
339
+ }
340
+
341
+ export type AcceptanceRuntimeCheckStatus = "passed" | "failed" | "blocked" | "not-applicable";
342
+
343
+ export interface AcceptanceRuntimeCheck {
344
+ id: string;
345
+ status: AcceptanceRuntimeCheckStatus;
346
+ message: string;
347
+ }
348
+
349
+ export interface AcceptanceVerifyResult {
350
+ id: string;
351
+ command: string;
352
+ cwd?: string;
353
+ exitCode: number | null;
354
+ status: "passed" | "failed" | "timed-out" | "allowed-failure";
355
+ stdout?: string;
356
+ stderr?: string;
357
+ durationMs: number;
358
+ }
359
+
360
+ export type AcceptanceLedgerStatus =
361
+ | "not-required"
362
+ | "claimed"
363
+ | "attested"
364
+ | "checked"
365
+ | "verified"
366
+ | "accepted"
367
+ | "blocked"
368
+ | "rejected";
369
+
370
+ export interface AcceptanceFinalizationTurn {
371
+ turn: number;
372
+ prompt: string;
373
+ status: AcceptanceLedgerStatus;
374
+ rawOutput?: string;
375
+ unconfirmedOutput?: string;
376
+ report?: AcceptanceReport;
377
+ parseError?: string;
378
+ runtimeChecks: AcceptanceRuntimeCheck[];
379
+ verifyRuns: AcceptanceVerifyResult[];
380
+ failureMessage?: string;
381
+ }
382
+
383
+ export interface AcceptanceFinalizationLedger {
384
+ mode: "self-review-loop";
385
+ status: "not-run" | "completed" | "blocked" | "failed";
386
+ maxTurns: number;
387
+ turns: AcceptanceFinalizationTurn[];
388
+ }
389
+
390
+ export interface AcceptanceLedger {
391
+ status: AcceptanceLedgerStatus;
392
+ explicit: boolean;
393
+ effectiveAcceptance: ResolvedAcceptanceConfig;
394
+ inferredReason: string[];
395
+ criteria: ResolvedAcceptanceGate[];
396
+ childReport?: AcceptanceReport;
397
+ childReportParseError?: string;
398
+ initialChildReport?: AcceptanceReport;
399
+ initialChildReportParseError?: string;
400
+ /** Prior full report retained as audit evidence, never as current acceptance. */
401
+ unconfirmedOutput?: string;
402
+ runtimeChecks: AcceptanceRuntimeCheck[];
403
+ verifyRuns: AcceptanceVerifyResult[];
404
+ finalization?: AcceptanceFinalizationLedger;
405
+ }
406
+
407
+ export interface ResourceLimitExceeded {
408
+ kind: "maxExecutionTimeMs" | "maxTokens";
409
+ limit: number;
410
+ observed?: number;
411
+ message: string;
412
+ }
413
+
414
+ export interface AgentProcessExit {
415
+ pid?: number;
416
+ code: number | null;
417
+ signal: NodeJS.Signals | null;
418
+ at: number;
419
+ }
420
+
421
+ export interface SingleResult {
422
+ accounting?: { state: "complete" | "incomplete"; error?: string };
423
+ nativeSessionId?: string;
424
+ terminalLeafId?: string | null;
425
+ terminalEntryId?: string;
426
+ auditPath?: string;
427
+ fullOutputPath?: string;
428
+ initialOutputPath?: string;
429
+ auditSaveError?: string;
430
+ agent: string;
431
+ agentProcessExit?: AgentProcessExit;
432
+ task: string;
433
+ exitCode: number;
434
+ detached?: boolean;
435
+ detachedReason?: string;
436
+ interrupted?: boolean;
437
+ timedOut?: boolean;
438
+ resourceLimitExceeded?: ResourceLimitExceeded;
439
+ messages?: Message[];
440
+ usage: Usage;
441
+ model?: string;
442
+ attemptedModels?: string[];
443
+ modelAttempts?: ModelAttempt[];
444
+ controlEvents?: ControlEvent[];
445
+ error?: string;
446
+ sessionFile?: string;
447
+ skills?: string[];
448
+ skillsWarning?: string;
449
+ progress?: AgentProgress;
450
+ progressSummary?: ProgressSummary;
451
+ toolCalls?: ToolCallSummary[];
452
+ artifactPaths?: ArtifactPaths;
453
+ truncation?: TruncationResult;
454
+ finalOutput?: string;
455
+ initialOutput?: string;
456
+ outputMode?: OutputMode;
457
+ savedOutputPath?: string;
458
+ outputReference?: SavedOutputReference;
459
+ outputSaveError?: string;
460
+ outputCleanup?: { path: string; action: "deleted" | "already-missing" | "skipped"; reason?: string; error?: string };
461
+ structuredOutput?: unknown;
462
+ structuredOutputPath?: string;
463
+ structuredOutputSchemaPath?: string;
464
+ acceptance?: AcceptanceLedger;
465
+ }
466
+
467
+ export type ManagementRunState = "live" | "completed" | "paused" | "blocked" | "failed" | "unknown";
468
+ export type ManagementAction = "status" | "nudge" | "resume" | "interrupt" | "extend" | "review";
469
+
470
+ export interface SavedLaunchConfig {
471
+ agent: import("../agents/agents.ts").AgentConfig;
472
+ model?: string;
473
+ thinking?: string;
474
+ /** Timestamp of the native model entry captured with this frozen launch. */
475
+ modelRecordedAt?: number;
476
+ modelCandidates: string[];
477
+ artifacts: boolean;
478
+ artifactsDir?: string;
479
+ share: boolean;
480
+ systemPrompt: string;
481
+ skills: string[];
482
+ cwd: string;
483
+ context: "fresh" | "fork";
484
+ output: string | false;
485
+ /** Proven generated output filename, independent of the selected profile; absent on legacy snapshots. */
486
+ generatedOutputFilename?: string;
487
+ outputMode: OutputMode;
488
+ outputSchema?: JsonSchemaObject;
489
+ effectiveAcceptance?: ResolvedAcceptanceConfig;
490
+ maxOutput?: MaxOutputConfig;
491
+ maxSubagentDepth?: number;
492
+ maxExecutionTimeMs?: number;
493
+ maxTokens?: number;
494
+ controlConfig?: ResolvedControlConfig;
495
+ projectTrust?: ChildProjectTrustPolicy;
496
+ projectTrusted?: boolean;
497
+ }
498
+
499
+ export interface ParentRunReview {
500
+ decision: "accepted" | "needs_changes";
501
+ message?: string;
502
+ reviewedAt: number;
503
+ }
504
+
505
+ export interface OwnedRun {
506
+ recoveryError?: string;
507
+ runId: string;
508
+ ownerSessionId: string;
509
+ source: "foreground" | "async";
510
+ mode: SubagentRunMode;
511
+ cwd: string;
512
+ task: string;
513
+ startedAt: number;
514
+ rootRunId: string;
515
+ predecessorRunId?: string;
516
+ predecessorIndex?: number;
517
+ asyncDir?: string;
518
+ pid?: number;
519
+ children: Array<{ agent: string; index: number; workflowNodeId?: string; task?: string; label?: string; sessionFile?: string }>;
520
+ review?: ParentRunReview;
521
+ completion?: { id: string; state: "pending" | "queued" | "dropped" | "journaled"; channel?: "notification" | "intercom"; queuedAt?: number; entryId?: string };
522
+ accounting?: { state: "pending" | "complete" | "incomplete"; error?: string };
523
+ delivery?: { notifiedAt: number; intercomDelivered: boolean; completionId?: string; entryId?: string };
524
+ legacy?: boolean;
525
+ error?: string;
526
+ }
527
+
528
+ export interface OwnedRunView extends OwnedRun {
529
+ state: ManagementRunState;
530
+ updatedAt: number;
531
+ attention: string[];
532
+ children: Array<OwnedRun["children"][number] & {
533
+ state: ManagementRunState;
534
+ result?: Omit<SingleResult, "artifactPaths"> & { artifactPaths?: Partial<ArtifactPaths> };
535
+ launch?: SavedLaunchConfig;
536
+ configuration: "saved" | "legacy-partial";
537
+ missingSession?: boolean;
538
+ identityUnavailable?: boolean;
539
+ modelSelection?: Pick<AgentProgress, "model" | "thinking" | "modelStartedAt">;
540
+ activity?: Partial<Pick<AgentProgress, "status" | "currentTool" | "currentToolArgs" | "currentPath" | "recentOutput" | "lastActivityAt" | "streamingText">>;
541
+ }>;
542
+ continuations: Array<{ runId: string; predecessorRunId: string; predecessorIndex?: number }>;
543
+ resultPath?: string;
544
+ canInterrupt: boolean;
545
+ diagnosis?: string;
546
+ }
547
+
548
+ export interface ManagementControl {
549
+ state: ManagementRunState;
550
+ runId: string;
551
+ capabilities: ManagementAction[];
552
+ nextActions: Array<{
553
+ action: ManagementAction;
554
+ runId: string;
555
+ index?: number;
556
+ intercomTarget?: string;
557
+ }>;
558
+ unavailableActions?: Partial<Record<ManagementAction, string>>;
559
+ revivedFromRunId?: string;
560
+ pendingReplyContextValid?: boolean;
561
+ }
562
+
563
+ export interface Details {
564
+ accounting?: { state: "incomplete"; error: string };
565
+ mode: SubagentRunMode | "management";
566
+ /** A receipt only when persisted on a native tool result with matching top-level usage. */
567
+ parentUsage?: { contributions: UsageContribution[] };
568
+ runId?: string;
569
+ context?: "fresh" | "fork";
570
+ results: SingleResult[];
571
+ controlEvents?: ControlEvent[];
572
+ asyncId?: string;
573
+ asyncDir?: string;
574
+ asyncPid?: number;
575
+ shareUrl?: string;
576
+ gistUrl?: string;
577
+ shareError?: string;
578
+ progress?: AgentProgress[];
579
+ progressSummary?: ProgressSummary;
580
+ intercomTargets?: string[];
581
+ managementControl?: ManagementControl;
582
+ managementControls?: ManagementControl[];
583
+ questions?: import("../runs/shared/supervisor-questions.ts").SupervisorQuestionSummary[];
584
+ questionList?: { total: number; offset: number; limit: number; nextOffset?: number };
585
+ wait?: { runId: string; completionId?: string; index?: number; status: "completed" | "cancelled" | "yielded" | "awaiting_input" | "unavailable" };
586
+ run?: OwnedRunView;
587
+ runs?: Array<Pick<OwnedRunView, "runId" | "source" | "mode" | "cwd" | "task" | "state" | "updatedAt" | "attention" | "review" | "rootRunId" | "predecessorRunId" | "predecessorIndex"> & { summary?: string; continuations?: string[] }>;
588
+ runList?: { total: number; offset: number; limit: number; nextOffset?: number; nextCursor?: string; version: number; freshness: import("../history/types.ts").HistoryFreshness };
589
+ history?: import("../history/types.ts").HistoryPage;
590
+ historySearch?: import("../history/types.ts").HistorySearchPage;
591
+ intercomDelivery?: {
592
+ delivered: boolean;
593
+ to: string;
594
+ status: SubagentResultStatus;
595
+ summary: string;
596
+ };
597
+ artifacts?: {
598
+ dir: string;
599
+ files: ArtifactPaths[];
600
+ };
601
+ truncation?: {
602
+ truncated: boolean;
603
+ originalBytes?: number;
604
+ originalLines?: number;
605
+ artifactPath?: string;
606
+ };
607
+ // Chain metadata for observability
608
+ chainAgents?: string[]; // Agent names in order, e.g., ["scout", "planner"]
609
+ totalSteps?: number; // Total steps in chain
610
+ currentStepIndex?: number; // 0-indexed current step (for running chains)
611
+ workflowGraph?: WorkflowGraphSnapshot;
612
+ outputs?: ChainOutputMap;
613
+ }
614
+
615
+ export type SubagentExecutionResult = AgentToolResult<Details> & {
616
+ /** Executor error marker; registered tools transfer it through Pi's native tool_result hook. */
617
+ isError?: boolean;
618
+ };
619
+
620
+ // ============================================================================
621
+ // Artifacts
622
+ // ============================================================================
623
+
624
+ export interface ArtifactPaths {
625
+ inputPath: string;
626
+ outputPath: string;
627
+ metadataPath: string;
628
+ }
629
+
630
+ // ============================================================================
631
+ // Async Execution
632
+ // ============================================================================
633
+
634
+ export interface AsyncParallelGroupStatus {
635
+ start: number;
636
+ count: number;
637
+ stepIndex: number;
638
+ }
639
+
640
+ export type AsyncResultTerminalState = "complete" | "failed" | "blocked" | "paused";
641
+
642
+ export interface AsyncResultChild extends Partial<Pick<SingleResult,
643
+ "task" | "finalOutput" | "initialOutput" | "outputMode" | "savedOutputPath" | "outputReference" | "outputSaveError" | "outputCleanup"
644
+ | "toolCalls" | "progressSummary" | "truncation" | "skills" | "skillsWarning" | "accounting" | "nativeSessionId" | "terminalLeafId" | "terminalEntryId" | "auditPath" | "auditSaveError" | "fullOutputPath" | "initialOutputPath"
645
+ >> {
646
+ usage?: Usage;
647
+ timedOut?: boolean;
648
+ agent?: string;
649
+ agentProcessExit?: AgentProcessExit;
650
+ exitCode?: number | null;
651
+ output?: string;
652
+ error?: string;
653
+ success?: boolean;
654
+ skipped?: boolean;
655
+ sessionFile?: string;
656
+ intercomTarget?: string;
657
+ model?: string;
658
+ attemptedModels?: string[];
659
+ modelAttempts?: ModelAttempt[];
660
+ artifactPaths?: Partial<ArtifactPaths>;
661
+ truncated?: boolean;
662
+ structuredOutput?: unknown;
663
+ structuredOutputPath?: string;
664
+ structuredOutputSchemaPath?: string;
665
+ acceptance?: AcceptanceLedger;
666
+ resourceLimitExceeded?: ResourceLimitExceeded;
667
+ interrupted?: boolean;
668
+ children?: unknown;
669
+ }
670
+
671
+ export interface AsyncResultFile {
672
+ legacySource?: string;
673
+ recordVersion?: 3;
674
+ completionId?: string;
675
+ maxOutput?: MaxOutputConfig;
676
+ error?: string;
677
+ runtimeVersion?: 2;
678
+ timedOut?: boolean;
679
+ id?: string;
680
+ runId?: string;
681
+ agent?: string;
682
+ mode?: SubagentRunMode;
683
+ success?: boolean;
684
+ state?: string;
685
+ summary?: string;
686
+ results?: AsyncResultChild[];
687
+ outputs?: ChainOutputMap;
688
+ workflowGraph?: WorkflowGraphSnapshot;
689
+ exitCode?: number;
690
+ timestamp?: number;
691
+ durationMs?: number;
692
+ truncated?: boolean;
693
+ artifactsDir?: string;
694
+ cwd?: string;
695
+ asyncDir?: string;
696
+ sessionId?: string;
697
+ sessionFile?: string;
698
+ intercomTarget?: string;
699
+ shareUrl?: string;
700
+ gistUrl?: string;
701
+ shareError?: string;
702
+ taskIndex?: number;
703
+ totalTasks?: number;
704
+ nestedChildren?: unknown;
705
+ }
706
+
707
+ export type NestedRunState = "queued" | "running" | "complete" | "failed" | "blocked" | "paused";
708
+ export type NestedOwnerState = "live" | "gone" | "unknown";
709
+
710
+ export interface NestedRunAddress {
711
+ id: string;
712
+ parentRunId: string;
713
+ parentStepIndex?: number;
714
+ parentAgent?: string;
715
+ depth: number;
716
+ path: Array<{ runId: string; stepIndex?: number; agent?: string }>;
717
+ }
718
+
719
+ export interface NestedStepSummary {
720
+ agent: string;
721
+ status: "pending" | "running" | "complete" | "completed" | "failed" | "blocked" | "paused" | "timed-out";
722
+ sessionFile?: string;
723
+ activityState?: ActivityState;
724
+ lastActivityAt?: number;
725
+ currentTool?: string;
726
+ currentToolStartedAt?: number;
727
+ currentPath?: string;
728
+ turnCount?: number;
729
+ toolCount?: number;
730
+ startedAt?: number;
731
+ endedAt?: number;
732
+ error?: string;
733
+ children?: NestedRunSummary[];
734
+ }
735
+
736
+ export interface NestedRunSummary extends NestedRunAddress {
737
+ indexedControl?: boolean;
738
+ asyncDir?: string;
739
+ pid?: number;
740
+ sessionId?: string;
741
+ sessionFile?: string;
742
+ intercomTarget?: string;
743
+ ownerIntercomTarget?: string;
744
+ leafIntercomTarget?: string;
745
+ ownerState?: NestedOwnerState;
746
+ controlInbox?: string;
747
+ capabilityToken?: string;
748
+ mode?: SubagentRunMode;
749
+ state: NestedRunState;
750
+ agent?: string;
751
+ agents?: string[];
752
+ currentStep?: number;
753
+ chainStepCount?: number;
754
+ parallelGroups?: AsyncParallelGroupStatus[];
755
+ steps?: NestedStepSummary[];
756
+ children?: NestedRunSummary[];
757
+ activityState?: ActivityState;
758
+ lastActivityAt?: number;
759
+ currentTool?: string;
760
+ currentToolStartedAt?: number;
761
+ currentPath?: string;
762
+ turnCount?: number;
763
+ toolCount?: number;
764
+ totalTokens?: TokenUsage;
765
+ startedAt?: number;
766
+ endedAt?: number;
767
+ lastUpdate?: number;
768
+ error?: string;
769
+ }
770
+
771
+ export interface NestedRouteInfo {
772
+ rootRunId: string;
773
+ eventSink: string;
774
+ controlInbox: string;
775
+ capabilityToken: string;
776
+ }
777
+
778
+ export interface AsyncStartedEvent {
779
+ id?: string;
780
+ asyncDir?: string;
781
+ pid?: number;
782
+ sessionId?: string;
783
+ mode?: SubagentRunMode;
784
+ agent?: string;
785
+ agents?: string[];
786
+ chain?: string[];
787
+ chainStepCount?: number;
788
+ parallelGroups?: AsyncParallelGroupStatus[];
789
+ workflowGraph?: WorkflowGraphSnapshot;
790
+ nestedRoute?: NestedRouteInfo;
791
+ }
792
+
793
+ export interface AsyncStatus {
794
+ runtimeVersion?: 2;
795
+ error?: string;
796
+ timeoutAt?: number;
797
+ timedOut?: boolean;
798
+ runId: string;
799
+ indexedControl?: boolean;
800
+ controlRequestFiles?: boolean;
801
+ sessionId?: string;
802
+ mode: SubagentRunMode;
803
+ state: "queued" | "running" | "complete" | "failed" | "blocked" | "paused";
804
+ activityState?: ActivityState;
805
+ lastActivityAt?: number;
806
+ currentTool?: string;
807
+ currentToolStartedAt?: number;
808
+ currentPath?: string;
809
+ turnCount?: number;
810
+ toolCount?: number;
811
+ startedAt: number;
812
+ endedAt?: number;
813
+ lastUpdate?: number;
814
+ pid?: number;
815
+ cwd?: string;
816
+ currentStep?: number;
817
+ chainStepCount?: number;
818
+ parallelGroups?: AsyncParallelGroupStatus[];
819
+ workflowGraph?: WorkflowGraphSnapshot;
820
+ steps?: Array<{
821
+ agent: string;
822
+ phase?: string;
823
+ label?: string;
824
+ outputName?: string;
825
+ structured?: boolean;
826
+ status: "pending" | "running" | "complete" | "completed" | "failed" | "blocked" | "paused" | "timed-out";
827
+ children?: NestedRunSummary[];
828
+ sessionFile?: string;
829
+ activityState?: ActivityState;
830
+ lastActivityAt?: number;
831
+ currentTool?: string;
832
+ currentToolArgs?: string;
833
+ streamingText?: string;
834
+ currentToolStartedAt?: number;
835
+ currentPath?: string;
836
+ recentTools?: Array<{ tool: string; args: string; endMs: number }>;
837
+ recentOutput?: string[];
838
+ turnCount?: number;
839
+ toolCount?: number;
840
+ startedAt?: number;
841
+ endedAt?: number;
842
+ durationMs?: number;
843
+ exitCode?: number | null;
844
+ agentProcessExit?: AgentProcessExit;
845
+ tokens?: TokenUsage;
846
+ skills?: string[];
847
+ model?: string;
848
+ thinking?: string;
849
+ modelStartedAt?: number;
850
+ attemptedModels?: string[];
851
+ modelAttempts?: ModelAttempt[];
852
+ error?: string;
853
+ structuredOutput?: unknown;
854
+ structuredOutputPath?: string;
855
+ structuredOutputSchemaPath?: string;
856
+ acceptance?: AcceptanceLedger;
857
+ resourceLimitExceeded?: ResourceLimitExceeded;
858
+ }>;
859
+ sessionDir?: string;
860
+ outputFile?: string;
861
+ totalTokens?: TokenUsage;
862
+ sessionFile?: string;
863
+ outputs?: ChainOutputMap;
864
+ }
865
+
866
+ export type AsyncJobStep = NonNullable<AsyncStatus["steps"]>[number] & {
867
+ index?: number;
868
+ };
869
+
870
+ export interface AsyncJobState {
871
+ asyncId: string;
872
+ asyncDir: string;
873
+ status: "queued" | "running" | "complete" | "failed" | "blocked" | "paused";
874
+ pid?: number;
875
+ sessionId?: string;
876
+ activityState?: ActivityState;
877
+ lastActivityAt?: number;
878
+ currentTool?: string;
879
+ currentToolStartedAt?: number;
880
+ currentPath?: string;
881
+ turnCount?: number;
882
+ toolCount?: number;
883
+ mode?: SubagentRunMode;
884
+ agents?: string[];
885
+ currentStep?: number;
886
+ chainStepCount?: number;
887
+ parallelGroups?: AsyncParallelGroupStatus[];
888
+ steps?: AsyncJobStep[];
889
+ stepsTotal?: number;
890
+ runningSteps?: number;
891
+ completedSteps?: number;
892
+ activeParallelGroup?: boolean;
893
+ startedAt?: number;
894
+ updatedAt?: number;
895
+ totalTokens?: TokenUsage;
896
+ sessionFile?: string;
897
+ controlEventCursor?: number;
898
+ controlEventIdentity?: string;
899
+ controlEventSince?: number;
900
+ nestedRoute?: NestedRouteInfo;
901
+ nestedChildren?: NestedRunSummary[];
902
+ }
903
+
904
+ export interface ForegroundResumeChild {
905
+ agent: string;
906
+ index: number;
907
+ sessionFile?: string;
908
+ status: SubagentResultStatus;
909
+ summary?: string;
910
+ artifactPath?: string;
911
+ effectiveAcceptance?: ResolvedAcceptanceConfig;
912
+ result?: SingleResult;
913
+ }
914
+
915
+ export interface ForegroundResumeRun {
916
+ runId: string;
917
+ mode: SubagentRunMode;
918
+ cwd: string;
919
+ updatedAt: number;
920
+ error?: string;
921
+ /** Logical work left after detachment, independent of child success. */
922
+ pausedReason?: string;
923
+ children: ForegroundResumeChild[];
924
+ }
925
+
926
+ export interface TimeoutExtensionResult {
927
+ ok: boolean;
928
+ timeoutAt?: number;
929
+ message: string;
930
+ }
931
+
932
+ export type TimeoutExtensionCallback = (additionalMs: number) => TimeoutExtensionResult;
933
+
934
+ export interface SubagentState {
935
+ baseCwd: string;
936
+ currentSessionId: string | null;
937
+ asyncJobs: Map<string, AsyncJobState>;
938
+ waitingRuns?: Map<string, number>;
939
+ isRunResultConsumed?: (runId: string) => boolean;
940
+ foregroundRuns?: Map<string, ForegroundResumeRun>;
941
+ ownedRuns?: Map<string, OwnedRun>;
942
+ historyIndex?: SubagentHistoryIndex;
943
+ historyReady?: Promise<void>;
944
+ historyClosing?: Promise<void>;
945
+ persistOwnedRun?: (run: OwnedRun) => void;
946
+ onRunsChanged?: () => void;
947
+ cleanupTimers: Map<string, ReturnType<typeof setTimeout>>;
948
+ lastUiContext: ExtensionContext | null;
949
+ poller: NodeJS.Timeout | null;
950
+ completionSeen: Map<string, number>;
951
+ watcher: FSWatcher | null;
952
+ watcherRestartTimer: ReturnType<typeof setTimeout> | null;
953
+ resultFileCoalescer: {
954
+ schedule(file: string, delayMs?: number): boolean;
955
+ clear(): void;
956
+ };
957
+ }
958
+
959
+ // ============================================================================
960
+ // Display
961
+ // ============================================================================
962
+
963
+ export type DisplayItem =
964
+ | { type: "text"; text: string }
965
+ | { type: "tool"; name: string; args: Record<string, unknown> };
966
+
967
+ // ============================================================================
968
+ // Error Handling
969
+ // ============================================================================
970
+
971
+ export interface ErrorInfo {
972
+ hasError: boolean;
973
+ exitCode?: number;
974
+ errorType?: string;
975
+ details?: string;
976
+ }
977
+
978
+ export interface IntercomEventBus {
979
+ on(channel: string, handler: (data: unknown) => void): () => void;
980
+ emit(channel: string, data: unknown): void;
981
+ }
982
+
983
+ export const INTERCOM_DETACH_REQUEST_EVENT = "pi-intercom:detach-request";
984
+ export const INTERCOM_DETACH_RESPONSE_EVENT = "pi-intercom:detach-response";
985
+ export const SUBAGENT_ASYNC_STARTED_EVENT = "subagent:async-started";
986
+ export const SUBAGENT_ASYNC_COMPLETE_EVENT = "subagent:async-complete";
987
+ export const SUBAGENT_CONTROL_EVENT = "subagent:control-event";
988
+ export const SUBAGENT_CONTROL_INTERCOM_EVENT = "subagent:control-intercom";
989
+ export const SUBAGENT_RESULT_INTERCOM_EVENT = "subagent:result-intercom";
990
+ export const SUBAGENT_RESULT_INTERCOM_DELIVERY_EVENT = "subagent:result-intercom-delivery";
991
+ export const SUBAGENT_LIVE_INTERCOM_EVENT = "subagent:live-intercom";
992
+ export const SUBAGENT_LIVE_INTERCOM_DELIVERY_EVENT = "subagent:live-intercom-delivery";
993
+ export const SUBAGENT_INTERCOM_HEALTH_REQUEST_EVENT = "subagent:intercom-health-request";
994
+ export const SUBAGENT_INTERCOM_HEALTH_RESPONSE_EVENT = "subagent:intercom-health-response";
995
+ export const SUBAGENT_INTERCOM_IDENTITY_REQUEST_EVENT = "subagent:intercom-identity-request";
996
+ export const SUBAGENT_INTERCOM_IDENTITY_RESPONSE_EVENT = "subagent:intercom-identity-response";
997
+
998
+ export interface SubagentIntercomConnection {
999
+ status: "connected" | "disconnected" | "connecting" | "unknown";
1000
+ sessionId?: string;
1001
+ reason?: string;
1002
+ }
1003
+
1004
+ export interface SubagentLiveIntercomHealth {
1005
+ target: string;
1006
+ status: "registered" | "none" | "missing" | "ambiguous" | "prefix_too_short";
1007
+ sessionId?: string;
1008
+ sessionName?: string;
1009
+ sessionStatus?: string;
1010
+ acceptsAsks?: boolean;
1011
+ pendingAsks?: number;
1012
+ }
1013
+
1014
+ // ============================================================================
1015
+ // Execution Options
1016
+ // ============================================================================
1017
+
1018
+ export type ChildProjectTrustPolicy = "inherit" | "approve" | "no-approve";
1019
+
1020
+ export interface ProjectTrustConfig {
1021
+ childRuns?: ChildProjectTrustPolicy;
1022
+ }
1023
+
1024
+ interface TopLevelParallelConfig {
1025
+ maxTasks?: number;
1026
+ concurrency?: number;
1027
+ }
1028
+
1029
+ interface ExtensionChainConfig {
1030
+ dynamicFanout?: {
1031
+ maxItems?: number;
1032
+ };
1033
+ }
1034
+
1035
+ export interface ExtensionConfig {
1036
+ /** Start authorized children with everyday tools; false restores the full subagent-only surface. */
1037
+ compactChildTools?: boolean;
1038
+ asyncByDefault?: boolean;
1039
+ forceTopLevelAsync?: boolean;
1040
+ defaultSessionDir?: string;
1041
+ maxSubagentDepth?: number;
1042
+ control?: ControlConfig;
1043
+ parallel?: TopLevelParallelConfig;
1044
+ chain?: ExtensionChainConfig;
1045
+ worktreeSetupHook?: string;
1046
+ worktreeSetupHookTimeoutMs?: number;
1047
+ projectTrust?: ChildProjectTrustPolicy | ProjectTrustConfig;
1048
+ }
1049
+
1050
+ // ============================================================================
1051
+ // Constants
1052
+ // ============================================================================
1053
+
1054
+ export const DEFAULT_MAX_OUTPUT: Required<MaxOutputConfig> = {
1055
+ bytes: 200 * 1024,
1056
+ lines: 5000,
1057
+ };
1058
+
1059
+ function sanitizeTempScopeSegment(value: string): string {
1060
+ const sanitized = value
1061
+ .trim()
1062
+ .replace(/[^A-Za-z0-9._-]+/g, "-")
1063
+ .replace(/^-+|-+$/g, "");
1064
+ return sanitized || "unknown";
1065
+ }
1066
+
1067
+ export function resolveTempScopeId(): string {
1068
+ if (typeof process.getuid === "function") return `uid-${process.getuid()}`;
1069
+
1070
+ for (const key of ["USERNAME", "USER", "LOGNAME"] as const) {
1071
+ const value = process.env[key];
1072
+ if (value) return `user-${sanitizeTempScopeSegment(value)}`;
1073
+ }
1074
+
1075
+ try {
1076
+ const username = os.userInfo().username;
1077
+ if (username) return `user-${sanitizeTempScopeSegment(username)}`;
1078
+ } catch {
1079
+ // Fall through to home-directory-based scoping.
1080
+ }
1081
+
1082
+ const homedir = process.env.HOME;
1083
+ if (homedir) return `home-${sanitizeTempScopeSegment(homedir)}`;
1084
+
1085
+ try {
1086
+ const fallbackHomedir = os.homedir();
1087
+ if (fallbackHomedir) return `home-${sanitizeTempScopeSegment(fallbackHomedir)}`;
1088
+ } catch {
1089
+ // Fall through to the last-resort shared scope.
1090
+ }
1091
+
1092
+ return "shared";
1093
+ }
1094
+
1095
+ const MAX_PARALLEL = 8;
1096
+ export const MAX_CONCURRENCY = 4;
1097
+
1098
+ export function resolveTempRootDir(configured = process.env.PI_SUBAGENT_TEMP_ROOT): string {
1099
+ const fallback = path.join(os.tmpdir(), `pi-subagents-${resolveTempScopeId()}`);
1100
+ if (!configured?.trim()) return fallback;
1101
+ const resolved = path.resolve(configured);
1102
+ if (!path.basename(resolved).startsWith("pi-subagents-")) {
1103
+ throw new Error("PI_SUBAGENT_TEMP_ROOT must name a dedicated 'pi-subagents-*' directory.");
1104
+ }
1105
+ return resolved;
1106
+ }
1107
+
1108
+ export const TEMP_ROOT_DIR = resolveTempRootDir();
1109
+ export const RESULTS_DIR = path.join(TEMP_ROOT_DIR, "async-subagent-results");
1110
+ export const ASYNC_DIR = path.join(TEMP_ROOT_DIR, "async-subagent-runs");
1111
+ export const RUNNER_ERROR_LOG_FILE = "runner-error.log";
1112
+ export const CHAIN_RUNS_DIR = path.join(TEMP_ROOT_DIR, "chain-runs");
1113
+ export const TEMP_ARTIFACTS_DIR = path.join(TEMP_ROOT_DIR, "artifacts");
1114
+ export const WIDGET_KEY = "subagent-async";
1115
+ export const SLASH_RESULT_TYPE = "subagent-slash-result";
1116
+ export const SLASH_SUBAGENT_REQUEST_EVENT = "subagent:slash:request";
1117
+ export const SLASH_SUBAGENT_STARTED_EVENT = "subagent:slash:started";
1118
+ export const SLASH_SUBAGENT_RESPONSE_EVENT = "subagent:slash:response";
1119
+ export const SLASH_SUBAGENT_UPDATE_EVENT = "subagent:slash:update";
1120
+ export const SLASH_SUBAGENT_CANCEL_EVENT = "subagent:slash:cancel";
1121
+ export const POLL_INTERVAL_MS = 1000;
1122
+ export const MAX_WIDGET_JOBS = 4;
1123
+ export const DEFAULT_SUBAGENT_MAX_DEPTH = 1;
1124
+ export const SUBAGENT_ACTIONS = ["list", "get", "create", "update", "delete", "status", "history", "search", "interrupt", "extend", "resume", "nudge", "questions", "answer", "review", "doctor"] as const;
1125
+
1126
+ export const DEFAULT_FORK_PREAMBLE =
1127
+ "You are a delegated subagent running from a fork of the parent session. " +
1128
+ "Treat the inherited conversation as reference-only context, not a live thread to continue. " +
1129
+ "Do not continue or answer prior messages as if they are waiting for a reply. " +
1130
+ "Your sole job is to execute the task below and return a focused result for that task using your tools.";
1131
+
1132
+ function normalizeTopLevelParallelValue(value: unknown): number | undefined {
1133
+ const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
1134
+ if (!Number.isInteger(parsed) || parsed < 1) return undefined;
1135
+ return parsed;
1136
+ }
1137
+
1138
+ export function resolveTopLevelParallelMaxTasks(value: unknown): number {
1139
+ return normalizeTopLevelParallelValue(value) ?? MAX_PARALLEL;
1140
+ }
1141
+
1142
+ export function resolveTopLevelParallelConcurrency(
1143
+ override: unknown,
1144
+ configValue: unknown,
1145
+ ): number {
1146
+ return normalizeTopLevelParallelValue(override)
1147
+ ?? normalizeTopLevelParallelValue(configValue)
1148
+ ?? MAX_CONCURRENCY;
1149
+ }
1150
+
1151
+ export function getAsyncConfigPath(suffix: string): string {
1152
+ return path.join(TEMP_ROOT_DIR, `async-cfg-${suffix}.json`);
1153
+ }
1154
+
1155
+ export function wrapForkTask(task: string, preamble?: string | false): string {
1156
+ if (preamble === false) return task;
1157
+ const effectivePreamble = preamble ?? DEFAULT_FORK_PREAMBLE;
1158
+ const wrappedPrefix = `${effectivePreamble}\n\nTask:\n`;
1159
+ if (task.startsWith(wrappedPrefix)) return task;
1160
+ return `${wrappedPrefix}${task}`;
1161
+ }
1162
+
1163
+ // ============================================================================
1164
+ // Recursion Depth Guard
1165
+ // ============================================================================
1166
+
1167
+ export function normalizeMaxSubagentDepth(value: unknown): number | undefined {
1168
+ const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
1169
+ if (!Number.isInteger(parsed) || parsed < 0) return undefined;
1170
+ return parsed;
1171
+ }
1172
+
1173
+ export function resolveCurrentMaxSubagentDepth(configMaxDepth?: number): number {
1174
+ return normalizeMaxSubagentDepth(process.env.PI_SUBAGENT_MAX_DEPTH)
1175
+ ?? normalizeMaxSubagentDepth(configMaxDepth)
1176
+ ?? DEFAULT_SUBAGENT_MAX_DEPTH;
1177
+ }
1178
+
1179
+ export function resolveChildMaxSubagentDepth(parentMaxDepth: number, agentMaxDepth?: number): number {
1180
+ const normalizedParent = normalizeMaxSubagentDepth(parentMaxDepth) ?? DEFAULT_SUBAGENT_MAX_DEPTH;
1181
+ const normalizedAgent = normalizeMaxSubagentDepth(agentMaxDepth);
1182
+ return normalizedAgent === undefined ? normalizedParent : Math.min(normalizedParent, normalizedAgent);
1183
+ }
1184
+
1185
+ function parseSubagentDepth(value: unknown): number | undefined {
1186
+ if (value === undefined || value === null || value === "") return 0;
1187
+ const depth = Number(value);
1188
+ return Number.isInteger(depth) && depth >= 0 ? depth : undefined;
1189
+ }
1190
+
1191
+ export function checkSubagentDepth(configMaxDepth?: number): { blocked: boolean; depth: number; maxDepth: number } {
1192
+ const maxDepth = resolveCurrentMaxSubagentDepth(configMaxDepth);
1193
+ const depth = parseSubagentDepth(process.env.PI_SUBAGENT_DEPTH);
1194
+ if (depth === undefined) return { blocked: true, depth: maxDepth, maxDepth };
1195
+ return { blocked: depth >= maxDepth, depth, maxDepth };
1196
+ }
1197
+
1198
+ export function getSubagentDepthEnv(maxDepth?: number): Record<string, string> {
1199
+ const childMaxDepth = normalizeMaxSubagentDepth(maxDepth) ?? resolveCurrentMaxSubagentDepth();
1200
+ const parentDepth = parseSubagentDepth(process.env.PI_SUBAGENT_DEPTH);
1201
+ const nextDepth = parentDepth === undefined ? childMaxDepth : parentDepth + 1;
1202
+ return {
1203
+ PI_SUBAGENT_DEPTH: String(nextDepth),
1204
+ PI_SUBAGENT_MAX_DEPTH: String(childMaxDepth),
1205
+ };
1206
+ }
1207
+
1208
+ // ============================================================================
1209
+ // Utility Functions
1210
+ // ============================================================================
1211
+
1212
+ function formatBytes(bytes: number): string {
1213
+ if (bytes < 1024) return `${bytes}B`;
1214
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
1215
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
1216
+ }
1217
+
1218
+ export function truncateOutput(
1219
+ output: string,
1220
+ config: Required<MaxOutputConfig>,
1221
+ artifactPath?: string,
1222
+ ): TruncationResult {
1223
+ const lines = output.split("\n");
1224
+ const bytes = Buffer.byteLength(output, "utf-8");
1225
+
1226
+ if (bytes <= config.bytes && lines.length <= config.lines) {
1227
+ return { text: output, truncated: false };
1228
+ }
1229
+
1230
+ let truncatedLines = lines;
1231
+ if (lines.length > config.lines) {
1232
+ truncatedLines = lines.slice(0, config.lines);
1233
+ }
1234
+
1235
+ let result = truncatedLines.join("\n");
1236
+ if (Buffer.byteLength(result, "utf-8") > config.bytes) {
1237
+ let low = 0;
1238
+ let high = result.length;
1239
+ while (low < high) {
1240
+ const mid = Math.floor((low + high + 1) / 2);
1241
+ if (Buffer.byteLength(result.slice(0, mid), "utf-8") <= config.bytes) {
1242
+ low = mid;
1243
+ } else {
1244
+ high = mid - 1;
1245
+ }
1246
+ }
1247
+ result = result.slice(0, low);
1248
+ }
1249
+
1250
+ const keptLines = result.split("\n").length;
1251
+ const marker = `[TRUNCATED: showing first ${keptLines} of ${lines.length} lines, ${formatBytes(Buffer.byteLength(result))} of ${formatBytes(bytes)}${artifactPath ? ` - full output at ${artifactPath}` : ""}]\n`;
1252
+
1253
+ return {
1254
+ text: marker + result,
1255
+ truncated: true,
1256
+ originalBytes: bytes,
1257
+ originalLines: lines.length,
1258
+ artifactPath,
1259
+ };
1260
+ }