@pasko70/pibo 2.2.5 → 2.3.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/dist/agent-runtime/context-build.js +5 -2
- package/dist/agent-runtimes/pi/adapter.js +1 -1
- package/dist/agent-runtimes/pi/runtime.js +25 -16
- package/dist/apps/chat-ui/assets/{dist-BK7eaoLT.js → dist-Byygd1lH.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-fNgdnmyE.js → dist-C9BrS7sL.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-wq3P0LZj.js → dist-CUcAofmV.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BCRR_a0Z.js → dist-D4RU6xu3.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CTUT484B.js → dist-DusFwy0L.js} +1 -1
- package/dist/apps/chat-ui/assets/{index-DsFKL_EZ.js → index-Bifi_kjN.js} +90 -90
- package/dist/apps/chat-ui/index.html +1 -1
- package/dist/apps/chat-vscode-web/assets/{index-R4FTxr78.js → index-WsLm1mo3.js} +5 -5
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/{pibo-vscode-ext-2.2.5.vsix → pibo-vscode-ext-2.3.0.vsix} +0 -0
- package/dist/core/codex-compat.js +1 -3
- package/dist/core/context-build.js +16 -7
- package/dist/core/session-router.js +221 -45
- package/dist/data/ingest-service.js +12 -0
- package/dist/debug/agents.js +391 -0
- package/dist/debug/index.js +7 -0
- package/dist/index.js +1 -1
- package/dist/session-ui/delegation.js +4 -2
- package/dist/shared/trace-async-agent-runs.js +4 -2
- package/dist/shared/trace-event-projection.js +8 -2
- package/dist/shared/trace-subagent-links.js +19 -6
- package/dist/subagents/observations.js +149 -0
- package/dist/subagents/tool.js +177 -46
- package/dist/tools/session-service.js +1 -0
- package/dist/tools/session-tool-set.js +9 -5
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta name="theme-color" content="#101d22" />
|
|
7
7
|
<title>Pibo</title>
|
|
8
|
-
<script type="module" crossorigin src="/apps/chat-vscode/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/apps/chat-vscode/assets/index-WsLm1mo3.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/apps/chat-vscode/assets/index-CF1-9PKU.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
Binary file
|
package/dist/apps/vscode-artifacts/{pibo-vscode-ext-2.2.5.vsix → pibo-vscode-ext-2.3.0.vsix}
RENAMED
|
Binary file
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const CODEX_COMPAT_SUBAGENTS = ["default", "explorer", "worker"];
|
|
2
1
|
function currentDate() {
|
|
3
2
|
return new Date().toISOString().slice(0, 10);
|
|
4
3
|
}
|
|
@@ -15,7 +14,7 @@ export function buildCodexCompatSystemPrompt(options) {
|
|
|
15
14
|
const compatibilityInstructions = [
|
|
16
15
|
"# Codex-Compatible Runtime",
|
|
17
16
|
"You are running in Pibo through the codex-compat profile. Match Codex-style tool use where the exposed Pibo tools support it, while staying truthful about implemented behavior.",
|
|
18
|
-
"Use Pibo's pibo_run_*
|
|
17
|
+
"Use Pibo's pibo_run_* and pibo_agents_* tools for parallel work, yielded runs, and delegated-agent lifecycle management.",
|
|
19
18
|
"Use direct execution for normal coding tasks. If a structured planning or user-input tool is not present, ask concise questions in normal chat.",
|
|
20
19
|
"When web_search is selected by the profile, use it for current or externally sourced information.",
|
|
21
20
|
childInstructions,
|
|
@@ -24,7 +23,6 @@ export function buildCodexCompatSystemPrompt(options) {
|
|
|
24
23
|
` <shell>${options.shell}</shell>`,
|
|
25
24
|
` <current_date>${options.currentDate ?? currentDate()}</current_date>`,
|
|
26
25
|
` <timezone>${options.timezone ?? currentTimezone()}</timezone>`,
|
|
27
|
-
` <subagents>${CODEX_COMPAT_SUBAGENTS.join(", ")}</subagents>`,
|
|
28
26
|
"</environment_context>",
|
|
29
27
|
options.baseSystemPrompt,
|
|
30
28
|
];
|
|
@@ -139,11 +139,20 @@ function sanitizeNode(input, parentId, order = 0) {
|
|
|
139
139
|
function countNodes(nodes) {
|
|
140
140
|
return nodes.reduce((count, node) => count + 1 + countNodes(node.children ?? []), 0);
|
|
141
141
|
}
|
|
142
|
-
function
|
|
142
|
+
function inspectionAgentsController() {
|
|
143
|
+
const fail = () => {
|
|
144
|
+
throw new Error("Context build inspection cannot execute delegated-agent tools");
|
|
145
|
+
};
|
|
143
146
|
return {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
sendMessage: fail,
|
|
148
|
+
listAgents: () => [],
|
|
149
|
+
observe: (input) => ({
|
|
150
|
+
filters: input,
|
|
151
|
+
observations: [],
|
|
152
|
+
nextAfterSequence: input.afterSequence ?? 0,
|
|
153
|
+
truncated: false,
|
|
154
|
+
}),
|
|
155
|
+
killAgent: fail,
|
|
147
156
|
};
|
|
148
157
|
}
|
|
149
158
|
function inspectionRunToolController() {
|
|
@@ -196,8 +205,8 @@ function toolDefinitionSchema(definition, toolInfo) {
|
|
|
196
205
|
function generatedOriginForTool(name, profile) {
|
|
197
206
|
if (name === "runtime")
|
|
198
207
|
return "Generated Pibo runtime tool selected by the profile.";
|
|
199
|
-
if (name.startsWith("
|
|
200
|
-
return "Generated
|
|
208
|
+
if (name.startsWith("pibo_agents_"))
|
|
209
|
+
return "Generated shared agent-management tool from the profile's delegated-agent list.";
|
|
201
210
|
if (name.startsWith("pibo_run_"))
|
|
202
211
|
return "Generated run-control tool from the pibo-run-control capability package.";
|
|
203
212
|
if (PIBO_GOAL_TOOL_NAMES.includes(name))
|
|
@@ -298,7 +307,7 @@ export async function inspectPiboContextBuild(options = {}) {
|
|
|
298
307
|
profile: inspectionProfile,
|
|
299
308
|
activeModel: undefined,
|
|
300
309
|
persistSession: false,
|
|
301
|
-
|
|
310
|
+
agentsController: options.agentsController ?? (hasEnabledSubagents ? inspectionAgentsController() : undefined),
|
|
302
311
|
runToolController: options.runToolController ?? (hasYieldableTools ? inspectionRunToolController() : undefined),
|
|
303
312
|
});
|
|
304
313
|
try {
|
|
@@ -3,7 +3,7 @@ import { InitialSessionContext, } from "./profiles.js";
|
|
|
3
3
|
import { createDefaultPiboPluginRegistry, createPiboProfileFromRegistryOrDefault, resolvePiboProfileNameFromRegistryOrDefault, selectDefaultPiboProfileName } from "../plugins/builtin.js";
|
|
4
4
|
import { RuntimeRoutedSession as RoutedSession, } from "../agent-runtime/routed-session.js";
|
|
5
5
|
import { runtimeSessionErrorDetails } from "./session-errors.js";
|
|
6
|
-
import {
|
|
6
|
+
import { normalizePiboAgentObservationCursor, normalizePiboAgentObservationLimit, normalizePiboAgentObservationOrder, parsePiboAgentObservationTimestamp, piboAgentObservationDetails, piboAgentObservationKind, piboAgentObservationRole, piboAgentObservationSourceFromEvent, piboAgentObservationText, } from "../subagents/observations.js";
|
|
7
7
|
import { PiboRunRegistry } from "../runs/registry.js";
|
|
8
8
|
import { PiboRunExecutionTimeoutError } from "../runs/lifecycle.js";
|
|
9
9
|
import { PiboRunResourceLimitError } from "../runs/resource-isolation.js";
|
|
@@ -32,6 +32,7 @@ import { PORTABLE_HISTORY_HANDOFF_METADATA_KEY, PORTABLE_HISTORY_LAST_IMPORT_MET
|
|
|
32
32
|
const DEFAULT_SUBAGENT_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
|
|
33
33
|
const DEFAULT_SUBAGENT_MAX_DEPTH = 1;
|
|
34
34
|
const MAX_SUBAGENT_THREAD_KEY_BYTES = 512;
|
|
35
|
+
const MAX_AGENT_OBSERVATIONS = 5_000;
|
|
35
36
|
const DEFAULT_ROUTED_SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
36
37
|
const DEFAULT_ROUTED_SESSION_DISPOSE_TIMEOUT_MS = 30 * 1000;
|
|
37
38
|
export const LOOP_RUNTIME_RETRY_DEFAULTS = {
|
|
@@ -235,6 +236,9 @@ export class PiboSessionRouter {
|
|
|
235
236
|
runtimeResourceSessions = new Map();
|
|
236
237
|
runtimeAuthFingerprints = new Map();
|
|
237
238
|
activeSubagentChildren = new Map();
|
|
239
|
+
agentObservations = [];
|
|
240
|
+
agentObservationEvictedThroughByParent = new Map();
|
|
241
|
+
nextAgentObservationSequence = 1;
|
|
238
242
|
scheduledRunReminders = new Map();
|
|
239
243
|
runReminderGenerations = new Map();
|
|
240
244
|
runCancellationHandlers = new Map();
|
|
@@ -563,32 +567,40 @@ export class PiboSessionRouter {
|
|
|
563
567
|
}
|
|
564
568
|
}
|
|
565
569
|
descendantSessionIds(parentId) {
|
|
566
|
-
const
|
|
570
|
+
const childrenByParent = new Map();
|
|
567
571
|
for (const session of this.sessionStore.list?.() ?? []) {
|
|
568
|
-
if (session.parentId
|
|
572
|
+
if (!session.parentId)
|
|
569
573
|
continue;
|
|
570
|
-
|
|
574
|
+
const children = childrenByParent.get(session.parentId) ?? [];
|
|
575
|
+
children.push(session);
|
|
576
|
+
childrenByParent.set(session.parentId, children);
|
|
577
|
+
}
|
|
578
|
+
const output = [];
|
|
579
|
+
const seen = new Set([parentId]);
|
|
580
|
+
const stack = [...(childrenByParent.get(parentId) ?? [])].reverse();
|
|
581
|
+
while (stack.length > 0) {
|
|
582
|
+
const session = stack.pop();
|
|
583
|
+
if (seen.has(session.id))
|
|
584
|
+
continue;
|
|
585
|
+
seen.add(session.id);
|
|
586
|
+
output.push(session.id);
|
|
587
|
+
const children = childrenByParent.get(session.id);
|
|
588
|
+
if (children)
|
|
589
|
+
stack.push(...[...children].reverse());
|
|
571
590
|
}
|
|
572
591
|
return output;
|
|
573
592
|
}
|
|
574
593
|
async killChildSessions(parentId, options) {
|
|
575
594
|
const killed = [];
|
|
576
595
|
const cancelledRuns = [];
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
if (
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
const runs = this.runRegistry.cancelControllerRuns(session.id);
|
|
586
|
-
cancelledRuns.push(...runs.map((r) => r.runId));
|
|
587
|
-
await this.invokeRunCancellationHandlers(runs);
|
|
588
|
-
}
|
|
589
|
-
const nested = await this.killChildSessions(session.id, options);
|
|
590
|
-
killed.push(...nested.killed);
|
|
591
|
-
cancelledRuns.push(...nested.cancelledRuns);
|
|
596
|
+
for (const id of this.descendantSessionIds(parentId)) {
|
|
597
|
+
const childSession = this.sessions.get(id);
|
|
598
|
+
if (childSession)
|
|
599
|
+
killed.push(await childSession.kill());
|
|
600
|
+
if (options?.includeRuns) {
|
|
601
|
+
const runs = this.runRegistry.cancelControllerRuns(id);
|
|
602
|
+
cancelledRuns.push(...runs.map((run) => run.runId));
|
|
603
|
+
await this.invokeRunCancellationHandlers(runs);
|
|
592
604
|
}
|
|
593
605
|
}
|
|
594
606
|
return { killed, cancelledRuns };
|
|
@@ -935,6 +947,8 @@ export class PiboSessionRouter {
|
|
|
935
947
|
await this.runtimeResourceService.dispose();
|
|
936
948
|
this.runtimeResourceSessions.clear();
|
|
937
949
|
this.activeSubagentChildren.clear();
|
|
950
|
+
this.agentObservations.length = 0;
|
|
951
|
+
this.agentObservationEvictedThroughByParent.clear();
|
|
938
952
|
await this.telemetryWriter?.dispose();
|
|
939
953
|
const lifecycleFailures = [...authDisposals, ...webAppDisposals]
|
|
940
954
|
.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
@@ -1099,7 +1113,7 @@ export class PiboSessionRouter {
|
|
|
1099
1113
|
historyHandoff = { mode: "fresh" };
|
|
1100
1114
|
}
|
|
1101
1115
|
const initialFastMode = resolvePiboSessionInitialFastMode(piboSession) ?? selectRequestedFastMode(sessionProfile, modelDefaults) ?? false;
|
|
1102
|
-
const
|
|
1116
|
+
const agentsController = this.createAgentsController(piboSession.id);
|
|
1103
1117
|
const runToolController = this.createRunToolController(piboSession.id);
|
|
1104
1118
|
const codeRuntimeToolController = this.runtimeRegistry.createController(piboSession.id);
|
|
1105
1119
|
const sessionGeneration = randomUUID();
|
|
@@ -1116,7 +1130,7 @@ export class PiboSessionRouter {
|
|
|
1116
1130
|
profile: sessionProfile,
|
|
1117
1131
|
cwd: workspace,
|
|
1118
1132
|
getActiveMessage: () => session?.getActiveMessage(),
|
|
1119
|
-
|
|
1133
|
+
agentsController,
|
|
1120
1134
|
runToolController,
|
|
1121
1135
|
runtimeToolController: codeRuntimeToolController,
|
|
1122
1136
|
});
|
|
@@ -1162,7 +1176,7 @@ export class PiboSessionRouter {
|
|
|
1162
1176
|
getActiveMessage: () => session?.getActiveMessage(),
|
|
1163
1177
|
},
|
|
1164
1178
|
services: {
|
|
1165
|
-
|
|
1179
|
+
agentsController,
|
|
1166
1180
|
runToolController,
|
|
1167
1181
|
codeRuntimeToolController,
|
|
1168
1182
|
portableTools,
|
|
@@ -1583,12 +1597,12 @@ export class PiboSessionRouter {
|
|
|
1583
1597
|
id: randomUUID(),
|
|
1584
1598
|
})));
|
|
1585
1599
|
}
|
|
1586
|
-
|
|
1600
|
+
createAgentsController(parentPiboSessionId) {
|
|
1587
1601
|
return {
|
|
1588
|
-
|
|
1602
|
+
sendMessage: async ({ subagent, message, threadKey, toolCallId, signal }) => {
|
|
1589
1603
|
this.assertSubagentDepth(parentPiboSessionId, subagent);
|
|
1590
1604
|
const child = this.resolveSubagentSession(parentPiboSessionId, subagent, threadKey);
|
|
1591
|
-
const
|
|
1605
|
+
const resolvedThreadKey = typeof child.metadata?.threadKey === "string" ? child.metadata.threadKey : "";
|
|
1592
1606
|
const event = {
|
|
1593
1607
|
type: "message",
|
|
1594
1608
|
piboSessionId: child.id,
|
|
@@ -1600,22 +1614,154 @@ export class PiboSessionRouter {
|
|
|
1600
1614
|
type: "subagent_session",
|
|
1601
1615
|
piboSessionId: parentPiboSessionId,
|
|
1602
1616
|
toolCallId,
|
|
1603
|
-
toolName,
|
|
1617
|
+
toolName: "pibo_agents_send_message",
|
|
1604
1618
|
subagentName: subagent.name,
|
|
1605
1619
|
childPiboSessionId: child.id,
|
|
1606
|
-
threadKey:
|
|
1620
|
+
threadKey: resolvedThreadKey,
|
|
1607
1621
|
});
|
|
1608
1622
|
const untrack = this.trackActiveSubagent(parentPiboSessionId, child.id);
|
|
1609
1623
|
try {
|
|
1610
1624
|
const reply = await this.emitMessageAndWaitForReply(event, subagent.timeoutMs ?? DEFAULT_SUBAGENT_REPLY_TIMEOUT_MS, signal);
|
|
1611
|
-
return {
|
|
1625
|
+
return {
|
|
1626
|
+
agentId: child.id,
|
|
1627
|
+
name: subagent.name,
|
|
1628
|
+
profile: child.profile,
|
|
1629
|
+
threadKey: resolvedThreadKey,
|
|
1630
|
+
eventId: event.id,
|
|
1631
|
+
reply,
|
|
1632
|
+
};
|
|
1612
1633
|
}
|
|
1613
1634
|
finally {
|
|
1614
1635
|
untrack();
|
|
1615
1636
|
}
|
|
1616
1637
|
},
|
|
1638
|
+
listAgents: () => this.listManagedAgents(parentPiboSessionId),
|
|
1639
|
+
observe: (input) => this.observeManagedAgents(parentPiboSessionId, input),
|
|
1640
|
+
killAgent: async (agentId) => await this.killManagedAgent(parentPiboSessionId, agentId),
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
listManagedAgents(parentPiboSessionId) {
|
|
1644
|
+
return this.sessionStore.find({
|
|
1645
|
+
channel: "pibo.subagents",
|
|
1646
|
+
kind: "subagent",
|
|
1647
|
+
parentId: parentPiboSessionId,
|
|
1648
|
+
}).map((session) => {
|
|
1649
|
+
const live = this.sessions.get(session.id)?.getStatus();
|
|
1650
|
+
const killed = session.metadata?.agentStatus === "killed";
|
|
1651
|
+
const running = !killed && Boolean(live && (live.processing || live.streaming || live.queuedMessages > 0));
|
|
1652
|
+
return {
|
|
1653
|
+
agentId: session.id,
|
|
1654
|
+
name: typeof session.metadata?.subagentName === "string" ? session.metadata.subagentName : session.profile,
|
|
1655
|
+
profile: session.profile,
|
|
1656
|
+
...(typeof session.metadata?.threadKey === "string" ? { threadKey: session.metadata.threadKey } : {}),
|
|
1657
|
+
status: killed ? "killed" : running ? "running" : "idle",
|
|
1658
|
+
createdAt: session.createdAt,
|
|
1659
|
+
updatedAt: session.updatedAt,
|
|
1660
|
+
...(session.activeModel ? { activeModel: { ...session.activeModel } } : {}),
|
|
1661
|
+
};
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
requireManagedAgent(parentPiboSessionId, agentId) {
|
|
1665
|
+
const session = this.sessionStore.get(agentId);
|
|
1666
|
+
if (!session
|
|
1667
|
+
|| session.parentId !== parentPiboSessionId
|
|
1668
|
+
|| session.channel !== "pibo.subagents"
|
|
1669
|
+
|| session.kind !== "subagent") {
|
|
1670
|
+
throw new Error(`Agent "${agentId}" is not owned by Pibo session "${parentPiboSessionId}".`);
|
|
1671
|
+
}
|
|
1672
|
+
return session;
|
|
1673
|
+
}
|
|
1674
|
+
observeManagedAgents(parentPiboSessionId, input) {
|
|
1675
|
+
const order = normalizePiboAgentObservationOrder(input.order);
|
|
1676
|
+
const limit = normalizePiboAgentObservationLimit(input.limit);
|
|
1677
|
+
const afterSequence = normalizePiboAgentObservationCursor(input.afterSequence);
|
|
1678
|
+
const since = parsePiboAgentObservationTimestamp(input.since, "since");
|
|
1679
|
+
const until = parsePiboAgentObservationTimestamp(input.until, "until");
|
|
1680
|
+
if (since !== undefined && until !== undefined && since > until) {
|
|
1681
|
+
throw new Error("Agent observation since must not be after until.");
|
|
1682
|
+
}
|
|
1683
|
+
const agentIds = input.agentIds ? new Set(input.agentIds) : undefined;
|
|
1684
|
+
if (agentIds) {
|
|
1685
|
+
for (const agentId of agentIds)
|
|
1686
|
+
this.requireManagedAgent(parentPiboSessionId, agentId);
|
|
1687
|
+
}
|
|
1688
|
+
const names = input.names ? new Set(input.names) : undefined;
|
|
1689
|
+
const threadKeys = input.threadKeys ? new Set(input.threadKeys) : undefined;
|
|
1690
|
+
const eventTypes = input.eventTypes ? new Set(input.eventTypes) : undefined;
|
|
1691
|
+
const kinds = input.kinds ? new Set(input.kinds) : undefined;
|
|
1692
|
+
const textContains = input.textContains?.toLowerCase();
|
|
1693
|
+
const matches = this.agentObservations.filter((observation) => {
|
|
1694
|
+
if (observation.managingParentId !== parentPiboSessionId)
|
|
1695
|
+
return false;
|
|
1696
|
+
if (agentIds && !agentIds.has(observation.agentId))
|
|
1697
|
+
return false;
|
|
1698
|
+
if (names && !names.has(observation.name))
|
|
1699
|
+
return false;
|
|
1700
|
+
if (threadKeys && (!observation.threadKey || !threadKeys.has(observation.threadKey)))
|
|
1701
|
+
return false;
|
|
1702
|
+
if (eventTypes && !eventTypes.has(observation.eventType))
|
|
1703
|
+
return false;
|
|
1704
|
+
if (kinds && !kinds.has(observation.kind))
|
|
1705
|
+
return false;
|
|
1706
|
+
if (afterSequence !== undefined && observation.sequence <= afterSequence)
|
|
1707
|
+
return false;
|
|
1708
|
+
const createdAt = Date.parse(observation.createdAt);
|
|
1709
|
+
if (since !== undefined && createdAt < since)
|
|
1710
|
+
return false;
|
|
1711
|
+
if (until !== undefined && createdAt > until)
|
|
1712
|
+
return false;
|
|
1713
|
+
if (textContains && !(observation.text ?? "").toLowerCase().includes(textContains))
|
|
1714
|
+
return false;
|
|
1715
|
+
return true;
|
|
1716
|
+
});
|
|
1717
|
+
const cursorPolling = afterSequence !== undefined;
|
|
1718
|
+
const ordered = cursorPolling
|
|
1719
|
+
? matches.slice(0, limit)
|
|
1720
|
+
: [...matches].sort((left, right) => order === "asc" ? left.sequence - right.sequence : right.sequence - left.sequence).slice(0, limit);
|
|
1721
|
+
if (cursorPolling && order === "desc")
|
|
1722
|
+
ordered.reverse();
|
|
1723
|
+
const selected = ordered.map((observation) => {
|
|
1724
|
+
const { managingParentId: _managingParentId, details, ...visible } = observation;
|
|
1725
|
+
return input.includeDetails === true && details !== undefined ? { ...visible, details } : visible;
|
|
1726
|
+
});
|
|
1727
|
+
const evictedThrough = this.agentObservationEvictedThroughByParent.get(parentPiboSessionId) ?? 0;
|
|
1728
|
+
const retentionTruncated = afterSequence === undefined ? evictedThrough > 0 : afterSequence < evictedThrough;
|
|
1729
|
+
const nextAfterSequence = selected.reduce((maximum, observation) => Math.max(maximum, observation.sequence), afterSequence === undefined ? 0 : Math.max(afterSequence, evictedThrough));
|
|
1730
|
+
return {
|
|
1731
|
+
filters: {
|
|
1732
|
+
...input,
|
|
1733
|
+
...(afterSequence !== undefined ? { afterSequence } : {}),
|
|
1734
|
+
order,
|
|
1735
|
+
limit,
|
|
1736
|
+
includeDetails: input.includeDetails === true,
|
|
1737
|
+
},
|
|
1738
|
+
observations: selected,
|
|
1739
|
+
nextAfterSequence,
|
|
1740
|
+
truncated: retentionTruncated || matches.length > selected.length,
|
|
1617
1741
|
};
|
|
1618
1742
|
}
|
|
1743
|
+
async killManagedAgent(parentPiboSessionId, agentId) {
|
|
1744
|
+
const child = this.requireManagedAgent(parentPiboSessionId, agentId);
|
|
1745
|
+
const ids = [agentId, ...this.descendantSessionIds(agentId)];
|
|
1746
|
+
const idSet = new Set(ids);
|
|
1747
|
+
const cancelledRuns = this.runRegistry.listAll({ includeConsumed: true, includeDetached: true })
|
|
1748
|
+
.filter((run) => idSet.has(run.controllerPiboSessionId) && !isTerminalRunStatus(run.status))
|
|
1749
|
+
.map((run) => run.runId);
|
|
1750
|
+
await Promise.allSettled(ids.flatMap((id) => this.sessions.has(id)
|
|
1751
|
+
? [this.emit({ type: "execution", piboSessionId: id, action: "abort", id: randomUUID() })]
|
|
1752
|
+
: []));
|
|
1753
|
+
if (child.metadata?.agentStatus !== "killed") {
|
|
1754
|
+
this.sessionStore.update(agentId, {
|
|
1755
|
+
metadata: {
|
|
1756
|
+
...(child.metadata ?? {}),
|
|
1757
|
+
agentStatus: "killed",
|
|
1758
|
+
killedAt: new Date().toISOString(),
|
|
1759
|
+
},
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
await this.disposeSessionSubtree(agentId, `killed by parent ${parentPiboSessionId}`, { cancelRuns: true });
|
|
1763
|
+
return { agentId, killed: ids, cancelledRuns };
|
|
1764
|
+
}
|
|
1619
1765
|
async invokeRunCancellationHandlers(runs) {
|
|
1620
1766
|
const results = await Promise.allSettled(runs.map(async (run) => {
|
|
1621
1767
|
const cancel = this.runCancellationHandlers.get(run.runId);
|
|
@@ -1735,35 +1881,33 @@ export class PiboSessionRouter {
|
|
|
1735
1881
|
const targetProfile = resolvePiboProfileNameFromRegistryOrDefault(this.pluginRegistry, subagent.targetProfile);
|
|
1736
1882
|
const parent = this.resolvePiboSession(parentPiboSessionId);
|
|
1737
1883
|
const resolvedThreadKey = resolveSubagentThreadKey(threadKey);
|
|
1738
|
-
const
|
|
1884
|
+
const identityMetadata = {
|
|
1739
1885
|
subagentName: subagent.name,
|
|
1740
|
-
subagentToolName: createSubagentToolName(subagent.name),
|
|
1741
1886
|
threadKey: resolvedThreadKey,
|
|
1742
1887
|
};
|
|
1743
|
-
const metadata = withWorkflowSessionKind(
|
|
1888
|
+
const metadata = withWorkflowSessionKind({
|
|
1889
|
+
...identityMetadata,
|
|
1890
|
+
subagentToolName: "pibo_agents_send_message",
|
|
1891
|
+
agentStatus: "active",
|
|
1892
|
+
}, "subagent");
|
|
1744
1893
|
const parentChatRoomId = typeof parent.metadata?.chatRoomId === "string" ? parent.metadata.chatRoomId : undefined;
|
|
1745
1894
|
if (parentChatRoomId)
|
|
1746
1895
|
metadata.chatRoomId = parentChatRoomId;
|
|
1747
1896
|
const newSessionMetadata = subagent.thinkingLevel
|
|
1748
1897
|
? { ...metadata, initialThinkingLevel: subagent.thinkingLevel }
|
|
1749
1898
|
: metadata;
|
|
1750
|
-
const
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
:
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
kind: "subagent",
|
|
1758
|
-
parentId: parent.id,
|
|
1759
|
-
profile: targetProfile,
|
|
1760
|
-
metadata: candidate,
|
|
1761
|
-
})[0]
|
|
1762
|
-
: undefined;
|
|
1763
|
-
const existing = findExisting(metadata) ?? findExisting(legacyMetadataWithChatRoom) ?? findExisting(legacyMetadata);
|
|
1899
|
+
const existing = this.sessionStore.find({
|
|
1900
|
+
channel: "pibo.subagents",
|
|
1901
|
+
kind: "subagent",
|
|
1902
|
+
parentId: parent.id,
|
|
1903
|
+
profile: targetProfile,
|
|
1904
|
+
metadata: identityMetadata,
|
|
1905
|
+
}).find((candidate) => candidate.metadata?.agentStatus !== "killed");
|
|
1764
1906
|
if (existing) {
|
|
1765
1907
|
const updatedMetadata = withWorkflowSessionKind({
|
|
1766
1908
|
...(existing.metadata ?? {}),
|
|
1909
|
+
subagentToolName: "pibo_agents_send_message",
|
|
1910
|
+
agentStatus: "active",
|
|
1767
1911
|
...(parentChatRoomId ? { chatRoomId: parentChatRoomId } : {}),
|
|
1768
1912
|
}, "subagent");
|
|
1769
1913
|
if (JSON.stringify(updatedMetadata) !== JSON.stringify(existing.metadata ?? {})) {
|
|
@@ -1793,8 +1937,40 @@ export class PiboSessionRouter {
|
|
|
1793
1937
|
});
|
|
1794
1938
|
return activeModel ? this.sessionStore.update(childSession.id, { activeModel }) ?? childSession : childSession;
|
|
1795
1939
|
}
|
|
1940
|
+
recordAgentObservation(event, session) {
|
|
1941
|
+
if (!session || session.kind !== "subagent" || session.channel !== "pibo.subagents" || !session.parentId)
|
|
1942
|
+
return;
|
|
1943
|
+
const name = typeof session.metadata?.subagentName === "string" ? session.metadata.subagentName : session.profile;
|
|
1944
|
+
const source = piboAgentObservationSourceFromEvent(event);
|
|
1945
|
+
const role = piboAgentObservationRole(source);
|
|
1946
|
+
const text = piboAgentObservationText(source);
|
|
1947
|
+
const observation = {
|
|
1948
|
+
managingParentId: session.parentId,
|
|
1949
|
+
sequence: this.nextAgentObservationSequence++,
|
|
1950
|
+
createdAt: new Date().toISOString(),
|
|
1951
|
+
agentId: session.id,
|
|
1952
|
+
name,
|
|
1953
|
+
...(typeof session.metadata?.threadKey === "string" ? { threadKey: session.metadata.threadKey } : {}),
|
|
1954
|
+
eventType: event.type,
|
|
1955
|
+
kind: piboAgentObservationKind(event.type),
|
|
1956
|
+
...(role ? { role } : {}),
|
|
1957
|
+
...(text ? { text } : {}),
|
|
1958
|
+
...("toolName" in event && typeof event.toolName === "string" ? { toolName: event.toolName } : {}),
|
|
1959
|
+
...("toolCallId" in event && typeof event.toolCallId === "string" ? { toolCallId: event.toolCallId } : {}),
|
|
1960
|
+
...(event.type === "tool_execution_finished" ? { isError: event.isError } : event.type === "session_error" ? { isError: true } : {}),
|
|
1961
|
+
details: piboAgentObservationDetails(event),
|
|
1962
|
+
};
|
|
1963
|
+
this.agentObservations.push(observation);
|
|
1964
|
+
if (this.agentObservations.length > MAX_AGENT_OBSERVATIONS) {
|
|
1965
|
+
const evicted = this.agentObservations.splice(0, this.agentObservations.length - MAX_AGENT_OBSERVATIONS);
|
|
1966
|
+
for (const item of evicted) {
|
|
1967
|
+
this.agentObservationEvictedThroughByParent.set(item.managingParentId, Math.max(this.agentObservationEvictedThroughByParent.get(item.managingParentId) ?? 0, item.sequence));
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1796
1971
|
emitOutput = (event) => {
|
|
1797
1972
|
const session = this.sessionStore.get(event.piboSessionId);
|
|
1973
|
+
this.recordAgentObservation(event, session);
|
|
1798
1974
|
this.telemetryRecorder?.recordOutput(event, { session, status: this.sessions.get(event.piboSessionId)?.getStatus() });
|
|
1799
1975
|
this.signalRegistry.project({ type: "pibo_output", event, session });
|
|
1800
1976
|
this.pluginRegistry.notifyEvent(event);
|
|
@@ -322,8 +322,20 @@ function attributesForOutputEvent(event) {
|
|
|
322
322
|
return { inlineText: event.text, source: event.source, queuedMessages: event.queuedMessages };
|
|
323
323
|
if (event.type === "message_steered")
|
|
324
324
|
return { inlineText: event.text, source: event.source, activeEventId: event.activeEventId };
|
|
325
|
+
if (event.type === "message_started")
|
|
326
|
+
return { inlineText: event.text, source: event.source };
|
|
327
|
+
if (event.type === "message_finished")
|
|
328
|
+
return { source: event.source };
|
|
325
329
|
if (event.type === "assistant_message" || event.type === "assistant_delta")
|
|
326
330
|
return { assistantIndex: event.assistantIndex, contentIndex: event.contentIndex };
|
|
331
|
+
if (event.type === "assistant_usage")
|
|
332
|
+
return {
|
|
333
|
+
inputTokens: event.inputTokens,
|
|
334
|
+
outputTokens: event.outputTokens,
|
|
335
|
+
cacheReadTokens: event.cacheReadTokens,
|
|
336
|
+
cacheWriteTokens: event.cacheWriteTokens,
|
|
337
|
+
totalTokens: event.totalTokens,
|
|
338
|
+
};
|
|
327
339
|
if (event.type === "thinking_started" || event.type === "thinking_delta" || event.type === "thinking_finished")
|
|
328
340
|
return { thinkingIndex: event.thinkingIndex, contentIndex: event.contentIndex };
|
|
329
341
|
if (event.type === "tool_call")
|