@copilotkit/runtime 1.56.2 → 1.56.4-canary.1777529757
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/converters/tanstack.cjs +121 -25
- package/dist/agent/converters/tanstack.cjs.map +1 -1
- package/dist/agent/converters/tanstack.d.cts.map +1 -1
- package/dist/agent/converters/tanstack.d.mts.map +1 -1
- package/dist/agent/converters/tanstack.mjs +121 -25
- package/dist/agent/converters/tanstack.mjs.map +1 -1
- package/dist/graphql/resolvers/copilot.resolver.cjs +2 -1
- package/dist/graphql/resolvers/copilot.resolver.cjs.map +1 -1
- package/dist/graphql/resolvers/copilot.resolver.mjs +2 -1
- package/dist/graphql/resolvers/copilot.resolver.mjs.map +1 -1
- package/dist/graphql/resolvers/resolve-message-id.cjs +19 -0
- package/dist/graphql/resolvers/resolve-message-id.cjs.map +1 -0
- package/dist/graphql/resolvers/resolve-message-id.mjs +18 -0
- package/dist/graphql/resolvers/resolve-message-id.mjs.map +1 -0
- package/dist/lib/runtime/agent-integrations/langgraph/agent.cjs +8 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.cjs.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.mjs +8 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.mjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.cjs +4 -2
- package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.mjs +4 -2
- package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
- package/dist/package.cjs +7 -7
- package/dist/package.mjs +7 -7
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/runtime/core/debug-event-bus.cjs +36 -0
- package/dist/v2/runtime/core/debug-event-bus.cjs.map +1 -0
- package/dist/v2/runtime/core/debug-event-bus.d.cts +19 -0
- package/dist/v2/runtime/core/debug-event-bus.d.cts.map +1 -0
- package/dist/v2/runtime/core/debug-event-bus.d.mts +19 -0
- package/dist/v2/runtime/core/debug-event-bus.d.mts.map +1 -0
- package/dist/v2/runtime/core/debug-event-bus.mjs +35 -0
- package/dist/v2/runtime/core/debug-event-bus.mjs.map +1 -0
- package/dist/v2/runtime/core/fetch-handler.cjs +8 -0
- package/dist/v2/runtime/core/fetch-handler.cjs.map +1 -1
- package/dist/v2/runtime/core/fetch-handler.d.cts.map +1 -1
- package/dist/v2/runtime/core/fetch-handler.d.mts.map +1 -1
- package/dist/v2/runtime/core/fetch-handler.mjs +8 -0
- package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -1
- package/dist/v2/runtime/core/fetch-router.cjs +1 -0
- package/dist/v2/runtime/core/fetch-router.cjs.map +1 -1
- package/dist/v2/runtime/core/fetch-router.mjs +1 -0
- package/dist/v2/runtime/core/fetch-router.mjs.map +1 -1
- package/dist/v2/runtime/core/hooks.cjs.map +1 -1
- package/dist/v2/runtime/core/hooks.d.cts +2 -0
- package/dist/v2/runtime/core/hooks.d.cts.map +1 -1
- package/dist/v2/runtime/core/hooks.d.mts +2 -0
- package/dist/v2/runtime/core/hooks.d.mts.map +1 -1
- package/dist/v2/runtime/core/hooks.mjs.map +1 -1
- package/dist/v2/runtime/core/runtime.cjs +5 -0
- package/dist/v2/runtime/core/runtime.cjs.map +1 -1
- package/dist/v2/runtime/core/runtime.d.cts +5 -0
- package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
- package/dist/v2/runtime/core/runtime.d.mts +5 -1
- package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
- package/dist/v2/runtime/core/runtime.mjs +5 -0
- package/dist/v2/runtime/core/runtime.mjs.map +1 -1
- package/dist/v2/runtime/endpoints/express.cjs +5 -5
- package/dist/v2/runtime/endpoints/express.cjs.map +1 -1
- package/dist/v2/runtime/endpoints/express.mjs +5 -5
- package/dist/v2/runtime/endpoints/express.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-connect.cjs +3 -2
- package/dist/v2/runtime/handlers/handle-connect.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-connect.mjs +3 -2
- package/dist/v2/runtime/handlers/handle-connect.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-debug-events.cjs +33 -0
- package/dist/v2/runtime/handlers/handle-debug-events.cjs.map +1 -0
- package/dist/v2/runtime/handlers/handle-debug-events.mjs +32 -0
- package/dist/v2/runtime/handlers/handle-debug-events.mjs.map +1 -0
- package/dist/v2/runtime/handlers/handle-run.cjs +1 -0
- package/dist/v2/runtime/handlers/handle-run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-run.mjs +1 -0
- package/dist/v2/runtime/handlers/handle-run.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/connect.cjs +24 -4
- package/dist/v2/runtime/handlers/intelligence/connect.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/connect.mjs +25 -5
- package/dist/v2/runtime/handlers/intelligence/connect.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/run.cjs +111 -26
- package/dist/v2/runtime/handlers/intelligence/run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/run.mjs +111 -26
- package/dist/v2/runtime/handlers/intelligence/run.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/intelligence-utils.cjs +7 -3
- package/dist/v2/runtime/handlers/shared/intelligence-utils.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/intelligence-utils.mjs +7 -3
- package/dist/v2/runtime/handlers/shared/intelligence-utils.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.cjs +5 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.mjs +5 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/sse-response.cjs +21 -1
- package/dist/v2/runtime/handlers/shared/sse-response.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/sse-response.mjs +21 -1
- package/dist/v2/runtime/handlers/shared/sse-response.mjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/connect.cjs +3 -1
- package/dist/v2/runtime/handlers/sse/connect.cjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/connect.mjs +3 -1
- package/dist/v2/runtime/handlers/sse/connect.mjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/run.cjs +3 -1
- package/dist/v2/runtime/handlers/sse/run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/run.mjs +3 -1
- package/dist/v2/runtime/handlers/sse/run.mjs.map +1 -1
- package/dist/v2/runtime/index.d.cts +1 -1
- package/dist/v2/runtime/index.d.mts +1 -2
- package/dist/v2/runtime/index.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.cjs +6 -8
- package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.cts +16 -21
- package/dist/v2/runtime/intelligence-platform/client.d.cts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.mts +16 -21
- package/dist/v2/runtime/intelligence-platform/client.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.mjs +6 -8
- package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -1
- package/dist/v2/runtime/runner/agent-runner.cjs.map +1 -1
- package/dist/v2/runtime/runner/agent-runner.d.cts +0 -1
- package/dist/v2/runtime/runner/agent-runner.d.cts.map +1 -1
- package/dist/v2/runtime/runner/agent-runner.d.mts +0 -1
- package/dist/v2/runtime/runner/agent-runner.d.mts.map +1 -1
- package/dist/v2/runtime/runner/agent-runner.mjs.map +1 -1
- package/dist/v2/runtime/runner/index.d.cts +1 -1
- package/dist/v2/runtime/runner/index.d.mts +1 -1
- package/dist/v2/runtime/runner/intelligence.cjs +47 -10
- package/dist/v2/runtime/runner/intelligence.cjs.map +1 -1
- package/dist/v2/runtime/runner/intelligence.d.cts +8 -1
- package/dist/v2/runtime/runner/intelligence.d.cts.map +1 -1
- package/dist/v2/runtime/runner/intelligence.d.mts +8 -1
- package/dist/v2/runtime/runner/intelligence.d.mts.map +1 -1
- package/dist/v2/runtime/runner/intelligence.mjs +47 -10
- package/dist/v2/runtime/runner/intelligence.mjs.map +1 -1
- package/dist/v2/runtime/telemetry/instance-created.cjs +33 -0
- package/dist/v2/runtime/telemetry/instance-created.cjs.map +1 -0
- package/dist/v2/runtime/telemetry/instance-created.mjs +33 -0
- package/dist/v2/runtime/telemetry/instance-created.mjs.map +1 -0
- package/dist/v2/runtime/telemetry/telemetry-client.cjs +1 -38
- package/dist/v2/runtime/telemetry/telemetry-client.cjs.map +1 -1
- package/dist/v2/runtime/telemetry/telemetry-client.mjs +1 -37
- package/dist/v2/runtime/telemetry/telemetry-client.mjs.map +1 -1
- package/package.json +8 -8
- package/src/agent/__tests__/agent-test-helpers.ts +31 -1
- package/src/agent/__tests__/converter-tanstack.test.ts +280 -0
- package/src/agent/converters/tanstack.ts +167 -10
- package/src/agents/langgraph/__tests__/event-source.test.ts +256 -0
- package/src/graphql/resolvers/__tests__/resolve-message-id.test.ts +25 -0
- package/src/graphql/resolvers/copilot.resolver.ts +2 -1
- package/src/graphql/resolvers/resolve-message-id.ts +14 -0
- package/src/lib/runtime/__tests__/handle-service-adapter.test.ts +108 -0
- package/src/lib/runtime/__tests__/retry-utils.test.ts +137 -0
- package/src/lib/runtime/agent-integrations/langgraph/__tests__/dispatch-event-filtering.test.ts +190 -0
- package/src/lib/runtime/agent-integrations/langgraph/agent.ts +8 -1
- package/src/lib/runtime/copilot-runtime.ts +20 -4
- package/src/lib/runtime/retry-utils.ts +41 -1
- package/src/v2/runtime/__tests__/express-fetch-bridge.test.ts +1 -1
- package/src/v2/runtime/__tests__/express-single-telemetry.integration.test.ts +65 -0
- package/src/v2/runtime/__tests__/express-telemetry.integration.test.ts +101 -0
- package/src/v2/runtime/__tests__/fetch-router.test.ts +22 -0
- package/src/v2/runtime/__tests__/handle-connect.test.ts +183 -23
- package/src/v2/runtime/__tests__/handle-run.test.ts +411 -33
- package/src/v2/runtime/__tests__/handle-threads.test.ts +66 -4
- package/src/v2/runtime/__tests__/hono-single-telemetry.integration.test.ts +46 -0
- package/src/v2/runtime/__tests__/hono-telemetry.integration.test.ts +99 -0
- package/src/v2/runtime/__tests__/integration/node-servers.integration.test.ts +19 -0
- package/src/v2/runtime/__tests__/integration/suites/debug-events.suite.ts +253 -0
- package/src/v2/runtime/__tests__/intelligence-run-telemetry.test.ts +194 -0
- package/src/v2/runtime/__tests__/runtime.test.ts +3 -1
- package/src/v2/runtime/__tests__/sse-response-telemetry.test.ts +108 -0
- package/src/v2/runtime/__tests__/telemetry.test.ts +0 -61
- package/src/v2/runtime/core/__tests__/debug-event-bus.test.ts +156 -0
- package/src/v2/runtime/core/debug-event-bus.ts +45 -0
- package/src/v2/runtime/core/fetch-handler.ts +7 -0
- package/src/v2/runtime/core/fetch-router.ts +11 -0
- package/src/v2/runtime/core/hooks.ts +2 -1
- package/src/v2/runtime/core/runtime.ts +12 -0
- package/src/v2/runtime/endpoints/express.ts +9 -3
- package/src/v2/runtime/handlers/__tests__/handle-debug-events.test.ts +176 -0
- package/src/v2/runtime/handlers/handle-connect.ts +2 -1
- package/src/v2/runtime/handlers/handle-debug-events.ts +52 -0
- package/src/v2/runtime/handlers/handle-run.ts +1 -0
- package/src/v2/runtime/handlers/intelligence/connect.ts +48 -11
- package/src/v2/runtime/handlers/intelligence/run.ts +162 -21
- package/src/v2/runtime/handlers/shared/intelligence-utils.ts +21 -1
- package/src/v2/runtime/handlers/shared/resolve-intelligence-user.ts +4 -1
- package/src/v2/runtime/handlers/shared/sse-response.ts +46 -0
- package/src/v2/runtime/handlers/sse/__tests__/sse-connect-agent-id.test.ts +71 -0
- package/src/v2/runtime/handlers/sse/connect.ts +6 -0
- package/src/v2/runtime/handlers/sse/run.ts +4 -0
- package/src/v2/runtime/intelligence-platform/__tests__/client.test.ts +33 -37
- package/src/v2/runtime/intelligence-platform/client.ts +37 -40
- package/src/v2/runtime/runner/__tests__/intelligence-runner.test.ts +66 -8
- package/src/v2/runtime/runner/agent-runner.ts +0 -1
- package/src/v2/runtime/runner/intelligence.ts +74 -15
- package/src/v2/runtime/telemetry/__tests__/instance-created.test.ts +96 -0
- package/src/v2/runtime/telemetry/instance-created.ts +44 -0
- package/src/v2/runtime/telemetry/telemetry-client.ts +1 -57
- package/dist/v2/runtime/intelligence-platform/index.d.mts +0 -2
- package/dist/v2/runtime/telemetry/utils.cjs +0 -15
- package/dist/v2/runtime/telemetry/utils.cjs.map +0 -1
- package/dist/v2/runtime/telemetry/utils.mjs +0 -14
- package/dist/v2/runtime/telemetry/utils.mjs.map +0 -1
- package/src/v2/runtime/telemetry/utils.ts +0 -15
|
@@ -24,6 +24,7 @@ import type {
|
|
|
24
24
|
} from "./middleware";
|
|
25
25
|
import { createLogger, type CopilotRuntimeLogger } from "../../../lib/logger";
|
|
26
26
|
import { TranscriptionService } from "../transcription-service/transcription-service";
|
|
27
|
+
import { DebugEventBus } from "./debug-event-bus";
|
|
27
28
|
import { AgentRunner } from "../runner/agent-runner";
|
|
28
29
|
import { InMemoryAgentRunner } from "../runner/in-memory";
|
|
29
30
|
import { IntelligenceAgentRunner } from "../runner/intelligence";
|
|
@@ -140,6 +141,7 @@ interface BaseCopilotRuntimeOptions extends CopilotRuntimeMiddlewares {
|
|
|
140
141
|
|
|
141
142
|
export interface CopilotRuntimeUser {
|
|
142
143
|
id: string;
|
|
144
|
+
name: string;
|
|
143
145
|
}
|
|
144
146
|
|
|
145
147
|
export type IdentifyUserCallback = (
|
|
@@ -189,6 +191,7 @@ export interface CopilotRuntimeLike {
|
|
|
189
191
|
identifyUser?: IdentifyUserCallback;
|
|
190
192
|
mode: RuntimeMode;
|
|
191
193
|
licenseChecker?: LicenseChecker;
|
|
194
|
+
debugEventBus?: DebugEventBus;
|
|
192
195
|
debug: ResolvedDebugConfig;
|
|
193
196
|
debugLogger?: CopilotRuntimeLogger;
|
|
194
197
|
}
|
|
@@ -218,6 +221,7 @@ abstract class BaseCopilotRuntime implements CopilotRuntimeLike {
|
|
|
218
221
|
public mcpApps: CopilotRuntimeOptions["mcpApps"];
|
|
219
222
|
public openGenerativeUI: CopilotRuntimeOptions["openGenerativeUI"];
|
|
220
223
|
public licenseChecker?: LicenseChecker;
|
|
224
|
+
public readonly debugEventBus?: DebugEventBus;
|
|
221
225
|
public debug: ResolvedDebugConfig;
|
|
222
226
|
public debugLogger?: CopilotRuntimeLogger;
|
|
223
227
|
|
|
@@ -243,6 +247,10 @@ abstract class BaseCopilotRuntime implements CopilotRuntimeLike {
|
|
|
243
247
|
this.mcpApps = mcpApps;
|
|
244
248
|
this.openGenerativeUI = openGenerativeUI;
|
|
245
249
|
this.runner = runner;
|
|
250
|
+
|
|
251
|
+
if (process.env.NODE_ENV !== "production") {
|
|
252
|
+
this.debugEventBus = new DebugEventBus();
|
|
253
|
+
}
|
|
246
254
|
this.debug = resolveDebugConfig(options.debug);
|
|
247
255
|
if (this.debug.enabled) {
|
|
248
256
|
this.debugLogger = createLogger({
|
|
@@ -407,6 +415,10 @@ export class CopilotRuntime implements CopilotRuntimeLike {
|
|
|
407
415
|
return this.delegate.licenseChecker;
|
|
408
416
|
}
|
|
409
417
|
|
|
418
|
+
get debugEventBus() {
|
|
419
|
+
return this.delegate.debugEventBus;
|
|
420
|
+
}
|
|
421
|
+
|
|
410
422
|
get debug(): ResolvedDebugConfig {
|
|
411
423
|
return this.delegate.debug;
|
|
412
424
|
}
|
|
@@ -147,15 +147,21 @@ export function createCopilotExpressHandler({
|
|
|
147
147
|
router.post(normalizedBase, expressHandler);
|
|
148
148
|
router.options(normalizedBase, expressHandler);
|
|
149
149
|
} else if (normalizedBase === "/") {
|
|
150
|
-
router.all(
|
|
150
|
+
router.all(/.*/, expressHandler);
|
|
151
151
|
} else {
|
|
152
|
-
router.all(
|
|
153
|
-
|
|
152
|
+
router.all(
|
|
153
|
+
new RegExp(`^${escapeRegExp(normalizedBase)}(\\/.*)?$`),
|
|
154
|
+
expressHandler,
|
|
155
|
+
);
|
|
154
156
|
}
|
|
155
157
|
|
|
156
158
|
return router;
|
|
157
159
|
}
|
|
158
160
|
|
|
161
|
+
function escapeRegExp(s: string): string {
|
|
162
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
163
|
+
}
|
|
164
|
+
|
|
159
165
|
function normalizeBasePath(path: string): string {
|
|
160
166
|
if (!path) {
|
|
161
167
|
throw new Error("basePath must be provided for Express endpoint");
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { handleDebugEvents } from "../handle-debug-events";
|
|
3
|
+
import { DebugEventBus } from "../../core/debug-event-bus";
|
|
4
|
+
import type { CopilotRuntimeLike } from "../../core/runtime";
|
|
5
|
+
import type { BaseEvent } from "@ag-ui/client";
|
|
6
|
+
|
|
7
|
+
/* ------------------------------------------------------------------------------------------------
|
|
8
|
+
* Helpers
|
|
9
|
+
* --------------------------------------------------------------------------------------------- */
|
|
10
|
+
|
|
11
|
+
function createMockRuntime(
|
|
12
|
+
overrides: { debugEventBus?: DebugEventBus } = {},
|
|
13
|
+
): Pick<CopilotRuntimeLike, "debugEventBus"> {
|
|
14
|
+
return {
|
|
15
|
+
debugEventBus: overrides.debugEventBus ?? new DebugEventBus(),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function createMockRequest(options: { signal?: AbortSignal } = {}): Request {
|
|
20
|
+
return new Request("http://localhost/cpk-debug-events", {
|
|
21
|
+
method: "GET",
|
|
22
|
+
signal: options.signal,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function createTestEvent(): BaseEvent {
|
|
27
|
+
return { type: "custom" } as BaseEvent;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function readNextSSELine(
|
|
31
|
+
reader: ReadableStreamDefaultReader<Uint8Array>,
|
|
32
|
+
): Promise<string> {
|
|
33
|
+
const decoder = new TextDecoder();
|
|
34
|
+
let accumulated = "";
|
|
35
|
+
while (true) {
|
|
36
|
+
const { value, done } = await reader.read();
|
|
37
|
+
if (done) break;
|
|
38
|
+
accumulated += decoder.decode(value, { stream: true });
|
|
39
|
+
if (accumulated.includes("\n\n")) return accumulated;
|
|
40
|
+
}
|
|
41
|
+
return accumulated;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* ------------------------------------------------------------------------------------------------
|
|
45
|
+
* Tests
|
|
46
|
+
* --------------------------------------------------------------------------------------------- */
|
|
47
|
+
|
|
48
|
+
describe("handleDebugEvents", () => {
|
|
49
|
+
let savedNodeEnv: string | undefined;
|
|
50
|
+
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
savedNodeEnv = process.env.NODE_ENV;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
if (savedNodeEnv === undefined) {
|
|
57
|
+
delete process.env.NODE_ENV;
|
|
58
|
+
} else {
|
|
59
|
+
process.env.NODE_ENV = savedNodeEnv;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("returns 404 when NODE_ENV is production", async () => {
|
|
64
|
+
process.env.NODE_ENV = "production";
|
|
65
|
+
|
|
66
|
+
const runtime = createMockRuntime();
|
|
67
|
+
const request = createMockRequest();
|
|
68
|
+
|
|
69
|
+
const response = handleDebugEvents({
|
|
70
|
+
runtime: runtime as CopilotRuntimeLike,
|
|
71
|
+
request,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(response.status).toBe(404);
|
|
75
|
+
expect(await response.text()).toBe("Not Found");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("returns 503 when debugEventBus is undefined", async () => {
|
|
79
|
+
process.env.NODE_ENV = "test";
|
|
80
|
+
|
|
81
|
+
const runtime = createMockRuntime({ debugEventBus: undefined });
|
|
82
|
+
// Remove the property so it's truly undefined
|
|
83
|
+
delete (runtime as Record<string, unknown>).debugEventBus;
|
|
84
|
+
|
|
85
|
+
const request = createMockRequest();
|
|
86
|
+
|
|
87
|
+
const response = handleDebugEvents({
|
|
88
|
+
runtime: runtime as CopilotRuntimeLike,
|
|
89
|
+
request,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(response.status).toBe(503);
|
|
93
|
+
expect(await response.text()).toBe("Debug event bus not available");
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("returns correct SSE response headers", () => {
|
|
97
|
+
process.env.NODE_ENV = "test";
|
|
98
|
+
|
|
99
|
+
const runtime = createMockRuntime();
|
|
100
|
+
const request = createMockRequest();
|
|
101
|
+
|
|
102
|
+
const response = handleDebugEvents({
|
|
103
|
+
runtime: runtime as CopilotRuntimeLike,
|
|
104
|
+
request,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
expect(response.status).toBe(200);
|
|
108
|
+
expect(response.headers.get("Content-Type")).toBe("text/event-stream");
|
|
109
|
+
expect(response.headers.get("Cache-Control")).toBe("no-cache");
|
|
110
|
+
expect(response.headers.get("Connection")).toBe("keep-alive");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("streams events as SSE data lines when bus broadcasts", async () => {
|
|
114
|
+
process.env.NODE_ENV = "test";
|
|
115
|
+
|
|
116
|
+
const bus = new DebugEventBus();
|
|
117
|
+
const runtime = createMockRuntime({ debugEventBus: bus });
|
|
118
|
+
const request = createMockRequest();
|
|
119
|
+
|
|
120
|
+
const response = handleDebugEvents({
|
|
121
|
+
runtime: runtime as CopilotRuntimeLike,
|
|
122
|
+
request,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const reader = response.body!.getReader();
|
|
126
|
+
|
|
127
|
+
// Read and discard the initial ": connected" SSE comment
|
|
128
|
+
const comment = await readNextSSELine(reader);
|
|
129
|
+
expect(comment).toMatch(/^: connected/);
|
|
130
|
+
|
|
131
|
+
// Broadcast an event through the bus
|
|
132
|
+
bus.broadcast(createTestEvent(), {
|
|
133
|
+
agentId: "agent-1",
|
|
134
|
+
threadId: "thread-1",
|
|
135
|
+
runId: "run-1",
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const line = await readNextSSELine(reader);
|
|
139
|
+
|
|
140
|
+
// The line should be "data: {json}\n\n"
|
|
141
|
+
expect(line).toMatch(/^data: \{.*\}\n\n$/);
|
|
142
|
+
|
|
143
|
+
const parsed = JSON.parse(line.replace("data: ", "").trim());
|
|
144
|
+
expect(parsed.agentId).toBe("agent-1");
|
|
145
|
+
expect(parsed.threadId).toBe("thread-1");
|
|
146
|
+
expect(parsed.runId).toBe("run-1");
|
|
147
|
+
expect(parsed.event).toEqual(createTestEvent());
|
|
148
|
+
expect(typeof parsed.timestamp).toBe("number");
|
|
149
|
+
|
|
150
|
+
reader.releaseLock();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("unsubscribes from bus when request is aborted", async () => {
|
|
154
|
+
process.env.NODE_ENV = "test";
|
|
155
|
+
|
|
156
|
+
const bus = new DebugEventBus();
|
|
157
|
+
const runtime = createMockRuntime({ debugEventBus: bus });
|
|
158
|
+
|
|
159
|
+
const abortController = new AbortController();
|
|
160
|
+
const request = createMockRequest({ signal: abortController.signal });
|
|
161
|
+
|
|
162
|
+
handleDebugEvents({
|
|
163
|
+
runtime: runtime as CopilotRuntimeLike,
|
|
164
|
+
request,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Before abort, the bus should have one listener
|
|
168
|
+
expect(bus.listenerCount).toBe(1);
|
|
169
|
+
|
|
170
|
+
// Abort the request
|
|
171
|
+
abortController.abort();
|
|
172
|
+
|
|
173
|
+
// After abort, the listener should be cleaned up
|
|
174
|
+
expect(bus.listenerCount).toBe(0);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
@@ -43,14 +43,15 @@ export async function handleConnectAgent({
|
|
|
43
43
|
return handleIntelligenceConnect({
|
|
44
44
|
runtime,
|
|
45
45
|
request,
|
|
46
|
+
agentId,
|
|
46
47
|
threadId: connectRequest.input.threadId,
|
|
47
|
-
lastSeenEventId: connectRequest.lastSeenEventId,
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
return handleSseConnect({
|
|
52
52
|
runtime,
|
|
53
53
|
request,
|
|
54
|
+
agentId,
|
|
54
55
|
threadId: connectRequest.input.threadId,
|
|
55
56
|
});
|
|
56
57
|
} catch (error) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { CopilotRuntimeLike } from "../core/runtime";
|
|
2
|
+
import { DebugEventEnvelope } from "@copilotkit/shared";
|
|
3
|
+
|
|
4
|
+
interface HandleDebugEventsParams {
|
|
5
|
+
runtime: CopilotRuntimeLike;
|
|
6
|
+
request: Request;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function handleDebugEvents({
|
|
10
|
+
runtime,
|
|
11
|
+
request,
|
|
12
|
+
}: HandleDebugEventsParams): Response {
|
|
13
|
+
if (process.env.NODE_ENV === "production") {
|
|
14
|
+
return new Response("Not Found", { status: 404 });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!runtime.debugEventBus) {
|
|
18
|
+
return new Response("Debug event bus not available", { status: 503 });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const bus = runtime.debugEventBus;
|
|
22
|
+
const encoder = new TextEncoder();
|
|
23
|
+
const stream = new TransformStream();
|
|
24
|
+
const writer = stream.writable.getWriter();
|
|
25
|
+
|
|
26
|
+
// Send an SSE comment immediately to flush response headers to the client.
|
|
27
|
+
// Without this, some frameworks buffer the response until actual data is written,
|
|
28
|
+
// leaving the client stuck in "connecting" state.
|
|
29
|
+
writer.write(encoder.encode(": connected\n\n")).catch(() => {});
|
|
30
|
+
|
|
31
|
+
const unsubscribe = bus.subscribe((envelope: DebugEventEnvelope) => {
|
|
32
|
+
if (request.signal.aborted) return;
|
|
33
|
+
const line = `data: ${JSON.stringify(envelope)}\n\n`;
|
|
34
|
+
writer.write(encoder.encode(line)).catch(() => {
|
|
35
|
+
// Client disconnected, will be cleaned up by abort handler.
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
request.signal.addEventListener("abort", () => {
|
|
40
|
+
unsubscribe();
|
|
41
|
+
writer.close().catch(() => {});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return new Response(stream.readable, {
|
|
45
|
+
status: 200,
|
|
46
|
+
headers: {
|
|
47
|
+
"Content-Type": "text/event-stream",
|
|
48
|
+
"Cache-Control": "no-cache",
|
|
49
|
+
Connection: "keep-alive",
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
import { CopilotIntelligenceRuntimeLike } from "../../core/runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { getPlatformErrorStatus } from "../shared/intelligence-utils";
|
|
3
3
|
import { resolveIntelligenceUser } from "../shared/resolve-intelligence-user";
|
|
4
4
|
import { isHandlerResponse } from "../shared/json-response";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Builds browser-facing realtime connection metadata owned by the runtime.
|
|
8
|
+
*/
|
|
9
|
+
function buildRealtimeConnectionInfo(params: {
|
|
10
|
+
clientUrl: string;
|
|
11
|
+
threadId: string;
|
|
12
|
+
}): { clientUrl: string; topic: string } {
|
|
13
|
+
return {
|
|
14
|
+
clientUrl: params.clientUrl,
|
|
15
|
+
topic: `thread:${params.threadId}`,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
6
19
|
interface HandleIntelligenceConnectParams {
|
|
7
20
|
runtime: CopilotIntelligenceRuntimeLike;
|
|
8
21
|
request: Request;
|
|
22
|
+
agentId: string;
|
|
9
23
|
threadId: string;
|
|
10
|
-
lastSeenEventId: string | null;
|
|
11
24
|
}
|
|
12
25
|
|
|
13
26
|
export async function handleIntelligenceConnect({
|
|
14
27
|
runtime,
|
|
15
28
|
request,
|
|
29
|
+
agentId,
|
|
16
30
|
threadId,
|
|
17
|
-
lastSeenEventId,
|
|
18
31
|
}: HandleIntelligenceConnectParams): Promise<Response> {
|
|
19
32
|
if (!runtime.intelligence) {
|
|
20
33
|
return Response.json(
|
|
@@ -35,7 +48,7 @@ export async function handleIntelligenceConnect({
|
|
|
35
48
|
const result = await runtime.intelligence.ɵconnectThread({
|
|
36
49
|
threadId,
|
|
37
50
|
userId: user.id,
|
|
38
|
-
|
|
51
|
+
agentId,
|
|
39
52
|
});
|
|
40
53
|
|
|
41
54
|
if (result === null) {
|
|
@@ -44,14 +57,38 @@ export async function handleIntelligenceConnect({
|
|
|
44
57
|
});
|
|
45
58
|
}
|
|
46
59
|
|
|
47
|
-
return Response.json(
|
|
48
|
-
|
|
49
|
-
|
|
60
|
+
return Response.json(
|
|
61
|
+
{
|
|
62
|
+
threadId: result.threadId,
|
|
63
|
+
joinToken: result.joinToken,
|
|
64
|
+
realtime: buildRealtimeConnectionInfo({
|
|
65
|
+
clientUrl: runtime.intelligence.ɵgetClientWsUrl(),
|
|
66
|
+
threadId: result.threadId,
|
|
67
|
+
}),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
headers: { "Cache-Control": "no-cache", Connection: "keep-alive" },
|
|
71
|
+
},
|
|
72
|
+
);
|
|
50
73
|
} catch (error) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
74
|
+
const status = getPlatformErrorStatus(error);
|
|
75
|
+
if (
|
|
76
|
+
status === 400 ||
|
|
77
|
+
status === 401 ||
|
|
78
|
+
status === 403 ||
|
|
79
|
+
status === 404 ||
|
|
80
|
+
status === 409
|
|
81
|
+
) {
|
|
82
|
+
return Response.json(
|
|
83
|
+
{
|
|
84
|
+
error: "Connect request rejected",
|
|
85
|
+
message:
|
|
86
|
+
error instanceof Error
|
|
87
|
+
? error.message
|
|
88
|
+
: "Intelligence platform rejected the connect request",
|
|
89
|
+
},
|
|
90
|
+
{ status },
|
|
91
|
+
);
|
|
55
92
|
}
|
|
56
93
|
|
|
57
94
|
console.error("Connect plan not available:", error);
|
|
@@ -1,10 +1,53 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AbstractAgent,
|
|
3
|
+
BaseEvent,
|
|
4
|
+
EventType,
|
|
5
|
+
Message,
|
|
6
|
+
RunAgentInput,
|
|
7
|
+
} from "@ag-ui/client";
|
|
2
8
|
import { CopilotIntelligenceRuntimeLike } from "../../core/runtime";
|
|
3
9
|
import { generateThreadNameForNewThread } from "./thread-names";
|
|
4
10
|
import { logger } from "@copilotkit/shared";
|
|
5
11
|
import { telemetry } from "../../telemetry";
|
|
6
12
|
import { resolveIntelligenceUser } from "../shared/resolve-intelligence-user";
|
|
7
13
|
import { isHandlerResponse } from "../shared/json-response";
|
|
14
|
+
import { AgentRunnerRunRequest } from "../../runner/agent-runner";
|
|
15
|
+
import { Observable } from "rxjs";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Builds browser-facing realtime connection metadata owned by the runtime.
|
|
19
|
+
*/
|
|
20
|
+
function buildRealtimeConnectionInfo(params: {
|
|
21
|
+
clientUrl: string;
|
|
22
|
+
threadId: string;
|
|
23
|
+
}): { clientUrl: string; topic: string } {
|
|
24
|
+
return {
|
|
25
|
+
clientUrl: params.clientUrl,
|
|
26
|
+
topic: `thread:${params.threadId}`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface RunnerStartupBoundary {
|
|
31
|
+
events: Observable<BaseEvent>;
|
|
32
|
+
startup: Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface RunnerWithStartupBoundary {
|
|
36
|
+
runWithStartupBoundary(request: AgentRunnerRunRequest): RunnerStartupBoundary;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function hasRunnerStartupBoundary(
|
|
40
|
+
runner: CopilotIntelligenceRuntimeLike["runner"],
|
|
41
|
+
): runner is CopilotIntelligenceRuntimeLike["runner"] &
|
|
42
|
+
RunnerWithStartupBoundary {
|
|
43
|
+
const candidate = runner as { runWithStartupBoundary?: unknown };
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
typeof candidate.runWithStartupBoundary === "function" &&
|
|
47
|
+
(Object.prototype.hasOwnProperty.call(runner, "runWithStartupBoundary") ||
|
|
48
|
+
Object.prototype.hasOwnProperty.call(runner, "threads"))
|
|
49
|
+
);
|
|
50
|
+
}
|
|
8
51
|
|
|
9
52
|
interface HandleIntelligenceRunParams {
|
|
10
53
|
runtime: CopilotIntelligenceRuntimeLike;
|
|
@@ -66,20 +109,23 @@ export async function handleIntelligenceRun({
|
|
|
66
109
|
);
|
|
67
110
|
}
|
|
68
111
|
|
|
69
|
-
let
|
|
112
|
+
let canonicalThreadId = input.threadId;
|
|
113
|
+
let canonicalRunId = input.runId;
|
|
70
114
|
let joinToken: string | undefined;
|
|
71
115
|
try {
|
|
72
116
|
const lockResult = await runtime.intelligence.ɵacquireThreadLock({
|
|
73
117
|
threadId: input.threadId,
|
|
74
118
|
runId: input.runId,
|
|
75
119
|
userId,
|
|
120
|
+
agentId,
|
|
76
121
|
...(runtime.lockKeyPrefix !== undefined
|
|
77
122
|
? { lockKeyPrefix: runtime.lockKeyPrefix }
|
|
78
123
|
: {}),
|
|
79
124
|
ttlSeconds: runtime.lockTtlSeconds,
|
|
80
125
|
});
|
|
126
|
+
canonicalThreadId = lockResult.threadId;
|
|
127
|
+
canonicalRunId = lockResult.runId;
|
|
81
128
|
joinToken = lockResult.joinToken;
|
|
82
|
-
joinCode = lockResult.joinCode;
|
|
83
129
|
} catch (error) {
|
|
84
130
|
logger.error("Thread lock denied:", error);
|
|
85
131
|
return Response.json(
|
|
@@ -90,21 +136,42 @@ export async function handleIntelligenceRun({
|
|
|
90
136
|
);
|
|
91
137
|
}
|
|
92
138
|
|
|
93
|
-
|
|
139
|
+
const cleanupLock = (reason: string): Promise<void> =>
|
|
140
|
+
runtime.intelligence
|
|
141
|
+
.ɵcleanupThreadLock({
|
|
142
|
+
threadId: canonicalThreadId || input.threadId,
|
|
143
|
+
runId: canonicalRunId || input.runId,
|
|
144
|
+
})
|
|
145
|
+
.catch((cleanupError) => {
|
|
146
|
+
logger.error(
|
|
147
|
+
{ err: cleanupError, reason },
|
|
148
|
+
"Failed to cleanup thread lock",
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (!canonicalThreadId || !canonicalRunId || !joinToken) {
|
|
153
|
+
await cleanupLock("malformed-lock-response");
|
|
94
154
|
return Response.json(
|
|
95
155
|
{
|
|
96
|
-
error: "
|
|
97
|
-
message:
|
|
156
|
+
error: "Run connection credentials not available",
|
|
157
|
+
message:
|
|
158
|
+
"Intelligence platform did not return canonical threadId, runId, and joinToken",
|
|
98
159
|
},
|
|
99
160
|
{ status: 502 },
|
|
100
161
|
);
|
|
101
162
|
}
|
|
102
163
|
|
|
164
|
+
const canonicalInput: RunAgentInput = {
|
|
165
|
+
...input,
|
|
166
|
+
threadId: canonicalThreadId,
|
|
167
|
+
runId: canonicalRunId,
|
|
168
|
+
};
|
|
169
|
+
|
|
103
170
|
let persistedInputMessages: Message[] | undefined;
|
|
104
171
|
if (Array.isArray(input.messages)) {
|
|
105
172
|
try {
|
|
106
173
|
const history = await runtime.intelligence.getThreadMessages({
|
|
107
|
-
threadId:
|
|
174
|
+
threadId: canonicalThreadId,
|
|
108
175
|
});
|
|
109
176
|
const historicMessageIds = new Set(
|
|
110
177
|
history.messages.map((message) => message.id),
|
|
@@ -114,6 +181,7 @@ export async function handleIntelligenceRun({
|
|
|
114
181
|
);
|
|
115
182
|
} catch (error) {
|
|
116
183
|
logger.error("Thread history lookup failed:", error);
|
|
184
|
+
await cleanupLock("thread-history-lookup-failed");
|
|
117
185
|
return Response.json(
|
|
118
186
|
{
|
|
119
187
|
error: "Thread history lookup failed",
|
|
@@ -130,8 +198,8 @@ export async function handleIntelligenceRun({
|
|
|
130
198
|
heartbeatTimer = setInterval(() => {
|
|
131
199
|
runtime.intelligence
|
|
132
200
|
.ɵrenewThreadLock({
|
|
133
|
-
threadId:
|
|
134
|
-
runId:
|
|
201
|
+
threadId: canonicalThreadId,
|
|
202
|
+
runId: canonicalRunId,
|
|
135
203
|
ttlSeconds: runtime.lockTtlSeconds,
|
|
136
204
|
...(runtime.lockKeyPrefix !== undefined
|
|
137
205
|
? { lockKeyPrefix: runtime.lockKeyPrefix }
|
|
@@ -139,6 +207,15 @@ export async function handleIntelligenceRun({
|
|
|
139
207
|
})
|
|
140
208
|
.catch((err) => {
|
|
141
209
|
logger.error("Failed to renew thread lock:", err);
|
|
210
|
+
clearHeartbeat();
|
|
211
|
+
try {
|
|
212
|
+
agent.abortRun();
|
|
213
|
+
} catch (abortError) {
|
|
214
|
+
logger.error(
|
|
215
|
+
"Failed to abort agent after lock renewal failure:",
|
|
216
|
+
abortError,
|
|
217
|
+
);
|
|
218
|
+
}
|
|
142
219
|
});
|
|
143
220
|
}, runtime.lockHeartbeatIntervalSeconds * 1_000);
|
|
144
221
|
|
|
@@ -149,19 +226,48 @@ export async function handleIntelligenceRun({
|
|
|
149
226
|
}
|
|
150
227
|
};
|
|
151
228
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
229
|
+
const runStarted = { current: false };
|
|
230
|
+
let immediateStartupErrorMessage: string | undefined;
|
|
231
|
+
let immediateStartupCleanup: Promise<void> | undefined;
|
|
232
|
+
|
|
233
|
+
const runRequest: AgentRunnerRunRequest = {
|
|
234
|
+
threadId: canonicalThreadId,
|
|
235
|
+
agent,
|
|
236
|
+
input: canonicalInput,
|
|
237
|
+
...(persistedInputMessages !== undefined ? { persistedInputMessages } : {}),
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
const runStart = hasRunnerStartupBoundary(runtime.runner)
|
|
242
|
+
? runtime.runner.runWithStartupBoundary(runRequest)
|
|
243
|
+
: {
|
|
244
|
+
events: runtime.runner.run(runRequest),
|
|
245
|
+
startup: Promise.resolve(),
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
runStart.events.subscribe({
|
|
249
|
+
next: (event: BaseEvent) => {
|
|
250
|
+
if (event.type === EventType.RUN_STARTED) {
|
|
251
|
+
runStarted.current = true;
|
|
252
|
+
}
|
|
253
|
+
if (event.type === EventType.RUN_ERROR && !runStarted.current) {
|
|
254
|
+
clearHeartbeat();
|
|
255
|
+
immediateStartupErrorMessage =
|
|
256
|
+
"message" in event && typeof event.message === "string"
|
|
257
|
+
? event.message
|
|
258
|
+
: "Runner failed before the run started";
|
|
259
|
+
immediateStartupCleanup = cleanupLock("runner-start-failed");
|
|
260
|
+
}
|
|
261
|
+
},
|
|
163
262
|
error: (error) => {
|
|
164
263
|
clearHeartbeat();
|
|
264
|
+
if (!runStarted.current) {
|
|
265
|
+
immediateStartupErrorMessage =
|
|
266
|
+
error instanceof Error ? error.message : String(error);
|
|
267
|
+
immediateStartupCleanup = cleanupLock("runner-start-error");
|
|
268
|
+
} else {
|
|
269
|
+
cleanupLock("runner-error");
|
|
270
|
+
}
|
|
165
271
|
telemetry.capture("oss.runtime.agent_execution_stream_errored", {
|
|
166
272
|
error: error instanceof Error ? error.message : String(error),
|
|
167
273
|
});
|
|
@@ -173,8 +279,43 @@ export async function handleIntelligenceRun({
|
|
|
173
279
|
},
|
|
174
280
|
});
|
|
175
281
|
|
|
282
|
+
await runStart.startup;
|
|
283
|
+
} catch (error) {
|
|
284
|
+
clearHeartbeat();
|
|
285
|
+
await (immediateStartupCleanup ?? cleanupLock("runner-start-threw"));
|
|
286
|
+
logger.error("Error starting agent runner:", error);
|
|
287
|
+
return Response.json(
|
|
288
|
+
{
|
|
289
|
+
error: "Failed to start runner",
|
|
290
|
+
message: error instanceof Error ? error.message : String(error),
|
|
291
|
+
},
|
|
292
|
+
{ status: 502 },
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (immediateStartupErrorMessage) {
|
|
297
|
+
await immediateStartupCleanup;
|
|
298
|
+
return Response.json(
|
|
299
|
+
{
|
|
300
|
+
error: "Failed to start runner",
|
|
301
|
+
message: immediateStartupErrorMessage,
|
|
302
|
+
},
|
|
303
|
+
{ status: 502 },
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// IntelligenceAgentRunner resolves this boundary after Phoenix channel join.
|
|
308
|
+
// Other runner implementations fall back to construction/subscription errors.
|
|
176
309
|
return Response.json(
|
|
177
|
-
{
|
|
310
|
+
{
|
|
311
|
+
threadId: canonicalThreadId,
|
|
312
|
+
runId: canonicalRunId,
|
|
313
|
+
joinToken,
|
|
314
|
+
realtime: buildRealtimeConnectionInfo({
|
|
315
|
+
clientUrl: runtime.intelligence.ɵgetClientWsUrl(),
|
|
316
|
+
threadId: canonicalThreadId,
|
|
317
|
+
}),
|
|
318
|
+
},
|
|
178
319
|
{
|
|
179
320
|
headers: { "Cache-Control": "no-cache" },
|
|
180
321
|
},
|