@pasko70/pibo 1.16.5 → 2.0.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/auth.js +28 -0
- package/dist/agent-runtime/capabilities.js +221 -0
- package/dist/agent-runtime/context-build.js +313 -0
- package/dist/agent-runtime/contract.js +45 -0
- package/dist/agent-runtime/errors.js +57 -0
- package/dist/agent-runtime/events.js +1 -0
- package/dist/agent-runtime/history.js +1 -0
- package/dist/agent-runtime/profile-validation.js +109 -0
- package/dist/agent-runtime/registry.js +608 -0
- package/dist/agent-runtime/resource-files.js +87 -0
- package/dist/agent-runtime/resource-service.js +635 -0
- package/dist/agent-runtime/resources.js +1 -0
- package/dist/agent-runtime/routed-session.js +931 -0
- package/dist/agent-runtime/testing/contract.js +51 -0
- package/dist/agent-runtime/testing/fake-adapter.js +192 -0
- package/dist/agent-runtime/types.js +3 -0
- package/dist/agent-runtimes/codex-native/adapter.js +905 -0
- package/dist/agent-runtimes/codex-native/auth.js +476 -0
- package/dist/agent-runtimes/codex-native/client.js +734 -0
- package/dist/agent-runtimes/codex-native/config.js +152 -0
- package/dist/agent-runtimes/codex-native/history.js +283 -0
- package/dist/agent-runtimes/codex-native/mcp-stdio-launcher.js +89 -0
- package/dist/agent-runtimes/codex-native/models.js +581 -0
- package/dist/agent-runtimes/codex-native/process.js +459 -0
- package/dist/agent-runtimes/codex-native/protocol-types.js +1 -0
- package/dist/agent-runtimes/codex-native/protocol-version.js +7 -0
- package/dist/agent-runtimes/codex-native/redaction.js +31 -0
- package/dist/agent-runtimes/codex-native/requests.js +378 -0
- package/dist/agent-runtimes/codex-native/resource-delivery.js +445 -0
- package/dist/agent-runtimes/codex-native/thread.js +388 -0
- package/dist/agent-runtimes/codex-native/turn.js +849 -0
- package/dist/agent-runtimes/pi/adapter.js +653 -0
- package/dist/agent-runtimes/pi/auth.js +455 -0
- package/dist/agent-runtimes/pi/history.js +640 -0
- package/dist/agent-runtimes/pi/model-catalog.js +87 -0
- package/dist/agent-runtimes/pi/routed-session.js +1464 -0
- package/dist/agent-runtimes/pi/runtime.js +534 -0
- package/dist/agent-runtimes/pi/tool-compiler.js +69 -0
- package/dist/apps/chat/agent-profiles.js +40 -23
- package/dist/apps/chat/agent-store.js +111 -64
- package/dist/apps/chat/chat-api-routes.js +1 -1
- package/dist/apps/chat/chat-request-normalizers.js +47 -0
- package/dist/apps/chat/data/chat-data-mappers.js +25 -9
- package/dist/apps/chat/data/history-query-service.js +108 -0
- package/dist/apps/chat/data/session-query-service.js +24 -3
- package/dist/apps/chat/data/timeline-query-service.js +3 -3
- package/dist/apps/chat/model-catalog.js +1 -55
- package/dist/apps/chat/provider-auth-actions.js +171 -23
- package/dist/apps/chat/stream.js +12 -0
- package/dist/apps/chat/trace-v2.js +1 -0
- package/dist/apps/chat/trace.js +126 -415
- package/dist/apps/chat/web-app.js +582 -157
- package/dist/apps/chat-ui/assets/{dist-QXwINWYY.js → dist-9v2ZXT6V.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CvZNkkOi.js → dist-B1LVAytl.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-_SP-MjLq.js → dist-C6LPDFXU.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Bad4Yz4P.js → dist-DVtXxfHc.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-xy-zomwl.js → dist-DW4Qrfbd.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DI4i80O2.js → dist-DmbsHdMC.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-D17yAUqp.js → dist-DyvwuSFO.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Bc3Vbgjh.js → dist-I26VB0QO.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BzqH7w58.js → dist-RtHbJRPV.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CMDJ-WZm.js → dist-sZgJkWZb.js} +1 -1
- package/dist/apps/chat-ui/assets/index-BPbNvcZe.css +1 -0
- package/dist/apps/chat-ui/assets/index-CIOf2uL2.js +237 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-1ivRyjFs.js +41 -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.0.0.vsix +0 -0
- package/dist/auth/login-actions.js +5 -251
- package/dist/cli-session/localSessionSource.js +8 -1
- package/dist/core/context-build.js +124 -20
- package/dist/core/default-profile.js +8 -0
- package/dist/core/profiles.js +30 -3
- package/dist/core/routed-session.js +5 -1446
- package/dist/core/runtime.js +5 -561
- package/dist/core/session-router.js +637 -83
- package/dist/data/cli.js +20 -3
- package/dist/data/schema.js +104 -1
- package/dist/data/session-store.js +24 -1
- package/dist/debug/events.js +25 -10
- package/dist/debug/failures.js +23 -3
- package/dist/debug/index.js +24 -6
- package/dist/debug/messages.js +87 -7
- package/dist/debug/persisted-payloads.js +31 -0
- package/dist/debug/pty.js +7 -6
- package/dist/debug/runtime-binding.js +29 -0
- package/dist/debug/session.js +137 -0
- package/dist/debug/summary.js +12 -0
- package/dist/debug/telemetry.js +28 -0
- package/dist/debug/tools.js +12 -2
- package/dist/debug/trace.js +154 -76
- package/dist/gateway/server.js +87 -2
- package/dist/gateway/tool.js +5 -5
- package/dist/index.js +21 -2
- package/dist/loops/tools.js +13 -12
- package/dist/mcp/agent-context.js +13 -4
- package/dist/mcp/client.js +10 -6
- package/dist/mcp/config.js +5 -2
- package/dist/mcp/runtime-session.js +166 -0
- package/dist/plugins/builtin.js +191 -53
- package/dist/plugins/codex-native.js +29 -0
- package/dist/plugins/registry.js +66 -2
- package/dist/runs/tools.js +26 -25
- package/dist/session-ui/terminalRows.js +2 -2
- package/dist/sessions/pibo-data-store.js +125 -16
- package/dist/sessions/runtime-binding.js +107 -0
- package/dist/sessions/sqlite-store.js +239 -18
- package/dist/sessions/store.js +86 -7
- package/dist/shared/trace-engine.js +18 -9
- package/dist/shared/trace-event-projection.js +29 -11
- package/dist/shared/{trace-transcript.js → trace-history.js} +193 -195
- package/dist/shared/trace-order.js +9 -4
- package/dist/shared/trace-page-merge.js +1 -1
- package/dist/signals/projector.js +20 -2
- package/dist/signals/registry.js +11 -0
- package/dist/subagents/tool.js +8 -6
- package/dist/tools/codex-browser.js +20 -19
- package/dist/tools/codex-compat.js +10 -9
- package/dist/tools/codex-image-generation.js +8 -6
- package/dist/tools/contract.js +45 -0
- package/dist/tools/credential-registry.js +182 -0
- package/dist/tools/mcp-bridge.js +511 -0
- package/dist/tools/payload-writer.js +17 -0
- package/dist/tools/runtime/tool.js +10 -9
- package/dist/tools/schema.js +9 -0
- package/dist/tools/session-service.js +193 -0
- package/dist/tools/session-tool-set.js +85 -0
- package/dist/web-annotations/tools.js +17 -16
- package/docs/README.md +11 -0
- package/package.json +3 -2
- package/skills/builtin/pibo-agent-runtime-adapter/SKILL.md +183 -0
- package/skills/builtin/pibo-agent-runtime-adapter/evals/README.md +10 -0
- package/skills/builtin/pibo-agent-runtime-adapter/evals/evals.json +45 -0
- package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/orion-full-harness.md +60 -0
- package/skills/builtin/pibo-agent-runtime-adapter/evals/fixtures/relay-partial-harness.md +52 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/capabilities-and-designer.md +194 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/history-debug-and-security.md +213 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/interfaces-and-registration.md +214 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/lifecycle-bindings-and-events.md +193 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/portable-delivery-and-native-behavior.md +226 -0
- package/skills/builtin/pibo-agent-runtime-adapter/references/testing-migration-and-validation.md +256 -0
- package/dist/apps/chat-ui/assets/index-C45B0rw7.js +0 -237
- package/dist/apps/chat-ui/assets/index-E0RmuCkY.css +0 -1
- package/dist/apps/chat-vscode-web/assets/index-D-tSsXLG.js +0 -41
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.16.5.vsix +0 -0
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { InitialSessionContext, } from "./profiles.js";
|
|
3
3
|
import { createDefaultPiboPluginRegistry, createPiboProfileFromRegistryOrDefault, resolvePiboProfileNameFromRegistryOrDefault, selectDefaultPiboProfileName } from "../plugins/builtin.js";
|
|
4
|
-
import {
|
|
5
|
-
import { RoutedSession } from "./routed-session.js";
|
|
4
|
+
import { RuntimeRoutedSession as RoutedSession, } from "../agent-runtime/routed-session.js";
|
|
6
5
|
import { runtimeSessionErrorDetails } from "./session-errors.js";
|
|
7
6
|
import { createSubagentToolName } from "../subagents/tool.js";
|
|
8
7
|
import { PiboRunRegistry } from "../runs/registry.js";
|
|
@@ -11,6 +10,9 @@ import { PiboRunResourceLimitError } from "../runs/resource-isolation.js";
|
|
|
11
10
|
import { createPiboSignalRegistry } from "../signals/registry.js";
|
|
12
11
|
import { createDefaultPiboReliabilityStore } from "../reliability/store.js";
|
|
13
12
|
import { InMemoryPiboSessionStore, } from "../sessions/store.js";
|
|
13
|
+
import { createLegacyPiRuntimeSessionBinding, RuntimeSessionBindingConflictError, } from "../sessions/runtime-binding.js";
|
|
14
|
+
import { AgentRuntimeBindingMissingError, AgentRuntimeUnavailableError } from "../agent-runtime/errors.js";
|
|
15
|
+
import { validateAgentRuntimeProfileCapabilities } from "../agent-runtime/profile-validation.js";
|
|
14
16
|
import { getDefaultPiboWorkspace } from "./workspace.js";
|
|
15
17
|
import { loadPiboModelDefaults, selectRequestedFastMode } from "./model-defaults.js";
|
|
16
18
|
import { loadPiboUserSettings } from "./user-settings.js";
|
|
@@ -22,8 +24,12 @@ import { withWorkflowSessionKind } from "../sessions/workflow-session-kind.js";
|
|
|
22
24
|
import { PiboRuntimeTelemetryRecorder } from "./runtime-telemetry.js";
|
|
23
25
|
import { createPiboProviderTelemetryExtension } from "./provider-telemetry.js";
|
|
24
26
|
import { AsyncTelemetryWriter } from "../data/telemetry-writer.js";
|
|
27
|
+
import { createPiboToolPayloadWriter } from "../tools/payload-writer.js";
|
|
28
|
+
import { PiboPortableToolService, } from "../tools/session-service.js";
|
|
29
|
+
import { PiboRuntimeResourceService, } from "../agent-runtime/resource-service.js";
|
|
25
30
|
const DEFAULT_SUBAGENT_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
|
|
26
31
|
const DEFAULT_SUBAGENT_MAX_DEPTH = 3;
|
|
32
|
+
const MAX_SUBAGENT_THREAD_KEY_BYTES = 512;
|
|
27
33
|
const DEFAULT_ROUTED_SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
28
34
|
const DEFAULT_ROUTED_SESSION_DISPOSE_TIMEOUT_MS = 30 * 1000;
|
|
29
35
|
export const LOOP_RUNTIME_RETRY_DEFAULTS = {
|
|
@@ -47,11 +53,27 @@ export function resolvePiboSessionInitialFastMode(session) {
|
|
|
47
53
|
function hasReachedSubagentMaxDepth(subagent, depth) {
|
|
48
54
|
return depth >= (subagent.maxDepth ?? DEFAULT_SUBAGENT_MAX_DEPTH);
|
|
49
55
|
}
|
|
50
|
-
function
|
|
56
|
+
function resolveSubagentThreadKey(threadKey) {
|
|
57
|
+
const normalized = threadKey?.trim();
|
|
58
|
+
if (!normalized)
|
|
59
|
+
return randomUUID();
|
|
60
|
+
if (Buffer.byteLength(normalized, "utf8") > MAX_SUBAGENT_THREAD_KEY_BYTES) {
|
|
61
|
+
throw new Error(`Subagent thread key exceeds ${MAX_SUBAGENT_THREAD_KEY_BYTES} bytes.`);
|
|
62
|
+
}
|
|
63
|
+
return normalized;
|
|
64
|
+
}
|
|
65
|
+
function subagentAbortError() {
|
|
66
|
+
const error = new Error("Subagent request was aborted.");
|
|
67
|
+
error.name = "AbortError";
|
|
68
|
+
return error;
|
|
69
|
+
}
|
|
70
|
+
function profileForSession(baseProfile, runtimeInstanceId, nativeSessionId, parentNativeSessionId, subagentDepth) {
|
|
51
71
|
const options = {
|
|
52
72
|
profileName: baseProfile.profileName,
|
|
53
|
-
|
|
54
|
-
|
|
73
|
+
runtimeInstanceId,
|
|
74
|
+
runtimeOptions: baseProfile.runtimeOptions,
|
|
75
|
+
sessionId: nativeSessionId,
|
|
76
|
+
parentSessionId: parentNativeSessionId,
|
|
55
77
|
model: baseProfile.model,
|
|
56
78
|
mainModel: baseProfile.mainModel,
|
|
57
79
|
subagentModel: baseProfile.subagentModel,
|
|
@@ -131,13 +153,32 @@ function isTerminalRunStatus(status) {
|
|
|
131
153
|
function asJsonObject(value) {
|
|
132
154
|
return value ?? {};
|
|
133
155
|
}
|
|
134
|
-
function shouldResetSessionAfterAction(action) {
|
|
135
|
-
|
|
156
|
+
function shouldResetSessionAfterAction(action, output) {
|
|
157
|
+
if (action === "login.apikey" || action === "logout")
|
|
158
|
+
return true;
|
|
159
|
+
if (action !== "login.complete")
|
|
160
|
+
return false;
|
|
161
|
+
const result = output?.type === "execution_result" && output.result && typeof output.result === "object" && !Array.isArray(output.result)
|
|
162
|
+
? output.result
|
|
163
|
+
: undefined;
|
|
164
|
+
return result?.state !== "pending";
|
|
136
165
|
}
|
|
137
166
|
function piboRoomIdFromMetadata(metadata) {
|
|
138
167
|
const value = metadata?.chatRoomId;
|
|
139
168
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
140
169
|
}
|
|
170
|
+
function runtimeBindingsEqual(left, right) {
|
|
171
|
+
return left.piboSessionId === right.piboSessionId
|
|
172
|
+
&& left.runtimeInstanceId === right.runtimeInstanceId
|
|
173
|
+
&& left.adapterId === right.adapterId
|
|
174
|
+
&& left.nativeSessionId === right.nativeSessionId
|
|
175
|
+
&& left.state === right.state
|
|
176
|
+
&& left.protocol === right.protocol
|
|
177
|
+
&& left.protocolVersion === right.protocolVersion
|
|
178
|
+
&& left.adapterVersion === right.adapterVersion
|
|
179
|
+
&& JSON.stringify(left.locator ?? null) === JSON.stringify(right.locator ?? null)
|
|
180
|
+
&& JSON.stringify(left.metadata ?? {}) === JSON.stringify(right.metadata ?? {});
|
|
181
|
+
}
|
|
141
182
|
class PiboSessionDisposalTimeoutError extends Error {
|
|
142
183
|
piboSessionId;
|
|
143
184
|
timeoutMs;
|
|
@@ -151,6 +192,9 @@ class PiboSessionDisposalTimeoutError extends Error {
|
|
|
151
192
|
function telemetryStoreFromSessionStore(store) {
|
|
152
193
|
return store.getTelemetryStore?.();
|
|
153
194
|
}
|
|
195
|
+
function payloadStoreFromSessionStore(store) {
|
|
196
|
+
return store.getPayloadStore?.();
|
|
197
|
+
}
|
|
154
198
|
function providerEventTelemetryModeFromEnv(env = process.env) {
|
|
155
199
|
const value = env.PIBO_TELEMETRY_PROVIDER_EVENTS?.trim().toLowerCase();
|
|
156
200
|
return value === "1" || value === "true" || value === "detailed" ? "detailed" : "aggregate";
|
|
@@ -164,6 +208,12 @@ export class PiboSessionRouter {
|
|
|
164
208
|
gatewayWorkAdmission = new GatewayWorkAdmissionController();
|
|
165
209
|
signalRegistry;
|
|
166
210
|
runtimeRegistry;
|
|
211
|
+
portableToolService;
|
|
212
|
+
portableToolSessions = new Map();
|
|
213
|
+
runtimeResourceService;
|
|
214
|
+
runtimeResourceSessions = new Map();
|
|
215
|
+
runtimeAuthFingerprints = new Map();
|
|
216
|
+
activeSubagentChildren = new Map();
|
|
167
217
|
scheduledRunReminders = new Map();
|
|
168
218
|
runReminderGenerations = new Map();
|
|
169
219
|
quiescingSessions = new Set();
|
|
@@ -173,6 +223,7 @@ export class PiboSessionRouter {
|
|
|
173
223
|
routedSessionDisposeTimeoutMs;
|
|
174
224
|
baseProfile;
|
|
175
225
|
pluginRegistry;
|
|
226
|
+
compatibilityRuntimeRegistry;
|
|
176
227
|
sessionStore;
|
|
177
228
|
reliabilityStore;
|
|
178
229
|
telemetryStore;
|
|
@@ -183,6 +234,9 @@ export class PiboSessionRouter {
|
|
|
183
234
|
constructor(options = {}) {
|
|
184
235
|
this.options = options;
|
|
185
236
|
this.pluginRegistry = options.pluginRegistry ?? createDefaultPiboPluginRegistry();
|
|
237
|
+
// Historical custom registries supplied only actions/profiles while runtime creation was implicit.
|
|
238
|
+
// Preserve that composition contract during the adapter migration without branching on adapter ids.
|
|
239
|
+
this.compatibilityRuntimeRegistry = options.pluginRegistry ? createDefaultPiboPluginRegistry() : undefined;
|
|
186
240
|
this.sessionStore = options.sessionStore ?? new InMemoryPiboSessionStore();
|
|
187
241
|
this.telemetryStore = options.telemetryStore ?? telemetryStoreFromSessionStore(this.sessionStore);
|
|
188
242
|
this.telemetryWriter = this.telemetryStore ? new AsyncTelemetryWriter(this.telemetryStore) : undefined;
|
|
@@ -207,6 +261,11 @@ export class PiboSessionRouter {
|
|
|
207
261
|
this.reliabilityStore = options.reliabilityStore ?? (options.persistSession === false ? undefined : createDefaultPiboReliabilityStore());
|
|
208
262
|
this.signalRegistry = options.signalRegistry ?? createPiboSignalRegistry();
|
|
209
263
|
this.runtimeRegistry = new RuntimeSessionRegistry({ cwd: options.cwd ?? getDefaultPiboWorkspace() });
|
|
264
|
+
const payloadStore = payloadStoreFromSessionStore(this.sessionStore);
|
|
265
|
+
this.portableToolService = new PiboPortableToolService({
|
|
266
|
+
...(payloadStore ? { payloadWriter: createPiboToolPayloadWriter(payloadStore) } : {}),
|
|
267
|
+
});
|
|
268
|
+
this.runtimeResourceService = options.runtimeResourceService ?? new PiboRuntimeResourceService();
|
|
210
269
|
this.runRegistry = new PiboRunRegistry({ store: this.reliabilityStore });
|
|
211
270
|
this.runRegistry.subscribe((event) => this.projectRunRegistryEvent(event));
|
|
212
271
|
const recoveredRuntimeState = options.recoverInterruptedRuntimeState
|
|
@@ -299,13 +358,23 @@ export class PiboSessionRouter {
|
|
|
299
358
|
teardownCompleted = true;
|
|
300
359
|
return output;
|
|
301
360
|
}
|
|
361
|
+
const childAbort = event.action === "abort"
|
|
362
|
+
? this.abortActiveSubagentSessions(event.piboSessionId)
|
|
363
|
+
: undefined;
|
|
302
364
|
const output = await session.executeAction(event);
|
|
365
|
+
await childAbort;
|
|
303
366
|
if (event.action === "kill" || event.action === "kill_all") {
|
|
304
367
|
await this.disposeSessionSubtree(event.piboSessionId, `${event.action} action`, { cancelRuns: event.action === "kill_all" });
|
|
305
368
|
teardownCompleted = true;
|
|
306
369
|
}
|
|
307
|
-
else if (shouldResetSessionAfterAction(event.action)) {
|
|
308
|
-
|
|
370
|
+
else if (shouldResetSessionAfterAction(event.action, output)) {
|
|
371
|
+
const runtimeInstanceId = this.getSessionRuntimeBinding(event.piboSessionId)?.runtimeInstanceId;
|
|
372
|
+
if (runtimeInstanceId) {
|
|
373
|
+
await this.resetCachedRuntimeAuthSessions(runtimeInstanceId, "runtime provider auth changed");
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
await this.resetCachedSession(event.piboSessionId, "runtime provider auth changed");
|
|
377
|
+
}
|
|
309
378
|
}
|
|
310
379
|
return output;
|
|
311
380
|
}
|
|
@@ -333,6 +402,9 @@ export class PiboSessionRouter {
|
|
|
333
402
|
this.scheduleIdleSessionEvictionIfIdle(event.piboSessionId);
|
|
334
403
|
}
|
|
335
404
|
}
|
|
405
|
+
async disposeSession(piboSessionId, reason = "session deleted") {
|
|
406
|
+
await this.disposeSessionSubtree(piboSessionId, reason, { cancelRuns: true });
|
|
407
|
+
}
|
|
336
408
|
async killSession(piboSessionId, options) {
|
|
337
409
|
const rootSession = this.sessions.get(piboSessionId);
|
|
338
410
|
if (!rootSession)
|
|
@@ -388,6 +460,15 @@ export class PiboSessionRouter {
|
|
|
388
460
|
finally {
|
|
389
461
|
if (timeout)
|
|
390
462
|
clearTimeout(timeout);
|
|
463
|
+
const portableTools = this.portableToolSessions.get(piboSessionId);
|
|
464
|
+
portableTools?.dispose();
|
|
465
|
+
if (this.portableToolSessions.get(piboSessionId) === portableTools)
|
|
466
|
+
this.portableToolSessions.delete(piboSessionId);
|
|
467
|
+
const resources = this.runtimeResourceSessions.get(piboSessionId);
|
|
468
|
+
if (resources)
|
|
469
|
+
await resources.dispose();
|
|
470
|
+
if (this.runtimeResourceSessions.get(piboSessionId) === resources)
|
|
471
|
+
this.runtimeResourceSessions.delete(piboSessionId);
|
|
391
472
|
}
|
|
392
473
|
}
|
|
393
474
|
async disposeSessionSubtree(piboSessionId, reason, options) {
|
|
@@ -480,13 +561,105 @@ export class PiboSessionRouter {
|
|
|
480
561
|
getPiboSessionIds() {
|
|
481
562
|
return [...this.sessions.keys()];
|
|
482
563
|
}
|
|
564
|
+
async getAgentRuntimeAuthStatus(runtimeInstanceId) {
|
|
565
|
+
const registry = this.resolveAgentRuntimeRegistry(runtimeInstanceId);
|
|
566
|
+
const statuses = await registry.getAgentRuntimeAuthStatus(runtimeInstanceId);
|
|
567
|
+
const fingerprint = statuses
|
|
568
|
+
.map((status) => `${status.id}:${status.configured}:${status.details?.accountType ?? ""}:${status.details?.planType ?? ""}`)
|
|
569
|
+
.sort()
|
|
570
|
+
.join("|");
|
|
571
|
+
const previous = this.runtimeAuthFingerprints.get(runtimeInstanceId);
|
|
572
|
+
this.runtimeAuthFingerprints.set(runtimeInstanceId, fingerprint);
|
|
573
|
+
if (previous !== undefined && previous !== fingerprint) {
|
|
574
|
+
await this.resetCachedRuntimeAuthSessions(runtimeInstanceId, "runtime provider auth changed");
|
|
575
|
+
}
|
|
576
|
+
return statuses;
|
|
577
|
+
}
|
|
578
|
+
async startAgentRuntimeAuth(runtimeInstanceId, input) {
|
|
579
|
+
const registry = this.resolveAgentRuntimeRegistry(runtimeInstanceId);
|
|
580
|
+
const result = await registry.startAgentRuntimeAuth(runtimeInstanceId, input);
|
|
581
|
+
if (result.state !== "pending") {
|
|
582
|
+
await this.resetCachedRuntimeAuthSessions(runtimeInstanceId, "runtime provider auth changed");
|
|
583
|
+
}
|
|
584
|
+
return result;
|
|
585
|
+
}
|
|
586
|
+
async completeAgentRuntimeAuth(runtimeInstanceId, input) {
|
|
587
|
+
const registry = this.resolveAgentRuntimeRegistry(runtimeInstanceId);
|
|
588
|
+
const result = await registry.completeAgentRuntimeAuth(runtimeInstanceId, input);
|
|
589
|
+
if (result.state !== "pending") {
|
|
590
|
+
await this.resetCachedRuntimeAuthSessions(runtimeInstanceId, "runtime provider auth changed");
|
|
591
|
+
}
|
|
592
|
+
return result;
|
|
593
|
+
}
|
|
594
|
+
async cancelAgentRuntimeAuth(runtimeInstanceId, input) {
|
|
595
|
+
return await this.resolveAgentRuntimeRegistry(runtimeInstanceId)
|
|
596
|
+
.cancelAgentRuntimeAuth(runtimeInstanceId, input);
|
|
597
|
+
}
|
|
598
|
+
async logoutAgentRuntimeAuth(runtimeInstanceId, input) {
|
|
599
|
+
const result = await this.resolveAgentRuntimeRegistry(runtimeInstanceId)
|
|
600
|
+
.logoutAgentRuntimeAuth(runtimeInstanceId, input);
|
|
601
|
+
await this.resetCachedRuntimeAuthSessions(runtimeInstanceId, "runtime provider auth changed");
|
|
602
|
+
return result;
|
|
603
|
+
}
|
|
604
|
+
getSessionRuntimeBinding(piboSessionId) {
|
|
605
|
+
const session = this.sessionStore.get(piboSessionId);
|
|
606
|
+
return session ? structuredClone(this.resolveSessionRuntimeBinding(session)) : undefined;
|
|
607
|
+
}
|
|
608
|
+
async rebindSessionRuntime(piboSessionId, input) {
|
|
609
|
+
const session = this.sessionStore.get(piboSessionId);
|
|
610
|
+
if (!session)
|
|
611
|
+
throw new Error(`Unknown Pibo session "${piboSessionId}".`);
|
|
612
|
+
const current = this.resolveSessionRuntimeBinding(session);
|
|
613
|
+
const currentRevision = current.revision ?? 1;
|
|
614
|
+
if (currentRevision !== input.expectedRevision) {
|
|
615
|
+
throw new RuntimeSessionBindingConflictError(piboSessionId, input.expectedRevision, currentRevision);
|
|
616
|
+
}
|
|
617
|
+
const liveStatus = this.sessions.get(piboSessionId)?.getStatus();
|
|
618
|
+
if (liveStatus && (liveStatus.processing || liveStatus.streaming || liveStatus.queuedMessages > 0)) {
|
|
619
|
+
throw new Error("A runtime binding can only be repaired or rebound while the session is idle.");
|
|
620
|
+
}
|
|
621
|
+
if (this.sessions.has(piboSessionId) || this.pendingSessions.has(piboSessionId)) {
|
|
622
|
+
await this.resetCachedSession(piboSessionId, "runtime binding rebind");
|
|
623
|
+
}
|
|
624
|
+
const registry = this.resolveAgentRuntimeRegistry(input.runtimeInstanceId);
|
|
625
|
+
const adapter = registry.requireAgentRuntimeAdapter(input.runtimeInstanceId);
|
|
626
|
+
const requestedState = input.state ?? (input.nativeSessionId ? "bound" : "unbound");
|
|
627
|
+
let next = {
|
|
628
|
+
piboSessionId,
|
|
629
|
+
runtimeInstanceId: input.runtimeInstanceId,
|
|
630
|
+
adapterId: adapter.descriptor.id,
|
|
631
|
+
nativeSessionId: input.nativeSessionId,
|
|
632
|
+
state: requestedState,
|
|
633
|
+
protocol: adapter.descriptor.protocol?.name,
|
|
634
|
+
protocolVersion: current.runtimeInstanceId === input.runtimeInstanceId ? current.protocolVersion : undefined,
|
|
635
|
+
locator: input.locator,
|
|
636
|
+
metadata: {},
|
|
637
|
+
};
|
|
638
|
+
if (next.state === "bound" && adapter.resolveBinding) {
|
|
639
|
+
next = await adapter.resolveBinding({
|
|
640
|
+
binding: next,
|
|
641
|
+
workspace: session.workspace ?? this.options.cwd ?? getDefaultPiboWorkspace(),
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
const mode = (current.state === "missing" || current.state === "error")
|
|
645
|
+
&& current.runtimeInstanceId === next.runtimeInstanceId
|
|
646
|
+
&& current.adapterId === next.adapterId
|
|
647
|
+
? "repair"
|
|
648
|
+
: "rebind";
|
|
649
|
+
const persisted = this.persistSessionRuntimeBinding(session, next, {
|
|
650
|
+
expectedRevision: input.expectedRevision,
|
|
651
|
+
mode,
|
|
652
|
+
});
|
|
653
|
+
return structuredClone(persisted);
|
|
654
|
+
}
|
|
483
655
|
getSessionRuntimeStatus(piboSessionId) {
|
|
484
|
-
|
|
656
|
+
const status = this.sessions.get(piboSessionId)?.getStatus();
|
|
657
|
+
return status ? this.withPersistedRuntimeBinding(status) : undefined;
|
|
485
658
|
}
|
|
486
659
|
async getSessionStatusSnapshot(piboSessionId) {
|
|
487
660
|
const session = await this.getOrCreateSession(piboSessionId);
|
|
488
661
|
try {
|
|
489
|
-
return await session.getStatusSnapshot();
|
|
662
|
+
return this.withPersistedRuntimeBinding(await session.getStatusSnapshot());
|
|
490
663
|
}
|
|
491
664
|
finally {
|
|
492
665
|
this.scheduleIdleSessionEvictionIfIdle(piboSessionId);
|
|
@@ -517,7 +690,7 @@ export class PiboSessionRouter {
|
|
|
517
690
|
});
|
|
518
691
|
}
|
|
519
692
|
listSessionRuntimeStatuses() {
|
|
520
|
-
return [...this.sessions.values()].map((session) => session.getStatus());
|
|
693
|
+
return [...this.sessions.values()].map((session) => this.withPersistedRuntimeBinding(session.getStatus()));
|
|
521
694
|
}
|
|
522
695
|
listRuns(options = {}) {
|
|
523
696
|
return this.runRegistry.listAll(options);
|
|
@@ -543,12 +716,42 @@ export class PiboSessionRouter {
|
|
|
543
716
|
subscribeSignalStatuses(listener) {
|
|
544
717
|
return this.signalRegistry.subscribeAll(listener);
|
|
545
718
|
}
|
|
546
|
-
async emitMessageAndWaitForReply(event, timeoutMs = 120000) {
|
|
719
|
+
async emitMessageAndWaitForReply(event, timeoutMs = 120000, signal) {
|
|
547
720
|
const eventWithId = { ...event, id: event.id ?? randomUUID() };
|
|
548
721
|
return await new Promise((resolve, reject) => {
|
|
549
722
|
let settled = false;
|
|
723
|
+
let messageDispatched = false;
|
|
550
724
|
let lastAssistantMessage;
|
|
551
725
|
let timeout;
|
|
726
|
+
const abortChild = () => {
|
|
727
|
+
if (!messageDispatched)
|
|
728
|
+
return;
|
|
729
|
+
void this.emit({
|
|
730
|
+
type: "execution",
|
|
731
|
+
piboSessionId: eventWithId.piboSessionId,
|
|
732
|
+
action: "abort",
|
|
733
|
+
id: randomUUID(),
|
|
734
|
+
}).catch(() => { });
|
|
735
|
+
};
|
|
736
|
+
const finish = (result) => {
|
|
737
|
+
if (settled)
|
|
738
|
+
return false;
|
|
739
|
+
settled = true;
|
|
740
|
+
if (timeout)
|
|
741
|
+
clearTimeout(timeout);
|
|
742
|
+
signal?.removeEventListener("abort", onAbort);
|
|
743
|
+
unsubscribe();
|
|
744
|
+
if (result instanceof Error)
|
|
745
|
+
reject(result);
|
|
746
|
+
else
|
|
747
|
+
resolve(result);
|
|
748
|
+
return true;
|
|
749
|
+
};
|
|
750
|
+
const onAbort = () => {
|
|
751
|
+
if (!finish(subagentAbortError()))
|
|
752
|
+
return;
|
|
753
|
+
abortChild();
|
|
754
|
+
};
|
|
552
755
|
const unsubscribe = this.subscribe((output) => {
|
|
553
756
|
if (output.piboSessionId !== eventWithId.piboSessionId ||
|
|
554
757
|
!("eventId" in output) ||
|
|
@@ -565,34 +768,18 @@ export class PiboSessionRouter {
|
|
|
565
768
|
finish(new Error(output.error));
|
|
566
769
|
}
|
|
567
770
|
});
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
clearTimeout(timeout);
|
|
574
|
-
unsubscribe();
|
|
575
|
-
if (result instanceof Error) {
|
|
576
|
-
reject(result);
|
|
577
|
-
}
|
|
578
|
-
else {
|
|
579
|
-
resolve(result);
|
|
580
|
-
}
|
|
581
|
-
};
|
|
771
|
+
if (signal?.aborted) {
|
|
772
|
+
onAbort();
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
582
776
|
timeout = setTimeout(() => {
|
|
583
|
-
if (settled)
|
|
584
|
-
return;
|
|
585
|
-
settled = true;
|
|
586
|
-
unsubscribe();
|
|
587
777
|
const timeoutError = new Error(`Timed out waiting for assistant reply from Pibo session "${eventWithId.piboSessionId}"`);
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
piboSessionId: eventWithId.piboSessionId,
|
|
592
|
-
action: "abort",
|
|
593
|
-
id: randomUUID(),
|
|
594
|
-
}).catch(() => { });
|
|
778
|
+
if (!finish(timeoutError))
|
|
779
|
+
return;
|
|
780
|
+
abortChild();
|
|
595
781
|
}, timeoutMs);
|
|
782
|
+
messageDispatched = true;
|
|
596
783
|
this.emit(eventWithId).catch(finish);
|
|
597
784
|
});
|
|
598
785
|
}
|
|
@@ -629,7 +816,18 @@ export class PiboSessionRouter {
|
|
|
629
816
|
throw new AggregateError(failures, "Failed to dispose all Pibo sessions");
|
|
630
817
|
}
|
|
631
818
|
finally {
|
|
819
|
+
const authDisposals = await Promise.allSettled([
|
|
820
|
+
this.pluginRegistry.disposeAgentRuntimeAuth(),
|
|
821
|
+
...(this.compatibilityRuntimeRegistry ? [this.compatibilityRuntimeRegistry.disposeAgentRuntimeAuth()] : []),
|
|
822
|
+
]);
|
|
823
|
+
await this.portableToolService.dispose();
|
|
824
|
+
await this.runtimeResourceService.dispose();
|
|
825
|
+
this.runtimeResourceSessions.clear();
|
|
826
|
+
this.activeSubagentChildren.clear();
|
|
632
827
|
await this.telemetryWriter?.dispose();
|
|
828
|
+
const authFailures = authDisposals.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
829
|
+
if (authFailures.length > 0)
|
|
830
|
+
throw new AggregateError(authFailures, "Failed to dispose runtime authentication controllers.");
|
|
633
831
|
}
|
|
634
832
|
}
|
|
635
833
|
clearIdleSessionTimer(piboSessionId) {
|
|
@@ -707,55 +905,317 @@ export class PiboSessionRouter {
|
|
|
707
905
|
let session;
|
|
708
906
|
this.signalRegistry.project({ type: "session_created", session: piboSession });
|
|
709
907
|
const profile = createPiboProfileFromRegistryOrDefault(this.pluginRegistry, piboSession.profile);
|
|
710
|
-
|
|
711
|
-
|
|
908
|
+
let binding = this.resolveSessionRuntimeBinding(piboSession);
|
|
909
|
+
const parent = piboSession.parentId ? this.resolvePiboSession(piboSession.parentId) : undefined;
|
|
910
|
+
const parentBinding = parent ? this.resolveSessionRuntimeBinding(parent) : undefined;
|
|
911
|
+
const parentModelScopeId = parent ? parentBinding?.nativeSessionId ?? parent.id : undefined;
|
|
912
|
+
const runtimeParentNativeSessionId = parentBinding
|
|
913
|
+
&& parentBinding.runtimeInstanceId === binding.runtimeInstanceId
|
|
914
|
+
&& parentBinding.adapterId === binding.adapterId
|
|
915
|
+
? parentBinding.nativeSessionId
|
|
712
916
|
: undefined;
|
|
713
917
|
const modelDefaults = this.resolveModelDefaults();
|
|
714
|
-
const activeModel = this.ensureSessionActiveModel(piboSession, profile,
|
|
918
|
+
const activeModel = this.ensureSessionActiveModel(piboSession, profile, parentModelScopeId, modelDefaults);
|
|
715
919
|
const initialThinkingLevel = resolvePiboSessionInitialThinkingLevel(piboSession);
|
|
716
|
-
const sessionProfile = profileForSession(profile,
|
|
920
|
+
const sessionProfile = profileForSession(profile, binding.runtimeInstanceId, binding.nativeSessionId, runtimeParentNativeSessionId, this.getSubagentDepth(piboSession.id));
|
|
717
921
|
const userSettings = loadPiboUserSettings();
|
|
718
922
|
const telemetryExtension = this.telemetryStore
|
|
719
923
|
? createPiboProviderTelemetryExtension({ store: this.telemetryStore, writer: this.telemetryWriter, session: piboSession, model: activeModel })
|
|
720
924
|
: undefined;
|
|
721
|
-
const
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
925
|
+
const runtimeRegistry = this.resolveAgentRuntimeRegistry(binding.runtimeInstanceId);
|
|
926
|
+
const runtimeAdapter = runtimeRegistry.requireAgentRuntimeAdapter(binding.runtimeInstanceId);
|
|
927
|
+
if (runtimeAdapter.descriptor.id !== binding.adapterId) {
|
|
928
|
+
throw new AgentRuntimeUnavailableError(binding.runtimeInstanceId, `Runtime binding for Pibo session "${piboSession.id}" expects adapter "${binding.adapterId}", but instance "${binding.runtimeInstanceId}" uses "${runtimeAdapter.descriptor.id}".`);
|
|
929
|
+
}
|
|
930
|
+
const workspace = piboSession.workspace ?? this.options.cwd ?? getDefaultPiboWorkspace();
|
|
931
|
+
if (binding.state === "bound" && runtimeAdapter.resolveBinding) {
|
|
932
|
+
const resolved = await runtimeAdapter.resolveBinding({ binding, workspace });
|
|
933
|
+
if (!runtimeBindingsEqual(binding, resolved)) {
|
|
934
|
+
binding = this.persistSessionRuntimeBinding(piboSession, resolved, {
|
|
935
|
+
expectedRevision: binding.revision,
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
this.assertOpenableRuntimeBinding(binding);
|
|
940
|
+
const profileDiagnostics = [
|
|
941
|
+
...validateAgentRuntimeProfileCapabilities(sessionProfile, runtimeAdapter.descriptor.capabilities),
|
|
942
|
+
...runtimeAdapter.validateProfile({
|
|
943
|
+
profile: sessionProfile,
|
|
944
|
+
workspace,
|
|
945
|
+
}),
|
|
946
|
+
];
|
|
947
|
+
const invalidProfile = profileDiagnostics.find((diagnostic) => diagnostic.severity === "error");
|
|
948
|
+
if (invalidProfile) {
|
|
949
|
+
throw new Error(`Runtime profile validation failed: ${invalidProfile.message}`);
|
|
950
|
+
}
|
|
951
|
+
const initialFastMode = resolvePiboSessionInitialFastMode(piboSession) ?? selectRequestedFastMode(sessionProfile, modelDefaults) ?? false;
|
|
952
|
+
const subagentRunner = this.createSubagentRunner(piboSession.id);
|
|
953
|
+
const runToolController = this.createRunToolController(piboSession.id);
|
|
954
|
+
const codeRuntimeToolController = this.runtimeRegistry.createController(piboSession.id);
|
|
955
|
+
const sessionGeneration = randomUUID();
|
|
956
|
+
const previousResources = this.runtimeResourceSessions.get(piboSession.id);
|
|
957
|
+
if (previousResources)
|
|
958
|
+
await previousResources.dispose();
|
|
959
|
+
this.portableToolSessions.get(piboSession.id)?.dispose();
|
|
960
|
+
const portableTools = this.portableToolService.createSession({
|
|
961
|
+
piboSessionId: piboSession.id,
|
|
962
|
+
piboRoomId: piboRoomIdFromMetadata(piboSession.metadata),
|
|
963
|
+
runtimeInstanceId: binding.runtimeInstanceId,
|
|
964
|
+
adapterId: binding.adapterId,
|
|
965
|
+
sessionGeneration,
|
|
726
966
|
profile: sessionProfile,
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
967
|
+
cwd: workspace,
|
|
968
|
+
getActiveMessage: () => session?.getActiveMessage(),
|
|
969
|
+
subagentRunner,
|
|
970
|
+
runToolController,
|
|
971
|
+
runtimeToolController: codeRuntimeToolController,
|
|
972
|
+
});
|
|
973
|
+
this.portableToolSessions.set(piboSession.id, portableTools);
|
|
974
|
+
let resources;
|
|
975
|
+
try {
|
|
976
|
+
resources = await this.runtimeResourceService.createSession({
|
|
737
977
|
piboSessionId: piboSession.id,
|
|
738
978
|
piboRoomId: piboRoomIdFromMetadata(piboSession.metadata),
|
|
979
|
+
runtimeInstanceId: binding.runtimeInstanceId,
|
|
980
|
+
adapterId: binding.adapterId,
|
|
981
|
+
sessionGeneration,
|
|
982
|
+
profile: sessionProfile,
|
|
983
|
+
cwd: workspace,
|
|
739
984
|
timezone: userSettings.timezone,
|
|
740
|
-
|
|
985
|
+
capabilities: runtimeAdapter.descriptor.capabilities,
|
|
986
|
+
});
|
|
987
|
+
this.runtimeResourceSessions.set(piboSession.id, resources);
|
|
988
|
+
}
|
|
989
|
+
catch (error) {
|
|
990
|
+
portableTools.dispose();
|
|
991
|
+
if (this.portableToolSessions.get(piboSession.id) === portableTools)
|
|
992
|
+
this.portableToolSessions.delete(piboSession.id);
|
|
993
|
+
throw error;
|
|
994
|
+
}
|
|
995
|
+
let runtimeSession;
|
|
996
|
+
try {
|
|
997
|
+
runtimeSession = await runtimeRegistry.openAgentRuntimeSession(binding.runtimeInstanceId, {
|
|
998
|
+
piboSession: { ...piboSession, runtimeBinding: binding },
|
|
999
|
+
profile: sessionProfile,
|
|
1000
|
+
binding,
|
|
1001
|
+
workspace,
|
|
1002
|
+
activeModel,
|
|
1003
|
+
productContext: {
|
|
1004
|
+
piboSessionId: piboSession.id,
|
|
1005
|
+
piboRoomId: piboRoomIdFromMetadata(piboSession.metadata),
|
|
1006
|
+
timezone: userSettings.timezone,
|
|
1007
|
+
getActiveMessage: () => session?.getActiveMessage(),
|
|
1008
|
+
},
|
|
1009
|
+
services: {
|
|
1010
|
+
subagentRunner,
|
|
1011
|
+
runToolController,
|
|
1012
|
+
codeRuntimeToolController,
|
|
1013
|
+
portableTools,
|
|
1014
|
+
resources,
|
|
1015
|
+
compatibility: {
|
|
1016
|
+
persistSession: this.options.persistSession,
|
|
1017
|
+
thinkingLevel: initialThinkingLevel ?? this.options.thinkingLevel,
|
|
1018
|
+
retryDefaults: resolvePiboSessionRetryDefaults(piboSession.kind, this.options.retryDefaults),
|
|
1019
|
+
extensionFactories: [
|
|
1020
|
+
...(telemetryExtension ? [telemetryExtension] : []),
|
|
1021
|
+
...(this.options.extensionFactories ?? []),
|
|
1022
|
+
],
|
|
1023
|
+
modelDefaults,
|
|
1024
|
+
initialFastMode,
|
|
1025
|
+
},
|
|
1026
|
+
},
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
catch (error) {
|
|
1030
|
+
portableTools.dispose();
|
|
1031
|
+
if (this.portableToolSessions.get(piboSession.id) === portableTools)
|
|
1032
|
+
this.portableToolSessions.delete(piboSession.id);
|
|
1033
|
+
await resources.dispose();
|
|
1034
|
+
if (this.runtimeResourceSessions.get(piboSession.id) === resources)
|
|
1035
|
+
this.runtimeResourceSessions.delete(piboSession.id);
|
|
1036
|
+
if (error instanceof AgentRuntimeBindingMissingError && binding.state === "bound") {
|
|
1037
|
+
this.persistSessionRuntimeBinding(piboSession, {
|
|
1038
|
+
...binding,
|
|
1039
|
+
state: "missing",
|
|
1040
|
+
metadata: {
|
|
1041
|
+
...(binding.metadata ?? {}),
|
|
1042
|
+
diagnosticCode: "runtime_binding_missing",
|
|
1043
|
+
diagnosticMessage: "The bound native session is no longer available in the configured runtime instance.",
|
|
1044
|
+
},
|
|
1045
|
+
}, {
|
|
1046
|
+
expectedRevision: binding.revision,
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
throw error;
|
|
1050
|
+
}
|
|
1051
|
+
try {
|
|
1052
|
+
const openedBinding = runtimeSession.getBinding();
|
|
1053
|
+
if (openedBinding.runtimeInstanceId !== binding.runtimeInstanceId || openedBinding.adapterId !== binding.adapterId) {
|
|
1054
|
+
throw new AgentRuntimeUnavailableError(binding.runtimeInstanceId, `Runtime instance "${binding.runtimeInstanceId}" opened an inconsistent binding for Pibo session "${piboSession.id}".`);
|
|
1055
|
+
}
|
|
1056
|
+
if (!runtimeBindingsEqual(binding, openedBinding)) {
|
|
1057
|
+
binding = this.persistSessionRuntimeBinding(piboSession, openedBinding, {
|
|
1058
|
+
expectedRevision: binding.revision,
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
catch (error) {
|
|
1063
|
+
await runtimeSession.dispose().catch(() => { });
|
|
1064
|
+
portableTools.dispose();
|
|
1065
|
+
if (this.portableToolSessions.get(piboSession.id) === portableTools)
|
|
1066
|
+
this.portableToolSessions.delete(piboSession.id);
|
|
1067
|
+
await resources.dispose();
|
|
1068
|
+
if (this.runtimeResourceSessions.get(piboSession.id) === resources)
|
|
1069
|
+
this.runtimeResourceSessions.delete(piboSession.id);
|
|
1070
|
+
throw error;
|
|
1071
|
+
}
|
|
1072
|
+
session = new RoutedSession(piboSession.id, runtimeSession, this.emitOutput, this.pluginRegistry, {
|
|
1073
|
+
forwardLegacyPiEvents: this.options.forwardPiEvents ?? false,
|
|
1074
|
+
onNativeEventTelemetry: this.telemetryRecorder
|
|
1075
|
+
? (id, event, context) => this.telemetryRecorder?.recordPiEvent(id, event, {
|
|
1076
|
+
session: this.sessionStore.get(id),
|
|
1077
|
+
status: context.status,
|
|
1078
|
+
activeEventId: context.activeEventId,
|
|
1079
|
+
})
|
|
1080
|
+
: undefined,
|
|
1081
|
+
onSessionOperation: (result, event) => this.handleSessionOperation(result, event),
|
|
1082
|
+
onKillChildren: (id, opts) => this.killChildSessions(id, opts),
|
|
1083
|
+
onStateChange: (state) => {
|
|
1084
|
+
this.signalRegistry.project({
|
|
1085
|
+
type: "session_processing_changed",
|
|
1086
|
+
piboSessionId: piboSession.id,
|
|
1087
|
+
processing: state.processing,
|
|
1088
|
+
queuedMessages: state.queuedMessages,
|
|
1089
|
+
});
|
|
1090
|
+
if (!state.processing && state.queuedMessages === 0 && !state.disposed) {
|
|
1091
|
+
this.syncLiveSessionRuntimeBinding(piboSession.id, runtimeSession);
|
|
1092
|
+
}
|
|
1093
|
+
if (state.disposed || state.processing || state.queuedMessages > 0)
|
|
1094
|
+
this.clearIdleSessionTimer(piboSession.id);
|
|
1095
|
+
else
|
|
1096
|
+
this.scheduleIdleSessionEvictionIfIdle(piboSession.id);
|
|
1097
|
+
},
|
|
1098
|
+
onMessagesInterrupted: (messages, reason) => this.telemetryRecorder?.recordMessagesInterrupted(messages, {
|
|
1099
|
+
session: this.sessionStore.get(piboSession.id),
|
|
1100
|
+
status: this.sessions.get(piboSession.id)?.getStatus(),
|
|
1101
|
+
}, reason),
|
|
1102
|
+
messagePreflight: this.options.messagePreflight,
|
|
1103
|
+
getRuntimeAuthStatus: () => runtimeRegistry.getAgentRuntimeAuthStatus(binding.runtimeInstanceId),
|
|
1104
|
+
startRuntimeAuth: async (input) => {
|
|
1105
|
+
const { runtimeInstanceId: _runtimeInstanceId, ...result } = await runtimeRegistry.startAgentRuntimeAuth(binding.runtimeInstanceId, input);
|
|
1106
|
+
return result;
|
|
1107
|
+
},
|
|
1108
|
+
completeRuntimeAuth: async (input) => {
|
|
1109
|
+
const { runtimeInstanceId: _runtimeInstanceId, ...result } = await runtimeRegistry.completeAgentRuntimeAuth(binding.runtimeInstanceId, input);
|
|
1110
|
+
return result;
|
|
1111
|
+
},
|
|
1112
|
+
cancelRuntimeAuth: async (input) => {
|
|
1113
|
+
const { runtimeInstanceId: _runtimeInstanceId, ...result } = await runtimeRegistry.cancelAgentRuntimeAuth(binding.runtimeInstanceId, input);
|
|
1114
|
+
return result;
|
|
1115
|
+
},
|
|
1116
|
+
logoutRuntimeAuth: async (input) => {
|
|
1117
|
+
const { runtimeInstanceId: _runtimeInstanceId, ...result } = await runtimeRegistry.logoutAgentRuntimeAuth(binding.runtimeInstanceId, input);
|
|
1118
|
+
return result;
|
|
741
1119
|
},
|
|
742
1120
|
});
|
|
743
|
-
const initialFastMode = resolvePiboSessionInitialFastMode(piboSession) ?? selectRequestedFastMode(sessionProfile, modelDefaults) ?? false;
|
|
744
|
-
session = new RoutedSession(piboSession.id, runtime, this.emitOutput, this.pluginRegistry, this.options.forwardPiEvents ?? false, this.telemetryRecorder
|
|
745
|
-
? (id, event, context) => this.telemetryRecorder?.recordPiEvent(id, event, { session: this.sessionStore.get(id), status: context.status, activeEventId: context.activeEventId })
|
|
746
|
-
: undefined, initialFastMode, (result, event) => this.handleSessionOperation(result, event), (id, opts) => this.killChildSessions(id, opts), (state) => {
|
|
747
|
-
this.signalRegistry.project({ type: "session_processing_changed", piboSessionId: piboSession.id, processing: state.processing, queuedMessages: state.queuedMessages });
|
|
748
|
-
if (state.disposed || state.processing || state.queuedMessages > 0)
|
|
749
|
-
this.clearIdleSessionTimer(piboSession.id);
|
|
750
|
-
else
|
|
751
|
-
this.scheduleIdleSessionEvictionIfIdle(piboSession.id);
|
|
752
|
-
}, (messages, reason) => this.telemetryRecorder?.recordMessagesInterrupted(messages, {
|
|
753
|
-
session: this.sessionStore.get(piboSession.id),
|
|
754
|
-
status: this.sessions.get(piboSession.id)?.getStatus(),
|
|
755
|
-
}, reason), this.options.messagePreflight);
|
|
756
1121
|
this.sessions.set(piboSession.id, session);
|
|
757
1122
|
return session;
|
|
758
1123
|
}
|
|
1124
|
+
resolveAgentRuntimeRegistry(instanceId) {
|
|
1125
|
+
if (this.pluginRegistry.getAgentRuntimeAdapter(instanceId))
|
|
1126
|
+
return this.pluginRegistry;
|
|
1127
|
+
if (this.compatibilityRuntimeRegistry?.getAgentRuntimeAdapter(instanceId))
|
|
1128
|
+
return this.compatibilityRuntimeRegistry;
|
|
1129
|
+
throw new Error(`Unknown agent runtime instance "${instanceId}".`);
|
|
1130
|
+
}
|
|
1131
|
+
resolveSessionRuntimeBinding(session) {
|
|
1132
|
+
return this.sessionStore.getRuntimeBinding?.(session.id)
|
|
1133
|
+
?? session.runtimeBinding
|
|
1134
|
+
?? createLegacyPiRuntimeSessionBinding(session.id, session.piSessionId, session.createdAt);
|
|
1135
|
+
}
|
|
1136
|
+
withPersistedRuntimeBinding(status) {
|
|
1137
|
+
const session = this.sessionStore.get(status.piboSessionId);
|
|
1138
|
+
if (!session)
|
|
1139
|
+
return status;
|
|
1140
|
+
const binding = this.resolveSessionRuntimeBinding(session);
|
|
1141
|
+
return {
|
|
1142
|
+
...status,
|
|
1143
|
+
runtimeBinding: {
|
|
1144
|
+
runtimeInstanceId: binding.runtimeInstanceId,
|
|
1145
|
+
adapterId: binding.adapterId,
|
|
1146
|
+
nativeSessionId: binding.nativeSessionId,
|
|
1147
|
+
state: binding.state,
|
|
1148
|
+
protocol: binding.protocol,
|
|
1149
|
+
protocolVersion: binding.protocolVersion,
|
|
1150
|
+
adapterVersion: binding.adapterVersion,
|
|
1151
|
+
revision: binding.revision,
|
|
1152
|
+
},
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
persistSessionRuntimeBinding(session, binding, options = {}) {
|
|
1156
|
+
const current = this.resolveSessionRuntimeBinding(session);
|
|
1157
|
+
const normalized = { ...structuredClone(binding), piboSessionId: session.id };
|
|
1158
|
+
if (runtimeBindingsEqual(current, normalized))
|
|
1159
|
+
return current;
|
|
1160
|
+
const persisted = this.sessionStore.updateRuntimeBinding?.(session.id, normalized, options);
|
|
1161
|
+
if (persisted) {
|
|
1162
|
+
const updatedSession = this.sessionStore.get(session.id);
|
|
1163
|
+
if (updatedSession)
|
|
1164
|
+
this.signalRegistry.project({ type: "session_created", session: updatedSession });
|
|
1165
|
+
return persisted;
|
|
1166
|
+
}
|
|
1167
|
+
const now = new Date().toISOString();
|
|
1168
|
+
if (normalized.adapterId === "pi" && normalized.nativeSessionId !== session.piSessionId) {
|
|
1169
|
+
this.sessionStore.update(session.id, { piSessionId: normalized.nativeSessionId ?? "" });
|
|
1170
|
+
}
|
|
1171
|
+
const updatedSession = this.sessionStore.get(session.id);
|
|
1172
|
+
if (updatedSession)
|
|
1173
|
+
this.signalRegistry.project({ type: "session_created", session: updatedSession });
|
|
1174
|
+
return {
|
|
1175
|
+
...normalized,
|
|
1176
|
+
revision: (current.revision ?? 1) + 1,
|
|
1177
|
+
createdAt: current.createdAt ?? session.createdAt,
|
|
1178
|
+
updatedAt: now,
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
syncLiveSessionRuntimeBinding(piboSessionId, runtimeSession) {
|
|
1182
|
+
const session = this.sessionStore.get(piboSessionId);
|
|
1183
|
+
if (!session)
|
|
1184
|
+
return;
|
|
1185
|
+
try {
|
|
1186
|
+
this.persistSessionRuntimeBinding(session, runtimeSession.getBinding());
|
|
1187
|
+
}
|
|
1188
|
+
catch (error) {
|
|
1189
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1190
|
+
this.emitOutput({
|
|
1191
|
+
type: "session_error",
|
|
1192
|
+
piboSessionId,
|
|
1193
|
+
error: `Failed to persist the live runtime binding: ${message}`,
|
|
1194
|
+
errorDetails: runtimeSessionErrorDetails(message),
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
assertOpenableRuntimeBinding(binding) {
|
|
1199
|
+
if (binding.state === "missing") {
|
|
1200
|
+
throw new AgentRuntimeBindingMissingError(binding.piboSessionId, binding.runtimeInstanceId, binding.nativeSessionId);
|
|
1201
|
+
}
|
|
1202
|
+
if (binding.state === "error") {
|
|
1203
|
+
const diagnostic = typeof binding.metadata?.diagnosticMessage === "string"
|
|
1204
|
+
? binding.metadata.diagnosticMessage
|
|
1205
|
+
: "The persisted runtime binding is in an error state.";
|
|
1206
|
+
throw new AgentRuntimeUnavailableError(binding.runtimeInstanceId, `Runtime binding for Pibo session "${binding.piboSessionId}" cannot be opened: ${diagnostic}`);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
createRuntimeBindingInput(profile) {
|
|
1210
|
+
const registry = this.resolveAgentRuntimeRegistry(profile.runtimeInstanceId);
|
|
1211
|
+
const adapter = registry.requireAgentRuntimeAdapter(profile.runtimeInstanceId);
|
|
1212
|
+
return {
|
|
1213
|
+
runtimeInstanceId: profile.runtimeInstanceId,
|
|
1214
|
+
adapterId: adapter.descriptor.id,
|
|
1215
|
+
state: "unbound",
|
|
1216
|
+
protocol: adapter.descriptor.protocol?.name,
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
759
1219
|
ensureSessionActiveModel(piboSession, profile, parentPiSessionId, modelDefaults) {
|
|
760
1220
|
const activeModel = resolvePiboSessionActiveModel({
|
|
761
1221
|
profile,
|
|
@@ -778,19 +1238,33 @@ export class PiboSessionRouter {
|
|
|
778
1238
|
async handleSessionOperation(result, event) {
|
|
779
1239
|
if (result.cancelled)
|
|
780
1240
|
return;
|
|
1241
|
+
const source = this.resolvePiboSession(event.piboSessionId);
|
|
1242
|
+
const previousBinding = this.resolveSessionRuntimeBinding(source);
|
|
1243
|
+
const liveBinding = this.sessions.get(event.piboSessionId)?.getRuntimeBinding();
|
|
1244
|
+
const currentBinding = {
|
|
1245
|
+
...previousBinding,
|
|
1246
|
+
...liveBinding,
|
|
1247
|
+
piboSessionId: source.id,
|
|
1248
|
+
nativeSessionId: result.current.piSessionId,
|
|
1249
|
+
state: "bound",
|
|
1250
|
+
locator: result.current.sessionFile
|
|
1251
|
+
? { kind: "local-file", value: result.current.sessionFile }
|
|
1252
|
+
: liveBinding?.locator ?? previousBinding.locator,
|
|
1253
|
+
};
|
|
781
1254
|
if (event.action === "session.fork" || event.action === "session.clone") {
|
|
782
1255
|
const action = event.action;
|
|
783
|
-
const created = this.createDerivedSession(result, action);
|
|
1256
|
+
const created = this.createDerivedSession(result, action, currentBinding);
|
|
784
1257
|
result.piboSessionId = created.id;
|
|
785
1258
|
await this.resetCachedSession(event.piboSessionId);
|
|
786
1259
|
return;
|
|
787
1260
|
}
|
|
788
|
-
this.
|
|
789
|
-
|
|
790
|
-
|
|
1261
|
+
this.persistSessionRuntimeBinding(source, currentBinding, {
|
|
1262
|
+
expectedRevision: previousBinding.revision,
|
|
1263
|
+
mode: "rebind",
|
|
791
1264
|
});
|
|
1265
|
+
this.sessionStore.update(event.piboSessionId, { workspace: result.current.cwd });
|
|
792
1266
|
}
|
|
793
|
-
createDerivedSession(result, action) {
|
|
1267
|
+
createDerivedSession(result, action, currentBinding) {
|
|
794
1268
|
const source = this.resolvePiboSession(result.piboSessionId);
|
|
795
1269
|
return this.sessionStore.create({
|
|
796
1270
|
channel: source.channel,
|
|
@@ -798,17 +1272,54 @@ export class PiboSessionRouter {
|
|
|
798
1272
|
profile: source.profile,
|
|
799
1273
|
parentId: source.kind === "subagent" ? source.parentId : undefined,
|
|
800
1274
|
originId: source.id,
|
|
801
|
-
|
|
1275
|
+
runtimeBinding: {
|
|
1276
|
+
runtimeInstanceId: currentBinding.runtimeInstanceId,
|
|
1277
|
+
adapterId: currentBinding.adapterId,
|
|
1278
|
+
nativeSessionId: currentBinding.nativeSessionId ?? result.current.piSessionId,
|
|
1279
|
+
state: "bound",
|
|
1280
|
+
protocol: currentBinding.protocol,
|
|
1281
|
+
protocolVersion: currentBinding.protocolVersion,
|
|
1282
|
+
adapterVersion: currentBinding.adapterVersion,
|
|
1283
|
+
locator: currentBinding.locator,
|
|
1284
|
+
metadata: currentBinding.metadata,
|
|
1285
|
+
},
|
|
802
1286
|
workspace: result.current.cwd,
|
|
803
1287
|
title: source.title,
|
|
804
1288
|
activeModel: source.activeModel,
|
|
805
1289
|
metadata: {
|
|
806
1290
|
...asJsonObject(source.metadata),
|
|
807
1291
|
originAction: action,
|
|
808
|
-
|
|
1292
|
+
originRuntimeNativeSessionId: result.previous.piSessionId,
|
|
1293
|
+
...(currentBinding.adapterId === "pi" ? { originPiSessionId: result.previous.piSessionId } : {}),
|
|
809
1294
|
},
|
|
810
1295
|
});
|
|
811
1296
|
}
|
|
1297
|
+
runtimeAuthAffectedInstanceIds(runtimeInstanceId) {
|
|
1298
|
+
const registry = this.resolveAgentRuntimeRegistry(runtimeInstanceId);
|
|
1299
|
+
const target = registry.requireAgentRuntimeAdapter(runtimeInstanceId);
|
|
1300
|
+
if (target.descriptor.capabilities.auth.credentialScope === "runtime-instance")
|
|
1301
|
+
return [runtimeInstanceId];
|
|
1302
|
+
return registry.getAgentRuntimeInstanceIds().filter((candidateId) => {
|
|
1303
|
+
const candidate = registry.getAgentRuntimeAdapter(candidateId);
|
|
1304
|
+
return candidate?.descriptor.id === target.descriptor.id
|
|
1305
|
+
&& candidate.descriptor.capabilities.auth.credentialScope === "adapter-shared";
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
async resetCachedRuntimeAuthSessions(runtimeInstanceId, reason) {
|
|
1309
|
+
const affectedInstanceIds = new Set(this.runtimeAuthAffectedInstanceIds(runtimeInstanceId));
|
|
1310
|
+
for (const affectedInstanceId of affectedInstanceIds)
|
|
1311
|
+
this.runtimeAuthFingerprints.delete(affectedInstanceId);
|
|
1312
|
+
const ids = [...new Set([...this.sessions.keys(), ...this.pendingSessions.keys()])]
|
|
1313
|
+
.filter((piboSessionId) => {
|
|
1314
|
+
const boundRuntimeInstanceId = this.getSessionRuntimeBinding(piboSessionId)?.runtimeInstanceId;
|
|
1315
|
+
return boundRuntimeInstanceId !== undefined && affectedInstanceIds.has(boundRuntimeInstanceId);
|
|
1316
|
+
});
|
|
1317
|
+
const results = await Promise.allSettled(ids.map(async (piboSessionId) => await this.resetCachedSession(piboSessionId, reason)));
|
|
1318
|
+
const failures = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
1319
|
+
if (failures.length > 0) {
|
|
1320
|
+
throw new AggregateError(failures, `Failed to reset cached sessions affected by runtime auth target "${runtimeInstanceId}".`);
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
812
1323
|
async resetCachedSession(piboSessionId, reason) {
|
|
813
1324
|
const existingDisposal = this.disposingSessions.get(piboSessionId);
|
|
814
1325
|
if (existingDisposal)
|
|
@@ -860,14 +1371,50 @@ export class PiboSessionRouter {
|
|
|
860
1371
|
channel: "pibo.runtime",
|
|
861
1372
|
kind: "runtime",
|
|
862
1373
|
profile: this.baseProfile.profileName,
|
|
1374
|
+
runtimeBinding: this.createRuntimeBindingInput(this.baseProfile),
|
|
863
1375
|
workspace: this.options.cwd ?? getDefaultPiboWorkspace(),
|
|
864
1376
|
});
|
|
865
1377
|
this.signalRegistry.project({ type: "session_created", session: created });
|
|
866
1378
|
return created;
|
|
867
1379
|
}
|
|
1380
|
+
trackActiveSubagent(parentPiboSessionId, childPiboSessionId) {
|
|
1381
|
+
let children = this.activeSubagentChildren.get(parentPiboSessionId);
|
|
1382
|
+
if (!children) {
|
|
1383
|
+
children = new Map();
|
|
1384
|
+
this.activeSubagentChildren.set(parentPiboSessionId, children);
|
|
1385
|
+
}
|
|
1386
|
+
children.set(childPiboSessionId, (children.get(childPiboSessionId) ?? 0) + 1);
|
|
1387
|
+
let active = true;
|
|
1388
|
+
return () => {
|
|
1389
|
+
if (!active)
|
|
1390
|
+
return;
|
|
1391
|
+
active = false;
|
|
1392
|
+
const current = this.activeSubagentChildren.get(parentPiboSessionId);
|
|
1393
|
+
if (!current)
|
|
1394
|
+
return;
|
|
1395
|
+
const remaining = (current.get(childPiboSessionId) ?? 1) - 1;
|
|
1396
|
+
if (remaining > 0)
|
|
1397
|
+
current.set(childPiboSessionId, remaining);
|
|
1398
|
+
else
|
|
1399
|
+
current.delete(childPiboSessionId);
|
|
1400
|
+
if (current.size === 0)
|
|
1401
|
+
this.activeSubagentChildren.delete(parentPiboSessionId);
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
async abortActiveSubagentSessions(parentPiboSessionId) {
|
|
1405
|
+
const childIds = [...(this.activeSubagentChildren.get(parentPiboSessionId)?.keys() ?? [])];
|
|
1406
|
+
if (childIds.length === 0)
|
|
1407
|
+
return;
|
|
1408
|
+
await Promise.allSettled(childIds.map(async (childPiboSessionId) => await this.emit({
|
|
1409
|
+
type: "execution",
|
|
1410
|
+
piboSessionId: childPiboSessionId,
|
|
1411
|
+
action: "abort",
|
|
1412
|
+
id: randomUUID(),
|
|
1413
|
+
})));
|
|
1414
|
+
}
|
|
868
1415
|
createSubagentRunner(parentPiboSessionId) {
|
|
869
1416
|
return {
|
|
870
|
-
runSubagent: async ({ subagent, message, threadKey, toolCallId }) => {
|
|
1417
|
+
runSubagent: async ({ subagent, message, threadKey, toolCallId, signal }) => {
|
|
871
1418
|
this.assertSubagentDepth(parentPiboSessionId, subagent);
|
|
872
1419
|
const child = this.resolveSubagentSession(parentPiboSessionId, subagent, threadKey);
|
|
873
1420
|
const toolName = createSubagentToolName(subagent.name);
|
|
@@ -887,8 +1434,14 @@ export class PiboSessionRouter {
|
|
|
887
1434
|
childPiboSessionId: child.id,
|
|
888
1435
|
threadKey: typeof child.metadata?.threadKey === "string" ? child.metadata.threadKey : undefined,
|
|
889
1436
|
});
|
|
890
|
-
const
|
|
891
|
-
|
|
1437
|
+
const untrack = this.trackActiveSubagent(parentPiboSessionId, child.id);
|
|
1438
|
+
try {
|
|
1439
|
+
const reply = await this.emitMessageAndWaitForReply(event, subagent.timeoutMs ?? DEFAULT_SUBAGENT_REPLY_TIMEOUT_MS, signal);
|
|
1440
|
+
return { piboSessionId: child.id, eventId: event.id, reply };
|
|
1441
|
+
}
|
|
1442
|
+
finally {
|
|
1443
|
+
untrack();
|
|
1444
|
+
}
|
|
892
1445
|
},
|
|
893
1446
|
};
|
|
894
1447
|
}
|
|
@@ -987,7 +1540,7 @@ export class PiboSessionRouter {
|
|
|
987
1540
|
resolveSubagentSession(parentPiboSessionId, subagent, threadKey) {
|
|
988
1541
|
const targetProfile = resolvePiboProfileNameFromRegistryOrDefault(this.pluginRegistry, subagent.targetProfile);
|
|
989
1542
|
const parent = this.resolvePiboSession(parentPiboSessionId);
|
|
990
|
-
const resolvedThreadKey =
|
|
1543
|
+
const resolvedThreadKey = resolveSubagentThreadKey(threadKey);
|
|
991
1544
|
const baseMetadata = {
|
|
992
1545
|
subagentName: subagent.name,
|
|
993
1546
|
subagentToolName: createSubagentToolName(subagent.name),
|
|
@@ -1027,6 +1580,7 @@ export class PiboSessionRouter {
|
|
|
1027
1580
|
kind: "subagent",
|
|
1028
1581
|
profile: targetProfile,
|
|
1029
1582
|
parentId: parent.id,
|
|
1583
|
+
runtimeBinding: this.createRuntimeBindingInput(childProfile),
|
|
1030
1584
|
workspace: parent.workspace,
|
|
1031
1585
|
metadata,
|
|
1032
1586
|
});
|
|
@@ -1034,7 +1588,7 @@ export class PiboSessionRouter {
|
|
|
1034
1588
|
const activeModel = resolvePiboSessionActiveModel({
|
|
1035
1589
|
profile: childProfile,
|
|
1036
1590
|
piboSession: childSession,
|
|
1037
|
-
parentPiSessionId: parent.
|
|
1591
|
+
parentPiSessionId: this.resolveSessionRuntimeBinding(parent).nativeSessionId ?? parent.id,
|
|
1038
1592
|
modelDefaults: this.resolveModelDefaults(),
|
|
1039
1593
|
});
|
|
1040
1594
|
return activeModel ? this.sessionStore.update(childSession.id, { activeModel }) ?? childSession : childSession;
|