@pasko70/pibo 2.2.4 → 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/capabilities.js +9 -1
- package/dist/agent-runtime/context-build.js +5 -2
- package/dist/agent-runtimes/codex-native/adapter.js +5 -0
- package/dist/agent-runtimes/omp/adapter.js +5 -0
- package/dist/agent-runtimes/omp/turn.js +2 -0
- package/dist/agent-runtimes/pi/adapter.js +28 -7
- package/dist/agent-runtimes/pi/intent-tracing.js +120 -0
- package/dist/agent-runtimes/pi/routed-session.js +25 -8
- package/dist/agent-runtimes/pi/runtime.js +28 -16
- package/dist/apps/chat/chat-settings-routes.js +44 -3
- package/dist/apps/chat/chat-transcription.js +85 -0
- package/dist/apps/chat/data/chat-data-mappers.js +4 -4
- package/dist/apps/chat/stream.js +23 -9
- package/dist/apps/chat/trace-v2.js +1 -0
- package/dist/apps/chat/web-app.js +49 -0
- package/dist/apps/chat-ui/assets/{dist-luJVFsmq.js → dist-Byygd1lH.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-ltfz1vFX.js → dist-C9BrS7sL.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-rf4HYdoa.js → dist-CUcAofmV.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CImWCF2M.js → dist-D4RU6xu3.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BFwTuvyi.js → dist-DusFwy0L.js} +1 -1
- package/dist/apps/chat-ui/assets/{index-nZQXUpxE.css → index-BJ56TREg.css} +1 -1
- package/dist/apps/chat-ui/assets/index-Bifi_kjN.js +228 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-WsLm1mo3.js +43 -0
- 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.3.0.vsix +0 -0
- package/dist/core/codex-compat.js +1 -3
- package/dist/core/context-build.js +16 -7
- package/dist/core/gateway-resource-guard.js +35 -14
- package/dist/core/gateway-settings.js +64 -0
- package/dist/core/session-router.js +226 -46
- package/dist/core/user-settings.js +20 -0
- package/dist/data/ingest-service.js +14 -2
- package/dist/debug/agents.js +391 -0
- package/dist/debug/index.js +14 -2
- package/dist/gateway/server.js +2 -0
- package/dist/index.js +6 -1
- package/dist/plugins/builtin.js +4 -2
- package/dist/plugins/openai-chatgpt-transcription.js +12 -0
- package/dist/plugins/openai-transcription.js +12 -0
- package/dist/plugins/registry.js +23 -0
- package/dist/session-ui/delegation.js +4 -2
- package/dist/session-ui/terminalRows.js +51 -1
- package/dist/shared/trace-async-agent-runs.js +4 -2
- package/dist/shared/trace-event-projection.js +12 -2
- package/dist/shared/trace-live-reducer.js +4 -0
- package/dist/shared/trace-patch-nodes.js +1 -0
- 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/dist/transcription/openai-chatgpt.js +148 -0
- package/dist/transcription/openai.js +72 -0
- package/dist/transcription/types.js +8 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/apps/chat-ui/assets/index-D2Maa2v1.js +0 -226
- package/dist/apps/chat-vscode-web/assets/index-BpurWVnX.js +0 -41
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-2.2.4.vsix +0 -0
|
@@ -18,7 +18,55 @@ export function buildCompactTerminalRows(traceView, options) {
|
|
|
18
18
|
.filter((item) => item.node.type !== "agent.turn" && (options.showThinking || item.node.type !== "model.reasoning"));
|
|
19
19
|
const candidates = syncThinkingToolRows(flatNodes.map((item) => createRowCandidate(item.node, item.turnId)));
|
|
20
20
|
applyCompletedTurnTiming(candidates, turnById);
|
|
21
|
-
|
|
21
|
+
const reconciled = reconcileConceptualRowCandidates(candidates);
|
|
22
|
+
const rows = (options.toolDisplayMode ?? "default") === "default"
|
|
23
|
+
? groupRelatedToolCandidates(reconciled).map((candidate) => candidate.row)
|
|
24
|
+
: reconciled.map((candidate) => candidate.row);
|
|
25
|
+
return applyToolDisplayMode(rows, options.toolDisplayMode ?? "default");
|
|
26
|
+
}
|
|
27
|
+
function applyToolDisplayMode(rows, mode) {
|
|
28
|
+
if (mode === "default")
|
|
29
|
+
return rows;
|
|
30
|
+
if (mode === "hide")
|
|
31
|
+
return rows.filter((row) => !isToolDisplayRow(row));
|
|
32
|
+
return rows.flatMap((row) => {
|
|
33
|
+
if (!isToolDisplayRow(row))
|
|
34
|
+
return [row];
|
|
35
|
+
const intent = row.intent?.trim();
|
|
36
|
+
if (mode === "intent" && !intent)
|
|
37
|
+
return [];
|
|
38
|
+
const slimRow = {
|
|
39
|
+
...row,
|
|
40
|
+
lines: row.lines.slice(0, 1),
|
|
41
|
+
input: undefined,
|
|
42
|
+
output: undefined,
|
|
43
|
+
error: undefined,
|
|
44
|
+
markdown: undefined,
|
|
45
|
+
expandable: false,
|
|
46
|
+
singleLine: true,
|
|
47
|
+
previewOmission: undefined,
|
|
48
|
+
detailItems: undefined,
|
|
49
|
+
};
|
|
50
|
+
if (mode !== "intent")
|
|
51
|
+
return [slimRow];
|
|
52
|
+
return [{
|
|
53
|
+
...slimRow,
|
|
54
|
+
title: undefined,
|
|
55
|
+
summary: undefined,
|
|
56
|
+
lines: [{
|
|
57
|
+
prefix: "bullet",
|
|
58
|
+
tokens: [token(intent, row.status === "error" ? "red" : row.status === "done" ? "green" : "cyan", "semibold")],
|
|
59
|
+
}],
|
|
60
|
+
}];
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function isToolDisplayRow(row) {
|
|
64
|
+
return row.id.startsWith("terminal:tool:")
|
|
65
|
+
|| row.kind === "tool.call"
|
|
66
|
+
|| row.kind === "tool.image"
|
|
67
|
+
|| row.kind === "tool.group.exploring"
|
|
68
|
+
|| row.kind === "tool.group.images"
|
|
69
|
+
|| row.kind === "agent.delegation";
|
|
22
70
|
}
|
|
23
71
|
export function findActiveTurnStartedAt(traceView) {
|
|
24
72
|
if (!traceView)
|
|
@@ -112,6 +160,7 @@ function createRowCandidate(node, turnId) {
|
|
|
112
160
|
row: {
|
|
113
161
|
...candidate.row,
|
|
114
162
|
id: compactTerminalRowIdentity(node),
|
|
163
|
+
intent: node.intent,
|
|
115
164
|
...debugFields(node),
|
|
116
165
|
},
|
|
117
166
|
};
|
|
@@ -164,6 +213,7 @@ function reconcileConceptualRowCandidates(candidates) {
|
|
|
164
213
|
...existing.row,
|
|
165
214
|
...candidate.row,
|
|
166
215
|
sourceNodeIds: [...new Set([...existing.row.sourceNodeIds, ...candidate.row.sourceNodeIds])],
|
|
216
|
+
intent: candidate.row.intent ?? existing.row.intent,
|
|
167
217
|
input: candidate.row.input ?? existing.row.input,
|
|
168
218
|
output: candidate.row.output ?? existing.row.output,
|
|
169
219
|
error: candidate.row.error ?? existing.row.error,
|
|
@@ -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
|
|
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`,
|
|
@@ -465,6 +465,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
465
465
|
id: `tool:${event.toolCallId}`,
|
|
466
466
|
parentId: turnParentId,
|
|
467
467
|
toolCallId: event.toolCallId,
|
|
468
|
+
intent: event.intent,
|
|
468
469
|
type: subagentTool ? "agent.delegation" : "tool.call",
|
|
469
470
|
title: event.toolName,
|
|
470
471
|
status: event.type === "tool_execution_finished"
|
|
@@ -685,6 +686,8 @@ function isNativeHistoryToolEchoEvent(event, coverage, sessionStatus) {
|
|
|
685
686
|
event.type !== "tool_execution_updated" &&
|
|
686
687
|
event.type !== "tool_execution_finished")
|
|
687
688
|
return false;
|
|
689
|
+
if (typeof event.intent === "string" && event.intent.trim())
|
|
690
|
+
return false;
|
|
688
691
|
return coverage.toolCallIds.has(event.toolCallId) || historyCoversEvent(event, coverage);
|
|
689
692
|
}
|
|
690
693
|
export function mergeMessageTurnTimings(...groups) {
|
|
@@ -917,6 +920,7 @@ function thinkingEventNodeId(event) {
|
|
|
917
920
|
}
|
|
918
921
|
function mergeToolEvent(target, update) {
|
|
919
922
|
target.status = update.status;
|
|
923
|
+
target.intent = update.intent ?? target.intent;
|
|
920
924
|
target.summary = update.summary ?? target.summary;
|
|
921
925
|
target.input = mergeDelegationInput(target, update);
|
|
922
926
|
target.output = update.output ?? target.output;
|
|
@@ -943,8 +947,14 @@ function findLegacySubagentLinkTarget(nodes, update) {
|
|
|
943
947
|
}
|
|
944
948
|
function delegationAgentName(node) {
|
|
945
949
|
const input = isObjectRecord(node.input) ? node.input : undefined;
|
|
946
|
-
const value = typeof input?.
|
|
947
|
-
|
|
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;
|
|
948
958
|
}
|
|
949
959
|
function delegationThreadKey(value) {
|
|
950
960
|
if (!isObjectRecord(value) || typeof value.threadKey !== "string")
|
|
@@ -80,6 +80,7 @@ function storedEventFromStreamEvent(event, piboSessionId, nextSequence, now) {
|
|
|
80
80
|
toolCallId: event.toolCallId,
|
|
81
81
|
toolName: event.toolName,
|
|
82
82
|
args: event.args,
|
|
83
|
+
...(event.intent ? { intent: event.intent } : {}),
|
|
83
84
|
};
|
|
84
85
|
return makeStored(event, piboSessionId, "tool_execution_started", payload, nextSequence, now);
|
|
85
86
|
}
|
|
@@ -95,6 +96,7 @@ function storedEventFromStreamEvent(event, piboSessionId, nextSequence, now) {
|
|
|
95
96
|
toolName: event.toolName,
|
|
96
97
|
args: event.args,
|
|
97
98
|
partialResult: event.partialResult,
|
|
99
|
+
...(event.intent ? { intent: event.intent } : {}),
|
|
98
100
|
}
|
|
99
101
|
: {
|
|
100
102
|
type: "tool_call",
|
|
@@ -104,6 +106,7 @@ function storedEventFromStreamEvent(event, piboSessionId, nextSequence, now) {
|
|
|
104
106
|
toolName: event.toolName,
|
|
105
107
|
args: event.args,
|
|
106
108
|
argsComplete: Boolean(event.argsComplete),
|
|
109
|
+
...(event.intent ? { intent: event.intent } : {}),
|
|
107
110
|
};
|
|
108
111
|
return makeStored(event, piboSessionId, sourceEventType, payload, nextSequence, now);
|
|
109
112
|
}
|
|
@@ -116,6 +119,7 @@ function storedEventFromStreamEvent(event, piboSessionId, nextSequence, now) {
|
|
|
116
119
|
toolName: event.toolName,
|
|
117
120
|
result: event.result,
|
|
118
121
|
isError: Boolean(event.isError),
|
|
122
|
+
...(event.intent ? { intent: event.intent } : {}),
|
|
119
123
|
};
|
|
120
124
|
return makeStored(event, piboSessionId, "tool_execution_finished", payload, nextSequence, now);
|
|
121
125
|
}
|
|
@@ -52,6 +52,7 @@ function traceNodeShallowEqual(left, right) {
|
|
|
52
52
|
left.eventId === right.eventId &&
|
|
53
53
|
left.toolCallId === right.toolCallId &&
|
|
54
54
|
left.runId === right.runId &&
|
|
55
|
+
left.intent === right.intent &&
|
|
55
56
|
left.type === right.type &&
|
|
56
57
|
left.title === right.title &&
|
|
57
58
|
left.status === right.status &&
|
|
@@ -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) =>
|
|
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
|
|
41
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
export const PIBO_AGENT_OBSERVATION_TEXT_MAX_BYTES = 4 * 1024;
|
|
2
|
+
export const PIBO_AGENT_OBSERVATION_DETAILS_MAX_BYTES = 32 * 1024;
|
|
3
|
+
export const PIBO_AGENT_OBSERVATION_DEFAULT_LIMIT = 50;
|
|
4
|
+
export const PIBO_AGENT_OBSERVATION_MAX_LIMIT = 200;
|
|
5
|
+
export function piboAgentObservationSourceFromEvent(event) {
|
|
6
|
+
const source = {
|
|
7
|
+
eventType: event.type,
|
|
8
|
+
fallbackText: "toolName" in event && typeof event.toolName === "string" ? event.toolName : event.type,
|
|
9
|
+
};
|
|
10
|
+
if ("source" in event && typeof event.source === "string")
|
|
11
|
+
source.source = event.source;
|
|
12
|
+
if ("text" in event)
|
|
13
|
+
source.text = event.text;
|
|
14
|
+
if (event.type === "session_error")
|
|
15
|
+
source.error = event.error;
|
|
16
|
+
if (event.type === "tool_call" || event.type === "tool_execution_started")
|
|
17
|
+
source.args = event.args;
|
|
18
|
+
if (event.type === "tool_execution_updated")
|
|
19
|
+
source.partialResult = event.partialResult;
|
|
20
|
+
if (event.type === "tool_execution_finished" || event.type === "execution_result" || event.type === "compaction_end")
|
|
21
|
+
source.result = event.result;
|
|
22
|
+
if (event.type === "execution_result")
|
|
23
|
+
source.action = event.action;
|
|
24
|
+
if (event.type === "compaction_start" || event.type === "compaction_end")
|
|
25
|
+
source.reason = event.reason;
|
|
26
|
+
if (event.type === "subagent_session")
|
|
27
|
+
source.subagentName = event.subagentName;
|
|
28
|
+
return source;
|
|
29
|
+
}
|
|
30
|
+
export function piboAgentObservationKind(eventType) {
|
|
31
|
+
if (["message_queued", "message_steered", "message_started", "assistant_delta", "assistant_message", "message_finished"].includes(eventType))
|
|
32
|
+
return "message";
|
|
33
|
+
if (eventType.startsWith("thinking_"))
|
|
34
|
+
return "thinking";
|
|
35
|
+
if (eventType.startsWith("tool_") || eventType === "subagent_session")
|
|
36
|
+
return "tool";
|
|
37
|
+
if (eventType === "session_error")
|
|
38
|
+
return "error";
|
|
39
|
+
if (eventType === "execution_result" || eventType.startsWith("compaction_"))
|
|
40
|
+
return "lifecycle";
|
|
41
|
+
return "event";
|
|
42
|
+
}
|
|
43
|
+
export function piboAgentObservationRole(source) {
|
|
44
|
+
const eventType = source.eventType;
|
|
45
|
+
if (eventType === "assistant_message" || eventType === "assistant_delta" || eventType.startsWith("thinking_"))
|
|
46
|
+
return "assistant";
|
|
47
|
+
if (eventType === "message_queued" || eventType === "message_steered" || eventType === "message_started" || eventType === "message_finished")
|
|
48
|
+
return source.source ?? "actor";
|
|
49
|
+
if (eventType.startsWith("tool_"))
|
|
50
|
+
return "tool";
|
|
51
|
+
if (eventType === "subagent_session")
|
|
52
|
+
return "agent";
|
|
53
|
+
if (eventType === "session_error" || eventType === "execution_result" || eventType.startsWith("compaction_"))
|
|
54
|
+
return "system";
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
export function piboAgentObservationText(source) {
|
|
58
|
+
if (typeof source.text === "string")
|
|
59
|
+
return boundPiboAgentObservationText(source.text);
|
|
60
|
+
if (typeof source.error === "string")
|
|
61
|
+
return boundPiboAgentObservationText(source.error);
|
|
62
|
+
if (source.eventType === "tool_call" || source.eventType === "tool_execution_started") {
|
|
63
|
+
return stringifyPiboAgentObservationValue(source.args);
|
|
64
|
+
}
|
|
65
|
+
if (source.eventType === "tool_execution_updated")
|
|
66
|
+
return stringifyPiboAgentObservationValue(source.partialResult);
|
|
67
|
+
if (source.eventType === "tool_execution_finished")
|
|
68
|
+
return stringifyPiboAgentObservationValue(source.result);
|
|
69
|
+
if (source.eventType === "subagent_session" && typeof source.subagentName === "string") {
|
|
70
|
+
return boundPiboAgentObservationText(source.subagentName);
|
|
71
|
+
}
|
|
72
|
+
if (source.eventType === "execution_result") {
|
|
73
|
+
return stringifyPiboAgentObservationValue(source.result) ?? stringifyPiboAgentObservationValue(source.action);
|
|
74
|
+
}
|
|
75
|
+
if ((source.eventType === "compaction_start" || source.eventType === "compaction_end") && typeof source.reason === "string") {
|
|
76
|
+
return boundPiboAgentObservationText(source.reason);
|
|
77
|
+
}
|
|
78
|
+
return stringifyPiboAgentObservationValue(source.fallbackText);
|
|
79
|
+
}
|
|
80
|
+
export function boundPiboAgentObservationText(value) {
|
|
81
|
+
if (Buffer.byteLength(value, "utf8") <= PIBO_AGENT_OBSERVATION_TEXT_MAX_BYTES)
|
|
82
|
+
return value;
|
|
83
|
+
const suffix = "…";
|
|
84
|
+
let end = Math.min(value.length, PIBO_AGENT_OBSERVATION_TEXT_MAX_BYTES);
|
|
85
|
+
while (end > 0 && Buffer.byteLength(`${value.slice(0, end)}${suffix}`, "utf8") > PIBO_AGENT_OBSERVATION_TEXT_MAX_BYTES)
|
|
86
|
+
end -= 1;
|
|
87
|
+
return `${value.slice(0, end)}${suffix}`;
|
|
88
|
+
}
|
|
89
|
+
export function stringifyPiboAgentObservationValue(value) {
|
|
90
|
+
if (typeof value === "string")
|
|
91
|
+
return boundPiboAgentObservationText(value);
|
|
92
|
+
if (value === undefined)
|
|
93
|
+
return undefined;
|
|
94
|
+
try {
|
|
95
|
+
return boundPiboAgentObservationText(JSON.stringify(value));
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return boundPiboAgentObservationText(String(value));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export function piboAgentObservationDetails(value) {
|
|
102
|
+
let serialized;
|
|
103
|
+
try {
|
|
104
|
+
serialized = JSON.stringify(value) ?? "null";
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return { truncated: true, preview: boundPiboAgentObservationText(String(value)) };
|
|
108
|
+
}
|
|
109
|
+
if (Buffer.byteLength(serialized, "utf8") <= PIBO_AGENT_OBSERVATION_DETAILS_MAX_BYTES) {
|
|
110
|
+
return JSON.parse(serialized);
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
truncated: true,
|
|
114
|
+
preview: boundPiboAgentObservationText(serialized),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export function parsePiboAgentObservationTimestamp(value, label) {
|
|
118
|
+
if (value === undefined)
|
|
119
|
+
return undefined;
|
|
120
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/.test(value)) {
|
|
121
|
+
throw new Error(`Agent observation ${label} must be a valid ISO-8601 timestamp.`);
|
|
122
|
+
}
|
|
123
|
+
const timestamp = Date.parse(value);
|
|
124
|
+
if (!Number.isFinite(timestamp))
|
|
125
|
+
throw new Error(`Agent observation ${label} must be a valid ISO-8601 timestamp.`);
|
|
126
|
+
return timestamp;
|
|
127
|
+
}
|
|
128
|
+
export function normalizePiboAgentObservationOrder(value) {
|
|
129
|
+
if (value === undefined)
|
|
130
|
+
return "asc";
|
|
131
|
+
if (value !== "asc" && value !== "desc")
|
|
132
|
+
throw new Error(`Agent observation order must be "asc" or "desc".`);
|
|
133
|
+
return value;
|
|
134
|
+
}
|
|
135
|
+
export function normalizePiboAgentObservationLimit(value) {
|
|
136
|
+
if (value === undefined)
|
|
137
|
+
return PIBO_AGENT_OBSERVATION_DEFAULT_LIMIT;
|
|
138
|
+
if (!Number.isInteger(value) || value < 1 || value > PIBO_AGENT_OBSERVATION_MAX_LIMIT) {
|
|
139
|
+
throw new Error(`Agent observation limit must be an integer from 1 to ${PIBO_AGENT_OBSERVATION_MAX_LIMIT}.`);
|
|
140
|
+
}
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
export function normalizePiboAgentObservationCursor(value) {
|
|
144
|
+
if (value === undefined)
|
|
145
|
+
return undefined;
|
|
146
|
+
if (!Number.isInteger(value) || value < 0)
|
|
147
|
+
throw new Error("Agent observation afterSequence must be a non-negative integer.");
|
|
148
|
+
return value;
|
|
149
|
+
}
|
package/dist/subagents/tool.js
CHANGED
|
@@ -1,16 +1,168 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
|
+
import { piboStringEnum } from "../tools/schema.js";
|
|
3
4
|
import { definePiboTool } from "../tools/contract.js";
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
export const PIBO_AGENT_TOOL_NAMES = [
|
|
6
|
+
"pibo_agents_send_message",
|
|
7
|
+
"pibo_agents_list_agents",
|
|
8
|
+
"pibo_agents_observe",
|
|
9
|
+
"pibo_agents_kill",
|
|
10
|
+
];
|
|
11
|
+
function availableAgentDescription(subagent) {
|
|
12
|
+
return subagent.description?.trim() || `Targets profile ${subagent.targetProfile}.`;
|
|
13
|
+
}
|
|
14
|
+
export function listAvailableAgents(subagents) {
|
|
15
|
+
return subagents
|
|
16
|
+
.filter((subagent) => subagent.enabled !== false)
|
|
17
|
+
.map((subagent) => ({
|
|
18
|
+
name: subagent.name,
|
|
19
|
+
description: availableAgentDescription(subagent),
|
|
20
|
+
profile: subagent.targetProfile,
|
|
21
|
+
...(subagent.model ? { model: { ...subagent.model } } : {}),
|
|
22
|
+
...(subagent.thinkingLevel ? { thinkingLevel: subagent.thinkingLevel } : {}),
|
|
23
|
+
}));
|
|
6
24
|
}
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
|
|
25
|
+
export function formatAvailableAgentsForPrompt(subagents) {
|
|
26
|
+
return listAvailableAgents(subagents)
|
|
27
|
+
.map((agent) => `- ${agent.name}: ${agent.description}`)
|
|
28
|
+
.join("\n");
|
|
10
29
|
}
|
|
30
|
+
function resultText(prefix, value) {
|
|
31
|
+
return `${prefix}\n${JSON.stringify(value, null, 2)}`;
|
|
32
|
+
}
|
|
33
|
+
export function createAgentToolDefinitions(subagents, controller) {
|
|
34
|
+
const enabled = subagents.filter((subagent) => subagent.enabled !== false);
|
|
35
|
+
if (enabled.length === 0)
|
|
36
|
+
return [];
|
|
37
|
+
const byName = new Map();
|
|
38
|
+
for (const subagent of enabled) {
|
|
39
|
+
if (byName.has(subagent.name))
|
|
40
|
+
throw new Error(`Duplicate agent name "${subagent.name}"`);
|
|
41
|
+
byName.set(subagent.name, subagent);
|
|
42
|
+
}
|
|
43
|
+
const names = [...byName.keys()];
|
|
44
|
+
const availableAgents = listAvailableAgents(enabled);
|
|
45
|
+
const catalog = formatAvailableAgentsForPrompt(enabled);
|
|
46
|
+
return [
|
|
47
|
+
definePiboTool({
|
|
48
|
+
name: "pibo_agents_send_message",
|
|
49
|
+
title: "Pibo Agents Send Message",
|
|
50
|
+
description: [
|
|
51
|
+
"Send a message to an available delegated agent. Foreground execution waits for the reply; use pibo_run_start for asynchronous delegation.",
|
|
52
|
+
"Available agents:",
|
|
53
|
+
catalog,
|
|
54
|
+
].join("\n"),
|
|
55
|
+
promptSnippet: "Send work to an available delegated agent by name. Reuse threadKey to continue its child session. Use pibo_run_start with this tool for asynchronous work. The tool definition lists the available names and parent-visible descriptions.",
|
|
56
|
+
executionMode: "parallel",
|
|
57
|
+
inputSchema: Type.Object({
|
|
58
|
+
name: piboStringEnum(names, { description: "Available delegated agent name" }),
|
|
59
|
+
message: Type.String({ description: "Message to send to the delegated agent" }),
|
|
60
|
+
threadKey: Type.Optional(Type.String({
|
|
61
|
+
description: "Stable key for continuing one delegated-agent conversation. Omit it to create a new child session.",
|
|
62
|
+
maxLength: 256,
|
|
63
|
+
})),
|
|
64
|
+
}),
|
|
65
|
+
async execute(toolCallId, params, signal) {
|
|
66
|
+
const subagent = byName.get(params.name);
|
|
67
|
+
if (!subagent)
|
|
68
|
+
throw new Error(`Unknown delegated agent "${params.name}"`);
|
|
69
|
+
const result = await controller.sendMessage({
|
|
70
|
+
subagent,
|
|
71
|
+
message: params.message,
|
|
72
|
+
threadKey: params.threadKey,
|
|
73
|
+
toolCallId,
|
|
74
|
+
signal,
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
content: [{
|
|
78
|
+
type: "text",
|
|
79
|
+
text: `Agent ${result.name} (${result.agentId}, thread ${result.threadKey}) replied:\n${result.reply.text}`,
|
|
80
|
+
}],
|
|
81
|
+
details: result,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
definePiboTool({
|
|
86
|
+
name: "pibo_agents_list_agents",
|
|
87
|
+
title: "Pibo Agents List Agents",
|
|
88
|
+
description: "List available delegated-agent profiles and child agent instances owned by this session.",
|
|
89
|
+
promptSnippet: "List available delegated agents and existing child instances with their agentId, thread, profile, and running, idle, or killed status.",
|
|
90
|
+
executionMode: "parallel",
|
|
91
|
+
annotations: { readOnly: true },
|
|
92
|
+
inputSchema: Type.Object({}),
|
|
93
|
+
async execute() {
|
|
94
|
+
const result = { availableAgents, agents: controller.listAgents() };
|
|
95
|
+
return {
|
|
96
|
+
content: [{ type: "text", text: resultText("Delegated agents:", result) }],
|
|
97
|
+
details: result,
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
definePiboTool({
|
|
102
|
+
name: "pibo_agents_observe",
|
|
103
|
+
title: "Pibo Agents Observe",
|
|
104
|
+
description: "Read bounded delegated-agent observations with exact agent, thread, event, kind, time, text, cursor, order, and limit filters.",
|
|
105
|
+
promptSnippet: "Observe child-agent activity. Array filters use OR within a field and different fields combine with AND. For cursor polling, pass afterSequence from the previous result; pages consume the oldest unseen observations even when order is desc.",
|
|
106
|
+
executionMode: "parallel",
|
|
107
|
+
annotations: { readOnly: true },
|
|
108
|
+
inputSchema: Type.Object({
|
|
109
|
+
agentIds: Type.Optional(Type.Array(Type.String({ description: "Owned child agentId" }), { maxItems: 50 })),
|
|
110
|
+
names: Type.Optional(Type.Array(piboStringEnum(names), { maxItems: 50 })),
|
|
111
|
+
threadKeys: Type.Optional(Type.Array(Type.String(), { maxItems: 50 })),
|
|
112
|
+
eventTypes: Type.Optional(Type.Array(Type.String({ description: "Exact Pibo output event type" }), { maxItems: 50 })),
|
|
113
|
+
kinds: Type.Optional(Type.Array(piboStringEnum(["message", "thinking", "tool", "error", "lifecycle", "event"]), { maxItems: 6 })),
|
|
114
|
+
since: Type.Optional(Type.String({ description: "Inclusive ISO-8601 lower timestamp bound" })),
|
|
115
|
+
until: Type.Optional(Type.String({ description: "Inclusive ISO-8601 upper timestamp bound" })),
|
|
116
|
+
textContains: Type.Optional(Type.String({ description: "Case-insensitive substring match against normalized observation text" })),
|
|
117
|
+
afterSequence: Type.Optional(Type.Integer({ description: "Exclusive live observation cursor. Cursor pages consume the oldest unseen observations; desc reverses only the returned page.", minimum: 0 })),
|
|
118
|
+
order: Type.Optional(piboStringEnum(["asc", "desc"], { default: "asc" })),
|
|
119
|
+
limit: Type.Optional(Type.Integer({ description: "Maximum observations to return", minimum: 1, maximum: 200, default: 50 })),
|
|
120
|
+
includeDetails: Type.Optional(Type.Boolean({ description: "Include the normalized source event in each observation" })),
|
|
121
|
+
}),
|
|
122
|
+
async execute(_toolCallId, params) {
|
|
123
|
+
const result = controller.observe(params);
|
|
124
|
+
return {
|
|
125
|
+
content: [{ type: "text", text: resultText("Agent observations:", result) }],
|
|
126
|
+
details: result,
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
}),
|
|
130
|
+
definePiboTool({
|
|
131
|
+
name: "pibo_agents_kill",
|
|
132
|
+
title: "Pibo Agents Kill",
|
|
133
|
+
description: "Terminate one owned child agent session subtree and cancel its yielded runs.",
|
|
134
|
+
promptSnippet: "Kill an owned child agent by agentId when its work is no longer needed. Use pibo_agents_list_agents to find the exact agentId.",
|
|
135
|
+
executionMode: "parallel",
|
|
136
|
+
annotations: { destructive: true, idempotent: true },
|
|
137
|
+
inputSchema: Type.Object({
|
|
138
|
+
agentId: Type.String({ description: "Exact child agentId returned by send_message or list_agents" }),
|
|
139
|
+
}),
|
|
140
|
+
async execute(_toolCallId, params) {
|
|
141
|
+
const result = await controller.killAgent(params.agentId);
|
|
142
|
+
return {
|
|
143
|
+
content: [{ type: "text", text: resultText(`Killed delegated agent ${params.agentId}.`, result) }],
|
|
144
|
+
details: result,
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
}),
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
function legacySubagentToolHash(value) {
|
|
151
|
+
return createHash("sha256").update(value).digest("hex").slice(0, 12);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* @deprecated Runtime-generated per-agent tools are no longer assembled by Pibo runtimes.
|
|
155
|
+
* This helper remains source-compatible for integrations migrating to PIBO_AGENT_TOOL_NAMES.
|
|
156
|
+
*/
|
|
11
157
|
export function createSubagentToolName(subagentName) {
|
|
12
|
-
|
|
158
|
+
const normalized = subagentName.trim().toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "");
|
|
159
|
+
return `pibo_subagent_${normalized || `subagent_${legacySubagentToolHash(subagentName)}`}`;
|
|
13
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* @deprecated Use createAgentToolDefinitions with a PiboAgentsController.
|
|
163
|
+
* Pibo runtimes expose only the four pibo_agents_* tools, but this legacy factory remains available
|
|
164
|
+
* for external callers during migration.
|
|
165
|
+
*/
|
|
14
166
|
export function createSubagentToolDefinitions(subagents, runner) {
|
|
15
167
|
const seen = new Set();
|
|
16
168
|
const definitions = [];
|
|
@@ -18,48 +170,27 @@ export function createSubagentToolDefinitions(subagents, runner) {
|
|
|
18
170
|
if (subagent.enabled === false)
|
|
19
171
|
continue;
|
|
20
172
|
const toolName = createSubagentToolName(subagent.name);
|
|
21
|
-
if (seen.has(toolName))
|
|
173
|
+
if (seen.has(toolName))
|
|
22
174
|
throw new Error(`Duplicate subagent tool name "${toolName}"`);
|
|
23
|
-
}
|
|
24
175
|
seen.add(toolName);
|
|
25
|
-
definitions.push(
|
|
176
|
+
definitions.push(definePiboTool({
|
|
177
|
+
name: toolName,
|
|
178
|
+
title: `Pibo Subagent ${subagent.name}`,
|
|
179
|
+
description: subagent.description ?? `Send a message to the ${subagent.name} subagent. Use threadKey to continue the same subagent session.`,
|
|
180
|
+
promptSnippet: subagent.description ?? `Send a message to the ${subagent.name} subagent. Pass the same threadKey when you want to continue the same subagent session.`,
|
|
181
|
+
executionMode: "parallel",
|
|
182
|
+
inputSchema: Type.Object({
|
|
183
|
+
message: Type.String({ description: "Message to send to the subagent" }),
|
|
184
|
+
threadKey: Type.Optional(Type.String({
|
|
185
|
+
description: "Stable key for continuing a previous subagent conversation. Omit it to create a new subagent session.",
|
|
186
|
+
maxLength: 256,
|
|
187
|
+
})),
|
|
188
|
+
}),
|
|
189
|
+
async execute(toolCallId, params, signal) {
|
|
190
|
+
const result = await runner.runSubagent({ subagent, message: params.message, threadKey: params.threadKey, toolCallId, signal });
|
|
191
|
+
return { content: [{ type: "text", text: result.reply.text }], details: result };
|
|
192
|
+
},
|
|
193
|
+
}));
|
|
26
194
|
}
|
|
27
195
|
return definitions;
|
|
28
196
|
}
|
|
29
|
-
function createSubagentToolDefinition(subagent, runner) {
|
|
30
|
-
const name = createSubagentToolName(subagent.name);
|
|
31
|
-
return definePiboTool({
|
|
32
|
-
name,
|
|
33
|
-
title: `Pibo Subagent ${subagent.name}`,
|
|
34
|
-
description: subagent.description ??
|
|
35
|
-
`Send a message to the ${subagent.name} subagent. Use threadKey to continue the same subagent session.`,
|
|
36
|
-
promptSnippet: subagent.description ??
|
|
37
|
-
`Send a message to the ${subagent.name} subagent. Pass the same threadKey when you want to continue the same subagent session.`,
|
|
38
|
-
executionMode: "parallel",
|
|
39
|
-
inputSchema: Type.Object({
|
|
40
|
-
message: Type.String({ description: "Message to send to the subagent" }),
|
|
41
|
-
threadKey: Type.Optional(Type.String({
|
|
42
|
-
description: "Stable key for continuing a previous subagent conversation. Omit it to create a new subagent session.",
|
|
43
|
-
maxLength: 256,
|
|
44
|
-
})),
|
|
45
|
-
}),
|
|
46
|
-
async execute(toolCallId, params, signal) {
|
|
47
|
-
const result = await runner.runSubagent({
|
|
48
|
-
subagent,
|
|
49
|
-
message: params.message,
|
|
50
|
-
threadKey: params.threadKey,
|
|
51
|
-
toolCallId,
|
|
52
|
-
signal,
|
|
53
|
-
});
|
|
54
|
-
return {
|
|
55
|
-
content: [
|
|
56
|
-
{
|
|
57
|
-
type: "text",
|
|
58
|
-
text: result.reply.text,
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
details: result,
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
}
|