@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.
- 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.4.0.vsix} +0 -0
- package/dist/compute/cli.js +13 -0
- package/dist/compute/pool/artifacts.js +116 -0
- package/dist/compute/pool/cli.js +156 -0
- package/dist/compute/pool/config.js +101 -0
- package/dist/compute/pool/docker.js +157 -0
- package/dist/compute/pool/seeds.js +201 -0
- package/dist/compute/pool/service.js +402 -0
- package/dist/compute/pool/store.js +239 -0
- package/dist/compute/pool/types.js +1 -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/resources/lifecycle.js +22 -2
- package/dist/resources/reaper.js +1 -0
- 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/dist/web/channel.js +9 -3
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -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
|
-
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createPiboGoalToolDefinitions, PIBO_GOAL_TOOL_NAMES } from "../loops/tools.js";
|
|
2
2
|
import { createRunToolDefinitions } from "../runs/tools.js";
|
|
3
|
-
import {
|
|
3
|
+
import { createAgentToolDefinitions } from "../subagents/tool.js";
|
|
4
4
|
import { CODEX_BROWSER_TOOL_NAMES, createCodexBrowserToolDefinitions, } from "./codex-browser.js";
|
|
5
5
|
import { createCodexCompatToolDefinitions } from "./codex-compat.js";
|
|
6
6
|
import { createRuntimeToolDefinition } from "./runtime/tool.js";
|
|
@@ -18,6 +18,7 @@ export function isEnabledCodexBrowserToolProfile(tool) {
|
|
|
18
18
|
}
|
|
19
19
|
export function isGeneratedPiboTool(name) {
|
|
20
20
|
return name === "runtime"
|
|
21
|
+
|| name.startsWith("pibo_agents_")
|
|
21
22
|
|| name.startsWith("pibo_subagent_")
|
|
22
23
|
|| name.startsWith("pibo_run_")
|
|
23
24
|
|| PIBO_GOAL_TOOL_NAMES.includes(name);
|
|
@@ -33,6 +34,9 @@ function getToolDefinition(tool, context = {}) {
|
|
|
33
34
|
/** Assemble the selected Pibo-managed tool set without importing any harness package. */
|
|
34
35
|
export function createPiboSessionToolDefinitions(options) {
|
|
35
36
|
const { profile } = options;
|
|
37
|
+
if (profile.subagents.some((subagent) => subagent.enabled !== false) && options.subagentRunner && !options.agentsController) {
|
|
38
|
+
throw new Error("CreatePiboSessionToolDefinitionsOptions.subagentRunner is retired. Provide agentsController so the session can expose the four pibo_agents_* management tools.");
|
|
39
|
+
}
|
|
36
40
|
const runtimeProfileTool = profile.tools.find(isEnabledRuntimeToolProfile);
|
|
37
41
|
const runtimeTool = runtimeProfileTool && options.runtimeToolController
|
|
38
42
|
? createRuntimeToolDefinition(options.runtimeToolController)
|
|
@@ -53,8 +57,8 @@ export function createPiboSessionToolDefinitions(options) {
|
|
|
53
57
|
const goalTools = profile.toolPackages.goalControl !== false
|
|
54
58
|
? createPiboGoalToolDefinitions(options.toolContext ?? {})
|
|
55
59
|
: [];
|
|
56
|
-
const
|
|
57
|
-
?
|
|
60
|
+
const agentTools = options.agentsController
|
|
61
|
+
? createAgentToolDefinitions(profile.subagents, options.agentsController)
|
|
58
62
|
: [];
|
|
59
63
|
const nativeYieldableTools = [...(options.nativeYieldableTools ?? [])];
|
|
60
64
|
const yieldableTools = [
|
|
@@ -64,7 +68,7 @@ export function createPiboSessionToolDefinitions(options) {
|
|
|
64
68
|
.map((tool) => getToolDefinition(tool, options.toolContext)),
|
|
65
69
|
...(runtimeTool && runtimeProfileTool?.yieldable !== false ? [runtimeTool] : []),
|
|
66
70
|
...codexBrowserTools.filter((definition) => profile.tools.find((tool) => tool.name === definition.name)?.yieldable !== false),
|
|
67
|
-
...
|
|
71
|
+
...agentTools,
|
|
68
72
|
...codexCompatTools,
|
|
69
73
|
];
|
|
70
74
|
const runTools = profile.toolPackages.runControl === true
|
|
@@ -77,7 +81,7 @@ export function createPiboSessionToolDefinitions(options) {
|
|
|
77
81
|
...profileToolDefinitions,
|
|
78
82
|
...(runtimeTool ? [runtimeTool] : []),
|
|
79
83
|
...codexBrowserTools,
|
|
80
|
-
...
|
|
84
|
+
...agentTools,
|
|
81
85
|
...codexCompatTools,
|
|
82
86
|
...goalTools,
|
|
83
87
|
...runTools,
|
package/dist/web/channel.js
CHANGED
|
@@ -78,7 +78,13 @@ export function stripSocketPeerHeaderFromResponse(response) {
|
|
|
78
78
|
headers,
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
|
-
function createRequestBaseURL(nodeRequest, host, port) {
|
|
81
|
+
function createRequestBaseURL(nodeRequest, host, port, canonicalBaseURL) {
|
|
82
|
+
const requestHost = firstHeaderValue(nodeRequest.headers.host);
|
|
83
|
+
if (canonicalBaseURL && requestHost) {
|
|
84
|
+
const canonical = new URL(canonicalBaseURL);
|
|
85
|
+
if (requestHost.toLowerCase() === canonical.host.toLowerCase())
|
|
86
|
+
return canonical.origin;
|
|
87
|
+
}
|
|
82
88
|
if (isLoopbackAddress(nodeRequest.socket.remoteAddress)) {
|
|
83
89
|
const forwardedHost = firstHeaderValue(nodeRequest.headers["x-forwarded-host"]);
|
|
84
90
|
const forwardedProto = firstHeaderValue(nodeRequest.headers["x-forwarded-proto"]);
|
|
@@ -86,7 +92,7 @@ function createRequestBaseURL(nodeRequest, host, port) {
|
|
|
86
92
|
return `${forwardedProto}://${forwardedHost}`;
|
|
87
93
|
}
|
|
88
94
|
}
|
|
89
|
-
return `http://${
|
|
95
|
+
return `http://${requestHost ?? `${host}:${port}`}`;
|
|
90
96
|
}
|
|
91
97
|
function isActiveRunStatus(status) {
|
|
92
98
|
return typeof status === "string" && ["queued", "starting", "running", "streaming", "waiting", "blocked", "retrying", "compacting", "pausing"].includes(status);
|
|
@@ -235,7 +241,7 @@ export function createWebHostChannel(options = {}) {
|
|
|
235
241
|
};
|
|
236
242
|
const handleRequest = async (nodeRequest, nodeResponse) => {
|
|
237
243
|
try {
|
|
238
|
-
const baseURL = createRequestBaseURL(nodeRequest, host, port);
|
|
244
|
+
const baseURL = createRequestBaseURL(nodeRequest, host, port, options.canonicalBaseURL);
|
|
239
245
|
const baseRequest = await nodeRequestToWebRequest(nodeRequest, baseURL);
|
|
240
246
|
// Inject the TCP socket peer into every request so the local auth
|
|
241
247
|
// plugin can apply the same loopback predicate from `getSession`
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pasko70/pibo",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@pasko70/pibo",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.4.0",
|
|
10
10
|
"workspaces": [
|
|
11
11
|
"packages/workflows"
|
|
12
12
|
],
|