@pasko70/pibo 2.2.5 → 2.4.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.
Files changed (43) hide show
  1. package/dist/agent-runtime/context-build.js +5 -2
  2. package/dist/agent-runtimes/pi/adapter.js +1 -1
  3. package/dist/agent-runtimes/pi/runtime.js +25 -16
  4. package/dist/apps/chat-ui/assets/{dist-BK7eaoLT.js → dist-Byygd1lH.js} +1 -1
  5. package/dist/apps/chat-ui/assets/{dist-fNgdnmyE.js → dist-C9BrS7sL.js} +1 -1
  6. package/dist/apps/chat-ui/assets/{dist-wq3P0LZj.js → dist-CUcAofmV.js} +1 -1
  7. package/dist/apps/chat-ui/assets/{dist-BCRR_a0Z.js → dist-D4RU6xu3.js} +1 -1
  8. package/dist/apps/chat-ui/assets/{dist-CTUT484B.js → dist-DusFwy0L.js} +1 -1
  9. package/dist/apps/chat-ui/assets/{index-DsFKL_EZ.js → index-Bifi_kjN.js} +90 -90
  10. package/dist/apps/chat-ui/index.html +1 -1
  11. package/dist/apps/chat-vscode-web/assets/{index-R4FTxr78.js → index-WsLm1mo3.js} +5 -5
  12. package/dist/apps/chat-vscode-web/index.html +1 -1
  13. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  14. package/dist/apps/vscode-artifacts/{pibo-vscode-ext-2.2.5.vsix → pibo-vscode-ext-2.4.0.vsix} +0 -0
  15. package/dist/compute/cli.js +13 -0
  16. package/dist/compute/pool/artifacts.js +116 -0
  17. package/dist/compute/pool/cli.js +156 -0
  18. package/dist/compute/pool/config.js +101 -0
  19. package/dist/compute/pool/docker.js +157 -0
  20. package/dist/compute/pool/seeds.js +201 -0
  21. package/dist/compute/pool/service.js +402 -0
  22. package/dist/compute/pool/store.js +239 -0
  23. package/dist/compute/pool/types.js +1 -0
  24. package/dist/core/codex-compat.js +1 -3
  25. package/dist/core/context-build.js +16 -7
  26. package/dist/core/session-router.js +221 -45
  27. package/dist/data/ingest-service.js +12 -0
  28. package/dist/debug/agents.js +391 -0
  29. package/dist/debug/index.js +7 -0
  30. package/dist/index.js +1 -1
  31. package/dist/resources/lifecycle.js +22 -2
  32. package/dist/resources/reaper.js +1 -0
  33. package/dist/session-ui/delegation.js +4 -2
  34. package/dist/shared/trace-async-agent-runs.js +4 -2
  35. package/dist/shared/trace-event-projection.js +8 -2
  36. package/dist/shared/trace-subagent-links.js +19 -6
  37. package/dist/subagents/observations.js +149 -0
  38. package/dist/subagents/tool.js +177 -46
  39. package/dist/tools/session-service.js +1 -0
  40. package/dist/tools/session-tool-set.js +9 -5
  41. package/dist/web/channel.js +9 -3
  42. package/npm-shrinkwrap.json +2 -2
  43. package/package.json +1 -1
@@ -0,0 +1,391 @@
1
+ import { normalizePiboAgentObservationCursor, normalizePiboAgentObservationLimit, normalizePiboAgentObservationOrder, parsePiboAgentObservationTimestamp, piboAgentObservationDetails, piboAgentObservationKind, piboAgentObservationRole, piboAgentObservationText, } from "../subagents/observations.js";
2
+ import { createDebugPayloadStore, hydrateDebugEventRow } from "./persisted-payloads.js";
3
+ import { eventAttributes, eventPayload } from "./payloads.js";
4
+ import { openReadOnlyDebugDatabase, withStorePath } from "./sql.js";
5
+ import { resolveDebugStore } from "./stores.js";
6
+ export async function runDebugAgentsCli(args) {
7
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
8
+ printDebugAgentsDiscovery();
9
+ return;
10
+ }
11
+ const parentPiboSessionId = args[0];
12
+ const command = args[1];
13
+ if (!command || command === "--help" || command === "-h") {
14
+ printDebugAgentsDiscovery(parentPiboSessionId);
15
+ return;
16
+ }
17
+ if (command !== "list" && command !== "observe") {
18
+ throw new Error(`Unknown pibo debug agents command "${command}". Run pibo debug agents ${parentPiboSessionId} --help.`);
19
+ }
20
+ if (args.slice(2).some((arg) => arg === "--help" || arg === "-h")) {
21
+ printDebugAgentsCommandHelp(parentPiboSessionId, command);
22
+ return;
23
+ }
24
+ const parsed = parseAgentDebugOptions(args.slice(2));
25
+ validateAgentDebugOptions(command, parsed);
26
+ const store = resolveDebugStore("pibo-data");
27
+ if (command === "list") {
28
+ const agents = inspectDebugAgentList(parentPiboSessionId, store, {
29
+ name: parsed.names[0],
30
+ status: parsed.status,
31
+ });
32
+ if (parsed.json)
33
+ console.log(JSON.stringify({ parentPiboSessionId, agents }, null, 2));
34
+ else
35
+ console.log(formatDebugAgentList(parentPiboSessionId, agents));
36
+ return;
37
+ }
38
+ const result = inspectDebugAgentObservations(parentPiboSessionId, store, {
39
+ agentIds: parsed.agentIds.length ? parsed.agentIds : undefined,
40
+ names: parsed.names.length ? parsed.names : undefined,
41
+ threadKeys: parsed.threadKeys.length ? parsed.threadKeys : undefined,
42
+ eventTypes: parsed.eventTypes.length ? parsed.eventTypes : undefined,
43
+ kinds: parsed.kinds.length ? parsed.kinds : undefined,
44
+ since: parsed.since,
45
+ until: parsed.until,
46
+ textContains: parsed.textContains,
47
+ afterSequence: parsed.afterSequence,
48
+ order: parsed.order,
49
+ limit: parsed.limit,
50
+ includeDetails: parsed.details,
51
+ });
52
+ if (parsed.json)
53
+ console.log(JSON.stringify(result, null, 2));
54
+ else
55
+ console.log(formatDebugAgentObservations(result));
56
+ }
57
+ export function inspectDebugAgentList(parentPiboSessionId, store, options = {}) {
58
+ if (!store.exists)
59
+ throw new Error(`Debug store "pibo-data" not found at ${store.path}`);
60
+ const db = openReadOnlyDebugDatabase(store);
61
+ try {
62
+ return readOwnedAgents(db, parentPiboSessionId)
63
+ .filter((agent) => !options.name || agent.name === options.name)
64
+ .filter((agent) => !options.status || agent.status === options.status);
65
+ }
66
+ catch (error) {
67
+ throw withStorePath(error, store);
68
+ }
69
+ finally {
70
+ db.close();
71
+ }
72
+ }
73
+ export function inspectDebugAgentObservations(parentPiboSessionId, store, input = {}) {
74
+ if (!store.exists)
75
+ throw new Error(`Debug store "pibo-data" not found at ${store.path}`);
76
+ const db = openReadOnlyDebugDatabase(store);
77
+ try {
78
+ const order = normalizePiboAgentObservationOrder(input.order);
79
+ const limit = normalizePiboAgentObservationLimit(input.limit);
80
+ const afterSequence = normalizePiboAgentObservationCursor(input.afterSequence);
81
+ const since = parsePiboAgentObservationTimestamp(input.since, "since");
82
+ const until = parsePiboAgentObservationTimestamp(input.until, "until");
83
+ if (since !== undefined && until !== undefined && since > until)
84
+ throw new Error("Agent observation since must not be after until.");
85
+ const owned = readOwnedAgents(db, parentPiboSessionId);
86
+ const ownedById = new Map(owned.map((agent) => [agent.agentId, agent]));
87
+ for (const agentId of input.agentIds ?? []) {
88
+ if (!ownedById.has(agentId))
89
+ throw new Error(`Agent "${agentId}" is not owned by Pibo session "${parentPiboSessionId}".`);
90
+ }
91
+ const agentIds = input.agentIds ? new Set(input.agentIds) : undefined;
92
+ const names = input.names ? new Set(input.names) : undefined;
93
+ const threadKeys = input.threadKeys ? new Set(input.threadKeys) : undefined;
94
+ const eventTypes = input.eventTypes ? new Set(input.eventTypes) : undefined;
95
+ const kinds = input.kinds ? new Set(input.kinds) : undefined;
96
+ const payloadStore = createDebugPayloadStore(db, store);
97
+ const clauses = ["s.parent_id = ?", "s.channel = 'pibo.subagents'", "s.kind = 'subagent'", "s.deleted_at IS NULL"];
98
+ const values = [parentPiboSessionId];
99
+ if (afterSequence !== undefined) {
100
+ clauses.push("e.stream_id > ?");
101
+ values.push(afterSequence);
102
+ }
103
+ const scanOrder = afterSequence !== undefined ? "ASC" : order.toUpperCase();
104
+ const statement = db.prepare(`
105
+ SELECT e.stream_id, e.session_id, e.session_sequence, e.event_id, e.type, e.created_at,
106
+ e.payload_ref, e.preview_text, e.attributes_json, s.profile, s.metadata_json
107
+ FROM event_log e
108
+ JOIN sessions s ON s.id = e.session_id
109
+ WHERE ${clauses.join(" AND ")}
110
+ ORDER BY e.stream_id ${scanOrder}
111
+ `);
112
+ const textContains = input.textContains?.toLowerCase();
113
+ const matches = [];
114
+ for (const rawRow of statement.iterate(...values)) {
115
+ const agent = ownedById.get(rawRow.session_id ?? "");
116
+ if (!agent)
117
+ continue;
118
+ if (agentIds && !agentIds.has(agent.agentId))
119
+ continue;
120
+ if (names && !names.has(agent.name))
121
+ continue;
122
+ if (threadKeys && (!agent.threadKey || !threadKeys.has(agent.threadKey)))
123
+ continue;
124
+ if (eventTypes && !eventTypes.has(rawRow.type))
125
+ continue;
126
+ const kind = piboAgentObservationKind(rawRow.type);
127
+ if (kinds && !kinds.has(kind))
128
+ continue;
129
+ const createdAt = Date.parse(rawRow.created_at);
130
+ if (since !== undefined && createdAt < since)
131
+ continue;
132
+ if (until !== undefined && createdAt > until)
133
+ continue;
134
+ const row = hydrateDebugEventRow(rawRow, payloadStore);
135
+ const attributes = eventAttributes(row);
136
+ const payload = { ...attributes, ...eventPayload(row) };
137
+ const source = debugAgentObservationSource(row, attributes);
138
+ const text = piboAgentObservationText(source);
139
+ if (textContains && !(text ?? "").toLowerCase().includes(textContains))
140
+ continue;
141
+ const role = piboAgentObservationRole(source);
142
+ matches.push({
143
+ streamId: row.stream_id,
144
+ createdAt: row.created_at,
145
+ agentId: agent.agentId,
146
+ name: agent.name,
147
+ ...(agent.threadKey ? { threadKey: agent.threadKey } : {}),
148
+ eventType: row.type,
149
+ kind,
150
+ ...(role ? { role } : {}),
151
+ ...(text ? { text } : {}),
152
+ ...(typeof payload.toolName === "string" ? { toolName: payload.toolName } : {}),
153
+ ...(typeof payload.toolCallId === "string" ? { toolCallId: payload.toolCallId } : {}),
154
+ ...(row.type === "tool_execution_finished" ? { isError: payload.isError === true } : row.type === "session_error" ? { isError: true } : {}),
155
+ ...(input.includeDetails === true ? { details: piboAgentObservationDetails(debugAgentObservationDetails(row, payload)) } : {}),
156
+ });
157
+ if (matches.length > limit)
158
+ break;
159
+ }
160
+ const truncated = matches.length > limit;
161
+ const observations = matches.slice(0, limit);
162
+ if (afterSequence !== undefined && order === "desc")
163
+ observations.reverse();
164
+ return {
165
+ parentPiboSessionId,
166
+ filters: {
167
+ ...input,
168
+ ...(afterSequence !== undefined ? { afterSequence } : {}),
169
+ order,
170
+ limit,
171
+ includeDetails: input.includeDetails === true,
172
+ },
173
+ observations,
174
+ nextAfterSequence: observations.reduce((maximum, observation) => Math.max(maximum, observation.streamId), afterSequence ?? 0),
175
+ truncated,
176
+ };
177
+ }
178
+ catch (error) {
179
+ throw withStorePath(error, store);
180
+ }
181
+ finally {
182
+ db.close();
183
+ }
184
+ }
185
+ function readOwnedAgents(db, parentPiboSessionId) {
186
+ const rows = db.prepare(`
187
+ SELECT id, profile, status, metadata_json, active_model_json, created_at, updated_at
188
+ FROM sessions
189
+ WHERE parent_id = ? AND channel = 'pibo.subagents' AND kind = 'subagent' AND deleted_at IS NULL
190
+ ORDER BY updated_at DESC
191
+ `).all(parentPiboSessionId);
192
+ return rows.map((row) => {
193
+ const metadata = parseObject(row.metadata_json);
194
+ const killed = metadata.agentStatus === "killed";
195
+ return {
196
+ agentId: row.id,
197
+ name: typeof metadata.subagentName === "string" ? metadata.subagentName : row.profile,
198
+ profile: row.profile,
199
+ ...(typeof metadata.threadKey === "string" ? { threadKey: metadata.threadKey } : {}),
200
+ status: killed ? "killed" : isRunningStatus(row.status) ? "running" : "idle",
201
+ createdAt: row.created_at,
202
+ updatedAt: row.updated_at,
203
+ ...(row.active_model_json ? { activeModel: JSON.parse(row.active_model_json) } : {}),
204
+ };
205
+ });
206
+ }
207
+ function debugAgentObservationSource(row, attributes) {
208
+ const inlinePayload = attributes.inlinePayload;
209
+ const source = {
210
+ eventType: row.type,
211
+ fallbackText: row.preview_text ?? row.type,
212
+ ...(typeof attributes.source === "string" ? { source: attributes.source } : {}),
213
+ };
214
+ if (row.type === "message_queued" || row.type === "message_steered" || row.type === "message_started") {
215
+ source.text = typeof attributes.inlineText === "string" ? attributes.inlineText : row.preview_text ?? undefined;
216
+ }
217
+ else if (row.type === "assistant_message" || row.type === "assistant_delta" || row.type === "thinking_delta" || row.type === "thinking_finished") {
218
+ source.text = typeof inlinePayload === "string" ? inlinePayload : row.preview_text ?? undefined;
219
+ }
220
+ else if (row.type === "session_error") {
221
+ source.error = attributes.error;
222
+ }
223
+ else if (row.type === "tool_call" || row.type === "tool_execution_started") {
224
+ source.args = inlinePayload;
225
+ }
226
+ else if (row.type === "tool_execution_updated") {
227
+ source.partialResult = inlinePayload;
228
+ }
229
+ else if (row.type === "tool_execution_finished" || row.type === "execution_result" || row.type === "compaction_end") {
230
+ source.result = inlinePayload;
231
+ }
232
+ if (row.type === "execution_result")
233
+ source.action = attributes.action;
234
+ if (row.type === "compaction_start" || row.type === "compaction_end")
235
+ source.reason = attributes.reason;
236
+ if (row.type === "subagent_session")
237
+ source.subagentName = attributes.subagentName;
238
+ return source;
239
+ }
240
+ function debugAgentObservationDetails(row, payload) {
241
+ return {
242
+ type: row.type,
243
+ ...(row.session_id ? { piboSessionId: row.session_id } : {}),
244
+ ...(row.event_id ? { eventId: row.event_id } : {}),
245
+ ...payload,
246
+ };
247
+ }
248
+ function parseObject(value) {
249
+ try {
250
+ const parsed = JSON.parse(value);
251
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
252
+ }
253
+ catch {
254
+ return {};
255
+ }
256
+ }
257
+ function isRunningStatus(status) {
258
+ return ["running", "streaming", "queued", "starting", "waiting", "blocked", "retrying"].includes(status);
259
+ }
260
+ function formatDebugAgentList(parentPiboSessionId, agents) {
261
+ if (agents.length === 0)
262
+ return `parent: ${parentPiboSessionId}\nagents: 0`;
263
+ return [
264
+ `parent: ${parentPiboSessionId}`,
265
+ "agentId\tname\tprofile\tthreadKey\tstatus\tupdatedAt",
266
+ ...agents.map((agent) => `${agent.agentId}\t${agent.name}\t${agent.profile}\t${agent.threadKey ?? ""}\t${agent.status}\t${agent.updatedAt}`),
267
+ `agents: ${agents.length}`,
268
+ ].join("\n");
269
+ }
270
+ function formatDebugAgentObservations(result) {
271
+ if (result.observations.length === 0)
272
+ return `parent: ${result.parentPiboSessionId}\nobservations: 0\nnextAfterSequence: ${result.nextAfterSequence}`;
273
+ return [
274
+ `parent: ${result.parentPiboSessionId}`,
275
+ "streamId\tcreatedAt\tagentId\tname\teventType\tkind\ttext",
276
+ ...result.observations.map((observation) => `${observation.streamId}\t${observation.createdAt}\t${observation.agentId}\t${observation.name}\t${observation.eventType}\t${observation.kind}\t${(observation.text ?? "").replaceAll("\n", "\\n")}`),
277
+ `observations: ${result.observations.length}${result.truncated ? " (limited)" : ""}`,
278
+ `nextAfterSequence: ${result.nextAfterSequence}`,
279
+ ].join("\n");
280
+ }
281
+ function printDebugAgentsDiscovery(parentPiboSessionId = "<parent-session-id>") {
282
+ console.log(`pibo debug agents - inspect delegated child agents
283
+
284
+ Usage:
285
+ pibo debug agents ${parentPiboSessionId} <command>
286
+
287
+ Commands:
288
+ list List child agents owned by the parent session.
289
+ observe Read persisted child-agent observations.
290
+
291
+ Next:
292
+ pibo debug agents ${parentPiboSessionId} list --help
293
+ pibo debug agents ${parentPiboSessionId} observe --help
294
+ `);
295
+ }
296
+ function printDebugAgentsCommandHelp(parentPiboSessionId, command) {
297
+ if (command === "list") {
298
+ console.log(`pibo debug agents ${parentPiboSessionId} list
299
+
300
+ Usage:
301
+ pibo debug agents ${parentPiboSessionId} list [--name name] [--status running|idle|killed] [--json]
302
+
303
+ Filters use exact values. The command inspects only direct pibo.subagents children owned by the parent session.`);
304
+ return;
305
+ }
306
+ console.log(`pibo debug agents ${parentPiboSessionId} observe
307
+
308
+ Usage:
309
+ pibo debug agents ${parentPiboSessionId} observe [--agent-id ps_...] [--name name] [--thread-key key]
310
+ [--event-type type] [--kind message|thinking|tool|error|lifecycle|event]
311
+ [--since iso] [--until iso] [--contains text] [--after-sequence n]
312
+ [--order asc|desc] [--limit 1..200] [--details] [--json]
313
+
314
+ Repeat --agent-id, --name, --thread-key, --event-type, or --kind for OR within that field.
315
+ Different fields combine with AND. With --after-sequence, pages always consume the oldest unseen rows;
316
+ --order desc reverses only the returned page, so nextAfterSequence remains safe for polling.`);
317
+ }
318
+ function parseAgentDebugOptions(args) {
319
+ const parsed = { json: false, details: false, agentIds: [], names: [], threadKeys: [], eventTypes: [], kinds: [] };
320
+ for (let index = 0; index < args.length; index += 1) {
321
+ const arg = args[index];
322
+ if (arg === "--json") {
323
+ parsed.json = true;
324
+ continue;
325
+ }
326
+ if (arg === "--details") {
327
+ parsed.details = true;
328
+ continue;
329
+ }
330
+ const value = args[index + 1];
331
+ if (!value)
332
+ throw new Error(`${arg} requires a value`);
333
+ if (arg === "--agent-id")
334
+ parsed.agentIds.push(value);
335
+ else if (arg === "--name")
336
+ parsed.names.push(value);
337
+ else if (arg === "--thread-key")
338
+ parsed.threadKeys.push(value);
339
+ else if (arg === "--event-type")
340
+ parsed.eventTypes.push(value);
341
+ else if (arg === "--kind") {
342
+ if (!["message", "thinking", "tool", "error", "lifecycle", "event"].includes(value))
343
+ throw new Error(`Invalid --kind "${value}"`);
344
+ parsed.kinds.push(value);
345
+ }
346
+ else if (arg === "--status") {
347
+ if (!["running", "idle", "killed"].includes(value))
348
+ throw new Error(`Invalid --status "${value}"`);
349
+ parsed.status = value;
350
+ }
351
+ else if (arg === "--since")
352
+ parsed.since = value;
353
+ else if (arg === "--until")
354
+ parsed.until = value;
355
+ else if (arg === "--contains")
356
+ parsed.textContains = value;
357
+ else if (arg === "--after-sequence")
358
+ parsed.afterSequence = parseNonNegativeInteger(value, arg);
359
+ else if (arg === "--order") {
360
+ if (value !== "asc" && value !== "desc")
361
+ throw new Error(`Invalid --order "${value}"`);
362
+ parsed.order = value;
363
+ }
364
+ else if (arg === "--limit")
365
+ parsed.limit = normalizePiboAgentObservationLimit(parseNonNegativeInteger(value, arg));
366
+ else
367
+ throw new Error(`Unknown pibo debug agents option "${arg}"`);
368
+ index += 1;
369
+ }
370
+ return parsed;
371
+ }
372
+ function validateAgentDebugOptions(command, parsed) {
373
+ if (command === "list") {
374
+ if (parsed.names.length > 1)
375
+ throw new Error("pibo debug agents list accepts at most one --name value");
376
+ if (parsed.details || parsed.agentIds.length > 0 || parsed.threadKeys.length > 0 || parsed.eventTypes.length > 0
377
+ || parsed.kinds.length > 0 || parsed.since !== undefined || parsed.until !== undefined
378
+ || parsed.textContains !== undefined || parsed.afterSequence !== undefined || parsed.order !== undefined
379
+ || parsed.limit !== undefined)
380
+ throw new Error("Unsupported option for pibo debug agents list. Run the list command with --help.");
381
+ return;
382
+ }
383
+ if (parsed.status !== undefined)
384
+ throw new Error("--status is supported only by pibo debug agents list");
385
+ }
386
+ function parseNonNegativeInteger(value, option) {
387
+ const parsed = Number(value);
388
+ if (!Number.isInteger(parsed) || parsed < 0)
389
+ throw new Error(`${option} requires a non-negative integer`);
390
+ return parsed;
391
+ }
@@ -44,6 +44,11 @@ export async function runDebugCli(argv = process.argv) {
44
44
  await runDebugEvents(args.slice(1));
45
45
  return;
46
46
  }
47
+ if (args[0] === "agents") {
48
+ const { runDebugAgentsCli } = await import("./agents.js");
49
+ await runDebugAgentsCli(args.slice(1));
50
+ return;
51
+ }
47
52
  if (args[0] === "jobs") {
48
53
  await runDebugJobs(args.slice(1));
49
54
  return;
@@ -1050,6 +1055,7 @@ Commands:
1050
1055
  final Show the latest assistant message
1051
1056
  trace Rebuild the Chat Web trace view for one Pibo Session
1052
1057
  events Inspect compact event payload fields for one Pibo Session
1058
+ agents Inspect delegated child agents and their persisted activity
1053
1059
  tool Inspect one grouped tool call
1054
1060
  failures List failed tool calls and trace/session errors
1055
1061
  jobs Inspect durable Pibo jobs and DLQ
@@ -1067,6 +1073,7 @@ Next:
1067
1073
  pibo debug messages <pibo-session-id> list
1068
1074
  pibo debug trace <pibo-session-id> --running-only
1069
1075
  pibo debug events stream --topic pibo.output
1076
+ pibo debug agents <parent-session-id> list
1070
1077
  pibo debug resources --json
1071
1078
  pibo debug signals tree ps_...
1072
1079
  pibo debug telemetry sessions --active
package/dist/index.js CHANGED
@@ -41,7 +41,7 @@ export { runGatewayClient } from "./gateway/client.js";
41
41
  export { LOCAL_TUI_CHANNEL_NAME, LocalRoutedTuiClient, createLocalRoutedTuiClient, createLocalRoutedTuiExtension, runLocalRoutedTui, } from "./local/tui.js";
42
42
  export { createWebHostChannel, DEFAULT_WEB_CHANNEL_HOST, DEFAULT_WEB_CHANNEL_PORT, WEB_CHANNEL_NAME } from "./web/channel.js";
43
43
  export { sendGatewayEvent, sendGatewayMessageAndWaitForReply } from "./gateway/request.js";
44
- export { createSubagentToolDefinitions, createSubagentToolName, } from "./subagents/tool.js";
44
+ export { createAgentToolDefinitions, createSubagentToolDefinitions, createSubagentToolName, formatAvailableAgentsForPrompt, listAvailableAgents, PIBO_AGENT_TOOL_NAMES, } from "./subagents/tool.js";
45
45
  export { PiboSteeringUnavailableError } from "./core/events.js";
46
46
  export { RuntimeSessionBindingConflictError, RuntimeSessionBindingTransitionError, assertRuntimeSessionBindingTransition, createInitialRuntimeSessionBinding, createLegacyPiRuntimeSessionBinding, nextRuntimeSessionBinding, } from "./sessions/runtime-binding.js";
47
47
  export { InMemoryPiboSessionStore, createPiSessionId, createPiboSessionId, createPiboSession, } from "./sessions/store.js";
@@ -6,6 +6,8 @@ import { promisify } from "node:util";
6
6
  import { applyComputeWorkerReapPlan, buildComputeWorkerReapPlan, planReapWorkers, } from "../compute/docker.js";
7
7
  import { defaultBrowserPoolRoot, defaultBrowserUseHome, getComputeResourceHealth, parseProcessList, } from "../compute/resource-health.js";
8
8
  import { loadBrowserPoolState, reapIdleBrowserPool, } from "../tools/browser-pool.js";
9
+ import { resolveDeploymentPoolConfig } from "../compute/pool/config.js";
10
+ import { applyDeploymentPoolReapPlan, planDeploymentPoolReap } from "../compute/pool/service.js";
9
11
  const execFileAsync = promisify(execFile);
10
12
  export async function collectManagedBrowserPools(rootDir) {
11
13
  const records = [];
@@ -56,7 +58,7 @@ export async function getActiveResourceLeases(browserPoolRoot = defaultBrowserPo
56
58
  export async function planResourceReap(options = {}) {
57
59
  const now = options.now ?? new Date();
58
60
  const resolved = resolveReapOptions(options);
59
- const [records, staleFiles, compute, health] = await Promise.all([
61
+ const [records, staleFiles, compute, health, deploymentPool] = await Promise.all([
60
62
  collectManagedBrowserPools(resolved.browserPoolRoot),
61
63
  planStaleCdpFiles(resolved.browserUseHome),
62
64
  planComputeReapSafely({ includeDev: resolved.includeDev, maxAgeMinutes: resolved.maxAgeMinutes, now }),
@@ -66,9 +68,10 @@ export async function planResourceReap(options = {}) {
66
68
  browserUseHome: resolved.browserUseHome,
67
69
  exemptBrowserUserDataDirs: [],
68
70
  }),
71
+ planDeploymentPoolReapSafely(now),
69
72
  ]);
70
73
  const unmanagedBrowsers = buildUnmanagedBrowserPlanItems(health.browserProcesses.unassignedMainProcessDetails, resolved.unmanagedBrowserGraceMinutes, new Set(resolved.exemptBrowserPids), new Set(resolved.exemptBrowserUserDataDirs), resolved.browserUseHome);
71
- return buildResourceReapPlan({ now, options: resolved, records, staleFiles, unmanagedBrowsers, compute });
74
+ return buildResourceReapPlan({ now, options: resolved, records, staleFiles, unmanagedBrowsers, compute, deploymentPool });
72
75
  }
73
76
  export function buildResourceReapPlan(input) {
74
77
  const browserItems = input.records.map((record) => buildBrowserReapPlanItem(record, input.now, input.options.idleTimeoutMinutes));
@@ -89,6 +92,7 @@ export function buildResourceReapPlan(input) {
89
92
  skipped: unmanagedBrowsers.filter((item) => item.action === "skip").length,
90
93
  },
91
94
  compute: input.compute,
95
+ deploymentPool: input.deploymentPool,
92
96
  worktreesPreserved: true,
93
97
  };
94
98
  }
@@ -112,6 +116,9 @@ export async function applyResourceReapPlan(plan, dependencies = {}) {
112
116
  }
113
117
  const removedStaleFiles = await applyStaleCdpFilePlan(confirmed.staleFiles.items, dependencies.isPidAlive);
114
118
  const removedComputeWorkers = await (dependencies.applyCompute ?? applyComputeWorkerReapPlan)(confirmed.compute);
119
+ const deploymentPoolResult = confirmed.deploymentPool
120
+ ? await (dependencies.applyDeploymentPool ?? applyDeploymentPoolReapPlan)(confirmed.deploymentPool)
121
+ : undefined;
115
122
  return {
116
123
  applied: true,
117
124
  plan: confirmed,
@@ -119,6 +126,8 @@ export async function applyResourceReapPlan(plan, dependencies = {}) {
119
126
  terminatedUnmanagedBrowsers,
120
127
  removedStaleFiles,
121
128
  removedComputeWorkers,
129
+ deploymentPoolResult,
130
+ removedDeploymentLeases: deploymentPoolResult?.releasedLeases ?? [],
122
131
  worktreesPreserved: true,
123
132
  };
124
133
  }
@@ -287,6 +296,17 @@ export async function planComputeReapSafely(options, planCompute = planReapWorke
287
296
  return plan;
288
297
  }
289
298
  }
299
+ async function planDeploymentPoolReapSafely(now) {
300
+ const config = resolveDeploymentPoolConfig();
301
+ if (!existsSync(config.databasePath))
302
+ return undefined;
303
+ try {
304
+ return await planDeploymentPoolReap({ config, now });
305
+ }
306
+ catch {
307
+ return undefined;
308
+ }
309
+ }
290
310
  async function planStaleCdpFiles(browserUseHome, isPidAlive = defaultIsPidAlive) {
291
311
  const stateDir = join(browserUseHome, "pibo-cdp");
292
312
  let files;
@@ -95,6 +95,7 @@ export class ResourceReaperService {
95
95
  unmanagedBrowsers: result.terminatedUnmanagedBrowsers.length,
96
96
  staleFiles: result.removedStaleFiles.length,
97
97
  computeWorkers: result.removedComputeWorkers.length,
98
+ ...(result.deploymentPoolResult ? { deploymentLeases: result.removedDeploymentLeases?.length ?? 0 } : {}),
98
99
  },
99
100
  lastError: undefined,
100
101
  };
@@ -16,7 +16,8 @@ export function resolveAgentDelegationStatus(childSignal, fallbackStatus = "done
16
16
  }
17
17
  export function extractAgentDelegationName(input, title, summary) {
18
18
  const record = isRecord(input) ? input : undefined;
19
- const rawName = stringValue(record?.subagentName)
19
+ const rawName = stringValue(record?.name)
20
+ ?? stringValue(record?.subagentName)
20
21
  ?? subagentNameFromToolName(title)
21
22
  ?? stringValue(summary)
22
23
  ?? stringValue(title)
@@ -68,10 +69,11 @@ function subagentNameFromToolName(value) {
68
69
  const name = nonEmpty(value);
69
70
  if (!name)
70
71
  return undefined;
71
- return name.replace(/^pibo_subagent_/, "");
72
+ return name === "pibo_agents_send_message" ? undefined : name.replace(/^pibo_subagent_/, "");
72
73
  }
73
74
  function titleCaseAgentName(value) {
74
75
  return value
76
+ .replace(/^pibo_agents_send_message$/, "Agent")
75
77
  .replace(/^pibo_subagent_/, "")
76
78
  .split(/[\s_-]+/)
77
79
  .filter(Boolean)
@@ -51,10 +51,12 @@ function createAsyncAgentRunNode(parent, piboSessionId, startedAt, delegation) {
51
51
  const toolName = stringValue(run?.toolName) ?? stringValue(input.toolName) ?? delegation?.title;
52
52
  if (!toolName || !isSubagentToolName(toolName))
53
53
  return undefined;
54
- const subagentName = stringValue(delegation?.summary) ?? subagentNameFromToolName(toolName);
54
+ const delegatedArguments = input.arguments;
55
+ const subagentName = stringValue(delegation?.summary)
56
+ ?? (isRecord(delegatedArguments) ? stringValue(delegatedArguments.name) : undefined)
57
+ ?? subagentNameFromToolName(toolName);
55
58
  const runId = stringValue(run?.runId);
56
59
  const runStatus = stringValue(run?.status);
57
- const delegatedArguments = input.arguments;
58
60
  const completionPolicy = stringValue(run?.completionPolicy) ?? stringValue(input.completionPolicy);
59
61
  return {
60
62
  id: `${parent.id}:async-agent`,
@@ -947,8 +947,14 @@ function findLegacySubagentLinkTarget(nodes, update) {
947
947
  }
948
948
  function delegationAgentName(node) {
949
949
  const input = isObjectRecord(node.input) ? node.input : undefined;
950
- const value = typeof input?.subagentName === "string" ? input.subagentName : node.summary ?? node.title;
951
- return typeof value === "string" ? value.replace(/^pibo_subagent_/, "").trim().toLowerCase() || undefined : undefined;
950
+ const value = typeof input?.name === "string"
951
+ ? input.name
952
+ : typeof input?.subagentName === "string"
953
+ ? input.subagentName
954
+ : node.summary ?? node.title;
955
+ return typeof value === "string"
956
+ ? value.replace(/^pibo_agents_send_message$/, "agent").replace(/^pibo_subagent_/, "").trim().toLowerCase() || undefined
957
+ : undefined;
952
958
  }
953
959
  function delegationThreadKey(value) {
954
960
  if (!isObjectRecord(value) || typeof value.threadKey !== "string")
@@ -22,9 +22,16 @@ export function mapTraceSubagentSessionLinks(events) {
22
22
  export function findLikelyTraceChildSession(piboSessionId, toolName, event, childByParent) {
23
23
  if (!isSubagentToolName(toolName))
24
24
  return undefined;
25
+ const agentName = toolEventAgentName(event);
25
26
  const candidates = childByParent
26
27
  .get(piboSessionId)
27
- ?.filter((session) => session.metadata?.subagentToolName === toolName) ?? [];
28
+ ?.filter((session) => {
29
+ if (toolName === "pibo_agents_send_message") {
30
+ return session.metadata?.subagentToolName === toolName
31
+ && (!agentName || session.metadata?.subagentName === agentName);
32
+ }
33
+ return session.metadata?.subagentToolName === toolName;
34
+ }) ?? [];
28
35
  const threadKey = toolEventThreadKey(event);
29
36
  if (threadKey) {
30
37
  return candidates.find((session) => session.metadata?.threadKey === threadKey)?.id;
@@ -32,15 +39,21 @@ export function findLikelyTraceChildSession(piboSessionId, toolName, event, chil
32
39
  return candidates.length === 1 ? candidates[0].id : undefined;
33
40
  }
34
41
  export function isSubagentToolName(name) {
35
- return name.startsWith("pibo_subagent_");
42
+ return name === "pibo_agents_send_message" || name.startsWith("pibo_subagent_");
36
43
  }
37
44
  export function subagentNameFromToolName(toolName) {
38
- return toolName.slice("pibo_subagent_".length);
45
+ return toolName === "pibo_agents_send_message" ? "agent" : toolName.slice("pibo_subagent_".length);
39
46
  }
40
- function toolEventThreadKey(event) {
41
- const args = "args" in event && event.args && typeof event.args === "object" && !Array.isArray(event.args)
47
+ function toolEventArguments(event) {
48
+ return "args" in event && event.args && typeof event.args === "object" && !Array.isArray(event.args)
42
49
  ? event.args
43
50
  : undefined;
44
- const threadKey = args && "threadKey" in args ? args.threadKey : undefined;
51
+ }
52
+ function toolEventAgentName(event) {
53
+ const name = toolEventArguments(event)?.name;
54
+ return typeof name === "string" && name.trim() ? name.trim() : undefined;
55
+ }
56
+ function toolEventThreadKey(event) {
57
+ const threadKey = toolEventArguments(event)?.threadKey;
45
58
  return typeof threadKey === "string" && threadKey.trim() ? threadKey.trim() : undefined;
46
59
  }