@ian-pascoe/pi-minimal-subagents 0.1.1 → 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 +58 -5
- package/package.json +1 -1
- package/src/minimal-subagents-capabilities.ts +8 -12
- package/src/minimal-subagents-config.ts +169 -63
- package/src/minimal-subagents-context.ts +7 -1
- package/src/minimal-subagents-coordinator.ts +932 -130
- package/src/minimal-subagents-delivery-ledger.ts +521 -0
- package/src/minimal-subagents-extension.ts +382 -64
- package/src/minimal-subagents-fork-lifecycle.ts +22 -12
- package/src/minimal-subagents-message-envelope.ts +20 -0
- package/src/minimal-subagents-registry-wire.ts +269 -0
- package/src/minimal-subagents-registry.ts +1487 -137
- package/src/minimal-subagents-render-contract.ts +279 -0
- package/src/minimal-subagents-rendering.ts +445 -399
- package/src/minimal-subagents-session-wire.ts +42 -0
- package/src/minimal-subagents-sessions.ts +428 -120
- package/src/minimal-subagents-shutdown.ts +1 -1
- package/src/minimal-subagents-tool-schemas.ts +21 -7
- package/src/minimal-subagents-tools.ts +46 -18
- package/src/minimal-subagents-types.ts +67 -27
- package/src/minimal-subagents-ui.ts +8 -5
|
@@ -21,9 +21,9 @@ export async function shutdownMinimalSubagentsSession(
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
while (true) {
|
|
24
|
+
if (!rootIdleGate.isRootIdle()) await rootIdleGate.waitForRootIdle();
|
|
24
25
|
await coordinator.waitForSettledOperations();
|
|
25
26
|
if (rootIdleGate.isRootIdle()) break;
|
|
26
|
-
await rootIdleGate.waitForRootIdle();
|
|
27
27
|
}
|
|
28
28
|
await coordinator.shutdownAfterSettling();
|
|
29
29
|
}
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import { StringEnum } from "@earendil-works/pi-ai";
|
|
2
|
-
import { Type
|
|
2
|
+
import { Type } from "typebox";
|
|
3
3
|
import { THINKING_LEVELS } from "./minimal-subagents-capabilities.js";
|
|
4
4
|
|
|
5
5
|
const SessionContextSchema = StringEnum(["inherit", "compact", "omit"] as const);
|
|
6
6
|
const ProjectContextSchema = StringEnum(["inherit", "omit"] as const);
|
|
7
7
|
const DelegationSchema = StringEnum(["none", "fanout"] as const);
|
|
8
8
|
const ThinkingLevelSchema = StringEnum(THINKING_LEVELS);
|
|
9
|
-
const ToolSelectionSchema = Type.Union(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const ToolSelectionSchema = Type.Union(
|
|
10
|
+
[
|
|
11
|
+
StringEnum(["none", "read", "modify"] as const),
|
|
12
|
+
Type.Array(Type.String({ minLength: 1 }), {
|
|
13
|
+
uniqueItems: true,
|
|
14
|
+
description:
|
|
15
|
+
"Exact ordinary tool names. Coordinator tools are injected separately and must not appear here. Arrays are not bundle names; use the string preset `read` or `modify` for bundled capabilities.",
|
|
16
|
+
}),
|
|
17
|
+
],
|
|
18
|
+
{
|
|
19
|
+
description:
|
|
20
|
+
'Use the string preset "read" for read, grep, find, and ls; use "modify" for the read bundle plus bash, edit, and write. An array grants exactly those named tools (ordinary tools only); coordinator tools are injected separately.',
|
|
21
|
+
},
|
|
22
|
+
);
|
|
13
23
|
const FRIENDLY_AGENT_ID_PATTERN = "^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$";
|
|
14
24
|
const CANONICAL_AGENT_ID_PATTERN =
|
|
15
25
|
"^(?:root\\.)?[A-Za-z0-9][A-Za-z0-9_-]{0,63}(?:\\.[A-Za-z0-9][A-Za-z0-9_-]{0,63})*$";
|
|
@@ -20,8 +30,9 @@ function canonicalAgentIdSchema(description?: string) {
|
|
|
20
30
|
|
|
21
31
|
/** Build all six strict TypeBox schemas, including the refreshed runtime model enum. */
|
|
22
32
|
export function createCoordinatorToolSchemas(modelIds: readonly string[]) {
|
|
23
|
-
const
|
|
24
|
-
|
|
33
|
+
const [firstModelId, ...remainingModelIds] = modelIds;
|
|
34
|
+
const explicitModelSchema =
|
|
35
|
+
firstModelId === undefined ? Type.Never() : StringEnum([firstModelId, ...remainingModelIds]);
|
|
25
36
|
return {
|
|
26
37
|
subagent: Type.Object({
|
|
27
38
|
task: Type.String({ minLength: 1, description: "Task for the persistent child agent" }),
|
|
@@ -49,6 +60,9 @@ export function createCoordinatorToolSchemas(modelIds: readonly string[]) {
|
|
|
49
60
|
}),
|
|
50
61
|
subagent_wait: Type.Object({
|
|
51
62
|
agent_id: canonicalAgentIdSchema("Direct child canonical agent ID"),
|
|
63
|
+
turn_id: Type.Optional(
|
|
64
|
+
Type.String({ minLength: 1, description: "Exact retained child turn ID" }),
|
|
65
|
+
),
|
|
52
66
|
timeout_ms: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
53
67
|
}),
|
|
54
68
|
subagent_status: Type.Object({
|
|
@@ -16,8 +16,17 @@ import {
|
|
|
16
16
|
renderCoordinatorToolResult,
|
|
17
17
|
type CoordinatorToolName,
|
|
18
18
|
} from "./minimal-subagents-rendering.js";
|
|
19
|
+
import type { CoordinatorToolCallInput } from "./minimal-subagents-render-contract.js";
|
|
19
20
|
import type { createCoordinatorToolSchemas } from "./minimal-subagents-tool-schemas.js";
|
|
20
|
-
import type {
|
|
21
|
+
import type {
|
|
22
|
+
AgentMessageResult,
|
|
23
|
+
CallerSnapshot,
|
|
24
|
+
CancelResult,
|
|
25
|
+
DeleteResult,
|
|
26
|
+
SpawnResult,
|
|
27
|
+
StatusResult,
|
|
28
|
+
WaitResult,
|
|
29
|
+
} from "./minimal-subagents-types.js";
|
|
21
30
|
|
|
22
31
|
const ORDINARY_CHILD_COORDINATOR_TOOL_NAMES = new Set([
|
|
23
32
|
"agent_message",
|
|
@@ -25,8 +34,15 @@ const ORDINARY_CHILD_COORDINATOR_TOOL_NAMES = new Set([
|
|
|
25
34
|
"subagent_status",
|
|
26
35
|
]);
|
|
27
36
|
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
/** Coordinator operations consumed by the six public coordinator tool definitions. */
|
|
38
|
+
export type CoordinatorToolOperations = Pick<
|
|
39
|
+
MinimalSubagentsCoordinator,
|
|
40
|
+
"spawn" | "inspectStatus" | "sendAgentMessage" | "wait" | "status" | "cancel" | "delete"
|
|
41
|
+
>;
|
|
42
|
+
|
|
43
|
+
/** Dependencies and caller policy used to create caller-bound coordinator tools. */
|
|
44
|
+
export interface CoordinatorToolDefinitionOptions {
|
|
45
|
+
coordinator: CoordinatorToolOperations;
|
|
30
46
|
callerId: string;
|
|
31
47
|
allowFanoutTools?: boolean;
|
|
32
48
|
modelRoles?: readonly MinimalSubagentsModelRole[];
|
|
@@ -61,15 +77,24 @@ async function runCoordinatorToolActivity<T>(
|
|
|
61
77
|
}
|
|
62
78
|
}
|
|
63
79
|
|
|
80
|
+
type CoordinatorToolResultDetails =
|
|
81
|
+
| SpawnResult
|
|
82
|
+
| AgentMessageResult
|
|
83
|
+
| WaitResult
|
|
84
|
+
| StatusResult
|
|
85
|
+
| CancelResult
|
|
86
|
+
| DeleteResult
|
|
87
|
+
| { agent_id: string; status: "waiting"; elapsed_ms: number };
|
|
88
|
+
|
|
64
89
|
function createCoordinatorToolRendering(toolName: CoordinatorToolName) {
|
|
65
90
|
return {
|
|
66
|
-
renderCall: (args:
|
|
91
|
+
renderCall: (args: CoordinatorToolCallInput, theme: Theme) =>
|
|
67
92
|
renderCoordinatorToolCall(toolName, args, theme),
|
|
68
93
|
renderResult: (
|
|
69
|
-
result: AgentToolResult<
|
|
94
|
+
result: AgentToolResult<CoordinatorToolResultDetails>,
|
|
70
95
|
renderOptions: ToolRenderResultOptions,
|
|
71
96
|
theme: Theme,
|
|
72
|
-
context: { args:
|
|
97
|
+
context: { args: CoordinatorToolCallInput; isError: boolean },
|
|
73
98
|
) =>
|
|
74
99
|
renderCoordinatorToolResult(
|
|
75
100
|
toolName,
|
|
@@ -82,7 +107,9 @@ function createCoordinatorToolRendering(toolName: CoordinatorToolName) {
|
|
|
82
107
|
};
|
|
83
108
|
}
|
|
84
109
|
|
|
85
|
-
function structuredToolResult
|
|
110
|
+
function structuredToolResult<TDetails extends CoordinatorToolResultDetails>(
|
|
111
|
+
result: TDetails,
|
|
112
|
+
): AgentToolResult<TDetails> {
|
|
86
113
|
const json = JSON.stringify(result, null, 2);
|
|
87
114
|
const truncated = truncateHead(json, {
|
|
88
115
|
maxBytes: DEFAULT_MAX_BYTES,
|
|
@@ -94,7 +121,7 @@ function structuredToolResult(result: unknown) {
|
|
|
94
121
|
};
|
|
95
122
|
}
|
|
96
123
|
|
|
97
|
-
function failedStructuredOperation(prefix: string, result:
|
|
124
|
+
function failedStructuredOperation(prefix: string, result: DeleteResult): never {
|
|
98
125
|
const json = JSON.stringify(result);
|
|
99
126
|
const truncated = truncateHead(json, {
|
|
100
127
|
maxBytes: DEFAULT_MAX_BYTES,
|
|
@@ -104,7 +131,7 @@ function failedStructuredOperation(prefix: string, result: unknown): never {
|
|
|
104
131
|
}
|
|
105
132
|
|
|
106
133
|
function callerSourceTurnId(
|
|
107
|
-
coordinator:
|
|
134
|
+
coordinator: CoordinatorToolOperations,
|
|
108
135
|
callerId: string,
|
|
109
136
|
toolCallId: string,
|
|
110
137
|
): string {
|
|
@@ -132,17 +159,17 @@ export function createCoordinatorToolDefinitions(
|
|
|
132
159
|
return runCoordinatorToolActivity(options, async () => {
|
|
133
160
|
const result = await options.coordinator.spawn(
|
|
134
161
|
options.callerId,
|
|
135
|
-
parameters
|
|
162
|
+
parameters,
|
|
136
163
|
options.captureCaller(context),
|
|
137
164
|
);
|
|
138
165
|
const status = options.coordinator.inspectStatus(result.agent_id);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
...(status && "agent" in status ? { agent: status.agent } : {}),
|
|
144
|
-
},
|
|
166
|
+
const details: SpawnResult & {
|
|
167
|
+
agent?: import("./minimal-subagents-types.js").AgentDetail;
|
|
168
|
+
} = {
|
|
169
|
+
...result,
|
|
145
170
|
};
|
|
171
|
+
if (status && "agent" in status) details.agent = status.agent;
|
|
172
|
+
return structuredToolResult(details);
|
|
146
173
|
});
|
|
147
174
|
},
|
|
148
175
|
...createCoordinatorToolRendering("subagent"),
|
|
@@ -152,7 +179,7 @@ export function createCoordinatorToolDefinitions(
|
|
|
152
179
|
name: "agent_message",
|
|
153
180
|
label: "Agent Message",
|
|
154
181
|
description:
|
|
155
|
-
"Send one mid-turn coordination message to a direct parent, direct sibling, or direct child
|
|
182
|
+
"Send one mid-turn coordination message to a direct parent, direct sibling, or direct child. The result says whether it was delivered through an active wait, queued for the recipient, or failed.",
|
|
156
183
|
promptSnippet: "Coordinate required mid-turn action with one adjacent agent",
|
|
157
184
|
parameters: options.schemas.agent_message,
|
|
158
185
|
async execute(toolCallId, parameters) {
|
|
@@ -175,7 +202,7 @@ export function createCoordinatorToolDefinitions(
|
|
|
175
202
|
name: "subagent_wait",
|
|
176
203
|
label: "Subagent Wait",
|
|
177
204
|
description:
|
|
178
|
-
"Wait for one direct child's
|
|
205
|
+
"Wait for one direct child's oldest observable turn, or select an exact retained turn_id. A Wait Event containing a Coordination Message may arrive first as event=message; call again for the terminal turn result. A successful wait durably claims that turn so later messages and its terminal result return through wait without duplicate automatic delivery. Timeout never cancels the child.",
|
|
179
206
|
promptSnippet: "Wait for one direct child's exact turn",
|
|
180
207
|
parameters: options.schemas.subagent_wait,
|
|
181
208
|
async execute(_toolCallId, parameters, signal, onUpdate) {
|
|
@@ -199,6 +226,7 @@ export function createCoordinatorToolDefinitions(
|
|
|
199
226
|
parameters.agent_id,
|
|
200
227
|
parameters.timeout_ms,
|
|
201
228
|
signal,
|
|
229
|
+
parameters.turn_id,
|
|
202
230
|
);
|
|
203
231
|
return {
|
|
204
232
|
...structuredToolResult(result),
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
2
2
|
import type { Usage } from "@earendil-works/pi-ai";
|
|
3
3
|
|
|
4
|
-
/** Canonical path-like identity for one persistent subagent. */
|
|
5
|
-
export type AgentId = string & { readonly __agentId: unique symbol };
|
|
6
|
-
|
|
7
4
|
/** Stable identity for one prompt and its complete assistant/tool loop. */
|
|
8
5
|
export type TurnId = string & { readonly __turnId: unique symbol };
|
|
9
6
|
|
|
@@ -58,13 +55,29 @@ export interface TurnResult {
|
|
|
58
55
|
elapsed_ms?: number;
|
|
59
56
|
}
|
|
60
57
|
|
|
61
|
-
/** Reports
|
|
58
|
+
/** Reports whether one direct message was handed to a wait, queued, or failed. */
|
|
59
|
+
export type AgentMessageDisposition = "delivered-via-wait" | "queued" | "failed";
|
|
60
|
+
|
|
62
61
|
export interface AgentMessageResult {
|
|
63
62
|
agent_id: string;
|
|
64
|
-
|
|
63
|
+
message_id: string;
|
|
64
|
+
disposition: AgentMessageDisposition;
|
|
65
65
|
error?: string;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/** Reports one coordination message returned before the source turn settles. */
|
|
69
|
+
export interface WaitMessageResult {
|
|
70
|
+
event: "message";
|
|
71
|
+
agent_id: string;
|
|
72
|
+
turn_id: string;
|
|
73
|
+
message_id: string;
|
|
74
|
+
delivery_id?: string;
|
|
75
|
+
message: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Reports one terminal child turn returned by subagent_wait. */
|
|
79
|
+
export type WaitResult = WaitMessageResult | ({ event: "turn" } & TurnResult);
|
|
80
|
+
|
|
68
81
|
/** Provides bounded hierarchy, usage, and best-known Runtime Profile data for one persistent agent. */
|
|
69
82
|
export interface AgentSummary extends RuntimeProfile {
|
|
70
83
|
agent_id: string;
|
|
@@ -92,7 +105,7 @@ export interface RecentAgentMessage {
|
|
|
92
105
|
/** Extends summary status with launch, dependency, and recent-message diagnostics. */
|
|
93
106
|
export interface AgentDetail extends AgentSummary {
|
|
94
107
|
session_file?: string;
|
|
95
|
-
launch_contract:
|
|
108
|
+
launch_contract: LaunchContract;
|
|
96
109
|
capability_ceiling: string[];
|
|
97
110
|
spawn_entry_id: string;
|
|
98
111
|
recent_messages: RecentAgentMessage[];
|
|
@@ -164,6 +177,8 @@ export interface CoordinatorMessage {
|
|
|
164
177
|
source_agent_id: string;
|
|
165
178
|
destination_agent_id?: string;
|
|
166
179
|
source_turn_id: string;
|
|
180
|
+
message_id: string;
|
|
181
|
+
delivery_id?: string;
|
|
167
182
|
status?: TurnStatus;
|
|
168
183
|
elapsed_ms?: number;
|
|
169
184
|
usage?: Usage;
|
|
@@ -172,8 +187,7 @@ export interface CoordinatorMessage {
|
|
|
172
187
|
|
|
173
188
|
/** Process-local adapter around one SDK-created Pi child session. */
|
|
174
189
|
export interface ChildAgentRuntime {
|
|
175
|
-
readonly
|
|
176
|
-
readonly sessionId: string;
|
|
190
|
+
readonly sessionLeafId: string | undefined;
|
|
177
191
|
readonly isRunning: boolean;
|
|
178
192
|
runPrompt(
|
|
179
193
|
task: string,
|
|
@@ -182,48 +196,55 @@ export interface ChildAgentRuntime {
|
|
|
182
196
|
callerThinkingLevel: ThinkingLevel,
|
|
183
197
|
): Promise<RuntimeTurnOutcome>;
|
|
184
198
|
runMessage(message: CoordinatorMessage): Promise<RuntimeTurnOutcome>;
|
|
185
|
-
/**
|
|
186
|
-
|
|
199
|
+
/** Queue one typed coordinator message into the child session. */
|
|
200
|
+
queueCoordinatorMessage(message: CoordinatorMessage): Promise<void>;
|
|
187
201
|
abort(): Promise<void>;
|
|
188
202
|
dispose(): void;
|
|
189
203
|
/** Return the live Runtime Profile, or undefined when the SDK session has no model. */
|
|
190
204
|
getRuntimeProfile(): RuntimeProfile | undefined;
|
|
191
205
|
snapshotCommittedMessages(): AgentMessage[];
|
|
192
|
-
hasDeliveryEvidence(sourceAgentId: string, sourceTurnId: string): boolean;
|
|
206
|
+
hasDeliveryEvidence(sourceAgentId: string, sourceTurnId: string, deliveryId?: string): boolean;
|
|
193
207
|
getUsage(): Usage | undefined;
|
|
194
|
-
cloneSession(): Promise<{ sessionFile: string; sessionId: string }>;
|
|
195
208
|
}
|
|
196
209
|
|
|
197
210
|
/** Identifies one writable child JSONL session owned by a coordinator root. */
|
|
198
211
|
export interface PersistedSessionIdentity {
|
|
199
212
|
sessionFile: string;
|
|
200
213
|
sessionId: string;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
/** Combines a persisted agent record with first-launch imported context. */
|
|
204
|
-
export interface RuntimeCreationRequest {
|
|
205
|
-
agent: PersistedAgent;
|
|
206
|
-
importedMessages: AgentMessage[];
|
|
214
|
+
sessionLeafId?: string;
|
|
207
215
|
}
|
|
208
216
|
|
|
209
217
|
/** Pi-specific session operations injected into the pure coordinator. */
|
|
210
218
|
export interface AgentSessionFactory {
|
|
211
219
|
createIdentity(agent: PersistedAgent, importedMessages: AgentMessage[]): PersistedSessionIdentity;
|
|
212
|
-
|
|
213
|
-
|
|
220
|
+
/** Open one verified persisted Child Agent runtime for launch or restoration. */
|
|
221
|
+
openRuntime(agent: PersistedAgent): Promise<ChildAgentRuntime>;
|
|
214
222
|
resolveLaunchMissingDependencies(agent: PersistedAgent): Promise<string[]>;
|
|
215
223
|
resolveRestorationMissingDependencies(agent: PersistedAgent): Promise<string[]>;
|
|
216
224
|
resolveThinkingLevel(modelId: string, requested: ThinkingLevel): ThinkingLevel;
|
|
217
225
|
modelSupportsImages(modelId: string): boolean;
|
|
226
|
+
/** Clone a child leaf owned by the active source root during confirmed shutdown. */
|
|
218
227
|
cloneSession(agent: PersistedAgent): Promise<PersistedSessionIdentity>;
|
|
219
|
-
|
|
228
|
+
/** Clone a source-owned leaf recovered from a proven destination branch. */
|
|
229
|
+
cloneForkSourceSession(
|
|
230
|
+
agent: PersistedAgent,
|
|
231
|
+
sourceRootSessionId: string,
|
|
232
|
+
): Promise<PersistedSessionIdentity>;
|
|
233
|
+
/** Append and verify destination-root ownership for one fork clone. */
|
|
234
|
+
adoptForkSessionOwnership(
|
|
235
|
+
agent: PersistedAgent,
|
|
236
|
+
sourceRootSessionId: string,
|
|
237
|
+
): Promise<PersistedSessionIdentity>;
|
|
238
|
+
trashSession(agent: PersistedAgent): Promise<void>;
|
|
220
239
|
}
|
|
221
240
|
|
|
222
241
|
/** Abstracts root message delivery and durable delivery-evidence lookup. */
|
|
223
242
|
export interface RootConversationEndpoint {
|
|
224
|
-
/**
|
|
225
|
-
|
|
226
|
-
hasDeliveryEvidence(sourceAgentId: string, sourceTurnId: string): boolean;
|
|
243
|
+
/** Queue one typed coordinator message into the root conversation. */
|
|
244
|
+
queueCoordinatorMessage(message: CoordinatorMessage): Promise<void>;
|
|
245
|
+
hasDeliveryEvidence(sourceAgentId: string, sourceTurnId: string, deliveryId?: string): boolean;
|
|
246
|
+
/** Report whether automatic delivery can start a new root turn without racing an active wait. */
|
|
247
|
+
isIdle(): boolean;
|
|
227
248
|
}
|
|
228
249
|
|
|
229
250
|
/** Stores root-owned agent identity, launch contract, availability, and latest activity. */
|
|
@@ -237,6 +258,7 @@ export interface PersistedAgent {
|
|
|
237
258
|
spawn_entry_id: string;
|
|
238
259
|
session_file?: string;
|
|
239
260
|
session_id?: string;
|
|
261
|
+
session_leaf_id?: string;
|
|
240
262
|
clone_error?: string;
|
|
241
263
|
launch_contract: LaunchContract;
|
|
242
264
|
capability_ceiling: string[];
|
|
@@ -250,7 +272,7 @@ export interface PersistedAgent {
|
|
|
250
272
|
deleted?: boolean;
|
|
251
273
|
}
|
|
252
274
|
|
|
253
|
-
/** Records
|
|
275
|
+
/** Records which conversation path owns one successful terminal result. */
|
|
254
276
|
export type DeliveryPath = "wait" | "message";
|
|
255
277
|
|
|
256
278
|
/** Stores a keyed successful result until destination evidence settles delivery. */
|
|
@@ -260,26 +282,44 @@ export interface PersistedDelivery {
|
|
|
260
282
|
destination_agent_id: string;
|
|
261
283
|
path: DeliveryPath;
|
|
262
284
|
settled: boolean;
|
|
285
|
+
sequence?: number;
|
|
263
286
|
result?: TurnResult;
|
|
264
287
|
error?: string;
|
|
265
288
|
}
|
|
266
289
|
|
|
267
|
-
/**
|
|
290
|
+
/** Stores one durable Coordination Message until destination evidence settles it. */
|
|
291
|
+
export interface PersistedCoordinationDelivery {
|
|
292
|
+
delivery_id: string;
|
|
293
|
+
sequence: number;
|
|
294
|
+
destination_agent_id: string;
|
|
295
|
+
path: DeliveryPath;
|
|
296
|
+
settled: boolean;
|
|
297
|
+
message: CoordinatorMessage;
|
|
298
|
+
error?: string;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/** Checkpoints live agents, tombstones, and only pending delivery-ledger items for one root. */
|
|
268
302
|
export interface RegistrySnapshot {
|
|
269
303
|
agents: PersistedAgent[];
|
|
270
304
|
tombstones: string[];
|
|
271
305
|
deliveries: PersistedDelivery[];
|
|
306
|
+
coordination_deliveries?: PersistedCoordinationDelivery[];
|
|
307
|
+
wait_claimed_turns?: string[];
|
|
308
|
+
next_delivery_sequence?: number;
|
|
272
309
|
}
|
|
273
310
|
|
|
274
311
|
/** Clones a registry snapshot while recording the source root session file. */
|
|
275
312
|
export interface ForkSnapshot extends RegistrySnapshot {
|
|
313
|
+
/** Canonical Pi root session file from which the selected fork branch originated. */
|
|
276
314
|
source_root_session_file: string;
|
|
315
|
+
/** Root identity that every cloned Child Session provenance record must match. */
|
|
316
|
+
source_root_session_id: string;
|
|
277
317
|
}
|
|
278
318
|
|
|
279
319
|
/** Appends root-owned registry events to the active root conversation branch. */
|
|
280
320
|
export interface RegistryWriter {
|
|
281
321
|
readonly rootSessionId: string;
|
|
282
|
-
append(event: import("./minimal-subagents-registry.js").
|
|
322
|
+
append(event: import("./minimal-subagents-registry.js").RegistryEventV2): void;
|
|
283
323
|
}
|
|
284
324
|
|
|
285
325
|
/** Describes concise lifecycle notices surfaced through Pi UI notifications. */
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
|
|
3
|
+
/** Theme operations used by the Minimal Subagents widget renderer. */
|
|
4
|
+
export type MinimalSubagentsWidgetTheme = Pick<Theme, "fg" | "bold">;
|
|
2
5
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
3
6
|
import {
|
|
4
7
|
sliceByColumn,
|
|
@@ -195,7 +198,7 @@ function renderMinimalSubagentsWidgetRowParts(
|
|
|
195
198
|
task: string | undefined,
|
|
196
199
|
duration: string | undefined,
|
|
197
200
|
profile: string,
|
|
198
|
-
theme:
|
|
201
|
+
theme: MinimalSubagentsWidgetTheme,
|
|
199
202
|
): MinimalSubagentsWidgetRowParts {
|
|
200
203
|
const branch = row.depth > 0 ? `${" ".repeat(row.depth)}╰─ ` : " ";
|
|
201
204
|
const styledBranch = theme.fg("borderMuted", branch);
|
|
@@ -225,7 +228,7 @@ function minimalSubagentsWidgetProfileBudget(
|
|
|
225
228
|
task: string | undefined,
|
|
226
229
|
duration: string | undefined,
|
|
227
230
|
separator: string,
|
|
228
|
-
theme:
|
|
231
|
+
theme: MinimalSubagentsWidgetTheme,
|
|
229
232
|
width: number,
|
|
230
233
|
): number {
|
|
231
234
|
const fixedParts = renderMinimalSubagentsWidgetRowParts(row, task, duration, "", theme);
|
|
@@ -235,7 +238,7 @@ function minimalSubagentsWidgetProfileBudget(
|
|
|
235
238
|
function renderMinimalSubagentsWidgetRow(
|
|
236
239
|
row: MinimalSubagentsWidgetRow,
|
|
237
240
|
width: number,
|
|
238
|
-
theme:
|
|
241
|
+
theme: MinimalSubagentsWidgetTheme,
|
|
239
242
|
): string {
|
|
240
243
|
const separator = theme.fg("dim", MINIMAL_SUBAGENTS_WIDGET_SEPARATOR_TEXT);
|
|
241
244
|
const task = row.task?.replace(/\s+/g, " ").trim() || undefined;
|
|
@@ -336,7 +339,7 @@ function renderMinimalSubagentsWidgetRow(
|
|
|
336
339
|
export function renderMinimalSubagentsWidgetLines(
|
|
337
340
|
view: MinimalSubagentsWidgetView,
|
|
338
341
|
width: number,
|
|
339
|
-
theme:
|
|
342
|
+
theme: MinimalSubagentsWidgetTheme,
|
|
340
343
|
): string[] {
|
|
341
344
|
if (width <= 0) return [];
|
|
342
345
|
const separator = theme.fg("dim", MINIMAL_SUBAGENTS_WIDGET_SEPARATOR_TEXT);
|
|
@@ -376,7 +379,7 @@ class MinimalSubagentsWidgetComponent implements Component {
|
|
|
376
379
|
constructor(
|
|
377
380
|
private view: MinimalSubagentsWidgetView,
|
|
378
381
|
private readonly tui: TUI,
|
|
379
|
-
private readonly theme:
|
|
382
|
+
private readonly theme: MinimalSubagentsWidgetTheme,
|
|
380
383
|
) {}
|
|
381
384
|
|
|
382
385
|
update(view: MinimalSubagentsWidgetView): void {
|