@copilotkit/runtime 1.64.2-canary.1785375021 → 1.64.2-canary.narrowinstall1

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.
Files changed (35) hide show
  1. package/dist/package.cjs +1 -1
  2. package/dist/runtime/package.mjs +1 -1
  3. package/dist/v2/runtime/core/channel-manager.cjs +3 -165
  4. package/dist/v2/runtime/core/channel-manager.cjs.map +1 -1
  5. package/dist/v2/runtime/core/channel-manager.d.cts +0 -2
  6. package/dist/v2/runtime/core/channel-manager.d.cts.map +1 -1
  7. package/dist/v2/runtime/core/channel-manager.d.mts +0 -2
  8. package/dist/v2/runtime/core/channel-manager.d.mts.map +1 -1
  9. package/dist/v2/runtime/core/channel-manager.mjs +3 -165
  10. package/dist/v2/runtime/core/channel-manager.mjs.map +1 -1
  11. package/dist/v2/runtime/core/fetch-handler.cjs +0 -3
  12. package/dist/v2/runtime/core/fetch-handler.cjs.map +1 -1
  13. package/dist/v2/runtime/core/fetch-handler.d.cts.map +1 -1
  14. package/dist/v2/runtime/core/fetch-handler.d.mts.map +1 -1
  15. package/dist/v2/runtime/core/fetch-handler.mjs +0 -3
  16. package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -1
  17. package/dist/v2/runtime/runner/agent-runner.cjs.map +1 -1
  18. package/dist/v2/runtime/runner/agent-runner.d.cts +0 -2
  19. package/dist/v2/runtime/runner/agent-runner.d.cts.map +1 -1
  20. package/dist/v2/runtime/runner/agent-runner.d.mts +0 -2
  21. package/dist/v2/runtime/runner/agent-runner.d.mts.map +1 -1
  22. package/dist/v2/runtime/runner/agent-runner.mjs.map +1 -1
  23. package/dist/v2/runtime/runner/in-memory.cjs +5 -2
  24. package/dist/v2/runtime/runner/in-memory.cjs.map +1 -1
  25. package/dist/v2/runtime/runner/in-memory.d.cts.map +1 -1
  26. package/dist/v2/runtime/runner/in-memory.d.mts.map +1 -1
  27. package/dist/v2/runtime/runner/in-memory.mjs +5 -2
  28. package/dist/v2/runtime/runner/in-memory.mjs.map +1 -1
  29. package/dist/v2/runtime/runner/intelligence.cjs +31 -36
  30. package/dist/v2/runtime/runner/intelligence.cjs.map +1 -1
  31. package/dist/v2/runtime/runner/intelligence.d.cts.map +1 -1
  32. package/dist/v2/runtime/runner/intelligence.d.mts.map +1 -1
  33. package/dist/v2/runtime/runner/intelligence.mjs +31 -36
  34. package/dist/v2/runtime/runner/intelligence.mjs.map +1 -1
  35. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory.d.mts","names":[],"sources":["../../../../src/v2/runtime/runner/in-memory.ts"],"mappings":";;;;;;AAuCA;;;;;AAAA,UAAiB,cAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA;EACA,cAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EACA,SAAA;AAAA;AAAA,cAiCW,mBAAA,SAA4B,WAAA;EAAA,SAC9B,6BAAA;EAiBI;;;;;;;;EAAA,iBAPI,eAAA;cAEL,OAAA;IAAY,eAAA;EAAA;EAKxB,GAAA,CAAI,OAAA,EAAS,qBAAA,GAAwB,UAAA,CAAW,SAAA;EAiOhD,OAAA,CAAQ,OAAA,EAAS,yBAAA,GAA4B,UAAA,CAAW,SAAA;EAqDxD,SAAA,CAAU,OAAA,EAAS,2BAAA,GAA8B,OAAA;EAKjD,IAAA,CAAK,OAAA,EAAS,sBAAA,GAAyB,OAAA;EA7SW;;;;;;;EAkVlD,WAAA,CAAA,GAAe,cAAA;EAhUF;;;;;;;;;EAiWb,iBAAA,CAAkB,QAAA,WAAmB,OAAA;EA3ElB;;;;;;;;EA0FnB,eAAA,CAAgB,QAAA,WAAmB,SAAA;EAfnC;;;;;;;;;;EAiCA,cAAA,CAAe,QAAA,WAAmB,MAAA;EAyBtB;;;;;;;;;EAAZ,YAAA,CAAA;AAAA"}
1
+ {"version":3,"file":"in-memory.d.mts","names":[],"sources":["../../../../src/v2/runtime/runner/in-memory.ts"],"mappings":";;;;;;AAuCA;;;;;AAAA,UAAiB,cAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA;EACA,cAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EACA,SAAA;AAAA;AAAA,cAiCW,mBAAA,SAA4B,WAAA;EAAA,SAC9B,6BAAA;EAiBI;;;;;;;;EAAA,iBAPI,eAAA;cAEL,OAAA;IAAY,eAAA;EAAA;EAKxB,GAAA,CAAI,OAAA,EAAS,qBAAA,GAAwB,UAAA,CAAW,SAAA;EAmOhD,OAAA,CAAQ,OAAA,EAAS,yBAAA,GAA4B,UAAA,CAAW,SAAA;EAqDxD,SAAA,CAAU,OAAA,EAAS,2BAAA,GAA8B,OAAA;EAKjD,IAAA,CAAK,OAAA,EAAS,sBAAA,GAAyB,OAAA;EA/SW;;;;;;;EAoVlD,WAAA,CAAA,GAAe,cAAA;EAlUF;;;;;;;;;EAmWb,iBAAA,CAAkB,QAAA,WAAmB,OAAA;EA3ElB;;;;;;;;EA0FnB,eAAA,CAAgB,QAAA,WAAmB,SAAA;EAfnC;;;;;;;;;;EAiCA,cAAA,CAAe,QAAA,WAAmB,MAAA;EAyBtB;;;;;;;;;EAAZ,YAAA,CAAA;AAAA"}
@@ -74,11 +74,14 @@ var InMemoryAgentRunner = class extends AgentRunner {
74
74
  const runStartedEvent = event;
75
75
  if (!runStartedEvent.input) {
76
76
  const sanitizedMessages = request.input.messages ? request.input.messages.filter((message) => !historicMessageIds.has(message.id)) : void 0;
77
- runStartedEvent.input = {
77
+ const updatedInput = {
78
78
  ...request.input,
79
79
  ...sanitizedMessages !== void 0 ? { messages: sanitizedMessages } : {}
80
80
  };
81
- processedEvent = runStartedEvent;
81
+ processedEvent = {
82
+ ...runStartedEvent,
83
+ input: updatedInput
84
+ };
82
85
  }
83
86
  }
84
87
  runSubject.next(processedEvent);
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory.mjs","names":[],"sources":["../../../../src/v2/runtime/runner/in-memory.ts"],"sourcesContent":["import type {\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n} from \"./agent-runner\";\nimport { AgentRunner } from \"./agent-runner\";\nimport type { AgentRunnerStopRequest } from \"./agent-runner\";\nimport type { Observable } from \"rxjs\";\nimport { ReplaySubject } from \"rxjs\";\nimport type {\n AbstractAgent,\n BaseEvent,\n Message,\n RunStartedEvent,\n StateSnapshotEvent,\n} from \"@ag-ui/client\";\nimport { EventType, compactEvents } from \"@ag-ui/client\";\nimport { finalizeRunEvents } from \"@copilotkit/shared\";\n\ninterface HistoricRun {\n threadId: string;\n runId: string;\n /** ID of the agent that executed this run. */\n agentId: string;\n parentRunId: string | null;\n events: BaseEvent[];\n /**\n * Snapshot of all messages (input + generated) at the end of this run.\n * Used by the local thread-messages fallback endpoint.\n */\n messages: Message[];\n createdAt: number;\n}\n\n/**\n * Lightweight thread summary returned by {@link InMemoryAgentRunner.listThreads}.\n * Shape matches the Intelligence platform's ThreadRecord so the same HTTP\n * response envelope can be used for both backends.\n */\nexport interface InMemoryThread {\n id: string;\n name: string | null;\n agentId: string;\n organizationId: \"\"; // always empty in in-memory mode\n createdById: \"\"; // always empty in in-memory mode\n archived: false; // always false in in-memory mode\n createdAt: string;\n updatedAt: string;\n}\n\nclass InMemoryEventStore {\n constructor(public threadId: string) {}\n\n /** The subject that current consumers subscribe to. */\n subject: ReplaySubject<BaseEvent> | null = null;\n\n /** True while a run is actively producing events. */\n isRunning = false;\n\n /** Current run ID */\n currentRunId: string | null = null;\n\n /** Historic completed runs */\n historicRuns: HistoricRun[] = [];\n\n /** Currently running agent instance (if any). */\n agent: AbstractAgent | null = null;\n\n /** Subject returned from run() while the run is active. */\n runSubject: ReplaySubject<BaseEvent> | null = null;\n\n /** True once stop() has been requested but the run has not yet finalized. */\n stopRequested = false;\n\n /** Reference to the events emitted in the current run. */\n currentEvents: BaseEvent[] | null = null;\n}\n\nconst GLOBAL_STORE = new Map<string, InMemoryEventStore>();\n\nexport class InMemoryAgentRunner extends AgentRunner {\n readonly ɵsupportsLocalThreadEndpoints = true;\n\n /**\n * How to handle a `run()` for a thread that already has an in-flight run.\n * `\"throw\"` (default) preserves the historic behavior. `\"supersede\"` aborts\n * the prior run (mirroring `stop()`) and starts the new one — opted into by\n * the hosted-bot listener so a fast follow-up turn on the same thread cleanly\n * replaces a still-running (or wedged) prior turn instead of erroring with\n * \"Thread already running\".\n */\n private readonly onConcurrentRun: \"throw\" | \"supersede\";\n\n constructor(options?: { onConcurrentRun?: \"throw\" | \"supersede\" }) {\n super();\n this.onConcurrentRun = options?.onConcurrentRun ?? \"throw\";\n }\n\n run(request: AgentRunnerRunRequest): Observable<BaseEvent> {\n let existingStore = GLOBAL_STORE.get(request.threadId);\n if (!existingStore) {\n existingStore = new InMemoryEventStore(request.threadId);\n GLOBAL_STORE.set(request.threadId, existingStore);\n }\n const store = existingStore; // Now store is const and non-null\n\n if (store.isRunning) {\n if (this.onConcurrentRun !== \"supersede\") {\n throw new Error(\"Thread already running\");\n }\n // Supersede: abort the prior (possibly wedged) run so this one can start.\n // Mirrors stop(). The prior run's async finalization runs later and is\n // prevented from clobbering this run's state by the run-id guard below.\n const priorAgent = store.agent;\n store.stopRequested = true;\n store.isRunning = false;\n if (priorAgent) {\n try {\n priorAgent.abortRun();\n } catch (error) {\n console.error(\"Failed to abort superseded run\", error);\n }\n }\n store.stopRequested = false;\n }\n store.isRunning = true;\n store.currentRunId = request.input.runId;\n store.agent = request.agent;\n store.stopRequested = false;\n\n // Track seen message IDs and current run events for this run\n const seenMessageIds = new Set<string>();\n const currentRunEvents: BaseEvent[] = [];\n store.currentEvents = currentRunEvents;\n\n // Get all previously seen message IDs from historic runs\n const historicMessageIds = new Set<string>();\n for (const run of store.historicRuns) {\n for (const event of run.events) {\n if (\"messageId\" in event && typeof event.messageId === \"string\") {\n historicMessageIds.add(event.messageId);\n }\n if (event.type === EventType.RUN_STARTED) {\n const runStarted = event as RunStartedEvent;\n const messages = runStarted.input?.messages ?? [];\n for (const message of messages) {\n historicMessageIds.add(message.id);\n }\n }\n }\n }\n\n const nextSubject = new ReplaySubject<BaseEvent>(Infinity);\n const prevSubject = store.subject;\n\n // Update the store's subject immediately\n store.subject = nextSubject;\n\n // Create a subject for run() return value\n const runSubject = new ReplaySubject<BaseEvent>(Infinity);\n store.runSubject = runSubject;\n\n // Helper function to run the agent and handle errors\n const runAgent = async () => {\n // Get parent run ID for chaining\n const lastRun = store.historicRuns[store.historicRuns.length - 1];\n const parentRunId = lastRun?.runId ?? null;\n\n try {\n await request.agent.runAgent(request.input, {\n onEvent: ({ event }) => {\n let processedEvent: BaseEvent = event;\n if (event.type === EventType.RUN_STARTED) {\n const runStartedEvent = event as RunStartedEvent;\n if (!runStartedEvent.input) {\n const sanitizedMessages = request.input.messages\n ? request.input.messages.filter(\n (message) => !historicMessageIds.has(message.id),\n )\n : undefined;\n const updatedInput = {\n ...request.input,\n ...(sanitizedMessages !== undefined\n ? { messages: sanitizedMessages }\n : {}),\n };\n runStartedEvent.input = updatedInput;\n processedEvent = runStartedEvent;\n }\n }\n\n runSubject.next(processedEvent); // For run() return - only agent events\n nextSubject.next(processedEvent); // For connect() / store - all events\n currentRunEvents.push(processedEvent); // Accumulate for storage\n },\n onNewMessage: ({ message }) => {\n // Called for each new message\n if (!seenMessageIds.has(message.id)) {\n seenMessageIds.add(message.id);\n }\n },\n onRunStartedEvent: () => {\n // Mark any messages from the input as seen so they aren't emitted twice\n if (request.input.messages) {\n for (const message of request.input.messages) {\n if (!seenMessageIds.has(message.id)) {\n seenMessageIds.add(message.id);\n }\n }\n }\n },\n });\n\n const appendedEvents = finalizeRunEvents(currentRunEvents, {\n stopRequested: store.stopRequested,\n });\n for (const event of appendedEvents) {\n runSubject.next(event);\n nextSubject.next(event);\n }\n\n // Store the completed run in memory with ONLY its events. Guard on the\n // per-run id (not the shared `store.currentRunId`): a superseded run no\n // longer owns the store, so it must not push history — and never under\n // a newer run's id, which would corrupt the thread's history.\n if (store.currentRunId === request.input.runId) {\n // Compact the events before storing (like SQLite does)\n const compactedEvents = compactEvents(currentRunEvents);\n\n store.historicRuns.push({\n threadId: request.threadId,\n runId: request.input.runId,\n agentId: request.agent.agentId ?? \"default\",\n parentRunId,\n events: compactedEvents,\n // Snapshot all messages (input + generated) for the thread-messages endpoint\n messages: Array.isArray(request.agent.messages)\n ? [...request.agent.messages]\n : [],\n createdAt: Date.now(),\n });\n }\n\n // Complete the run. Guard the shared-store reset: if a newer run has\n // superseded this one (`currentRunId` changed), that run now owns the\n // store — don't clobber its state. Always complete THIS run's subjects.\n if (store.currentRunId === request.input.runId) {\n store.currentEvents = null;\n store.currentRunId = null;\n store.agent = null;\n store.runSubject = null;\n store.stopRequested = false;\n store.isRunning = false;\n }\n runSubject.complete();\n nextSubject.complete();\n } catch (error) {\n const interruptionMessage =\n error instanceof Error ? error.message : String(error);\n const appendedEvents = finalizeRunEvents(currentRunEvents, {\n stopRequested: store.stopRequested,\n interruptionMessage,\n });\n for (const event of appendedEvents) {\n runSubject.next(event);\n nextSubject.next(event);\n }\n\n // Store the run even if it failed (partial events). Same per-run guard:\n // a superseded run's error teardown must not push history under the\n // newer run's id (see success-path note).\n if (\n store.currentRunId === request.input.runId &&\n currentRunEvents.length > 0\n ) {\n // Compact the events before storing (like SQLite does)\n const compactedEvents = compactEvents(currentRunEvents);\n store.historicRuns.push({\n threadId: request.threadId,\n runId: request.input.runId,\n agentId: request.agent.agentId ?? \"default\",\n parentRunId,\n events: compactedEvents,\n messages: Array.isArray(request.agent.messages)\n ? [...request.agent.messages]\n : [],\n createdAt: Date.now(),\n });\n }\n\n // Complete the run (see success-path note). Same run-id guard so a\n // superseded run's error teardown can't reset the newer run's state.\n if (store.currentRunId === request.input.runId) {\n store.currentEvents = null;\n store.currentRunId = null;\n store.agent = null;\n store.runSubject = null;\n store.stopRequested = false;\n store.isRunning = false;\n }\n runSubject.complete();\n nextSubject.complete();\n }\n };\n\n // Bridge previous events if they exist\n if (prevSubject) {\n prevSubject.subscribe({\n next: (e) => nextSubject.next(e),\n error: (err) => nextSubject.error(err),\n complete: () => {\n // Don't complete nextSubject here - it needs to stay open for new events\n },\n });\n }\n\n // Start the agent execution immediately (not lazily)\n runAgent();\n\n // Return the run subject (only agent events, no injected messages)\n return runSubject.asObservable();\n }\n\n connect(request: AgentRunnerConnectRequest): Observable<BaseEvent> {\n const store = GLOBAL_STORE.get(request.threadId);\n const connectionSubject = new ReplaySubject<BaseEvent>(Infinity);\n\n if (!store) {\n // No store means no events\n connectionSubject.complete();\n return connectionSubject.asObservable();\n }\n\n // Collect all historic events from memory\n const allHistoricEvents: BaseEvent[] = [];\n for (const run of store.historicRuns) {\n allHistoricEvents.push(...run.events);\n }\n\n // Apply compaction to all historic events together (like SQLite)\n const compactedEvents = compactEvents(allHistoricEvents);\n\n // Emit compacted events and track message IDs\n const emittedMessageIds = new Set<string>();\n for (const event of compactedEvents) {\n connectionSubject.next(event);\n if (\"messageId\" in event && typeof event.messageId === \"string\") {\n emittedMessageIds.add(event.messageId);\n }\n }\n\n // Bridge active run to connection if exists\n if (store.subject && (store.isRunning || store.stopRequested)) {\n store.subject.subscribe({\n next: (event) => {\n // Skip message events that we've already emitted from historic\n if (\n \"messageId\" in event &&\n typeof event.messageId === \"string\" &&\n emittedMessageIds.has(event.messageId)\n ) {\n return;\n }\n connectionSubject.next(event);\n },\n complete: () => connectionSubject.complete(),\n error: (err) => connectionSubject.error(err),\n });\n } else {\n // No active run, complete after historic events\n connectionSubject.complete();\n }\n\n return connectionSubject.asObservable();\n }\n\n isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean> {\n const store = GLOBAL_STORE.get(request.threadId);\n return Promise.resolve(store?.isRunning ?? false);\n }\n\n stop(request: AgentRunnerStopRequest): Promise<boolean | undefined> {\n const store = GLOBAL_STORE.get(request.threadId);\n if (!store || !store.isRunning) {\n return Promise.resolve(false);\n }\n if (store.stopRequested) {\n return Promise.resolve(false);\n }\n\n store.stopRequested = true;\n store.isRunning = false;\n\n const agent = store.agent;\n if (!agent) {\n store.stopRequested = false;\n store.isRunning = false;\n return Promise.resolve(false);\n }\n\n try {\n agent.abortRun();\n return Promise.resolve(true);\n } catch (error) {\n console.error(\"Failed to abort agent run\", error);\n store.stopRequested = false;\n store.isRunning = true;\n return Promise.resolve(false);\n }\n }\n\n /**\n * Returns a summary of every thread that has been run through this runner.\n *\n * This powers the local-dev fallback for `GET /threads` when the Intelligence\n * platform is not configured. Each entry mirrors the shape of a platform\n * `ThreadRecord` so the HTTP handler can use the same response envelope.\n */\n listThreads(): InMemoryThread[] {\n const threads: InMemoryThread[] = [];\n for (const [threadId, store] of GLOBAL_STORE) {\n if (store.historicRuns.length === 0) continue;\n const firstRun = store.historicRuns[0]!;\n const lastRun = store.historicRuns[store.historicRuns.length - 1]!;\n threads.push({\n id: threadId,\n name: null,\n agentId: lastRun.agentId,\n organizationId: \"\",\n createdById: \"\",\n archived: false,\n createdAt: new Date(firstRun.createdAt).toISOString(),\n updatedAt: new Date(lastRun.createdAt).toISOString(),\n });\n }\n // Most recently updated first\n return threads.sort(\n (a, b) =>\n new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n /**\n * Returns all messages for a thread, using the snapshot captured at the end\n * of the most recent run.\n *\n * This powers the local-dev fallback for `GET /threads/:threadId/messages`\n * when the Intelligence platform is not configured. The returned `Message[]`\n * objects come directly from the ag-ui agent, so their shape is compatible\n * with the Intelligence platform's `ThreadMessage` type.\n */\n getThreadMessages(threadId: string): Message[] {\n const store = GLOBAL_STORE.get(threadId);\n if (!store || store.historicRuns.length === 0) return [];\n // The last run's snapshot has the complete conversation history\n return store.historicRuns[store.historicRuns.length - 1]!.messages;\n }\n\n /**\n * Returns all AG-UI events for a thread, compacted across historic runs.\n *\n * Powers the local-dev fallback for `GET /threads/:threadId/events` when the\n * Intelligence platform is not configured. The compaction logic matches\n * the connection-replay path in {@link connect}, so the stream a\n * late-joining inspector sees matches what this method returns.\n */\n getThreadEvents(threadId: string): BaseEvent[] {\n const store = GLOBAL_STORE.get(threadId);\n if (!store || store.historicRuns.length === 0) return [];\n const all: BaseEvent[] = [];\n for (const run of store.historicRuns) all.push(...run.events);\n return compactEvents(all);\n }\n\n /**\n * Returns the agent state snapshot for a thread.\n *\n * Derived from the last `STATE_SNAPSHOT` in the compacted event stream. The\n * AG-UI `compactEvents` helper consolidates STATE_DELTA events and produces\n * a single trailing STATE_SNAPSHOT when state changes exist, so this is a\n * faithful view of state at the end of the most recent run.\n *\n * Returns `null` when the thread has never emitted a STATE_SNAPSHOT.\n */\n getThreadState(threadId: string): Record<string, unknown> | null {\n const events = this.getThreadEvents(threadId);\n // Walk backwards — the last snapshot wins.\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i]!;\n if (event.type === EventType.STATE_SNAPSHOT) {\n const snapshot = (event as StateSnapshotEvent).snapshot;\n if (snapshot && typeof snapshot === \"object\") {\n return snapshot as Record<string, unknown>;\n }\n return null;\n }\n }\n return null;\n }\n\n /**\n * Clears all in-memory thread history.\n *\n * Powers the local-dev fallback for `POST /threads/clear`, letting consumers\n * (e.g. the demo's Clear button) reset to an empty thread list without\n * restarting the runtime. Intentionally not exposed on the Intelligence\n * platform path: there, thread history lives in a real database and must\n * not be wiped this way.\n */\n clearThreads(): void {\n GLOBAL_STORE.clear();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"in-memory.mjs","names":[],"sources":["../../../../src/v2/runtime/runner/in-memory.ts"],"sourcesContent":["import type {\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n} from \"./agent-runner\";\nimport { AgentRunner } from \"./agent-runner\";\nimport type { AgentRunnerStopRequest } from \"./agent-runner\";\nimport type { Observable } from \"rxjs\";\nimport { ReplaySubject } from \"rxjs\";\nimport type {\n AbstractAgent,\n BaseEvent,\n Message,\n RunStartedEvent,\n StateSnapshotEvent,\n} from \"@ag-ui/client\";\nimport { EventType, compactEvents } from \"@ag-ui/client\";\nimport { finalizeRunEvents } from \"@copilotkit/shared\";\n\ninterface HistoricRun {\n threadId: string;\n runId: string;\n /** ID of the agent that executed this run. */\n agentId: string;\n parentRunId: string | null;\n events: BaseEvent[];\n /**\n * Snapshot of all messages (input + generated) at the end of this run.\n * Used by the local thread-messages fallback endpoint.\n */\n messages: Message[];\n createdAt: number;\n}\n\n/**\n * Lightweight thread summary returned by {@link InMemoryAgentRunner.listThreads}.\n * Shape matches the Intelligence platform's ThreadRecord so the same HTTP\n * response envelope can be used for both backends.\n */\nexport interface InMemoryThread {\n id: string;\n name: string | null;\n agentId: string;\n organizationId: \"\"; // always empty in in-memory mode\n createdById: \"\"; // always empty in in-memory mode\n archived: false; // always false in in-memory mode\n createdAt: string;\n updatedAt: string;\n}\n\nclass InMemoryEventStore {\n constructor(public threadId: string) {}\n\n /** The subject that current consumers subscribe to. */\n subject: ReplaySubject<BaseEvent> | null = null;\n\n /** True while a run is actively producing events. */\n isRunning = false;\n\n /** Current run ID */\n currentRunId: string | null = null;\n\n /** Historic completed runs */\n historicRuns: HistoricRun[] = [];\n\n /** Currently running agent instance (if any). */\n agent: AbstractAgent | null = null;\n\n /** Subject returned from run() while the run is active. */\n runSubject: ReplaySubject<BaseEvent> | null = null;\n\n /** True once stop() has been requested but the run has not yet finalized. */\n stopRequested = false;\n\n /** Reference to the events emitted in the current run. */\n currentEvents: BaseEvent[] | null = null;\n}\n\nconst GLOBAL_STORE = new Map<string, InMemoryEventStore>();\n\nexport class InMemoryAgentRunner extends AgentRunner {\n readonly ɵsupportsLocalThreadEndpoints = true;\n\n /**\n * How to handle a `run()` for a thread that already has an in-flight run.\n * `\"throw\"` (default) preserves the historic behavior. `\"supersede\"` aborts\n * the prior run (mirroring `stop()`) and starts the new one — opted into by\n * the hosted-bot listener so a fast follow-up turn on the same thread cleanly\n * replaces a still-running (or wedged) prior turn instead of erroring with\n * \"Thread already running\".\n */\n private readonly onConcurrentRun: \"throw\" | \"supersede\";\n\n constructor(options?: { onConcurrentRun?: \"throw\" | \"supersede\" }) {\n super();\n this.onConcurrentRun = options?.onConcurrentRun ?? \"throw\";\n }\n\n run(request: AgentRunnerRunRequest): Observable<BaseEvent> {\n let existingStore = GLOBAL_STORE.get(request.threadId);\n if (!existingStore) {\n existingStore = new InMemoryEventStore(request.threadId);\n GLOBAL_STORE.set(request.threadId, existingStore);\n }\n const store = existingStore; // Now store is const and non-null\n\n if (store.isRunning) {\n if (this.onConcurrentRun !== \"supersede\") {\n throw new Error(\"Thread already running\");\n }\n // Supersede: abort the prior (possibly wedged) run so this one can start.\n // Mirrors stop(). The prior run's async finalization runs later and is\n // prevented from clobbering this run's state by the run-id guard below.\n const priorAgent = store.agent;\n store.stopRequested = true;\n store.isRunning = false;\n if (priorAgent) {\n try {\n priorAgent.abortRun();\n } catch (error) {\n console.error(\"Failed to abort superseded run\", error);\n }\n }\n store.stopRequested = false;\n }\n store.isRunning = true;\n store.currentRunId = request.input.runId;\n store.agent = request.agent;\n store.stopRequested = false;\n\n // Track seen message IDs and current run events for this run\n const seenMessageIds = new Set<string>();\n const currentRunEvents: BaseEvent[] = [];\n store.currentEvents = currentRunEvents;\n\n // Get all previously seen message IDs from historic runs\n const historicMessageIds = new Set<string>();\n for (const run of store.historicRuns) {\n for (const event of run.events) {\n if (\"messageId\" in event && typeof event.messageId === \"string\") {\n historicMessageIds.add(event.messageId);\n }\n if (event.type === EventType.RUN_STARTED) {\n const runStarted = event as RunStartedEvent;\n const messages = runStarted.input?.messages ?? [];\n for (const message of messages) {\n historicMessageIds.add(message.id);\n }\n }\n }\n }\n\n const nextSubject = new ReplaySubject<BaseEvent>(Infinity);\n const prevSubject = store.subject;\n\n // Update the store's subject immediately\n store.subject = nextSubject;\n\n // Create a subject for run() return value\n const runSubject = new ReplaySubject<BaseEvent>(Infinity);\n store.runSubject = runSubject;\n\n // Helper function to run the agent and handle errors\n const runAgent = async () => {\n // Get parent run ID for chaining\n const lastRun = store.historicRuns[store.historicRuns.length - 1];\n const parentRunId = lastRun?.runId ?? null;\n\n try {\n await request.agent.runAgent(request.input, {\n onEvent: ({ event }) => {\n let processedEvent: BaseEvent = event;\n if (event.type === EventType.RUN_STARTED) {\n const runStartedEvent = event as RunStartedEvent;\n if (!runStartedEvent.input) {\n const sanitizedMessages = request.input.messages\n ? request.input.messages.filter(\n (message) => !historicMessageIds.has(message.id),\n )\n : undefined;\n const updatedInput = {\n ...request.input,\n ...(sanitizedMessages !== undefined\n ? { messages: sanitizedMessages }\n : {}),\n };\n processedEvent = {\n ...runStartedEvent,\n input: updatedInput,\n } as RunStartedEvent;\n }\n }\n\n runSubject.next(processedEvent); // For run() return - only agent events\n nextSubject.next(processedEvent); // For connect() / store - all events\n currentRunEvents.push(processedEvent); // Accumulate for storage\n },\n onNewMessage: ({ message }) => {\n // Called for each new message\n if (!seenMessageIds.has(message.id)) {\n seenMessageIds.add(message.id);\n }\n },\n onRunStartedEvent: () => {\n // Mark any messages from the input as seen so they aren't emitted twice\n if (request.input.messages) {\n for (const message of request.input.messages) {\n if (!seenMessageIds.has(message.id)) {\n seenMessageIds.add(message.id);\n }\n }\n }\n },\n });\n\n const appendedEvents = finalizeRunEvents(currentRunEvents, {\n stopRequested: store.stopRequested,\n });\n for (const event of appendedEvents) {\n runSubject.next(event);\n nextSubject.next(event);\n }\n\n // Store the completed run in memory with ONLY its events. Guard on the\n // per-run id (not the shared `store.currentRunId`): a superseded run no\n // longer owns the store, so it must not push history — and never under\n // a newer run's id, which would corrupt the thread's history.\n if (store.currentRunId === request.input.runId) {\n // Compact the events before storing (like SQLite does)\n const compactedEvents = compactEvents(currentRunEvents);\n\n store.historicRuns.push({\n threadId: request.threadId,\n runId: request.input.runId,\n agentId: request.agent.agentId ?? \"default\",\n parentRunId,\n events: compactedEvents,\n // Snapshot all messages (input + generated) for the thread-messages endpoint\n messages: Array.isArray(request.agent.messages)\n ? [...request.agent.messages]\n : [],\n createdAt: Date.now(),\n });\n }\n\n // Complete the run. Guard the shared-store reset: if a newer run has\n // superseded this one (`currentRunId` changed), that run now owns the\n // store — don't clobber its state. Always complete THIS run's subjects.\n if (store.currentRunId === request.input.runId) {\n store.currentEvents = null;\n store.currentRunId = null;\n store.agent = null;\n store.runSubject = null;\n store.stopRequested = false;\n store.isRunning = false;\n }\n runSubject.complete();\n nextSubject.complete();\n } catch (error) {\n const interruptionMessage =\n error instanceof Error ? error.message : String(error);\n const appendedEvents = finalizeRunEvents(currentRunEvents, {\n stopRequested: store.stopRequested,\n interruptionMessage,\n });\n for (const event of appendedEvents) {\n runSubject.next(event);\n nextSubject.next(event);\n }\n\n // Store the run even if it failed (partial events). Same per-run guard:\n // a superseded run's error teardown must not push history under the\n // newer run's id (see success-path note).\n if (\n store.currentRunId === request.input.runId &&\n currentRunEvents.length > 0\n ) {\n // Compact the events before storing (like SQLite does)\n const compactedEvents = compactEvents(currentRunEvents);\n store.historicRuns.push({\n threadId: request.threadId,\n runId: request.input.runId,\n agentId: request.agent.agentId ?? \"default\",\n parentRunId,\n events: compactedEvents,\n messages: Array.isArray(request.agent.messages)\n ? [...request.agent.messages]\n : [],\n createdAt: Date.now(),\n });\n }\n\n // Complete the run (see success-path note). Same run-id guard so a\n // superseded run's error teardown can't reset the newer run's state.\n if (store.currentRunId === request.input.runId) {\n store.currentEvents = null;\n store.currentRunId = null;\n store.agent = null;\n store.runSubject = null;\n store.stopRequested = false;\n store.isRunning = false;\n }\n runSubject.complete();\n nextSubject.complete();\n }\n };\n\n // Bridge previous events if they exist\n if (prevSubject) {\n prevSubject.subscribe({\n next: (e) => nextSubject.next(e),\n error: (err) => nextSubject.error(err),\n complete: () => {\n // Don't complete nextSubject here - it needs to stay open for new events\n },\n });\n }\n\n // Start the agent execution immediately (not lazily)\n runAgent();\n\n // Return the run subject (only agent events, no injected messages)\n return runSubject.asObservable();\n }\n\n connect(request: AgentRunnerConnectRequest): Observable<BaseEvent> {\n const store = GLOBAL_STORE.get(request.threadId);\n const connectionSubject = new ReplaySubject<BaseEvent>(Infinity);\n\n if (!store) {\n // No store means no events\n connectionSubject.complete();\n return connectionSubject.asObservable();\n }\n\n // Collect all historic events from memory\n const allHistoricEvents: BaseEvent[] = [];\n for (const run of store.historicRuns) {\n allHistoricEvents.push(...run.events);\n }\n\n // Apply compaction to all historic events together (like SQLite)\n const compactedEvents = compactEvents(allHistoricEvents);\n\n // Emit compacted events and track message IDs\n const emittedMessageIds = new Set<string>();\n for (const event of compactedEvents) {\n connectionSubject.next(event);\n if (\"messageId\" in event && typeof event.messageId === \"string\") {\n emittedMessageIds.add(event.messageId);\n }\n }\n\n // Bridge active run to connection if exists\n if (store.subject && (store.isRunning || store.stopRequested)) {\n store.subject.subscribe({\n next: (event) => {\n // Skip message events that we've already emitted from historic\n if (\n \"messageId\" in event &&\n typeof event.messageId === \"string\" &&\n emittedMessageIds.has(event.messageId)\n ) {\n return;\n }\n connectionSubject.next(event);\n },\n complete: () => connectionSubject.complete(),\n error: (err) => connectionSubject.error(err),\n });\n } else {\n // No active run, complete after historic events\n connectionSubject.complete();\n }\n\n return connectionSubject.asObservable();\n }\n\n isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean> {\n const store = GLOBAL_STORE.get(request.threadId);\n return Promise.resolve(store?.isRunning ?? false);\n }\n\n stop(request: AgentRunnerStopRequest): Promise<boolean | undefined> {\n const store = GLOBAL_STORE.get(request.threadId);\n if (!store || !store.isRunning) {\n return Promise.resolve(false);\n }\n if (store.stopRequested) {\n return Promise.resolve(false);\n }\n\n store.stopRequested = true;\n store.isRunning = false;\n\n const agent = store.agent;\n if (!agent) {\n store.stopRequested = false;\n store.isRunning = false;\n return Promise.resolve(false);\n }\n\n try {\n agent.abortRun();\n return Promise.resolve(true);\n } catch (error) {\n console.error(\"Failed to abort agent run\", error);\n store.stopRequested = false;\n store.isRunning = true;\n return Promise.resolve(false);\n }\n }\n\n /**\n * Returns a summary of every thread that has been run through this runner.\n *\n * This powers the local-dev fallback for `GET /threads` when the Intelligence\n * platform is not configured. Each entry mirrors the shape of a platform\n * `ThreadRecord` so the HTTP handler can use the same response envelope.\n */\n listThreads(): InMemoryThread[] {\n const threads: InMemoryThread[] = [];\n for (const [threadId, store] of GLOBAL_STORE) {\n if (store.historicRuns.length === 0) continue;\n const firstRun = store.historicRuns[0]!;\n const lastRun = store.historicRuns[store.historicRuns.length - 1]!;\n threads.push({\n id: threadId,\n name: null,\n agentId: lastRun.agentId,\n organizationId: \"\",\n createdById: \"\",\n archived: false,\n createdAt: new Date(firstRun.createdAt).toISOString(),\n updatedAt: new Date(lastRun.createdAt).toISOString(),\n });\n }\n // Most recently updated first\n return threads.sort(\n (a, b) =>\n new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n /**\n * Returns all messages for a thread, using the snapshot captured at the end\n * of the most recent run.\n *\n * This powers the local-dev fallback for `GET /threads/:threadId/messages`\n * when the Intelligence platform is not configured. The returned `Message[]`\n * objects come directly from the ag-ui agent, so their shape is compatible\n * with the Intelligence platform's `ThreadMessage` type.\n */\n getThreadMessages(threadId: string): Message[] {\n const store = GLOBAL_STORE.get(threadId);\n if (!store || store.historicRuns.length === 0) return [];\n // The last run's snapshot has the complete conversation history\n return store.historicRuns[store.historicRuns.length - 1]!.messages;\n }\n\n /**\n * Returns all AG-UI events for a thread, compacted across historic runs.\n *\n * Powers the local-dev fallback for `GET /threads/:threadId/events` when the\n * Intelligence platform is not configured. The compaction logic matches\n * the connection-replay path in {@link connect}, so the stream a\n * late-joining inspector sees matches what this method returns.\n */\n getThreadEvents(threadId: string): BaseEvent[] {\n const store = GLOBAL_STORE.get(threadId);\n if (!store || store.historicRuns.length === 0) return [];\n const all: BaseEvent[] = [];\n for (const run of store.historicRuns) all.push(...run.events);\n return compactEvents(all);\n }\n\n /**\n * Returns the agent state snapshot for a thread.\n *\n * Derived from the last `STATE_SNAPSHOT` in the compacted event stream. The\n * AG-UI `compactEvents` helper consolidates STATE_DELTA events and produces\n * a single trailing STATE_SNAPSHOT when state changes exist, so this is a\n * faithful view of state at the end of the most recent run.\n *\n * Returns `null` when the thread has never emitted a STATE_SNAPSHOT.\n */\n getThreadState(threadId: string): Record<string, unknown> | null {\n const events = this.getThreadEvents(threadId);\n // Walk backwards — the last snapshot wins.\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i]!;\n if (event.type === EventType.STATE_SNAPSHOT) {\n const snapshot = (event as StateSnapshotEvent).snapshot;\n if (snapshot && typeof snapshot === \"object\") {\n return snapshot as Record<string, unknown>;\n }\n return null;\n }\n }\n return null;\n }\n\n /**\n * Clears all in-memory thread history.\n *\n * Powers the local-dev fallback for `POST /threads/clear`, letting consumers\n * (e.g. the demo's Clear button) reset to an empty thread list without\n * restarting the runtime. Intentionally not exposed on the Intelligence\n * platform path: there, thread history lives in a real database and must\n * not be wiped this way.\n */\n clearThreads(): void {\n GLOBAL_STORE.clear();\n }\n}\n"],"mappings":";;;;;;;AAkDA,IAAM,qBAAN,MAAyB;CACvB,YAAY,AAAO,UAAkB;EAAlB;iBAGwB;mBAG/B;sBAGkB;sBAGA,EAAE;eAGF;oBAGgB;uBAG9B;uBAGoB;;;AAGtC,MAAM,+BAAe,IAAI,KAAiC;AAE1D,IAAa,sBAAb,cAAyC,YAAY;CAanD,YAAY,SAAuD;AACjE,SAAO;uCAbgC;AAcvC,OAAK,kBAAkB,SAAS,mBAAmB;;CAGrD,IAAI,SAAuD;EACzD,IAAI,gBAAgB,aAAa,IAAI,QAAQ,SAAS;AACtD,MAAI,CAAC,eAAe;AAClB,mBAAgB,IAAI,mBAAmB,QAAQ,SAAS;AACxD,gBAAa,IAAI,QAAQ,UAAU,cAAc;;EAEnD,MAAM,QAAQ;AAEd,MAAI,MAAM,WAAW;AACnB,OAAI,KAAK,oBAAoB,YAC3B,OAAM,IAAI,MAAM,yBAAyB;GAK3C,MAAM,aAAa,MAAM;AACzB,SAAM,gBAAgB;AACtB,SAAM,YAAY;AAClB,OAAI,WACF,KAAI;AACF,eAAW,UAAU;YACd,OAAO;AACd,YAAQ,MAAM,kCAAkC,MAAM;;AAG1D,SAAM,gBAAgB;;AAExB,QAAM,YAAY;AAClB,QAAM,eAAe,QAAQ,MAAM;AACnC,QAAM,QAAQ,QAAQ;AACtB,QAAM,gBAAgB;EAGtB,MAAM,iCAAiB,IAAI,KAAa;EACxC,MAAM,mBAAgC,EAAE;AACxC,QAAM,gBAAgB;EAGtB,MAAM,qCAAqB,IAAI,KAAa;AAC5C,OAAK,MAAM,OAAO,MAAM,aACtB,MAAK,MAAM,SAAS,IAAI,QAAQ;AAC9B,OAAI,eAAe,SAAS,OAAO,MAAM,cAAc,SACrD,oBAAmB,IAAI,MAAM,UAAU;AAEzC,OAAI,MAAM,SAAS,UAAU,aAAa;IAExC,MAAM,WADa,MACS,OAAO,YAAY,EAAE;AACjD,SAAK,MAAM,WAAW,SACpB,oBAAmB,IAAI,QAAQ,GAAG;;;EAM1C,MAAM,cAAc,IAAI,cAAyB,SAAS;EAC1D,MAAM,cAAc,MAAM;AAG1B,QAAM,UAAU;EAGhB,MAAM,aAAa,IAAI,cAAyB,SAAS;AACzD,QAAM,aAAa;EAGnB,MAAM,WAAW,YAAY;GAG3B,MAAM,cADU,MAAM,aAAa,MAAM,aAAa,SAAS,IAClC,SAAS;AAEtC,OAAI;AACF,UAAM,QAAQ,MAAM,SAAS,QAAQ,OAAO;KAC1C,UAAU,EAAE,YAAY;MACtB,IAAI,iBAA4B;AAChC,UAAI,MAAM,SAAS,UAAU,aAAa;OACxC,MAAM,kBAAkB;AACxB,WAAI,CAAC,gBAAgB,OAAO;QAC1B,MAAM,oBAAoB,QAAQ,MAAM,WACpC,QAAQ,MAAM,SAAS,QACpB,YAAY,CAAC,mBAAmB,IAAI,QAAQ,GAAG,CACjD,GACD;QACJ,MAAM,eAAe;SACnB,GAAG,QAAQ;SACX,GAAI,sBAAsB,SACtB,EAAE,UAAU,mBAAmB,GAC/B,EAAE;SACP;AACD,yBAAiB;SACf,GAAG;SACH,OAAO;SACR;;;AAIL,iBAAW,KAAK,eAAe;AAC/B,kBAAY,KAAK,eAAe;AAChC,uBAAiB,KAAK,eAAe;;KAEvC,eAAe,EAAE,cAAc;AAE7B,UAAI,CAAC,eAAe,IAAI,QAAQ,GAAG,CACjC,gBAAe,IAAI,QAAQ,GAAG;;KAGlC,yBAAyB;AAEvB,UAAI,QAAQ,MAAM,UAChB;YAAK,MAAM,WAAW,QAAQ,MAAM,SAClC,KAAI,CAAC,eAAe,IAAI,QAAQ,GAAG,CACjC,gBAAe,IAAI,QAAQ,GAAG;;;KAKvC,CAAC;IAEF,MAAM,iBAAiB,kBAAkB,kBAAkB,EACzD,eAAe,MAAM,eACtB,CAAC;AACF,SAAK,MAAM,SAAS,gBAAgB;AAClC,gBAAW,KAAK,MAAM;AACtB,iBAAY,KAAK,MAAM;;AAOzB,QAAI,MAAM,iBAAiB,QAAQ,MAAM,OAAO;KAE9C,MAAM,kBAAkB,cAAc,iBAAiB;AAEvD,WAAM,aAAa,KAAK;MACtB,UAAU,QAAQ;MAClB,OAAO,QAAQ,MAAM;MACrB,SAAS,QAAQ,MAAM,WAAW;MAClC;MACA,QAAQ;MAER,UAAU,MAAM,QAAQ,QAAQ,MAAM,SAAS,GAC3C,CAAC,GAAG,QAAQ,MAAM,SAAS,GAC3B,EAAE;MACN,WAAW,KAAK,KAAK;MACtB,CAAC;;AAMJ,QAAI,MAAM,iBAAiB,QAAQ,MAAM,OAAO;AAC9C,WAAM,gBAAgB;AACtB,WAAM,eAAe;AACrB,WAAM,QAAQ;AACd,WAAM,aAAa;AACnB,WAAM,gBAAgB;AACtB,WAAM,YAAY;;AAEpB,eAAW,UAAU;AACrB,gBAAY,UAAU;YACf,OAAO;IACd,MAAM,sBACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IACxD,MAAM,iBAAiB,kBAAkB,kBAAkB;KACzD,eAAe,MAAM;KACrB;KACD,CAAC;AACF,SAAK,MAAM,SAAS,gBAAgB;AAClC,gBAAW,KAAK,MAAM;AACtB,iBAAY,KAAK,MAAM;;AAMzB,QACE,MAAM,iBAAiB,QAAQ,MAAM,SACrC,iBAAiB,SAAS,GAC1B;KAEA,MAAM,kBAAkB,cAAc,iBAAiB;AACvD,WAAM,aAAa,KAAK;MACtB,UAAU,QAAQ;MAClB,OAAO,QAAQ,MAAM;MACrB,SAAS,QAAQ,MAAM,WAAW;MAClC;MACA,QAAQ;MACR,UAAU,MAAM,QAAQ,QAAQ,MAAM,SAAS,GAC3C,CAAC,GAAG,QAAQ,MAAM,SAAS,GAC3B,EAAE;MACN,WAAW,KAAK,KAAK;MACtB,CAAC;;AAKJ,QAAI,MAAM,iBAAiB,QAAQ,MAAM,OAAO;AAC9C,WAAM,gBAAgB;AACtB,WAAM,eAAe;AACrB,WAAM,QAAQ;AACd,WAAM,aAAa;AACnB,WAAM,gBAAgB;AACtB,WAAM,YAAY;;AAEpB,eAAW,UAAU;AACrB,gBAAY,UAAU;;;AAK1B,MAAI,YACF,aAAY,UAAU;GACpB,OAAO,MAAM,YAAY,KAAK,EAAE;GAChC,QAAQ,QAAQ,YAAY,MAAM,IAAI;GACtC,gBAAgB;GAGjB,CAAC;AAIJ,YAAU;AAGV,SAAO,WAAW,cAAc;;CAGlC,QAAQ,SAA2D;EACjE,MAAM,QAAQ,aAAa,IAAI,QAAQ,SAAS;EAChD,MAAM,oBAAoB,IAAI,cAAyB,SAAS;AAEhE,MAAI,CAAC,OAAO;AAEV,qBAAkB,UAAU;AAC5B,UAAO,kBAAkB,cAAc;;EAIzC,MAAM,oBAAiC,EAAE;AACzC,OAAK,MAAM,OAAO,MAAM,aACtB,mBAAkB,KAAK,GAAG,IAAI,OAAO;EAIvC,MAAM,kBAAkB,cAAc,kBAAkB;EAGxD,MAAM,oCAAoB,IAAI,KAAa;AAC3C,OAAK,MAAM,SAAS,iBAAiB;AACnC,qBAAkB,KAAK,MAAM;AAC7B,OAAI,eAAe,SAAS,OAAO,MAAM,cAAc,SACrD,mBAAkB,IAAI,MAAM,UAAU;;AAK1C,MAAI,MAAM,YAAY,MAAM,aAAa,MAAM,eAC7C,OAAM,QAAQ,UAAU;GACtB,OAAO,UAAU;AAEf,QACE,eAAe,SACf,OAAO,MAAM,cAAc,YAC3B,kBAAkB,IAAI,MAAM,UAAU,CAEtC;AAEF,sBAAkB,KAAK,MAAM;;GAE/B,gBAAgB,kBAAkB,UAAU;GAC5C,QAAQ,QAAQ,kBAAkB,MAAM,IAAI;GAC7C,CAAC;MAGF,mBAAkB,UAAU;AAG9B,SAAO,kBAAkB,cAAc;;CAGzC,UAAU,SAAwD;EAChE,MAAM,QAAQ,aAAa,IAAI,QAAQ,SAAS;AAChD,SAAO,QAAQ,QAAQ,OAAO,aAAa,MAAM;;CAGnD,KAAK,SAA+D;EAClE,MAAM,QAAQ,aAAa,IAAI,QAAQ,SAAS;AAChD,MAAI,CAAC,SAAS,CAAC,MAAM,UACnB,QAAO,QAAQ,QAAQ,MAAM;AAE/B,MAAI,MAAM,cACR,QAAO,QAAQ,QAAQ,MAAM;AAG/B,QAAM,gBAAgB;AACtB,QAAM,YAAY;EAElB,MAAM,QAAQ,MAAM;AACpB,MAAI,CAAC,OAAO;AACV,SAAM,gBAAgB;AACtB,SAAM,YAAY;AAClB,UAAO,QAAQ,QAAQ,MAAM;;AAG/B,MAAI;AACF,SAAM,UAAU;AAChB,UAAO,QAAQ,QAAQ,KAAK;WACrB,OAAO;AACd,WAAQ,MAAM,6BAA6B,MAAM;AACjD,SAAM,gBAAgB;AACtB,SAAM,YAAY;AAClB,UAAO,QAAQ,QAAQ,MAAM;;;;;;;;;;CAWjC,cAAgC;EAC9B,MAAM,UAA4B,EAAE;AACpC,OAAK,MAAM,CAAC,UAAU,UAAU,cAAc;AAC5C,OAAI,MAAM,aAAa,WAAW,EAAG;GACrC,MAAM,WAAW,MAAM,aAAa;GACpC,MAAM,UAAU,MAAM,aAAa,MAAM,aAAa,SAAS;AAC/D,WAAQ,KAAK;IACX,IAAI;IACJ,MAAM;IACN,SAAS,QAAQ;IACjB,gBAAgB;IAChB,aAAa;IACb,UAAU;IACV,WAAW,IAAI,KAAK,SAAS,UAAU,CAAC,aAAa;IACrD,WAAW,IAAI,KAAK,QAAQ,UAAU,CAAC,aAAa;IACrD,CAAC;;AAGJ,SAAO,QAAQ,MACZ,GAAG,MACF,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,CACpE;;;;;;;;;;;CAYH,kBAAkB,UAA6B;EAC7C,MAAM,QAAQ,aAAa,IAAI,SAAS;AACxC,MAAI,CAAC,SAAS,MAAM,aAAa,WAAW,EAAG,QAAO,EAAE;AAExD,SAAO,MAAM,aAAa,MAAM,aAAa,SAAS,GAAI;;;;;;;;;;CAW5D,gBAAgB,UAA+B;EAC7C,MAAM,QAAQ,aAAa,IAAI,SAAS;AACxC,MAAI,CAAC,SAAS,MAAM,aAAa,WAAW,EAAG,QAAO,EAAE;EACxD,MAAM,MAAmB,EAAE;AAC3B,OAAK,MAAM,OAAO,MAAM,aAAc,KAAI,KAAK,GAAG,IAAI,OAAO;AAC7D,SAAO,cAAc,IAAI;;;;;;;;;;;;CAa3B,eAAe,UAAkD;EAC/D,MAAM,SAAS,KAAK,gBAAgB,SAAS;AAE7C,OAAK,IAAI,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;GAC3C,MAAM,QAAQ,OAAO;AACrB,OAAI,MAAM,SAAS,UAAU,gBAAgB;IAC3C,MAAM,WAAY,MAA6B;AAC/C,QAAI,YAAY,OAAO,aAAa,SAClC,QAAO;AAET,WAAO;;;AAGX,SAAO;;;;;;;;;;;CAYT,eAAqB;AACnB,eAAa,OAAO"}
@@ -36,9 +36,9 @@ var IntelligenceAgentRunner = class extends require_agent_runner.AgentRunner {
36
36
  * closeWasClean = true and reset the reconnect timer — permanently
37
37
  * killing retries.
38
38
  */
39
- createSocket(authToken = this.options.authToken) {
39
+ createSocket() {
40
40
  const socket = new phoenix.Socket(this.options.url, {
41
- ...authToken ? { authToken } : {},
41
+ ...this.options.authToken ? { authToken: this.options.authToken } : {},
42
42
  reconnectAfterMs: (0, _copilotkit_shared.phoenixExponentialBackoff)(100, this.options.maxReconnectMs ?? 1e4),
43
43
  rejoinAfterMs: (0, _copilotkit_shared.phoenixExponentialBackoff)(1e3, this.options.maxRejoinMs ?? 3e4)
44
44
  });
@@ -54,10 +54,11 @@ var IntelligenceAgentRunner = class extends require_agent_runner.AgentRunner {
54
54
  return payload;
55
55
  }
56
56
  stampCanonicalRunOwnership(event, request) {
57
- const eventRecord = event;
58
- eventRecord.threadId = request.threadId;
59
- eventRecord.runId = request.input.runId;
60
- return eventRecord;
57
+ return {
58
+ ...event,
59
+ threadId: request.threadId,
60
+ runId: request.input.runId
61
+ };
61
62
  }
62
63
  stampRunnerMetadata(event, state) {
63
64
  const eventRecord = event;
@@ -70,12 +71,14 @@ var IntelligenceAgentRunner = class extends require_agent_runner.AgentRunner {
70
71
  return eventRecord;
71
72
  }
72
73
  const eventSeq = state.nextEventSeq++;
73
- eventRecord.metadata = {
74
- ...existingMetadata,
75
- cpki_event_id: typeof existingMetadata.cpki_event_id === "string" ? existingMetadata.cpki_event_id : (0, node_crypto.randomUUID)(),
76
- cpki_event_seq: eventSeq
74
+ return {
75
+ ...eventRecord,
76
+ metadata: {
77
+ ...existingMetadata,
78
+ cpki_event_id: typeof existingMetadata.cpki_event_id === "string" ? existingMetadata.cpki_event_id : (0, node_crypto.randomUUID)(),
79
+ cpki_event_seq: eventSeq
80
+ }
77
81
  };
78
- return eventRecord;
79
82
  }
80
83
  run(request) {
81
84
  return this.createRunObservable(request);
@@ -99,7 +102,7 @@ var IntelligenceAgentRunner = class extends require_agent_runner.AgentRunner {
99
102
  const { threadId, agent, input } = request;
100
103
  if (this.threads.get(threadId)?.isRunning) throw new Error("Thread already running");
101
104
  return new rxjs.Observable((observer) => {
102
- const socket = this.createSocket(request.authToken);
105
+ const socket = this.createSocket();
103
106
  const channel = socket.channel(`ingestion:${input.runId}`, {
104
107
  thread_id: threadId,
105
108
  run_id: input.runId
@@ -131,9 +134,7 @@ var IntelligenceAgentRunner = class extends require_agent_runner.AgentRunner {
131
134
  });
132
135
  channel.join().receive("ok", () => {
133
136
  startupBoundary?.resolveStartup();
134
- this.executeAgentRun(request, state, threadId, (event) => {
135
- observer.next(event);
136
- }).subscribe({ complete: () => observer.complete() });
137
+ this.executeAgentRun(request, state, threadId).subscribe({ complete: () => observer.complete() });
137
138
  }).receive("error", (resp) => {
138
139
  const error = /* @__PURE__ */ new Error(`Failed to join channel: ${JSON.stringify(resp)}`);
139
140
  const errorEvent = {
@@ -202,7 +203,7 @@ var IntelligenceAgentRunner = class extends require_agent_runner.AgentRunner {
202
203
  } catch {}
203
204
  return Promise.resolve(true);
204
205
  }
205
- executeAgentRun(request, state, threadId, onRunError) {
206
+ executeAgentRun(request, state, threadId) {
206
207
  const { currentEvents, channel } = state;
207
208
  const pushCanonicalEvent = (event) => {
208
209
  const canonicalEvent = this.stampRunnerMetadata(this.stampCanonicalRunOwnership(event, request), state);
@@ -214,20 +215,21 @@ var IntelligenceAgentRunner = class extends require_agent_runner.AgentRunner {
214
215
  const buildRunStartedEvent = (source) => {
215
216
  const baseInput = source?.input ?? request.input;
216
217
  const persistedInputMessages = getPersistedInputMessages();
217
- const event = source ?? {
218
- type: _ag_ui_client.EventType.RUN_STARTED,
219
- threadId: request.threadId,
220
- runId: request.input.runId
221
- };
222
- event.threadId = request.threadId;
223
- event.runId = request.input.runId;
224
- event.input = {
225
- ...baseInput,
218
+ return {
219
+ ...source ?? {
220
+ type: _ag_ui_client.EventType.RUN_STARTED,
221
+ threadId: request.threadId,
222
+ runId: request.input.runId
223
+ },
226
224
  threadId: request.threadId,
227
225
  runId: request.input.runId,
228
- ...persistedInputMessages !== void 0 ? { messages: persistedInputMessages } : {}
226
+ input: {
227
+ ...baseInput,
228
+ threadId: request.threadId,
229
+ runId: request.input.runId,
230
+ ...persistedInputMessages !== void 0 ? { messages: persistedInputMessages } : {}
231
+ }
229
232
  };
230
- return event;
231
233
  };
232
234
  const ensureRunStarted = () => {
233
235
  if (!state.hasRunStarted) {
@@ -244,17 +246,10 @@ var IntelligenceAgentRunner = class extends require_agent_runner.AgentRunner {
244
246
  pushCanonicalEvent(event);
245
247
  } })).pipe((0, rxjs_operators.catchError)((error) => {
246
248
  ensureRunStarted();
247
- const existingError = currentEvents.find((event) => event.type === _ag_ui_client.EventType.RUN_ERROR);
248
- if (existingError) {
249
- onRunError(existingError);
250
- return rxjs.EMPTY;
251
- }
252
- const errorEvent = {
249
+ pushCanonicalEvent({
253
250
  type: _ag_ui_client.EventType.RUN_ERROR,
254
251
  message: error instanceof Error ? error.message : String(error)
255
- };
256
- pushCanonicalEvent(errorEvent);
257
- onRunError(errorEvent);
252
+ });
258
253
  return rxjs.EMPTY;
259
254
  }), (0, rxjs_operators.finalize)(() => {
260
255
  ensureRunStarted();
@@ -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 type {\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n} from \"./agent-runner\";\nimport { AgentRunner } from \"./agent-runner\";\nimport type { AgentRunnerStopRequest } from \"./agent-runner\";\nimport { EMPTY, Observable, from } from \"rxjs\";\nimport { catchError, finalize } from \"rxjs/operators\";\nimport type { AbstractAgent, BaseEvent, RunStartedEvent } from \"@ag-ui/client\";\nimport { EventType } from \"@ag-ui/client\";\nimport {\n finalizeRunEvents,\n AG_UI_CHANNEL_EVENT,\n phoenixExponentialBackoff,\n} from \"@copilotkit/shared\";\nimport type { Channel } from \"phoenix\";\nimport { Socket } 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(authToken = this.options.authToken): Socket {\n const socket = new Socket(this.options.url, {\n ...(authToken ? { 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 const eventRecord = event as BaseEvent & Record<string, unknown>;\n eventRecord.threadId = request.threadId;\n eventRecord.runId = request.input.runId;\n return eventRecord;\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 eventRecord.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 return eventRecord;\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(request.authToken);\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, (event) => {\n observer.next(event);\n }).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 // The emitted values are ignored by the caller (only `complete` matters);\n // `runAgent()` resolves with a RunAgentResult that flows through `from()`.\n private executeAgentRun(\n request: AgentRunnerRunRequest,\n state: ThreadState,\n threadId: string,\n onRunError: (event: BaseEvent) => void,\n ): Observable<unknown> {\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 const event =\n source ??\n ({\n type: EventType.RUN_STARTED,\n threadId: request.threadId,\n runId: request.input.runId,\n } as RunStartedEvent);\n event.threadId = request.threadId;\n event.runId = request.input.runId;\n event.input = {\n ...baseInput,\n threadId: request.threadId,\n runId: request.input.runId,\n ...(persistedInputMessages !== undefined\n ? { messages: persistedInputMessages }\n : {}),\n };\n return event;\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 existingError = currentEvents.find(\n (event) => event.type === EventType.RUN_ERROR,\n );\n if (existingError) {\n onRunError(existingError);\n return EMPTY;\n }\n const errorEvent = {\n type: EventType.RUN_ERROR,\n message: error instanceof Error ? error.message : String(error),\n } as BaseEvent;\n pushCanonicalEvent(errorEvent);\n onRunError(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":";;;;;;;;;;;AA+CA,IAAa,0BAAb,cAA6CA,iCAAY;CAIvD,YAAY,SAAyC;AACnD,SAAO;iCAHS,IAAI,KAA0B;AAK9C,OAAK,UAAU;;;;;;;;;;;;;;;;;;;;;;;CAwBjB,AAAQ,aAAa,YAAY,KAAK,QAAQ,WAAmB;EAC/D,MAAM,SAAS,IAAIC,eAAO,KAAK,QAAQ,KAAK;GAC1C,GAAI,YAAY,EAAE,WAAW,GAAG,EAAE;GAClC,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;EAKzB,MAAM,UAAU,EACd,GALqB,KAAK,oBAC1B,KAAK,2BAA2B,OAAO,QAAQ,EAC/C,MACD,EAGA;AAED,UAAQ,WAAW,QAAQ;AAC3B,UAAQ,QAAQ,QAAQ,MAAM;AAC9B,UAAQ,YAAY,QAAQ;AAC5B,UAAQ,SAAS,QAAQ,MAAM;AAE/B,SAAO;;CAGT,AAAQ,2BACN,OACA,SACW;EACX,MAAM,cAAc;AACpB,cAAY,WAAW,QAAQ;AAC/B,cAAY,QAAQ,QAAQ,MAAM;AAClC,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,cAAY,WAAW;GACrB,GAAG;GACH,eACE,OAAO,iBAAiB,kBAAkB,WACtC,iBAAiB,6CACL;GAClB,gBAAgB;GACjB;AACD,SAAO;;CAGT,IAAI,SAAuD;AACzD,SAAO,KAAK,oBAAoB,QAAQ;;CAG1C,uBACE,SACuB;EACvB,IAAI;EACJ,IAAI;EACJ,MAAM,UAAU,IAAI,SAAe,SAAS,WAAW;AACrD,oBAAiB;AACjB,mBAAgB;IAChB;AAEF,SAAO;GACL,QAAQ,KAAK,oBAAoB,SAAS;IACxC,sBAAsB,kBAAkB;IACxC,gBAAgB,UAAU,gBAAgB,MAAM;IACjD,CAAC;GACF;GACD;;CAGH,AAAQ,oBACN,SACA,iBAIuB;EACvB,MAAM,EAAE,UAAU,OAAO,UAAU;AAGnC,MADiB,KAAK,QAAQ,IAAI,SAAS,EAC7B,UACZ,OAAM,IAAI,MAAM,yBAAyB;AAG3C,SAAO,IAAIC,iBAAY,aAAa;GAClC,MAAM,SAAS,KAAK,aAAa,QAAQ,UAAU;GAEnD,MAAM,UAAU,OAAO,QAAQ,aAAa,MAAM,SAAS;IACzD,WAAW;IACX,QAAQ,MAAM;IACf,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,qBAAiB,gBAAgB;AACjC,SAAK,gBAAgB,SAAS,OAAO,WAAW,UAAU;AACxD,cAAS,KAAK,MAAM;MACpB,CAAC,UAAU,EACX,gBAAgB,SAAS,UAAU,EACpC,CAAC;KACF,CACD,QAAQ,UAAU,SAAS;IAC1B,MAAM,wBAAQ,IAAI,MAChB,2BAA2B,KAAK,UAAU,KAAK,GAChD;IACD,MAAM,aAAa;KACjB,MAAMA,wBAAU;KAChB,SAAS,MAAM;KACf,MAAM;KACP;AACD,aAAS,KAAK,WAAW;AACzB,UAAM,cAAc,KAAK,WAAW;AACpC,SAAK,aAAa,SAAS;AAC3B,qBAAiB,cAAc,MAAM;AACrC,aAAS,UAAU;KACnB,CACD,QAAQ,iBAAiB;IACxB,MAAM,wBAAQ,IAAI,MAAM,4BAA4B;IACpD,MAAM,aAAa;KACjB,MAAMA,wBAAU;KAChB,SAAS,MAAM;KACf,MAAM;KACP;AACD,aAAS,KAAK,WAAW;AACzB,UAAM,cAAc,KAAK,WAAW;AACpC,SAAK,aAAa,SAAS;AAC3B,qBAAiB,cAAc,MAAM;AACrC,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;;CAK9B,AAAQ,gBACN,SACA,OACA,UACA,YACqB;EACrB,MAAM,EAAE,eAAe,YAAY;EACnC,MAAM,sBAAsB,UAA2B;GACrD,MAAM,iBAAiB,KAAK,oBAC1B,KAAK,2BAA2B,OAAO,QAAQ,EAC/C,MACD;AACD,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;GAC1D,MAAM,QACJ,UACC;IACC,MAAMA,wBAAU;IAChB,UAAU,QAAQ;IAClB,OAAO,QAAQ,MAAM;IACtB;AACH,SAAM,WAAW,QAAQ;AACzB,SAAM,QAAQ,QAAQ,MAAM;AAC5B,SAAM,QAAQ;IACZ,GAAG;IACH,UAAU,QAAQ;IAClB,OAAO,QAAQ,MAAM;IACrB,GAAI,2BAA2B,SAC3B,EAAE,UAAU,wBAAwB,GACpC,EAAE;IACP;AACD,UAAO;;EAGT,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;GAClB,MAAM,gBAAgB,cAAc,MACjC,UAAU,MAAM,SAASA,wBAAU,UACrC;AACD,OAAI,eAAe;AACjB,eAAW,cAAc;AACzB,WAAOC;;GAET,MAAM,aAAa;IACjB,MAAMD,wBAAU;IAChB,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAChE;AACD,sBAAmB,WAAW;AAC9B,cAAW,WAAW;AACtB,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 type {\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n} from \"./agent-runner\";\nimport { AgentRunner } from \"./agent-runner\";\nimport type { AgentRunnerStopRequest } from \"./agent-runner\";\nimport { EMPTY, Observable, from } from \"rxjs\";\nimport { catchError, finalize } from \"rxjs/operators\";\nimport type { AbstractAgent, BaseEvent, RunStartedEvent } from \"@ag-ui/client\";\nimport { EventType } from \"@ag-ui/client\";\nimport {\n finalizeRunEvents,\n AG_UI_CHANNEL_EVENT,\n phoenixExponentialBackoff,\n} from \"@copilotkit/shared\";\nimport type { Channel } from \"phoenix\";\nimport { Socket } 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 // The emitted values are ignored by the caller (only `complete` matters);\n // `runAgent()` resolves with a RunAgentResult that flows through `from()`.\n private executeAgentRun(\n request: AgentRunnerRunRequest,\n state: ThreadState,\n threadId: string,\n ): Observable<unknown> {\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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"intelligence.d.cts","names":[],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"mappings":";;;;;;UAoBiB,8BAAA;EAA8B;EAE7C,GAAA;EAF6C;EAI7C,SAAA;EAAA;EAEA,cAAA;EAEA;EAAA,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;EAnBrB;;;;;;;AAeF;;;;;;;;;;;;;;EAfE,QA8CQ,YAAA;EAAA,QAgBA,wBAAA;EAAA,QAqBA,0BAAA;EAAA,QAUA,mBAAA;EA4BR,GAAA,CAAI,OAAA,EAAS,qBAAA,GAAwB,UAAA,CAAW,SAAA;EAIhD,sBAAA,CACE,OAAA,EAAS,qBAAA,GACR,qBAAA;EAAA,QAiBK,mBAAA;EA6HR,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,QAsB/B,eAAA;EAtSA;;;;;;;EAAA,QAsZA,YAAA;AAAA"}
1
+ {"version":3,"file":"intelligence.d.cts","names":[],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"mappings":";;;;;;UAoBiB,8BAAA;EAA8B;EAE7C,GAAA;EAF6C;EAI7C,SAAA;EAAA;EAEA,cAAA;EAEA;EAAA,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;EAnBrB;;;;;;;AAeF;;;;;;;;;;;;;;EAfE,QA8CQ,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,QAsB/B,eAAA;EAvSA;;;;;;;EAAA,QA8YA,YAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"intelligence.d.mts","names":[],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"mappings":";;;;;;UAoBiB,8BAAA;EAA8B;EAE7C,GAAA;EAF6C;EAI7C,SAAA;EAAA;EAEA,cAAA;EAEA;EAAA,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;EAnBrB;;;;;;;AAeF;;;;;;;;;;;;;;EAfE,QA8CQ,YAAA;EAAA,QAgBA,wBAAA;EAAA,QAqBA,0BAAA;EAAA,QAUA,mBAAA;EA4BR,GAAA,CAAI,OAAA,EAAS,qBAAA,GAAwB,UAAA,CAAW,SAAA;EAIhD,sBAAA,CACE,OAAA,EAAS,qBAAA,GACR,qBAAA;EAAA,QAiBK,mBAAA;EA6HR,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,QAsB/B,eAAA;EAtSA;;;;;;;EAAA,QAsZA,YAAA;AAAA"}
1
+ {"version":3,"file":"intelligence.d.mts","names":[],"sources":["../../../../src/v2/runtime/runner/intelligence.ts"],"mappings":";;;;;;UAoBiB,8BAAA;EAA8B;EAE7C,GAAA;EAF6C;EAI7C,SAAA;EAAA;EAEA,cAAA;EAEA;EAAA,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;EAnBrB;;;;;;;AAeF;;;;;;;;;;;;;;EAfE,QA8CQ,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,QAsB/B,eAAA;EAvSA;;;;;;;EAAA,QA8YA,YAAA;AAAA"}
@@ -35,9 +35,9 @@ var IntelligenceAgentRunner = class extends AgentRunner {
35
35
  * closeWasClean = true and reset the reconnect timer — permanently
36
36
  * killing retries.
37
37
  */
38
- createSocket(authToken = this.options.authToken) {
38
+ createSocket() {
39
39
  const socket = new Socket(this.options.url, {
40
- ...authToken ? { authToken } : {},
40
+ ...this.options.authToken ? { authToken: this.options.authToken } : {},
41
41
  reconnectAfterMs: phoenixExponentialBackoff(100, this.options.maxReconnectMs ?? 1e4),
42
42
  rejoinAfterMs: phoenixExponentialBackoff(1e3, this.options.maxRejoinMs ?? 3e4)
43
43
  });
@@ -53,10 +53,11 @@ var IntelligenceAgentRunner = class extends AgentRunner {
53
53
  return payload;
54
54
  }
55
55
  stampCanonicalRunOwnership(event, request) {
56
- const eventRecord = event;
57
- eventRecord.threadId = request.threadId;
58
- eventRecord.runId = request.input.runId;
59
- return eventRecord;
56
+ return {
57
+ ...event,
58
+ threadId: request.threadId,
59
+ runId: request.input.runId
60
+ };
60
61
  }
61
62
  stampRunnerMetadata(event, state) {
62
63
  const eventRecord = event;
@@ -69,12 +70,14 @@ var IntelligenceAgentRunner = class extends AgentRunner {
69
70
  return eventRecord;
70
71
  }
71
72
  const eventSeq = state.nextEventSeq++;
72
- eventRecord.metadata = {
73
- ...existingMetadata,
74
- cpki_event_id: typeof existingMetadata.cpki_event_id === "string" ? existingMetadata.cpki_event_id : randomUUID$1(),
75
- cpki_event_seq: eventSeq
73
+ return {
74
+ ...eventRecord,
75
+ metadata: {
76
+ ...existingMetadata,
77
+ cpki_event_id: typeof existingMetadata.cpki_event_id === "string" ? existingMetadata.cpki_event_id : randomUUID$1(),
78
+ cpki_event_seq: eventSeq
79
+ }
76
80
  };
77
- return eventRecord;
78
81
  }
79
82
  run(request) {
80
83
  return this.createRunObservable(request);
@@ -98,7 +101,7 @@ var IntelligenceAgentRunner = class extends AgentRunner {
98
101
  const { threadId, agent, input } = request;
99
102
  if (this.threads.get(threadId)?.isRunning) throw new Error("Thread already running");
100
103
  return new Observable((observer) => {
101
- const socket = this.createSocket(request.authToken);
104
+ const socket = this.createSocket();
102
105
  const channel = socket.channel(`ingestion:${input.runId}`, {
103
106
  thread_id: threadId,
104
107
  run_id: input.runId
@@ -130,9 +133,7 @@ var IntelligenceAgentRunner = class extends AgentRunner {
130
133
  });
131
134
  channel.join().receive("ok", () => {
132
135
  startupBoundary?.resolveStartup();
133
- this.executeAgentRun(request, state, threadId, (event) => {
134
- observer.next(event);
135
- }).subscribe({ complete: () => observer.complete() });
136
+ this.executeAgentRun(request, state, threadId).subscribe({ complete: () => observer.complete() });
136
137
  }).receive("error", (resp) => {
137
138
  const error = /* @__PURE__ */ new Error(`Failed to join channel: ${JSON.stringify(resp)}`);
138
139
  const errorEvent = {
@@ -201,7 +202,7 @@ var IntelligenceAgentRunner = class extends AgentRunner {
201
202
  } catch {}
202
203
  return Promise.resolve(true);
203
204
  }
204
- executeAgentRun(request, state, threadId, onRunError) {
205
+ executeAgentRun(request, state, threadId) {
205
206
  const { currentEvents, channel } = state;
206
207
  const pushCanonicalEvent = (event) => {
207
208
  const canonicalEvent = this.stampRunnerMetadata(this.stampCanonicalRunOwnership(event, request), state);
@@ -213,20 +214,21 @@ var IntelligenceAgentRunner = class extends AgentRunner {
213
214
  const buildRunStartedEvent = (source) => {
214
215
  const baseInput = source?.input ?? request.input;
215
216
  const persistedInputMessages = getPersistedInputMessages();
216
- const event = source ?? {
217
- type: EventType.RUN_STARTED,
218
- threadId: request.threadId,
219
- runId: request.input.runId
220
- };
221
- event.threadId = request.threadId;
222
- event.runId = request.input.runId;
223
- event.input = {
224
- ...baseInput,
217
+ return {
218
+ ...source ?? {
219
+ type: EventType.RUN_STARTED,
220
+ threadId: request.threadId,
221
+ runId: request.input.runId
222
+ },
225
223
  threadId: request.threadId,
226
224
  runId: request.input.runId,
227
- ...persistedInputMessages !== void 0 ? { messages: persistedInputMessages } : {}
225
+ input: {
226
+ ...baseInput,
227
+ threadId: request.threadId,
228
+ runId: request.input.runId,
229
+ ...persistedInputMessages !== void 0 ? { messages: persistedInputMessages } : {}
230
+ }
228
231
  };
229
- return event;
230
232
  };
231
233
  const ensureRunStarted = () => {
232
234
  if (!state.hasRunStarted) {
@@ -243,17 +245,10 @@ var IntelligenceAgentRunner = class extends AgentRunner {
243
245
  pushCanonicalEvent(event);
244
246
  } })).pipe(catchError$1((error) => {
245
247
  ensureRunStarted();
246
- const existingError = currentEvents.find((event) => event.type === EventType.RUN_ERROR);
247
- if (existingError) {
248
- onRunError(existingError);
249
- return EMPTY;
250
- }
251
- const errorEvent = {
248
+ pushCanonicalEvent({
252
249
  type: EventType.RUN_ERROR,
253
250
  message: error instanceof Error ? error.message : String(error)
254
- };
255
- pushCanonicalEvent(errorEvent);
256
- onRunError(errorEvent);
251
+ });
257
252
  return EMPTY;
258
253
  }), finalize$1(() => {
259
254
  ensureRunStarted();