pi-subagent-in-memory 0.1.5 โ†’ 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -40,12 +40,20 @@ Each running subagent is displayed as a colored card widget above the editor:
40
40
 
41
41
  ### ๐Ÿ” Subagent Detail Overlay (`Ctrl+N`)
42
42
 
43
- Press **Ctrl+1** through **Ctrl+9** to open a detail popup for the corresponding subagent:
43
+ Press **Ctrl+1** through **Ctrl+9** to open a detail popup for the **N-th visible** subagent card (1 = leftmost/topmost in the current window):
44
44
 
45
45
  - **Prompt** โ€” Full prompt text with word wrapping (up to 5 lines)
46
46
  - **Messages** โ€” Live-updating stream of the subagent's activity (text output, tool calls, status changes), always showing the latest 5 lines
47
47
  - Press the same **Ctrl+N** shortcut or **Escape** to close the overlay
48
48
 
49
+ ### ๐Ÿ“‘ Paging Through Cards (`Ctrl+Alt+โ†/โ†’`)
50
+
51
+ When more subagents have been spawned than fit in the visible window (see `/saim-set-max-tui-overlays` below):
52
+
53
+ - **Ctrl+Alt+โ†** scrolls back to older subagent cards
54
+ - **Ctrl+Alt+โ†’** scrolls forward to newer subagent cards
55
+ - A `subagents Xโ€“Y of N (Ctrl+Alt+โ†/โ†’ to page)` hint is displayed above the cards whenever paging is active
56
+
49
57
  ### ๐Ÿ“ JSONL Session Logging
50
58
 
51
59
  Every subagent session is logged to disk for debugging and auditing:
@@ -71,9 +79,17 @@ The JSONL log includes:
71
79
 
72
80
  Subagents can spawn their own subagents. All nested cards render in the main agent's widget โ€” they share the same module-level state regardless of nesting depth. This is achieved by passing the `subagent_create` tool directly as an `AgentTool` to child sessions.
73
81
 
74
- ### ๐Ÿงน `/in-memory-clear-widgets` Slash Command
82
+ ### ๐ŸŽ›๏ธ TUI Overlay Slash Commands
83
+
84
+ | Command | Description |
85
+ |---------|-------------|
86
+ | `/saim-toggle-overlay [on\|off\|toggle]` | Enable, disable, or toggle the subagent TUI overlay. When disabled, **no card widget is mounted even while subagents are actively running** โ€” they continue executing silently in the background. |
87
+ | `/saim-set-max-tui-overlays <N>` | Set the maximum number of cards displayed at once (1โ€“9, default 3). Older cards remain accessible via **Ctrl+Alt+โ†/โ†’**. |
88
+ | `/saim-clear-tui-overlay` | Clear all subagent cards from the TUI and close any open detail overlay. |
89
+
90
+ ### ๐Ÿšฉ `--saim-no-tui` CLI Flag
75
91
 
76
- Type `/in-memory-clear-widgets` in the pi prompt to clear all subagent card widgets from the TUI. Useful after a batch of subagent runs when you want a clean view.
92
+ Start `pi` with `--saim-no-tui` to launch with the subagent overlay disabled (equivalent to running `/saim-toggle-overlay off` immediately on startup). Subagents still run normally โ€” only the TUI cards are hidden.
77
93
 
78
94
  ## Install
79
95
 
@@ -92,7 +108,7 @@ pi remove npm:pi-subagent-in-memory
92
108
  After installing, start pi and check:
93
109
 
94
110
  1. The `subagent_create` tool should appear in the tool list
95
- 2. The `/in-memory-clear-widgets` command should be available (type `/` to see commands)
111
+ 2. The `/saim-toggle-overlay`, `/saim-set-max-tui-overlays`, and `/saim-clear-tui-overlay` commands should be available (type `/` to see commands)
96
112
  3. Ask the agent to "run a subagent to list files" โ€” you should see a card widget appear
97
113
 
98
114
  ## Usage Examples
@@ -118,7 +134,7 @@ Once installed, the LLM will discover the `subagent_create` tool from its schema
118
134
 
119
135
  ## How It Works
120
136
 
121
- 1. **Tool registration** โ€” On load, registers `subagent_create` as a tool and `/in-memory-clear-widgets` as a command. No system prompt modifications.
137
+ 1. **Tool registration** โ€” On load, registers `subagent_create` as a tool plus the `/saim-*` commands and `--saim-no-tui` flag. No system prompt modifications.
122
138
  2. **Session creation** โ€” When the LLM calls `subagent_create`, a new `createAgentSession` is created in-process with its own model, auth, and coding tools (read, write, edit, bash, grep, find, ls).
123
139
  3. **Event streaming** โ€” All subagent events (text deltas, tool calls, completions) are forwarded as `tool_execution_update` events to the parent agent and logged to JSONL.
124
140
  4. **Widget rendering** โ€” A TUI widget renders card(s) above the editor, updated on every event.
@@ -13,9 +13,15 @@
13
13
  * - Live TUI card widgets showing subagent status and output
14
14
  * - JSONL event logging to ~/.pi/subagent-in-memory/<sessionId>/
15
15
  * - Nested subagent support (subagents can spawn subagents)
16
- * - /in-memory-clear-widgets slash command to remove widget cards
16
+ * - Slash commands to control TUI overlay:
17
+ * /saim-toggle-overlay [on|off] โ€” enable/disable rendering
18
+ * /saim-set-max-tui-overlays <N> โ€” limit visible cards (1-9)
19
+ * /saim-clear-tui-overlay โ€” clear all cards & close any overlay
17
20
  * - Multi-provider support (Anthropic, OpenAI, Google, etc.)
18
- * - Ctrl+Alt+<N> to inspect subagent prompt & live messages
21
+ * - Ctrl+<N> to inspect subagent prompt & live messages
22
+ * - Ctrl+Alt+Left / Ctrl+Alt+Right to page through cards when there are
23
+ * more subagents than the visible window allows
24
+ * - --saim-no-tui CLI flag to start with the overlay disabled
19
25
  *
20
26
  * Results are written to ./.pi/subagent-in-memory/<mainSessionId>/subagent_<N>/result.md
21
27
  * (or error.md on failure) so the calling agent gets a short pointer instead of
@@ -24,19 +30,12 @@
24
30
 
25
31
  import { Type, type Static } from "@sinclair/typebox";
26
32
  import {
27
- createAgentSession,
33
+ createAgentSessionFromServices,
34
+ createAgentSessionServices,
28
35
  SessionManager,
29
- AuthStorage,
30
- DefaultResourceLoader,
31
- getAgentDir,
32
- createCodingTools,
33
- createGrepTool,
34
- createFindTool,
35
- createLsTool,
36
36
  } from "@mariozechner/pi-coding-agent";
37
37
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
38
- import type { AgentToolResult, AgentToolUpdateCallback } from "@mariozechner/pi-coding-agent";
39
- import { resolveModel } from "./model.ts";
38
+ import type { AgentToolResult, AgentToolUpdateCallback, ToolDefinition } from "@mariozechner/pi-coding-agent";
40
39
  import { renderCard, type CardTheme } from "./tui-draw.ts";
41
40
 
42
41
  import { visibleWidth, truncateToWidth, wrapTextWithAnsi, matchesKey, Key } from "@mariozechner/pi-tui";
@@ -142,21 +141,72 @@ let widgetRenderVersion = 0;
142
141
 
143
142
  // Track open detail overlay so we can trigger re-renders
144
143
  let activeDetailTui: any = null;
144
+ let activeDetailDone: ((result: void) => void) | null = null;
145
+
146
+ // โ”€โ”€ TUI overlay controls (commands & flag) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
147
+ const DEFAULT_MAX_VISIBLE_OVERLAYS = 3;
148
+ const MAX_OVERLAYS_HARD_LIMIT = 9;
149
+ let overlayEnabled = true;
150
+ let maxVisibleOverlays = DEFAULT_MAX_VISIBLE_OVERLAYS;
151
+ // Number of cards to skip from the END of the list. 0 means "show the latest
152
+ // `maxVisibleOverlays`". Increasing windowOffset pages back into older cards.
153
+ let windowOffset = 0;
154
+
155
+ function getVisibleSubagents(): SubagentCard[] {
156
+ if (subagents.length === 0) return [];
157
+ const total = subagents.length;
158
+ const window = Math.min(maxVisibleOverlays, total);
159
+ // Clamp offset to valid range; user paging may have left it stale.
160
+ const maxOffset = Math.max(0, total - window);
161
+ if (windowOffset > maxOffset) windowOffset = maxOffset;
162
+ if (windowOffset < 0) windowOffset = 0;
163
+ const end = total - windowOffset;
164
+ const start = Math.max(0, end - window);
165
+ return subagents.slice(start, end);
166
+ }
167
+
168
+ function unmountWidget() {
169
+ if (!currentCtx) return;
170
+ if (widgetMounted) {
171
+ currentCtx.ui.setWidget("in-memory-subagent-cards", undefined);
172
+ }
173
+ widgetMounted = false;
174
+ widgetTui = null;
175
+ }
176
+
177
+ function closeActiveDetail() {
178
+ if (activeDetailDone) {
179
+ try { activeDetailDone(); } catch {}
180
+ }
181
+ activeDetailTui = null;
182
+ activeDetailDone = null;
183
+ }
145
184
 
146
185
  function renderSubagentCards(theme: any, width: number): string[] {
147
- if (subagents.length === 0) return [];
186
+ if (!overlayEnabled) return [];
187
+ const visible = getVisibleSubagents();
188
+ if (visible.length === 0) return [];
148
189
 
149
190
  // Derive cols from columnWidthPercent (all cards share the same value).
150
- const pct = subagents[subagents.length - 1].columnWidthPercent;
191
+ const pct = visible[visible.length - 1].columnWidthPercent;
151
192
  const cols = Math.min(3, Math.max(1, Math.round(100 / pct)));
152
193
  const gap = 1;
153
194
  const colWidth = Math.floor((width - gap * (cols - 1)) / cols);
154
195
  const maxContentLines = 4;
155
196
  const lines: string[] = [""];
156
197
 
157
- for (let i = 0; i < subagents.length; i += cols) {
158
- const rowCards = subagents.slice(i, i + cols).map((sa, idx) => {
159
- const cardTheme = CARD_THEMES[(i + idx) % CARD_THEMES.length];
198
+ // Page indicator if there are more cards than fit on screen
199
+ const total = subagents.length;
200
+ if (total > visible.length) {
201
+ const firstVisible = total - windowOffset - visible.length + 1;
202
+ const lastVisible = total - windowOffset;
203
+ const hint = `subagents ${firstVisible}โ€“${lastVisible} of ${total} (Ctrl+Alt+โ†/โ†’ to page)`;
204
+ lines.push(theme.fg("dim", truncateToWidth(hint, width)));
205
+ }
206
+
207
+ for (let i = 0; i < visible.length; i += cols) {
208
+ const rowCards = visible.slice(i, i + cols).map((sa, idx) => {
209
+ const cardTheme = CARD_THEMES[(sa.num - 1) % CARD_THEMES.length];
160
210
 
161
211
  const titleText = `${sa.title} [${sa.modelLabel}]`;
162
212
  const innerW = colWidth - 4;
@@ -166,8 +216,8 @@ function renderSubagentCards(theme: any, width: number): string[] {
166
216
  const trimmedLines = contentLines.map((l) =>
167
217
  visibleWidth(l) > innerW ? truncateToWidth(l, innerW - 1) + "โ€ฆ" : l
168
218
  );
169
- const visible = trimmedLines.slice(0, maxContentLines);
170
- const content = visible.join("\n") + (contentLines.length > maxContentLines ? "\nโ€ฆ" : "");
219
+ const visibleContentLines = trimmedLines.slice(0, maxContentLines);
220
+ const content = visibleContentLines.join("\n") + (contentLines.length > maxContentLines ? "\nโ€ฆ" : "");
171
221
 
172
222
  let statusRaw: string;
173
223
  if (sa.status === "created") {
@@ -286,12 +336,8 @@ function requestSubagentRender() {
286
336
  syncAnimationTimer();
287
337
 
288
338
  if (!currentCtx) return;
289
- if (subagents.length === 0) {
290
- if (widgetMounted) {
291
- currentCtx.ui.setWidget("in-memory-subagent-cards", undefined);
292
- widgetMounted = false;
293
- widgetTui = null;
294
- }
339
+ if (!overlayEnabled || subagents.length === 0) {
340
+ unmountWidget();
295
341
  try { activeDetailTui?.requestRender(); } catch {}
296
342
  return;
297
343
  }
@@ -460,8 +506,8 @@ async function executeSubagent(
460
506
  fallbackCwd?: string,
461
507
  ): Promise<AgentToolResult<any>> {
462
508
  subagentCount++;
463
- const subagentNum = subagentCount;
464
- const outDir = join(".pi", "subagent-in-memory", mainSessionId, `subagent_${subagentNum}`);
509
+ const subagentNum = subagents.length + 1; // display number based on currently visible cards
510
+ const outDir = join(".pi", "subagent-in-memory", mainSessionId, `subagent_${subagentCount}`);
465
511
  mkdirSync(outDir, { recursive: true });
466
512
 
467
513
  // Parse "provider/model" format (e.g. "openai/gpt-4o-mini")
@@ -477,36 +523,44 @@ async function executeSubagent(
477
523
  throw new Error("Could not determine model. Provide provider and model parameters.");
478
524
  }
479
525
 
480
- const { model: resolvedModel, apiKey } = await resolveModel(providerName, modelId);
481
-
482
526
  const cwd = params.cwd ?? fallbackCwd ?? process.cwd();
483
527
 
484
- const authStorage = AuthStorage.create();
485
- authStorage.setRuntimeApiKey(providerName, apiKey);
486
-
487
- // Create tools for the subagent, including nested subagent support
488
- const tools = [
489
- ...createCodingTools(cwd),
490
- createGrepTool(cwd),
491
- createFindTool(cwd),
492
- createLsTool(cwd),
493
- createSubagentAgentTool(providerName, modelId, cwd),
494
- ];
495
-
496
- const resourceLoader = new DefaultResourceLoader({
497
- cwd,
498
- agentDir: getAgentDir(),
499
- });
500
- await resourceLoader.reload();
528
+ // Create pi's normal cwd-bound services first. This loads packages from
529
+ // ~/.pi/agent/settings.json and <cwd>/.pi/settings.json, then applies any
530
+ // extension-provided registerProvider() calls to the model registry. Resolving
531
+ // the requested model after this step is what makes package-provided models
532
+ // such as openai-codex/gpt-5.5 visible to subagents.
533
+ const services = await createAgentSessionServices({ cwd });
534
+ const resolvedModel = services.modelRegistry.find(providerName, modelId);
535
+ if (!resolvedModel) {
536
+ const providerModels = services.modelRegistry
537
+ .getAll()
538
+ .filter((model) => model.provider === providerName)
539
+ .map((model) => model.id)
540
+ .sort();
541
+ const diagnostics = services.diagnostics
542
+ .filter((diagnostic) => diagnostic.type === "error")
543
+ .map((diagnostic) => diagnostic.message);
544
+ const details = [
545
+ providerModels.length > 0
546
+ ? `Known models for ${providerName}: ${providerModels.join(", ")}`
547
+ : `Provider ${providerName} has no registered models.`,
548
+ diagnostics.length > 0 ? `Service diagnostics: ${diagnostics.join("; ")}` : undefined,
549
+ ].filter(Boolean).join(" ");
550
+ throw new Error(`Could not find model ${providerName}/${modelId}. ${details}`.trim());
551
+ }
501
552
 
502
- const { session } = await createAgentSession({
553
+ const { session } = await createAgentSessionFromServices({
554
+ services,
555
+ sessionManager: SessionManager.inMemory(),
503
556
  model: resolvedModel,
504
- authStorage,
505
- tools,
506
557
  thinkingLevel: "off",
507
- cwd,
508
- sessionManager: SessionManager.inMemory(),
509
- resourceLoader,
558
+ // Keep subagent context/tool surface intentionally small: built-in coding
559
+ // tools plus nested subagent support. Package extensions are still loaded
560
+ // above so provider registrations are available, but their tools are not
561
+ // activated unless explicitly listed here.
562
+ tools: ["read", "bash", "edit", "write", "grep", "find", "ls", "subagent_create"],
563
+ customTools: [createSubagentAgentTool(providerName, modelId, cwd)],
510
564
  });
511
565
 
512
566
  // Set up JSONL event log
@@ -766,7 +820,7 @@ function createSubagentAgentTool(
766
820
  parentProvider: string,
767
821
  parentModel: string,
768
822
  parentCwd: string,
769
- ) {
823
+ ): ToolDefinition<typeof SubagentParams> {
770
824
  return {
771
825
  name: "subagent_create",
772
826
  label: "Subagent",
@@ -779,6 +833,7 @@ function createSubagentAgentTool(
779
833
  params: SubagentParamsType,
780
834
  signal?: AbortSignal,
781
835
  onUpdate?: AgentToolUpdateCallback,
836
+ _ctx?: any,
782
837
  ) {
783
838
  return executeSubagent(
784
839
  toolCallId,
@@ -795,46 +850,142 @@ function createSubagentAgentTool(
795
850
 
796
851
  // โ”€โ”€ Extension entry point โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
797
852
  export default function (pi: ExtensionAPI) {
853
+ pi.registerFlag("saim-no-tui", {
854
+ description: "Start with the subagent TUI overlay disabled (equivalent to /saim-toggle-overlay off).",
855
+ type: "boolean",
856
+ default: false,
857
+ });
858
+
798
859
  pi.on("session_start", async (_event, ctx) => {
799
860
  currentCtx = ctx;
800
861
  mainSessionId = ctx.sessionManager.getSessionId?.() ?? `session-${Date.now()}`;
801
862
  subagentCount = 0;
802
863
  subagents.length = 0;
803
864
  activeDetailTui = null;
865
+ activeDetailDone = null;
804
866
  widgetMounted = false;
805
867
  widgetTui = null;
868
+ windowOffset = 0;
806
869
  if (flashTimer) { clearInterval(flashTimer); flashTimer = null; }
807
870
  ctx.ui.setWidget("in-memory-subagent-cards", undefined);
871
+
872
+ // Apply --saim-no-tui flag if present
873
+ if (pi.getFlag("saim-no-tui") === true) {
874
+ overlayEnabled = false;
875
+ }
876
+
808
877
  requestSubagentRender();
809
878
  });
810
879
 
811
- pi.registerCommand("in-memory-clear-widgets", {
812
- description: "Clear all in-memory subagent card widgets",
880
+ pi.registerCommand("saim-clear-tui-overlay", {
881
+ description: "Clear subagent TUI cards and close any open detail overlay",
813
882
  handler: async (_args, ctx) => {
814
883
  subagents.length = 0;
815
- activeDetailTui = null;
816
- widgetMounted = false;
817
- widgetTui = null;
884
+ windowOffset = 0;
885
+ closeActiveDetail();
886
+ unmountWidget();
818
887
  if (flashTimer) { clearInterval(flashTimer); flashTimer = null; }
819
- ctx.ui.setWidget("in-memory-subagent-cards", undefined);
820
- ctx.ui.notify("In-memory subagent widgets cleared", "info");
888
+ ctx.ui.notify("Subagent TUI cards cleared", "info");
889
+ },
890
+ });
891
+
892
+ pi.registerCommand("saim-toggle-overlay", {
893
+ description: "Enable or disable subagent detail overlays. Usage: /saim-toggle-overlay [on|off|toggle]",
894
+ handler: async (args, ctx) => {
895
+ const arg = (args ?? "").trim().toLowerCase();
896
+ let next: boolean;
897
+ if (arg === "on" || arg === "true" || arg === "1") {
898
+ next = true;
899
+ } else if (arg === "off" || arg === "false" || arg === "0") {
900
+ next = false;
901
+ } else if (arg === "" || arg === "toggle") {
902
+ next = !overlayEnabled;
903
+ } else {
904
+ ctx.ui.notify(`Unknown argument "${arg}". Use on, off, or toggle.`, "warning");
905
+ return;
906
+ }
907
+ overlayEnabled = next;
908
+ if (!overlayEnabled) {
909
+ // Force-tear down even while subagents are running.
910
+ closeActiveDetail();
911
+ unmountWidget();
912
+ }
913
+ requestSubagentRender();
914
+ ctx.ui.notify(`Subagent TUI overlay ${overlayEnabled ? "enabled" : "disabled"}`, "info");
915
+ },
916
+ });
917
+
918
+ pi.registerCommand("saim-set-max-tui-overlays", {
919
+ description: `Set max visible subagent cards (1-${MAX_OVERLAYS_HARD_LIMIT}). Older cards remain accessible via Ctrl+Alt+โ†/โ†’.`,
920
+ handler: async (args, ctx) => {
921
+ const n = parseInt((args ?? "").trim(), 10);
922
+ if (!Number.isFinite(n) || n < 1 || n > MAX_OVERLAYS_HARD_LIMIT) {
923
+ ctx.ui.notify(
924
+ `Provide an integer between 1 and ${MAX_OVERLAYS_HARD_LIMIT}.`,
925
+ "warning",
926
+ );
927
+ return;
928
+ }
929
+ maxVisibleOverlays = n;
930
+ windowOffset = 0;
931
+ requestSubagentRender();
932
+ ctx.ui.notify(`Max visible subagent cards set to ${n}`, "info");
821
933
  },
822
934
  });
823
935
 
824
- // Register Ctrl+1 through Ctrl+9 to open subagent detail overlay
936
+ // Page through cards when there are more subagents than fit on screen.
937
+ pi.registerShortcut(Key.ctrlAlt("left"), {
938
+ description: "Page to older subagent cards",
939
+ handler: async (ctx) => {
940
+ if (!overlayEnabled) return;
941
+ const total = subagents.length;
942
+ const window = Math.min(maxVisibleOverlays, total);
943
+ const maxOffset = Math.max(0, total - window);
944
+ if (windowOffset >= maxOffset) {
945
+ ctx.ui.notify("Already showing the oldest subagents", "info");
946
+ return;
947
+ }
948
+ windowOffset = Math.min(maxOffset, windowOffset + window);
949
+ requestSubagentRender();
950
+ },
951
+ });
952
+
953
+ pi.registerShortcut(Key.ctrlAlt("right"), {
954
+ description: "Page to newer subagent cards",
955
+ handler: async (ctx) => {
956
+ if (!overlayEnabled) return;
957
+ if (windowOffset === 0) {
958
+ ctx.ui.notify("Already showing the latest subagents", "info");
959
+ return;
960
+ }
961
+ const window = Math.min(maxVisibleOverlays, subagents.length);
962
+ windowOffset = Math.max(0, windowOffset - window);
963
+ requestSubagentRender();
964
+ },
965
+ });
966
+
967
+ // Register Ctrl+1 through Ctrl+9 to open subagent detail overlay.
968
+ // The number maps to the position WITHIN the currently visible window
969
+ // (1 = first visible card), not the absolute subagent number.
825
970
  for (let n = 1; n <= 9; n++) {
826
971
  pi.registerShortcut(Key.ctrl(`${n}` as any), {
827
- description: `Inspect subagent #${n}`,
972
+ description: `Inspect visible subagent #${n}`,
828
973
  handler: async (ctx) => {
829
- const card = subagents.find((sa) => sa.num === n);
974
+ if (!overlayEnabled) {
975
+ ctx.ui.notify("Subagent TUI overlay is disabled", "warning");
976
+ return;
977
+ }
978
+ const visible = getVisibleSubagents();
979
+ const card = visible[n - 1];
830
980
  if (!card) {
831
- ctx.ui.notify(`No subagent #${n}`, "warning");
981
+ ctx.ui.notify(`No visible subagent #${n}`, "warning");
832
982
  return;
833
983
  }
834
984
 
835
985
  await ctx.ui.custom<void>(
836
986
  (tui: any, theme: any, _keybindings: any, done: (result: void) => void) => {
837
987
  activeDetailTui = tui;
988
+ activeDetailDone = done;
838
989
  return new SubagentDetailOverlay(card, n, theme, done);
839
990
  },
840
991
  {
@@ -849,6 +1000,7 @@ export default function (pi: ExtensionAPI) {
849
1000
  );
850
1001
 
851
1002
  activeDetailTui = null;
1003
+ activeDetailDone = null;
852
1004
  syncAnimationTimer();
853
1005
  requestSubagentRender();
854
1006
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-subagent-in-memory",
3
- "version": "0.1.5",
3
+ "version": "0.2.1",
4
4
  "description": "In-process subagent tool for pi with live TUI card widgets, JSONL session logging, and zero system-prompt overhead.",
5
5
  "repository": {
6
6
  "type": "git",