@kenkaiiii/ggcoder 5.15.1 → 5.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/assets/end-notification.mp3 +0 -0
  2. package/assets/skills/evidence-led-ui/LICENSES.md +68 -0
  3. package/assets/skills/evidence-led-ui/SKILL.md +139 -0
  4. package/{LICENSE → assets/skills/evidence-led-ui/corpus/awesome-design-md/LICENSE} +1 -1
  5. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/airbnb/DESIGN.md +545 -0
  6. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/airtable/DESIGN.md +554 -0
  7. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/apple/DESIGN.md +562 -0
  8. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/binance/DESIGN.md +634 -0
  9. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/bmw/DESIGN.md +544 -0
  10. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/bmw-m/DESIGN.md +503 -0
  11. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/bugatti/DESIGN.md +454 -0
  12. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/cal/DESIGN.md +542 -0
  13. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/claude/DESIGN.md +589 -0
  14. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/clay/DESIGN.md +541 -0
  15. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/clickhouse/DESIGN.md +544 -0
  16. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/cohere/DESIGN.md +451 -0
  17. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/coinbase/DESIGN.md +570 -0
  18. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/composio/DESIGN.md +506 -0
  19. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/cursor/DESIGN.md +537 -0
  20. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/dell-1996/DESIGN.md +632 -0
  21. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/elevenlabs/DESIGN.md +504 -0
  22. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/expo/DESIGN.md +526 -0
  23. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/ferrari/DESIGN.md +531 -0
  24. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/figma/DESIGN.md +578 -0
  25. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/framer/DESIGN.md +544 -0
  26. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/hashicorp/DESIGN.md +575 -0
  27. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/hp/DESIGN.md +670 -0
  28. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/ibm/DESIGN.md +550 -0
  29. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/intercom/DESIGN.md +546 -0
  30. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/kraken/DESIGN.md +125 -0
  31. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/lamborghini/DESIGN.md +288 -0
  32. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/linear.app/DESIGN.md +548 -0
  33. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/lovable/DESIGN.md +298 -0
  34. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/mastercard/DESIGN.md +365 -0
  35. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/meta/DESIGN.md +683 -0
  36. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/minimax/DESIGN.md +746 -0
  37. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/mintlify/DESIGN.md +852 -0
  38. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/miro/DESIGN.md +825 -0
  39. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/mistral.ai/DESIGN.md +773 -0
  40. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/mongodb/DESIGN.md +767 -0
  41. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/nike/DESIGN.md +575 -0
  42. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/nintendo-2001/DESIGN.md +649 -0
  43. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/notion/DESIGN.md +821 -0
  44. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/nvidia/DESIGN.md +640 -0
  45. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/ollama/DESIGN.md +539 -0
  46. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/opencode.ai/DESIGN.md +521 -0
  47. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/pinterest/DESIGN.md +597 -0
  48. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/playstation/DESIGN.md +661 -0
  49. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/posthog/DESIGN.md +690 -0
  50. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/raycast/DESIGN.md +669 -0
  51. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/renault/DESIGN.md +589 -0
  52. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/replicate/DESIGN.md +616 -0
  53. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/resend/DESIGN.md +585 -0
  54. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/revolut/DESIGN.md +636 -0
  55. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/runwayml/DESIGN.md +244 -0
  56. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/sanity/DESIGN.md +357 -0
  57. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/sentry/DESIGN.md +551 -0
  58. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/shopify/DESIGN.md +516 -0
  59. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/slack/DESIGN.md +482 -0
  60. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/spacex/DESIGN.md +363 -0
  61. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/spotify/DESIGN.md +246 -0
  62. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/starbucks/DESIGN.md +580 -0
  63. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/stripe/DESIGN.md +487 -0
  64. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/supabase/DESIGN.md +462 -0
  65. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/superhuman/DESIGN.md +448 -0
  66. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/tesla/DESIGN.md +286 -0
  67. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/theverge/DESIGN.md +339 -0
  68. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/together.ai/DESIGN.md +633 -0
  69. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/uber/DESIGN.md +636 -0
  70. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/vercel/DESIGN.md +736 -0
  71. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/vodafone/DESIGN.md +538 -0
  72. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/voltagent/DESIGN.md +521 -0
  73. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/warp/DESIGN.md +526 -0
  74. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/webflow/DESIGN.md +588 -0
  75. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/wired/DESIGN.md +497 -0
  76. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/wise/DESIGN.md +544 -0
  77. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/x.ai/DESIGN.md +465 -0
  78. package/assets/skills/evidence-led-ui/corpus/awesome-design-md/design-md/zapier/DESIGN.md +537 -0
  79. package/assets/skills/evidence-led-ui/data/corpus-manifest.json +768 -0
  80. package/assets/skills/evidence-led-ui/data/observations.json +47053 -0
  81. package/assets/skills/evidence-led-ui/references/anti-defaults.md +203 -0
  82. package/assets/skills/evidence-led-ui/references/archetypes.md +97 -0
  83. package/assets/skills/evidence-led-ui/references/craft-rulings.md +167 -0
  84. package/assets/skills/evidence-led-ui/references/methodology.md +72 -0
  85. package/assets/skills/evidence-led-ui/references/observed-patterns.md +68 -0
  86. package/assets/skills/evidence-led-ui/references/production-contract.md +120 -0
  87. package/assets/skills/evidence-led-ui/references/provenance.md +117 -0
  88. package/assets/skills/evidence-led-ui/references/quality-rubric.md +126 -0
  89. package/dist/app-sidecar.js +161 -48
  90. package/dist/app-sidecar.js.map +1 -1
  91. package/dist/chat-agents/general.test.js +3 -0
  92. package/dist/chat-agents/general.test.js.map +1 -1
  93. package/dist/chat-agents/jiwa.d.ts +53 -0
  94. package/dist/chat-agents/jiwa.d.ts.map +1 -0
  95. package/dist/chat-agents/jiwa.js +352 -0
  96. package/dist/chat-agents/jiwa.js.map +1 -0
  97. package/dist/chat-agents/jiwa.test.d.ts +2 -0
  98. package/dist/chat-agents/jiwa.test.d.ts.map +1 -0
  99. package/dist/chat-agents/jiwa.test.js +66 -0
  100. package/dist/chat-agents/jiwa.test.js.map +1 -0
  101. package/dist/chat-agents/shared.d.ts.map +1 -1
  102. package/dist/chat-agents/shared.js +5 -1
  103. package/dist/chat-agents/shared.js.map +1 -1
  104. package/dist/cli.d.ts.map +1 -1
  105. package/dist/cli.js +15 -0
  106. package/dist/cli.js.map +1 -1
  107. package/dist/core/agent-session-review-coverage.test.d.ts +2 -0
  108. package/dist/core/agent-session-review-coverage.test.d.ts.map +1 -0
  109. package/dist/core/agent-session-review-coverage.test.js +57 -0
  110. package/dist/core/agent-session-review-coverage.test.js.map +1 -0
  111. package/dist/core/agent-session.d.ts +13 -7
  112. package/dist/core/agent-session.d.ts.map +1 -1
  113. package/dist/core/agent-session.js +143 -38
  114. package/dist/core/agent-session.js.map +1 -1
  115. package/dist/core/compaction/compactor.test.js +1 -1
  116. package/dist/core/compaction/compactor.test.js.map +1 -1
  117. package/dist/core/event-bus.d.ts +2 -0
  118. package/dist/core/event-bus.d.ts.map +1 -1
  119. package/dist/core/event-bus.js.map +1 -1
  120. package/dist/core/ideal-review.d.ts +27 -0
  121. package/dist/core/ideal-review.d.ts.map +1 -1
  122. package/dist/core/ideal-review.js +64 -0
  123. package/dist/core/ideal-review.js.map +1 -1
  124. package/dist/core/ideal-review.test.js +34 -1
  125. package/dist/core/ideal-review.test.js.map +1 -1
  126. package/dist/core/ken-prompt.d.ts +3 -3
  127. package/dist/core/ken-prompt.d.ts.map +1 -1
  128. package/dist/core/ken-prompt.js +10 -10
  129. package/dist/core/ken-prompt.js.map +1 -1
  130. package/dist/core/ken-prompt.test.js +17 -0
  131. package/dist/core/ken-prompt.test.js.map +1 -1
  132. package/dist/core/loop-breaker.d.ts +23 -16
  133. package/dist/core/loop-breaker.d.ts.map +1 -1
  134. package/dist/core/loop-breaker.js +52 -11
  135. package/dist/core/loop-breaker.js.map +1 -1
  136. package/dist/core/loop-breaker.test.js +37 -16
  137. package/dist/core/loop-breaker.test.js.map +1 -1
  138. package/dist/core/lsp/client.d.ts +3 -0
  139. package/dist/core/lsp/client.d.ts.map +1 -1
  140. package/dist/core/lsp/client.js +20 -0
  141. package/dist/core/lsp/client.js.map +1 -1
  142. package/dist/core/lsp/manager.d.ts +32 -9
  143. package/dist/core/lsp/manager.d.ts.map +1 -1
  144. package/dist/core/lsp/manager.js +89 -37
  145. package/dist/core/lsp/manager.js.map +1 -1
  146. package/dist/core/lsp/manager.test.js +56 -4
  147. package/dist/core/lsp/manager.test.js.map +1 -1
  148. package/dist/core/run-lifecycle.d.ts +40 -0
  149. package/dist/core/run-lifecycle.d.ts.map +1 -0
  150. package/dist/core/run-lifecycle.js +95 -0
  151. package/dist/core/run-lifecycle.js.map +1 -0
  152. package/dist/core/run-lifecycle.test.d.ts +2 -0
  153. package/dist/core/run-lifecycle.test.d.ts.map +1 -0
  154. package/dist/core/run-lifecycle.test.js +64 -0
  155. package/dist/core/run-lifecycle.test.js.map +1 -0
  156. package/dist/core/session-manager.d.ts +25 -1
  157. package/dist/core/session-manager.d.ts.map +1 -1
  158. package/dist/core/session-manager.js +66 -1
  159. package/dist/core/session-manager.js.map +1 -1
  160. package/dist/core/session-manager.test.js +80 -2
  161. package/dist/core/session-manager.test.js.map +1 -1
  162. package/dist/core/skills-routing.test.d.ts +2 -0
  163. package/dist/core/skills-routing.test.d.ts.map +1 -0
  164. package/dist/core/skills-routing.test.js +70 -0
  165. package/dist/core/skills-routing.test.js.map +1 -0
  166. package/dist/core/skills.d.ts +2 -0
  167. package/dist/core/skills.d.ts.map +1 -1
  168. package/dist/core/skills.js +32 -9
  169. package/dist/core/skills.js.map +1 -1
  170. package/dist/core/subagent-manager.d.ts +40 -3
  171. package/dist/core/subagent-manager.d.ts.map +1 -1
  172. package/dist/core/subagent-manager.js +342 -30
  173. package/dist/core/subagent-manager.js.map +1 -1
  174. package/dist/core/subagent-manager.test.js +189 -3
  175. package/dist/core/subagent-manager.test.js.map +1 -1
  176. package/dist/core/subagent-store.d.ts +20 -0
  177. package/dist/core/subagent-store.d.ts.map +1 -0
  178. package/dist/core/subagent-store.js +177 -0
  179. package/dist/core/subagent-store.js.map +1 -0
  180. package/dist/core/subagent-store.test.d.ts +2 -0
  181. package/dist/core/subagent-store.test.d.ts.map +1 -0
  182. package/dist/core/subagent-store.test.js +94 -0
  183. package/dist/core/subagent-store.test.js.map +1 -0
  184. package/dist/modes/agent-home-mode.d.ts.map +1 -1
  185. package/dist/modes/agent-home-mode.js +10 -3
  186. package/dist/modes/agent-home-mode.js.map +1 -1
  187. package/dist/modes/serve-mode.d.ts.map +1 -1
  188. package/dist/modes/serve-mode.js +10 -3
  189. package/dist/modes/serve-mode.js.map +1 -1
  190. package/dist/modes/subagent-worker-mode.d.ts +2 -0
  191. package/dist/modes/subagent-worker-mode.d.ts.map +1 -1
  192. package/dist/modes/subagent-worker-mode.js +13 -3
  193. package/dist/modes/subagent-worker-mode.js.map +1 -1
  194. package/dist/system-prompt.js +2 -2
  195. package/dist/system-prompt.js.map +1 -1
  196. package/dist/system-prompt.test.js +3 -0
  197. package/dist/system-prompt.test.js.map +1 -1
  198. package/dist/tools/skill.d.ts.map +1 -1
  199. package/dist/tools/skill.js +8 -3
  200. package/dist/tools/skill.js.map +1 -1
  201. package/dist/tools/tasks.d.ts +1 -1
  202. package/dist/tools/web-fetch.d.ts +1 -1
  203. package/dist/ui/App.d.ts +7 -1
  204. package/dist/ui/App.d.ts.map +1 -1
  205. package/dist/ui/App.js +63 -17
  206. package/dist/ui/App.js.map +1 -1
  207. package/dist/ui/components/Footer.d.ts +1 -0
  208. package/dist/ui/components/Footer.d.ts.map +1 -1
  209. package/dist/ui/components/Footer.js +3 -3
  210. package/dist/ui/components/Footer.js.map +1 -1
  211. package/dist/ui/components/Footer.test.d.ts +2 -0
  212. package/dist/ui/components/Footer.test.d.ts.map +1 -0
  213. package/dist/ui/components/Footer.test.js +16 -0
  214. package/dist/ui/components/Footer.test.js.map +1 -0
  215. package/dist/ui/components/SkillsOverlay.d.ts.map +1 -1
  216. package/dist/ui/components/SkillsOverlay.js +8 -3
  217. package/dist/ui/components/SkillsOverlay.js.map +1 -1
  218. package/dist/ui/hooks/useAgentLoop.d.ts +8 -3
  219. package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
  220. package/dist/ui/hooks/useAgentLoop.js +71 -26
  221. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  222. package/dist/ui/hooks/useAgentLoop.test.js +27 -0
  223. package/dist/ui/hooks/useAgentLoop.test.js.map +1 -1
  224. package/dist/ui/hooks/useSessionPersistence.d.ts +4 -2
  225. package/dist/ui/hooks/useSessionPersistence.d.ts.map +1 -1
  226. package/dist/ui/hooks/useSessionPersistence.js +7 -1
  227. package/dist/ui/hooks/useSessionPersistence.js.map +1 -1
  228. package/dist/ui/render.d.ts +7 -0
  229. package/dist/ui/render.d.ts.map +1 -1
  230. package/dist/ui/render.js +4 -0
  231. package/dist/ui/render.js.map +1 -1
  232. package/package.json +6 -5
@@ -1 +1 @@
1
- {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
- import type { Provider, ThinkingLevel } from "@kenkaiiii/gg-ai";
1
+ import type { Message, Provider, ThinkingLevel } from "@kenkaiiii/gg-ai";
2
2
  import type { AgentDefinition } from "./agents.js";
3
- export type SubAgentState = "starting" | "running" | "completed" | "failed" | "interrupted" | "closed";
3
+ import { SubAgentStore } from "./subagent-store.js";
4
+ export type SubAgentState = "starting" | "running" | "completed" | "failed" | "interrupted" | "closed" | "reaped";
4
5
  export interface SubAgentSnapshot {
5
6
  agent_id: string;
6
7
  task_name: string;
@@ -17,6 +18,13 @@ export interface SubAgentSnapshot {
17
18
  };
18
19
  output?: string;
19
20
  error?: string;
21
+ agent_name?: string;
22
+ provider?: string;
23
+ model?: string;
24
+ child_session_id?: string;
25
+ child_session_path?: string;
26
+ collected?: boolean;
27
+ recovered?: boolean;
20
28
  }
21
29
  export interface SubAgentManagerOptions {
22
30
  cwd: string;
@@ -29,40 +37,69 @@ export interface SubAgentManagerOptions {
29
37
  onState?: (snapshot: SubAgentSnapshot) => void;
30
38
  workerEntry?: string;
31
39
  idleTimeoutMs?: number;
40
+ store?: SubAgentStore;
41
+ sessionRootDir?: string;
32
42
  }
43
+ /** Shared pre-finalization hook used by both AgentSession and the Ink host. */
44
+ export declare function buildSubAgentCompletionFollowUp(manager: Pick<SubAgentManager, "completionGateMessage"> | undefined): Message[] | null;
33
45
  export declare class SubAgentManager {
34
46
  private readonly options;
35
47
  private readonly workers;
36
48
  private readonly snapshots;
37
49
  private readonly listeners;
38
50
  private shuttingDown;
51
+ private shutdownPromise?;
52
+ private readonly store;
53
+ private readonly sessionRootDir;
54
+ private parentSessionId?;
55
+ private persistQueue;
56
+ private persistPending;
57
+ private persistScheduled;
39
58
  constructor(options: SubAgentManagerOptions);
59
+ /** Restore bounded history; dead in-flight workers become honestly interrupted. */
60
+ hydrate(parentSessionId: string): Promise<void>;
61
+ /** Rebind durable child history after parent compaction creates a continuation. */
62
+ rebindParentSession(parentSessionId: string): Promise<void>;
63
+ /** A genuinely new parent starts with no unrelated child history. */
64
+ resetParentSession(parentSessionId: string): Promise<void>;
65
+ waitForPersistence(): Promise<void>;
40
66
  spawn(taskName: string, task: string, agentName?: string): Promise<SubAgentSnapshot>;
41
67
  sendMessage(agentId: string, message: string): Promise<number>;
42
68
  followup(agentId: string, task: string): Promise<SubAgentSnapshot>;
43
- interrupt(agentId: string): Promise<SubAgentSnapshot>;
69
+ interrupt(agentId: string, collectResult?: boolean): Promise<SubAgentSnapshot>;
44
70
  subscribe(listener: (snapshot: SubAgentSnapshot) => void): () => void;
45
71
  list(): SubAgentSnapshot[];
46
72
  wait(agentIds?: string[], condition?: "any" | "all", timeoutMs?: number): Promise<{
47
73
  timed_out: boolean;
48
74
  agents: SubAgentSnapshot[];
49
75
  }>;
76
+ completionGate(): {
77
+ active: SubAgentSnapshot[];
78
+ uncollected: SubAgentSnapshot[];
79
+ unresolved: number;
80
+ };
81
+ completionGateMessage(): string | undefined;
50
82
  interruptAll(): Promise<void>;
51
83
  shutdownAll(): Promise<void>;
52
84
  /** Synchronous process-exit fallback: terminate detached process groups immediately. */
53
85
  shutdownAllNow(): void;
86
+ private markCollected;
87
+ private spawnWorkerProcess;
88
+ private respawnRecovered;
54
89
  private attach;
55
90
  private handleFrame;
56
91
  private request;
57
92
  private waitForChange;
58
93
  private publish;
59
94
  private snapshot;
95
+ private queuePersist;
60
96
  private elapsed;
61
97
  private activeCount;
62
98
  private isActive;
63
99
  private isTerminal;
64
100
  private requireWorker;
65
101
  private assertAvailable;
102
+ private assertChildSessionPath;
66
103
  private createId;
67
104
  private scheduleIdleReap;
68
105
  private reapExcessIdle;
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-manager.d.ts","sourceRoot":"","sources":["../../src/core/subagent-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subagent-manager.d.ts","sourceRoot":"","sources":["../../src/core/subagent-manager.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,11 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { createInterface } from "node:readline";
4
+ import path from "node:path";
5
+ import { getAppPaths } from "@kenkaiiii/gg-core";
6
+ import { SubAgentStore } from "./subagent-store.js";
7
+ import { SessionManager } from "./session-manager.js";
8
+ import { log } from "./logger.js";
4
9
  import { boundSubAgentOutput, childSubAgentEnv, childThinkingLevel, resolveSubAgentCliEntry, selectSubAgent, subAgentCacheKey, SUB_AGENT_MAX_STDERR_CHARS, } from "../tools/subagent-shared.js";
5
10
  const ACTIVE_LIMIT = 4;
6
11
  const RETAINED_WORKER_LIMIT = 8;
@@ -13,14 +18,94 @@ function activity(name, args) {
13
18
  const value = Object.values(args).find((candidate) => typeof candidate === "string");
14
19
  return value ? `${name}: ${String(value).slice(0, 60)}` : name;
15
20
  }
21
+ /** Shared pre-finalization hook used by both AgentSession and the Ink host. */
22
+ export function buildSubAgentCompletionFollowUp(manager) {
23
+ const message = manager?.completionGateMessage();
24
+ return message ? [{ role: "user", content: message }] : null;
25
+ }
16
26
  export class SubAgentManager {
17
27
  options;
18
28
  workers = new Map();
19
29
  snapshots = new Map();
20
30
  listeners = new Set();
21
31
  shuttingDown = false;
32
+ shutdownPromise;
33
+ store;
34
+ sessionRootDir;
35
+ parentSessionId;
36
+ persistQueue = Promise.resolve();
37
+ persistPending = false;
38
+ persistScheduled = false;
22
39
  constructor(options) {
23
40
  this.options = options;
41
+ const paths = getAppPaths();
42
+ this.store = options.store ?? new SubAgentStore(paths.subagentsDir);
43
+ this.sessionRootDir = options.sessionRootDir ?? paths.subagentSessionsDir;
44
+ }
45
+ /** Restore bounded history; dead in-flight workers become honestly interrupted. */
46
+ async hydrate(parentSessionId) {
47
+ if (this.workers.size > 0) {
48
+ await this.shutdownAll();
49
+ this.workers.clear();
50
+ this.shuttingDown = false;
51
+ this.shutdownPromise = undefined;
52
+ }
53
+ await this.waitForPersistence();
54
+ this.parentSessionId = parentSessionId;
55
+ this.snapshots.clear();
56
+ const records = await this.store.load(this.options.cwd, parentSessionId);
57
+ for (const persisted of records) {
58
+ const snapshot = {
59
+ ...persisted,
60
+ ...(persisted.state === "starting" || persisted.state === "running"
61
+ ? {
62
+ state: "interrupted",
63
+ error: "Interrupted by process restart",
64
+ updated_at: Date.now(),
65
+ recovered: true,
66
+ }
67
+ : { recovered: true }),
68
+ };
69
+ this.snapshots.set(snapshot.agent_id, snapshot);
70
+ this.options.onState?.(snapshot);
71
+ for (const listener of this.listeners)
72
+ listener(snapshot);
73
+ }
74
+ this.queuePersist();
75
+ await this.waitForPersistence();
76
+ const referencedChildSessions = await this.store.listChildSessionPaths();
77
+ await new SessionManager(this.sessionRootDir)
78
+ .pruneOldSessions({
79
+ maxAgeDays: 30,
80
+ keepPaths: referencedChildSessions,
81
+ })
82
+ .catch((error) => {
83
+ log("WARN", "subagent", "Failed to prune old subagent sessions", {
84
+ error: error instanceof Error ? error.message : String(error),
85
+ });
86
+ });
87
+ }
88
+ /** Rebind durable child history after parent compaction creates a continuation. */
89
+ async rebindParentSession(parentSessionId) {
90
+ await this.waitForPersistence();
91
+ this.parentSessionId = parentSessionId;
92
+ this.queuePersist();
93
+ await this.persistQueue;
94
+ }
95
+ /** A genuinely new parent starts with no unrelated child history. */
96
+ async resetParentSession(parentSessionId) {
97
+ await this.shutdownAll();
98
+ await this.waitForPersistence();
99
+ this.shuttingDown = false;
100
+ this.shutdownPromise = undefined;
101
+ this.workers.clear();
102
+ this.snapshots.clear();
103
+ this.parentSessionId = parentSessionId;
104
+ this.queuePersist();
105
+ await this.persistQueue;
106
+ }
107
+ async waitForPersistence() {
108
+ await this.persistQueue;
24
109
  }
25
110
  async spawn(taskName, task, agentName) {
26
111
  this.assertAvailable();
@@ -39,12 +124,7 @@ export class SubAgentManager {
39
124
  throw new Error(`Unknown agent: "${agentName}"`);
40
125
  const now = Date.now();
41
126
  const agentId = this.createId();
42
- const child = spawn(process.execPath, [this.options.workerEntry ?? resolveSubAgentCliEntry(), "--subagent-worker"], {
43
- cwd: this.options.cwd,
44
- stdio: ["pipe", "pipe", "pipe"],
45
- env: childSubAgentEnv(),
46
- detached: process.platform !== "win32",
47
- });
127
+ const child = this.spawnWorkerProcess();
48
128
  const record = {
49
129
  agent_id: agentId,
50
130
  task_name: taskName,
@@ -55,6 +135,10 @@ export class SubAgentManager {
55
135
  turn_count: 0,
56
136
  tool_use_count: 0,
57
137
  token_usage: { input: 0, output: 0 },
138
+ agent_name: selection.agentDef?.name,
139
+ provider,
140
+ model: selection.model,
141
+ collected: false,
58
142
  process: child,
59
143
  requests: new Map(),
60
144
  requestSequence: 0,
@@ -65,8 +149,9 @@ export class SubAgentManager {
65
149
  this.workers.set(agentId, record);
66
150
  this.publish(record);
67
151
  this.attach(record);
152
+ await this.waitForPersistence();
68
153
  try {
69
- await this.request(record, "initialize", {
154
+ const initialized = await this.request(record, "initialize", {
70
155
  options: {
71
156
  provider,
72
157
  model: selection.model,
@@ -77,16 +162,29 @@ export class SubAgentManager {
77
162
  thinkingLevel: childThinkingLevel(this.options.getThinkingLevel()),
78
163
  allowedTools: selection.agentDef?.tools.length ? selection.agentDef.tools : undefined,
79
164
  promptCacheKey: subAgentCacheKey(this.options.getCacheKey?.(), selection.model, selection.agentDef?.name ?? "default"),
165
+ sessionRootDir: this.sessionRootDir,
80
166
  },
81
167
  });
168
+ record.child_session_id =
169
+ typeof initialized.child_session_id === "string" ? initialized.child_session_id : undefined;
170
+ if (typeof initialized.model === "string")
171
+ record.model = initialized.model;
172
+ record.child_session_path =
173
+ typeof initialized.child_session_path === "string"
174
+ ? this.assertChildSessionPath(initialized.child_session_path)
175
+ : undefined;
176
+ this.publish(record);
177
+ await this.waitForPersistence();
82
178
  await this.request(record, "start", { task });
83
179
  record.state = "running";
84
180
  record.updated_at = Date.now();
85
181
  this.publish(record);
182
+ await this.waitForPersistence();
86
183
  return this.snapshot(record);
87
184
  }
88
185
  catch (error) {
89
186
  this.fail(record, error);
187
+ await this.waitForPersistence();
90
188
  throw error;
91
189
  }
92
190
  }
@@ -99,7 +197,13 @@ export class SubAgentManager {
99
197
  }
100
198
  async followup(agentId, task) {
101
199
  this.assertAvailable();
102
- const worker = this.requireWorker(agentId);
200
+ let worker = this.workers.get(agentId);
201
+ if (!worker) {
202
+ const recovered = this.snapshots.get(agentId);
203
+ if (!recovered)
204
+ throw new Error(`Unknown agent: ${agentId}`);
205
+ worker = await this.respawnRecovered(recovered);
206
+ }
103
207
  if (worker.state === "running" || worker.state === "starting") {
104
208
  throw new Error(`Agent ${agentId} already has an active turn`);
105
209
  }
@@ -109,19 +213,24 @@ export class SubAgentManager {
109
213
  worker.taskOutput = "";
110
214
  worker.output = undefined;
111
215
  worker.error = undefined;
216
+ worker.collected = false;
112
217
  await this.request(worker, "followup", { task });
113
218
  worker.state = "running";
114
219
  worker.updated_at = Date.now();
115
220
  this.publish(worker);
221
+ await this.waitForPersistence();
116
222
  return this.snapshot(worker);
117
223
  }
118
- async interrupt(agentId) {
224
+ async interrupt(agentId, collectResult = true) {
119
225
  const worker = this.requireWorker(agentId);
120
226
  if (worker.state !== "running")
121
227
  throw new Error(`Agent ${agentId} is not running`);
122
228
  const changed = this.waitForChange(agentId);
123
229
  await this.request(worker, "interrupt");
124
230
  await changed;
231
+ if (collectResult)
232
+ this.markCollected(agentId);
233
+ await this.waitForPersistence();
125
234
  return this.snapshot(worker);
126
235
  }
127
236
  subscribe(listener) {
@@ -147,17 +256,29 @@ export class SubAgentManager {
147
256
  const boundedTimeout = Math.min(Math.max(timeoutMs, 0), MAX_WAIT_MS);
148
257
  const terminal = () => ids.filter((id) => this.isTerminal(this.snapshots.get(id)?.state));
149
258
  const ready = () => condition === "all" ? terminal().length === ids.length : terminal().length > 0;
259
+ const deadline = Date.now() + boundedTimeout;
150
260
  let timedOut = false;
151
- if (!ready()) {
152
- const changes = ids.map((id) => this.waitForChange(id));
153
- const requestedChange = condition === "all"
154
- ? Promise.all(changes).then(() => true)
155
- : Promise.race(changes).then(() => true);
156
- timedOut = !(await Promise.race([
157
- requestedChange,
158
- new Promise((resolve) => setTimeout(() => resolve(false), boundedTimeout)),
159
- ]));
261
+ while (!ready()) {
262
+ const remaining = deadline - Date.now();
263
+ if (remaining <= 0) {
264
+ timedOut = true;
265
+ break;
266
+ }
267
+ const pendingIds = ids.filter((id) => !this.isTerminal(this.snapshots.get(id)?.state));
268
+ const changed = await Promise.race([
269
+ Promise.race(pendingIds.map((id) => this.waitForChange(id))).then(() => true),
270
+ new Promise((resolve) => setTimeout(() => resolve(false), remaining)),
271
+ ]);
272
+ if (!changed && !ready())
273
+ timedOut = true;
274
+ if (!changed)
275
+ break;
276
+ }
277
+ for (const id of ids) {
278
+ if (this.isTerminal(this.snapshots.get(id)?.state))
279
+ this.markCollected(id);
160
280
  }
281
+ await this.waitForPersistence();
161
282
  let chars = 0;
162
283
  const agents = ids.map((id) => {
163
284
  const snapshot = { ...this.snapshots.get(id) };
@@ -170,16 +291,39 @@ export class SubAgentManager {
170
291
  });
171
292
  return { timed_out: timedOut, agents };
172
293
  }
294
+ completionGate() {
295
+ const snapshots = this.list();
296
+ const active = snapshots.filter((snapshot) => this.isActive(snapshot));
297
+ const uncollected = snapshots.filter((snapshot) => this.isTerminal(snapshot.state) && snapshot.collected !== true);
298
+ return { active, uncollected, unresolved: active.length + uncollected.length };
299
+ }
300
+ completionGateMessage() {
301
+ const gate = this.completionGate();
302
+ if (gate.unresolved === 0)
303
+ return undefined;
304
+ const activeIds = gate.active.map((snapshot) => snapshot.agent_id).sort();
305
+ const uncollectedIds = gate.uncollected.map((snapshot) => snapshot.agent_id).sort();
306
+ const unresolvedIds = [...new Set([...activeIds, ...uncollectedIds])];
307
+ return [
308
+ "Child-agent completion gate: the parent cannot finish with unresolved child work.",
309
+ `Unresolved agent IDs: ${unresolvedIds.join(", ")}.`,
310
+ activeIds.length > 0
311
+ ? `Active agent IDs: ${activeIds.join(", ")}. Wait for them with wait_agent, or interrupt them before collecting their terminal result.`
312
+ : "All children are terminal, but their results have not been collected.",
313
+ `Call wait_agent with agent_ids [${unresolvedIds.map((id) => `"${id}"`).join(", ")}] and condition "all" before finishing.`,
314
+ ].join("\n");
315
+ }
173
316
  async interruptAll() {
174
317
  await Promise.allSettled([...this.workers.values()]
175
318
  .filter((worker) => this.isActive(worker))
176
- .map((worker) => worker.state === "starting" ? this.close(worker) : this.interrupt(worker.agent_id)));
319
+ .map((worker) => worker.state === "starting" ? this.close(worker) : this.interrupt(worker.agent_id, false)));
177
320
  }
178
321
  async shutdownAll() {
179
- if (this.shuttingDown)
180
- return;
181
- this.shuttingDown = true;
182
- await Promise.allSettled([...this.workers.values()].map((worker) => this.close(worker)));
322
+ if (!this.shutdownPromise) {
323
+ this.shuttingDown = true;
324
+ this.shutdownPromise = Promise.allSettled([...this.workers.values()].map((worker) => this.close(worker, false, true))).then(() => undefined);
325
+ }
326
+ await this.shutdownPromise;
183
327
  }
184
328
  /** Synchronous process-exit fallback: terminate detached process groups immediately. */
185
329
  shutdownAllNow() {
@@ -187,6 +331,100 @@ export class SubAgentManager {
187
331
  for (const worker of this.workers.values())
188
332
  this.kill(worker);
189
333
  }
334
+ markCollected(agentId) {
335
+ const worker = this.workers.get(agentId);
336
+ if (worker) {
337
+ worker.collected = true;
338
+ worker.updated_at = Date.now();
339
+ this.publish(worker);
340
+ return;
341
+ }
342
+ const snapshot = this.snapshots.get(agentId);
343
+ if (!snapshot)
344
+ return;
345
+ const collected = { ...snapshot, collected: true, updated_at: Date.now() };
346
+ this.snapshots.set(agentId, collected);
347
+ this.options.onState?.(collected);
348
+ for (const listener of this.listeners)
349
+ listener(collected);
350
+ this.queuePersist();
351
+ }
352
+ spawnWorkerProcess() {
353
+ return spawn(process.execPath, [this.options.workerEntry ?? resolveSubAgentCliEntry(), "--subagent-worker"], {
354
+ cwd: this.options.cwd,
355
+ stdio: ["pipe", "pipe", "pipe"],
356
+ env: childSubAgentEnv(),
357
+ detached: process.platform !== "win32",
358
+ });
359
+ }
360
+ async respawnRecovered(snapshot) {
361
+ if (!snapshot.child_session_path) {
362
+ throw new Error(`Agent ${snapshot.agent_id} was reaped and has no recoverable child session`);
363
+ }
364
+ const agentDef = snapshot.agent_name
365
+ ? this.options.agents.find((candidate) => candidate.name === snapshot.agent_name)
366
+ : undefined;
367
+ const provider = snapshot.provider ?? this.options.getProvider();
368
+ const model = snapshot.model ?? this.options.getModel();
369
+ const parentModel = this.options.getModel();
370
+ const childSessionPath = this.assertChildSessionPath(snapshot.child_session_path);
371
+ const child = this.spawnWorkerProcess();
372
+ const worker = {
373
+ ...snapshot,
374
+ state: "starting",
375
+ updated_at: Date.now(),
376
+ current_activity: undefined,
377
+ output: undefined,
378
+ error: undefined,
379
+ collected: false,
380
+ recovered: false,
381
+ process: child,
382
+ requests: new Map(),
383
+ requestSequence: 0,
384
+ stderr: "",
385
+ taskOutput: "",
386
+ turnResolvers: new Set(),
387
+ };
388
+ this.workers.set(worker.agent_id, worker);
389
+ this.publish(worker);
390
+ this.attach(worker);
391
+ await this.waitForPersistence();
392
+ try {
393
+ const initialized = await this.request(worker, "initialize", {
394
+ options: {
395
+ provider,
396
+ model,
397
+ fallbackModel: model === parentModel ? undefined : parentModel,
398
+ cwd: this.options.cwd,
399
+ baseUrl: this.options.getBaseUrl?.(),
400
+ systemPrompt: agentDef?.systemPrompt,
401
+ thinkingLevel: childThinkingLevel(this.options.getThinkingLevel()),
402
+ allowedTools: agentDef?.tools.length ? agentDef.tools : undefined,
403
+ promptCacheKey: subAgentCacheKey(this.options.getCacheKey?.(), model, agentDef?.name ?? "default"),
404
+ sessionRootDir: this.sessionRootDir,
405
+ childSessionPath,
406
+ },
407
+ });
408
+ if (typeof initialized.child_session_id === "string") {
409
+ worker.child_session_id = initialized.child_session_id;
410
+ }
411
+ if (typeof initialized.child_session_path === "string") {
412
+ worker.child_session_path = this.assertChildSessionPath(initialized.child_session_path);
413
+ }
414
+ if (typeof initialized.model === "string")
415
+ worker.model = initialized.model;
416
+ worker.state = snapshot.state;
417
+ worker.updated_at = Date.now();
418
+ this.publish(worker);
419
+ await this.waitForPersistence();
420
+ return worker;
421
+ }
422
+ catch (error) {
423
+ this.fail(worker, error);
424
+ await this.waitForPersistence();
425
+ throw error;
426
+ }
427
+ }
190
428
  attach(worker) {
191
429
  const lines = createInterface({ input: worker.process.stdout });
192
430
  lines.on("line", (line) => {
@@ -242,7 +480,8 @@ export class SubAgentManager {
242
480
  worker.token_usage.output += usage?.outputTokens ?? 0;
243
481
  }
244
482
  worker.updated_at = Date.now();
245
- this.publish(worker);
483
+ const durableProgress = event === "tool_call_start" || event === "turn_end";
484
+ this.publish(worker, durableProgress);
246
485
  return;
247
486
  }
248
487
  if (frame.type === "turn_complete") {
@@ -254,6 +493,8 @@ export class SubAgentManager {
254
493
  : "failed";
255
494
  worker.output = boundSubAgentOutput(String(frame.output ?? worker.taskOutput));
256
495
  worker.error = frame.error ? String(frame.error) : undefined;
496
+ if (typeof frame.model === "string")
497
+ worker.model = frame.model;
257
498
  worker.current_activity = undefined;
258
499
  worker.updated_at = Date.now();
259
500
  this.publish(worker);
@@ -280,7 +521,7 @@ export class SubAgentManager {
280
521
  worker.turnResolvers.add(resolve);
281
522
  });
282
523
  }
283
- publish(worker) {
524
+ publish(worker, persist = true) {
284
525
  const snapshot = this.snapshot(worker);
285
526
  this.snapshots.delete(worker.agent_id);
286
527
  this.snapshots.set(worker.agent_id, snapshot);
@@ -289,9 +530,65 @@ export class SubAgentManager {
289
530
  this.options.onState?.(snapshot);
290
531
  for (const listener of this.listeners)
291
532
  listener(snapshot);
533
+ if (persist)
534
+ this.queuePersist();
292
535
  }
293
536
  snapshot(worker) {
294
- return { ...worker, elapsed_ms: this.elapsed(worker), token_usage: { ...worker.token_usage } };
537
+ return {
538
+ agent_id: worker.agent_id,
539
+ task_name: worker.task_name,
540
+ state: worker.state,
541
+ started_at: worker.started_at,
542
+ updated_at: worker.updated_at,
543
+ elapsed_ms: this.elapsed(worker),
544
+ current_activity: worker.current_activity,
545
+ turn_count: worker.turn_count,
546
+ tool_use_count: worker.tool_use_count,
547
+ token_usage: { ...worker.token_usage },
548
+ output: worker.output,
549
+ error: worker.error,
550
+ agent_name: worker.agent_name,
551
+ provider: worker.provider,
552
+ model: worker.model,
553
+ child_session_id: worker.child_session_id,
554
+ child_session_path: worker.child_session_path,
555
+ collected: worker.collected,
556
+ recovered: worker.recovered,
557
+ };
558
+ }
559
+ queuePersist() {
560
+ if (!this.parentSessionId)
561
+ return;
562
+ this.persistPending = true;
563
+ if (this.persistScheduled)
564
+ return;
565
+ this.persistScheduled = true;
566
+ this.persistQueue = this.persistQueue
567
+ .catch(() => { })
568
+ .then(async () => {
569
+ while (this.persistPending) {
570
+ this.persistPending = false;
571
+ const parentSessionId = this.parentSessionId;
572
+ if (!parentSessionId)
573
+ continue;
574
+ const records = [...this.snapshots.values()].map((snapshot) => ({
575
+ ...snapshot,
576
+ token_usage: { ...snapshot.token_usage },
577
+ }));
578
+ await this.store.save(this.options.cwd, parentSessionId, records);
579
+ }
580
+ })
581
+ .catch((error) => {
582
+ this.persistPending = false;
583
+ log("WARN", "subagent", "Failed to persist subagent state", {
584
+ error: error instanceof Error ? error.message : String(error),
585
+ });
586
+ })
587
+ .finally(() => {
588
+ this.persistScheduled = false;
589
+ if (this.persistPending)
590
+ this.queuePersist();
591
+ });
295
592
  }
296
593
  elapsed(snapshot) {
297
594
  return ((this.isTerminal(snapshot.state) ? snapshot.updated_at : Date.now()) - snapshot.started_at);
@@ -303,7 +600,11 @@ export class SubAgentManager {
303
600
  return worker.state === "starting" || worker.state === "running";
304
601
  }
305
602
  isTerminal(state) {
306
- return (state === "completed" || state === "failed" || state === "interrupted" || state === "closed");
603
+ return (state === "completed" ||
604
+ state === "failed" ||
605
+ state === "interrupted" ||
606
+ state === "closed" ||
607
+ state === "reaped");
307
608
  }
308
609
  requireWorker(agentId) {
309
610
  const worker = this.workers.get(agentId);
@@ -315,6 +616,14 @@ export class SubAgentManager {
315
616
  if (this.shuttingDown)
316
617
  throw new Error("Subagent manager is shutting down");
317
618
  }
619
+ assertChildSessionPath(candidate) {
620
+ const root = path.resolve(this.sessionRootDir);
621
+ const resolved = path.resolve(candidate);
622
+ if (!resolved.startsWith(`${root}${path.sep}`) || path.extname(resolved) !== ".jsonl") {
623
+ throw new Error("Recovered child session path is outside the subagent session root");
624
+ }
625
+ return resolved;
626
+ }
318
627
  createId() {
319
628
  let id;
320
629
  do
@@ -333,7 +642,7 @@ export class SubAgentManager {
333
642
  .filter((worker) => this.isTerminal(worker.state))
334
643
  .sort((a, b) => a.updated_at - b.updated_at);
335
644
  while (idle.length > RETAINED_WORKER_LIMIT)
336
- void this.close(idle.shift());
645
+ void this.close(idle.shift(), true);
337
646
  }
338
647
  fail(worker, error, kill = true) {
339
648
  if (this.isTerminal(worker.state))
@@ -352,7 +661,7 @@ export class SubAgentManager {
352
661
  if (kill)
353
662
  this.kill(worker);
354
663
  }
355
- async close(worker) {
664
+ async close(worker, reaped = false, preserveTerminal = false) {
356
665
  clearTimeout(worker.idleTimer);
357
666
  if (worker.process.stdin?.writable) {
358
667
  await Promise.race([
@@ -368,7 +677,10 @@ export class SubAgentManager {
368
677
  for (const resolve of worker.turnResolvers)
369
678
  resolve();
370
679
  worker.turnResolvers.clear();
371
- worker.state = "closed";
680
+ if (reaped)
681
+ worker.state = "reaped";
682
+ else if (!preserveTerminal || !this.isTerminal(worker.state))
683
+ worker.state = "closed";
372
684
  worker.updated_at = Date.now();
373
685
  this.publish(worker);
374
686
  this.workers.delete(worker.agent_id);