@copilotkit/runtime 1.56.2 → 1.56.4
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/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/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 +2 -2
- package/dist/package.mjs +2 -2
- 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/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 +3 -3
- 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/copilot-runtime.ts +20 -4
- package/src/lib/runtime/retry-utils.ts +41 -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/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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intelligence.cjs","names":["AgentRunner","Socket","Observable","AG_UI_CHANNEL_EVENT","EventType","EMPTY"],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"sourcesContent":["import {\n AgentRunner,\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n type AgentRunnerStopRequest,\n} from \"./agent-runner\";\nimport { EMPTY, Observable, from } from \"rxjs\";\nimport { catchError, finalize } from \"rxjs/operators\";\nimport {\n AbstractAgent,\n BaseEvent,\n EventType,\n RunStartedEvent,\n} from \"@ag-ui/client\";\nimport {\n finalizeRunEvents,\n AG_UI_CHANNEL_EVENT,\n phoenixExponentialBackoff,\n} from \"@copilotkit/shared\";\nimport { Socket, Channel } from \"phoenix\";\nimport { randomUUID } from \"node:crypto\";\n\nexport interface IntelligenceAgentRunnerOptions {\n /** Phoenix runner websocket URL, e.g. \"ws://localhost:4000/runner\" */\n url: string;\n /** Optional Phoenix socket auth token used during websocket connect. */\n authToken?: string;\n /** Max delay (ms) for WebSocket reconnect backoff. @default 10_000 */\n maxReconnectMs?: number;\n /** Max delay (ms) for channel rejoin backoff. @default 30_000 */\n maxRejoinMs?: number;\n}\n\ninterface ThreadState {\n socket: Socket;\n channel: Channel;\n isRunning: boolean;\n stopRequested: boolean;\n agent: AbstractAgent | null;\n currentEvents: BaseEvent[];\n nextEventSeq: number;\n hasRunStarted: boolean;\n}\n\nexport class IntelligenceAgentRunner extends AgentRunner {\n private options: IntelligenceAgentRunnerOptions;\n private threads = new Map<string, ThreadState>();\n\n constructor(options: IntelligenceAgentRunnerOptions) {\n super();\n // Store config — sockets are created per-run, not eagerly.\n this.options = options;\n }\n\n /**\n * Create a new Phoenix socket with explicit exponential backoff.\n *\n * Each run/connect gets its own socket so that:\n * - A socket failure only affects a single thread, not all threads.\n * - Cleanup is simple: channel.leave() + socket.disconnect() tears\n * down everything for that run with no shared-state concerns.\n * - Each run gets its own independent retry budget.\n *\n * reconnectAfterMs — delay before Phoenix reconnects the WebSocket\n * after an unclean close. 100ms base, doubling up to maxReconnectMs (default 10s).\n *\n * rejoinAfterMs — delay before Phoenix re-joins a channel that\n * entered the \"errored\" state. 1s base, doubling up to maxRejoinMs (default 30s).\n *\n * These are set explicitly because Phoenix's default schedule is a\n * fixed stepped array (not exponential), and any code that calls\n * socket.disconnect() in an onError handler will set\n * closeWasClean = true and reset the reconnect timer — permanently\n * killing retries.\n */\n private createSocket(): Socket {\n const socket = new Socket(this.options.url, {\n ...(this.options.authToken ? { authToken: this.options.authToken } : {}),\n reconnectAfterMs: phoenixExponentialBackoff(\n 100,\n this.options.maxReconnectMs ?? 10_000,\n ),\n rejoinAfterMs: phoenixExponentialBackoff(\n 1_000,\n this.options.maxRejoinMs ?? 30_000,\n ),\n });\n socket.connect();\n return socket;\n }\n\n private createRunnerEventPayload(\n event: BaseEvent,\n request: AgentRunnerRunRequest,\n state: ThreadState,\n ): Record<string, unknown> {\n const canonicalEvent = this.stampRunnerMetadata(event, state);\n const payload = {\n ...(canonicalEvent as Record<string, unknown>),\n };\n\n payload.thread_id ??= request.threadId;\n\n const runId = payload.runId ?? payload.run_id ?? request.input.runId;\n\n if (runId) {\n payload.run_id = runId;\n }\n\n return payload;\n }\n\n private stampRunnerMetadata(event: BaseEvent, state: ThreadState): BaseEvent {\n const eventRecord = event as BaseEvent & {\n metadata?: Record<string, unknown>;\n };\n\n const existingMetadata = eventRecord.metadata ?? {};\n const hasEventId = typeof existingMetadata.cpki_event_id === \"string\";\n const hasEventSeq = typeof existingMetadata.cpki_event_seq === \"number\";\n\n if (hasEventId && hasEventSeq) {\n const eventSeq = existingMetadata.cpki_event_seq as number;\n state.nextEventSeq = Math.max(state.nextEventSeq, eventSeq + 1);\n return eventRecord;\n }\n\n const eventSeq = state.nextEventSeq++;\n\n return {\n ...eventRecord,\n metadata: {\n ...existingMetadata,\n cpki_event_id:\n typeof existingMetadata.cpki_event_id === \"string\"\n ? existingMetadata.cpki_event_id\n : randomUUID(),\n cpki_event_seq: eventSeq,\n },\n };\n }\n\n run(request: AgentRunnerRunRequest): Observable<BaseEvent> {\n const { threadId, agent, input, joinCode } = request;\n\n const existing = this.threads.get(threadId);\n if (existing?.isRunning) {\n throw new Error(\"Thread already running\");\n }\n\n return new Observable((observer) => {\n const socket = this.createSocket();\n\n const channelTopic = joinCode ?? threadId;\n const channel = socket.channel(`ingestion:${channelTopic}`, {\n runId: input.runId,\n });\n\n const state: ThreadState = {\n socket,\n channel,\n isRunning: true,\n stopRequested: false,\n agent,\n currentEvents: [],\n nextEventSeq: 1,\n hasRunStarted: false,\n };\n this.threads.set(threadId, state);\n\n // Track consecutive socket errors for this run. Phoenix retries\n // automatically via reconnectAfterMs, but if the connection fails\n // repeatedly we abort the agent — otherwise runAgent() completes\n // normally, finalization events buffer silently on the dead\n // channel, and the client never receives them.\n //\n // Aborting the agent is the single trigger that cascades through\n // the existing error pipeline: runAgent() rejects → catchError\n // pushes RUN_ERROR → finalize calls finalizeRunEvents +\n // removeThread → channel.leave() + socket.disconnect().\n const MAX_CONSECUTIVE_ERRORS = 5;\n let consecutiveErrors = 0;\n\n socket.onError(() => {\n consecutiveErrors++;\n if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS && state.agent) {\n try {\n state.agent.abortRun();\n } catch {\n // Ignore abort errors.\n }\n }\n // Otherwise: Phoenix retries automatically using the exponential\n // backoff schedule configured in createSocket().\n });\n\n socket.onOpen(() => {\n // A successful (re)connection resets the counter so transient\n // network blips don't accumulate across recoveries.\n consecutiveErrors = 0;\n });\n\n // Listen for custom \"stop\" events pushed by the client over the\n // channel. This must be registered before channel.join() so the\n // handler is in place by the time the server starts relaying messages.\n // The client sends the stop event before leaving the channel, so the\n // runner is guaranteed to receive it while still joined.\n channel.on(AG_UI_CHANNEL_EVENT, (payload: BaseEvent) => {\n if (\n payload.type === EventType.CUSTOM &&\n (payload as BaseEvent & { name?: string }).name === \"stop\"\n ) {\n this.stop({ threadId });\n }\n });\n\n channel\n .join()\n .receive(\"ok\", () => {\n this.executeAgentRun(request, state, threadId).subscribe({\n complete: () => observer.complete(),\n });\n })\n .receive(\"error\", (resp) => {\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: `Failed to join channel: ${JSON.stringify(resp)}`,\n code: \"CHANNEL_JOIN_ERROR\",\n } as BaseEvent;\n observer.next(errorEvent);\n state.currentEvents.push(errorEvent);\n this.removeThread(threadId);\n observer.complete();\n })\n .receive(\"timeout\", () => {\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: \"Timed out joining channel\",\n code: \"CHANNEL_JOIN_TIMEOUT\",\n } as BaseEvent;\n observer.next(errorEvent);\n state.currentEvents.push(errorEvent);\n this.removeThread(threadId);\n observer.complete();\n });\n\n return () => {\n this.removeThread(threadId);\n };\n });\n }\n\n connect(request: AgentRunnerConnectRequest): Observable<BaseEvent> {\n const { threadId } = request;\n\n return new Observable((observer) => {\n const socket = this.createSocket();\n\n const channel = socket.channel(`thread:${threadId}`);\n\n channel.on(\"ag_ui_event\", (payload: BaseEvent) => {\n observer.next(payload);\n\n if (\n payload.type === EventType.RUN_FINISHED ||\n payload.type === EventType.RUN_ERROR\n ) {\n observer.complete();\n }\n });\n\n const cleanup = () => {\n channel.leave();\n socket.disconnect();\n };\n\n channel\n .join()\n .receive(\"ok\", () => undefined)\n .receive(\"error\", (resp) => {\n observer.error(\n new Error(`Failed to join channel: ${JSON.stringify(resp)}`),\n );\n cleanup();\n })\n .receive(\"timeout\", () => {\n observer.error(new Error(\"Timed out joining channel\"));\n cleanup();\n });\n\n return () => {\n cleanup();\n };\n });\n }\n\n isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean> {\n const state = this.threads.get(request.threadId);\n return Promise.resolve(state?.isRunning ?? false);\n }\n\n stop(request: AgentRunnerStopRequest): Promise<boolean | undefined> {\n const state = this.threads.get(request.threadId);\n if (!state || !state.isRunning || state.stopRequested) {\n return Promise.resolve(false);\n }\n\n state.stopRequested = true;\n\n // Direct local abort — the runtime is the authority.\n if (state.agent) {\n try {\n state.agent.abortRun();\n } catch {\n // Ignore abort errors.\n }\n }\n\n return Promise.resolve(true);\n }\n\n private executeAgentRun(\n request: AgentRunnerRunRequest,\n state: ThreadState,\n threadId: string,\n ): Observable<void> {\n const { currentEvents, channel } = state;\n const pushCanonicalEvent = (event: BaseEvent): void => {\n const canonicalEvent = this.stampRunnerMetadata(event, state);\n currentEvents.push(canonicalEvent);\n\n if (canonicalEvent.type === EventType.RUN_STARTED) {\n state.hasRunStarted = true;\n }\n\n channel.push(\n \"event\",\n this.createRunnerEventPayload(canonicalEvent, request, state),\n );\n };\n\n const getPersistedInputMessages = () =>\n request.persistedInputMessages ?? request.input.messages;\n\n const buildRunStartedEvent = (\n source?: RunStartedEvent,\n ): RunStartedEvent => {\n const baseInput = source?.input ?? request.input;\n const persistedInputMessages = getPersistedInputMessages();\n\n return {\n ...(source ?? {\n type: EventType.RUN_STARTED,\n threadId: request.threadId,\n runId: request.input.runId,\n }),\n input: {\n ...baseInput,\n ...(persistedInputMessages !== undefined\n ? { messages: persistedInputMessages }\n : {}),\n },\n } as RunStartedEvent;\n };\n\n const ensureRunStarted = (): void => {\n if (!state.hasRunStarted) {\n state.hasRunStarted = true;\n pushCanonicalEvent(buildRunStartedEvent());\n }\n };\n\n return from(\n request.agent.runAgent(request.input, {\n onEvent: ({ event }: { event: BaseEvent }) => {\n if (event.type === EventType.RUN_STARTED) {\n pushCanonicalEvent(buildRunStartedEvent(event as RunStartedEvent));\n return;\n }\n\n ensureRunStarted();\n pushCanonicalEvent(event);\n },\n }),\n ).pipe(\n catchError((error) => {\n ensureRunStarted();\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: error instanceof Error ? error.message : String(error),\n } as BaseEvent;\n pushCanonicalEvent(errorEvent);\n return EMPTY;\n }),\n finalize(() => {\n ensureRunStarted();\n const appended = finalizeRunEvents(currentEvents, {\n stopRequested: state.stopRequested,\n });\n for (const event of appended) {\n channel.push(\n \"event\",\n this.createRunnerEventPayload(event, request, state),\n );\n }\n this.removeThread(threadId);\n }),\n );\n }\n\n /**\n * Tear down all resources for a thread: leave the channel,\n * disconnect the per-run socket, and remove the thread state.\n *\n * Idempotent — safe to call multiple times for the same threadId\n * (e.g. from join error handlers, finalize, and Observable teardown).\n */\n private removeThread(threadId: string): void {\n const state = this.threads.get(threadId);\n if (!state) {\n return;\n }\n\n // Delete first so concurrent calls see the entry as already removed.\n this.threads.delete(threadId);\n\n try {\n state.channel.leave();\n } catch {\n // Channel may already be closed/left.\n }\n try {\n state.socket.disconnect();\n } catch {\n // Socket may already be disconnected.\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AA6CA,IAAa,0BAAb,cAA6CA,iCAAY;CAIvD,YAAY,SAAyC;AACnD,SAAO;iCAHS,IAAI,KAA0B;AAK9C,OAAK,UAAU;;;;;;;;;;;;;;;;;;;;;;;CAwBjB,AAAQ,eAAuB;EAC7B,MAAM,SAAS,IAAIC,eAAO,KAAK,QAAQ,KAAK;GAC1C,GAAI,KAAK,QAAQ,YAAY,EAAE,WAAW,KAAK,QAAQ,WAAW,GAAG,EAAE;GACvE,oEACE,KACA,KAAK,QAAQ,kBAAkB,IAChC;GACD,iEACE,KACA,KAAK,QAAQ,eAAe,IAC7B;GACF,CAAC;AACF,SAAO,SAAS;AAChB,SAAO;;CAGT,AAAQ,yBACN,OACA,SACA,OACyB;EAEzB,MAAM,UAAU,EACd,GAFqB,KAAK,oBAAoB,OAAO,MAAM,EAG5D;AAED,UAAQ,cAAc,QAAQ;EAE9B,MAAM,QAAQ,QAAQ,SAAS,QAAQ,UAAU,QAAQ,MAAM;AAE/D,MAAI,MACF,SAAQ,SAAS;AAGnB,SAAO;;CAGT,AAAQ,oBAAoB,OAAkB,OAA+B;EAC3E,MAAM,cAAc;EAIpB,MAAM,mBAAmB,YAAY,YAAY,EAAE;EACnD,MAAM,aAAa,OAAO,iBAAiB,kBAAkB;EAC7D,MAAM,cAAc,OAAO,iBAAiB,mBAAmB;AAE/D,MAAI,cAAc,aAAa;GAC7B,MAAM,WAAW,iBAAiB;AAClC,SAAM,eAAe,KAAK,IAAI,MAAM,cAAc,WAAW,EAAE;AAC/D,UAAO;;EAGT,MAAM,WAAW,MAAM;AAEvB,SAAO;GACL,GAAG;GACH,UAAU;IACR,GAAG;IACH,eACE,OAAO,iBAAiB,kBAAkB,WACtC,iBAAiB,6CACL;IAClB,gBAAgB;IACjB;GACF;;CAGH,IAAI,SAAuD;EACzD,MAAM,EAAE,UAAU,OAAO,OAAO,aAAa;AAG7C,MADiB,KAAK,QAAQ,IAAI,SAAS,EAC7B,UACZ,OAAM,IAAI,MAAM,yBAAyB;AAG3C,SAAO,IAAIC,iBAAY,aAAa;GAClC,MAAM,SAAS,KAAK,cAAc;GAElC,MAAM,eAAe,YAAY;GACjC,MAAM,UAAU,OAAO,QAAQ,aAAa,gBAAgB,EAC1D,OAAO,MAAM,OACd,CAAC;GAEF,MAAM,QAAqB;IACzB;IACA;IACA,WAAW;IACX,eAAe;IACf;IACA,eAAe,EAAE;IACjB,cAAc;IACd,eAAe;IAChB;AACD,QAAK,QAAQ,IAAI,UAAU,MAAM;GAYjC,MAAM,yBAAyB;GAC/B,IAAI,oBAAoB;AAExB,UAAO,cAAc;AACnB;AACA,QAAI,qBAAqB,0BAA0B,MAAM,MACvD,KAAI;AACF,WAAM,MAAM,UAAU;YAChB;KAMV;AAEF,UAAO,aAAa;AAGlB,wBAAoB;KACpB;AAOF,WAAQ,GAAGC,yCAAsB,YAAuB;AACtD,QACE,QAAQ,SAASC,wBAAU,UAC1B,QAA0C,SAAS,OAEpD,MAAK,KAAK,EAAE,UAAU,CAAC;KAEzB;AAEF,WACG,MAAM,CACN,QAAQ,YAAY;AACnB,SAAK,gBAAgB,SAAS,OAAO,SAAS,CAAC,UAAU,EACvD,gBAAgB,SAAS,UAAU,EACpC,CAAC;KACF,CACD,QAAQ,UAAU,SAAS;IAC1B,MAAM,aAAa;KACjB,MAAMA,wBAAU;KAChB,SAAS,2BAA2B,KAAK,UAAU,KAAK;KACxD,MAAM;KACP;AACD,aAAS,KAAK,WAAW;AACzB,UAAM,cAAc,KAAK,WAAW;AACpC,SAAK,aAAa,SAAS;AAC3B,aAAS,UAAU;KACnB,CACD,QAAQ,iBAAiB;IACxB,MAAM,aAAa;KACjB,MAAMA,wBAAU;KAChB,SAAS;KACT,MAAM;KACP;AACD,aAAS,KAAK,WAAW;AACzB,UAAM,cAAc,KAAK,WAAW;AACpC,SAAK,aAAa,SAAS;AAC3B,aAAS,UAAU;KACnB;AAEJ,gBAAa;AACX,SAAK,aAAa,SAAS;;IAE7B;;CAGJ,QAAQ,SAA2D;EACjE,MAAM,EAAE,aAAa;AAErB,SAAO,IAAIF,iBAAY,aAAa;GAClC,MAAM,SAAS,KAAK,cAAc;GAElC,MAAM,UAAU,OAAO,QAAQ,UAAU,WAAW;AAEpD,WAAQ,GAAG,gBAAgB,YAAuB;AAChD,aAAS,KAAK,QAAQ;AAEtB,QACE,QAAQ,SAASE,wBAAU,gBAC3B,QAAQ,SAASA,wBAAU,UAE3B,UAAS,UAAU;KAErB;GAEF,MAAM,gBAAgB;AACpB,YAAQ,OAAO;AACf,WAAO,YAAY;;AAGrB,WACG,MAAM,CACN,QAAQ,YAAY,OAAU,CAC9B,QAAQ,UAAU,SAAS;AAC1B,aAAS,sBACP,IAAI,MAAM,2BAA2B,KAAK,UAAU,KAAK,GAAG,CAC7D;AACD,aAAS;KACT,CACD,QAAQ,iBAAiB;AACxB,aAAS,sBAAM,IAAI,MAAM,4BAA4B,CAAC;AACtD,aAAS;KACT;AAEJ,gBAAa;AACX,aAAS;;IAEX;;CAGJ,UAAU,SAAwD;EAChE,MAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ,SAAS;AAChD,SAAO,QAAQ,QAAQ,OAAO,aAAa,MAAM;;CAGnD,KAAK,SAA+D;EAClE,MAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ,SAAS;AAChD,MAAI,CAAC,SAAS,CAAC,MAAM,aAAa,MAAM,cACtC,QAAO,QAAQ,QAAQ,MAAM;AAG/B,QAAM,gBAAgB;AAGtB,MAAI,MAAM,MACR,KAAI;AACF,SAAM,MAAM,UAAU;UAChB;AAKV,SAAO,QAAQ,QAAQ,KAAK;;CAG9B,AAAQ,gBACN,SACA,OACA,UACkB;EAClB,MAAM,EAAE,eAAe,YAAY;EACnC,MAAM,sBAAsB,UAA2B;GACrD,MAAM,iBAAiB,KAAK,oBAAoB,OAAO,MAAM;AAC7D,iBAAc,KAAK,eAAe;AAElC,OAAI,eAAe,SAASA,wBAAU,YACpC,OAAM,gBAAgB;AAGxB,WAAQ,KACN,SACA,KAAK,yBAAyB,gBAAgB,SAAS,MAAM,CAC9D;;EAGH,MAAM,kCACJ,QAAQ,0BAA0B,QAAQ,MAAM;EAElD,MAAM,wBACJ,WACoB;GACpB,MAAM,YAAY,QAAQ,SAAS,QAAQ;GAC3C,MAAM,yBAAyB,2BAA2B;AAE1D,UAAO;IACL,GAAI,UAAU;KACZ,MAAMA,wBAAU;KAChB,UAAU,QAAQ;KAClB,OAAO,QAAQ,MAAM;KACtB;IACD,OAAO;KACL,GAAG;KACH,GAAI,2BAA2B,SAC3B,EAAE,UAAU,wBAAwB,GACpC,EAAE;KACP;IACF;;EAGH,MAAM,yBAA+B;AACnC,OAAI,CAAC,MAAM,eAAe;AACxB,UAAM,gBAAgB;AACtB,uBAAmB,sBAAsB,CAAC;;;AAI9C,wBACE,QAAQ,MAAM,SAAS,QAAQ,OAAO,EACpC,UAAU,EAAE,YAAkC;AAC5C,OAAI,MAAM,SAASA,wBAAU,aAAa;AACxC,uBAAmB,qBAAqB,MAAyB,CAAC;AAClE;;AAGF,qBAAkB;AAClB,sBAAmB,MAAM;KAE5B,CAAC,CACH,CAAC,qCACY,UAAU;AACpB,qBAAkB;AAKlB,sBAJmB;IACjB,MAAMA,wBAAU;IAChB,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAChE,CAC6B;AAC9B,UAAOC;IACP,qCACa;AACb,qBAAkB;GAClB,MAAM,qDAA6B,eAAe,EAChD,eAAe,MAAM,eACtB,CAAC;AACF,QAAK,MAAM,SAAS,SAClB,SAAQ,KACN,SACA,KAAK,yBAAyB,OAAO,SAAS,MAAM,CACrD;AAEH,QAAK,aAAa,SAAS;IAC3B,CACH;;;;;;;;;CAUH,AAAQ,aAAa,UAAwB;EAC3C,MAAM,QAAQ,KAAK,QAAQ,IAAI,SAAS;AACxC,MAAI,CAAC,MACH;AAIF,OAAK,QAAQ,OAAO,SAAS;AAE7B,MAAI;AACF,SAAM,QAAQ,OAAO;UACf;AAGR,MAAI;AACF,SAAM,OAAO,YAAY;UACnB"}
|
|
1
|
+
{"version":3,"file":"intelligence.cjs","names":["AgentRunner","Socket","Observable","AG_UI_CHANNEL_EVENT","EventType","EMPTY"],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"sourcesContent":["import {\n AgentRunner,\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n type AgentRunnerStopRequest,\n} from \"./agent-runner\";\nimport { EMPTY, Observable, from } from \"rxjs\";\nimport { catchError, finalize } from \"rxjs/operators\";\nimport {\n AbstractAgent,\n BaseEvent,\n EventType,\n RunStartedEvent,\n} from \"@ag-ui/client\";\nimport {\n finalizeRunEvents,\n AG_UI_CHANNEL_EVENT,\n phoenixExponentialBackoff,\n} from \"@copilotkit/shared\";\nimport { Socket, Channel } from \"phoenix\";\nimport { randomUUID } from \"node:crypto\";\n\nexport interface IntelligenceAgentRunnerOptions {\n /** Phoenix runner websocket URL, e.g. \"ws://localhost:4000/runner\" */\n url: string;\n /** Optional Phoenix socket auth token used during websocket connect. */\n authToken?: string;\n /** Max delay (ms) for WebSocket reconnect backoff. @default 10_000 */\n maxReconnectMs?: number;\n /** Max delay (ms) for channel rejoin backoff. @default 30_000 */\n maxRejoinMs?: number;\n}\n\nexport interface RunnerStartupBoundary {\n events: Observable<BaseEvent>;\n startup: Promise<void>;\n}\n\ninterface ThreadState {\n socket: Socket;\n channel: Channel;\n isRunning: boolean;\n stopRequested: boolean;\n agent: AbstractAgent | null;\n currentEvents: BaseEvent[];\n nextEventSeq: number;\n hasRunStarted: boolean;\n}\n\nexport class IntelligenceAgentRunner extends AgentRunner {\n private options: IntelligenceAgentRunnerOptions;\n private threads = new Map<string, ThreadState>();\n\n constructor(options: IntelligenceAgentRunnerOptions) {\n super();\n // Store config — sockets are created per-run, not eagerly.\n this.options = options;\n }\n\n /**\n * Create a new Phoenix socket with explicit exponential backoff.\n *\n * Each run/connect gets its own socket so that:\n * - A socket failure only affects a single thread, not all threads.\n * - Cleanup is simple: channel.leave() + socket.disconnect() tears\n * down everything for that run with no shared-state concerns.\n * - Each run gets its own independent retry budget.\n *\n * reconnectAfterMs — delay before Phoenix reconnects the WebSocket\n * after an unclean close. 100ms base, doubling up to maxReconnectMs (default 10s).\n *\n * rejoinAfterMs — delay before Phoenix re-joins a channel that\n * entered the \"errored\" state. 1s base, doubling up to maxRejoinMs (default 30s).\n *\n * These are set explicitly because Phoenix's default schedule is a\n * fixed stepped array (not exponential), and any code that calls\n * socket.disconnect() in an onError handler will set\n * closeWasClean = true and reset the reconnect timer — permanently\n * killing retries.\n */\n private createSocket(): Socket {\n const socket = new Socket(this.options.url, {\n ...(this.options.authToken ? { authToken: this.options.authToken } : {}),\n reconnectAfterMs: phoenixExponentialBackoff(\n 100,\n this.options.maxReconnectMs ?? 10_000,\n ),\n rejoinAfterMs: phoenixExponentialBackoff(\n 1_000,\n this.options.maxRejoinMs ?? 30_000,\n ),\n });\n socket.connect();\n return socket;\n }\n\n private createRunnerEventPayload(\n event: BaseEvent,\n request: AgentRunnerRunRequest,\n state: ThreadState,\n ): Record<string, unknown> {\n const canonicalEvent = this.stampRunnerMetadata(\n this.stampCanonicalRunOwnership(event, request),\n state,\n );\n const payload = {\n ...(canonicalEvent as Record<string, unknown>),\n };\n\n payload.threadId = request.threadId;\n payload.runId = request.input.runId;\n payload.thread_id = request.threadId;\n payload.run_id = request.input.runId;\n\n return payload;\n }\n\n private stampCanonicalRunOwnership(\n event: BaseEvent,\n request: AgentRunnerRunRequest,\n ): BaseEvent {\n return {\n ...(event as BaseEvent & Record<string, unknown>),\n threadId: request.threadId,\n runId: request.input.runId,\n } as BaseEvent;\n }\n\n private stampRunnerMetadata(event: BaseEvent, state: ThreadState): BaseEvent {\n const eventRecord = event as BaseEvent & {\n metadata?: Record<string, unknown>;\n };\n\n const existingMetadata = eventRecord.metadata ?? {};\n const hasEventId = typeof existingMetadata.cpki_event_id === \"string\";\n const hasEventSeq = typeof existingMetadata.cpki_event_seq === \"number\";\n\n if (hasEventId && hasEventSeq) {\n const eventSeq = existingMetadata.cpki_event_seq as number;\n state.nextEventSeq = Math.max(state.nextEventSeq, eventSeq + 1);\n return eventRecord;\n }\n\n const eventSeq = state.nextEventSeq++;\n\n return {\n ...eventRecord,\n metadata: {\n ...existingMetadata,\n cpki_event_id:\n typeof existingMetadata.cpki_event_id === \"string\"\n ? existingMetadata.cpki_event_id\n : randomUUID(),\n cpki_event_seq: eventSeq,\n },\n };\n }\n\n run(request: AgentRunnerRunRequest): Observable<BaseEvent> {\n return this.createRunObservable(request);\n }\n\n runWithStartupBoundary(\n request: AgentRunnerRunRequest,\n ): RunnerStartupBoundary {\n let resolveStartup: (() => void) | undefined;\n let rejectStartup: ((reason: Error) => void) | undefined;\n const startup = new Promise<void>((resolve, reject) => {\n resolveStartup = resolve;\n rejectStartup = reject;\n });\n\n return {\n events: this.createRunObservable(request, {\n resolveStartup: () => resolveStartup?.(),\n rejectStartup: (error) => rejectStartup?.(error),\n }),\n startup,\n };\n }\n\n private createRunObservable(\n request: AgentRunnerRunRequest,\n startupBoundary?: {\n resolveStartup: () => void;\n rejectStartup: (error: Error) => void;\n },\n ): Observable<BaseEvent> {\n const { threadId, agent, input } = request;\n\n const existing = this.threads.get(threadId);\n if (existing?.isRunning) {\n throw new Error(\"Thread already running\");\n }\n\n return new Observable((observer) => {\n const socket = this.createSocket();\n\n const channel = socket.channel(`ingestion:${input.runId}`, {\n thread_id: threadId,\n run_id: input.runId,\n });\n\n const state: ThreadState = {\n socket,\n channel,\n isRunning: true,\n stopRequested: false,\n agent,\n currentEvents: [],\n nextEventSeq: 1,\n hasRunStarted: false,\n };\n this.threads.set(threadId, state);\n\n // Track consecutive socket errors for this run. Phoenix retries\n // automatically via reconnectAfterMs, but if the connection fails\n // repeatedly we abort the agent — otherwise runAgent() completes\n // normally, finalization events buffer silently on the dead\n // channel, and the client never receives them.\n //\n // Aborting the agent is the single trigger that cascades through\n // the existing error pipeline: runAgent() rejects → catchError\n // pushes RUN_ERROR → finalize calls finalizeRunEvents +\n // removeThread → channel.leave() + socket.disconnect().\n const MAX_CONSECUTIVE_ERRORS = 5;\n let consecutiveErrors = 0;\n\n socket.onError(() => {\n consecutiveErrors++;\n if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS && state.agent) {\n try {\n state.agent.abortRun();\n } catch {\n // Ignore abort errors.\n }\n }\n // Otherwise: Phoenix retries automatically using the exponential\n // backoff schedule configured in createSocket().\n });\n\n socket.onOpen(() => {\n // A successful (re)connection resets the counter so transient\n // network blips don't accumulate across recoveries.\n consecutiveErrors = 0;\n });\n\n // Listen for custom \"stop\" events pushed by the client over the\n // channel. This must be registered before channel.join() so the\n // handler is in place by the time the server starts relaying messages.\n // The client sends the stop event before leaving the channel, so the\n // runner is guaranteed to receive it while still joined.\n channel.on(AG_UI_CHANNEL_EVENT, (payload: BaseEvent) => {\n if (\n payload.type === EventType.CUSTOM &&\n (payload as BaseEvent & { name?: string }).name === \"stop\"\n ) {\n this.stop({ threadId });\n }\n });\n\n channel\n .join()\n .receive(\"ok\", () => {\n startupBoundary?.resolveStartup();\n this.executeAgentRun(request, state, threadId).subscribe({\n complete: () => observer.complete(),\n });\n })\n .receive(\"error\", (resp) => {\n const error = new Error(\n `Failed to join channel: ${JSON.stringify(resp)}`,\n );\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: error.message,\n code: \"CHANNEL_JOIN_ERROR\",\n } as BaseEvent;\n observer.next(errorEvent);\n state.currentEvents.push(errorEvent);\n this.removeThread(threadId);\n startupBoundary?.rejectStartup(error);\n observer.complete();\n })\n .receive(\"timeout\", () => {\n const error = new Error(\"Timed out joining channel\");\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: error.message,\n code: \"CHANNEL_JOIN_TIMEOUT\",\n } as BaseEvent;\n observer.next(errorEvent);\n state.currentEvents.push(errorEvent);\n this.removeThread(threadId);\n startupBoundary?.rejectStartup(error);\n observer.complete();\n });\n\n return () => {\n this.removeThread(threadId);\n };\n });\n }\n\n connect(request: AgentRunnerConnectRequest): Observable<BaseEvent> {\n const { threadId } = request;\n\n return new Observable((observer) => {\n const socket = this.createSocket();\n\n const channel = socket.channel(`thread:${threadId}`);\n\n channel.on(\"ag_ui_event\", (payload: BaseEvent) => {\n observer.next(payload);\n\n if (\n payload.type === EventType.RUN_FINISHED ||\n payload.type === EventType.RUN_ERROR\n ) {\n observer.complete();\n }\n });\n\n const cleanup = () => {\n channel.leave();\n socket.disconnect();\n };\n\n channel\n .join()\n .receive(\"ok\", () => undefined)\n .receive(\"error\", (resp) => {\n observer.error(\n new Error(`Failed to join channel: ${JSON.stringify(resp)}`),\n );\n cleanup();\n })\n .receive(\"timeout\", () => {\n observer.error(new Error(\"Timed out joining channel\"));\n cleanup();\n });\n\n return () => {\n cleanup();\n };\n });\n }\n\n isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean> {\n const state = this.threads.get(request.threadId);\n return Promise.resolve(state?.isRunning ?? false);\n }\n\n stop(request: AgentRunnerStopRequest): Promise<boolean | undefined> {\n const state = this.threads.get(request.threadId);\n if (!state || !state.isRunning || state.stopRequested) {\n return Promise.resolve(false);\n }\n\n state.stopRequested = true;\n\n // Direct local abort — the runtime is the authority.\n if (state.agent) {\n try {\n state.agent.abortRun();\n } catch {\n // Ignore abort errors.\n }\n }\n\n return Promise.resolve(true);\n }\n\n private executeAgentRun(\n request: AgentRunnerRunRequest,\n state: ThreadState,\n threadId: string,\n ): Observable<void> {\n const { currentEvents, channel } = state;\n const pushCanonicalEvent = (event: BaseEvent): void => {\n const canonicalEvent = this.stampRunnerMetadata(\n this.stampCanonicalRunOwnership(event, request),\n state,\n );\n currentEvents.push(canonicalEvent);\n\n if (canonicalEvent.type === EventType.RUN_STARTED) {\n state.hasRunStarted = true;\n }\n\n channel.push(\n \"event\",\n this.createRunnerEventPayload(canonicalEvent, request, state),\n );\n };\n\n const getPersistedInputMessages = () =>\n request.persistedInputMessages ?? request.input.messages;\n\n const buildRunStartedEvent = (\n source?: RunStartedEvent,\n ): RunStartedEvent => {\n const baseInput = source?.input ?? request.input;\n const persistedInputMessages = getPersistedInputMessages();\n\n return {\n ...(source ?? {\n type: EventType.RUN_STARTED,\n threadId: request.threadId,\n runId: request.input.runId,\n }),\n threadId: request.threadId,\n runId: request.input.runId,\n input: {\n ...baseInput,\n threadId: request.threadId,\n runId: request.input.runId,\n ...(persistedInputMessages !== undefined\n ? { messages: persistedInputMessages }\n : {}),\n },\n } as RunStartedEvent;\n };\n\n const ensureRunStarted = (): void => {\n if (!state.hasRunStarted) {\n state.hasRunStarted = true;\n pushCanonicalEvent(buildRunStartedEvent());\n }\n };\n\n return from(\n request.agent.runAgent(request.input, {\n onEvent: ({ event }: { event: BaseEvent }) => {\n if (event.type === EventType.RUN_STARTED) {\n pushCanonicalEvent(buildRunStartedEvent(event as RunStartedEvent));\n return;\n }\n\n ensureRunStarted();\n pushCanonicalEvent(event);\n },\n }),\n ).pipe(\n catchError((error) => {\n ensureRunStarted();\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: error instanceof Error ? error.message : String(error),\n } as BaseEvent;\n pushCanonicalEvent(errorEvent);\n return EMPTY;\n }),\n finalize(() => {\n ensureRunStarted();\n const appended = finalizeRunEvents(currentEvents, {\n stopRequested: state.stopRequested,\n });\n for (const event of appended) {\n channel.push(\n \"event\",\n this.createRunnerEventPayload(event, request, state),\n );\n }\n this.removeThread(threadId);\n }),\n );\n }\n\n /**\n * Tear down all resources for a thread: leave the channel,\n * disconnect the per-run socket, and remove the thread state.\n *\n * Idempotent — safe to call multiple times for the same threadId\n * (e.g. from join error handlers, finalize, and Observable teardown).\n */\n private removeThread(threadId: string): void {\n const state = this.threads.get(threadId);\n if (!state) {\n return;\n }\n\n // Delete first so concurrent calls see the entry as already removed.\n this.threads.delete(threadId);\n\n try {\n state.channel.leave();\n } catch {\n // Channel may already be closed/left.\n }\n try {\n state.socket.disconnect();\n } catch {\n // Socket may already be disconnected.\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -14,6 +14,10 @@ interface IntelligenceAgentRunnerOptions {
|
|
|
14
14
|
/** Max delay (ms) for channel rejoin backoff. @default 30_000 */
|
|
15
15
|
maxRejoinMs?: number;
|
|
16
16
|
}
|
|
17
|
+
interface RunnerStartupBoundary {
|
|
18
|
+
events: Observable<BaseEvent>;
|
|
19
|
+
startup: Promise<void>;
|
|
20
|
+
}
|
|
17
21
|
declare class IntelligenceAgentRunner extends AgentRunner {
|
|
18
22
|
private options;
|
|
19
23
|
private threads;
|
|
@@ -41,8 +45,11 @@ declare class IntelligenceAgentRunner extends AgentRunner {
|
|
|
41
45
|
*/
|
|
42
46
|
private createSocket;
|
|
43
47
|
private createRunnerEventPayload;
|
|
48
|
+
private stampCanonicalRunOwnership;
|
|
44
49
|
private stampRunnerMetadata;
|
|
45
50
|
run(request: AgentRunnerRunRequest): Observable<BaseEvent>;
|
|
51
|
+
runWithStartupBoundary(request: AgentRunnerRunRequest): RunnerStartupBoundary;
|
|
52
|
+
private createRunObservable;
|
|
46
53
|
connect(request: AgentRunnerConnectRequest): Observable<BaseEvent>;
|
|
47
54
|
isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean>;
|
|
48
55
|
stop(request: AgentRunnerStopRequest): Promise<boolean | undefined>;
|
|
@@ -57,5 +64,5 @@ declare class IntelligenceAgentRunner extends AgentRunner {
|
|
|
57
64
|
private removeThread;
|
|
58
65
|
}
|
|
59
66
|
//#endregion
|
|
60
|
-
export { IntelligenceAgentRunner, IntelligenceAgentRunnerOptions };
|
|
67
|
+
export { IntelligenceAgentRunner, IntelligenceAgentRunnerOptions, RunnerStartupBoundary };
|
|
61
68
|
//# sourceMappingURL=intelligence.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intelligence.d.cts","names":[],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"mappings":";;;;;;UAuBiB,8BAAA;;EAEf,GAAA;EAF6C;EAI7C,SAAA;EAJ6C;EAM7C,cAAA;EAFA;EAIA,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"intelligence.d.cts","names":[],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"mappings":";;;;;;UAuBiB,8BAAA;;EAEf,GAAA;EAF6C;EAI7C,SAAA;EAJ6C;EAM7C,cAAA;EAFA;EAIA,WAAA;AAAA;AAAA,UAGe,qBAAA;EACf,MAAA,EAAQ,UAAA,CAAW,SAAA;EACnB,OAAA,EAAS,OAAA;AAAA;AAAA,cAcE,uBAAA,SAAgC,WAAA;EAAA,QACnC,OAAA;EAAA,QACA,OAAA;cAEI,OAAA,EAAS,8BAAA;EAlBL;;;;;;;;;AAclB;;;;;;;;;;;;EAdkB,QA6CR,YAAA;EAAA,QAgBA,wBAAA;EAAA,QAqBA,0BAAA;EAAA,QAWA,mBAAA;EA8BR,GAAA,CAAI,OAAA,EAAS,qBAAA,GAAwB,UAAA,CAAW,SAAA;EAIhD,sBAAA,CACE,OAAA,EAAS,qBAAA,GACR,qBAAA;EAAA,QAiBK,mBAAA;EA2HR,OAAA,CAAQ,OAAA,EAAS,yBAAA,GAA4B,UAAA,CAAW,SAAA;EA4CxD,SAAA,CAAU,OAAA,EAAS,2BAAA,GAA8B,OAAA;EAKjD,IAAA,CAAK,OAAA,EAAS,sBAAA,GAAyB,OAAA;EAAA,QAoB/B,eAAA;EAhUa;;;;;;;EAAA,QAuab,YAAA;AAAA"}
|
|
@@ -14,6 +14,10 @@ interface IntelligenceAgentRunnerOptions {
|
|
|
14
14
|
/** Max delay (ms) for channel rejoin backoff. @default 30_000 */
|
|
15
15
|
maxRejoinMs?: number;
|
|
16
16
|
}
|
|
17
|
+
interface RunnerStartupBoundary {
|
|
18
|
+
events: Observable<BaseEvent>;
|
|
19
|
+
startup: Promise<void>;
|
|
20
|
+
}
|
|
17
21
|
declare class IntelligenceAgentRunner extends AgentRunner {
|
|
18
22
|
private options;
|
|
19
23
|
private threads;
|
|
@@ -41,8 +45,11 @@ declare class IntelligenceAgentRunner extends AgentRunner {
|
|
|
41
45
|
*/
|
|
42
46
|
private createSocket;
|
|
43
47
|
private createRunnerEventPayload;
|
|
48
|
+
private stampCanonicalRunOwnership;
|
|
44
49
|
private stampRunnerMetadata;
|
|
45
50
|
run(request: AgentRunnerRunRequest): Observable<BaseEvent>;
|
|
51
|
+
runWithStartupBoundary(request: AgentRunnerRunRequest): RunnerStartupBoundary;
|
|
52
|
+
private createRunObservable;
|
|
46
53
|
connect(request: AgentRunnerConnectRequest): Observable<BaseEvent>;
|
|
47
54
|
isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean>;
|
|
48
55
|
stop(request: AgentRunnerStopRequest): Promise<boolean | undefined>;
|
|
@@ -57,5 +64,5 @@ declare class IntelligenceAgentRunner extends AgentRunner {
|
|
|
57
64
|
private removeThread;
|
|
58
65
|
}
|
|
59
66
|
//#endregion
|
|
60
|
-
export { IntelligenceAgentRunner, IntelligenceAgentRunnerOptions };
|
|
67
|
+
export { IntelligenceAgentRunner, IntelligenceAgentRunnerOptions, RunnerStartupBoundary };
|
|
61
68
|
//# sourceMappingURL=intelligence.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intelligence.d.mts","names":[],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"mappings":";;;;;;UAuBiB,8BAAA;;EAEf,GAAA;EAF6C;EAI7C,SAAA;EAJ6C;EAM7C,cAAA;EAFA;EAIA,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"intelligence.d.mts","names":[],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"mappings":";;;;;;UAuBiB,8BAAA;;EAEf,GAAA;EAF6C;EAI7C,SAAA;EAJ6C;EAM7C,cAAA;EAFA;EAIA,WAAA;AAAA;AAAA,UAGe,qBAAA;EACf,MAAA,EAAQ,UAAA,CAAW,SAAA;EACnB,OAAA,EAAS,OAAA;AAAA;AAAA,cAcE,uBAAA,SAAgC,WAAA;EAAA,QACnC,OAAA;EAAA,QACA,OAAA;cAEI,OAAA,EAAS,8BAAA;EAlBL;;;;;;;;;AAclB;;;;;;;;;;;;EAdkB,QA6CR,YAAA;EAAA,QAgBA,wBAAA;EAAA,QAqBA,0BAAA;EAAA,QAWA,mBAAA;EA8BR,GAAA,CAAI,OAAA,EAAS,qBAAA,GAAwB,UAAA,CAAW,SAAA;EAIhD,sBAAA,CACE,OAAA,EAAS,qBAAA,GACR,qBAAA;EAAA,QAiBK,mBAAA;EA2HR,OAAA,CAAQ,OAAA,EAAS,yBAAA,GAA4B,UAAA,CAAW,SAAA;EA4CxD,SAAA,CAAU,OAAA,EAAS,2BAAA,GAA8B,OAAA;EAKjD,IAAA,CAAK,OAAA,EAAS,sBAAA,GAAyB,OAAA;EAAA,QAoB/B,eAAA;EAhUa;;;;;;;EAAA,QAuab,YAAA;AAAA"}
|
|
@@ -45,12 +45,20 @@ var IntelligenceAgentRunner = class extends AgentRunner {
|
|
|
45
45
|
return socket;
|
|
46
46
|
}
|
|
47
47
|
createRunnerEventPayload(event, request, state) {
|
|
48
|
-
const payload = { ...this.stampRunnerMetadata(event, state) };
|
|
49
|
-
payload.
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
const payload = { ...this.stampRunnerMetadata(this.stampCanonicalRunOwnership(event, request), state) };
|
|
49
|
+
payload.threadId = request.threadId;
|
|
50
|
+
payload.runId = request.input.runId;
|
|
51
|
+
payload.thread_id = request.threadId;
|
|
52
|
+
payload.run_id = request.input.runId;
|
|
52
53
|
return payload;
|
|
53
54
|
}
|
|
55
|
+
stampCanonicalRunOwnership(event, request) {
|
|
56
|
+
return {
|
|
57
|
+
...event,
|
|
58
|
+
threadId: request.threadId,
|
|
59
|
+
runId: request.input.runId
|
|
60
|
+
};
|
|
61
|
+
}
|
|
54
62
|
stampRunnerMetadata(event, state) {
|
|
55
63
|
const eventRecord = event;
|
|
56
64
|
const existingMetadata = eventRecord.metadata ?? {};
|
|
@@ -72,12 +80,32 @@ var IntelligenceAgentRunner = class extends AgentRunner {
|
|
|
72
80
|
};
|
|
73
81
|
}
|
|
74
82
|
run(request) {
|
|
75
|
-
|
|
83
|
+
return this.createRunObservable(request);
|
|
84
|
+
}
|
|
85
|
+
runWithStartupBoundary(request) {
|
|
86
|
+
let resolveStartup;
|
|
87
|
+
let rejectStartup;
|
|
88
|
+
const startup = new Promise((resolve, reject) => {
|
|
89
|
+
resolveStartup = resolve;
|
|
90
|
+
rejectStartup = reject;
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
events: this.createRunObservable(request, {
|
|
94
|
+
resolveStartup: () => resolveStartup?.(),
|
|
95
|
+
rejectStartup: (error) => rejectStartup?.(error)
|
|
96
|
+
}),
|
|
97
|
+
startup
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
createRunObservable(request, startupBoundary) {
|
|
101
|
+
const { threadId, agent, input } = request;
|
|
76
102
|
if (this.threads.get(threadId)?.isRunning) throw new Error("Thread already running");
|
|
77
103
|
return new Observable((observer) => {
|
|
78
104
|
const socket = this.createSocket();
|
|
79
|
-
const
|
|
80
|
-
|
|
105
|
+
const channel = socket.channel(`ingestion:${input.runId}`, {
|
|
106
|
+
thread_id: threadId,
|
|
107
|
+
run_id: input.runId
|
|
108
|
+
});
|
|
81
109
|
const state = {
|
|
82
110
|
socket,
|
|
83
111
|
channel,
|
|
@@ -104,26 +132,31 @@ var IntelligenceAgentRunner = class extends AgentRunner {
|
|
|
104
132
|
if (payload.type === EventType.CUSTOM && payload.name === "stop") this.stop({ threadId });
|
|
105
133
|
});
|
|
106
134
|
channel.join().receive("ok", () => {
|
|
135
|
+
startupBoundary?.resolveStartup();
|
|
107
136
|
this.executeAgentRun(request, state, threadId).subscribe({ complete: () => observer.complete() });
|
|
108
137
|
}).receive("error", (resp) => {
|
|
138
|
+
const error = /* @__PURE__ */ new Error(`Failed to join channel: ${JSON.stringify(resp)}`);
|
|
109
139
|
const errorEvent = {
|
|
110
140
|
type: EventType.RUN_ERROR,
|
|
111
|
-
message:
|
|
141
|
+
message: error.message,
|
|
112
142
|
code: "CHANNEL_JOIN_ERROR"
|
|
113
143
|
};
|
|
114
144
|
observer.next(errorEvent);
|
|
115
145
|
state.currentEvents.push(errorEvent);
|
|
116
146
|
this.removeThread(threadId);
|
|
147
|
+
startupBoundary?.rejectStartup(error);
|
|
117
148
|
observer.complete();
|
|
118
149
|
}).receive("timeout", () => {
|
|
150
|
+
const error = /* @__PURE__ */ new Error("Timed out joining channel");
|
|
119
151
|
const errorEvent = {
|
|
120
152
|
type: EventType.RUN_ERROR,
|
|
121
|
-
message:
|
|
153
|
+
message: error.message,
|
|
122
154
|
code: "CHANNEL_JOIN_TIMEOUT"
|
|
123
155
|
};
|
|
124
156
|
observer.next(errorEvent);
|
|
125
157
|
state.currentEvents.push(errorEvent);
|
|
126
158
|
this.removeThread(threadId);
|
|
159
|
+
startupBoundary?.rejectStartup(error);
|
|
127
160
|
observer.complete();
|
|
128
161
|
});
|
|
129
162
|
return () => {
|
|
@@ -172,7 +205,7 @@ var IntelligenceAgentRunner = class extends AgentRunner {
|
|
|
172
205
|
executeAgentRun(request, state, threadId) {
|
|
173
206
|
const { currentEvents, channel } = state;
|
|
174
207
|
const pushCanonicalEvent = (event) => {
|
|
175
|
-
const canonicalEvent = this.stampRunnerMetadata(event, state);
|
|
208
|
+
const canonicalEvent = this.stampRunnerMetadata(this.stampCanonicalRunOwnership(event, request), state);
|
|
176
209
|
currentEvents.push(canonicalEvent);
|
|
177
210
|
if (canonicalEvent.type === EventType.RUN_STARTED) state.hasRunStarted = true;
|
|
178
211
|
channel.push("event", this.createRunnerEventPayload(canonicalEvent, request, state));
|
|
@@ -187,8 +220,12 @@ var IntelligenceAgentRunner = class extends AgentRunner {
|
|
|
187
220
|
threadId: request.threadId,
|
|
188
221
|
runId: request.input.runId
|
|
189
222
|
},
|
|
223
|
+
threadId: request.threadId,
|
|
224
|
+
runId: request.input.runId,
|
|
190
225
|
input: {
|
|
191
226
|
...baseInput,
|
|
227
|
+
threadId: request.threadId,
|
|
228
|
+
runId: request.input.runId,
|
|
192
229
|
...persistedInputMessages !== void 0 ? { messages: persistedInputMessages } : {}
|
|
193
230
|
}
|
|
194
231
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intelligence.mjs","names":["randomUUID","catchError","finalize"],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"sourcesContent":["import {\n AgentRunner,\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n type AgentRunnerStopRequest,\n} from \"./agent-runner\";\nimport { EMPTY, Observable, from } from \"rxjs\";\nimport { catchError, finalize } from \"rxjs/operators\";\nimport {\n AbstractAgent,\n BaseEvent,\n EventType,\n RunStartedEvent,\n} from \"@ag-ui/client\";\nimport {\n finalizeRunEvents,\n AG_UI_CHANNEL_EVENT,\n phoenixExponentialBackoff,\n} from \"@copilotkit/shared\";\nimport { Socket, Channel } from \"phoenix\";\nimport { randomUUID } from \"node:crypto\";\n\nexport interface IntelligenceAgentRunnerOptions {\n /** Phoenix runner websocket URL, e.g. \"ws://localhost:4000/runner\" */\n url: string;\n /** Optional Phoenix socket auth token used during websocket connect. */\n authToken?: string;\n /** Max delay (ms) for WebSocket reconnect backoff. @default 10_000 */\n maxReconnectMs?: number;\n /** Max delay (ms) for channel rejoin backoff. @default 30_000 */\n maxRejoinMs?: number;\n}\n\ninterface ThreadState {\n socket: Socket;\n channel: Channel;\n isRunning: boolean;\n stopRequested: boolean;\n agent: AbstractAgent | null;\n currentEvents: BaseEvent[];\n nextEventSeq: number;\n hasRunStarted: boolean;\n}\n\nexport class IntelligenceAgentRunner extends AgentRunner {\n private options: IntelligenceAgentRunnerOptions;\n private threads = new Map<string, ThreadState>();\n\n constructor(options: IntelligenceAgentRunnerOptions) {\n super();\n // Store config — sockets are created per-run, not eagerly.\n this.options = options;\n }\n\n /**\n * Create a new Phoenix socket with explicit exponential backoff.\n *\n * Each run/connect gets its own socket so that:\n * - A socket failure only affects a single thread, not all threads.\n * - Cleanup is simple: channel.leave() + socket.disconnect() tears\n * down everything for that run with no shared-state concerns.\n * - Each run gets its own independent retry budget.\n *\n * reconnectAfterMs — delay before Phoenix reconnects the WebSocket\n * after an unclean close. 100ms base, doubling up to maxReconnectMs (default 10s).\n *\n * rejoinAfterMs — delay before Phoenix re-joins a channel that\n * entered the \"errored\" state. 1s base, doubling up to maxRejoinMs (default 30s).\n *\n * These are set explicitly because Phoenix's default schedule is a\n * fixed stepped array (not exponential), and any code that calls\n * socket.disconnect() in an onError handler will set\n * closeWasClean = true and reset the reconnect timer — permanently\n * killing retries.\n */\n private createSocket(): Socket {\n const socket = new Socket(this.options.url, {\n ...(this.options.authToken ? { authToken: this.options.authToken } : {}),\n reconnectAfterMs: phoenixExponentialBackoff(\n 100,\n this.options.maxReconnectMs ?? 10_000,\n ),\n rejoinAfterMs: phoenixExponentialBackoff(\n 1_000,\n this.options.maxRejoinMs ?? 30_000,\n ),\n });\n socket.connect();\n return socket;\n }\n\n private createRunnerEventPayload(\n event: BaseEvent,\n request: AgentRunnerRunRequest,\n state: ThreadState,\n ): Record<string, unknown> {\n const canonicalEvent = this.stampRunnerMetadata(event, state);\n const payload = {\n ...(canonicalEvent as Record<string, unknown>),\n };\n\n payload.thread_id ??= request.threadId;\n\n const runId = payload.runId ?? payload.run_id ?? request.input.runId;\n\n if (runId) {\n payload.run_id = runId;\n }\n\n return payload;\n }\n\n private stampRunnerMetadata(event: BaseEvent, state: ThreadState): BaseEvent {\n const eventRecord = event as BaseEvent & {\n metadata?: Record<string, unknown>;\n };\n\n const existingMetadata = eventRecord.metadata ?? {};\n const hasEventId = typeof existingMetadata.cpki_event_id === \"string\";\n const hasEventSeq = typeof existingMetadata.cpki_event_seq === \"number\";\n\n if (hasEventId && hasEventSeq) {\n const eventSeq = existingMetadata.cpki_event_seq as number;\n state.nextEventSeq = Math.max(state.nextEventSeq, eventSeq + 1);\n return eventRecord;\n }\n\n const eventSeq = state.nextEventSeq++;\n\n return {\n ...eventRecord,\n metadata: {\n ...existingMetadata,\n cpki_event_id:\n typeof existingMetadata.cpki_event_id === \"string\"\n ? existingMetadata.cpki_event_id\n : randomUUID(),\n cpki_event_seq: eventSeq,\n },\n };\n }\n\n run(request: AgentRunnerRunRequest): Observable<BaseEvent> {\n const { threadId, agent, input, joinCode } = request;\n\n const existing = this.threads.get(threadId);\n if (existing?.isRunning) {\n throw new Error(\"Thread already running\");\n }\n\n return new Observable((observer) => {\n const socket = this.createSocket();\n\n const channelTopic = joinCode ?? threadId;\n const channel = socket.channel(`ingestion:${channelTopic}`, {\n runId: input.runId,\n });\n\n const state: ThreadState = {\n socket,\n channel,\n isRunning: true,\n stopRequested: false,\n agent,\n currentEvents: [],\n nextEventSeq: 1,\n hasRunStarted: false,\n };\n this.threads.set(threadId, state);\n\n // Track consecutive socket errors for this run. Phoenix retries\n // automatically via reconnectAfterMs, but if the connection fails\n // repeatedly we abort the agent — otherwise runAgent() completes\n // normally, finalization events buffer silently on the dead\n // channel, and the client never receives them.\n //\n // Aborting the agent is the single trigger that cascades through\n // the existing error pipeline: runAgent() rejects → catchError\n // pushes RUN_ERROR → finalize calls finalizeRunEvents +\n // removeThread → channel.leave() + socket.disconnect().\n const MAX_CONSECUTIVE_ERRORS = 5;\n let consecutiveErrors = 0;\n\n socket.onError(() => {\n consecutiveErrors++;\n if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS && state.agent) {\n try {\n state.agent.abortRun();\n } catch {\n // Ignore abort errors.\n }\n }\n // Otherwise: Phoenix retries automatically using the exponential\n // backoff schedule configured in createSocket().\n });\n\n socket.onOpen(() => {\n // A successful (re)connection resets the counter so transient\n // network blips don't accumulate across recoveries.\n consecutiveErrors = 0;\n });\n\n // Listen for custom \"stop\" events pushed by the client over the\n // channel. This must be registered before channel.join() so the\n // handler is in place by the time the server starts relaying messages.\n // The client sends the stop event before leaving the channel, so the\n // runner is guaranteed to receive it while still joined.\n channel.on(AG_UI_CHANNEL_EVENT, (payload: BaseEvent) => {\n if (\n payload.type === EventType.CUSTOM &&\n (payload as BaseEvent & { name?: string }).name === \"stop\"\n ) {\n this.stop({ threadId });\n }\n });\n\n channel\n .join()\n .receive(\"ok\", () => {\n this.executeAgentRun(request, state, threadId).subscribe({\n complete: () => observer.complete(),\n });\n })\n .receive(\"error\", (resp) => {\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: `Failed to join channel: ${JSON.stringify(resp)}`,\n code: \"CHANNEL_JOIN_ERROR\",\n } as BaseEvent;\n observer.next(errorEvent);\n state.currentEvents.push(errorEvent);\n this.removeThread(threadId);\n observer.complete();\n })\n .receive(\"timeout\", () => {\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: \"Timed out joining channel\",\n code: \"CHANNEL_JOIN_TIMEOUT\",\n } as BaseEvent;\n observer.next(errorEvent);\n state.currentEvents.push(errorEvent);\n this.removeThread(threadId);\n observer.complete();\n });\n\n return () => {\n this.removeThread(threadId);\n };\n });\n }\n\n connect(request: AgentRunnerConnectRequest): Observable<BaseEvent> {\n const { threadId } = request;\n\n return new Observable((observer) => {\n const socket = this.createSocket();\n\n const channel = socket.channel(`thread:${threadId}`);\n\n channel.on(\"ag_ui_event\", (payload: BaseEvent) => {\n observer.next(payload);\n\n if (\n payload.type === EventType.RUN_FINISHED ||\n payload.type === EventType.RUN_ERROR\n ) {\n observer.complete();\n }\n });\n\n const cleanup = () => {\n channel.leave();\n socket.disconnect();\n };\n\n channel\n .join()\n .receive(\"ok\", () => undefined)\n .receive(\"error\", (resp) => {\n observer.error(\n new Error(`Failed to join channel: ${JSON.stringify(resp)}`),\n );\n cleanup();\n })\n .receive(\"timeout\", () => {\n observer.error(new Error(\"Timed out joining channel\"));\n cleanup();\n });\n\n return () => {\n cleanup();\n };\n });\n }\n\n isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean> {\n const state = this.threads.get(request.threadId);\n return Promise.resolve(state?.isRunning ?? false);\n }\n\n stop(request: AgentRunnerStopRequest): Promise<boolean | undefined> {\n const state = this.threads.get(request.threadId);\n if (!state || !state.isRunning || state.stopRequested) {\n return Promise.resolve(false);\n }\n\n state.stopRequested = true;\n\n // Direct local abort — the runtime is the authority.\n if (state.agent) {\n try {\n state.agent.abortRun();\n } catch {\n // Ignore abort errors.\n }\n }\n\n return Promise.resolve(true);\n }\n\n private executeAgentRun(\n request: AgentRunnerRunRequest,\n state: ThreadState,\n threadId: string,\n ): Observable<void> {\n const { currentEvents, channel } = state;\n const pushCanonicalEvent = (event: BaseEvent): void => {\n const canonicalEvent = this.stampRunnerMetadata(event, state);\n currentEvents.push(canonicalEvent);\n\n if (canonicalEvent.type === EventType.RUN_STARTED) {\n state.hasRunStarted = true;\n }\n\n channel.push(\n \"event\",\n this.createRunnerEventPayload(canonicalEvent, request, state),\n );\n };\n\n const getPersistedInputMessages = () =>\n request.persistedInputMessages ?? request.input.messages;\n\n const buildRunStartedEvent = (\n source?: RunStartedEvent,\n ): RunStartedEvent => {\n const baseInput = source?.input ?? request.input;\n const persistedInputMessages = getPersistedInputMessages();\n\n return {\n ...(source ?? {\n type: EventType.RUN_STARTED,\n threadId: request.threadId,\n runId: request.input.runId,\n }),\n input: {\n ...baseInput,\n ...(persistedInputMessages !== undefined\n ? { messages: persistedInputMessages }\n : {}),\n },\n } as RunStartedEvent;\n };\n\n const ensureRunStarted = (): void => {\n if (!state.hasRunStarted) {\n state.hasRunStarted = true;\n pushCanonicalEvent(buildRunStartedEvent());\n }\n };\n\n return from(\n request.agent.runAgent(request.input, {\n onEvent: ({ event }: { event: BaseEvent }) => {\n if (event.type === EventType.RUN_STARTED) {\n pushCanonicalEvent(buildRunStartedEvent(event as RunStartedEvent));\n return;\n }\n\n ensureRunStarted();\n pushCanonicalEvent(event);\n },\n }),\n ).pipe(\n catchError((error) => {\n ensureRunStarted();\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: error instanceof Error ? error.message : String(error),\n } as BaseEvent;\n pushCanonicalEvent(errorEvent);\n return EMPTY;\n }),\n finalize(() => {\n ensureRunStarted();\n const appended = finalizeRunEvents(currentEvents, {\n stopRequested: state.stopRequested,\n });\n for (const event of appended) {\n channel.push(\n \"event\",\n this.createRunnerEventPayload(event, request, state),\n );\n }\n this.removeThread(threadId);\n }),\n );\n }\n\n /**\n * Tear down all resources for a thread: leave the channel,\n * disconnect the per-run socket, and remove the thread state.\n *\n * Idempotent — safe to call multiple times for the same threadId\n * (e.g. from join error handlers, finalize, and Observable teardown).\n */\n private removeThread(threadId: string): void {\n const state = this.threads.get(threadId);\n if (!state) {\n return;\n }\n\n // Delete first so concurrent calls see the entry as already removed.\n this.threads.delete(threadId);\n\n try {\n state.channel.leave();\n } catch {\n // Channel may already be closed/left.\n }\n try {\n state.socket.disconnect();\n } catch {\n // Socket may already be disconnected.\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"intelligence.mjs","names":["randomUUID","catchError","finalize"],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"sourcesContent":["import {\n AgentRunner,\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n type AgentRunnerStopRequest,\n} from \"./agent-runner\";\nimport { EMPTY, Observable, from } from \"rxjs\";\nimport { catchError, finalize } from \"rxjs/operators\";\nimport {\n AbstractAgent,\n BaseEvent,\n EventType,\n RunStartedEvent,\n} from \"@ag-ui/client\";\nimport {\n finalizeRunEvents,\n AG_UI_CHANNEL_EVENT,\n phoenixExponentialBackoff,\n} from \"@copilotkit/shared\";\nimport { Socket, Channel } from \"phoenix\";\nimport { randomUUID } from \"node:crypto\";\n\nexport interface IntelligenceAgentRunnerOptions {\n /** Phoenix runner websocket URL, e.g. \"ws://localhost:4000/runner\" */\n url: string;\n /** Optional Phoenix socket auth token used during websocket connect. */\n authToken?: string;\n /** Max delay (ms) for WebSocket reconnect backoff. @default 10_000 */\n maxReconnectMs?: number;\n /** Max delay (ms) for channel rejoin backoff. @default 30_000 */\n maxRejoinMs?: number;\n}\n\nexport interface RunnerStartupBoundary {\n events: Observable<BaseEvent>;\n startup: Promise<void>;\n}\n\ninterface ThreadState {\n socket: Socket;\n channel: Channel;\n isRunning: boolean;\n stopRequested: boolean;\n agent: AbstractAgent | null;\n currentEvents: BaseEvent[];\n nextEventSeq: number;\n hasRunStarted: boolean;\n}\n\nexport class IntelligenceAgentRunner extends AgentRunner {\n private options: IntelligenceAgentRunnerOptions;\n private threads = new Map<string, ThreadState>();\n\n constructor(options: IntelligenceAgentRunnerOptions) {\n super();\n // Store config — sockets are created per-run, not eagerly.\n this.options = options;\n }\n\n /**\n * Create a new Phoenix socket with explicit exponential backoff.\n *\n * Each run/connect gets its own socket so that:\n * - A socket failure only affects a single thread, not all threads.\n * - Cleanup is simple: channel.leave() + socket.disconnect() tears\n * down everything for that run with no shared-state concerns.\n * - Each run gets its own independent retry budget.\n *\n * reconnectAfterMs — delay before Phoenix reconnects the WebSocket\n * after an unclean close. 100ms base, doubling up to maxReconnectMs (default 10s).\n *\n * rejoinAfterMs — delay before Phoenix re-joins a channel that\n * entered the \"errored\" state. 1s base, doubling up to maxRejoinMs (default 30s).\n *\n * These are set explicitly because Phoenix's default schedule is a\n * fixed stepped array (not exponential), and any code that calls\n * socket.disconnect() in an onError handler will set\n * closeWasClean = true and reset the reconnect timer — permanently\n * killing retries.\n */\n private createSocket(): Socket {\n const socket = new Socket(this.options.url, {\n ...(this.options.authToken ? { authToken: this.options.authToken } : {}),\n reconnectAfterMs: phoenixExponentialBackoff(\n 100,\n this.options.maxReconnectMs ?? 10_000,\n ),\n rejoinAfterMs: phoenixExponentialBackoff(\n 1_000,\n this.options.maxRejoinMs ?? 30_000,\n ),\n });\n socket.connect();\n return socket;\n }\n\n private createRunnerEventPayload(\n event: BaseEvent,\n request: AgentRunnerRunRequest,\n state: ThreadState,\n ): Record<string, unknown> {\n const canonicalEvent = this.stampRunnerMetadata(\n this.stampCanonicalRunOwnership(event, request),\n state,\n );\n const payload = {\n ...(canonicalEvent as Record<string, unknown>),\n };\n\n payload.threadId = request.threadId;\n payload.runId = request.input.runId;\n payload.thread_id = request.threadId;\n payload.run_id = request.input.runId;\n\n return payload;\n }\n\n private stampCanonicalRunOwnership(\n event: BaseEvent,\n request: AgentRunnerRunRequest,\n ): BaseEvent {\n return {\n ...(event as BaseEvent & Record<string, unknown>),\n threadId: request.threadId,\n runId: request.input.runId,\n } as BaseEvent;\n }\n\n private stampRunnerMetadata(event: BaseEvent, state: ThreadState): BaseEvent {\n const eventRecord = event as BaseEvent & {\n metadata?: Record<string, unknown>;\n };\n\n const existingMetadata = eventRecord.metadata ?? {};\n const hasEventId = typeof existingMetadata.cpki_event_id === \"string\";\n const hasEventSeq = typeof existingMetadata.cpki_event_seq === \"number\";\n\n if (hasEventId && hasEventSeq) {\n const eventSeq = existingMetadata.cpki_event_seq as number;\n state.nextEventSeq = Math.max(state.nextEventSeq, eventSeq + 1);\n return eventRecord;\n }\n\n const eventSeq = state.nextEventSeq++;\n\n return {\n ...eventRecord,\n metadata: {\n ...existingMetadata,\n cpki_event_id:\n typeof existingMetadata.cpki_event_id === \"string\"\n ? existingMetadata.cpki_event_id\n : randomUUID(),\n cpki_event_seq: eventSeq,\n },\n };\n }\n\n run(request: AgentRunnerRunRequest): Observable<BaseEvent> {\n return this.createRunObservable(request);\n }\n\n runWithStartupBoundary(\n request: AgentRunnerRunRequest,\n ): RunnerStartupBoundary {\n let resolveStartup: (() => void) | undefined;\n let rejectStartup: ((reason: Error) => void) | undefined;\n const startup = new Promise<void>((resolve, reject) => {\n resolveStartup = resolve;\n rejectStartup = reject;\n });\n\n return {\n events: this.createRunObservable(request, {\n resolveStartup: () => resolveStartup?.(),\n rejectStartup: (error) => rejectStartup?.(error),\n }),\n startup,\n };\n }\n\n private createRunObservable(\n request: AgentRunnerRunRequest,\n startupBoundary?: {\n resolveStartup: () => void;\n rejectStartup: (error: Error) => void;\n },\n ): Observable<BaseEvent> {\n const { threadId, agent, input } = request;\n\n const existing = this.threads.get(threadId);\n if (existing?.isRunning) {\n throw new Error(\"Thread already running\");\n }\n\n return new Observable((observer) => {\n const socket = this.createSocket();\n\n const channel = socket.channel(`ingestion:${input.runId}`, {\n thread_id: threadId,\n run_id: input.runId,\n });\n\n const state: ThreadState = {\n socket,\n channel,\n isRunning: true,\n stopRequested: false,\n agent,\n currentEvents: [],\n nextEventSeq: 1,\n hasRunStarted: false,\n };\n this.threads.set(threadId, state);\n\n // Track consecutive socket errors for this run. Phoenix retries\n // automatically via reconnectAfterMs, but if the connection fails\n // repeatedly we abort the agent — otherwise runAgent() completes\n // normally, finalization events buffer silently on the dead\n // channel, and the client never receives them.\n //\n // Aborting the agent is the single trigger that cascades through\n // the existing error pipeline: runAgent() rejects → catchError\n // pushes RUN_ERROR → finalize calls finalizeRunEvents +\n // removeThread → channel.leave() + socket.disconnect().\n const MAX_CONSECUTIVE_ERRORS = 5;\n let consecutiveErrors = 0;\n\n socket.onError(() => {\n consecutiveErrors++;\n if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS && state.agent) {\n try {\n state.agent.abortRun();\n } catch {\n // Ignore abort errors.\n }\n }\n // Otherwise: Phoenix retries automatically using the exponential\n // backoff schedule configured in createSocket().\n });\n\n socket.onOpen(() => {\n // A successful (re)connection resets the counter so transient\n // network blips don't accumulate across recoveries.\n consecutiveErrors = 0;\n });\n\n // Listen for custom \"stop\" events pushed by the client over the\n // channel. This must be registered before channel.join() so the\n // handler is in place by the time the server starts relaying messages.\n // The client sends the stop event before leaving the channel, so the\n // runner is guaranteed to receive it while still joined.\n channel.on(AG_UI_CHANNEL_EVENT, (payload: BaseEvent) => {\n if (\n payload.type === EventType.CUSTOM &&\n (payload as BaseEvent & { name?: string }).name === \"stop\"\n ) {\n this.stop({ threadId });\n }\n });\n\n channel\n .join()\n .receive(\"ok\", () => {\n startupBoundary?.resolveStartup();\n this.executeAgentRun(request, state, threadId).subscribe({\n complete: () => observer.complete(),\n });\n })\n .receive(\"error\", (resp) => {\n const error = new Error(\n `Failed to join channel: ${JSON.stringify(resp)}`,\n );\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: error.message,\n code: \"CHANNEL_JOIN_ERROR\",\n } as BaseEvent;\n observer.next(errorEvent);\n state.currentEvents.push(errorEvent);\n this.removeThread(threadId);\n startupBoundary?.rejectStartup(error);\n observer.complete();\n })\n .receive(\"timeout\", () => {\n const error = new Error(\"Timed out joining channel\");\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: error.message,\n code: \"CHANNEL_JOIN_TIMEOUT\",\n } as BaseEvent;\n observer.next(errorEvent);\n state.currentEvents.push(errorEvent);\n this.removeThread(threadId);\n startupBoundary?.rejectStartup(error);\n observer.complete();\n });\n\n return () => {\n this.removeThread(threadId);\n };\n });\n }\n\n connect(request: AgentRunnerConnectRequest): Observable<BaseEvent> {\n const { threadId } = request;\n\n return new Observable((observer) => {\n const socket = this.createSocket();\n\n const channel = socket.channel(`thread:${threadId}`);\n\n channel.on(\"ag_ui_event\", (payload: BaseEvent) => {\n observer.next(payload);\n\n if (\n payload.type === EventType.RUN_FINISHED ||\n payload.type === EventType.RUN_ERROR\n ) {\n observer.complete();\n }\n });\n\n const cleanup = () => {\n channel.leave();\n socket.disconnect();\n };\n\n channel\n .join()\n .receive(\"ok\", () => undefined)\n .receive(\"error\", (resp) => {\n observer.error(\n new Error(`Failed to join channel: ${JSON.stringify(resp)}`),\n );\n cleanup();\n })\n .receive(\"timeout\", () => {\n observer.error(new Error(\"Timed out joining channel\"));\n cleanup();\n });\n\n return () => {\n cleanup();\n };\n });\n }\n\n isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean> {\n const state = this.threads.get(request.threadId);\n return Promise.resolve(state?.isRunning ?? false);\n }\n\n stop(request: AgentRunnerStopRequest): Promise<boolean | undefined> {\n const state = this.threads.get(request.threadId);\n if (!state || !state.isRunning || state.stopRequested) {\n return Promise.resolve(false);\n }\n\n state.stopRequested = true;\n\n // Direct local abort — the runtime is the authority.\n if (state.agent) {\n try {\n state.agent.abortRun();\n } catch {\n // Ignore abort errors.\n }\n }\n\n return Promise.resolve(true);\n }\n\n private executeAgentRun(\n request: AgentRunnerRunRequest,\n state: ThreadState,\n threadId: string,\n ): Observable<void> {\n const { currentEvents, channel } = state;\n const pushCanonicalEvent = (event: BaseEvent): void => {\n const canonicalEvent = this.stampRunnerMetadata(\n this.stampCanonicalRunOwnership(event, request),\n state,\n );\n currentEvents.push(canonicalEvent);\n\n if (canonicalEvent.type === EventType.RUN_STARTED) {\n state.hasRunStarted = true;\n }\n\n channel.push(\n \"event\",\n this.createRunnerEventPayload(canonicalEvent, request, state),\n );\n };\n\n const getPersistedInputMessages = () =>\n request.persistedInputMessages ?? request.input.messages;\n\n const buildRunStartedEvent = (\n source?: RunStartedEvent,\n ): RunStartedEvent => {\n const baseInput = source?.input ?? request.input;\n const persistedInputMessages = getPersistedInputMessages();\n\n return {\n ...(source ?? {\n type: EventType.RUN_STARTED,\n threadId: request.threadId,\n runId: request.input.runId,\n }),\n threadId: request.threadId,\n runId: request.input.runId,\n input: {\n ...baseInput,\n threadId: request.threadId,\n runId: request.input.runId,\n ...(persistedInputMessages !== undefined\n ? { messages: persistedInputMessages }\n : {}),\n },\n } as RunStartedEvent;\n };\n\n const ensureRunStarted = (): void => {\n if (!state.hasRunStarted) {\n state.hasRunStarted = true;\n pushCanonicalEvent(buildRunStartedEvent());\n }\n };\n\n return from(\n request.agent.runAgent(request.input, {\n onEvent: ({ event }: { event: BaseEvent }) => {\n if (event.type === EventType.RUN_STARTED) {\n pushCanonicalEvent(buildRunStartedEvent(event as RunStartedEvent));\n return;\n }\n\n ensureRunStarted();\n pushCanonicalEvent(event);\n },\n }),\n ).pipe(\n catchError((error) => {\n ensureRunStarted();\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: error instanceof Error ? error.message : String(error),\n } as BaseEvent;\n pushCanonicalEvent(errorEvent);\n return EMPTY;\n }),\n finalize(() => {\n ensureRunStarted();\n const appended = finalizeRunEvents(currentEvents, {\n stopRequested: state.stopRequested,\n });\n for (const event of appended) {\n channel.push(\n \"event\",\n this.createRunnerEventPayload(event, request, state),\n );\n }\n this.removeThread(threadId);\n }),\n );\n }\n\n /**\n * Tear down all resources for a thread: leave the channel,\n * disconnect the per-run socket, and remove the thread state.\n *\n * Idempotent — safe to call multiple times for the same threadId\n * (e.g. from join error handlers, finalize, and Observable teardown).\n */\n private removeThread(threadId: string): void {\n const state = this.threads.get(threadId);\n if (!state) {\n return;\n }\n\n // Delete first so concurrent calls see the entry as already removed.\n this.threads.delete(threadId);\n\n try {\n state.channel.leave();\n } catch {\n // Channel may already be closed/left.\n }\n try {\n state.socket.disconnect();\n } catch {\n // Socket may already be disconnected.\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require("reflect-metadata");
|
|
2
|
+
const require_telemetry_client = require('./telemetry-client.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/v2/runtime/telemetry/instance-created.ts
|
|
5
|
+
/**
|
|
6
|
+
* Fire the `oss.runtime.instance_created` telemetry event for a v2 runtime
|
|
7
|
+
* handler. Called once per handler factory invocation (not per request).
|
|
8
|
+
*
|
|
9
|
+
* v2 does not have a concept of remote endpoints or standalone actions, so
|
|
10
|
+
* those counts are 0 / []. `cloud.api_key_provided` is false at this level
|
|
11
|
+
* because in v2 the cloud public key arrives per-request via the
|
|
12
|
+
* `x-copilotcloud-public-api-key` header — not at handler creation time.
|
|
13
|
+
* See `handlers/handle-run.ts` for the per-request event that DOES carry
|
|
14
|
+
* the key when present.
|
|
15
|
+
*
|
|
16
|
+
* Errors resolving agents are swallowed — telemetry must never break
|
|
17
|
+
* runtime setup.
|
|
18
|
+
*/
|
|
19
|
+
function fireInstanceCreatedTelemetry({ runtime }) {
|
|
20
|
+
(typeof runtime.agents === "function" ? Promise.resolve(null) : Promise.resolve(runtime.agents)).then((agents) => {
|
|
21
|
+
require_telemetry_client.default.capture("oss.runtime.instance_created", {
|
|
22
|
+
actionsAmount: 0,
|
|
23
|
+
endpointTypes: [],
|
|
24
|
+
endpointsAmount: 0,
|
|
25
|
+
agentsAmount: agents ? Object.keys(agents).length : null,
|
|
26
|
+
"cloud.api_key_provided": false
|
|
27
|
+
});
|
|
28
|
+
}).catch(() => {});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
exports.fireInstanceCreatedTelemetry = fireInstanceCreatedTelemetry;
|
|
33
|
+
//# sourceMappingURL=instance-created.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-created.cjs","names":[],"sources":["../../../../src/v2/runtime/telemetry/instance-created.ts"],"sourcesContent":["import { telemetry } from \".\";\nimport type { CopilotRuntimeLike } from \"../core/runtime\";\n\n/**\n * Fire the `oss.runtime.instance_created` telemetry event for a v2 runtime\n * handler. Called once per handler factory invocation (not per request).\n *\n * v2 does not have a concept of remote endpoints or standalone actions, so\n * those counts are 0 / []. `cloud.api_key_provided` is false at this level\n * because in v2 the cloud public key arrives per-request via the\n * `x-copilotcloud-public-api-key` header — not at handler creation time.\n * See `handlers/handle-run.ts` for the per-request event that DOES carry\n * the key when present.\n *\n * Errors resolving agents are swallowed — telemetry must never break\n * runtime setup.\n */\nexport function fireInstanceCreatedTelemetry({\n runtime,\n}: {\n runtime: CopilotRuntimeLike;\n}): void {\n // agents can be a static Record, a Promise, or a per-request factory.\n // Factory configs cannot be resolved at handler-creation time (no Request\n // context), so report agentsAmount as null in that case.\n const agentsPromise =\n typeof runtime.agents === \"function\"\n ? Promise.resolve<Record<string, unknown> | null>(null)\n : Promise.resolve(runtime.agents);\n\n agentsPromise\n .then((agents) => {\n telemetry.capture(\"oss.runtime.instance_created\", {\n actionsAmount: 0,\n endpointTypes: [],\n endpointsAmount: 0,\n agentsAmount: agents ? Object.keys(agents).length : null,\n \"cloud.api_key_provided\": false,\n });\n })\n .catch(() => {\n // Swallow — telemetry must not break runtime creation.\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,SAAgB,6BAA6B,EAC3C,WAGO;AASP,EAJE,OAAO,QAAQ,WAAW,aACtB,QAAQ,QAAwC,KAAK,GACrD,QAAQ,QAAQ,QAAQ,OAAO,EAGlC,MAAM,WAAW;AAChB,mCAAU,QAAQ,gCAAgC;GAChD,eAAe;GACf,eAAe,EAAE;GACjB,iBAAiB;GACjB,cAAc,SAAS,OAAO,KAAK,OAAO,CAAC,SAAS;GACpD,0BAA0B;GAC3B,CAAC;GACF,CACD,YAAY,GAEX"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import telemetry from "./telemetry-client.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/v2/runtime/telemetry/instance-created.ts
|
|
5
|
+
/**
|
|
6
|
+
* Fire the `oss.runtime.instance_created` telemetry event for a v2 runtime
|
|
7
|
+
* handler. Called once per handler factory invocation (not per request).
|
|
8
|
+
*
|
|
9
|
+
* v2 does not have a concept of remote endpoints or standalone actions, so
|
|
10
|
+
* those counts are 0 / []. `cloud.api_key_provided` is false at this level
|
|
11
|
+
* because in v2 the cloud public key arrives per-request via the
|
|
12
|
+
* `x-copilotcloud-public-api-key` header — not at handler creation time.
|
|
13
|
+
* See `handlers/handle-run.ts` for the per-request event that DOES carry
|
|
14
|
+
* the key when present.
|
|
15
|
+
*
|
|
16
|
+
* Errors resolving agents are swallowed — telemetry must never break
|
|
17
|
+
* runtime setup.
|
|
18
|
+
*/
|
|
19
|
+
function fireInstanceCreatedTelemetry({ runtime }) {
|
|
20
|
+
(typeof runtime.agents === "function" ? Promise.resolve(null) : Promise.resolve(runtime.agents)).then((agents) => {
|
|
21
|
+
telemetry.capture("oss.runtime.instance_created", {
|
|
22
|
+
actionsAmount: 0,
|
|
23
|
+
endpointTypes: [],
|
|
24
|
+
endpointsAmount: 0,
|
|
25
|
+
agentsAmount: agents ? Object.keys(agents).length : null,
|
|
26
|
+
"cloud.api_key_provided": false
|
|
27
|
+
});
|
|
28
|
+
}).catch(() => {});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { fireInstanceCreatedTelemetry };
|
|
33
|
+
//# sourceMappingURL=instance-created.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-created.mjs","names":[],"sources":["../../../../src/v2/runtime/telemetry/instance-created.ts"],"sourcesContent":["import { telemetry } from \".\";\nimport type { CopilotRuntimeLike } from \"../core/runtime\";\n\n/**\n * Fire the `oss.runtime.instance_created` telemetry event for a v2 runtime\n * handler. Called once per handler factory invocation (not per request).\n *\n * v2 does not have a concept of remote endpoints or standalone actions, so\n * those counts are 0 / []. `cloud.api_key_provided` is false at this level\n * because in v2 the cloud public key arrives per-request via the\n * `x-copilotcloud-public-api-key` header — not at handler creation time.\n * See `handlers/handle-run.ts` for the per-request event that DOES carry\n * the key when present.\n *\n * Errors resolving agents are swallowed — telemetry must never break\n * runtime setup.\n */\nexport function fireInstanceCreatedTelemetry({\n runtime,\n}: {\n runtime: CopilotRuntimeLike;\n}): void {\n // agents can be a static Record, a Promise, or a per-request factory.\n // Factory configs cannot be resolved at handler-creation time (no Request\n // context), so report agentsAmount as null in that case.\n const agentsPromise =\n typeof runtime.agents === \"function\"\n ? Promise.resolve<Record<string, unknown> | null>(null)\n : Promise.resolve(runtime.agents);\n\n agentsPromise\n .then((agents) => {\n telemetry.capture(\"oss.runtime.instance_created\", {\n actionsAmount: 0,\n endpointTypes: [],\n endpointsAmount: 0,\n agentsAmount: agents ? Object.keys(agents).length : null,\n \"cloud.api_key_provided\": false,\n });\n })\n .catch(() => {\n // Swallow — telemetry must not break runtime creation.\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,SAAgB,6BAA6B,EAC3C,WAGO;AASP,EAJE,OAAO,QAAQ,WAAW,aACtB,QAAQ,QAAwC,KAAK,GACrD,QAAQ,QAAQ,QAAQ,OAAO,EAGlC,MAAM,WAAW;AAChB,YAAU,QAAQ,gCAAgC;GAChD,eAAe;GACf,eAAe,EAAE;GACjB,iBAAiB;GACjB,cAAc,SAAS,OAAO,KAAK,OAAO,CAAC,SAAS;GACpD,0BAA0B;GAC3B,CAAC;GACF,CACD,YAAY,GAEX"}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
require("reflect-metadata");
|
|
2
|
-
const require_runtime = require('../../../_virtual/_rolldown/runtime.cjs');
|
|
3
|
-
const require_utils = require('./utils.cjs');
|
|
4
2
|
const require_scarf_client = require('./scarf-client.cjs');
|
|
5
|
-
let _segment_analytics_node = require("@segment/analytics-node");
|
|
6
|
-
let uuid = require("uuid");
|
|
7
3
|
|
|
8
4
|
//#region src/v2/runtime/telemetry/telemetry-client.ts
|
|
9
5
|
function isTelemetryDisabled() {
|
|
@@ -11,58 +7,25 @@ function isTelemetryDisabled() {
|
|
|
11
7
|
}
|
|
12
8
|
var TelemetryClient = class {
|
|
13
9
|
constructor({ telemetryDisabled, sampleRate } = {}) {
|
|
14
|
-
this.globalProperties = {};
|
|
15
10
|
this.telemetryDisabled = false;
|
|
16
11
|
this.sampleRate = .05;
|
|
17
|
-
this.anonymousId = `anon_${(0, uuid.v4)()}`;
|
|
18
12
|
this.telemetryDisabled = telemetryDisabled ?? isTelemetryDisabled();
|
|
19
|
-
if (this.telemetryDisabled) {
|
|
20
|
-
this.setSampleRate(sampleRate);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
13
|
this.setSampleRate(sampleRate);
|
|
24
|
-
this.segment = new _segment_analytics_node.Analytics({ writeKey: process.env.COPILOTKIT_SEGMENT_WRITE_KEY || "n7XAZtQCGS2v1vvBy3LgBCv2h3Y8whja" });
|
|
25
14
|
}
|
|
26
15
|
shouldSendEvent() {
|
|
27
16
|
if (this.telemetryDisabled) return false;
|
|
28
17
|
return Math.random() < this.sampleRate;
|
|
29
18
|
}
|
|
30
|
-
async capture(event,
|
|
19
|
+
async capture(event, _properties) {
|
|
31
20
|
if (!this.shouldSendEvent()) return;
|
|
32
|
-
const flattenedProperties = require_utils.flattenObject(properties);
|
|
33
|
-
const propertiesWithGlobal = {
|
|
34
|
-
...this.globalProperties,
|
|
35
|
-
...flattenedProperties
|
|
36
|
-
};
|
|
37
|
-
const orderedPropertiesWithGlobal = Object.keys(propertiesWithGlobal).sort().reduce((obj, key) => {
|
|
38
|
-
obj[key] = propertiesWithGlobal[key];
|
|
39
|
-
return obj;
|
|
40
|
-
}, {});
|
|
41
|
-
if (this.segment) this.segment.track({
|
|
42
|
-
anonymousId: this.anonymousId,
|
|
43
|
-
event,
|
|
44
|
-
properties: { ...orderedPropertiesWithGlobal }
|
|
45
|
-
});
|
|
46
21
|
await require_scarf_client.default.logEvent({ event });
|
|
47
22
|
}
|
|
48
|
-
setGlobalProperties(properties) {
|
|
49
|
-
const flattenedProperties = require_utils.flattenObject(properties);
|
|
50
|
-
this.globalProperties = {
|
|
51
|
-
...this.globalProperties,
|
|
52
|
-
...flattenedProperties
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
23
|
setSampleRate(sampleRate) {
|
|
56
24
|
let _sampleRate;
|
|
57
25
|
_sampleRate = sampleRate ?? .05;
|
|
58
26
|
if (process.env.COPILOTKIT_TELEMETRY_SAMPLE_RATE) _sampleRate = parseFloat(process.env.COPILOTKIT_TELEMETRY_SAMPLE_RATE);
|
|
59
27
|
if (_sampleRate < 0 || _sampleRate > 1) throw new Error("Sample rate must be between 0 and 1");
|
|
60
28
|
this.sampleRate = _sampleRate;
|
|
61
|
-
this.setGlobalProperties({
|
|
62
|
-
sampleRate: this.sampleRate,
|
|
63
|
-
sampleRateAdjustmentFactor: 1 - this.sampleRate,
|
|
64
|
-
sampleWeight: 1 / this.sampleRate
|
|
65
|
-
});
|
|
66
29
|
}
|
|
67
30
|
};
|
|
68
31
|
const telemetry = new TelemetryClient();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry-client.cjs","names":["
|
|
1
|
+
{"version":3,"file":"telemetry-client.cjs","names":["scarfClient"],"sources":["../../../../src/v2/runtime/telemetry/telemetry-client.ts"],"sourcesContent":["import { AnalyticsEvents } from \"./events\";\nimport scarfClient from \"./scarf-client\";\n\nexport function isTelemetryDisabled(): boolean {\n return (\n (process.env as Record<string, string | undefined>)\n .COPILOTKIT_TELEMETRY_DISABLED === \"true\" ||\n (process.env as Record<string, string | undefined>)\n .COPILOTKIT_TELEMETRY_DISABLED === \"1\" ||\n (process.env as Record<string, string | undefined>).DO_NOT_TRACK ===\n \"true\" ||\n (process.env as Record<string, string | undefined>).DO_NOT_TRACK === \"1\"\n );\n}\n\nexport class TelemetryClient {\n private telemetryDisabled: boolean = false;\n private sampleRate: number = 0.05;\n\n constructor({\n telemetryDisabled,\n sampleRate,\n }: {\n telemetryDisabled?: boolean;\n sampleRate?: number;\n } = {}) {\n this.telemetryDisabled = telemetryDisabled ?? isTelemetryDisabled();\n this.setSampleRate(sampleRate);\n }\n\n private shouldSendEvent() {\n if (this.telemetryDisabled) {\n return false;\n }\n const randomNumber = Math.random();\n return randomNumber < this.sampleRate;\n }\n\n async capture<K extends keyof AnalyticsEvents>(\n event: K,\n _properties: AnalyticsEvents[K],\n ) {\n if (!this.shouldSendEvent()) {\n return;\n }\n\n await scarfClient.logEvent({\n event,\n });\n }\n\n private setSampleRate(sampleRate: number | undefined) {\n let _sampleRate: number;\n\n _sampleRate = sampleRate ?? 0.05;\n\n if (process.env.COPILOTKIT_TELEMETRY_SAMPLE_RATE) {\n _sampleRate = parseFloat(process.env.COPILOTKIT_TELEMETRY_SAMPLE_RATE);\n }\n\n if (_sampleRate < 0 || _sampleRate > 1) {\n throw new Error(\"Sample rate must be between 0 and 1\");\n }\n\n this.sampleRate = _sampleRate;\n }\n}\n\nconst telemetry = new TelemetryClient();\nexport default telemetry;\n"],"mappings":";;;;AAGA,SAAgB,sBAA+B;AAC7C,QACG,QAAQ,IACN,kCAAkC,UACpC,QAAQ,IACN,kCAAkC,OACpC,QAAQ,IAA2C,iBAClD,UACD,QAAQ,IAA2C,iBAAiB;;AAIzE,IAAa,kBAAb,MAA6B;CAI3B,YAAY,EACV,mBACA,eAIE,EAAE,EAAE;2BAT6B;oBACR;AAS3B,OAAK,oBAAoB,qBAAqB,qBAAqB;AACnE,OAAK,cAAc,WAAW;;CAGhC,AAAQ,kBAAkB;AACxB,MAAI,KAAK,kBACP,QAAO;AAGT,SADqB,KAAK,QAAQ,GACZ,KAAK;;CAG7B,MAAM,QACJ,OACA,aACA;AACA,MAAI,CAAC,KAAK,iBAAiB,CACzB;AAGF,QAAMA,6BAAY,SAAS,EACzB,OACD,CAAC;;CAGJ,AAAQ,cAAc,YAAgC;EACpD,IAAI;AAEJ,gBAAc,cAAc;AAE5B,MAAI,QAAQ,IAAI,iCACd,eAAc,WAAW,QAAQ,IAAI,iCAAiC;AAGxE,MAAI,cAAc,KAAK,cAAc,EACnC,OAAM,IAAI,MAAM,sCAAsC;AAGxD,OAAK,aAAa;;;AAItB,MAAM,YAAY,IAAI,iBAAiB"}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
|
-
import { flattenObject } from "./utils.mjs";
|
|
3
2
|
import scarf_client_default from "./scarf-client.mjs";
|
|
4
|
-
import { Analytics } from "@segment/analytics-node";
|
|
5
|
-
import { v4 } from "uuid";
|
|
6
3
|
|
|
7
4
|
//#region src/v2/runtime/telemetry/telemetry-client.ts
|
|
8
5
|
function isTelemetryDisabled() {
|
|
@@ -10,58 +7,25 @@ function isTelemetryDisabled() {
|
|
|
10
7
|
}
|
|
11
8
|
var TelemetryClient = class {
|
|
12
9
|
constructor({ telemetryDisabled, sampleRate } = {}) {
|
|
13
|
-
this.globalProperties = {};
|
|
14
10
|
this.telemetryDisabled = false;
|
|
15
11
|
this.sampleRate = .05;
|
|
16
|
-
this.anonymousId = `anon_${v4()}`;
|
|
17
12
|
this.telemetryDisabled = telemetryDisabled ?? isTelemetryDisabled();
|
|
18
|
-
if (this.telemetryDisabled) {
|
|
19
|
-
this.setSampleRate(sampleRate);
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
13
|
this.setSampleRate(sampleRate);
|
|
23
|
-
this.segment = new Analytics({ writeKey: process.env.COPILOTKIT_SEGMENT_WRITE_KEY || "n7XAZtQCGS2v1vvBy3LgBCv2h3Y8whja" });
|
|
24
14
|
}
|
|
25
15
|
shouldSendEvent() {
|
|
26
16
|
if (this.telemetryDisabled) return false;
|
|
27
17
|
return Math.random() < this.sampleRate;
|
|
28
18
|
}
|
|
29
|
-
async capture(event,
|
|
19
|
+
async capture(event, _properties) {
|
|
30
20
|
if (!this.shouldSendEvent()) return;
|
|
31
|
-
const flattenedProperties = flattenObject(properties);
|
|
32
|
-
const propertiesWithGlobal = {
|
|
33
|
-
...this.globalProperties,
|
|
34
|
-
...flattenedProperties
|
|
35
|
-
};
|
|
36
|
-
const orderedPropertiesWithGlobal = Object.keys(propertiesWithGlobal).sort().reduce((obj, key) => {
|
|
37
|
-
obj[key] = propertiesWithGlobal[key];
|
|
38
|
-
return obj;
|
|
39
|
-
}, {});
|
|
40
|
-
if (this.segment) this.segment.track({
|
|
41
|
-
anonymousId: this.anonymousId,
|
|
42
|
-
event,
|
|
43
|
-
properties: { ...orderedPropertiesWithGlobal }
|
|
44
|
-
});
|
|
45
21
|
await scarf_client_default.logEvent({ event });
|
|
46
22
|
}
|
|
47
|
-
setGlobalProperties(properties) {
|
|
48
|
-
const flattenedProperties = flattenObject(properties);
|
|
49
|
-
this.globalProperties = {
|
|
50
|
-
...this.globalProperties,
|
|
51
|
-
...flattenedProperties
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
23
|
setSampleRate(sampleRate) {
|
|
55
24
|
let _sampleRate;
|
|
56
25
|
_sampleRate = sampleRate ?? .05;
|
|
57
26
|
if (process.env.COPILOTKIT_TELEMETRY_SAMPLE_RATE) _sampleRate = parseFloat(process.env.COPILOTKIT_TELEMETRY_SAMPLE_RATE);
|
|
58
27
|
if (_sampleRate < 0 || _sampleRate > 1) throw new Error("Sample rate must be between 0 and 1");
|
|
59
28
|
this.sampleRate = _sampleRate;
|
|
60
|
-
this.setGlobalProperties({
|
|
61
|
-
sampleRate: this.sampleRate,
|
|
62
|
-
sampleRateAdjustmentFactor: 1 - this.sampleRate,
|
|
63
|
-
sampleWeight: 1 / this.sampleRate
|
|
64
|
-
});
|
|
65
29
|
}
|
|
66
30
|
};
|
|
67
31
|
const telemetry = new TelemetryClient();
|