@copilotkit/runtime 1.62.2-canary.1783457132 → 1.62.3
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/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/v2/index.cjs +1 -5
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/index.mjs +2 -2
- package/dist/v2/runtime/core/fetch-handler.cjs +24 -1
- 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 +24 -1
- package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -1
- package/dist/v2/runtime/core/fetch-router.cjs +8 -0
- package/dist/v2/runtime/core/fetch-router.cjs.map +1 -1
- package/dist/v2/runtime/core/fetch-router.mjs +8 -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 +3 -0
- package/dist/v2/runtime/core/hooks.d.cts.map +1 -1
- package/dist/v2/runtime/core/hooks.d.mts +3 -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/endpoints/single-route-helpers.cjs +1 -0
- package/dist/v2/runtime/endpoints/single-route-helpers.cjs.map +1 -1
- package/dist/v2/runtime/endpoints/single-route-helpers.mjs +1 -0
- package/dist/v2/runtime/endpoints/single-route-helpers.mjs.map +1 -1
- package/dist/v2/runtime/handlers/get-runtime-info.cjs +1 -0
- package/dist/v2/runtime/handlers/get-runtime-info.cjs.map +1 -1
- package/dist/v2/runtime/handlers/get-runtime-info.mjs +1 -0
- package/dist/v2/runtime/handlers/get-runtime-info.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-suggest.cjs +83 -0
- package/dist/v2/runtime/handlers/handle-suggest.cjs.map +1 -0
- package/dist/v2/runtime/handlers/handle-suggest.mjs +82 -0
- package/dist/v2/runtime/handlers/handle-suggest.mjs.map +1 -0
- package/dist/v2/runtime/handlers/shared/sse-response.cjs +4 -4
- package/dist/v2/runtime/handlers/shared/sse-response.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/sse-response.mjs +4 -4
- package/dist/v2/runtime/handlers/shared/sse-response.mjs.map +1 -1
- package/dist/v2/runtime/index.d.cts +1 -1
- package/dist/v2/runtime/index.d.mts +1 -1
- package/dist/v2/runtime/runner/in-memory.cjs +37 -221
- package/dist/v2/runtime/runner/in-memory.cjs.map +1 -1
- package/dist/v2/runtime/runner/in-memory.d.cts +3 -164
- package/dist/v2/runtime/runner/in-memory.d.cts.map +1 -1
- package/dist/v2/runtime/runner/in-memory.d.mts +3 -164
- package/dist/v2/runtime/runner/in-memory.d.mts.map +1 -1
- package/dist/v2/runtime/runner/in-memory.mjs +38 -218
- package/dist/v2/runtime/runner/in-memory.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/index.mjs +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse-response.cjs","names":["EventEncoder","createLogger"],"sources":["../../../../../src/v2/runtime/handlers/shared/sse-response.ts"],"sourcesContent":["import { BaseEvent } from \"@ag-ui/client\";\nimport { EventEncoder } from \"@ag-ui/encoder\";\nimport { Observable, Subscription } from \"rxjs\";\nimport { ResolvedDebugConfig } from \"@copilotkit/shared\";\nimport {\n createLogger,\n type CopilotRuntimeLogger,\n} from \"../../../../lib/logger\";\nimport { telemetry } from \"../../telemetry\";\nimport { DebugEventBus } from \"../../core/debug-event-bus\";\n\ninterface CreateSseEventResponseParams {\n request: Request;\n observableFactory: () =>\n | Promise<Observable<BaseEvent>>\n | Observable<BaseEvent>;\n debugEventBus?: DebugEventBus;\n agentId?: string;\n debug?: ResolvedDebugConfig;\n /** Pre-created logger instance to avoid creating a new pino logger per request. */\n logger?: CopilotRuntimeLogger;\n}\n\nexport function createSseEventResponse({\n request,\n observableFactory,\n debugEventBus,\n agentId,\n debug,\n logger,\n}: CreateSseEventResponseParams): Response {\n const stream = new TransformStream();\n const writer = stream.writable.getWriter();\n const encoder = new EventEncoder();\n let streamClosed = false;\n let debugThreadId = \"\";\n let debugRunId = \"\";\n\n const debugLogger = debug?.enabled\n ? (logger ??\n createLogger({ level: \"debug\", component: \"copilotkit-debug\" }))\n : undefined;\n\n const closeStream = async () => {\n if (!streamClosed) {\n try {\n await writer.close();\n streamClosed = true;\n } catch {\n // Stream already closed.\n }\n }\n };\n\n const logError = (error: unknown) => {\n console.error(\"Error running agent:\", error);\n console.error(\n \"Error stack:\",\n error instanceof Error ? error.stack : \"No stack trace\",\n );\n console.error(\"Error details:\", {\n name: error instanceof Error ? error.name : \"Unknown\",\n message: error instanceof Error ? error.message : String(error),\n cause: error instanceof Error ? error.cause : undefined,\n });\n };\n\n let subscription: Subscription | undefined;\n\n (async () => {\n const observable = await observableFactory();\n\n telemetry.capture(\"oss.runtime.agent_execution_stream_started\", {});\n\n if (debug?.lifecycle) {\n debugLogger!.debug(\"SSE stream opened\");\n }\n\n let eventCount = 0;\n let loggedEventCount = 0;\n\n subscription = observable.subscribe({\n next: async (event) => {\n // Extract threadId/runId from RUN_STARTED\n if (event.type === \"RUN_STARTED\") {\n const e = event as { threadId?: string; runId?: string };\n debugThreadId = e.threadId ?? \"\";\n debugRunId = e.runId ?? \"\";\n }\n\n // Broadcast to debug listeners BEFORE the stream-closed gate below.\n // Intentional: debug subscribers (e.g. the VS Code Inspector panel)\n // should still receive trailing events after the SSE client for\n // this request closed its connection — they're independent\n // consumers observing the underlying runtime, not the request's\n // response stream.\n //\n // Wrapped in try/catch so a buggy debug subscriber can't propagate\n // an exception into this observer — if the throw reached the\n // `next` callback it would get routed to `error` by RxJS, closing\n // the SSE stream for an unrelated reason. Log via `logError` and\n // move on.\n if (debugEventBus) {\n try {\n debugEventBus.broadcast(event, {\n agentId: agentId ?? \"\",\n threadId: debugThreadId,\n runId: debugRunId,\n });\n } catch (broadcastError) {\n logError(broadcastError);\n }\n }\n\n if (!request.signal.aborted && !streamClosed) {\n try {\n eventCount++;\n if (debug?.events) {\n loggedEventCount++;\n if (debug.verbose) {\n debugLogger!.debug({ event }, \"Event emitted\");\n } else {\n debugLogger!.debug(\n { type: event.type, ...summarizeEvent(event) },\n \"Event emitted\",\n );\n }\n }\n await writer.write(encoder.encode(event));\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n streamClosed = true;\n } else {\n // Non-abort write failures (backpressure disconnects,\n // transform-stream exceptions, …) were previously swallowed\n // silently — `streamClosed` stayed `false` and the next\n // event re-attempted a broken writer. Log and mark the\n // stream closed so we stop trying.\n logError(error);\n streamClosed = true;\n }\n }\n }\n },\n error: async (error) => {\n telemetry.capture(\"oss.runtime.agent_execution_stream_errored\", {\n error: error instanceof Error ? error.message : String(error),\n });\n if (debug?.lifecycle) {\n debugLogger!.debug(\n { error: error instanceof Error ? error.message : String(error) },\n \"SSE stream errored\",\n );\n }\n logError(error);\n await closeStream();\n },\n complete: async () => {\n telemetry.capture(\"oss.runtime.agent_execution_stream_ended\", {});\n if (debug?.lifecycle) {\n debugLogger!.debug(\n { eventCount, loggedEventCount },\n \"SSE stream completed\",\n );\n }\n await closeStream();\n },\n });\n\n // If the client disconnected before the subscription was created,\n // unsubscribe immediately to avoid leaking the observable.\n if (request.signal.aborted) {\n subscription.unsubscribe();\n }\n })().catch(async (error) => {\n logError(error);\n await closeStream();\n });\n\n request.signal.addEventListener(\"abort\", () => {\n subscription?.unsubscribe();\n });\n\n return new Response(stream.readable, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n}\n\nfunction summarizeEvent(event: BaseEvent): Record<string, unknown> {\n const e = event as any;\n const summary: Record<string, unknown> = {};\n\n if (e.messageId) summary.messageId = e.messageId;\n if (e.toolCallId) summary.toolCallId = e.toolCallId;\n if (e.toolCallName) summary.toolCallName = e.toolCallName;\n if (e.role) summary.role = e.role;\n if (e.delta != null && typeof e.delta === \"string\")\n summary.deltaLength = e.delta.length;\n if (e.snapshot && typeof e.snapshot === \"object\")\n summary.snapshotKeys = Object.keys(e.snapshot);\n if (e.delta && Array.isArray(e.delta))\n summary.operationCount = e.delta.length;\n if (e.threadId) summary.threadId = e.threadId;\n if (e.runId) summary.runId = e.runId;\n if (e.message) summary.message = e.message;\n if (e.code) summary.code = e.code;\n if (e.stepName) summary.stepName = e.stepName;\n\n return summary;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sse-response.cjs","names":["EventEncoder","createLogger"],"sources":["../../../../../src/v2/runtime/handlers/shared/sse-response.ts"],"sourcesContent":["import type { BaseEvent } from \"@ag-ui/client\";\nimport { EventEncoder } from \"@ag-ui/encoder\";\nimport type { Observable, Subscription } from \"rxjs\";\nimport type { ResolvedDebugConfig } from \"@copilotkit/shared\";\nimport { createLogger } from \"../../../../lib/logger\";\nimport type { CopilotRuntimeLogger } from \"../../../../lib/logger\";\nimport { telemetry } from \"../../telemetry\";\nimport type { DebugEventBus } from \"../../core/debug-event-bus\";\n\ninterface CreateSseEventResponseParams {\n request: Request;\n observableFactory: () =>\n | Promise<Observable<BaseEvent>>\n | Observable<BaseEvent>;\n debugEventBus?: DebugEventBus;\n agentId?: string;\n debug?: ResolvedDebugConfig;\n /** Pre-created logger instance to avoid creating a new pino logger per request. */\n logger?: CopilotRuntimeLogger;\n /**\n * Whether to emit `oss.runtime.agent_execution_stream_*` telemetry for this\n * stream. Defaults to `true`. The stateless `/suggest` path sets this to\n * `false`: a suggestion is a side-effect-free structured completion, not a\n * tracked run, and under `available: \"always\"` it fires often enough to flood\n * run telemetry.\n */\n captureTelemetry?: boolean;\n}\n\nexport function createSseEventResponse({\n request,\n observableFactory,\n debugEventBus,\n agentId,\n debug,\n logger,\n captureTelemetry = true,\n}: CreateSseEventResponseParams): Response {\n const stream = new TransformStream();\n const writer = stream.writable.getWriter();\n const encoder = new EventEncoder();\n let streamClosed = false;\n let debugThreadId = \"\";\n let debugRunId = \"\";\n\n const debugLogger = debug?.enabled\n ? (logger ??\n createLogger({ level: \"debug\", component: \"copilotkit-debug\" }))\n : undefined;\n\n const closeStream = async () => {\n if (!streamClosed) {\n try {\n await writer.close();\n streamClosed = true;\n } catch {\n // Stream already closed.\n }\n }\n };\n\n const logError = (error: unknown) => {\n console.error(\"Error running agent:\", error);\n console.error(\n \"Error stack:\",\n error instanceof Error ? error.stack : \"No stack trace\",\n );\n console.error(\"Error details:\", {\n name: error instanceof Error ? error.name : \"Unknown\",\n message: error instanceof Error ? error.message : String(error),\n cause: error instanceof Error ? error.cause : undefined,\n });\n };\n\n let subscription: Subscription | undefined;\n\n (async () => {\n const observable = await observableFactory();\n\n if (captureTelemetry) {\n telemetry.capture(\"oss.runtime.agent_execution_stream_started\", {});\n }\n\n if (debug?.lifecycle) {\n debugLogger!.debug(\"SSE stream opened\");\n }\n\n let eventCount = 0;\n let loggedEventCount = 0;\n\n subscription = observable.subscribe({\n next: async (event) => {\n // Extract threadId/runId from RUN_STARTED\n if (event.type === \"RUN_STARTED\") {\n const e = event as { threadId?: string; runId?: string };\n debugThreadId = e.threadId ?? \"\";\n debugRunId = e.runId ?? \"\";\n }\n\n // Broadcast to debug listeners BEFORE the stream-closed gate below.\n // Intentional: debug subscribers (e.g. the VS Code Inspector panel)\n // should still receive trailing events after the SSE client for\n // this request closed its connection — they're independent\n // consumers observing the underlying runtime, not the request's\n // response stream.\n //\n // Wrapped in try/catch so a buggy debug subscriber can't propagate\n // an exception into this observer — if the throw reached the\n // `next` callback it would get routed to `error` by RxJS, closing\n // the SSE stream for an unrelated reason. Log via `logError` and\n // move on.\n if (debugEventBus) {\n try {\n debugEventBus.broadcast(event, {\n agentId: agentId ?? \"\",\n threadId: debugThreadId,\n runId: debugRunId,\n });\n } catch (broadcastError) {\n logError(broadcastError);\n }\n }\n\n if (!request.signal.aborted && !streamClosed) {\n try {\n eventCount++;\n if (debug?.events) {\n loggedEventCount++;\n if (debug.verbose) {\n debugLogger!.debug({ event }, \"Event emitted\");\n } else {\n debugLogger!.debug(\n { type: event.type, ...summarizeEvent(event) },\n \"Event emitted\",\n );\n }\n }\n await writer.write(encoder.encode(event));\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n streamClosed = true;\n } else {\n // Non-abort write failures (backpressure disconnects,\n // transform-stream exceptions, …) were previously swallowed\n // silently — `streamClosed` stayed `false` and the next\n // event re-attempted a broken writer. Log and mark the\n // stream closed so we stop trying.\n logError(error);\n streamClosed = true;\n }\n }\n }\n },\n error: async (error) => {\n if (captureTelemetry) {\n telemetry.capture(\"oss.runtime.agent_execution_stream_errored\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n if (debug?.lifecycle) {\n debugLogger!.debug(\n { error: error instanceof Error ? error.message : String(error) },\n \"SSE stream errored\",\n );\n }\n logError(error);\n await closeStream();\n },\n complete: async () => {\n if (captureTelemetry) {\n telemetry.capture(\"oss.runtime.agent_execution_stream_ended\", {});\n }\n if (debug?.lifecycle) {\n debugLogger!.debug(\n { eventCount, loggedEventCount },\n \"SSE stream completed\",\n );\n }\n await closeStream();\n },\n });\n\n // If the client disconnected before the subscription was created,\n // unsubscribe immediately to avoid leaking the observable.\n if (request.signal.aborted) {\n subscription.unsubscribe();\n }\n })().catch(async (error) => {\n logError(error);\n await closeStream();\n });\n\n request.signal.addEventListener(\"abort\", () => {\n subscription?.unsubscribe();\n });\n\n return new Response(stream.readable, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n}\n\nfunction summarizeEvent(event: BaseEvent): Record<string, unknown> {\n const e = event as any;\n const summary: Record<string, unknown> = {};\n\n if (e.messageId) summary.messageId = e.messageId;\n if (e.toolCallId) summary.toolCallId = e.toolCallId;\n if (e.toolCallName) summary.toolCallName = e.toolCallName;\n if (e.role) summary.role = e.role;\n if (e.delta != null && typeof e.delta === \"string\")\n summary.deltaLength = e.delta.length;\n if (e.snapshot && typeof e.snapshot === \"object\")\n summary.snapshotKeys = Object.keys(e.snapshot);\n if (e.delta && Array.isArray(e.delta))\n summary.operationCount = e.delta.length;\n if (e.threadId) summary.threadId = e.threadId;\n if (e.runId) summary.runId = e.runId;\n if (e.message) summary.message = e.message;\n if (e.code) summary.code = e.code;\n if (e.stepName) summary.stepName = e.stepName;\n\n return summary;\n}\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import telemetry from "../../telemetry/telemetry-client.mjs";
|
|
|
4
4
|
import { EventEncoder } from "@ag-ui/encoder";
|
|
5
5
|
|
|
6
6
|
//#region src/v2/runtime/handlers/shared/sse-response.ts
|
|
7
|
-
function createSseEventResponse({ request, observableFactory, debugEventBus, agentId, debug, logger }) {
|
|
7
|
+
function createSseEventResponse({ request, observableFactory, debugEventBus, agentId, debug, logger, captureTelemetry = true }) {
|
|
8
8
|
const stream = new TransformStream();
|
|
9
9
|
const writer = stream.writable.getWriter();
|
|
10
10
|
const encoder = new EventEncoder();
|
|
@@ -33,7 +33,7 @@ function createSseEventResponse({ request, observableFactory, debugEventBus, age
|
|
|
33
33
|
let subscription;
|
|
34
34
|
(async () => {
|
|
35
35
|
const observable = await observableFactory();
|
|
36
|
-
telemetry.capture("oss.runtime.agent_execution_stream_started", {});
|
|
36
|
+
if (captureTelemetry) telemetry.capture("oss.runtime.agent_execution_stream_started", {});
|
|
37
37
|
if (debug?.lifecycle) debugLogger.debug("SSE stream opened");
|
|
38
38
|
let eventCount = 0;
|
|
39
39
|
let loggedEventCount = 0;
|
|
@@ -73,13 +73,13 @@ function createSseEventResponse({ request, observableFactory, debugEventBus, age
|
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
error: async (error) => {
|
|
76
|
-
telemetry.capture("oss.runtime.agent_execution_stream_errored", { error: error instanceof Error ? error.message : String(error) });
|
|
76
|
+
if (captureTelemetry) telemetry.capture("oss.runtime.agent_execution_stream_errored", { error: error instanceof Error ? error.message : String(error) });
|
|
77
77
|
if (debug?.lifecycle) debugLogger.debug({ error: error instanceof Error ? error.message : String(error) }, "SSE stream errored");
|
|
78
78
|
logError(error);
|
|
79
79
|
await closeStream();
|
|
80
80
|
},
|
|
81
81
|
complete: async () => {
|
|
82
|
-
telemetry.capture("oss.runtime.agent_execution_stream_ended", {});
|
|
82
|
+
if (captureTelemetry) telemetry.capture("oss.runtime.agent_execution_stream_ended", {});
|
|
83
83
|
if (debug?.lifecycle) debugLogger.debug({
|
|
84
84
|
eventCount,
|
|
85
85
|
loggedEventCount
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse-response.mjs","names":[],"sources":["../../../../../src/v2/runtime/handlers/shared/sse-response.ts"],"sourcesContent":["import { BaseEvent } from \"@ag-ui/client\";\nimport { EventEncoder } from \"@ag-ui/encoder\";\nimport { Observable, Subscription } from \"rxjs\";\nimport { ResolvedDebugConfig } from \"@copilotkit/shared\";\nimport {\n createLogger,\n type CopilotRuntimeLogger,\n} from \"../../../../lib/logger\";\nimport { telemetry } from \"../../telemetry\";\nimport { DebugEventBus } from \"../../core/debug-event-bus\";\n\ninterface CreateSseEventResponseParams {\n request: Request;\n observableFactory: () =>\n | Promise<Observable<BaseEvent>>\n | Observable<BaseEvent>;\n debugEventBus?: DebugEventBus;\n agentId?: string;\n debug?: ResolvedDebugConfig;\n /** Pre-created logger instance to avoid creating a new pino logger per request. */\n logger?: CopilotRuntimeLogger;\n}\n\nexport function createSseEventResponse({\n request,\n observableFactory,\n debugEventBus,\n agentId,\n debug,\n logger,\n}: CreateSseEventResponseParams): Response {\n const stream = new TransformStream();\n const writer = stream.writable.getWriter();\n const encoder = new EventEncoder();\n let streamClosed = false;\n let debugThreadId = \"\";\n let debugRunId = \"\";\n\n const debugLogger = debug?.enabled\n ? (logger ??\n createLogger({ level: \"debug\", component: \"copilotkit-debug\" }))\n : undefined;\n\n const closeStream = async () => {\n if (!streamClosed) {\n try {\n await writer.close();\n streamClosed = true;\n } catch {\n // Stream already closed.\n }\n }\n };\n\n const logError = (error: unknown) => {\n console.error(\"Error running agent:\", error);\n console.error(\n \"Error stack:\",\n error instanceof Error ? error.stack : \"No stack trace\",\n );\n console.error(\"Error details:\", {\n name: error instanceof Error ? error.name : \"Unknown\",\n message: error instanceof Error ? error.message : String(error),\n cause: error instanceof Error ? error.cause : undefined,\n });\n };\n\n let subscription: Subscription | undefined;\n\n (async () => {\n const observable = await observableFactory();\n\n telemetry.capture(\"oss.runtime.agent_execution_stream_started\", {});\n\n if (debug?.lifecycle) {\n debugLogger!.debug(\"SSE stream opened\");\n }\n\n let eventCount = 0;\n let loggedEventCount = 0;\n\n subscription = observable.subscribe({\n next: async (event) => {\n // Extract threadId/runId from RUN_STARTED\n if (event.type === \"RUN_STARTED\") {\n const e = event as { threadId?: string; runId?: string };\n debugThreadId = e.threadId ?? \"\";\n debugRunId = e.runId ?? \"\";\n }\n\n // Broadcast to debug listeners BEFORE the stream-closed gate below.\n // Intentional: debug subscribers (e.g. the VS Code Inspector panel)\n // should still receive trailing events after the SSE client for\n // this request closed its connection — they're independent\n // consumers observing the underlying runtime, not the request's\n // response stream.\n //\n // Wrapped in try/catch so a buggy debug subscriber can't propagate\n // an exception into this observer — if the throw reached the\n // `next` callback it would get routed to `error` by RxJS, closing\n // the SSE stream for an unrelated reason. Log via `logError` and\n // move on.\n if (debugEventBus) {\n try {\n debugEventBus.broadcast(event, {\n agentId: agentId ?? \"\",\n threadId: debugThreadId,\n runId: debugRunId,\n });\n } catch (broadcastError) {\n logError(broadcastError);\n }\n }\n\n if (!request.signal.aborted && !streamClosed) {\n try {\n eventCount++;\n if (debug?.events) {\n loggedEventCount++;\n if (debug.verbose) {\n debugLogger!.debug({ event }, \"Event emitted\");\n } else {\n debugLogger!.debug(\n { type: event.type, ...summarizeEvent(event) },\n \"Event emitted\",\n );\n }\n }\n await writer.write(encoder.encode(event));\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n streamClosed = true;\n } else {\n // Non-abort write failures (backpressure disconnects,\n // transform-stream exceptions, …) were previously swallowed\n // silently — `streamClosed` stayed `false` and the next\n // event re-attempted a broken writer. Log and mark the\n // stream closed so we stop trying.\n logError(error);\n streamClosed = true;\n }\n }\n }\n },\n error: async (error) => {\n telemetry.capture(\"oss.runtime.agent_execution_stream_errored\", {\n error: error instanceof Error ? error.message : String(error),\n });\n if (debug?.lifecycle) {\n debugLogger!.debug(\n { error: error instanceof Error ? error.message : String(error) },\n \"SSE stream errored\",\n );\n }\n logError(error);\n await closeStream();\n },\n complete: async () => {\n telemetry.capture(\"oss.runtime.agent_execution_stream_ended\", {});\n if (debug?.lifecycle) {\n debugLogger!.debug(\n { eventCount, loggedEventCount },\n \"SSE stream completed\",\n );\n }\n await closeStream();\n },\n });\n\n // If the client disconnected before the subscription was created,\n // unsubscribe immediately to avoid leaking the observable.\n if (request.signal.aborted) {\n subscription.unsubscribe();\n }\n })().catch(async (error) => {\n logError(error);\n await closeStream();\n });\n\n request.signal.addEventListener(\"abort\", () => {\n subscription?.unsubscribe();\n });\n\n return new Response(stream.readable, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n}\n\nfunction summarizeEvent(event: BaseEvent): Record<string, unknown> {\n const e = event as any;\n const summary: Record<string, unknown> = {};\n\n if (e.messageId) summary.messageId = e.messageId;\n if (e.toolCallId) summary.toolCallId = e.toolCallId;\n if (e.toolCallName) summary.toolCallName = e.toolCallName;\n if (e.role) summary.role = e.role;\n if (e.delta != null && typeof e.delta === \"string\")\n summary.deltaLength = e.delta.length;\n if (e.snapshot && typeof e.snapshot === \"object\")\n summary.snapshotKeys = Object.keys(e.snapshot);\n if (e.delta && Array.isArray(e.delta))\n summary.operationCount = e.delta.length;\n if (e.threadId) summary.threadId = e.threadId;\n if (e.runId) summary.runId = e.runId;\n if (e.message) summary.message = e.message;\n if (e.code) summary.code = e.code;\n if (e.stepName) summary.stepName = e.stepName;\n\n return summary;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sse-response.mjs","names":[],"sources":["../../../../../src/v2/runtime/handlers/shared/sse-response.ts"],"sourcesContent":["import type { BaseEvent } from \"@ag-ui/client\";\nimport { EventEncoder } from \"@ag-ui/encoder\";\nimport type { Observable, Subscription } from \"rxjs\";\nimport type { ResolvedDebugConfig } from \"@copilotkit/shared\";\nimport { createLogger } from \"../../../../lib/logger\";\nimport type { CopilotRuntimeLogger } from \"../../../../lib/logger\";\nimport { telemetry } from \"../../telemetry\";\nimport type { DebugEventBus } from \"../../core/debug-event-bus\";\n\ninterface CreateSseEventResponseParams {\n request: Request;\n observableFactory: () =>\n | Promise<Observable<BaseEvent>>\n | Observable<BaseEvent>;\n debugEventBus?: DebugEventBus;\n agentId?: string;\n debug?: ResolvedDebugConfig;\n /** Pre-created logger instance to avoid creating a new pino logger per request. */\n logger?: CopilotRuntimeLogger;\n /**\n * Whether to emit `oss.runtime.agent_execution_stream_*` telemetry for this\n * stream. Defaults to `true`. The stateless `/suggest` path sets this to\n * `false`: a suggestion is a side-effect-free structured completion, not a\n * tracked run, and under `available: \"always\"` it fires often enough to flood\n * run telemetry.\n */\n captureTelemetry?: boolean;\n}\n\nexport function createSseEventResponse({\n request,\n observableFactory,\n debugEventBus,\n agentId,\n debug,\n logger,\n captureTelemetry = true,\n}: CreateSseEventResponseParams): Response {\n const stream = new TransformStream();\n const writer = stream.writable.getWriter();\n const encoder = new EventEncoder();\n let streamClosed = false;\n let debugThreadId = \"\";\n let debugRunId = \"\";\n\n const debugLogger = debug?.enabled\n ? (logger ??\n createLogger({ level: \"debug\", component: \"copilotkit-debug\" }))\n : undefined;\n\n const closeStream = async () => {\n if (!streamClosed) {\n try {\n await writer.close();\n streamClosed = true;\n } catch {\n // Stream already closed.\n }\n }\n };\n\n const logError = (error: unknown) => {\n console.error(\"Error running agent:\", error);\n console.error(\n \"Error stack:\",\n error instanceof Error ? error.stack : \"No stack trace\",\n );\n console.error(\"Error details:\", {\n name: error instanceof Error ? error.name : \"Unknown\",\n message: error instanceof Error ? error.message : String(error),\n cause: error instanceof Error ? error.cause : undefined,\n });\n };\n\n let subscription: Subscription | undefined;\n\n (async () => {\n const observable = await observableFactory();\n\n if (captureTelemetry) {\n telemetry.capture(\"oss.runtime.agent_execution_stream_started\", {});\n }\n\n if (debug?.lifecycle) {\n debugLogger!.debug(\"SSE stream opened\");\n }\n\n let eventCount = 0;\n let loggedEventCount = 0;\n\n subscription = observable.subscribe({\n next: async (event) => {\n // Extract threadId/runId from RUN_STARTED\n if (event.type === \"RUN_STARTED\") {\n const e = event as { threadId?: string; runId?: string };\n debugThreadId = e.threadId ?? \"\";\n debugRunId = e.runId ?? \"\";\n }\n\n // Broadcast to debug listeners BEFORE the stream-closed gate below.\n // Intentional: debug subscribers (e.g. the VS Code Inspector panel)\n // should still receive trailing events after the SSE client for\n // this request closed its connection — they're independent\n // consumers observing the underlying runtime, not the request's\n // response stream.\n //\n // Wrapped in try/catch so a buggy debug subscriber can't propagate\n // an exception into this observer — if the throw reached the\n // `next` callback it would get routed to `error` by RxJS, closing\n // the SSE stream for an unrelated reason. Log via `logError` and\n // move on.\n if (debugEventBus) {\n try {\n debugEventBus.broadcast(event, {\n agentId: agentId ?? \"\",\n threadId: debugThreadId,\n runId: debugRunId,\n });\n } catch (broadcastError) {\n logError(broadcastError);\n }\n }\n\n if (!request.signal.aborted && !streamClosed) {\n try {\n eventCount++;\n if (debug?.events) {\n loggedEventCount++;\n if (debug.verbose) {\n debugLogger!.debug({ event }, \"Event emitted\");\n } else {\n debugLogger!.debug(\n { type: event.type, ...summarizeEvent(event) },\n \"Event emitted\",\n );\n }\n }\n await writer.write(encoder.encode(event));\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n streamClosed = true;\n } else {\n // Non-abort write failures (backpressure disconnects,\n // transform-stream exceptions, …) were previously swallowed\n // silently — `streamClosed` stayed `false` and the next\n // event re-attempted a broken writer. Log and mark the\n // stream closed so we stop trying.\n logError(error);\n streamClosed = true;\n }\n }\n }\n },\n error: async (error) => {\n if (captureTelemetry) {\n telemetry.capture(\"oss.runtime.agent_execution_stream_errored\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n if (debug?.lifecycle) {\n debugLogger!.debug(\n { error: error instanceof Error ? error.message : String(error) },\n \"SSE stream errored\",\n );\n }\n logError(error);\n await closeStream();\n },\n complete: async () => {\n if (captureTelemetry) {\n telemetry.capture(\"oss.runtime.agent_execution_stream_ended\", {});\n }\n if (debug?.lifecycle) {\n debugLogger!.debug(\n { eventCount, loggedEventCount },\n \"SSE stream completed\",\n );\n }\n await closeStream();\n },\n });\n\n // If the client disconnected before the subscription was created,\n // unsubscribe immediately to avoid leaking the observable.\n if (request.signal.aborted) {\n subscription.unsubscribe();\n }\n })().catch(async (error) => {\n logError(error);\n await closeStream();\n });\n\n request.signal.addEventListener(\"abort\", () => {\n subscription?.unsubscribe();\n });\n\n return new Response(stream.readable, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n}\n\nfunction summarizeEvent(event: BaseEvent): Record<string, unknown> {\n const e = event as any;\n const summary: Record<string, unknown> = {};\n\n if (e.messageId) summary.messageId = e.messageId;\n if (e.toolCallId) summary.toolCallId = e.toolCallId;\n if (e.toolCallName) summary.toolCallName = e.toolCallName;\n if (e.role) summary.role = e.role;\n if (e.delta != null && typeof e.delta === \"string\")\n summary.deltaLength = e.delta.length;\n if (e.snapshot && typeof e.snapshot === \"object\")\n summary.snapshotKeys = Object.keys(e.snapshot);\n if (e.delta && Array.isArray(e.delta))\n summary.operationCount = e.delta.length;\n if (e.threadId) summary.threadId = e.threadId;\n if (e.runId) summary.runId = e.runId;\n if (e.message) summary.message = e.message;\n if (e.code) summary.code = e.code;\n if (e.stepName) summary.stepName = e.stepName;\n\n return summary;\n}\n"],"mappings":";;;;;;AA6BA,SAAgB,uBAAuB,EACrC,SACA,mBACA,eACA,SACA,OACA,QACA,mBAAmB,QACsB;CACzC,MAAM,SAAS,IAAI,iBAAiB;CACpC,MAAM,SAAS,OAAO,SAAS,WAAW;CAC1C,MAAM,UAAU,IAAI,cAAc;CAClC,IAAI,eAAe;CACnB,IAAI,gBAAgB;CACpB,IAAI,aAAa;CAEjB,MAAM,cAAc,OAAO,UACtB,UACD,aAAa;EAAE,OAAO;EAAS,WAAW;EAAoB,CAAC,GAC/D;CAEJ,MAAM,cAAc,YAAY;AAC9B,MAAI,CAAC,aACH,KAAI;AACF,SAAM,OAAO,OAAO;AACpB,kBAAe;UACT;;CAMZ,MAAM,YAAY,UAAmB;AACnC,UAAQ,MAAM,wBAAwB,MAAM;AAC5C,UAAQ,MACN,gBACA,iBAAiB,QAAQ,MAAM,QAAQ,iBACxC;AACD,UAAQ,MAAM,kBAAkB;GAC9B,MAAM,iBAAiB,QAAQ,MAAM,OAAO;GAC5C,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAC/D,OAAO,iBAAiB,QAAQ,MAAM,QAAQ;GAC/C,CAAC;;CAGJ,IAAI;AAEJ,EAAC,YAAY;EACX,MAAM,aAAa,MAAM,mBAAmB;AAE5C,MAAI,iBACF,WAAU,QAAQ,8CAA8C,EAAE,CAAC;AAGrE,MAAI,OAAO,UACT,aAAa,MAAM,oBAAoB;EAGzC,IAAI,aAAa;EACjB,IAAI,mBAAmB;AAEvB,iBAAe,WAAW,UAAU;GAClC,MAAM,OAAO,UAAU;AAErB,QAAI,MAAM,SAAS,eAAe;KAChC,MAAM,IAAI;AACV,qBAAgB,EAAE,YAAY;AAC9B,kBAAa,EAAE,SAAS;;AAe1B,QAAI,cACF,KAAI;AACF,mBAAc,UAAU,OAAO;MAC7B,SAAS,WAAW;MACpB,UAAU;MACV,OAAO;MACR,CAAC;aACK,gBAAgB;AACvB,cAAS,eAAe;;AAI5B,QAAI,CAAC,QAAQ,OAAO,WAAW,CAAC,aAC9B,KAAI;AACF;AACA,SAAI,OAAO,QAAQ;AACjB;AACA,UAAI,MAAM,QACR,aAAa,MAAM,EAAE,OAAO,EAAE,gBAAgB;UAE9C,aAAa,MACX;OAAE,MAAM,MAAM;OAAM,GAAG,eAAe,MAAM;OAAE,EAC9C,gBACD;;AAGL,WAAM,OAAO,MAAM,QAAQ,OAAO,MAAM,CAAC;aAClC,OAAO;AACd,SAAI,iBAAiB,SAAS,MAAM,SAAS,aAC3C,gBAAe;UACV;AAML,eAAS,MAAM;AACf,qBAAe;;;;GAKvB,OAAO,OAAO,UAAU;AACtB,QAAI,iBACF,WAAU,QAAQ,8CAA8C,EAC9D,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAC9D,CAAC;AAEJ,QAAI,OAAO,UACT,aAAa,MACX,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACjE,qBACD;AAEH,aAAS,MAAM;AACf,UAAM,aAAa;;GAErB,UAAU,YAAY;AACpB,QAAI,iBACF,WAAU,QAAQ,4CAA4C,EAAE,CAAC;AAEnE,QAAI,OAAO,UACT,aAAa,MACX;KAAE;KAAY;KAAkB,EAChC,uBACD;AAEH,UAAM,aAAa;;GAEtB,CAAC;AAIF,MAAI,QAAQ,OAAO,QACjB,cAAa,aAAa;KAE1B,CAAC,MAAM,OAAO,UAAU;AAC1B,WAAS,MAAM;AACf,QAAM,aAAa;GACnB;AAEF,SAAQ,OAAO,iBAAiB,eAAe;AAC7C,gBAAc,aAAa;GAC3B;AAEF,QAAO,IAAI,SAAS,OAAO,UAAU;EACnC,QAAQ;EACR,SAAS;GACP,gBAAgB;GAChB,iBAAiB;GACjB,YAAY;GACb;EACF,CAAC;;AAGJ,SAAS,eAAe,OAA2C;CACjE,MAAM,IAAI;CACV,MAAM,UAAmC,EAAE;AAE3C,KAAI,EAAE,UAAW,SAAQ,YAAY,EAAE;AACvC,KAAI,EAAE,WAAY,SAAQ,aAAa,EAAE;AACzC,KAAI,EAAE,aAAc,SAAQ,eAAe,EAAE;AAC7C,KAAI,EAAE,KAAM,SAAQ,OAAO,EAAE;AAC7B,KAAI,EAAE,SAAS,QAAQ,OAAO,EAAE,UAAU,SACxC,SAAQ,cAAc,EAAE,MAAM;AAChC,KAAI,EAAE,YAAY,OAAO,EAAE,aAAa,SACtC,SAAQ,eAAe,OAAO,KAAK,EAAE,SAAS;AAChD,KAAI,EAAE,SAAS,MAAM,QAAQ,EAAE,MAAM,CACnC,SAAQ,iBAAiB,EAAE,MAAM;AACnC,KAAI,EAAE,SAAU,SAAQ,WAAW,EAAE;AACrC,KAAI,EAAE,MAAO,SAAQ,QAAQ,EAAE;AAC/B,KAAI,EAAE,QAAS,SAAQ,UAAU,EAAE;AACnC,KAAI,EAAE,KAAM,SAAQ,OAAO,EAAE;AAC7B,KAAI,EAAE,SAAU,SAAQ,WAAW,EAAE;AAErC,QAAO"}
|
|
@@ -10,7 +10,7 @@ import { createCopilotEndpointSingleRoute } from "./endpoints/hono-single.cjs";
|
|
|
10
10
|
import { CopilotExpressEndpointParams, createCopilotExpressHandler } from "./endpoints/express.cjs";
|
|
11
11
|
import { createCopilotEndpointSingleRouteExpress } from "./endpoints/express-single.cjs";
|
|
12
12
|
import "./endpoints/index.cjs";
|
|
13
|
-
import { InMemoryAgentRunner,
|
|
13
|
+
import { InMemoryAgentRunner, InMemoryThread } from "./runner/in-memory.cjs";
|
|
14
14
|
import { IntelligenceAgentRunner, IntelligenceAgentRunnerOptions, RunnerStartupBoundary } from "./runner/intelligence.cjs";
|
|
15
15
|
import { finalizeRunEvents } from "./runner/index.cjs";
|
|
16
16
|
import { CopilotRuntimeFetchHandler, CopilotRuntimeHandlerOptions, createCopilotRuntimeHandler } from "./core/fetch-handler.cjs";
|
|
@@ -10,7 +10,7 @@ import { createCopilotEndpointSingleRoute } from "./endpoints/hono-single.mjs";
|
|
|
10
10
|
import { CopilotExpressEndpointParams, createCopilotExpressHandler } from "./endpoints/express.mjs";
|
|
11
11
|
import { createCopilotEndpointSingleRouteExpress } from "./endpoints/express-single.mjs";
|
|
12
12
|
import "./endpoints/index.mjs";
|
|
13
|
-
import { InMemoryAgentRunner,
|
|
13
|
+
import { InMemoryAgentRunner, InMemoryThread } from "./runner/in-memory.mjs";
|
|
14
14
|
import { IntelligenceAgentRunner, IntelligenceAgentRunnerOptions, RunnerStartupBoundary } from "./runner/intelligence.mjs";
|
|
15
15
|
import { finalizeRunEvents } from "./runner/index.mjs";
|
|
16
16
|
import { CopilotRuntimeFetchHandler, CopilotRuntimeHandlerOptions, createCopilotRuntimeHandler } from "./core/fetch-handler.mjs";
|
|
@@ -6,26 +6,6 @@ let rxjs = require("rxjs");
|
|
|
6
6
|
let _ag_ui_client = require("@ag-ui/client");
|
|
7
7
|
|
|
8
8
|
//#region src/v2/runtime/runner/in-memory.ts
|
|
9
|
-
const ɵINMEMORY_DEFAULTS = {
|
|
10
|
-
maxThreads: 1e3,
|
|
11
|
-
maxRunsPerThread: 100,
|
|
12
|
-
maxBytes: 512 * 1024 ** 2
|
|
13
|
-
};
|
|
14
|
-
const EVICTION_GUIDANCE = "[CopilotKit] InMemoryAgentRunner evicted in-memory thread history to stay under memory limits. This runner is bounded and non-durable by design. For durable or production threads, configure an Intelligence backend.";
|
|
15
|
-
const LIMITS_CLOBBER_GUIDANCE = "[CopilotKit] InMemoryAgentRunner was constructed with in-memory limits that differ from the already-configured process-global store; the last-constructed runner's limits apply to ALL in-memory threads (the store is shared per-process). Configure a single consistent set of limits, or use an Intelligence backend for isolated bounds.";
|
|
16
|
-
/**
|
|
17
|
-
* Best-effort approximate byte size of a value, via serialized length.
|
|
18
|
-
* Never throws — returns 0 when the value cannot be serialized. This is an
|
|
19
|
-
* approximation (UTF-16 length, not exact heap bytes), used only for relative
|
|
20
|
-
* accounting against `maxBytes`.
|
|
21
|
-
*/
|
|
22
|
-
function ɵestimateBytes(value) {
|
|
23
|
-
try {
|
|
24
|
-
return JSON.stringify(value)?.length ?? 0;
|
|
25
|
-
} catch {
|
|
26
|
-
return 0;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
9
|
var InMemoryEventStore = class {
|
|
30
10
|
constructor(threadId) {
|
|
31
11
|
this.threadId = threadId;
|
|
@@ -37,195 +17,21 @@ var InMemoryEventStore = class {
|
|
|
37
17
|
this.runSubject = null;
|
|
38
18
|
this.stopRequested = false;
|
|
39
19
|
this.currentEvents = null;
|
|
40
|
-
this.messagesSnapshot = [];
|
|
41
|
-
this.approxMessagesSnapshotBytes = 0;
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
var ɵBoundedThreadStore = class {
|
|
45
|
-
constructor(limits) {
|
|
46
|
-
this.limits = limits;
|
|
47
|
-
this.map = /* @__PURE__ */ new Map();
|
|
48
|
-
this.totalBytes = 0;
|
|
49
|
-
this.warned = false;
|
|
50
|
-
this.limitsExplicitlySet = false;
|
|
51
|
-
this.clobberWarned = false;
|
|
52
|
-
}
|
|
53
|
-
get byteTotal() {
|
|
54
|
-
return this.totalBytes;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Reconfigure the process-global store's bounds. Called by the
|
|
58
|
-
* {@link InMemoryAgentRunner} constructor when limits are passed. Because the
|
|
59
|
-
* store is a per-process singleton, this replaces the bounds for ALL in-memory
|
|
60
|
-
* threads. Emits {@link LIMITS_CLOBBER_GUIDANCE} at most ONCE per store when a
|
|
61
|
-
* SECOND (or later) explicit set arrives whose resolved values differ from the
|
|
62
|
-
* prior explicit set — i.e. a genuine clobber of an already-customized config.
|
|
63
|
-
* The first explicit customization (defaults → custom) is the intended
|
|
64
|
-
* override and never warns; identical re-sets never warn.
|
|
65
|
-
*/
|
|
66
|
-
setLimits(limits) {
|
|
67
|
-
if (this.limitsExplicitlySet && !this.clobberWarned && (limits.maxThreads !== this.limits.maxThreads || limits.maxRunsPerThread !== this.limits.maxRunsPerThread || limits.maxBytes !== this.limits.maxBytes)) {
|
|
68
|
-
this.clobberWarned = true;
|
|
69
|
-
try {
|
|
70
|
-
console.warn(LIMITS_CLOBBER_GUIDANCE);
|
|
71
|
-
} catch {}
|
|
72
|
-
}
|
|
73
|
-
this.limitsExplicitlySet = true;
|
|
74
|
-
this.limits = limits;
|
|
75
|
-
}
|
|
76
|
-
get size() {
|
|
77
|
-
return this.map.size;
|
|
78
|
-
}
|
|
79
|
-
/** Re-insert at the tail so Map iteration order stays LRU-first. */
|
|
80
|
-
touchOrder(threadId, store) {
|
|
81
|
-
this.map.delete(threadId);
|
|
82
|
-
this.map.set(threadId, store);
|
|
83
|
-
}
|
|
84
|
-
getOrCreate(threadId) {
|
|
85
|
-
const existing = this.map.get(threadId);
|
|
86
|
-
if (existing) {
|
|
87
|
-
this.touchOrder(threadId, existing);
|
|
88
|
-
return existing;
|
|
89
|
-
}
|
|
90
|
-
const store = new InMemoryEventStore(threadId);
|
|
91
|
-
this.map.set(threadId, store);
|
|
92
|
-
this.evictThreadsIfNeeded(threadId);
|
|
93
|
-
return store;
|
|
94
|
-
}
|
|
95
|
-
get(threadId, opts) {
|
|
96
|
-
const store = this.map.get(threadId);
|
|
97
|
-
if (store && opts.touch) this.touchOrder(threadId, store);
|
|
98
|
-
return store;
|
|
99
|
-
}
|
|
100
|
-
peek(threadId) {
|
|
101
|
-
return this.map.get(threadId);
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Evict the least-recently-used thread that is neither running NOR
|
|
105
|
-
* mid-finalization. Returns false if none evictable. The `protect` thread
|
|
106
|
-
* (typically the one just created) is never evicted, so a fresh thread is not
|
|
107
|
-
* immediately dropped when it is the only non-running candidate.
|
|
108
|
-
*
|
|
109
|
-
* A thread is skipped while `isRunning` OR `stopRequested` is set.
|
|
110
|
-
* `stop()` flips `isRunning` to false the moment it aborts the agent, but the
|
|
111
|
-
* run keeps finalizing asynchronously (the abort trips the `catch` in
|
|
112
|
-
* `runAgent`, which later calls `appendRun`). During that window
|
|
113
|
-
* `stopRequested` stays true; evicting the thread then would make the pending
|
|
114
|
-
* `appendRun` hit `if (!store) return` and silently drop the aborted run's
|
|
115
|
-
* history. Guarding on `stopRequested` keeps the thread alive until
|
|
116
|
-
* finalization completes.
|
|
117
|
-
*/
|
|
118
|
-
evictOneLru(protect) {
|
|
119
|
-
for (const [threadId, store] of this.map) {
|
|
120
|
-
if (threadId === protect) continue;
|
|
121
|
-
if (store.isRunning || store.stopRequested) continue;
|
|
122
|
-
this.removeThread(threadId, store);
|
|
123
|
-
this.noteEviction();
|
|
124
|
-
return true;
|
|
125
|
-
}
|
|
126
|
-
return false;
|
|
127
|
-
}
|
|
128
|
-
appendRun(threadId, run) {
|
|
129
|
-
const store = this.map.get(threadId);
|
|
130
|
-
if (!store) return;
|
|
131
|
-
if (run.messages.length > 0) {
|
|
132
|
-
this.totalBytes -= store.approxMessagesSnapshotBytes;
|
|
133
|
-
store.messagesSnapshot = run.messages;
|
|
134
|
-
store.approxMessagesSnapshotBytes = ɵestimateBytes(run.messages);
|
|
135
|
-
this.totalBytes += store.approxMessagesSnapshotBytes;
|
|
136
|
-
}
|
|
137
|
-
run.messages = [];
|
|
138
|
-
run.approxMessageBytes = 0;
|
|
139
|
-
run.approxEventBytes = ɵestimateBytes(run.events);
|
|
140
|
-
store.historicRuns.push(run);
|
|
141
|
-
this.totalBytes += run.approxEventBytes;
|
|
142
|
-
this.touchOrder(threadId, store);
|
|
143
|
-
this.enforceRunCap(store);
|
|
144
|
-
this.evictByBytesIfNeeded(threadId);
|
|
145
|
-
}
|
|
146
|
-
enforceRunCap(store) {
|
|
147
|
-
const cap = this.limits.maxRunsPerThread;
|
|
148
|
-
if (!cap || cap === Infinity) return;
|
|
149
|
-
while (store.historicRuns.length > cap) {
|
|
150
|
-
const dropped = store.historicRuns.shift();
|
|
151
|
-
this.totalBytes -= dropped.approxEventBytes ?? 0;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Trim the store back under the byte ceiling by evicting LRU non-running
|
|
156
|
-
* threads. `protect` (the just-appended thread) is never self-evicted, so a
|
|
157
|
-
* fresh run pushes OTHER threads out rather than dropping itself.
|
|
158
|
-
*/
|
|
159
|
-
evictByBytesIfNeeded(protect) {
|
|
160
|
-
while (this.totalBytes > this.limits.maxBytes) if (!this.evictOneLru(protect)) break;
|
|
161
|
-
}
|
|
162
|
-
removeThread(threadId, store) {
|
|
163
|
-
for (const run of store.historicRuns) this.totalBytes -= run.approxEventBytes ?? 0;
|
|
164
|
-
this.totalBytes -= store.approxMessagesSnapshotBytes;
|
|
165
|
-
this.map.delete(threadId);
|
|
166
|
-
}
|
|
167
|
-
evictThreadsIfNeeded(protect) {
|
|
168
|
-
while (this.map.size > this.limits.maxThreads) if (!this.evictOneLru(protect)) break;
|
|
169
|
-
}
|
|
170
|
-
noteEviction() {
|
|
171
|
-
if (this.warned) return;
|
|
172
|
-
this.warned = true;
|
|
173
|
-
try {
|
|
174
|
-
console.warn(EVICTION_GUIDANCE);
|
|
175
|
-
} catch {}
|
|
176
|
-
}
|
|
177
|
-
listThreads() {
|
|
178
|
-
const threads = [];
|
|
179
|
-
for (const [threadId, store] of this.map) {
|
|
180
|
-
if (store.historicRuns.length === 0) continue;
|
|
181
|
-
const firstRun = store.historicRuns[0];
|
|
182
|
-
const lastRun = store.historicRuns[store.historicRuns.length - 1];
|
|
183
|
-
threads.push({
|
|
184
|
-
id: threadId,
|
|
185
|
-
name: null,
|
|
186
|
-
agentId: lastRun.agentId,
|
|
187
|
-
organizationId: "",
|
|
188
|
-
createdById: "",
|
|
189
|
-
archived: false,
|
|
190
|
-
createdAt: new Date(firstRun.createdAt).toISOString(),
|
|
191
|
-
updatedAt: new Date(lastRun.createdAt).toISOString()
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
return threads.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
195
|
-
}
|
|
196
|
-
clear() {
|
|
197
|
-
this.map.clear();
|
|
198
|
-
this.totalBytes = 0;
|
|
199
|
-
this.warned = false;
|
|
200
20
|
}
|
|
201
21
|
};
|
|
202
|
-
|
|
203
|
-
* Process-wide singleton backing every {@link InMemoryAgentRunner}. Exported
|
|
204
|
-
* (with the `ɵ` internal-API prefix) so tests can inspect the exact store the
|
|
205
|
-
* runner writes to; not part of the public API.
|
|
206
|
-
*/
|
|
207
|
-
const ɵGLOBAL_STORE = new ɵBoundedThreadStore(ɵINMEMORY_DEFAULTS);
|
|
208
|
-
const sharedStore = ɵGLOBAL_STORE;
|
|
22
|
+
const GLOBAL_STORE = /* @__PURE__ */ new Map();
|
|
209
23
|
var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
* for safe defaults ({@link ɵINMEMORY_DEFAULTS}). When multiple runners are
|
|
213
|
-
* constructed with differing limits, the last-constructed wins — in practice
|
|
214
|
-
* the OSS/SSE default construction passes nothing. If a second (or later)
|
|
215
|
-
* runner is constructed with limits that DIFFER from an already-customized
|
|
216
|
-
* store, a one-time `console.warn` is emitted to signal that the shared store's
|
|
217
|
-
* bounds are being clobbered for ALL in-memory threads.
|
|
218
|
-
*/
|
|
219
|
-
constructor(limits) {
|
|
220
|
-
super();
|
|
24
|
+
constructor(..._args) {
|
|
25
|
+
super(..._args);
|
|
221
26
|
this.ɵsupportsLocalThreadEndpoints = true;
|
|
222
|
-
if (limits) sharedStore.setLimits({
|
|
223
|
-
...ɵINMEMORY_DEFAULTS,
|
|
224
|
-
...limits
|
|
225
|
-
});
|
|
226
27
|
}
|
|
227
28
|
run(request) {
|
|
228
|
-
|
|
29
|
+
let existingStore = GLOBAL_STORE.get(request.threadId);
|
|
30
|
+
if (!existingStore) {
|
|
31
|
+
existingStore = new InMemoryEventStore(request.threadId);
|
|
32
|
+
GLOBAL_STORE.set(request.threadId, existingStore);
|
|
33
|
+
}
|
|
34
|
+
const store = existingStore;
|
|
229
35
|
if (store.isRunning) throw new Error("Thread already running");
|
|
230
36
|
store.isRunning = true;
|
|
231
37
|
store.currentRunId = request.input.runId;
|
|
@@ -287,7 +93,7 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
287
93
|
}
|
|
288
94
|
if (store.currentRunId) {
|
|
289
95
|
const compactedEvents = (0, _ag_ui_client.compactEvents)(currentRunEvents);
|
|
290
|
-
|
|
96
|
+
store.historicRuns.push({
|
|
291
97
|
threadId: request.threadId,
|
|
292
98
|
runId: store.currentRunId,
|
|
293
99
|
agentId: request.agent.agentId ?? "default",
|
|
@@ -305,7 +111,6 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
305
111
|
store.isRunning = false;
|
|
306
112
|
runSubject.complete();
|
|
307
113
|
nextSubject.complete();
|
|
308
|
-
store.subject = null;
|
|
309
114
|
} catch (error) {
|
|
310
115
|
const interruptionMessage = error instanceof Error ? error.message : String(error);
|
|
311
116
|
const appendedEvents = (0, _copilotkit_shared.finalizeRunEvents)(currentRunEvents, {
|
|
@@ -318,7 +123,7 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
318
123
|
}
|
|
319
124
|
if (store.currentRunId && currentRunEvents.length > 0) {
|
|
320
125
|
const compactedEvents = (0, _ag_ui_client.compactEvents)(currentRunEvents);
|
|
321
|
-
|
|
126
|
+
store.historicRuns.push({
|
|
322
127
|
threadId: request.threadId,
|
|
323
128
|
runId: store.currentRunId,
|
|
324
129
|
agentId: request.agent.agentId ?? "default",
|
|
@@ -336,7 +141,6 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
336
141
|
store.isRunning = false;
|
|
337
142
|
runSubject.complete();
|
|
338
143
|
nextSubject.complete();
|
|
339
|
-
store.subject = null;
|
|
340
144
|
}
|
|
341
145
|
};
|
|
342
146
|
if (prevSubject) prevSubject.subscribe({
|
|
@@ -348,7 +152,7 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
348
152
|
return runSubject.asObservable();
|
|
349
153
|
}
|
|
350
154
|
connect(request) {
|
|
351
|
-
const store =
|
|
155
|
+
const store = GLOBAL_STORE.get(request.threadId);
|
|
352
156
|
const connectionSubject = new rxjs.ReplaySubject(Infinity);
|
|
353
157
|
if (!store) {
|
|
354
158
|
connectionSubject.complete();
|
|
@@ -374,11 +178,11 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
374
178
|
return connectionSubject.asObservable();
|
|
375
179
|
}
|
|
376
180
|
isRunning(request) {
|
|
377
|
-
const store =
|
|
181
|
+
const store = GLOBAL_STORE.get(request.threadId);
|
|
378
182
|
return Promise.resolve(store?.isRunning ?? false);
|
|
379
183
|
}
|
|
380
184
|
stop(request) {
|
|
381
|
-
const store =
|
|
185
|
+
const store = GLOBAL_STORE.get(request.threadId);
|
|
382
186
|
if (!store || !store.isRunning) return Promise.resolve(false);
|
|
383
187
|
if (store.stopRequested) return Promise.resolve(false);
|
|
384
188
|
store.stopRequested = true;
|
|
@@ -407,7 +211,23 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
407
211
|
* `ThreadRecord` so the HTTP handler can use the same response envelope.
|
|
408
212
|
*/
|
|
409
213
|
listThreads() {
|
|
410
|
-
|
|
214
|
+
const threads = [];
|
|
215
|
+
for (const [threadId, store] of GLOBAL_STORE) {
|
|
216
|
+
if (store.historicRuns.length === 0) continue;
|
|
217
|
+
const firstRun = store.historicRuns[0];
|
|
218
|
+
const lastRun = store.historicRuns[store.historicRuns.length - 1];
|
|
219
|
+
threads.push({
|
|
220
|
+
id: threadId,
|
|
221
|
+
name: null,
|
|
222
|
+
agentId: lastRun.agentId,
|
|
223
|
+
organizationId: "",
|
|
224
|
+
createdById: "",
|
|
225
|
+
archived: false,
|
|
226
|
+
createdAt: new Date(firstRun.createdAt).toISOString(),
|
|
227
|
+
updatedAt: new Date(lastRun.createdAt).toISOString()
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return threads.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
411
231
|
}
|
|
412
232
|
/**
|
|
413
233
|
* Returns all messages for a thread, using the snapshot captured at the end
|
|
@@ -419,9 +239,9 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
419
239
|
* with the Intelligence platform's `ThreadMessage` type.
|
|
420
240
|
*/
|
|
421
241
|
getThreadMessages(threadId) {
|
|
422
|
-
const store =
|
|
423
|
-
if (!store) return [];
|
|
424
|
-
return [
|
|
242
|
+
const store = GLOBAL_STORE.get(threadId);
|
|
243
|
+
if (!store || store.historicRuns.length === 0) return [];
|
|
244
|
+
return store.historicRuns[store.historicRuns.length - 1].messages;
|
|
425
245
|
}
|
|
426
246
|
/**
|
|
427
247
|
* Returns all AG-UI events for a thread, compacted across historic runs.
|
|
@@ -432,7 +252,7 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
432
252
|
* late-joining inspector sees matches what this method returns.
|
|
433
253
|
*/
|
|
434
254
|
getThreadEvents(threadId) {
|
|
435
|
-
const store =
|
|
255
|
+
const store = GLOBAL_STORE.get(threadId);
|
|
436
256
|
if (!store || store.historicRuns.length === 0) return [];
|
|
437
257
|
const all = [];
|
|
438
258
|
for (const run of store.historicRuns) all.push(...run.events);
|
|
@@ -454,7 +274,7 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
454
274
|
const event = events[i];
|
|
455
275
|
if (event.type === _ag_ui_client.EventType.STATE_SNAPSHOT) {
|
|
456
276
|
const snapshot = event.snapshot;
|
|
457
|
-
if (snapshot && typeof snapshot === "object"
|
|
277
|
+
if (snapshot && typeof snapshot === "object") return snapshot;
|
|
458
278
|
return null;
|
|
459
279
|
}
|
|
460
280
|
}
|
|
@@ -470,14 +290,10 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
|
|
|
470
290
|
* not be wiped this way.
|
|
471
291
|
*/
|
|
472
292
|
clearThreads() {
|
|
473
|
-
|
|
293
|
+
GLOBAL_STORE.clear();
|
|
474
294
|
}
|
|
475
295
|
};
|
|
476
296
|
|
|
477
297
|
//#endregion
|
|
478
298
|
exports.InMemoryAgentRunner = InMemoryAgentRunner;
|
|
479
|
-
exports.ɵBoundedThreadStore = ɵBoundedThreadStore;
|
|
480
|
-
exports.ɵGLOBAL_STORE = ɵGLOBAL_STORE;
|
|
481
|
-
exports.ɵINMEMORY_DEFAULTS = ɵINMEMORY_DEFAULTS;
|
|
482
|
-
exports.ɵestimateBytes = ɵestimateBytes;
|
|
483
299
|
//# sourceMappingURL=in-memory.cjs.map
|