@copilotkit/core 1.63.3-canary.rc-1 → 1.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +50 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +50 -16
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +52 -16
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["Observable","Socket","NEVER","EMPTY","AbstractAgent","Subject","EMPTY","EventType","Notification","isAbortError","EMPTY","HttpAgent","RUNTIME_MODE_SSE","RUNTIME_MODE_INTELLIGENCE","#connectViaDelegate","#connectViaHttp","#runViaDelegate","#runViaHttp","RUNTIME_MODE_SSE","HttpAgent","HttpAgent","Subscription","BehaviorSubject","Subject","asapScheduler","REQUEST_TIMEOUT_MS","MAX_SOCKET_RETRIES","asapScheduler","ɵcreateMemoryStore","Throttler","Observable","#responses","#pending","#replace","#sealed","#respond"],"sources":["../src/utils/phoenix-observable.ts","../src/intelligence-agent.ts","../src/agent.ts","../src/core/agent-registry.ts","../src/core/context-store.ts","../src/core/suggestion-engine.ts","../src/core/run-handler.ts","../src/core/state-manager.ts","../src/core/thread-store-registry.ts","../src/utils/micro-redux.ts","../src/memory-errors.ts","../src/memory.ts","../src/core/core.ts","../src/types.ts","../src/utils/markdown.ts","../src/threads.ts","../src/features.ts","../src/interrupt-state.ts"],"sourcesContent":["import { Socket } from \"phoenix\";\nimport { EMPTY, NEVER, Observable, concat, defer, of, throwError } from \"rxjs\";\nimport {\n filter,\n finalize,\n mergeMap,\n scan,\n shareReplay,\n switchMap,\n take,\n} from \"rxjs/operators\";\n\n/**\n * Minimal Phoenix push contract used by the observable adapters.\n */\nexport interface ɵPhoenixPushLike {\n receive(\n status: string,\n callback: (payload?: unknown) => unknown,\n ): ɵPhoenixPushLike;\n}\n\n/**\n * Minimal Phoenix channel contract used by the observable adapters.\n */\nexport interface ɵPhoenixChannelLike {\n on(event: string, callback: (payload: unknown) => void): number;\n off(event: string, ref?: number): void;\n onError?(callback: (reason?: unknown) => void): unknown;\n join(params?: Record<string, unknown>): ɵPhoenixPushLike;\n push?(event: string, payload: unknown): ɵPhoenixPushLike;\n leave(): void;\n}\n\n/**\n * Minimal Phoenix socket contract used by the observable adapters.\n */\nexport interface ɵPhoenixSocketLike {\n connect(): void;\n disconnect(): void;\n channel(topic: string, params?: Record<string, unknown>): ɵPhoenixChannelLike;\n onError(callback: (error?: unknown) => void): unknown;\n onOpen(callback: () => void): unknown;\n}\n\n/**\n * Socket lifecycle notifications exposed by {@link ɵphoenixSocket$}.\n */\nexport type ɵPhoenixSocketSignal =\n | { type: \"open\" }\n | { type: \"error\"; error?: unknown };\n\n/**\n * Terminal outcomes of a Phoenix channel join attempt.\n */\nexport type ɵPhoenixJoinOutcome =\n | { type: \"joined\" }\n | { type: \"error\"; response?: unknown }\n | { type: \"timeout\" };\n\n/**\n * Active Phoenix socket session plus its derived lifecycle stream.\n */\nexport interface ɵPhoenixSocketSession {\n socket: ɵPhoenixSocketLike;\n signals$: Observable<ɵPhoenixSocketSignal>;\n}\n\n/**\n * Active Phoenix channel session plus its derived join-outcome stream.\n */\nexport interface ɵPhoenixChannelSession {\n channel: ɵPhoenixChannelLike;\n joinOutcome$: Observable<ɵPhoenixJoinOutcome>;\n}\n\n/**\n * Options for creating a cold Phoenix socket session stream.\n */\nexport interface ɵPhoenixSocketOptions {\n url: string;\n options?: Record<string, unknown>;\n}\n\n/**\n * Options for creating a cold Phoenix channel session stream from a socket stream.\n */\nexport interface ɵPhoenixChannelOptions {\n socket$: Observable<ɵPhoenixSocketSession>;\n topic: string;\n params?: Record<string, unknown>;\n leaveOnUnsubscribe?: boolean;\n}\n\n/**\n * Adapt Phoenix socket open/error callbacks into an observable signal stream.\n *\n * The returned observable is shared and replayable by the caller when needed,\n * but this helper itself does not own socket connection teardown.\n */\nfunction ɵcreatePhoenixSocketSignals$(\n socket: ɵPhoenixSocketLike,\n): Observable<ɵPhoenixSocketSignal> {\n return new Observable<ɵPhoenixSocketSignal>((observer) => {\n socket.onOpen(() => observer.next({ type: \"open\" }));\n socket.onError((error) => observer.next({ type: \"error\", error }));\n });\n}\n\n/**\n * Adapt a Phoenix channel join attempt into a single-outcome observable.\n */\nfunction ɵcreatePhoenixJoinOutcome$(\n channel: ɵPhoenixChannelLike,\n): Observable<ɵPhoenixJoinOutcome> {\n return new Observable<ɵPhoenixJoinOutcome>((observer) => {\n channel\n .join()\n .receive(\"ok\", () => {\n observer.next({ type: \"joined\" });\n observer.complete();\n })\n .receive(\"error\", (response?: unknown) => {\n observer.next({ type: \"error\", response });\n observer.complete();\n })\n .receive(\"timeout\", () => {\n observer.next({ type: \"timeout\" });\n observer.complete();\n });\n });\n}\n\n/**\n * Create a cold Phoenix socket session.\n *\n * The socket is constructed and connected on subscription, and disconnected on\n * teardown. Each subscription creates an isolated socket instance.\n */\nexport function ɵphoenixSocket$(\n options: ɵPhoenixSocketOptions,\n): Observable<ɵPhoenixSocketSession> {\n return defer(() => {\n const socket = new Socket(\n options.url,\n options.options as ConstructorParameters<typeof Socket>[1],\n ) as ɵPhoenixSocketLike;\n const signals$ = ɵcreatePhoenixSocketSignals$(socket).pipe(\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n\n socket.connect();\n\n return concat(\n of({\n socket,\n signals$,\n }),\n NEVER,\n ).pipe(finalize(() => socket.disconnect()));\n });\n}\n\n/**\n * Create a cold Phoenix channel session from a socket session stream.\n *\n * A channel is created and joined for each active socket session. If the\n * upstream socket session changes, the previous channel is left before the\n * next one becomes active.\n */\nexport function ɵphoenixChannel$(\n options: ɵPhoenixChannelOptions,\n): Observable<ɵPhoenixChannelSession> {\n return options.socket$.pipe(\n switchMap(({ socket }) =>\n defer(() => {\n const channel = socket.channel(options.topic, options.params);\n const joinOutcome$ = ɵcreatePhoenixJoinOutcome$(channel).pipe(\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n\n return concat(\n of({\n channel,\n joinOutcome$,\n }),\n NEVER,\n ).pipe(\n finalize(() => {\n if (options.leaveOnUnsubscribe !== false) {\n channel.leave();\n }\n }),\n );\n }),\n ),\n );\n}\n\n/**\n * Observe a named Phoenix channel event as an observable payload stream.\n */\nexport function ɵobservePhoenixEvent$<T>(\n channel: ɵPhoenixChannelLike,\n eventName: string,\n): Observable<T> {\n return new Observable<T>((observer) => {\n const ref = channel.on(eventName, (payload) => observer.next(payload as T));\n\n return () => {\n channel.off(eventName, ref);\n };\n });\n}\n\n/**\n * Flatten channel sessions into their join-outcome stream.\n */\nexport function ɵobservePhoenixJoinOutcome$(\n channel$: Observable<ɵPhoenixChannelSession>,\n): Observable<ɵPhoenixJoinOutcome> {\n return channel$.pipe(switchMap((session) => session.joinOutcome$));\n}\n\n/**\n * Complete when a channel joins successfully, or error if the join fails.\n */\nexport function ɵjoinPhoenixChannel$(\n channel$: Observable<ɵPhoenixChannelSession>,\n): Observable<never> {\n return ɵobservePhoenixJoinOutcome$(channel$).pipe(\n take(1),\n mergeMap((outcome) => {\n if (outcome.type === \"joined\") {\n return EMPTY;\n }\n\n throw outcome.type === \"timeout\"\n ? new Error(\"Timed out joining channel\")\n : new Error(\n `Failed to join channel: ${JSON.stringify(outcome.response)}`,\n );\n }),\n );\n}\n\n/**\n * Flatten socket sessions into their lifecycle signal stream.\n */\nexport function ɵobservePhoenixSocketSignals$(\n socket$: Observable<ɵPhoenixSocketSession>,\n): Observable<ɵPhoenixSocketSignal> {\n return socket$.pipe(switchMap((session) => session.signals$));\n}\n\n/**\n * Error after a socket emits the configured number of consecutive error\n * signals, resetting the counter after each successful open signal.\n */\nexport function ɵobservePhoenixSocketHealth$(\n socketSignals$: Observable<ɵPhoenixSocketSignal>,\n maxConsecutiveErrors: number,\n): Observable<never> {\n return socketSignals$.pipe(\n scan(\n (consecutiveErrors, signal) =>\n signal.type === \"open\" ? 0 : consecutiveErrors + 1,\n 0,\n ),\n filter((consecutiveErrors) => consecutiveErrors >= maxConsecutiveErrors),\n take(1),\n mergeMap((consecutiveErrors) =>\n throwError(\n () =>\n new Error(\n `WebSocket connection failed after ${consecutiveErrors} consecutive errors`,\n ),\n ),\n ),\n );\n}\n","import type {\n RunAgentInput,\n RunAgentParameters,\n RunAgentResult,\n AgentSubscriber,\n BaseEvent,\n} from \"@ag-ui/client\";\nimport {\n AbstractAgent,\n EventType,\n randomUUID,\n transformChunks,\n structuredClone_,\n} from \"@ag-ui/client\";\n\nimport {\n EMPTY,\n Subject,\n Notification,\n combineLatest,\n defer,\n dematerialize,\n lastValueFrom,\n merge,\n switchMap,\n throwError,\n} from \"rxjs\";\nimport type { ObservableNotification, Observable } from \"rxjs\";\nimport {\n catchError,\n delay,\n endWith,\n filter,\n finalize,\n ignoreElements,\n mergeMap,\n share,\n shareReplay,\n switchMap as switchMapOperator,\n take,\n takeUntil,\n tap,\n} from \"rxjs/operators\";\nimport { phoenixExponentialBackoff } from \"@copilotkit/shared\";\nimport {\n ɵphoenixChannel$,\n ɵphoenixSocket$,\n ɵjoinPhoenixChannel$,\n ɵobservePhoenixSocketSignals$,\n ɵobservePhoenixSocketHealth$,\n ɵobservePhoenixEvent$,\n} from \"./utils/phoenix-observable\";\nimport type {\n ɵPhoenixChannelLike,\n ɵPhoenixChannelSession,\n ɵPhoenixPushLike,\n ɵPhoenixSocketLike,\n ɵPhoenixSocketSession,\n} from \"./utils/phoenix-observable\";\n\n/**\n * Structural Phoenix socket/channel contracts used by this agent, derived from\n * the minimal `*Like` interfaces in {@link ./utils/phoenix-observable}.\n */\ntype Socket = ɵPhoenixSocketLike;\n\ninterface Channel extends ɵPhoenixChannelLike {\n push(event: string, payload: unknown): ɵPhoenixPushLike;\n}\n\nconst CLIENT_AG_UI_EVENT = \"ag_ui_event\";\nconst REPLAY_COMPLETE_EVENT = \"replay_complete\";\nconst STREAM_IDLE_EVENT = \"stream_idle\";\nconst STOP_RUN_EVENT = \"stop_run\";\nconst CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS = 100;\n\ninterface IntelligenceAgentSharedState {\n lastSeenEventIds: Map<string, string>;\n}\n\ninterface RealtimeConnectionInfo {\n clientUrl: string;\n topic: string;\n}\n\ninterface ThreadJoinCredentials {\n threadId: string;\n runId: string | null;\n joinToken: string;\n realtime: RealtimeConnectionInfo;\n}\n\nexport class AgentThreadLockedError extends Error {\n constructor(threadId?: string) {\n super(threadId ? `Thread ${threadId} is locked` : \"Thread is locked\");\n this.name = \"AgentThreadLockedError\";\n }\n}\n\n/**\n * Typed contract for agents that expose the completion promise of their\n * currently in-flight run.\n *\n * `IntelligenceAgent` resolves this promise once a run's observable pipeline\n * finalizes (see {@link IntelligenceAgent.connectAgent}). Consumers (e.g. the\n * v2 `CopilotChat` send-serialization path) await it to let an in-flight run —\n * notably an interrupt RESUME — finish before dispatching a new run, instead\n * of pre-empting it.\n *\n * The base `AbstractAgent` from `@ag-ui/client` only declares this property\n * privately, so it is reachable only through this contract plus the\n * {@link isRunCompletionAware} type guard. This keeps callers off `as unknown`\n * casts while still degrading safely for agents that don't implement it.\n */\nexport interface RunCompletionAware {\n /**\n * Resolves when the active run's pipeline finalizes (completes, errors, or is\n * detached). `undefined` when no run is in flight.\n */\n readonly activeRunCompletionPromise?: Promise<void>;\n}\n\n/**\n * Type guard for {@link RunCompletionAware}. Returns true when `agent` exposes\n * an `activeRunCompletionPromise` property, so callers can await an in-flight\n * run without an `as unknown as` cast. Returns false for agents that don't\n * implement the contract, letting the caller skip the await and degrade safely.\n */\nexport function isRunCompletionAware(\n agent: unknown,\n): agent is RunCompletionAware {\n return (\n typeof agent === \"object\" &&\n agent !== null &&\n \"activeRunCompletionPromise\" in agent\n );\n}\n\nexport interface IntelligenceAgentConfig {\n /** Phoenix websocket URL, e.g. \"ws://localhost:4000/socket\" */\n url: string;\n /** Runtime REST URL, e.g. \"http://localhost:4000\" */\n runtimeUrl: string;\n /** Agent identifier for REST endpoints */\n agentId: string;\n /** Optional params sent on socket connect (e.g. auth token) */\n socketParams?: Record<string, string>;\n /** Optional headers sent with REST requests */\n headers?: Record<string, string>;\n /** Optional credentials mode for fetch requests */\n credentials?: RequestCredentials;\n}\n\nexport class IntelligenceAgent extends AbstractAgent {\n private config: IntelligenceAgentConfig;\n private socket: Socket | null = null;\n private activeChannel: Channel | null = null;\n private canonicalRunId: string | null = null;\n private sharedState: IntelligenceAgentSharedState;\n\n constructor(\n config: IntelligenceAgentConfig,\n sharedState: IntelligenceAgentSharedState = {\n lastSeenEventIds: new Map<string, string>(),\n },\n ) {\n super();\n this.config = config;\n this.sharedState = sharedState;\n }\n\n clone(): IntelligenceAgent {\n return new IntelligenceAgent(this.config, this.sharedState);\n }\n\n /**\n * Override of AbstractAgent.connectAgent that removes the `verifyEvents` step.\n *\n * Background: AbstractAgent's connectAgent pipeline runs events through\n * `verifyEvents`, which validates that the stream follows the AG-UI protocol\n * lifecycle — specifically, it expects a RUN_STARTED event before any content\n * events and a RUN_FINISHED/RUN_ERROR event to complete the stream.\n *\n * IntelligenceAgent uses long-lived WebSocket connections rather than\n * request-scoped SSE streams. When connecting to replay historical messages\n * for an existing thread, the connection semantics don't map to a single\n * agent run start/stop cycle. The replayed events may not include\n * RUN_STARTED/RUN_FINISHED bookends (or may contain events from multiple\n * past runs), which causes verifyEvents to either never complete or to\n * error out.\n *\n * This override replicates the base connectAgent implementation exactly,\n * substituting only `transformChunks` (which is still needed for message\n * reassembly) and omitting `verifyEvents`.\n *\n * TODO: Remove this override once AG-UI's AbstractAgent supports opting out\n * of verifyEvents for transports with different connection life-cycles.\n */\n override async connectAgent(\n parameters?: RunAgentParameters,\n subscriber?: AgentSubscriber,\n ): Promise<RunAgentResult> {\n // Access private fields through a type escape hatch — these are set/read\n // by the base class and must be managed identically to the original.\n // Using `any` because these fields are private in AbstractAgent, and\n // intersecting private+public members of the same name produces `never`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const self = this as any;\n\n try {\n this.isRunning = true;\n this.agentId = this.agentId ?? randomUUID();\n\n const effectiveParameters =\n parameters?.runId || !this.canonicalRunId\n ? parameters\n : {\n ...parameters,\n runId: this.canonicalRunId,\n };\n const input = this.prepareRunAgentInput(effectiveParameters);\n let result: RunAgentResult[\"result\"];\n const previousMessageIds = new Set(this.messages.map((m) => m.id));\n const subscribers: AgentSubscriber[] = [\n {\n onRunFinishedEvent: (event) => {\n if (event.outcome === \"success\") {\n result = event.result;\n }\n },\n },\n ...this.subscribers,\n subscriber ?? {},\n ];\n\n await this.onInitialize(input, subscribers);\n\n self.activeRunDetach$ = new Subject<void>();\n let resolveCompletion: (() => void) | undefined;\n self.activeRunCompletionPromise = new Promise<void>((resolve) => {\n resolveCompletion = resolve;\n });\n\n const source$ = defer(() => this.connect(input)).pipe(\n // transformChunks reassembles partial/streamed messages — still needed.\n transformChunks(this.debugLogger),\n // NOTE: verifyEvents is intentionally omitted here. See JSDoc above.\n takeUntil(self.activeRunDetach$),\n );\n\n const applied$ = this.apply(input, source$, subscribers);\n const processed$ = this.processApplyEvents(input, applied$, subscribers);\n\n await lastValueFrom(\n processed$.pipe(\n catchError((error) => {\n this.isRunning = false;\n return this.onError(input, error, subscribers);\n }),\n finalize(() => {\n this.isRunning = false;\n this.onFinalize(input, subscribers);\n resolveCompletion?.();\n resolveCompletion = undefined;\n self.activeRunCompletionPromise = undefined;\n self.activeRunDetach$ = undefined;\n }),\n ),\n { defaultValue: undefined },\n );\n\n const newMessages = structuredClone_(this.messages).filter(\n (m) => !previousMessageIds.has(m.id),\n );\n return { result, newMessages };\n } finally {\n this.isRunning = false;\n }\n }\n\n abortRun(): void {\n if (this.activeChannel && this.canonicalRunId) {\n // Defer cleanup until the push is acknowledged so socket.disconnect()\n // doesn't clear the push buffer before the stop signal is sent.\n // The 5-second fallback handles the case where the socket is down and\n // Phoenix never flushes the buffered push (its .receive(\"timeout\") only\n // fires for pushes that were actually sent but not replied to).\n // detachActiveRun() gracefully tears down the connectAgent() pipeline;\n // cleanup() follows as a safety net for the run() path.\n const fallback = setTimeout(() => clear(), 5_000);\n const clear = () => {\n clearTimeout(fallback);\n void this.detachActiveRun();\n this.cleanup();\n };\n\n this.activeChannel\n .push(STOP_RUN_EVENT, { run_id: this.canonicalRunId })\n .receive(\"ok\", clear)\n .receive(\"error\", clear)\n .receive(\"timeout\", clear);\n } else {\n void this.detachActiveRun();\n this.cleanup();\n }\n }\n\n /**\n * Trigger the run via REST, then join the realtime thread channel and relay\n * server-pushed AG-UI events to the Observable subscriber.\n */\n run(input: RunAgentInput): Observable<BaseEvent> {\n this.threadId = input.threadId;\n this.canonicalRunId = input.runId;\n\n return defer(() => this.requestJoinCredentials$(\"run\", input)).pipe(\n switchMap((credentials) => {\n if (credentials === null) {\n return throwError(\n () => new Error(\"REST run request returned no credentials\"),\n );\n }\n\n const canonicalInput = this.applyCanonicalRunIdentity(\n input,\n credentials,\n { fallbackToInputRunId: true },\n );\n\n return this.observeThread$(canonicalInput, credentials, {\n completeOnRunError: false,\n streamMode: \"run\",\n });\n }),\n );\n }\n\n /**\n * Reconnect to an existing thread by fetching websocket credentials and\n * joining the realtime thread channel.\n */\n /**\n * Reconnect to an existing thread by fetching websocket credentials\n * and joining the realtime thread channel.\n *\n * Note: this method does NOT clear the replay cursor. Whether to\n * request a full historical replay vs. resume from\n * `lastSeenEventId` is a decision the caller (typically\n * `RunHandler.connectAgent`) makes by calling\n * {@link clearReconnectCursor} ahead of time on a fresh thread\n * restore. Same-thread churn re-connects preserve the cursor so the\n * gateway only streams events past it instead of replaying the\n * entire history every time the chat re-opens a socket.\n */\n protected connect(input: RunAgentInput): Observable<BaseEvent> {\n this.threadId = input.threadId;\n this.canonicalRunId = null;\n const replayCursor = this.getReconnectCursor(input);\n\n return defer(() =>\n this.requestJoinCredentials$(\"connect\", input, replayCursor),\n ).pipe(\n switchMap((credentials) => {\n if (credentials === null) {\n return EMPTY;\n }\n\n const canonicalInput = this.applyCanonicalRunIdentity(\n input,\n credentials,\n { fallbackToInputRunId: false },\n );\n\n return this.observeThread$(canonicalInput, credentials, {\n completeOnRunError: false,\n streamMode: \"connect\",\n replayCursor,\n });\n }),\n );\n }\n\n /**\n * Tear down a specific channel + socket pair that belongs to one pipeline.\n * Only nulls instance references when they still point to the owned resource,\n * so a concurrent pipeline's resources are never clobbered.\n */\n private cleanupOwned(\n ownChannel: Channel | null,\n ownSocket: Socket | null,\n ): void {\n if (ownChannel) {\n ownChannel.leave();\n if (this.activeChannel === ownChannel) {\n this.activeChannel = null;\n }\n }\n if (ownSocket) {\n ownSocket.disconnect();\n if (this.socket === ownSocket) {\n this.socket = null;\n }\n }\n this.canonicalRunId = null;\n }\n\n private cleanup(): void {\n this.cleanupOwned(this.activeChannel, this.socket);\n }\n\n private requestJoinCredentials$(\n mode: \"run\" | \"connect\",\n input: RunAgentInput,\n replayCursor?: string | null,\n ): Observable<ThreadJoinCredentials | null> {\n return defer(async () => {\n try {\n const response = await fetch(this.buildRuntimeUrl(mode), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.config.headers,\n },\n body: JSON.stringify({\n threadId: input.threadId,\n runId: input.runId,\n messages: input.messages,\n tools: input.tools,\n context: input.context,\n state: input.state,\n forwardedProps: input.forwardedProps,\n ...(mode === \"connect\"\n ? {\n lastSeenEventId:\n replayCursor === undefined\n ? this.getReconnectCursor(input)\n : replayCursor,\n }\n : {}),\n }),\n ...(this.config.credentials\n ? { credentials: this.config.credentials }\n : {}),\n });\n\n if (response.status === 204 && mode === \"connect\") {\n return null;\n }\n\n if (response.status === 409 && mode === \"run\") {\n throw new AgentThreadLockedError(input.threadId);\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new Error(\n text || response.statusText || String(response.status),\n );\n }\n\n return this.normalizeJoinCredentials(await response.json(), input);\n } catch (error) {\n if (error instanceof AgentThreadLockedError) {\n throw error;\n }\n throw new Error(\n `REST ${mode} request failed: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n });\n }\n\n private normalizeJoinCredentials(\n payload: unknown,\n input: RunAgentInput,\n ): ThreadJoinCredentials {\n const envelope =\n payload && typeof payload === \"object\"\n ? (payload as Record<string, unknown>)\n : null;\n const realtime =\n envelope?.realtime && typeof envelope.realtime === \"object\"\n ? (envelope.realtime as Record<string, unknown>)\n : null;\n\n if (typeof envelope?.joinToken !== \"string\" || !envelope.joinToken) {\n throw new Error(\"missing joinToken\");\n }\n\n if (typeof realtime?.clientUrl !== \"string\" || !realtime.clientUrl) {\n throw new Error(\"missing realtime.clientUrl\");\n }\n\n if (typeof realtime.topic !== \"string\" || !realtime.topic) {\n throw new Error(\"missing realtime.topic\");\n }\n\n return {\n threadId:\n typeof envelope.threadId === \"string\" && envelope.threadId\n ? envelope.threadId\n : input.threadId,\n runId:\n typeof envelope.runId === \"string\" && envelope.runId\n ? envelope.runId\n : null,\n joinToken: envelope.joinToken,\n realtime: {\n clientUrl: realtime.clientUrl,\n topic: realtime.topic,\n },\n };\n }\n\n private observeThread$(\n input: RunAgentInput,\n credentials: ThreadJoinCredentials,\n options: {\n completeOnRunError: boolean;\n streamMode: \"run\" | \"connect\";\n channelMode?: \"run\" | \"connect\";\n replayCursor?: string | null;\n },\n ): Observable<BaseEvent> {\n return this.observeThreadSession$(input, credentials, options).pipe(\n catchError((error) => {\n if (!this.isSocketReconnectExhaustedError(error)) {\n return throwError(() => error);\n }\n\n const replayCursor = this.getReconnectCursor(input);\n return this.requestJoinCredentials$(\n \"connect\",\n input,\n replayCursor,\n ).pipe(\n switchMap((refreshedCredentials) =>\n refreshedCredentials === null\n ? EMPTY\n : this.observeThread$(\n this.applyCanonicalRunIdentity(input, refreshedCredentials, {\n fallbackToInputRunId: options.streamMode === \"run\",\n }),\n refreshedCredentials,\n {\n ...options,\n channelMode: \"connect\",\n replayCursor,\n },\n ),\n ),\n );\n }),\n );\n }\n\n private observeThreadSession$(\n input: RunAgentInput,\n credentials: ThreadJoinCredentials,\n options: {\n completeOnRunError: boolean;\n streamMode: \"run\" | \"connect\";\n channelMode?: \"run\" | \"connect\";\n replayCursor?: string | null;\n },\n ): Observable<BaseEvent> {\n return defer(() => {\n // Capture references to the socket and channel created by THIS pipeline\n // so the finalize closure only tears down its own resources. Without\n // this, a fire-and-forget detachActiveRun() from run-handler can race:\n // the old pipeline's deferred cleanup reads from `this.socket` /\n // `this.activeChannel`, which by then may already point to the NEW\n // pipeline's resources — destroying the live connection and preventing\n // the stop signal from ever reaching the backend.\n let ownSocket: Socket | null = null;\n let ownChannel: Channel | null = null;\n\n const socket$ = ɵphoenixSocket$({\n url: credentials.realtime.clientUrl,\n options: {\n params: {\n ...this.config.socketParams,\n join_token: credentials.joinToken,\n },\n reconnectAfterMs: phoenixExponentialBackoff(100, 10_000),\n rejoinAfterMs: phoenixExponentialBackoff(1_000, 30_000),\n },\n }).pipe(\n tap(({ socket }) => {\n ownSocket = socket as Socket;\n this.socket = ownSocket;\n }),\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n const params = this.createThreadChannelParams(\n input,\n options.channelMode ?? options.streamMode,\n options.replayCursor,\n );\n const channel$ = ɵphoenixChannel$({\n socket$,\n topic: credentials.realtime.topic,\n params,\n }).pipe(\n tap(({ channel }) => {\n ownChannel = channel as Channel;\n this.activeChannel = ownChannel;\n }),\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n const reconnectCursor = this.readDurableEventId(\n options.replayCursor ?? this.getReconnectCursor(input),\n );\n let latestObservedReplayCursor: string | null = null;\n const threadEvents$ = this.observeThreadEvents$(\n input.threadId,\n channel$,\n options,\n ).pipe(\n tap((payload) => {\n latestObservedReplayCursor =\n this.readEventId(payload) ?? latestObservedReplayCursor;\n }),\n share(),\n );\n const replayComplete$ = this.observeControlEvent$(\n input.threadId,\n channel$,\n REPLAY_COMPLETE_EVENT,\n ).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const streamIdle$ = this.observeControlEvent$(\n input.threadId,\n channel$,\n STREAM_IDLE_EVENT,\n ).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const streamIdleCompletion$ =\n options.streamMode === \"connect\"\n ? merge(\n combineLatest([\n replayComplete$.pipe(take(1)),\n streamIdle$.pipe(take(1)),\n ]),\n streamIdle$.pipe(\n take(1),\n filter((payload) =>\n this.canFallbackCompleteConnect(\n payload,\n reconnectCursor,\n latestObservedReplayCursor,\n ),\n ),\n delay(CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS),\n ),\n ).pipe(take(1))\n : EMPTY;\n const threadCompleted$ = threadEvents$.pipe(\n ignoreElements(),\n endWith(null),\n take(1),\n );\n const terminal$ = merge(threadCompleted$, streamIdleCompletion$);\n\n return merge(\n this.joinThreadChannel$(channel$),\n this.observeSocketHealth$(socket$).pipe(takeUntil(terminal$)),\n threadEvents$.pipe(takeUntil(streamIdleCompletion$)),\n replayComplete$.pipe(ignoreElements(), takeUntil(terminal$)),\n streamIdleCompletion$.pipe(\n ignoreElements(),\n takeUntil(threadCompleted$),\n ),\n ).pipe(finalize(() => this.cleanupOwned(ownChannel, ownSocket)));\n });\n }\n\n private joinThreadChannel$(\n channel$: Observable<ɵPhoenixChannelSession>,\n ): Observable<never> {\n return ɵjoinPhoenixChannel$(channel$);\n }\n\n private observeSocketHealth$(\n socket$: Observable<ɵPhoenixSocketSession>,\n ): Observable<never> {\n return ɵobservePhoenixSocketHealth$(\n ɵobservePhoenixSocketSignals$(socket$),\n 5,\n );\n }\n\n private observeThreadEvents$(\n threadId: string,\n channel$: Observable<ɵPhoenixChannelSession>,\n options: { completeOnRunError: boolean; streamMode: \"run\" | \"connect\" },\n ): Observable<BaseEvent> {\n return channel$.pipe(\n switchMapOperator(({ channel }) =>\n this.observeChannelEvent$<BaseEvent>(channel, CLIENT_AG_UI_EVENT),\n ),\n tap((payload) => {\n this.updateLastSeenEventId(threadId, payload);\n }),\n mergeMap(\n (payload) =>\n this.createThreadNotifications(payload, {\n completeOnRunError: options.completeOnRunError,\n completeOnRunFinished: options.streamMode === \"run\",\n errorOnRunError: options.streamMode === \"run\",\n }) as ObservableNotification<BaseEvent>[],\n ),\n dematerialize(),\n );\n }\n\n private observeControlEvent$(\n threadId: string,\n channel$: Observable<ɵPhoenixChannelSession>,\n eventName: string,\n ): Observable<unknown> {\n return channel$.pipe(\n switchMapOperator(({ channel }) =>\n this.observeChannelEvent$<unknown>(channel, eventName),\n ),\n tap((payload) =>\n this.updateLastSeenEventIdFromControl(threadId, payload),\n ),\n );\n }\n\n private observeChannelEvent$<T>(\n channel: ɵPhoenixChannelLike,\n eventName: string,\n ): Observable<T> {\n return ɵobservePhoenixEvent$<T>(channel, eventName);\n }\n\n private createThreadNotifications(\n payload: BaseEvent,\n options: {\n completeOnRunError: boolean;\n completeOnRunFinished: boolean;\n errorOnRunError: boolean;\n },\n ): Array<Notification<BaseEvent>> {\n if (payload.type === EventType.RUN_FINISHED) {\n return options.completeOnRunFinished\n ? [Notification.createNext(payload), Notification.createComplete()]\n : [Notification.createNext(payload)];\n }\n\n if (payload.type === EventType.RUN_ERROR) {\n const errorMessage =\n (payload as BaseEvent & { message?: string }).message ?? \"Run error\";\n\n return options.completeOnRunError\n ? [Notification.createNext(payload), Notification.createComplete()]\n : options.errorOnRunError\n ? [\n Notification.createNext(payload),\n Notification.createError(new Error(errorMessage)),\n ]\n : [Notification.createNext(payload)];\n }\n\n return [Notification.createNext(payload)];\n }\n\n private buildRuntimeUrl(mode: \"run\" | \"connect\"): string {\n const path = `${this.config.runtimeUrl}/agent/${encodeURIComponent(this.config.agentId)}/${mode}`;\n const origin =\n typeof window !== \"undefined\" && window.location\n ? window.location.origin\n : \"http://localhost\";\n\n return new URL(path, new URL(this.config.runtimeUrl, origin)).toString();\n }\n\n private createThreadChannelParams(\n input: RunAgentInput,\n streamMode: \"run\" | \"connect\",\n replayCursor?: string | null,\n ): Record<string, unknown> {\n return streamMode === \"run\"\n ? {\n stream_mode: \"run\",\n run_id: input.runId,\n }\n : {\n stream_mode: \"connect\",\n last_seen_event_id:\n replayCursor === undefined\n ? this.getReconnectCursor(input)\n : replayCursor,\n };\n }\n\n private getLastSeenEventId(threadId: string): string | null {\n return this.sharedState.lastSeenEventIds.get(threadId) ?? null;\n }\n\n private getReconnectCursor(input: RunAgentInput): string | null {\n return this.getLastSeenEventId(input.threadId);\n }\n\n /**\n * Drop the cached `lastSeenEventId` cursor for `threadId` so the\n * next connect to that topic asks the gateway for a full historical\n * replay (rather than resuming). Public because\n * `RunHandler.connectAgent` calls it on a detected thread switch\n * to rebuild local state from scratch, and skips it on same-thread\n * churn so the gateway can resume.\n */\n public clearReconnectCursor(threadId: string): void {\n this.sharedState.lastSeenEventIds.delete(threadId);\n }\n\n private updateLastSeenEventId(threadId: string, payload: BaseEvent): void {\n const eventId = this.readEventId(payload);\n if (!eventId) {\n return;\n }\n\n this.advanceLastSeenEventId(threadId, eventId);\n }\n\n private updateLastSeenEventIdFromControl(\n threadId: string,\n payload: unknown,\n ): void {\n const eventId = this.readControlEventId(payload);\n if (!eventId) {\n return;\n }\n\n this.advanceLastSeenEventId(threadId, eventId);\n }\n\n private advanceLastSeenEventId(threadId: string, eventId: string): void {\n this.sharedState.lastSeenEventIds.set(threadId, eventId);\n }\n\n private readEventId(payload: BaseEvent): string | null {\n const metadata = (payload as BaseEvent & { metadata?: unknown }).metadata;\n if (!metadata || typeof metadata !== \"object\") {\n return null;\n }\n\n const eventMetadata = metadata as { cpki_event_id?: unknown };\n return this.readDurableEventId(eventMetadata.cpki_event_id);\n }\n\n private readControlEventId(payload: unknown): string | null {\n if (!payload || typeof payload !== \"object\") {\n return null;\n }\n\n const controlPayload = payload as {\n latestEventId?: unknown;\n latest_event_id?: unknown;\n };\n const latestEventId =\n controlPayload.latestEventId ?? controlPayload.latest_event_id;\n return this.readDurableEventId(latestEventId);\n }\n\n private readDurableEventId(eventId: unknown): string | null {\n if (typeof eventId !== \"string\" || eventId.trim() === \"\") {\n return null;\n }\n\n return eventId.startsWith(\"cpki_ingested\") ? null : eventId;\n }\n\n private canFallbackCompleteConnect(\n streamIdlePayload: unknown,\n reconnectCursor: string | null,\n latestObservedReplayCursor: string | null,\n ): boolean {\n const idleCursor = this.readControlEventId(streamIdlePayload);\n if (!idleCursor) {\n return true;\n }\n\n return (\n idleCursor === reconnectCursor ||\n idleCursor === latestObservedReplayCursor\n );\n }\n\n private applyCanonicalRunIdentity(\n input: RunAgentInput,\n credentials: ThreadJoinCredentials,\n options: { fallbackToInputRunId: boolean },\n ): RunAgentInput {\n this.threadId = credentials.threadId;\n const runId =\n credentials.runId ?? (options.fallbackToInputRunId ? input.runId : null);\n this.canonicalRunId = runId;\n\n return {\n ...input,\n threadId: credentials.threadId,\n ...(runId === null ? {} : { runId }),\n };\n }\n\n private isSocketReconnectExhaustedError(error: unknown): boolean {\n return (\n error instanceof Error &&\n error.message.includes(\"WebSocket connection failed after\")\n );\n }\n}\n","import type {\n AbstractAgent,\n AgentCapabilities,\n AgentSubscriber,\n BaseEvent,\n HttpAgentConfig,\n RunAgentInput,\n RunAgentParameters,\n RunAgentResult,\n} from \"@ag-ui/client\";\nimport {\n HttpAgent,\n runHttpRequest,\n transformHttpEventStream,\n} from \"@ag-ui/client\";\nimport type { Observable } from \"rxjs\";\nimport { EMPTY, defer, from } from \"rxjs\";\nimport { catchError, switchMap } from \"rxjs/operators\";\nimport {\n RUNTIME_MODE_SSE,\n RUNTIME_MODE_INTELLIGENCE,\n} from \"@copilotkit/shared\";\nimport type {\n IntelligenceRuntimeInfo,\n RuntimeInfo,\n RuntimeMode,\n ResolvedDebugConfig,\n} from \"@copilotkit/shared\";\nimport { IntelligenceAgent } from \"./intelligence-agent\";\nimport type { CopilotRuntimeTransport } from \"./types\";\n\ntype ResolvedRuntimeMode = RuntimeMode | \"pending\";\n\ninterface RunnableAgent {\n connect(input: RunAgentInput): Observable<BaseEvent>;\n run(input: RunAgentInput): Observable<BaseEvent>;\n}\n\nfunction hasHeaders(\n agent: AbstractAgent,\n): agent is AbstractAgent & { headers?: Record<string, string> } {\n return \"headers\" in agent;\n}\n\nfunction hasCredentials(\n agent: AbstractAgent,\n): agent is AbstractAgent & { credentials?: RequestCredentials } {\n return \"credentials\" in agent;\n}\n\nfunction isZodError(error: unknown): boolean {\n return (\n error !== null &&\n typeof error === \"object\" &&\n \"name\" in error &&\n (error as { name: string }).name === \"ZodError\"\n );\n}\n\nfunction isAbortError(error: unknown): boolean {\n return (\n (error instanceof DOMException || error instanceof Error) &&\n (error as Error).name === \"AbortError\"\n );\n}\n\nfunction withAbortErrorHandling(\n observable: Observable<BaseEvent>,\n): Observable<BaseEvent> {\n return observable.pipe(\n catchError((error) => {\n if (isZodError(error) || isAbortError(error)) {\n return EMPTY;\n }\n throw error;\n }),\n );\n}\n\nexport interface ProxiedCopilotRuntimeAgentConfig extends Omit<\n HttpAgentConfig,\n \"url\"\n> {\n runtimeUrl?: string;\n transport?: CopilotRuntimeTransport;\n credentials?: RequestCredentials;\n runtimeMode?: ResolvedRuntimeMode;\n intelligence?: IntelligenceRuntimeInfo;\n capabilities?: AgentCapabilities;\n debug?: ResolvedDebugConfig;\n /**\n * When set, runtime requests (HTTP path, single-route envelope, intelligence\n * delegate) are routed to this agent on the runtime instead of `agentId`.\n * The local `agentId` remains the registry key used for subscriber\n * bookkeeping; only outbound routing is overridden.\n */\n runtimeAgentId?: string;\n}\n\nexport class ProxiedCopilotRuntimeAgent extends HttpAgent {\n runtimeUrl?: string;\n credentials?: RequestCredentials;\n // `readonly` because `super.url` is baked at construction; mutating\n // `runtimeAgentId` post-construction would desync the REST `run` URL\n // (already captured) from `routedAgentId()` (consulted per-call by\n // stop/connect/single-route paths).\n readonly runtimeAgentId?: string;\n private transport: CopilotRuntimeTransport;\n private singleEndpointUrl?: string;\n private runtimeMode: ResolvedRuntimeMode;\n private intelligence?: IntelligenceRuntimeInfo;\n private _capabilities?: AgentCapabilities;\n private delegate?: AbstractAgent;\n private runtimeInfoPromise?: Promise<void>;\n\n constructor(config: ProxiedCopilotRuntimeAgentConfig) {\n const normalizedRuntimeUrl = config.runtimeUrl\n ? config.runtimeUrl.replace(/\\/$/, \"\")\n : undefined;\n const transport = config.transport ?? \"auto\";\n const routedId = config.runtimeAgentId ?? config.agentId ?? \"\";\n const runUrl =\n transport === \"single\"\n ? (normalizedRuntimeUrl ?? config.runtimeUrl ?? \"\")\n : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(routedId)}/run`;\n\n if (!runUrl) {\n throw new Error(\n \"ProxiedCopilotRuntimeAgent requires a runtimeUrl when transport is set to 'single'.\",\n );\n }\n\n super({\n ...config,\n url: runUrl,\n });\n this.runtimeUrl = normalizedRuntimeUrl ?? config.runtimeUrl;\n this.credentials = config.credentials;\n this.runtimeAgentId = config.runtimeAgentId;\n this.transport = transport;\n this.runtimeMode = config.runtimeMode ?? RUNTIME_MODE_SSE;\n this.intelligence = config.intelligence;\n this._capabilities = config.capabilities;\n if (config.debug) {\n this.debug = config.debug;\n }\n if (this.transport === \"single\") {\n this.singleEndpointUrl = this.runtimeUrl;\n }\n }\n\n /**\n * The agent id used for outbound runtime requests — `runtimeAgentId` when\n * set (manually-registered proxy), otherwise `agentId` (registry id\n * matches runtime id). Subscriber bookkeeping keeps using `agentId`\n * directly.\n *\n * Throws when both are unset: a proxy reaching an HTTP path with no\n * routable id is a bug, and a missing id would otherwise produce a\n * malformed `/agent//run` or `/agent/undefined/connect` URL silently.\n */\n private routedAgentId(): string {\n const id = this.runtimeAgentId ?? this.agentId;\n if (!id) {\n throw new Error(\n \"ProxiedCopilotRuntimeAgent: cannot make a runtime request without an agentId or runtimeAgentId.\",\n );\n }\n return id;\n }\n\n get capabilities(): AgentCapabilities | undefined {\n return this._capabilities;\n }\n\n override requestInit(input: RunAgentInput): RequestInit {\n const baseInit = super.requestInit(input);\n return {\n ...baseInit,\n ...(this.credentials ? { credentials: this.credentials } : {}),\n };\n }\n\n async getCapabilities(): Promise<AgentCapabilities> {\n return this._capabilities ?? {};\n }\n\n override async detachActiveRun(): Promise<void> {\n if (this.delegate) {\n await this.delegate.detachActiveRun();\n }\n await super.detachActiveRun();\n }\n\n abortRun(): void {\n if (this.delegate) {\n this.syncDelegate(this.delegate);\n this.delegate.abortRun();\n // Also detach the proxy's own runAgent pipeline so the proxy's\n // isRunning resets and onRunFinalized fires even if the delegate's\n // observable doesn't propagate a clean completion.\n void this.detachActiveRun();\n return;\n }\n\n if (!this.agentId || !this.threadId) {\n return;\n }\n\n if (typeof fetch === \"undefined\") {\n return;\n }\n\n const routedId = this.routedAgentId();\n\n if (this.transport === \"single\") {\n if (!this.singleEndpointUrl) {\n return;\n }\n\n const headers = new Headers({\n ...this.headers,\n \"Content-Type\": \"application/json\",\n });\n void fetch(this.singleEndpointUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n method: \"agent/stop\",\n params: {\n agentId: routedId,\n threadId: this.threadId,\n },\n }),\n ...(this.credentials ? { credentials: this.credentials } : {}),\n }).catch((error) => {\n console.error(\"ProxiedCopilotRuntimeAgent: stop request failed\", error);\n });\n return;\n }\n\n if (!this.runtimeUrl) {\n return;\n }\n\n const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(routedId)}/stop/${encodeURIComponent(this.threadId)}`;\n const origin =\n typeof window !== \"undefined\" && window.location\n ? window.location.origin\n : \"http://localhost\";\n const base = new URL(this.runtimeUrl, origin);\n const stopUrl = new URL(stopPath, base);\n\n void fetch(stopUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.headers,\n },\n ...(this.credentials ? { credentials: this.credentials } : {}),\n }).catch((error) => {\n console.error(\"ProxiedCopilotRuntimeAgent: stop request failed\", error);\n });\n }\n\n override async connectAgent(\n parameters?: RunAgentParameters,\n subscriber?: AgentSubscriber,\n ): Promise<RunAgentResult> {\n if (this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) {\n return super.connectAgent(parameters, subscriber);\n }\n\n // If the delegate already has an active run (e.g. from a previous\n // connectAgent call that hasn't finished yet), detach it first. This\n // ensures only one run is active on the delegate at a time — without it,\n // two parallel runs would both pump events into the shared delegate,\n // and both bridge subscriptions would copy the interleaved messages to\n // the proxy, causing the UI to flicker between the two conversations.\n if (this.delegate) {\n await this.delegate.detachActiveRun();\n }\n\n // Ensure the delegate exists and is synced with the proxy's current state.\n await this.resolveDelegate();\n const delegate = this.delegate!;\n\n // Subscribe a bridging observer FIRST so it fires before the forwarded\n // UI subscribers. This keeps proxy.messages in sync with the delegate\n // in real-time — otherwise the UI re-renders (triggered by the\n // forwarded onMessagesChanged) but reads stale proxy.messages because\n // the final sync only happens after connectAgent resolves.\n const bridgeSub = delegate.subscribe({\n onMessagesChanged: () => {\n this.setMessages([...delegate.messages]);\n },\n onStateChanged: () => {\n this.setState({ ...delegate.state });\n },\n // Mirror isRunning so the proxy reflects the delegate's run lifecycle.\n // Without this, UI components read proxy.isRunning (always false) even\n // though the delegate is actively running, causing the stop button to\n // never appear.\n onRunInitialized: () => {\n this.isRunning = true;\n },\n onRunFinalized: () => {\n this.isRunning = false;\n },\n // Local exception (network error, deserialization failure, etc.)\n onRunFailed: () => {\n this.isRunning = false;\n },\n // Protocol-level RUN_ERROR event from the backend\n onRunErrorEvent: () => {\n this.isRunning = false;\n },\n });\n\n // Forward the proxy's subscribers to the delegate so that UI hooks\n // (e.g. useAgent's onMessagesChanged) receive real-time updates as\n // the delegate processes events during connectAgent.\n const forwardedSubs = this.subscribers.map((s) => delegate.subscribe(s));\n\n try {\n const result = await delegate.connectAgent(parameters, subscriber);\n\n // Final sync to guarantee the proxy reflects the delegate's end state.\n this.setMessages([...delegate.messages]);\n this.setState({ ...delegate.state });\n\n return result;\n } finally {\n // Ensure the proxy's isRunning is reset — the bridging subscription\n // may have already handled this, but if the delegate threw before\n // firing onRunFinalized the proxy would be stuck in isRunning=true.\n this.isRunning = false;\n // Remove forwarded subscribers to avoid duplicate notifications on\n // subsequent calls (they'll be re-forwarded next time).\n bridgeSub.unsubscribe();\n for (const sub of forwardedSubs) {\n sub.unsubscribe();\n }\n }\n }\n\n connect(input: RunAgentInput): Observable<BaseEvent> {\n if (\n this.runtimeMode === \"pending\" ||\n (this.transport === \"auto\" &&\n this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE)\n ) {\n return defer(() => from(this.ensureRuntimeConfiguration())).pipe(\n switchMap(() => this.connect(input)),\n );\n }\n if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE) {\n return this.#connectViaDelegate(input);\n }\n return this.#connectViaHttp(input);\n }\n\n public run(input: RunAgentInput): Observable<BaseEvent> {\n if (\n this.runtimeMode === \"pending\" ||\n (this.transport === \"auto\" &&\n this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE)\n ) {\n return defer(() => from(this.ensureRuntimeConfiguration())).pipe(\n switchMap(() => this.run(input)),\n );\n }\n if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE) {\n return this.#runViaDelegate(input);\n }\n return this.#runViaHttp(input);\n }\n\n #connectViaDelegate(input: RunAgentInput): Observable<BaseEvent> {\n return defer(() => from(this.resolveDelegate())).pipe(\n switchMap((delegate) => withAbortErrorHandling(delegate.connect(input))),\n );\n }\n\n #connectViaHttp(input: RunAgentInput): Observable<BaseEvent> {\n const routedId = this.routedAgentId();\n if (this.transport === \"single\") {\n if (!this.singleEndpointUrl) {\n throw new Error(\"Single endpoint transport requires a runtimeUrl\");\n }\n\n const requestInit = this.createSingleRouteRequestInit(\n input,\n \"agent/connect\",\n {\n agentId: routedId,\n },\n );\n const httpEvents = runHttpRequest(() =>\n this.fetch(this.singleEndpointUrl!, requestInit),\n );\n return withAbortErrorHandling(transformHttpEventStream(httpEvents));\n }\n\n const connectUrl = `${this.runtimeUrl}/agent/${routedId}/connect`;\n const connectRequestInit = this.requestInit(input);\n const httpEvents = runHttpRequest(() =>\n this.fetch(connectUrl, connectRequestInit),\n );\n return withAbortErrorHandling(transformHttpEventStream(httpEvents));\n }\n\n #runViaDelegate(input: RunAgentInput): Observable<BaseEvent> {\n return defer(() => from(this.resolveDelegate())).pipe(\n switchMap((delegate) => withAbortErrorHandling(delegate.run(input))),\n );\n }\n\n #runViaHttp(input: RunAgentInput): Observable<BaseEvent> {\n if (this.transport === \"single\") {\n if (!this.singleEndpointUrl) {\n throw new Error(\"Single endpoint transport requires a runtimeUrl\");\n }\n\n const requestInit = this.createSingleRouteRequestInit(\n input,\n \"agent/run\",\n {\n agentId: this.routedAgentId(),\n },\n );\n const httpEvents = runHttpRequest(() =>\n this.fetch(this.singleEndpointUrl!, requestInit),\n );\n return withAbortErrorHandling(transformHttpEventStream(httpEvents));\n }\n\n return withAbortErrorHandling(super.run(input));\n }\n\n public override clone(): ProxiedCopilotRuntimeAgent {\n const cloned = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: this.runtimeUrl,\n agentId: this.agentId,\n runtimeAgentId: this.runtimeAgentId,\n description: this.description,\n headers: { ...this.headers },\n credentials: this.credentials,\n transport: this.transport,\n runtimeMode: this.runtimeMode,\n intelligence: this.intelligence,\n capabilities: this._capabilities,\n debug: this.debug,\n });\n cloned.threadId = this.threadId;\n cloned.setState(this.state);\n cloned.setMessages(this.messages);\n if (this.delegate) {\n const clonedDelegate: AbstractAgent = this.delegate.clone();\n cloned.delegate = clonedDelegate;\n cloned.syncDelegate(clonedDelegate);\n }\n return cloned;\n }\n\n /**\n * Drop the delegate's cached `lastSeenEventId` for this thread so\n * the next connect requests a full historical replay from the\n * gateway. Used by `RunHandler.connectAgent` on a detected thread\n * switch (the chat moved between threads, so its local\n * messages/state are about to be cleared and need rebuilding from\n * the gateway). Skipped on same-thread churn re-connects so the\n * gateway can resume from the cursor instead.\n *\n * No-op for non-Intelligence runtime modes — the HTTP transport\n * doesn't replay.\n */\n public clearReplayCursor(threadId: string): void {\n if (this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) return;\n const delegate = this.delegate as\n | { clearReconnectCursor?: (id: string) => void }\n | null\n | undefined;\n delegate?.clearReconnectCursor?.(threadId);\n }\n\n private async resolveDelegate(): Promise<RunnableAgent> {\n await this.ensureRuntimeConfiguration();\n\n if (!this.delegate) {\n if (this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) {\n throw new Error(\"A delegate is only created for Intelligence mode\");\n }\n this.delegate = this.createIntelligenceDelegate();\n }\n\n this.syncDelegate(this.delegate);\n\n // AbstractAgent declares connect() as protected, but concrete delegates\n // (IntelligenceAgent, HttpAgent) expose both connect() and run() publicly.\n return this.delegate as unknown as RunnableAgent;\n }\n\n /** Resolve transport and runtime mode before the first outbound request. */\n private async ensureRuntimeConfiguration(): Promise<void> {\n if (\n this.runtimeMode === RUNTIME_MODE_INTELLIGENCE ||\n (this.runtimeMode !== \"pending\" && this.transport !== \"auto\")\n ) {\n return;\n }\n\n if (!this.runtimeUrl) {\n throw new Error(\"Runtime URL is not set\");\n }\n\n const runtimeInfoPromise =\n this.runtimeInfoPromise ??\n this.fetchRuntimeInfo().then((runtimeInfo) => {\n this.runtimeMode = runtimeInfo.mode ?? RUNTIME_MODE_SSE;\n this.intelligence = runtimeInfo.intelligence;\n });\n this.runtimeInfoPromise = runtimeInfoPromise;\n\n try {\n await runtimeInfoPromise;\n } catch (error) {\n if (this.runtimeInfoPromise === runtimeInfoPromise) {\n this.runtimeInfoPromise = undefined;\n }\n throw error;\n }\n }\n\n private async fetchRuntimeInfo(): Promise<RuntimeInfo> {\n const headers: Record<string, string> = {\n ...this.headers,\n };\n\n if (this.transport === \"auto\") {\n return this.fetchRuntimeInfoAutoDetect(headers);\n }\n\n let init: RequestInit;\n let url: string;\n\n if (this.transport === \"single\") {\n if (!this.singleEndpointUrl) {\n throw new Error(\"Single endpoint transport requires a runtimeUrl\");\n }\n if (!headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n url = this.runtimeUrl!;\n init = { method: \"POST\", body: JSON.stringify({ method: \"info\" }) };\n } else {\n url = `${this.runtimeUrl}/info`;\n init = {};\n }\n\n const response = await fetch(url, {\n ...init,\n headers,\n ...(this.credentials ? { credentials: this.credentials } : {}),\n });\n if (!response.ok) {\n throw new Error(\n `Runtime info request failed with status ${response.status}`,\n );\n }\n return (await response.json()) as RuntimeInfo;\n }\n\n private async fetchRuntimeInfoAutoDetect(\n headers: Record<string, string>,\n ): Promise<RuntimeInfo> {\n // Try REST first (GET /info)\n try {\n const response = await fetch(`${this.runtimeUrl}/info`, {\n headers: { ...headers },\n ...(this.credentials ? { credentials: this.credentials } : {}),\n });\n // Only treat a successful (2xx) response as a valid REST runtime.\n // 404/405 means the endpoint doesn't exist; other non-2xx errors\n // (500, 403, etc.) should also fall through to single-endpoint.\n if (response.status >= 200 && response.status < 300) {\n this.transport = \"rest\";\n return (await response.json()) as RuntimeInfo;\n }\n } catch {\n // REST failed — fall through to single-endpoint attempt\n }\n\n // Try single-endpoint (POST with { method: \"info\" })\n const singleHeaders = { ...headers };\n if (!singleHeaders[\"Content-Type\"]) {\n singleHeaders[\"Content-Type\"] = \"application/json\";\n }\n const response = await fetch(this.runtimeUrl!, {\n method: \"POST\",\n headers: singleHeaders,\n body: JSON.stringify({ method: \"info\" }),\n ...(this.credentials ? { credentials: this.credentials } : {}),\n });\n if (!response.ok) {\n throw new Error(\n `Runtime info request failed with status ${response.status}`,\n );\n }\n this.transport = \"single\";\n this.singleEndpointUrl = this.runtimeUrl;\n return (await response.json()) as RuntimeInfo;\n }\n\n private createSingleRouteRequestInit(\n input: RunAgentInput,\n method: string,\n params?: Record<string, string>,\n ): RequestInit {\n if (!this.agentId) {\n throw new Error(\n \"ProxiedCopilotRuntimeAgent requires agentId to make runtime requests\",\n );\n }\n\n const baseInit = super.requestInit(input);\n const headers = new Headers(baseInit.headers ?? {});\n headers.set(\"Content-Type\", \"application/json\");\n headers.set(\"Accept\", headers.get(\"Accept\") ?? \"text/event-stream\");\n\n let originalBody: unknown = undefined;\n if (typeof baseInit.body === \"string\") {\n try {\n originalBody = JSON.parse(baseInit.body);\n } catch (error) {\n console.warn(\n \"ProxiedCopilotRuntimeAgent: failed to parse request body for single route transport\",\n error,\n );\n }\n }\n\n const envelope: Record<string, unknown> = { method };\n\n if (params && Object.keys(params).length > 0) {\n envelope.params = params;\n }\n\n if (originalBody !== undefined) {\n envelope.body = originalBody;\n }\n\n return {\n ...baseInit,\n headers,\n body: JSON.stringify(envelope),\n ...(this.credentials ? { credentials: this.credentials } : {}),\n };\n }\n\n private createIntelligenceDelegate(): AbstractAgent {\n const routedId = this.routedAgentId();\n if (!this.runtimeUrl || !routedId || !this.intelligence?.wsUrl) {\n throw new Error(\n \"Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata\",\n );\n }\n\n return new IntelligenceAgent({\n url: this.intelligence.wsUrl,\n runtimeUrl: this.runtimeUrl,\n agentId: routedId,\n headers: { ...this.headers },\n credentials: this.credentials,\n });\n }\n\n private syncDelegate(delegate: AbstractAgent): void {\n // Delegate is the IntelligenceAgent that talks to the runtime — it must\n // use the routed id so that requests reach the right runtime agent.\n delegate.agentId = this.routedAgentId();\n delegate.description = this.description;\n delegate.threadId = this.threadId;\n delegate.setMessages(this.messages);\n delegate.setState(this.state);\n\n if (hasHeaders(delegate)) {\n delegate.headers = { ...this.headers };\n }\n\n if (hasCredentials(delegate)) {\n delegate.credentials = this.credentials;\n }\n }\n}\n","import type { AbstractAgent } from \"@ag-ui/client\";\nimport { HttpAgent } from \"@ag-ui/client\";\nimport type {\n RuntimeInfo,\n AgentDescription,\n RuntimeMode,\n RuntimeLicenseStatus,\n IntelligenceRuntimeInfo,\n ThreadEndpointRuntimeInfo,\n} from \"@copilotkit/shared\";\nimport {\n logger,\n RUNTIME_MODE_SSE,\n resolveDebugConfig,\n} from \"@copilotkit/shared\";\nimport { ProxiedCopilotRuntimeAgent } from \"../agent\";\nimport type { CopilotKitCore, CopilotKitCoreFriendsAccess } from \"./core\";\nimport {\n CopilotKitCoreErrorCode,\n CopilotKitCoreRuntimeConnectionStatus,\n} from \"./core\";\nimport type { CopilotRuntimeTransport } from \"../types\";\n\nexport interface CopilotKitCoreAddAgentParams {\n id: string;\n agent: AbstractAgent;\n}\n\n/**\n * Parameters for registering a proxied agent against an existing runtime agent.\n */\nexport interface CopilotKitCoreRegisterProxiedAgentParams {\n /**\n * The local registry id under which the proxy is registered. Used by\n * `useAgent`, state-manager subscriptions, and all subscriber bookkeeping.\n * Must not collide with any existing local or runtime-discovered agent id.\n */\n agentId: string;\n /**\n * The id of the runtime agent that this proxy routes outbound HTTP requests\n * to. Invisible to subscribers — only affects URL paths and single-route\n * envelopes.\n */\n runtimeAgentId: string;\n}\n\nexport interface CopilotKitCoreRegisterProxiedAgentResult {\n agent: ProxiedCopilotRuntimeAgent;\n unregister: () => void;\n}\n\n/**\n * Manages agent registration, lifecycle, and runtime connectivity for CopilotKitCore.\n * Handles both local development agents and remote runtime agents.\n */\nexport class AgentRegistry {\n private _agents: Record<string, AbstractAgent> = {};\n private localAgents: Record<string, AbstractAgent> = {};\n private remoteAgents: Record<string, AbstractAgent> = {};\n\n private _runtimeUrl?: string;\n // Tracks an in-flight `/info` connection so concurrent calls targeting the\n // same runtime (url + requested transport) collapse to a single request\n // instead of each firing their own. See #5801.\n private _connectionInFlight?: { key: string; promise: Promise<void> };\n private _runtimeVersion?: string;\n private _runtimeConnectionStatus: CopilotKitCoreRuntimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Disconnected;\n private _runtimeTransport: CopilotRuntimeTransport = \"auto\";\n // The transport MODE last requested via `setRuntimeTransport` (e.g. \"auto\").\n // Distinct from `_runtimeTransport`, which auto-detect overwrites with the\n // RESOLVED value (\"rest\"/\"single\"). The idempotency guard compares against\n // this so re-applying the same mode (the provider effect re-applies \"auto\"\n // on every render) is a no-op instead of re-running the /info handshake.\n private _requestedTransport: CopilotRuntimeTransport = \"auto\";\n private _audioFileTranscriptionEnabled: boolean = false;\n private _runtimeMode: RuntimeMode = RUNTIME_MODE_SSE;\n private _intelligence?: IntelligenceRuntimeInfo;\n private _threadEndpoints?: ThreadEndpointRuntimeInfo;\n private _suggestions?: boolean;\n private _a2uiEnabled: boolean = false;\n private _a2uiAgents?: string[];\n private _openGenerativeUIEnabled: boolean = false;\n private _licenseStatus?: RuntimeLicenseStatus;\n private _telemetryDisabled: boolean = false;\n\n /**\n * The headers each HttpAgent was constructed with, captured on the first\n * `applyHeadersToAgent` call for that agent (which, for agents the registry\n * owns, happens at registration before any core headers are applied). Core\n * headers are merged ON TOP of this baseline so that headers configured\n * directly on an agent (e.g. an `Authorization` for a self-hosted backend)\n * survive registration instead of being silently replaced. The baseline is\n * captured once and never re-captured, so a later direct mutation of\n * `agent.headers` is not folded into it. See #5635.\n */\n private agentOwnHeaders = new WeakMap<HttpAgent, Record<string, string>>();\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Get all agents as a readonly record\n */\n get agents(): Readonly<Record<string, AbstractAgent>> {\n return this._agents;\n }\n\n get runtimeUrl(): string | undefined {\n return this._runtimeUrl;\n }\n\n get runtimeVersion(): string | undefined {\n return this._runtimeVersion;\n }\n\n get runtimeConnectionStatus(): CopilotKitCoreRuntimeConnectionStatus {\n return this._runtimeConnectionStatus;\n }\n\n get runtimeTransport(): CopilotRuntimeTransport {\n return this._runtimeTransport;\n }\n\n get audioFileTranscriptionEnabled(): boolean {\n return this._audioFileTranscriptionEnabled;\n }\n\n get runtimeMode(): RuntimeMode {\n return this._runtimeMode;\n }\n\n get intelligence(): IntelligenceRuntimeInfo | undefined {\n return this._intelligence;\n }\n\n get threadEndpoints(): ThreadEndpointRuntimeInfo | undefined {\n return this._threadEndpoints;\n }\n\n get suggestions(): boolean | undefined {\n return this._suggestions;\n }\n\n get a2uiEnabled(): boolean {\n return this._a2uiEnabled;\n }\n\n /**\n * Agent ids the runtime applies A2UI to (#5369). `undefined` means A2UI\n * applies to every agent — or is disabled entirely; check `a2uiEnabled`.\n */\n get a2uiAgents(): string[] | undefined {\n return this._a2uiAgents;\n }\n\n get openGenerativeUIEnabled(): boolean {\n return this._openGenerativeUIEnabled;\n }\n\n get licenseStatus(): RuntimeLicenseStatus | undefined {\n return this._licenseStatus;\n }\n\n get telemetryDisabled(): boolean {\n return this._telemetryDisabled;\n }\n\n /**\n * Initialize agents from configuration\n */\n initialize(agents: Record<string, AbstractAgent>): void {\n this.localAgents = this.assignAgentIds(agents);\n this.applyHeadersToAgents(this.localAgents);\n this.applyCredentialsToAgents(this.localAgents);\n this._agents = this.localAgents;\n }\n\n /**\n * Set the runtime URL and update connection\n */\n setRuntimeUrl(\n runtimeUrl: string | undefined,\n options?: { deferConnection?: boolean },\n ): void {\n const normalizedRuntimeUrl = runtimeUrl\n ? runtimeUrl.replace(/\\/$/, \"\")\n : undefined;\n\n if (this._runtimeUrl === normalizedRuntimeUrl) {\n return;\n }\n\n this._runtimeUrl = normalizedRuntimeUrl;\n\n // Deferred construction (see CopilotKitCore.connect / #5801): record the URL\n // so getters/hooks see it synchronously, but do NOT start the `/info` fetch\n // here. The host starts it from a commit-phase effect via `connect()`, so\n // renders discarded before commit never issue a request.\n if (options?.deferConnection) {\n return;\n }\n\n void this.updateRuntimeConnection();\n }\n\n /**\n * Start the initial runtime connection if it has not been started yet.\n *\n * Backs {@link CopilotKitCore.connect}. Idempotent: it only kicks off a fetch\n * when a `runtimeUrl` is set and the connection is still `Disconnected` (its\n * state before any connect attempt). `updateRuntimeConnection` flips the\n * status to `Connecting` synchronously, so a second call — e.g. React\n * StrictMode double-invoking the mount effect — bails here. A genuine config\n * change still reconnects through `setRuntimeUrl`/`setRuntimeTransport`. See\n * #5801.\n */\n connectRuntime(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n if (!this._runtimeUrl) {\n return;\n }\n if (\n this._runtimeConnectionStatus !==\n CopilotKitCoreRuntimeConnectionStatus.Disconnected\n ) {\n return;\n }\n void this.updateRuntimeConnection();\n }\n\n setRuntimeTransport(runtimeTransport: CopilotRuntimeTransport): void {\n // Guard on the requested MODE, not the resolved value: after auto-detect\n // writes `_runtimeTransport = \"rest\"`, re-applying the same requested\n // \"auto\" must not be treated as a change (otherwise every provider\n // re-render re-runs the /info handshake and rebuilds agents).\n if (this._requestedTransport === runtimeTransport) {\n return;\n }\n\n this._requestedTransport = runtimeTransport;\n this._runtimeTransport = runtimeTransport;\n void this.updateRuntimeConnection();\n }\n\n /**\n * Set all agents at once (for development use)\n */\n setAgents__unsafe_dev_only(agents: Record<string, AbstractAgent>): void {\n // Validate all agents before making any changes\n Object.entries(agents).forEach(([id, agent]) => {\n if (agent) {\n this.validateAndAssignAgentId(id, agent);\n }\n });\n this.localAgents = agents;\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n this.applyHeadersToAgents(this._agents);\n this.applyCredentialsToAgents(this._agents);\n void this.notifyAgentsChanged();\n }\n\n /**\n * Add a single agent (for development use)\n */\n addAgent__unsafe_dev_only({ id, agent }: CopilotKitCoreAddAgentParams): void {\n this.validateAndAssignAgentId(id, agent);\n this.localAgents[id] = agent;\n this.applyHeadersToAgent(agent);\n this.applyCredentialsToAgent(agent);\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n void this.notifyAgentsChanged();\n }\n\n /**\n * Remove an agent by ID (for development use)\n */\n removeAgent__unsafe_dev_only(id: string): void {\n delete this.localAgents[id];\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n void this.notifyAgentsChanged();\n }\n\n /**\n * Register a proxied agent that routes outbound runtime requests to an\n * existing runtime agent (`runtimeAgentId`) while exposing a distinct local\n * registry id (`agentId`). Throws if `agentId` is already taken by either a\n * local or runtime-discovered agent.\n *\n * Use this to mount multiple frontend agents against a single runtime\n * agent (e.g. a chat-1 / chat-2 pair both proxying to \"default\") without\n * implicit per-thread cloning. The returned `unregister` removes the proxy\n * from the registry and emits `onAgentsChanged`.\n */\n registerProxiedAgent({\n agentId,\n runtimeAgentId,\n }: CopilotKitCoreRegisterProxiedAgentParams): CopilotKitCoreRegisterProxiedAgentResult {\n // Use hasOwnProperty rather than `in`: `in` walks the prototype chain,\n // so an agentId of \"__proto__\", \"constructor\", \"toString\" etc. would\n // falsely test as already-registered.\n if (Object.prototype.hasOwnProperty.call(this._agents, agentId)) {\n throw new Error(\n `CopilotKitCore.registerProxiedAgent: agentId \"${agentId}\" is already registered. ` +\n `Pick a different agentId, or unregister the existing agent first.`,\n );\n }\n\n const friends = this.core as unknown as CopilotKitCoreFriendsAccess;\n const debug = friends.debug;\n const agent = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: this._runtimeUrl,\n agentId,\n runtimeAgentId,\n transport: this._runtimeTransport,\n credentials: friends.credentials,\n // If runtime info has already synced, mirror its mode/intelligence so\n // the proxy doesn't have to re-resolve. Otherwise stay \"pending\" until\n // /info lands.\n runtimeMode: this._runtimeUrl\n ? this._runtimeConnectionStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Connected\n ? this._runtimeMode\n : \"pending\"\n : RUNTIME_MODE_SSE,\n intelligence: this._intelligence,\n debug: debug ? resolveDebugConfig(debug) : undefined,\n });\n this.applyHeadersToAgent(agent);\n\n this.localAgents[agentId] = agent;\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n void this.notifyAgentsChanged();\n\n return {\n agent,\n unregister: () => {\n // Only unregister if the same instance is still in place — guards\n // against double-unregister or against unregistering after a\n // subsequent register replaced the slot.\n if (this.localAgents[agentId] === agent) {\n delete this.localAgents[agentId];\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n void this.notifyAgentsChanged();\n }\n },\n };\n }\n\n /**\n * Get an agent by ID\n */\n getAgent(id: string): AbstractAgent | undefined {\n if (id in this._agents) {\n return this._agents[id] as AbstractAgent;\n }\n\n // Silently return undefined if we're still loading runtime agents\n if (\n this.runtimeUrl !== undefined &&\n (this.runtimeConnectionStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Disconnected ||\n this.runtimeConnectionStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Connecting)\n ) {\n return undefined;\n }\n\n console.warn(`Agent ${id} not found`);\n return undefined;\n }\n\n /**\n * Apply current core headers to an agent, merged ON TOP of the agent's own\n * construction-time headers (the per-agent baseline in `agentOwnHeaders`).\n * Core wins on a key conflict. Non-`HttpAgent` agents are left untouched\n * because only `HttpAgent` carries a `headers` field. See #5635.\n */\n applyHeadersToAgent(agent: AbstractAgent): void {\n if (agent instanceof HttpAgent) {\n // Capture the agent's construction-time headers once, before any core\n // headers overwrite them. On every subsequent apply we rebuild from this\n // baseline so re-applying core headers (e.g. via setHeaders) never loses\n // the agent's own headers.\n if (!this.agentOwnHeaders.has(agent)) {\n this.agentOwnHeaders.set(agent, { ...agent.headers });\n }\n agent.headers = {\n ...this.agentOwnHeaders.get(agent),\n ...(this.core as unknown as CopilotKitCoreFriendsAccess).headers,\n };\n }\n }\n\n /**\n * Apply current headers to all agents\n */\n applyHeadersToAgents(agents: Record<string, AbstractAgent>): void {\n Object.values(agents).forEach((agent) => {\n this.applyHeadersToAgent(agent);\n });\n }\n\n /**\n * Apply current credentials to an agent\n */\n applyCredentialsToAgent(agent: AbstractAgent): void {\n if (agent instanceof ProxiedCopilotRuntimeAgent) {\n agent.credentials = (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).credentials;\n }\n }\n\n /**\n * Apply current credentials to all agents\n */\n applyCredentialsToAgents(agents: Record<string, AbstractAgent>): void {\n Object.values(agents).forEach((agent) => {\n this.applyCredentialsToAgent(agent);\n });\n }\n\n /**\n * Update runtime connection and fetch remote agents\n */\n private async updateRuntimeConnection(): Promise<void> {\n // Skip fetching on the server (SSR)\n if (typeof window === \"undefined\") {\n return;\n }\n\n // In-flight guard: if a connection to the same target (runtime url +\n // requested transport) is already running, reuse it instead of starting a\n // second `/info` request. A change to a different target supersedes it. See\n // #5801.\n const key = `${this._runtimeUrl ?? \"\"}::${this._requestedTransport}`;\n const inFlight = this._connectionInFlight;\n if (inFlight && inFlight.key === key) {\n return inFlight.promise;\n }\n\n const promise = this.performRuntimeConnection();\n this._connectionInFlight = { key, promise };\n void promise.finally(() => {\n if (this._connectionInFlight?.promise === promise) {\n this._connectionInFlight = undefined;\n }\n });\n return promise;\n }\n\n private async performRuntimeConnection(): Promise<void> {\n if (!this.runtimeUrl) {\n this._runtimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Disconnected;\n this._runtimeVersion = undefined;\n this._audioFileTranscriptionEnabled = false;\n this._runtimeMode = RUNTIME_MODE_SSE;\n this._intelligence = undefined;\n this._threadEndpoints = undefined;\n this._suggestions = undefined;\n this._a2uiEnabled = false;\n this._a2uiAgents = undefined;\n this._openGenerativeUIEnabled = false;\n this.remoteAgents = {};\n this._agents = this.localAgents;\n\n await this.notifyRuntimeStatusChanged(\n CopilotKitCoreRuntimeConnectionStatus.Disconnected,\n );\n await this.notifyAgentsChanged();\n return;\n }\n\n this._runtimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Connecting;\n await this.notifyRuntimeStatusChanged(\n CopilotKitCoreRuntimeConnectionStatus.Connecting,\n );\n\n try {\n const runtimeInfoResponse = await this.fetchRuntimeInfo();\n const {\n version,\n ...runtimeInfo\n }: {\n agents: Record<string, AgentDescription>;\n version: string;\n mode?: RuntimeMode;\n intelligence?: IntelligenceRuntimeInfo;\n threadEndpoints?: ThreadEndpointRuntimeInfo;\n suggestions?: boolean;\n } = runtimeInfoResponse;\n\n const credentials = (this.core as unknown as CopilotKitCoreFriendsAccess)\n .credentials;\n const rawDebug = (this.core as unknown as CopilotKitCoreFriendsAccess)\n .debug;\n const agents: Record<string, AbstractAgent> = Object.fromEntries(\n Object.entries(runtimeInfo.agents).map(\n ([id, { description, capabilities }]) => {\n // Reuse the already-registered instance for ids that are still\n // present. A re-connection (an /info re-settle, a header/config or\n // transport change) re-runs this method, but the runtime agent for\n // a given id is the SAME logical agent — minting a fresh instance\n // would discard its accumulated `messages`/`threadId` and its live\n // subscriptions. Downstream (e.g. the `use-agent` memo) keys on the\n // instance identity returned by `getAgent(id)`, so replacing it\n // unmounts an already-rendered conversation. Only re-apply what the\n // registry owns (headers + credentials) in place; the proxy\n // re-resolves its own runtime mode/intelligence via `/info`.\n const existing = Object.prototype.hasOwnProperty.call(\n this.remoteAgents,\n id,\n )\n ? this.remoteAgents[id]\n : undefined;\n if (existing instanceof ProxiedCopilotRuntimeAgent) {\n this.applyHeadersToAgent(existing);\n this.applyCredentialsToAgent(existing);\n return [id, existing];\n }\n const agent = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: this.runtimeUrl,\n agentId: id, // Runtime agents always have their ID set correctly\n description: description,\n transport: this._runtimeTransport,\n credentials,\n runtimeMode: runtimeInfoResponse.mode ?? RUNTIME_MODE_SSE,\n intelligence: runtimeInfoResponse.intelligence,\n capabilities,\n debug: rawDebug ? resolveDebugConfig(rawDebug) : undefined,\n });\n this.applyHeadersToAgent(agent);\n return [id, agent];\n },\n ),\n );\n\n // Reassign the full set: ids present in `runtimeInfo.agents` are carried\n // over (reused or freshly minted above); ids no longer advertised are\n // dropped because they are absent from this rebuilt map.\n this.remoteAgents = agents;\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n this._runtimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Connected;\n this._runtimeVersion = version;\n this._audioFileTranscriptionEnabled =\n runtimeInfoResponse.audioFileTranscriptionEnabled ?? false;\n this._runtimeMode = runtimeInfoResponse.mode ?? RUNTIME_MODE_SSE;\n this._intelligence = runtimeInfoResponse.intelligence;\n this._threadEndpoints = runtimeInfoResponse.threadEndpoints;\n this._suggestions = runtimeInfoResponse.suggestions;\n const a2uiInfo = runtimeInfoResponse.a2ui;\n this._a2uiEnabled =\n a2uiInfo?.enabled ?? runtimeInfoResponse.a2uiEnabled ?? false;\n this._a2uiAgents = a2uiInfo?.enabled ? a2uiInfo.agents : undefined;\n this._openGenerativeUIEnabled =\n runtimeInfoResponse.openGenerativeUIEnabled ?? false;\n this._licenseStatus = runtimeInfoResponse.licenseStatus;\n this._telemetryDisabled = runtimeInfoResponse.telemetryDisabled ?? false;\n\n await this.notifyRuntimeStatusChanged(\n CopilotKitCoreRuntimeConnectionStatus.Connected,\n );\n await this.notifyAgentsChanged();\n } catch (error) {\n this._runtimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Error;\n this._runtimeVersion = undefined;\n this._audioFileTranscriptionEnabled = false;\n this._runtimeMode = RUNTIME_MODE_SSE;\n this._intelligence = undefined;\n this._threadEndpoints = undefined;\n this._suggestions = undefined;\n this._a2uiEnabled = false;\n this._a2uiAgents = undefined;\n this._openGenerativeUIEnabled = false;\n this.remoteAgents = {};\n this._agents = this.localAgents;\n\n await this.notifyRuntimeStatusChanged(\n CopilotKitCoreRuntimeConnectionStatus.Error,\n );\n await this.notifyAgentsChanged();\n\n const message =\n error instanceof Error ? error.message : JSON.stringify(error);\n logger.warn(\n `Failed to load runtime info (${this.runtimeUrl}/info): ${message}`,\n );\n const runtimeError =\n error instanceof Error ? error : new Error(String(error));\n await (this.core as unknown as CopilotKitCoreFriendsAccess).emitError({\n error: runtimeError,\n code: CopilotKitCoreErrorCode.RUNTIME_INFO_FETCH_FAILED,\n context: {\n runtimeUrl: this.runtimeUrl,\n },\n });\n }\n }\n\n private async fetchRuntimeInfo(): Promise<RuntimeInfo> {\n if (!this.runtimeUrl) {\n throw new Error(\"Runtime URL is not set\");\n }\n\n const baseHeaders = (this.core as unknown as CopilotKitCoreFriendsAccess)\n .headers;\n const credentials = (this.core as unknown as CopilotKitCoreFriendsAccess)\n .credentials;\n const headers: Record<string, string> = {\n ...baseHeaders,\n };\n\n if (this._runtimeTransport === \"single\") {\n return this.fetchRuntimeInfoSingle(headers, credentials);\n }\n\n if (this._runtimeTransport === \"auto\") {\n return this.fetchRuntimeInfoAutoDetect(headers, credentials);\n }\n\n // REST transport\n const response = await fetch(`${this.runtimeUrl}/info`, {\n headers,\n ...(credentials ? { credentials } : {}),\n });\n if (!response.ok) {\n throw new Error(\n `Runtime info request failed with status ${response.status}`,\n );\n }\n return (await response.json()) as RuntimeInfo;\n }\n\n private async fetchRuntimeInfoSingle(\n headers: Record<string, string>,\n credentials: RequestCredentials | undefined,\n ): Promise<RuntimeInfo> {\n if (!headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n const response = await fetch(this.runtimeUrl!, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ method: \"info\" }),\n ...(credentials ? { credentials } : {}),\n });\n if (!response.ok) {\n throw new Error(\n `Runtime info request failed with status ${response.status}`,\n );\n }\n return (await response.json()) as RuntimeInfo;\n }\n\n /**\n * Auto-detect transport by trying REST first, then falling back to single-endpoint.\n * Updates `_runtimeTransport` to the detected value so subsequent requests use it directly.\n */\n private async fetchRuntimeInfoAutoDetect(\n headers: Record<string, string>,\n credentials: RequestCredentials | undefined,\n ): Promise<RuntimeInfo> {\n // Try REST first (GET /info)\n try {\n const response = await fetch(`${this.runtimeUrl}/info`, {\n headers: { ...headers },\n ...(credentials ? { credentials } : {}),\n });\n // Only treat a successful (2xx) response as a valid REST runtime.\n // 404/405 means the endpoint doesn't exist; other non-2xx errors\n // (500, 403, etc.) should also fall through to single-endpoint.\n if (response.status >= 200 && response.status < 300) {\n this._runtimeTransport = \"rest\";\n return (await response.json()) as RuntimeInfo;\n }\n // Non-2xx — try single-endpoint below\n } catch {\n // REST failed (network error, etc.) — fall through to single-endpoint attempt\n }\n\n const result = await this.fetchRuntimeInfoSingle(\n { ...headers },\n credentials,\n );\n this._runtimeTransport = \"single\";\n return result;\n }\n\n /**\n * Assign agent IDs to a record of agents\n */\n private assignAgentIds(\n agents: Record<string, AbstractAgent>,\n ): Record<string, AbstractAgent> {\n Object.entries(agents).forEach(([id, agent]) => {\n if (agent) {\n this.validateAndAssignAgentId(id, agent);\n }\n });\n return agents;\n }\n\n /**\n * Validate and assign an agent ID\n */\n private validateAndAssignAgentId(\n registrationId: string,\n agent: AbstractAgent,\n ): void {\n if (agent.agentId && agent.agentId !== registrationId) {\n throw new Error(\n `Agent registration mismatch: Agent with ID \"${agent.agentId}\" cannot be registered under key \"${registrationId}\". ` +\n `The agent ID must match the registration key or be undefined.`,\n );\n }\n if (!agent.agentId) {\n agent.agentId = registrationId;\n }\n }\n\n /**\n * Notify subscribers of runtime status changes\n */\n private async notifyRuntimeStatusChanged(\n status: CopilotKitCoreRuntimeConnectionStatus,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onRuntimeConnectionStatusChanged?.({\n copilotkit: this.core,\n status,\n }),\n \"Error in CopilotKitCore subscriber (onRuntimeConnectionStatusChanged):\",\n );\n }\n\n /**\n * Notify subscribers of agent changes\n */\n private async notifyAgentsChanged(): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onAgentsChanged?.({\n copilotkit: this.core,\n agents: this._agents,\n }),\n \"Subscriber onAgentsChanged error:\",\n );\n }\n}\n","import type { Context } from \"@ag-ui/client\";\nimport { randomUUID } from \"@copilotkit/shared\";\nimport type { CopilotKitCore } from \"./core\";\nimport type { CopilotKitCoreFriendsAccess } from \"./core\";\n\n/**\n * A context entry with optional per-agent scoping.\n * When `agentIds` is set, the entry is forwarded only to runs of those agents;\n * when omitted, the entry is forwarded to every agent run.\n */\nexport interface ScopedContext extends Context {\n agentIds?: string[];\n}\n\n/**\n * Manages context storage and lifecycle for CopilotKitCore.\n * Context represents additional information available to agents during execution.\n */\nexport class ContextStore {\n private _context: Record<string, ScopedContext> = {};\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Get all context entries as a readonly record\n */\n get context(): Readonly<Record<string, ScopedContext>> {\n return this._context;\n }\n\n /**\n * Add a new context entry. Pass `agentIds` to restrict the entry to runs of\n * specific agents (#5369); omit it for context every agent should receive.\n * @returns The ID of the created context entry\n */\n addContext({ description, value, agentIds }: ScopedContext): string {\n const id = randomUUID();\n this._context[id] = {\n description,\n value,\n ...(agentIds ? { agentIds } : {}),\n };\n void this.notifySubscribers();\n return id;\n }\n\n /**\n * Build the context array for a run of the given agent: entries scoped to\n * other agents are dropped, and the scoping metadata is stripped so only\n * protocol-shaped `{ description, value }` entries go over the wire.\n */\n getContextForAgent(agentId?: string): Context[] {\n return Object.values(this._context)\n .filter(\n (entry) =>\n !entry.agentIds ||\n (agentId !== undefined && entry.agentIds.includes(agentId)),\n )\n .map(({ description, value }) => ({ description, value }));\n }\n\n /**\n * Remove a context entry by ID\n */\n removeContext(id: string): void {\n delete this._context[id];\n void this.notifySubscribers();\n }\n\n /**\n * Notify all subscribers of context changes\n */\n private async notifySubscribers(): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onContextChanged?.({\n copilotkit: this.core,\n context: this._context,\n }),\n \"Subscriber onContextChanged error:\",\n );\n }\n}\n","import type { AbstractAgent, Message, Tool } from \"@ag-ui/client\";\nimport { HttpAgent } from \"@ag-ui/client\";\nimport { randomUUID, partialJSONParse } from \"@copilotkit/shared\";\nimport type { CopilotKitCore } from \"./core\";\nimport type { CopilotKitCoreGetSuggestionsResult } from \"./core\";\nimport type { CopilotKitCoreFriendsAccess } from \"./core\";\nimport type {\n DynamicSuggestionsConfig,\n StaticSuggestionsConfig,\n Suggestion,\n SuggestionsConfig,\n} from \"../types\";\n\n/**\n * The minimal cancellation surface a running suggestion generation exposes.\n * Both a cloned `AbstractAgent` (via `abortRun`) and the stateless fetch shim\n * (which aborts an `AbortController`) satisfy this, so `clearSuggestions` can\n * cancel either uniformly.\n */\ninterface AbortableSuggestionRun {\n abortRun(): void;\n}\n\n/**\n * Manages suggestion generation, streaming, and lifecycle for CopilotKitCore.\n * Handles both dynamic (AI-generated) and static suggestions.\n */\nexport class SuggestionEngine {\n private _suggestionsConfig: Record<string, SuggestionsConfig> = {};\n private _suggestions: Record<string, Record<string, Suggestion[]>> = {};\n private _runningSuggestions: Record<string, AbortableSuggestionRun[]> = {};\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Initialize with suggestion configs\n */\n initialize(suggestionsConfig: SuggestionsConfig[]): void {\n for (const config of suggestionsConfig) {\n this._suggestionsConfig[randomUUID()] = config;\n }\n }\n\n /**\n * Add a suggestion configuration\n * @returns The ID of the created config\n */\n addSuggestionsConfig(config: SuggestionsConfig): string {\n const id = randomUUID();\n this._suggestionsConfig[id] = config;\n void this.notifySuggestionsConfigChanged();\n return id;\n }\n\n /**\n * Remove a suggestion configuration by ID\n */\n removeSuggestionsConfig(id: string): void {\n delete this._suggestionsConfig[id];\n void this.notifySuggestionsConfigChanged();\n }\n\n /**\n * Reload suggestions for a specific agent\n * This triggers generation of new suggestions based on current configs\n */\n public reloadSuggestions(agentId: string): void {\n this.clearSuggestions(agentId);\n\n // The agent may legitimately be missing here (e.g. runtime info still loading,\n // or the consumer agent is configured but not yet registered) — static suggestions\n // don't need it, only dynamic generation does. Treat that case as \"no messages yet\"\n // and process static configs anyway.\n const agent = (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).getAgent(agentId);\n\n const messageCount = agent?.messages?.length ?? 0;\n let hasAnySuggestions = false;\n\n for (const config of Object.values(this._suggestionsConfig)) {\n // Check if config applies to this agent\n if (\n config.consumerAgentId !== undefined &&\n config.consumerAgentId !== \"*\" &&\n config.consumerAgentId !== agentId\n ) {\n continue;\n }\n\n // Check availability based on message count\n if (!this.shouldShowSuggestions(config, messageCount)) {\n continue;\n }\n\n const suggestionId = randomUUID();\n\n if (isDynamicSuggestionsConfig(config)) {\n // Dynamic suggestions need a real agent (provider + consumer messages).\n // Skip when the agent isn't ready yet — `reloadSuggestions` will be\n // called again once it is.\n if (!agent) {\n continue;\n }\n if (!hasAnySuggestions) {\n hasAnySuggestions = true;\n void this.notifySuggestionsStartedLoading(agentId);\n }\n void this.generateSuggestions(suggestionId, config, agentId);\n } else if (isStaticSuggestionsConfig(config)) {\n this.addStaticSuggestions(suggestionId, config, agentId);\n }\n }\n }\n\n /**\n * Clear all suggestions for a specific agent\n */\n public clearSuggestions(agentId: string): void {\n const runningAgents = this._runningSuggestions[agentId];\n if (runningAgents) {\n for (const agent of runningAgents) {\n agent.abortRun();\n }\n delete this._runningSuggestions[agentId];\n }\n this._suggestions[agentId] = {};\n\n void this.notifySuggestionsChanged(agentId, []);\n }\n\n /**\n * Get current suggestions for an agent\n */\n public getSuggestions(agentId: string): CopilotKitCoreGetSuggestionsResult {\n const suggestions = Object.values(this._suggestions[agentId] ?? {}).flat();\n const isLoading = (this._runningSuggestions[agentId]?.length ?? 0) > 0;\n return { suggestions, isLoading };\n }\n\n /**\n * Generate suggestions by running a provider agent and extracting the\n * `copilotkitSuggest` tool call from its streamed messages.\n *\n * Two transports, one set of mechanics: both seed an agent with the\n * consumer's messages + state and the instruction, then `runAgent` with\n * forced `copilotkitSuggest` tool choice, parsing suggestions as messages\n * stream in via `onMessagesChanged`.\n *\n * - **Stateless** (runtime advertises `suggestions` and transport isn't\n * `single`): a stock `HttpAgent` pointed at `/agent/:id/suggest`. That\n * endpoint runs the provider directly and streams AG-UI SSE **without**\n * persisting a thread, and a plain `HttpAgent` only ever speaks REST SSE —\n * it never routes through the Intelligence websocket delegate (which would\n * persist a thread). This is the path that removes the thread flood.\n * - **Fallback** (capability absent → old runtime, or `single` transport):\n * clone the provider agent and run it client-side, as before.\n *\n * Gated to non-`single` transports because this client only builds the\n * multi-route `/agent/:id/suggest` URL; single-route deployments (not the\n * persisting-thread/Intelligence case) fall through to the clone fallback.\n */\n private async generateSuggestions(\n suggestionId: string,\n config: DynamicSuggestionsConfig,\n consumerAgentId: string,\n ): Promise<void> {\n // The cancellable handle for this generation, removed from the running set\n // in `finally`. `abortRun` flips `aborted` before cancelling the underlying\n // agent so the `catch` can distinguish a deliberate clear/reload from a real\n // failure — some engines (undici, some React Native) reject an aborted run\n // with a non-\"AbortError\" error that `isAbortError` alone would misclassify.\n let runHandle: AbortableSuggestionRun | undefined = undefined;\n let aborted = false;\n try {\n const friends = this.core as unknown as CopilotKitCoreFriendsAccess;\n const resolvedProviderAgentId = config.providerAgentId ?? \"default\";\n const suggestionsProviderAgent = friends.getAgent(\n resolvedProviderAgentId,\n );\n if (!suggestionsProviderAgent) {\n throw new Error(\n `Suggestions provider agent not found: ${resolvedProviderAgentId}`,\n );\n }\n const suggestionsConsumerAgent = friends.getAgent(consumerAgentId);\n if (!suggestionsConsumerAgent) {\n throw new Error(\n `Suggestions consumer agent not found: ${consumerAgentId}`,\n );\n }\n\n const instructionContent = [\n `Suggest what the user could say next. Provide clear, highly relevant suggestions by calling the \\`copilotkitSuggest\\` tool.`,\n `Provide at least ${config.minSuggestions ?? 1} and at most ${\n config.maxSuggestions ?? 3\n } suggestions.`,\n `The user has the following tools available: ${JSON.stringify(\n friends.buildFrontendTools(consumerAgentId),\n )}.`,\n ` ${config.instructions}`,\n ].join(\"\\n\");\n\n // Initialize suggestion storage for this agent/suggestion combo\n this._suggestions[consumerAgentId] = {\n ...this._suggestions[consumerAgentId],\n [suggestionId]: [],\n };\n\n // Deep-clone the consumer's messages + state so the suggestion run sees\n // the same context a real turn would, without sharing mutable references.\n const seededMessages: Message[] = JSON.parse(\n JSON.stringify(suggestionsConsumerAgent.messages),\n );\n const seededState: unknown = JSON.parse(\n JSON.stringify(suggestionsConsumerAgent.state ?? {}),\n );\n\n const useStateless =\n this.core.suggestions === true &&\n this.core.runtimeTransport !== \"single\";\n\n let suggestionAgent: AbstractAgent;\n if (useStateless) {\n const suggestUrl = `${this.core.runtimeUrl}/agent/${encodeURIComponent(\n resolvedProviderAgentId,\n )}/suggest`;\n const credentials = this.core.credentials;\n suggestionAgent = new HttpAgent({\n agentId: resolvedProviderAgentId,\n url: suggestUrl,\n headers: { ...this.core.headers },\n // `HttpAgentConfig` has no `credentials` field; inject it via a fetch\n // wrapper so cookie-based / self-hosted auth still rides along on the\n // `/suggest` request.\n ...(credentials\n ? {\n fetch: (url: string, requestInit: RequestInit) =>\n fetch(url, { ...requestInit, credentials }),\n }\n : {}),\n });\n } else {\n suggestionAgent = suggestionsProviderAgent.clone();\n }\n\n suggestionAgent.threadId = suggestionId;\n suggestionAgent.setMessages(seededMessages);\n suggestionAgent.setState(seededState);\n\n runHandle = {\n abortRun: () => {\n aborted = true;\n suggestionAgent.abortRun();\n },\n };\n this._runningSuggestions[consumerAgentId] = [\n ...(this._runningSuggestions[consumerAgentId] ?? []),\n runHandle,\n ];\n\n suggestionAgent.addMessage({\n id: suggestionId,\n role: \"user\",\n content: instructionContent,\n });\n\n await suggestionAgent.runAgent(\n {\n context: friends.getContextForAgent(consumerAgentId),\n forwardedProps: {\n ...friends.properties,\n toolChoice: {\n type: \"function\",\n function: { name: \"copilotkitSuggest\" },\n },\n },\n tools: [SUGGEST_TOOL],\n },\n {\n onMessagesChanged: ({ messages }) => {\n this.extractSuggestions(\n messages,\n suggestionId,\n consumerAgentId,\n true,\n );\n },\n },\n );\n } catch (error) {\n // An abort is expected when suggestions are cleared/reloaded mid-flight;\n // swallow it quietly rather than surfacing it as a failure. `isAbortError`\n // is the primary (name-based) check; `aborted` covers engines that reject\n // an aborted run with a differently-named error (or a `TypeError`).\n if (!isAbortError(error) && !aborted) {\n console.warn(\"Error generating suggestions:\", error);\n }\n } finally {\n // Finalize suggestions by marking them as no longer loading\n this.finalizeSuggestions(suggestionId, consumerAgentId);\n\n // Remove this run from the running set. `runHandle` may be undefined when\n // generation threw before it was assigned (e.g. provider/consumer agent\n // lookup failed); still perform cleanup so the loading balance holds. If\n // no runs remain for this consumer, emit finished-loading — otherwise a\n // subscriber that saw `started` would hang in the loading state.\n const runningAgents = this._runningSuggestions[consumerAgentId];\n const remaining = runHandle\n ? (runningAgents ?? []).filter((a) => a !== runHandle)\n : (runningAgents ?? []);\n\n if (remaining.length === 0) {\n delete this._runningSuggestions[consumerAgentId];\n await this.notifySuggestionsFinishedLoading(consumerAgentId);\n } else {\n this._runningSuggestions[consumerAgentId] = remaining;\n }\n }\n }\n\n /**\n * Finalize suggestions by marking them as no longer loading\n */\n private finalizeSuggestions(\n suggestionId: string,\n consumerAgentId: string,\n ): void {\n const agentSuggestions = this._suggestions[consumerAgentId];\n const currentSuggestions = agentSuggestions?.[suggestionId];\n\n if (\n agentSuggestions &&\n currentSuggestions &&\n currentSuggestions.length > 0\n ) {\n // Filter out empty suggestions and mark remaining as no longer loading\n const finalizedSuggestions = currentSuggestions\n .filter(\n (suggestion) => suggestion.title !== \"\" || suggestion.message !== \"\",\n )\n .map((suggestion) => ({\n ...suggestion,\n isLoading: false,\n }));\n\n if (finalizedSuggestions.length > 0) {\n agentSuggestions[suggestionId] = finalizedSuggestions;\n } else {\n delete agentSuggestions[suggestionId];\n }\n\n // Get all aggregated suggestions for this agent\n const allSuggestions = Object.values(\n this._suggestions[consumerAgentId] ?? {},\n ).flat();\n\n void this.notifySuggestionsChanged(\n consumerAgentId,\n allSuggestions,\n \"finalized\",\n );\n }\n }\n\n /**\n * Extract suggestions from messages (called during streaming)\n */\n extractSuggestions(\n messages: readonly Message[],\n suggestionId: string,\n consumerAgentId: string,\n isRunning: boolean,\n ): void {\n const idx = messages.findIndex((message) => message.id === suggestionId);\n if (idx == -1) {\n return;\n }\n\n const suggestions: Suggestion[] = [];\n const newMessages = messages.slice(idx + 1);\n\n for (const message of newMessages) {\n if (message.role === \"assistant\" && message.toolCalls) {\n for (const toolCall of message.toolCalls) {\n if (toolCall.function.name === \"copilotkitSuggest\") {\n // Join all argument chunks into a single string for parsing\n // arguments can be either a string or an array of strings\n const fullArgs = Array.isArray(toolCall.function.arguments)\n ? toolCall.function.arguments.join(\"\")\n : toolCall.function.arguments;\n const parsed = partialJSONParse(fullArgs);\n if (\n parsed &&\n typeof parsed === \"object\" &&\n \"suggestions\" in parsed\n ) {\n const parsedSuggestions = (parsed as any).suggestions;\n if (Array.isArray(parsedSuggestions)) {\n for (const item of parsedSuggestions) {\n if (item && typeof item === \"object\" && \"title\" in item) {\n suggestions.push({\n title: item.title ?? \"\",\n message: item.message ?? \"\",\n // Defaults to false; only the trailing item is flipped to\n // true below, and only while a streaming run is in flight.\n isLoading: false,\n });\n }\n }\n }\n }\n }\n }\n }\n }\n\n // Set isLoading for the last suggestion if still running\n if (isRunning && suggestions.length > 0) {\n suggestions[suggestions.length - 1]!.isLoading = true;\n }\n\n const agentSuggestions = this._suggestions[consumerAgentId];\n if (agentSuggestions) {\n agentSuggestions[suggestionId] = suggestions;\n\n // Get all aggregated suggestions for this agent\n const allSuggestions = Object.values(\n this._suggestions[consumerAgentId] ?? {},\n ).flat();\n\n void this.notifySuggestionsChanged(\n consumerAgentId,\n allSuggestions,\n \"suggestions changed\",\n );\n }\n }\n\n /**\n * Notify subscribers of suggestions config changes\n */\n private async notifySuggestionsConfigChanged(): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onSuggestionsConfigChanged?.({\n copilotkit: this.core,\n suggestionsConfig: this._suggestionsConfig,\n }),\n \"Subscriber onSuggestionsConfigChanged error:\",\n );\n }\n\n /**\n * Notify subscribers of suggestions changes\n */\n private async notifySuggestionsChanged(\n agentId: string,\n suggestions: Suggestion[],\n context: string = \"\",\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onSuggestionsChanged?.({\n copilotkit: this.core,\n agentId,\n suggestions,\n }),\n `Subscriber onSuggestionsChanged error: ${context}`,\n );\n }\n\n /**\n * Notify subscribers that suggestions started loading\n */\n private async notifySuggestionsStartedLoading(\n agentId: string,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onSuggestionsStartedLoading?.({\n copilotkit: this.core,\n agentId,\n }),\n \"Subscriber onSuggestionsStartedLoading error:\",\n );\n }\n\n /**\n * Notify subscribers that suggestions finished loading\n */\n private async notifySuggestionsFinishedLoading(\n agentId: string,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onSuggestionsFinishedLoading?.({\n copilotkit: this.core,\n agentId,\n }),\n \"Subscriber onSuggestionsFinishedLoading error:\",\n );\n }\n\n /**\n * Check if suggestions should be shown based on availability and message count\n */\n private shouldShowSuggestions(\n config: SuggestionsConfig,\n messageCount: number,\n ): boolean {\n const availability = config.available;\n\n // Default behavior if no availability specified\n if (!availability) {\n if (isDynamicSuggestionsConfig(config)) {\n return messageCount > 0; // Default: after-first-message\n } else {\n return messageCount === 0; // Default: before-first-message\n }\n }\n\n switch (availability) {\n case \"disabled\":\n return false;\n case \"before-first-message\":\n return messageCount === 0;\n case \"after-first-message\":\n return messageCount > 0;\n case \"always\":\n return true;\n default:\n return false;\n }\n }\n\n /**\n * Add static suggestions directly without AI generation\n */\n private addStaticSuggestions(\n suggestionId: string,\n config: StaticSuggestionsConfig,\n consumerAgentId: string,\n ): void {\n // Mark all as not loading since they're static\n const suggestions = config.suggestions.map((s) => ({\n ...s,\n isLoading: false,\n }));\n\n // Store suggestions\n this._suggestions[consumerAgentId] = {\n ...this._suggestions[consumerAgentId],\n [suggestionId]: suggestions,\n };\n\n // Notify subscribers\n const allSuggestions = Object.values(\n this._suggestions[consumerAgentId] ?? {},\n ).flat();\n\n void this.notifySuggestionsChanged(\n consumerAgentId,\n allSuggestions,\n \"static suggestions added\",\n );\n }\n}\n\n/**\n * Detects an `AbortController`-driven cancellation so the stateless path can\n * treat it as an expected (non-error) outcome on clear/reload.\n */\nexport function isAbortError(error: unknown): boolean {\n // Detect purely by name: a `DOMException` is NOT `instanceof Error` in Safari\n // and older engines, so gating on `instanceof Error` would misclassify a real\n // user abort as a failure in the browser (this package runs client-side).\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"name\" in error &&\n (error as { name?: unknown }).name === \"AbortError\"\n );\n}\n\n/**\n * Type guard for dynamic suggestions config\n */\nfunction isDynamicSuggestionsConfig(\n config: SuggestionsConfig,\n): config is DynamicSuggestionsConfig {\n return \"instructions\" in config;\n}\n\n/**\n * Type guard for static suggestions config\n */\nfunction isStaticSuggestionsConfig(\n config: SuggestionsConfig,\n): config is StaticSuggestionsConfig {\n return \"suggestions\" in config;\n}\n\n/**\n * The tool definition for AI-generated suggestions\n */\nconst SUGGEST_TOOL: Tool = {\n name: \"copilotkitSuggest\",\n description: \"Suggest what the user could say next\",\n parameters: {\n type: \"object\",\n properties: {\n suggestions: {\n type: \"array\",\n description: \"List of suggestions shown to the user as buttons.\",\n items: {\n type: \"object\",\n properties: {\n title: {\n type: \"string\",\n description:\n \"The title of the suggestion. This is shown as a button and should be short.\",\n },\n message: {\n type: \"string\",\n description:\n \"The message to send when the suggestion is clicked. This should be a clear, complete sentence \" +\n \"and will be sent as an instruction to the AI.\",\n },\n },\n required: [\"title\", \"message\"],\n },\n },\n },\n required: [\"suggestions\"],\n },\n};\n","import type {\n AbstractAgent,\n AgentSubscriber,\n Message,\n RunAgentResult,\n ResumeEntry,\n Tool,\n ToolCall,\n} from \"@ag-ui/client\";\nimport { randomUUID, logger, schemaToJsonSchema } from \"@copilotkit/shared\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport type { CopilotKitCore, CopilotKitCoreFriendsAccess } from \"./core\";\nimport { CopilotKitCoreErrorCode } from \"./core\";\nimport { AgentThreadLockedError } from \"../intelligence-agent\";\nimport type { FrontendTool } from \"../types\";\n\nexport interface CopilotKitCoreRunAgentParams {\n agent: AbstractAgent;\n forwardedProps?: Record<string, unknown>;\n /**\n * Optional caller-supplied run identifier forwarded to the underlying AG-UI\n * agent. When omitted, the agent creates one.\n */\n runId?: string;\n /**\n * Per-interrupt responses addressing every open AG-UI interrupt from the\n * previous run. Forwarded to the agent as the standard `resume` array.\n */\n resume?: ResumeEntry[];\n}\n\nexport interface CopilotKitCoreConnectAgentParams {\n agent: AbstractAgent;\n}\n\nexport interface CopilotKitCoreGetToolParams {\n toolName: string;\n agentId?: string;\n}\n\n/**\n * Parameters for programmatic tool execution via `copilotkit.runTool()`.\n */\nexport interface CopilotKitCoreRunToolParams {\n /** Name of the registered frontend tool to execute. */\n name: string;\n /** Optional agent ID. If omitted, uses the default agent lookup. */\n agentId?: string;\n /** Parameters to pass to the tool handler. */\n parameters?: Record<string, unknown>;\n /**\n * Whether to trigger an LLM follow-up after tool execution.\n * - `false` (default): execute tool, add messages to history, done.\n * - `\"generate\"`: after execution, trigger another agent run so the LLM responds to the tool result.\n * - Any other string: add a user message with this text, then trigger another agent run.\n */\n followUp?: string | false;\n}\n\n/**\n * Result of programmatic tool execution via `copilotkit.runTool()`.\n */\nexport interface CopilotKitCoreRunToolResult {\n /** The unique ID of the tool call. */\n toolCallId: string;\n /** The stringified result from the tool handler. */\n result: string;\n /** Error message if the handler failed. */\n error?: string;\n}\n\n/**\n * Internal result from the shared tool handler execution logic.\n */\ninterface ExecuteToolHandlerResult {\n result: string;\n error?: string;\n isArgumentError: boolean;\n}\n\n/**\n * Absolute safety cap on the depth of recursive follow-up runs triggered by\n * `processAgentResult`. Without this, any scenario that keeps\n * `needsFollowUp = true` (e.g. the LLM repeatedly calling the same tool, a\n * backend that errors after receiving tool results, or input processors that\n * reprocess tool messages) would loop indefinitely, silently consuming API\n * quota and potentially DOS'ing the backend.\n *\n * The cap is deliberately high so that legitimate multi-step agent workflows\n * (search → fill form → confirm → update → send email, etc.) are never\n * affected; it only trips on runaway recursion.\n */\nconst MAX_FOLLOW_UP_DEPTH = 100;\n\n/**\n * Handles agent execution, tool calling, and agent connectivity for CopilotKitCore.\n * Manages the complete lifecycle of agent runs including tool execution and follow-ups.\n */\nexport class RunHandler {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private _tools: FrontendTool<any>[] = [];\n\n /**\n * Tracks whether the current run (including in-flight tool execution)\n * has been aborted via `stopAgent()` or `agent.abortRun()`. Created\n * fresh in `runAgent()`, aborted by `abortCurrentRun()`.\n */\n private _runAbortController: AbortController | null = null;\n\n /**\n * Tracks recursive `runAgent` depth so that the abort controller and\n * `agent.abortRun()` intercept are only set up / torn down at the\n * top-level call, not on follow-up recursive calls from\n * `processAgentResult`.\n */\n private _runDepth = 0;\n\n /**\n * Tracks the threadId of the most recent `connectAgent` call so we\n * can distinguish a fresh thread restore (different threadId than\n * last time — chat is rebuilding state from scratch, must clear\n * messages/state and ask the gateway for a full replay) from a\n * same-thread churn re-connect (effect-dep churn or transient\n * disconnect — local messages/state are still meaningful, must\n * preserve them and let the gateway resume from\n * `lastSeenEventId`).\n *\n * Tyler's bug fired because every `connectAgent` was treated as a\n * fresh restore, which forced the gateway to replay the full\n * thread history on every churn re-connect and amplified the\n * downstream churn into duplicate `cpki_event_id` rows in the\n * inspector and intermittent \"Message not found\" toasts.\n */\n private _lastConnectedThreadIdsByAgent = new Map<string, string | null>();\n private _anonymousAgentIds = new WeakMap<AbstractAgent, string>();\n private _nextAnonymousAgentId = 0;\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Abort the current run. Called by `CopilotKitCore.stopAgent()` to signal\n * that in-flight tool handlers should stop and `processAgentResult` should\n * not start a follow-up run.\n */\n abortCurrentRun(): void {\n this._runAbortController?.abort();\n }\n\n /**\n * Typed access to CopilotKitCore's internal (\"friend\") methods.\n * Centralises the single unavoidable cast so call-sites stay clean.\n */\n private get _internal(): CopilotKitCoreFriendsAccess {\n return this.core as unknown as CopilotKitCoreFriendsAccess;\n }\n\n /**\n * Return a stable restore-tracking key for the logical agent being\n * connected. Named agents share their last-thread marker across proxy\n * instances; anonymous agents fall back to object identity.\n */\n private getConnectRestoreKey(agent: AbstractAgent): string {\n if (agent.agentId) {\n return `agent:${agent.agentId}`;\n }\n\n const existing = this._anonymousAgentIds.get(agent);\n if (existing) {\n return existing;\n }\n\n const anonymousId = `anonymous:${this._nextAnonymousAgentId}`;\n this._nextAnonymousAgentId += 1;\n this._anonymousAgentIds.set(agent, anonymousId);\n return anonymousId;\n }\n\n /**\n * Get all tools as a readonly array\n */\n get tools(): Readonly<FrontendTool<any>[]> {\n return this._tools;\n }\n\n /**\n * Initialize with tools\n */\n initialize(tools: FrontendTool<any>[]): void {\n this._tools = tools;\n }\n\n /**\n * Add a tool to the registry\n */\n addTool<T extends Record<string, unknown> = Record<string, unknown>>(\n tool: FrontendTool<T>,\n ): void {\n // Check if a tool with the same name and agentId already exists\n const existingToolIndex = this._tools.findIndex(\n (t) => t.name === tool.name && t.agentId === tool.agentId,\n );\n\n if (existingToolIndex !== -1) {\n logger.warn(\n `Tool already exists: '${tool.name}' for agent '${tool.agentId || \"global\"}', skipping.`,\n );\n return;\n }\n\n this._tools.push(tool);\n }\n\n /**\n * Remove a tool by name and optionally by agentId\n */\n removeTool(id: string, agentId?: string): void {\n this._tools = this._tools.filter((tool) => {\n // Remove tool if both name and agentId match\n if (agentId !== undefined) {\n return !(tool.name === id && tool.agentId === agentId);\n }\n // If no agentId specified, only remove global tools with matching name\n return !(tool.name === id && !tool.agentId);\n });\n }\n\n /**\n * Get a tool by name and optionally by agentId.\n * If agentId is provided, it will first look for an agent-specific tool,\n * then fall back to a global tool with the same name.\n */\n getTool(params: CopilotKitCoreGetToolParams): FrontendTool<any> | undefined {\n const { toolName, agentId } = params;\n\n // If agentId is provided, first look for agent-specific tool\n if (agentId) {\n const agentTool = this._tools.find(\n (tool) => tool.name === toolName && tool.agentId === agentId,\n );\n if (agentTool) {\n return agentTool;\n }\n }\n\n // Fall back to global tool (no agentId)\n return this._tools.find((tool) => tool.name === toolName && !tool.agentId);\n }\n\n /**\n * Set all tools at once. Replaces existing tools.\n */\n setTools(tools: FrontendTool<any>[]): void {\n this._tools = [...tools];\n }\n\n /**\n * Connect an agent (establish initial connection)\n */\n async connectAgent({\n agent,\n }: CopilotKitCoreConnectAgentParams): Promise<RunAgentResult> {\n try {\n const incomingThreadId = agent.threadId ?? null;\n const restoreKey = this.getConnectRestoreKey(agent);\n const isFreshRestore =\n incomingThreadId !==\n (this._lastConnectedThreadIdsByAgent.get(restoreKey) ?? null);\n this._lastConnectedThreadIdsByAgent.set(restoreKey, incomingThreadId);\n\n // Detach any active run before connecting to avoid previous runs\n // interfering. This stays unconditional — both fresh restores and\n // churn re-connects need the previous socket torn down before a new\n // one can open.\n await agent.detachActiveRun();\n\n // State reset + replay-cursor clear are gated on actually moving\n // to a different thread. On same-thread churn, the local\n // messages/state are still the right view of the thread, and the\n // gateway can resume from `lastSeenEventId` instead of replaying\n // the full history.\n if (isFreshRestore) {\n agent.setMessages([]);\n agent.setState({});\n const cursorAware = agent as {\n clearReconnectCursor?: (id: string) => void;\n clearReplayCursor?: (id: string) => void;\n };\n if (incomingThreadId) {\n if (typeof cursorAware.clearReplayCursor === \"function\") {\n cursorAware.clearReplayCursor(incomingThreadId);\n }\n if (typeof cursorAware.clearReconnectCursor === \"function\") {\n cursorAware.clearReconnectCursor(incomingThreadId);\n }\n }\n }\n\n // Re-apply core headers (merged on top of the agent's own headers) so a\n // late header update is picked up without clobbering per-agent headers.\n this._internal.applyHeadersToAgent(agent);\n\n // Notify subscribers (e.g. the inspector) about the agent that is about\n // to run. Per-thread clones are not in the agent registry, so\n // onAgentsChanged never fires for them and they would otherwise be\n // invisible to subscribers.\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onAgentRunStarted?.({\n copilotkit: this.core,\n agent,\n }),\n \"Subscriber onAgentRunStarted error:\",\n );\n\n const runAgentResult = await agent.connectAgent(\n {\n forwardedProps: this._internal.properties,\n tools: this.buildFrontendTools(agent.agentId),\n context: this._internal.getContextForAgent(agent.agentId),\n },\n this.createAgentErrorSubscriber(agent),\n );\n\n return this.processAgentResult({\n runAgentResult,\n agent,\n executeFrontendTools: false,\n });\n } catch (error) {\n const connectError =\n error instanceof Error ? error : new Error(String(error));\n // Silently ignore abort errors (e.g. from navigation during active requests)\n const isAbort =\n connectError.name === \"AbortError\" ||\n connectError.message === \"Fetch is aborted\" ||\n connectError.message === \"signal is aborted without reason\" ||\n connectError.message === \"component unmounted\";\n if (!isAbort) {\n const context: Record<string, any> = {};\n if (agent.agentId) {\n context.agentId = agent.agentId;\n }\n await this._internal.emitError({\n error: connectError,\n code: CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED,\n context,\n });\n }\n return { result: undefined, newMessages: [] };\n }\n }\n\n /**\n * Run an agent\n */\n async runAgent({\n agent,\n forwardedProps,\n resume,\n runId,\n }: CopilotKitCoreRunAgentParams): Promise<RunAgentResult> {\n // Agent ID is guaranteed to be set by validateAndAssignAgentId\n if (agent.agentId) {\n void this._internal.suggestionEngine.clearSuggestions(agent.agentId);\n }\n\n // Re-apply core headers (merged on top of the agent's own headers) so a\n // late header update is picked up without clobbering per-agent headers.\n this._internal.applyHeadersToAgent(agent);\n\n // Detach any active run (e.g. a long-lived connectAgent pipeline) before\n // starting a new run. We await the detach to ensure the previous pipeline\n // has fully finalized — its activeRunCompletionPromise resolves once the\n // observable finalize block runs, which happens synchronously after the\n // takeUntil signal completes the chain. This prevents a race where the new\n // runAgent() overwrites activeRunDetach$ / activeRunCompletionPromise before\n // the old pipeline can clean up, causing dropped runs.\n //\n // Historical note: an earlier version used fire-and-forget (`void`) here\n // because awaiting caused a deadlock when connectAgent's\n // ConnectNotImplementedError cleanup was still in-flight. That deadlock\n // was resolved in @ag-ui/client ≥0.0.42 where the catchError path\n // (ConnectNotImplementedError → EMPTY) always runs the finalize block,\n // so the completion promise now resolves reliably.\n if (agent.detachActiveRun) {\n await agent.detachActiveRun();\n }\n\n // Set up abort controller and agent.abortRun() intercept only for the\n // top-level call. Recursive follow-up calls from processAgentResult\n // reuse the same controller.\n const isTopLevel = this._runDepth === 0;\n let originalAbortRun: (() => void) | undefined;\n\n if (isTopLevel) {\n this._runAbortController = new AbortController();\n\n // Intercept agent.abortRun() so that calling it directly (not via\n // stopAgent) also aborts in-flight tool execution and prevents\n // follow-up runs.\n const controller = this._runAbortController;\n originalAbortRun = agent.abortRun.bind(agent);\n agent.abortRun = () => {\n controller.abort();\n originalAbortRun!();\n };\n\n // Notify subscribers (e.g. the inspector) about the agent that is about\n // to run. Per-thread clones are not in the agent registry, so\n // onAgentsChanged never fires for them and they would otherwise be\n // invisible to subscribers. Fired once per top-level run; recursive\n // follow-up runs reuse the same instance and need no re-notification.\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onAgentRunStarted?.({\n copilotkit: this.core,\n agent,\n }),\n \"Subscriber onAgentRunStarted error:\",\n );\n }\n\n this._runDepth++;\n\n try {\n const runAgentResult = await agent.runAgent(\n {\n forwardedProps: {\n ...this._internal.properties,\n ...forwardedProps,\n },\n ...(resume !== undefined ? { resume } : {}),\n ...(runId !== undefined ? { runId } : {}),\n tools: this.buildFrontendTools(agent.agentId),\n context: this._internal.getContextForAgent(agent.agentId),\n },\n this.createAgentErrorSubscriber(agent),\n );\n return await this.processAgentResult({ runAgentResult, agent });\n } catch (error) {\n const runError =\n error instanceof Error ? error : new Error(String(error));\n const context: Record<string, any> = {};\n if (agent.agentId) {\n context.agentId = agent.agentId;\n }\n await this._internal.emitError({\n error: runError,\n code: CopilotKitCoreErrorCode.AGENT_RUN_FAILED,\n context,\n });\n return { result: undefined, newMessages: [] };\n } finally {\n this._runDepth--;\n // Restore original abortRun when the entire chain (including\n // recursive follow-ups) is complete.\n if (isTopLevel && originalAbortRun) {\n agent.abortRun = originalAbortRun;\n }\n }\n }\n\n /**\n * Process agent result and execute tools\n */\n private async processAgentResult({\n runAgentResult,\n agent,\n executeFrontendTools = true,\n }: {\n runAgentResult: RunAgentResult;\n agent: AbstractAgent;\n executeFrontendTools?: boolean;\n }): Promise<RunAgentResult> {\n const { newMessages } = runAgentResult;\n // Agent ID is guaranteed to be set by validateAndAssignAgentId\n const agentId = agent.agentId!;\n\n let needsFollowUp = false;\n\n if (executeFrontendTools) {\n for (const message of newMessages) {\n if (message.role === \"assistant\") {\n for (const toolCall of message.toolCalls || []) {\n if (\n newMessages.findIndex(\n (m) => m.role === \"tool\" && m.toolCallId === toolCall.id,\n ) === -1\n ) {\n const tool = this.getTool({\n toolName: toolCall.function.name,\n agentId: agent.agentId,\n });\n if (tool) {\n const followUp = await this.executeSpecificTool(\n tool,\n toolCall,\n message,\n agent,\n agentId,\n );\n if (followUp) {\n needsFollowUp = true;\n }\n } else {\n // Wildcard fallback for undefined tools\n const wildcardTool = this.getTool({\n toolName: \"*\",\n agentId: agent.agentId,\n });\n if (wildcardTool) {\n const followUp = await this.executeWildcardTool(\n wildcardTool,\n toolCall,\n message,\n agent,\n agentId,\n );\n if (followUp) {\n needsFollowUp = true;\n }\n }\n }\n }\n }\n }\n }\n }\n\n if (needsFollowUp && !this._runAbortController?.signal.aborted) {\n // Circuit breaker: bail out instead of recursing once the follow-up\n // chain exceeds an absolute safety cap. `_runDepth` reflects the current\n // depth of nested runAgent calls (it is incremented in runAgent and\n // decremented in its finally block), so a runaway loop — repeated\n // identical tool calls, a backend that keeps erroring after tool\n // results, reprocessed tool messages, etc. — eventually trips this\n // guard rather than looping forever and exhausting API quota.\n if (this._runDepth >= MAX_FOLLOW_UP_DEPTH) {\n logger.warn(\n `[CopilotKit] Follow-up depth limit (${MAX_FOLLOW_UP_DEPTH}) reached for agent \"${agentId}\". ` +\n `Stopping recursive follow-up runs to prevent an infinite loop. ` +\n `This usually indicates a tool that keeps requesting a follow-up (e.g. the LLM repeatedly ` +\n `calling the same tool). Consider setting \"followUp: false\" on the offending tool.`,\n );\n } else {\n // Yield to the framework scheduler before the follow-up run so that any\n // deferred state updates (e.g. React useEffect in useAgentContext) can\n // complete and write fresh values into the context store before runAgent\n // reads it. The base implementation is a no-op; React overrides this.\n await this._internal.waitForPendingFrameworkUpdates();\n return await this.runAgent({ agent });\n }\n }\n\n void this._internal.suggestionEngine.reloadSuggestions(agentId);\n\n return runAgentResult;\n }\n\n /**\n * Shared handler execution logic used by executeSpecificTool, executeWildcardTool, and runTool.\n * Handles arg parsing, subscriber notifications, handler invocation, result stringification,\n * and error handling.\n */\n private async executeToolHandler({\n tool,\n toolCall,\n agent,\n agentId,\n handlerArgs,\n toolType,\n messageId,\n }: {\n tool: FrontendTool<any>;\n toolCall: { id: string; function: { name: string; arguments: string } };\n agent: AbstractAgent;\n agentId: string;\n handlerArgs: unknown;\n toolType: string;\n messageId?: string;\n }): Promise<ExecuteToolHandlerResult> {\n let toolCallResult = \"\";\n let errorMessage: string | undefined;\n let isArgumentError = false;\n\n let parsedArgs: unknown;\n try {\n parsedArgs = parseToolArguments(handlerArgs, toolCall.function.name);\n } catch (error) {\n const parseError =\n error instanceof Error ? error : new Error(String(error));\n errorMessage = parseError.message;\n isArgumentError = true;\n await this._internal.emitError({\n error: parseError,\n code: CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED,\n context: {\n agentId,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n rawArguments: handlerArgs,\n toolType,\n ...(messageId ? { messageId } : {}),\n },\n });\n }\n\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onToolExecutionStart?.({\n copilotkit: this.core,\n toolCallId: toolCall.id,\n agentId,\n toolName: toolCall.function.name,\n args: parsedArgs,\n }),\n \"Subscriber onToolExecutionStart error:\",\n );\n\n if (!errorMessage) {\n try {\n const result = await tool.handler!(parsedArgs as any, {\n toolCall: toolCall as any,\n agent,\n signal: this._runAbortController?.signal,\n });\n if (result === undefined || result === null) {\n toolCallResult = \"\";\n } else if (typeof result === \"string\") {\n toolCallResult = result;\n } else {\n toolCallResult = JSON.stringify(result);\n }\n } catch (error) {\n const handlerError =\n error instanceof Error ? error : new Error(String(error));\n errorMessage = handlerError.message;\n await this._internal.emitError({\n error: handlerError,\n code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,\n context: {\n agentId,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n parsedArgs,\n toolType,\n ...(messageId ? { messageId } : {}),\n },\n });\n }\n }\n\n if (errorMessage) {\n toolCallResult = `Error: ${errorMessage}`;\n }\n\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onToolExecutionEnd?.({\n copilotkit: this.core,\n toolCallId: toolCall.id,\n agentId,\n toolName: toolCall.function.name,\n result: errorMessage ? \"\" : toolCallResult,\n error: errorMessage,\n }),\n \"Subscriber onToolExecutionEnd error:\",\n );\n\n return { result: toolCallResult, error: errorMessage, isArgumentError };\n }\n\n /**\n * Execute a specific tool\n */\n private async executeSpecificTool(\n tool: FrontendTool<any>,\n toolCall: ToolCall,\n message: Message,\n agent: AbstractAgent,\n agentId: string,\n ): Promise<boolean> {\n // Check if tool is constrained to a specific agent\n if (tool?.agentId && tool.agentId !== agent.agentId) {\n // Tool is not available for this agent, skip it\n return false;\n }\n\n let handlerResult: ExecuteToolHandlerResult = {\n result: \"\",\n error: undefined,\n isArgumentError: false,\n };\n\n if (tool?.handler) {\n handlerResult = await this.executeToolHandler({\n tool,\n toolCall,\n agent,\n agentId,\n handlerArgs: toolCall.function.arguments,\n toolType: \"specific\",\n messageId: message.id,\n });\n }\n\n {\n const messageIndex = agent.messages.findIndex((m) => m.id === message.id);\n if (messageIndex === -1) {\n // Parent message no longer in agent's messages (e.g. thread was switched\n // while the tool handler was still executing). Skip result insertion and\n // do not request a follow-up to avoid mutating the wrong thread.\n return false;\n }\n const toolMessage = {\n id: randomUUID(),\n role: \"tool\" as const,\n toolCallId: toolCall.id,\n content: handlerResult.result,\n };\n agent.messages.splice(messageIndex + 1, 0, toolMessage);\n\n if (!handlerResult.error && tool?.followUp !== false) {\n return true; // Needs follow-up\n }\n }\n\n return false;\n }\n\n /**\n * Execute a wildcard tool.\n * Wildcard tools receive args wrapped as `{toolName, args}`, which differs from\n * specific tools, so this method keeps its own arg-wrapping logic rather than\n * delegating to `executeToolHandler`.\n */\n private async executeWildcardTool(\n wildcardTool: FrontendTool<any>,\n toolCall: ToolCall,\n message: Message,\n agent: AbstractAgent,\n agentId: string,\n ): Promise<boolean> {\n // Check if wildcard tool is constrained to a specific agent\n if (wildcardTool?.agentId && wildcardTool.agentId !== agent.agentId) {\n // Wildcard tool is not available for this agent, skip it\n return false;\n }\n\n let toolCallResult = \"\";\n let errorMessage: string | undefined;\n\n if (wildcardTool?.handler) {\n let parsedArgs: unknown;\n try {\n parsedArgs = parseToolArguments(\n toolCall.function.arguments,\n toolCall.function.name,\n );\n } catch (error) {\n const parseError =\n error instanceof Error ? error : new Error(String(error));\n errorMessage = parseError.message;\n await this._internal.emitError({\n error: parseError,\n code: CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED,\n context: {\n agentId: agentId,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n rawArguments: toolCall.function.arguments,\n toolType: \"wildcard\",\n messageId: message.id,\n },\n });\n }\n\n const wildcardArgs = {\n toolName: toolCall.function.name,\n args: parsedArgs,\n };\n\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onToolExecutionStart?.({\n copilotkit: this.core,\n toolCallId: toolCall.id,\n agentId: agentId,\n toolName: toolCall.function.name,\n args: wildcardArgs,\n }),\n \"Subscriber onToolExecutionStart error:\",\n );\n\n if (!errorMessage) {\n try {\n const result = await wildcardTool.handler(wildcardArgs as any, {\n toolCall,\n agent,\n });\n if (result === undefined || result === null) {\n toolCallResult = \"\";\n } else if (typeof result === \"string\") {\n toolCallResult = result;\n } else {\n toolCallResult = JSON.stringify(result);\n }\n } catch (error) {\n const handlerError =\n error instanceof Error ? error : new Error(String(error));\n errorMessage = handlerError.message;\n await this._internal.emitError({\n error: handlerError,\n code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,\n context: {\n agentId: agentId,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n parsedArgs: wildcardArgs,\n toolType: \"wildcard\",\n messageId: message.id,\n },\n });\n }\n }\n\n if (errorMessage) {\n toolCallResult = `Error: ${errorMessage}`;\n }\n\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onToolExecutionEnd?.({\n copilotkit: this.core,\n toolCallId: toolCall.id,\n agentId: agentId,\n toolName: toolCall.function.name,\n result: errorMessage ? \"\" : toolCallResult,\n error: errorMessage,\n }),\n \"Subscriber onToolExecutionEnd error:\",\n );\n }\n\n {\n const messageIndex = agent.messages.findIndex((m) => m.id === message.id);\n if (messageIndex === -1) {\n // Parent message no longer in agent's messages (e.g. thread was switched\n // while the tool handler was still executing). Skip result insertion and\n // do not request a follow-up to avoid mutating the wrong thread.\n return false;\n }\n const toolMessage = {\n id: randomUUID(),\n role: \"tool\" as const,\n toolCallId: toolCall.id,\n content: toolCallResult,\n };\n agent.messages.splice(messageIndex + 1, 0, toolMessage);\n\n if (!errorMessage && wildcardTool?.followUp !== false) {\n return true; // Needs follow-up\n }\n }\n\n return false;\n }\n\n /**\n * Programmatically execute a registered frontend tool without going through an LLM turn.\n * The handler runs, render components show up in the UI, and both the tool call and\n * result messages are added to `agent.messages`.\n */\n async runTool(\n params: CopilotKitCoreRunToolParams,\n ): Promise<CopilotKitCoreRunToolResult> {\n const { name, agentId, parameters = {}, followUp = false } = params;\n\n // 1. Look up the tool\n const tool = this.getTool({ toolName: name, agentId });\n if (!tool) {\n const error = new Error(`Tool not found: ${name}`);\n await this._internal.emitError({\n error,\n code: CopilotKitCoreErrorCode.TOOL_NOT_FOUND,\n context: { toolName: name, agentId },\n });\n throw error;\n }\n\n // 2. Look up the agent\n const resolvedAgentId = agentId ?? \"default\";\n const agent = this._internal.getAgent(resolvedAgentId);\n if (!agent) {\n const error = new Error(`Agent not found: ${resolvedAgentId}`);\n await this._internal.emitError({\n error,\n code: CopilotKitCoreErrorCode.AGENT_NOT_FOUND,\n context: { agentId: resolvedAgentId },\n });\n throw error;\n }\n\n // 3. Create assistant message with tool call\n const toolCallId = randomUUID();\n const assistantToolCall = {\n id: toolCallId,\n type: \"function\" as const,\n function: {\n name,\n arguments: JSON.stringify(parameters),\n },\n };\n const assistantMessage: Message = {\n id: randomUUID(),\n role: \"assistant\",\n content: \"\",\n toolCalls: [assistantToolCall],\n };\n\n // 4. Push assistant message into agent's messages\n agent.messages.push(assistantMessage);\n\n // 5. Execute the tool handler (if it has one)\n let handlerResult: ExecuteToolHandlerResult = {\n result: \"\",\n error: undefined,\n isArgumentError: false,\n };\n\n if (tool.handler) {\n handlerResult = await this.executeToolHandler({\n tool,\n toolCall: assistantToolCall,\n agent,\n agentId: resolvedAgentId,\n handlerArgs: parameters,\n toolType: \"runTool\",\n });\n }\n\n // 6. Create and insert tool result message\n const toolResultMessage: Message = {\n id: randomUUID(),\n role: \"tool\",\n toolCallId,\n content: handlerResult.result,\n };\n\n const assistantIndex = agent.messages.findIndex(\n (m) => m.id === assistantMessage.id,\n );\n if (assistantIndex !== -1) {\n agent.messages.splice(assistantIndex + 1, 0, toolResultMessage);\n } else {\n // Fallback: push to end if assistant message was removed\n agent.messages.push(toolResultMessage);\n }\n\n // 7. Handle followUp (only if no error)\n if (!handlerResult.error && followUp !== false) {\n if (typeof followUp === \"string\" && followUp !== \"generate\") {\n // Custom text: add a user message first\n const userMessage: Message = {\n id: randomUUID(),\n role: \"user\",\n content: followUp,\n };\n agent.messages.push(userMessage);\n }\n // Yield to the framework scheduler so deferred state updates (e.g. React\n // useEffect in useAgentContext) can complete before the follow-up run reads\n // the context store. Mirrors the same yield in processAgentResult.\n await this._internal.waitForPendingFrameworkUpdates();\n // Trigger agent run for both \"generate\" and custom text\n await this.runAgent({ agent });\n }\n\n // 8. Return result\n return {\n toolCallId,\n result: handlerResult.result,\n error: handlerResult.error,\n };\n }\n\n /**\n * Build frontend tools for an agent\n */\n buildFrontendTools(agentId?: string): Tool[] {\n return this._tools\n .filter(\n (tool) =>\n tool.available !== false &&\n (tool.available as boolean | string | undefined) !== \"disabled\" &&\n (!tool.agentId || tool.agentId === agentId),\n )\n .map((tool) => ({\n name: tool.name,\n description: tool.description ?? \"\",\n parameters: createToolSchema(tool),\n }));\n }\n\n /**\n * Create an agent error subscriber\n */\n private createAgentErrorSubscriber(agent: AbstractAgent): AgentSubscriber {\n const emitAgentError = async (\n error: Error,\n code: CopilotKitCoreErrorCode,\n extraContext: Record<string, any> = {},\n ) => {\n const context: Record<string, any> = { ...extraContext };\n if (agent.agentId) {\n context.agentId = agent.agentId;\n }\n await this._internal.emitError({\n error,\n code,\n context,\n });\n };\n\n return {\n onRunFailed: async ({ error }: { error: Error }) => {\n const code =\n error instanceof AgentThreadLockedError\n ? CopilotKitCoreErrorCode.AGENT_THREAD_LOCKED\n : CopilotKitCoreErrorCode.AGENT_RUN_FAILED_EVENT;\n await emitAgentError(error, code, {\n source: \"onRunFailed\",\n });\n },\n onRunErrorEvent: async ({ event }) => {\n // A user-initiated stop (stopAgent / agent.abortRun) makes the agent\n // emit a terminal RUN_ERROR — often code \"abort\" — as its cancellation\n // signal. That is expected, not a failure: surfacing it would pop an\n // error banner on Stop (#5966, follow-up to #5812). Mirror the\n // local-abort suppression on the runAgent/connectAgent paths and skip\n // it. Prefer the abort controller (the client's own record that it\n // initiated the stop) over the agent-supplied `code`, which is not\n // standardized across agents.\n const runWasAborted = this._runAbortController?.signal.aborted === true;\n if (runWasAborted || event?.code === \"abort\") {\n return;\n }\n\n const eventError =\n event?.rawEvent instanceof Error\n ? event.rawEvent\n : event?.rawEvent?.error instanceof Error\n ? event.rawEvent.error\n : undefined;\n\n const errorMessage =\n typeof event?.rawEvent?.error === \"string\"\n ? event.rawEvent.error\n : (event?.message ?? \"Agent run error\");\n\n const rawError = eventError ?? new Error(errorMessage);\n\n if (event?.code && !(rawError as any).code) {\n (rawError as any).code = event.code;\n }\n\n await emitAgentError(\n rawError,\n CopilotKitCoreErrorCode.AGENT_RUN_ERROR_EVENT,\n {\n source: \"onRunErrorEvent\",\n event,\n runtimeErrorCode: event?.code,\n },\n );\n },\n };\n }\n}\n\n/**\n * Empty tool schema constant\n */\nconst EMPTY_TOOL_SCHEMA = {\n type: \"object\",\n properties: {},\n} as const satisfies Record<string, unknown>;\n\n/**\n * Create a JSON schema from a tool's parameters\n */\nfunction createToolSchema(tool: FrontendTool<any>): Record<string, unknown> {\n if (!tool.parameters) {\n return { ...EMPTY_TOOL_SCHEMA };\n }\n\n const rawSchema = schemaToJsonSchema(tool.parameters, {\n zodToJsonSchema: (schema, options) =>\n zodToJsonSchema(\n schema as Parameters<typeof zodToJsonSchema>[0],\n options as Parameters<typeof zodToJsonSchema>[1],\n ),\n });\n\n if (!rawSchema || typeof rawSchema !== \"object\") {\n return { ...EMPTY_TOOL_SCHEMA };\n }\n\n const { $schema: _$schema, ...schema } = rawSchema as Record<string, unknown>;\n\n if (typeof schema.type !== \"string\") {\n schema.type = \"object\";\n }\n if (typeof schema.properties !== \"object\" || schema.properties === null) {\n schema.properties = {};\n }\n\n stripAdditionalProperties(schema);\n return schema;\n}\n\nfunction stripAdditionalProperties(schema: unknown): void {\n if (!schema || typeof schema !== \"object\") {\n return;\n }\n\n if (Array.isArray(schema)) {\n schema.forEach(stripAdditionalProperties);\n return;\n }\n\n const record = schema as Record<string, unknown>;\n\n if (record.additionalProperties !== undefined) {\n delete record.additionalProperties;\n }\n\n for (const value of Object.values(record)) {\n stripAdditionalProperties(value);\n }\n}\n\n/**\n * Ensures parsed tool arguments are a plain object.\n * Throws for non-object values so the caller's catch block can emit\n * a structured TOOL_ARGUMENT_PARSE_FAILED error.\n *\n * @internal Exported for testing only.\n */\nexport function ensureObjectArgs(\n parsed: unknown,\n toolName: string,\n): Record<string, unknown> {\n if (typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n throw new Error(\n `Tool arguments for ${toolName} parsed to non-object (${typeof parsed})`,\n );\n}\n\n/**\n * Parses raw tool call arguments into a validated object.\n *\n * Some LLM providers (e.g. @ai-sdk/openai-compatible) may send empty string \"\",\n * null, or undefined instead of \"{}\". This function normalises those cases to an\n * empty object so callers don't crash on JSON.parse(\"\").\n *\n * A debug-level warning is emitted when the fallback triggers so silent coercion\n * is observable in logs.\n *\n * @internal Exported for testing only.\n */\nexport function parseToolArguments(\n rawArgs: unknown,\n toolName: string,\n): Record<string, unknown> {\n if (rawArgs === \"\" || rawArgs === null || rawArgs === undefined) {\n logger.debug(\n `[parseToolArguments] Tool \"${toolName}\" received empty/null/undefined arguments — defaulting to {}`,\n );\n return {};\n }\n const parsed = typeof rawArgs === \"string\" ? JSON.parse(rawArgs) : rawArgs;\n return ensureObjectArgs(parsed, toolName);\n}\n","import type {\n AbstractAgent,\n Message,\n State,\n RunAgentInput,\n StateSnapshotEvent,\n StateDeltaEvent,\n MessagesSnapshotEvent,\n} from \"@ag-ui/client\";\nimport { randomUUID } from \"@ag-ui/client\";\nimport type { CopilotKitCore } from \"./core\";\n\n/**\n * Manages state and message tracking by run for CopilotKitCore.\n * Tracks agent state snapshots and message-to-run associations.\n */\nexport class StateManager {\n // State tracking: agentId -> threadId -> runId -> state\n private stateByRun: Map<string, Map<string, Map<string, State>>> = new Map();\n\n // Message tracking: agentId -> threadId -> messageId -> runId\n private messageToRun: Map<string, Map<string, Map<string, string>>> =\n new Map();\n\n // Active run tracking: `agentId:threadId` -> runId (used when messages arrive without input)\n private activeRun: Map<string, string> = new Map();\n\n // Agent subscriptions for cleanup\n private agentSubscriptions: Map<string, () => void> = new Map();\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Initialize state tracking for an agent\n */\n initialize(): void {\n // Will be called when CopilotKitCore is initialized\n }\n\n /**\n * Subscribe to an agent's events to track state and messages.\n */\n subscribeToAgent(agent: AbstractAgent): void {\n if (!agent.agentId) {\n return; // Skip agents without IDs\n }\n\n const agentId = agent.agentId;\n\n // Unsubscribe existing subscription for this agent only\n const existingUnsubscribe = this.agentSubscriptions.get(agentId);\n if (existingUnsubscribe) {\n existingUnsubscribe();\n this.agentSubscriptions.delete(agentId);\n }\n\n // Subscribe to agent events.\n //\n // Two invariants this subscription must uphold:\n //\n // 1. Revocation: the ag-ui pipeline captures `o = [...agent.subscribers]` at\n // runAgent() start. If this subscription is replaced by a newer one before\n // the pipeline finishes, the old pipeline may still call these callbacks\n // with the old input.runId. `revoked = true` turns them into no-ops once\n // the replacement subscription is in place.\n //\n // 2. Run isolation within one subscription: in tests (and edge cases), a new\n // run's events can arrive through the same subscription before the new\n // pipeline is set up. Concretely: the test emits RUN_STARTED for run2\n // before copilotkit.runAgent() has had a chance to set up the new\n // pipeline. At that point S1 is still active and sees run2's events with\n // input1.runId. To prevent both runs from sharing the same runId key, we\n // detect the \"seen RUN_FINISHED, then RUN_STARTED again\" pattern and\n // generate a fresh runId for the second logical run.\n let revoked = false;\n let subRunId: string | undefined; // runId assigned to the current logical run\n let runFinished = false; // true after RUN_FINISHED, reset on next RUN_STARTED\n\n const effectiveInput = (input: RunAgentInput): RunAgentInput => ({\n ...input,\n runId: subRunId ?? input.runId,\n });\n\n const { unsubscribe } = agent.subscribe({\n onRunStartedEvent: ({ input, state }) => {\n if (revoked) return;\n if (runFinished && input.runId === subRunId) {\n // A new logical run's events are arriving through this same (old)\n // subscription. This happens when the test emits events before\n // copilotkit.runAgent() has had a chance to set up the new pipeline:\n // the old pipeline reuses input1.runId for all events, so\n // input.runId equals the previous run's runId. Generate a fresh\n // runId so the new run's state doesn't collide with the old one.\n subRunId = randomUUID();\n } else {\n subRunId = input.runId;\n }\n runFinished = false;\n this.handleRunStarted(agent, effectiveInput(input), state);\n },\n onRunFinishedEvent: ({ input, state }) => {\n if (revoked) return;\n runFinished = true;\n this.handleRunFinished(agent, effectiveInput(input), state);\n },\n // A run error terminates the run — treat identically to finished for cleanup\n onRunErrorEvent: ({ input, state }) => {\n if (revoked) return;\n runFinished = true;\n this.handleRunFinished(agent, effectiveInput(input), state);\n },\n onStateSnapshotEvent: ({ event, input, state }) => {\n if (revoked) return;\n this.handleStateSnapshot(agent, event, effectiveInput(input), state);\n },\n onStateDeltaEvent: ({ event, input, state }) => {\n if (revoked) return;\n this.handleStateDelta(agent, event, effectiveInput(input), state);\n },\n onMessagesSnapshotEvent: ({ event, input, messages }) => {\n if (revoked) return;\n this.handleMessagesSnapshot(\n agent,\n event,\n effectiveInput(input),\n messages,\n );\n },\n onNewMessage: ({ message, input }) => {\n if (revoked) return;\n this.handleNewMessage(\n agent,\n message,\n input ? effectiveInput(input) : undefined,\n );\n },\n });\n\n this.agentSubscriptions.set(agentId, () => {\n revoked = true;\n unsubscribe();\n });\n }\n\n /**\n * Unsubscribe an agent's subscription.\n */\n unsubscribeFromAgent(agentId: string): void {\n const unsubscribe = this.agentSubscriptions.get(agentId);\n if (unsubscribe) {\n unsubscribe();\n this.agentSubscriptions.delete(agentId);\n }\n }\n\n /**\n * Get state for a specific run\n * Returns a deep copy to prevent external mutations\n */\n getStateByRun(\n agentId: string,\n threadId: string,\n runId: string,\n ): State | undefined {\n const state = this.stateByRun.get(agentId)?.get(threadId)?.get(runId);\n if (!state) return undefined;\n // Return a deep copy to prevent mutations\n return JSON.parse(JSON.stringify(state));\n }\n\n /**\n * Get runId associated with a message\n */\n getRunIdForMessage(\n agentId: string,\n threadId: string,\n messageId: string,\n ): string | undefined {\n return this.messageToRun.get(agentId)?.get(threadId)?.get(messageId);\n }\n\n /**\n * Get all states for an agent's thread\n */\n getStatesForThread(agentId: string, threadId: string): Map<string, State> {\n return this.stateByRun.get(agentId)?.get(threadId) ?? new Map();\n }\n\n /**\n * Get all run IDs for an agent's thread\n */\n getRunIdsForThread(agentId: string, threadId: string): string[] {\n const threadStates = this.stateByRun.get(agentId)?.get(threadId);\n return threadStates ? Array.from(threadStates.keys()) : [];\n }\n\n /**\n * Handle run started event\n */\n private handleRunStarted(\n agent: AbstractAgent,\n input: RunAgentInput,\n state: State,\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n this.activeRun.set(`${agent.agentId}:${threadId}`, runId);\n // Only persist state when it carries real data. An empty {} from an\n // initial-state-less run would cause getStateByRun to return {} instead\n // of undefined, breaking renderers that rely on undefined to mean \"no\n // state snapshot received yet\".\n if (state && Object.keys(state).length > 0) {\n this.saveState(agent.agentId, threadId, runId, state);\n }\n }\n\n /**\n * Handle run finished event\n */\n private handleRunFinished(\n agent: AbstractAgent,\n input: RunAgentInput,\n state: State,\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n this.activeRun.delete(`${agent.agentId}:${threadId}`);\n if (state && Object.keys(state).length > 0) {\n this.saveState(agent.agentId, threadId, runId, state);\n }\n }\n\n /**\n * Handle state snapshot event\n */\n private handleStateSnapshot(\n agent: AbstractAgent,\n event: StateSnapshotEvent,\n input: RunAgentInput,\n state: State,\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n // Merge snapshot into current state\n const mergedState = { ...state, ...event.snapshot };\n this.saveState(agent.agentId, threadId, runId, mergedState);\n }\n\n /**\n * Handle state delta event\n */\n private handleStateDelta(\n agent: AbstractAgent,\n event: StateDeltaEvent,\n input: RunAgentInput,\n state: State,\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n // State is already updated by the agent, just save it\n this.saveState(agent.agentId, threadId, runId, state);\n }\n\n /**\n * Handle messages snapshot event\n */\n private handleMessagesSnapshot(\n agent: AbstractAgent,\n event: MessagesSnapshotEvent,\n input: RunAgentInput,\n messages: readonly Message[],\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n\n // Associate all messages in the snapshot with this run\n for (const message of event.messages) {\n this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);\n }\n }\n\n /**\n * Handle new message event\n */\n private handleNewMessage(\n agent: AbstractAgent,\n message: Message,\n input?: RunAgentInput,\n ): void {\n if (!agent.agentId) return;\n\n if (!input) {\n // ag-ui calls addMessage() without input, so input is undefined here.\n // Fall back to the currently-active run for this agent's thread.\n const threadId = agent.threadId ?? \"\";\n const runId = this.activeRun.get(`${agent.agentId}:${threadId}`);\n if (runId) {\n this.associateMessageWithRun(\n agent.agentId,\n threadId,\n message.id,\n runId,\n );\n }\n return;\n }\n\n const { threadId, runId } = input;\n this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);\n }\n\n /**\n * Save state for a specific run\n */\n private saveState(\n agentId: string,\n threadId: string,\n runId: string,\n state: State,\n ): void {\n // Ensure nested maps exist\n if (!this.stateByRun.has(agentId)) {\n this.stateByRun.set(agentId, new Map());\n }\n const agentStates = this.stateByRun.get(agentId)!;\n\n if (!agentStates.has(threadId)) {\n agentStates.set(threadId, new Map());\n }\n const threadStates = agentStates.get(threadId)!;\n\n // Deep copy the state to prevent mutations\n threadStates.set(runId, JSON.parse(JSON.stringify(state)));\n }\n\n /**\n * Associate a message with a run\n */\n private associateMessageWithRun(\n agentId: string,\n threadId: string,\n messageId: string,\n runId: string,\n ): void {\n // Ensure nested maps exist\n if (!this.messageToRun.has(agentId)) {\n this.messageToRun.set(agentId, new Map());\n }\n const agentMessages = this.messageToRun.get(agentId)!;\n\n if (!agentMessages.has(threadId)) {\n agentMessages.set(threadId, new Map());\n }\n const threadMessages = agentMessages.get(threadId)!;\n\n threadMessages.set(messageId, runId);\n }\n\n /**\n * Clear all state for an agent\n */\n clearAgentState(agentId: string): void {\n this.stateByRun.delete(agentId);\n this.messageToRun.delete(agentId);\n }\n\n /**\n * Clear all state for a thread\n */\n clearThreadState(agentId: string, threadId: string): void {\n this.stateByRun.get(agentId)?.delete(threadId);\n this.messageToRun.get(agentId)?.delete(threadId);\n }\n}\n","import { type ɵThreadStore } from \"../threads\";\nimport type { CopilotKitCore } from \"./core\";\nimport { CopilotKitCoreFriendsAccess, CopilotKitCoreSubscriber } from \"./core\";\n\nexport class ThreadStoreRegistry {\n private _stores: Record<string, ɵThreadStore> = {};\n // Cached frozen snapshot of `_stores`. Invalidated to `null` on every\n // `register`/`unregister` so the next `getAll()` rebuilds it. Stable\n // references between mutations matter for `useSyncExternalStore` consumers\n // that compare snapshot identity to decide whether to re-render.\n private _snapshot: Readonly<Record<string, ɵThreadStore>> | null = null;\n\n constructor(private core: CopilotKitCore) {}\n\n register(agentId: string, store: ɵThreadStore): void {\n if (agentId in this._stores) {\n // Capture the previous store before deleting it. `notifyUnregistered`\n // dispatches via `Promise.all` and returns control to this synchronous\n // body before async subscribers resume — by then `this._stores[agentId]`\n // already holds the new store, so the previous store must be forwarded\n // explicitly via the payload. Subscribers MUST NOT call\n // `registry.get(agentId)` from `onThreadStoreUnregistered` to recover\n // the previous store; use the `prevStore` field on the payload instead.\n const prevStore = this._stores[agentId]!;\n delete this._stores[agentId];\n this._snapshot = null;\n this.notifyUnregistered(agentId, prevStore).catch((err) => {\n console.error(\"ThreadStoreRegistry notifyUnregistered failed:\", err);\n });\n }\n this._stores[agentId] = store;\n this._snapshot = null;\n this.notifyRegistered(agentId, store).catch((err) => {\n console.error(\"ThreadStoreRegistry notifyRegistered failed:\", err);\n });\n }\n\n unregister(agentId: string): void {\n if (!(agentId in this._stores)) return;\n // Capture before delete for the same reason as `register()` above.\n const prevStore = this._stores[agentId]!;\n delete this._stores[agentId];\n this._snapshot = null;\n this.notifyUnregistered(agentId, prevStore).catch((err) => {\n console.error(\"ThreadStoreRegistry notifyUnregistered failed:\", err);\n });\n }\n\n get(agentId: string): ɵThreadStore | undefined {\n return this._stores[agentId];\n }\n\n getAll(): Readonly<Record<string, ɵThreadStore>> {\n // Cache a frozen snapshot so consecutive calls return the same reference.\n // `useSyncExternalStore` and other identity-comparing consumers depend on\n // this stability to skip re-renders when nothing has actually changed.\n // `Object.freeze` makes the `Readonly<>` claim true at runtime, not just\n // at the type level — attempts to mutate the snapshot throw in strict\n // mode and are silently ignored in sloppy mode (rather than corrupting\n // the registry). Invalidated to `null` by `register`/`unregister`.\n if (this._snapshot === null) {\n this._snapshot = Object.freeze({ ...this._stores });\n }\n return this._snapshot;\n }\n\n private async notifyRegistered(\n agentId: string,\n store: ɵThreadStore,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber: CopilotKitCoreSubscriber) =>\n subscriber.onThreadStoreRegistered?.({\n copilotkit: this.core,\n agentId,\n store,\n }),\n \"Subscriber onThreadStoreRegistered error:\",\n );\n }\n\n private async notifyUnregistered(\n agentId: string,\n prevStore: ɵThreadStore,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber: CopilotKitCoreSubscriber) =>\n subscriber.onThreadStoreUnregistered?.({\n copilotkit: this.core,\n agentId,\n prevStore,\n }),\n \"Subscriber onThreadStoreUnregistered error:\",\n );\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n BehaviorSubject,\n Observable,\n OperatorFunction,\n Subject,\n Subscription,\n asapScheduler,\n} from \"rxjs\";\nimport { distinctUntilChanged, filter, map, observeOn } from \"rxjs/operators\";\n\n/**\n * The minimal action shape used by this micro-redux implementation.\n */\nexport interface AnyAction {\n type: string;\n}\n\n/**\n * A typed action creator function with a `type` literal and runtime matcher.\n */\nexport type ActionCreator<\n Type extends string,\n Args extends unknown[] = unknown[],\n Action extends AnyAction & { type: Type } = { type: Type },\n> = ((...args: Args) => Action) & {\n type: Type;\n match(action: AnyAction): action is Action;\n};\n\n/**\n * Extracts the action type produced by an action creator.\n */\nexport type ActionFromCreator<T> = T extends (...args: any[]) => infer A\n ? A\n : never;\n\n/**\n * Extracts a union of actions produced by a tuple/array of action creators.\n */\nexport type ActionFromCreators<\n Creators extends readonly ActionCreator<string, any[], any>[],\n> = ActionFromCreator<Creators[number]>;\n\n/**\n * A reducer transforms state in response to actions.\n */\nexport type Reducer<State, Action extends AnyAction = AnyAction> = (\n state: State | undefined,\n action: Action,\n) => State;\n\n/**\n * A selector derives a value from state.\n */\nexport type Selector<State, Result> = (state: State) => Result;\n\n/**\n * Marker config for action creators that accept no payload.\n */\nexport interface EmptyActionConfig {\n readonly kind: \"empty\";\n}\n\nconst PROPS_MARKER: unique symbol = Symbol(\"props_marker\");\n\n/**\n * Marker config for action creators that require payload props.\n */\nexport interface PropsActionConfig<Props extends Record<string, unknown>> {\n readonly kind: \"props\";\n readonly [PROPS_MARKER]?: Props;\n}\n\n/**\n * Supported action creator config node in an action group.\n */\nexport type ActionConfig =\n | EmptyActionConfig\n | PropsActionConfig<Record<string, unknown>>;\n\n/**\n * Shape of an action group declaration object.\n */\nexport type ActionGroupConfig = Record<string, ActionConfig>;\n\n/**\n * Maps an action group declaration to a strongly typed action-creator object.\n */\nexport type ActionGroupResult<\n Source extends string,\n Config extends ActionGroupConfig,\n> = {\n [K in keyof Config & string]: Config[K] extends PropsActionConfig<infer P>\n ? ActionCreator<`[${Source}] ${K}`, [P], { type: `[${Source}] ${K}` } & P>\n : ActionCreator<`[${Source}] ${K}`, [], { type: `[${Source}] ${K}` }>;\n};\n\ninterface OnReducerEntry<\n State,\n Action extends AnyAction = AnyAction,\n Creators extends readonly ActionCreator<string, any[], any>[] =\n readonly ActionCreator<string, any[], any>[],\n> {\n creators: Creators;\n reducer: (state: State, action: Action) => State;\n}\n\ntype ActionFromOnReducerEntry<TEntry> =\n TEntry extends OnReducerEntry<any, infer TAction, any> ? TAction : never;\n\n/**\n * Effect contract for streams that emit actions to dispatch.\n */\nexport interface DispatchingEffect<\n State,\n InputAction extends AnyAction = AnyAction,\n OutputAction extends AnyAction = AnyAction,\n> {\n run: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<OutputAction>;\n dispatch: true;\n}\n\n/**\n * Effect contract for side-effect-only streams whose emissions are ignored.\n */\nexport interface NonDispatchingEffect<\n State,\n InputAction extends AnyAction = AnyAction,\n> {\n run: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<unknown>;\n dispatch: false;\n}\n\n/**\n * Union of supported effect shapes.\n */\nexport type Effect<\n State,\n InputAction extends AnyAction = AnyAction,\n OutputAction extends AnyAction = AnyAction,\n> =\n | DispatchingEffect<State, InputAction, OutputAction>\n | NonDispatchingEffect<State, InputAction>;\n\n/**\n * Lifecycle actions dispatched by the store.\n */\nexport type StoreLifecycleAction =\n | { type: \"@@micro-redux/init\" }\n | { type: \"@@micro-redux/stop\" };\n\n/**\n * Options for a dispatching effect.\n */\nexport interface DispatchingEffectOptions {\n dispatch?: true;\n}\n\n/**\n * Options for a non-dispatching effect.\n */\nexport interface NonDispatchingEffectOptions {\n dispatch: false;\n}\n\nconst INTERNAL_ACTION_TYPES = {\n boot: \"@@micro-redux/boot\",\n init: \"@@micro-redux/init\",\n stop: \"@@micro-redux/stop\",\n} as const;\n\nconst INTERNAL_BOOT_ACTION: AnyAction = { type: INTERNAL_ACTION_TYPES.boot };\n\n/**\n * Builds a typed action creator from a type string and payload factory.\n */\nfunction createTypedActionCreator<\n Type extends string,\n Args extends unknown[],\n Payload extends Record<string, unknown>,\n>(\n type: Type,\n factory: (...args: Args) => Payload,\n): ActionCreator<Type, Args, { type: Type } & Payload> {\n const creator = ((...args: Args) => ({\n ...factory(...args),\n type,\n })) as ActionCreator<Type, Args, { type: Type } & Payload>;\n\n creator.type = type;\n creator.match = (action: AnyAction): action is { type: Type } & Payload =>\n action.type === type;\n\n return creator;\n}\n\n/**\n * Declares a payload-based action config for `createActionGroup`.\n *\n * @example\n * ```ts\n * const actions = createActionGroup(\"User\", {\n * loaded: props<{ id: string }>(),\n * });\n * ```\n */\nexport function props<\n Props extends Record<string, unknown>,\n>(): PropsActionConfig<Props> {\n return { kind: \"props\" };\n}\n\n/**\n * Declares a no-payload action config for `createActionGroup`.\n *\n * @example\n * ```ts\n * const actions = createActionGroup(\"User\", {\n * reset: empty(),\n * });\n * ```\n */\nexport function empty(): EmptyActionConfig {\n return { kind: \"empty\" };\n}\n\n/**\n * Creates a namespaced group of typed action creators.\n *\n * Action types are formatted as: `[Source] actionName`.\n */\nexport function createActionGroup<\n const Source extends string,\n const Config extends ActionGroupConfig,\n>(source: Source, config: Config): ActionGroupResult<Source, Config> {\n const group = {} as ActionGroupResult<Source, Config>;\n\n for (const eventName of Object.keys(config) as Array<keyof Config & string>) {\n const eventConfig = config[eventName];\n if (!eventConfig) {\n continue;\n }\n\n const actionType = `[${source}] ${eventName}` as const;\n\n if (eventConfig.kind === \"props\") {\n group[eventName] = createTypedActionCreator(\n actionType,\n (payload: Record<string, unknown>) => ({ ...payload }),\n ) as ActionGroupResult<Source, Config>[typeof eventName];\n continue;\n }\n\n group[eventName] = createTypedActionCreator(\n actionType,\n () => ({}),\n ) as ActionGroupResult<Source, Config>[typeof eventName];\n }\n\n return group;\n}\n\n/**\n * Registers one reducer handler for one or more action creators.\n *\n * @throws Error when called without at least one action creator and reducer.\n */\nexport function on<\n State,\n const Creators extends readonly ActionCreator<string, any[], any>[],\n Action extends ActionFromCreators<Creators>,\n>(\n ...args: [\n ...creators: Creators,\n reducer: (state: State, action: Action) => State,\n ]\n): OnReducerEntry<State, Action, Creators> {\n if (args.length < 2) {\n throw new Error(\"on requires at least one action creator and one reducer\");\n }\n\n const reducer = args[args.length - 1] as (\n state: State,\n action: Action,\n ) => State;\n const creators = args.slice(0, -1) as unknown as Creators;\n\n return {\n creators,\n reducer,\n };\n}\n\n/**\n * Creates a reducer from an initial state and `on(...)` handler entries.\n *\n * Unknown action types return the current state unchanged.\n */\nexport function createReducer<\n State,\n const Entries extends readonly OnReducerEntry<any, any, any>[],\n>(\n initialState: State,\n ...entries: Entries\n): Reducer<State, ActionFromOnReducerEntry<Entries[number]>> {\n type ReducerAction = ActionFromOnReducerEntry<Entries[number]>;\n\n const reducerMap = new Map<\n string,\n Array<(state: State, action: ReducerAction) => State>\n >();\n\n for (const entry of entries) {\n for (const creator of entry.creators) {\n const handlers = reducerMap.get(creator.type) ?? [];\n handlers.push(\n entry.reducer as unknown as (\n state: State,\n action: ReducerAction,\n ) => State,\n );\n reducerMap.set(creator.type, handlers);\n }\n }\n\n return (state: State | undefined, action: ReducerAction): State => {\n const currentState = state ?? initialState;\n const handlers = reducerMap.get(action.type);\n\n if (!handlers || handlers.length === 0) {\n return currentState;\n }\n\n let nextState = currentState;\n for (const handler of handlers) {\n nextState = handler(nextState, action);\n }\n return nextState;\n };\n}\n\n/**\n * Creates a memoized selector from a single projector.\n */\nexport function createSelector<State, Result>(\n projector: (state: State) => Result,\n): Selector<State, Result>;\n\n/**\n * Creates a memoized selector from input selectors and a projector.\n *\n * Memoization uses one-entry caching over the latest input selector values.\n */\nexport function createSelector<\n State,\n const Selectors extends readonly Selector<State, unknown>[],\n Result,\n>(\n ...args: [\n ...selectors: Selectors,\n projector: (\n ...inputs: { [K in keyof Selectors]: ReturnType<Selectors[K]> }\n ) => Result,\n ]\n): Selector<State, Result>;\n\n/**\n * Creates a selector that caches and reuses the last computed result\n * when all input references are unchanged.\n */\nexport function createSelector<State, Result>(\n ...args:\n | [(state: State) => Result]\n | [\n ...selectors: Array<Selector<State, unknown>>,\n projector: (...inputs: unknown[]) => Result,\n ]\n): Selector<State, Result> {\n if (args.length === 1) {\n const projector = args[0] as (state: State) => Result;\n let hasCached = false;\n let lastState: State | undefined;\n let lastResult: Result;\n\n return (state: State): Result => {\n if (hasCached && state === lastState) {\n return lastResult;\n }\n\n lastState = state;\n lastResult = projector(state);\n hasCached = true;\n return lastResult;\n };\n }\n\n const projector = args[args.length - 1] as (...inputs: unknown[]) => Result;\n const selectors = args.slice(0, -1) as Array<Selector<State, unknown>>;\n\n let hasCached = false;\n let lastInputs: unknown[] = [];\n let lastResult: Result;\n\n return (state: State): Result => {\n const inputs = selectors.map((selector) => selector(state));\n\n if (\n hasCached &&\n inputs.length === lastInputs.length &&\n inputs.every((value, index) => value === lastInputs[index])\n ) {\n return lastResult;\n }\n\n lastInputs = inputs;\n lastResult = projector(...inputs);\n hasCached = true;\n return lastResult;\n };\n}\n\n/**\n * RxJS operator that maps state emissions through a selector and suppresses\n * unchanged projected values via reference equality.\n */\nexport function select<State, Result>(\n selector: Selector<State, Result>,\n): OperatorFunction<State, Result> {\n return (source$) => source$.pipe(map(selector), distinctUntilChanged());\n}\n\n/**\n * RxJS operator that filters an action stream by action creators and narrows\n * the output action type to the matched creator union.\n *\n * @throws Error when called without at least one action creator.\n */\nexport function ofType<\n const Creators extends readonly ActionCreator<string, any[], AnyAction>[],\n>(\n ...creators: Creators\n): OperatorFunction<AnyAction, ActionFromCreators<Creators>> {\n if (creators.length === 0) {\n throw new Error(\"ofType requires at least one action creator\");\n }\n\n const actionTypes = new Set(creators.map((creator) => creator.type));\n return (source$) => {\n return source$.pipe(\n filter((action: AnyAction): action is ActionFromCreators<Creators> => {\n return actionTypes.has(action.type);\n }),\n );\n };\n}\n\n/**\n * Creates a dispatching effect. Emitted actions are automatically dispatched.\n */\nexport function createEffect<\n State,\n InputAction extends AnyAction,\n OutputAction extends AnyAction,\n>(\n factory: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<OutputAction>,\n options?: DispatchingEffectOptions,\n): DispatchingEffect<State, InputAction, OutputAction>;\n\n/**\n * Creates a non-dispatching effect. Emitted values are ignored.\n */\nexport function createEffect<State, InputAction extends AnyAction>(\n factory: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<unknown>,\n options: NonDispatchingEffectOptions,\n): NonDispatchingEffect<State, InputAction>;\n\n/**\n * Creates an effect descriptor consumed by `createStore`.\n */\nexport function createEffect<\n State,\n InputAction extends AnyAction,\n OutputAction extends AnyAction,\n>(\n factory: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<OutputAction>,\n options: DispatchingEffectOptions | NonDispatchingEffectOptions = {},\n): Effect<State, InputAction, OutputAction> {\n if (options.dispatch === false) {\n return {\n run: factory,\n dispatch: false,\n };\n }\n\n return {\n run: factory,\n dispatch: true,\n };\n}\n\n/**\n * Store interface returned by `createStore`.\n */\nexport interface Store<State, Action extends AnyAction = AnyAction> {\n dispatch(action: Action): void;\n getState(): State;\n readonly state$: Observable<State>;\n readonly actions$: Observable<Action | StoreLifecycleAction>;\n select<Result>(selector: Selector<State, Result>): Observable<Result>;\n init(): void;\n stop(): void;\n}\n\n/**\n * Creates a small observable store with reducer + effects.\n *\n * Behavior:\n * - `init()` starts effects and dispatches `@@micro-redux/init`.\n * - `stop()` dispatches `@@micro-redux/stop` and unsubscribes all effects.\n * - Effect action observation is scheduled on `asapScheduler` to avoid\n * synchronous re-entrancy in the effect loop.\n * - Any effect error triggers fail-fast teardown and errors both `actions$`\n * and `state$`.\n */\nexport function createStore<\n State,\n Action extends AnyAction = AnyAction,\n>(options: {\n reducer: Reducer<State, Action | StoreLifecycleAction>;\n effects?: Array<Effect<State, Action | StoreLifecycleAction, Action>>;\n}): Store<State, Action> {\n const reducer = options.reducer;\n const effects = options.effects ?? [];\n\n let hasFatalError = false;\n let isRunning = false;\n let effectSubscriptions = new Subscription();\n\n let currentState = reducer(\n undefined,\n INTERNAL_BOOT_ACTION as Action | StoreLifecycleAction,\n );\n const stateSubject = new BehaviorSubject<State>(currentState);\n const actionsSubject = new Subject<Action | StoreLifecycleAction>();\n\n const dispatchInternal = (action: Action | StoreLifecycleAction): void => {\n if (hasFatalError) {\n throw new Error(\"Store is in a failed state due to an effect error\");\n }\n\n currentState = reducer(currentState, action);\n stateSubject.next(currentState);\n actionsSubject.next(action);\n };\n\n const failFast = (error: unknown): void => {\n if (hasFatalError) {\n return;\n }\n\n hasFatalError = true;\n isRunning = false;\n effectSubscriptions.unsubscribe();\n effectSubscriptions = new Subscription();\n\n actionsSubject.error(error);\n stateSubject.error(error);\n };\n\n const startEffects = (): void => {\n for (const effect of effects) {\n const scheduledActions$ = actionsSubject\n .asObservable()\n .pipe(observeOn(asapScheduler));\n const state$ = stateSubject.asObservable();\n\n if (effect.dispatch) {\n const subscription = effect.run(scheduledActions$, state$).subscribe({\n next: (effectAction) => {\n if (hasFatalError) {\n return;\n }\n dispatchInternal(effectAction);\n },\n error: (error) => {\n failFast(error);\n },\n });\n\n effectSubscriptions.add(subscription);\n continue;\n }\n\n const subscription = effect.run(scheduledActions$, state$).subscribe({\n error: (error) => {\n failFast(error);\n },\n });\n\n effectSubscriptions.add(subscription);\n }\n };\n\n return {\n dispatch(action: Action): void {\n dispatchInternal(action);\n },\n getState(): State {\n return currentState;\n },\n get state$(): Observable<State> {\n return stateSubject.asObservable();\n },\n get actions$(): Observable<Action | StoreLifecycleAction> {\n return actionsSubject.asObservable();\n },\n select<Result>(selector: Selector<State, Result>): Observable<Result> {\n return stateSubject.asObservable().pipe(select(selector));\n },\n init(): void {\n if (hasFatalError || isRunning) {\n return;\n }\n\n isRunning = true;\n startEffects();\n\n if (hasFatalError) {\n return;\n }\n\n dispatchInternal({ type: INTERNAL_ACTION_TYPES.init });\n },\n stop(): void {\n if (hasFatalError || !isRunning) {\n return;\n }\n\n dispatchInternal({ type: INTERNAL_ACTION_TYPES.stop });\n effectSubscriptions.unsubscribe();\n effectSubscriptions = new Subscription();\n isRunning = false;\n },\n };\n}\n","/**\n * Memory error registry — stable codes for the errors the memory store throws.\n *\n * The memory store (`memory.ts`) used to throw bare `new Error(\"Failed to fetch\n * memories: 500\")` / `\"Request timed out\"` / `\"Request failed: <status>\"`. Those\n * reach the `error` selector (and the consumer UI via `useMemories` /\n * `injectMemories`) verbatim, with no machine-readable `code`/`category`/\n * `retryable`, so they cannot be grouped in observability or branched on by\n * consumers.\n *\n * Per the repo's error-handling architecture standard (AGENTS.md: \"Each project\n * must maintain an explicit error registry\"), this file is the explicit registry\n * for the memory feature. It is deliberately scoped to memory — not a repo-wide\n * registry refactor — because `packages/core` has no pre-existing\n * code/category/retryable registry convention to plug into (the runtime's\n * `lib/error-messages.ts` is a message-templating table, not a typed\n * code/category/retryable registry). It mirrors the existing\n * `AgentThreadLockedError extends Error` precedent in\n * `intelligence-agent.ts`: a real `Error` subclass so `instanceof Error` holds\n * and the public `MemoryState.error: Error | null` contract is preserved.\n *\n * `docsPath` is recorded per entry per the standard; there is no\n * `docs/errors/<project>.md` in this repo, so this docblock plus the registry\n * are the source of truth.\n *\n * Each registry entry carries:\n * - `code`: stable identifier (e.g. `MEMORY_LIST_FAILED`).\n * - `category`: one of the standard categories\n * (`validation`|`auth`|`permission`|`not_found`|`conflict`|`rate_limit`|`internal`|`dependency`).\n * - `retryable`: whether a retry could plausibly succeed (timeouts + transient\n * dependency failures are retryable; client-caused 4xx are not).\n * - `message`: the default human-readable message (callers may override with a\n * status-bearing string to preserve the prior wording).\n * - `docsPath`: documentation pointer for the code.\n */\n\n/** Standard error categories from the repo error-handling architecture. */\nexport type MemoryErrorCategory =\n | \"validation\"\n | \"auth\"\n | \"permission\"\n | \"not_found\"\n | \"conflict\"\n | \"rate_limit\"\n | \"internal\"\n | \"dependency\";\n\n/** Stable codes for the memory store's surfaced errors. */\nexport type MemoryErrorCode =\n | \"MEMORY_LIST_FAILED\"\n | \"MEMORY_CREDENTIALS_FAILED\"\n | \"MEMORY_MUTATION_FAILED\"\n | \"MEMORY_REQUEST_TIMEOUT\";\n\n/** A single registry entry describing one memory error code. */\nexport interface MemoryErrorRegistryEntry {\n readonly code: MemoryErrorCode;\n readonly category: MemoryErrorCategory;\n readonly retryable: boolean;\n readonly message: string;\n readonly docsPath: string;\n}\n\n/**\n * The memory error registry: the single source of truth for memory error\n * metadata. Keyed by `code` so a code maps to exactly one category/retryable\n * default.\n *\n * Categories/retryable rationale:\n * - List/credentials/mutation failures are `dependency` (the runtime/platform\n * the store calls failed). A 5xx is transient (`retryable: true`); a 4xx is\n * caller-caused, so the helpers below downgrade those to non-retryable.\n * - Timeouts are `dependency` and `retryable: true` (the request may simply be\n * slow).\n */\nexport const MEMORY_ERROR_REGISTRY: Readonly<\n Record<MemoryErrorCode, MemoryErrorRegistryEntry>\n> = Object.freeze({\n MEMORY_LIST_FAILED: {\n code: \"MEMORY_LIST_FAILED\",\n category: \"dependency\",\n retryable: true,\n message: \"Failed to fetch memories\",\n docsPath: \"docs/errors/memory.md#memory_list_failed\",\n },\n MEMORY_CREDENTIALS_FAILED: {\n code: \"MEMORY_CREDENTIALS_FAILED\",\n category: \"dependency\",\n retryable: true,\n message: \"Failed to fetch memory subscribe credentials\",\n docsPath: \"docs/errors/memory.md#memory_credentials_failed\",\n },\n MEMORY_MUTATION_FAILED: {\n code: \"MEMORY_MUTATION_FAILED\",\n category: \"dependency\",\n retryable: true,\n message: \"Memory mutation request failed\",\n docsPath: \"docs/errors/memory.md#memory_mutation_failed\",\n },\n MEMORY_REQUEST_TIMEOUT: {\n code: \"MEMORY_REQUEST_TIMEOUT\",\n category: \"dependency\",\n retryable: true,\n message: \"Request timed out\",\n docsPath: \"docs/errors/memory.md#memory_request_timeout\",\n },\n});\n\n/**\n * An `Error` carrying a stable memory error `code`, `category`, and `retryable`\n * flag so consumers and observability can branch on it without string-matching\n * the message.\n *\n * It is a real `Error` subclass: `instanceof Error` is true, so the public\n * `MemoryState.error: Error | null` contract (and the `error: Error | null`\n * surfaced by `useMemories` / `injectMemories`) holds unchanged. Existing\n * consumers that only read `.message` keep working; the richer fields are\n * additive.\n */\nexport class MemoryError extends Error {\n /** Stable, machine-readable error identifier. */\n readonly code: MemoryErrorCode;\n /** Coarse error category for grouping/observability. */\n readonly category: MemoryErrorCategory;\n /** Whether retrying the operation could plausibly succeed. */\n readonly retryable: boolean;\n\n /**\n * @param code - Registry code identifying this error.\n * @param options - Optional overrides:\n * - `message`: human-readable message (defaults to the registry message;\n * callers pass a status-bearing string to preserve prior wording).\n * - `retryable`: overrides the registry default (e.g. a 4xx list failure is\n * not retryable even though the code's default is).\n * - `cause`: the underlying error, preserved for debugging.\n */\n constructor(\n code: MemoryErrorCode,\n options?: { message?: string; retryable?: boolean; cause?: unknown },\n ) {\n const entry = MEMORY_ERROR_REGISTRY[code];\n super(options?.message ?? entry.message, { cause: options?.cause });\n this.name = \"MemoryError\";\n this.code = code;\n this.category = entry.category;\n this.retryable = options?.retryable ?? entry.retryable;\n // Restore the prototype chain for environments that downlevel `extends`\n // (matches the pattern the SDK relies on for cross-target `instanceof`).\n Object.setPrototypeOf(this, MemoryError.prototype);\n }\n}\n\n/**\n * Narrows an HTTP status to whether the failure is worth retrying: a 5xx (or a\n * missing/0 status) is a transient dependency failure and retryable; a 4xx is\n * caller-caused and not. Used so a `MEMORY_LIST_FAILED`/`MEMORY_MUTATION_FAILED`\n * carries an accurate `retryable` flag derived from the response status.\n */\nexport function isRetryableStatus(status: number): boolean {\n return !(Number.isInteger(status) && status >= 400 && status <= 499);\n}\n","import { phoenixExponentialBackoff } from \"@copilotkit/shared\";\nimport type { Observable } from \"rxjs\";\nimport {\n asapScheduler,\n defer,\n firstValueFrom,\n merge,\n observeOn,\n of,\n} from \"rxjs\";\nimport { fromFetch } from \"rxjs/fetch\";\nimport {\n catchError,\n concatWith,\n filter,\n finalize,\n map,\n mergeMap,\n share,\n shareReplay,\n switchMap,\n take,\n takeUntil,\n timeout,\n withLatestFrom,\n} from \"rxjs/operators\";\nimport {\n createActionGroup,\n createEffect,\n createReducer,\n createSelector,\n createStore,\n empty,\n ofType,\n on,\n props,\n} from \"./utils/micro-redux\";\nimport type { Reducer, Store } from \"./utils/micro-redux\";\nimport { MemoryError, isRetryableStatus } from \"./memory-errors\";\nimport {\n ɵphoenixChannel$,\n ɵphoenixSocket$,\n ɵjoinPhoenixChannel$,\n ɵobservePhoenixEvent$,\n ɵobservePhoenixSocketHealth$,\n ɵobservePhoenixSocketSignals$,\n} from \"./utils/phoenix-observable\";\nimport type { ɵPhoenixChannelSession } from \"./utils/phoenix-observable\";\n\n// Runtime-relative path, mirroring the thread store's `/threads` (NOT\n// `/api/threads`): `runtimeUrl` is the CopilotKit runtime mount (e.g.\n// `/api/copilotkit`), and the runtime maps `/memories` to the app-api's\n// `/api/memories` the same way it maps `/threads` -> `/api/threads`.\nconst MEMORIES_PATH = \"/memories\";\nconst MEMORIES_SUBSCRIBE_PATH = \"/memories/subscribe\";\nconst REQUEST_TIMEOUT_MS = 15_000;\n/** Consecutive socket errors tolerated before the realtime stream gives up. */\nconst MAX_SOCKET_RETRIES = 5;\n/**\n * HTTP status codes that indicate memory routes are not configured (non-fatal).\n * 404/501 mean the route is absent/unimplemented; 422 is the runtime's\n * MISSING_INTELLIGENCE signal (intelligence not configured on the deployment —\n * see packages/runtime/.../handlers/intelligence/memories.ts). All three map to\n * the graceful \"not available\" locked-teaser path, not a hard error.\n */\nconst ROUTE_UNAVAILABLE_STATUSES = new Set([404, 422, 501]);\n/**\n * Thrown when a memory route returns a 404/422/501 — treated as \"not\n * configured\" (422 is the runtime's MISSING_INTELLIGENCE signal).\n */\nclass MemoryRouteUnavailableError extends Error {}\n\n/** Public, customer-facing memory kind vocabulary (single taxonomy, no mapping). */\nexport type MemoryKind = \"topical\" | \"episodic\" | \"operational\";\n\n/** Visibility scope of a memory. */\nexport type MemoryScope = \"user\" | \"project\";\n\n/**\n * Health of the realtime (`user_meta:memories:<code>`) connection that streams\n * live `memory_metadata` deltas. Distinct from `available`/`error`, which\n * describe the REST list route: `realtimeStatus` reports ONLY whether the\n * realtime socket/channel is live so the UI can stop showing a \"live\" indicator\n * over a frozen snapshot once the socket permanently gives up.\n *\n * - `\"connecting\"` — fetching join credentials / opening the socket / joining\n * the channel (the default, and the state every `contextChanged`/`stopped`\n * resets to).\n * - `\"connected\"` — the channel join succeeded; live deltas are flowing.\n * - `\"unavailable\"` — the socket exhausted its retries or the join failed\n * permanently; the snapshot is frozen and no deltas will arrive. This is a\n * silent degrade for `available`/`error` (those stay untouched) — only this\n * signal flips.\n */\nexport type MemoryRealtimeStatus = \"connecting\" | \"connected\" | \"unavailable\";\n\n/**\n * A memory as projected across the public REST/realtime boundary — the minimal\n * shape the SDK surfaces. Mirrors the server's `PublicMemory` projection.\n */\nexport interface Memory {\n id: string;\n kind: MemoryKind;\n scope: MemoryScope;\n content: string;\n sourceThreadIds: readonly string[];\n invalidatedAt: string | null;\n}\n\n/** Input for creating a memory; `scope` defaults to `\"user\"` (v1 is user-scoped). */\nexport interface NewMemory {\n content: string;\n kind: MemoryKind;\n scope?: MemoryScope;\n sourceThreadIds?: readonly string[];\n}\n\n/**\n * New values for superseding (updating) a memory — same shape as create.\n *\n * Supersede is a FULL replacement, not a partial patch: this is the complete\n * definition of the new memory that replaces the old one. `content` and `kind`\n * are required and must be re-supplied, and an omitted `sourceThreadIds` resets\n * the new memory's source threads to `[]` — it does NOT preserve the prior\n * memory's value.\n */\nexport type MemoryChanges = NewMemory;\n\n/** Outcome of a mutation, tracked so the caller's promise resolves/rejects. */\ntype MemoryMutationOutcome =\n | { requestId: string; sessionId: number; ok: true; memory: Memory | null }\n | { requestId: string; sessionId: number; ok: false; error: Error };\n\n/**\n * Runtime wiring for the memory store: where to reach the REST surface and the\n * headers (auth + `X-Cpki-User-Id`) to send. Scoped to the current user; v1\n * surfaces user-scoped memories only.\n */\ninterface MemoryRuntimeContext {\n runtimeUrl: string;\n /** WebSocket URL for the realtime gateway (e.g. `wss://gw.example.com/client`). */\n wsUrl: string;\n headers: Record<string, string>;\n includeInvalidated?: boolean;\n}\n\n/**\n * In-memory state for the memory store. Session-guarded like the thread store:\n * `sessionId` is bumped whenever the runtime context changes so that responses\n * and realtime deltas from a previous context are ignored.\n */\ninterface MemoryState {\n memories: Memory[];\n isLoading: boolean;\n inFlightMutationCount: number;\n error: Error | null;\n context: MemoryRuntimeContext | null;\n sessionId: number;\n available: boolean;\n realtimeStatus: MemoryRealtimeStatus;\n}\n\n// Deep-frozen so `getServerState()` (which returns this exact reference) cannot\n// be mutated by any caller; a single in-place write would otherwise corrupt\n// every SSR snapshot process-wide. The freeze covers the nested `memories`\n// array too — a shallow `Object.freeze` would leave `getServerState().memories`\n// mutable (`.push(...)` would silently succeed), so the empty array is frozen\n// before being sealed into the state. The reducers always build NEW state\n// objects/arrays (they spread, never mutate in place), so they are unaffected\n// and runtime behavior is unchanged.\nconst initialMemoryState: MemoryState = Object.freeze({\n memories: Object.freeze([]) as unknown as Memory[],\n isLoading: false,\n inFlightMutationCount: 0,\n error: null,\n context: null,\n sessionId: 0,\n available: true,\n realtimeStatus: \"connecting\",\n});\n\nconst memoryAdapterEvents = createActionGroup(\"Memory Adapter\", {\n started: empty(),\n stopped: empty(),\n contextChanged: props<{ context: MemoryRuntimeContext | null }>(),\n addRequested: props<{ requestId: string; input: NewMemory }>(),\n updateRequested: props<{\n requestId: string;\n id: string;\n changes: MemoryChanges;\n }>(),\n removeRequested: props<{ requestId: string; id: string }>(),\n});\n\nconst memoryRestEvents = createActionGroup(\"Memory REST\", {\n listRequested: props<{ sessionId: number }>(),\n listSucceeded: props<{ sessionId: number; memories: Memory[] }>(),\n listFailed: props<{ sessionId: number; error: Error }>(),\n listUnavailable: props<{ sessionId: number }>(),\n mutationFinished: props<{ outcome: MemoryMutationOutcome }>(),\n credentialsRequested: props<{ sessionId: number }>(),\n credentialsSucceeded: props<{\n sessionId: number;\n joinToken: string;\n joinCode: string;\n }>(),\n // Credentials outcomes are a SILENT degrade: they feed only the realtime\n // socket effect and deliberately do NOT touch the reducer's `available`/\n // `error`, which describe the REST list route. See the reducer note near the\n // list handlers.\n credentialsFailed: props<{ sessionId: number; error: Error }>(),\n credentialsUnavailable: props<{ sessionId: number }>(),\n});\n\nconst memoryDomainEvents = createActionGroup(\"Memory Domain\", {\n memoryUpserted: props<{ sessionId: number; memory: Memory }>(),\n memoryInvalidated: props<{ sessionId: number; memoryId: string }>(),\n // Realtime-connection health transitions, session-stamped like every other\n // realtime delta so the reducer's session guard drops transitions left over\n // from a superseded context. These flip ONLY `realtimeStatus`; they never\n // touch `available`/`error` (the realtime path is a silent degrade for those).\n realtimeConnecting: props<{ sessionId: number }>(),\n realtimeConnected: props<{ sessionId: number }>(),\n realtimeUnavailable: props<{ sessionId: number }>(),\n});\n\n/** Wire shape of a memory inside a `memory_metadata` payload (carries tenant ids). */\ninterface MemoryMetadataPayloadMemory extends Memory {\n organizationId: string;\n projectId: string;\n}\n\n/**\n * The realtime `memory_metadata` event broadcast on the `user_meta` channel:\n * `created`/`updated` carry the full memory, `invalidated` carries only its id.\n * The gateway strips `userId` before broadcasting and only delivers\n * user-scoped memories, so this is always the current user's stream.\n */\ntype MemoryMetadataEvent =\n | {\n operation: \"created\" | \"updated\";\n memoryId: string;\n organizationId: string;\n projectId: string;\n occurredAt: string;\n memory: MemoryMetadataPayloadMemory;\n }\n | {\n operation: \"invalidated\";\n memoryId: string;\n organizationId: string;\n projectId: string;\n occurredAt: string;\n invalidated: { id: string };\n };\n\n/** Projects a wire memory to the public {@link Memory} shape (drops tenant ids). */\nfunction toMemory(memory: MemoryMetadataPayloadMemory): Memory {\n return {\n id: memory.id,\n kind: memory.kind,\n scope: memory.scope,\n content: memory.content,\n sourceThreadIds: memory.sourceThreadIds,\n invalidatedAt: memory.invalidatedAt,\n };\n}\n\n/**\n * Maps a realtime `memory_metadata` event to the domain action that applies it:\n * `created`/`updated` upsert the projected memory, `invalidated` removes it by\n * id. Carries the current `sessionId` so the reducer's session guard can drop\n * deltas left over from a previous context.\n */\nfunction mapMemoryMetadataEvent(\n event: MemoryMetadataEvent,\n sessionId: number,\n):\n | ReturnType<typeof memoryDomainEvents.memoryUpserted>\n | ReturnType<typeof memoryDomainEvents.memoryInvalidated> {\n if (event.operation === \"invalidated\") {\n return memoryDomainEvents.memoryInvalidated({\n sessionId,\n memoryId: event.invalidated.id,\n });\n }\n\n return memoryDomainEvents.memoryUpserted({\n sessionId,\n memory: toMemory(event.memory),\n });\n}\n\n/**\n * Inserts or replaces a memory by id. A new memory is prepended (newest first,\n * matching the REST list's `created_at DESC` ordering without needing a date\n * field on the public projection); an existing memory is replaced in place.\n */\nfunction upsertMemory(memories: Memory[], memory: Memory): Memory[] {\n const existingIndex = memories.findIndex((item) => item.id === memory.id);\n if (existingIndex === -1) {\n return [memory, ...memories];\n }\n\n const next = [...memories];\n next[existingIndex] = memory;\n return next;\n}\n\nconst memoryReducer = createReducer(\n initialMemoryState,\n on(memoryAdapterEvents.contextChanged, (state: MemoryState, { context }) => ({\n ...state,\n context,\n sessionId: state.sessionId + 1,\n memories: [],\n isLoading: Boolean(context),\n inFlightMutationCount: 0,\n error: null,\n available: true,\n // A new context re-opens the realtime socket from scratch, so the connection\n // is \"connecting\" again until the new channel joins.\n realtimeStatus: \"connecting\" as MemoryRealtimeStatus,\n })),\n on(memoryAdapterEvents.stopped, (state: MemoryState) => ({\n ...state,\n memories: [],\n isLoading: false,\n inFlightMutationCount: 0,\n error: null,\n // Reset to the default (`true`), matching `contextChanged`. Otherwise a\n // `stop()` then `start()` WITHOUT a new `setContext` would retain a stale\n // `available: false` from a prior unconfigured session.\n available: true,\n // Reset to the default (\"connecting\"), matching `contextChanged`. A later\n // `start()` re-opens the socket; a stale \"unavailable\"/\"connected\" from the\n // prior session must not leak into the next.\n realtimeStatus: \"connecting\" as MemoryRealtimeStatus,\n })),\n on(memoryRestEvents.listRequested, (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId || !state.context) {\n return state;\n }\n\n return {\n ...state,\n isLoading: true,\n error: null,\n available: true,\n };\n }),\n on(\n memoryRestEvents.listFailed,\n (state: MemoryState, { sessionId, error }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n isLoading: false,\n error,\n };\n },\n ),\n on(memoryRestEvents.listUnavailable, (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n memories: [],\n isLoading: false,\n error: null,\n available: false,\n };\n }),\n on(\n memoryAdapterEvents.addRequested,\n memoryAdapterEvents.updateRequested,\n memoryAdapterEvents.removeRequested,\n (state: MemoryState) => ({\n ...state,\n inFlightMutationCount: state.inFlightMutationCount + 1,\n }),\n ),\n on(memoryRestEvents.mutationFinished, (state: MemoryState, { outcome }) => {\n // Drop results from a superseded session. `contextChanged`/`stopped` already\n // reset `inFlightMutationCount`, so a mutation that resolves after the\n // context switched must not write a stale error into the new session.\n // Mirrors every other session-scoped handler (and threads.ts).\n if (outcome.sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n inFlightMutationCount: Math.max(0, state.inFlightMutationCount - 1),\n // On success clear any previously surfaced mutation error so a later\n // successful mutation does not leave a phantom sticky error banner.\n error: outcome.ok ? null : outcome.error,\n };\n }),\n on(\n memoryRestEvents.listSucceeded,\n (state: MemoryState, { sessionId, memories }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n memories,\n isLoading: false,\n error: null,\n // A successful list proves the memory route is available.\n available: true,\n };\n },\n ),\n // NOTE: `credentialsFailed` and `credentialsUnavailable` intentionally have NO\n // reducer cases. `available`/`error` describe the REST list route only and are\n // driven exclusively by the list events above. The credentials/realtime path\n // is a silent degrade by design: a missing/unconfigured `/memories/subscribe`\n // route (404/501/422) or a credentials error must not flip `available` or\n // surface an `error`, because the list route can still be perfectly healthy.\n // Otherwise `available` would be order-dependent on whichever of the two\n // concurrent `contextChanged` bootstraps responds last. Realtime failures are\n // handled where they occur (the socket effect retries and gives up via\n // console.warn); they do not belong in the REST availability state.\n on(\n memoryDomainEvents.memoryUpserted,\n (state: MemoryState, { sessionId, memory }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n memories: upsertMemory(state.memories, memory),\n };\n },\n ),\n on(\n memoryDomainEvents.memoryInvalidated,\n (state: MemoryState, { sessionId, memoryId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n memories: state.memories.filter((memory) => memory.id !== memoryId),\n };\n },\n ),\n // Realtime-connection health. Session-guarded so a transition from a\n // superseded context is ignored. These flip ONLY `realtimeStatus`; `available`\n // and `error` describe the REST list route and are intentionally untouched.\n on(\n memoryDomainEvents.realtimeConnecting,\n (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n realtimeStatus: \"connecting\" as MemoryRealtimeStatus,\n };\n },\n ),\n on(\n memoryDomainEvents.realtimeConnected,\n (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n realtimeStatus: \"connected\" as MemoryRealtimeStatus,\n };\n },\n ),\n on(\n memoryDomainEvents.realtimeUnavailable,\n (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n realtimeStatus: \"unavailable\" as MemoryRealtimeStatus,\n };\n },\n ),\n) as Reducer<MemoryState>;\n\nconst selectMemories = createSelector((state: MemoryState) => state.memories);\nconst selectMemoriesIsLoading = createSelector(\n (state: MemoryState) => state.isLoading,\n);\nconst selectMemoriesError = createSelector((state: MemoryState) => state.error);\n/**\n * Reports whether at least one mutation is in flight. Derived from\n * `inFlightMutationCount` so concurrent mutations stay correct: the boolean\n * only clears once every in-flight mutation has settled.\n */\nconst selectMemoriesIsMutating = createSelector(\n (state: MemoryState) => state.inFlightMutationCount > 0,\n);\n/**\n * Reports whether the memory routes are available. Becomes `false` after a\n * 404, 422 (the runtime's MISSING_INTELLIGENCE signal), or 501 response during\n * an auto-activation read; defaults to `true`.\n */\nconst selectMemoriesAvailable = createSelector(\n (state: MemoryState) => state.available,\n);\n/**\n * Reports the realtime-connection health (see {@link MemoryRealtimeStatus}).\n * Distinct from `available`/`error`: it reflects ONLY the live socket/channel,\n * so the UI can suppress a \"live\" indicator once realtime permanently dies even\n * while the REST list route stays healthy. Defaults to `\"connecting\"`.\n */\nconst selectMemoriesRealtimeStatus = createSelector(\n (state: MemoryState) => state.realtimeStatus,\n);\n\n/**\n * Dependencies injected into the memory store. The store opens its own\n * `user_meta:memories:<joinCode>` socket/channel and does not share the\n * thread store's socket, so only a `fetch` implementation is required.\n */\ninterface MemoryEnvironment {\n fetch: typeof fetch;\n}\n\ninterface MemoryStore {\n start(): void;\n stop(): void;\n setContext(context: MemoryRuntimeContext | null): void;\n /**\n * Re-fetches the REST snapshot without clearing the current list. Resolves\n * once the re-pull settles (success or failure) for the current context, so\n * callers (e.g. a `useMemories` `refresh()`) can await it. Resolves\n * immediately when no context is set.\n */\n refresh(): Promise<void>;\n /** Creates a memory; resolves to the stored memory (server-authoritative). */\n addMemory(input: NewMemory): Promise<Memory>;\n /** Supersedes a memory; resolves to the new memory (its id changes). */\n updateMemory(id: string, changes: MemoryChanges): Promise<Memory>;\n /** Retires a memory (non-lossy delete). */\n removeMemory(id: string): Promise<void>;\n getState(): MemoryState;\n /**\n * Stable, render-safe state for SSR/prerender. React's\n * `useSyncExternalStore` requires a `getServerSnapshot` during SSR/prerender\n * (e.g. Next.js); without one React throws \"Missing getServerSnapshot\". The\n * returned reference is stable across calls so React does not loop. There is\n * no client-side memory data during prerender, so this is the empty initial\n * state (no memories, not loading, no error).\n */\n getServerState(): MemoryState;\n select: Store<MemoryState>[\"select\"];\n}\n\nconst MEMORY_METADATA_EVENT = \"memory_metadata\";\n\nfunction memoryFromFetch<T>(\n input: string,\n init: RequestInit & {\n selector: (response: Response) => Promise<T>;\n fetch: typeof fetch;\n },\n): Observable<T> {\n return fromFetch(input, init);\n}\n\n/**\n * Fetches the memory snapshot and maps it to a success/failure action. Keeps\n * only user-scoped memories (v1 surfaces user scope only; the realtime stream\n * is user-scoped too), so project-scoped rows visible to the caller are\n * dropped from the store.\n */\nfunction createMemoryFetchObservable(\n environment: MemoryEnvironment,\n context: MemoryRuntimeContext,\n sessionId: number,\n): Observable<\n | ReturnType<typeof memoryRestEvents.listSucceeded>\n | ReturnType<typeof memoryRestEvents.listFailed>\n | ReturnType<typeof memoryRestEvents.listUnavailable>\n> {\n return defer(() => {\n const qs = context.includeInvalidated ? \"?includeInvalidated=true\" : \"\";\n return memoryFromFetch(`${context.runtimeUrl}${MEMORIES_PATH}${qs}`, {\n selector: (response) => {\n if (!response.ok) {\n if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) {\n throw new MemoryRouteUnavailableError(String(response.status));\n }\n throw new MemoryError(\"MEMORY_LIST_FAILED\", {\n message: `Failed to fetch memories: ${response.status}`,\n retryable: isRetryableStatus(response.status),\n });\n }\n\n return response.json() as Promise<{ memories: Memory[] }>;\n },\n fetch: environment.fetch,\n method: \"GET\",\n headers: { ...context.headers },\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new MemoryError(\"MEMORY_REQUEST_TIMEOUT\");\n },\n }),\n map((data) =>\n memoryRestEvents.listSucceeded({\n sessionId,\n memories: data.memories.filter((memory) => memory.scope === \"user\"),\n }),\n ),\n catchError((error) => {\n if (error instanceof MemoryRouteUnavailableError) {\n return of(memoryRestEvents.listUnavailable({ sessionId }));\n }\n return of(\n memoryRestEvents.listFailed({\n sessionId,\n error: error instanceof Error ? error : new Error(String(error)),\n }),\n );\n }),\n );\n });\n}\n\n/**\n * Fetches join credentials from the `/memories/subscribe` endpoint and maps\n * the response to a success/failure action. Requires both `joinToken` and\n * `joinCode` to be non-empty strings; throws otherwise so the `catchError`\n * path emits `credentialsFailed`.\n */\nfunction createMemoryCredentialsFetchObservable(\n environment: MemoryEnvironment,\n context: MemoryRuntimeContext,\n sessionId: number,\n): Observable<\n | ReturnType<typeof memoryRestEvents.credentialsSucceeded>\n | ReturnType<typeof memoryRestEvents.credentialsFailed>\n | ReturnType<typeof memoryRestEvents.credentialsUnavailable>\n> {\n return defer(() =>\n memoryFromFetch(`${context.runtimeUrl}${MEMORIES_SUBSCRIBE_PATH}`, {\n selector: async (response) => {\n if (!response.ok) {\n if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) {\n throw new MemoryRouteUnavailableError(String(response.status));\n }\n throw new MemoryError(\"MEMORY_CREDENTIALS_FAILED\", {\n message: `Failed to fetch memory subscribe credentials: ${response.status}`,\n retryable: isRetryableStatus(response.status),\n });\n }\n\n return response.json() as Promise<{\n joinToken: string;\n joinCode: string;\n }>;\n },\n fetch: environment.fetch,\n method: \"POST\",\n headers: { ...context.headers, \"Content-Type\": \"application/json\" },\n body: JSON.stringify({}),\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new MemoryError(\"MEMORY_REQUEST_TIMEOUT\");\n },\n }),\n map((data) => {\n if (typeof data.joinToken !== \"string\" || data.joinToken.length === 0) {\n throw new Error(\"missing joinToken\");\n }\n if (typeof data.joinCode !== \"string\" || data.joinCode.length === 0) {\n throw new Error(\"missing joinCode\");\n }\n\n return memoryRestEvents.credentialsSucceeded({\n sessionId,\n joinToken: data.joinToken,\n joinCode: data.joinCode,\n });\n }),\n catchError((error) => {\n if (error instanceof MemoryRouteUnavailableError) {\n return of(memoryRestEvents.credentialsUnavailable({ sessionId }));\n }\n return of(\n memoryRestEvents.credentialsFailed({\n sessionId,\n error: error instanceof Error ? error : new Error(String(error)),\n }),\n );\n }),\n ),\n );\n}\n\ntype MemoryMutationAction =\n | ReturnType<typeof memoryDomainEvents.memoryUpserted>\n | ReturnType<typeof memoryDomainEvents.memoryInvalidated>\n | ReturnType<typeof memoryRestEvents.mutationFinished>;\n\ntype MemoryMutationRequest =\n | {\n requestId: string;\n sessionId: number;\n kind: \"add\";\n body: Record<string, unknown>;\n }\n | {\n requestId: string;\n sessionId: number;\n kind: \"update\";\n id: string;\n body: Record<string, unknown>;\n }\n | { requestId: string; sessionId: number; kind: \"remove\"; id: string };\n\n/** Projects a REST mutation response to the public {@link Memory} shape. */\nfunction responseToMemory(data: {\n id: string;\n kind: MemoryKind;\n scope: MemoryScope;\n content: string;\n sourceThreadIds: readonly string[];\n invalidatedAt: string | null;\n}): Memory {\n return {\n id: data.id,\n kind: data.kind,\n scope: data.scope,\n content: data.content,\n sourceThreadIds: data.sourceThreadIds,\n invalidatedAt: data.invalidatedAt,\n };\n}\n\nconst MEMORY_KINDS: ReadonlySet<string> = new Set([\n \"topical\",\n \"episodic\",\n \"operational\",\n]);\nconst MEMORY_SCOPES: ReadonlySet<string> = new Set([\"user\", \"project\"]);\n\n/**\n * Validates the required fields of a create/supersede REST response before it is\n * projected to a {@link Memory}. Returns an `Error` describing the first\n * missing/invalid field, or `null` when the body is well-formed. Without this a\n * malformed 200 body yields a Memory with undefined fields that gets upserted.\n */\nfunction validateMutationResponse(\n data: Record<string, unknown> | null,\n): Error | null {\n if (!data || typeof data !== \"object\") {\n return new Error(\"memory mutation response missing/invalid body\");\n }\n if (typeof data.id !== \"string\" || data.id.length === 0) {\n return new Error(\"memory mutation response missing/invalid id\");\n }\n if (typeof data.kind !== \"string\" || !MEMORY_KINDS.has(data.kind)) {\n return new Error(\"memory mutation response missing/invalid kind\");\n }\n if (typeof data.scope !== \"string\" || !MEMORY_SCOPES.has(data.scope)) {\n return new Error(\"memory mutation response missing/invalid scope\");\n }\n if (typeof data.content !== \"string\") {\n return new Error(\"memory mutation response missing/invalid content\");\n }\n // `sourceThreadIds` is `readonly string[]` on the public Memory; a malformed\n // 200 that omits it (or sends a non-array) would otherwise yield a Memory\n // whose `sourceThreadIds` is `undefined`, violating the type for every\n // consumer that maps over it.\n if (\n !Array.isArray(data.sourceThreadIds) ||\n !data.sourceThreadIds.every((id) => typeof id === \"string\")\n ) {\n return new Error(\n \"memory mutation response missing/invalid sourceThreadIds\",\n );\n }\n // `invalidatedAt` is `string | null`; reject any other type so it is not\n // copied through as `undefined`.\n if (data.invalidatedAt !== null && typeof data.invalidatedAt !== \"string\") {\n return new Error(\"memory mutation response missing/invalid invalidatedAt\");\n }\n return null;\n}\n\n/**\n * Request body for create/supersede. `scope` is forwarded only when the caller\n * supplies it: the platform owns the default (`scope` defaults to `\"user\"` in\n * the `/api/memories` schema), so the store does not second-guess it here —\n * one default, at the contract owner. `sourceThreadIds` defaults to `[]`.\n */\nfunction toMutationBody(input: NewMemory): Record<string, unknown> {\n return {\n content: input.content,\n kind: input.kind,\n ...(input.scope !== undefined ? { scope: input.scope } : {}),\n sourceThreadIds: input.sourceThreadIds ?? [],\n };\n}\n\n/**\n * Builds the actions a successful mutation dispatches (server-authoritative):\n * the REST response is applied to local state immediately, and the realtime\n * event reconciles idempotently (upsert-by-id). `mutationFinished` resolves the\n * caller's promise.\n */\nfunction buildMutationSuccessActions(\n request: MemoryMutationRequest,\n data: Record<string, unknown> | null,\n): MemoryMutationAction[] {\n const { requestId, sessionId } = request;\n\n if (request.kind === \"remove\") {\n // The platform's DELETE returns a bare 204 with NO body (the runtime\n // handler responds `new Response(null, { status: 204 })` and the client's\n // `removeMemory` is `Promise<void>`), so there is no confirmation field to\n // validate here — removal is status-code-confirmed. We optimistically remove\n // the row locally on any 2xx; the realtime `memory_metadata` `invalidated`\n // event (and the next REST refresh) reconcile idempotently.\n return [\n memoryDomainEvents.memoryInvalidated({ sessionId, memoryId: request.id }),\n memoryRestEvents.mutationFinished({\n outcome: { requestId, sessionId, ok: true, memory: null },\n }),\n ];\n }\n\n // Validate the required fields before projecting. A malformed 200 body would\n // otherwise yield a Memory with undefined fields that gets upserted into\n // state. Fail the mutation instead, mirroring the `retiredId` validation\n // below and the credentials path's joinToken/joinCode validation.\n const validationError = validateMutationResponse(data);\n if (validationError) {\n return [\n memoryRestEvents.mutationFinished({\n outcome: { requestId, sessionId, ok: false, error: validationError },\n }),\n ];\n }\n\n const memory = responseToMemory(\n data as Parameters<typeof responseToMemory>[0],\n );\n\n if (request.kind === \"update\") {\n // `retiredId` is optional on the server type. Without it the\n // `memoryInvalidated` would be a no-op (no id to remove), leaving the old\n // memory as a duplicate next to the new one. Validate it like the\n // credentials path validates joinToken/joinCode, and fail the mutation\n // rather than apply a half-baked supersede.\n const retiredId = (data as { retiredId?: string }).retiredId;\n if (typeof retiredId !== \"string\" || retiredId.length === 0) {\n return [\n memoryRestEvents.mutationFinished({\n outcome: {\n requestId,\n sessionId,\n ok: false,\n error: new Error(\"supersede response missing retiredId\"),\n },\n }),\n ];\n }\n\n return [\n memoryDomainEvents.memoryInvalidated({ sessionId, memoryId: retiredId }),\n memoryDomainEvents.memoryUpserted({ sessionId, memory }),\n memoryRestEvents.mutationFinished({\n outcome: { requestId, sessionId, ok: true, memory },\n }),\n ];\n }\n\n return [\n memoryDomainEvents.memoryUpserted({ sessionId, memory }),\n memoryRestEvents.mutationFinished({\n outcome: { requestId, sessionId, ok: true, memory },\n }),\n ];\n}\n\n/** Performs a create/supersede/retire HTTP call and emits its resulting actions. */\nfunction createMemoryMutationObservable(\n environment: MemoryEnvironment,\n context: MemoryRuntimeContext,\n request: MemoryMutationRequest,\n): Observable<MemoryMutationAction> {\n const method =\n request.kind === \"add\"\n ? \"POST\"\n : request.kind === \"update\"\n ? \"PATCH\"\n : \"DELETE\";\n const path =\n request.kind === \"add\"\n ? MEMORIES_PATH\n : `${MEMORIES_PATH}/${encodeURIComponent(request.id)}`;\n\n return defer(() =>\n memoryFromFetch(`${context.runtimeUrl}${path}`, {\n selector: async (response) => {\n if (!response.ok) {\n throw new MemoryError(\"MEMORY_MUTATION_FAILED\", {\n message: `Request failed: ${response.status}`,\n retryable: isRetryableStatus(response.status),\n });\n }\n\n return request.kind === \"remove\"\n ? null\n : ((await response.json()) as Record<string, unknown>);\n },\n fetch: environment.fetch,\n method,\n headers: { ...context.headers, \"Content-Type\": \"application/json\" },\n body:\n request.kind === \"remove\" ? undefined : JSON.stringify(request.body),\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new MemoryError(\"MEMORY_REQUEST_TIMEOUT\");\n },\n }),\n mergeMap((data) => of(...buildMutationSuccessActions(request, data))),\n catchError((error) =>\n of(\n memoryRestEvents.mutationFinished({\n outcome: {\n requestId: request.requestId,\n sessionId: request.sessionId,\n ok: false,\n error: error instanceof Error ? error : new Error(String(error)),\n },\n }),\n ),\n ),\n ),\n );\n}\n\n/**\n * Creates the framework-agnostic memory store: a REST snapshot on `setContext`,\n * server-authoritative add/update/remove mutations, and realtime\n * `memory_metadata` deltas off the injected `user_meta` event source — all\n * reduced into observable state.\n */\nfunction createMemoryStore(environment: MemoryEnvironment): MemoryStore {\n // Per-store request-id counter. Kept as a closure variable (not a\n // module-level global) so each store instance has its own monotonic sequence:\n // sharing one global across instances is a latent cross-instance/SSR hazard\n // and makes request ids non-reproducible in tests that reset a single store.\n let memoryRequestId = 0;\n const createMemoryRequestId = (): string => {\n memoryRequestId += 1;\n return `memory-request-${memoryRequestId}`;\n };\n\n const bootstrapEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryAdapterEvents.contextChanged),\n withLatestFrom(state$),\n filter(([, state]) => Boolean(state.context)),\n map(([, state]) =>\n memoryRestEvents.listRequested({ sessionId: state.sessionId }),\n ),\n ),\n );\n\n const credentialsBootstrapEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryAdapterEvents.contextChanged),\n withLatestFrom(state$),\n filter(([, state]) => Boolean(state.context)),\n map(([, state]) =>\n memoryRestEvents.credentialsRequested({ sessionId: state.sessionId }),\n ),\n ),\n );\n\n const credentialsFetchEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryRestEvents.credentialsRequested),\n switchMap((action) =>\n state$.pipe(\n map((state) => state.context),\n filter((context): context is MemoryRuntimeContext =>\n Boolean(context),\n ),\n take(1),\n map((context) => ({ action, context })),\n takeUntil(\n actions$.pipe(\n ofType(\n memoryAdapterEvents.contextChanged,\n memoryAdapterEvents.stopped,\n ),\n ),\n ),\n switchMap(({ action: currentAction, context }) =>\n createMemoryCredentialsFetchObservable(\n environment,\n context,\n currentAction.sessionId,\n ),\n ),\n ),\n ),\n ),\n );\n\n const fetchEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryRestEvents.listRequested),\n switchMap((action) =>\n state$.pipe(\n map((state) => state.context),\n filter((context): context is MemoryRuntimeContext =>\n Boolean(context),\n ),\n take(1),\n map((context) => ({ action, context })),\n takeUntil(\n actions$.pipe(\n ofType(\n memoryAdapterEvents.contextChanged,\n memoryAdapterEvents.stopped,\n ),\n ),\n ),\n switchMap(({ action: currentAction, context }) =>\n createMemoryFetchObservable(\n environment,\n context,\n currentAction.sessionId,\n ),\n ),\n ),\n ),\n ),\n );\n\n const mutationEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(\n memoryAdapterEvents.addRequested,\n memoryAdapterEvents.updateRequested,\n memoryAdapterEvents.removeRequested,\n ),\n withLatestFrom(state$),\n mergeMap(([action, state]) => {\n const context = state.context;\n const sessionId = state.sessionId;\n if (!context?.runtimeUrl) {\n return of(\n memoryRestEvents.mutationFinished({\n outcome: {\n requestId: action.requestId,\n sessionId,\n ok: false,\n error: new Error(\"Runtime URL is not configured\"),\n },\n }),\n );\n }\n\n if (memoryAdapterEvents.addRequested.match(action)) {\n return createMemoryMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n kind: \"add\",\n body: toMutationBody(action.input),\n });\n }\n if (memoryAdapterEvents.updateRequested.match(action)) {\n return createMemoryMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n kind: \"update\",\n id: action.id,\n body: toMutationBody(action.changes),\n });\n }\n return createMemoryMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n kind: \"remove\",\n id: action.id,\n });\n }),\n ),\n );\n\n const socketEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryRestEvents.credentialsSucceeded),\n withLatestFrom(state$),\n filter(([action, state]) => {\n return (\n action.sessionId === state.sessionId &&\n Boolean(state.context?.wsUrl)\n );\n }),\n switchMap(([action, state]) => {\n const context = state.context as MemoryRuntimeContext;\n const { joinToken, joinCode } = action;\n const sessionId = action.sessionId;\n const shutdown$ = actions$.pipe(\n ofType(\n memoryAdapterEvents.contextChanged,\n memoryAdapterEvents.stopped,\n ),\n );\n\n return defer(() => {\n const socket$ = ɵphoenixSocket$({\n url: context.wsUrl,\n options: {\n params: { join_token: joinToken },\n reconnectAfterMs: phoenixExponentialBackoff(100, 10_000),\n rejoinAfterMs: phoenixExponentialBackoff(1_000, 30_000),\n },\n }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const channel$ = ɵphoenixChannel$({\n socket$,\n topic: `user_meta:memories:${joinCode}`,\n }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const socketSignals$ =\n ɵobservePhoenixSocketSignals$(socket$).pipe(share());\n // The socket give-up signal: completes the realtime stream after the\n // health check throws. ALSO surfaces the give-up as a status delta\n // (`realtimeUnavailable`) so the UI can drop its \"live\" indicator —\n // this is the permanent-death signal that was previously only a\n // `console.warn`. `available`/`error` stay untouched by design (the\n // realtime path is a silent degrade for the REST list route).\n const fatalSocketShutdown$ = ɵobservePhoenixSocketHealth$(\n socketSignals$,\n MAX_SOCKET_RETRIES,\n ).pipe(\n catchError(() => {\n console.warn(\n `[memory] WebSocket failed after ${MAX_SOCKET_RETRIES} attempts, giving up`,\n );\n return of(undefined);\n }),\n share(),\n );\n // The give-up mapped to a status delta. Emitted from the merged stream\n // (not the `takeUntil` notifier) so the `realtimeUnavailable` action is\n // dispatched BEFORE teardown: the merged stream is `takeUntil`'d by a\n // microtask-deferred copy of the give-up signal, so this synchronous\n // emission always wins the race and the action reaches the reducer.\n const fatalStatus$ = fatalSocketShutdown$.pipe(\n map(() => memoryDomainEvents.realtimeUnavailable({ sessionId })),\n );\n const metadata$ = channel$.pipe(\n switchMap(({ channel }: ɵPhoenixChannelSession) =>\n ɵobservePhoenixEvent$<MemoryMetadataEvent>(\n channel,\n MEMORY_METADATA_EVENT,\n ),\n ),\n map((event) => mapMemoryMetadataEvent(event, action.sessionId)),\n );\n\n // Drives the actual `channel.join()` AND maps the join outcome to a\n // realtime-status delta. `ɵphoenixChannel$` only creates the channel +\n // a lazy join-outcome stream; the join is sent when that stream is\n // subscribed. Observing channel events (`metadata$`) alone does NOT\n // subscribe it, so without this the socket connects but never joins\n // `user_meta:memories:<code>` and no realtime deltas arrive. The thread\n // store joins for the same reason (its merged `joinOutcome$`).\n //\n // On a successful join -> `realtimeConnected` (the \"live\" signal). On a\n // failed/timed-out join we KEEP the `console.warn` and emit\n // `realtimeUnavailable`, then swallow the error so a transient\n // rejection doesn't tear down the metadata stream (Phoenix re-attempts\n // the join on socket reconnect); the next successful join re-emits\n // `realtimeConnected`.\n const join$ = ɵjoinPhoenixChannel$(channel$).pipe(\n // `ɵjoinPhoenixChannel$` emits `never` (it completes on success), so\n // this concat surfaces the connected status once the join resolves.\n concatWith(\n of(memoryDomainEvents.realtimeConnected({ sessionId })),\n ),\n catchError((error) => {\n console.warn(\n `[memory] failed to join user_meta:memories:${joinCode}`,\n error,\n );\n return of(\n memoryDomainEvents.realtimeUnavailable({ sessionId }),\n );\n }),\n );\n\n return merge(\n // Surface \"connecting\" immediately when the realtime stream starts\n // (credentials succeeded -> socket subscribing/joining). Reset to\n // this on every (re)subscribe so a prior session's terminal status\n // can't bleed through before the new join resolves.\n of(memoryDomainEvents.realtimeConnecting({ sessionId })),\n metadata$,\n join$,\n fatalStatus$,\n ).pipe(\n takeUntil(\n merge(\n shutdown$,\n // Defer the give-up teardown by a microtask so `fatalStatus$`'s\n // synchronous `realtimeUnavailable` emission is dispatched before\n // the stream is torn down. `observeOn(asapScheduler)` schedules\n // the teardown after the current microtask drains.\n fatalSocketShutdown$.pipe(observeOn(asapScheduler)),\n ),\n ),\n finalize(() => {\n // Socket/channel teardown is handled by the `finalize` operators\n // inside `ɵphoenixSocket$`/`ɵphoenixChannel$`; this hook exists to\n // mirror the thread store's socket-effect lifecycle shape.\n }),\n );\n });\n }),\n ),\n );\n\n const store = createStore<MemoryState>({\n reducer: memoryReducer,\n effects: [\n bootstrapEffect,\n credentialsBootstrapEffect,\n fetchEffect,\n credentialsFetchEffect,\n mutationEffect,\n socketEffect,\n ],\n });\n\n function trackMutation<T>(\n dispatchAction:\n | ReturnType<typeof memoryAdapterEvents.addRequested>\n | ReturnType<typeof memoryAdapterEvents.updateRequested>\n | ReturnType<typeof memoryAdapterEvents.removeRequested>,\n extract: (outcome: Extract<MemoryMutationOutcome, { ok: true }>) => T,\n ): Promise<T> {\n const { requestId } = dispatchAction;\n const completion$ = merge(\n store.actions$.pipe(\n ofType(memoryRestEvents.mutationFinished),\n filter((action) => action.outcome.requestId === requestId),\n map((action) => action.outcome),\n ),\n store.actions$.pipe(\n ofType(memoryAdapterEvents.stopped),\n map(\n () =>\n ({\n requestId,\n sessionId: store.getState().sessionId,\n ok: false,\n error: new Error(\n \"Memory store stopped before mutation completed\",\n ),\n }) satisfies MemoryMutationOutcome,\n ),\n ),\n ).pipe(take(1));\n\n const resultPromise = firstValueFrom(completion$).then((outcome) => {\n if (!outcome.ok) {\n throw outcome.error;\n }\n return extract(outcome);\n });\n\n store.dispatch(dispatchAction);\n return resultPromise;\n }\n\n return {\n start(): void {\n store.init();\n store.dispatch(memoryAdapterEvents.started());\n },\n stop(): void {\n store.dispatch(memoryAdapterEvents.stopped());\n store.stop();\n },\n setContext(context: MemoryRuntimeContext | null): void {\n store.dispatch(memoryAdapterEvents.contextChanged({ context }));\n },\n refresh(): Promise<void> {\n const { sessionId, context } = store.getState();\n if (!context) return Promise.resolve();\n\n // Settle when the re-pulled snapshot completes for this session (success\n // or failure), or if the store is stopped first. Subscribe before\n // dispatching so the resulting list action can't slip past, mirroring\n // trackMutation.\n const completion$ = merge(\n store.actions$.pipe(\n ofType(\n memoryRestEvents.listSucceeded,\n memoryRestEvents.listFailed,\n // `listUnavailable` (404/501/422) is the third terminal outcome of\n // the list fetch. Without it `await refresh()` would hang forever\n // against an unconfigured route.\n memoryRestEvents.listUnavailable,\n ),\n filter((action) => action.sessionId === sessionId),\n ),\n store.actions$.pipe(ofType(memoryAdapterEvents.stopped)),\n // The list `fetchEffect` has `takeUntil(contextChanged, stopped)`, so a\n // `contextChanged` fired after this `listRequested` but before the fetch\n // settles tears down the fetch with NO terminal list action for our\n // session — `await refresh()` would hang forever. Settle on it too.\n store.actions$.pipe(ofType(memoryAdapterEvents.contextChanged)),\n ).pipe(take(1));\n\n // `await refresh()` resolving must mean the snapshot actually refreshed,\n // so reject on anything that isn't a successful re-pull — a failed list\n // (its error also lands in the `error` selector) or the store being\n // stopped mid-flight. This keeps `refresh` fully symmetric with the\n // mutation methods, which reject on both failure and stop via\n // `trackMutation`.\n const done = firstValueFrom(completion$).then((action) => {\n if (memoryRestEvents.listFailed.match(action)) {\n throw action.error;\n }\n if (memoryAdapterEvents.stopped.match(action)) {\n throw new Error(\"Memory store stopped before refresh completed\");\n }\n // A `contextChanged` superseded this refresh: a new context is loading\n // its own snapshot, so this refresh is moot. RESOLVE (do not reject) —\n // resolving is the least-surprising outcome for a superseded refresh.\n if (memoryAdapterEvents.contextChanged.match(action)) {\n return;\n }\n // `listSucceeded` and `listUnavailable` both RESOLVE: an unavailable\n // (not-configured) route is a non-fatal terminal state, consistent with\n // the auto-load path which leaves `available: false` without erroring.\n });\n store.dispatch(memoryRestEvents.listRequested({ sessionId }));\n return done;\n },\n addMemory(input: NewMemory): Promise<Memory> {\n return trackMutation(\n memoryAdapterEvents.addRequested({\n requestId: createMemoryRequestId(),\n input,\n }),\n (outcome) => {\n if (outcome.memory == null) {\n throw new Error(\"add resolved without a memory\");\n }\n return outcome.memory;\n },\n );\n },\n updateMemory(id: string, changes: MemoryChanges): Promise<Memory> {\n return trackMutation(\n memoryAdapterEvents.updateRequested({\n requestId: createMemoryRequestId(),\n id,\n changes,\n }),\n (outcome) => {\n if (outcome.memory == null) {\n throw new Error(\"update resolved without a memory\");\n }\n return outcome.memory;\n },\n );\n },\n removeMemory(id: string): Promise<void> {\n return trackMutation(\n memoryAdapterEvents.removeRequested({\n requestId: createMemoryRequestId(),\n id,\n }),\n () => undefined,\n );\n },\n getState(): MemoryState {\n return store.getState();\n },\n getServerState(): MemoryState {\n return initialMemoryState;\n },\n select: store.select.bind(store),\n };\n}\n\n// `Memory`, `MemoryKind`, `MemoryScope`, `NewMemory`, and `MemoryChanges` are\n// the consumer-facing memory types surfaced by the framework hooks\n// (`useMemories` / `injectMemories`); they are exported unprefixed from their\n// declarations above. The remaining memory internals keep the `ɵ` prefix.\n// The memory error registry surface is consumer-facing: `MemoryError` is what\n// `MemoryState.error` (and the `error: Error | null` from `useMemories` /\n// `injectMemories`) carries on a failure, and consumers branch on its\n// `code`/`category`/`retryable`. Re-exported unprefixed here so it ships through\n// `index.ts` (`export * from \"./memory\"`) alongside the memory types.\nexport {\n MemoryError,\n MEMORY_ERROR_REGISTRY,\n isRetryableStatus as ɵisRetryableMemoryStatus,\n} from \"./memory-errors\";\nexport type {\n MemoryErrorCode,\n MemoryErrorCategory,\n MemoryErrorRegistryEntry,\n} from \"./memory-errors\";\n\nexport type ɵMemoryState = MemoryState;\nexport type ɵMemoryRuntimeContext = MemoryRuntimeContext;\nexport type ɵMemoryMetadataEvent = MemoryMetadataEvent;\nexport type ɵMemoryEnvironment = MemoryEnvironment;\nexport type ɵMemoryStore = MemoryStore;\nexport const ɵmemoryAdapterEvents = memoryAdapterEvents;\nexport const ɵmemoryRestEvents = memoryRestEvents;\nexport const ɵmemoryDomainEvents = memoryDomainEvents;\nexport const ɵmemoryReducer = memoryReducer;\nexport const ɵmapMemoryMetadataEvent = mapMemoryMetadataEvent;\nexport const ɵselectMemories = selectMemories;\nexport const ɵselectMemoriesIsLoading = selectMemoriesIsLoading;\nexport const ɵselectMemoriesError = selectMemoriesError;\nexport const ɵselectMemoriesIsMutating = selectMemoriesIsMutating;\nexport const ɵselectMemoriesAvailable = selectMemoriesAvailable;\nexport const ɵselectMemoriesRealtimeStatus = selectMemoriesRealtimeStatus;\nexport { createMemoryStore as ɵcreateMemoryStore };\n","import type { AbstractAgent, Context, State } from \"@ag-ui/client\";\nimport type { AgentSubscriber } from \"@ag-ui/client\";\nimport { Throttler } from \"@tanstack/pacer\";\nimport type {\n FrontendTool,\n SuggestionsConfig,\n Suggestion,\n CopilotRuntimeTransport,\n RuntimeMode,\n RuntimeLicenseStatus,\n IntelligenceRuntimeInfo,\n ThreadEndpointRuntimeInfo,\n} from \"../types\";\nimport type {\n CopilotKitCoreAddAgentParams,\n CopilotKitCoreRegisterProxiedAgentParams,\n CopilotKitCoreRegisterProxiedAgentResult,\n} from \"./agent-registry\";\nimport { AgentRegistry } from \"./agent-registry\";\nimport type { ScopedContext } from \"./context-store\";\nimport { ContextStore } from \"./context-store\";\nimport { SuggestionEngine } from \"./suggestion-engine\";\nimport type {\n CopilotKitCoreRunAgentParams,\n CopilotKitCoreConnectAgentParams,\n CopilotKitCoreGetToolParams,\n CopilotKitCoreRunToolParams,\n CopilotKitCoreRunToolResult,\n} from \"./run-handler\";\nimport { RunHandler } from \"./run-handler\";\nimport type { DebugConfig } from \"@copilotkit/shared\";\nimport { StateManager } from \"./state-manager\";\nimport { ThreadStoreRegistry } from \"./thread-store-registry\";\nimport type { ɵThreadStore } from \"../threads\";\nimport { ɵcreateMemoryStore } from \"../memory\";\nimport type { ɵMemoryStore } from \"../memory\";\n\n/** Configuration options for `CopilotKitCore`. */\nexport interface CopilotKitCoreConfig {\n /** The endpoint of the CopilotRuntime. */\n runtimeUrl?: string;\n /** Transport style for CopilotRuntime endpoints. Defaults to REST. */\n runtimeTransport?: CopilotRuntimeTransport;\n /**\n * When true, the constructor sets the runtime config but does NOT start the\n * `/info` connection. Call {@link CopilotKitCore.connect} to start it —\n * typically from a host's commit-phase effect. This prevents a burst of\n * duplicate `/info` requests when a host constructs (and discards) the core\n * during render, e.g. React concurrent rendering / Suspense / StrictMode.\n * See https://github.com/CopilotKit/CopilotKit/issues/5801.\n */\n deferInitialConnection?: boolean;\n /** Mapping from agent name to its `AbstractAgent` instance. For development only - production requires CopilotRuntime. */\n agents__unsafe_dev_only?: Record<string, AbstractAgent>;\n /**\n * Headers sent with every runtime request and merged on top of each\n * `HttpAgent`'s own headers (the core value wins on a key conflict). See\n * `setHeaders`.\n */\n headers?: Record<string, string>;\n /** Credentials mode for fetch requests (e.g., \"include\" for HTTP-only cookies). */\n credentials?: RequestCredentials;\n /** Properties sent as `forwardedProps` to the AG-UI agent. */\n properties?: Record<string, unknown>;\n /** Ordered collection of frontend tools available to the core. */\n tools?: FrontendTool<any>[];\n /** Suggestions config for the core. */\n suggestionsConfig?: SuggestionsConfig[];\n /** Enable debug logging for the client-side event pipeline. */\n debug?: DebugConfig;\n}\n\nexport type {\n CopilotKitCoreAddAgentParams,\n CopilotKitCoreRegisterProxiedAgentParams,\n CopilotKitCoreRegisterProxiedAgentResult,\n};\nexport type {\n CopilotKitCoreRunAgentParams,\n CopilotKitCoreConnectAgentParams,\n CopilotKitCoreGetToolParams,\n CopilotKitCoreRunToolParams,\n CopilotKitCoreRunToolResult,\n};\n\nexport interface CopilotKitCoreStopAgentParams {\n agent: AbstractAgent;\n}\n\nexport type CopilotKitCoreGetSuggestionsResult = {\n suggestions: Suggestion[];\n isLoading: boolean;\n};\n\nexport enum CopilotKitCoreErrorCode {\n RUNTIME_INFO_FETCH_FAILED = \"runtime_info_fetch_failed\",\n AGENT_CONNECT_FAILED = \"agent_connect_failed\",\n AGENT_RUN_FAILED = \"agent_run_failed\",\n AGENT_RUN_FAILED_EVENT = \"agent_run_failed_event\",\n AGENT_RUN_ERROR_EVENT = \"agent_run_error_event\",\n TOOL_ARGUMENT_PARSE_FAILED = \"tool_argument_parse_failed\",\n TOOL_HANDLER_FAILED = \"tool_handler_failed\",\n TOOL_NOT_FOUND = \"tool_not_found\",\n AGENT_NOT_FOUND = \"agent_not_found\",\n /**\n * Emitted when an agent run fails because the thread is already locked\n * by another active run.\n *\n * @example\n * ```tsx\n * <CopilotKitProvider\n * onError={({ code, error, context }) => {\n * if (code === \"agent_thread_locked\") {\n * // Show \"Agent is busy, retry?\" UI\n * }\n * }}\n * />\n * ```\n */\n AGENT_THREAD_LOCKED = \"agent_thread_locked\",\n // Transcription errors\n TRANSCRIPTION_FAILED = \"transcription_failed\",\n TRANSCRIPTION_SERVICE_NOT_CONFIGURED = \"transcription_service_not_configured\",\n TRANSCRIPTION_INVALID_AUDIO = \"transcription_invalid_audio\",\n TRANSCRIPTION_RATE_LIMITED = \"transcription_rate_limited\",\n TRANSCRIPTION_AUTH_FAILED = \"transcription_auth_failed\",\n TRANSCRIPTION_NETWORK_ERROR = \"transcription_network_error\",\n SUBSCRIBER_CALLBACK_FAILED = \"subscriber_callback_failed\",\n}\n\nexport interface CopilotKitCoreSubscriber {\n onRuntimeConnectionStatusChanged?: (event: {\n copilotkit: CopilotKitCore;\n status: CopilotKitCoreRuntimeConnectionStatus;\n }) => void | Promise<void>;\n onToolExecutionStart?: (event: {\n copilotkit: CopilotKitCore;\n toolCallId: string;\n agentId: string;\n toolName: string;\n args: unknown;\n }) => void | Promise<void>;\n onToolExecutionEnd?: (event: {\n copilotkit: CopilotKitCore;\n toolCallId: string;\n agentId: string;\n toolName: string;\n result: string;\n error?: string;\n }) => void | Promise<void>;\n onAgentsChanged?: (event: {\n copilotkit: CopilotKitCore;\n agents: Readonly<Record<string, AbstractAgent>>;\n }) => void | Promise<void>;\n /**\n * Fired when an agent run or connect begins. The `agent` may be a per-thread\n * clone that is not present in `core.agents`, so `onAgentsChanged` never fires\n * for it. Subscribers (e.g. the inspector) can use this to subscribe to the\n * running instance's AG-UI events.\n */\n onAgentRunStarted?: (event: {\n copilotkit: CopilotKitCore;\n agent: AbstractAgent;\n }) => void | Promise<void>;\n onContextChanged?: (event: {\n copilotkit: CopilotKitCore;\n context: Readonly<Record<string, Context>>;\n }) => void | Promise<void>;\n onSuggestionsConfigChanged?: (event: {\n copilotkit: CopilotKitCore;\n suggestionsConfig: Readonly<Record<string, SuggestionsConfig>>;\n }) => void | Promise<void>;\n onSuggestionsChanged?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n suggestions: Suggestion[];\n }) => void | Promise<void>;\n onSuggestionsStartedLoading?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n }) => void | Promise<void>;\n onSuggestionsFinishedLoading?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n }) => void | Promise<void>;\n onPropertiesChanged?: (event: {\n copilotkit: CopilotKitCore;\n properties: Readonly<Record<string, unknown>>;\n }) => void | Promise<void>;\n onHeadersChanged?: (event: {\n copilotkit: CopilotKitCore;\n headers: Readonly<Record<string, string>>;\n }) => void | Promise<void>;\n onError?: (event: {\n copilotkit: CopilotKitCore;\n error: Error;\n code: CopilotKitCoreErrorCode;\n context: Record<string, any>;\n }) => void | Promise<void>;\n onThreadStoreRegistered?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n store: ɵThreadStore;\n }) => void | Promise<void>;\n /**\n * Fired when a thread store is removed from the registry, either by an\n * explicit `unregister()` call or by a `register()` call that replaces an\n * existing store for the same `agentId`.\n *\n * The previous store is delivered via `prevStore` so subscribers can tear\n * down state that depends on the concrete instance (e.g. cancel an active\n * subscription) without consulting the registry. By the time async\n * subscribers resume after an `await`, a replacement `register()` may have\n * already installed the new store under the same key, so calling\n * `registry.get(agentId)` inside this callback is unsafe and may return\n * the new store instead of the unregistered one.\n */\n onThreadStoreUnregistered?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n prevStore: ɵThreadStore;\n }) => void | Promise<void>;\n}\n\n// Subscription object returned by subscribe() and subscribeToAgentWithOptions()\nexport interface CopilotKitCoreSubscription {\n unsubscribe: () => void;\n}\n\n/**\n * The callback keys accepted by {@link CopilotKitCore.subscribeToAgentWithOptions}.\n * This tuple is the single source of truth — both the\n * `SubscribeToAgentSubscriber` type and the runtime `ALLOWED_KEYS` set\n * are derived from it, so they cannot desynchronise.\n */\nconst SUBSCRIBE_TO_AGENT_KEYS = [\n \"onMessagesChanged\",\n \"onStateChanged\",\n \"onRunInitialized\",\n \"onRunFinalized\",\n \"onRunFailed\",\n \"onRunErrorEvent\",\n] as const satisfies readonly (keyof AgentSubscriber)[];\n\n/**\n * Runtime allowlist derived from {@link SUBSCRIBE_TO_AGENT_KEYS}. Hoisted\n * to module scope so the Set is allocated once, not per-subscription.\n */\nconst ALLOWED_KEYS: ReadonlySet<(typeof SUBSCRIBE_TO_AGENT_KEYS)[number]> =\n new Set(SUBSCRIBE_TO_AGENT_KEYS);\n\n/**\n * The subset of `AgentSubscriber` callbacks accepted by\n * {@link CopilotKitCore.subscribeToAgentWithOptions}. Only the callbacks\n * listed in {@link SUBSCRIBE_TO_AGENT_KEYS} are supported:\n * `onMessagesChanged`, `onStateChanged`, and the four run lifecycle\n * callbacks (`onRunInitialized`, `onRunFinalized`, `onRunFailed`,\n * `onRunErrorEvent`).\n *\n * Two categories of `AgentSubscriber` members are excluded:\n *\n * - **AG-UI event handlers** (`onEvent`, `onToolCallStartEvent`, etc.)\n * return `AgentStateMutation` with `stopPropagation` — semantics that\n * the throttle and error-protection wrappers cannot safely mediate.\n *\n * - **Per-item notification callbacks** (`onNewMessage`, `onNewToolCall`)\n * return `void` and have no mutation concerns, but are excluded to keep\n * the surface area minimal — `onMessagesChanged` already covers the\n * same data at a coarser granularity, and throttling per-item callbacks\n * would have different semantic expectations.\n *\n * `onRunErrorEvent` is technically an AG-UI event handler (its return type\n * includes `stopPropagation`), but it is included here because all\n * framework consumers need it to reset `isRunning` on protocol-level\n * `RUN_ERROR` events — distinct from `onRunFailed` which handles local\n * exceptions like network errors. In practice, consumers return `void`\n * from this callback, so the `stopPropagation` semantics are unused.\n *\n * Note: the included lifecycle callbacks return\n * `Omit<AgentStateMutation, \"stopPropagation\">` (or full\n * `AgentStateMutation` in the case of `onRunErrorEvent`). On the error\n * path, `safeCall` discards those return values (see its inline\n * documentation).\n *\n * Use `agent.subscribe()` directly when event mutation or per-item\n * notification semantics are needed.\n */\nexport type SubscribeToAgentSubscriber = Pick<\n AgentSubscriber,\n (typeof SUBSCRIBE_TO_AGENT_KEYS)[number]\n>;\n\n/** Options for {@link CopilotKitCore.subscribeToAgentWithOptions}. */\nexport interface SubscribeToAgentOptions {\n /**\n * Throttle interval (ms) for `onMessagesChanged` / `onStateChanged`.\n * Non-negative finite number; `0` explicitly disables throttling.\n * Falls back to `defaultThrottleMs` when `undefined`.\n */\n throttleMs?: number;\n}\n\nexport enum CopilotKitCoreRuntimeConnectionStatus {\n Disconnected = \"disconnected\",\n Connected = \"connected\",\n Connecting = \"connecting\",\n Error = \"error\",\n}\n\n/**\n * Internal interface for delegate classes to access CopilotKitCore methods.\n * This provides type safety while allowing controlled access to private functionality.\n */\nexport interface CopilotKitCoreFriendsAccess {\n // Notification methods\n notifySubscribers(\n handler: (subscriber: CopilotKitCoreSubscriber) => void | Promise<void>,\n errorMessage: string,\n ): Promise<void>;\n\n emitError(params: {\n error: Error;\n code: CopilotKitCoreErrorCode;\n context?: Record<string, any>;\n }): Promise<void>;\n\n // Getters for internal state\n readonly headers: Readonly<Record<string, string>>;\n readonly credentials: RequestCredentials | undefined;\n readonly properties: Readonly<Record<string, unknown>>;\n readonly context: Readonly<Record<string, Context>>;\n readonly debug?: DebugConfig;\n\n // Internal methods\n buildFrontendTools(agentId?: string): import(\"@ag-ui/client\").Tool[];\n getContextForAgent(agentId?: string): Context[];\n getAgent(id: string): AbstractAgent | undefined;\n /**\n * Re-apply the current core headers to a single agent, merged on top of the\n * headers the agent was constructed with. The single source of truth for\n * header application; the run handler uses it so a run never clobbers\n * per-agent headers (see #5635).\n */\n applyHeadersToAgent(agent: AbstractAgent): void;\n\n // References to delegate subsystems\n readonly suggestionEngine: {\n clearSuggestions(agentId: string): void;\n reloadSuggestions(agentId: string): void;\n };\n\n /**\n * Called before each follow-up agent run (after tool execution).\n * See CopilotKitCore.waitForPendingFrameworkUpdates for details.\n */\n waitForPendingFrameworkUpdates(): Promise<void>;\n}\n\n/**\n * Normalize a header map to the internal invariant: a `Record<string, string>`\n * with no `null`/`undefined` values. Entries whose value is `null`/`undefined`\n * are dropped (this is how a header is cleared). Shared by the constructor and\n * `setHeaders` so both write paths into `_headers` enforce the same invariant.\n */\nfunction normalizeHeaders(\n headers: Record<string, string | null | undefined>,\n): Record<string, string> {\n return Object.fromEntries(\n Object.entries(headers).filter(\n (entry): entry is [string, string] => entry[1] != null,\n ),\n );\n}\n\nexport class CopilotKitCore {\n private _headers: Record<string, string>;\n private _credentials?: RequestCredentials;\n private _properties: Record<string, unknown>;\n private _defaultThrottleMs?: number;\n private _debug?: DebugConfig;\n\n private subscribers: Set<CopilotKitCoreSubscriber> = new Set();\n\n // Delegate classes\n private agentRegistry: AgentRegistry;\n private contextStore: ContextStore;\n private suggestionEngine: SuggestionEngine;\n private runHandler: RunHandler;\n private stateManager: StateManager;\n private threadStoreRegistry: ThreadStoreRegistry;\n /**\n * The single core-owned memory store, created lazily on first\n * `getMemoryStore()` and kept user-scoped for the lifetime of the core.\n * Its runtime context is wired by the core itself (see `syncMemoryContext`),\n * so callers never register or look it up by `agentId`.\n */\n private _memoryStore?: ɵMemoryStore;\n /**\n * Tracks the agent IDs from the most recent `onAgentsChanged` notification.\n * Used to gate thread-store auto-unregister so the FIRST empty-agents\n * notification (before published agents are merged in) does not rip out a\n * store that was registered prior to that initial notification.\n */\n private previousAgentIds: Set<string> = new Set();\n\n constructor({\n runtimeUrl,\n runtimeTransport = \"auto\",\n deferInitialConnection = false,\n headers = {},\n credentials,\n properties = {},\n agents__unsafe_dev_only = {},\n tools = [],\n suggestionsConfig = [],\n debug,\n }: CopilotKitCoreConfig) {\n this._headers = normalizeHeaders(headers);\n this._credentials = credentials;\n this._properties = properties;\n this._debug = debug;\n\n // Initialize delegate classes\n this.agentRegistry = new AgentRegistry(this);\n this.contextStore = new ContextStore(this);\n this.suggestionEngine = new SuggestionEngine(this);\n this.runHandler = new RunHandler(this);\n this.stateManager = new StateManager(this);\n this.threadStoreRegistry = new ThreadStoreRegistry(this);\n\n // Initialize each subsystem\n this.agentRegistry.initialize(agents__unsafe_dev_only);\n this.runHandler.initialize(tools);\n this.suggestionEngine.initialize(suggestionsConfig);\n this.stateManager.initialize();\n\n this.agentRegistry.setRuntimeTransport(runtimeTransport);\n this.agentRegistry.setRuntimeUrl(runtimeUrl, {\n deferConnection: deferInitialConnection,\n });\n\n // Seed the previous-agents snapshot from the constructor-supplied agents.\n // `agentRegistry.initialize` does not emit `onAgentsChanged`, so the\n // subscriber below would otherwise see its first non-empty notification\n // as an \"addition\" relative to an empty baseline — and a later removal\n // of those same agents would NOT trigger the auto-unregister branch\n // because the guard would think the agentId was never previously\n // present. Seeding the set here keeps the guard honest.\n this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));\n\n // Subscribe to agent changes to track state for new agents\n this.subscribe({\n // Re-sync the memory store's runtime context whenever the runtime\n // connection status changes. The `/info` fetch sets the connection\n // status and `intelligence` together before firing this notification,\n // so this single hook covers both connection and intelligence changes.\n // Guarded so we never instantiate the store just to sync it.\n onRuntimeConnectionStatusChanged: () => {\n if (this._memoryStore) this.syncMemoryContext();\n },\n onAgentsChanged: ({ agents }) => {\n Object.values(agents).forEach((agent) => {\n if (agent.agentId) {\n this.stateManager.subscribeToAgent(agent);\n }\n });\n\n // Unregister thread stores for agents that have been removed.\n //\n // Critically, only unregister an agentId that was present in the\n // PREVIOUS agents snapshot AND is missing from the new one. Without\n // the \"previously had\" guard, the FIRST `onAgentsChanged({ agents: {} })`\n // delivered to a freshly-published core would tear out a thread store\n // that a consumer (e.g. useThreads) just registered — `core.agents`\n // is asynchronously populated and the empty-map notification fires\n // before the published agents are merged in.\n const currentAgentIds = new Set(Object.keys(agents));\n // Each iteration is wrapped so a throw on one id does not stall\n // cleanup for the rest of the set. Both registries' unregister\n // paths are idempotent, so re-attempts on the next\n // onAgentsChanged are safe.\n for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) {\n if (\n this.previousAgentIds.has(agentId) &&\n !currentAgentIds.has(agentId)\n ) {\n try {\n this.threadStoreRegistry.unregister(agentId);\n } catch (err) {\n console.error(\n `CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for \"${agentId}\":`,\n err,\n );\n }\n }\n }\n\n // Symmetric cleanup for state-manager subscriptions: any agentId\n // that disappeared from the registry (e.g. via `unregister()` from\n // a registerProxiedAgent caller) should release its StateManager\n // subscription. Without this, the subscription leaks — events from\n // a still-running observable on the removed agent would continue\n // to populate stateByRun/messageToRun for the dead id.\n for (const agentId of this.previousAgentIds) {\n if (!currentAgentIds.has(agentId)) {\n try {\n this.stateManager.unsubscribeFromAgent(agentId);\n } catch (err) {\n console.error(\n `CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for \"${agentId}\":`,\n err,\n );\n }\n }\n }\n\n this.previousAgentIds = currentAgentIds;\n },\n });\n }\n\n /**\n * Internal method used by delegate classes and subclasses to notify subscribers\n */\n protected async notifySubscribers(\n handler: (subscriber: CopilotKitCoreSubscriber) => void | Promise<void>,\n errorMessage: string,\n ): Promise<void> {\n await Promise.all(\n Array.from(this.subscribers).map(async (subscriber) => {\n try {\n await handler(subscriber);\n } catch (error) {\n console.error(errorMessage, error);\n }\n }),\n );\n }\n\n /**\n * Internal method used by delegate classes to emit errors\n */\n private async emitError({\n error,\n code,\n context = {},\n }: {\n error: Error;\n code: CopilotKitCoreErrorCode;\n context?: Record<string, any>;\n }): Promise<void> {\n await this.notifySubscribers(\n (subscriber) =>\n subscriber.onError?.({\n copilotkit: this,\n error,\n code,\n context,\n }),\n \"Subscriber onError error:\",\n );\n }\n\n /**\n * Log a message to the console and emit an error to subscribers.\n * Catches failures from `emitError` itself to prevent unhandled rejections.\n */\n private logAndEmitError(\n message: string,\n params: {\n error: Error;\n code: CopilotKitCoreErrorCode;\n context?: Record<string, any>;\n },\n logLevel: \"error\" | \"warn\" = \"error\",\n ): void {\n console[logLevel](message, params.error);\n this.emitError(params).catch((emitErr: unknown) => {\n console.error(message + \" — emitError itself failed:\", emitErr);\n });\n }\n\n /**\n * Snapshot accessors\n */\n get context(): Readonly<Record<string, ScopedContext>> {\n return this.contextStore.context;\n }\n\n get agents(): Readonly<Record<string, AbstractAgent>> {\n return this.agentRegistry.agents;\n }\n\n get tools(): Readonly<FrontendTool<any>[]> {\n return this.runHandler.tools;\n }\n\n get runtimeUrl(): string | undefined {\n return this.agentRegistry.runtimeUrl;\n }\n\n setRuntimeUrl(runtimeUrl: string | undefined): void {\n this.agentRegistry.setRuntimeUrl(runtimeUrl);\n }\n\n /**\n * Start the runtime `/info` connection if it has not been started yet.\n *\n * Intended to be driven from a host's commit-phase effect when the core was\n * constructed with {@link CopilotKitCoreConfig.deferInitialConnection}. Safe\n * to call repeatedly — it is a no-op once a connection is in progress or\n * settled, so a double-invoked mount effect (React StrictMode) collapses to a\n * single request. See #5801.\n */\n connect(): void {\n this.agentRegistry.connectRuntime();\n }\n\n get runtimeTransport(): CopilotRuntimeTransport {\n return this.agentRegistry.runtimeTransport;\n }\n\n setRuntimeTransport(runtimeTransport: CopilotRuntimeTransport): void {\n this.agentRegistry.setRuntimeTransport(runtimeTransport);\n }\n\n get runtimeVersion(): string | undefined {\n return this.agentRegistry.runtimeVersion;\n }\n\n get headers(): Readonly<Record<string, string>> {\n return this._headers;\n }\n\n get credentials(): RequestCredentials | undefined {\n return this._credentials;\n }\n\n get properties(): Readonly<Record<string, unknown>> {\n return this._properties;\n }\n\n /**\n * Default throttle interval (ms) used by `subscribeToAgentWithOptions()`\n * when the caller does not specify an explicit `throttleMs`.\n * `undefined` means no default is configured; `0` means no throttling.\n */\n get defaultThrottleMs(): number | undefined {\n return this._defaultThrottleMs;\n }\n\n /**\n * Set the default throttle interval (ms) for `subscribeToAgentWithOptions()`.\n *\n * Accepts a non-negative finite number or `undefined` (to clear the\n * default). Invalid values (NaN, Infinity, negative) are logged as\n * errors and ignored — the previous valid value is preserved.\n */\n setDefaultThrottleMs(value: number | undefined): void {\n if (value !== undefined && (!Number.isFinite(value) || value < 0)) {\n this.logAndEmitError(\n `CopilotKitCore.setDefaultThrottleMs: value must be a non-negative finite number or undefined, ` +\n `got ${value}. Keeping current value (${this._defaultThrottleMs}).`,\n {\n error: new Error(\n `setDefaultThrottleMs: invalid value (${value}), keeping current value (${this._defaultThrottleMs})`,\n ),\n code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,\n context: { value, currentValue: this._defaultThrottleMs },\n },\n );\n return;\n }\n this._defaultThrottleMs = value;\n }\n\n get debug(): DebugConfig | undefined {\n return this._debug;\n }\n\n setDebug(debug: DebugConfig | undefined): void {\n this._debug = debug;\n }\n\n get runtimeConnectionStatus(): CopilotKitCoreRuntimeConnectionStatus {\n return this.agentRegistry.runtimeConnectionStatus;\n }\n\n get audioFileTranscriptionEnabled(): boolean {\n return this.agentRegistry.audioFileTranscriptionEnabled;\n }\n\n get runtimeMode(): RuntimeMode {\n return this.agentRegistry.runtimeMode;\n }\n\n get intelligence(): IntelligenceRuntimeInfo | undefined {\n return this.agentRegistry.intelligence;\n }\n\n get threadEndpoints(): ThreadEndpointRuntimeInfo | undefined {\n return this.agentRegistry.threadEndpoints;\n }\n\n get suggestions(): boolean | undefined {\n return this.agentRegistry.suggestions;\n }\n\n get a2uiEnabled(): boolean {\n return this.agentRegistry.a2uiEnabled;\n }\n\n /**\n * Agent ids the runtime applies A2UI to. `undefined` means A2UI applies to\n * every agent (or is disabled — check `a2uiEnabled`).\n */\n get a2uiAgents(): string[] | undefined {\n return this.agentRegistry.a2uiAgents;\n }\n\n get openGenerativeUIEnabled(): boolean {\n return this.agentRegistry.openGenerativeUIEnabled;\n }\n\n get licenseStatus(): RuntimeLicenseStatus | undefined {\n return this.agentRegistry.licenseStatus;\n }\n\n get telemetryDisabled(): boolean {\n return this.agentRegistry.telemetryDisabled;\n }\n\n /**\n * Configuration updates\n */\n /**\n * Replace the headers sent with every runtime request.\n *\n * This is an overwrite, not a merge — the supplied object becomes the\n * complete header set. Entries whose value is `null` or `undefined` are\n * dropped, which is how you clear a header (e.g. removing `Authorization`\n * on logout) without leaving an empty-string value behind:\n *\n * ```ts\n * copilotkit.setHeaders({\n * ...copilotkit.headers,\n * Authorization: token ? `Bearer ${token}` : null,\n * });\n * ```\n *\n * The resulting header set is also re-applied to every agent in the registry\n * and `onHeadersChanged` subscribers are notified. These headers are merged\n * ON TOP of the headers each `HttpAgent` was constructed with, so per-agent\n * headers (e.g. an `Authorization` for a self-hosted backend) are preserved;\n * on a key conflict the core-level value wins.\n *\n * Because the agent's construction-time headers form the merge baseline, this\n * method can override a per-agent header but cannot REMOVE one: clearing a\n * core key here only drops the core-level override, after which the agent's\n * own value (if any) re-surfaces. To change a header an agent was constructed\n * with, set it at the provider/core level instead of on the agent, or update\n * it on the agent directly. The clear-on-logout pattern above is for\n * core-level headers.\n */\n setHeaders(headers: Record<string, string | null | undefined>): void {\n this._headers = normalizeHeaders(headers);\n if (this._memoryStore) this.syncMemoryContext();\n this.agentRegistry.applyHeadersToAgents(\n this.agentRegistry.agents as Record<string, AbstractAgent>,\n );\n void this.notifySubscribers(\n (subscriber) =>\n subscriber.onHeadersChanged?.({\n copilotkit: this,\n headers: this.headers,\n }),\n \"Subscriber onHeadersChanged error:\",\n );\n }\n\n setCredentials(credentials: RequestCredentials | undefined): void {\n this._credentials = credentials;\n this.agentRegistry.applyCredentialsToAgents(\n this.agentRegistry.agents as Record<string, AbstractAgent>,\n );\n }\n\n setProperties(properties: Record<string, unknown>): void {\n this._properties = properties;\n void this.notifySubscribers(\n (subscriber) =>\n subscriber.onPropertiesChanged?.({\n copilotkit: this,\n properties: this.properties,\n }),\n \"Subscriber onPropertiesChanged error:\",\n );\n }\n\n /**\n * Agent management (delegated to AgentRegistry)\n */\n setAgents__unsafe_dev_only(agents: Record<string, AbstractAgent>): void {\n this.agentRegistry.setAgents__unsafe_dev_only(agents);\n }\n\n addAgent__unsafe_dev_only(params: CopilotKitCoreAddAgentParams): void {\n this.agentRegistry.addAgent__unsafe_dev_only(params);\n }\n\n removeAgent__unsafe_dev_only(id: string): void {\n this.agentRegistry.removeAgent__unsafe_dev_only(id);\n }\n\n /**\n * Register a proxied agent against an existing runtime agent. The proxy is\n * exposed under `agentId` (local registry id) and routes outbound runtime\n * requests to `runtimeAgentId`. Throws if `agentId` is already taken.\n *\n * Returns the minted proxy and an `unregister` handle for cleanup.\n *\n * Use this to mount multiple frontend agents against a single runtime\n * agent (e.g. one per chat window) without implicit per-thread cloning.\n *\n * @example\n * const { agent, unregister } = copilotkit.registerProxiedAgent({\n * agentId: \"chat-1\",\n * runtimeAgentId: \"default\",\n * });\n * // ... <CopilotChat agentId=\"chat-1\" />\n * // on cleanup:\n * unregister();\n */\n registerProxiedAgent(\n params: CopilotKitCoreRegisterProxiedAgentParams,\n ): CopilotKitCoreRegisterProxiedAgentResult {\n return this.agentRegistry.registerProxiedAgent(params);\n }\n\n getAgent(id: string): AbstractAgent | undefined {\n return this.agentRegistry.getAgent(id);\n }\n\n /**\n * Re-apply the current headers to a single agent (delegated to\n * AgentRegistry). Core headers are merged on top of the agent's own\n * construction-time headers rather than replacing them, so headers\n * configured directly on an `HttpAgent` (e.g. an `Authorization` for a\n * self-hosted backend) survive header updates instead of being silently\n * dropped (see #5635). On a key conflict the core-level value wins.\n *\n * The merge baseline is the agent's headers as captured the first time the\n * agent is applied (at registration), so the way to change headers\n * afterwards is `setHeaders` (which re-applies to every agent), not mutating\n * `agent.headers` directly — a direct mutation is overwritten on the next\n * re-apply.\n */\n applyHeadersToAgent(agent: AbstractAgent): void {\n this.agentRegistry.applyHeadersToAgent(agent);\n }\n\n /**\n * Context management (delegated to ContextStore).\n * Pass `agentIds` to restrict the entry to runs of specific agents;\n * omit it for context every agent should receive.\n */\n addContext(context: ScopedContext): string {\n return this.contextStore.addContext(context);\n }\n\n removeContext(id: string): void {\n this.contextStore.removeContext(id);\n }\n\n /**\n * Build the context array for a run of the given agent, dropping entries\n * scoped to other agents and stripping the scoping metadata.\n */\n getContextForAgent(agentId?: string): Context[] {\n return this.contextStore.getContextForAgent(agentId);\n }\n\n /**\n * Thread store registry (delegated to ThreadStoreRegistry)\n */\n registerThreadStore(agentId: string, store: ɵThreadStore): void {\n this.threadStoreRegistry.register(agentId, store);\n }\n\n unregisterThreadStore(agentId: string): void {\n this.threadStoreRegistry.unregister(agentId);\n }\n\n getThreadStore(agentId: string): ɵThreadStore | undefined {\n return this.threadStoreRegistry.get(agentId);\n }\n\n getThreadStores(): Readonly<Record<string, ɵThreadStore>> {\n return this.threadStoreRegistry.getAll();\n }\n\n /**\n * Returns the single core-owned, user-scoped memory store, creating and\n * starting it on first access. Unlike thread stores, memory is not scoped per\n * agent: there is exactly one store whose runtime context the core wires\n * itself (see `syncMemoryContext`), so consumers (e.g. a `useMemories`\n * binding) just read this store rather than registering one.\n */\n getMemoryStore(): ɵMemoryStore {\n return this.ensureMemoryStore();\n }\n\n /**\n * Lazily creates, starts, and context-syncs the core-owned memory store on\n * first access, then returns it. Subsequent calls return the existing store.\n * The store is constructed with a bound `globalThis.fetch` and immediately\n * has its runtime context synced from the current connection state.\n */\n private ensureMemoryStore(): ɵMemoryStore {\n if (!this._memoryStore) {\n this._memoryStore = ɵcreateMemoryStore({\n fetch: globalThis.fetch.bind(globalThis),\n });\n this._memoryStore.start();\n this.syncMemoryContext();\n }\n return this._memoryStore;\n }\n\n /**\n * Pushes the current runtime wiring into the memory store. When the runtime\n * is connected and both the intelligence WebSocket URL and runtime URL are\n * available, the store receives a context (runtime URL, WebSocket URL, and a\n * copy of the current headers); otherwise its context is cleared. No-op when\n * the store has not been created yet.\n */\n private syncMemoryContext(): void {\n if (!this._memoryStore) return;\n if (\n this.runtimeConnectionStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Connected &&\n this.intelligence?.wsUrl &&\n this.runtimeUrl\n ) {\n this._memoryStore.setContext({\n runtimeUrl: this.runtimeUrl,\n wsUrl: this.intelligence.wsUrl,\n headers: { ...this.headers },\n });\n } else {\n this._memoryStore.setContext(null);\n }\n }\n\n /**\n * Suggestions management (delegated to SuggestionEngine)\n */\n addSuggestionsConfig(config: SuggestionsConfig): string {\n return this.suggestionEngine.addSuggestionsConfig(config);\n }\n\n removeSuggestionsConfig(id: string): void {\n this.suggestionEngine.removeSuggestionsConfig(id);\n }\n\n reloadSuggestions(agentId: string): void {\n this.suggestionEngine.reloadSuggestions(agentId);\n }\n\n clearSuggestions(agentId: string): void {\n this.suggestionEngine.clearSuggestions(agentId);\n }\n\n getSuggestions(agentId: string): CopilotKitCoreGetSuggestionsResult {\n return this.suggestionEngine.getSuggestions(agentId);\n }\n\n /**\n * Tool management (delegated to RunHandler)\n */\n addTool<T extends Record<string, unknown> = Record<string, unknown>>(\n tool: FrontendTool<T>,\n ): void {\n this.runHandler.addTool(tool);\n }\n\n removeTool(id: string, agentId?: string): void {\n this.runHandler.removeTool(id, agentId);\n }\n\n getTool(params: CopilotKitCoreGetToolParams): FrontendTool<any> | undefined {\n return this.runHandler.getTool(params);\n }\n\n setTools(tools: FrontendTool<any>[]): void {\n this.runHandler.setTools(tools);\n }\n\n /**\n * Subscription lifecycle\n */\n subscribe(subscriber: CopilotKitCoreSubscriber): CopilotKitCoreSubscription {\n this.subscribers.add(subscriber);\n\n // Return subscription with unsubscribe method\n return {\n unsubscribe: () => {\n this.subscribers.delete(subscriber);\n },\n };\n }\n\n /**\n * Subscribe to an agent's notification and lifecycle events with\n * optional configuration (e.g. throttling).\n *\n * Wraps every callback with error protection (`safeCall`) and applies\n * the options before delegating to `agent.subscribe()`.\n *\n * See {@link SubscribeToAgentSubscriber} for the accepted callback subset\n * and the rationale for excluding AG-UI event handlers.\n */\n subscribeToAgentWithOptions(\n agent: AbstractAgent,\n subscriber: SubscribeToAgentSubscriber,\n options?: SubscribeToAgentOptions,\n ): CopilotKitCoreSubscription {\n const resolved = options?.throttleMs ?? this._defaultThrottleMs ?? 0;\n\n let effectiveMs = 0;\n if (!Number.isFinite(resolved) || resolved < 0) {\n const source =\n options?.throttleMs !== undefined ? \"throttleMs\" : \"defaultThrottleMs\";\n this.logAndEmitError(\n `CopilotKitCore.subscribeToAgentWithOptions: ${source} must be a non-negative finite number, ` +\n `got ${resolved}. Falling back to unthrottled.`,\n {\n error: new Error(\n `subscribeToAgentWithOptions: invalid ${source} (${resolved}), falling back to unthrottled`,\n ),\n code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,\n context: { agentId: agent.agentId, source, value: resolved },\n },\n );\n } else {\n effectiveMs = resolved;\n }\n\n const agentLabel = agent.agentId || \"(unknown agent)\";\n\n // Wraps a callback so that synchronous throws and async rejections are\n // caught, logged, and emitted — preventing one failing callback from\n // corrupting the agent's notification loop.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const safeCall = <F extends (...args: any[]) => any>(\n label: string,\n fn: F,\n ...args: Parameters<F>\n ): any => {\n const reportError = (err: unknown, verb: string) => {\n this.logAndEmitError(\n `CopilotKitCore.subscribeToAgentWithOptions[${agentLabel}]: ${label} callback ${verb}:`,\n {\n error: err instanceof Error ? err : new Error(String(err)),\n code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,\n context: { agentId: agent.agentId, callback: label },\n },\n );\n };\n try {\n const result = fn(...args);\n if (result instanceof Promise) {\n return result.catch((err: unknown) => {\n reportError(err, \"rejected\");\n });\n }\n return result;\n } catch (err) {\n reportError(err, \"threw\");\n }\n };\n\n const guardAll = (\n sub: SubscribeToAgentSubscriber,\n ): SubscribeToAgentSubscriber => {\n const guarded: SubscribeToAgentSubscriber = {};\n if (sub.onMessagesChanged) {\n const fn = sub.onMessagesChanged;\n guarded.onMessagesChanged = (params) =>\n safeCall(\"onMessagesChanged\", fn, params);\n }\n if (sub.onStateChanged) {\n const fn = sub.onStateChanged;\n guarded.onStateChanged = (params) =>\n safeCall(\"onStateChanged\", fn, params);\n }\n if (sub.onRunInitialized) {\n const fn = sub.onRunInitialized;\n guarded.onRunInitialized = (params) =>\n safeCall(\"onRunInitialized\", fn, params);\n }\n if (sub.onRunFinalized) {\n const fn = sub.onRunFinalized;\n guarded.onRunFinalized = (params) =>\n safeCall(\"onRunFinalized\", fn, params);\n }\n if (sub.onRunFailed) {\n const fn = sub.onRunFailed;\n guarded.onRunFailed = (params) => safeCall(\"onRunFailed\", fn, params);\n }\n if (sub.onRunErrorEvent) {\n const fn = sub.onRunErrorEvent;\n guarded.onRunErrorEvent = (params) =>\n safeCall(\"onRunErrorEvent\", fn, params);\n }\n return guarded;\n };\n\n // Warn about unsupported keys so JS / `as any` consumers get diagnostics.\n for (const key of Object.keys(subscriber)) {\n if (\n typeof (subscriber as Record<string, unknown>)[key] === \"function\" &&\n !(ALLOWED_KEYS as ReadonlySet<string>).has(key)\n ) {\n const message =\n `CopilotKitCore.subscribeToAgentWithOptions[${agentLabel}]: callback \"${key}\" is not supported ` +\n `and was dropped. Supported callbacks: ${Array.from(ALLOWED_KEYS).join(\", \")}. ` +\n `Use agent.subscribe() directly for event handlers and per-item notifications.`;\n this.logAndEmitError(\n message,\n {\n error: new Error(message),\n code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,\n context: { agentId: agent.agentId, droppedCallback: key },\n },\n \"warn\",\n );\n }\n }\n\n // No throttle — guard callbacks and subscribe directly.\n if (effectiveMs <= 0) {\n const subscription = agent.subscribe(guardAll(subscriber));\n return { unsubscribe: () => subscription.unsubscribe() };\n }\n\n // Throttled path: lifecycle callbacks fire immediately; onMessagesChanged\n // and onStateChanged share a single Throttler that flushes the latest\n // params for both channels.\n let active = true;\n let latestMessagesParams:\n | Parameters<\n NonNullable<SubscribeToAgentSubscriber[\"onMessagesChanged\"]>\n >[0]\n | null = null;\n let latestStateParams:\n | Parameters<NonNullable<SubscribeToAgentSubscriber[\"onStateChanged\"]>>[0]\n | null = null;\n\n const flushPending = () => {\n if (active && subscriber.onMessagesChanged && latestMessagesParams) {\n const params = latestMessagesParams;\n latestMessagesParams = null;\n safeCall(\"onMessagesChanged\", subscriber.onMessagesChanged, params);\n }\n if (active && subscriber.onStateChanged && latestStateParams) {\n const params = latestStateParams;\n latestStateParams = null;\n safeCall(\"onStateChanged\", subscriber.onStateChanged, params);\n }\n };\n\n const throttler = new Throttler(flushPending, {\n wait: effectiveMs,\n leading: true,\n trailing: true,\n });\n\n // Lifecycle callbacks are guarded but never throttled.\n const lifecycleOnly: SubscribeToAgentSubscriber = {};\n if (subscriber.onRunInitialized)\n lifecycleOnly.onRunInitialized = subscriber.onRunInitialized;\n if (subscriber.onRunFinalized)\n lifecycleOnly.onRunFinalized = subscriber.onRunFinalized;\n if (subscriber.onRunFailed)\n lifecycleOnly.onRunFailed = subscriber.onRunFailed;\n if (subscriber.onRunErrorEvent)\n lifecycleOnly.onRunErrorEvent = subscriber.onRunErrorEvent;\n\n const wrappedSubscriber: SubscribeToAgentSubscriber =\n guardAll(lifecycleOnly);\n\n if (subscriber.onMessagesChanged) {\n wrappedSubscriber.onMessagesChanged = (params) => {\n latestMessagesParams = params;\n throttler.maybeExecute();\n };\n }\n\n if (subscriber.onStateChanged) {\n wrappedSubscriber.onStateChanged = (params) => {\n latestStateParams = params;\n throttler.maybeExecute();\n };\n }\n\n const subscription = agent.subscribe(wrappedSubscriber);\n\n return {\n unsubscribe: () => {\n active = false;\n throttler.cancel();\n subscription.unsubscribe();\n },\n };\n }\n\n /**\n * Agent connectivity (delegated to RunHandler)\n */\n async connectAgent(\n params: CopilotKitCoreConnectAgentParams,\n ): Promise<import(\"@ag-ui/client\").RunAgentResult> {\n return this.runHandler.connectAgent(params);\n }\n\n stopAgent(params: CopilotKitCoreStopAgentParams): void {\n this.runHandler.abortCurrentRun();\n params.agent.abortRun();\n }\n\n async runAgent(\n params: CopilotKitCoreRunAgentParams,\n ): Promise<import(\"@ag-ui/client\").RunAgentResult> {\n return this.runHandler.runAgent(params);\n }\n\n /**\n * Programmatically execute a registered frontend tool without going through an LLM turn.\n * The handler runs, render components show up in the UI, and both the tool call and\n * result messages are added to `agent.messages`.\n */\n async runTool(\n params: CopilotKitCoreRunToolParams,\n ): Promise<CopilotKitCoreRunToolResult> {\n return this.runHandler.runTool(params);\n }\n\n /**\n * State management (delegated to StateManager)\n */\n getStateByRun(\n agentId: string,\n threadId: string,\n runId: string,\n ): State | undefined {\n return this.stateManager.getStateByRun(agentId, threadId, runId);\n }\n\n getRunIdForMessage(\n agentId: string,\n threadId: string,\n messageId: string,\n ): string | undefined {\n return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);\n }\n\n getRunIdsForThread(agentId: string, threadId: string): string[] {\n return this.stateManager.getRunIdsForThread(agentId, threadId);\n }\n\n /**\n * Internal method used by RunHandler to build frontend tools\n */\n private buildFrontendTools(agentId?: string): import(\"@ag-ui/client\").Tool[] {\n return this.runHandler.buildFrontendTools(agentId);\n }\n\n /**\n * Called before each follow-up agent run (after tool execution).\n *\n * When a frontend tool handler calls framework state setters (e.g. React's\n * setState), those updates are batched and deferred — they do not take effect\n * until the framework's scheduler runs (React uses MessageChannel).\n * useAgentContext registers context via useLayoutEffect, which runs\n * synchronously after React commits that deferred batch.\n *\n * Without yielding here, the follow-up runAgent reads the context store\n * synchronously while the deferred updates are still pending, producing stale\n * context for the next agent turn.\n *\n * Override in framework-specific subclasses to yield to the framework\n * scheduler before the follow-up run. The base implementation is a no-op\n * because non-React environments have no deferred state to flush.\n */\n async waitForPendingFrameworkUpdates(): Promise<void> {}\n}\n","import type { AbstractAgent, ToolCall } from \"@ag-ui/client\";\nimport type {\n IntelligenceRuntimeInfo,\n RuntimeMode,\n RuntimeLicenseStatus,\n ThreadEndpointRuntimeInfo,\n} from \"@copilotkit/shared\";\nimport type { StandardSchemaV1 } from \"@copilotkit/shared\";\n\n/**\n * Status of a tool call execution\n */\nexport enum ToolCallStatus {\n InProgress = \"inProgress\",\n Executing = \"executing\",\n Complete = \"complete\",\n}\n\nexport type CopilotRuntimeTransport = \"rest\" | \"single\" | \"auto\";\nexport type {\n RuntimeMode,\n IntelligenceRuntimeInfo,\n RuntimeLicenseStatus,\n ThreadEndpointRuntimeInfo,\n};\n\n/**\n * Context passed to a frontend tool handler\n */\nexport type FrontendToolHandlerContext = {\n toolCall: ToolCall;\n agent: AbstractAgent;\n /** Aborted when `stopAgent()` is called. Handlers can check `signal.aborted`\n * or pass the signal to fetch/setTimeout to cooperatively cancel. */\n signal?: AbortSignal;\n};\n\nexport type FrontendTool<\n T extends Record<string, unknown> = Record<string, unknown>,\n> = {\n name: string;\n description?: string;\n parameters?: StandardSchemaV1<any, T>;\n handler?: (args: T, context: FrontendToolHandlerContext) => Promise<unknown>;\n followUp?: boolean;\n /**\n * Optional agent ID to constrain this tool to a specific agent.\n * If specified, this tool will only be available to the specified agent.\n */\n agentId?: string;\n /**\n * Whether this tool is available to the agent.\n * Set to false to hide the tool from the agent without unregistering it.\n * Defaults to true when not specified.\n */\n available?: boolean;\n};\n\nexport type Suggestion = {\n title: string;\n message: string;\n /** Indicates whether this suggestion is still being generated. */\n isLoading: boolean;\n /** Optional CSS class name applied to the suggestion pill. */\n className?: string;\n};\n\nexport type SuggestionAvailability =\n | \"before-first-message\"\n | \"after-first-message\"\n | \"always\"\n | \"disabled\";\n\nexport type DynamicSuggestionsConfig = {\n /**\n * A prompt or instructions for the GPT to generate suggestions.\n */\n instructions: string;\n /**\n * The minimum number of suggestions to generate. Defaults to `1`.\n * @default 1\n */\n minSuggestions?: number;\n /**\n * The maximum number of suggestions to generate. Defaults to `3`.\n * @default 1\n */\n maxSuggestions?: number;\n\n /**\n * When the suggestions are available. Defaults to \"after-first-message\".\n */\n available?: SuggestionAvailability;\n\n /**\n * The agent ID of the provider of the suggestions. Defaults to `\"default\"`.\n */\n providerAgentId?: string;\n\n /**\n * The agent ID of the consumer of the suggestions. Defaults to `\"*\"` (all agents).\n */\n consumerAgentId?: string;\n};\n\nexport type StaticSuggestionsConfig = {\n /**\n * The suggestions to display.\n */\n suggestions: Omit<Suggestion, \"isLoading\">[];\n\n /**\n * When the suggestions are available. Defaults to \"before-first-message\".\n */\n available?: SuggestionAvailability;\n\n /**\n * The agent ID of the consumer of the suggestions. Defaults to `\"*\"` (all agents).\n */\n consumerAgentId?: string;\n};\n\nexport type SuggestionsConfig =\n | DynamicSuggestionsConfig\n | StaticSuggestionsConfig;\n","export function completePartialMarkdown(input: string): string {\n let s = input;\n\n // Handle code fences first - use FIRST unmatched fence for proper nesting\n const fenceMatches = Array.from(s.matchAll(/^(\\s*)(`{3,}|~{3,})/gm));\n if (fenceMatches.length % 2 === 1) {\n const [, indent, fence] = fenceMatches[0]!;\n s += `\\n${indent}${fence}`;\n }\n\n // Identify incomplete links at the end and close them\n const incompleteLinkMatch = s.match(/\\[([^\\]]*)\\]\\(([^)]*)$/);\n if (incompleteLinkMatch) {\n s += \")\";\n }\n\n // State-based parsing\n interface OpenElement {\n type: string;\n marker: string;\n position: number;\n }\n\n const openElements: OpenElement[] = [];\n const chars = Array.from(s);\n\n // First pass: identify code block boundaries and inline code to avoid processing their content\n const codeBlockRanges: Array<{ start: number; end: number }> = [];\n const inlineCodeRanges: Array<{ start: number; end: number }> = [];\n\n // Find code block ranges\n let tempCodeFenceCount = 0;\n let currentCodeBlockStart = -1;\n\n for (let i = 0; i < chars.length; i++) {\n if (i === 0 || chars[i - 1] === \"\\n\") {\n const lineMatch = s.substring(i).match(/^(\\s*)(`{3,}|~{3,})/);\n if (lineMatch) {\n tempCodeFenceCount++;\n if (tempCodeFenceCount % 2 === 1) {\n currentCodeBlockStart = i;\n } else if (currentCodeBlockStart !== -1) {\n codeBlockRanges.push({\n start: currentCodeBlockStart,\n end: i + lineMatch[0].length,\n });\n currentCodeBlockStart = -1;\n }\n i += lineMatch[0].length - 1;\n }\n }\n }\n\n // Find inline code ranges\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] === \"`\") {\n // Check if escaped\n let backslashCount = 0;\n for (let j = i - 1; j >= 0 && chars[j] === \"\\\\\"; j--) {\n backslashCount++;\n }\n if (backslashCount % 2 === 0) {\n // Not escaped - find the closing backtick\n for (let j = i + 1; j < chars.length; j++) {\n if (chars[j] === \"`\") {\n let closingBackslashCount = 0;\n for (let k = j - 1; k >= 0 && chars[k] === \"\\\\\"; k--) {\n closingBackslashCount++;\n }\n if (closingBackslashCount % 2 === 0) {\n inlineCodeRanges.push({ start: i, end: j + 1 });\n i = j;\n break;\n }\n }\n }\n }\n }\n }\n\n // Helper function to check if position is in code\n const isInCode = (pos: number): boolean => {\n return (\n codeBlockRanges.some((range) => pos >= range.start && pos < range.end) ||\n inlineCodeRanges.some((range) => pos >= range.start && pos < range.end)\n );\n };\n\n // Second pass: process markdown elements, skipping code regions\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i];\n const nextChar = chars[i + 1];\n const prevChar = chars[i - 1];\n\n if (isInCode(i)) {\n continue;\n }\n\n // Handle brackets (but not if they're part of already-complete links)\n if (char === \"[\") {\n // Check if this is part of a complete link [text](url)\n let isCompleteLink = false;\n let bracketDepth = 1;\n let j = i + 1;\n\n // Find the matching ]\n while (j < chars.length && bracketDepth > 0) {\n if (chars[j] === \"[\" && !isInCode(j)) bracketDepth++;\n if (chars[j] === \"]\" && !isInCode(j)) bracketDepth--;\n j++;\n }\n\n // Check if followed by (\n if (bracketDepth === 0 && chars[j] === \"(\") {\n // Find the closing )\n let parenDepth = 1;\n j++;\n while (j < chars.length && parenDepth > 0) {\n if (chars[j] === \"(\" && !isInCode(j)) parenDepth++;\n if (chars[j] === \")\" && !isInCode(j)) parenDepth--;\n j++;\n }\n if (parenDepth === 0) {\n isCompleteLink = true;\n i = j - 1;\n continue;\n }\n }\n\n // This is a standalone bracket, treat as markdown\n if (!isCompleteLink) {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"bracket\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({ type: \"bracket\", marker: \"[\", position: i });\n }\n }\n }\n\n // Handle double emphasis first (**, __, ~~) - these take precedence\n else if (char === \"*\" && nextChar === \"*\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"bold_star\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({ type: \"bold_star\", marker: \"**\", position: i });\n }\n i++; // Skip next character\n } else if (char === \"_\" && nextChar === \"_\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"bold_underscore\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({\n type: \"bold_underscore\",\n marker: \"__\",\n position: i,\n });\n }\n i++; // Skip next character\n } else if (char === \"~\" && nextChar === \"~\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"strike\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({ type: \"strike\", marker: \"~~\", position: i });\n }\n i++; // Skip next character\n }\n\n // Handle single emphasis (*, _) - only if not part of double\n else if (char === \"*\" && prevChar !== \"*\" && nextChar !== \"*\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"italic_star\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({ type: \"italic_star\", marker: \"*\", position: i });\n }\n } else if (char === \"_\" && prevChar !== \"_\" && nextChar !== \"_\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"italic_underscore\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({\n type: \"italic_underscore\",\n marker: \"_\",\n position: i,\n });\n }\n }\n }\n\n // Handle remaining unmatched backticks (outside of inline code ranges)\n let backtickCount = 0;\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] === \"`\" && !isInCode(i)) {\n backtickCount++;\n }\n }\n if (backtickCount % 2 === 1) {\n s += \"`\";\n }\n\n // Close remaining open elements in reverse order (LIFO stack semantics)\n openElements.sort((a, b) => b.position - a.position);\n\n const closers = openElements.map((el) => {\n switch (el.type) {\n case \"bracket\":\n return \"]\";\n case \"bold_star\":\n return \"**\";\n case \"bold_underscore\":\n return \"__\";\n case \"strike\":\n return \"~~\";\n case \"italic_star\":\n return \"*\";\n case \"italic_underscore\":\n return \"_\";\n default:\n return \"\";\n }\n });\n\n let result = s + closers.join(\"\");\n\n // Handle parentheses ONLY if not inside code\n const finalFenceMatches = Array.from(\n result.matchAll(/^(\\s*)(`{3,}|~{3,})/gm),\n );\n const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;\n const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;\n\n let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;\n\n if (shouldCloseParens) {\n const lastOpenParen = result.lastIndexOf(\"(\");\n if (lastOpenParen !== -1) {\n // Check if this paren is inside a backtick pair\n const beforeParen = result.substring(0, lastOpenParen);\n const backticksBeforeParen = (beforeParen.match(/`/g) || []).length;\n if (backticksBeforeParen % 2 === 1) {\n shouldCloseParens = false;\n }\n }\n }\n\n if (shouldCloseParens) {\n const openParens = (result.match(/\\(/g) || []).length;\n const closeParens = (result.match(/\\)/g) || []).length;\n if (openParens > closeParens) {\n result += \")\".repeat(openParens - closeParens);\n }\n }\n\n return result;\n}\n","import { phoenixExponentialBackoff } from \"@copilotkit/shared\";\nimport type { Subscription } from \"rxjs\";\nimport { defer, firstValueFrom, merge, Observable, of } from \"rxjs\";\nimport {\n catchError,\n filter,\n map,\n mergeMap,\n share,\n shareReplay,\n switchMap,\n take,\n takeUntil,\n tap,\n timeout,\n withLatestFrom,\n} from \"rxjs/operators\";\nimport {\n createActionGroup,\n createEffect,\n createReducer,\n createSelector,\n createStore,\n empty,\n ofType,\n on,\n props,\n} from \"./utils/micro-redux\";\nimport type { Reducer, Store } from \"./utils/micro-redux\";\nimport {\n ɵphoenixChannel$,\n ɵphoenixSocket$,\n ɵobservePhoenixEvent$,\n ɵobservePhoenixJoinOutcome$,\n ɵobservePhoenixSocketHealth$,\n ɵobservePhoenixSocketSignals$,\n} from \"./utils/phoenix-observable\";\nimport type { ɵPhoenixChannelSession } from \"./utils/phoenix-observable\";\n\nconst THREADS_CHANNEL_EVENT = \"thread_metadata\";\nconst THREAD_RUN_ACTIVITY_CHANNEL_EVENT = \"thread_run_activity\";\nconst THREAD_SUBSCRIBE_PATH = \"/threads/subscribe\";\nconst MAX_SOCKET_RETRIES = 5;\nconst REQUEST_TIMEOUT_MS = 15_000;\n\ninterface ThreadRecord {\n id: string;\n organizationId: string;\n agentId: string;\n createdById: string;\n name: string | null;\n archived: boolean;\n createdAt: string;\n updatedAt: string;\n lastRunAt?: string;\n}\n\ninterface ThreadRuntimeContext {\n runtimeUrl: string;\n headers: Record<string, string>;\n wsUrl?: string;\n agentId: string;\n includeArchived?: boolean;\n limit?: number;\n}\n\ntype ThreadMetadataEvent =\n | {\n operation: \"created\" | \"renamed\" | \"archived\" | \"unarchived\" | \"updated\";\n threadId: string;\n userId: string;\n organizationId: string;\n occurredAt: string;\n thread: ThreadRecord;\n }\n | {\n operation: \"deleted\";\n threadId: string;\n userId: string;\n organizationId: string;\n occurredAt: string;\n deleted: {\n id: string;\n };\n };\n\n/**\n * Internal notification emitted when Intelligence observes new run activity\n * for a thread without changing that thread's metadata row.\n */\nexport type ThreadRunActivityNotification = {\n type: \"thread_run_activity\";\n threadId: string;\n agentId?: string;\n runId?: string;\n eventType: string;\n latestEventId?: string;\n};\n\ntype ThreadRunActivityGatewayPayload = {\n threadId?: unknown;\n thread_id?: unknown;\n agentId?: unknown;\n agent_id?: unknown;\n runId?: unknown;\n run_id?: unknown;\n eventType?: unknown;\n event_type?: unknown;\n latestEventId?: unknown;\n latest_event_id?: unknown;\n};\n\ninterface ThreadListResponse {\n threads: ThreadRecord[];\n joinCode?: string | null;\n nextCursor?: string | null;\n}\n\ninterface ThreadMetadataCredentialsResponse {\n joinToken: string;\n}\n\ninterface MutationRequest {\n requestId: string;\n /** Session the mutation was dispatched in; stale results are dropped. */\n sessionId: number;\n path: string;\n method: \"PATCH\" | \"POST\" | \"DELETE\";\n body: Record<string, unknown>;\n}\n\ntype MutationOutcome =\n | { requestId: string; sessionId: number; ok: true }\n | { requestId: string; sessionId: number; ok: false; error: Error };\n\ninterface ThreadEnvironment {\n fetch: typeof fetch;\n /**\n * Optional callback invoked whenever a thread mutation (rename, archive,\n * unarchive, delete) is rejected by the server. Lets framework wrappers\n * surface a transient error toast without subscribing to the error\n * selector. The error is also recorded in `state.error` regardless.\n *\n * Fired after any rollback (delete) has been applied to local state.\n */\n onError?: (error: Error) => void;\n}\n\ninterface ThreadState {\n threads: ThreadRecord[];\n isLoading: boolean;\n isFetchingNextPage: boolean;\n error: Error | null;\n /**\n * Error from the most recent failed next-page (`fetchMore`) load, or `null`.\n * Tracked SEPARATELY from `error` so a paginated-load failure surfaces an\n * inline \"couldn't load more\" affordance without replacing the already-loaded\n * list with a full-panel error. Cleared when a fetch-more is retried or when\n * one succeeds; reset on context change / stop.\n */\n fetchMoreError: Error | null;\n context: ThreadRuntimeContext | null;\n sessionId: number;\n metadataCredentialsRequested: boolean;\n metadataJoinCode: string | null;\n nextCursor: string | null;\n /** Number of thread mutations currently awaiting a server response. */\n inFlightMutationCount: number;\n /**\n * Rows optimistically removed by an in-flight `delete`, keyed by the\n * originating request id. DELETE is the one mutation that rolls back on\n * rejection, so the removed row is parked here and restored if the server\n * rejects. Rename/archive/unarchive are optimistic no-rollback and do not\n * populate this map.\n */\n pendingDeletes: Record<string, ThreadRecord>;\n}\n\nconst initialThreadState: ThreadState = {\n threads: [],\n isLoading: false,\n isFetchingNextPage: false,\n error: null,\n fetchMoreError: null,\n context: null,\n sessionId: 0,\n metadataCredentialsRequested: false,\n metadataJoinCode: null,\n nextCursor: null,\n inFlightMutationCount: 0,\n pendingDeletes: {},\n};\n\nconst threadAdapterEvents = createActionGroup(\"Thread Adapter\", {\n started: empty(),\n stopped: empty(),\n contextChanged: props<{ context: ThreadRuntimeContext | null }>(),\n fetchNextPageRequested: empty(),\n renameRequested: props<{\n requestId: string;\n threadId: string;\n name: string;\n }>(),\n archiveRequested: props<{ requestId: string; threadId: string }>(),\n unarchiveRequested: props<{ requestId: string; threadId: string }>(),\n deleteRequested: props<{ requestId: string; threadId: string }>(),\n newThreadStarted: empty(),\n});\n\nconst threadRestEvents = createActionGroup(\"Thread REST\", {\n listRequested: props<{ sessionId: number }>(),\n listSucceeded: props<{\n sessionId: number;\n threads: ThreadRecord[];\n joinCode: string | null;\n nextCursor: string | null;\n }>(),\n listFailed: props<{ sessionId: number; error: Error }>(),\n nextPageSucceeded: props<{\n sessionId: number;\n threads: ThreadRecord[];\n nextCursor: string | null;\n }>(),\n nextPageFailed: props<{ sessionId: number; error: Error }>(),\n metadataCredentialsRequested: props<{ sessionId: number }>(),\n metadataCredentialsSucceeded: props<{\n sessionId: number;\n joinToken: string;\n }>(),\n metadataCredentialsFailed: props<{ sessionId: number; error: Error }>(),\n mutationFinished: props<{ outcome: MutationOutcome }>(),\n});\n\nconst threadSocketEvents = createActionGroup(\"Thread Socket\", {\n opened: props<{ sessionId: number }>(),\n errored: props<{ sessionId: number }>(),\n joinFailed: props<{ sessionId: number }>(),\n joinTimedOut: props<{ sessionId: number }>(),\n metadataReceived: props<{\n sessionId: number;\n payload: ThreadMetadataEvent;\n }>(),\n runActivityReceived: props<{\n sessionId: number;\n notification: ThreadRunActivityNotification;\n }>(),\n});\n\nconst threadDomainEvents = createActionGroup(\"Thread Domain\", {\n threadUpserted: props<{ sessionId: number; thread: ThreadRecord }>(),\n threadDeleted: props<{ sessionId: number; threadId: string }>(),\n});\n\nfunction sortThreadsByRecency(threads: ThreadRecord[]): ThreadRecord[] {\n // Prefer lastRunAt so the order reflects actual agent activity and stays\n // stable when a user performs metadata-only actions like archive or rename.\n // Fall back to updatedAt (and then createdAt) for threads that have never run.\n return [...threads].sort((left, right) => {\n const leftKey = left.lastRunAt ?? left.updatedAt ?? left.createdAt;\n const rightKey = right.lastRunAt ?? right.updatedAt ?? right.createdAt;\n return rightKey.localeCompare(leftKey);\n });\n}\n\nfunction upsertThread(\n threads: ThreadRecord[],\n thread: ThreadRecord,\n): ThreadRecord[] {\n const existingIndex = threads.findIndex((item) => item.id === thread.id);\n if (existingIndex === -1) {\n return sortThreadsByRecency([...threads, thread]);\n }\n\n const next = [...threads];\n next[existingIndex] = thread;\n return sortThreadsByRecency(next);\n}\n\n/**\n * Returns a non-empty string payload field or undefined for absent fields.\n */\nfunction optionalString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/**\n * Converts gateway run-activity payloads into the internal TypeScript shape.\n */\nfunction normalizeThreadRunActivityNotification(\n payload: ThreadRunActivityGatewayPayload,\n): ThreadRunActivityNotification | null {\n const threadId = optionalString(payload.threadId ?? payload.thread_id);\n const eventType = optionalString(payload.eventType ?? payload.event_type);\n\n if (!threadId || !eventType) {\n return null;\n }\n\n return {\n type: \"thread_run_activity\",\n threadId,\n agentId: optionalString(payload.agentId ?? payload.agent_id),\n runId: optionalString(payload.runId ?? payload.run_id),\n eventType,\n latestEventId: optionalString(\n payload.latestEventId ?? payload.latest_event_id,\n ),\n };\n}\n\nconst threadReducer = createReducer(\n initialThreadState,\n on(threadAdapterEvents.contextChanged, (state: ThreadState, { context }) => ({\n ...state,\n context,\n sessionId: state.sessionId + 1,\n threads: [],\n isLoading: Boolean(context),\n isFetchingNextPage: false,\n error: null,\n fetchMoreError: null,\n metadataCredentialsRequested: false,\n metadataJoinCode: null,\n nextCursor: null,\n inFlightMutationCount: 0,\n pendingDeletes: {},\n })),\n on(threadAdapterEvents.stopped, (state: ThreadState) => ({\n ...state,\n threads: [],\n isLoading: false,\n isFetchingNextPage: false,\n error: null,\n fetchMoreError: null,\n metadataCredentialsRequested: false,\n metadataJoinCode: null,\n nextCursor: null,\n inFlightMutationCount: 0,\n pendingDeletes: {},\n })),\n on(threadRestEvents.listRequested, (state: ThreadState, { sessionId }) => {\n if (sessionId !== state.sessionId || !state.context) {\n return state;\n }\n\n return {\n ...state,\n isLoading: true,\n error: null,\n // A full-list refetch supersedes any prior fetch-more failure: the whole\n // list is being reloaded, so the stale inline \"couldn't load more\" banner\n // must not survive onto the fresh list.\n fetchMoreError: null,\n };\n }),\n on(\n threadRestEvents.listSucceeded,\n (state: ThreadState, { sessionId, threads, joinCode, nextCursor }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n const joinCodeChanged = joinCode !== state.metadataJoinCode;\n\n return {\n ...state,\n threads: sortThreadsByRecency(threads),\n isLoading: false,\n error: null,\n // The fresh full list also clears any lingering fetch-more error, in\n // case the list arrived without passing through `listRequested`.\n fetchMoreError: null,\n metadataJoinCode: joinCode,\n metadataCredentialsRequested: joinCodeChanged\n ? false\n : state.metadataCredentialsRequested,\n nextCursor,\n };\n },\n ),\n on(\n threadRestEvents.listFailed,\n (state: ThreadState, { sessionId, error }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n isLoading: false,\n error,\n };\n },\n ),\n on(\n threadRestEvents.nextPageSucceeded,\n (state: ThreadState, { sessionId, threads, nextCursor }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n let merged = state.threads;\n for (const thread of threads) {\n merged = upsertThread(merged, thread);\n }\n\n return {\n ...state,\n threads: merged,\n isFetchingNextPage: false,\n // A successful next page clears any prior fetch-more error.\n fetchMoreError: null,\n nextCursor,\n };\n },\n ),\n on(\n threadRestEvents.nextPageFailed,\n (state: ThreadState, { sessionId, error }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n // A failed next-page load records the error on the DEDICATED fetch-more\n // channel — NOT `state.error` — so the already-loaded list is preserved\n // and the drawer renders an inline \"couldn't load more — retry\" panel\n // rather than replacing the whole list with a full-panel error.\n return {\n ...state,\n isFetchingNextPage: false,\n fetchMoreError: error,\n };\n },\n ),\n on(\n threadRestEvents.metadataCredentialsFailed,\n (state: ThreadState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n // Non-fatal: the metadata-credentials (realtime join-token) fetch runs\n // AFTER the thread list has already loaded and only powers the realtime\n // channel. A failure means realtime won't connect, but the fetched list\n // is still valid — so we do NOT write `state.error` (which would replace\n // the whole list with a \"couldn't load\" panel). The failure is surfaced\n // as a diagnostic warning instead (socketDiagnosticsEffect), mirroring the\n // stay-stale handling of a realtime channel join failure. Clear the\n // request latch so a later list refresh can retry realtime setup.\n return {\n ...state,\n metadataCredentialsRequested: false,\n };\n },\n ),\n on(\n threadRestEvents.metadataCredentialsRequested,\n (state: ThreadState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n metadataCredentialsRequested: true,\n };\n },\n ),\n on(threadAdapterEvents.fetchNextPageRequested, (state: ThreadState) => {\n if (!state.nextCursor || state.isFetchingNextPage) {\n return state;\n }\n\n return {\n ...state,\n isFetchingNextPage: true,\n // Clear any prior fetch-more error so a retry dismisses the inline panel\n // immediately while the next-page request is in flight.\n fetchMoreError: null,\n };\n }),\n on(\n threadAdapterEvents.renameRequested,\n (state: ThreadState, { threadId, name }) => {\n // Optimistic, no-rollback: reflect the new name immediately. A failure\n // surfaces via `error`/`onError` but the local row is left as-is; a\n // realtime metadata event or refetch reconciles the true server state.\n const existing = state.threads.find((thread) => thread.id === threadId);\n const inFlightMutationCount = state.inFlightMutationCount + 1;\n if (!existing) {\n return { ...state, inFlightMutationCount };\n }\n\n return {\n ...state,\n threads: upsertThread(state.threads, { ...existing, name }),\n inFlightMutationCount,\n };\n },\n ),\n on(\n threadAdapterEvents.archiveRequested,\n (state: ThreadState, { threadId }) => {\n // Optimistic, no-rollback. When archived threads are hidden, drop the\n // row; otherwise flip the flag in place. Note: archiving the active\n // thread is non-destructive — the wrapper keeps viewing it.\n const existing = state.threads.find((thread) => thread.id === threadId);\n const inFlightMutationCount = state.inFlightMutationCount + 1;\n if (!existing) {\n return { ...state, inFlightMutationCount };\n }\n\n if (!state.context?.includeArchived) {\n return {\n ...state,\n threads: state.threads.filter((thread) => thread.id !== threadId),\n inFlightMutationCount,\n };\n }\n\n return {\n ...state,\n threads: upsertThread(state.threads, { ...existing, archived: true }),\n inFlightMutationCount,\n };\n },\n ),\n on(\n threadAdapterEvents.unarchiveRequested,\n (state: ThreadState, { threadId }) => {\n // Optimistic, no-rollback.\n const existing = state.threads.find((thread) => thread.id === threadId);\n const inFlightMutationCount = state.inFlightMutationCount + 1;\n if (!existing) {\n return { ...state, inFlightMutationCount };\n }\n\n return {\n ...state,\n threads: upsertThread(state.threads, { ...existing, archived: false }),\n inFlightMutationCount,\n };\n },\n ),\n on(\n threadAdapterEvents.deleteRequested,\n (state: ThreadState, { requestId, threadId }) => {\n // Optimistic WITH rollback: remove the row now, but park it under the\n // request id so it can be restored if the server rejects the delete.\n const existing = state.threads.find((thread) => thread.id === threadId);\n const inFlightMutationCount = state.inFlightMutationCount + 1;\n if (!existing) {\n return { ...state, inFlightMutationCount };\n }\n\n return {\n ...state,\n threads: state.threads.filter((thread) => thread.id !== threadId),\n pendingDeletes: { ...state.pendingDeletes, [requestId]: existing },\n inFlightMutationCount,\n };\n },\n ),\n on(threadAdapterEvents.newThreadStarted, (state: ThreadState) => ({\n // Lazy creation: a fresh client-side thread does NOT add a phantom row —\n // it only materializes once its first run persists server-side. The\n // store-side concern is purely to clear any stale error so the welcome\n // screen renders cleanly; the wrapper owns the active/explicit threadId.\n ...state,\n error: null,\n })),\n on(threadRestEvents.mutationFinished, (state: ThreadState, { outcome }) => {\n // Drop results from a superseded session. `contextChanged`/`stopped` already\n // reset `threads`, `pendingDeletes`, and `inFlightMutationCount`, so a\n // mutation that resolves after the context switched must not write an error,\n // fire onError (guarded in subscribeErrors), or roll a stale row back into\n // the new list. Mirrors every other session-scoped handler.\n if (outcome.sessionId !== state.sessionId) {\n return state;\n }\n\n const inFlightMutationCount = Math.max(0, state.inFlightMutationCount - 1);\n\n if (outcome.ok) {\n // Success: drop any parked delete-rollback snapshot for this request.\n if (state.pendingDeletes[outcome.requestId] === undefined) {\n return { ...state, inFlightMutationCount };\n }\n\n const { [outcome.requestId]: _settled, ...rest } = state.pendingDeletes;\n return { ...state, inFlightMutationCount, pendingDeletes: rest };\n }\n\n // Failure: surface the error. For a rejected delete, restore the row that\n // was optimistically removed (rollback). Other mutations are no-rollback.\n const rolledBack = state.pendingDeletes[outcome.requestId];\n if (rolledBack === undefined) {\n return { ...state, inFlightMutationCount, error: outcome.error };\n }\n\n const { [outcome.requestId]: _restored, ...rest } = state.pendingDeletes;\n return {\n ...state,\n threads: upsertThread(state.threads, rolledBack),\n pendingDeletes: rest,\n inFlightMutationCount,\n error: outcome.error,\n };\n }),\n on(\n threadDomainEvents.threadUpserted,\n (state: ThreadState, { sessionId, thread }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n threads: upsertThread(state.threads, thread),\n };\n },\n ),\n on(\n threadDomainEvents.threadDeleted,\n (state: ThreadState, { sessionId, threadId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n threads: state.threads.filter((thread) => thread.id !== threadId),\n };\n },\n ),\n) as Reducer<ThreadState>;\n\n/**\n * The set of memoized thread selectors bound to a single store instance.\n *\n * @see createThreadSelectors\n */\ninterface ThreadSelectors {\n threads: (state: ThreadState) => ThreadRecord[];\n isLoading: (state: ThreadState) => boolean;\n error: (state: ThreadState) => Error | null;\n fetchMoreError: (state: ThreadState) => Error | null;\n hasNextPage: (state: ThreadState) => boolean;\n isFetchingNextPage: (state: ThreadState) => boolean;\n isMutating: (state: ThreadState) => boolean;\n}\n\n/**\n * Builds a fresh set of memoized thread selectors.\n *\n * Each `createSelector` closure owns a private one-entry cache. Sharing a\n * single module-level selector instance across multiple concurrent stores\n * (e.g. a `<CopilotThreadsDrawer>` plus an independent `useThreads`) makes every\n * cross-store emission a cache miss, defeating memoization and risking\n * emission instability for any future selector that allocates a new\n * object/array. Creating a per-store instance keeps each store's cache\n * isolated so concurrent stores never thrash one another.\n */\nfunction createThreadSelectors(): ThreadSelectors {\n return {\n threads: createSelector((state: ThreadState) => state.threads),\n isLoading: createSelector((state: ThreadState) => state.isLoading),\n error: createSelector((state: ThreadState) => state.error),\n fetchMoreError: createSelector(\n (state: ThreadState) => state.fetchMoreError,\n ),\n hasNextPage: createSelector(\n (state: ThreadState) => state.nextCursor != null,\n ),\n isFetchingNextPage: createSelector(\n (state: ThreadState) => state.isFetchingNextPage,\n ),\n isMutating: createSelector(\n (state: ThreadState) => state.inFlightMutationCount > 0,\n ),\n };\n}\n\n// Standalone selector instances retained for callers that read a one-off\n// snapshot (e.g. `selectThreads(store.getState())`) where cross-store memo\n// isolation is irrelevant. Subscriptions through `store.select(...)` should\n// prefer the per-store `ThreadStore.selectors` bundle below.\nconst standaloneSelectors = createThreadSelectors();\nconst selectThreads = standaloneSelectors.threads;\nconst selectThreadsIsLoading = standaloneSelectors.isLoading;\nconst selectThreadsError = standaloneSelectors.error;\nconst selectFetchMoreError = standaloneSelectors.fetchMoreError;\nconst selectHasNextPage = standaloneSelectors.hasNextPage;\nconst selectIsFetchingNextPage = standaloneSelectors.isFetchingNextPage;\nconst selectIsMutating = standaloneSelectors.isMutating;\n\ninterface ThreadStore {\n start(): void;\n stop(): void;\n setContext(context: ThreadRuntimeContext | null): void;\n /** Re-fetches the thread list without resetting the current list to empty. */\n refresh(): void;\n /**\n * Re-fetches the thread list without resetting the current list to empty.\n *\n * Public, design-named alias of {@link refresh} used by the drawer's\n * error-state Retry affordance and the Active/All filter-change refetch.\n */\n refetchThreads(): void;\n /**\n * Resets to a fresh, client-side thread so the welcome screen can show.\n *\n * Lazy creation: no phantom row is added to the list — the new thread only\n * materializes once its first run persists server-side. This is distinct\n * from selecting an existing thread (which the wrapper marks *explicit*,\n * suppressing the welcome screen): the thread produced here is NOT explicit.\n */\n startNewThread(): void;\n fetchNextPage(): void;\n renameThread(threadId: string, name: string): Promise<void>;\n archiveThread(threadId: string): Promise<void>;\n unarchiveThread(threadId: string): Promise<void>;\n deleteThread(threadId: string): Promise<void>;\n /**\n * Subscribes to synthetic run-activity notifications without changing the\n * thread metadata list.\n */\n subscribeToRunActivity?(\n callback: (notification: ThreadRunActivityNotification) => void,\n ): Subscription;\n getState(): ThreadState;\n /**\n * Returns a stable initial snapshot for server-side rendering.\n *\n * `useSyncExternalStore` requires a `getServerSnapshot` during SSR/prerender\n * (e.g. Next.js); without one React throws \"Missing getServerSnapshot\". The\n * returned reference is stable across calls so React does not loop. There is\n * no client-side thread data during prerender, so this is the empty initial\n * state.\n */\n getServerState(): ThreadState;\n select: Store<ThreadState>[\"select\"];\n /**\n * Memoized selectors bound to THIS store instance.\n *\n * Subscriptions should pass these to {@link select} (e.g.\n * `store.select(store.selectors.threads)`) so each store keeps its own\n * one-entry memo cache. Sharing the module-level singletons across\n * concurrent stores defeats memoization and risks emission instability.\n */\n selectors: ThreadSelectors;\n}\n\nlet threadRequestId = 0;\n\nfunction createThreadRequestId(): string {\n threadRequestId += 1;\n return `thread-request-${threadRequestId}`;\n}\n\nfunction threadFromFetch<T>(\n input: string,\n init: RequestInit & {\n selector: (response: Response) => Promise<T>;\n fetch: typeof fetch;\n },\n): Observable<T> {\n return new Observable<T>((subscriber) => {\n const { fetch: fetchImpl, selector, signal, ...requestInit } = init;\n const controller = new AbortController();\n const abortRequest = () => controller.abort();\n\n if (signal?.aborted) {\n abortRequest();\n } else {\n signal?.addEventListener(\"abort\", abortRequest, { once: true });\n }\n\n fetchImpl(input, { ...requestInit, signal: controller.signal })\n .then((response) => selector(response))\n .then((value) => {\n if (subscriber.closed) return;\n subscriber.next(value);\n subscriber.complete();\n })\n .catch((error) => {\n if (!subscriber.closed) {\n subscriber.error(error);\n }\n });\n\n return () => {\n signal?.removeEventListener(\"abort\", abortRequest);\n abortRequest();\n };\n });\n}\n\nfunction createThreadFetchObservable(\n environment: ThreadEnvironment,\n context: ThreadRuntimeContext,\n sessionId: number,\n): Observable<\n | ReturnType<typeof threadRestEvents.listSucceeded>\n | ReturnType<typeof threadRestEvents.listFailed>\n> {\n return defer(() => {\n const params: Record<string, string> = {\n agentId: context.agentId,\n };\n if (context.includeArchived) params.includeArchived = \"true\";\n if (context.limit != null) params.limit = String(context.limit);\n\n const qs = new URLSearchParams(params);\n return threadFromFetch(`${context.runtimeUrl}/threads?${qs.toString()}`, {\n selector: (response) => {\n if (!response.ok) {\n throw new Error(`Failed to fetch threads: ${response.status}`);\n }\n\n return response.json() as Promise<ThreadListResponse>;\n },\n fetch: environment.fetch,\n method: \"GET\",\n headers: { ...context.headers },\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new Error(\"Request timed out\");\n },\n }),\n map((data) =>\n threadRestEvents.listSucceeded({\n sessionId,\n threads: data.threads,\n joinCode:\n typeof data.joinCode === \"string\" && data.joinCode.length > 0\n ? data.joinCode\n : null,\n nextCursor: data.nextCursor ?? null,\n }),\n ),\n catchError((error) => {\n return of(\n threadRestEvents.listFailed({\n sessionId,\n error: error instanceof Error ? error : new Error(String(error)),\n }),\n );\n }),\n );\n });\n}\n\nfunction createThreadMetadataCredentialsObservable(\n environment: ThreadEnvironment,\n context: ThreadRuntimeContext,\n sessionId: number,\n): Observable<\n | ReturnType<typeof threadRestEvents.metadataCredentialsSucceeded>\n | ReturnType<typeof threadRestEvents.metadataCredentialsFailed>\n> {\n return defer(() => {\n return threadFromFetch(`${context.runtimeUrl}${THREAD_SUBSCRIBE_PATH}`, {\n selector: async (response) => {\n if (!response.ok) {\n throw new Error(\n `Failed to fetch thread metadata credentials: ${response.status}`,\n );\n }\n\n return response.json() as Promise<ThreadMetadataCredentialsResponse>;\n },\n fetch: environment.fetch,\n method: \"POST\",\n headers: {\n ...context.headers,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({}),\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new Error(\"Request timed out\");\n },\n }),\n map((data) => {\n if (typeof data.joinToken !== \"string\" || data.joinToken.length === 0) {\n throw new Error(\"missing joinToken\");\n }\n\n return threadRestEvents.metadataCredentialsSucceeded({\n sessionId,\n joinToken: data.joinToken,\n });\n }),\n catchError((error) => {\n return of(\n threadRestEvents.metadataCredentialsFailed({\n sessionId,\n error: error instanceof Error ? error : new Error(String(error)),\n }),\n );\n }),\n );\n });\n}\n\nfunction createThreadMutationObservable(\n environment: ThreadEnvironment,\n context: ThreadRuntimeContext,\n request: MutationRequest,\n): Observable<ReturnType<typeof threadRestEvents.mutationFinished>> {\n return defer(() => {\n return threadFromFetch(`${context.runtimeUrl}${request.path}`, {\n selector: async (response) => {\n if (!response.ok) {\n throw new Error(`Request failed: ${response.status}`);\n }\n\n return null;\n },\n fetch: environment.fetch,\n method: request.method,\n headers: {\n ...context.headers,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request.body),\n }).pipe(\n map(() =>\n threadRestEvents.mutationFinished({\n outcome: {\n requestId: request.requestId,\n sessionId: request.sessionId,\n ok: true,\n },\n }),\n ),\n catchError((error) => {\n return of(\n threadRestEvents.mutationFinished({\n outcome: {\n requestId: request.requestId,\n sessionId: request.sessionId,\n ok: false,\n error: error instanceof Error ? error : new Error(String(error)),\n },\n }),\n );\n }),\n );\n });\n}\n\nfunction createThreadStore(environment: ThreadEnvironment): ThreadStore {\n // Per-store selector instances keep this store's memo cache isolated from\n // any other concurrent store (see createThreadSelectors).\n const selectors = createThreadSelectors();\n\n const bootstrapEffect = createEffect(\n (\n actions$,\n state$: Observable<ThreadState>,\n ): Observable<ReturnType<typeof threadRestEvents.listRequested>> =>\n actions$.pipe(\n ofType(threadAdapterEvents.contextChanged),\n withLatestFrom(state$),\n filter(([, state]) => Boolean(state.context)),\n map(([, state]) =>\n threadRestEvents.listRequested({ sessionId: state.sessionId }),\n ),\n ),\n );\n\n const fetchEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadRestEvents.listRequested),\n switchMap((action) =>\n state$.pipe(\n map((state) => state.context),\n filter((context): context is ThreadRuntimeContext =>\n Boolean(context),\n ),\n take(1),\n map((context) => ({ action, context })),\n takeUntil(\n actions$.pipe(\n ofType(\n threadAdapterEvents.contextChanged,\n threadAdapterEvents.stopped,\n ),\n ),\n ),\n switchMap(({ action: currentAction, context }) =>\n createThreadFetchObservable(\n environment,\n context,\n currentAction.sessionId,\n ),\n ),\n ),\n ),\n ),\n );\n\n const metadataCredentialsEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadRestEvents.listSucceeded),\n withLatestFrom(state$),\n filter(([action, state]) => {\n return (\n action.sessionId === state.sessionId &&\n !state.metadataCredentialsRequested &&\n Boolean(state.context?.wsUrl) &&\n Boolean(state.metadataJoinCode)\n );\n }),\n map(([action]) =>\n threadRestEvents.metadataCredentialsRequested({\n sessionId: action.sessionId,\n }),\n ),\n ),\n );\n\n const metadataCredentialsFetchEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadRestEvents.metadataCredentialsRequested),\n switchMap((action) =>\n state$.pipe(\n map((state) => state.context),\n filter((context): context is ThreadRuntimeContext =>\n Boolean(context),\n ),\n take(1),\n map((context) => ({ action, context })),\n takeUntil(\n actions$.pipe(\n ofType(\n threadAdapterEvents.contextChanged,\n threadAdapterEvents.stopped,\n ),\n ),\n ),\n switchMap(({ action: currentAction, context }) =>\n createThreadMetadataCredentialsObservable(\n environment,\n context,\n currentAction.sessionId,\n ),\n ),\n ),\n ),\n ),\n );\n\n const socketEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadRestEvents.metadataCredentialsSucceeded),\n withLatestFrom(state$),\n filter(([action, state]) => {\n return (\n action.sessionId === state.sessionId &&\n Boolean(state.context?.wsUrl)\n );\n }),\n switchMap(([action, state]) => {\n const context = state.context as ThreadRuntimeContext;\n const joinToken = action.joinToken as string;\n const joinCode = state.metadataJoinCode as string;\n const shutdown$ = actions$.pipe(\n ofType(\n threadAdapterEvents.contextChanged,\n threadAdapterEvents.stopped,\n ),\n );\n\n return defer(() => {\n const socket$ = ɵphoenixSocket$({\n url: context.wsUrl!,\n options: {\n params: { join_token: joinToken },\n reconnectAfterMs: phoenixExponentialBackoff(100, 10_000),\n rejoinAfterMs: phoenixExponentialBackoff(1_000, 30_000),\n },\n }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const channel$ = ɵphoenixChannel$({\n socket$,\n topic: `user_meta:${joinCode}`,\n }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const socketSignals$ =\n ɵobservePhoenixSocketSignals$(socket$).pipe(share());\n const fatalSocketShutdown$ = ɵobservePhoenixSocketHealth$(\n socketSignals$,\n MAX_SOCKET_RETRIES,\n ).pipe(\n catchError(() => {\n console.warn(\n `[threads] WebSocket failed after ${MAX_SOCKET_RETRIES} attempts, giving up`,\n );\n return of(undefined);\n }),\n share(),\n );\n const socketLifecycle$ = socketSignals$.pipe(\n map((signal) =>\n signal.type === \"open\"\n ? threadSocketEvents.opened({ sessionId: action.sessionId })\n : threadSocketEvents.errored({ sessionId: action.sessionId }),\n ),\n );\n const metadata$ = channel$.pipe(\n switchMap(({ channel }: ɵPhoenixChannelSession) =>\n ɵobservePhoenixEvent$<ThreadMetadataEvent>(\n channel,\n THREADS_CHANNEL_EVENT,\n ),\n ),\n map((payload) =>\n threadSocketEvents.metadataReceived({\n sessionId: action.sessionId,\n payload,\n }),\n ),\n );\n const runActivity$ = channel$.pipe(\n switchMap(({ channel }: ɵPhoenixChannelSession) =>\n ɵobservePhoenixEvent$<ThreadRunActivityGatewayPayload>(\n channel,\n THREAD_RUN_ACTIVITY_CHANNEL_EVENT,\n ),\n ),\n map((payload) => normalizeThreadRunActivityNotification(payload)),\n filter(\n (notification): notification is ThreadRunActivityNotification =>\n notification !== null,\n ),\n map((notification) =>\n threadSocketEvents.runActivityReceived({\n sessionId: action.sessionId,\n notification,\n }),\n ),\n );\n const joinOutcome$ = ɵobservePhoenixJoinOutcome$(channel$).pipe(\n filter((outcome) => outcome.type !== \"joined\"),\n map((outcome) =>\n outcome.type === \"timeout\"\n ? threadSocketEvents.joinTimedOut({\n sessionId: action.sessionId,\n })\n : threadSocketEvents.joinFailed({\n sessionId: action.sessionId,\n }),\n ),\n );\n\n return merge(\n socketLifecycle$,\n metadata$,\n runActivity$,\n joinOutcome$,\n ).pipe(takeUntil(merge(shutdown$, fatalSocketShutdown$)));\n });\n }),\n ),\n );\n\n const realtimeMappingEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadSocketEvents.metadataReceived),\n withLatestFrom(state$),\n filter(([action, state]) => action.sessionId === state.sessionId),\n map(([action, state]) => {\n if (action.payload.operation === \"deleted\") {\n return threadDomainEvents.threadDeleted({\n sessionId: action.sessionId,\n threadId: action.payload.deleted.id,\n });\n }\n\n // When includeArchived is false, an \"archived\" event should remove\n // the thread from the local list rather than upserting it.\n if (\n action.payload.operation === \"archived\" &&\n !state.context?.includeArchived\n ) {\n return threadDomainEvents.threadDeleted({\n sessionId: action.sessionId,\n threadId: action.payload.threadId,\n });\n }\n\n return threadDomainEvents.threadUpserted({\n sessionId: action.sessionId,\n thread: action.payload.thread,\n });\n }),\n ),\n );\n\n // Observability-only effect for realtime-join health. The socket effect\n // dispatches `joinFailed`/`joinTimedOut`/`errored` but the reducer has no\n // handler for them by design: a transient WS drop while the (already\n // fetched) list is present must NOT become a hard list error — the user\n // keeps the stale list. Previously these actions were silently swallowed,\n // leaving a realtime-join failure with zero signal. This effect emits a\n // non-fatal warning (mirroring the MAX_SOCKET_RETRIES warn) so the failure\n // is diagnosable. Session-guarded so a superseded session stays quiet.\n const socketDiagnosticsEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(\n threadSocketEvents.joinFailed,\n threadSocketEvents.joinTimedOut,\n threadSocketEvents.errored,\n threadRestEvents.metadataCredentialsFailed,\n ),\n withLatestFrom(state$),\n filter(([action, state]) => action.sessionId === state.sessionId),\n tap(([action]) => {\n const reason = threadSocketEvents.joinTimedOut.match(action)\n ? \"channel join timed out\"\n : threadSocketEvents.joinFailed.match(action)\n ? \"channel join was rejected\"\n : threadRestEvents.metadataCredentialsFailed.match(action)\n ? \"metadata credentials fetch failed\"\n : \"socket errored\";\n console.warn(\n `[threads] realtime ${reason}; the thread list may be stale until reconnect`,\n );\n }),\n ),\n { dispatch: false },\n );\n\n const fetchNextPageEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadAdapterEvents.fetchNextPageRequested),\n withLatestFrom(state$),\n filter(\n ([, state]) => Boolean(state.context) && Boolean(state.nextCursor),\n ),\n switchMap(([, state]) => {\n const context = state.context as ThreadRuntimeContext;\n const params: Record<string, string> = {\n agentId: context.agentId,\n cursor: state.nextCursor!,\n };\n if (context.includeArchived) params.includeArchived = \"true\";\n if (context.limit != null) params.limit = String(context.limit);\n\n return threadFromFetch(\n `${context.runtimeUrl}/threads?${new URLSearchParams(params).toString()}`,\n {\n selector: (response) => {\n if (!response.ok) {\n throw new Error(\n `Failed to fetch next page: ${response.status}`,\n );\n }\n\n return response.json() as Promise<ThreadListResponse>;\n },\n fetch: environment.fetch,\n method: \"GET\",\n headers: { ...context.headers },\n },\n ).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new Error(\"Request timed out\");\n },\n }),\n map((data) =>\n threadRestEvents.nextPageSucceeded({\n sessionId: state.sessionId,\n threads: data.threads,\n nextCursor: data.nextCursor ?? null,\n }),\n ),\n catchError((error) =>\n of(\n threadRestEvents.nextPageFailed({\n sessionId: state.sessionId,\n error:\n error instanceof Error ? error : new Error(String(error)),\n }),\n ),\n ),\n takeUntil(\n actions$.pipe(\n ofType(\n threadAdapterEvents.contextChanged,\n threadAdapterEvents.stopped,\n ),\n ),\n ),\n );\n }),\n ),\n );\n\n const mutationEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(\n threadAdapterEvents.renameRequested,\n threadAdapterEvents.archiveRequested,\n threadAdapterEvents.unarchiveRequested,\n threadAdapterEvents.deleteRequested,\n ),\n withLatestFrom(state$),\n mergeMap(([action, state]) => {\n // Capture the dispatching session so a result that resolves after a\n // `contextChanged` is dropped by the reducer instead of leaking an\n // error/onError/rollback into the new session. The mergeMap is not\n // cancelled on context change, so the session tag is the guard.\n const sessionId = state.sessionId;\n const context = state.context;\n if (!context?.runtimeUrl) {\n const requestId = action.requestId;\n return of(\n threadRestEvents.mutationFinished({\n outcome: {\n requestId,\n sessionId,\n ok: false,\n error: new Error(\"Runtime URL is not configured\"),\n },\n }),\n );\n }\n\n const commonBody = {\n agentId: context.agentId,\n };\n\n if (threadAdapterEvents.renameRequested.match(action)) {\n return createThreadMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n method: \"PATCH\",\n path: `/threads/${encodeURIComponent(action.threadId)}`,\n body: {\n ...commonBody,\n name: action.name,\n },\n });\n }\n\n if (threadAdapterEvents.archiveRequested.match(action)) {\n return createThreadMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n method: \"POST\",\n path: `/threads/${encodeURIComponent(action.threadId)}/archive`,\n body: commonBody,\n });\n }\n\n if (threadAdapterEvents.unarchiveRequested.match(action)) {\n return createThreadMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n method: \"PATCH\",\n path: `/threads/${encodeURIComponent(action.threadId)}`,\n body: {\n ...commonBody,\n archived: false,\n },\n });\n }\n\n return createThreadMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n method: \"DELETE\",\n path: `/threads/${encodeURIComponent(action.threadId)}`,\n body: commonBody,\n });\n }),\n ),\n );\n\n const store = createStore<ThreadState>({\n reducer: threadReducer,\n effects: [\n bootstrapEffect,\n fetchEffect,\n metadataCredentialsEffect,\n metadataCredentialsFetchEffect,\n socketEffect,\n realtimeMappingEffect,\n socketDiagnosticsEffect,\n fetchNextPageEffect,\n mutationEffect,\n ],\n });\n\n function trackMutation(\n dispatchAction:\n | ReturnType<typeof threadAdapterEvents.renameRequested>\n | ReturnType<typeof threadAdapterEvents.archiveRequested>\n | ReturnType<typeof threadAdapterEvents.unarchiveRequested>\n | ReturnType<typeof threadAdapterEvents.deleteRequested>,\n ): Promise<void> {\n const completion$ = merge(\n store.actions$.pipe(\n ofType(threadRestEvents.mutationFinished),\n filter(\n (action) => action.outcome.requestId === dispatchAction.requestId,\n ),\n map((action) => action.outcome),\n ),\n store.actions$.pipe(\n ofType(threadAdapterEvents.stopped),\n map(\n () =>\n ({\n requestId: dispatchAction.requestId,\n sessionId: store.getState().sessionId,\n ok: false,\n error: new Error(\n \"Thread store stopped before mutation completed\",\n ),\n }) satisfies MutationOutcome,\n ),\n ),\n ).pipe(take(1));\n\n const resultPromise = firstValueFrom(completion$).then((outcome) => {\n if (outcome.ok) {\n return;\n }\n\n throw outcome.error;\n });\n\n store.dispatch(dispatchAction);\n return resultPromise;\n }\n\n // Surface mutation rejections to the optional environment callback. The\n // reducer has already applied any delete rollback by the time this fires\n // (the store reduces state before re-emitting the action), so consumers see\n // a consistent list when they react to the error.\n let errorSubscription: Subscription | null = null;\n const subscribeErrors = (): void => {\n if (!environment.onError || errorSubscription) {\n return;\n }\n\n errorSubscription = store.actions$\n .pipe(\n ofType(threadRestEvents.mutationFinished),\n // Drop stale-session failures: a mutation that rejects after a\n // `contextChanged` belongs to a context the user already left, so\n // surfacing it would fire onError for the wrong session. The reducer\n // applies the same guard before writing `state.error`.\n filter(\n (action) =>\n !action.outcome.ok &&\n action.outcome.sessionId === store.getState().sessionId,\n ),\n )\n .subscribe((action) => {\n if (!action.outcome.ok) {\n environment.onError?.(action.outcome.error);\n }\n });\n };\n\n return {\n start(): void {\n store.init();\n subscribeErrors();\n store.dispatch(threadAdapterEvents.started());\n },\n stop(): void {\n store.dispatch(threadAdapterEvents.stopped());\n errorSubscription?.unsubscribe();\n errorSubscription = null;\n store.stop();\n },\n setContext(context: ThreadRuntimeContext | null): void {\n store.dispatch(threadAdapterEvents.contextChanged({ context }));\n },\n refresh(): void {\n const { sessionId, context } = store.getState();\n if (!context) return;\n store.dispatch(threadRestEvents.listRequested({ sessionId }));\n },\n refetchThreads(): void {\n const { sessionId, context } = store.getState();\n if (!context) return;\n store.dispatch(threadRestEvents.listRequested({ sessionId }));\n },\n startNewThread(): void {\n store.dispatch(threadAdapterEvents.newThreadStarted());\n },\n fetchNextPage(): void {\n store.dispatch(threadAdapterEvents.fetchNextPageRequested());\n },\n renameThread(threadId: string, name: string): Promise<void> {\n return trackMutation(\n threadAdapterEvents.renameRequested({\n requestId: createThreadRequestId(),\n threadId,\n name,\n }),\n );\n },\n archiveThread(threadId: string): Promise<void> {\n return trackMutation(\n threadAdapterEvents.archiveRequested({\n requestId: createThreadRequestId(),\n threadId,\n }),\n );\n },\n unarchiveThread(threadId: string): Promise<void> {\n return trackMutation(\n threadAdapterEvents.unarchiveRequested({\n requestId: createThreadRequestId(),\n threadId,\n }),\n );\n },\n deleteThread(threadId: string): Promise<void> {\n return trackMutation(\n threadAdapterEvents.deleteRequested({\n requestId: createThreadRequestId(),\n threadId,\n }),\n );\n },\n subscribeToRunActivity(\n callback: (notification: ThreadRunActivityNotification) => void,\n ): Subscription {\n return store.actions$\n .pipe(\n ofType(threadSocketEvents.runActivityReceived),\n filter((action) => action.sessionId === store.getState().sessionId),\n map((action) => action.notification),\n )\n .subscribe(callback);\n },\n getState(): ThreadState {\n return store.getState();\n },\n getServerState(): ThreadState {\n return initialThreadState;\n },\n select: store.select.bind(store),\n selectors,\n };\n}\n\nexport type ɵThread = ThreadRecord;\nexport type ɵThreadRuntimeContext = ThreadRuntimeContext;\nexport type ɵThreadMetadataEvent = ThreadMetadataEvent;\nexport type ɵThreadEnvironment = ThreadEnvironment;\nexport type ɵThreadStore = ThreadStore;\nexport type ɵThreadSelectors = ThreadSelectors;\nexport const ɵthreadAdapterEvents = threadAdapterEvents;\nexport const ɵcreateThreadSelectors = createThreadSelectors;\nexport const ɵselectThreads = selectThreads;\nexport const ɵselectThreadsIsLoading = selectThreadsIsLoading;\nexport const ɵselectThreadsError = selectThreadsError;\nexport const ɵselectFetchMoreError = selectFetchMoreError;\nexport const ɵselectHasNextPage = selectHasNextPage;\nexport const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;\nexport const ɵselectIsMutating = selectIsMutating;\nexport { createThreadStore as ɵcreateThreadStore };\n/**\n * Number of consecutive WebSocket connection failures after which the\n * threads channel tears itself down rather than retrying indefinitely.\n * Exposed for tests so they can assert teardown semantics without\n * hardcoding the threshold separately from production.\n */\nexport const ɵMAX_SOCKET_RETRIES = MAX_SOCKET_RETRIES;\n","/**\n * Central registry of CopilotKit feature names.\n *\n * Feature names are the strings passed to a license context's `checkFeature`\n * (see `@copilotkit/shared`'s `LicenseContextValue`). Historically the only\n * features referenced by literal were the chat surfaces (`chat`, `sidebar`,\n * `popup`); this module makes the set explicit and typed so new surfaces —\n * such as the threads drawer — register a real, discoverable feature name\n * rather than an ad-hoc string scattered across components.\n *\n * `checkFeature` itself still accepts any `string` for backward compatibility;\n * this registry simply documents and types the names CopilotKit recognises.\n */\n\n/**\n * The set of feature names CopilotKit recognises.\n *\n * Frozen so the array cannot be mutated at runtime. Add new surfaces here when\n * they begin gating behaviour on `checkFeature`.\n */\nexport const ɵCOPILOTKIT_FEATURES = Object.freeze([\n \"chat\",\n \"sidebar\",\n \"popup\",\n \"threads\",\n] as const);\n\n/**\n * Union of recognised CopilotKit feature names.\n */\nexport type ɵCopilotKitFeature = (typeof ɵCOPILOTKIT_FEATURES)[number];\n\nconst FEATURE_SET: ReadonlySet<string> = new Set(ɵCOPILOTKIT_FEATURES);\n\n/**\n * Type guard: returns `true` when `name` is a recognised CopilotKit feature.\n *\n * @param name - Candidate feature name.\n * @returns Whether `name` is a registered feature.\n *\n * @example\n * ```ts\n * if (ɵisCopilotKitFeature(\"threads\")) {\n * // narrowed to ɵCopilotKitFeature\n * }\n * ```\n */\nexport function ɵisCopilotKitFeature(name: string): name is ɵCopilotKitFeature {\n return FEATURE_SET.has(name);\n}\n","import { buildResumeArray, isInterruptExpired } from \"@ag-ui/client\";\nimport type { Interrupt, ResumeEntry } from \"@ag-ui/client\";\n\ntype ResumeResponse =\n | { status: \"resolved\"; payload?: unknown }\n | { status: \"cancelled\" };\n\n/** @internal Application authors must not depend on this contract. */\nexport interface ɵInterruptEvent<TValue = unknown> {\n name: string;\n value: TValue;\n}\n\n/** @internal Application authors must not depend on this contract. */\nexport type ɵPendingInterrupt<TValue = unknown> =\n | { kind: \"legacy\"; event: ɵInterruptEvent<TValue> }\n | { kind: \"standard\"; interrupts: readonly Interrupt[] };\n\n/** @internal Application authors must not depend on this contract. */\nexport interface ɵInterruptToolResult {\n toolCallId: string;\n content: string;\n}\n\n/** @internal Application authors must not depend on this contract. */\nexport type ɵInterruptDecision =\n | { kind: \"ignored\" }\n | { kind: \"waiting\" }\n | { kind: \"dismiss\" }\n | {\n kind: \"expired\";\n interrupt: Interrupt;\n }\n | {\n kind: \"legacy-resume\";\n payload: unknown;\n interruptValue: unknown;\n }\n | {\n kind: \"resume\";\n resume: ResumeEntry[];\n toolResults: ɵInterruptToolResult[];\n };\n\nfunction toolResultContent(response: ResumeResponse): string {\n if (response.status === \"cancelled\") {\n return JSON.stringify({ status: \"cancelled\" });\n }\n return JSON.stringify(response.payload ?? { status: \"resolved\" });\n}\n\n/**\n * @internal Framework-neutral interrupt response state shared by framework\n * adapters. Application authors must not depend on this API.\n */\nexport class ɵInterruptState<TValue = unknown> {\n readonly #responses: Record<string, ResumeResponse> = {};\n #pending: ɵPendingInterrupt<TValue> | null = null;\n #sealed = false;\n\n /** Return the active normalized interrupt without exposing mutable state. */\n get pending(): ɵPendingInterrupt<TValue> | null {\n const pending = this.#pending;\n if (pending?.kind === \"standard\") {\n return { kind: \"standard\", interrupts: [...pending.interrupts] };\n }\n return pending;\n }\n\n /** Replace the current interrupt with a legacy custom-event interrupt. */\n setLegacy(event: ɵInterruptEvent<TValue>): void {\n this.#replace({ kind: \"legacy\", event });\n }\n\n /** Replace the current interrupt with an AG-UI standard interrupt set. */\n setStandard(interrupts: readonly Interrupt[]): void {\n this.#replace({ kind: \"standard\", interrupts: [...interrupts] });\n }\n\n /** Clear all pending interrupt data and accumulated responses. */\n clear(): void {\n this.#pending = null;\n this.#sealed = false;\n for (const id of Object.keys(this.#responses)) delete this.#responses[id];\n }\n\n /** Record a resolved response and return the next framework action. */\n resolve(payload?: unknown, interruptId?: string): ɵInterruptDecision {\n const pending = this.#pending;\n if (!pending || this.#sealed) return { kind: \"ignored\" };\n if (pending.kind === \"legacy\") {\n this.#sealed = true;\n return {\n kind: \"legacy-resume\",\n payload,\n interruptValue: pending.event.value,\n };\n }\n return this.#respond(pending.interrupts, interruptId, {\n status: \"resolved\",\n payload,\n });\n }\n\n /** Record a cancelled response and return the next framework action. */\n cancel(interruptId?: string): ɵInterruptDecision {\n const pending = this.#pending;\n if (!pending || this.#sealed) return { kind: \"ignored\" };\n if (pending.kind === \"legacy\") {\n this.#sealed = true;\n return { kind: \"dismiss\" };\n }\n return this.#respond(pending.interrupts, interruptId, {\n status: \"cancelled\",\n });\n }\n\n #replace(pending: ɵPendingInterrupt<TValue>): void {\n this.clear();\n this.#pending = pending;\n }\n\n #respond(\n interrupts: readonly Interrupt[],\n interruptId: string | undefined,\n response: ResumeResponse,\n ): ɵInterruptDecision {\n const id = interruptId ?? interrupts[0]?.id;\n if (!id || !interrupts.some((interrupt) => interrupt.id === id)) {\n return { kind: \"ignored\" };\n }\n this.#responses[id] = response;\n if (!interrupts.every((interrupt) => this.#responses[interrupt.id])) {\n return { kind: \"waiting\" };\n }\n\n const expired = interrupts.find((interrupt) =>\n isInterruptExpired(interrupt),\n );\n if (expired) {\n this.#sealed = true;\n return { kind: \"expired\", interrupt: expired };\n }\n\n const mutableInterrupts = [...interrupts];\n const resume = buildResumeArray(mutableInterrupts, this.#responses);\n const toolResults = mutableInterrupts.flatMap((interrupt) => {\n if (!interrupt.toolCallId) return [];\n return [\n {\n toolCallId: interrupt.toolCallId,\n content: toolResultContent(this.#responses[interrupt.id]!),\n },\n ];\n });\n this.#sealed = true;\n return { kind: \"resume\", resume, toolResults };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Observable","Socket","NEVER","EMPTY","AbstractAgent","Subject","EMPTY","EventType","Notification","isAbortError","EMPTY","HttpAgent","RUNTIME_MODE_SSE","RUNTIME_MODE_INTELLIGENCE","#connectViaDelegate","#connectViaHttp","#runViaDelegate","#runViaHttp","RUNTIME_MODE_SSE","HttpAgent","HttpAgent","Subscription","BehaviorSubject","Subject","asapScheduler","REQUEST_TIMEOUT_MS","MAX_SOCKET_RETRIES","asapScheduler","ɵcreateMemoryStore","Throttler","Observable","#responses","#pending","#replace","#sealed","#respond"],"sources":["../src/utils/phoenix-observable.ts","../src/intelligence-agent.ts","../src/agent.ts","../src/core/agent-registry.ts","../src/core/context-store.ts","../src/core/suggestion-engine.ts","../src/core/run-handler.ts","../src/core/state-manager.ts","../src/core/thread-store-registry.ts","../src/utils/micro-redux.ts","../src/memory-errors.ts","../src/memory.ts","../src/core/core.ts","../src/types.ts","../src/utils/markdown.ts","../src/threads.ts","../src/features.ts","../src/interrupt-state.ts"],"sourcesContent":["import { Socket } from \"phoenix\";\nimport { EMPTY, NEVER, Observable, concat, defer, of, throwError } from \"rxjs\";\nimport {\n filter,\n finalize,\n mergeMap,\n scan,\n shareReplay,\n switchMap,\n take,\n} from \"rxjs/operators\";\n\n/**\n * Minimal Phoenix push contract used by the observable adapters.\n */\nexport interface ɵPhoenixPushLike {\n receive(\n status: string,\n callback: (payload?: unknown) => unknown,\n ): ɵPhoenixPushLike;\n}\n\n/**\n * Minimal Phoenix channel contract used by the observable adapters.\n */\nexport interface ɵPhoenixChannelLike {\n on(event: string, callback: (payload: unknown) => void): number;\n off(event: string, ref?: number): void;\n onError?(callback: (reason?: unknown) => void): unknown;\n join(params?: Record<string, unknown>): ɵPhoenixPushLike;\n push?(event: string, payload: unknown): ɵPhoenixPushLike;\n leave(): void;\n}\n\n/**\n * Minimal Phoenix socket contract used by the observable adapters.\n */\nexport interface ɵPhoenixSocketLike {\n connect(): void;\n disconnect(): void;\n channel(topic: string, params?: Record<string, unknown>): ɵPhoenixChannelLike;\n onError(callback: (error?: unknown) => void): unknown;\n onOpen(callback: () => void): unknown;\n}\n\n/**\n * Socket lifecycle notifications exposed by {@link ɵphoenixSocket$}.\n */\nexport type ɵPhoenixSocketSignal =\n | { type: \"open\" }\n | { type: \"error\"; error?: unknown };\n\n/**\n * Terminal outcomes of a Phoenix channel join attempt.\n */\nexport type ɵPhoenixJoinOutcome =\n | { type: \"joined\" }\n | { type: \"error\"; response?: unknown }\n | { type: \"timeout\" };\n\n/**\n * Active Phoenix socket session plus its derived lifecycle stream.\n */\nexport interface ɵPhoenixSocketSession {\n socket: ɵPhoenixSocketLike;\n signals$: Observable<ɵPhoenixSocketSignal>;\n}\n\n/**\n * Active Phoenix channel session plus its derived join-outcome stream.\n */\nexport interface ɵPhoenixChannelSession {\n channel: ɵPhoenixChannelLike;\n joinOutcome$: Observable<ɵPhoenixJoinOutcome>;\n}\n\n/**\n * Options for creating a cold Phoenix socket session stream.\n */\nexport interface ɵPhoenixSocketOptions {\n url: string;\n options?: Record<string, unknown>;\n}\n\n/**\n * Options for creating a cold Phoenix channel session stream from a socket stream.\n */\nexport interface ɵPhoenixChannelOptions {\n socket$: Observable<ɵPhoenixSocketSession>;\n topic: string;\n params?: Record<string, unknown>;\n leaveOnUnsubscribe?: boolean;\n}\n\n/**\n * Adapt Phoenix socket open/error callbacks into an observable signal stream.\n *\n * The returned observable is shared and replayable by the caller when needed,\n * but this helper itself does not own socket connection teardown.\n */\nfunction ɵcreatePhoenixSocketSignals$(\n socket: ɵPhoenixSocketLike,\n): Observable<ɵPhoenixSocketSignal> {\n return new Observable<ɵPhoenixSocketSignal>((observer) => {\n socket.onOpen(() => observer.next({ type: \"open\" }));\n socket.onError((error) => observer.next({ type: \"error\", error }));\n });\n}\n\n/**\n * Adapt a Phoenix channel join attempt into a single-outcome observable.\n */\nfunction ɵcreatePhoenixJoinOutcome$(\n channel: ɵPhoenixChannelLike,\n): Observable<ɵPhoenixJoinOutcome> {\n return new Observable<ɵPhoenixJoinOutcome>((observer) => {\n channel\n .join()\n .receive(\"ok\", () => {\n observer.next({ type: \"joined\" });\n observer.complete();\n })\n .receive(\"error\", (response?: unknown) => {\n observer.next({ type: \"error\", response });\n observer.complete();\n })\n .receive(\"timeout\", () => {\n observer.next({ type: \"timeout\" });\n observer.complete();\n });\n });\n}\n\n/**\n * Create a cold Phoenix socket session.\n *\n * The socket is constructed and connected on subscription, and disconnected on\n * teardown. Each subscription creates an isolated socket instance.\n */\nexport function ɵphoenixSocket$(\n options: ɵPhoenixSocketOptions,\n): Observable<ɵPhoenixSocketSession> {\n return defer(() => {\n const socket = new Socket(\n options.url,\n options.options as ConstructorParameters<typeof Socket>[1],\n ) as ɵPhoenixSocketLike;\n const signals$ = ɵcreatePhoenixSocketSignals$(socket).pipe(\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n\n socket.connect();\n\n return concat(\n of({\n socket,\n signals$,\n }),\n NEVER,\n ).pipe(finalize(() => socket.disconnect()));\n });\n}\n\n/**\n * Create a cold Phoenix channel session from a socket session stream.\n *\n * A channel is created and joined for each active socket session. If the\n * upstream socket session changes, the previous channel is left before the\n * next one becomes active.\n */\nexport function ɵphoenixChannel$(\n options: ɵPhoenixChannelOptions,\n): Observable<ɵPhoenixChannelSession> {\n return options.socket$.pipe(\n switchMap(({ socket }) =>\n defer(() => {\n const channel = socket.channel(options.topic, options.params);\n const joinOutcome$ = ɵcreatePhoenixJoinOutcome$(channel).pipe(\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n\n return concat(\n of({\n channel,\n joinOutcome$,\n }),\n NEVER,\n ).pipe(\n finalize(() => {\n if (options.leaveOnUnsubscribe !== false) {\n channel.leave();\n }\n }),\n );\n }),\n ),\n );\n}\n\n/**\n * Observe a named Phoenix channel event as an observable payload stream.\n */\nexport function ɵobservePhoenixEvent$<T>(\n channel: ɵPhoenixChannelLike,\n eventName: string,\n): Observable<T> {\n return new Observable<T>((observer) => {\n const ref = channel.on(eventName, (payload) => observer.next(payload as T));\n\n return () => {\n channel.off(eventName, ref);\n };\n });\n}\n\n/**\n * Flatten channel sessions into their join-outcome stream.\n */\nexport function ɵobservePhoenixJoinOutcome$(\n channel$: Observable<ɵPhoenixChannelSession>,\n): Observable<ɵPhoenixJoinOutcome> {\n return channel$.pipe(switchMap((session) => session.joinOutcome$));\n}\n\n/**\n * Complete when a channel joins successfully, or error if the join fails.\n */\nexport function ɵjoinPhoenixChannel$(\n channel$: Observable<ɵPhoenixChannelSession>,\n): Observable<never> {\n return ɵobservePhoenixJoinOutcome$(channel$).pipe(\n take(1),\n mergeMap((outcome) => {\n if (outcome.type === \"joined\") {\n return EMPTY;\n }\n\n throw outcome.type === \"timeout\"\n ? new Error(\"Timed out joining channel\")\n : new Error(\n `Failed to join channel: ${JSON.stringify(outcome.response)}`,\n );\n }),\n );\n}\n\n/**\n * Flatten socket sessions into their lifecycle signal stream.\n */\nexport function ɵobservePhoenixSocketSignals$(\n socket$: Observable<ɵPhoenixSocketSession>,\n): Observable<ɵPhoenixSocketSignal> {\n return socket$.pipe(switchMap((session) => session.signals$));\n}\n\n/**\n * Error after a socket emits the configured number of consecutive error\n * signals, resetting the counter after each successful open signal.\n */\nexport function ɵobservePhoenixSocketHealth$(\n socketSignals$: Observable<ɵPhoenixSocketSignal>,\n maxConsecutiveErrors: number,\n): Observable<never> {\n return socketSignals$.pipe(\n scan(\n (consecutiveErrors, signal) =>\n signal.type === \"open\" ? 0 : consecutiveErrors + 1,\n 0,\n ),\n filter((consecutiveErrors) => consecutiveErrors >= maxConsecutiveErrors),\n take(1),\n mergeMap((consecutiveErrors) =>\n throwError(\n () =>\n new Error(\n `WebSocket connection failed after ${consecutiveErrors} consecutive errors`,\n ),\n ),\n ),\n );\n}\n","import type {\n RunAgentInput,\n RunAgentParameters,\n RunAgentResult,\n AgentSubscriber,\n BaseEvent,\n} from \"@ag-ui/client\";\nimport {\n AbstractAgent,\n EventType,\n randomUUID,\n transformChunks,\n structuredClone_,\n} from \"@ag-ui/client\";\n\nimport {\n EMPTY,\n Subject,\n Notification,\n combineLatest,\n defer,\n dematerialize,\n lastValueFrom,\n merge,\n switchMap,\n throwError,\n} from \"rxjs\";\nimport type { ObservableNotification, Observable } from \"rxjs\";\nimport {\n catchError,\n delay,\n endWith,\n filter,\n finalize,\n ignoreElements,\n mergeMap,\n share,\n shareReplay,\n switchMap as switchMapOperator,\n take,\n takeUntil,\n tap,\n} from \"rxjs/operators\";\nimport { phoenixExponentialBackoff } from \"@copilotkit/shared\";\nimport {\n ɵphoenixChannel$,\n ɵphoenixSocket$,\n ɵjoinPhoenixChannel$,\n ɵobservePhoenixSocketSignals$,\n ɵobservePhoenixSocketHealth$,\n ɵobservePhoenixEvent$,\n} from \"./utils/phoenix-observable\";\nimport type {\n ɵPhoenixChannelLike,\n ɵPhoenixChannelSession,\n ɵPhoenixPushLike,\n ɵPhoenixSocketLike,\n ɵPhoenixSocketSession,\n} from \"./utils/phoenix-observable\";\n\n/**\n * Structural Phoenix socket/channel contracts used by this agent, derived from\n * the minimal `*Like` interfaces in {@link ./utils/phoenix-observable}.\n */\ntype Socket = ɵPhoenixSocketLike;\n\ninterface Channel extends ɵPhoenixChannelLike {\n push(event: string, payload: unknown): ɵPhoenixPushLike;\n}\n\nconst CLIENT_AG_UI_EVENT = \"ag_ui_event\";\nconst REPLAY_COMPLETE_EVENT = \"replay_complete\";\nconst STREAM_IDLE_EVENT = \"stream_idle\";\nconst STOP_RUN_EVENT = \"stop_run\";\nconst CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS = 100;\n\ninterface IntelligenceAgentSharedState {\n lastSeenEventIds: Map<string, string>;\n}\n\ninterface RealtimeConnectionInfo {\n clientUrl: string;\n topic: string;\n}\n\ninterface ThreadJoinCredentials {\n threadId: string;\n runId: string | null;\n joinToken: string;\n realtime: RealtimeConnectionInfo;\n}\n\nexport class AgentThreadLockedError extends Error {\n constructor(threadId?: string) {\n super(threadId ? `Thread ${threadId} is locked` : \"Thread is locked\");\n this.name = \"AgentThreadLockedError\";\n }\n}\n\n/**\n * Typed contract for agents that expose the completion promise of their\n * currently in-flight run.\n *\n * `IntelligenceAgent` resolves this promise once a run's observable pipeline\n * finalizes (see {@link IntelligenceAgent.connectAgent}). Consumers (e.g. the\n * v2 `CopilotChat` send-serialization path) await it to let an in-flight run —\n * notably an interrupt RESUME — finish before dispatching a new run, instead\n * of pre-empting it.\n *\n * The base `AbstractAgent` from `@ag-ui/client` only declares this property\n * privately, so it is reachable only through this contract plus the\n * {@link isRunCompletionAware} type guard. This keeps callers off `as unknown`\n * casts while still degrading safely for agents that don't implement it.\n */\nexport interface RunCompletionAware {\n /**\n * Resolves when the active run's pipeline finalizes (completes, errors, or is\n * detached). `undefined` when no run is in flight.\n */\n readonly activeRunCompletionPromise?: Promise<void>;\n}\n\n/**\n * Type guard for {@link RunCompletionAware}. Returns true when `agent` exposes\n * an `activeRunCompletionPromise` property, so callers can await an in-flight\n * run without an `as unknown as` cast. Returns false for agents that don't\n * implement the contract, letting the caller skip the await and degrade safely.\n */\nexport function isRunCompletionAware(\n agent: unknown,\n): agent is RunCompletionAware {\n return (\n typeof agent === \"object\" &&\n agent !== null &&\n \"activeRunCompletionPromise\" in agent\n );\n}\n\nexport interface IntelligenceAgentConfig {\n /** Phoenix websocket URL, e.g. \"ws://localhost:4000/socket\" */\n url: string;\n /** Runtime REST URL, e.g. \"http://localhost:4000\" */\n runtimeUrl: string;\n /** Agent identifier for REST endpoints */\n agentId: string;\n /** Optional params sent on socket connect (e.g. auth token) */\n socketParams?: Record<string, string>;\n /** Optional headers sent with REST requests */\n headers?: Record<string, string>;\n /** Optional credentials mode for fetch requests */\n credentials?: RequestCredentials;\n}\n\nexport class IntelligenceAgent extends AbstractAgent {\n private config: IntelligenceAgentConfig;\n private socket: Socket | null = null;\n private activeChannel: Channel | null = null;\n private canonicalRunId: string | null = null;\n private sharedState: IntelligenceAgentSharedState;\n\n constructor(\n config: IntelligenceAgentConfig,\n sharedState: IntelligenceAgentSharedState = {\n lastSeenEventIds: new Map<string, string>(),\n },\n ) {\n super();\n this.config = config;\n this.sharedState = sharedState;\n }\n\n clone(): IntelligenceAgent {\n return new IntelligenceAgent(this.config, this.sharedState);\n }\n\n /**\n * Override of AbstractAgent.connectAgent that removes the `verifyEvents` step.\n *\n * Background: AbstractAgent's connectAgent pipeline runs events through\n * `verifyEvents`, which validates that the stream follows the AG-UI protocol\n * lifecycle — specifically, it expects a RUN_STARTED event before any content\n * events and a RUN_FINISHED/RUN_ERROR event to complete the stream.\n *\n * IntelligenceAgent uses long-lived WebSocket connections rather than\n * request-scoped SSE streams. When connecting to replay historical messages\n * for an existing thread, the connection semantics don't map to a single\n * agent run start/stop cycle. The replayed events may not include\n * RUN_STARTED/RUN_FINISHED bookends (or may contain events from multiple\n * past runs), which causes verifyEvents to either never complete or to\n * error out.\n *\n * This override replicates the base connectAgent implementation exactly,\n * substituting only `transformChunks` (which is still needed for message\n * reassembly) and omitting `verifyEvents`.\n *\n * TODO: Remove this override once AG-UI's AbstractAgent supports opting out\n * of verifyEvents for transports with different connection life-cycles.\n */\n override async connectAgent(\n parameters?: RunAgentParameters,\n subscriber?: AgentSubscriber,\n ): Promise<RunAgentResult> {\n // Access private fields through a type escape hatch — these are set/read\n // by the base class and must be managed identically to the original.\n // Using `any` because these fields are private in AbstractAgent, and\n // intersecting private+public members of the same name produces `never`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const self = this as any;\n\n try {\n this.isRunning = true;\n this.agentId = this.agentId ?? randomUUID();\n\n const effectiveParameters =\n parameters?.runId || !this.canonicalRunId\n ? parameters\n : {\n ...parameters,\n runId: this.canonicalRunId,\n };\n const input = this.prepareRunAgentInput(effectiveParameters);\n let result: RunAgentResult[\"result\"];\n const previousMessageIds = new Set(this.messages.map((m) => m.id));\n const subscribers: AgentSubscriber[] = [\n {\n onRunFinishedEvent: (event) => {\n if (event.outcome === \"success\") {\n result = event.result;\n }\n },\n },\n ...this.subscribers,\n subscriber ?? {},\n ];\n\n await this.onInitialize(input, subscribers);\n\n self.activeRunDetach$ = new Subject<void>();\n let resolveCompletion: (() => void) | undefined;\n self.activeRunCompletionPromise = new Promise<void>((resolve) => {\n resolveCompletion = resolve;\n });\n\n const source$ = defer(() => this.connect(input)).pipe(\n // transformChunks reassembles partial/streamed messages — still needed.\n transformChunks(this.debugLogger),\n // NOTE: verifyEvents is intentionally omitted here. See JSDoc above.\n takeUntil(self.activeRunDetach$),\n );\n\n const applied$ = this.apply(input, source$, subscribers);\n const processed$ = this.processApplyEvents(input, applied$, subscribers);\n\n await lastValueFrom(\n processed$.pipe(\n catchError((error) => {\n this.isRunning = false;\n return this.onError(input, error, subscribers);\n }),\n finalize(() => {\n this.isRunning = false;\n this.onFinalize(input, subscribers);\n resolveCompletion?.();\n resolveCompletion = undefined;\n self.activeRunCompletionPromise = undefined;\n self.activeRunDetach$ = undefined;\n }),\n ),\n { defaultValue: undefined },\n );\n\n const newMessages = structuredClone_(this.messages).filter(\n (m) => !previousMessageIds.has(m.id),\n );\n return { result, newMessages };\n } finally {\n this.isRunning = false;\n }\n }\n\n abortRun(): void {\n if (this.activeChannel && this.canonicalRunId) {\n // Defer cleanup until the push is acknowledged so socket.disconnect()\n // doesn't clear the push buffer before the stop signal is sent.\n // The 5-second fallback handles the case where the socket is down and\n // Phoenix never flushes the buffered push (its .receive(\"timeout\") only\n // fires for pushes that were actually sent but not replied to).\n // detachActiveRun() gracefully tears down the connectAgent() pipeline;\n // cleanup() follows as a safety net for the run() path.\n const fallback = setTimeout(() => clear(), 5_000);\n const clear = () => {\n clearTimeout(fallback);\n void this.detachActiveRun();\n this.cleanup();\n };\n\n this.activeChannel\n .push(STOP_RUN_EVENT, { run_id: this.canonicalRunId })\n .receive(\"ok\", clear)\n .receive(\"error\", clear)\n .receive(\"timeout\", clear);\n } else {\n void this.detachActiveRun();\n this.cleanup();\n }\n }\n\n /**\n * Trigger the run via REST, then join the realtime thread channel and relay\n * server-pushed AG-UI events to the Observable subscriber.\n */\n run(input: RunAgentInput): Observable<BaseEvent> {\n this.threadId = input.threadId;\n this.canonicalRunId = input.runId;\n\n return defer(() => this.requestJoinCredentials$(\"run\", input)).pipe(\n switchMap((credentials) => {\n if (credentials === null) {\n return throwError(\n () => new Error(\"REST run request returned no credentials\"),\n );\n }\n\n const canonicalInput = this.applyCanonicalRunIdentity(\n input,\n credentials,\n { fallbackToInputRunId: true },\n );\n\n return this.observeThread$(canonicalInput, credentials, {\n completeOnRunError: false,\n streamMode: \"run\",\n });\n }),\n );\n }\n\n /**\n * Reconnect to an existing thread by fetching websocket credentials and\n * joining the realtime thread channel.\n */\n /**\n * Reconnect to an existing thread by fetching websocket credentials\n * and joining the realtime thread channel.\n *\n * Note: this method does NOT clear the replay cursor. Whether to\n * request a full historical replay vs. resume from\n * `lastSeenEventId` is a decision the caller (typically\n * `RunHandler.connectAgent`) makes by calling\n * {@link clearReconnectCursor} ahead of time on a fresh thread\n * restore. Same-thread churn re-connects preserve the cursor so the\n * gateway only streams events past it instead of replaying the\n * entire history every time the chat re-opens a socket.\n */\n protected connect(input: RunAgentInput): Observable<BaseEvent> {\n this.threadId = input.threadId;\n this.canonicalRunId = null;\n const replayCursor = this.getReconnectCursor(input);\n\n return defer(() =>\n this.requestJoinCredentials$(\"connect\", input, replayCursor),\n ).pipe(\n switchMap((credentials) => {\n if (credentials === null) {\n return EMPTY;\n }\n\n const canonicalInput = this.applyCanonicalRunIdentity(\n input,\n credentials,\n { fallbackToInputRunId: false },\n );\n\n return this.observeThread$(canonicalInput, credentials, {\n completeOnRunError: false,\n streamMode: \"connect\",\n replayCursor,\n });\n }),\n );\n }\n\n /**\n * Tear down a specific channel + socket pair that belongs to one pipeline.\n * Only nulls instance references when they still point to the owned resource,\n * so a concurrent pipeline's resources are never clobbered.\n */\n private cleanupOwned(\n ownChannel: Channel | null,\n ownSocket: Socket | null,\n ): void {\n if (ownChannel) {\n ownChannel.leave();\n if (this.activeChannel === ownChannel) {\n this.activeChannel = null;\n }\n }\n if (ownSocket) {\n ownSocket.disconnect();\n if (this.socket === ownSocket) {\n this.socket = null;\n }\n }\n this.canonicalRunId = null;\n }\n\n private cleanup(): void {\n this.cleanupOwned(this.activeChannel, this.socket);\n }\n\n private requestJoinCredentials$(\n mode: \"run\" | \"connect\",\n input: RunAgentInput,\n replayCursor?: string | null,\n ): Observable<ThreadJoinCredentials | null> {\n return defer(async () => {\n try {\n const response = await fetch(this.buildRuntimeUrl(mode), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.config.headers,\n },\n body: JSON.stringify({\n threadId: input.threadId,\n runId: input.runId,\n messages: input.messages,\n tools: input.tools,\n context: input.context,\n state: input.state,\n forwardedProps: input.forwardedProps,\n ...(mode === \"connect\"\n ? {\n lastSeenEventId:\n replayCursor === undefined\n ? this.getReconnectCursor(input)\n : replayCursor,\n }\n : {}),\n }),\n ...(this.config.credentials\n ? { credentials: this.config.credentials }\n : {}),\n });\n\n if (response.status === 204 && mode === \"connect\") {\n return null;\n }\n\n if (response.status === 409 && mode === \"run\") {\n throw new AgentThreadLockedError(input.threadId);\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new Error(\n text || response.statusText || String(response.status),\n );\n }\n\n return this.normalizeJoinCredentials(await response.json(), input);\n } catch (error) {\n if (error instanceof AgentThreadLockedError) {\n throw error;\n }\n throw new Error(\n `REST ${mode} request failed: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n );\n }\n });\n }\n\n private normalizeJoinCredentials(\n payload: unknown,\n input: RunAgentInput,\n ): ThreadJoinCredentials {\n const envelope =\n payload && typeof payload === \"object\"\n ? (payload as Record<string, unknown>)\n : null;\n const realtime =\n envelope?.realtime && typeof envelope.realtime === \"object\"\n ? (envelope.realtime as Record<string, unknown>)\n : null;\n\n if (typeof envelope?.joinToken !== \"string\" || !envelope.joinToken) {\n throw new Error(\"missing joinToken\");\n }\n\n if (typeof realtime?.clientUrl !== \"string\" || !realtime.clientUrl) {\n throw new Error(\"missing realtime.clientUrl\");\n }\n\n if (typeof realtime.topic !== \"string\" || !realtime.topic) {\n throw new Error(\"missing realtime.topic\");\n }\n\n return {\n threadId:\n typeof envelope.threadId === \"string\" && envelope.threadId\n ? envelope.threadId\n : input.threadId,\n runId:\n typeof envelope.runId === \"string\" && envelope.runId\n ? envelope.runId\n : null,\n joinToken: envelope.joinToken,\n realtime: {\n clientUrl: realtime.clientUrl,\n topic: realtime.topic,\n },\n };\n }\n\n private observeThread$(\n input: RunAgentInput,\n credentials: ThreadJoinCredentials,\n options: {\n completeOnRunError: boolean;\n streamMode: \"run\" | \"connect\";\n channelMode?: \"run\" | \"connect\";\n replayCursor?: string | null;\n },\n ): Observable<BaseEvent> {\n return this.observeThreadSession$(input, credentials, options).pipe(\n catchError((error) => {\n if (!this.isSocketReconnectExhaustedError(error)) {\n return throwError(() => error);\n }\n\n const replayCursor = this.getReconnectCursor(input);\n return this.requestJoinCredentials$(\n \"connect\",\n input,\n replayCursor,\n ).pipe(\n switchMap((refreshedCredentials) =>\n refreshedCredentials === null\n ? EMPTY\n : this.observeThread$(\n this.applyCanonicalRunIdentity(input, refreshedCredentials, {\n fallbackToInputRunId: options.streamMode === \"run\",\n }),\n refreshedCredentials,\n {\n ...options,\n channelMode: \"connect\",\n replayCursor,\n },\n ),\n ),\n );\n }),\n );\n }\n\n private observeThreadSession$(\n input: RunAgentInput,\n credentials: ThreadJoinCredentials,\n options: {\n completeOnRunError: boolean;\n streamMode: \"run\" | \"connect\";\n channelMode?: \"run\" | \"connect\";\n replayCursor?: string | null;\n },\n ): Observable<BaseEvent> {\n return defer(() => {\n // Capture references to the socket and channel created by THIS pipeline\n // so the finalize closure only tears down its own resources. Without\n // this, a fire-and-forget detachActiveRun() from run-handler can race:\n // the old pipeline's deferred cleanup reads from `this.socket` /\n // `this.activeChannel`, which by then may already point to the NEW\n // pipeline's resources — destroying the live connection and preventing\n // the stop signal from ever reaching the backend.\n let ownSocket: Socket | null = null;\n let ownChannel: Channel | null = null;\n\n const socket$ = ɵphoenixSocket$({\n url: credentials.realtime.clientUrl,\n options: {\n params: {\n ...this.config.socketParams,\n join_token: credentials.joinToken,\n },\n reconnectAfterMs: phoenixExponentialBackoff(100, 10_000),\n rejoinAfterMs: phoenixExponentialBackoff(1_000, 30_000),\n },\n }).pipe(\n tap(({ socket }) => {\n ownSocket = socket as Socket;\n this.socket = ownSocket;\n }),\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n const params = this.createThreadChannelParams(\n input,\n options.channelMode ?? options.streamMode,\n options.replayCursor,\n );\n const channel$ = ɵphoenixChannel$({\n socket$,\n topic: credentials.realtime.topic,\n params,\n }).pipe(\n tap(({ channel }) => {\n ownChannel = channel as Channel;\n this.activeChannel = ownChannel;\n }),\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n const reconnectCursor = this.readDurableEventId(\n options.replayCursor ?? this.getReconnectCursor(input),\n );\n let latestObservedReplayCursor: string | null = null;\n const threadEvents$ = this.observeThreadEvents$(\n input.threadId,\n channel$,\n options,\n ).pipe(\n tap((payload) => {\n latestObservedReplayCursor =\n this.readEventId(payload) ?? latestObservedReplayCursor;\n }),\n share(),\n );\n const replayComplete$ = this.observeControlEvent$(\n input.threadId,\n channel$,\n REPLAY_COMPLETE_EVENT,\n ).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const streamIdle$ = this.observeControlEvent$(\n input.threadId,\n channel$,\n STREAM_IDLE_EVENT,\n ).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const streamIdleCompletion$ =\n options.streamMode === \"connect\"\n ? merge(\n combineLatest([\n replayComplete$.pipe(take(1)),\n streamIdle$.pipe(take(1)),\n ]),\n streamIdle$.pipe(\n take(1),\n filter((payload) =>\n this.canFallbackCompleteConnect(\n payload,\n reconnectCursor,\n latestObservedReplayCursor,\n ),\n ),\n delay(CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS),\n ),\n ).pipe(take(1))\n : EMPTY;\n const threadCompleted$ = threadEvents$.pipe(\n ignoreElements(),\n endWith(null),\n take(1),\n );\n const terminal$ = merge(threadCompleted$, streamIdleCompletion$);\n\n return merge(\n this.joinThreadChannel$(channel$),\n this.observeSocketHealth$(socket$).pipe(takeUntil(terminal$)),\n threadEvents$.pipe(takeUntil(streamIdleCompletion$)),\n replayComplete$.pipe(ignoreElements(), takeUntil(terminal$)),\n streamIdleCompletion$.pipe(\n ignoreElements(),\n takeUntil(threadCompleted$),\n ),\n ).pipe(finalize(() => this.cleanupOwned(ownChannel, ownSocket)));\n });\n }\n\n private joinThreadChannel$(\n channel$: Observable<ɵPhoenixChannelSession>,\n ): Observable<never> {\n return ɵjoinPhoenixChannel$(channel$);\n }\n\n private observeSocketHealth$(\n socket$: Observable<ɵPhoenixSocketSession>,\n ): Observable<never> {\n return ɵobservePhoenixSocketHealth$(\n ɵobservePhoenixSocketSignals$(socket$),\n 5,\n );\n }\n\n private observeThreadEvents$(\n threadId: string,\n channel$: Observable<ɵPhoenixChannelSession>,\n options: { completeOnRunError: boolean; streamMode: \"run\" | \"connect\" },\n ): Observable<BaseEvent> {\n return channel$.pipe(\n switchMapOperator(({ channel }) =>\n this.observeChannelEvent$<BaseEvent>(channel, CLIENT_AG_UI_EVENT),\n ),\n tap((payload) => {\n this.updateLastSeenEventId(threadId, payload);\n }),\n mergeMap(\n (payload) =>\n this.createThreadNotifications(payload, {\n completeOnRunError: options.completeOnRunError,\n completeOnRunFinished: options.streamMode === \"run\",\n errorOnRunError: options.streamMode === \"run\",\n }) as ObservableNotification<BaseEvent>[],\n ),\n dematerialize(),\n );\n }\n\n private observeControlEvent$(\n threadId: string,\n channel$: Observable<ɵPhoenixChannelSession>,\n eventName: string,\n ): Observable<unknown> {\n return channel$.pipe(\n switchMapOperator(({ channel }) =>\n this.observeChannelEvent$<unknown>(channel, eventName),\n ),\n tap((payload) =>\n this.updateLastSeenEventIdFromControl(threadId, payload),\n ),\n );\n }\n\n private observeChannelEvent$<T>(\n channel: ɵPhoenixChannelLike,\n eventName: string,\n ): Observable<T> {\n return ɵobservePhoenixEvent$<T>(channel, eventName);\n }\n\n private createThreadNotifications(\n payload: BaseEvent,\n options: {\n completeOnRunError: boolean;\n completeOnRunFinished: boolean;\n errorOnRunError: boolean;\n },\n ): Array<Notification<BaseEvent>> {\n if (payload.type === EventType.RUN_FINISHED) {\n return options.completeOnRunFinished\n ? [Notification.createNext(payload), Notification.createComplete()]\n : [Notification.createNext(payload)];\n }\n\n if (payload.type === EventType.RUN_ERROR) {\n const errorMessage =\n (payload as BaseEvent & { message?: string }).message ?? \"Run error\";\n\n return options.completeOnRunError\n ? [Notification.createNext(payload), Notification.createComplete()]\n : options.errorOnRunError\n ? [\n Notification.createNext(payload),\n Notification.createError(new Error(errorMessage)),\n ]\n : [Notification.createNext(payload)];\n }\n\n return [Notification.createNext(payload)];\n }\n\n private buildRuntimeUrl(mode: \"run\" | \"connect\"): string {\n const path = `${this.config.runtimeUrl}/agent/${encodeURIComponent(this.config.agentId)}/${mode}`;\n const origin =\n typeof window !== \"undefined\" && window.location\n ? window.location.origin\n : \"http://localhost\";\n\n return new URL(path, new URL(this.config.runtimeUrl, origin)).toString();\n }\n\n private createThreadChannelParams(\n input: RunAgentInput,\n streamMode: \"run\" | \"connect\",\n replayCursor?: string | null,\n ): Record<string, unknown> {\n return streamMode === \"run\"\n ? {\n stream_mode: \"run\",\n run_id: input.runId,\n }\n : {\n stream_mode: \"connect\",\n last_seen_event_id:\n replayCursor === undefined\n ? this.getReconnectCursor(input)\n : replayCursor,\n };\n }\n\n private getLastSeenEventId(threadId: string): string | null {\n return this.sharedState.lastSeenEventIds.get(threadId) ?? null;\n }\n\n private getReconnectCursor(input: RunAgentInput): string | null {\n return this.getLastSeenEventId(input.threadId);\n }\n\n /**\n * Drop the cached `lastSeenEventId` cursor for `threadId` so the\n * next connect to that topic asks the gateway for a full historical\n * replay (rather than resuming). Public because\n * `RunHandler.connectAgent` calls it on a detected thread switch\n * to rebuild local state from scratch, and skips it on same-thread\n * churn so the gateway can resume.\n */\n public clearReconnectCursor(threadId: string): void {\n this.sharedState.lastSeenEventIds.delete(threadId);\n }\n\n private updateLastSeenEventId(threadId: string, payload: BaseEvent): void {\n const eventId = this.readEventId(payload);\n if (!eventId) {\n return;\n }\n\n this.advanceLastSeenEventId(threadId, eventId);\n }\n\n private updateLastSeenEventIdFromControl(\n threadId: string,\n payload: unknown,\n ): void {\n const eventId = this.readControlEventId(payload);\n if (!eventId) {\n return;\n }\n\n this.advanceLastSeenEventId(threadId, eventId);\n }\n\n private advanceLastSeenEventId(threadId: string, eventId: string): void {\n this.sharedState.lastSeenEventIds.set(threadId, eventId);\n }\n\n private readEventId(payload: BaseEvent): string | null {\n const metadata = (payload as BaseEvent & { metadata?: unknown }).metadata;\n if (!metadata || typeof metadata !== \"object\") {\n return null;\n }\n\n const eventMetadata = metadata as { cpki_event_id?: unknown };\n return this.readDurableEventId(eventMetadata.cpki_event_id);\n }\n\n private readControlEventId(payload: unknown): string | null {\n if (!payload || typeof payload !== \"object\") {\n return null;\n }\n\n const controlPayload = payload as {\n latestEventId?: unknown;\n latest_event_id?: unknown;\n };\n const latestEventId =\n controlPayload.latestEventId ?? controlPayload.latest_event_id;\n return this.readDurableEventId(latestEventId);\n }\n\n private readDurableEventId(eventId: unknown): string | null {\n if (typeof eventId !== \"string\" || eventId.trim() === \"\") {\n return null;\n }\n\n return eventId.startsWith(\"cpki_ingested\") ? null : eventId;\n }\n\n private canFallbackCompleteConnect(\n streamIdlePayload: unknown,\n reconnectCursor: string | null,\n latestObservedReplayCursor: string | null,\n ): boolean {\n const idleCursor = this.readControlEventId(streamIdlePayload);\n if (!idleCursor) {\n return true;\n }\n\n return (\n idleCursor === reconnectCursor ||\n idleCursor === latestObservedReplayCursor\n );\n }\n\n private applyCanonicalRunIdentity(\n input: RunAgentInput,\n credentials: ThreadJoinCredentials,\n options: { fallbackToInputRunId: boolean },\n ): RunAgentInput {\n this.threadId = credentials.threadId;\n const runId =\n credentials.runId ?? (options.fallbackToInputRunId ? input.runId : null);\n this.canonicalRunId = runId;\n\n return {\n ...input,\n threadId: credentials.threadId,\n ...(runId === null ? {} : { runId }),\n };\n }\n\n private isSocketReconnectExhaustedError(error: unknown): boolean {\n return (\n error instanceof Error &&\n error.message.includes(\"WebSocket connection failed after\")\n );\n }\n}\n","import type {\n AbstractAgent,\n AgentCapabilities,\n AgentSubscriber,\n BaseEvent,\n HttpAgentConfig,\n RunAgentInput,\n RunAgentParameters,\n RunAgentResult,\n} from \"@ag-ui/client\";\nimport {\n HttpAgent,\n runHttpRequest,\n transformHttpEventStream,\n} from \"@ag-ui/client\";\nimport type { Observable } from \"rxjs\";\nimport { EMPTY, defer, from } from \"rxjs\";\nimport { catchError, switchMap } from \"rxjs/operators\";\nimport {\n RUNTIME_MODE_SSE,\n RUNTIME_MODE_INTELLIGENCE,\n} from \"@copilotkit/shared\";\nimport type {\n IntelligenceRuntimeInfo,\n RuntimeInfo,\n RuntimeMode,\n ResolvedDebugConfig,\n} from \"@copilotkit/shared\";\nimport { IntelligenceAgent } from \"./intelligence-agent\";\nimport type { CopilotRuntimeTransport } from \"./types\";\n\ntype ResolvedRuntimeMode = RuntimeMode | \"pending\";\n\ninterface RunnableAgent {\n connect(input: RunAgentInput): Observable<BaseEvent>;\n run(input: RunAgentInput): Observable<BaseEvent>;\n}\n\nfunction hasHeaders(\n agent: AbstractAgent,\n): agent is AbstractAgent & { headers?: Record<string, string> } {\n return \"headers\" in agent;\n}\n\nfunction hasCredentials(\n agent: AbstractAgent,\n): agent is AbstractAgent & { credentials?: RequestCredentials } {\n return \"credentials\" in agent;\n}\n\nfunction isZodError(error: unknown): boolean {\n return (\n error !== null &&\n typeof error === \"object\" &&\n \"name\" in error &&\n (error as { name: string }).name === \"ZodError\"\n );\n}\n\nfunction isAbortError(error: unknown): boolean {\n return (\n (error instanceof DOMException || error instanceof Error) &&\n (error as Error).name === \"AbortError\"\n );\n}\n\nfunction withAbortErrorHandling(\n observable: Observable<BaseEvent>,\n): Observable<BaseEvent> {\n return observable.pipe(\n catchError((error) => {\n if (isZodError(error) || isAbortError(error)) {\n return EMPTY;\n }\n throw error;\n }),\n );\n}\n\nexport interface ProxiedCopilotRuntimeAgentConfig extends Omit<\n HttpAgentConfig,\n \"url\"\n> {\n runtimeUrl?: string;\n transport?: CopilotRuntimeTransport;\n credentials?: RequestCredentials;\n runtimeMode?: ResolvedRuntimeMode;\n intelligence?: IntelligenceRuntimeInfo;\n capabilities?: AgentCapabilities;\n debug?: ResolvedDebugConfig;\n /**\n * When set, runtime requests (HTTP path, single-route envelope, intelligence\n * delegate) are routed to this agent on the runtime instead of `agentId`.\n * The local `agentId` remains the registry key used for subscriber\n * bookkeeping; only outbound routing is overridden.\n */\n runtimeAgentId?: string;\n}\n\nexport class ProxiedCopilotRuntimeAgent extends HttpAgent {\n runtimeUrl?: string;\n credentials?: RequestCredentials;\n // `readonly` because `super.url` is baked at construction; mutating\n // `runtimeAgentId` post-construction would desync the REST `run` URL\n // (already captured) from `routedAgentId()` (consulted per-call by\n // stop/connect/single-route paths).\n readonly runtimeAgentId?: string;\n private transport: CopilotRuntimeTransport;\n private singleEndpointUrl?: string;\n private runtimeMode: ResolvedRuntimeMode;\n private intelligence?: IntelligenceRuntimeInfo;\n private _capabilities?: AgentCapabilities;\n private delegate?: AbstractAgent;\n private runtimeInfoPromise?: Promise<void>;\n\n constructor(config: ProxiedCopilotRuntimeAgentConfig) {\n const normalizedRuntimeUrl = config.runtimeUrl\n ? config.runtimeUrl.replace(/\\/$/, \"\")\n : undefined;\n const transport = config.transport ?? \"auto\";\n const routedId = config.runtimeAgentId ?? config.agentId ?? \"\";\n const runUrl =\n transport === \"single\"\n ? (normalizedRuntimeUrl ?? config.runtimeUrl ?? \"\")\n : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(routedId)}/run`;\n\n if (!runUrl) {\n throw new Error(\n \"ProxiedCopilotRuntimeAgent requires a runtimeUrl when transport is set to 'single'.\",\n );\n }\n\n super({\n ...config,\n url: runUrl,\n });\n this.runtimeUrl = normalizedRuntimeUrl ?? config.runtimeUrl;\n this.credentials = config.credentials;\n this.runtimeAgentId = config.runtimeAgentId;\n this.transport = transport;\n this.runtimeMode = config.runtimeMode ?? RUNTIME_MODE_SSE;\n this.intelligence = config.intelligence;\n this._capabilities = config.capabilities;\n if (config.debug) {\n this.debug = config.debug;\n }\n if (this.transport === \"single\") {\n this.singleEndpointUrl = this.runtimeUrl;\n }\n }\n\n /**\n * The agent id used for outbound runtime requests — `runtimeAgentId` when\n * set (manually-registered proxy), otherwise `agentId` (registry id\n * matches runtime id). Subscriber bookkeeping keeps using `agentId`\n * directly.\n *\n * Throws when both are unset: a proxy reaching an HTTP path with no\n * routable id is a bug, and a missing id would otherwise produce a\n * malformed `/agent//run` or `/agent/undefined/connect` URL silently.\n */\n private routedAgentId(): string {\n const id = this.runtimeAgentId ?? this.agentId;\n if (!id) {\n throw new Error(\n \"ProxiedCopilotRuntimeAgent: cannot make a runtime request without an agentId or runtimeAgentId.\",\n );\n }\n return id;\n }\n\n get capabilities(): AgentCapabilities | undefined {\n return this._capabilities;\n }\n\n override requestInit(input: RunAgentInput): RequestInit {\n const baseInit = super.requestInit(input);\n return {\n ...baseInit,\n ...(this.credentials ? { credentials: this.credentials } : {}),\n };\n }\n\n async getCapabilities(): Promise<AgentCapabilities> {\n return this._capabilities ?? {};\n }\n\n override async detachActiveRun(): Promise<void> {\n if (this.delegate) {\n await this.delegate.detachActiveRun();\n }\n await super.detachActiveRun();\n }\n\n abortRun(): void {\n if (this.delegate) {\n this.syncDelegate(this.delegate);\n this.delegate.abortRun();\n // Also detach the proxy's own runAgent pipeline so the proxy's\n // isRunning resets and onRunFinalized fires even if the delegate's\n // observable doesn't propagate a clean completion.\n void this.detachActiveRun();\n return;\n }\n\n if (!this.agentId || !this.threadId) {\n return;\n }\n\n if (typeof fetch === \"undefined\") {\n return;\n }\n\n const routedId = this.routedAgentId();\n\n if (this.transport === \"single\") {\n if (!this.singleEndpointUrl) {\n return;\n }\n\n const headers = new Headers({\n ...this.headers,\n \"Content-Type\": \"application/json\",\n });\n void fetch(this.singleEndpointUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n method: \"agent/stop\",\n params: {\n agentId: routedId,\n threadId: this.threadId,\n },\n }),\n ...(this.credentials ? { credentials: this.credentials } : {}),\n }).catch((error) => {\n console.error(\"ProxiedCopilotRuntimeAgent: stop request failed\", error);\n });\n return;\n }\n\n if (!this.runtimeUrl) {\n return;\n }\n\n const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(routedId)}/stop/${encodeURIComponent(this.threadId)}`;\n const origin =\n typeof window !== \"undefined\" && window.location\n ? window.location.origin\n : \"http://localhost\";\n const base = new URL(this.runtimeUrl, origin);\n const stopUrl = new URL(stopPath, base);\n\n void fetch(stopUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.headers,\n },\n ...(this.credentials ? { credentials: this.credentials } : {}),\n }).catch((error) => {\n console.error(\"ProxiedCopilotRuntimeAgent: stop request failed\", error);\n });\n }\n\n override async connectAgent(\n parameters?: RunAgentParameters,\n subscriber?: AgentSubscriber,\n ): Promise<RunAgentResult> {\n if (this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) {\n return super.connectAgent(parameters, subscriber);\n }\n\n // If the delegate already has an active run (e.g. from a previous\n // connectAgent call that hasn't finished yet), detach it first. This\n // ensures only one run is active on the delegate at a time — without it,\n // two parallel runs would both pump events into the shared delegate,\n // and both bridge subscriptions would copy the interleaved messages to\n // the proxy, causing the UI to flicker between the two conversations.\n if (this.delegate) {\n await this.delegate.detachActiveRun();\n }\n\n // Ensure the delegate exists and is synced with the proxy's current state.\n await this.resolveDelegate();\n const delegate = this.delegate!;\n\n // Subscribe a bridging observer FIRST so it fires before the forwarded\n // UI subscribers. This keeps proxy.messages in sync with the delegate\n // in real-time — otherwise the UI re-renders (triggered by the\n // forwarded onMessagesChanged) but reads stale proxy.messages because\n // the final sync only happens after connectAgent resolves.\n const bridgeSub = delegate.subscribe({\n onMessagesChanged: () => {\n this.setMessages([...delegate.messages]);\n },\n onStateChanged: () => {\n this.setState({ ...delegate.state });\n },\n // Mirror isRunning so the proxy reflects the delegate's run lifecycle.\n // Without this, UI components read proxy.isRunning (always false) even\n // though the delegate is actively running, causing the stop button to\n // never appear.\n onRunInitialized: () => {\n this.isRunning = true;\n },\n onRunFinalized: () => {\n this.isRunning = false;\n },\n // Local exception (network error, deserialization failure, etc.)\n onRunFailed: () => {\n this.isRunning = false;\n },\n // Protocol-level RUN_ERROR event from the backend\n onRunErrorEvent: () => {\n this.isRunning = false;\n },\n });\n\n // Forward the proxy's subscribers to the delegate so that UI hooks\n // (e.g. useAgent's onMessagesChanged) receive real-time updates as\n // the delegate processes events during connectAgent.\n const forwardedSubs = this.subscribers.map((s) => delegate.subscribe(s));\n\n try {\n const result = await delegate.connectAgent(parameters, subscriber);\n\n // Final sync to guarantee the proxy reflects the delegate's end state.\n this.setMessages([...delegate.messages]);\n this.setState({ ...delegate.state });\n\n return result;\n } finally {\n // Ensure the proxy's isRunning is reset — the bridging subscription\n // may have already handled this, but if the delegate threw before\n // firing onRunFinalized the proxy would be stuck in isRunning=true.\n this.isRunning = false;\n // Remove forwarded subscribers to avoid duplicate notifications on\n // subsequent calls (they'll be re-forwarded next time).\n bridgeSub.unsubscribe();\n for (const sub of forwardedSubs) {\n sub.unsubscribe();\n }\n }\n }\n\n connect(input: RunAgentInput): Observable<BaseEvent> {\n if (\n this.runtimeMode === \"pending\" ||\n (this.transport === \"auto\" &&\n this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE)\n ) {\n return defer(() => from(this.ensureRuntimeConfiguration())).pipe(\n switchMap(() => this.connect(input)),\n );\n }\n if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE) {\n return this.#connectViaDelegate(input);\n }\n return this.#connectViaHttp(input);\n }\n\n public run(input: RunAgentInput): Observable<BaseEvent> {\n if (\n this.runtimeMode === \"pending\" ||\n (this.transport === \"auto\" &&\n this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE)\n ) {\n return defer(() => from(this.ensureRuntimeConfiguration())).pipe(\n switchMap(() => this.run(input)),\n );\n }\n if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE) {\n return this.#runViaDelegate(input);\n }\n return this.#runViaHttp(input);\n }\n\n #connectViaDelegate(input: RunAgentInput): Observable<BaseEvent> {\n return defer(() => from(this.resolveDelegate())).pipe(\n switchMap((delegate) => withAbortErrorHandling(delegate.connect(input))),\n );\n }\n\n #connectViaHttp(input: RunAgentInput): Observable<BaseEvent> {\n const routedId = this.routedAgentId();\n if (this.transport === \"single\") {\n if (!this.singleEndpointUrl) {\n throw new Error(\"Single endpoint transport requires a runtimeUrl\");\n }\n\n const requestInit = this.createSingleRouteRequestInit(\n input,\n \"agent/connect\",\n {\n agentId: routedId,\n },\n );\n const httpEvents = runHttpRequest(() =>\n this.fetch(this.singleEndpointUrl!, requestInit),\n );\n return withAbortErrorHandling(transformHttpEventStream(httpEvents));\n }\n\n const connectUrl = `${this.runtimeUrl}/agent/${routedId}/connect`;\n const connectRequestInit = this.requestInit(input);\n const httpEvents = runHttpRequest(() =>\n this.fetch(connectUrl, connectRequestInit),\n );\n return withAbortErrorHandling(transformHttpEventStream(httpEvents));\n }\n\n #runViaDelegate(input: RunAgentInput): Observable<BaseEvent> {\n return defer(() => from(this.resolveDelegate())).pipe(\n switchMap((delegate) => withAbortErrorHandling(delegate.run(input))),\n );\n }\n\n #runViaHttp(input: RunAgentInput): Observable<BaseEvent> {\n if (this.transport === \"single\") {\n if (!this.singleEndpointUrl) {\n throw new Error(\"Single endpoint transport requires a runtimeUrl\");\n }\n\n const requestInit = this.createSingleRouteRequestInit(\n input,\n \"agent/run\",\n {\n agentId: this.routedAgentId(),\n },\n );\n const httpEvents = runHttpRequest(() =>\n this.fetch(this.singleEndpointUrl!, requestInit),\n );\n return withAbortErrorHandling(transformHttpEventStream(httpEvents));\n }\n\n return withAbortErrorHandling(super.run(input));\n }\n\n public override clone(): ProxiedCopilotRuntimeAgent {\n const cloned = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: this.runtimeUrl,\n agentId: this.agentId,\n runtimeAgentId: this.runtimeAgentId,\n description: this.description,\n headers: { ...this.headers },\n credentials: this.credentials,\n transport: this.transport,\n runtimeMode: this.runtimeMode,\n intelligence: this.intelligence,\n capabilities: this._capabilities,\n debug: this.debug,\n });\n cloned.threadId = this.threadId;\n cloned.setState(this.state);\n cloned.setMessages(this.messages);\n if (this.delegate) {\n const clonedDelegate: AbstractAgent = this.delegate.clone();\n cloned.delegate = clonedDelegate;\n cloned.syncDelegate(clonedDelegate);\n }\n return cloned;\n }\n\n /**\n * Drop the delegate's cached `lastSeenEventId` for this thread so\n * the next connect requests a full historical replay from the\n * gateway. Used by `RunHandler.connectAgent` on a detected thread\n * switch (the chat moved between threads, so its local\n * messages/state are about to be cleared and need rebuilding from\n * the gateway). Skipped on same-thread churn re-connects so the\n * gateway can resume from the cursor instead.\n *\n * No-op for non-Intelligence runtime modes — the HTTP transport\n * doesn't replay.\n */\n public clearReplayCursor(threadId: string): void {\n if (this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) return;\n const delegate = this.delegate as\n | { clearReconnectCursor?: (id: string) => void }\n | null\n | undefined;\n delegate?.clearReconnectCursor?.(threadId);\n }\n\n private async resolveDelegate(): Promise<RunnableAgent> {\n await this.ensureRuntimeConfiguration();\n\n if (!this.delegate) {\n if (this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) {\n throw new Error(\"A delegate is only created for Intelligence mode\");\n }\n this.delegate = this.createIntelligenceDelegate();\n }\n\n this.syncDelegate(this.delegate);\n\n // AbstractAgent declares connect() as protected, but concrete delegates\n // (IntelligenceAgent, HttpAgent) expose both connect() and run() publicly.\n return this.delegate as unknown as RunnableAgent;\n }\n\n /** Resolve transport and runtime mode before the first outbound request. */\n private async ensureRuntimeConfiguration(): Promise<void> {\n if (\n this.runtimeMode === RUNTIME_MODE_INTELLIGENCE ||\n (this.runtimeMode !== \"pending\" && this.transport !== \"auto\")\n ) {\n return;\n }\n\n if (!this.runtimeUrl) {\n throw new Error(\"Runtime URL is not set\");\n }\n\n const runtimeInfoPromise =\n this.runtimeInfoPromise ??\n this.fetchRuntimeInfo().then((runtimeInfo) => {\n this.runtimeMode = runtimeInfo.mode ?? RUNTIME_MODE_SSE;\n this.intelligence = runtimeInfo.intelligence;\n });\n this.runtimeInfoPromise = runtimeInfoPromise;\n\n try {\n await runtimeInfoPromise;\n } catch (error) {\n if (this.runtimeInfoPromise === runtimeInfoPromise) {\n this.runtimeInfoPromise = undefined;\n }\n throw error;\n }\n }\n\n private async fetchRuntimeInfo(): Promise<RuntimeInfo> {\n const headers: Record<string, string> = {\n ...this.headers,\n };\n\n if (this.transport === \"auto\") {\n return this.fetchRuntimeInfoAutoDetect(headers);\n }\n\n let init: RequestInit;\n let url: string;\n\n if (this.transport === \"single\") {\n if (!this.singleEndpointUrl) {\n throw new Error(\"Single endpoint transport requires a runtimeUrl\");\n }\n if (!headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n url = this.runtimeUrl!;\n init = { method: \"POST\", body: JSON.stringify({ method: \"info\" }) };\n } else {\n url = `${this.runtimeUrl}/info`;\n init = {};\n }\n\n const response = await fetch(url, {\n ...init,\n headers,\n ...(this.credentials ? { credentials: this.credentials } : {}),\n });\n if (!response.ok) {\n throw new Error(\n `Runtime info request failed with status ${response.status}`,\n );\n }\n return (await response.json()) as RuntimeInfo;\n }\n\n private async fetchRuntimeInfoAutoDetect(\n headers: Record<string, string>,\n ): Promise<RuntimeInfo> {\n // Try REST first (GET /info)\n try {\n const response = await fetch(`${this.runtimeUrl}/info`, {\n headers: { ...headers },\n ...(this.credentials ? { credentials: this.credentials } : {}),\n });\n // Only treat a successful (2xx) response as a valid REST runtime.\n // 404/405 means the endpoint doesn't exist; other non-2xx errors\n // (500, 403, etc.) should also fall through to single-endpoint.\n if (response.status >= 200 && response.status < 300) {\n this.transport = \"rest\";\n return (await response.json()) as RuntimeInfo;\n }\n } catch {\n // REST failed — fall through to single-endpoint attempt\n }\n\n // Try single-endpoint (POST with { method: \"info\" })\n const singleHeaders = { ...headers };\n if (!singleHeaders[\"Content-Type\"]) {\n singleHeaders[\"Content-Type\"] = \"application/json\";\n }\n const response = await fetch(this.runtimeUrl!, {\n method: \"POST\",\n headers: singleHeaders,\n body: JSON.stringify({ method: \"info\" }),\n ...(this.credentials ? { credentials: this.credentials } : {}),\n });\n if (!response.ok) {\n throw new Error(\n `Runtime info request failed with status ${response.status}`,\n );\n }\n this.transport = \"single\";\n this.singleEndpointUrl = this.runtimeUrl;\n return (await response.json()) as RuntimeInfo;\n }\n\n private createSingleRouteRequestInit(\n input: RunAgentInput,\n method: string,\n params?: Record<string, string>,\n ): RequestInit {\n if (!this.agentId) {\n throw new Error(\n \"ProxiedCopilotRuntimeAgent requires agentId to make runtime requests\",\n );\n }\n\n const baseInit = super.requestInit(input);\n const headers = new Headers(baseInit.headers ?? {});\n headers.set(\"Content-Type\", \"application/json\");\n headers.set(\"Accept\", headers.get(\"Accept\") ?? \"text/event-stream\");\n\n let originalBody: unknown = undefined;\n if (typeof baseInit.body === \"string\") {\n try {\n originalBody = JSON.parse(baseInit.body);\n } catch (error) {\n console.warn(\n \"ProxiedCopilotRuntimeAgent: failed to parse request body for single route transport\",\n error,\n );\n }\n }\n\n const envelope: Record<string, unknown> = { method };\n\n if (params && Object.keys(params).length > 0) {\n envelope.params = params;\n }\n\n if (originalBody !== undefined) {\n envelope.body = originalBody;\n }\n\n return {\n ...baseInit,\n headers,\n body: JSON.stringify(envelope),\n ...(this.credentials ? { credentials: this.credentials } : {}),\n };\n }\n\n private createIntelligenceDelegate(): AbstractAgent {\n const routedId = this.routedAgentId();\n if (!this.runtimeUrl || !routedId || !this.intelligence?.wsUrl) {\n throw new Error(\n \"Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata\",\n );\n }\n\n return new IntelligenceAgent({\n url: this.intelligence.wsUrl,\n runtimeUrl: this.runtimeUrl,\n agentId: routedId,\n headers: { ...this.headers },\n credentials: this.credentials,\n });\n }\n\n private syncDelegate(delegate: AbstractAgent): void {\n // Delegate is the IntelligenceAgent that talks to the runtime — it must\n // use the routed id so that requests reach the right runtime agent.\n delegate.agentId = this.routedAgentId();\n delegate.description = this.description;\n delegate.threadId = this.threadId;\n delegate.setMessages(this.messages);\n delegate.setState(this.state);\n\n if (hasHeaders(delegate)) {\n delegate.headers = { ...this.headers };\n }\n\n if (hasCredentials(delegate)) {\n delegate.credentials = this.credentials;\n }\n }\n}\n","import type { AbstractAgent } from \"@ag-ui/client\";\nimport { HttpAgent } from \"@ag-ui/client\";\nimport type {\n RuntimeInfo,\n AgentDescription,\n RuntimeMode,\n RuntimeLicenseStatus,\n IntelligenceRuntimeInfo,\n ThreadEndpointRuntimeInfo,\n} from \"@copilotkit/shared\";\nimport {\n logger,\n RUNTIME_MODE_SSE,\n resolveDebugConfig,\n} from \"@copilotkit/shared\";\nimport { ProxiedCopilotRuntimeAgent } from \"../agent\";\nimport type { CopilotKitCore, CopilotKitCoreFriendsAccess } from \"./core\";\nimport {\n CopilotKitCoreErrorCode,\n CopilotKitCoreRuntimeConnectionStatus,\n} from \"./core\";\nimport type { CopilotRuntimeTransport } from \"../types\";\n\nexport interface CopilotKitCoreAddAgentParams {\n id: string;\n agent: AbstractAgent;\n}\n\n/**\n * Parameters for registering a proxied agent against an existing runtime agent.\n */\nexport interface CopilotKitCoreRegisterProxiedAgentParams {\n /**\n * The local registry id under which the proxy is registered. Used by\n * `useAgent`, state-manager subscriptions, and all subscriber bookkeeping.\n * Must not collide with any existing local or runtime-discovered agent id.\n */\n agentId: string;\n /**\n * The id of the runtime agent that this proxy routes outbound HTTP requests\n * to. Invisible to subscribers — only affects URL paths and single-route\n * envelopes.\n */\n runtimeAgentId: string;\n}\n\nexport interface CopilotKitCoreRegisterProxiedAgentResult {\n agent: ProxiedCopilotRuntimeAgent;\n unregister: () => void;\n}\n\n/**\n * Manages agent registration, lifecycle, and runtime connectivity for CopilotKitCore.\n * Handles both local development agents and remote runtime agents.\n */\nexport class AgentRegistry {\n private _agents: Record<string, AbstractAgent> = {};\n private localAgents: Record<string, AbstractAgent> = {};\n private remoteAgents: Record<string, AbstractAgent> = {};\n\n private _runtimeUrl?: string;\n // Tracks an in-flight `/info` connection so concurrent calls targeting the\n // same runtime (url + requested transport) collapse to a single request\n // instead of each firing their own. See #5801.\n private _connectionInFlight?: { key: string; promise: Promise<void> };\n private _runtimeVersion?: string;\n private _runtimeConnectionStatus: CopilotKitCoreRuntimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Disconnected;\n private _runtimeTransport: CopilotRuntimeTransport = \"auto\";\n // The transport MODE last requested via `setRuntimeTransport` (e.g. \"auto\").\n // Distinct from `_runtimeTransport`, which auto-detect overwrites with the\n // RESOLVED value (\"rest\"/\"single\"). The idempotency guard compares against\n // this so re-applying the same mode (the provider effect re-applies \"auto\"\n // on every render) is a no-op instead of re-running the /info handshake.\n private _requestedTransport: CopilotRuntimeTransport = \"auto\";\n private _audioFileTranscriptionEnabled: boolean = false;\n private _runtimeMode: RuntimeMode = RUNTIME_MODE_SSE;\n private _intelligence?: IntelligenceRuntimeInfo;\n private _threadEndpoints?: ThreadEndpointRuntimeInfo;\n private _suggestions?: boolean;\n private _a2uiEnabled: boolean = false;\n private _a2uiAgents?: string[];\n private _openGenerativeUIEnabled: boolean = false;\n private _licenseStatus?: RuntimeLicenseStatus;\n private _telemetryDisabled: boolean = false;\n\n /**\n * The headers each HttpAgent was constructed with, captured on the first\n * `applyHeadersToAgent` call for that agent (which, for agents the registry\n * owns, happens at registration before any core headers are applied). Core\n * headers are merged ON TOP of this baseline so that headers configured\n * directly on an agent (e.g. an `Authorization` for a self-hosted backend)\n * survive registration instead of being silently replaced. The baseline is\n * captured once and never re-captured, so a later direct mutation of\n * `agent.headers` is not folded into it. See #5635.\n */\n private agentOwnHeaders = new WeakMap<HttpAgent, Record<string, string>>();\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Get all agents as a readonly record\n */\n get agents(): Readonly<Record<string, AbstractAgent>> {\n return this._agents;\n }\n\n get runtimeUrl(): string | undefined {\n return this._runtimeUrl;\n }\n\n get runtimeVersion(): string | undefined {\n return this._runtimeVersion;\n }\n\n get runtimeConnectionStatus(): CopilotKitCoreRuntimeConnectionStatus {\n return this._runtimeConnectionStatus;\n }\n\n get runtimeTransport(): CopilotRuntimeTransport {\n return this._runtimeTransport;\n }\n\n get audioFileTranscriptionEnabled(): boolean {\n return this._audioFileTranscriptionEnabled;\n }\n\n get runtimeMode(): RuntimeMode {\n return this._runtimeMode;\n }\n\n get intelligence(): IntelligenceRuntimeInfo | undefined {\n return this._intelligence;\n }\n\n get threadEndpoints(): ThreadEndpointRuntimeInfo | undefined {\n return this._threadEndpoints;\n }\n\n get suggestions(): boolean | undefined {\n return this._suggestions;\n }\n\n get a2uiEnabled(): boolean {\n return this._a2uiEnabled;\n }\n\n /**\n * Agent ids the runtime applies A2UI to (#5369). `undefined` means A2UI\n * applies to every agent — or is disabled entirely; check `a2uiEnabled`.\n */\n get a2uiAgents(): string[] | undefined {\n return this._a2uiAgents;\n }\n\n get openGenerativeUIEnabled(): boolean {\n return this._openGenerativeUIEnabled;\n }\n\n get licenseStatus(): RuntimeLicenseStatus | undefined {\n return this._licenseStatus;\n }\n\n get telemetryDisabled(): boolean {\n return this._telemetryDisabled;\n }\n\n /**\n * Initialize agents from configuration\n */\n initialize(agents: Record<string, AbstractAgent>): void {\n this.localAgents = this.assignAgentIds(agents);\n this.applyHeadersToAgents(this.localAgents);\n this.applyCredentialsToAgents(this.localAgents);\n this._agents = this.localAgents;\n }\n\n /**\n * Set the runtime URL and update connection\n */\n setRuntimeUrl(\n runtimeUrl: string | undefined,\n options?: { deferConnection?: boolean },\n ): void {\n const normalizedRuntimeUrl = runtimeUrl\n ? runtimeUrl.replace(/\\/$/, \"\")\n : undefined;\n\n if (this._runtimeUrl === normalizedRuntimeUrl) {\n return;\n }\n\n this._runtimeUrl = normalizedRuntimeUrl;\n\n // Deferred construction (see CopilotKitCore.connect / #5801): record the URL\n // so getters/hooks see it synchronously, but do NOT start the `/info` fetch\n // here. The host starts it from a commit-phase effect via `connect()`, so\n // renders discarded before commit never issue a request.\n if (options?.deferConnection) {\n return;\n }\n\n void this.updateRuntimeConnection();\n }\n\n /**\n * Start the initial runtime connection if it has not been started yet.\n *\n * Backs {@link CopilotKitCore.connect}. Idempotent: it only kicks off a fetch\n * when a `runtimeUrl` is set and the connection is still `Disconnected` (its\n * state before any connect attempt). `updateRuntimeConnection` flips the\n * status to `Connecting` synchronously, so a second call — e.g. React\n * StrictMode double-invoking the mount effect — bails here. A genuine config\n * change still reconnects through `setRuntimeUrl`/`setRuntimeTransport`. See\n * #5801.\n */\n connectRuntime(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n if (!this._runtimeUrl) {\n return;\n }\n if (\n this._runtimeConnectionStatus !==\n CopilotKitCoreRuntimeConnectionStatus.Disconnected\n ) {\n return;\n }\n void this.updateRuntimeConnection();\n }\n\n setRuntimeTransport(runtimeTransport: CopilotRuntimeTransport): void {\n // Guard on the requested MODE, not the resolved value: after auto-detect\n // writes `_runtimeTransport = \"rest\"`, re-applying the same requested\n // \"auto\" must not be treated as a change (otherwise every provider\n // re-render re-runs the /info handshake and rebuilds agents).\n if (this._requestedTransport === runtimeTransport) {\n return;\n }\n\n this._requestedTransport = runtimeTransport;\n this._runtimeTransport = runtimeTransport;\n void this.updateRuntimeConnection();\n }\n\n /**\n * Set all agents at once (for development use)\n */\n setAgents__unsafe_dev_only(agents: Record<string, AbstractAgent>): void {\n // Validate all agents before making any changes\n Object.entries(agents).forEach(([id, agent]) => {\n if (agent) {\n this.validateAndAssignAgentId(id, agent);\n }\n });\n this.localAgents = agents;\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n this.applyHeadersToAgents(this._agents);\n this.applyCredentialsToAgents(this._agents);\n void this.notifyAgentsChanged();\n }\n\n /**\n * Add a single agent (for development use)\n */\n addAgent__unsafe_dev_only({ id, agent }: CopilotKitCoreAddAgentParams): void {\n this.validateAndAssignAgentId(id, agent);\n this.localAgents[id] = agent;\n this.applyHeadersToAgent(agent);\n this.applyCredentialsToAgent(agent);\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n void this.notifyAgentsChanged();\n }\n\n /**\n * Remove an agent by ID (for development use)\n */\n removeAgent__unsafe_dev_only(id: string): void {\n delete this.localAgents[id];\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n void this.notifyAgentsChanged();\n }\n\n /**\n * Register a proxied agent that routes outbound runtime requests to an\n * existing runtime agent (`runtimeAgentId`) while exposing a distinct local\n * registry id (`agentId`). Throws if `agentId` is already taken by either a\n * local or runtime-discovered agent.\n *\n * Use this to mount multiple frontend agents against a single runtime\n * agent (e.g. a chat-1 / chat-2 pair both proxying to \"default\") without\n * implicit per-thread cloning. The returned `unregister` removes the proxy\n * from the registry and emits `onAgentsChanged`.\n */\n registerProxiedAgent({\n agentId,\n runtimeAgentId,\n }: CopilotKitCoreRegisterProxiedAgentParams): CopilotKitCoreRegisterProxiedAgentResult {\n // Use hasOwnProperty rather than `in`: `in` walks the prototype chain,\n // so an agentId of \"__proto__\", \"constructor\", \"toString\" etc. would\n // falsely test as already-registered.\n if (Object.prototype.hasOwnProperty.call(this._agents, agentId)) {\n throw new Error(\n `CopilotKitCore.registerProxiedAgent: agentId \"${agentId}\" is already registered. ` +\n `Pick a different agentId, or unregister the existing agent first.`,\n );\n }\n\n const friends = this.core as unknown as CopilotKitCoreFriendsAccess;\n const debug = friends.debug;\n const agent = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: this._runtimeUrl,\n agentId,\n runtimeAgentId,\n transport: this._runtimeTransport,\n credentials: friends.credentials,\n // If runtime info has already synced, mirror its mode/intelligence so\n // the proxy doesn't have to re-resolve. Otherwise stay \"pending\" until\n // /info lands.\n runtimeMode: this._runtimeUrl\n ? this._runtimeConnectionStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Connected\n ? this._runtimeMode\n : \"pending\"\n : RUNTIME_MODE_SSE,\n intelligence: this._intelligence,\n debug: debug ? resolveDebugConfig(debug) : undefined,\n });\n this.applyHeadersToAgent(agent);\n\n this.localAgents[agentId] = agent;\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n void this.notifyAgentsChanged();\n\n return {\n agent,\n unregister: () => {\n // Only unregister if the same instance is still in place — guards\n // against double-unregister or against unregistering after a\n // subsequent register replaced the slot.\n if (this.localAgents[agentId] === agent) {\n delete this.localAgents[agentId];\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n void this.notifyAgentsChanged();\n }\n },\n };\n }\n\n /**\n * Get an agent by ID\n */\n getAgent(id: string): AbstractAgent | undefined {\n if (id in this._agents) {\n return this._agents[id] as AbstractAgent;\n }\n\n // Silently return undefined if we're still loading runtime agents\n if (\n this.runtimeUrl !== undefined &&\n (this.runtimeConnectionStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Disconnected ||\n this.runtimeConnectionStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Connecting)\n ) {\n return undefined;\n }\n\n console.warn(`Agent ${id} not found`);\n return undefined;\n }\n\n /**\n * Apply current core headers to an agent, merged ON TOP of the agent's own\n * construction-time headers (the per-agent baseline in `agentOwnHeaders`).\n * Core wins on a key conflict. Non-`HttpAgent` agents are left untouched\n * because only `HttpAgent` carries a `headers` field. See #5635.\n */\n applyHeadersToAgent(agent: AbstractAgent): void {\n if (agent instanceof HttpAgent) {\n // Capture the agent's construction-time headers once, before any core\n // headers overwrite them. On every subsequent apply we rebuild from this\n // baseline so re-applying core headers (e.g. via setHeaders) never loses\n // the agent's own headers.\n if (!this.agentOwnHeaders.has(agent)) {\n this.agentOwnHeaders.set(agent, { ...agent.headers });\n }\n agent.headers = {\n ...this.agentOwnHeaders.get(agent),\n ...(this.core as unknown as CopilotKitCoreFriendsAccess).headers,\n };\n }\n }\n\n /**\n * Apply current headers to all agents\n */\n applyHeadersToAgents(agents: Record<string, AbstractAgent>): void {\n Object.values(agents).forEach((agent) => {\n this.applyHeadersToAgent(agent);\n });\n }\n\n /**\n * Apply current credentials to an agent\n */\n applyCredentialsToAgent(agent: AbstractAgent): void {\n if (agent instanceof ProxiedCopilotRuntimeAgent) {\n agent.credentials = (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).credentials;\n }\n }\n\n /**\n * Apply current credentials to all agents\n */\n applyCredentialsToAgents(agents: Record<string, AbstractAgent>): void {\n Object.values(agents).forEach((agent) => {\n this.applyCredentialsToAgent(agent);\n });\n }\n\n /**\n * Update runtime connection and fetch remote agents\n */\n private async updateRuntimeConnection(): Promise<void> {\n // Skip fetching on the server (SSR)\n if (typeof window === \"undefined\") {\n return;\n }\n\n // In-flight guard: if a connection to the same target (runtime url +\n // requested transport) is already running, reuse it instead of starting a\n // second `/info` request. A change to a different target supersedes it. See\n // #5801.\n const key = `${this._runtimeUrl ?? \"\"}::${this._requestedTransport}`;\n const inFlight = this._connectionInFlight;\n if (inFlight && inFlight.key === key) {\n return inFlight.promise;\n }\n\n const promise = this.performRuntimeConnection();\n this._connectionInFlight = { key, promise };\n void promise.finally(() => {\n if (this._connectionInFlight?.promise === promise) {\n this._connectionInFlight = undefined;\n }\n });\n return promise;\n }\n\n private async performRuntimeConnection(): Promise<void> {\n if (!this.runtimeUrl) {\n this._runtimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Disconnected;\n this._runtimeVersion = undefined;\n this._audioFileTranscriptionEnabled = false;\n this._runtimeMode = RUNTIME_MODE_SSE;\n this._intelligence = undefined;\n this._threadEndpoints = undefined;\n this._suggestions = undefined;\n this._a2uiEnabled = false;\n this._a2uiAgents = undefined;\n this._openGenerativeUIEnabled = false;\n this.remoteAgents = {};\n this._agents = this.localAgents;\n\n await this.notifyRuntimeStatusChanged(\n CopilotKitCoreRuntimeConnectionStatus.Disconnected,\n );\n await this.notifyAgentsChanged();\n return;\n }\n\n this._runtimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Connecting;\n await this.notifyRuntimeStatusChanged(\n CopilotKitCoreRuntimeConnectionStatus.Connecting,\n );\n\n try {\n const runtimeInfoResponse = await this.fetchRuntimeInfo();\n const {\n version,\n ...runtimeInfo\n }: {\n agents: Record<string, AgentDescription>;\n version: string;\n mode?: RuntimeMode;\n intelligence?: IntelligenceRuntimeInfo;\n threadEndpoints?: ThreadEndpointRuntimeInfo;\n suggestions?: boolean;\n } = runtimeInfoResponse;\n\n const credentials = (this.core as unknown as CopilotKitCoreFriendsAccess)\n .credentials;\n const rawDebug = (this.core as unknown as CopilotKitCoreFriendsAccess)\n .debug;\n const agents: Record<string, AbstractAgent> = Object.fromEntries(\n Object.entries(runtimeInfo.agents).map(\n ([id, { description, capabilities }]) => {\n // Reuse the already-registered instance for ids that are still\n // present. A re-connection (an /info re-settle, a header/config or\n // transport change) re-runs this method, but the runtime agent for\n // a given id is the SAME logical agent — minting a fresh instance\n // would discard its accumulated `messages`/`threadId` and its live\n // subscriptions. Downstream (e.g. the `use-agent` memo) keys on the\n // instance identity returned by `getAgent(id)`, so replacing it\n // unmounts an already-rendered conversation. Only re-apply what the\n // registry owns (headers + credentials) in place; the proxy\n // re-resolves its own runtime mode/intelligence via `/info`.\n const existing = Object.prototype.hasOwnProperty.call(\n this.remoteAgents,\n id,\n )\n ? this.remoteAgents[id]\n : undefined;\n if (existing instanceof ProxiedCopilotRuntimeAgent) {\n this.applyHeadersToAgent(existing);\n this.applyCredentialsToAgent(existing);\n return [id, existing];\n }\n const agent = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: this.runtimeUrl,\n agentId: id, // Runtime agents always have their ID set correctly\n description: description,\n transport: this._runtimeTransport,\n credentials,\n runtimeMode: runtimeInfoResponse.mode ?? RUNTIME_MODE_SSE,\n intelligence: runtimeInfoResponse.intelligence,\n capabilities,\n debug: rawDebug ? resolveDebugConfig(rawDebug) : undefined,\n });\n this.applyHeadersToAgent(agent);\n return [id, agent];\n },\n ),\n );\n\n // Reassign the full set: ids present in `runtimeInfo.agents` are carried\n // over (reused or freshly minted above); ids no longer advertised are\n // dropped because they are absent from this rebuilt map.\n this.remoteAgents = agents;\n this._agents = { ...this.localAgents, ...this.remoteAgents };\n this._runtimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Connected;\n this._runtimeVersion = version;\n this._audioFileTranscriptionEnabled =\n runtimeInfoResponse.audioFileTranscriptionEnabled ?? false;\n this._runtimeMode = runtimeInfoResponse.mode ?? RUNTIME_MODE_SSE;\n this._intelligence = runtimeInfoResponse.intelligence;\n this._threadEndpoints = runtimeInfoResponse.threadEndpoints;\n this._suggestions = runtimeInfoResponse.suggestions;\n const a2uiInfo = runtimeInfoResponse.a2ui;\n this._a2uiEnabled =\n a2uiInfo?.enabled ?? runtimeInfoResponse.a2uiEnabled ?? false;\n this._a2uiAgents = a2uiInfo?.enabled ? a2uiInfo.agents : undefined;\n this._openGenerativeUIEnabled =\n runtimeInfoResponse.openGenerativeUIEnabled ?? false;\n this._licenseStatus = runtimeInfoResponse.licenseStatus;\n this._telemetryDisabled = runtimeInfoResponse.telemetryDisabled ?? false;\n\n await this.notifyRuntimeStatusChanged(\n CopilotKitCoreRuntimeConnectionStatus.Connected,\n );\n await this.notifyAgentsChanged();\n } catch (error) {\n this._runtimeConnectionStatus =\n CopilotKitCoreRuntimeConnectionStatus.Error;\n this._runtimeVersion = undefined;\n this._audioFileTranscriptionEnabled = false;\n this._runtimeMode = RUNTIME_MODE_SSE;\n this._intelligence = undefined;\n this._threadEndpoints = undefined;\n this._suggestions = undefined;\n this._a2uiEnabled = false;\n this._a2uiAgents = undefined;\n this._openGenerativeUIEnabled = false;\n this.remoteAgents = {};\n this._agents = this.localAgents;\n\n await this.notifyRuntimeStatusChanged(\n CopilotKitCoreRuntimeConnectionStatus.Error,\n );\n await this.notifyAgentsChanged();\n\n const message =\n error instanceof Error ? error.message : JSON.stringify(error);\n logger.warn(\n `Failed to load runtime info (${this.runtimeUrl}/info): ${message}`,\n );\n const runtimeError =\n error instanceof Error ? error : new Error(String(error));\n await (this.core as unknown as CopilotKitCoreFriendsAccess).emitError({\n error: runtimeError,\n code: CopilotKitCoreErrorCode.RUNTIME_INFO_FETCH_FAILED,\n context: {\n runtimeUrl: this.runtimeUrl,\n },\n });\n }\n }\n\n private async fetchRuntimeInfo(): Promise<RuntimeInfo> {\n if (!this.runtimeUrl) {\n throw new Error(\"Runtime URL is not set\");\n }\n\n const baseHeaders = (this.core as unknown as CopilotKitCoreFriendsAccess)\n .headers;\n const credentials = (this.core as unknown as CopilotKitCoreFriendsAccess)\n .credentials;\n const headers: Record<string, string> = {\n ...baseHeaders,\n };\n\n if (this._runtimeTransport === \"single\") {\n return this.fetchRuntimeInfoSingle(headers, credentials);\n }\n\n if (this._runtimeTransport === \"auto\") {\n return this.fetchRuntimeInfoAutoDetect(headers, credentials);\n }\n\n // REST transport\n const response = await fetch(`${this.runtimeUrl}/info`, {\n headers,\n ...(credentials ? { credentials } : {}),\n });\n if (!response.ok) {\n throw new Error(\n `Runtime info request failed with status ${response.status}`,\n );\n }\n return (await response.json()) as RuntimeInfo;\n }\n\n private async fetchRuntimeInfoSingle(\n headers: Record<string, string>,\n credentials: RequestCredentials | undefined,\n ): Promise<RuntimeInfo> {\n if (!headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n const response = await fetch(this.runtimeUrl!, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ method: \"info\" }),\n ...(credentials ? { credentials } : {}),\n });\n if (!response.ok) {\n throw new Error(\n `Runtime info request failed with status ${response.status}`,\n );\n }\n return (await response.json()) as RuntimeInfo;\n }\n\n /**\n * Auto-detect transport by trying REST first, then falling back to single-endpoint.\n * Updates `_runtimeTransport` to the detected value so subsequent requests use it directly.\n */\n private async fetchRuntimeInfoAutoDetect(\n headers: Record<string, string>,\n credentials: RequestCredentials | undefined,\n ): Promise<RuntimeInfo> {\n // Try REST first (GET /info)\n try {\n const response = await fetch(`${this.runtimeUrl}/info`, {\n headers: { ...headers },\n ...(credentials ? { credentials } : {}),\n });\n // Only treat a successful (2xx) response as a valid REST runtime.\n // 404/405 means the endpoint doesn't exist; other non-2xx errors\n // (500, 403, etc.) should also fall through to single-endpoint.\n if (response.status >= 200 && response.status < 300) {\n this._runtimeTransport = \"rest\";\n return (await response.json()) as RuntimeInfo;\n }\n // Non-2xx — try single-endpoint below\n } catch {\n // REST failed (network error, etc.) — fall through to single-endpoint attempt\n }\n\n const result = await this.fetchRuntimeInfoSingle(\n { ...headers },\n credentials,\n );\n this._runtimeTransport = \"single\";\n return result;\n }\n\n /**\n * Assign agent IDs to a record of agents\n */\n private assignAgentIds(\n agents: Record<string, AbstractAgent>,\n ): Record<string, AbstractAgent> {\n Object.entries(agents).forEach(([id, agent]) => {\n if (agent) {\n this.validateAndAssignAgentId(id, agent);\n }\n });\n return agents;\n }\n\n /**\n * Validate and assign an agent ID\n */\n private validateAndAssignAgentId(\n registrationId: string,\n agent: AbstractAgent,\n ): void {\n if (agent.agentId && agent.agentId !== registrationId) {\n throw new Error(\n `Agent registration mismatch: Agent with ID \"${agent.agentId}\" cannot be registered under key \"${registrationId}\". ` +\n `The agent ID must match the registration key or be undefined.`,\n );\n }\n if (!agent.agentId) {\n agent.agentId = registrationId;\n }\n }\n\n /**\n * Notify subscribers of runtime status changes\n */\n private async notifyRuntimeStatusChanged(\n status: CopilotKitCoreRuntimeConnectionStatus,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onRuntimeConnectionStatusChanged?.({\n copilotkit: this.core,\n status,\n }),\n \"Error in CopilotKitCore subscriber (onRuntimeConnectionStatusChanged):\",\n );\n }\n\n /**\n * Notify subscribers of agent changes\n */\n private async notifyAgentsChanged(): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onAgentsChanged?.({\n copilotkit: this.core,\n agents: this._agents,\n }),\n \"Subscriber onAgentsChanged error:\",\n );\n }\n}\n","import type { Context } from \"@ag-ui/client\";\nimport { randomUUID } from \"@copilotkit/shared\";\nimport type { CopilotKitCore } from \"./core\";\nimport type { CopilotKitCoreFriendsAccess } from \"./core\";\n\n/**\n * A context entry with optional per-agent scoping.\n * When `agentIds` is set, the entry is forwarded only to runs of those agents;\n * when omitted, the entry is forwarded to every agent run.\n */\nexport interface ScopedContext extends Context {\n agentIds?: string[];\n}\n\n/**\n * Manages context storage and lifecycle for CopilotKitCore.\n * Context represents additional information available to agents during execution.\n */\nexport class ContextStore {\n private _context: Record<string, ScopedContext> = {};\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Get all context entries as a readonly record\n */\n get context(): Readonly<Record<string, ScopedContext>> {\n return this._context;\n }\n\n /**\n * Add a new context entry. Pass `agentIds` to restrict the entry to runs of\n * specific agents (#5369); omit it for context every agent should receive.\n * @returns The ID of the created context entry\n */\n addContext({ description, value, agentIds }: ScopedContext): string {\n const id = randomUUID();\n this._context[id] = {\n description,\n value,\n ...(agentIds ? { agentIds } : {}),\n };\n void this.notifySubscribers();\n return id;\n }\n\n /**\n * Build the context array for a run of the given agent: entries scoped to\n * other agents are dropped, and the scoping metadata is stripped so only\n * protocol-shaped `{ description, value }` entries go over the wire.\n */\n getContextForAgent(agentId?: string): Context[] {\n return Object.values(this._context)\n .filter(\n (entry) =>\n !entry.agentIds ||\n (agentId !== undefined && entry.agentIds.includes(agentId)),\n )\n .map(({ description, value }) => ({ description, value }));\n }\n\n /**\n * Remove a context entry by ID\n */\n removeContext(id: string): void {\n delete this._context[id];\n void this.notifySubscribers();\n }\n\n /**\n * Notify all subscribers of context changes\n */\n private async notifySubscribers(): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onContextChanged?.({\n copilotkit: this.core,\n context: this._context,\n }),\n \"Subscriber onContextChanged error:\",\n );\n }\n}\n","import type { AbstractAgent, Message, Tool } from \"@ag-ui/client\";\nimport { HttpAgent } from \"@ag-ui/client\";\nimport { randomUUID, partialJSONParse } from \"@copilotkit/shared\";\nimport type { CopilotKitCore } from \"./core\";\nimport type { CopilotKitCoreGetSuggestionsResult } from \"./core\";\nimport type { CopilotKitCoreFriendsAccess } from \"./core\";\nimport type {\n DynamicSuggestionsConfig,\n StaticSuggestionsConfig,\n Suggestion,\n SuggestionsConfig,\n} from \"../types\";\n\n/**\n * The minimal cancellation surface a running suggestion generation exposes.\n * Both a cloned `AbstractAgent` (via `abortRun`) and the stateless fetch shim\n * (which aborts an `AbortController`) satisfy this, so `clearSuggestions` can\n * cancel either uniformly.\n */\ninterface AbortableSuggestionRun {\n abortRun(): void;\n}\n\n/**\n * Manages suggestion generation, streaming, and lifecycle for CopilotKitCore.\n * Handles both dynamic (AI-generated) and static suggestions.\n */\nexport class SuggestionEngine {\n private _suggestionsConfig: Record<string, SuggestionsConfig> = {};\n private _suggestions: Record<string, Record<string, Suggestion[]>> = {};\n private _runningSuggestions: Record<string, AbortableSuggestionRun[]> = {};\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Initialize with suggestion configs\n */\n initialize(suggestionsConfig: SuggestionsConfig[]): void {\n for (const config of suggestionsConfig) {\n this._suggestionsConfig[randomUUID()] = config;\n }\n }\n\n /**\n * Add a suggestion configuration\n * @returns The ID of the created config\n */\n addSuggestionsConfig(config: SuggestionsConfig): string {\n const id = randomUUID();\n this._suggestionsConfig[id] = config;\n void this.notifySuggestionsConfigChanged();\n return id;\n }\n\n /**\n * Remove a suggestion configuration by ID\n */\n removeSuggestionsConfig(id: string): void {\n delete this._suggestionsConfig[id];\n void this.notifySuggestionsConfigChanged();\n }\n\n /**\n * Reload suggestions for a specific agent\n * This triggers generation of new suggestions based on current configs\n */\n public reloadSuggestions(agentId: string): void {\n this.clearSuggestions(agentId);\n\n // The agent may legitimately be missing here (e.g. runtime info still loading,\n // or the consumer agent is configured but not yet registered) — static suggestions\n // don't need it, only dynamic generation does. Treat that case as \"no messages yet\"\n // and process static configs anyway.\n const agent = (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).getAgent(agentId);\n\n const messageCount = agent?.messages?.length ?? 0;\n let hasAnySuggestions = false;\n\n for (const config of Object.values(this._suggestionsConfig)) {\n // Check if config applies to this agent\n if (\n config.consumerAgentId !== undefined &&\n config.consumerAgentId !== \"*\" &&\n config.consumerAgentId !== agentId\n ) {\n continue;\n }\n\n // Check availability based on message count\n if (!this.shouldShowSuggestions(config, messageCount)) {\n continue;\n }\n\n const suggestionId = randomUUID();\n\n if (isDynamicSuggestionsConfig(config)) {\n // Dynamic suggestions need a real agent (provider + consumer messages).\n // Skip when the agent isn't ready yet — `reloadSuggestions` will be\n // called again once it is.\n if (!agent) {\n continue;\n }\n if (!hasAnySuggestions) {\n hasAnySuggestions = true;\n void this.notifySuggestionsStartedLoading(agentId);\n }\n void this.generateSuggestions(suggestionId, config, agentId);\n } else if (isStaticSuggestionsConfig(config)) {\n this.addStaticSuggestions(suggestionId, config, agentId);\n }\n }\n }\n\n /**\n * Clear all suggestions for a specific agent\n */\n public clearSuggestions(agentId: string): void {\n const runningAgents = this._runningSuggestions[agentId];\n if (runningAgents) {\n for (const agent of runningAgents) {\n agent.abortRun();\n }\n delete this._runningSuggestions[agentId];\n }\n this._suggestions[agentId] = {};\n\n void this.notifySuggestionsChanged(agentId, []);\n }\n\n /**\n * Get current suggestions for an agent\n */\n public getSuggestions(agentId: string): CopilotKitCoreGetSuggestionsResult {\n const suggestions = Object.values(this._suggestions[agentId] ?? {}).flat();\n const isLoading = (this._runningSuggestions[agentId]?.length ?? 0) > 0;\n return { suggestions, isLoading };\n }\n\n /**\n * Generate suggestions by running a provider agent and extracting the\n * `copilotkitSuggest` tool call from its streamed messages.\n *\n * Two transports, one set of mechanics: both seed an agent with the\n * consumer's messages + state and the instruction, then `runAgent` with\n * forced `copilotkitSuggest` tool choice, parsing suggestions as messages\n * stream in via `onMessagesChanged`.\n *\n * - **Stateless** (runtime advertises `suggestions` and transport isn't\n * `single`): a stock `HttpAgent` pointed at `/agent/:id/suggest`. That\n * endpoint runs the provider directly and streams AG-UI SSE **without**\n * persisting a thread, and a plain `HttpAgent` only ever speaks REST SSE —\n * it never routes through the Intelligence websocket delegate (which would\n * persist a thread). This is the path that removes the thread flood.\n * - **Fallback** (capability absent → old runtime, or `single` transport):\n * clone the provider agent and run it client-side, as before.\n *\n * Gated to non-`single` transports because this client only builds the\n * multi-route `/agent/:id/suggest` URL; single-route deployments (not the\n * persisting-thread/Intelligence case) fall through to the clone fallback.\n */\n private async generateSuggestions(\n suggestionId: string,\n config: DynamicSuggestionsConfig,\n consumerAgentId: string,\n ): Promise<void> {\n // The cancellable handle for this generation, removed from the running set\n // in `finally`. `abortRun` flips `aborted` before cancelling the underlying\n // agent so the `catch` can distinguish a deliberate clear/reload from a real\n // failure — some engines (undici, some React Native) reject an aborted run\n // with a non-\"AbortError\" error that `isAbortError` alone would misclassify.\n let runHandle: AbortableSuggestionRun | undefined = undefined;\n let aborted = false;\n try {\n const friends = this.core as unknown as CopilotKitCoreFriendsAccess;\n const resolvedProviderAgentId = config.providerAgentId ?? \"default\";\n const suggestionsProviderAgent = friends.getAgent(\n resolvedProviderAgentId,\n );\n if (!suggestionsProviderAgent) {\n throw new Error(\n `Suggestions provider agent not found: ${resolvedProviderAgentId}`,\n );\n }\n const suggestionsConsumerAgent = friends.getAgent(consumerAgentId);\n if (!suggestionsConsumerAgent) {\n throw new Error(\n `Suggestions consumer agent not found: ${consumerAgentId}`,\n );\n }\n\n const instructionContent = [\n `Suggest what the user could say next. Provide clear, highly relevant suggestions by calling the \\`copilotkitSuggest\\` tool.`,\n `Provide at least ${config.minSuggestions ?? 1} and at most ${\n config.maxSuggestions ?? 3\n } suggestions.`,\n `The user has the following tools available: ${JSON.stringify(\n friends.buildFrontendTools(consumerAgentId),\n )}.`,\n ` ${config.instructions}`,\n ].join(\"\\n\");\n\n // Initialize suggestion storage for this agent/suggestion combo\n this._suggestions[consumerAgentId] = {\n ...this._suggestions[consumerAgentId],\n [suggestionId]: [],\n };\n\n // Deep-clone the consumer's messages + state so the suggestion run sees\n // the same context a real turn would, without sharing mutable references.\n const seededMessages: Message[] = JSON.parse(\n JSON.stringify(suggestionsConsumerAgent.messages),\n );\n const seededState: unknown = JSON.parse(\n JSON.stringify(suggestionsConsumerAgent.state ?? {}),\n );\n\n const useStateless =\n this.core.suggestions === true &&\n this.core.runtimeTransport !== \"single\";\n\n let suggestionAgent: AbstractAgent;\n if (useStateless) {\n const suggestUrl = `${this.core.runtimeUrl}/agent/${encodeURIComponent(\n resolvedProviderAgentId,\n )}/suggest`;\n const credentials = this.core.credentials;\n suggestionAgent = new HttpAgent({\n agentId: resolvedProviderAgentId,\n url: suggestUrl,\n headers: { ...this.core.headers },\n // `HttpAgentConfig` has no `credentials` field; inject it via a fetch\n // wrapper so cookie-based / self-hosted auth still rides along on the\n // `/suggest` request.\n ...(credentials\n ? {\n fetch: (url: string, requestInit: RequestInit) =>\n fetch(url, { ...requestInit, credentials }),\n }\n : {}),\n });\n } else {\n suggestionAgent = suggestionsProviderAgent.clone();\n }\n\n suggestionAgent.threadId = suggestionId;\n suggestionAgent.setMessages(seededMessages);\n suggestionAgent.setState(seededState);\n\n runHandle = {\n abortRun: () => {\n aborted = true;\n suggestionAgent.abortRun();\n },\n };\n this._runningSuggestions[consumerAgentId] = [\n ...(this._runningSuggestions[consumerAgentId] ?? []),\n runHandle,\n ];\n\n suggestionAgent.addMessage({\n id: suggestionId,\n role: \"user\",\n content: instructionContent,\n });\n\n await suggestionAgent.runAgent(\n {\n context: friends.getContextForAgent(consumerAgentId),\n forwardedProps: {\n ...friends.properties,\n toolChoice: {\n type: \"function\",\n function: { name: \"copilotkitSuggest\" },\n },\n },\n tools: [SUGGEST_TOOL],\n },\n {\n onMessagesChanged: ({ messages }) => {\n this.extractSuggestions(\n messages,\n suggestionId,\n consumerAgentId,\n true,\n );\n },\n },\n );\n } catch (error) {\n // An abort is expected when suggestions are cleared/reloaded mid-flight;\n // swallow it quietly rather than surfacing it as a failure. `isAbortError`\n // is the primary (name-based) check; `aborted` covers engines that reject\n // an aborted run with a differently-named error (or a `TypeError`).\n if (!isAbortError(error) && !aborted) {\n console.warn(\"Error generating suggestions:\", error);\n }\n } finally {\n // Finalize suggestions by marking them as no longer loading\n this.finalizeSuggestions(suggestionId, consumerAgentId);\n\n // Remove this run from the running set. `runHandle` may be undefined when\n // generation threw before it was assigned (e.g. provider/consumer agent\n // lookup failed); still perform cleanup so the loading balance holds. If\n // no runs remain for this consumer, emit finished-loading — otherwise a\n // subscriber that saw `started` would hang in the loading state.\n const runningAgents = this._runningSuggestions[consumerAgentId];\n const remaining = runHandle\n ? (runningAgents ?? []).filter((a) => a !== runHandle)\n : (runningAgents ?? []);\n\n if (remaining.length === 0) {\n delete this._runningSuggestions[consumerAgentId];\n await this.notifySuggestionsFinishedLoading(consumerAgentId);\n } else {\n this._runningSuggestions[consumerAgentId] = remaining;\n }\n }\n }\n\n /**\n * Finalize suggestions by marking them as no longer loading\n */\n private finalizeSuggestions(\n suggestionId: string,\n consumerAgentId: string,\n ): void {\n const agentSuggestions = this._suggestions[consumerAgentId];\n const currentSuggestions = agentSuggestions?.[suggestionId];\n\n if (\n agentSuggestions &&\n currentSuggestions &&\n currentSuggestions.length > 0\n ) {\n // Filter out empty suggestions and mark remaining as no longer loading\n const finalizedSuggestions = currentSuggestions\n .filter(\n (suggestion) => suggestion.title !== \"\" || suggestion.message !== \"\",\n )\n .map((suggestion) => ({\n ...suggestion,\n isLoading: false,\n }));\n\n if (finalizedSuggestions.length > 0) {\n agentSuggestions[suggestionId] = finalizedSuggestions;\n } else {\n delete agentSuggestions[suggestionId];\n }\n\n // Get all aggregated suggestions for this agent\n const allSuggestions = Object.values(\n this._suggestions[consumerAgentId] ?? {},\n ).flat();\n\n void this.notifySuggestionsChanged(\n consumerAgentId,\n allSuggestions,\n \"finalized\",\n );\n }\n }\n\n /**\n * Extract suggestions from messages (called during streaming)\n */\n extractSuggestions(\n messages: readonly Message[],\n suggestionId: string,\n consumerAgentId: string,\n isRunning: boolean,\n ): void {\n const idx = messages.findIndex((message) => message.id === suggestionId);\n if (idx == -1) {\n return;\n }\n\n const suggestions: Suggestion[] = [];\n const newMessages = messages.slice(idx + 1);\n\n for (const message of newMessages) {\n if (message.role === \"assistant\" && message.toolCalls) {\n for (const toolCall of message.toolCalls) {\n if (toolCall.function.name === \"copilotkitSuggest\") {\n // Join all argument chunks into a single string for parsing\n // arguments can be either a string or an array of strings\n const fullArgs = Array.isArray(toolCall.function.arguments)\n ? toolCall.function.arguments.join(\"\")\n : toolCall.function.arguments;\n const parsed = partialJSONParse(fullArgs);\n if (\n parsed &&\n typeof parsed === \"object\" &&\n \"suggestions\" in parsed\n ) {\n const parsedSuggestions = (parsed as any).suggestions;\n if (Array.isArray(parsedSuggestions)) {\n for (const item of parsedSuggestions) {\n if (item && typeof item === \"object\" && \"title\" in item) {\n suggestions.push({\n title: item.title ?? \"\",\n message: item.message ?? \"\",\n // Defaults to false; only the trailing item is flipped to\n // true below, and only while a streaming run is in flight.\n isLoading: false,\n });\n }\n }\n }\n }\n }\n }\n }\n }\n\n // Set isLoading for the last suggestion if still running\n if (isRunning && suggestions.length > 0) {\n suggestions[suggestions.length - 1]!.isLoading = true;\n }\n\n const agentSuggestions = this._suggestions[consumerAgentId];\n if (agentSuggestions) {\n agentSuggestions[suggestionId] = suggestions;\n\n // Get all aggregated suggestions for this agent\n const allSuggestions = Object.values(\n this._suggestions[consumerAgentId] ?? {},\n ).flat();\n\n void this.notifySuggestionsChanged(\n consumerAgentId,\n allSuggestions,\n \"suggestions changed\",\n );\n }\n }\n\n /**\n * Notify subscribers of suggestions config changes\n */\n private async notifySuggestionsConfigChanged(): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onSuggestionsConfigChanged?.({\n copilotkit: this.core,\n suggestionsConfig: this._suggestionsConfig,\n }),\n \"Subscriber onSuggestionsConfigChanged error:\",\n );\n }\n\n /**\n * Notify subscribers of suggestions changes\n */\n private async notifySuggestionsChanged(\n agentId: string,\n suggestions: Suggestion[],\n context: string = \"\",\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onSuggestionsChanged?.({\n copilotkit: this.core,\n agentId,\n suggestions,\n }),\n `Subscriber onSuggestionsChanged error: ${context}`,\n );\n }\n\n /**\n * Notify subscribers that suggestions started loading\n */\n private async notifySuggestionsStartedLoading(\n agentId: string,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onSuggestionsStartedLoading?.({\n copilotkit: this.core,\n agentId,\n }),\n \"Subscriber onSuggestionsStartedLoading error:\",\n );\n }\n\n /**\n * Notify subscribers that suggestions finished loading\n */\n private async notifySuggestionsFinishedLoading(\n agentId: string,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber) =>\n subscriber.onSuggestionsFinishedLoading?.({\n copilotkit: this.core,\n agentId,\n }),\n \"Subscriber onSuggestionsFinishedLoading error:\",\n );\n }\n\n /**\n * Check if suggestions should be shown based on availability and message count\n */\n private shouldShowSuggestions(\n config: SuggestionsConfig,\n messageCount: number,\n ): boolean {\n const availability = config.available;\n\n // Default behavior if no availability specified\n if (!availability) {\n if (isDynamicSuggestionsConfig(config)) {\n return messageCount > 0; // Default: after-first-message\n } else {\n return messageCount === 0; // Default: before-first-message\n }\n }\n\n switch (availability) {\n case \"disabled\":\n return false;\n case \"before-first-message\":\n return messageCount === 0;\n case \"after-first-message\":\n return messageCount > 0;\n case \"always\":\n return true;\n default:\n return false;\n }\n }\n\n /**\n * Add static suggestions directly without AI generation\n */\n private addStaticSuggestions(\n suggestionId: string,\n config: StaticSuggestionsConfig,\n consumerAgentId: string,\n ): void {\n // Mark all as not loading since they're static\n const suggestions = config.suggestions.map((s) => ({\n ...s,\n isLoading: false,\n }));\n\n // Store suggestions\n this._suggestions[consumerAgentId] = {\n ...this._suggestions[consumerAgentId],\n [suggestionId]: suggestions,\n };\n\n // Notify subscribers\n const allSuggestions = Object.values(\n this._suggestions[consumerAgentId] ?? {},\n ).flat();\n\n void this.notifySuggestionsChanged(\n consumerAgentId,\n allSuggestions,\n \"static suggestions added\",\n );\n }\n}\n\n/**\n * Detects an `AbortController`-driven cancellation so the stateless path can\n * treat it as an expected (non-error) outcome on clear/reload.\n */\nexport function isAbortError(error: unknown): boolean {\n // Detect purely by name: a `DOMException` is NOT `instanceof Error` in Safari\n // and older engines, so gating on `instanceof Error` would misclassify a real\n // user abort as a failure in the browser (this package runs client-side).\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"name\" in error &&\n (error as { name?: unknown }).name === \"AbortError\"\n );\n}\n\n/**\n * Type guard for dynamic suggestions config\n */\nfunction isDynamicSuggestionsConfig(\n config: SuggestionsConfig,\n): config is DynamicSuggestionsConfig {\n return \"instructions\" in config;\n}\n\n/**\n * Type guard for static suggestions config\n */\nfunction isStaticSuggestionsConfig(\n config: SuggestionsConfig,\n): config is StaticSuggestionsConfig {\n return \"suggestions\" in config;\n}\n\n/**\n * The tool definition for AI-generated suggestions\n */\nconst SUGGEST_TOOL: Tool = {\n name: \"copilotkitSuggest\",\n description: \"Suggest what the user could say next\",\n parameters: {\n type: \"object\",\n properties: {\n suggestions: {\n type: \"array\",\n description: \"List of suggestions shown to the user as buttons.\",\n items: {\n type: \"object\",\n properties: {\n title: {\n type: \"string\",\n description:\n \"The title of the suggestion. This is shown as a button and should be short.\",\n },\n message: {\n type: \"string\",\n description:\n \"The message to send when the suggestion is clicked. This should be a clear, complete sentence \" +\n \"and will be sent as an instruction to the AI.\",\n },\n },\n required: [\"title\", \"message\"],\n },\n },\n },\n required: [\"suggestions\"],\n },\n};\n","import type {\n AbstractAgent,\n AgentSubscriber,\n Message,\n RunAgentResult,\n ResumeEntry,\n Tool,\n ToolCall,\n} from \"@ag-ui/client\";\nimport { randomUUID, logger, schemaToJsonSchema } from \"@copilotkit/shared\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport type { CopilotKitCore, CopilotKitCoreFriendsAccess } from \"./core\";\nimport { CopilotKitCoreErrorCode } from \"./core\";\nimport { AgentThreadLockedError } from \"../intelligence-agent\";\nimport type { FrontendTool } from \"../types\";\n\nexport interface CopilotKitCoreRunAgentParams {\n agent: AbstractAgent;\n forwardedProps?: Record<string, unknown>;\n /**\n * Optional caller-supplied run identifier forwarded to the underlying AG-UI\n * agent. When omitted, the agent creates one.\n */\n runId?: string;\n /**\n * Per-interrupt responses addressing every open AG-UI interrupt from the\n * previous run. Forwarded to the agent as the standard `resume` array.\n */\n resume?: ResumeEntry[];\n}\n\nexport interface CopilotKitCoreConnectAgentParams {\n agent: AbstractAgent;\n}\n\nexport interface CopilotKitCoreGetToolParams {\n toolName: string;\n agentId?: string;\n}\n\n/**\n * Parameters for programmatic tool execution via `copilotkit.runTool()`.\n */\nexport interface CopilotKitCoreRunToolParams {\n /** Name of the registered frontend tool to execute. */\n name: string;\n /** Optional agent ID. If omitted, uses the default agent lookup. */\n agentId?: string;\n /** Parameters to pass to the tool handler. */\n parameters?: Record<string, unknown>;\n /**\n * Whether to trigger an LLM follow-up after tool execution.\n * - `false` (default): execute tool, add messages to history, done.\n * - `\"generate\"`: after execution, trigger another agent run so the LLM responds to the tool result.\n * - Any other string: add a user message with this text, then trigger another agent run.\n */\n followUp?: string | false;\n}\n\n/**\n * Result of programmatic tool execution via `copilotkit.runTool()`.\n */\nexport interface CopilotKitCoreRunToolResult {\n /** The unique ID of the tool call. */\n toolCallId: string;\n /** The stringified result from the tool handler. */\n result: string;\n /** Error message if the handler failed. */\n error?: string;\n}\n\n/**\n * Internal result from the shared tool handler execution logic.\n */\ninterface ExecuteToolHandlerResult {\n result: string;\n error?: string;\n isArgumentError: boolean;\n}\n\n/**\n * Absolute safety cap on the depth of recursive follow-up runs triggered by\n * `processAgentResult`. Without this, any scenario that keeps\n * `needsFollowUp = true` (e.g. the LLM repeatedly calling the same tool, a\n * backend that errors after receiving tool results, or input processors that\n * reprocess tool messages) would loop indefinitely, silently consuming API\n * quota and potentially DOS'ing the backend.\n *\n * The cap is deliberately high so that legitimate multi-step agent workflows\n * (search → fill form → confirm → update → send email, etc.) are never\n * affected; it only trips on runaway recursion.\n */\nconst MAX_FOLLOW_UP_DEPTH = 100;\n\n/**\n * Handles agent execution, tool calling, and agent connectivity for CopilotKitCore.\n * Manages the complete lifecycle of agent runs including tool execution and follow-ups.\n */\nexport class RunHandler {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private _tools: FrontendTool<any>[] = [];\n\n /**\n * Tracks whether the current run (including in-flight tool execution)\n * has been aborted via `stopAgent()` or `agent.abortRun()`. Created\n * fresh in `runAgent()`, aborted by `abortCurrentRun()`.\n */\n private _runAbortController: AbortController | null = null;\n\n /**\n * Tracks recursive `runAgent` depth so that the abort controller and\n * `agent.abortRun()` intercept are only set up / torn down at the\n * top-level call, not on follow-up recursive calls from\n * `processAgentResult`.\n */\n private _runDepth = 0;\n\n /**\n * Tracks the threadId of the most recent `connectAgent` call so we\n * can distinguish a fresh thread restore (different threadId than\n * last time — chat is rebuilding state from scratch, must clear\n * messages/state and ask the gateway for a full replay) from a\n * same-thread churn re-connect (effect-dep churn or transient\n * disconnect — local messages/state are still meaningful, must\n * preserve them and let the gateway resume from\n * `lastSeenEventId`).\n *\n * Tyler's bug fired because every `connectAgent` was treated as a\n * fresh restore, which forced the gateway to replay the full\n * thread history on every churn re-connect and amplified the\n * downstream churn into duplicate `cpki_event_id` rows in the\n * inspector and intermittent \"Message not found\" toasts.\n */\n private _lastConnectedThreadIdsByAgent = new Map<string, string | null>();\n private _anonymousAgentIds = new WeakMap<AbstractAgent, string>();\n private _nextAnonymousAgentId = 0;\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Abort the current run. Called by `CopilotKitCore.stopAgent()` to signal\n * that in-flight tool handlers should stop and `processAgentResult` should\n * not start a follow-up run.\n */\n abortCurrentRun(): void {\n this._runAbortController?.abort();\n }\n\n /**\n * Typed access to CopilotKitCore's internal (\"friend\") methods.\n * Centralises the single unavoidable cast so call-sites stay clean.\n */\n private get _internal(): CopilotKitCoreFriendsAccess {\n return this.core as unknown as CopilotKitCoreFriendsAccess;\n }\n\n /**\n * Return a stable restore-tracking key for the logical agent being\n * connected. Named agents share their last-thread marker across proxy\n * instances; anonymous agents fall back to object identity.\n */\n private getConnectRestoreKey(agent: AbstractAgent): string {\n if (agent.agentId) {\n return `agent:${agent.agentId}`;\n }\n\n const existing = this._anonymousAgentIds.get(agent);\n if (existing) {\n return existing;\n }\n\n const anonymousId = `anonymous:${this._nextAnonymousAgentId}`;\n this._nextAnonymousAgentId += 1;\n this._anonymousAgentIds.set(agent, anonymousId);\n return anonymousId;\n }\n\n /**\n * Get all tools as a readonly array\n */\n get tools(): Readonly<FrontendTool<any>[]> {\n return this._tools;\n }\n\n /**\n * Initialize with tools\n */\n initialize(tools: FrontendTool<any>[]): void {\n this._tools = tools;\n }\n\n /**\n * Add a tool to the registry\n */\n addTool<T extends Record<string, unknown> = Record<string, unknown>>(\n tool: FrontendTool<T>,\n ): void {\n // Check if a tool with the same name and agentId already exists\n const existingToolIndex = this._tools.findIndex(\n (t) => t.name === tool.name && t.agentId === tool.agentId,\n );\n\n if (existingToolIndex !== -1) {\n logger.warn(\n `Tool already exists: '${tool.name}' for agent '${tool.agentId || \"global\"}', skipping.`,\n );\n return;\n }\n\n this._tools.push(tool);\n }\n\n /**\n * Remove a tool by name and optionally by agentId\n */\n removeTool(id: string, agentId?: string): void {\n this._tools = this._tools.filter((tool) => {\n // Remove tool if both name and agentId match\n if (agentId !== undefined) {\n return !(tool.name === id && tool.agentId === agentId);\n }\n // If no agentId specified, only remove global tools with matching name\n return !(tool.name === id && !tool.agentId);\n });\n }\n\n /**\n * Get a tool by name and optionally by agentId.\n * If agentId is provided, it will first look for an agent-specific tool,\n * then fall back to a global tool with the same name.\n */\n getTool(params: CopilotKitCoreGetToolParams): FrontendTool<any> | undefined {\n const { toolName, agentId } = params;\n\n // If agentId is provided, first look for agent-specific tool\n if (agentId) {\n const agentTool = this._tools.find(\n (tool) => tool.name === toolName && tool.agentId === agentId,\n );\n if (agentTool) {\n return agentTool;\n }\n }\n\n // Fall back to global tool (no agentId)\n return this._tools.find((tool) => tool.name === toolName && !tool.agentId);\n }\n\n /**\n * Set all tools at once. Replaces existing tools.\n */\n setTools(tools: FrontendTool<any>[]): void {\n this._tools = [...tools];\n }\n\n /**\n * Connect an agent (establish initial connection)\n */\n async connectAgent({\n agent,\n }: CopilotKitCoreConnectAgentParams): Promise<RunAgentResult> {\n try {\n const incomingThreadId = agent.threadId ?? null;\n const restoreKey = this.getConnectRestoreKey(agent);\n const isFreshRestore =\n incomingThreadId !==\n (this._lastConnectedThreadIdsByAgent.get(restoreKey) ?? null);\n this._lastConnectedThreadIdsByAgent.set(restoreKey, incomingThreadId);\n\n // Detach any active run before connecting to avoid previous runs\n // interfering. This stays unconditional — both fresh restores and\n // churn re-connects need the previous socket torn down before a new\n // one can open.\n await agent.detachActiveRun();\n\n // State reset + replay-cursor clear are gated on actually moving\n // to a different thread. On same-thread churn, the local\n // messages/state are still the right view of the thread, and the\n // gateway can resume from `lastSeenEventId` instead of replaying\n // the full history.\n if (isFreshRestore) {\n agent.setMessages([]);\n agent.setState({});\n const cursorAware = agent as {\n clearReconnectCursor?: (id: string) => void;\n clearReplayCursor?: (id: string) => void;\n };\n if (incomingThreadId) {\n if (typeof cursorAware.clearReplayCursor === \"function\") {\n cursorAware.clearReplayCursor(incomingThreadId);\n }\n if (typeof cursorAware.clearReconnectCursor === \"function\") {\n cursorAware.clearReconnectCursor(incomingThreadId);\n }\n }\n }\n\n // Re-apply core headers (merged on top of the agent's own headers) so a\n // late header update is picked up without clobbering per-agent headers.\n this._internal.applyHeadersToAgent(agent);\n\n // Notify subscribers (e.g. the inspector) about the agent that is about\n // to run. Per-thread clones are not in the agent registry, so\n // onAgentsChanged never fires for them and they would otherwise be\n // invisible to subscribers.\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onAgentRunStarted?.({\n copilotkit: this.core,\n agent,\n }),\n \"Subscriber onAgentRunStarted error:\",\n );\n\n const runAgentResult = await agent.connectAgent(\n {\n forwardedProps: this._internal.properties,\n tools: this.buildFrontendTools(agent.agentId),\n context: this._internal.getContextForAgent(agent.agentId),\n },\n this.createAgentErrorSubscriber(agent),\n );\n\n return this.processAgentResult({\n runAgentResult,\n agent,\n executeFrontendTools: false,\n });\n } catch (error) {\n const connectError =\n error instanceof Error ? error : new Error(String(error));\n // Silently ignore abort errors (e.g. from navigation during active requests)\n const isAbort =\n connectError.name === \"AbortError\" ||\n connectError.message === \"Fetch is aborted\" ||\n connectError.message === \"signal is aborted without reason\" ||\n connectError.message === \"component unmounted\";\n if (!isAbort) {\n const context: Record<string, any> = {};\n if (agent.agentId) {\n context.agentId = agent.agentId;\n }\n await this._internal.emitError({\n error: connectError,\n code: CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED,\n context,\n });\n }\n return { result: undefined, newMessages: [] };\n }\n }\n\n /**\n * Run an agent\n */\n async runAgent({\n agent,\n forwardedProps,\n resume,\n runId,\n }: CopilotKitCoreRunAgentParams): Promise<RunAgentResult> {\n // Agent ID is guaranteed to be set by validateAndAssignAgentId\n if (agent.agentId) {\n void this._internal.suggestionEngine.clearSuggestions(agent.agentId);\n }\n\n // Re-apply core headers (merged on top of the agent's own headers) so a\n // late header update is picked up without clobbering per-agent headers.\n this._internal.applyHeadersToAgent(agent);\n\n // Detach any active run (e.g. a long-lived connectAgent pipeline) before\n // starting a new run. We await the detach to ensure the previous pipeline\n // has fully finalized — its activeRunCompletionPromise resolves once the\n // observable finalize block runs, which happens synchronously after the\n // takeUntil signal completes the chain. This prevents a race where the new\n // runAgent() overwrites activeRunDetach$ / activeRunCompletionPromise before\n // the old pipeline can clean up, causing dropped runs.\n //\n // Historical note: an earlier version used fire-and-forget (`void`) here\n // because awaiting caused a deadlock when connectAgent's\n // ConnectNotImplementedError cleanup was still in-flight. That deadlock\n // was resolved in @ag-ui/client ≥0.0.42 where the catchError path\n // (ConnectNotImplementedError → EMPTY) always runs the finalize block,\n // so the completion promise now resolves reliably.\n if (agent.detachActiveRun) {\n await agent.detachActiveRun();\n }\n\n // Set up abort controller and agent.abortRun() intercept only for the\n // top-level call. Recursive follow-up calls from processAgentResult\n // reuse the same controller.\n const isTopLevel = this._runDepth === 0;\n let originalAbortRun: (() => void) | undefined;\n\n if (isTopLevel) {\n this._runAbortController = new AbortController();\n\n // Intercept agent.abortRun() so that calling it directly (not via\n // stopAgent) also aborts in-flight tool execution and prevents\n // follow-up runs.\n const controller = this._runAbortController;\n originalAbortRun = agent.abortRun.bind(agent);\n agent.abortRun = () => {\n controller.abort();\n originalAbortRun!();\n };\n\n // Notify subscribers (e.g. the inspector) about the agent that is about\n // to run. Per-thread clones are not in the agent registry, so\n // onAgentsChanged never fires for them and they would otherwise be\n // invisible to subscribers. Fired once per top-level run; recursive\n // follow-up runs reuse the same instance and need no re-notification.\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onAgentRunStarted?.({\n copilotkit: this.core,\n agent,\n }),\n \"Subscriber onAgentRunStarted error:\",\n );\n }\n\n this._runDepth++;\n\n try {\n const runAgentResult = await agent.runAgent(\n {\n forwardedProps: {\n ...this._internal.properties,\n ...forwardedProps,\n },\n ...(resume !== undefined ? { resume } : {}),\n ...(runId !== undefined ? { runId } : {}),\n tools: this.buildFrontendTools(agent.agentId),\n context: this._internal.getContextForAgent(agent.agentId),\n },\n this.createAgentErrorSubscriber(agent),\n );\n return await this.processAgentResult({ runAgentResult, agent });\n } catch (error) {\n const runError =\n error instanceof Error ? error : new Error(String(error));\n const context: Record<string, any> = {};\n if (agent.agentId) {\n context.agentId = agent.agentId;\n }\n await this._internal.emitError({\n error: runError,\n code: CopilotKitCoreErrorCode.AGENT_RUN_FAILED,\n context,\n });\n return { result: undefined, newMessages: [] };\n } finally {\n this._runDepth--;\n // Restore original abortRun when the entire chain (including\n // recursive follow-ups) is complete.\n if (isTopLevel && originalAbortRun) {\n agent.abortRun = originalAbortRun;\n }\n }\n }\n\n /**\n * Process agent result and execute tools\n */\n private async processAgentResult({\n runAgentResult,\n agent,\n executeFrontendTools = true,\n }: {\n runAgentResult: RunAgentResult;\n agent: AbstractAgent;\n executeFrontendTools?: boolean;\n }): Promise<RunAgentResult> {\n const { newMessages } = runAgentResult;\n // Agent ID is guaranteed to be set by validateAndAssignAgentId\n const agentId = agent.agentId!;\n\n let needsFollowUp = false;\n\n if (executeFrontendTools) {\n for (const message of newMessages) {\n if (message.role === \"assistant\") {\n for (const toolCall of message.toolCalls || []) {\n const tool = this.getTool({\n toolName: toolCall.function.name,\n agentId: agent.agentId,\n });\n\n let wildcardTool: FrontendTool<any> | undefined;\n const getWildcardTool = () => {\n if (tool || wildcardTool) {\n return wildcardTool;\n }\n wildcardTool = this.getTool({\n toolName: \"*\",\n agentId: agent.agentId,\n });\n return wildcardTool;\n };\n\n let existingResultIndex = newMessages.findIndex(\n (m) => m.role === \"tool\" && m.toolCallId === toolCall.id,\n );\n const existingResult =\n existingResultIndex === -1\n ? undefined\n : newMessages[existingResultIndex];\n const executableTool = tool ?? getWildcardTool();\n\n if (\n existingResult &&\n executableTool?.handler &&\n this.isFrontendPlaceholderResult(existingResult)\n ) {\n newMessages.splice(existingResultIndex, 1);\n existingResultIndex = -1;\n\n const agentMsgIdx = agent.messages.findIndex(\n (m) => m.role === \"tool\" && m.toolCallId === toolCall.id,\n );\n if (agentMsgIdx !== -1) {\n agent.messages.splice(agentMsgIdx, 1);\n }\n }\n\n if (existingResultIndex === -1) {\n if (tool) {\n const followUp = await this.executeSpecificTool(\n tool,\n toolCall,\n message,\n agent,\n agentId,\n );\n if (followUp) {\n needsFollowUp = true;\n }\n } else {\n const fallbackTool = getWildcardTool();\n if (fallbackTool) {\n const followUp = await this.executeWildcardTool(\n fallbackTool,\n toolCall,\n message,\n agent,\n agentId,\n );\n if (followUp) {\n needsFollowUp = true;\n }\n }\n }\n }\n }\n }\n }\n }\n\n if (needsFollowUp && !this._runAbortController?.signal.aborted) {\n // Circuit breaker: bail out instead of recursing once the follow-up\n // chain exceeds an absolute safety cap. `_runDepth` reflects the current\n // depth of nested runAgent calls (it is incremented in runAgent and\n // decremented in its finally block), so a runaway loop — repeated\n // identical tool calls, a backend that keeps erroring after tool\n // results, reprocessed tool messages, etc. — eventually trips this\n // guard rather than looping forever and exhausting API quota.\n if (this._runDepth >= MAX_FOLLOW_UP_DEPTH) {\n logger.warn(\n `[CopilotKit] Follow-up depth limit (${MAX_FOLLOW_UP_DEPTH}) reached for agent \"${agentId}\". ` +\n `Stopping recursive follow-up runs to prevent an infinite loop. ` +\n `This usually indicates a tool that keeps requesting a follow-up (e.g. the LLM repeatedly ` +\n `calling the same tool). Consider setting \"followUp: false\" on the offending tool.`,\n );\n } else {\n // Yield to the framework scheduler before the follow-up run so that any\n // deferred state updates (e.g. React useEffect in useAgentContext) can\n // complete and write fresh values into the context store before runAgent\n // reads it. The base implementation is a no-op; React overrides this.\n await this._internal.waitForPendingFrameworkUpdates();\n return await this.runAgent({ agent });\n }\n }\n\n void this._internal.suggestionEngine.reloadSuggestions(agentId);\n\n return runAgentResult;\n }\n\n private isFrontendPlaceholderResult(message: Message): boolean {\n if (message.role !== \"tool\") {\n return false;\n }\n\n const normalized = this.normalizeToolResultContent(message.content);\n return normalized === \"Forwarded to client\";\n }\n\n private normalizeToolResultContent(content: unknown): string | null {\n if (typeof content === \"string\") {\n return content.trim();\n }\n\n if (Array.isArray(content)) {\n const text = content\n .flatMap((part) => {\n if (typeof part === \"string\") {\n return [part];\n }\n if (\n part &&\n typeof part === \"object\" &&\n \"text\" in part &&\n typeof (part as { text?: unknown }).text === \"string\"\n ) {\n return [(part as { text: string }).text];\n }\n return [];\n })\n .join(\"\")\n .trim();\n return text.length > 0 ? text : null;\n }\n\n if (\n content &&\n typeof content === \"object\" &&\n \"text\" in content &&\n typeof (content as { text?: unknown }).text === \"string\"\n ) {\n return (content as { text: string }).text.trim();\n }\n\n return null;\n }\n\n /**\n * Shared handler execution logic used by executeSpecificTool, executeWildcardTool, and runTool.\n * Handles arg parsing, subscriber notifications, handler invocation, result stringification,\n * and error handling.\n */\n private async executeToolHandler({\n tool,\n toolCall,\n agent,\n agentId,\n handlerArgs,\n toolType,\n messageId,\n }: {\n tool: FrontendTool<any>;\n toolCall: { id: string; function: { name: string; arguments: string } };\n agent: AbstractAgent;\n agentId: string;\n handlerArgs: unknown;\n toolType: string;\n messageId?: string;\n }): Promise<ExecuteToolHandlerResult> {\n let toolCallResult = \"\";\n let errorMessage: string | undefined;\n let isArgumentError = false;\n\n let parsedArgs: unknown;\n try {\n parsedArgs = parseToolArguments(handlerArgs, toolCall.function.name);\n } catch (error) {\n const parseError =\n error instanceof Error ? error : new Error(String(error));\n errorMessage = parseError.message;\n isArgumentError = true;\n await this._internal.emitError({\n error: parseError,\n code: CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED,\n context: {\n agentId,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n rawArguments: handlerArgs,\n toolType,\n ...(messageId ? { messageId } : {}),\n },\n });\n }\n\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onToolExecutionStart?.({\n copilotkit: this.core,\n toolCallId: toolCall.id,\n agentId,\n toolName: toolCall.function.name,\n args: parsedArgs,\n }),\n \"Subscriber onToolExecutionStart error:\",\n );\n\n if (!errorMessage) {\n try {\n const result = await tool.handler!(parsedArgs as any, {\n toolCall: toolCall as any,\n agent,\n signal: this._runAbortController?.signal,\n });\n if (result === undefined || result === null) {\n toolCallResult = \"\";\n } else if (typeof result === \"string\") {\n toolCallResult = result;\n } else {\n toolCallResult = JSON.stringify(result);\n }\n } catch (error) {\n const handlerError =\n error instanceof Error ? error : new Error(String(error));\n errorMessage = handlerError.message;\n await this._internal.emitError({\n error: handlerError,\n code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,\n context: {\n agentId,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n parsedArgs,\n toolType,\n ...(messageId ? { messageId } : {}),\n },\n });\n }\n }\n\n if (errorMessage) {\n toolCallResult = `Error: ${errorMessage}`;\n }\n\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onToolExecutionEnd?.({\n copilotkit: this.core,\n toolCallId: toolCall.id,\n agentId,\n toolName: toolCall.function.name,\n result: errorMessage ? \"\" : toolCallResult,\n error: errorMessage,\n }),\n \"Subscriber onToolExecutionEnd error:\",\n );\n\n return { result: toolCallResult, error: errorMessage, isArgumentError };\n }\n\n /**\n * Execute a specific tool\n */\n private async executeSpecificTool(\n tool: FrontendTool<any>,\n toolCall: ToolCall,\n message: Message,\n agent: AbstractAgent,\n agentId: string,\n ): Promise<boolean> {\n // Check if tool is constrained to a specific agent\n if (tool?.agentId && tool.agentId !== agent.agentId) {\n // Tool is not available for this agent, skip it\n return false;\n }\n\n let handlerResult: ExecuteToolHandlerResult = {\n result: \"\",\n error: undefined,\n isArgumentError: false,\n };\n\n if (tool?.handler) {\n handlerResult = await this.executeToolHandler({\n tool,\n toolCall,\n agent,\n agentId,\n handlerArgs: toolCall.function.arguments,\n toolType: \"specific\",\n messageId: message.id,\n });\n }\n\n {\n const messageIndex = agent.messages.findIndex((m) => m.id === message.id);\n if (messageIndex === -1) {\n // Parent message no longer in agent's messages (e.g. thread was switched\n // while the tool handler was still executing). Skip result insertion and\n // do not request a follow-up to avoid mutating the wrong thread.\n return false;\n }\n // Find the correct insertion point: after the parent assistant message\n // and any tool-result messages already inserted for earlier tool calls\n // in the same batch. This preserves tool-result ordering relative to\n // the toolCalls array, which some providers (OpenAI) require.\n let insertAt = messageIndex + 1;\n while (\n insertAt < agent.messages.length &&\n agent.messages[insertAt]?.role === \"tool\"\n ) {\n insertAt++;\n }\n const toolMessage = {\n id: randomUUID(),\n role: \"tool\" as const,\n toolCallId: toolCall.id,\n content: handlerResult.result,\n };\n agent.messages.splice(insertAt, 0, toolMessage);\n\n if (!handlerResult.error && tool?.followUp !== false) {\n return true; // Needs follow-up\n }\n }\n\n return false;\n }\n\n /**\n * Execute a wildcard tool.\n * Wildcard tools receive args wrapped as `{toolName, args}`, which differs from\n * specific tools, so this method keeps its own arg-wrapping logic rather than\n * delegating to `executeToolHandler`.\n */\n private async executeWildcardTool(\n wildcardTool: FrontendTool<any>,\n toolCall: ToolCall,\n message: Message,\n agent: AbstractAgent,\n agentId: string,\n ): Promise<boolean> {\n // Check if wildcard tool is constrained to a specific agent\n if (wildcardTool?.agentId && wildcardTool.agentId !== agent.agentId) {\n // Wildcard tool is not available for this agent, skip it\n return false;\n }\n\n let toolCallResult = \"\";\n let errorMessage: string | undefined;\n\n if (wildcardTool?.handler) {\n let parsedArgs: unknown;\n try {\n parsedArgs = parseToolArguments(\n toolCall.function.arguments,\n toolCall.function.name,\n );\n } catch (error) {\n const parseError =\n error instanceof Error ? error : new Error(String(error));\n errorMessage = parseError.message;\n await this._internal.emitError({\n error: parseError,\n code: CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED,\n context: {\n agentId: agentId,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n rawArguments: toolCall.function.arguments,\n toolType: \"wildcard\",\n messageId: message.id,\n },\n });\n }\n\n const wildcardArgs = {\n toolName: toolCall.function.name,\n args: parsedArgs,\n };\n\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onToolExecutionStart?.({\n copilotkit: this.core,\n toolCallId: toolCall.id,\n agentId: agentId,\n toolName: toolCall.function.name,\n args: wildcardArgs,\n }),\n \"Subscriber onToolExecutionStart error:\",\n );\n\n if (!errorMessage) {\n try {\n const result = await wildcardTool.handler(wildcardArgs as any, {\n toolCall,\n agent,\n });\n if (result === undefined || result === null) {\n toolCallResult = \"\";\n } else if (typeof result === \"string\") {\n toolCallResult = result;\n } else {\n toolCallResult = JSON.stringify(result);\n }\n } catch (error) {\n const handlerError =\n error instanceof Error ? error : new Error(String(error));\n errorMessage = handlerError.message;\n await this._internal.emitError({\n error: handlerError,\n code: CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED,\n context: {\n agentId: agentId,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n parsedArgs: wildcardArgs,\n toolType: \"wildcard\",\n messageId: message.id,\n },\n });\n }\n }\n\n if (errorMessage) {\n toolCallResult = `Error: ${errorMessage}`;\n }\n\n await this._internal.notifySubscribers(\n (subscriber) =>\n subscriber.onToolExecutionEnd?.({\n copilotkit: this.core,\n toolCallId: toolCall.id,\n agentId: agentId,\n toolName: toolCall.function.name,\n result: errorMessage ? \"\" : toolCallResult,\n error: errorMessage,\n }),\n \"Subscriber onToolExecutionEnd error:\",\n );\n }\n\n {\n const messageIndex = agent.messages.findIndex((m) => m.id === message.id);\n if (messageIndex === -1) {\n // Parent message no longer in agent's messages (e.g. thread was switched\n // while the tool handler was still executing). Skip result insertion and\n // do not request a follow-up to avoid mutating the wrong thread.\n return false;\n }\n // Find the correct insertion point: after the parent assistant message\n // and any tool-result messages already inserted for earlier tool calls\n // in the same batch. This preserves tool-result ordering relative to\n // the toolCalls array, which some providers (OpenAI) require.\n let insertAt = messageIndex + 1;\n while (\n insertAt < agent.messages.length &&\n agent.messages[insertAt]?.role === \"tool\"\n ) {\n insertAt++;\n }\n const toolMessage = {\n id: randomUUID(),\n role: \"tool\" as const,\n toolCallId: toolCall.id,\n content: toolCallResult,\n };\n agent.messages.splice(insertAt, 0, toolMessage);\n\n if (!errorMessage && wildcardTool?.followUp !== false) {\n return true; // Needs follow-up\n }\n }\n\n return false;\n }\n\n /**\n * Programmatically execute a registered frontend tool without going through an LLM turn.\n * The handler runs, render components show up in the UI, and both the tool call and\n * result messages are added to `agent.messages`.\n */\n async runTool(\n params: CopilotKitCoreRunToolParams,\n ): Promise<CopilotKitCoreRunToolResult> {\n const { name, agentId, parameters = {}, followUp = false } = params;\n\n // 1. Look up the tool\n const tool = this.getTool({ toolName: name, agentId });\n if (!tool) {\n const error = new Error(`Tool not found: ${name}`);\n await this._internal.emitError({\n error,\n code: CopilotKitCoreErrorCode.TOOL_NOT_FOUND,\n context: { toolName: name, agentId },\n });\n throw error;\n }\n\n // 2. Look up the agent\n const resolvedAgentId = agentId ?? \"default\";\n const agent = this._internal.getAgent(resolvedAgentId);\n if (!agent) {\n const error = new Error(`Agent not found: ${resolvedAgentId}`);\n await this._internal.emitError({\n error,\n code: CopilotKitCoreErrorCode.AGENT_NOT_FOUND,\n context: { agentId: resolvedAgentId },\n });\n throw error;\n }\n\n // 3. Create assistant message with tool call\n const toolCallId = randomUUID();\n const assistantToolCall = {\n id: toolCallId,\n type: \"function\" as const,\n function: {\n name,\n arguments: JSON.stringify(parameters),\n },\n };\n const assistantMessage: Message = {\n id: randomUUID(),\n role: \"assistant\",\n content: \"\",\n toolCalls: [assistantToolCall],\n };\n\n // 4. Push assistant message into agent's messages\n agent.messages.push(assistantMessage);\n\n // 5. Execute the tool handler (if it has one)\n let handlerResult: ExecuteToolHandlerResult = {\n result: \"\",\n error: undefined,\n isArgumentError: false,\n };\n\n if (tool.handler) {\n handlerResult = await this.executeToolHandler({\n tool,\n toolCall: assistantToolCall,\n agent,\n agentId: resolvedAgentId,\n handlerArgs: parameters,\n toolType: \"runTool\",\n });\n }\n\n // 6. Create and insert tool result message\n const toolResultMessage: Message = {\n id: randomUUID(),\n role: \"tool\",\n toolCallId,\n content: handlerResult.result,\n };\n\n const assistantIndex = agent.messages.findIndex(\n (m) => m.id === assistantMessage.id,\n );\n if (assistantIndex !== -1) {\n agent.messages.splice(assistantIndex + 1, 0, toolResultMessage);\n } else {\n // Fallback: push to end if assistant message was removed\n agent.messages.push(toolResultMessage);\n }\n\n // 7. Handle followUp (only if no error)\n if (!handlerResult.error && followUp !== false) {\n if (typeof followUp === \"string\" && followUp !== \"generate\") {\n // Custom text: add a user message first\n const userMessage: Message = {\n id: randomUUID(),\n role: \"user\",\n content: followUp,\n };\n agent.messages.push(userMessage);\n }\n // Yield to the framework scheduler so deferred state updates (e.g. React\n // useEffect in useAgentContext) can complete before the follow-up run reads\n // the context store. Mirrors the same yield in processAgentResult.\n await this._internal.waitForPendingFrameworkUpdates();\n // Trigger agent run for both \"generate\" and custom text\n await this.runAgent({ agent });\n }\n\n // 8. Return result\n return {\n toolCallId,\n result: handlerResult.result,\n error: handlerResult.error,\n };\n }\n\n /**\n * Build frontend tools for an agent\n */\n buildFrontendTools(agentId?: string): Tool[] {\n return this._tools\n .filter(\n (tool) =>\n tool.available !== false &&\n (tool.available as boolean | string | undefined) !== \"disabled\" &&\n (!tool.agentId || tool.agentId === agentId),\n )\n .map((tool) => ({\n name: tool.name,\n description: tool.description ?? \"\",\n parameters: createToolSchema(tool),\n }));\n }\n\n /**\n * Create an agent error subscriber\n */\n private createAgentErrorSubscriber(agent: AbstractAgent): AgentSubscriber {\n const emitAgentError = async (\n error: Error,\n code: CopilotKitCoreErrorCode,\n extraContext: Record<string, any> = {},\n ) => {\n const context: Record<string, any> = { ...extraContext };\n if (agent.agentId) {\n context.agentId = agent.agentId;\n }\n await this._internal.emitError({\n error,\n code,\n context,\n });\n };\n\n return {\n onRunFailed: async ({ error }: { error: Error }) => {\n const code =\n error instanceof AgentThreadLockedError\n ? CopilotKitCoreErrorCode.AGENT_THREAD_LOCKED\n : CopilotKitCoreErrorCode.AGENT_RUN_FAILED_EVENT;\n await emitAgentError(error, code, {\n source: \"onRunFailed\",\n });\n },\n onRunErrorEvent: async ({ event }) => {\n // A user-initiated stop (stopAgent / agent.abortRun) makes the agent\n // emit a terminal RUN_ERROR — often code \"abort\" — as its cancellation\n // signal. That is expected, not a failure: surfacing it would pop an\n // error banner on Stop (#5966, follow-up to #5812). Mirror the\n // local-abort suppression on the runAgent/connectAgent paths and skip\n // it. Prefer the abort controller (the client's own record that it\n // initiated the stop) over the agent-supplied `code`, which is not\n // standardized across agents.\n const runWasAborted = this._runAbortController?.signal.aborted === true;\n if (runWasAborted || event?.code === \"abort\") {\n return;\n }\n\n const eventError =\n event?.rawEvent instanceof Error\n ? event.rawEvent\n : event?.rawEvent?.error instanceof Error\n ? event.rawEvent.error\n : undefined;\n\n const errorMessage =\n typeof event?.rawEvent?.error === \"string\"\n ? event.rawEvent.error\n : (event?.message ?? \"Agent run error\");\n\n const rawError = eventError ?? new Error(errorMessage);\n\n if (event?.code && !(rawError as any).code) {\n (rawError as any).code = event.code;\n }\n\n await emitAgentError(\n rawError,\n CopilotKitCoreErrorCode.AGENT_RUN_ERROR_EVENT,\n {\n source: \"onRunErrorEvent\",\n event,\n runtimeErrorCode: event?.code,\n },\n );\n },\n };\n }\n}\n\n/**\n * Empty tool schema constant\n */\nconst EMPTY_TOOL_SCHEMA = {\n type: \"object\",\n properties: {},\n} as const satisfies Record<string, unknown>;\n\n/**\n * Create a JSON schema from a tool's parameters\n */\nfunction createToolSchema(tool: FrontendTool<any>): Record<string, unknown> {\n if (!tool.parameters) {\n return { ...EMPTY_TOOL_SCHEMA };\n }\n\n const rawSchema = schemaToJsonSchema(tool.parameters, {\n zodToJsonSchema: (schema, options) =>\n zodToJsonSchema(\n schema as Parameters<typeof zodToJsonSchema>[0],\n options as Parameters<typeof zodToJsonSchema>[1],\n ),\n });\n\n if (!rawSchema || typeof rawSchema !== \"object\") {\n return { ...EMPTY_TOOL_SCHEMA };\n }\n\n const { $schema: _$schema, ...schema } = rawSchema as Record<string, unknown>;\n\n if (typeof schema.type !== \"string\") {\n schema.type = \"object\";\n }\n if (typeof schema.properties !== \"object\" || schema.properties === null) {\n schema.properties = {};\n }\n\n stripAdditionalProperties(schema);\n return schema;\n}\n\nfunction stripAdditionalProperties(schema: unknown): void {\n if (!schema || typeof schema !== \"object\") {\n return;\n }\n\n if (Array.isArray(schema)) {\n schema.forEach(stripAdditionalProperties);\n return;\n }\n\n const record = schema as Record<string, unknown>;\n\n if (record.additionalProperties !== undefined) {\n delete record.additionalProperties;\n }\n\n for (const value of Object.values(record)) {\n stripAdditionalProperties(value);\n }\n}\n\n/**\n * Ensures parsed tool arguments are a plain object.\n * Throws for non-object values so the caller's catch block can emit\n * a structured TOOL_ARGUMENT_PARSE_FAILED error.\n *\n * @internal Exported for testing only.\n */\nexport function ensureObjectArgs(\n parsed: unknown,\n toolName: string,\n): Record<string, unknown> {\n if (typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n throw new Error(\n `Tool arguments for ${toolName} parsed to non-object (${typeof parsed})`,\n );\n}\n\n/**\n * Parses raw tool call arguments into a validated object.\n *\n * Some LLM providers (e.g. @ai-sdk/openai-compatible) may send empty string \"\",\n * null, or undefined instead of \"{}\". This function normalises those cases to an\n * empty object so callers don't crash on JSON.parse(\"\").\n *\n * A debug-level warning is emitted when the fallback triggers so silent coercion\n * is observable in logs.\n *\n * @internal Exported for testing only.\n */\nexport function parseToolArguments(\n rawArgs: unknown,\n toolName: string,\n): Record<string, unknown> {\n if (rawArgs === \"\" || rawArgs === null || rawArgs === undefined) {\n logger.debug(\n `[parseToolArguments] Tool \"${toolName}\" received empty/null/undefined arguments — defaulting to {}`,\n );\n return {};\n }\n const parsed = typeof rawArgs === \"string\" ? JSON.parse(rawArgs) : rawArgs;\n return ensureObjectArgs(parsed, toolName);\n}\n","import type {\n AbstractAgent,\n Message,\n State,\n RunAgentInput,\n StateSnapshotEvent,\n StateDeltaEvent,\n MessagesSnapshotEvent,\n} from \"@ag-ui/client\";\nimport { randomUUID } from \"@ag-ui/client\";\nimport type { CopilotKitCore } from \"./core\";\n\n/**\n * Manages state and message tracking by run for CopilotKitCore.\n * Tracks agent state snapshots and message-to-run associations.\n */\nexport class StateManager {\n // State tracking: agentId -> threadId -> runId -> state\n private stateByRun: Map<string, Map<string, Map<string, State>>> = new Map();\n\n // Message tracking: agentId -> threadId -> messageId -> runId\n private messageToRun: Map<string, Map<string, Map<string, string>>> =\n new Map();\n\n // Active run tracking: `agentId:threadId` -> runId (used when messages arrive without input)\n private activeRun: Map<string, string> = new Map();\n\n // Agent subscriptions for cleanup\n private agentSubscriptions: Map<string, () => void> = new Map();\n\n constructor(private core: CopilotKitCore) {}\n\n /**\n * Initialize state tracking for an agent\n */\n initialize(): void {\n // Will be called when CopilotKitCore is initialized\n }\n\n /**\n * Subscribe to an agent's events to track state and messages.\n */\n subscribeToAgent(agent: AbstractAgent): void {\n if (!agent.agentId) {\n return; // Skip agents without IDs\n }\n\n const agentId = agent.agentId;\n\n // Unsubscribe existing subscription for this agent only\n const existingUnsubscribe = this.agentSubscriptions.get(agentId);\n if (existingUnsubscribe) {\n existingUnsubscribe();\n this.agentSubscriptions.delete(agentId);\n }\n\n // Subscribe to agent events.\n //\n // Two invariants this subscription must uphold:\n //\n // 1. Revocation: the ag-ui pipeline captures `o = [...agent.subscribers]` at\n // runAgent() start. If this subscription is replaced by a newer one before\n // the pipeline finishes, the old pipeline may still call these callbacks\n // with the old input.runId. `revoked = true` turns them into no-ops once\n // the replacement subscription is in place.\n //\n // 2. Run isolation within one subscription: in tests (and edge cases), a new\n // run's events can arrive through the same subscription before the new\n // pipeline is set up. Concretely: the test emits RUN_STARTED for run2\n // before copilotkit.runAgent() has had a chance to set up the new\n // pipeline. At that point S1 is still active and sees run2's events with\n // input1.runId. To prevent both runs from sharing the same runId key, we\n // detect the \"seen RUN_FINISHED, then RUN_STARTED again\" pattern and\n // generate a fresh runId for the second logical run.\n let revoked = false;\n let subRunId: string | undefined; // runId assigned to the current logical run\n let runFinished = false; // true after RUN_FINISHED, reset on next RUN_STARTED\n\n const effectiveInput = (input: RunAgentInput): RunAgentInput => ({\n ...input,\n runId: subRunId ?? input.runId,\n });\n\n const { unsubscribe } = agent.subscribe({\n onRunStartedEvent: ({ input, state }) => {\n if (revoked) return;\n if (runFinished && input.runId === subRunId) {\n // A new logical run's events are arriving through this same (old)\n // subscription. This happens when the test emits events before\n // copilotkit.runAgent() has had a chance to set up the new pipeline:\n // the old pipeline reuses input1.runId for all events, so\n // input.runId equals the previous run's runId. Generate a fresh\n // runId so the new run's state doesn't collide with the old one.\n subRunId = randomUUID();\n } else {\n subRunId = input.runId;\n }\n runFinished = false;\n this.handleRunStarted(agent, effectiveInput(input), state);\n },\n onRunFinishedEvent: ({ input, state }) => {\n if (revoked) return;\n runFinished = true;\n this.handleRunFinished(agent, effectiveInput(input), state);\n },\n // A run error terminates the run — treat identically to finished for cleanup\n onRunErrorEvent: ({ input, state }) => {\n if (revoked) return;\n runFinished = true;\n this.handleRunFinished(agent, effectiveInput(input), state);\n },\n onStateSnapshotEvent: ({ event, input, state }) => {\n if (revoked) return;\n this.handleStateSnapshot(agent, event, effectiveInput(input), state);\n },\n onStateDeltaEvent: ({ event, input, state }) => {\n if (revoked) return;\n this.handleStateDelta(agent, event, effectiveInput(input), state);\n },\n onMessagesSnapshotEvent: ({ event, input, messages }) => {\n if (revoked) return;\n this.handleMessagesSnapshot(\n agent,\n event,\n effectiveInput(input),\n messages,\n );\n },\n onNewMessage: ({ message, input }) => {\n if (revoked) return;\n this.handleNewMessage(\n agent,\n message,\n input ? effectiveInput(input) : undefined,\n );\n },\n });\n\n this.agentSubscriptions.set(agentId, () => {\n revoked = true;\n unsubscribe();\n });\n }\n\n /**\n * Unsubscribe an agent's subscription.\n */\n unsubscribeFromAgent(agentId: string): void {\n const unsubscribe = this.agentSubscriptions.get(agentId);\n if (unsubscribe) {\n unsubscribe();\n this.agentSubscriptions.delete(agentId);\n }\n }\n\n /**\n * Get state for a specific run\n * Returns a deep copy to prevent external mutations\n */\n getStateByRun(\n agentId: string,\n threadId: string,\n runId: string,\n ): State | undefined {\n const state = this.stateByRun.get(agentId)?.get(threadId)?.get(runId);\n if (!state) return undefined;\n // Return a deep copy to prevent mutations\n return JSON.parse(JSON.stringify(state));\n }\n\n /**\n * Get runId associated with a message\n */\n getRunIdForMessage(\n agentId: string,\n threadId: string,\n messageId: string,\n ): string | undefined {\n return this.messageToRun.get(agentId)?.get(threadId)?.get(messageId);\n }\n\n /**\n * Get all states for an agent's thread\n */\n getStatesForThread(agentId: string, threadId: string): Map<string, State> {\n return this.stateByRun.get(agentId)?.get(threadId) ?? new Map();\n }\n\n /**\n * Get all run IDs for an agent's thread\n */\n getRunIdsForThread(agentId: string, threadId: string): string[] {\n const threadStates = this.stateByRun.get(agentId)?.get(threadId);\n return threadStates ? Array.from(threadStates.keys()) : [];\n }\n\n /**\n * Handle run started event\n */\n private handleRunStarted(\n agent: AbstractAgent,\n input: RunAgentInput,\n state: State,\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n this.activeRun.set(`${agent.agentId}:${threadId}`, runId);\n // Only persist state when it carries real data. An empty {} from an\n // initial-state-less run would cause getStateByRun to return {} instead\n // of undefined, breaking renderers that rely on undefined to mean \"no\n // state snapshot received yet\".\n if (state && Object.keys(state).length > 0) {\n this.saveState(agent.agentId, threadId, runId, state);\n }\n }\n\n /**\n * Handle run finished event\n */\n private handleRunFinished(\n agent: AbstractAgent,\n input: RunAgentInput,\n state: State,\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n this.activeRun.delete(`${agent.agentId}:${threadId}`);\n if (state && Object.keys(state).length > 0) {\n this.saveState(agent.agentId, threadId, runId, state);\n }\n }\n\n /**\n * Handle state snapshot event\n */\n private handleStateSnapshot(\n agent: AbstractAgent,\n event: StateSnapshotEvent,\n input: RunAgentInput,\n state: State,\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n // Merge snapshot into current state\n const mergedState = { ...state, ...event.snapshot };\n this.saveState(agent.agentId, threadId, runId, mergedState);\n }\n\n /**\n * Handle state delta event\n */\n private handleStateDelta(\n agent: AbstractAgent,\n event: StateDeltaEvent,\n input: RunAgentInput,\n state: State,\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n // State is already updated by the agent, just save it\n this.saveState(agent.agentId, threadId, runId, state);\n }\n\n /**\n * Handle messages snapshot event\n */\n private handleMessagesSnapshot(\n agent: AbstractAgent,\n event: MessagesSnapshotEvent,\n input: RunAgentInput,\n messages: readonly Message[],\n ): void {\n if (!agent.agentId) return;\n\n const { threadId, runId } = input;\n\n // Associate all messages in the snapshot with this run\n for (const message of event.messages) {\n this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);\n }\n }\n\n /**\n * Handle new message event\n */\n private handleNewMessage(\n agent: AbstractAgent,\n message: Message,\n input?: RunAgentInput,\n ): void {\n if (!agent.agentId) return;\n\n if (!input) {\n // ag-ui calls addMessage() without input, so input is undefined here.\n // Fall back to the currently-active run for this agent's thread.\n const threadId = agent.threadId ?? \"\";\n const runId = this.activeRun.get(`${agent.agentId}:${threadId}`);\n if (runId) {\n this.associateMessageWithRun(\n agent.agentId,\n threadId,\n message.id,\n runId,\n );\n }\n return;\n }\n\n const { threadId, runId } = input;\n this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);\n }\n\n /**\n * Save state for a specific run\n */\n private saveState(\n agentId: string,\n threadId: string,\n runId: string,\n state: State,\n ): void {\n // Ensure nested maps exist\n if (!this.stateByRun.has(agentId)) {\n this.stateByRun.set(agentId, new Map());\n }\n const agentStates = this.stateByRun.get(agentId)!;\n\n if (!agentStates.has(threadId)) {\n agentStates.set(threadId, new Map());\n }\n const threadStates = agentStates.get(threadId)!;\n\n // Deep copy the state to prevent mutations\n threadStates.set(runId, JSON.parse(JSON.stringify(state)));\n }\n\n /**\n * Associate a message with a run\n */\n private associateMessageWithRun(\n agentId: string,\n threadId: string,\n messageId: string,\n runId: string,\n ): void {\n // Ensure nested maps exist\n if (!this.messageToRun.has(agentId)) {\n this.messageToRun.set(agentId, new Map());\n }\n const agentMessages = this.messageToRun.get(agentId)!;\n\n if (!agentMessages.has(threadId)) {\n agentMessages.set(threadId, new Map());\n }\n const threadMessages = agentMessages.get(threadId)!;\n\n threadMessages.set(messageId, runId);\n }\n\n /**\n * Clear all state for an agent\n */\n clearAgentState(agentId: string): void {\n this.stateByRun.delete(agentId);\n this.messageToRun.delete(agentId);\n }\n\n /**\n * Clear all state for a thread\n */\n clearThreadState(agentId: string, threadId: string): void {\n this.stateByRun.get(agentId)?.delete(threadId);\n this.messageToRun.get(agentId)?.delete(threadId);\n }\n}\n","import { type ɵThreadStore } from \"../threads\";\nimport type { CopilotKitCore } from \"./core\";\nimport { CopilotKitCoreFriendsAccess, CopilotKitCoreSubscriber } from \"./core\";\n\nexport class ThreadStoreRegistry {\n private _stores: Record<string, ɵThreadStore> = {};\n // Cached frozen snapshot of `_stores`. Invalidated to `null` on every\n // `register`/`unregister` so the next `getAll()` rebuilds it. Stable\n // references between mutations matter for `useSyncExternalStore` consumers\n // that compare snapshot identity to decide whether to re-render.\n private _snapshot: Readonly<Record<string, ɵThreadStore>> | null = null;\n\n constructor(private core: CopilotKitCore) {}\n\n register(agentId: string, store: ɵThreadStore): void {\n if (agentId in this._stores) {\n // Capture the previous store before deleting it. `notifyUnregistered`\n // dispatches via `Promise.all` and returns control to this synchronous\n // body before async subscribers resume — by then `this._stores[agentId]`\n // already holds the new store, so the previous store must be forwarded\n // explicitly via the payload. Subscribers MUST NOT call\n // `registry.get(agentId)` from `onThreadStoreUnregistered` to recover\n // the previous store; use the `prevStore` field on the payload instead.\n const prevStore = this._stores[agentId]!;\n delete this._stores[agentId];\n this._snapshot = null;\n this.notifyUnregistered(agentId, prevStore).catch((err) => {\n console.error(\"ThreadStoreRegistry notifyUnregistered failed:\", err);\n });\n }\n this._stores[agentId] = store;\n this._snapshot = null;\n this.notifyRegistered(agentId, store).catch((err) => {\n console.error(\"ThreadStoreRegistry notifyRegistered failed:\", err);\n });\n }\n\n unregister(agentId: string): void {\n if (!(agentId in this._stores)) return;\n // Capture before delete for the same reason as `register()` above.\n const prevStore = this._stores[agentId]!;\n delete this._stores[agentId];\n this._snapshot = null;\n this.notifyUnregistered(agentId, prevStore).catch((err) => {\n console.error(\"ThreadStoreRegistry notifyUnregistered failed:\", err);\n });\n }\n\n get(agentId: string): ɵThreadStore | undefined {\n return this._stores[agentId];\n }\n\n getAll(): Readonly<Record<string, ɵThreadStore>> {\n // Cache a frozen snapshot so consecutive calls return the same reference.\n // `useSyncExternalStore` and other identity-comparing consumers depend on\n // this stability to skip re-renders when nothing has actually changed.\n // `Object.freeze` makes the `Readonly<>` claim true at runtime, not just\n // at the type level — attempts to mutate the snapshot throw in strict\n // mode and are silently ignored in sloppy mode (rather than corrupting\n // the registry). Invalidated to `null` by `register`/`unregister`.\n if (this._snapshot === null) {\n this._snapshot = Object.freeze({ ...this._stores });\n }\n return this._snapshot;\n }\n\n private async notifyRegistered(\n agentId: string,\n store: ɵThreadStore,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber: CopilotKitCoreSubscriber) =>\n subscriber.onThreadStoreRegistered?.({\n copilotkit: this.core,\n agentId,\n store,\n }),\n \"Subscriber onThreadStoreRegistered error:\",\n );\n }\n\n private async notifyUnregistered(\n agentId: string,\n prevStore: ɵThreadStore,\n ): Promise<void> {\n await (\n this.core as unknown as CopilotKitCoreFriendsAccess\n ).notifySubscribers(\n (subscriber: CopilotKitCoreSubscriber) =>\n subscriber.onThreadStoreUnregistered?.({\n copilotkit: this.core,\n agentId,\n prevStore,\n }),\n \"Subscriber onThreadStoreUnregistered error:\",\n );\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n BehaviorSubject,\n Observable,\n OperatorFunction,\n Subject,\n Subscription,\n asapScheduler,\n} from \"rxjs\";\nimport { distinctUntilChanged, filter, map, observeOn } from \"rxjs/operators\";\n\n/**\n * The minimal action shape used by this micro-redux implementation.\n */\nexport interface AnyAction {\n type: string;\n}\n\n/**\n * A typed action creator function with a `type` literal and runtime matcher.\n */\nexport type ActionCreator<\n Type extends string,\n Args extends unknown[] = unknown[],\n Action extends AnyAction & { type: Type } = { type: Type },\n> = ((...args: Args) => Action) & {\n type: Type;\n match(action: AnyAction): action is Action;\n};\n\n/**\n * Extracts the action type produced by an action creator.\n */\nexport type ActionFromCreator<T> = T extends (...args: any[]) => infer A\n ? A\n : never;\n\n/**\n * Extracts a union of actions produced by a tuple/array of action creators.\n */\nexport type ActionFromCreators<\n Creators extends readonly ActionCreator<string, any[], any>[],\n> = ActionFromCreator<Creators[number]>;\n\n/**\n * A reducer transforms state in response to actions.\n */\nexport type Reducer<State, Action extends AnyAction = AnyAction> = (\n state: State | undefined,\n action: Action,\n) => State;\n\n/**\n * A selector derives a value from state.\n */\nexport type Selector<State, Result> = (state: State) => Result;\n\n/**\n * Marker config for action creators that accept no payload.\n */\nexport interface EmptyActionConfig {\n readonly kind: \"empty\";\n}\n\nconst PROPS_MARKER: unique symbol = Symbol(\"props_marker\");\n\n/**\n * Marker config for action creators that require payload props.\n */\nexport interface PropsActionConfig<Props extends Record<string, unknown>> {\n readonly kind: \"props\";\n readonly [PROPS_MARKER]?: Props;\n}\n\n/**\n * Supported action creator config node in an action group.\n */\nexport type ActionConfig =\n | EmptyActionConfig\n | PropsActionConfig<Record<string, unknown>>;\n\n/**\n * Shape of an action group declaration object.\n */\nexport type ActionGroupConfig = Record<string, ActionConfig>;\n\n/**\n * Maps an action group declaration to a strongly typed action-creator object.\n */\nexport type ActionGroupResult<\n Source extends string,\n Config extends ActionGroupConfig,\n> = {\n [K in keyof Config & string]: Config[K] extends PropsActionConfig<infer P>\n ? ActionCreator<`[${Source}] ${K}`, [P], { type: `[${Source}] ${K}` } & P>\n : ActionCreator<`[${Source}] ${K}`, [], { type: `[${Source}] ${K}` }>;\n};\n\ninterface OnReducerEntry<\n State,\n Action extends AnyAction = AnyAction,\n Creators extends readonly ActionCreator<string, any[], any>[] =\n readonly ActionCreator<string, any[], any>[],\n> {\n creators: Creators;\n reducer: (state: State, action: Action) => State;\n}\n\ntype ActionFromOnReducerEntry<TEntry> =\n TEntry extends OnReducerEntry<any, infer TAction, any> ? TAction : never;\n\n/**\n * Effect contract for streams that emit actions to dispatch.\n */\nexport interface DispatchingEffect<\n State,\n InputAction extends AnyAction = AnyAction,\n OutputAction extends AnyAction = AnyAction,\n> {\n run: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<OutputAction>;\n dispatch: true;\n}\n\n/**\n * Effect contract for side-effect-only streams whose emissions are ignored.\n */\nexport interface NonDispatchingEffect<\n State,\n InputAction extends AnyAction = AnyAction,\n> {\n run: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<unknown>;\n dispatch: false;\n}\n\n/**\n * Union of supported effect shapes.\n */\nexport type Effect<\n State,\n InputAction extends AnyAction = AnyAction,\n OutputAction extends AnyAction = AnyAction,\n> =\n | DispatchingEffect<State, InputAction, OutputAction>\n | NonDispatchingEffect<State, InputAction>;\n\n/**\n * Lifecycle actions dispatched by the store.\n */\nexport type StoreLifecycleAction =\n | { type: \"@@micro-redux/init\" }\n | { type: \"@@micro-redux/stop\" };\n\n/**\n * Options for a dispatching effect.\n */\nexport interface DispatchingEffectOptions {\n dispatch?: true;\n}\n\n/**\n * Options for a non-dispatching effect.\n */\nexport interface NonDispatchingEffectOptions {\n dispatch: false;\n}\n\nconst INTERNAL_ACTION_TYPES = {\n boot: \"@@micro-redux/boot\",\n init: \"@@micro-redux/init\",\n stop: \"@@micro-redux/stop\",\n} as const;\n\nconst INTERNAL_BOOT_ACTION: AnyAction = { type: INTERNAL_ACTION_TYPES.boot };\n\n/**\n * Builds a typed action creator from a type string and payload factory.\n */\nfunction createTypedActionCreator<\n Type extends string,\n Args extends unknown[],\n Payload extends Record<string, unknown>,\n>(\n type: Type,\n factory: (...args: Args) => Payload,\n): ActionCreator<Type, Args, { type: Type } & Payload> {\n const creator = ((...args: Args) => ({\n ...factory(...args),\n type,\n })) as ActionCreator<Type, Args, { type: Type } & Payload>;\n\n creator.type = type;\n creator.match = (action: AnyAction): action is { type: Type } & Payload =>\n action.type === type;\n\n return creator;\n}\n\n/**\n * Declares a payload-based action config for `createActionGroup`.\n *\n * @example\n * ```ts\n * const actions = createActionGroup(\"User\", {\n * loaded: props<{ id: string }>(),\n * });\n * ```\n */\nexport function props<\n Props extends Record<string, unknown>,\n>(): PropsActionConfig<Props> {\n return { kind: \"props\" };\n}\n\n/**\n * Declares a no-payload action config for `createActionGroup`.\n *\n * @example\n * ```ts\n * const actions = createActionGroup(\"User\", {\n * reset: empty(),\n * });\n * ```\n */\nexport function empty(): EmptyActionConfig {\n return { kind: \"empty\" };\n}\n\n/**\n * Creates a namespaced group of typed action creators.\n *\n * Action types are formatted as: `[Source] actionName`.\n */\nexport function createActionGroup<\n const Source extends string,\n const Config extends ActionGroupConfig,\n>(source: Source, config: Config): ActionGroupResult<Source, Config> {\n const group = {} as ActionGroupResult<Source, Config>;\n\n for (const eventName of Object.keys(config) as Array<keyof Config & string>) {\n const eventConfig = config[eventName];\n if (!eventConfig) {\n continue;\n }\n\n const actionType = `[${source}] ${eventName}` as const;\n\n if (eventConfig.kind === \"props\") {\n group[eventName] = createTypedActionCreator(\n actionType,\n (payload: Record<string, unknown>) => ({ ...payload }),\n ) as ActionGroupResult<Source, Config>[typeof eventName];\n continue;\n }\n\n group[eventName] = createTypedActionCreator(\n actionType,\n () => ({}),\n ) as ActionGroupResult<Source, Config>[typeof eventName];\n }\n\n return group;\n}\n\n/**\n * Registers one reducer handler for one or more action creators.\n *\n * @throws Error when called without at least one action creator and reducer.\n */\nexport function on<\n State,\n const Creators extends readonly ActionCreator<string, any[], any>[],\n Action extends ActionFromCreators<Creators>,\n>(\n ...args: [\n ...creators: Creators,\n reducer: (state: State, action: Action) => State,\n ]\n): OnReducerEntry<State, Action, Creators> {\n if (args.length < 2) {\n throw new Error(\"on requires at least one action creator and one reducer\");\n }\n\n const reducer = args[args.length - 1] as (\n state: State,\n action: Action,\n ) => State;\n const creators = args.slice(0, -1) as unknown as Creators;\n\n return {\n creators,\n reducer,\n };\n}\n\n/**\n * Creates a reducer from an initial state and `on(...)` handler entries.\n *\n * Unknown action types return the current state unchanged.\n */\nexport function createReducer<\n State,\n const Entries extends readonly OnReducerEntry<any, any, any>[],\n>(\n initialState: State,\n ...entries: Entries\n): Reducer<State, ActionFromOnReducerEntry<Entries[number]>> {\n type ReducerAction = ActionFromOnReducerEntry<Entries[number]>;\n\n const reducerMap = new Map<\n string,\n Array<(state: State, action: ReducerAction) => State>\n >();\n\n for (const entry of entries) {\n for (const creator of entry.creators) {\n const handlers = reducerMap.get(creator.type) ?? [];\n handlers.push(\n entry.reducer as unknown as (\n state: State,\n action: ReducerAction,\n ) => State,\n );\n reducerMap.set(creator.type, handlers);\n }\n }\n\n return (state: State | undefined, action: ReducerAction): State => {\n const currentState = state ?? initialState;\n const handlers = reducerMap.get(action.type);\n\n if (!handlers || handlers.length === 0) {\n return currentState;\n }\n\n let nextState = currentState;\n for (const handler of handlers) {\n nextState = handler(nextState, action);\n }\n return nextState;\n };\n}\n\n/**\n * Creates a memoized selector from a single projector.\n */\nexport function createSelector<State, Result>(\n projector: (state: State) => Result,\n): Selector<State, Result>;\n\n/**\n * Creates a memoized selector from input selectors and a projector.\n *\n * Memoization uses one-entry caching over the latest input selector values.\n */\nexport function createSelector<\n State,\n const Selectors extends readonly Selector<State, unknown>[],\n Result,\n>(\n ...args: [\n ...selectors: Selectors,\n projector: (\n ...inputs: { [K in keyof Selectors]: ReturnType<Selectors[K]> }\n ) => Result,\n ]\n): Selector<State, Result>;\n\n/**\n * Creates a selector that caches and reuses the last computed result\n * when all input references are unchanged.\n */\nexport function createSelector<State, Result>(\n ...args:\n | [(state: State) => Result]\n | [\n ...selectors: Array<Selector<State, unknown>>,\n projector: (...inputs: unknown[]) => Result,\n ]\n): Selector<State, Result> {\n if (args.length === 1) {\n const projector = args[0] as (state: State) => Result;\n let hasCached = false;\n let lastState: State | undefined;\n let lastResult: Result;\n\n return (state: State): Result => {\n if (hasCached && state === lastState) {\n return lastResult;\n }\n\n lastState = state;\n lastResult = projector(state);\n hasCached = true;\n return lastResult;\n };\n }\n\n const projector = args[args.length - 1] as (...inputs: unknown[]) => Result;\n const selectors = args.slice(0, -1) as Array<Selector<State, unknown>>;\n\n let hasCached = false;\n let lastInputs: unknown[] = [];\n let lastResult: Result;\n\n return (state: State): Result => {\n const inputs = selectors.map((selector) => selector(state));\n\n if (\n hasCached &&\n inputs.length === lastInputs.length &&\n inputs.every((value, index) => value === lastInputs[index])\n ) {\n return lastResult;\n }\n\n lastInputs = inputs;\n lastResult = projector(...inputs);\n hasCached = true;\n return lastResult;\n };\n}\n\n/**\n * RxJS operator that maps state emissions through a selector and suppresses\n * unchanged projected values via reference equality.\n */\nexport function select<State, Result>(\n selector: Selector<State, Result>,\n): OperatorFunction<State, Result> {\n return (source$) => source$.pipe(map(selector), distinctUntilChanged());\n}\n\n/**\n * RxJS operator that filters an action stream by action creators and narrows\n * the output action type to the matched creator union.\n *\n * @throws Error when called without at least one action creator.\n */\nexport function ofType<\n const Creators extends readonly ActionCreator<string, any[], AnyAction>[],\n>(\n ...creators: Creators\n): OperatorFunction<AnyAction, ActionFromCreators<Creators>> {\n if (creators.length === 0) {\n throw new Error(\"ofType requires at least one action creator\");\n }\n\n const actionTypes = new Set(creators.map((creator) => creator.type));\n return (source$) => {\n return source$.pipe(\n filter((action: AnyAction): action is ActionFromCreators<Creators> => {\n return actionTypes.has(action.type);\n }),\n );\n };\n}\n\n/**\n * Creates a dispatching effect. Emitted actions are automatically dispatched.\n */\nexport function createEffect<\n State,\n InputAction extends AnyAction,\n OutputAction extends AnyAction,\n>(\n factory: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<OutputAction>,\n options?: DispatchingEffectOptions,\n): DispatchingEffect<State, InputAction, OutputAction>;\n\n/**\n * Creates a non-dispatching effect. Emitted values are ignored.\n */\nexport function createEffect<State, InputAction extends AnyAction>(\n factory: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<unknown>,\n options: NonDispatchingEffectOptions,\n): NonDispatchingEffect<State, InputAction>;\n\n/**\n * Creates an effect descriptor consumed by `createStore`.\n */\nexport function createEffect<\n State,\n InputAction extends AnyAction,\n OutputAction extends AnyAction,\n>(\n factory: (\n actions$: Observable<InputAction>,\n state$: Observable<State>,\n ) => Observable<OutputAction>,\n options: DispatchingEffectOptions | NonDispatchingEffectOptions = {},\n): Effect<State, InputAction, OutputAction> {\n if (options.dispatch === false) {\n return {\n run: factory,\n dispatch: false,\n };\n }\n\n return {\n run: factory,\n dispatch: true,\n };\n}\n\n/**\n * Store interface returned by `createStore`.\n */\nexport interface Store<State, Action extends AnyAction = AnyAction> {\n dispatch(action: Action): void;\n getState(): State;\n readonly state$: Observable<State>;\n readonly actions$: Observable<Action | StoreLifecycleAction>;\n select<Result>(selector: Selector<State, Result>): Observable<Result>;\n init(): void;\n stop(): void;\n}\n\n/**\n * Creates a small observable store with reducer + effects.\n *\n * Behavior:\n * - `init()` starts effects and dispatches `@@micro-redux/init`.\n * - `stop()` dispatches `@@micro-redux/stop` and unsubscribes all effects.\n * - Effect action observation is scheduled on `asapScheduler` to avoid\n * synchronous re-entrancy in the effect loop.\n * - Any effect error triggers fail-fast teardown and errors both `actions$`\n * and `state$`.\n */\nexport function createStore<\n State,\n Action extends AnyAction = AnyAction,\n>(options: {\n reducer: Reducer<State, Action | StoreLifecycleAction>;\n effects?: Array<Effect<State, Action | StoreLifecycleAction, Action>>;\n}): Store<State, Action> {\n const reducer = options.reducer;\n const effects = options.effects ?? [];\n\n let hasFatalError = false;\n let isRunning = false;\n let effectSubscriptions = new Subscription();\n\n let currentState = reducer(\n undefined,\n INTERNAL_BOOT_ACTION as Action | StoreLifecycleAction,\n );\n const stateSubject = new BehaviorSubject<State>(currentState);\n const actionsSubject = new Subject<Action | StoreLifecycleAction>();\n\n const dispatchInternal = (action: Action | StoreLifecycleAction): void => {\n if (hasFatalError) {\n throw new Error(\"Store is in a failed state due to an effect error\");\n }\n\n currentState = reducer(currentState, action);\n stateSubject.next(currentState);\n actionsSubject.next(action);\n };\n\n const failFast = (error: unknown): void => {\n if (hasFatalError) {\n return;\n }\n\n hasFatalError = true;\n isRunning = false;\n effectSubscriptions.unsubscribe();\n effectSubscriptions = new Subscription();\n\n actionsSubject.error(error);\n stateSubject.error(error);\n };\n\n const startEffects = (): void => {\n for (const effect of effects) {\n const scheduledActions$ = actionsSubject\n .asObservable()\n .pipe(observeOn(asapScheduler));\n const state$ = stateSubject.asObservable();\n\n if (effect.dispatch) {\n const subscription = effect.run(scheduledActions$, state$).subscribe({\n next: (effectAction) => {\n if (hasFatalError) {\n return;\n }\n dispatchInternal(effectAction);\n },\n error: (error) => {\n failFast(error);\n },\n });\n\n effectSubscriptions.add(subscription);\n continue;\n }\n\n const subscription = effect.run(scheduledActions$, state$).subscribe({\n error: (error) => {\n failFast(error);\n },\n });\n\n effectSubscriptions.add(subscription);\n }\n };\n\n return {\n dispatch(action: Action): void {\n dispatchInternal(action);\n },\n getState(): State {\n return currentState;\n },\n get state$(): Observable<State> {\n return stateSubject.asObservable();\n },\n get actions$(): Observable<Action | StoreLifecycleAction> {\n return actionsSubject.asObservable();\n },\n select<Result>(selector: Selector<State, Result>): Observable<Result> {\n return stateSubject.asObservable().pipe(select(selector));\n },\n init(): void {\n if (hasFatalError || isRunning) {\n return;\n }\n\n isRunning = true;\n startEffects();\n\n if (hasFatalError) {\n return;\n }\n\n dispatchInternal({ type: INTERNAL_ACTION_TYPES.init });\n },\n stop(): void {\n if (hasFatalError || !isRunning) {\n return;\n }\n\n dispatchInternal({ type: INTERNAL_ACTION_TYPES.stop });\n effectSubscriptions.unsubscribe();\n effectSubscriptions = new Subscription();\n isRunning = false;\n },\n };\n}\n","/**\n * Memory error registry — stable codes for the errors the memory store throws.\n *\n * The memory store (`memory.ts`) used to throw bare `new Error(\"Failed to fetch\n * memories: 500\")` / `\"Request timed out\"` / `\"Request failed: <status>\"`. Those\n * reach the `error` selector (and the consumer UI via `useMemories` /\n * `injectMemories`) verbatim, with no machine-readable `code`/`category`/\n * `retryable`, so they cannot be grouped in observability or branched on by\n * consumers.\n *\n * Per the repo's error-handling architecture standard (AGENTS.md: \"Each project\n * must maintain an explicit error registry\"), this file is the explicit registry\n * for the memory feature. It is deliberately scoped to memory — not a repo-wide\n * registry refactor — because `packages/core` has no pre-existing\n * code/category/retryable registry convention to plug into (the runtime's\n * `lib/error-messages.ts` is a message-templating table, not a typed\n * code/category/retryable registry). It mirrors the existing\n * `AgentThreadLockedError extends Error` precedent in\n * `intelligence-agent.ts`: a real `Error` subclass so `instanceof Error` holds\n * and the public `MemoryState.error: Error | null` contract is preserved.\n *\n * `docsPath` is recorded per entry per the standard; there is no\n * `docs/errors/<project>.md` in this repo, so this docblock plus the registry\n * are the source of truth.\n *\n * Each registry entry carries:\n * - `code`: stable identifier (e.g. `MEMORY_LIST_FAILED`).\n * - `category`: one of the standard categories\n * (`validation`|`auth`|`permission`|`not_found`|`conflict`|`rate_limit`|`internal`|`dependency`).\n * - `retryable`: whether a retry could plausibly succeed (timeouts + transient\n * dependency failures are retryable; client-caused 4xx are not).\n * - `message`: the default human-readable message (callers may override with a\n * status-bearing string to preserve the prior wording).\n * - `docsPath`: documentation pointer for the code.\n */\n\n/** Standard error categories from the repo error-handling architecture. */\nexport type MemoryErrorCategory =\n | \"validation\"\n | \"auth\"\n | \"permission\"\n | \"not_found\"\n | \"conflict\"\n | \"rate_limit\"\n | \"internal\"\n | \"dependency\";\n\n/** Stable codes for the memory store's surfaced errors. */\nexport type MemoryErrorCode =\n | \"MEMORY_LIST_FAILED\"\n | \"MEMORY_CREDENTIALS_FAILED\"\n | \"MEMORY_MUTATION_FAILED\"\n | \"MEMORY_REQUEST_TIMEOUT\";\n\n/** A single registry entry describing one memory error code. */\nexport interface MemoryErrorRegistryEntry {\n readonly code: MemoryErrorCode;\n readonly category: MemoryErrorCategory;\n readonly retryable: boolean;\n readonly message: string;\n readonly docsPath: string;\n}\n\n/**\n * The memory error registry: the single source of truth for memory error\n * metadata. Keyed by `code` so a code maps to exactly one category/retryable\n * default.\n *\n * Categories/retryable rationale:\n * - List/credentials/mutation failures are `dependency` (the runtime/platform\n * the store calls failed). A 5xx is transient (`retryable: true`); a 4xx is\n * caller-caused, so the helpers below downgrade those to non-retryable.\n * - Timeouts are `dependency` and `retryable: true` (the request may simply be\n * slow).\n */\nexport const MEMORY_ERROR_REGISTRY: Readonly<\n Record<MemoryErrorCode, MemoryErrorRegistryEntry>\n> = Object.freeze({\n MEMORY_LIST_FAILED: {\n code: \"MEMORY_LIST_FAILED\",\n category: \"dependency\",\n retryable: true,\n message: \"Failed to fetch memories\",\n docsPath: \"docs/errors/memory.md#memory_list_failed\",\n },\n MEMORY_CREDENTIALS_FAILED: {\n code: \"MEMORY_CREDENTIALS_FAILED\",\n category: \"dependency\",\n retryable: true,\n message: \"Failed to fetch memory subscribe credentials\",\n docsPath: \"docs/errors/memory.md#memory_credentials_failed\",\n },\n MEMORY_MUTATION_FAILED: {\n code: \"MEMORY_MUTATION_FAILED\",\n category: \"dependency\",\n retryable: true,\n message: \"Memory mutation request failed\",\n docsPath: \"docs/errors/memory.md#memory_mutation_failed\",\n },\n MEMORY_REQUEST_TIMEOUT: {\n code: \"MEMORY_REQUEST_TIMEOUT\",\n category: \"dependency\",\n retryable: true,\n message: \"Request timed out\",\n docsPath: \"docs/errors/memory.md#memory_request_timeout\",\n },\n});\n\n/**\n * An `Error` carrying a stable memory error `code`, `category`, and `retryable`\n * flag so consumers and observability can branch on it without string-matching\n * the message.\n *\n * It is a real `Error` subclass: `instanceof Error` is true, so the public\n * `MemoryState.error: Error | null` contract (and the `error: Error | null`\n * surfaced by `useMemories` / `injectMemories`) holds unchanged. Existing\n * consumers that only read `.message` keep working; the richer fields are\n * additive.\n */\nexport class MemoryError extends Error {\n /** Stable, machine-readable error identifier. */\n readonly code: MemoryErrorCode;\n /** Coarse error category for grouping/observability. */\n readonly category: MemoryErrorCategory;\n /** Whether retrying the operation could plausibly succeed. */\n readonly retryable: boolean;\n\n /**\n * @param code - Registry code identifying this error.\n * @param options - Optional overrides:\n * - `message`: human-readable message (defaults to the registry message;\n * callers pass a status-bearing string to preserve prior wording).\n * - `retryable`: overrides the registry default (e.g. a 4xx list failure is\n * not retryable even though the code's default is).\n * - `cause`: the underlying error, preserved for debugging.\n */\n constructor(\n code: MemoryErrorCode,\n options?: { message?: string; retryable?: boolean; cause?: unknown },\n ) {\n const entry = MEMORY_ERROR_REGISTRY[code];\n super(options?.message ?? entry.message, { cause: options?.cause });\n this.name = \"MemoryError\";\n this.code = code;\n this.category = entry.category;\n this.retryable = options?.retryable ?? entry.retryable;\n // Restore the prototype chain for environments that downlevel `extends`\n // (matches the pattern the SDK relies on for cross-target `instanceof`).\n Object.setPrototypeOf(this, MemoryError.prototype);\n }\n}\n\n/**\n * Narrows an HTTP status to whether the failure is worth retrying: a 5xx (or a\n * missing/0 status) is a transient dependency failure and retryable; a 4xx is\n * caller-caused and not. Used so a `MEMORY_LIST_FAILED`/`MEMORY_MUTATION_FAILED`\n * carries an accurate `retryable` flag derived from the response status.\n */\nexport function isRetryableStatus(status: number): boolean {\n return !(Number.isInteger(status) && status >= 400 && status <= 499);\n}\n","import { phoenixExponentialBackoff } from \"@copilotkit/shared\";\nimport type { Observable } from \"rxjs\";\nimport {\n asapScheduler,\n defer,\n firstValueFrom,\n merge,\n observeOn,\n of,\n} from \"rxjs\";\nimport { fromFetch } from \"rxjs/fetch\";\nimport {\n catchError,\n concatWith,\n filter,\n finalize,\n map,\n mergeMap,\n share,\n shareReplay,\n switchMap,\n take,\n takeUntil,\n timeout,\n withLatestFrom,\n} from \"rxjs/operators\";\nimport {\n createActionGroup,\n createEffect,\n createReducer,\n createSelector,\n createStore,\n empty,\n ofType,\n on,\n props,\n} from \"./utils/micro-redux\";\nimport type { Reducer, Store } from \"./utils/micro-redux\";\nimport { MemoryError, isRetryableStatus } from \"./memory-errors\";\nimport {\n ɵphoenixChannel$,\n ɵphoenixSocket$,\n ɵjoinPhoenixChannel$,\n ɵobservePhoenixEvent$,\n ɵobservePhoenixSocketHealth$,\n ɵobservePhoenixSocketSignals$,\n} from \"./utils/phoenix-observable\";\nimport type { ɵPhoenixChannelSession } from \"./utils/phoenix-observable\";\n\n// Runtime-relative path, mirroring the thread store's `/threads` (NOT\n// `/api/threads`): `runtimeUrl` is the CopilotKit runtime mount (e.g.\n// `/api/copilotkit`), and the runtime maps `/memories` to the app-api's\n// `/api/memories` the same way it maps `/threads` -> `/api/threads`.\nconst MEMORIES_PATH = \"/memories\";\nconst MEMORIES_SUBSCRIBE_PATH = \"/memories/subscribe\";\nconst REQUEST_TIMEOUT_MS = 15_000;\n/** Consecutive socket errors tolerated before the realtime stream gives up. */\nconst MAX_SOCKET_RETRIES = 5;\n/**\n * HTTP status codes that indicate memory routes are not configured (non-fatal).\n * 404/501 mean the route is absent/unimplemented; 422 is the runtime's\n * MISSING_INTELLIGENCE signal (intelligence not configured on the deployment —\n * see packages/runtime/.../handlers/intelligence/memories.ts). All three map to\n * the graceful \"not available\" locked-teaser path, not a hard error.\n */\nconst ROUTE_UNAVAILABLE_STATUSES = new Set([404, 422, 501]);\n/**\n * Thrown when a memory route returns a 404/422/501 — treated as \"not\n * configured\" (422 is the runtime's MISSING_INTELLIGENCE signal).\n */\nclass MemoryRouteUnavailableError extends Error {}\n\n/** Public, customer-facing memory kind vocabulary (single taxonomy, no mapping). */\nexport type MemoryKind = \"topical\" | \"episodic\" | \"operational\";\n\n/** Visibility scope of a memory. */\nexport type MemoryScope = \"user\" | \"project\";\n\n/**\n * Health of the realtime (`user_meta:memories:<code>`) connection that streams\n * live `memory_metadata` deltas. Distinct from `available`/`error`, which\n * describe the REST list route: `realtimeStatus` reports ONLY whether the\n * realtime socket/channel is live so the UI can stop showing a \"live\" indicator\n * over a frozen snapshot once the socket permanently gives up.\n *\n * - `\"connecting\"` — fetching join credentials / opening the socket / joining\n * the channel (the default, and the state every `contextChanged`/`stopped`\n * resets to).\n * - `\"connected\"` — the channel join succeeded; live deltas are flowing.\n * - `\"unavailable\"` — the socket exhausted its retries or the join failed\n * permanently; the snapshot is frozen and no deltas will arrive. This is a\n * silent degrade for `available`/`error` (those stay untouched) — only this\n * signal flips.\n */\nexport type MemoryRealtimeStatus = \"connecting\" | \"connected\" | \"unavailable\";\n\n/**\n * A memory as projected across the public REST/realtime boundary — the minimal\n * shape the SDK surfaces. Mirrors the server's `PublicMemory` projection.\n */\nexport interface Memory {\n id: string;\n kind: MemoryKind;\n scope: MemoryScope;\n content: string;\n sourceThreadIds: readonly string[];\n invalidatedAt: string | null;\n}\n\n/** Input for creating a memory; `scope` defaults to `\"user\"` (v1 is user-scoped). */\nexport interface NewMemory {\n content: string;\n kind: MemoryKind;\n scope?: MemoryScope;\n sourceThreadIds?: readonly string[];\n}\n\n/**\n * New values for superseding (updating) a memory — same shape as create.\n *\n * Supersede is a FULL replacement, not a partial patch: this is the complete\n * definition of the new memory that replaces the old one. `content` and `kind`\n * are required and must be re-supplied, and an omitted `sourceThreadIds` resets\n * the new memory's source threads to `[]` — it does NOT preserve the prior\n * memory's value.\n */\nexport type MemoryChanges = NewMemory;\n\n/** Outcome of a mutation, tracked so the caller's promise resolves/rejects. */\ntype MemoryMutationOutcome =\n | { requestId: string; sessionId: number; ok: true; memory: Memory | null }\n | { requestId: string; sessionId: number; ok: false; error: Error };\n\n/**\n * Runtime wiring for the memory store: where to reach the REST surface and the\n * headers (auth + `X-Cpki-User-Id`) to send. Scoped to the current user; v1\n * surfaces user-scoped memories only.\n */\ninterface MemoryRuntimeContext {\n runtimeUrl: string;\n /** WebSocket URL for the realtime gateway (e.g. `wss://gw.example.com/client`). */\n wsUrl: string;\n headers: Record<string, string>;\n includeInvalidated?: boolean;\n}\n\n/**\n * In-memory state for the memory store. Session-guarded like the thread store:\n * `sessionId` is bumped whenever the runtime context changes so that responses\n * and realtime deltas from a previous context are ignored.\n */\ninterface MemoryState {\n memories: Memory[];\n isLoading: boolean;\n inFlightMutationCount: number;\n error: Error | null;\n context: MemoryRuntimeContext | null;\n sessionId: number;\n available: boolean;\n realtimeStatus: MemoryRealtimeStatus;\n}\n\n// Deep-frozen so `getServerState()` (which returns this exact reference) cannot\n// be mutated by any caller; a single in-place write would otherwise corrupt\n// every SSR snapshot process-wide. The freeze covers the nested `memories`\n// array too — a shallow `Object.freeze` would leave `getServerState().memories`\n// mutable (`.push(...)` would silently succeed), so the empty array is frozen\n// before being sealed into the state. The reducers always build NEW state\n// objects/arrays (they spread, never mutate in place), so they are unaffected\n// and runtime behavior is unchanged.\nconst initialMemoryState: MemoryState = Object.freeze({\n memories: Object.freeze([]) as unknown as Memory[],\n isLoading: false,\n inFlightMutationCount: 0,\n error: null,\n context: null,\n sessionId: 0,\n available: true,\n realtimeStatus: \"connecting\",\n});\n\nconst memoryAdapterEvents = createActionGroup(\"Memory Adapter\", {\n started: empty(),\n stopped: empty(),\n contextChanged: props<{ context: MemoryRuntimeContext | null }>(),\n addRequested: props<{ requestId: string; input: NewMemory }>(),\n updateRequested: props<{\n requestId: string;\n id: string;\n changes: MemoryChanges;\n }>(),\n removeRequested: props<{ requestId: string; id: string }>(),\n});\n\nconst memoryRestEvents = createActionGroup(\"Memory REST\", {\n listRequested: props<{ sessionId: number }>(),\n listSucceeded: props<{ sessionId: number; memories: Memory[] }>(),\n listFailed: props<{ sessionId: number; error: Error }>(),\n listUnavailable: props<{ sessionId: number }>(),\n mutationFinished: props<{ outcome: MemoryMutationOutcome }>(),\n credentialsRequested: props<{ sessionId: number }>(),\n credentialsSucceeded: props<{\n sessionId: number;\n joinToken: string;\n joinCode: string;\n }>(),\n // Credentials outcomes are a SILENT degrade: they feed only the realtime\n // socket effect and deliberately do NOT touch the reducer's `available`/\n // `error`, which describe the REST list route. See the reducer note near the\n // list handlers.\n credentialsFailed: props<{ sessionId: number; error: Error }>(),\n credentialsUnavailable: props<{ sessionId: number }>(),\n});\n\nconst memoryDomainEvents = createActionGroup(\"Memory Domain\", {\n memoryUpserted: props<{ sessionId: number; memory: Memory }>(),\n memoryInvalidated: props<{ sessionId: number; memoryId: string }>(),\n // Realtime-connection health transitions, session-stamped like every other\n // realtime delta so the reducer's session guard drops transitions left over\n // from a superseded context. These flip ONLY `realtimeStatus`; they never\n // touch `available`/`error` (the realtime path is a silent degrade for those).\n realtimeConnecting: props<{ sessionId: number }>(),\n realtimeConnected: props<{ sessionId: number }>(),\n realtimeUnavailable: props<{ sessionId: number }>(),\n});\n\n/** Wire shape of a memory inside a `memory_metadata` payload (carries tenant ids). */\ninterface MemoryMetadataPayloadMemory extends Memory {\n organizationId: string;\n projectId: string;\n}\n\n/**\n * The realtime `memory_metadata` event broadcast on the `user_meta` channel:\n * `created`/`updated` carry the full memory, `invalidated` carries only its id.\n * The gateway strips `userId` before broadcasting and only delivers\n * user-scoped memories, so this is always the current user's stream.\n */\ntype MemoryMetadataEvent =\n | {\n operation: \"created\" | \"updated\";\n memoryId: string;\n organizationId: string;\n projectId: string;\n occurredAt: string;\n memory: MemoryMetadataPayloadMemory;\n }\n | {\n operation: \"invalidated\";\n memoryId: string;\n organizationId: string;\n projectId: string;\n occurredAt: string;\n invalidated: { id: string };\n };\n\n/** Projects a wire memory to the public {@link Memory} shape (drops tenant ids). */\nfunction toMemory(memory: MemoryMetadataPayloadMemory): Memory {\n return {\n id: memory.id,\n kind: memory.kind,\n scope: memory.scope,\n content: memory.content,\n sourceThreadIds: memory.sourceThreadIds,\n invalidatedAt: memory.invalidatedAt,\n };\n}\n\n/**\n * Maps a realtime `memory_metadata` event to the domain action that applies it:\n * `created`/`updated` upsert the projected memory, `invalidated` removes it by\n * id. Carries the current `sessionId` so the reducer's session guard can drop\n * deltas left over from a previous context.\n */\nfunction mapMemoryMetadataEvent(\n event: MemoryMetadataEvent,\n sessionId: number,\n):\n | ReturnType<typeof memoryDomainEvents.memoryUpserted>\n | ReturnType<typeof memoryDomainEvents.memoryInvalidated> {\n if (event.operation === \"invalidated\") {\n return memoryDomainEvents.memoryInvalidated({\n sessionId,\n memoryId: event.invalidated.id,\n });\n }\n\n return memoryDomainEvents.memoryUpserted({\n sessionId,\n memory: toMemory(event.memory),\n });\n}\n\n/**\n * Inserts or replaces a memory by id. A new memory is prepended (newest first,\n * matching the REST list's `created_at DESC` ordering without needing a date\n * field on the public projection); an existing memory is replaced in place.\n */\nfunction upsertMemory(memories: Memory[], memory: Memory): Memory[] {\n const existingIndex = memories.findIndex((item) => item.id === memory.id);\n if (existingIndex === -1) {\n return [memory, ...memories];\n }\n\n const next = [...memories];\n next[existingIndex] = memory;\n return next;\n}\n\nconst memoryReducer = createReducer(\n initialMemoryState,\n on(memoryAdapterEvents.contextChanged, (state: MemoryState, { context }) => ({\n ...state,\n context,\n sessionId: state.sessionId + 1,\n memories: [],\n isLoading: Boolean(context),\n inFlightMutationCount: 0,\n error: null,\n available: true,\n // A new context re-opens the realtime socket from scratch, so the connection\n // is \"connecting\" again until the new channel joins.\n realtimeStatus: \"connecting\" as MemoryRealtimeStatus,\n })),\n on(memoryAdapterEvents.stopped, (state: MemoryState) => ({\n ...state,\n memories: [],\n isLoading: false,\n inFlightMutationCount: 0,\n error: null,\n // Reset to the default (`true`), matching `contextChanged`. Otherwise a\n // `stop()` then `start()` WITHOUT a new `setContext` would retain a stale\n // `available: false` from a prior unconfigured session.\n available: true,\n // Reset to the default (\"connecting\"), matching `contextChanged`. A later\n // `start()` re-opens the socket; a stale \"unavailable\"/\"connected\" from the\n // prior session must not leak into the next.\n realtimeStatus: \"connecting\" as MemoryRealtimeStatus,\n })),\n on(memoryRestEvents.listRequested, (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId || !state.context) {\n return state;\n }\n\n return {\n ...state,\n isLoading: true,\n error: null,\n available: true,\n };\n }),\n on(\n memoryRestEvents.listFailed,\n (state: MemoryState, { sessionId, error }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n isLoading: false,\n error,\n };\n },\n ),\n on(memoryRestEvents.listUnavailable, (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n memories: [],\n isLoading: false,\n error: null,\n available: false,\n };\n }),\n on(\n memoryAdapterEvents.addRequested,\n memoryAdapterEvents.updateRequested,\n memoryAdapterEvents.removeRequested,\n (state: MemoryState) => ({\n ...state,\n inFlightMutationCount: state.inFlightMutationCount + 1,\n }),\n ),\n on(memoryRestEvents.mutationFinished, (state: MemoryState, { outcome }) => {\n // Drop results from a superseded session. `contextChanged`/`stopped` already\n // reset `inFlightMutationCount`, so a mutation that resolves after the\n // context switched must not write a stale error into the new session.\n // Mirrors every other session-scoped handler (and threads.ts).\n if (outcome.sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n inFlightMutationCount: Math.max(0, state.inFlightMutationCount - 1),\n // On success clear any previously surfaced mutation error so a later\n // successful mutation does not leave a phantom sticky error banner.\n error: outcome.ok ? null : outcome.error,\n };\n }),\n on(\n memoryRestEvents.listSucceeded,\n (state: MemoryState, { sessionId, memories }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n memories,\n isLoading: false,\n error: null,\n // A successful list proves the memory route is available.\n available: true,\n };\n },\n ),\n // NOTE: `credentialsFailed` and `credentialsUnavailable` intentionally have NO\n // reducer cases. `available`/`error` describe the REST list route only and are\n // driven exclusively by the list events above. The credentials/realtime path\n // is a silent degrade by design: a missing/unconfigured `/memories/subscribe`\n // route (404/501/422) or a credentials error must not flip `available` or\n // surface an `error`, because the list route can still be perfectly healthy.\n // Otherwise `available` would be order-dependent on whichever of the two\n // concurrent `contextChanged` bootstraps responds last. Realtime failures are\n // handled where they occur (the socket effect retries and gives up via\n // console.warn); they do not belong in the REST availability state.\n on(\n memoryDomainEvents.memoryUpserted,\n (state: MemoryState, { sessionId, memory }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n memories: upsertMemory(state.memories, memory),\n };\n },\n ),\n on(\n memoryDomainEvents.memoryInvalidated,\n (state: MemoryState, { sessionId, memoryId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n memories: state.memories.filter((memory) => memory.id !== memoryId),\n };\n },\n ),\n // Realtime-connection health. Session-guarded so a transition from a\n // superseded context is ignored. These flip ONLY `realtimeStatus`; `available`\n // and `error` describe the REST list route and are intentionally untouched.\n on(\n memoryDomainEvents.realtimeConnecting,\n (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n realtimeStatus: \"connecting\" as MemoryRealtimeStatus,\n };\n },\n ),\n on(\n memoryDomainEvents.realtimeConnected,\n (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n realtimeStatus: \"connected\" as MemoryRealtimeStatus,\n };\n },\n ),\n on(\n memoryDomainEvents.realtimeUnavailable,\n (state: MemoryState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n realtimeStatus: \"unavailable\" as MemoryRealtimeStatus,\n };\n },\n ),\n) as Reducer<MemoryState>;\n\nconst selectMemories = createSelector((state: MemoryState) => state.memories);\nconst selectMemoriesIsLoading = createSelector(\n (state: MemoryState) => state.isLoading,\n);\nconst selectMemoriesError = createSelector((state: MemoryState) => state.error);\n/**\n * Reports whether at least one mutation is in flight. Derived from\n * `inFlightMutationCount` so concurrent mutations stay correct: the boolean\n * only clears once every in-flight mutation has settled.\n */\nconst selectMemoriesIsMutating = createSelector(\n (state: MemoryState) => state.inFlightMutationCount > 0,\n);\n/**\n * Reports whether the memory routes are available. Becomes `false` after a\n * 404, 422 (the runtime's MISSING_INTELLIGENCE signal), or 501 response during\n * an auto-activation read; defaults to `true`.\n */\nconst selectMemoriesAvailable = createSelector(\n (state: MemoryState) => state.available,\n);\n/**\n * Reports the realtime-connection health (see {@link MemoryRealtimeStatus}).\n * Distinct from `available`/`error`: it reflects ONLY the live socket/channel,\n * so the UI can suppress a \"live\" indicator once realtime permanently dies even\n * while the REST list route stays healthy. Defaults to `\"connecting\"`.\n */\nconst selectMemoriesRealtimeStatus = createSelector(\n (state: MemoryState) => state.realtimeStatus,\n);\n\n/**\n * Dependencies injected into the memory store. The store opens its own\n * `user_meta:memories:<joinCode>` socket/channel and does not share the\n * thread store's socket, so only a `fetch` implementation is required.\n */\ninterface MemoryEnvironment {\n fetch: typeof fetch;\n}\n\ninterface MemoryStore {\n start(): void;\n stop(): void;\n setContext(context: MemoryRuntimeContext | null): void;\n /**\n * Re-fetches the REST snapshot without clearing the current list. Resolves\n * once the re-pull settles (success or failure) for the current context, so\n * callers (e.g. a `useMemories` `refresh()`) can await it. Resolves\n * immediately when no context is set.\n */\n refresh(): Promise<void>;\n /** Creates a memory; resolves to the stored memory (server-authoritative). */\n addMemory(input: NewMemory): Promise<Memory>;\n /** Supersedes a memory; resolves to the new memory (its id changes). */\n updateMemory(id: string, changes: MemoryChanges): Promise<Memory>;\n /** Retires a memory (non-lossy delete). */\n removeMemory(id: string): Promise<void>;\n getState(): MemoryState;\n /**\n * Stable, render-safe state for SSR/prerender. React's\n * `useSyncExternalStore` requires a `getServerSnapshot` during SSR/prerender\n * (e.g. Next.js); without one React throws \"Missing getServerSnapshot\". The\n * returned reference is stable across calls so React does not loop. There is\n * no client-side memory data during prerender, so this is the empty initial\n * state (no memories, not loading, no error).\n */\n getServerState(): MemoryState;\n select: Store<MemoryState>[\"select\"];\n}\n\nconst MEMORY_METADATA_EVENT = \"memory_metadata\";\n\nfunction memoryFromFetch<T>(\n input: string,\n init: RequestInit & {\n selector: (response: Response) => Promise<T>;\n fetch: typeof fetch;\n },\n): Observable<T> {\n return fromFetch(input, init);\n}\n\n/**\n * Fetches the memory snapshot and maps it to a success/failure action. Keeps\n * only user-scoped memories (v1 surfaces user scope only; the realtime stream\n * is user-scoped too), so project-scoped rows visible to the caller are\n * dropped from the store.\n */\nfunction createMemoryFetchObservable(\n environment: MemoryEnvironment,\n context: MemoryRuntimeContext,\n sessionId: number,\n): Observable<\n | ReturnType<typeof memoryRestEvents.listSucceeded>\n | ReturnType<typeof memoryRestEvents.listFailed>\n | ReturnType<typeof memoryRestEvents.listUnavailable>\n> {\n return defer(() => {\n const qs = context.includeInvalidated ? \"?includeInvalidated=true\" : \"\";\n return memoryFromFetch(`${context.runtimeUrl}${MEMORIES_PATH}${qs}`, {\n selector: (response) => {\n if (!response.ok) {\n if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) {\n throw new MemoryRouteUnavailableError(String(response.status));\n }\n throw new MemoryError(\"MEMORY_LIST_FAILED\", {\n message: `Failed to fetch memories: ${response.status}`,\n retryable: isRetryableStatus(response.status),\n });\n }\n\n return response.json() as Promise<{ memories: Memory[] }>;\n },\n fetch: environment.fetch,\n method: \"GET\",\n headers: { ...context.headers },\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new MemoryError(\"MEMORY_REQUEST_TIMEOUT\");\n },\n }),\n map((data) =>\n memoryRestEvents.listSucceeded({\n sessionId,\n memories: data.memories.filter((memory) => memory.scope === \"user\"),\n }),\n ),\n catchError((error) => {\n if (error instanceof MemoryRouteUnavailableError) {\n return of(memoryRestEvents.listUnavailable({ sessionId }));\n }\n return of(\n memoryRestEvents.listFailed({\n sessionId,\n error: error instanceof Error ? error : new Error(String(error)),\n }),\n );\n }),\n );\n });\n}\n\n/**\n * Fetches join credentials from the `/memories/subscribe` endpoint and maps\n * the response to a success/failure action. Requires both `joinToken` and\n * `joinCode` to be non-empty strings; throws otherwise so the `catchError`\n * path emits `credentialsFailed`.\n */\nfunction createMemoryCredentialsFetchObservable(\n environment: MemoryEnvironment,\n context: MemoryRuntimeContext,\n sessionId: number,\n): Observable<\n | ReturnType<typeof memoryRestEvents.credentialsSucceeded>\n | ReturnType<typeof memoryRestEvents.credentialsFailed>\n | ReturnType<typeof memoryRestEvents.credentialsUnavailable>\n> {\n return defer(() =>\n memoryFromFetch(`${context.runtimeUrl}${MEMORIES_SUBSCRIBE_PATH}`, {\n selector: async (response) => {\n if (!response.ok) {\n if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) {\n throw new MemoryRouteUnavailableError(String(response.status));\n }\n throw new MemoryError(\"MEMORY_CREDENTIALS_FAILED\", {\n message: `Failed to fetch memory subscribe credentials: ${response.status}`,\n retryable: isRetryableStatus(response.status),\n });\n }\n\n return response.json() as Promise<{\n joinToken: string;\n joinCode: string;\n }>;\n },\n fetch: environment.fetch,\n method: \"POST\",\n headers: { ...context.headers, \"Content-Type\": \"application/json\" },\n body: JSON.stringify({}),\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new MemoryError(\"MEMORY_REQUEST_TIMEOUT\");\n },\n }),\n map((data) => {\n if (typeof data.joinToken !== \"string\" || data.joinToken.length === 0) {\n throw new Error(\"missing joinToken\");\n }\n if (typeof data.joinCode !== \"string\" || data.joinCode.length === 0) {\n throw new Error(\"missing joinCode\");\n }\n\n return memoryRestEvents.credentialsSucceeded({\n sessionId,\n joinToken: data.joinToken,\n joinCode: data.joinCode,\n });\n }),\n catchError((error) => {\n if (error instanceof MemoryRouteUnavailableError) {\n return of(memoryRestEvents.credentialsUnavailable({ sessionId }));\n }\n return of(\n memoryRestEvents.credentialsFailed({\n sessionId,\n error: error instanceof Error ? error : new Error(String(error)),\n }),\n );\n }),\n ),\n );\n}\n\ntype MemoryMutationAction =\n | ReturnType<typeof memoryDomainEvents.memoryUpserted>\n | ReturnType<typeof memoryDomainEvents.memoryInvalidated>\n | ReturnType<typeof memoryRestEvents.mutationFinished>;\n\ntype MemoryMutationRequest =\n | {\n requestId: string;\n sessionId: number;\n kind: \"add\";\n body: Record<string, unknown>;\n }\n | {\n requestId: string;\n sessionId: number;\n kind: \"update\";\n id: string;\n body: Record<string, unknown>;\n }\n | { requestId: string; sessionId: number; kind: \"remove\"; id: string };\n\n/** Projects a REST mutation response to the public {@link Memory} shape. */\nfunction responseToMemory(data: {\n id: string;\n kind: MemoryKind;\n scope: MemoryScope;\n content: string;\n sourceThreadIds: readonly string[];\n invalidatedAt: string | null;\n}): Memory {\n return {\n id: data.id,\n kind: data.kind,\n scope: data.scope,\n content: data.content,\n sourceThreadIds: data.sourceThreadIds,\n invalidatedAt: data.invalidatedAt,\n };\n}\n\nconst MEMORY_KINDS: ReadonlySet<string> = new Set([\n \"topical\",\n \"episodic\",\n \"operational\",\n]);\nconst MEMORY_SCOPES: ReadonlySet<string> = new Set([\"user\", \"project\"]);\n\n/**\n * Validates the required fields of a create/supersede REST response before it is\n * projected to a {@link Memory}. Returns an `Error` describing the first\n * missing/invalid field, or `null` when the body is well-formed. Without this a\n * malformed 200 body yields a Memory with undefined fields that gets upserted.\n */\nfunction validateMutationResponse(\n data: Record<string, unknown> | null,\n): Error | null {\n if (!data || typeof data !== \"object\") {\n return new Error(\"memory mutation response missing/invalid body\");\n }\n if (typeof data.id !== \"string\" || data.id.length === 0) {\n return new Error(\"memory mutation response missing/invalid id\");\n }\n if (typeof data.kind !== \"string\" || !MEMORY_KINDS.has(data.kind)) {\n return new Error(\"memory mutation response missing/invalid kind\");\n }\n if (typeof data.scope !== \"string\" || !MEMORY_SCOPES.has(data.scope)) {\n return new Error(\"memory mutation response missing/invalid scope\");\n }\n if (typeof data.content !== \"string\") {\n return new Error(\"memory mutation response missing/invalid content\");\n }\n // `sourceThreadIds` is `readonly string[]` on the public Memory; a malformed\n // 200 that omits it (or sends a non-array) would otherwise yield a Memory\n // whose `sourceThreadIds` is `undefined`, violating the type for every\n // consumer that maps over it.\n if (\n !Array.isArray(data.sourceThreadIds) ||\n !data.sourceThreadIds.every((id) => typeof id === \"string\")\n ) {\n return new Error(\n \"memory mutation response missing/invalid sourceThreadIds\",\n );\n }\n // `invalidatedAt` is `string | null`; reject any other type so it is not\n // copied through as `undefined`.\n if (data.invalidatedAt !== null && typeof data.invalidatedAt !== \"string\") {\n return new Error(\"memory mutation response missing/invalid invalidatedAt\");\n }\n return null;\n}\n\n/**\n * Request body for create/supersede. `scope` is forwarded only when the caller\n * supplies it: the platform owns the default (`scope` defaults to `\"user\"` in\n * the `/api/memories` schema), so the store does not second-guess it here —\n * one default, at the contract owner. `sourceThreadIds` defaults to `[]`.\n */\nfunction toMutationBody(input: NewMemory): Record<string, unknown> {\n return {\n content: input.content,\n kind: input.kind,\n ...(input.scope !== undefined ? { scope: input.scope } : {}),\n sourceThreadIds: input.sourceThreadIds ?? [],\n };\n}\n\n/**\n * Builds the actions a successful mutation dispatches (server-authoritative):\n * the REST response is applied to local state immediately, and the realtime\n * event reconciles idempotently (upsert-by-id). `mutationFinished` resolves the\n * caller's promise.\n */\nfunction buildMutationSuccessActions(\n request: MemoryMutationRequest,\n data: Record<string, unknown> | null,\n): MemoryMutationAction[] {\n const { requestId, sessionId } = request;\n\n if (request.kind === \"remove\") {\n // The platform's DELETE returns a bare 204 with NO body (the runtime\n // handler responds `new Response(null, { status: 204 })` and the client's\n // `removeMemory` is `Promise<void>`), so there is no confirmation field to\n // validate here — removal is status-code-confirmed. We optimistically remove\n // the row locally on any 2xx; the realtime `memory_metadata` `invalidated`\n // event (and the next REST refresh) reconcile idempotently.\n return [\n memoryDomainEvents.memoryInvalidated({ sessionId, memoryId: request.id }),\n memoryRestEvents.mutationFinished({\n outcome: { requestId, sessionId, ok: true, memory: null },\n }),\n ];\n }\n\n // Validate the required fields before projecting. A malformed 200 body would\n // otherwise yield a Memory with undefined fields that gets upserted into\n // state. Fail the mutation instead, mirroring the `retiredId` validation\n // below and the credentials path's joinToken/joinCode validation.\n const validationError = validateMutationResponse(data);\n if (validationError) {\n return [\n memoryRestEvents.mutationFinished({\n outcome: { requestId, sessionId, ok: false, error: validationError },\n }),\n ];\n }\n\n const memory = responseToMemory(\n data as Parameters<typeof responseToMemory>[0],\n );\n\n if (request.kind === \"update\") {\n // `retiredId` is optional on the server type. Without it the\n // `memoryInvalidated` would be a no-op (no id to remove), leaving the old\n // memory as a duplicate next to the new one. Validate it like the\n // credentials path validates joinToken/joinCode, and fail the mutation\n // rather than apply a half-baked supersede.\n const retiredId = (data as { retiredId?: string }).retiredId;\n if (typeof retiredId !== \"string\" || retiredId.length === 0) {\n return [\n memoryRestEvents.mutationFinished({\n outcome: {\n requestId,\n sessionId,\n ok: false,\n error: new Error(\"supersede response missing retiredId\"),\n },\n }),\n ];\n }\n\n return [\n memoryDomainEvents.memoryInvalidated({ sessionId, memoryId: retiredId }),\n memoryDomainEvents.memoryUpserted({ sessionId, memory }),\n memoryRestEvents.mutationFinished({\n outcome: { requestId, sessionId, ok: true, memory },\n }),\n ];\n }\n\n return [\n memoryDomainEvents.memoryUpserted({ sessionId, memory }),\n memoryRestEvents.mutationFinished({\n outcome: { requestId, sessionId, ok: true, memory },\n }),\n ];\n}\n\n/** Performs a create/supersede/retire HTTP call and emits its resulting actions. */\nfunction createMemoryMutationObservable(\n environment: MemoryEnvironment,\n context: MemoryRuntimeContext,\n request: MemoryMutationRequest,\n): Observable<MemoryMutationAction> {\n const method =\n request.kind === \"add\"\n ? \"POST\"\n : request.kind === \"update\"\n ? \"PATCH\"\n : \"DELETE\";\n const path =\n request.kind === \"add\"\n ? MEMORIES_PATH\n : `${MEMORIES_PATH}/${encodeURIComponent(request.id)}`;\n\n return defer(() =>\n memoryFromFetch(`${context.runtimeUrl}${path}`, {\n selector: async (response) => {\n if (!response.ok) {\n throw new MemoryError(\"MEMORY_MUTATION_FAILED\", {\n message: `Request failed: ${response.status}`,\n retryable: isRetryableStatus(response.status),\n });\n }\n\n return request.kind === \"remove\"\n ? null\n : ((await response.json()) as Record<string, unknown>);\n },\n fetch: environment.fetch,\n method,\n headers: { ...context.headers, \"Content-Type\": \"application/json\" },\n body:\n request.kind === \"remove\" ? undefined : JSON.stringify(request.body),\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new MemoryError(\"MEMORY_REQUEST_TIMEOUT\");\n },\n }),\n mergeMap((data) => of(...buildMutationSuccessActions(request, data))),\n catchError((error) =>\n of(\n memoryRestEvents.mutationFinished({\n outcome: {\n requestId: request.requestId,\n sessionId: request.sessionId,\n ok: false,\n error: error instanceof Error ? error : new Error(String(error)),\n },\n }),\n ),\n ),\n ),\n );\n}\n\n/**\n * Creates the framework-agnostic memory store: a REST snapshot on `setContext`,\n * server-authoritative add/update/remove mutations, and realtime\n * `memory_metadata` deltas off the injected `user_meta` event source — all\n * reduced into observable state.\n */\nfunction createMemoryStore(environment: MemoryEnvironment): MemoryStore {\n // Per-store request-id counter. Kept as a closure variable (not a\n // module-level global) so each store instance has its own monotonic sequence:\n // sharing one global across instances is a latent cross-instance/SSR hazard\n // and makes request ids non-reproducible in tests that reset a single store.\n let memoryRequestId = 0;\n const createMemoryRequestId = (): string => {\n memoryRequestId += 1;\n return `memory-request-${memoryRequestId}`;\n };\n\n const bootstrapEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryAdapterEvents.contextChanged),\n withLatestFrom(state$),\n filter(([, state]) => Boolean(state.context)),\n map(([, state]) =>\n memoryRestEvents.listRequested({ sessionId: state.sessionId }),\n ),\n ),\n );\n\n const credentialsBootstrapEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryAdapterEvents.contextChanged),\n withLatestFrom(state$),\n filter(([, state]) => Boolean(state.context)),\n map(([, state]) =>\n memoryRestEvents.credentialsRequested({ sessionId: state.sessionId }),\n ),\n ),\n );\n\n const credentialsFetchEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryRestEvents.credentialsRequested),\n switchMap((action) =>\n state$.pipe(\n map((state) => state.context),\n filter((context): context is MemoryRuntimeContext =>\n Boolean(context),\n ),\n take(1),\n map((context) => ({ action, context })),\n takeUntil(\n actions$.pipe(\n ofType(\n memoryAdapterEvents.contextChanged,\n memoryAdapterEvents.stopped,\n ),\n ),\n ),\n switchMap(({ action: currentAction, context }) =>\n createMemoryCredentialsFetchObservable(\n environment,\n context,\n currentAction.sessionId,\n ),\n ),\n ),\n ),\n ),\n );\n\n const fetchEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryRestEvents.listRequested),\n switchMap((action) =>\n state$.pipe(\n map((state) => state.context),\n filter((context): context is MemoryRuntimeContext =>\n Boolean(context),\n ),\n take(1),\n map((context) => ({ action, context })),\n takeUntil(\n actions$.pipe(\n ofType(\n memoryAdapterEvents.contextChanged,\n memoryAdapterEvents.stopped,\n ),\n ),\n ),\n switchMap(({ action: currentAction, context }) =>\n createMemoryFetchObservable(\n environment,\n context,\n currentAction.sessionId,\n ),\n ),\n ),\n ),\n ),\n );\n\n const mutationEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(\n memoryAdapterEvents.addRequested,\n memoryAdapterEvents.updateRequested,\n memoryAdapterEvents.removeRequested,\n ),\n withLatestFrom(state$),\n mergeMap(([action, state]) => {\n const context = state.context;\n const sessionId = state.sessionId;\n if (!context?.runtimeUrl) {\n return of(\n memoryRestEvents.mutationFinished({\n outcome: {\n requestId: action.requestId,\n sessionId,\n ok: false,\n error: new Error(\"Runtime URL is not configured\"),\n },\n }),\n );\n }\n\n if (memoryAdapterEvents.addRequested.match(action)) {\n return createMemoryMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n kind: \"add\",\n body: toMutationBody(action.input),\n });\n }\n if (memoryAdapterEvents.updateRequested.match(action)) {\n return createMemoryMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n kind: \"update\",\n id: action.id,\n body: toMutationBody(action.changes),\n });\n }\n return createMemoryMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n kind: \"remove\",\n id: action.id,\n });\n }),\n ),\n );\n\n const socketEffect = createEffect(\n (actions$, state$: Observable<MemoryState>) =>\n actions$.pipe(\n ofType(memoryRestEvents.credentialsSucceeded),\n withLatestFrom(state$),\n filter(([action, state]) => {\n return (\n action.sessionId === state.sessionId &&\n Boolean(state.context?.wsUrl)\n );\n }),\n switchMap(([action, state]) => {\n const context = state.context as MemoryRuntimeContext;\n const { joinToken, joinCode } = action;\n const sessionId = action.sessionId;\n const shutdown$ = actions$.pipe(\n ofType(\n memoryAdapterEvents.contextChanged,\n memoryAdapterEvents.stopped,\n ),\n );\n\n return defer(() => {\n const socket$ = ɵphoenixSocket$({\n url: context.wsUrl,\n options: {\n params: { join_token: joinToken },\n reconnectAfterMs: phoenixExponentialBackoff(100, 10_000),\n rejoinAfterMs: phoenixExponentialBackoff(1_000, 30_000),\n },\n }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const channel$ = ɵphoenixChannel$({\n socket$,\n topic: `user_meta:memories:${joinCode}`,\n }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const socketSignals$ =\n ɵobservePhoenixSocketSignals$(socket$).pipe(share());\n // The socket give-up signal: completes the realtime stream after the\n // health check throws. ALSO surfaces the give-up as a status delta\n // (`realtimeUnavailable`) so the UI can drop its \"live\" indicator —\n // this is the permanent-death signal that was previously only a\n // `console.warn`. `available`/`error` stay untouched by design (the\n // realtime path is a silent degrade for the REST list route).\n const fatalSocketShutdown$ = ɵobservePhoenixSocketHealth$(\n socketSignals$,\n MAX_SOCKET_RETRIES,\n ).pipe(\n catchError(() => {\n console.warn(\n `[memory] WebSocket failed after ${MAX_SOCKET_RETRIES} attempts, giving up`,\n );\n return of(undefined);\n }),\n share(),\n );\n // The give-up mapped to a status delta. Emitted from the merged stream\n // (not the `takeUntil` notifier) so the `realtimeUnavailable` action is\n // dispatched BEFORE teardown: the merged stream is `takeUntil`'d by a\n // microtask-deferred copy of the give-up signal, so this synchronous\n // emission always wins the race and the action reaches the reducer.\n const fatalStatus$ = fatalSocketShutdown$.pipe(\n map(() => memoryDomainEvents.realtimeUnavailable({ sessionId })),\n );\n const metadata$ = channel$.pipe(\n switchMap(({ channel }: ɵPhoenixChannelSession) =>\n ɵobservePhoenixEvent$<MemoryMetadataEvent>(\n channel,\n MEMORY_METADATA_EVENT,\n ),\n ),\n map((event) => mapMemoryMetadataEvent(event, action.sessionId)),\n );\n\n // Drives the actual `channel.join()` AND maps the join outcome to a\n // realtime-status delta. `ɵphoenixChannel$` only creates the channel +\n // a lazy join-outcome stream; the join is sent when that stream is\n // subscribed. Observing channel events (`metadata$`) alone does NOT\n // subscribe it, so without this the socket connects but never joins\n // `user_meta:memories:<code>` and no realtime deltas arrive. The thread\n // store joins for the same reason (its merged `joinOutcome$`).\n //\n // On a successful join -> `realtimeConnected` (the \"live\" signal). On a\n // failed/timed-out join we KEEP the `console.warn` and emit\n // `realtimeUnavailable`, then swallow the error so a transient\n // rejection doesn't tear down the metadata stream (Phoenix re-attempts\n // the join on socket reconnect); the next successful join re-emits\n // `realtimeConnected`.\n const join$ = ɵjoinPhoenixChannel$(channel$).pipe(\n // `ɵjoinPhoenixChannel$` emits `never` (it completes on success), so\n // this concat surfaces the connected status once the join resolves.\n concatWith(\n of(memoryDomainEvents.realtimeConnected({ sessionId })),\n ),\n catchError((error) => {\n console.warn(\n `[memory] failed to join user_meta:memories:${joinCode}`,\n error,\n );\n return of(\n memoryDomainEvents.realtimeUnavailable({ sessionId }),\n );\n }),\n );\n\n return merge(\n // Surface \"connecting\" immediately when the realtime stream starts\n // (credentials succeeded -> socket subscribing/joining). Reset to\n // this on every (re)subscribe so a prior session's terminal status\n // can't bleed through before the new join resolves.\n of(memoryDomainEvents.realtimeConnecting({ sessionId })),\n metadata$,\n join$,\n fatalStatus$,\n ).pipe(\n takeUntil(\n merge(\n shutdown$,\n // Defer the give-up teardown by a microtask so `fatalStatus$`'s\n // synchronous `realtimeUnavailable` emission is dispatched before\n // the stream is torn down. `observeOn(asapScheduler)` schedules\n // the teardown after the current microtask drains.\n fatalSocketShutdown$.pipe(observeOn(asapScheduler)),\n ),\n ),\n finalize(() => {\n // Socket/channel teardown is handled by the `finalize` operators\n // inside `ɵphoenixSocket$`/`ɵphoenixChannel$`; this hook exists to\n // mirror the thread store's socket-effect lifecycle shape.\n }),\n );\n });\n }),\n ),\n );\n\n const store = createStore<MemoryState>({\n reducer: memoryReducer,\n effects: [\n bootstrapEffect,\n credentialsBootstrapEffect,\n fetchEffect,\n credentialsFetchEffect,\n mutationEffect,\n socketEffect,\n ],\n });\n\n function trackMutation<T>(\n dispatchAction:\n | ReturnType<typeof memoryAdapterEvents.addRequested>\n | ReturnType<typeof memoryAdapterEvents.updateRequested>\n | ReturnType<typeof memoryAdapterEvents.removeRequested>,\n extract: (outcome: Extract<MemoryMutationOutcome, { ok: true }>) => T,\n ): Promise<T> {\n const { requestId } = dispatchAction;\n const completion$ = merge(\n store.actions$.pipe(\n ofType(memoryRestEvents.mutationFinished),\n filter((action) => action.outcome.requestId === requestId),\n map((action) => action.outcome),\n ),\n store.actions$.pipe(\n ofType(memoryAdapterEvents.stopped),\n map(\n () =>\n ({\n requestId,\n sessionId: store.getState().sessionId,\n ok: false,\n error: new Error(\n \"Memory store stopped before mutation completed\",\n ),\n }) satisfies MemoryMutationOutcome,\n ),\n ),\n ).pipe(take(1));\n\n const resultPromise = firstValueFrom(completion$).then((outcome) => {\n if (!outcome.ok) {\n throw outcome.error;\n }\n return extract(outcome);\n });\n\n store.dispatch(dispatchAction);\n return resultPromise;\n }\n\n return {\n start(): void {\n store.init();\n store.dispatch(memoryAdapterEvents.started());\n },\n stop(): void {\n store.dispatch(memoryAdapterEvents.stopped());\n store.stop();\n },\n setContext(context: MemoryRuntimeContext | null): void {\n store.dispatch(memoryAdapterEvents.contextChanged({ context }));\n },\n refresh(): Promise<void> {\n const { sessionId, context } = store.getState();\n if (!context) return Promise.resolve();\n\n // Settle when the re-pulled snapshot completes for this session (success\n // or failure), or if the store is stopped first. Subscribe before\n // dispatching so the resulting list action can't slip past, mirroring\n // trackMutation.\n const completion$ = merge(\n store.actions$.pipe(\n ofType(\n memoryRestEvents.listSucceeded,\n memoryRestEvents.listFailed,\n // `listUnavailable` (404/501/422) is the third terminal outcome of\n // the list fetch. Without it `await refresh()` would hang forever\n // against an unconfigured route.\n memoryRestEvents.listUnavailable,\n ),\n filter((action) => action.sessionId === sessionId),\n ),\n store.actions$.pipe(ofType(memoryAdapterEvents.stopped)),\n // The list `fetchEffect` has `takeUntil(contextChanged, stopped)`, so a\n // `contextChanged` fired after this `listRequested` but before the fetch\n // settles tears down the fetch with NO terminal list action for our\n // session — `await refresh()` would hang forever. Settle on it too.\n store.actions$.pipe(ofType(memoryAdapterEvents.contextChanged)),\n ).pipe(take(1));\n\n // `await refresh()` resolving must mean the snapshot actually refreshed,\n // so reject on anything that isn't a successful re-pull — a failed list\n // (its error also lands in the `error` selector) or the store being\n // stopped mid-flight. This keeps `refresh` fully symmetric with the\n // mutation methods, which reject on both failure and stop via\n // `trackMutation`.\n const done = firstValueFrom(completion$).then((action) => {\n if (memoryRestEvents.listFailed.match(action)) {\n throw action.error;\n }\n if (memoryAdapterEvents.stopped.match(action)) {\n throw new Error(\"Memory store stopped before refresh completed\");\n }\n // A `contextChanged` superseded this refresh: a new context is loading\n // its own snapshot, so this refresh is moot. RESOLVE (do not reject) —\n // resolving is the least-surprising outcome for a superseded refresh.\n if (memoryAdapterEvents.contextChanged.match(action)) {\n return;\n }\n // `listSucceeded` and `listUnavailable` both RESOLVE: an unavailable\n // (not-configured) route is a non-fatal terminal state, consistent with\n // the auto-load path which leaves `available: false` without erroring.\n });\n store.dispatch(memoryRestEvents.listRequested({ sessionId }));\n return done;\n },\n addMemory(input: NewMemory): Promise<Memory> {\n return trackMutation(\n memoryAdapterEvents.addRequested({\n requestId: createMemoryRequestId(),\n input,\n }),\n (outcome) => {\n if (outcome.memory == null) {\n throw new Error(\"add resolved without a memory\");\n }\n return outcome.memory;\n },\n );\n },\n updateMemory(id: string, changes: MemoryChanges): Promise<Memory> {\n return trackMutation(\n memoryAdapterEvents.updateRequested({\n requestId: createMemoryRequestId(),\n id,\n changes,\n }),\n (outcome) => {\n if (outcome.memory == null) {\n throw new Error(\"update resolved without a memory\");\n }\n return outcome.memory;\n },\n );\n },\n removeMemory(id: string): Promise<void> {\n return trackMutation(\n memoryAdapterEvents.removeRequested({\n requestId: createMemoryRequestId(),\n id,\n }),\n () => undefined,\n );\n },\n getState(): MemoryState {\n return store.getState();\n },\n getServerState(): MemoryState {\n return initialMemoryState;\n },\n select: store.select.bind(store),\n };\n}\n\n// `Memory`, `MemoryKind`, `MemoryScope`, `NewMemory`, and `MemoryChanges` are\n// the consumer-facing memory types surfaced by the framework hooks\n// (`useMemories` / `injectMemories`); they are exported unprefixed from their\n// declarations above. The remaining memory internals keep the `ɵ` prefix.\n// The memory error registry surface is consumer-facing: `MemoryError` is what\n// `MemoryState.error` (and the `error: Error | null` from `useMemories` /\n// `injectMemories`) carries on a failure, and consumers branch on its\n// `code`/`category`/`retryable`. Re-exported unprefixed here so it ships through\n// `index.ts` (`export * from \"./memory\"`) alongside the memory types.\nexport {\n MemoryError,\n MEMORY_ERROR_REGISTRY,\n isRetryableStatus as ɵisRetryableMemoryStatus,\n} from \"./memory-errors\";\nexport type {\n MemoryErrorCode,\n MemoryErrorCategory,\n MemoryErrorRegistryEntry,\n} from \"./memory-errors\";\n\nexport type ɵMemoryState = MemoryState;\nexport type ɵMemoryRuntimeContext = MemoryRuntimeContext;\nexport type ɵMemoryMetadataEvent = MemoryMetadataEvent;\nexport type ɵMemoryEnvironment = MemoryEnvironment;\nexport type ɵMemoryStore = MemoryStore;\nexport const ɵmemoryAdapterEvents = memoryAdapterEvents;\nexport const ɵmemoryRestEvents = memoryRestEvents;\nexport const ɵmemoryDomainEvents = memoryDomainEvents;\nexport const ɵmemoryReducer = memoryReducer;\nexport const ɵmapMemoryMetadataEvent = mapMemoryMetadataEvent;\nexport const ɵselectMemories = selectMemories;\nexport const ɵselectMemoriesIsLoading = selectMemoriesIsLoading;\nexport const ɵselectMemoriesError = selectMemoriesError;\nexport const ɵselectMemoriesIsMutating = selectMemoriesIsMutating;\nexport const ɵselectMemoriesAvailable = selectMemoriesAvailable;\nexport const ɵselectMemoriesRealtimeStatus = selectMemoriesRealtimeStatus;\nexport { createMemoryStore as ɵcreateMemoryStore };\n","import type { AbstractAgent, Context, State } from \"@ag-ui/client\";\nimport type { AgentSubscriber } from \"@ag-ui/client\";\nimport { Throttler } from \"@tanstack/pacer\";\nimport type {\n FrontendTool,\n SuggestionsConfig,\n Suggestion,\n CopilotRuntimeTransport,\n RuntimeMode,\n RuntimeLicenseStatus,\n IntelligenceRuntimeInfo,\n ThreadEndpointRuntimeInfo,\n} from \"../types\";\nimport type {\n CopilotKitCoreAddAgentParams,\n CopilotKitCoreRegisterProxiedAgentParams,\n CopilotKitCoreRegisterProxiedAgentResult,\n} from \"./agent-registry\";\nimport { AgentRegistry } from \"./agent-registry\";\nimport type { ScopedContext } from \"./context-store\";\nimport { ContextStore } from \"./context-store\";\nimport { SuggestionEngine } from \"./suggestion-engine\";\nimport type {\n CopilotKitCoreRunAgentParams,\n CopilotKitCoreConnectAgentParams,\n CopilotKitCoreGetToolParams,\n CopilotKitCoreRunToolParams,\n CopilotKitCoreRunToolResult,\n} from \"./run-handler\";\nimport { RunHandler } from \"./run-handler\";\nimport type { DebugConfig } from \"@copilotkit/shared\";\nimport { StateManager } from \"./state-manager\";\nimport { ThreadStoreRegistry } from \"./thread-store-registry\";\nimport type { ɵThreadStore } from \"../threads\";\nimport { ɵcreateMemoryStore } from \"../memory\";\nimport type { ɵMemoryStore } from \"../memory\";\n\n/** Configuration options for `CopilotKitCore`. */\nexport interface CopilotKitCoreConfig {\n /** The endpoint of the CopilotRuntime. */\n runtimeUrl?: string;\n /** Transport style for CopilotRuntime endpoints. Defaults to REST. */\n runtimeTransport?: CopilotRuntimeTransport;\n /**\n * When true, the constructor sets the runtime config but does NOT start the\n * `/info` connection. Call {@link CopilotKitCore.connect} to start it —\n * typically from a host's commit-phase effect. This prevents a burst of\n * duplicate `/info` requests when a host constructs (and discards) the core\n * during render, e.g. React concurrent rendering / Suspense / StrictMode.\n * See https://github.com/CopilotKit/CopilotKit/issues/5801.\n */\n deferInitialConnection?: boolean;\n /** Mapping from agent name to its `AbstractAgent` instance. For development only - production requires CopilotRuntime. */\n agents__unsafe_dev_only?: Record<string, AbstractAgent>;\n /**\n * Headers sent with every runtime request and merged on top of each\n * `HttpAgent`'s own headers (the core value wins on a key conflict). See\n * `setHeaders`.\n */\n headers?: Record<string, string>;\n /** Credentials mode for fetch requests (e.g., \"include\" for HTTP-only cookies). */\n credentials?: RequestCredentials;\n /** Properties sent as `forwardedProps` to the AG-UI agent. */\n properties?: Record<string, unknown>;\n /** Ordered collection of frontend tools available to the core. */\n tools?: FrontendTool<any>[];\n /** Suggestions config for the core. */\n suggestionsConfig?: SuggestionsConfig[];\n /** Enable debug logging for the client-side event pipeline. */\n debug?: DebugConfig;\n}\n\nexport type {\n CopilotKitCoreAddAgentParams,\n CopilotKitCoreRegisterProxiedAgentParams,\n CopilotKitCoreRegisterProxiedAgentResult,\n};\nexport type {\n CopilotKitCoreRunAgentParams,\n CopilotKitCoreConnectAgentParams,\n CopilotKitCoreGetToolParams,\n CopilotKitCoreRunToolParams,\n CopilotKitCoreRunToolResult,\n};\n\nexport interface CopilotKitCoreStopAgentParams {\n agent: AbstractAgent;\n}\n\nexport type CopilotKitCoreGetSuggestionsResult = {\n suggestions: Suggestion[];\n isLoading: boolean;\n};\n\nexport enum CopilotKitCoreErrorCode {\n RUNTIME_INFO_FETCH_FAILED = \"runtime_info_fetch_failed\",\n AGENT_CONNECT_FAILED = \"agent_connect_failed\",\n AGENT_RUN_FAILED = \"agent_run_failed\",\n AGENT_RUN_FAILED_EVENT = \"agent_run_failed_event\",\n AGENT_RUN_ERROR_EVENT = \"agent_run_error_event\",\n TOOL_ARGUMENT_PARSE_FAILED = \"tool_argument_parse_failed\",\n TOOL_HANDLER_FAILED = \"tool_handler_failed\",\n TOOL_NOT_FOUND = \"tool_not_found\",\n AGENT_NOT_FOUND = \"agent_not_found\",\n /**\n * Emitted when an agent run fails because the thread is already locked\n * by another active run.\n *\n * @example\n * ```tsx\n * <CopilotKitProvider\n * onError={({ code, error, context }) => {\n * if (code === \"agent_thread_locked\") {\n * // Show \"Agent is busy, retry?\" UI\n * }\n * }}\n * />\n * ```\n */\n AGENT_THREAD_LOCKED = \"agent_thread_locked\",\n // Transcription errors\n TRANSCRIPTION_FAILED = \"transcription_failed\",\n TRANSCRIPTION_SERVICE_NOT_CONFIGURED = \"transcription_service_not_configured\",\n TRANSCRIPTION_INVALID_AUDIO = \"transcription_invalid_audio\",\n TRANSCRIPTION_RATE_LIMITED = \"transcription_rate_limited\",\n TRANSCRIPTION_AUTH_FAILED = \"transcription_auth_failed\",\n TRANSCRIPTION_NETWORK_ERROR = \"transcription_network_error\",\n SUBSCRIBER_CALLBACK_FAILED = \"subscriber_callback_failed\",\n}\n\nexport interface CopilotKitCoreSubscriber {\n onRuntimeConnectionStatusChanged?: (event: {\n copilotkit: CopilotKitCore;\n status: CopilotKitCoreRuntimeConnectionStatus;\n }) => void | Promise<void>;\n onToolExecutionStart?: (event: {\n copilotkit: CopilotKitCore;\n toolCallId: string;\n agentId: string;\n toolName: string;\n args: unknown;\n }) => void | Promise<void>;\n onToolExecutionEnd?: (event: {\n copilotkit: CopilotKitCore;\n toolCallId: string;\n agentId: string;\n toolName: string;\n result: string;\n error?: string;\n }) => void | Promise<void>;\n onAgentsChanged?: (event: {\n copilotkit: CopilotKitCore;\n agents: Readonly<Record<string, AbstractAgent>>;\n }) => void | Promise<void>;\n /**\n * Fired when an agent run or connect begins. The `agent` may be a per-thread\n * clone that is not present in `core.agents`, so `onAgentsChanged` never fires\n * for it. Subscribers (e.g. the inspector) can use this to subscribe to the\n * running instance's AG-UI events.\n */\n onAgentRunStarted?: (event: {\n copilotkit: CopilotKitCore;\n agent: AbstractAgent;\n }) => void | Promise<void>;\n onContextChanged?: (event: {\n copilotkit: CopilotKitCore;\n context: Readonly<Record<string, Context>>;\n }) => void | Promise<void>;\n onSuggestionsConfigChanged?: (event: {\n copilotkit: CopilotKitCore;\n suggestionsConfig: Readonly<Record<string, SuggestionsConfig>>;\n }) => void | Promise<void>;\n onSuggestionsChanged?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n suggestions: Suggestion[];\n }) => void | Promise<void>;\n onSuggestionsStartedLoading?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n }) => void | Promise<void>;\n onSuggestionsFinishedLoading?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n }) => void | Promise<void>;\n onPropertiesChanged?: (event: {\n copilotkit: CopilotKitCore;\n properties: Readonly<Record<string, unknown>>;\n }) => void | Promise<void>;\n onHeadersChanged?: (event: {\n copilotkit: CopilotKitCore;\n headers: Readonly<Record<string, string>>;\n }) => void | Promise<void>;\n onError?: (event: {\n copilotkit: CopilotKitCore;\n error: Error;\n code: CopilotKitCoreErrorCode;\n context: Record<string, any>;\n }) => void | Promise<void>;\n onThreadStoreRegistered?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n store: ɵThreadStore;\n }) => void | Promise<void>;\n /**\n * Fired when a thread store is removed from the registry, either by an\n * explicit `unregister()` call or by a `register()` call that replaces an\n * existing store for the same `agentId`.\n *\n * The previous store is delivered via `prevStore` so subscribers can tear\n * down state that depends on the concrete instance (e.g. cancel an active\n * subscription) without consulting the registry. By the time async\n * subscribers resume after an `await`, a replacement `register()` may have\n * already installed the new store under the same key, so calling\n * `registry.get(agentId)` inside this callback is unsafe and may return\n * the new store instead of the unregistered one.\n */\n onThreadStoreUnregistered?: (event: {\n copilotkit: CopilotKitCore;\n agentId: string;\n prevStore: ɵThreadStore;\n }) => void | Promise<void>;\n}\n\n// Subscription object returned by subscribe() and subscribeToAgentWithOptions()\nexport interface CopilotKitCoreSubscription {\n unsubscribe: () => void;\n}\n\n/**\n * The callback keys accepted by {@link CopilotKitCore.subscribeToAgentWithOptions}.\n * This tuple is the single source of truth — both the\n * `SubscribeToAgentSubscriber` type and the runtime `ALLOWED_KEYS` set\n * are derived from it, so they cannot desynchronise.\n */\nconst SUBSCRIBE_TO_AGENT_KEYS = [\n \"onMessagesChanged\",\n \"onStateChanged\",\n \"onRunInitialized\",\n \"onRunFinalized\",\n \"onRunFailed\",\n \"onRunErrorEvent\",\n] as const satisfies readonly (keyof AgentSubscriber)[];\n\n/**\n * Runtime allowlist derived from {@link SUBSCRIBE_TO_AGENT_KEYS}. Hoisted\n * to module scope so the Set is allocated once, not per-subscription.\n */\nconst ALLOWED_KEYS: ReadonlySet<(typeof SUBSCRIBE_TO_AGENT_KEYS)[number]> =\n new Set(SUBSCRIBE_TO_AGENT_KEYS);\n\n/**\n * The subset of `AgentSubscriber` callbacks accepted by\n * {@link CopilotKitCore.subscribeToAgentWithOptions}. Only the callbacks\n * listed in {@link SUBSCRIBE_TO_AGENT_KEYS} are supported:\n * `onMessagesChanged`, `onStateChanged`, and the four run lifecycle\n * callbacks (`onRunInitialized`, `onRunFinalized`, `onRunFailed`,\n * `onRunErrorEvent`).\n *\n * Two categories of `AgentSubscriber` members are excluded:\n *\n * - **AG-UI event handlers** (`onEvent`, `onToolCallStartEvent`, etc.)\n * return `AgentStateMutation` with `stopPropagation` — semantics that\n * the throttle and error-protection wrappers cannot safely mediate.\n *\n * - **Per-item notification callbacks** (`onNewMessage`, `onNewToolCall`)\n * return `void` and have no mutation concerns, but are excluded to keep\n * the surface area minimal — `onMessagesChanged` already covers the\n * same data at a coarser granularity, and throttling per-item callbacks\n * would have different semantic expectations.\n *\n * `onRunErrorEvent` is technically an AG-UI event handler (its return type\n * includes `stopPropagation`), but it is included here because all\n * framework consumers need it to reset `isRunning` on protocol-level\n * `RUN_ERROR` events — distinct from `onRunFailed` which handles local\n * exceptions like network errors. In practice, consumers return `void`\n * from this callback, so the `stopPropagation` semantics are unused.\n *\n * Note: the included lifecycle callbacks return\n * `Omit<AgentStateMutation, \"stopPropagation\">` (or full\n * `AgentStateMutation` in the case of `onRunErrorEvent`). On the error\n * path, `safeCall` discards those return values (see its inline\n * documentation).\n *\n * Use `agent.subscribe()` directly when event mutation or per-item\n * notification semantics are needed.\n */\nexport type SubscribeToAgentSubscriber = Pick<\n AgentSubscriber,\n (typeof SUBSCRIBE_TO_AGENT_KEYS)[number]\n>;\n\n/** Options for {@link CopilotKitCore.subscribeToAgentWithOptions}. */\nexport interface SubscribeToAgentOptions {\n /**\n * Throttle interval (ms) for `onMessagesChanged` / `onStateChanged`.\n * Non-negative finite number; `0` explicitly disables throttling.\n * Falls back to `defaultThrottleMs` when `undefined`.\n */\n throttleMs?: number;\n}\n\nexport enum CopilotKitCoreRuntimeConnectionStatus {\n Disconnected = \"disconnected\",\n Connected = \"connected\",\n Connecting = \"connecting\",\n Error = \"error\",\n}\n\n/**\n * Internal interface for delegate classes to access CopilotKitCore methods.\n * This provides type safety while allowing controlled access to private functionality.\n */\nexport interface CopilotKitCoreFriendsAccess {\n // Notification methods\n notifySubscribers(\n handler: (subscriber: CopilotKitCoreSubscriber) => void | Promise<void>,\n errorMessage: string,\n ): Promise<void>;\n\n emitError(params: {\n error: Error;\n code: CopilotKitCoreErrorCode;\n context?: Record<string, any>;\n }): Promise<void>;\n\n // Getters for internal state\n readonly headers: Readonly<Record<string, string>>;\n readonly credentials: RequestCredentials | undefined;\n readonly properties: Readonly<Record<string, unknown>>;\n readonly context: Readonly<Record<string, Context>>;\n readonly debug?: DebugConfig;\n\n // Internal methods\n buildFrontendTools(agentId?: string): import(\"@ag-ui/client\").Tool[];\n getContextForAgent(agentId?: string): Context[];\n getAgent(id: string): AbstractAgent | undefined;\n /**\n * Re-apply the current core headers to a single agent, merged on top of the\n * headers the agent was constructed with. The single source of truth for\n * header application; the run handler uses it so a run never clobbers\n * per-agent headers (see #5635).\n */\n applyHeadersToAgent(agent: AbstractAgent): void;\n\n // References to delegate subsystems\n readonly suggestionEngine: {\n clearSuggestions(agentId: string): void;\n reloadSuggestions(agentId: string): void;\n };\n\n /**\n * Called before each follow-up agent run (after tool execution).\n * See CopilotKitCore.waitForPendingFrameworkUpdates for details.\n */\n waitForPendingFrameworkUpdates(): Promise<void>;\n}\n\n/**\n * Normalize a header map to the internal invariant: a `Record<string, string>`\n * with no `null`/`undefined` values. Entries whose value is `null`/`undefined`\n * are dropped (this is how a header is cleared). Shared by the constructor and\n * `setHeaders` so both write paths into `_headers` enforce the same invariant.\n */\nfunction normalizeHeaders(\n headers: Record<string, string | null | undefined>,\n): Record<string, string> {\n return Object.fromEntries(\n Object.entries(headers).filter(\n (entry): entry is [string, string] => entry[1] != null,\n ),\n );\n}\n\nexport class CopilotKitCore {\n private _headers: Record<string, string>;\n private _credentials?: RequestCredentials;\n private _properties: Record<string, unknown>;\n private _defaultThrottleMs?: number;\n private _debug?: DebugConfig;\n\n private subscribers: Set<CopilotKitCoreSubscriber> = new Set();\n\n // Delegate classes\n private agentRegistry: AgentRegistry;\n private contextStore: ContextStore;\n private suggestionEngine: SuggestionEngine;\n private runHandler: RunHandler;\n private stateManager: StateManager;\n private threadStoreRegistry: ThreadStoreRegistry;\n /**\n * The single core-owned memory store, created lazily on first\n * `getMemoryStore()` and kept user-scoped for the lifetime of the core.\n * Its runtime context is wired by the core itself (see `syncMemoryContext`),\n * so callers never register or look it up by `agentId`.\n */\n private _memoryStore?: ɵMemoryStore;\n /**\n * Tracks the agent IDs from the most recent `onAgentsChanged` notification.\n * Used to gate thread-store auto-unregister so the FIRST empty-agents\n * notification (before published agents are merged in) does not rip out a\n * store that was registered prior to that initial notification.\n */\n private previousAgentIds: Set<string> = new Set();\n\n constructor({\n runtimeUrl,\n runtimeTransport = \"auto\",\n deferInitialConnection = false,\n headers = {},\n credentials,\n properties = {},\n agents__unsafe_dev_only = {},\n tools = [],\n suggestionsConfig = [],\n debug,\n }: CopilotKitCoreConfig) {\n this._headers = normalizeHeaders(headers);\n this._credentials = credentials;\n this._properties = properties;\n this._debug = debug;\n\n // Initialize delegate classes\n this.agentRegistry = new AgentRegistry(this);\n this.contextStore = new ContextStore(this);\n this.suggestionEngine = new SuggestionEngine(this);\n this.runHandler = new RunHandler(this);\n this.stateManager = new StateManager(this);\n this.threadStoreRegistry = new ThreadStoreRegistry(this);\n\n // Initialize each subsystem\n this.agentRegistry.initialize(agents__unsafe_dev_only);\n this.runHandler.initialize(tools);\n this.suggestionEngine.initialize(suggestionsConfig);\n this.stateManager.initialize();\n\n this.agentRegistry.setRuntimeTransport(runtimeTransport);\n this.agentRegistry.setRuntimeUrl(runtimeUrl, {\n deferConnection: deferInitialConnection,\n });\n\n // Seed the previous-agents snapshot from the constructor-supplied agents.\n // `agentRegistry.initialize` does not emit `onAgentsChanged`, so the\n // subscriber below would otherwise see its first non-empty notification\n // as an \"addition\" relative to an empty baseline — and a later removal\n // of those same agents would NOT trigger the auto-unregister branch\n // because the guard would think the agentId was never previously\n // present. Seeding the set here keeps the guard honest.\n this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));\n\n // Subscribe to agent changes to track state for new agents\n this.subscribe({\n // Re-sync the memory store's runtime context whenever the runtime\n // connection status changes. The `/info` fetch sets the connection\n // status and `intelligence` together before firing this notification,\n // so this single hook covers both connection and intelligence changes.\n // Guarded so we never instantiate the store just to sync it.\n onRuntimeConnectionStatusChanged: () => {\n if (this._memoryStore) this.syncMemoryContext();\n },\n onAgentsChanged: ({ agents }) => {\n Object.values(agents).forEach((agent) => {\n if (agent.agentId) {\n this.stateManager.subscribeToAgent(agent);\n }\n });\n\n // Unregister thread stores for agents that have been removed.\n //\n // Critically, only unregister an agentId that was present in the\n // PREVIOUS agents snapshot AND is missing from the new one. Without\n // the \"previously had\" guard, the FIRST `onAgentsChanged({ agents: {} })`\n // delivered to a freshly-published core would tear out a thread store\n // that a consumer (e.g. useThreads) just registered — `core.agents`\n // is asynchronously populated and the empty-map notification fires\n // before the published agents are merged in.\n const currentAgentIds = new Set(Object.keys(agents));\n // Each iteration is wrapped so a throw on one id does not stall\n // cleanup for the rest of the set. Both registries' unregister\n // paths are idempotent, so re-attempts on the next\n // onAgentsChanged are safe.\n for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) {\n if (\n this.previousAgentIds.has(agentId) &&\n !currentAgentIds.has(agentId)\n ) {\n try {\n this.threadStoreRegistry.unregister(agentId);\n } catch (err) {\n console.error(\n `CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for \"${agentId}\":`,\n err,\n );\n }\n }\n }\n\n // Symmetric cleanup for state-manager subscriptions: any agentId\n // that disappeared from the registry (e.g. via `unregister()` from\n // a registerProxiedAgent caller) should release its StateManager\n // subscription. Without this, the subscription leaks — events from\n // a still-running observable on the removed agent would continue\n // to populate stateByRun/messageToRun for the dead id.\n for (const agentId of this.previousAgentIds) {\n if (!currentAgentIds.has(agentId)) {\n try {\n this.stateManager.unsubscribeFromAgent(agentId);\n } catch (err) {\n console.error(\n `CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for \"${agentId}\":`,\n err,\n );\n }\n }\n }\n\n this.previousAgentIds = currentAgentIds;\n },\n });\n }\n\n /**\n * Internal method used by delegate classes and subclasses to notify subscribers\n */\n protected async notifySubscribers(\n handler: (subscriber: CopilotKitCoreSubscriber) => void | Promise<void>,\n errorMessage: string,\n ): Promise<void> {\n await Promise.all(\n Array.from(this.subscribers).map(async (subscriber) => {\n try {\n await handler(subscriber);\n } catch (error) {\n console.error(errorMessage, error);\n }\n }),\n );\n }\n\n /**\n * Internal method used by delegate classes to emit errors\n */\n private async emitError({\n error,\n code,\n context = {},\n }: {\n error: Error;\n code: CopilotKitCoreErrorCode;\n context?: Record<string, any>;\n }): Promise<void> {\n await this.notifySubscribers(\n (subscriber) =>\n subscriber.onError?.({\n copilotkit: this,\n error,\n code,\n context,\n }),\n \"Subscriber onError error:\",\n );\n }\n\n /**\n * Log a message to the console and emit an error to subscribers.\n * Catches failures from `emitError` itself to prevent unhandled rejections.\n */\n private logAndEmitError(\n message: string,\n params: {\n error: Error;\n code: CopilotKitCoreErrorCode;\n context?: Record<string, any>;\n },\n logLevel: \"error\" | \"warn\" = \"error\",\n ): void {\n console[logLevel](message, params.error);\n this.emitError(params).catch((emitErr: unknown) => {\n console.error(message + \" — emitError itself failed:\", emitErr);\n });\n }\n\n /**\n * Snapshot accessors\n */\n get context(): Readonly<Record<string, ScopedContext>> {\n return this.contextStore.context;\n }\n\n get agents(): Readonly<Record<string, AbstractAgent>> {\n return this.agentRegistry.agents;\n }\n\n get tools(): Readonly<FrontendTool<any>[]> {\n return this.runHandler.tools;\n }\n\n get runtimeUrl(): string | undefined {\n return this.agentRegistry.runtimeUrl;\n }\n\n setRuntimeUrl(runtimeUrl: string | undefined): void {\n this.agentRegistry.setRuntimeUrl(runtimeUrl);\n }\n\n /**\n * Start the runtime `/info` connection if it has not been started yet.\n *\n * Intended to be driven from a host's commit-phase effect when the core was\n * constructed with {@link CopilotKitCoreConfig.deferInitialConnection}. Safe\n * to call repeatedly — it is a no-op once a connection is in progress or\n * settled, so a double-invoked mount effect (React StrictMode) collapses to a\n * single request. See #5801.\n */\n connect(): void {\n this.agentRegistry.connectRuntime();\n }\n\n get runtimeTransport(): CopilotRuntimeTransport {\n return this.agentRegistry.runtimeTransport;\n }\n\n setRuntimeTransport(runtimeTransport: CopilotRuntimeTransport): void {\n this.agentRegistry.setRuntimeTransport(runtimeTransport);\n }\n\n get runtimeVersion(): string | undefined {\n return this.agentRegistry.runtimeVersion;\n }\n\n get headers(): Readonly<Record<string, string>> {\n return this._headers;\n }\n\n get credentials(): RequestCredentials | undefined {\n return this._credentials;\n }\n\n get properties(): Readonly<Record<string, unknown>> {\n return this._properties;\n }\n\n /**\n * Default throttle interval (ms) used by `subscribeToAgentWithOptions()`\n * when the caller does not specify an explicit `throttleMs`.\n * `undefined` means no default is configured; `0` means no throttling.\n */\n get defaultThrottleMs(): number | undefined {\n return this._defaultThrottleMs;\n }\n\n /**\n * Set the default throttle interval (ms) for `subscribeToAgentWithOptions()`.\n *\n * Accepts a non-negative finite number or `undefined` (to clear the\n * default). Invalid values (NaN, Infinity, negative) are logged as\n * errors and ignored — the previous valid value is preserved.\n */\n setDefaultThrottleMs(value: number | undefined): void {\n if (value !== undefined && (!Number.isFinite(value) || value < 0)) {\n this.logAndEmitError(\n `CopilotKitCore.setDefaultThrottleMs: value must be a non-negative finite number or undefined, ` +\n `got ${value}. Keeping current value (${this._defaultThrottleMs}).`,\n {\n error: new Error(\n `setDefaultThrottleMs: invalid value (${value}), keeping current value (${this._defaultThrottleMs})`,\n ),\n code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,\n context: { value, currentValue: this._defaultThrottleMs },\n },\n );\n return;\n }\n this._defaultThrottleMs = value;\n }\n\n get debug(): DebugConfig | undefined {\n return this._debug;\n }\n\n setDebug(debug: DebugConfig | undefined): void {\n this._debug = debug;\n }\n\n get runtimeConnectionStatus(): CopilotKitCoreRuntimeConnectionStatus {\n return this.agentRegistry.runtimeConnectionStatus;\n }\n\n get audioFileTranscriptionEnabled(): boolean {\n return this.agentRegistry.audioFileTranscriptionEnabled;\n }\n\n get runtimeMode(): RuntimeMode {\n return this.agentRegistry.runtimeMode;\n }\n\n get intelligence(): IntelligenceRuntimeInfo | undefined {\n return this.agentRegistry.intelligence;\n }\n\n get threadEndpoints(): ThreadEndpointRuntimeInfo | undefined {\n return this.agentRegistry.threadEndpoints;\n }\n\n get suggestions(): boolean | undefined {\n return this.agentRegistry.suggestions;\n }\n\n get a2uiEnabled(): boolean {\n return this.agentRegistry.a2uiEnabled;\n }\n\n /**\n * Agent ids the runtime applies A2UI to. `undefined` means A2UI applies to\n * every agent (or is disabled — check `a2uiEnabled`).\n */\n get a2uiAgents(): string[] | undefined {\n return this.agentRegistry.a2uiAgents;\n }\n\n get openGenerativeUIEnabled(): boolean {\n return this.agentRegistry.openGenerativeUIEnabled;\n }\n\n get licenseStatus(): RuntimeLicenseStatus | undefined {\n return this.agentRegistry.licenseStatus;\n }\n\n get telemetryDisabled(): boolean {\n return this.agentRegistry.telemetryDisabled;\n }\n\n /**\n * Configuration updates\n */\n /**\n * Replace the headers sent with every runtime request.\n *\n * This is an overwrite, not a merge — the supplied object becomes the\n * complete header set. Entries whose value is `null` or `undefined` are\n * dropped, which is how you clear a header (e.g. removing `Authorization`\n * on logout) without leaving an empty-string value behind:\n *\n * ```ts\n * copilotkit.setHeaders({\n * ...copilotkit.headers,\n * Authorization: token ? `Bearer ${token}` : null,\n * });\n * ```\n *\n * The resulting header set is also re-applied to every agent in the registry\n * and `onHeadersChanged` subscribers are notified. These headers are merged\n * ON TOP of the headers each `HttpAgent` was constructed with, so per-agent\n * headers (e.g. an `Authorization` for a self-hosted backend) are preserved;\n * on a key conflict the core-level value wins.\n *\n * Because the agent's construction-time headers form the merge baseline, this\n * method can override a per-agent header but cannot REMOVE one: clearing a\n * core key here only drops the core-level override, after which the agent's\n * own value (if any) re-surfaces. To change a header an agent was constructed\n * with, set it at the provider/core level instead of on the agent, or update\n * it on the agent directly. The clear-on-logout pattern above is for\n * core-level headers.\n */\n setHeaders(headers: Record<string, string | null | undefined>): void {\n this._headers = normalizeHeaders(headers);\n if (this._memoryStore) this.syncMemoryContext();\n this.agentRegistry.applyHeadersToAgents(\n this.agentRegistry.agents as Record<string, AbstractAgent>,\n );\n void this.notifySubscribers(\n (subscriber) =>\n subscriber.onHeadersChanged?.({\n copilotkit: this,\n headers: this.headers,\n }),\n \"Subscriber onHeadersChanged error:\",\n );\n }\n\n setCredentials(credentials: RequestCredentials | undefined): void {\n this._credentials = credentials;\n this.agentRegistry.applyCredentialsToAgents(\n this.agentRegistry.agents as Record<string, AbstractAgent>,\n );\n }\n\n setProperties(properties: Record<string, unknown>): void {\n this._properties = properties;\n void this.notifySubscribers(\n (subscriber) =>\n subscriber.onPropertiesChanged?.({\n copilotkit: this,\n properties: this.properties,\n }),\n \"Subscriber onPropertiesChanged error:\",\n );\n }\n\n /**\n * Agent management (delegated to AgentRegistry)\n */\n setAgents__unsafe_dev_only(agents: Record<string, AbstractAgent>): void {\n this.agentRegistry.setAgents__unsafe_dev_only(agents);\n }\n\n addAgent__unsafe_dev_only(params: CopilotKitCoreAddAgentParams): void {\n this.agentRegistry.addAgent__unsafe_dev_only(params);\n }\n\n removeAgent__unsafe_dev_only(id: string): void {\n this.agentRegistry.removeAgent__unsafe_dev_only(id);\n }\n\n /**\n * Register a proxied agent against an existing runtime agent. The proxy is\n * exposed under `agentId` (local registry id) and routes outbound runtime\n * requests to `runtimeAgentId`. Throws if `agentId` is already taken.\n *\n * Returns the minted proxy and an `unregister` handle for cleanup.\n *\n * Use this to mount multiple frontend agents against a single runtime\n * agent (e.g. one per chat window) without implicit per-thread cloning.\n *\n * @example\n * const { agent, unregister } = copilotkit.registerProxiedAgent({\n * agentId: \"chat-1\",\n * runtimeAgentId: \"default\",\n * });\n * // ... <CopilotChat agentId=\"chat-1\" />\n * // on cleanup:\n * unregister();\n */\n registerProxiedAgent(\n params: CopilotKitCoreRegisterProxiedAgentParams,\n ): CopilotKitCoreRegisterProxiedAgentResult {\n return this.agentRegistry.registerProxiedAgent(params);\n }\n\n getAgent(id: string): AbstractAgent | undefined {\n return this.agentRegistry.getAgent(id);\n }\n\n /**\n * Re-apply the current headers to a single agent (delegated to\n * AgentRegistry). Core headers are merged on top of the agent's own\n * construction-time headers rather than replacing them, so headers\n * configured directly on an `HttpAgent` (e.g. an `Authorization` for a\n * self-hosted backend) survive header updates instead of being silently\n * dropped (see #5635). On a key conflict the core-level value wins.\n *\n * The merge baseline is the agent's headers as captured the first time the\n * agent is applied (at registration), so the way to change headers\n * afterwards is `setHeaders` (which re-applies to every agent), not mutating\n * `agent.headers` directly — a direct mutation is overwritten on the next\n * re-apply.\n */\n applyHeadersToAgent(agent: AbstractAgent): void {\n this.agentRegistry.applyHeadersToAgent(agent);\n }\n\n /**\n * Context management (delegated to ContextStore).\n * Pass `agentIds` to restrict the entry to runs of specific agents;\n * omit it for context every agent should receive.\n */\n addContext(context: ScopedContext): string {\n return this.contextStore.addContext(context);\n }\n\n removeContext(id: string): void {\n this.contextStore.removeContext(id);\n }\n\n /**\n * Build the context array for a run of the given agent, dropping entries\n * scoped to other agents and stripping the scoping metadata.\n */\n getContextForAgent(agentId?: string): Context[] {\n return this.contextStore.getContextForAgent(agentId);\n }\n\n /**\n * Thread store registry (delegated to ThreadStoreRegistry)\n */\n registerThreadStore(agentId: string, store: ɵThreadStore): void {\n this.threadStoreRegistry.register(agentId, store);\n }\n\n unregisterThreadStore(agentId: string): void {\n this.threadStoreRegistry.unregister(agentId);\n }\n\n getThreadStore(agentId: string): ɵThreadStore | undefined {\n return this.threadStoreRegistry.get(agentId);\n }\n\n getThreadStores(): Readonly<Record<string, ɵThreadStore>> {\n return this.threadStoreRegistry.getAll();\n }\n\n /**\n * Returns the single core-owned, user-scoped memory store, creating and\n * starting it on first access. Unlike thread stores, memory is not scoped per\n * agent: there is exactly one store whose runtime context the core wires\n * itself (see `syncMemoryContext`), so consumers (e.g. a `useMemories`\n * binding) just read this store rather than registering one.\n */\n getMemoryStore(): ɵMemoryStore {\n return this.ensureMemoryStore();\n }\n\n /**\n * Lazily creates, starts, and context-syncs the core-owned memory store on\n * first access, then returns it. Subsequent calls return the existing store.\n * The store is constructed with a bound `globalThis.fetch` and immediately\n * has its runtime context synced from the current connection state.\n */\n private ensureMemoryStore(): ɵMemoryStore {\n if (!this._memoryStore) {\n this._memoryStore = ɵcreateMemoryStore({\n fetch: globalThis.fetch.bind(globalThis),\n });\n this._memoryStore.start();\n this.syncMemoryContext();\n }\n return this._memoryStore;\n }\n\n /**\n * Pushes the current runtime wiring into the memory store. When the runtime\n * is connected and both the intelligence WebSocket URL and runtime URL are\n * available, the store receives a context (runtime URL, WebSocket URL, and a\n * copy of the current headers); otherwise its context is cleared. No-op when\n * the store has not been created yet.\n */\n private syncMemoryContext(): void {\n if (!this._memoryStore) return;\n if (\n this.runtimeConnectionStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Connected &&\n this.intelligence?.wsUrl &&\n this.runtimeUrl\n ) {\n this._memoryStore.setContext({\n runtimeUrl: this.runtimeUrl,\n wsUrl: this.intelligence.wsUrl,\n headers: { ...this.headers },\n });\n } else {\n this._memoryStore.setContext(null);\n }\n }\n\n /**\n * Suggestions management (delegated to SuggestionEngine)\n */\n addSuggestionsConfig(config: SuggestionsConfig): string {\n return this.suggestionEngine.addSuggestionsConfig(config);\n }\n\n removeSuggestionsConfig(id: string): void {\n this.suggestionEngine.removeSuggestionsConfig(id);\n }\n\n reloadSuggestions(agentId: string): void {\n this.suggestionEngine.reloadSuggestions(agentId);\n }\n\n clearSuggestions(agentId: string): void {\n this.suggestionEngine.clearSuggestions(agentId);\n }\n\n getSuggestions(agentId: string): CopilotKitCoreGetSuggestionsResult {\n return this.suggestionEngine.getSuggestions(agentId);\n }\n\n /**\n * Tool management (delegated to RunHandler)\n */\n addTool<T extends Record<string, unknown> = Record<string, unknown>>(\n tool: FrontendTool<T>,\n ): void {\n this.runHandler.addTool(tool);\n }\n\n removeTool(id: string, agentId?: string): void {\n this.runHandler.removeTool(id, agentId);\n }\n\n getTool(params: CopilotKitCoreGetToolParams): FrontendTool<any> | undefined {\n return this.runHandler.getTool(params);\n }\n\n setTools(tools: FrontendTool<any>[]): void {\n this.runHandler.setTools(tools);\n }\n\n /**\n * Subscription lifecycle\n */\n subscribe(subscriber: CopilotKitCoreSubscriber): CopilotKitCoreSubscription {\n this.subscribers.add(subscriber);\n\n // Return subscription with unsubscribe method\n return {\n unsubscribe: () => {\n this.subscribers.delete(subscriber);\n },\n };\n }\n\n /**\n * Subscribe to an agent's notification and lifecycle events with\n * optional configuration (e.g. throttling).\n *\n * Wraps every callback with error protection (`safeCall`) and applies\n * the options before delegating to `agent.subscribe()`.\n *\n * See {@link SubscribeToAgentSubscriber} for the accepted callback subset\n * and the rationale for excluding AG-UI event handlers.\n */\n subscribeToAgentWithOptions(\n agent: AbstractAgent,\n subscriber: SubscribeToAgentSubscriber,\n options?: SubscribeToAgentOptions,\n ): CopilotKitCoreSubscription {\n const resolved = options?.throttleMs ?? this._defaultThrottleMs ?? 0;\n\n let effectiveMs = 0;\n if (!Number.isFinite(resolved) || resolved < 0) {\n const source =\n options?.throttleMs !== undefined ? \"throttleMs\" : \"defaultThrottleMs\";\n this.logAndEmitError(\n `CopilotKitCore.subscribeToAgentWithOptions: ${source} must be a non-negative finite number, ` +\n `got ${resolved}. Falling back to unthrottled.`,\n {\n error: new Error(\n `subscribeToAgentWithOptions: invalid ${source} (${resolved}), falling back to unthrottled`,\n ),\n code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,\n context: { agentId: agent.agentId, source, value: resolved },\n },\n );\n } else {\n effectiveMs = resolved;\n }\n\n const agentLabel = agent.agentId || \"(unknown agent)\";\n\n // Wraps a callback so that synchronous throws and async rejections are\n // caught, logged, and emitted — preventing one failing callback from\n // corrupting the agent's notification loop.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const safeCall = <F extends (...args: any[]) => any>(\n label: string,\n fn: F,\n ...args: Parameters<F>\n ): any => {\n const reportError = (err: unknown, verb: string) => {\n this.logAndEmitError(\n `CopilotKitCore.subscribeToAgentWithOptions[${agentLabel}]: ${label} callback ${verb}:`,\n {\n error: err instanceof Error ? err : new Error(String(err)),\n code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,\n context: { agentId: agent.agentId, callback: label },\n },\n );\n };\n try {\n const result = fn(...args);\n if (result instanceof Promise) {\n return result.catch((err: unknown) => {\n reportError(err, \"rejected\");\n });\n }\n return result;\n } catch (err) {\n reportError(err, \"threw\");\n }\n };\n\n const guardAll = (\n sub: SubscribeToAgentSubscriber,\n ): SubscribeToAgentSubscriber => {\n const guarded: SubscribeToAgentSubscriber = {};\n if (sub.onMessagesChanged) {\n const fn = sub.onMessagesChanged;\n guarded.onMessagesChanged = (params) =>\n safeCall(\"onMessagesChanged\", fn, params);\n }\n if (sub.onStateChanged) {\n const fn = sub.onStateChanged;\n guarded.onStateChanged = (params) =>\n safeCall(\"onStateChanged\", fn, params);\n }\n if (sub.onRunInitialized) {\n const fn = sub.onRunInitialized;\n guarded.onRunInitialized = (params) =>\n safeCall(\"onRunInitialized\", fn, params);\n }\n if (sub.onRunFinalized) {\n const fn = sub.onRunFinalized;\n guarded.onRunFinalized = (params) =>\n safeCall(\"onRunFinalized\", fn, params);\n }\n if (sub.onRunFailed) {\n const fn = sub.onRunFailed;\n guarded.onRunFailed = (params) => safeCall(\"onRunFailed\", fn, params);\n }\n if (sub.onRunErrorEvent) {\n const fn = sub.onRunErrorEvent;\n guarded.onRunErrorEvent = (params) =>\n safeCall(\"onRunErrorEvent\", fn, params);\n }\n return guarded;\n };\n\n // Warn about unsupported keys so JS / `as any` consumers get diagnostics.\n for (const key of Object.keys(subscriber)) {\n if (\n typeof (subscriber as Record<string, unknown>)[key] === \"function\" &&\n !(ALLOWED_KEYS as ReadonlySet<string>).has(key)\n ) {\n const message =\n `CopilotKitCore.subscribeToAgentWithOptions[${agentLabel}]: callback \"${key}\" is not supported ` +\n `and was dropped. Supported callbacks: ${Array.from(ALLOWED_KEYS).join(\", \")}. ` +\n `Use agent.subscribe() directly for event handlers and per-item notifications.`;\n this.logAndEmitError(\n message,\n {\n error: new Error(message),\n code: CopilotKitCoreErrorCode.SUBSCRIBER_CALLBACK_FAILED,\n context: { agentId: agent.agentId, droppedCallback: key },\n },\n \"warn\",\n );\n }\n }\n\n // No throttle — guard callbacks and subscribe directly.\n if (effectiveMs <= 0) {\n const subscription = agent.subscribe(guardAll(subscriber));\n return { unsubscribe: () => subscription.unsubscribe() };\n }\n\n // Throttled path: lifecycle callbacks fire immediately; onMessagesChanged\n // and onStateChanged share a single Throttler that flushes the latest\n // params for both channels.\n let active = true;\n let latestMessagesParams:\n | Parameters<\n NonNullable<SubscribeToAgentSubscriber[\"onMessagesChanged\"]>\n >[0]\n | null = null;\n let latestStateParams:\n | Parameters<NonNullable<SubscribeToAgentSubscriber[\"onStateChanged\"]>>[0]\n | null = null;\n\n const flushPending = () => {\n if (active && subscriber.onMessagesChanged && latestMessagesParams) {\n const params = latestMessagesParams;\n latestMessagesParams = null;\n safeCall(\"onMessagesChanged\", subscriber.onMessagesChanged, params);\n }\n if (active && subscriber.onStateChanged && latestStateParams) {\n const params = latestStateParams;\n latestStateParams = null;\n safeCall(\"onStateChanged\", subscriber.onStateChanged, params);\n }\n };\n\n const throttler = new Throttler(flushPending, {\n wait: effectiveMs,\n leading: true,\n trailing: true,\n });\n\n // Lifecycle callbacks are guarded but never throttled.\n const lifecycleOnly: SubscribeToAgentSubscriber = {};\n if (subscriber.onRunInitialized)\n lifecycleOnly.onRunInitialized = subscriber.onRunInitialized;\n if (subscriber.onRunFinalized)\n lifecycleOnly.onRunFinalized = subscriber.onRunFinalized;\n if (subscriber.onRunFailed)\n lifecycleOnly.onRunFailed = subscriber.onRunFailed;\n if (subscriber.onRunErrorEvent)\n lifecycleOnly.onRunErrorEvent = subscriber.onRunErrorEvent;\n\n const wrappedSubscriber: SubscribeToAgentSubscriber =\n guardAll(lifecycleOnly);\n\n if (subscriber.onMessagesChanged) {\n wrappedSubscriber.onMessagesChanged = (params) => {\n latestMessagesParams = params;\n throttler.maybeExecute();\n };\n }\n\n if (subscriber.onStateChanged) {\n wrappedSubscriber.onStateChanged = (params) => {\n latestStateParams = params;\n throttler.maybeExecute();\n };\n }\n\n const subscription = agent.subscribe(wrappedSubscriber);\n\n return {\n unsubscribe: () => {\n active = false;\n throttler.cancel();\n subscription.unsubscribe();\n },\n };\n }\n\n /**\n * Agent connectivity (delegated to RunHandler)\n */\n async connectAgent(\n params: CopilotKitCoreConnectAgentParams,\n ): Promise<import(\"@ag-ui/client\").RunAgentResult> {\n return this.runHandler.connectAgent(params);\n }\n\n stopAgent(params: CopilotKitCoreStopAgentParams): void {\n this.runHandler.abortCurrentRun();\n params.agent.abortRun();\n }\n\n async runAgent(\n params: CopilotKitCoreRunAgentParams,\n ): Promise<import(\"@ag-ui/client\").RunAgentResult> {\n return this.runHandler.runAgent(params);\n }\n\n /**\n * Programmatically execute a registered frontend tool without going through an LLM turn.\n * The handler runs, render components show up in the UI, and both the tool call and\n * result messages are added to `agent.messages`.\n */\n async runTool(\n params: CopilotKitCoreRunToolParams,\n ): Promise<CopilotKitCoreRunToolResult> {\n return this.runHandler.runTool(params);\n }\n\n /**\n * State management (delegated to StateManager)\n */\n getStateByRun(\n agentId: string,\n threadId: string,\n runId: string,\n ): State | undefined {\n return this.stateManager.getStateByRun(agentId, threadId, runId);\n }\n\n getRunIdForMessage(\n agentId: string,\n threadId: string,\n messageId: string,\n ): string | undefined {\n return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);\n }\n\n getRunIdsForThread(agentId: string, threadId: string): string[] {\n return this.stateManager.getRunIdsForThread(agentId, threadId);\n }\n\n /**\n * Internal method used by RunHandler to build frontend tools\n */\n private buildFrontendTools(agentId?: string): import(\"@ag-ui/client\").Tool[] {\n return this.runHandler.buildFrontendTools(agentId);\n }\n\n /**\n * Called before each follow-up agent run (after tool execution).\n *\n * When a frontend tool handler calls framework state setters (e.g. React's\n * setState), those updates are batched and deferred — they do not take effect\n * until the framework's scheduler runs (React uses MessageChannel).\n * useAgentContext registers context via useLayoutEffect, which runs\n * synchronously after React commits that deferred batch.\n *\n * Without yielding here, the follow-up runAgent reads the context store\n * synchronously while the deferred updates are still pending, producing stale\n * context for the next agent turn.\n *\n * Override in framework-specific subclasses to yield to the framework\n * scheduler before the follow-up run. The base implementation is a no-op\n * because non-React environments have no deferred state to flush.\n */\n async waitForPendingFrameworkUpdates(): Promise<void> {}\n}\n","import type { AbstractAgent, ToolCall } from \"@ag-ui/client\";\nimport type {\n IntelligenceRuntimeInfo,\n RuntimeMode,\n RuntimeLicenseStatus,\n ThreadEndpointRuntimeInfo,\n} from \"@copilotkit/shared\";\nimport type { StandardSchemaV1 } from \"@copilotkit/shared\";\n\n/**\n * Status of a tool call execution\n */\nexport enum ToolCallStatus {\n InProgress = \"inProgress\",\n Executing = \"executing\",\n Complete = \"complete\",\n}\n\nexport type CopilotRuntimeTransport = \"rest\" | \"single\" | \"auto\";\nexport type {\n RuntimeMode,\n IntelligenceRuntimeInfo,\n RuntimeLicenseStatus,\n ThreadEndpointRuntimeInfo,\n};\n\n/**\n * Context passed to a frontend tool handler\n */\nexport type FrontendToolHandlerContext = {\n toolCall: ToolCall;\n agent: AbstractAgent;\n /** Aborted when `stopAgent()` is called. Handlers can check `signal.aborted`\n * or pass the signal to fetch/setTimeout to cooperatively cancel. */\n signal?: AbortSignal;\n};\n\nexport type FrontendTool<\n T extends Record<string, unknown> = Record<string, unknown>,\n> = {\n name: string;\n description?: string;\n parameters?: StandardSchemaV1<any, T>;\n handler?: (args: T, context: FrontendToolHandlerContext) => Promise<unknown>;\n followUp?: boolean;\n /**\n * Optional agent ID to constrain this tool to a specific agent.\n * If specified, this tool will only be available to the specified agent.\n */\n agentId?: string;\n /**\n * Whether this tool is available to the agent.\n * Set to false to hide the tool from the agent without unregistering it.\n * Defaults to true when not specified.\n */\n available?: boolean;\n};\n\nexport type Suggestion = {\n title: string;\n message: string;\n /** Indicates whether this suggestion is still being generated. */\n isLoading: boolean;\n /** Optional CSS class name applied to the suggestion pill. */\n className?: string;\n};\n\nexport type SuggestionAvailability =\n | \"before-first-message\"\n | \"after-first-message\"\n | \"always\"\n | \"disabled\";\n\nexport type DynamicSuggestionsConfig = {\n /**\n * A prompt or instructions for the GPT to generate suggestions.\n */\n instructions: string;\n /**\n * The minimum number of suggestions to generate. Defaults to `1`.\n * @default 1\n */\n minSuggestions?: number;\n /**\n * The maximum number of suggestions to generate. Defaults to `3`.\n * @default 1\n */\n maxSuggestions?: number;\n\n /**\n * When the suggestions are available. Defaults to \"after-first-message\".\n */\n available?: SuggestionAvailability;\n\n /**\n * The agent ID of the provider of the suggestions. Defaults to `\"default\"`.\n */\n providerAgentId?: string;\n\n /**\n * The agent ID of the consumer of the suggestions. Defaults to `\"*\"` (all agents).\n */\n consumerAgentId?: string;\n};\n\nexport type StaticSuggestionsConfig = {\n /**\n * The suggestions to display.\n */\n suggestions: Omit<Suggestion, \"isLoading\">[];\n\n /**\n * When the suggestions are available. Defaults to \"before-first-message\".\n */\n available?: SuggestionAvailability;\n\n /**\n * The agent ID of the consumer of the suggestions. Defaults to `\"*\"` (all agents).\n */\n consumerAgentId?: string;\n};\n\nexport type SuggestionsConfig =\n | DynamicSuggestionsConfig\n | StaticSuggestionsConfig;\n","export function completePartialMarkdown(input: string): string {\n let s = input;\n\n // Handle code fences first - use FIRST unmatched fence for proper nesting\n const fenceMatches = Array.from(s.matchAll(/^(\\s*)(`{3,}|~{3,})/gm));\n if (fenceMatches.length % 2 === 1) {\n const [, indent, fence] = fenceMatches[0]!;\n s += `\\n${indent}${fence}`;\n }\n\n // Identify incomplete links at the end and close them\n const incompleteLinkMatch = s.match(/\\[([^\\]]*)\\]\\(([^)]*)$/);\n if (incompleteLinkMatch) {\n s += \")\";\n }\n\n // State-based parsing\n interface OpenElement {\n type: string;\n marker: string;\n position: number;\n }\n\n const openElements: OpenElement[] = [];\n const chars = Array.from(s);\n\n // First pass: identify code block boundaries and inline code to avoid processing their content\n const codeBlockRanges: Array<{ start: number; end: number }> = [];\n const inlineCodeRanges: Array<{ start: number; end: number }> = [];\n\n // Find code block ranges\n let tempCodeFenceCount = 0;\n let currentCodeBlockStart = -1;\n\n for (let i = 0; i < chars.length; i++) {\n if (i === 0 || chars[i - 1] === \"\\n\") {\n const lineMatch = s.substring(i).match(/^(\\s*)(`{3,}|~{3,})/);\n if (lineMatch) {\n tempCodeFenceCount++;\n if (tempCodeFenceCount % 2 === 1) {\n currentCodeBlockStart = i;\n } else if (currentCodeBlockStart !== -1) {\n codeBlockRanges.push({\n start: currentCodeBlockStart,\n end: i + lineMatch[0].length,\n });\n currentCodeBlockStart = -1;\n }\n i += lineMatch[0].length - 1;\n }\n }\n }\n\n // Find inline code ranges\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] === \"`\") {\n // Check if escaped\n let backslashCount = 0;\n for (let j = i - 1; j >= 0 && chars[j] === \"\\\\\"; j--) {\n backslashCount++;\n }\n if (backslashCount % 2 === 0) {\n // Not escaped - find the closing backtick\n for (let j = i + 1; j < chars.length; j++) {\n if (chars[j] === \"`\") {\n let closingBackslashCount = 0;\n for (let k = j - 1; k >= 0 && chars[k] === \"\\\\\"; k--) {\n closingBackslashCount++;\n }\n if (closingBackslashCount % 2 === 0) {\n inlineCodeRanges.push({ start: i, end: j + 1 });\n i = j;\n break;\n }\n }\n }\n }\n }\n }\n\n // Helper function to check if position is in code\n const isInCode = (pos: number): boolean => {\n return (\n codeBlockRanges.some((range) => pos >= range.start && pos < range.end) ||\n inlineCodeRanges.some((range) => pos >= range.start && pos < range.end)\n );\n };\n\n // Second pass: process markdown elements, skipping code regions\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i];\n const nextChar = chars[i + 1];\n const prevChar = chars[i - 1];\n\n if (isInCode(i)) {\n continue;\n }\n\n // Handle brackets (but not if they're part of already-complete links)\n if (char === \"[\") {\n // Check if this is part of a complete link [text](url)\n let isCompleteLink = false;\n let bracketDepth = 1;\n let j = i + 1;\n\n // Find the matching ]\n while (j < chars.length && bracketDepth > 0) {\n if (chars[j] === \"[\" && !isInCode(j)) bracketDepth++;\n if (chars[j] === \"]\" && !isInCode(j)) bracketDepth--;\n j++;\n }\n\n // Check if followed by (\n if (bracketDepth === 0 && chars[j] === \"(\") {\n // Find the closing )\n let parenDepth = 1;\n j++;\n while (j < chars.length && parenDepth > 0) {\n if (chars[j] === \"(\" && !isInCode(j)) parenDepth++;\n if (chars[j] === \")\" && !isInCode(j)) parenDepth--;\n j++;\n }\n if (parenDepth === 0) {\n isCompleteLink = true;\n i = j - 1;\n continue;\n }\n }\n\n // This is a standalone bracket, treat as markdown\n if (!isCompleteLink) {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"bracket\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({ type: \"bracket\", marker: \"[\", position: i });\n }\n }\n }\n\n // Handle double emphasis first (**, __, ~~) - these take precedence\n else if (char === \"*\" && nextChar === \"*\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"bold_star\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({ type: \"bold_star\", marker: \"**\", position: i });\n }\n i++; // Skip next character\n } else if (char === \"_\" && nextChar === \"_\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"bold_underscore\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({\n type: \"bold_underscore\",\n marker: \"__\",\n position: i,\n });\n }\n i++; // Skip next character\n } else if (char === \"~\" && nextChar === \"~\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"strike\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({ type: \"strike\", marker: \"~~\", position: i });\n }\n i++; // Skip next character\n }\n\n // Handle single emphasis (*, _) - only if not part of double\n else if (char === \"*\" && prevChar !== \"*\" && nextChar !== \"*\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"italic_star\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({ type: \"italic_star\", marker: \"*\", position: i });\n }\n } else if (char === \"_\" && prevChar !== \"_\" && nextChar !== \"_\") {\n const existingIndex = openElements.findIndex(\n (el) => el.type === \"italic_underscore\",\n );\n if (existingIndex !== -1) {\n openElements.splice(existingIndex, 1);\n } else {\n openElements.push({\n type: \"italic_underscore\",\n marker: \"_\",\n position: i,\n });\n }\n }\n }\n\n // Handle remaining unmatched backticks (outside of inline code ranges)\n let backtickCount = 0;\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] === \"`\" && !isInCode(i)) {\n backtickCount++;\n }\n }\n if (backtickCount % 2 === 1) {\n s += \"`\";\n }\n\n // Close remaining open elements in reverse order (LIFO stack semantics)\n openElements.sort((a, b) => b.position - a.position);\n\n const closers = openElements.map((el) => {\n switch (el.type) {\n case \"bracket\":\n return \"]\";\n case \"bold_star\":\n return \"**\";\n case \"bold_underscore\":\n return \"__\";\n case \"strike\":\n return \"~~\";\n case \"italic_star\":\n return \"*\";\n case \"italic_underscore\":\n return \"_\";\n default:\n return \"\";\n }\n });\n\n let result = s + closers.join(\"\");\n\n // Handle parentheses ONLY if not inside code\n const finalFenceMatches = Array.from(\n result.matchAll(/^(\\s*)(`{3,}|~{3,})/gm),\n );\n const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;\n const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;\n\n let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;\n\n if (shouldCloseParens) {\n const lastOpenParen = result.lastIndexOf(\"(\");\n if (lastOpenParen !== -1) {\n // Check if this paren is inside a backtick pair\n const beforeParen = result.substring(0, lastOpenParen);\n const backticksBeforeParen = (beforeParen.match(/`/g) || []).length;\n if (backticksBeforeParen % 2 === 1) {\n shouldCloseParens = false;\n }\n }\n }\n\n if (shouldCloseParens) {\n const openParens = (result.match(/\\(/g) || []).length;\n const closeParens = (result.match(/\\)/g) || []).length;\n if (openParens > closeParens) {\n result += \")\".repeat(openParens - closeParens);\n }\n }\n\n return result;\n}\n","import { phoenixExponentialBackoff } from \"@copilotkit/shared\";\nimport type { Subscription } from \"rxjs\";\nimport { defer, firstValueFrom, merge, Observable, of } from \"rxjs\";\nimport {\n catchError,\n filter,\n map,\n mergeMap,\n share,\n shareReplay,\n switchMap,\n take,\n takeUntil,\n tap,\n timeout,\n withLatestFrom,\n} from \"rxjs/operators\";\nimport {\n createActionGroup,\n createEffect,\n createReducer,\n createSelector,\n createStore,\n empty,\n ofType,\n on,\n props,\n} from \"./utils/micro-redux\";\nimport type { Reducer, Store } from \"./utils/micro-redux\";\nimport {\n ɵphoenixChannel$,\n ɵphoenixSocket$,\n ɵobservePhoenixEvent$,\n ɵobservePhoenixJoinOutcome$,\n ɵobservePhoenixSocketHealth$,\n ɵobservePhoenixSocketSignals$,\n} from \"./utils/phoenix-observable\";\nimport type { ɵPhoenixChannelSession } from \"./utils/phoenix-observable\";\n\nconst THREADS_CHANNEL_EVENT = \"thread_metadata\";\nconst THREAD_RUN_ACTIVITY_CHANNEL_EVENT = \"thread_run_activity\";\nconst THREAD_SUBSCRIBE_PATH = \"/threads/subscribe\";\nconst MAX_SOCKET_RETRIES = 5;\nconst REQUEST_TIMEOUT_MS = 15_000;\n\ninterface ThreadRecord {\n id: string;\n organizationId: string;\n agentId: string;\n createdById: string;\n name: string | null;\n archived: boolean;\n createdAt: string;\n updatedAt: string;\n lastRunAt?: string;\n}\n\ninterface ThreadRuntimeContext {\n runtimeUrl: string;\n headers: Record<string, string>;\n wsUrl?: string;\n agentId: string;\n includeArchived?: boolean;\n limit?: number;\n}\n\ntype ThreadMetadataEvent =\n | {\n operation: \"created\" | \"renamed\" | \"archived\" | \"unarchived\" | \"updated\";\n threadId: string;\n userId: string;\n organizationId: string;\n occurredAt: string;\n thread: ThreadRecord;\n }\n | {\n operation: \"deleted\";\n threadId: string;\n userId: string;\n organizationId: string;\n occurredAt: string;\n deleted: {\n id: string;\n };\n };\n\n/**\n * Internal notification emitted when Intelligence observes new run activity\n * for a thread without changing that thread's metadata row.\n */\nexport type ThreadRunActivityNotification = {\n type: \"thread_run_activity\";\n threadId: string;\n agentId?: string;\n runId?: string;\n eventType: string;\n latestEventId?: string;\n};\n\ntype ThreadRunActivityGatewayPayload = {\n threadId?: unknown;\n thread_id?: unknown;\n agentId?: unknown;\n agent_id?: unknown;\n runId?: unknown;\n run_id?: unknown;\n eventType?: unknown;\n event_type?: unknown;\n latestEventId?: unknown;\n latest_event_id?: unknown;\n};\n\ninterface ThreadListResponse {\n threads: ThreadRecord[];\n joinCode?: string | null;\n nextCursor?: string | null;\n}\n\ninterface ThreadMetadataCredentialsResponse {\n joinToken: string;\n}\n\ninterface MutationRequest {\n requestId: string;\n /** Session the mutation was dispatched in; stale results are dropped. */\n sessionId: number;\n path: string;\n method: \"PATCH\" | \"POST\" | \"DELETE\";\n body: Record<string, unknown>;\n}\n\ntype MutationOutcome =\n | { requestId: string; sessionId: number; ok: true }\n | { requestId: string; sessionId: number; ok: false; error: Error };\n\ninterface ThreadEnvironment {\n fetch: typeof fetch;\n /**\n * Optional callback invoked whenever a thread mutation (rename, archive,\n * unarchive, delete) is rejected by the server. Lets framework wrappers\n * surface a transient error toast without subscribing to the error\n * selector. The error is also recorded in `state.error` regardless.\n *\n * Fired after any rollback (delete) has been applied to local state.\n */\n onError?: (error: Error) => void;\n}\n\ninterface ThreadState {\n threads: ThreadRecord[];\n isLoading: boolean;\n isFetchingNextPage: boolean;\n error: Error | null;\n /**\n * Error from the most recent failed next-page (`fetchMore`) load, or `null`.\n * Tracked SEPARATELY from `error` so a paginated-load failure surfaces an\n * inline \"couldn't load more\" affordance without replacing the already-loaded\n * list with a full-panel error. Cleared when a fetch-more is retried or when\n * one succeeds; reset on context change / stop.\n */\n fetchMoreError: Error | null;\n context: ThreadRuntimeContext | null;\n sessionId: number;\n metadataCredentialsRequested: boolean;\n metadataJoinCode: string | null;\n nextCursor: string | null;\n /** Number of thread mutations currently awaiting a server response. */\n inFlightMutationCount: number;\n /**\n * Rows optimistically removed by an in-flight `delete`, keyed by the\n * originating request id. DELETE is the one mutation that rolls back on\n * rejection, so the removed row is parked here and restored if the server\n * rejects. Rename/archive/unarchive are optimistic no-rollback and do not\n * populate this map.\n */\n pendingDeletes: Record<string, ThreadRecord>;\n}\n\nconst initialThreadState: ThreadState = {\n threads: [],\n isLoading: false,\n isFetchingNextPage: false,\n error: null,\n fetchMoreError: null,\n context: null,\n sessionId: 0,\n metadataCredentialsRequested: false,\n metadataJoinCode: null,\n nextCursor: null,\n inFlightMutationCount: 0,\n pendingDeletes: {},\n};\n\nconst threadAdapterEvents = createActionGroup(\"Thread Adapter\", {\n started: empty(),\n stopped: empty(),\n contextChanged: props<{ context: ThreadRuntimeContext | null }>(),\n fetchNextPageRequested: empty(),\n renameRequested: props<{\n requestId: string;\n threadId: string;\n name: string;\n }>(),\n archiveRequested: props<{ requestId: string; threadId: string }>(),\n unarchiveRequested: props<{ requestId: string; threadId: string }>(),\n deleteRequested: props<{ requestId: string; threadId: string }>(),\n newThreadStarted: empty(),\n});\n\nconst threadRestEvents = createActionGroup(\"Thread REST\", {\n listRequested: props<{ sessionId: number }>(),\n listSucceeded: props<{\n sessionId: number;\n threads: ThreadRecord[];\n joinCode: string | null;\n nextCursor: string | null;\n }>(),\n listFailed: props<{ sessionId: number; error: Error }>(),\n nextPageSucceeded: props<{\n sessionId: number;\n threads: ThreadRecord[];\n nextCursor: string | null;\n }>(),\n nextPageFailed: props<{ sessionId: number; error: Error }>(),\n metadataCredentialsRequested: props<{ sessionId: number }>(),\n metadataCredentialsSucceeded: props<{\n sessionId: number;\n joinToken: string;\n }>(),\n metadataCredentialsFailed: props<{ sessionId: number; error: Error }>(),\n mutationFinished: props<{ outcome: MutationOutcome }>(),\n});\n\nconst threadSocketEvents = createActionGroup(\"Thread Socket\", {\n opened: props<{ sessionId: number }>(),\n errored: props<{ sessionId: number }>(),\n joinFailed: props<{ sessionId: number }>(),\n joinTimedOut: props<{ sessionId: number }>(),\n metadataReceived: props<{\n sessionId: number;\n payload: ThreadMetadataEvent;\n }>(),\n runActivityReceived: props<{\n sessionId: number;\n notification: ThreadRunActivityNotification;\n }>(),\n});\n\nconst threadDomainEvents = createActionGroup(\"Thread Domain\", {\n threadUpserted: props<{ sessionId: number; thread: ThreadRecord }>(),\n threadDeleted: props<{ sessionId: number; threadId: string }>(),\n});\n\nfunction sortThreadsByRecency(threads: ThreadRecord[]): ThreadRecord[] {\n // Prefer lastRunAt so the order reflects actual agent activity and stays\n // stable when a user performs metadata-only actions like archive or rename.\n // Fall back to updatedAt (and then createdAt) for threads that have never run.\n return [...threads].sort((left, right) => {\n const leftKey = left.lastRunAt ?? left.updatedAt ?? left.createdAt;\n const rightKey = right.lastRunAt ?? right.updatedAt ?? right.createdAt;\n return rightKey.localeCompare(leftKey);\n });\n}\n\nfunction upsertThread(\n threads: ThreadRecord[],\n thread: ThreadRecord,\n): ThreadRecord[] {\n const existingIndex = threads.findIndex((item) => item.id === thread.id);\n if (existingIndex === -1) {\n return sortThreadsByRecency([...threads, thread]);\n }\n\n const next = [...threads];\n next[existingIndex] = thread;\n return sortThreadsByRecency(next);\n}\n\n/**\n * Returns a non-empty string payload field or undefined for absent fields.\n */\nfunction optionalString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/**\n * Converts gateway run-activity payloads into the internal TypeScript shape.\n */\nfunction normalizeThreadRunActivityNotification(\n payload: ThreadRunActivityGatewayPayload,\n): ThreadRunActivityNotification | null {\n const threadId = optionalString(payload.threadId ?? payload.thread_id);\n const eventType = optionalString(payload.eventType ?? payload.event_type);\n\n if (!threadId || !eventType) {\n return null;\n }\n\n return {\n type: \"thread_run_activity\",\n threadId,\n agentId: optionalString(payload.agentId ?? payload.agent_id),\n runId: optionalString(payload.runId ?? payload.run_id),\n eventType,\n latestEventId: optionalString(\n payload.latestEventId ?? payload.latest_event_id,\n ),\n };\n}\n\nconst threadReducer = createReducer(\n initialThreadState,\n on(threadAdapterEvents.contextChanged, (state: ThreadState, { context }) => ({\n ...state,\n context,\n sessionId: state.sessionId + 1,\n threads: [],\n isLoading: Boolean(context),\n isFetchingNextPage: false,\n error: null,\n fetchMoreError: null,\n metadataCredentialsRequested: false,\n metadataJoinCode: null,\n nextCursor: null,\n inFlightMutationCount: 0,\n pendingDeletes: {},\n })),\n on(threadAdapterEvents.stopped, (state: ThreadState) => ({\n ...state,\n threads: [],\n isLoading: false,\n isFetchingNextPage: false,\n error: null,\n fetchMoreError: null,\n metadataCredentialsRequested: false,\n metadataJoinCode: null,\n nextCursor: null,\n inFlightMutationCount: 0,\n pendingDeletes: {},\n })),\n on(threadRestEvents.listRequested, (state: ThreadState, { sessionId }) => {\n if (sessionId !== state.sessionId || !state.context) {\n return state;\n }\n\n return {\n ...state,\n isLoading: true,\n error: null,\n // A full-list refetch supersedes any prior fetch-more failure: the whole\n // list is being reloaded, so the stale inline \"couldn't load more\" banner\n // must not survive onto the fresh list.\n fetchMoreError: null,\n };\n }),\n on(\n threadRestEvents.listSucceeded,\n (state: ThreadState, { sessionId, threads, joinCode, nextCursor }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n const joinCodeChanged = joinCode !== state.metadataJoinCode;\n\n return {\n ...state,\n threads: sortThreadsByRecency(threads),\n isLoading: false,\n error: null,\n // The fresh full list also clears any lingering fetch-more error, in\n // case the list arrived without passing through `listRequested`.\n fetchMoreError: null,\n metadataJoinCode: joinCode,\n metadataCredentialsRequested: joinCodeChanged\n ? false\n : state.metadataCredentialsRequested,\n nextCursor,\n };\n },\n ),\n on(\n threadRestEvents.listFailed,\n (state: ThreadState, { sessionId, error }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n isLoading: false,\n error,\n };\n },\n ),\n on(\n threadRestEvents.nextPageSucceeded,\n (state: ThreadState, { sessionId, threads, nextCursor }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n let merged = state.threads;\n for (const thread of threads) {\n merged = upsertThread(merged, thread);\n }\n\n return {\n ...state,\n threads: merged,\n isFetchingNextPage: false,\n // A successful next page clears any prior fetch-more error.\n fetchMoreError: null,\n nextCursor,\n };\n },\n ),\n on(\n threadRestEvents.nextPageFailed,\n (state: ThreadState, { sessionId, error }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n // A failed next-page load records the error on the DEDICATED fetch-more\n // channel — NOT `state.error` — so the already-loaded list is preserved\n // and the drawer renders an inline \"couldn't load more — retry\" panel\n // rather than replacing the whole list with a full-panel error.\n return {\n ...state,\n isFetchingNextPage: false,\n fetchMoreError: error,\n };\n },\n ),\n on(\n threadRestEvents.metadataCredentialsFailed,\n (state: ThreadState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n // Non-fatal: the metadata-credentials (realtime join-token) fetch runs\n // AFTER the thread list has already loaded and only powers the realtime\n // channel. A failure means realtime won't connect, but the fetched list\n // is still valid — so we do NOT write `state.error` (which would replace\n // the whole list with a \"couldn't load\" panel). The failure is surfaced\n // as a diagnostic warning instead (socketDiagnosticsEffect), mirroring the\n // stay-stale handling of a realtime channel join failure. Clear the\n // request latch so a later list refresh can retry realtime setup.\n return {\n ...state,\n metadataCredentialsRequested: false,\n };\n },\n ),\n on(\n threadRestEvents.metadataCredentialsRequested,\n (state: ThreadState, { sessionId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n metadataCredentialsRequested: true,\n };\n },\n ),\n on(threadAdapterEvents.fetchNextPageRequested, (state: ThreadState) => {\n if (!state.nextCursor || state.isFetchingNextPage) {\n return state;\n }\n\n return {\n ...state,\n isFetchingNextPage: true,\n // Clear any prior fetch-more error so a retry dismisses the inline panel\n // immediately while the next-page request is in flight.\n fetchMoreError: null,\n };\n }),\n on(\n threadAdapterEvents.renameRequested,\n (state: ThreadState, { threadId, name }) => {\n // Optimistic, no-rollback: reflect the new name immediately. A failure\n // surfaces via `error`/`onError` but the local row is left as-is; a\n // realtime metadata event or refetch reconciles the true server state.\n const existing = state.threads.find((thread) => thread.id === threadId);\n const inFlightMutationCount = state.inFlightMutationCount + 1;\n if (!existing) {\n return { ...state, inFlightMutationCount };\n }\n\n return {\n ...state,\n threads: upsertThread(state.threads, { ...existing, name }),\n inFlightMutationCount,\n };\n },\n ),\n on(\n threadAdapterEvents.archiveRequested,\n (state: ThreadState, { threadId }) => {\n // Optimistic, no-rollback. When archived threads are hidden, drop the\n // row; otherwise flip the flag in place. Note: archiving the active\n // thread is non-destructive — the wrapper keeps viewing it.\n const existing = state.threads.find((thread) => thread.id === threadId);\n const inFlightMutationCount = state.inFlightMutationCount + 1;\n if (!existing) {\n return { ...state, inFlightMutationCount };\n }\n\n if (!state.context?.includeArchived) {\n return {\n ...state,\n threads: state.threads.filter((thread) => thread.id !== threadId),\n inFlightMutationCount,\n };\n }\n\n return {\n ...state,\n threads: upsertThread(state.threads, { ...existing, archived: true }),\n inFlightMutationCount,\n };\n },\n ),\n on(\n threadAdapterEvents.unarchiveRequested,\n (state: ThreadState, { threadId }) => {\n // Optimistic, no-rollback.\n const existing = state.threads.find((thread) => thread.id === threadId);\n const inFlightMutationCount = state.inFlightMutationCount + 1;\n if (!existing) {\n return { ...state, inFlightMutationCount };\n }\n\n return {\n ...state,\n threads: upsertThread(state.threads, { ...existing, archived: false }),\n inFlightMutationCount,\n };\n },\n ),\n on(\n threadAdapterEvents.deleteRequested,\n (state: ThreadState, { requestId, threadId }) => {\n // Optimistic WITH rollback: remove the row now, but park it under the\n // request id so it can be restored if the server rejects the delete.\n const existing = state.threads.find((thread) => thread.id === threadId);\n const inFlightMutationCount = state.inFlightMutationCount + 1;\n if (!existing) {\n return { ...state, inFlightMutationCount };\n }\n\n return {\n ...state,\n threads: state.threads.filter((thread) => thread.id !== threadId),\n pendingDeletes: { ...state.pendingDeletes, [requestId]: existing },\n inFlightMutationCount,\n };\n },\n ),\n on(threadAdapterEvents.newThreadStarted, (state: ThreadState) => ({\n // Lazy creation: a fresh client-side thread does NOT add a phantom row —\n // it only materializes once its first run persists server-side. The\n // store-side concern is purely to clear any stale error so the welcome\n // screen renders cleanly; the wrapper owns the active/explicit threadId.\n ...state,\n error: null,\n })),\n on(threadRestEvents.mutationFinished, (state: ThreadState, { outcome }) => {\n // Drop results from a superseded session. `contextChanged`/`stopped` already\n // reset `threads`, `pendingDeletes`, and `inFlightMutationCount`, so a\n // mutation that resolves after the context switched must not write an error,\n // fire onError (guarded in subscribeErrors), or roll a stale row back into\n // the new list. Mirrors every other session-scoped handler.\n if (outcome.sessionId !== state.sessionId) {\n return state;\n }\n\n const inFlightMutationCount = Math.max(0, state.inFlightMutationCount - 1);\n\n if (outcome.ok) {\n // Success: drop any parked delete-rollback snapshot for this request.\n if (state.pendingDeletes[outcome.requestId] === undefined) {\n return { ...state, inFlightMutationCount };\n }\n\n const { [outcome.requestId]: _settled, ...rest } = state.pendingDeletes;\n return { ...state, inFlightMutationCount, pendingDeletes: rest };\n }\n\n // Failure: surface the error. For a rejected delete, restore the row that\n // was optimistically removed (rollback). Other mutations are no-rollback.\n const rolledBack = state.pendingDeletes[outcome.requestId];\n if (rolledBack === undefined) {\n return { ...state, inFlightMutationCount, error: outcome.error };\n }\n\n const { [outcome.requestId]: _restored, ...rest } = state.pendingDeletes;\n return {\n ...state,\n threads: upsertThread(state.threads, rolledBack),\n pendingDeletes: rest,\n inFlightMutationCount,\n error: outcome.error,\n };\n }),\n on(\n threadDomainEvents.threadUpserted,\n (state: ThreadState, { sessionId, thread }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n threads: upsertThread(state.threads, thread),\n };\n },\n ),\n on(\n threadDomainEvents.threadDeleted,\n (state: ThreadState, { sessionId, threadId }) => {\n if (sessionId !== state.sessionId) {\n return state;\n }\n\n return {\n ...state,\n threads: state.threads.filter((thread) => thread.id !== threadId),\n };\n },\n ),\n) as Reducer<ThreadState>;\n\n/**\n * The set of memoized thread selectors bound to a single store instance.\n *\n * @see createThreadSelectors\n */\ninterface ThreadSelectors {\n threads: (state: ThreadState) => ThreadRecord[];\n isLoading: (state: ThreadState) => boolean;\n error: (state: ThreadState) => Error | null;\n fetchMoreError: (state: ThreadState) => Error | null;\n hasNextPage: (state: ThreadState) => boolean;\n isFetchingNextPage: (state: ThreadState) => boolean;\n isMutating: (state: ThreadState) => boolean;\n}\n\n/**\n * Builds a fresh set of memoized thread selectors.\n *\n * Each `createSelector` closure owns a private one-entry cache. Sharing a\n * single module-level selector instance across multiple concurrent stores\n * (e.g. a `<CopilotThreadsDrawer>` plus an independent `useThreads`) makes every\n * cross-store emission a cache miss, defeating memoization and risking\n * emission instability for any future selector that allocates a new\n * object/array. Creating a per-store instance keeps each store's cache\n * isolated so concurrent stores never thrash one another.\n */\nfunction createThreadSelectors(): ThreadSelectors {\n return {\n threads: createSelector((state: ThreadState) => state.threads),\n isLoading: createSelector((state: ThreadState) => state.isLoading),\n error: createSelector((state: ThreadState) => state.error),\n fetchMoreError: createSelector(\n (state: ThreadState) => state.fetchMoreError,\n ),\n hasNextPage: createSelector(\n (state: ThreadState) => state.nextCursor != null,\n ),\n isFetchingNextPage: createSelector(\n (state: ThreadState) => state.isFetchingNextPage,\n ),\n isMutating: createSelector(\n (state: ThreadState) => state.inFlightMutationCount > 0,\n ),\n };\n}\n\n// Standalone selector instances retained for callers that read a one-off\n// snapshot (e.g. `selectThreads(store.getState())`) where cross-store memo\n// isolation is irrelevant. Subscriptions through `store.select(...)` should\n// prefer the per-store `ThreadStore.selectors` bundle below.\nconst standaloneSelectors = createThreadSelectors();\nconst selectThreads = standaloneSelectors.threads;\nconst selectThreadsIsLoading = standaloneSelectors.isLoading;\nconst selectThreadsError = standaloneSelectors.error;\nconst selectFetchMoreError = standaloneSelectors.fetchMoreError;\nconst selectHasNextPage = standaloneSelectors.hasNextPage;\nconst selectIsFetchingNextPage = standaloneSelectors.isFetchingNextPage;\nconst selectIsMutating = standaloneSelectors.isMutating;\n\ninterface ThreadStore {\n start(): void;\n stop(): void;\n setContext(context: ThreadRuntimeContext | null): void;\n /** Re-fetches the thread list without resetting the current list to empty. */\n refresh(): void;\n /**\n * Re-fetches the thread list without resetting the current list to empty.\n *\n * Public, design-named alias of {@link refresh} used by the drawer's\n * error-state Retry affordance and the Active/All filter-change refetch.\n */\n refetchThreads(): void;\n /**\n * Resets to a fresh, client-side thread so the welcome screen can show.\n *\n * Lazy creation: no phantom row is added to the list — the new thread only\n * materializes once its first run persists server-side. This is distinct\n * from selecting an existing thread (which the wrapper marks *explicit*,\n * suppressing the welcome screen): the thread produced here is NOT explicit.\n */\n startNewThread(): void;\n fetchNextPage(): void;\n renameThread(threadId: string, name: string): Promise<void>;\n archiveThread(threadId: string): Promise<void>;\n unarchiveThread(threadId: string): Promise<void>;\n deleteThread(threadId: string): Promise<void>;\n /**\n * Subscribes to synthetic run-activity notifications without changing the\n * thread metadata list.\n */\n subscribeToRunActivity?(\n callback: (notification: ThreadRunActivityNotification) => void,\n ): Subscription;\n getState(): ThreadState;\n /**\n * Returns a stable initial snapshot for server-side rendering.\n *\n * `useSyncExternalStore` requires a `getServerSnapshot` during SSR/prerender\n * (e.g. Next.js); without one React throws \"Missing getServerSnapshot\". The\n * returned reference is stable across calls so React does not loop. There is\n * no client-side thread data during prerender, so this is the empty initial\n * state.\n */\n getServerState(): ThreadState;\n select: Store<ThreadState>[\"select\"];\n /**\n * Memoized selectors bound to THIS store instance.\n *\n * Subscriptions should pass these to {@link select} (e.g.\n * `store.select(store.selectors.threads)`) so each store keeps its own\n * one-entry memo cache. Sharing the module-level singletons across\n * concurrent stores defeats memoization and risks emission instability.\n */\n selectors: ThreadSelectors;\n}\n\nlet threadRequestId = 0;\n\nfunction createThreadRequestId(): string {\n threadRequestId += 1;\n return `thread-request-${threadRequestId}`;\n}\n\nfunction threadFromFetch<T>(\n input: string,\n init: RequestInit & {\n selector: (response: Response) => Promise<T>;\n fetch: typeof fetch;\n },\n): Observable<T> {\n return new Observable<T>((subscriber) => {\n const { fetch: fetchImpl, selector, signal, ...requestInit } = init;\n const controller = new AbortController();\n const abortRequest = () => controller.abort();\n\n if (signal?.aborted) {\n abortRequest();\n } else {\n signal?.addEventListener(\"abort\", abortRequest, { once: true });\n }\n\n fetchImpl(input, { ...requestInit, signal: controller.signal })\n .then((response) => selector(response))\n .then((value) => {\n if (subscriber.closed) return;\n subscriber.next(value);\n subscriber.complete();\n })\n .catch((error) => {\n if (!subscriber.closed) {\n subscriber.error(error);\n }\n });\n\n return () => {\n signal?.removeEventListener(\"abort\", abortRequest);\n abortRequest();\n };\n });\n}\n\nfunction createThreadFetchObservable(\n environment: ThreadEnvironment,\n context: ThreadRuntimeContext,\n sessionId: number,\n): Observable<\n | ReturnType<typeof threadRestEvents.listSucceeded>\n | ReturnType<typeof threadRestEvents.listFailed>\n> {\n return defer(() => {\n const params: Record<string, string> = {\n agentId: context.agentId,\n };\n if (context.includeArchived) params.includeArchived = \"true\";\n if (context.limit != null) params.limit = String(context.limit);\n\n const qs = new URLSearchParams(params);\n return threadFromFetch(`${context.runtimeUrl}/threads?${qs.toString()}`, {\n selector: (response) => {\n if (!response.ok) {\n throw new Error(`Failed to fetch threads: ${response.status}`);\n }\n\n return response.json() as Promise<ThreadListResponse>;\n },\n fetch: environment.fetch,\n method: \"GET\",\n headers: { ...context.headers },\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new Error(\"Request timed out\");\n },\n }),\n map((data) =>\n threadRestEvents.listSucceeded({\n sessionId,\n threads: data.threads,\n joinCode:\n typeof data.joinCode === \"string\" && data.joinCode.length > 0\n ? data.joinCode\n : null,\n nextCursor: data.nextCursor ?? null,\n }),\n ),\n catchError((error) => {\n return of(\n threadRestEvents.listFailed({\n sessionId,\n error: error instanceof Error ? error : new Error(String(error)),\n }),\n );\n }),\n );\n });\n}\n\nfunction createThreadMetadataCredentialsObservable(\n environment: ThreadEnvironment,\n context: ThreadRuntimeContext,\n sessionId: number,\n): Observable<\n | ReturnType<typeof threadRestEvents.metadataCredentialsSucceeded>\n | ReturnType<typeof threadRestEvents.metadataCredentialsFailed>\n> {\n return defer(() => {\n return threadFromFetch(`${context.runtimeUrl}${THREAD_SUBSCRIBE_PATH}`, {\n selector: async (response) => {\n if (!response.ok) {\n throw new Error(\n `Failed to fetch thread metadata credentials: ${response.status}`,\n );\n }\n\n return response.json() as Promise<ThreadMetadataCredentialsResponse>;\n },\n fetch: environment.fetch,\n method: \"POST\",\n headers: {\n ...context.headers,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({}),\n }).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new Error(\"Request timed out\");\n },\n }),\n map((data) => {\n if (typeof data.joinToken !== \"string\" || data.joinToken.length === 0) {\n throw new Error(\"missing joinToken\");\n }\n\n return threadRestEvents.metadataCredentialsSucceeded({\n sessionId,\n joinToken: data.joinToken,\n });\n }),\n catchError((error) => {\n return of(\n threadRestEvents.metadataCredentialsFailed({\n sessionId,\n error: error instanceof Error ? error : new Error(String(error)),\n }),\n );\n }),\n );\n });\n}\n\nfunction createThreadMutationObservable(\n environment: ThreadEnvironment,\n context: ThreadRuntimeContext,\n request: MutationRequest,\n): Observable<ReturnType<typeof threadRestEvents.mutationFinished>> {\n return defer(() => {\n return threadFromFetch(`${context.runtimeUrl}${request.path}`, {\n selector: async (response) => {\n if (!response.ok) {\n throw new Error(`Request failed: ${response.status}`);\n }\n\n return null;\n },\n fetch: environment.fetch,\n method: request.method,\n headers: {\n ...context.headers,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request.body),\n }).pipe(\n map(() =>\n threadRestEvents.mutationFinished({\n outcome: {\n requestId: request.requestId,\n sessionId: request.sessionId,\n ok: true,\n },\n }),\n ),\n catchError((error) => {\n return of(\n threadRestEvents.mutationFinished({\n outcome: {\n requestId: request.requestId,\n sessionId: request.sessionId,\n ok: false,\n error: error instanceof Error ? error : new Error(String(error)),\n },\n }),\n );\n }),\n );\n });\n}\n\nfunction createThreadStore(environment: ThreadEnvironment): ThreadStore {\n // Per-store selector instances keep this store's memo cache isolated from\n // any other concurrent store (see createThreadSelectors).\n const selectors = createThreadSelectors();\n\n const bootstrapEffect = createEffect(\n (\n actions$,\n state$: Observable<ThreadState>,\n ): Observable<ReturnType<typeof threadRestEvents.listRequested>> =>\n actions$.pipe(\n ofType(threadAdapterEvents.contextChanged),\n withLatestFrom(state$),\n filter(([, state]) => Boolean(state.context)),\n map(([, state]) =>\n threadRestEvents.listRequested({ sessionId: state.sessionId }),\n ),\n ),\n );\n\n const fetchEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadRestEvents.listRequested),\n switchMap((action) =>\n state$.pipe(\n map((state) => state.context),\n filter((context): context is ThreadRuntimeContext =>\n Boolean(context),\n ),\n take(1),\n map((context) => ({ action, context })),\n takeUntil(\n actions$.pipe(\n ofType(\n threadAdapterEvents.contextChanged,\n threadAdapterEvents.stopped,\n ),\n ),\n ),\n switchMap(({ action: currentAction, context }) =>\n createThreadFetchObservable(\n environment,\n context,\n currentAction.sessionId,\n ),\n ),\n ),\n ),\n ),\n );\n\n const metadataCredentialsEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadRestEvents.listSucceeded),\n withLatestFrom(state$),\n filter(([action, state]) => {\n return (\n action.sessionId === state.sessionId &&\n !state.metadataCredentialsRequested &&\n Boolean(state.context?.wsUrl) &&\n Boolean(state.metadataJoinCode)\n );\n }),\n map(([action]) =>\n threadRestEvents.metadataCredentialsRequested({\n sessionId: action.sessionId,\n }),\n ),\n ),\n );\n\n const metadataCredentialsFetchEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadRestEvents.metadataCredentialsRequested),\n switchMap((action) =>\n state$.pipe(\n map((state) => state.context),\n filter((context): context is ThreadRuntimeContext =>\n Boolean(context),\n ),\n take(1),\n map((context) => ({ action, context })),\n takeUntil(\n actions$.pipe(\n ofType(\n threadAdapterEvents.contextChanged,\n threadAdapterEvents.stopped,\n ),\n ),\n ),\n switchMap(({ action: currentAction, context }) =>\n createThreadMetadataCredentialsObservable(\n environment,\n context,\n currentAction.sessionId,\n ),\n ),\n ),\n ),\n ),\n );\n\n const socketEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadRestEvents.metadataCredentialsSucceeded),\n withLatestFrom(state$),\n filter(([action, state]) => {\n return (\n action.sessionId === state.sessionId &&\n Boolean(state.context?.wsUrl)\n );\n }),\n switchMap(([action, state]) => {\n const context = state.context as ThreadRuntimeContext;\n const joinToken = action.joinToken as string;\n const joinCode = state.metadataJoinCode as string;\n const shutdown$ = actions$.pipe(\n ofType(\n threadAdapterEvents.contextChanged,\n threadAdapterEvents.stopped,\n ),\n );\n\n return defer(() => {\n const socket$ = ɵphoenixSocket$({\n url: context.wsUrl!,\n options: {\n params: { join_token: joinToken },\n reconnectAfterMs: phoenixExponentialBackoff(100, 10_000),\n rejoinAfterMs: phoenixExponentialBackoff(1_000, 30_000),\n },\n }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const channel$ = ɵphoenixChannel$({\n socket$,\n topic: `user_meta:${joinCode}`,\n }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n const socketSignals$ =\n ɵobservePhoenixSocketSignals$(socket$).pipe(share());\n const fatalSocketShutdown$ = ɵobservePhoenixSocketHealth$(\n socketSignals$,\n MAX_SOCKET_RETRIES,\n ).pipe(\n catchError(() => {\n console.warn(\n `[threads] WebSocket failed after ${MAX_SOCKET_RETRIES} attempts, giving up`,\n );\n return of(undefined);\n }),\n share(),\n );\n const socketLifecycle$ = socketSignals$.pipe(\n map((signal) =>\n signal.type === \"open\"\n ? threadSocketEvents.opened({ sessionId: action.sessionId })\n : threadSocketEvents.errored({ sessionId: action.sessionId }),\n ),\n );\n const metadata$ = channel$.pipe(\n switchMap(({ channel }: ɵPhoenixChannelSession) =>\n ɵobservePhoenixEvent$<ThreadMetadataEvent>(\n channel,\n THREADS_CHANNEL_EVENT,\n ),\n ),\n map((payload) =>\n threadSocketEvents.metadataReceived({\n sessionId: action.sessionId,\n payload,\n }),\n ),\n );\n const runActivity$ = channel$.pipe(\n switchMap(({ channel }: ɵPhoenixChannelSession) =>\n ɵobservePhoenixEvent$<ThreadRunActivityGatewayPayload>(\n channel,\n THREAD_RUN_ACTIVITY_CHANNEL_EVENT,\n ),\n ),\n map((payload) => normalizeThreadRunActivityNotification(payload)),\n filter(\n (notification): notification is ThreadRunActivityNotification =>\n notification !== null,\n ),\n map((notification) =>\n threadSocketEvents.runActivityReceived({\n sessionId: action.sessionId,\n notification,\n }),\n ),\n );\n const joinOutcome$ = ɵobservePhoenixJoinOutcome$(channel$).pipe(\n filter((outcome) => outcome.type !== \"joined\"),\n map((outcome) =>\n outcome.type === \"timeout\"\n ? threadSocketEvents.joinTimedOut({\n sessionId: action.sessionId,\n })\n : threadSocketEvents.joinFailed({\n sessionId: action.sessionId,\n }),\n ),\n );\n\n return merge(\n socketLifecycle$,\n metadata$,\n runActivity$,\n joinOutcome$,\n ).pipe(takeUntil(merge(shutdown$, fatalSocketShutdown$)));\n });\n }),\n ),\n );\n\n const realtimeMappingEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadSocketEvents.metadataReceived),\n withLatestFrom(state$),\n filter(([action, state]) => action.sessionId === state.sessionId),\n map(([action, state]) => {\n if (action.payload.operation === \"deleted\") {\n return threadDomainEvents.threadDeleted({\n sessionId: action.sessionId,\n threadId: action.payload.deleted.id,\n });\n }\n\n // When includeArchived is false, an \"archived\" event should remove\n // the thread from the local list rather than upserting it.\n if (\n action.payload.operation === \"archived\" &&\n !state.context?.includeArchived\n ) {\n return threadDomainEvents.threadDeleted({\n sessionId: action.sessionId,\n threadId: action.payload.threadId,\n });\n }\n\n return threadDomainEvents.threadUpserted({\n sessionId: action.sessionId,\n thread: action.payload.thread,\n });\n }),\n ),\n );\n\n // Observability-only effect for realtime-join health. The socket effect\n // dispatches `joinFailed`/`joinTimedOut`/`errored` but the reducer has no\n // handler for them by design: a transient WS drop while the (already\n // fetched) list is present must NOT become a hard list error — the user\n // keeps the stale list. Previously these actions were silently swallowed,\n // leaving a realtime-join failure with zero signal. This effect emits a\n // non-fatal warning (mirroring the MAX_SOCKET_RETRIES warn) so the failure\n // is diagnosable. Session-guarded so a superseded session stays quiet.\n const socketDiagnosticsEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(\n threadSocketEvents.joinFailed,\n threadSocketEvents.joinTimedOut,\n threadSocketEvents.errored,\n threadRestEvents.metadataCredentialsFailed,\n ),\n withLatestFrom(state$),\n filter(([action, state]) => action.sessionId === state.sessionId),\n tap(([action]) => {\n const reason = threadSocketEvents.joinTimedOut.match(action)\n ? \"channel join timed out\"\n : threadSocketEvents.joinFailed.match(action)\n ? \"channel join was rejected\"\n : threadRestEvents.metadataCredentialsFailed.match(action)\n ? \"metadata credentials fetch failed\"\n : \"socket errored\";\n console.warn(\n `[threads] realtime ${reason}; the thread list may be stale until reconnect`,\n );\n }),\n ),\n { dispatch: false },\n );\n\n const fetchNextPageEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(threadAdapterEvents.fetchNextPageRequested),\n withLatestFrom(state$),\n filter(\n ([, state]) => Boolean(state.context) && Boolean(state.nextCursor),\n ),\n switchMap(([, state]) => {\n const context = state.context as ThreadRuntimeContext;\n const params: Record<string, string> = {\n agentId: context.agentId,\n cursor: state.nextCursor!,\n };\n if (context.includeArchived) params.includeArchived = \"true\";\n if (context.limit != null) params.limit = String(context.limit);\n\n return threadFromFetch(\n `${context.runtimeUrl}/threads?${new URLSearchParams(params).toString()}`,\n {\n selector: (response) => {\n if (!response.ok) {\n throw new Error(\n `Failed to fetch next page: ${response.status}`,\n );\n }\n\n return response.json() as Promise<ThreadListResponse>;\n },\n fetch: environment.fetch,\n method: \"GET\",\n headers: { ...context.headers },\n },\n ).pipe(\n timeout({\n first: REQUEST_TIMEOUT_MS,\n with: () => {\n throw new Error(\"Request timed out\");\n },\n }),\n map((data) =>\n threadRestEvents.nextPageSucceeded({\n sessionId: state.sessionId,\n threads: data.threads,\n nextCursor: data.nextCursor ?? null,\n }),\n ),\n catchError((error) =>\n of(\n threadRestEvents.nextPageFailed({\n sessionId: state.sessionId,\n error:\n error instanceof Error ? error : new Error(String(error)),\n }),\n ),\n ),\n takeUntil(\n actions$.pipe(\n ofType(\n threadAdapterEvents.contextChanged,\n threadAdapterEvents.stopped,\n ),\n ),\n ),\n );\n }),\n ),\n );\n\n const mutationEffect = createEffect(\n (actions$, state$: Observable<ThreadState>) =>\n actions$.pipe(\n ofType(\n threadAdapterEvents.renameRequested,\n threadAdapterEvents.archiveRequested,\n threadAdapterEvents.unarchiveRequested,\n threadAdapterEvents.deleteRequested,\n ),\n withLatestFrom(state$),\n mergeMap(([action, state]) => {\n // Capture the dispatching session so a result that resolves after a\n // `contextChanged` is dropped by the reducer instead of leaking an\n // error/onError/rollback into the new session. The mergeMap is not\n // cancelled on context change, so the session tag is the guard.\n const sessionId = state.sessionId;\n const context = state.context;\n if (!context?.runtimeUrl) {\n const requestId = action.requestId;\n return of(\n threadRestEvents.mutationFinished({\n outcome: {\n requestId,\n sessionId,\n ok: false,\n error: new Error(\"Runtime URL is not configured\"),\n },\n }),\n );\n }\n\n const commonBody = {\n agentId: context.agentId,\n };\n\n if (threadAdapterEvents.renameRequested.match(action)) {\n return createThreadMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n method: \"PATCH\",\n path: `/threads/${encodeURIComponent(action.threadId)}`,\n body: {\n ...commonBody,\n name: action.name,\n },\n });\n }\n\n if (threadAdapterEvents.archiveRequested.match(action)) {\n return createThreadMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n method: \"POST\",\n path: `/threads/${encodeURIComponent(action.threadId)}/archive`,\n body: commonBody,\n });\n }\n\n if (threadAdapterEvents.unarchiveRequested.match(action)) {\n return createThreadMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n method: \"PATCH\",\n path: `/threads/${encodeURIComponent(action.threadId)}`,\n body: {\n ...commonBody,\n archived: false,\n },\n });\n }\n\n return createThreadMutationObservable(environment, context, {\n requestId: action.requestId,\n sessionId,\n method: \"DELETE\",\n path: `/threads/${encodeURIComponent(action.threadId)}`,\n body: commonBody,\n });\n }),\n ),\n );\n\n const store = createStore<ThreadState>({\n reducer: threadReducer,\n effects: [\n bootstrapEffect,\n fetchEffect,\n metadataCredentialsEffect,\n metadataCredentialsFetchEffect,\n socketEffect,\n realtimeMappingEffect,\n socketDiagnosticsEffect,\n fetchNextPageEffect,\n mutationEffect,\n ],\n });\n\n function trackMutation(\n dispatchAction:\n | ReturnType<typeof threadAdapterEvents.renameRequested>\n | ReturnType<typeof threadAdapterEvents.archiveRequested>\n | ReturnType<typeof threadAdapterEvents.unarchiveRequested>\n | ReturnType<typeof threadAdapterEvents.deleteRequested>,\n ): Promise<void> {\n const completion$ = merge(\n store.actions$.pipe(\n ofType(threadRestEvents.mutationFinished),\n filter(\n (action) => action.outcome.requestId === dispatchAction.requestId,\n ),\n map((action) => action.outcome),\n ),\n store.actions$.pipe(\n ofType(threadAdapterEvents.stopped),\n map(\n () =>\n ({\n requestId: dispatchAction.requestId,\n sessionId: store.getState().sessionId,\n ok: false,\n error: new Error(\n \"Thread store stopped before mutation completed\",\n ),\n }) satisfies MutationOutcome,\n ),\n ),\n ).pipe(take(1));\n\n const resultPromise = firstValueFrom(completion$).then((outcome) => {\n if (outcome.ok) {\n return;\n }\n\n throw outcome.error;\n });\n\n store.dispatch(dispatchAction);\n return resultPromise;\n }\n\n // Surface mutation rejections to the optional environment callback. The\n // reducer has already applied any delete rollback by the time this fires\n // (the store reduces state before re-emitting the action), so consumers see\n // a consistent list when they react to the error.\n let errorSubscription: Subscription | null = null;\n const subscribeErrors = (): void => {\n if (!environment.onError || errorSubscription) {\n return;\n }\n\n errorSubscription = store.actions$\n .pipe(\n ofType(threadRestEvents.mutationFinished),\n // Drop stale-session failures: a mutation that rejects after a\n // `contextChanged` belongs to a context the user already left, so\n // surfacing it would fire onError for the wrong session. The reducer\n // applies the same guard before writing `state.error`.\n filter(\n (action) =>\n !action.outcome.ok &&\n action.outcome.sessionId === store.getState().sessionId,\n ),\n )\n .subscribe((action) => {\n if (!action.outcome.ok) {\n environment.onError?.(action.outcome.error);\n }\n });\n };\n\n return {\n start(): void {\n store.init();\n subscribeErrors();\n store.dispatch(threadAdapterEvents.started());\n },\n stop(): void {\n store.dispatch(threadAdapterEvents.stopped());\n errorSubscription?.unsubscribe();\n errorSubscription = null;\n store.stop();\n },\n setContext(context: ThreadRuntimeContext | null): void {\n store.dispatch(threadAdapterEvents.contextChanged({ context }));\n },\n refresh(): void {\n const { sessionId, context } = store.getState();\n if (!context) return;\n store.dispatch(threadRestEvents.listRequested({ sessionId }));\n },\n refetchThreads(): void {\n const { sessionId, context } = store.getState();\n if (!context) return;\n store.dispatch(threadRestEvents.listRequested({ sessionId }));\n },\n startNewThread(): void {\n store.dispatch(threadAdapterEvents.newThreadStarted());\n },\n fetchNextPage(): void {\n store.dispatch(threadAdapterEvents.fetchNextPageRequested());\n },\n renameThread(threadId: string, name: string): Promise<void> {\n return trackMutation(\n threadAdapterEvents.renameRequested({\n requestId: createThreadRequestId(),\n threadId,\n name,\n }),\n );\n },\n archiveThread(threadId: string): Promise<void> {\n return trackMutation(\n threadAdapterEvents.archiveRequested({\n requestId: createThreadRequestId(),\n threadId,\n }),\n );\n },\n unarchiveThread(threadId: string): Promise<void> {\n return trackMutation(\n threadAdapterEvents.unarchiveRequested({\n requestId: createThreadRequestId(),\n threadId,\n }),\n );\n },\n deleteThread(threadId: string): Promise<void> {\n return trackMutation(\n threadAdapterEvents.deleteRequested({\n requestId: createThreadRequestId(),\n threadId,\n }),\n );\n },\n subscribeToRunActivity(\n callback: (notification: ThreadRunActivityNotification) => void,\n ): Subscription {\n return store.actions$\n .pipe(\n ofType(threadSocketEvents.runActivityReceived),\n filter((action) => action.sessionId === store.getState().sessionId),\n map((action) => action.notification),\n )\n .subscribe(callback);\n },\n getState(): ThreadState {\n return store.getState();\n },\n getServerState(): ThreadState {\n return initialThreadState;\n },\n select: store.select.bind(store),\n selectors,\n };\n}\n\nexport type ɵThread = ThreadRecord;\nexport type ɵThreadRuntimeContext = ThreadRuntimeContext;\nexport type ɵThreadMetadataEvent = ThreadMetadataEvent;\nexport type ɵThreadEnvironment = ThreadEnvironment;\nexport type ɵThreadStore = ThreadStore;\nexport type ɵThreadSelectors = ThreadSelectors;\nexport const ɵthreadAdapterEvents = threadAdapterEvents;\nexport const ɵcreateThreadSelectors = createThreadSelectors;\nexport const ɵselectThreads = selectThreads;\nexport const ɵselectThreadsIsLoading = selectThreadsIsLoading;\nexport const ɵselectThreadsError = selectThreadsError;\nexport const ɵselectFetchMoreError = selectFetchMoreError;\nexport const ɵselectHasNextPage = selectHasNextPage;\nexport const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;\nexport const ɵselectIsMutating = selectIsMutating;\nexport { createThreadStore as ɵcreateThreadStore };\n/**\n * Number of consecutive WebSocket connection failures after which the\n * threads channel tears itself down rather than retrying indefinitely.\n * Exposed for tests so they can assert teardown semantics without\n * hardcoding the threshold separately from production.\n */\nexport const ɵMAX_SOCKET_RETRIES = MAX_SOCKET_RETRIES;\n","/**\n * Central registry of CopilotKit feature names.\n *\n * Feature names are the strings passed to a license context's `checkFeature`\n * (see `@copilotkit/shared`'s `LicenseContextValue`). Historically the only\n * features referenced by literal were the chat surfaces (`chat`, `sidebar`,\n * `popup`); this module makes the set explicit and typed so new surfaces —\n * such as the threads drawer — register a real, discoverable feature name\n * rather than an ad-hoc string scattered across components.\n *\n * `checkFeature` itself still accepts any `string` for backward compatibility;\n * this registry simply documents and types the names CopilotKit recognises.\n */\n\n/**\n * The set of feature names CopilotKit recognises.\n *\n * Frozen so the array cannot be mutated at runtime. Add new surfaces here when\n * they begin gating behaviour on `checkFeature`.\n */\nexport const ɵCOPILOTKIT_FEATURES = Object.freeze([\n \"chat\",\n \"sidebar\",\n \"popup\",\n \"threads\",\n] as const);\n\n/**\n * Union of recognised CopilotKit feature names.\n */\nexport type ɵCopilotKitFeature = (typeof ɵCOPILOTKIT_FEATURES)[number];\n\nconst FEATURE_SET: ReadonlySet<string> = new Set(ɵCOPILOTKIT_FEATURES);\n\n/**\n * Type guard: returns `true` when `name` is a recognised CopilotKit feature.\n *\n * @param name - Candidate feature name.\n * @returns Whether `name` is a registered feature.\n *\n * @example\n * ```ts\n * if (ɵisCopilotKitFeature(\"threads\")) {\n * // narrowed to ɵCopilotKitFeature\n * }\n * ```\n */\nexport function ɵisCopilotKitFeature(name: string): name is ɵCopilotKitFeature {\n return FEATURE_SET.has(name);\n}\n","import { buildResumeArray, isInterruptExpired } from \"@ag-ui/client\";\nimport type { Interrupt, ResumeEntry } from \"@ag-ui/client\";\n\ntype ResumeResponse =\n | { status: \"resolved\"; payload?: unknown }\n | { status: \"cancelled\" };\n\n/** @internal Application authors must not depend on this contract. */\nexport interface ɵInterruptEvent<TValue = unknown> {\n name: string;\n value: TValue;\n}\n\n/** @internal Application authors must not depend on this contract. */\nexport type ɵPendingInterrupt<TValue = unknown> =\n | { kind: \"legacy\"; event: ɵInterruptEvent<TValue> }\n | { kind: \"standard\"; interrupts: readonly Interrupt[] };\n\n/** @internal Application authors must not depend on this contract. */\nexport interface ɵInterruptToolResult {\n toolCallId: string;\n content: string;\n}\n\n/** @internal Application authors must not depend on this contract. */\nexport type ɵInterruptDecision =\n | { kind: \"ignored\" }\n | { kind: \"waiting\" }\n | { kind: \"dismiss\" }\n | {\n kind: \"expired\";\n interrupt: Interrupt;\n }\n | {\n kind: \"legacy-resume\";\n payload: unknown;\n interruptValue: unknown;\n }\n | {\n kind: \"resume\";\n resume: ResumeEntry[];\n toolResults: ɵInterruptToolResult[];\n };\n\nfunction toolResultContent(response: ResumeResponse): string {\n if (response.status === \"cancelled\") {\n return JSON.stringify({ status: \"cancelled\" });\n }\n return JSON.stringify(response.payload ?? { status: \"resolved\" });\n}\n\n/**\n * @internal Framework-neutral interrupt response state shared by framework\n * adapters. Application authors must not depend on this API.\n */\nexport class ɵInterruptState<TValue = unknown> {\n readonly #responses: Record<string, ResumeResponse> = {};\n #pending: ɵPendingInterrupt<TValue> | null = null;\n #sealed = false;\n\n /** Return the active normalized interrupt without exposing mutable state. */\n get pending(): ɵPendingInterrupt<TValue> | null {\n const pending = this.#pending;\n if (pending?.kind === \"standard\") {\n return { kind: \"standard\", interrupts: [...pending.interrupts] };\n }\n return pending;\n }\n\n /** Replace the current interrupt with a legacy custom-event interrupt. */\n setLegacy(event: ɵInterruptEvent<TValue>): void {\n this.#replace({ kind: \"legacy\", event });\n }\n\n /** Replace the current interrupt with an AG-UI standard interrupt set. */\n setStandard(interrupts: readonly Interrupt[]): void {\n this.#replace({ kind: \"standard\", interrupts: [...interrupts] });\n }\n\n /** Clear all pending interrupt data and accumulated responses. */\n clear(): void {\n this.#pending = null;\n this.#sealed = false;\n for (const id of Object.keys(this.#responses)) delete this.#responses[id];\n }\n\n /** Record a resolved response and return the next framework action. */\n resolve(payload?: unknown, interruptId?: string): ɵInterruptDecision {\n const pending = this.#pending;\n if (!pending || this.#sealed) return { kind: \"ignored\" };\n if (pending.kind === \"legacy\") {\n this.#sealed = true;\n return {\n kind: \"legacy-resume\",\n payload,\n interruptValue: pending.event.value,\n };\n }\n return this.#respond(pending.interrupts, interruptId, {\n status: \"resolved\",\n payload,\n });\n }\n\n /** Record a cancelled response and return the next framework action. */\n cancel(interruptId?: string): ɵInterruptDecision {\n const pending = this.#pending;\n if (!pending || this.#sealed) return { kind: \"ignored\" };\n if (pending.kind === \"legacy\") {\n this.#sealed = true;\n return { kind: \"dismiss\" };\n }\n return this.#respond(pending.interrupts, interruptId, {\n status: \"cancelled\",\n });\n }\n\n #replace(pending: ɵPendingInterrupt<TValue>): void {\n this.clear();\n this.#pending = pending;\n }\n\n #respond(\n interrupts: readonly Interrupt[],\n interruptId: string | undefined,\n response: ResumeResponse,\n ): ɵInterruptDecision {\n const id = interruptId ?? interrupts[0]?.id;\n if (!id || !interrupts.some((interrupt) => interrupt.id === id)) {\n return { kind: \"ignored\" };\n }\n this.#responses[id] = response;\n if (!interrupts.every((interrupt) => this.#responses[interrupt.id])) {\n return { kind: \"waiting\" };\n }\n\n const expired = interrupts.find((interrupt) =>\n isInterruptExpired(interrupt),\n );\n if (expired) {\n this.#sealed = true;\n return { kind: \"expired\", interrupt: expired };\n }\n\n const mutableInterrupts = [...interrupts];\n const resume = buildResumeArray(mutableInterrupts, this.#responses);\n const toolResults = mutableInterrupts.flatMap((interrupt) => {\n if (!interrupt.toolCallId) return [];\n return [\n {\n toolCallId: interrupt.toolCallId,\n content: toolResultContent(this.#responses[interrupt.id]!),\n },\n ];\n });\n this.#sealed = true;\n return { kind: \"resume\", resume, toolResults };\n }\n}\n"],"mappings":"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"}
|