pi-subagents-lite 1.4.4 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-subagents-lite",
3
- "version": "1.4.4",
3
+ "version": "1.4.5",
4
4
  "description": "Lightweight sub-agents for pi — spawn specialized agents with isolated sessions, tools, and models.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -27,7 +27,7 @@ import { buildAgentPrompt, type PromptExtras } from "../prompt/prompts.js";
27
27
  import { preloadSkills, loadSkillMeta, type SkillMeta } from "../prompt/skill-loader.js";
28
28
  import { type EnvInfo, type RunCallbacks, type RunTunables, SHORT_ID_LENGTH } from "../types.js";
29
29
  import type { SubagentType, SystemPromptMode } from "./types.js";
30
- import { getStore } from "../shell.js";
30
+ import { getStore, enterSubagentSpawn, exitSubagentSpawn } from "../shell.js";
31
31
  import { DEFAULT_GRACE_TURNS, CUSTOM_PROMPT_PATH } from "../config/config-io.js";
32
32
 
33
33
  /** Normalize max turns. undefined or 0 = unlimited, otherwise minimum 1. */
@@ -516,6 +516,22 @@ export async function runAgent(
516
516
  type: SubagentType,
517
517
  prompt: string,
518
518
  options: RunOptions,
519
+ ): Promise<RunResult> {
520
+ // Bracket the whole subagent lifecycle so the extension factory can detect
521
+ // it's being re-loaded inside a subagent and avoid clobbering the parent shell.
522
+ enterSubagentSpawn();
523
+ try {
524
+ return await runAgentImpl(ctx, type, prompt, options);
525
+ } finally {
526
+ exitSubagentSpawn();
527
+ }
528
+ }
529
+
530
+ async function runAgentImpl(
531
+ ctx: ExtensionContext,
532
+ type: SubagentType,
533
+ prompt: string,
534
+ options: RunOptions,
519
535
  ): Promise<RunResult> {
520
536
  const store = getStore();
521
537
  const config = getConfig(type, store.agent.loadSkillsImplicitly, store.agent.loadExtensionsImplicitly);
package/src/index.ts CHANGED
@@ -24,11 +24,15 @@
24
24
  */
25
25
 
26
26
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
27
- import { setPiInstance } from "./shell.js";
27
+ import { setPiInstance, isInsideSubagentSpawn } from "./shell.js";
28
28
  import { registerTools } from "./registration.js";
29
29
  import { setupEventListeners } from "./events.js";
30
30
 
31
31
  export default function (pi: ExtensionAPI) {
32
+ // Subagents re-load this extension under their own pi/runtime. Stay inert so
33
+ // we never overwrite the parent-owned shell (pi, sessionCtx, manager, ...).
34
+ // The completion nudge relies on those still pointing at the parent session.
35
+ if (isInsideSubagentSpawn()) return;
32
36
  setPiInstance(pi);
33
37
  registerTools(pi);
34
38
  setupEventListeners(pi);
package/src/shell.ts CHANGED
@@ -99,3 +99,31 @@ export function setWidget(w: AgentWidget | null): void {
99
99
  export function setCoordinator(c: SpawnCoordinator | null): void {
100
100
  shell.coordinator = c;
101
101
  }
102
+
103
+ // ============================================================================
104
+ // Subagent spawn context
105
+ // ============================================================================
106
+
107
+ /**
108
+ * Nesting depth of in-flight subagent spawns.
109
+ *
110
+ * Subagents are created via runAgent(), which re-loads this extension fresh
111
+ * (new runtime, new pi/ctx). Without protection those re-loads clobber the
112
+ * parent-owned shell singletons below, so the nudge would later route to a
113
+ * dead subagent session instead of the parent. The factory checks this flag
114
+ * and stays inert while a subagent is spawning.
115
+ */
116
+ let subagentSpawnDepth = 0;
117
+
118
+ export function enterSubagentSpawn(): void {
119
+ subagentSpawnDepth++;
120
+ }
121
+
122
+ export function exitSubagentSpawn(): void {
123
+ if (subagentSpawnDepth > 0) subagentSpawnDepth--;
124
+ }
125
+
126
+ /** True while a subagent is being spawned (factory/session_start run in subagent context). */
127
+ export function isInsideSubagentSpawn(): boolean {
128
+ return subagentSpawnDepth > 0;
129
+ }