@bastani/atomic 0.9.5-alpha.7 → 0.9.5-alpha.8

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 (177) hide show
  1. package/CHANGELOG.md +17 -2
  2. package/dist/builtin/cursor/package.json +2 -2
  3. package/dist/builtin/intercom/CHANGELOG.md +17 -0
  4. package/dist/builtin/intercom/README.md +27 -21
  5. package/dist/builtin/intercom/broker/broker.ts +3 -6
  6. package/dist/builtin/intercom/broker/paths.ts +42 -5
  7. package/dist/builtin/intercom/broker/spawn.ts +78 -10
  8. package/dist/builtin/intercom/config.ts +6 -3
  9. package/dist/builtin/intercom/contact-supervisor-tool.ts +6 -4
  10. package/dist/builtin/intercom/index-heavy.ts +1 -1
  11. package/dist/builtin/intercom/index.ts +162 -130
  12. package/dist/builtin/intercom/intercom-tool.ts +9 -3
  13. package/dist/builtin/intercom/package.json +10 -1
  14. package/dist/builtin/intercom/result-renderers.ts +1 -1
  15. package/dist/builtin/intercom/ui/compose.ts +2 -2
  16. package/dist/builtin/intercom/ui/inline-message.ts +2 -2
  17. package/dist/builtin/intercom/ui/session-list.ts +2 -2
  18. package/dist/builtin/mcp/package.json +1 -1
  19. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  20. package/dist/builtin/subagents/package.json +1 -1
  21. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +15 -48
  22. package/dist/builtin/subagents/src/tui/render-layout.ts +9 -0
  23. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +27 -25
  24. package/dist/builtin/subagents/src/tui/render-widget.ts +46 -69
  25. package/dist/builtin/subagents/src/tui/render.ts +1 -1
  26. package/dist/builtin/web-access/package.json +1 -1
  27. package/dist/builtin/workflows/CHANGELOG.md +11 -0
  28. package/dist/builtin/workflows/README.md +3 -1
  29. package/dist/builtin/workflows/builtin/goal-artifacts.ts +3 -1
  30. package/dist/builtin/workflows/builtin/goal-prompts.ts +23 -2
  31. package/dist/builtin/workflows/builtin/goal-reducer.ts +21 -0
  32. package/dist/builtin/workflows/builtin/goal-review.ts +60 -6
  33. package/dist/builtin/workflows/builtin/goal-runner.ts +32 -21
  34. package/dist/builtin/workflows/builtin/goal-types.ts +7 -1
  35. package/dist/builtin/workflows/builtin/ralph-core.ts +52 -4
  36. package/dist/builtin/workflows/builtin/ralph-review-gate.ts +10 -3
  37. package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +23 -2
  38. package/dist/builtin/workflows/builtin/ralph-runner.ts +38 -16
  39. package/dist/builtin/workflows/builtin/review-convergence.ts +111 -0
  40. package/dist/builtin/workflows/package.json +1 -1
  41. package/dist/builtin/workflows/skills/create-spec/SKILL.md +2 -0
  42. package/dist/builtin/workflows/src/durable/child-primitive.ts +12 -8
  43. package/dist/builtin/workflows/src/durable/dbos-backend.ts +47 -2
  44. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +28 -0
  45. package/dist/builtin/workflows/src/durable/stage-primitive.ts +165 -27
  46. package/dist/builtin/workflows/src/durable/types.ts +14 -1
  47. package/dist/builtin/workflows/src/engine/run.ts +12 -13
  48. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +2 -0
  49. package/dist/builtin/workflows/src/runs/foreground/executor-continuation.ts +13 -3
  50. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +1 -1
  51. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +18 -19
  52. package/dist/builtin/workflows/src/runs/foreground/stage-runner-unresolved-overflow.ts +38 -0
  53. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +18 -1
  54. package/dist/builtin/workflows/src/shared/persistence-restore.ts +23 -5
  55. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
  56. package/dist/bun/internal-intercom-broker.d.ts +6 -0
  57. package/dist/bun/internal-intercom-broker.d.ts.map +1 -0
  58. package/dist/bun/internal-intercom-broker.js +39 -0
  59. package/dist/bun/internal-intercom-broker.js.map +1 -0
  60. package/dist/bun/split-loader.d.ts.map +1 -1
  61. package/dist/bun/split-loader.js +21 -8
  62. package/dist/bun/split-loader.js.map +1 -1
  63. package/dist/core/agent-session-auto-compaction.d.ts +4 -5
  64. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  65. package/dist/core/agent-session-auto-compaction.js +49 -9
  66. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  67. package/dist/core/agent-session-events.d.ts.map +1 -1
  68. package/dist/core/agent-session-events.js +3 -1
  69. package/dist/core/agent-session-events.js.map +1 -1
  70. package/dist/core/agent-session-methods.d.ts +9 -3
  71. package/dist/core/agent-session-methods.d.ts.map +1 -1
  72. package/dist/core/agent-session-methods.js.map +1 -1
  73. package/dist/core/agent-session-models.d.ts +2 -2
  74. package/dist/core/agent-session-models.d.ts.map +1 -1
  75. package/dist/core/agent-session-models.js.map +1 -1
  76. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  77. package/dist/core/agent-session-prompt.js +1 -0
  78. package/dist/core/agent-session-prompt.js.map +1 -1
  79. package/dist/core/agent-session-retry.d.ts +2 -0
  80. package/dist/core/agent-session-retry.d.ts.map +1 -1
  81. package/dist/core/agent-session-retry.js +152 -4
  82. package/dist/core/agent-session-retry.js.map +1 -1
  83. package/dist/core/agent-session-services.d.ts +1 -0
  84. package/dist/core/agent-session-services.d.ts.map +1 -1
  85. package/dist/core/agent-session-services.js +1 -0
  86. package/dist/core/agent-session-services.js.map +1 -1
  87. package/dist/core/agent-session-types.d.ts +15 -1
  88. package/dist/core/agent-session-types.d.ts.map +1 -1
  89. package/dist/core/agent-session-types.js.map +1 -1
  90. package/dist/core/agent-session.d.ts +4 -0
  91. package/dist/core/agent-session.d.ts.map +1 -1
  92. package/dist/core/agent-session.js +4 -0
  93. package/dist/core/agent-session.js.map +1 -1
  94. package/dist/core/compaction/context-compaction-runner.d.ts.map +1 -1
  95. package/dist/core/compaction/context-compaction-runner.js +36 -20
  96. package/dist/core/compaction/context-compaction-runner.js.map +1 -1
  97. package/dist/core/copilot-anthropic-sse-repair.d.ts +23 -0
  98. package/dist/core/copilot-anthropic-sse-repair.d.ts.map +1 -0
  99. package/dist/core/copilot-anthropic-sse-repair.js +340 -0
  100. package/dist/core/copilot-anthropic-sse-repair.js.map +1 -0
  101. package/dist/core/copilot-gemini-reasoning.d.ts +16 -8
  102. package/dist/core/copilot-gemini-reasoning.d.ts.map +1 -1
  103. package/dist/core/copilot-gemini-reasoning.js +27 -22
  104. package/dist/core/copilot-gemini-reasoning.js.map +1 -1
  105. package/dist/core/copilot-hosts.d.ts +12 -0
  106. package/dist/core/copilot-hosts.d.ts.map +1 -0
  107. package/dist/core/copilot-hosts.js +33 -0
  108. package/dist/core/copilot-hosts.js.map +1 -0
  109. package/dist/core/extensions/agent-events.d.ts +1 -1
  110. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  111. package/dist/core/extensions/agent-events.js.map +1 -1
  112. package/dist/core/http-dispatcher.d.ts.map +1 -1
  113. package/dist/core/http-dispatcher.js +5 -5
  114. package/dist/core/http-dispatcher.js.map +1 -1
  115. package/dist/core/sdk-types.d.ts +2 -0
  116. package/dist/core/sdk-types.d.ts.map +1 -1
  117. package/dist/core/sdk-types.js.map +1 -1
  118. package/dist/core/sdk.d.ts.map +1 -1
  119. package/dist/core/sdk.js +1 -0
  120. package/dist/core/sdk.js.map +1 -1
  121. package/dist/core/settings-manager-basic-accessors.d.ts +1 -0
  122. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  123. package/dist/core/settings-manager-basic-accessors.js +6 -0
  124. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  125. package/dist/core/settings-types.d.ts +1 -0
  126. package/dist/core/settings-types.d.ts.map +1 -1
  127. package/dist/core/settings-types.js.map +1 -1
  128. package/dist/index-extensions.d.ts +1 -1
  129. package/dist/index-extensions.d.ts.map +1 -1
  130. package/dist/index-extensions.js.map +1 -1
  131. package/dist/main-deferred-startup.d.ts +12 -0
  132. package/dist/main-deferred-startup.d.ts.map +1 -1
  133. package/dist/main-deferred-startup.js +21 -0
  134. package/dist/main-deferred-startup.js.map +1 -1
  135. package/dist/main-early-input.d.ts +41 -0
  136. package/dist/main-early-input.d.ts.map +1 -0
  137. package/dist/main-early-input.js +147 -0
  138. package/dist/main-early-input.js.map +1 -0
  139. package/dist/main.d.ts +0 -6
  140. package/dist/main.d.ts.map +1 -1
  141. package/dist/main.js +19 -13
  142. package/dist/main.js.map +1 -1
  143. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  144. package/dist/modes/interactive/components/chat-session-host-events.js +15 -0
  145. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  146. package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
  147. package/dist/modes/interactive/interactive-agent-events.js +24 -0
  148. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  149. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  150. package/dist/modes/interactive/interactive-input-handling.js +279 -181
  151. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  152. package/dist/modes/interactive/interactive-mode-base.d.ts +9 -0
  153. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  154. package/dist/modes/interactive/interactive-mode-base.js +36 -0
  155. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  156. package/dist/modes/interactive/interactive-mode-surface.d.ts +4 -0
  157. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  158. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  159. package/dist/modes/interactive/interactive-mode-types.d.ts +3 -0
  160. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  161. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  162. package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
  163. package/dist/modes/interactive/interactive-render-chat.js +21 -9
  164. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  165. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  166. package/dist/modes/interactive/interactive-startup.js +6 -1
  167. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  168. package/docs/compaction.md +4 -0
  169. package/docs/json.md +3 -1
  170. package/docs/providers.md +1 -0
  171. package/docs/rpc.md +3 -1
  172. package/docs/settings.md +26 -0
  173. package/docs/terminal-setup.md +4 -0
  174. package/docs/usage.md +2 -2
  175. package/docs/workflows.md +13 -3
  176. package/npm-shrinkwrap.json +513 -23
  177. package/package.json +3 -2
@@ -1,57 +1,54 @@
1
- import type { ExtensionAPI, ExtensionContext, HandlerFn, MessageRenderer, RegisteredCommand, ToolDefinition } from "@bastani/atomic";
2
- import { Text } from "@mariozechner/pi-tui";
1
+ import type { AgentEndEvent, AgentStartEvent, ExtensionAPI, ExtensionCommandContext, ExtensionContext, ExtensionHandler, MessageRenderer, ModelSelectEvent, RegisteredCommand, SessionShutdownEvent, SessionStartEvent, ToolDefinition, ToolExecutionEndEvent, ToolExecutionStartEvent, TurnEndEvent, TurnStartEvent } from "@bastani/atomic";
2
+ import { Text } from "@earendil-works/pi-tui";
3
3
  import { Type } from "typebox";
4
4
  import { renderIntercomToolResult } from "./result-renderers.js";
5
5
 
6
6
  type CapturedCommand = Omit<RegisteredCommand, "name" | "sourceInfo">;
7
7
  type CapturedShortcut = Parameters<ExtensionAPI["registerShortcut"]>[1];
8
8
  type EventHandler = Parameters<ExtensionAPI["events"]["on"]>[1];
9
+ type EventPayload = Parameters<EventHandler>[0];
9
10
  type ToolRenderResultArgs = Parameters<NonNullable<ToolDefinition["renderResult"]>>;
11
+
12
+ type ForwardedEventMap = {
13
+ session_start: SessionStartEvent;
14
+ session_shutdown: SessionShutdownEvent;
15
+ turn_start: TurnStartEvent;
16
+ turn_end: TurnEndEvent;
17
+ agent_start: AgentStartEvent;
18
+ agent_end: AgentEndEvent;
19
+ tool_execution_start: ToolExecutionStartEvent;
20
+ tool_execution_end: ToolExecutionEndEvent;
21
+ model_select: ModelSelectEvent;
22
+ };
23
+
24
+ type LazyLifecycleEvent = keyof ForwardedEventMap;
25
+ type ForwardedHandler<K extends LazyLifecycleEvent> = ExtensionHandler<ForwardedEventMap[K]>;
26
+ type ForwardedHandlerMap = { [K in LazyLifecycleEvent]: ForwardedHandler<K>[] };
27
+ type AnyForwardedHandler = { [K in LazyLifecycleEvent]: ForwardedHandler<K> }[LazyLifecycleEvent];
28
+
10
29
  type CapturedHeavy = {
11
30
  tools: Map<string, ToolDefinition>;
12
31
  commands: Map<string, CapturedCommand>;
13
- handlers: Map<string, HandlerFn[]>;
32
+ handlers: ForwardedHandlerMap;
14
33
  shortcuts: Map<string, CapturedShortcut>;
15
34
  eventHandlers: Map<string, EventHandler[]>;
16
35
  };
17
- type LifecycleSnapshot = {
18
- event: unknown;
36
+
37
+ type LifecycleSnapshot<K extends LazyLifecycleEvent> = {
38
+ event: ForwardedEventMap[K];
19
39
  ctx: ExtensionContext;
20
40
  };
21
41
 
22
- type SessionSnapshot = LifecycleSnapshot & {
42
+ type SessionSnapshot = LifecycleSnapshot<"session_start"> & {
23
43
  generation: number;
24
44
  };
25
45
 
26
46
  type ActiveLifecycleState = {
27
- turnStart: LifecycleSnapshot | null;
28
- agentStart: LifecycleSnapshot | null;
29
- activeTools: Map<string, LifecycleSnapshot>;
30
- modelSelect: LifecycleSnapshot | null;
47
+ turnStart: LifecycleSnapshot<"turn_start"> | null;
48
+ agentStart: LifecycleSnapshot<"agent_start"> | null;
49
+ activeTools: Map<string, LifecycleSnapshot<"tool_execution_start">>;
50
+ modelSelect: LifecycleSnapshot<"model_select"> | null;
31
51
  };
32
-
33
- type LazyLifecycleEvent =
34
- | "session_start"
35
- | "session_shutdown"
36
- | "turn_start"
37
- | "turn_end"
38
- | "agent_start"
39
- | "agent_end"
40
- | "tool_execution_start"
41
- | "tool_execution_end"
42
- | "model_select";
43
-
44
- const FORWARDED_EVENTS: readonly LazyLifecycleEvent[] = [
45
- "session_start",
46
- "session_shutdown",
47
- "turn_start",
48
- "turn_end",
49
- "agent_start",
50
- "agent_end",
51
- "tool_execution_start",
52
- "tool_execution_end",
53
- "model_select",
54
- ];
55
52
  const SUBAGENT_CONTROL_INTERCOM_EVENT = "subagent:control-intercom";
56
53
  const SUBAGENT_RESULT_INTERCOM_EVENT = "subagent:result-intercom";
57
54
 
@@ -59,16 +56,67 @@ function hasSubagentIntercomEnv(): boolean {
59
56
  return Object.keys(process.env).some((key) => key.endsWith("_SUBAGENT_ORCHESTRATOR_TARGET"));
60
57
  }
61
58
 
62
- function getToolCallId(event: unknown): string | null {
63
- if (typeof event !== "object" || event === null || !("toolCallId" in event)) return null;
64
- const toolCallId = event.toolCallId;
65
- return typeof toolCallId === "string" ? toolCallId : null;
59
+ function createSyntheticSessionStartEvent(): SessionStartEvent {
60
+ return { type: "session_start", reason: "startup" };
66
61
  }
67
62
 
68
- function addHandler(captured: CapturedHeavy, event: string, handler: HandlerFn): void {
69
- const handlers = captured.handlers.get(event) ?? [];
70
- handlers.push(handler);
71
- captured.handlers.set(event, handlers);
63
+ function createForwardedHandlerMap(): ForwardedHandlerMap {
64
+ return {
65
+ session_start: [],
66
+ session_shutdown: [],
67
+ turn_start: [],
68
+ turn_end: [],
69
+ agent_start: [],
70
+ agent_end: [],
71
+ tool_execution_start: [],
72
+ tool_execution_end: [],
73
+ model_select: [],
74
+ };
75
+ }
76
+
77
+ function addHandler<K extends LazyLifecycleEvent>(captured: CapturedHeavy, event: K, handler: ForwardedHandler<K>): void {
78
+ captured.handlers[event].push(handler);
79
+ }
80
+
81
+ function captureForwardedHandler(captured: CapturedHeavy, event: "session_start", handler: ForwardedHandler<"session_start">): void;
82
+ function captureForwardedHandler(captured: CapturedHeavy, event: "session_shutdown", handler: ForwardedHandler<"session_shutdown">): void;
83
+ function captureForwardedHandler(captured: CapturedHeavy, event: "turn_start", handler: ForwardedHandler<"turn_start">): void;
84
+ function captureForwardedHandler(captured: CapturedHeavy, event: "turn_end", handler: ForwardedHandler<"turn_end">): void;
85
+ function captureForwardedHandler(captured: CapturedHeavy, event: "agent_start", handler: ForwardedHandler<"agent_start">): void;
86
+ function captureForwardedHandler(captured: CapturedHeavy, event: "agent_end", handler: ForwardedHandler<"agent_end">): void;
87
+ function captureForwardedHandler(captured: CapturedHeavy, event: "tool_execution_start", handler: ForwardedHandler<"tool_execution_start">): void;
88
+ function captureForwardedHandler(captured: CapturedHeavy, event: "tool_execution_end", handler: ForwardedHandler<"tool_execution_end">): void;
89
+ function captureForwardedHandler(captured: CapturedHeavy, event: "model_select", handler: ForwardedHandler<"model_select">): void;
90
+ function captureForwardedHandler(captured: CapturedHeavy, event: LazyLifecycleEvent, handler: AnyForwardedHandler): void;
91
+ function captureForwardedHandler(captured: CapturedHeavy, event: LazyLifecycleEvent, handler: AnyForwardedHandler): void {
92
+ switch (event) {
93
+ case "session_start":
94
+ addHandler(captured, event, handler as ForwardedHandler<"session_start">);
95
+ return;
96
+ case "session_shutdown":
97
+ addHandler(captured, event, handler as ForwardedHandler<"session_shutdown">);
98
+ return;
99
+ case "turn_start":
100
+ addHandler(captured, event, handler as ForwardedHandler<"turn_start">);
101
+ return;
102
+ case "turn_end":
103
+ addHandler(captured, event, handler as ForwardedHandler<"turn_end">);
104
+ return;
105
+ case "agent_start":
106
+ addHandler(captured, event, handler as ForwardedHandler<"agent_start">);
107
+ return;
108
+ case "agent_end":
109
+ addHandler(captured, event, handler as ForwardedHandler<"agent_end">);
110
+ return;
111
+ case "tool_execution_start":
112
+ addHandler(captured, event, handler as ForwardedHandler<"tool_execution_start">);
113
+ return;
114
+ case "tool_execution_end":
115
+ addHandler(captured, event, handler as ForwardedHandler<"tool_execution_end">);
116
+ return;
117
+ case "model_select":
118
+ addHandler(captured, event, handler as ForwardedHandler<"model_select">);
119
+ }
72
120
  }
73
121
 
74
122
  function addEventHandler(captured: CapturedHeavy, event: string, handler: EventHandler): void {
@@ -77,13 +125,13 @@ function addEventHandler(captured: CapturedHeavy, event: string, handler: EventH
77
125
  captured.eventHandlers.set(event, handlers);
78
126
  }
79
127
 
80
- async function dispatchHandlers(captured: CapturedHeavy, eventName: string, event: unknown, ctx: ExtensionContext): Promise<void> {
81
- for (const handler of captured.handlers.get(eventName) ?? []) {
128
+ async function dispatchHandlers<K extends LazyLifecycleEvent>(captured: CapturedHeavy, eventName: K, event: ForwardedEventMap[K], ctx: ExtensionContext): Promise<void> {
129
+ for (const handler of captured.handlers[eventName]) {
82
130
  await handler(event, ctx);
83
131
  }
84
132
  }
85
133
 
86
- async function dispatchEventHandlers(captured: CapturedHeavy, eventName: string, payload: unknown): Promise<void> {
134
+ async function dispatchEventHandlers(captured: CapturedHeavy, eventName: string, payload: EventPayload): Promise<void> {
87
135
  for (const handler of captured.eventHandlers.get(eventName) ?? []) {
88
136
  await handler(payload);
89
137
  }
@@ -99,8 +147,8 @@ function createHeavyProxy(pi: ExtensionAPI, captured: CapturedHeavy): ExtensionA
99
147
  return (name: string, options: CapturedCommand) => captured.commands.set(name, options);
100
148
  }
101
149
  if (prop === "on") {
102
- return (event: string, handler: HandlerFn) => {
103
- addHandler(captured, event, handler);
150
+ return (event: LazyLifecycleEvent, handler: AnyForwardedHandler) => {
151
+ captureForwardedHandler(captured, event, handler);
104
152
  };
105
153
  }
106
154
  if (prop === "registerShortcut") {
@@ -136,19 +184,19 @@ async function executeHeavyTool(
136
184
  loadHeavy: (ctx?: ExtensionContext) => Promise<CapturedHeavy>,
137
185
  name: string,
138
186
  args: Parameters<NonNullable<ToolDefinition["execute"]>>,
139
- ): Promise<ReturnType<NonNullable<ToolDefinition["execute"]>>> {
187
+ ): Promise<Awaited<ReturnType<NonNullable<ToolDefinition["execute"]>>>> {
140
188
  const ctx = args[4];
141
189
  const heavy = await loadHeavy(ctx);
142
190
  const tool = heavy.tools.get(name);
143
191
  if (!tool?.execute) throw new Error(`Intercom tool implementation not found: ${name}`);
144
- return tool.execute(...args) as ReturnType<NonNullable<ToolDefinition["execute"]>>;
192
+ return await tool.execute(...args) as Awaited<ReturnType<NonNullable<ToolDefinition["execute"]>>>;
145
193
  }
146
194
 
147
- async function runHeavyCommand(loadHeavy: (ctx?: ExtensionContext) => Promise<CapturedHeavy>, args: string | undefined, ctx: ExtensionContext): Promise<void> {
195
+ async function runHeavyCommand(loadHeavy: (ctx?: ExtensionContext) => Promise<CapturedHeavy>, args: string | undefined, ctx: ExtensionCommandContext): Promise<void> {
148
196
  const heavy = await loadHeavy(ctx);
149
197
  const command = heavy.commands.get("intercom");
150
198
  if (!command) throw new Error("Intercom command implementation not found");
151
- await command.handler(args, ctx);
199
+ await command.handler(args ?? "", ctx);
152
200
  }
153
201
 
154
202
  function renderHeavyToolResult(loadedHeavy: CapturedHeavy | null, name: string, args: ToolRenderResultArgs): ReturnType<NonNullable<ToolDefinition["renderResult"]>> {
@@ -194,7 +242,7 @@ export default function intercom(pi: ExtensionAPI) {
194
242
  const captured: CapturedHeavy = {
195
243
  tools: new Map(),
196
244
  commands: new Map(),
197
- handlers: new Map(),
245
+ handlers: createForwardedHandlerMap(),
198
246
  shortcuts: new Map(),
199
247
  eventHandlers: new Map(),
200
248
  };
@@ -202,7 +250,7 @@ export default function intercom(pi: ExtensionAPI) {
202
250
  await mod.default(createHeavyProxy(pi, captured));
203
251
  loadedHeavy = captured;
204
252
  if (!sessionSnapshot && ctx) {
205
- sessionSnapshot = { event: {}, ctx, generation: ++lifecycleGeneration };
253
+ sessionSnapshot = { event: createSyntheticSessionStartEvent(), ctx, generation: ++lifecycleGeneration };
206
254
  }
207
255
  await replaySessionStart(captured);
208
256
  return captured;
@@ -210,88 +258,72 @@ export default function intercom(pi: ExtensionAPI) {
210
258
  }
211
259
  const heavy = await heavyPromise;
212
260
  if (!sessionSnapshot && ctx) {
213
- sessionSnapshot = { event: {}, ctx, generation: ++lifecycleGeneration };
261
+ sessionSnapshot = { event: createSyntheticSessionStartEvent(), ctx, generation: ++lifecycleGeneration };
214
262
  await replaySessionStart(heavy);
215
263
  }
216
264
  return heavy;
217
265
  }
218
266
 
219
- for (const eventName of FORWARDED_EVENTS) {
220
- switch (eventName) {
221
- case "session_start":
222
- pi.on("session_start", async (event, ctx) => {
223
- const generation = ++lifecycleGeneration;
224
- sessionSnapshot = { event, ctx, generation };
225
- if (loadedHeavy) {
226
- replayedGeneration = generation;
227
- await dispatchHandlers(loadedHeavy, "session_start", event, ctx);
228
- }
229
- });
230
- break;
231
- case "session_shutdown":
232
- pi.on("session_shutdown", async (event, ctx) => {
233
- ++lifecycleGeneration;
234
- activeLifecycle.turnStart = null;
235
- activeLifecycle.agentStart = null;
236
- activeLifecycle.activeTools.clear();
237
- activeLifecycle.modelSelect = null;
238
- if (loadedHeavy) {
239
- await dispatchHandlers(loadedHeavy, "session_shutdown", event, ctx);
240
- }
241
- sessionSnapshot = null;
242
- replayedGeneration = lifecycleGeneration;
243
- });
244
- break;
245
- case "turn_start":
246
- pi.on("turn_start", async (event, ctx) => {
247
- activeLifecycle.turnStart = { event, ctx };
248
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "turn_start", event, ctx);
249
- });
250
- break;
251
- case "turn_end":
252
- pi.on("turn_end", async (event, ctx) => {
253
- activeLifecycle.turnStart = null;
254
- activeLifecycle.agentStart = null;
255
- activeLifecycle.activeTools.clear();
256
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "turn_end", event, ctx);
257
- });
258
- break;
259
- case "agent_start":
260
- pi.on("agent_start", async (event, ctx) => {
261
- activeLifecycle.agentStart = { event, ctx };
262
- activeLifecycle.activeTools.clear();
263
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "agent_start", event, ctx);
264
- });
265
- break;
266
- case "agent_end":
267
- pi.on("agent_end", async (event, ctx) => {
268
- activeLifecycle.agentStart = null;
269
- activeLifecycle.activeTools.clear();
270
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "agent_end", event, ctx);
271
- });
272
- break;
273
- case "tool_execution_start":
274
- pi.on("tool_execution_start", async (event, ctx) => {
275
- const toolCallId = getToolCallId(event);
276
- if (toolCallId) activeLifecycle.activeTools.set(toolCallId, { event, ctx });
277
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "tool_execution_start", event, ctx);
278
- });
279
- break;
280
- case "tool_execution_end":
281
- pi.on("tool_execution_end", async (event, ctx) => {
282
- const toolCallId = getToolCallId(event);
283
- if (toolCallId) activeLifecycle.activeTools.delete(toolCallId);
284
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "tool_execution_end", event, ctx);
285
- });
286
- break;
287
- case "model_select":
288
- pi.on("model_select", async (event, ctx) => {
289
- activeLifecycle.modelSelect = { event, ctx };
290
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "model_select", event, ctx);
291
- });
292
- break;
267
+ pi.on("session_start", async (event, ctx) => {
268
+ const generation = ++lifecycleGeneration;
269
+ sessionSnapshot = { event, ctx, generation };
270
+ if (loadedHeavy) {
271
+ replayedGeneration = generation;
272
+ await dispatchHandlers(loadedHeavy, "session_start", event, ctx);
293
273
  }
294
- }
274
+ });
275
+
276
+ pi.on("session_shutdown", async (event, ctx) => {
277
+ ++lifecycleGeneration;
278
+ activeLifecycle.turnStart = null;
279
+ activeLifecycle.agentStart = null;
280
+ activeLifecycle.activeTools.clear();
281
+ activeLifecycle.modelSelect = null;
282
+ if (loadedHeavy) {
283
+ await dispatchHandlers(loadedHeavy, "session_shutdown", event, ctx);
284
+ }
285
+ sessionSnapshot = null;
286
+ replayedGeneration = lifecycleGeneration;
287
+ });
288
+
289
+ pi.on("turn_start", async (event, ctx) => {
290
+ activeLifecycle.turnStart = { event, ctx };
291
+ if (loadedHeavy) await dispatchHandlers(loadedHeavy, "turn_start", event, ctx);
292
+ });
293
+
294
+ pi.on("turn_end", async (event, ctx) => {
295
+ activeLifecycle.turnStart = null;
296
+ activeLifecycle.agentStart = null;
297
+ activeLifecycle.activeTools.clear();
298
+ if (loadedHeavy) await dispatchHandlers(loadedHeavy, "turn_end", event, ctx);
299
+ });
300
+
301
+ pi.on("agent_start", async (event, ctx) => {
302
+ activeLifecycle.agentStart = { event, ctx };
303
+ activeLifecycle.activeTools.clear();
304
+ if (loadedHeavy) await dispatchHandlers(loadedHeavy, "agent_start", event, ctx);
305
+ });
306
+
307
+ pi.on("agent_end", async (event, ctx) => {
308
+ activeLifecycle.agentStart = null;
309
+ activeLifecycle.activeTools.clear();
310
+ if (loadedHeavy) await dispatchHandlers(loadedHeavy, "agent_end", event, ctx);
311
+ });
312
+
313
+ pi.on("tool_execution_start", async (event, ctx) => {
314
+ activeLifecycle.activeTools.set(event.toolCallId, { event, ctx });
315
+ if (loadedHeavy) await dispatchHandlers(loadedHeavy, "tool_execution_start", event, ctx);
316
+ });
317
+
318
+ pi.on("tool_execution_end", async (event, ctx) => {
319
+ activeLifecycle.activeTools.delete(event.toolCallId);
320
+ if (loadedHeavy) await dispatchHandlers(loadedHeavy, "tool_execution_end", event, ctx);
321
+ });
322
+
323
+ pi.on("model_select", async (event, ctx) => {
324
+ activeLifecycle.modelSelect = { event, ctx };
325
+ if (loadedHeavy) await dispatchHandlers(loadedHeavy, "model_select", event, ctx);
326
+ });
295
327
 
296
328
  pi.registerShortcut("alt+m", {
297
329
  description: "Open session intercom overlay",
@@ -322,7 +354,7 @@ export default function intercom(pi: ExtensionAPI) {
322
354
  pi.registerTool({
323
355
  name: "intercom",
324
356
  label: "Intercom",
325
- description: `Send a message to another pi session running on this machine.
357
+ description: `Send a message to another local agent session running on this machine.
326
358
  Use this to communicate findings, request help, or coordinate work with other sessions.
327
359
 
328
360
  Usage:
@@ -332,7 +364,7 @@ Usage:
332
364
  intercom({ action: "reply", message: "..." }) → Reply to the active/single pending ask
333
365
  intercom({ action: "pending" }) → List unresolved inbound asks
334
366
  intercom({ action: "status" }) → Show connection status`,
335
- promptSnippet: "Use to coordinate with other local pi sessions: list peers, send updates, ask for help, or check intercom connectivity.",
367
+ promptSnippet: "Use to coordinate with other local agent sessions: list peers, send updates, ask for help, or check intercom connectivity.",
336
368
  parameters: Type.Object({
337
369
  action: Type.String({ description: "Action: 'list', 'send', 'ask', 'reply', 'pending', or 'status'" }),
338
370
  to: Type.Optional(Type.String({ description: "Target session name or ID (for 'send', 'ask', or disambiguating 'reply')" })),
@@ -1,7 +1,7 @@
1
1
  import type { ExtensionAPI } from "@bastani/atomic";
2
2
  import { randomUUID } from "crypto";
3
3
  import { Type } from "typebox";
4
- import { Text } from "@mariozechner/pi-tui";
4
+ import { Text } from "@earendil-works/pi-tui";
5
5
  import type { IntercomClient } from "./broker/client.ts";
6
6
  import type { Message } from "./types.ts";
7
7
  import { renderIntercomResult } from "./result-renderers.js";
@@ -30,7 +30,7 @@ export function registerIntercomTool(pi: ExtensionAPI, deps: IntercomToolDeps):
30
30
  pi.registerTool({
31
31
  name: "intercom",
32
32
  label: "Intercom",
33
- description: `Send a message to another pi session running on this machine.
33
+ description: `Send a message to another local agent session running on this machine.
34
34
  Use this to communicate findings, request help, or coordinate work with other sessions.
35
35
 
36
36
  Usage:
@@ -41,7 +41,7 @@ Usage:
41
41
  intercom({ action: "pending" }) → List unresolved inbound asks
42
42
  intercom({ action: "status" }) → Show connection status`,
43
43
  promptSnippet:
44
- "Use to coordinate with other local pi sessions: list peers, send updates, ask for help, or check intercom connectivity.",
44
+ "Use to coordinate with other local agent sessions: list peers, send updates, ask for help, or check intercom connectivity.",
45
45
 
46
46
  parameters: Type.Object({
47
47
  action: Type.String({
@@ -104,6 +104,7 @@ Usage:
104
104
  return {
105
105
  content: [{ type: "text", text: `${currentSection}\n\n${otherSection}` }],
106
106
  isError: false,
107
+ details: {},
107
108
  };
108
109
  } catch (error) {
109
110
  return {
@@ -141,6 +142,7 @@ Usage:
141
142
  return {
142
143
  content: [{ type: "text", text: "Message cancelled by user" }],
143
144
  isError: false,
145
+ details: {},
144
146
  };
145
147
  }
146
148
  }
@@ -268,6 +270,7 @@ Usage:
268
270
  return {
269
271
  content: [{ type: "text", text: `**Reply from ${to}:**\n${replyText}${replyAttachments}` }],
270
272
  isError: false,
273
+ details: {},
271
274
  };
272
275
  } catch (error) {
273
276
  rejectReplyWaiter(toError(error));
@@ -343,6 +346,7 @@ Usage:
343
346
  return {
344
347
  content: [{ type: "text", text: "No unresolved inbound asks." }],
345
348
  isError: false,
349
+ details: {},
346
350
  };
347
351
  }
348
352
 
@@ -355,6 +359,7 @@ Usage:
355
359
  return {
356
360
  content: [{ type: "text", text: `**Pending asks:**\n${lines.join("\n")}` }],
357
361
  isError: false,
362
+ details: {},
358
363
  };
359
364
  }
360
365
 
@@ -368,6 +373,7 @@ Usage:
368
373
  text: `**Intercom Status:**\nConnected: Yes\nSession ID: ${mySessionId}\nActive sessions: ${sessions.length}`,
369
374
  }],
370
375
  isError: false,
376
+ details: {},
371
377
  };
372
378
  } catch (error) {
373
379
  return {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/intercom",
3
- "version": "0.9.5-alpha.7",
3
+ "version": "0.9.5-alpha.8",
4
4
  "private": true,
5
5
  "description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
6
6
  "contributors": [
@@ -29,6 +29,14 @@
29
29
  "CHANGELOG.md",
30
30
  "LICENSE"
31
31
  ],
32
+ "atomic": {
33
+ "extensions": [
34
+ "./index.ts"
35
+ ],
36
+ "skills": [
37
+ "./skills"
38
+ ]
39
+ },
32
40
  "pi": {
33
41
  "extensions": [
34
42
  "./index.ts"
@@ -50,6 +58,7 @@
50
58
  }
51
59
  },
52
60
  "dependencies": {
61
+ "tsx": "^4.20.6",
53
62
  "typebox": "^1.1.24"
54
63
  }
55
64
  }
@@ -1,5 +1,5 @@
1
1
  import type { ToolDefinition } from "@bastani/atomic";
2
- import { Text } from "@mariozechner/pi-tui";
2
+ import { Text } from "@earendil-works/pi-tui";
3
3
 
4
4
  type ToolResultRenderer = NonNullable<ToolDefinition["renderResult"]>;
5
5
  type ToolRenderResultArgs = Parameters<ToolResultRenderer>;
@@ -1,5 +1,5 @@
1
- import type { Component, TUI } from "@mariozechner/pi-tui";
2
- import { truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
1
+ import type { Component, TUI } from "@earendil-works/pi-tui";
2
+ import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
3
3
  import type { KeybindingsManager, Theme } from "@bastani/atomic";
4
4
  import type { IntercomClient } from "../broker/client.js";
5
5
  import type { SessionInfo } from "../types.js";
@@ -1,5 +1,5 @@
1
- import type { Component } from "@mariozechner/pi-tui";
2
- import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@mariozechner/pi-tui";
1
+ import type { Component } from "@earendil-works/pi-tui";
2
+ import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
3
3
  import type { Theme } from "@bastani/atomic";
4
4
  import type { SessionInfo, Message } from "../types.js";
5
5
 
@@ -1,5 +1,5 @@
1
- import type { Component } from "@mariozechner/pi-tui";
2
- import { truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
1
+ import type { Component } from "@earendil-works/pi-tui";
2
+ import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
3
3
  import type { KeybindingsManager, Theme } from "@bastani/atomic";
4
4
  import type { SessionInfo } from "../types.js";
5
5
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.9.5-alpha.7",
3
+ "version": "0.9.5-alpha.8",
4
4
  "private": true,
5
5
  "description": "Atomic extension that adapts MCP (Model Context Protocol) servers into the coding agent. Fork of: https://github.com/nicobailon/pi-mcp-adapter",
6
6
  "contributors": [
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.9.5-alpha.8] - 2026-07-08
6
+
7
+ ### Fixed
8
+
9
+ - Updated async/background subagent status widgets so running job, parallel child-agent, chain-step, and nested child rows reuse the same foreground pulsing-dot glyph treatment instead of braille spinner glyphs, while preserving counts, metadata, live-detail hints, and output paths.
10
+
5
11
  ## [0.9.5-alpha.5] - 2026-07-06
6
12
 
7
13
  ### Changed
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/subagents",
3
- "version": "0.9.5-alpha.7",
3
+ "version": "0.9.5-alpha.8",
4
4
  "private": true,
5
5
  "description": "Atomic extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification. Fork of: https://github.com/nicobailon/pi-subagents",
6
6
  "contributors": [