@ian-pascoe/pi-minimal-subagents 0.1.0 → 0.2.0
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 +77 -9
- package/package.json +6 -6
- package/src/minimal-subagents-capabilities.ts +8 -8
- package/src/minimal-subagents-config.ts +222 -73
- package/src/minimal-subagents-context.ts +7 -1
- package/src/minimal-subagents-coordinator.ts +943 -116
- package/src/minimal-subagents-delivery-ledger.ts +529 -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 +1505 -132
- package/src/minimal-subagents-render-contract.ts +301 -0
- package/src/minimal-subagents-rendering.ts +513 -372
- package/src/minimal-subagents-session-wire.ts +42 -0
- package/src/minimal-subagents-sessions.ts +437 -101
- package/src/minimal-subagents-shutdown.ts +1 -1
- package/src/minimal-subagents-tool-schemas.ts +21 -7
- package/src/minimal-subagents-tools.ts +75 -25
- package/src/minimal-subagents-types.ts +76 -21
- package/src/minimal-subagents-ui.ts +214 -23
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentToolResult,
|
|
3
|
+
MessageRenderer,
|
|
4
|
+
ToolDefinition,
|
|
5
|
+
} from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { Type, type Static, type TSchema } from "typebox";
|
|
7
|
+
import { Value } from "typebox/value";
|
|
8
|
+
|
|
9
|
+
/** Names of the six coordinator tools with custom transcript renderers. */
|
|
10
|
+
export type CoordinatorToolName =
|
|
11
|
+
| "subagent"
|
|
12
|
+
| "agent_message"
|
|
13
|
+
| "subagent_wait"
|
|
14
|
+
| "subagent_status"
|
|
15
|
+
| "subagent_cancel"
|
|
16
|
+
| "subagent_delete";
|
|
17
|
+
|
|
18
|
+
const RenderUsageSchema = Type.Object({
|
|
19
|
+
input: Type.Number(),
|
|
20
|
+
output: Type.Number(),
|
|
21
|
+
cacheRead: Type.Number(),
|
|
22
|
+
cacheWrite: Type.Number(),
|
|
23
|
+
cacheWrite1h: Type.Optional(Type.Number()),
|
|
24
|
+
reasoning: Type.Optional(Type.Number()),
|
|
25
|
+
totalTokens: Type.Number(),
|
|
26
|
+
cost: Type.Object({
|
|
27
|
+
input: Type.Number(),
|
|
28
|
+
output: Type.Number(),
|
|
29
|
+
cacheRead: Type.Number(),
|
|
30
|
+
cacheWrite: Type.Number(),
|
|
31
|
+
total: Type.Number(),
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const RenderLaunchContractSchema = Type.Object({
|
|
36
|
+
session_context: Type.Optional(Type.String()),
|
|
37
|
+
project_context: Type.Optional(Type.String()),
|
|
38
|
+
model: Type.Optional(Type.String()),
|
|
39
|
+
thinking_level: Type.Optional(Type.String()),
|
|
40
|
+
delegation: Type.Optional(Type.String()),
|
|
41
|
+
ordinary_tools: Type.Optional(Type.Array(Type.String())),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const RenderTurnResultSchema = Type.Object({
|
|
45
|
+
agent_id: Type.Optional(Type.String()),
|
|
46
|
+
turn_id: Type.Optional(Type.String()),
|
|
47
|
+
status: Type.Optional(Type.String()),
|
|
48
|
+
output: Type.Optional(Type.String()),
|
|
49
|
+
error: Type.Optional(Type.String()),
|
|
50
|
+
usage: Type.Optional(RenderUsageSchema),
|
|
51
|
+
elapsed_ms: Type.Optional(Type.Number()),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const RenderRecentMessageSchema = Type.Object({
|
|
55
|
+
source_agent_id: Type.Optional(Type.String()),
|
|
56
|
+
content: Type.Optional(Type.String()),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
/** Structurally parsed hierarchy status used only by transcript presentation. */
|
|
60
|
+
export const RenderStatusAgentSchema = Type.Object({
|
|
61
|
+
agent_id: Type.Optional(Type.String()),
|
|
62
|
+
parent_id: Type.Optional(Type.String()),
|
|
63
|
+
state: Type.Optional(Type.String()),
|
|
64
|
+
availability: Type.Optional(Type.String()),
|
|
65
|
+
active_turn_id: Type.Optional(Type.String()),
|
|
66
|
+
latest_turn: Type.Optional(
|
|
67
|
+
Type.Object({
|
|
68
|
+
turn_id: Type.Optional(Type.String()),
|
|
69
|
+
status: Type.Optional(Type.String()),
|
|
70
|
+
}),
|
|
71
|
+
),
|
|
72
|
+
tools: Type.Optional(Type.Array(Type.String())),
|
|
73
|
+
elapsed_ms: Type.Optional(Type.Number()),
|
|
74
|
+
model: Type.Optional(Type.String()),
|
|
75
|
+
thinking_level: Type.Optional(Type.String()),
|
|
76
|
+
task: Type.Optional(Type.String()),
|
|
77
|
+
child_count: Type.Optional(Type.Number()),
|
|
78
|
+
session_file: Type.Optional(Type.String()),
|
|
79
|
+
launch_contract: Type.Optional(RenderLaunchContractSchema),
|
|
80
|
+
capability_ceiling: Type.Optional(Type.Array(Type.String())),
|
|
81
|
+
spawn_entry_id: Type.Optional(Type.String()),
|
|
82
|
+
recent_messages: Type.Optional(Type.Array(RenderRecentMessageSchema)),
|
|
83
|
+
latest_result: Type.Optional(RenderTurnResultSchema),
|
|
84
|
+
missing_dependencies: Type.Optional(Type.Array(Type.String())),
|
|
85
|
+
unavailable_reason: Type.Optional(Type.String()),
|
|
86
|
+
usage: Type.Optional(RenderUsageSchema),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const SpawnCallArgumentsSchema = Type.Object({
|
|
90
|
+
task: Type.Optional(Type.String()),
|
|
91
|
+
agent_id: Type.Optional(Type.String()),
|
|
92
|
+
session_context: Type.Optional(Type.String()),
|
|
93
|
+
project_context: Type.Optional(Type.String()),
|
|
94
|
+
model: Type.Optional(Type.String()),
|
|
95
|
+
thinking_level: Type.Optional(Type.String()),
|
|
96
|
+
delegation: Type.Optional(Type.String()),
|
|
97
|
+
});
|
|
98
|
+
const MessageCallArgumentsSchema = Type.Object({
|
|
99
|
+
agent_id: Type.Optional(Type.String()),
|
|
100
|
+
message: Type.Optional(Type.String()),
|
|
101
|
+
behavior: Type.Optional(Type.String()),
|
|
102
|
+
});
|
|
103
|
+
const WaitCallArgumentsSchema = Type.Object({ agent_id: Type.Optional(Type.String()) });
|
|
104
|
+
const StatusCallArgumentsSchema = Type.Object({ agent_id: Type.Optional(Type.String()) });
|
|
105
|
+
const ManagementCallArgumentsSchema = Type.Object({
|
|
106
|
+
agent_id: Type.Optional(Type.String()),
|
|
107
|
+
recursive: Type.Optional(Type.Boolean()),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
/** Tool-call contracts keep each coordinator name correlated with its own arguments. */
|
|
111
|
+
export const coordinatorToolCallSchemas = {
|
|
112
|
+
subagent: SpawnCallArgumentsSchema,
|
|
113
|
+
agent_message: MessageCallArgumentsSchema,
|
|
114
|
+
subagent_wait: WaitCallArgumentsSchema,
|
|
115
|
+
subagent_status: StatusCallArgumentsSchema,
|
|
116
|
+
subagent_cancel: ManagementCallArgumentsSchema,
|
|
117
|
+
subagent_delete: ManagementCallArgumentsSchema,
|
|
118
|
+
} as const satisfies { readonly [Name in CoordinatorToolName]: TSchema };
|
|
119
|
+
|
|
120
|
+
const SpawnDetailsSchema = Type.Object({
|
|
121
|
+
agent_id: Type.String(),
|
|
122
|
+
turn_id: Type.String(),
|
|
123
|
+
status: Type.String(),
|
|
124
|
+
agent: Type.Optional(RenderStatusAgentSchema),
|
|
125
|
+
});
|
|
126
|
+
const CurrentMessageDetailsSchema = Type.Object({
|
|
127
|
+
agent_id: Type.String(),
|
|
128
|
+
message_id: Type.Optional(Type.String()),
|
|
129
|
+
disposition: Type.String(),
|
|
130
|
+
behavior: Type.Optional(Type.String()),
|
|
131
|
+
error: Type.Optional(Type.String()),
|
|
132
|
+
});
|
|
133
|
+
const LegacyMessageDetailsSchema = Type.Object({
|
|
134
|
+
agent_id: Type.String(),
|
|
135
|
+
message_id: Type.Optional(Type.String()),
|
|
136
|
+
delivered: Type.Boolean(),
|
|
137
|
+
behavior: Type.Optional(Type.String()),
|
|
138
|
+
error: Type.Optional(Type.String()),
|
|
139
|
+
});
|
|
140
|
+
const WaitMessageDetailsSchema = Type.Object({
|
|
141
|
+
event: Type.Literal("message"),
|
|
142
|
+
agent_id: Type.String(),
|
|
143
|
+
turn_id: Type.String(),
|
|
144
|
+
message_id: Type.String(),
|
|
145
|
+
message: Type.String(),
|
|
146
|
+
elapsed_ms: Type.Optional(Type.Number()),
|
|
147
|
+
usage: Type.Optional(RenderUsageSchema),
|
|
148
|
+
});
|
|
149
|
+
const WaitTurnDetailsSchema = Type.Object({
|
|
150
|
+
event: Type.Optional(Type.Literal("turn")),
|
|
151
|
+
agent_id: Type.String(),
|
|
152
|
+
turn_id: Type.Optional(Type.String()),
|
|
153
|
+
status: Type.String(),
|
|
154
|
+
output: Type.Optional(Type.String()),
|
|
155
|
+
error: Type.Optional(Type.String()),
|
|
156
|
+
elapsed_ms: Type.Optional(Type.Number()),
|
|
157
|
+
usage: Type.Optional(RenderUsageSchema),
|
|
158
|
+
});
|
|
159
|
+
const StatusDetailsSchema = Type.Union([
|
|
160
|
+
Type.Object({
|
|
161
|
+
parent_id: Type.Optional(Type.String()),
|
|
162
|
+
agents: Type.Array(RenderStatusAgentSchema),
|
|
163
|
+
}),
|
|
164
|
+
Type.Object({ agent: RenderStatusAgentSchema }),
|
|
165
|
+
]);
|
|
166
|
+
const CancelDetailsSchema = Type.Object({
|
|
167
|
+
agent_id: Type.String(),
|
|
168
|
+
recursive: Type.Boolean(),
|
|
169
|
+
affected_agent_ids: Type.Array(Type.String()),
|
|
170
|
+
cancelled_turn_ids: Type.Array(Type.String()),
|
|
171
|
+
});
|
|
172
|
+
const DeleteDetailsSchema = Type.Object({
|
|
173
|
+
agent_id: Type.String(),
|
|
174
|
+
recursive: Type.Boolean(),
|
|
175
|
+
deleted_agent_ids: Type.Array(Type.String()),
|
|
176
|
+
tombstoned_agent_ids: Type.Array(Type.String()),
|
|
177
|
+
trashed_session_files: Type.Array(Type.String()),
|
|
178
|
+
failures: Type.Array(
|
|
179
|
+
Type.Object({
|
|
180
|
+
agent_id: Type.String(),
|
|
181
|
+
error: Type.String(),
|
|
182
|
+
}),
|
|
183
|
+
),
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
/** Result-detail contracts keep current and tolerated legacy transcript shapes explicit. */
|
|
187
|
+
export const coordinatorToolResultSchemas = {
|
|
188
|
+
subagent: SpawnDetailsSchema,
|
|
189
|
+
agent_message: Type.Union([CurrentMessageDetailsSchema, LegacyMessageDetailsSchema]),
|
|
190
|
+
subagent_wait: Type.Union([WaitMessageDetailsSchema, WaitTurnDetailsSchema]),
|
|
191
|
+
subagent_status: StatusDetailsSchema,
|
|
192
|
+
subagent_cancel: CancelDetailsSchema,
|
|
193
|
+
subagent_delete: DeleteDetailsSchema,
|
|
194
|
+
} as const satisfies { readonly [Name in CoordinatorToolName]: TSchema };
|
|
195
|
+
|
|
196
|
+
export type SpawnCallArguments = Static<typeof SpawnCallArgumentsSchema>;
|
|
197
|
+
export type MessageCallArguments = Static<typeof MessageCallArgumentsSchema>;
|
|
198
|
+
export type WaitCallArguments = Static<typeof WaitCallArgumentsSchema>;
|
|
199
|
+
export type StatusCallArguments = Static<typeof StatusCallArgumentsSchema>;
|
|
200
|
+
export type ManagementCallArguments = Static<typeof ManagementCallArgumentsSchema>;
|
|
201
|
+
export type SpawnRenderDetails = Static<typeof SpawnDetailsSchema>;
|
|
202
|
+
export type MessageRenderDetails = Static<
|
|
203
|
+
typeof CurrentMessageDetailsSchema | typeof LegacyMessageDetailsSchema
|
|
204
|
+
>;
|
|
205
|
+
export type WaitRenderDetails = Static<
|
|
206
|
+
typeof WaitMessageDetailsSchema | typeof WaitTurnDetailsSchema
|
|
207
|
+
>;
|
|
208
|
+
export type StatusRenderDetails = Static<typeof StatusDetailsSchema>;
|
|
209
|
+
export type CancelRenderDetails = Static<typeof CancelDetailsSchema>;
|
|
210
|
+
export type DeleteRenderDetails = Static<typeof DeleteDetailsSchema>;
|
|
211
|
+
export type RenderStatusAgent = Static<typeof RenderStatusAgentSchema>;
|
|
212
|
+
|
|
213
|
+
/** Raw tool arguments supplied by Pi's tool-rendering interface. */
|
|
214
|
+
export type CoordinatorToolCallInput = Parameters<NonNullable<ToolDefinition["renderCall"]>>[0];
|
|
215
|
+
|
|
216
|
+
type CoordinatorMessageInput = Parameters<MessageRenderer>[0];
|
|
217
|
+
|
|
218
|
+
/** Parsed tool-call arguments tagged by their coordinator tool name. */
|
|
219
|
+
export type ParsedCoordinatorToolCall =
|
|
220
|
+
| { toolName: "subagent"; args: SpawnCallArguments }
|
|
221
|
+
| { toolName: "agent_message"; args: MessageCallArguments }
|
|
222
|
+
| { toolName: "subagent_wait"; args: WaitCallArguments }
|
|
223
|
+
| { toolName: "subagent_status"; args: StatusCallArguments }
|
|
224
|
+
| { toolName: "subagent_cancel"; args: ManagementCallArguments }
|
|
225
|
+
| { toolName: "subagent_delete"; args: ManagementCallArguments };
|
|
226
|
+
|
|
227
|
+
/** Parsed result details tagged by their coordinator tool name. */
|
|
228
|
+
export type ParsedCoordinatorToolResult =
|
|
229
|
+
| { toolName: "subagent"; details: SpawnRenderDetails }
|
|
230
|
+
| { toolName: "agent_message"; details: MessageRenderDetails }
|
|
231
|
+
| { toolName: "subagent_wait"; details: WaitRenderDetails }
|
|
232
|
+
| { toolName: "subagent_status"; details: StatusRenderDetails }
|
|
233
|
+
| { toolName: "subagent_cancel"; details: CancelRenderDetails }
|
|
234
|
+
| { toolName: "subagent_delete"; details: DeleteRenderDetails };
|
|
235
|
+
|
|
236
|
+
/** Parse one historical tool call without coercing or cleaning its captured arguments. */
|
|
237
|
+
export function parseCoordinatorToolCall(
|
|
238
|
+
toolName: CoordinatorToolName,
|
|
239
|
+
args: CoordinatorToolCallInput,
|
|
240
|
+
): ParsedCoordinatorToolCall | undefined {
|
|
241
|
+
switch (toolName) {
|
|
242
|
+
case "subagent":
|
|
243
|
+
return Value.Check(SpawnCallArgumentsSchema, args) ? { toolName, args } : undefined;
|
|
244
|
+
case "agent_message":
|
|
245
|
+
return Value.Check(MessageCallArgumentsSchema, args) ? { toolName, args } : undefined;
|
|
246
|
+
case "subagent_wait":
|
|
247
|
+
return Value.Check(WaitCallArgumentsSchema, args) ? { toolName, args } : undefined;
|
|
248
|
+
case "subagent_status":
|
|
249
|
+
return Value.Check(StatusCallArgumentsSchema, args) ? { toolName, args } : undefined;
|
|
250
|
+
case "subagent_cancel":
|
|
251
|
+
return Value.Check(ManagementCallArgumentsSchema, args) ? { toolName, args } : undefined;
|
|
252
|
+
case "subagent_delete":
|
|
253
|
+
return Value.Check(ManagementCallArgumentsSchema, args) ? { toolName, args } : undefined;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Parse one historical tool result exactly once at the transcript rendering boundary. */
|
|
258
|
+
export function parseCoordinatorToolResult(
|
|
259
|
+
toolName: CoordinatorToolName,
|
|
260
|
+
details: AgentToolResult<unknown>["details"],
|
|
261
|
+
): ParsedCoordinatorToolResult | undefined {
|
|
262
|
+
switch (toolName) {
|
|
263
|
+
case "subagent":
|
|
264
|
+
return Value.Check(SpawnDetailsSchema, details) ? { toolName, details } : undefined;
|
|
265
|
+
case "agent_message":
|
|
266
|
+
return Value.Check(coordinatorToolResultSchemas.agent_message, details)
|
|
267
|
+
? { toolName, details }
|
|
268
|
+
: undefined;
|
|
269
|
+
case "subagent_wait":
|
|
270
|
+
return Value.Check(coordinatorToolResultSchemas.subagent_wait, details)
|
|
271
|
+
? { toolName, details }
|
|
272
|
+
: undefined;
|
|
273
|
+
case "subagent_status":
|
|
274
|
+
return Value.Check(StatusDetailsSchema, details) ? { toolName, details } : undefined;
|
|
275
|
+
case "subagent_cancel":
|
|
276
|
+
return Value.Check(CancelDetailsSchema, details) ? { toolName, details } : undefined;
|
|
277
|
+
case "subagent_delete":
|
|
278
|
+
return Value.Check(DeleteDetailsSchema, details) ? { toolName, details } : undefined;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** Coordinator message metadata accepted from current and historical Pi transcripts. */
|
|
283
|
+
export const CoordinatorMessageRenderDetailsSchema = Type.Object({
|
|
284
|
+
source_agent_id: Type.Optional(Type.String()),
|
|
285
|
+
destination_agent_id: Type.Optional(Type.String()),
|
|
286
|
+
source_turn_id: Type.Optional(Type.String()),
|
|
287
|
+
agent_id: Type.Optional(Type.String()),
|
|
288
|
+
turn_id: Type.Optional(Type.String()),
|
|
289
|
+
status: Type.Optional(Type.String()),
|
|
290
|
+
elapsed_ms: Type.Optional(Type.Number()),
|
|
291
|
+
usage: Type.Optional(RenderUsageSchema),
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
export type CoordinatorMessageRenderDetails = Static<typeof CoordinatorMessageRenderDetailsSchema>;
|
|
295
|
+
|
|
296
|
+
/** Parse optional custom-message details while tolerating legacy field names. */
|
|
297
|
+
export function parseCoordinatorMessageDetails(
|
|
298
|
+
details: CoordinatorMessageInput["details"],
|
|
299
|
+
): CoordinatorMessageRenderDetails | undefined {
|
|
300
|
+
return Value.Check(CoordinatorMessageRenderDetailsSchema, details) ? details : undefined;
|
|
301
|
+
}
|