@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
|
@@ -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";
|
|
@@ -15,6 +15,7 @@ import { AgentRuntimeBindingMissingError, AgentRuntimeUnavailableError } from ".
|
|
|
15
15
|
import { validateAgentRuntimeProfileCapabilities } from "../agent-runtime/profile-validation.js";
|
|
16
16
|
import { getDefaultPiboWorkspace } from "./workspace.js";
|
|
17
17
|
import { loadPiboModelDefaults, selectRequestedFastMode } from "./model-defaults.js";
|
|
18
|
+
import { loadPiboGatewaySettings } from "./gateway-settings.js";
|
|
18
19
|
import { loadPiboUserSettings } from "./user-settings.js";
|
|
19
20
|
import { resolvePiboSessionActiveModel } from "./session-model.js";
|
|
20
21
|
import { isPiboThinkingLevel } from "./thinking.js";
|
|
@@ -31,6 +32,7 @@ import { PORTABLE_HISTORY_HANDOFF_METADATA_KEY, PORTABLE_HISTORY_LAST_IMPORT_MET
|
|
|
31
32
|
const DEFAULT_SUBAGENT_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
|
|
32
33
|
const DEFAULT_SUBAGENT_MAX_DEPTH = 1;
|
|
33
34
|
const MAX_SUBAGENT_THREAD_KEY_BYTES = 512;
|
|
35
|
+
const MAX_AGENT_OBSERVATIONS = 5_000;
|
|
34
36
|
const DEFAULT_ROUTED_SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
35
37
|
const DEFAULT_ROUTED_SESSION_DISPOSE_TIMEOUT_MS = 30 * 1000;
|
|
36
38
|
export const LOOP_RUNTIME_RETRY_DEFAULTS = {
|
|
@@ -234,6 +236,9 @@ export class PiboSessionRouter {
|
|
|
234
236
|
runtimeResourceSessions = new Map();
|
|
235
237
|
runtimeAuthFingerprints = new Map();
|
|
236
238
|
activeSubagentChildren = new Map();
|
|
239
|
+
agentObservations = [];
|
|
240
|
+
agentObservationEvictedThroughByParent = new Map();
|
|
241
|
+
nextAgentObservationSequence = 1;
|
|
237
242
|
scheduledRunReminders = new Map();
|
|
238
243
|
runReminderGenerations = new Map();
|
|
239
244
|
runCancellationHandlers = new Map();
|
|
@@ -562,32 +567,40 @@ export class PiboSessionRouter {
|
|
|
562
567
|
}
|
|
563
568
|
}
|
|
564
569
|
descendantSessionIds(parentId) {
|
|
565
|
-
const
|
|
570
|
+
const childrenByParent = new Map();
|
|
566
571
|
for (const session of this.sessionStore.list?.() ?? []) {
|
|
567
|
-
if (session.parentId
|
|
572
|
+
if (!session.parentId)
|
|
573
|
+
continue;
|
|
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))
|
|
568
584
|
continue;
|
|
569
|
-
|
|
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());
|
|
570
590
|
}
|
|
571
591
|
return output;
|
|
572
592
|
}
|
|
573
593
|
async killChildSessions(parentId, options) {
|
|
574
594
|
const killed = [];
|
|
575
595
|
const cancelledRuns = [];
|
|
576
|
-
const
|
|
577
|
-
|
|
578
|
-
if (
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
const runs = this.runRegistry.cancelControllerRuns(session.id);
|
|
585
|
-
cancelledRuns.push(...runs.map((r) => r.runId));
|
|
586
|
-
await this.invokeRunCancellationHandlers(runs);
|
|
587
|
-
}
|
|
588
|
-
const nested = await this.killChildSessions(session.id, options);
|
|
589
|
-
killed.push(...nested.killed);
|
|
590
|
-
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);
|
|
591
604
|
}
|
|
592
605
|
}
|
|
593
606
|
return { killed, cancelledRuns };
|
|
@@ -934,6 +947,8 @@ export class PiboSessionRouter {
|
|
|
934
947
|
await this.runtimeResourceService.dispose();
|
|
935
948
|
this.runtimeResourceSessions.clear();
|
|
936
949
|
this.activeSubagentChildren.clear();
|
|
950
|
+
this.agentObservations.length = 0;
|
|
951
|
+
this.agentObservationEvictedThroughByParent.clear();
|
|
937
952
|
await this.telemetryWriter?.dispose();
|
|
938
953
|
const lifecycleFailures = [...authDisposals, ...webAppDisposals]
|
|
939
954
|
.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
@@ -1098,7 +1113,7 @@ export class PiboSessionRouter {
|
|
|
1098
1113
|
historyHandoff = { mode: "fresh" };
|
|
1099
1114
|
}
|
|
1100
1115
|
const initialFastMode = resolvePiboSessionInitialFastMode(piboSession) ?? selectRequestedFastMode(sessionProfile, modelDefaults) ?? false;
|
|
1101
|
-
const
|
|
1116
|
+
const agentsController = this.createAgentsController(piboSession.id);
|
|
1102
1117
|
const runToolController = this.createRunToolController(piboSession.id);
|
|
1103
1118
|
const codeRuntimeToolController = this.runtimeRegistry.createController(piboSession.id);
|
|
1104
1119
|
const sessionGeneration = randomUUID();
|
|
@@ -1115,7 +1130,7 @@ export class PiboSessionRouter {
|
|
|
1115
1130
|
profile: sessionProfile,
|
|
1116
1131
|
cwd: workspace,
|
|
1117
1132
|
getActiveMessage: () => session?.getActiveMessage(),
|
|
1118
|
-
|
|
1133
|
+
agentsController,
|
|
1119
1134
|
runToolController,
|
|
1120
1135
|
runtimeToolController: codeRuntimeToolController,
|
|
1121
1136
|
});
|
|
@@ -1161,7 +1176,7 @@ export class PiboSessionRouter {
|
|
|
1161
1176
|
getActiveMessage: () => session?.getActiveMessage(),
|
|
1162
1177
|
},
|
|
1163
1178
|
services: {
|
|
1164
|
-
|
|
1179
|
+
agentsController,
|
|
1165
1180
|
runToolController,
|
|
1166
1181
|
codeRuntimeToolController,
|
|
1167
1182
|
portableTools,
|
|
@@ -1582,12 +1597,12 @@ export class PiboSessionRouter {
|
|
|
1582
1597
|
id: randomUUID(),
|
|
1583
1598
|
})));
|
|
1584
1599
|
}
|
|
1585
|
-
|
|
1600
|
+
createAgentsController(parentPiboSessionId) {
|
|
1586
1601
|
return {
|
|
1587
|
-
|
|
1602
|
+
sendMessage: async ({ subagent, message, threadKey, toolCallId, signal }) => {
|
|
1588
1603
|
this.assertSubagentDepth(parentPiboSessionId, subagent);
|
|
1589
1604
|
const child = this.resolveSubagentSession(parentPiboSessionId, subagent, threadKey);
|
|
1590
|
-
const
|
|
1605
|
+
const resolvedThreadKey = typeof child.metadata?.threadKey === "string" ? child.metadata.threadKey : "";
|
|
1591
1606
|
const event = {
|
|
1592
1607
|
type: "message",
|
|
1593
1608
|
piboSessionId: child.id,
|
|
@@ -1599,22 +1614,154 @@ export class PiboSessionRouter {
|
|
|
1599
1614
|
type: "subagent_session",
|
|
1600
1615
|
piboSessionId: parentPiboSessionId,
|
|
1601
1616
|
toolCallId,
|
|
1602
|
-
toolName,
|
|
1617
|
+
toolName: "pibo_agents_send_message",
|
|
1603
1618
|
subagentName: subagent.name,
|
|
1604
1619
|
childPiboSessionId: child.id,
|
|
1605
|
-
threadKey:
|
|
1620
|
+
threadKey: resolvedThreadKey,
|
|
1606
1621
|
});
|
|
1607
1622
|
const untrack = this.trackActiveSubagent(parentPiboSessionId, child.id);
|
|
1608
1623
|
try {
|
|
1609
1624
|
const reply = await this.emitMessageAndWaitForReply(event, subagent.timeoutMs ?? DEFAULT_SUBAGENT_REPLY_TIMEOUT_MS, signal);
|
|
1610
|
-
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
|
+
};
|
|
1611
1633
|
}
|
|
1612
1634
|
finally {
|
|
1613
1635
|
untrack();
|
|
1614
1636
|
}
|
|
1615
1637
|
},
|
|
1638
|
+
listAgents: () => this.listManagedAgents(parentPiboSessionId),
|
|
1639
|
+
observe: (input) => this.observeManagedAgents(parentPiboSessionId, input),
|
|
1640
|
+
killAgent: async (agentId) => await this.killManagedAgent(parentPiboSessionId, agentId),
|
|
1616
1641
|
};
|
|
1617
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,
|
|
1741
|
+
};
|
|
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
|
+
}
|
|
1618
1765
|
async invokeRunCancellationHandlers(runs) {
|
|
1619
1766
|
const results = await Promise.allSettled(runs.map(async (run) => {
|
|
1620
1767
|
const cancel = this.runCancellationHandlers.get(run.runId);
|
|
@@ -1630,7 +1777,10 @@ export class PiboSessionRouter {
|
|
|
1630
1777
|
createRunToolController(parentPiboSessionId) {
|
|
1631
1778
|
return {
|
|
1632
1779
|
startToolRun: ({ toolName, params, completionPolicy, retryable, maxAttempts, timeoutMs, serviceWarning, resources, execute, cancel }) => {
|
|
1633
|
-
const admission = this.gatewayWorkAdmission.reserve(`yielded run ${toolName}
|
|
1780
|
+
const admission = this.gatewayWorkAdmission.reserve(`yielded run ${toolName}`, {
|
|
1781
|
+
sessionId: parentPiboSessionId,
|
|
1782
|
+
gatewaySettings: loadPiboGatewaySettings(),
|
|
1783
|
+
});
|
|
1634
1784
|
if (resources)
|
|
1635
1785
|
resources.admission = admission.admission;
|
|
1636
1786
|
const reminderGeneration = this.runReminderGeneration(parentPiboSessionId);
|
|
@@ -1731,35 +1881,33 @@ export class PiboSessionRouter {
|
|
|
1731
1881
|
const targetProfile = resolvePiboProfileNameFromRegistryOrDefault(this.pluginRegistry, subagent.targetProfile);
|
|
1732
1882
|
const parent = this.resolvePiboSession(parentPiboSessionId);
|
|
1733
1883
|
const resolvedThreadKey = resolveSubagentThreadKey(threadKey);
|
|
1734
|
-
const
|
|
1884
|
+
const identityMetadata = {
|
|
1735
1885
|
subagentName: subagent.name,
|
|
1736
|
-
subagentToolName: createSubagentToolName(subagent.name),
|
|
1737
1886
|
threadKey: resolvedThreadKey,
|
|
1738
1887
|
};
|
|
1739
|
-
const metadata = withWorkflowSessionKind(
|
|
1888
|
+
const metadata = withWorkflowSessionKind({
|
|
1889
|
+
...identityMetadata,
|
|
1890
|
+
subagentToolName: "pibo_agents_send_message",
|
|
1891
|
+
agentStatus: "active",
|
|
1892
|
+
}, "subagent");
|
|
1740
1893
|
const parentChatRoomId = typeof parent.metadata?.chatRoomId === "string" ? parent.metadata.chatRoomId : undefined;
|
|
1741
1894
|
if (parentChatRoomId)
|
|
1742
1895
|
metadata.chatRoomId = parentChatRoomId;
|
|
1743
1896
|
const newSessionMetadata = subagent.thinkingLevel
|
|
1744
1897
|
? { ...metadata, initialThinkingLevel: subagent.thinkingLevel }
|
|
1745
1898
|
: metadata;
|
|
1746
|
-
const
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
:
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
kind: "subagent",
|
|
1754
|
-
parentId: parent.id,
|
|
1755
|
-
profile: targetProfile,
|
|
1756
|
-
metadata: candidate,
|
|
1757
|
-
})[0]
|
|
1758
|
-
: undefined;
|
|
1759
|
-
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");
|
|
1760
1906
|
if (existing) {
|
|
1761
1907
|
const updatedMetadata = withWorkflowSessionKind({
|
|
1762
1908
|
...(existing.metadata ?? {}),
|
|
1909
|
+
subagentToolName: "pibo_agents_send_message",
|
|
1910
|
+
agentStatus: "active",
|
|
1763
1911
|
...(parentChatRoomId ? { chatRoomId: parentChatRoomId } : {}),
|
|
1764
1912
|
}, "subagent");
|
|
1765
1913
|
if (JSON.stringify(updatedMetadata) !== JSON.stringify(existing.metadata ?? {})) {
|
|
@@ -1789,8 +1937,40 @@ export class PiboSessionRouter {
|
|
|
1789
1937
|
});
|
|
1790
1938
|
return activeModel ? this.sessionStore.update(childSession.id, { activeModel }) ?? childSession : childSession;
|
|
1791
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
|
+
}
|
|
1792
1971
|
emitOutput = (event) => {
|
|
1793
1972
|
const session = this.sessionStore.get(event.piboSessionId);
|
|
1973
|
+
this.recordAgentObservation(event, session);
|
|
1794
1974
|
this.telemetryRecorder?.recordOutput(event, { session, status: this.sessions.get(event.piboSessionId)?.getStatus() });
|
|
1795
1975
|
this.signalRegistry.project({ type: "pibo_output", event, session });
|
|
1796
1976
|
this.pluginRegistry.notifyEvent(event);
|
|
@@ -5,6 +5,8 @@ import { sanitizeTelemetryRetentionSettings } from "./telemetry-retention-settin
|
|
|
5
5
|
import { sanitizeTelemetryStaleThresholdSettings } from "./telemetry-staleness.js";
|
|
6
6
|
export const DEFAULT_USER_TIMEZONE = "UTC";
|
|
7
7
|
export const DEFAULT_WEB_ANNOTATIONS_TOGGLE_SHORTCUT = "Alt+Shift+A";
|
|
8
|
+
export const DEFAULT_TRANSCRIPTION_PROVIDER_ID = "openai-chatgpt";
|
|
9
|
+
const LEGACY_OPENAI_TRANSCRIPTION_PROVIDER_ID = "openai";
|
|
8
10
|
export const DEFAULT_PIBO_USER_SETTINGS_PATH = "user-settings.json";
|
|
9
11
|
export function loadPiboUserSettings() {
|
|
10
12
|
return sanitizeUserSettings(readState().settings);
|
|
@@ -37,6 +39,23 @@ export function sanitizeShortcut(value) {
|
|
|
37
39
|
const shortcut = value.replace(/[\u0000-\u001f\u007f]/g, "").trim();
|
|
38
40
|
return shortcut && shortcut.length <= 80 ? shortcut : undefined;
|
|
39
41
|
}
|
|
42
|
+
export function sanitizeTranscriptionProviderId(value) {
|
|
43
|
+
if (typeof value !== "string")
|
|
44
|
+
return undefined;
|
|
45
|
+
const providerId = value.trim();
|
|
46
|
+
return /^[a-z0-9][a-z0-9._-]{0,79}$/i.test(providerId) ? providerId : undefined;
|
|
47
|
+
}
|
|
48
|
+
export function sanitizeTranscriptionSettings(value) {
|
|
49
|
+
const raw = value && typeof value === "object" && !Array.isArray(value)
|
|
50
|
+
? value
|
|
51
|
+
: {};
|
|
52
|
+
const providerId = sanitizeTranscriptionProviderId(raw.providerId);
|
|
53
|
+
return {
|
|
54
|
+
providerId: providerId === LEGACY_OPENAI_TRANSCRIPTION_PROVIDER_ID
|
|
55
|
+
? DEFAULT_TRANSCRIPTION_PROVIDER_ID
|
|
56
|
+
: providerId ?? DEFAULT_TRANSCRIPTION_PROVIDER_ID,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
40
59
|
export function sanitizeTimezone(value) {
|
|
41
60
|
if (typeof value !== "string")
|
|
42
61
|
return undefined;
|
|
@@ -58,6 +77,7 @@ function sanitizeUserSettings(value) {
|
|
|
58
77
|
return {
|
|
59
78
|
timezone: sanitizeTimezone(raw.timezone) ?? DEFAULT_USER_TIMEZONE,
|
|
60
79
|
shortcuts: sanitizeShortcutSettings(raw.shortcuts),
|
|
80
|
+
transcription: sanitizeTranscriptionSettings(raw.transcription),
|
|
61
81
|
telemetryStaleThresholds: sanitizeTelemetryStaleThresholdSettings(raw.telemetryStaleThresholds),
|
|
62
82
|
telemetryRetention: sanitizeTelemetryRetentionSettings(raw.telemetryRetention),
|
|
63
83
|
};
|
|
@@ -322,14 +322,26 @@ 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")
|
|
330
|
-
return { toolCallId: event.toolCallId, toolName: event.toolName, argsComplete: event.argsComplete };
|
|
342
|
+
return { toolCallId: event.toolCallId, toolName: event.toolName, argsComplete: event.argsComplete, intent: event.intent };
|
|
331
343
|
if (event.type === "tool_execution_started" || event.type === "tool_execution_updated" || event.type === "tool_execution_finished")
|
|
332
|
-
return { toolCallId: event.toolCallId, toolName: event.toolName, isError: "isError" in event ? event.isError : undefined };
|
|
344
|
+
return { toolCallId: event.toolCallId, toolName: event.toolName, isError: "isError" in event ? event.isError : undefined, intent: event.intent };
|
|
333
345
|
if (event.type === "subagent_session")
|
|
334
346
|
return { toolCallId: event.toolCallId, toolName: event.toolName, subagentName: event.subagentName, childPiboSessionId: event.childPiboSessionId, threadKey: event.threadKey };
|
|
335
347
|
if (event.type === "execution_result")
|