pi-subagents 0.33.0 → 0.33.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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.33.1] - 2026-07-03
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Avoid native supervisor-channel tool conflicts when `pi-intercom` is also installed by deferring native tool registration until runtime startup and keeping a namespaced native supervisor reply tool.
|
|
9
|
+
|
|
5
10
|
## [0.33.0] - 2026-07-03
|
|
6
11
|
|
|
7
12
|
### Added
|
package/README.md
CHANGED
|
@@ -267,7 +267,7 @@ Add `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the syn
|
|
|
267
267
|
|
|
268
268
|
## Native supervisor coordination
|
|
269
269
|
|
|
270
|
-
Child agents can talk back to the parent Pi session without installing `pi-intercom`. `pi-subagents` now provides the child-facing `contact_supervisor` tool and the parent-facing `
|
|
270
|
+
Child agents can talk back to the parent Pi session without installing `pi-intercom`. `pi-subagents` now provides the child-facing `contact_supervisor` tool and the parent-facing `subagent_supervisor({ action: "reply" })` path natively. If no external `pi-intercom` tool owns the `intercom` name, the native channel also exposes `intercom` as a compatibility fallback.
|
|
271
271
|
|
|
272
272
|
Use it for work where the child might need a decision instead of guessing:
|
|
273
273
|
|
|
@@ -283,7 +283,7 @@ The child can use one dedicated coordination tool:
|
|
|
283
283
|
|
|
284
284
|
- `contact_supervisor`: the child contacts the parent/supervisor session that delegated the task. Use `reason: "need_decision"` for blocking decisions or clarification, `reason: "interview_request"` for structured input, and `reason: "progress_update"` for short non-blocking updates when a discovery changes the plan. Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing or artifact-writing instructions; no-edit wins.
|
|
285
285
|
|
|
286
|
-
Supervisor messages are scoped to the exact Pi session id that spawned the child. A second Pi session in the same repository does not receive those requests.
|
|
286
|
+
The parent replies with `subagent_supervisor({ action: "reply", replyTo, message })` or checks pending requests with `subagent_supervisor({ action: "pending" })`. Supervisor messages are scoped to the exact Pi session id that spawned the child. A second Pi session in the same repository does not receive those requests.
|
|
287
287
|
|
|
288
288
|
Child-side routine completion handoffs are still not expected. If a child appears stalled, needs-attention notices can show up in the parent session with useful next actions, such as checking `subagent({ action: "status" })`, interrupting the run, or nudging the child.
|
|
289
289
|
|
package/package.json
CHANGED
|
@@ -550,18 +550,20 @@ contact_supervisor({
|
|
|
550
550
|
})
|
|
551
551
|
```
|
|
552
552
|
|
|
553
|
-
The parent replies with:
|
|
553
|
+
The parent replies with the native supervisor tool:
|
|
554
554
|
|
|
555
555
|
```typescript
|
|
556
|
-
|
|
556
|
+
subagent_supervisor({ action: "reply", message: "Optimize for readability." })
|
|
557
557
|
```
|
|
558
558
|
|
|
559
559
|
Or inspects unresolved asks first:
|
|
560
560
|
|
|
561
561
|
```typescript
|
|
562
|
-
|
|
562
|
+
subagent_supervisor({ action: "pending" })
|
|
563
563
|
```
|
|
564
564
|
|
|
565
|
+
If no external `pi-intercom` tool owns the `intercom` name, native supervisor coordination may also expose `intercom` as a compatibility fallback. Prefer `subagent_supervisor` for parent replies because it never overrides installed `pi-intercom`.
|
|
566
|
+
|
|
565
567
|
If intercom messages do not show up, run `subagent({ action: "doctor" })` or `/subagents-doctor`.
|
|
566
568
|
|
|
567
569
|
## Management Mode
|
|
@@ -18,6 +18,7 @@ import { writeAtomicJson } from "../shared/atomic-json.ts";
|
|
|
18
18
|
const SUPERVISOR_CHANNEL_ROOT = path.join(TEMP_ROOT_DIR, "supervisor-channels");
|
|
19
19
|
const REQUESTS_DIR = "requests";
|
|
20
20
|
const REPLIES_DIR = "replies";
|
|
21
|
+
export const NATIVE_SUPERVISOR_TOOL_NAME = "subagent_supervisor";
|
|
21
22
|
const MAX_MESSAGE_BYTES = 64 * 1024;
|
|
22
23
|
const DEFAULT_ASK_TIMEOUT_MS = 10 * 60 * 1000;
|
|
23
24
|
const CHANNEL_POLL_MS = Math.min(POLL_INTERVAL_MS, 500);
|
|
@@ -275,8 +276,9 @@ function hasTool(pi: ExtensionAPI, name: string): boolean {
|
|
|
275
276
|
}
|
|
276
277
|
}
|
|
277
278
|
|
|
278
|
-
export function registerNativeSupervisorClient(pi: ExtensionAPI): void {
|
|
279
|
+
export function registerNativeSupervisorClient(pi: ExtensionAPI, options: { includeIntercomFallback?: boolean } = {}): void {
|
|
279
280
|
if (!readChildMetadata()) return;
|
|
281
|
+
const includeIntercomFallback = options.includeIntercomFallback !== false;
|
|
280
282
|
if (!hasTool(pi, "contact_supervisor")) {
|
|
281
283
|
const tool: ToolDefinition<typeof ContactSupervisorParamsSchema, Record<string, unknown>> = {
|
|
282
284
|
name: "contact_supervisor",
|
|
@@ -289,7 +291,7 @@ export function registerNativeSupervisorClient(pi: ExtensionAPI): void {
|
|
|
289
291
|
};
|
|
290
292
|
pi.registerTool(tool);
|
|
291
293
|
}
|
|
292
|
-
if (!hasTool(pi, "intercom")) {
|
|
294
|
+
if (includeIntercomFallback && !hasTool(pi, "intercom")) {
|
|
293
295
|
const tool: ToolDefinition<typeof IntercomParamsSchema, Record<string, unknown>> = {
|
|
294
296
|
name: "intercom",
|
|
295
297
|
label: "Intercom",
|
|
@@ -349,12 +351,13 @@ function listRequestFiles(): Array<{ channelDir: string; file: string }> {
|
|
|
349
351
|
}
|
|
350
352
|
|
|
351
353
|
function currentContextSessionId(state: Pick<SubagentState, "currentSessionId">, ctx: ExtensionContext): string | undefined {
|
|
352
|
-
if (state.currentSessionId) return state.currentSessionId;
|
|
353
354
|
try {
|
|
354
|
-
|
|
355
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
356
|
+
if (sessionId) return sessionId;
|
|
355
357
|
} catch {
|
|
356
|
-
|
|
358
|
+
// Fall through to the last known identity.
|
|
357
359
|
}
|
|
360
|
+
return state.currentSessionId ?? undefined;
|
|
358
361
|
}
|
|
359
362
|
|
|
360
363
|
function requestMatchesContext(request: SupervisorRequest, state: Pick<SubagentState, "currentSessionId">, ctx: ExtensionContext): boolean {
|
|
@@ -363,14 +366,14 @@ function requestMatchesContext(request: SupervisorRequest, state: Pick<SubagentS
|
|
|
363
366
|
}
|
|
364
367
|
|
|
365
368
|
function formatPendingLine(request: PendingSupervisorRequest): string {
|
|
366
|
-
const replyHint = request.expectsReply ? ` Reply:
|
|
369
|
+
const replyHint = request.expectsReply ? ` Reply: ${NATIVE_SUPERVISOR_TOOL_NAME}({ action: "reply", replyTo: "${request.id}", message: "..." })` : "";
|
|
367
370
|
return `- ${request.id}: ${request.agent} [${request.runId}#${request.childIndex}] ${request.reason}.${replyHint}`;
|
|
368
371
|
}
|
|
369
372
|
|
|
370
373
|
function requestVisibleText(request: PendingSupervisorRequest): string {
|
|
371
374
|
const lines = [request.message];
|
|
372
375
|
if (request.expectsReply) {
|
|
373
|
-
lines.push("", `Reply with:
|
|
376
|
+
lines.push("", `Reply with: ${NATIVE_SUPERVISOR_TOOL_NAME}({ action: "reply", replyTo: "${request.id}", message: "..." })`);
|
|
374
377
|
}
|
|
375
378
|
return lines.join("\n");
|
|
376
379
|
}
|
|
@@ -424,11 +427,13 @@ function publicPendingRequests(pending: Map<string, PendingSupervisorRequest>):
|
|
|
424
427
|
}));
|
|
425
428
|
}
|
|
426
429
|
|
|
427
|
-
function buildParentIntercomTool(pending: Map<string, PendingSupervisorRequest
|
|
430
|
+
function buildParentIntercomTool(pending: Map<string, PendingSupervisorRequest>, name = "intercom"): ToolDefinition<typeof IntercomParamsSchema, Record<string, unknown>> {
|
|
428
431
|
return {
|
|
429
|
-
name
|
|
430
|
-
label: "Intercom",
|
|
431
|
-
description:
|
|
432
|
+
name,
|
|
433
|
+
label: name === "intercom" ? "Intercom" : "Subagent Supervisor",
|
|
434
|
+
description: name === "intercom"
|
|
435
|
+
? "Native pi-subagents supervisor channel. Use reply/pending/status to answer child subagent requests."
|
|
436
|
+
: "Native pi-subagents supervisor channel. Use reply/pending/status to answer child subagent requests without overriding pi-intercom.",
|
|
432
437
|
parameters: IntercomParamsSchema,
|
|
433
438
|
async execute(_id, params) {
|
|
434
439
|
const input = params as IntercomParams;
|
|
@@ -458,7 +463,10 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
|
|
|
458
463
|
const seenFiles = new Set<string>();
|
|
459
464
|
let poller: ReturnType<typeof setInterval> | undefined;
|
|
460
465
|
|
|
461
|
-
|
|
466
|
+
const registerParentTools = (): void => {
|
|
467
|
+
if (!hasTool(pi, NATIVE_SUPERVISOR_TOOL_NAME)) pi.registerTool(buildParentIntercomTool(pending, NATIVE_SUPERVISOR_TOOL_NAME));
|
|
468
|
+
if (!hasTool(pi, "intercom")) pi.registerTool(buildParentIntercomTool(pending));
|
|
469
|
+
};
|
|
462
470
|
|
|
463
471
|
const poll = (): void => {
|
|
464
472
|
const ctx = state.lastUiContext;
|
|
@@ -495,6 +503,7 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
|
|
|
495
503
|
return {
|
|
496
504
|
start: () => {
|
|
497
505
|
if (poller) return;
|
|
506
|
+
registerParentTools();
|
|
498
507
|
poll();
|
|
499
508
|
poller = setInterval(poll, CHANNEL_POLL_MS);
|
|
500
509
|
poller.unref?.();
|
|
@@ -261,7 +261,21 @@ function registerSteeringInbox(pi: ExtensionAPI): void {
|
|
|
261
261
|
export default function registerSubagentPromptRuntime(pi: ExtensionAPI): void {
|
|
262
262
|
registerSteeringInbox(pi);
|
|
263
263
|
registerToolBudget(pi, decodeToolBudgetEnv(process.env[TOOL_BUDGET_ENV]));
|
|
264
|
-
|
|
264
|
+
let nativeSupervisorClientRegistered = false;
|
|
265
|
+
let nativeSupervisorFallbackRegistered = false;
|
|
266
|
+
const registerNativeSupervisorClientOnce = (): void => {
|
|
267
|
+
if (nativeSupervisorClientRegistered) return;
|
|
268
|
+
nativeSupervisorClientRegistered = true;
|
|
269
|
+
registerNativeSupervisorClient(pi, { includeIntercomFallback: false });
|
|
270
|
+
};
|
|
271
|
+
const registerNativeSupervisorFallbackOnce = (): void => {
|
|
272
|
+
registerNativeSupervisorClientOnce();
|
|
273
|
+
if (nativeSupervisorFallbackRegistered) return;
|
|
274
|
+
nativeSupervisorFallbackRegistered = true;
|
|
275
|
+
registerNativeSupervisorClient(pi);
|
|
276
|
+
};
|
|
277
|
+
const onRuntimeEvent = pi.on as unknown as (event: string, handler: (event: unknown) => unknown) => void;
|
|
278
|
+
onRuntimeEvent("session_start", registerNativeSupervisorClientOnce);
|
|
265
279
|
const structuredOutputPath = process.env[STRUCTURED_OUTPUT_CAPTURE_ENV];
|
|
266
280
|
const structuredSchemaPath = process.env[STRUCTURED_OUTPUT_SCHEMA_ENV];
|
|
267
281
|
if (structuredOutputPath && structuredSchemaPath) {
|
|
@@ -300,7 +314,6 @@ export default function registerSubagentPromptRuntime(pi: ExtensionAPI): void {
|
|
|
300
314
|
});
|
|
301
315
|
}
|
|
302
316
|
|
|
303
|
-
const onRuntimeEvent = pi.on as unknown as (event: string, handler: (event: unknown) => unknown) => void;
|
|
304
317
|
onRuntimeEvent("context", (event: { messages: unknown[] }) => {
|
|
305
318
|
const messages = stripParentOnlySubagentMessages(event.messages);
|
|
306
319
|
if (messages === event.messages) return undefined;
|
|
@@ -308,6 +321,7 @@ export default function registerSubagentPromptRuntime(pi: ExtensionAPI): void {
|
|
|
308
321
|
});
|
|
309
322
|
|
|
310
323
|
onRuntimeEvent("before_agent_start", async (event: { systemPrompt: string }) => {
|
|
324
|
+
registerNativeSupervisorFallbackOnce();
|
|
311
325
|
const intercomSessionName = process.env[SUBAGENT_INTERCOM_SESSION_NAME_ENV]?.trim();
|
|
312
326
|
if (intercomSessionName && typeof pi.setSessionName === "function") {
|
|
313
327
|
pi.setSessionName(intercomSessionName);
|