pi-subagents-lite 1.4.6 → 1.4.7
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
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type AgentStatus,
|
|
15
15
|
type CompactionInfo,
|
|
16
16
|
type RunCallbacks,
|
|
17
|
+
type StopInitiator,
|
|
17
18
|
SHORT_ID_LENGTH,
|
|
18
19
|
type SpawnConfig,
|
|
19
20
|
type ToolActivity,
|
|
@@ -267,7 +268,7 @@ export class AgentManager {
|
|
|
267
268
|
|
|
268
269
|
// Wire parent abort signal to stop the subagent when the parent is interrupted
|
|
269
270
|
if (options.signal) {
|
|
270
|
-
options.signal.addEventListener("abort", () => this.abort(id), { once: true });
|
|
271
|
+
options.signal.addEventListener("abort", () => this.abort(id, "agent"), { once: true });
|
|
271
272
|
}
|
|
272
273
|
|
|
273
274
|
const promise = runAgent(ctx, type, prompt, {
|
|
@@ -465,18 +466,18 @@ export class AgentManager {
|
|
|
465
466
|
);
|
|
466
467
|
}
|
|
467
468
|
|
|
468
|
-
abort(id: string): boolean {
|
|
469
|
+
abort(id: string, stoppedBy?: StopInitiator): boolean {
|
|
469
470
|
const record = this.agents.get(id);
|
|
470
471
|
if (!record) return false;
|
|
471
472
|
|
|
472
|
-
return this.stopAgent(record);
|
|
473
|
+
return this.stopAgent(record, stoppedBy);
|
|
473
474
|
}
|
|
474
475
|
|
|
475
476
|
/**
|
|
476
477
|
* Stop an agent by aborting its session or removing it from the queue.
|
|
477
478
|
* Returns true if the agent was stopped, false if it wasn't running/queued.
|
|
478
479
|
*/
|
|
479
|
-
private stopAgent(record: AgentRecord): boolean {
|
|
480
|
+
private stopAgent(record: AgentRecord, stoppedBy?: StopInitiator): boolean {
|
|
480
481
|
if (record.lifecycle.status === "queued") {
|
|
481
482
|
this.queue = this.queue.filter(q => q.id !== record.id);
|
|
482
483
|
} else if (record.lifecycle.status !== "running") {
|
|
@@ -485,6 +486,7 @@ export class AgentManager {
|
|
|
485
486
|
record.execution.abortController?.abort();
|
|
486
487
|
}
|
|
487
488
|
record.lifecycle.status = "stopped";
|
|
489
|
+
record.lifecycle.stoppedBy = stoppedBy;
|
|
488
490
|
record.lifecycle.completedAt = Date.now();
|
|
489
491
|
return true;
|
|
490
492
|
}
|
|
@@ -88,6 +88,17 @@ export function buildAgentDetails(
|
|
|
88
88
|
return details;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Result text plus status note, for display.
|
|
93
|
+
*
|
|
94
|
+
* Shared by the foreground tool result and the subagent-result nudge so both
|
|
95
|
+
* callers stay in sync on the nullish default and separator handling — they
|
|
96
|
+
* have diverged before. getStatusNote owns the leading separator.
|
|
97
|
+
*/
|
|
98
|
+
export function formatResultContent(record: AgentRecord): string {
|
|
99
|
+
return (record.result ?? "") + getStatusNote(record.lifecycle);
|
|
100
|
+
}
|
|
101
|
+
|
|
91
102
|
// ============================================================================
|
|
92
103
|
// Tool execute handlers
|
|
93
104
|
// ============================================================================
|
|
@@ -186,8 +197,7 @@ export async function executeAgentTool(
|
|
|
186
197
|
return errorResult(`Agent failed: ${record.error || "unknown error"}`, details);
|
|
187
198
|
}
|
|
188
199
|
|
|
189
|
-
|
|
190
|
-
return successResult((record.result ?? "") + statusNote, details);
|
|
200
|
+
return successResult(formatResultContent(record), details);
|
|
191
201
|
}
|
|
192
202
|
|
|
193
203
|
// ============================================================================
|
|
@@ -244,7 +254,7 @@ export async function executeStopAgentTool(
|
|
|
244
254
|
}
|
|
245
255
|
|
|
246
256
|
// Attempt to stop the running/queued agent
|
|
247
|
-
if (getManager()!.abort(agentId)) {
|
|
257
|
+
if (getManager()!.abort(agentId, "agent")) {
|
|
248
258
|
return successResult(`Stopped agent ${agentId.slice(0, SHORT_ID_LENGTH)}`);
|
|
249
259
|
}
|
|
250
260
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import { getStatusNote } from "../status-note.js";
|
|
2
1
|
import { getPiInstance, getSessionCtx, getWidget } from "../shell.js";
|
|
2
|
+
import { SHORT_ID_LENGTH } from "../types.js";
|
|
3
|
+
|
|
4
|
+
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
5
|
+
import type { AgentRecord, SpawnConfig, ToolActivity } from "../types.js";
|
|
6
|
+
import type { AgentManager, SpawnOptions } from "../agents/agent-manager.js";
|
|
7
|
+
import { buildAgentDetails, formatResultContent } from "../agents/tool-execution.js";
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* spawn-coordinator.ts — Spawn-and-track coordination for subagents.
|
|
5
11
|
*
|
|
@@ -11,11 +17,6 @@ import { getPiInstance, getSessionCtx, getWidget } from "../shell.js";
|
|
|
11
17
|
* D6 (Nudge owned here), D2 (peers with AgentManager).
|
|
12
18
|
*/
|
|
13
19
|
|
|
14
|
-
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
15
|
-
import type { AgentRecord, SpawnConfig, ToolActivity } from "../types.js";
|
|
16
|
-
import type { AgentManager, SpawnOptions } from "../agents/agent-manager.js";
|
|
17
|
-
import { buildAgentDetails } from "../agents/tool-execution.js";
|
|
18
|
-
|
|
19
20
|
// ============================================================================
|
|
20
21
|
// Types
|
|
21
22
|
// ============================================================================
|
|
@@ -234,7 +235,7 @@ export class SpawnCoordinator {
|
|
|
234
235
|
pi.sendMessage(
|
|
235
236
|
{
|
|
236
237
|
customType: "subagent-result",
|
|
237
|
-
content: `[Subagent "${record.display.type}" ${record.lifecycle.status}]\n\n${
|
|
238
|
+
content: `[Subagent "${record.display.type}" ${record.id.slice(0, SHORT_ID_LENGTH)} ${record.lifecycle.status}]\n\n${formatResultContent(record)}`,
|
|
238
239
|
details,
|
|
239
240
|
display: true,
|
|
240
241
|
},
|
package/src/status-note.ts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { AgentLifecycle, AgentStatus, StopInitiator } from "./types.js";
|
|
2
|
+
|
|
3
|
+
const STATUS_NOTES: Partial<Record<AgentStatus, string>> = {
|
|
3
4
|
aborted: "hit the turn limit before completion; output may be incomplete",
|
|
4
5
|
turn_limited: "wrapped up at the turn limit — output may be partial",
|
|
5
6
|
};
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
const STOP_NOTES: Record<StopInitiator, string> = {
|
|
9
|
+
user: "STOPPED BY THE USER before completion — output is partial; the task was NOT finished",
|
|
10
|
+
agent: "stopped before completion — output is partial; the task was NOT finished",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function getStatusNote(lifecycle: AgentLifecycle): string {
|
|
14
|
+
const note =
|
|
15
|
+
lifecycle.status === "stopped"
|
|
16
|
+
// A stopped agent with no recorded initiator reads as an agent stop.
|
|
17
|
+
? STOP_NOTES[lifecycle.stoppedBy ?? "agent"]
|
|
18
|
+
: STATUS_NOTES[lifecycle.status];
|
|
9
19
|
return note ? ` (${note})` : "";
|
|
10
20
|
}
|
package/src/types.ts
CHANGED
|
@@ -95,6 +95,9 @@ export interface CompactionInfo {
|
|
|
95
95
|
/** Possible agent lifecycle statuses. */
|
|
96
96
|
export type AgentStatus = "queued" | "running" | "completed" | "turn_limited" | "aborted" | "stopped" | "error";
|
|
97
97
|
|
|
98
|
+
/** Who initiated an agent stop: "user" via UI menu, or "agent" via StopAgent tool. */
|
|
99
|
+
export type StopInitiator = "user" | "agent";
|
|
100
|
+
|
|
98
101
|
/**
|
|
99
102
|
* Lifecycle state: when the agent started, completed, and its current status.
|
|
100
103
|
* Used by agent-manager (lifecycle control), menus (status display), widget (linger logic).
|
|
@@ -103,6 +106,7 @@ export interface AgentLifecycle {
|
|
|
103
106
|
status: AgentStatus;
|
|
104
107
|
startedAt: number;
|
|
105
108
|
completedAt?: number;
|
|
109
|
+
stoppedBy?: StopInitiator;
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
/**
|
|
@@ -134,7 +134,7 @@ export function buildAgentActionsList(
|
|
|
134
134
|
input.onEscape = () => setActive(list);
|
|
135
135
|
setActive(input);
|
|
136
136
|
} else if (item.value === "stop") {
|
|
137
|
-
getManager()?.abort(record.id);
|
|
137
|
+
getManager()?.abort(record.id, "user");
|
|
138
138
|
ctx.ui.notify(`Stopped ${shortId}`, "info");
|
|
139
139
|
onClose();
|
|
140
140
|
}
|
|
@@ -186,7 +186,7 @@ export async function showRunningAgentsMenu(
|
|
|
186
186
|
agentList.onSelect = async (item) => {
|
|
187
187
|
if (item.value === "__stop-all") {
|
|
188
188
|
for (const r of running) {
|
|
189
|
-
getManager()?.abort(r.id);
|
|
189
|
+
getManager()?.abort(r.id, "user");
|
|
190
190
|
}
|
|
191
191
|
ctx.ui.notify(`Stopped ${running.length} agent(s)`, "info");
|
|
192
192
|
done(undefined);
|