@copilotkit/core 1.62.2 → 1.63.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.mjs CHANGED
@@ -1,10 +1,11 @@
1
1
  import { Throttler } from "@tanstack/pacer";
2
2
  import { AbstractAgent, EventType, HttpAgent, randomUUID, runHttpRequest, structuredClone_, transformChunks, transformHttpEventStream } from "@ag-ui/client";
3
3
  import { RUNTIME_MODE_INTELLIGENCE, RUNTIME_MODE_SSE, logger, partialJSONParse, phoenixExponentialBackoff, randomUUID as randomUUID$1, resolveDebugConfig, schemaToJsonSchema } from "@copilotkit/shared";
4
- import { BehaviorSubject, EMPTY, NEVER, Notification, Observable, Subject, Subscription, asapScheduler, combineLatest, concat, defer, dematerialize, firstValueFrom, from, lastValueFrom, merge, of, switchMap, throwError } from "rxjs";
5
- import { catchError, delay, distinctUntilChanged, endWith, filter, finalize, ignoreElements, map, mergeMap, observeOn, scan, share, shareReplay, switchMap as switchMap$1, take, takeUntil, tap, timeout, withLatestFrom } from "rxjs/operators";
4
+ import { BehaviorSubject, EMPTY, NEVER, Notification, Observable, Subject, Subscription, asapScheduler, combineLatest, concat, defer, dematerialize, firstValueFrom, from, lastValueFrom, merge, observeOn, of, switchMap, throwError } from "rxjs";
5
+ import { catchError, concatWith, delay, distinctUntilChanged, endWith, filter, finalize, ignoreElements, map, mergeMap, observeOn as observeOn$1, scan, share, shareReplay, switchMap as switchMap$1, take, takeUntil, tap, timeout, withLatestFrom } from "rxjs/operators";
6
6
  import { Socket } from "phoenix";
7
7
  import { zodToJsonSchema } from "zod-to-json-schema";
8
+ import { fromFetch } from "rxjs/fetch";
8
9
 
9
10
  //#region src/utils/phoenix-observable.ts
10
11
  /**
@@ -542,12 +543,12 @@ function hasCredentials(agent) {
542
543
  function isZodError(error) {
543
544
  return error !== null && typeof error === "object" && "name" in error && error.name === "ZodError";
544
545
  }
545
- function isAbortError(error) {
546
+ function isAbortError$1(error) {
546
547
  return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
547
548
  }
548
549
  function withAbortErrorHandling(observable) {
549
550
  return observable.pipe(catchError((error) => {
550
- if (isZodError(error) || isAbortError(error)) return EMPTY;
551
+ if (isZodError(error) || isAbortError$1(error)) return EMPTY;
551
552
  throw error;
552
553
  }));
553
554
  }
@@ -887,6 +888,7 @@ var AgentRegistry = class {
887
888
  localAgents = {};
888
889
  remoteAgents = {};
889
890
  _runtimeUrl;
891
+ _connectionInFlight;
890
892
  _runtimeVersion;
891
893
  _runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Disconnected;
892
894
  _runtimeTransport = "auto";
@@ -895,6 +897,7 @@ var AgentRegistry = class {
895
897
  _runtimeMode = RUNTIME_MODE_SSE;
896
898
  _intelligence;
897
899
  _threadEndpoints;
900
+ _suggestions;
898
901
  _a2uiEnabled = false;
899
902
  _a2uiAgents;
900
903
  _openGenerativeUIEnabled = false;
@@ -944,6 +947,9 @@ var AgentRegistry = class {
944
947
  get threadEndpoints() {
945
948
  return this._threadEndpoints;
946
949
  }
950
+ get suggestions() {
951
+ return this._suggestions;
952
+ }
947
953
  get a2uiEnabled() {
948
954
  return this._a2uiEnabled;
949
955
  }
@@ -975,10 +981,28 @@ var AgentRegistry = class {
975
981
  /**
976
982
  * Set the runtime URL and update connection
977
983
  */
978
- setRuntimeUrl(runtimeUrl) {
984
+ setRuntimeUrl(runtimeUrl, options) {
979
985
  const normalizedRuntimeUrl = runtimeUrl ? runtimeUrl.replace(/\/$/, "") : void 0;
980
986
  if (this._runtimeUrl === normalizedRuntimeUrl) return;
981
987
  this._runtimeUrl = normalizedRuntimeUrl;
988
+ if (options?.deferConnection) return;
989
+ this.updateRuntimeConnection();
990
+ }
991
+ /**
992
+ * Start the initial runtime connection if it has not been started yet.
993
+ *
994
+ * Backs {@link CopilotKitCore.connect}. Idempotent: it only kicks off a fetch
995
+ * when a `runtimeUrl` is set and the connection is still `Disconnected` (its
996
+ * state before any connect attempt). `updateRuntimeConnection` flips the
997
+ * status to `Connecting` synchronously, so a second call — e.g. React
998
+ * StrictMode double-invoking the mount effect — bails here. A genuine config
999
+ * change still reconnects through `setRuntimeUrl`/`setRuntimeTransport`. See
1000
+ * #5801.
1001
+ */
1002
+ connectRuntime() {
1003
+ if (typeof window === "undefined") return;
1004
+ if (!this._runtimeUrl) return;
1005
+ if (this._runtimeConnectionStatus !== CopilotKitCoreRuntimeConnectionStatus.Disconnected) return;
982
1006
  this.updateRuntimeConnection();
983
1007
  }
984
1008
  setRuntimeTransport(runtimeTransport) {
@@ -1124,6 +1148,20 @@ var AgentRegistry = class {
1124
1148
  */
1125
1149
  async updateRuntimeConnection() {
1126
1150
  if (typeof window === "undefined") return;
1151
+ const key = `${this._runtimeUrl ?? ""}::${this._requestedTransport}`;
1152
+ const inFlight = this._connectionInFlight;
1153
+ if (inFlight && inFlight.key === key) return inFlight.promise;
1154
+ const promise = this.performRuntimeConnection();
1155
+ this._connectionInFlight = {
1156
+ key,
1157
+ promise
1158
+ };
1159
+ promise.finally(() => {
1160
+ if (this._connectionInFlight?.promise === promise) this._connectionInFlight = void 0;
1161
+ });
1162
+ return promise;
1163
+ }
1164
+ async performRuntimeConnection() {
1127
1165
  if (!this.runtimeUrl) {
1128
1166
  this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Disconnected;
1129
1167
  this._runtimeVersion = void 0;
@@ -1131,6 +1169,7 @@ var AgentRegistry = class {
1131
1169
  this._runtimeMode = RUNTIME_MODE_SSE;
1132
1170
  this._intelligence = void 0;
1133
1171
  this._threadEndpoints = void 0;
1172
+ this._suggestions = void 0;
1134
1173
  this._a2uiEnabled = false;
1135
1174
  this._a2uiAgents = void 0;
1136
1175
  this._openGenerativeUIEnabled = false;
@@ -1178,6 +1217,7 @@ var AgentRegistry = class {
1178
1217
  this._runtimeMode = runtimeInfoResponse.mode ?? RUNTIME_MODE_SSE;
1179
1218
  this._intelligence = runtimeInfoResponse.intelligence;
1180
1219
  this._threadEndpoints = runtimeInfoResponse.threadEndpoints;
1220
+ this._suggestions = runtimeInfoResponse.suggestions;
1181
1221
  const a2uiInfo = runtimeInfoResponse.a2ui;
1182
1222
  this._a2uiEnabled = a2uiInfo?.enabled ?? runtimeInfoResponse.a2uiEnabled ?? false;
1183
1223
  this._a2uiAgents = a2uiInfo?.enabled ? a2uiInfo.agents : void 0;
@@ -1193,6 +1233,7 @@ var AgentRegistry = class {
1193
1233
  this._runtimeMode = RUNTIME_MODE_SSE;
1194
1234
  this._intelligence = void 0;
1195
1235
  this._threadEndpoints = void 0;
1236
+ this._suggestions = void 0;
1196
1237
  this._a2uiEnabled = false;
1197
1238
  this._a2uiAgents = void 0;
1198
1239
  this._openGenerativeUIEnabled = false;
@@ -1432,38 +1473,81 @@ var SuggestionEngine = class {
1432
1473
  };
1433
1474
  }
1434
1475
  /**
1435
- * Generate suggestions using a provider agent
1476
+ * Generate suggestions by running a provider agent and extracting the
1477
+ * `copilotkitSuggest` tool call from its streamed messages.
1478
+ *
1479
+ * Two transports, one set of mechanics: both seed an agent with the
1480
+ * consumer's messages + state and the instruction, then `runAgent` with
1481
+ * forced `copilotkitSuggest` tool choice, parsing suggestions as messages
1482
+ * stream in via `onMessagesChanged`.
1483
+ *
1484
+ * - **Stateless** (runtime advertises `suggestions` and transport isn't
1485
+ * `single`): a stock `HttpAgent` pointed at `/agent/:id/suggest`. That
1486
+ * endpoint runs the provider directly and streams AG-UI SSE **without**
1487
+ * persisting a thread, and a plain `HttpAgent` only ever speaks REST SSE —
1488
+ * it never routes through the Intelligence websocket delegate (which would
1489
+ * persist a thread). This is the path that removes the thread flood.
1490
+ * - **Fallback** (capability absent → old runtime, or `single` transport):
1491
+ * clone the provider agent and run it client-side, as before.
1492
+ *
1493
+ * Gated to non-`single` transports because this client only builds the
1494
+ * multi-route `/agent/:id/suggest` URL; single-route deployments (not the
1495
+ * persisting-thread/Intelligence case) fall through to the clone fallback.
1436
1496
  */
1437
1497
  async generateSuggestions(suggestionId, config, consumerAgentId) {
1438
- let agent = void 0;
1498
+ let runHandle = void 0;
1499
+ let aborted = false;
1439
1500
  try {
1440
- const suggestionsProviderAgent = this.core.getAgent(config.providerAgentId ?? "default");
1441
- if (!suggestionsProviderAgent) throw new Error(`Suggestions provider agent not found: ${config.providerAgentId}`);
1442
- const suggestionsConsumerAgent = this.core.getAgent(consumerAgentId);
1501
+ const friends = this.core;
1502
+ const resolvedProviderAgentId = config.providerAgentId ?? "default";
1503
+ const suggestionsProviderAgent = friends.getAgent(resolvedProviderAgentId);
1504
+ if (!suggestionsProviderAgent) throw new Error(`Suggestions provider agent not found: ${resolvedProviderAgentId}`);
1505
+ const suggestionsConsumerAgent = friends.getAgent(consumerAgentId);
1443
1506
  if (!suggestionsConsumerAgent) throw new Error(`Suggestions consumer agent not found: ${consumerAgentId}`);
1444
- agent = suggestionsProviderAgent.clone();
1445
- agent.threadId = suggestionId;
1446
- agent.messages = JSON.parse(JSON.stringify(suggestionsConsumerAgent.messages));
1447
- agent.state = JSON.parse(JSON.stringify(suggestionsConsumerAgent.state));
1507
+ const instructionContent = [
1508
+ `Suggest what the user could say next. Provide clear, highly relevant suggestions by calling the \`copilotkitSuggest\` tool.`,
1509
+ `Provide at least ${config.minSuggestions ?? 1} and at most ${config.maxSuggestions ?? 3} suggestions.`,
1510
+ `The user has the following tools available: ${JSON.stringify(friends.buildFrontendTools(consumerAgentId))}.`,
1511
+ ` ${config.instructions}`
1512
+ ].join("\n");
1448
1513
  this._suggestions[consumerAgentId] = {
1449
1514
  ...this._suggestions[consumerAgentId],
1450
1515
  [suggestionId]: []
1451
1516
  };
1452
- this._runningSuggestions[consumerAgentId] = [...this._runningSuggestions[consumerAgentId] ?? [], agent];
1453
- agent.addMessage({
1517
+ const seededMessages = JSON.parse(JSON.stringify(suggestionsConsumerAgent.messages));
1518
+ const seededState = JSON.parse(JSON.stringify(suggestionsConsumerAgent.state ?? {}));
1519
+ const useStateless = this.core.suggestions === true && this.core.runtimeTransport !== "single";
1520
+ let suggestionAgent;
1521
+ if (useStateless) {
1522
+ const suggestUrl = `${this.core.runtimeUrl}/agent/${encodeURIComponent(resolvedProviderAgentId)}/suggest`;
1523
+ const credentials = this.core.credentials;
1524
+ suggestionAgent = new HttpAgent({
1525
+ agentId: resolvedProviderAgentId,
1526
+ url: suggestUrl,
1527
+ headers: { ...this.core.headers },
1528
+ ...credentials ? { fetch: (url, requestInit) => fetch(url, {
1529
+ ...requestInit,
1530
+ credentials
1531
+ }) } : {}
1532
+ });
1533
+ } else suggestionAgent = suggestionsProviderAgent.clone();
1534
+ suggestionAgent.threadId = suggestionId;
1535
+ suggestionAgent.setMessages(seededMessages);
1536
+ suggestionAgent.setState(seededState);
1537
+ runHandle = { abortRun: () => {
1538
+ aborted = true;
1539
+ suggestionAgent.abortRun();
1540
+ } };
1541
+ this._runningSuggestions[consumerAgentId] = [...this._runningSuggestions[consumerAgentId] ?? [], runHandle];
1542
+ suggestionAgent.addMessage({
1454
1543
  id: suggestionId,
1455
1544
  role: "user",
1456
- content: [
1457
- `Suggest what the user could say next. Provide clear, highly relevant suggestions by calling the \`copilotkitSuggest\` tool.`,
1458
- `Provide at least ${config.minSuggestions ?? 1} and at most ${config.maxSuggestions ?? 3} suggestions.`,
1459
- `The user has the following tools available: ${JSON.stringify(this.core.buildFrontendTools(consumerAgentId))}.`,
1460
- ` ${config.instructions}`
1461
- ].join("\n")
1545
+ content: instructionContent
1462
1546
  });
1463
- await agent.runAgent({
1464
- context: this.core.getContextForAgent(consumerAgentId),
1547
+ await suggestionAgent.runAgent({
1548
+ context: friends.getContextForAgent(consumerAgentId),
1465
1549
  forwardedProps: {
1466
- ...this.core.properties,
1550
+ ...friends.properties,
1467
1551
  toolChoice: {
1468
1552
  type: "function",
1469
1553
  function: { name: "copilotkitSuggest" }
@@ -1474,18 +1558,15 @@ var SuggestionEngine = class {
1474
1558
  this.extractSuggestions(messages, suggestionId, consumerAgentId, true);
1475
1559
  } });
1476
1560
  } catch (error) {
1477
- console.warn("Error generating suggestions:", error);
1561
+ if (!isAbortError(error) && !aborted) console.warn("Error generating suggestions:", error);
1478
1562
  } finally {
1479
1563
  this.finalizeSuggestions(suggestionId, consumerAgentId);
1480
1564
  const runningAgents = this._runningSuggestions[consumerAgentId];
1481
- if (agent && runningAgents) {
1482
- const filteredAgents = runningAgents.filter((a) => a !== agent);
1483
- this._runningSuggestions[consumerAgentId] = filteredAgents;
1484
- if (filteredAgents.length === 0) {
1485
- delete this._runningSuggestions[consumerAgentId];
1486
- await this.notifySuggestionsFinishedLoading(consumerAgentId);
1487
- }
1488
- }
1565
+ const remaining = runHandle ? (runningAgents ?? []).filter((a) => a !== runHandle) : runningAgents ?? [];
1566
+ if (remaining.length === 0) {
1567
+ delete this._runningSuggestions[consumerAgentId];
1568
+ await this.notifySuggestionsFinishedLoading(consumerAgentId);
1569
+ } else this._runningSuggestions[consumerAgentId] = remaining;
1489
1570
  }
1490
1571
  }
1491
1572
  /**
@@ -1605,6 +1686,13 @@ var SuggestionEngine = class {
1605
1686
  }
1606
1687
  };
1607
1688
  /**
1689
+ * Detects an `AbortController`-driven cancellation so the stateless path can
1690
+ * treat it as an expected (non-error) outcome on clear/reload.
1691
+ */
1692
+ function isAbortError(error) {
1693
+ return typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
1694
+ }
1695
+ /**
1608
1696
  * Type guard for dynamic suggestions config
1609
1697
  */
1610
1698
  function isDynamicSuggestionsConfig(config) {
@@ -2564,153 +2652,1135 @@ var ThreadStoreRegistry = class {
2564
2652
  };
2565
2653
 
2566
2654
  //#endregion
2567
- //#region src/core/core.ts
2568
- let CopilotKitCoreErrorCode = /* @__PURE__ */ function(CopilotKitCoreErrorCode) {
2569
- CopilotKitCoreErrorCode["RUNTIME_INFO_FETCH_FAILED"] = "runtime_info_fetch_failed";
2570
- CopilotKitCoreErrorCode["AGENT_CONNECT_FAILED"] = "agent_connect_failed";
2571
- CopilotKitCoreErrorCode["AGENT_RUN_FAILED"] = "agent_run_failed";
2572
- CopilotKitCoreErrorCode["AGENT_RUN_FAILED_EVENT"] = "agent_run_failed_event";
2573
- CopilotKitCoreErrorCode["AGENT_RUN_ERROR_EVENT"] = "agent_run_error_event";
2574
- CopilotKitCoreErrorCode["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
2575
- CopilotKitCoreErrorCode["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
2576
- CopilotKitCoreErrorCode["TOOL_NOT_FOUND"] = "tool_not_found";
2577
- CopilotKitCoreErrorCode["AGENT_NOT_FOUND"] = "agent_not_found";
2578
- /**
2579
- * Emitted when an agent run fails because the thread is already locked
2580
- * by another active run.
2581
- *
2582
- * @example
2583
- * ```tsx
2584
- * <CopilotKitProvider
2585
- * onError={({ code, error, context }) => {
2586
- * if (code === "agent_thread_locked") {
2587
- * // Show "Agent is busy, retry?" UI
2588
- * }
2589
- * }}
2590
- * />
2591
- * ```
2592
- */
2593
- CopilotKitCoreErrorCode["AGENT_THREAD_LOCKED"] = "agent_thread_locked";
2594
- CopilotKitCoreErrorCode["TRANSCRIPTION_FAILED"] = "transcription_failed";
2595
- CopilotKitCoreErrorCode["TRANSCRIPTION_SERVICE_NOT_CONFIGURED"] = "transcription_service_not_configured";
2596
- CopilotKitCoreErrorCode["TRANSCRIPTION_INVALID_AUDIO"] = "transcription_invalid_audio";
2597
- CopilotKitCoreErrorCode["TRANSCRIPTION_RATE_LIMITED"] = "transcription_rate_limited";
2598
- CopilotKitCoreErrorCode["TRANSCRIPTION_AUTH_FAILED"] = "transcription_auth_failed";
2599
- CopilotKitCoreErrorCode["TRANSCRIPTION_NETWORK_ERROR"] = "transcription_network_error";
2600
- CopilotKitCoreErrorCode["SUBSCRIBER_CALLBACK_FAILED"] = "subscriber_callback_failed";
2601
- return CopilotKitCoreErrorCode;
2602
- }({});
2655
+ //#region src/utils/micro-redux.ts
2656
+ const INTERNAL_ACTION_TYPES = {
2657
+ boot: "@@micro-redux/boot",
2658
+ init: "@@micro-redux/init",
2659
+ stop: "@@micro-redux/stop"
2660
+ };
2661
+ const INTERNAL_BOOT_ACTION = { type: INTERNAL_ACTION_TYPES.boot };
2603
2662
  /**
2604
- * Runtime allowlist derived from {@link SUBSCRIBE_TO_AGENT_KEYS}. Hoisted
2605
- * to module scope so the Set is allocated once, not per-subscription.
2663
+ * Builds a typed action creator from a type string and payload factory.
2606
2664
  */
2607
- const ALLOWED_KEYS = new Set([
2608
- "onMessagesChanged",
2609
- "onStateChanged",
2610
- "onRunInitialized",
2611
- "onRunFinalized",
2612
- "onRunFailed",
2613
- "onRunErrorEvent"
2614
- ]);
2615
- let CopilotKitCoreRuntimeConnectionStatus = /* @__PURE__ */ function(CopilotKitCoreRuntimeConnectionStatus) {
2616
- CopilotKitCoreRuntimeConnectionStatus["Disconnected"] = "disconnected";
2617
- CopilotKitCoreRuntimeConnectionStatus["Connected"] = "connected";
2618
- CopilotKitCoreRuntimeConnectionStatus["Connecting"] = "connecting";
2619
- CopilotKitCoreRuntimeConnectionStatus["Error"] = "error";
2620
- return CopilotKitCoreRuntimeConnectionStatus;
2621
- }({});
2665
+ function createTypedActionCreator(type, factory) {
2666
+ const creator = ((...args) => ({
2667
+ ...factory(...args),
2668
+ type
2669
+ }));
2670
+ creator.type = type;
2671
+ creator.match = (action) => action.type === type;
2672
+ return creator;
2673
+ }
2622
2674
  /**
2623
- * Normalize a header map to the internal invariant: a `Record<string, string>`
2624
- * with no `null`/`undefined` values. Entries whose value is `null`/`undefined`
2625
- * are dropped (this is how a header is cleared). Shared by the constructor and
2626
- * `setHeaders` so both write paths into `_headers` enforce the same invariant.
2675
+ * Declares a payload-based action config for `createActionGroup`.
2676
+ *
2677
+ * @example
2678
+ * ```ts
2679
+ * const actions = createActionGroup("User", {
2680
+ * loaded: props<{ id: string }>(),
2681
+ * });
2682
+ * ```
2627
2683
  */
2628
- function normalizeHeaders(headers) {
2629
- return Object.fromEntries(Object.entries(headers).filter((entry) => entry[1] != null));
2684
+ function props() {
2685
+ return { kind: "props" };
2630
2686
  }
2631
- var CopilotKitCore = class {
2632
- _headers;
2633
- _credentials;
2634
- _properties;
2635
- _defaultThrottleMs;
2636
- _debug;
2637
- subscribers = /* @__PURE__ */ new Set();
2638
- agentRegistry;
2639
- contextStore;
2640
- suggestionEngine;
2641
- runHandler;
2642
- stateManager;
2643
- threadStoreRegistry;
2644
- /**
2645
- * Tracks the agent IDs from the most recent `onAgentsChanged` notification.
2646
- * Used to gate thread-store auto-unregister so the FIRST empty-agents
2647
- * notification (before published agents are merged in) does not rip out a
2648
- * store that was registered prior to that initial notification.
2649
- */
2650
- previousAgentIds = /* @__PURE__ */ new Set();
2651
- constructor({ runtimeUrl, runtimeTransport = "auto", headers = {}, credentials, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [], debug }) {
2652
- this._headers = normalizeHeaders(headers);
2653
- this._credentials = credentials;
2654
- this._properties = properties;
2655
- this._debug = debug;
2656
- this.agentRegistry = new AgentRegistry(this);
2657
- this.contextStore = new ContextStore(this);
2658
- this.suggestionEngine = new SuggestionEngine(this);
2659
- this.runHandler = new RunHandler(this);
2660
- this.stateManager = new StateManager(this);
2661
- this.threadStoreRegistry = new ThreadStoreRegistry(this);
2662
- this.agentRegistry.initialize(agents__unsafe_dev_only);
2663
- this.runHandler.initialize(tools);
2664
- this.suggestionEngine.initialize(suggestionsConfig);
2665
- this.stateManager.initialize();
2666
- this.agentRegistry.setRuntimeTransport(runtimeTransport);
2667
- this.agentRegistry.setRuntimeUrl(runtimeUrl);
2668
- this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));
2669
- this.subscribe({ onAgentsChanged: ({ agents }) => {
2670
- Object.values(agents).forEach((agent) => {
2671
- if (agent.agentId) this.stateManager.subscribeToAgent(agent);
2672
- });
2673
- const currentAgentIds = new Set(Object.keys(agents));
2674
- for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
2675
- this.threadStoreRegistry.unregister(agentId);
2676
- } catch (err) {
2677
- console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
2678
- }
2679
- for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) try {
2680
- this.stateManager.unsubscribeFromAgent(agentId);
2681
- } catch (err) {
2682
- console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
2683
- }
2684
- this.previousAgentIds = currentAgentIds;
2685
- } });
2687
+ /**
2688
+ * Declares a no-payload action config for `createActionGroup`.
2689
+ *
2690
+ * @example
2691
+ * ```ts
2692
+ * const actions = createActionGroup("User", {
2693
+ * reset: empty(),
2694
+ * });
2695
+ * ```
2696
+ */
2697
+ function empty() {
2698
+ return { kind: "empty" };
2699
+ }
2700
+ /**
2701
+ * Creates a namespaced group of typed action creators.
2702
+ *
2703
+ * Action types are formatted as: `[Source] actionName`.
2704
+ */
2705
+ function createActionGroup(source, config) {
2706
+ const group = {};
2707
+ for (const eventName of Object.keys(config)) {
2708
+ const eventConfig = config[eventName];
2709
+ if (!eventConfig) continue;
2710
+ const actionType = `[${source}] ${eventName}`;
2711
+ if (eventConfig.kind === "props") {
2712
+ group[eventName] = createTypedActionCreator(actionType, (payload) => ({ ...payload }));
2713
+ continue;
2714
+ }
2715
+ group[eventName] = createTypedActionCreator(actionType, () => ({}));
2686
2716
  }
2687
- /**
2688
- * Internal method used by delegate classes and subclasses to notify subscribers
2689
- */
2690
- async notifySubscribers(handler, errorMessage) {
2691
- await Promise.all(Array.from(this.subscribers).map(async (subscriber) => {
2692
- try {
2693
- await handler(subscriber);
2694
- } catch (error) {
2695
- console.error(errorMessage, error);
2696
- }
2697
- }));
2717
+ return group;
2718
+ }
2719
+ /**
2720
+ * Registers one reducer handler for one or more action creators.
2721
+ *
2722
+ * @throws Error when called without at least one action creator and reducer.
2723
+ */
2724
+ function on(...args) {
2725
+ if (args.length < 2) throw new Error("on requires at least one action creator and one reducer");
2726
+ const reducer = args[args.length - 1];
2727
+ return {
2728
+ creators: args.slice(0, -1),
2729
+ reducer
2730
+ };
2731
+ }
2732
+ /**
2733
+ * Creates a reducer from an initial state and `on(...)` handler entries.
2734
+ *
2735
+ * Unknown action types return the current state unchanged.
2736
+ */
2737
+ function createReducer(initialState, ...entries) {
2738
+ const reducerMap = /* @__PURE__ */ new Map();
2739
+ for (const entry of entries) for (const creator of entry.creators) {
2740
+ const handlers = reducerMap.get(creator.type) ?? [];
2741
+ handlers.push(entry.reducer);
2742
+ reducerMap.set(creator.type, handlers);
2698
2743
  }
2699
- /**
2700
- * Internal method used by delegate classes to emit errors
2701
- */
2702
- async emitError({ error, code, context = {} }) {
2703
- await this.notifySubscribers((subscriber) => subscriber.onError?.({
2704
- copilotkit: this,
2705
- error,
2706
- code,
2707
- context
2708
- }), "Subscriber onError error:");
2744
+ return (state, action) => {
2745
+ const currentState = state ?? initialState;
2746
+ const handlers = reducerMap.get(action.type);
2747
+ if (!handlers || handlers.length === 0) return currentState;
2748
+ let nextState = currentState;
2749
+ for (const handler of handlers) nextState = handler(nextState, action);
2750
+ return nextState;
2751
+ };
2752
+ }
2753
+ /**
2754
+ * Creates a selector that caches and reuses the last computed result
2755
+ * when all input references are unchanged.
2756
+ */
2757
+ function createSelector(...args) {
2758
+ if (args.length === 1) {
2759
+ const projector = args[0];
2760
+ let hasCached = false;
2761
+ let lastState;
2762
+ let lastResult;
2763
+ return (state) => {
2764
+ if (hasCached && state === lastState) return lastResult;
2765
+ lastState = state;
2766
+ lastResult = projector(state);
2767
+ hasCached = true;
2768
+ return lastResult;
2769
+ };
2709
2770
  }
2710
- /**
2711
- * Log a message to the console and emit an error to subscribers.
2712
- * Catches failures from `emitError` itself to prevent unhandled rejections.
2713
- */
2771
+ const projector = args[args.length - 1];
2772
+ const selectors = args.slice(0, -1);
2773
+ let hasCached = false;
2774
+ let lastInputs = [];
2775
+ let lastResult;
2776
+ return (state) => {
2777
+ const inputs = selectors.map((selector) => selector(state));
2778
+ if (hasCached && inputs.length === lastInputs.length && inputs.every((value, index) => value === lastInputs[index])) return lastResult;
2779
+ lastInputs = inputs;
2780
+ lastResult = projector(...inputs);
2781
+ hasCached = true;
2782
+ return lastResult;
2783
+ };
2784
+ }
2785
+ /**
2786
+ * RxJS operator that maps state emissions through a selector and suppresses
2787
+ * unchanged projected values via reference equality.
2788
+ */
2789
+ function select(selector) {
2790
+ return (source$) => source$.pipe(map(selector), distinctUntilChanged());
2791
+ }
2792
+ /**
2793
+ * RxJS operator that filters an action stream by action creators and narrows
2794
+ * the output action type to the matched creator union.
2795
+ *
2796
+ * @throws Error when called without at least one action creator.
2797
+ */
2798
+ function ofType(...creators) {
2799
+ if (creators.length === 0) throw new Error("ofType requires at least one action creator");
2800
+ const actionTypes = new Set(creators.map((creator) => creator.type));
2801
+ return (source$) => {
2802
+ return source$.pipe(filter((action) => {
2803
+ return actionTypes.has(action.type);
2804
+ }));
2805
+ };
2806
+ }
2807
+ /**
2808
+ * Creates an effect descriptor consumed by `createStore`.
2809
+ */
2810
+ function createEffect(factory, options = {}) {
2811
+ if (options.dispatch === false) return {
2812
+ run: factory,
2813
+ dispatch: false
2814
+ };
2815
+ return {
2816
+ run: factory,
2817
+ dispatch: true
2818
+ };
2819
+ }
2820
+ /**
2821
+ * Creates a small observable store with reducer + effects.
2822
+ *
2823
+ * Behavior:
2824
+ * - `init()` starts effects and dispatches `@@micro-redux/init`.
2825
+ * - `stop()` dispatches `@@micro-redux/stop` and unsubscribes all effects.
2826
+ * - Effect action observation is scheduled on `asapScheduler` to avoid
2827
+ * synchronous re-entrancy in the effect loop.
2828
+ * - Any effect error triggers fail-fast teardown and errors both `actions$`
2829
+ * and `state$`.
2830
+ */
2831
+ function createStore(options) {
2832
+ const reducer = options.reducer;
2833
+ const effects = options.effects ?? [];
2834
+ let hasFatalError = false;
2835
+ let isRunning = false;
2836
+ let effectSubscriptions = new Subscription();
2837
+ let currentState = reducer(void 0, INTERNAL_BOOT_ACTION);
2838
+ const stateSubject = new BehaviorSubject(currentState);
2839
+ const actionsSubject = new Subject();
2840
+ const dispatchInternal = (action) => {
2841
+ if (hasFatalError) throw new Error("Store is in a failed state due to an effect error");
2842
+ currentState = reducer(currentState, action);
2843
+ stateSubject.next(currentState);
2844
+ actionsSubject.next(action);
2845
+ };
2846
+ const failFast = (error) => {
2847
+ if (hasFatalError) return;
2848
+ hasFatalError = true;
2849
+ isRunning = false;
2850
+ effectSubscriptions.unsubscribe();
2851
+ effectSubscriptions = new Subscription();
2852
+ actionsSubject.error(error);
2853
+ stateSubject.error(error);
2854
+ };
2855
+ const startEffects = () => {
2856
+ for (const effect of effects) {
2857
+ const scheduledActions$ = actionsSubject.asObservable().pipe(observeOn$1(asapScheduler));
2858
+ const state$ = stateSubject.asObservable();
2859
+ if (effect.dispatch) {
2860
+ const subscription = effect.run(scheduledActions$, state$).subscribe({
2861
+ next: (effectAction) => {
2862
+ if (hasFatalError) return;
2863
+ dispatchInternal(effectAction);
2864
+ },
2865
+ error: (error) => {
2866
+ failFast(error);
2867
+ }
2868
+ });
2869
+ effectSubscriptions.add(subscription);
2870
+ continue;
2871
+ }
2872
+ const subscription = effect.run(scheduledActions$, state$).subscribe({ error: (error) => {
2873
+ failFast(error);
2874
+ } });
2875
+ effectSubscriptions.add(subscription);
2876
+ }
2877
+ };
2878
+ return {
2879
+ dispatch(action) {
2880
+ dispatchInternal(action);
2881
+ },
2882
+ getState() {
2883
+ return currentState;
2884
+ },
2885
+ get state$() {
2886
+ return stateSubject.asObservable();
2887
+ },
2888
+ get actions$() {
2889
+ return actionsSubject.asObservable();
2890
+ },
2891
+ select(selector) {
2892
+ return stateSubject.asObservable().pipe(select(selector));
2893
+ },
2894
+ init() {
2895
+ if (hasFatalError || isRunning) return;
2896
+ isRunning = true;
2897
+ startEffects();
2898
+ if (hasFatalError) return;
2899
+ dispatchInternal({ type: INTERNAL_ACTION_TYPES.init });
2900
+ },
2901
+ stop() {
2902
+ if (hasFatalError || !isRunning) return;
2903
+ dispatchInternal({ type: INTERNAL_ACTION_TYPES.stop });
2904
+ effectSubscriptions.unsubscribe();
2905
+ effectSubscriptions = new Subscription();
2906
+ isRunning = false;
2907
+ }
2908
+ };
2909
+ }
2910
+
2911
+ //#endregion
2912
+ //#region src/memory-errors.ts
2913
+ /**
2914
+ * The memory error registry: the single source of truth for memory error
2915
+ * metadata. Keyed by `code` so a code maps to exactly one category/retryable
2916
+ * default.
2917
+ *
2918
+ * Categories/retryable rationale:
2919
+ * - List/credentials/mutation failures are `dependency` (the runtime/platform
2920
+ * the store calls failed). A 5xx is transient (`retryable: true`); a 4xx is
2921
+ * caller-caused, so the helpers below downgrade those to non-retryable.
2922
+ * - Timeouts are `dependency` and `retryable: true` (the request may simply be
2923
+ * slow).
2924
+ */
2925
+ const MEMORY_ERROR_REGISTRY = Object.freeze({
2926
+ MEMORY_LIST_FAILED: {
2927
+ code: "MEMORY_LIST_FAILED",
2928
+ category: "dependency",
2929
+ retryable: true,
2930
+ message: "Failed to fetch memories",
2931
+ docsPath: "docs/errors/memory.md#memory_list_failed"
2932
+ },
2933
+ MEMORY_CREDENTIALS_FAILED: {
2934
+ code: "MEMORY_CREDENTIALS_FAILED",
2935
+ category: "dependency",
2936
+ retryable: true,
2937
+ message: "Failed to fetch memory subscribe credentials",
2938
+ docsPath: "docs/errors/memory.md#memory_credentials_failed"
2939
+ },
2940
+ MEMORY_MUTATION_FAILED: {
2941
+ code: "MEMORY_MUTATION_FAILED",
2942
+ category: "dependency",
2943
+ retryable: true,
2944
+ message: "Memory mutation request failed",
2945
+ docsPath: "docs/errors/memory.md#memory_mutation_failed"
2946
+ },
2947
+ MEMORY_REQUEST_TIMEOUT: {
2948
+ code: "MEMORY_REQUEST_TIMEOUT",
2949
+ category: "dependency",
2950
+ retryable: true,
2951
+ message: "Request timed out",
2952
+ docsPath: "docs/errors/memory.md#memory_request_timeout"
2953
+ }
2954
+ });
2955
+ /**
2956
+ * An `Error` carrying a stable memory error `code`, `category`, and `retryable`
2957
+ * flag so consumers and observability can branch on it without string-matching
2958
+ * the message.
2959
+ *
2960
+ * It is a real `Error` subclass: `instanceof Error` is true, so the public
2961
+ * `MemoryState.error: Error | null` contract (and the `error: Error | null`
2962
+ * surfaced by `useMemories` / `injectMemories`) holds unchanged. Existing
2963
+ * consumers that only read `.message` keep working; the richer fields are
2964
+ * additive.
2965
+ */
2966
+ var MemoryError = class MemoryError extends Error {
2967
+ /** Stable, machine-readable error identifier. */
2968
+ code;
2969
+ /** Coarse error category for grouping/observability. */
2970
+ category;
2971
+ /** Whether retrying the operation could plausibly succeed. */
2972
+ retryable;
2973
+ /**
2974
+ * @param code - Registry code identifying this error.
2975
+ * @param options - Optional overrides:
2976
+ * - `message`: human-readable message (defaults to the registry message;
2977
+ * callers pass a status-bearing string to preserve prior wording).
2978
+ * - `retryable`: overrides the registry default (e.g. a 4xx list failure is
2979
+ * not retryable even though the code's default is).
2980
+ * - `cause`: the underlying error, preserved for debugging.
2981
+ */
2982
+ constructor(code, options) {
2983
+ const entry = MEMORY_ERROR_REGISTRY[code];
2984
+ super(options?.message ?? entry.message, { cause: options?.cause });
2985
+ this.name = "MemoryError";
2986
+ this.code = code;
2987
+ this.category = entry.category;
2988
+ this.retryable = options?.retryable ?? entry.retryable;
2989
+ Object.setPrototypeOf(this, MemoryError.prototype);
2990
+ }
2991
+ };
2992
+ /**
2993
+ * Narrows an HTTP status to whether the failure is worth retrying: a 5xx (or a
2994
+ * missing/0 status) is a transient dependency failure and retryable; a 4xx is
2995
+ * caller-caused and not. Used so a `MEMORY_LIST_FAILED`/`MEMORY_MUTATION_FAILED`
2996
+ * carries an accurate `retryable` flag derived from the response status.
2997
+ */
2998
+ function isRetryableStatus(status) {
2999
+ return !(Number.isInteger(status) && status >= 400 && status <= 499);
3000
+ }
3001
+
3002
+ //#endregion
3003
+ //#region src/memory.ts
3004
+ const MEMORIES_PATH = "/memories";
3005
+ const MEMORIES_SUBSCRIBE_PATH = "/memories/subscribe";
3006
+ const REQUEST_TIMEOUT_MS$1 = 15e3;
3007
+ /** Consecutive socket errors tolerated before the realtime stream gives up. */
3008
+ const MAX_SOCKET_RETRIES$1 = 5;
3009
+ /**
3010
+ * HTTP status codes that indicate memory routes are not configured (non-fatal).
3011
+ * 404/501 mean the route is absent/unimplemented; 422 is the runtime's
3012
+ * MISSING_INTELLIGENCE signal (intelligence not configured on the deployment —
3013
+ * see packages/runtime/.../handlers/intelligence/memories.ts). All three map to
3014
+ * the graceful "not available" locked-teaser path, not a hard error.
3015
+ */
3016
+ const ROUTE_UNAVAILABLE_STATUSES = new Set([
3017
+ 404,
3018
+ 422,
3019
+ 501
3020
+ ]);
3021
+ /**
3022
+ * Thrown when a memory route returns a 404/422/501 — treated as "not
3023
+ * configured" (422 is the runtime's MISSING_INTELLIGENCE signal).
3024
+ */
3025
+ var MemoryRouteUnavailableError = class extends Error {};
3026
+ const initialMemoryState = Object.freeze({
3027
+ memories: Object.freeze([]),
3028
+ isLoading: false,
3029
+ inFlightMutationCount: 0,
3030
+ error: null,
3031
+ context: null,
3032
+ sessionId: 0,
3033
+ available: true,
3034
+ realtimeStatus: "connecting"
3035
+ });
3036
+ const memoryAdapterEvents = createActionGroup("Memory Adapter", {
3037
+ started: empty(),
3038
+ stopped: empty(),
3039
+ contextChanged: props(),
3040
+ addRequested: props(),
3041
+ updateRequested: props(),
3042
+ removeRequested: props()
3043
+ });
3044
+ const memoryRestEvents = createActionGroup("Memory REST", {
3045
+ listRequested: props(),
3046
+ listSucceeded: props(),
3047
+ listFailed: props(),
3048
+ listUnavailable: props(),
3049
+ mutationFinished: props(),
3050
+ credentialsRequested: props(),
3051
+ credentialsSucceeded: props(),
3052
+ credentialsFailed: props(),
3053
+ credentialsUnavailable: props()
3054
+ });
3055
+ const memoryDomainEvents = createActionGroup("Memory Domain", {
3056
+ memoryUpserted: props(),
3057
+ memoryInvalidated: props(),
3058
+ realtimeConnecting: props(),
3059
+ realtimeConnected: props(),
3060
+ realtimeUnavailable: props()
3061
+ });
3062
+ /** Projects a wire memory to the public {@link Memory} shape (drops tenant ids). */
3063
+ function toMemory(memory) {
3064
+ return {
3065
+ id: memory.id,
3066
+ kind: memory.kind,
3067
+ scope: memory.scope,
3068
+ content: memory.content,
3069
+ sourceThreadIds: memory.sourceThreadIds,
3070
+ invalidatedAt: memory.invalidatedAt
3071
+ };
3072
+ }
3073
+ /**
3074
+ * Maps a realtime `memory_metadata` event to the domain action that applies it:
3075
+ * `created`/`updated` upsert the projected memory, `invalidated` removes it by
3076
+ * id. Carries the current `sessionId` so the reducer's session guard can drop
3077
+ * deltas left over from a previous context.
3078
+ */
3079
+ function mapMemoryMetadataEvent(event, sessionId) {
3080
+ if (event.operation === "invalidated") return memoryDomainEvents.memoryInvalidated({
3081
+ sessionId,
3082
+ memoryId: event.invalidated.id
3083
+ });
3084
+ return memoryDomainEvents.memoryUpserted({
3085
+ sessionId,
3086
+ memory: toMemory(event.memory)
3087
+ });
3088
+ }
3089
+ /**
3090
+ * Inserts or replaces a memory by id. A new memory is prepended (newest first,
3091
+ * matching the REST list's `created_at DESC` ordering without needing a date
3092
+ * field on the public projection); an existing memory is replaced in place.
3093
+ */
3094
+ function upsertMemory(memories, memory) {
3095
+ const existingIndex = memories.findIndex((item) => item.id === memory.id);
3096
+ if (existingIndex === -1) return [memory, ...memories];
3097
+ const next = [...memories];
3098
+ next[existingIndex] = memory;
3099
+ return next;
3100
+ }
3101
+ const memoryReducer = createReducer(initialMemoryState, on(memoryAdapterEvents.contextChanged, (state, { context }) => ({
3102
+ ...state,
3103
+ context,
3104
+ sessionId: state.sessionId + 1,
3105
+ memories: [],
3106
+ isLoading: Boolean(context),
3107
+ inFlightMutationCount: 0,
3108
+ error: null,
3109
+ available: true,
3110
+ realtimeStatus: "connecting"
3111
+ })), on(memoryAdapterEvents.stopped, (state) => ({
3112
+ ...state,
3113
+ memories: [],
3114
+ isLoading: false,
3115
+ inFlightMutationCount: 0,
3116
+ error: null,
3117
+ available: true,
3118
+ realtimeStatus: "connecting"
3119
+ })), on(memoryRestEvents.listRequested, (state, { sessionId }) => {
3120
+ if (sessionId !== state.sessionId || !state.context) return state;
3121
+ return {
3122
+ ...state,
3123
+ isLoading: true,
3124
+ error: null,
3125
+ available: true
3126
+ };
3127
+ }), on(memoryRestEvents.listFailed, (state, { sessionId, error }) => {
3128
+ if (sessionId !== state.sessionId) return state;
3129
+ return {
3130
+ ...state,
3131
+ isLoading: false,
3132
+ error
3133
+ };
3134
+ }), on(memoryRestEvents.listUnavailable, (state, { sessionId }) => {
3135
+ if (sessionId !== state.sessionId) return state;
3136
+ return {
3137
+ ...state,
3138
+ memories: [],
3139
+ isLoading: false,
3140
+ error: null,
3141
+ available: false
3142
+ };
3143
+ }), on(memoryAdapterEvents.addRequested, memoryAdapterEvents.updateRequested, memoryAdapterEvents.removeRequested, (state) => ({
3144
+ ...state,
3145
+ inFlightMutationCount: state.inFlightMutationCount + 1
3146
+ })), on(memoryRestEvents.mutationFinished, (state, { outcome }) => {
3147
+ if (outcome.sessionId !== state.sessionId) return state;
3148
+ return {
3149
+ ...state,
3150
+ inFlightMutationCount: Math.max(0, state.inFlightMutationCount - 1),
3151
+ error: outcome.ok ? null : outcome.error
3152
+ };
3153
+ }), on(memoryRestEvents.listSucceeded, (state, { sessionId, memories }) => {
3154
+ if (sessionId !== state.sessionId) return state;
3155
+ return {
3156
+ ...state,
3157
+ memories,
3158
+ isLoading: false,
3159
+ error: null,
3160
+ available: true
3161
+ };
3162
+ }), on(memoryDomainEvents.memoryUpserted, (state, { sessionId, memory }) => {
3163
+ if (sessionId !== state.sessionId) return state;
3164
+ return {
3165
+ ...state,
3166
+ memories: upsertMemory(state.memories, memory)
3167
+ };
3168
+ }), on(memoryDomainEvents.memoryInvalidated, (state, { sessionId, memoryId }) => {
3169
+ if (sessionId !== state.sessionId) return state;
3170
+ return {
3171
+ ...state,
3172
+ memories: state.memories.filter((memory) => memory.id !== memoryId)
3173
+ };
3174
+ }), on(memoryDomainEvents.realtimeConnecting, (state, { sessionId }) => {
3175
+ if (sessionId !== state.sessionId) return state;
3176
+ return {
3177
+ ...state,
3178
+ realtimeStatus: "connecting"
3179
+ };
3180
+ }), on(memoryDomainEvents.realtimeConnected, (state, { sessionId }) => {
3181
+ if (sessionId !== state.sessionId) return state;
3182
+ return {
3183
+ ...state,
3184
+ realtimeStatus: "connected"
3185
+ };
3186
+ }), on(memoryDomainEvents.realtimeUnavailable, (state, { sessionId }) => {
3187
+ if (sessionId !== state.sessionId) return state;
3188
+ return {
3189
+ ...state,
3190
+ realtimeStatus: "unavailable"
3191
+ };
3192
+ }));
3193
+ const selectMemories = createSelector((state) => state.memories);
3194
+ const selectMemoriesIsLoading = createSelector((state) => state.isLoading);
3195
+ const selectMemoriesError = createSelector((state) => state.error);
3196
+ /**
3197
+ * Reports whether at least one mutation is in flight. Derived from
3198
+ * `inFlightMutationCount` so concurrent mutations stay correct: the boolean
3199
+ * only clears once every in-flight mutation has settled.
3200
+ */
3201
+ const selectMemoriesIsMutating = createSelector((state) => state.inFlightMutationCount > 0);
3202
+ /**
3203
+ * Reports whether the memory routes are available. Becomes `false` after a
3204
+ * 404, 422 (the runtime's MISSING_INTELLIGENCE signal), or 501 response during
3205
+ * an auto-activation read; defaults to `true`.
3206
+ */
3207
+ const selectMemoriesAvailable = createSelector((state) => state.available);
3208
+ /**
3209
+ * Reports the realtime-connection health (see {@link MemoryRealtimeStatus}).
3210
+ * Distinct from `available`/`error`: it reflects ONLY the live socket/channel,
3211
+ * so the UI can suppress a "live" indicator once realtime permanently dies even
3212
+ * while the REST list route stays healthy. Defaults to `"connecting"`.
3213
+ */
3214
+ const selectMemoriesRealtimeStatus = createSelector((state) => state.realtimeStatus);
3215
+ const MEMORY_METADATA_EVENT = "memory_metadata";
3216
+ function memoryFromFetch(input, init) {
3217
+ return fromFetch(input, init);
3218
+ }
3219
+ /**
3220
+ * Fetches the memory snapshot and maps it to a success/failure action. Keeps
3221
+ * only user-scoped memories (v1 surfaces user scope only; the realtime stream
3222
+ * is user-scoped too), so project-scoped rows visible to the caller are
3223
+ * dropped from the store.
3224
+ */
3225
+ function createMemoryFetchObservable(environment, context, sessionId) {
3226
+ return defer(() => {
3227
+ const qs = context.includeInvalidated ? "?includeInvalidated=true" : "";
3228
+ return memoryFromFetch(`${context.runtimeUrl}${MEMORIES_PATH}${qs}`, {
3229
+ selector: (response) => {
3230
+ if (!response.ok) {
3231
+ if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) throw new MemoryRouteUnavailableError(String(response.status));
3232
+ throw new MemoryError("MEMORY_LIST_FAILED", {
3233
+ message: `Failed to fetch memories: ${response.status}`,
3234
+ retryable: isRetryableStatus(response.status)
3235
+ });
3236
+ }
3237
+ return response.json();
3238
+ },
3239
+ fetch: environment.fetch,
3240
+ method: "GET",
3241
+ headers: { ...context.headers }
3242
+ }).pipe(timeout({
3243
+ first: REQUEST_TIMEOUT_MS$1,
3244
+ with: () => {
3245
+ throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
3246
+ }
3247
+ }), map((data) => memoryRestEvents.listSucceeded({
3248
+ sessionId,
3249
+ memories: data.memories.filter((memory) => memory.scope === "user")
3250
+ })), catchError((error) => {
3251
+ if (error instanceof MemoryRouteUnavailableError) return of(memoryRestEvents.listUnavailable({ sessionId }));
3252
+ return of(memoryRestEvents.listFailed({
3253
+ sessionId,
3254
+ error: error instanceof Error ? error : new Error(String(error))
3255
+ }));
3256
+ }));
3257
+ });
3258
+ }
3259
+ /**
3260
+ * Fetches join credentials from the `/memories/subscribe` endpoint and maps
3261
+ * the response to a success/failure action. Requires both `joinToken` and
3262
+ * `joinCode` to be non-empty strings; throws otherwise so the `catchError`
3263
+ * path emits `credentialsFailed`.
3264
+ */
3265
+ function createMemoryCredentialsFetchObservable(environment, context, sessionId) {
3266
+ return defer(() => memoryFromFetch(`${context.runtimeUrl}${MEMORIES_SUBSCRIBE_PATH}`, {
3267
+ selector: async (response) => {
3268
+ if (!response.ok) {
3269
+ if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) throw new MemoryRouteUnavailableError(String(response.status));
3270
+ throw new MemoryError("MEMORY_CREDENTIALS_FAILED", {
3271
+ message: `Failed to fetch memory subscribe credentials: ${response.status}`,
3272
+ retryable: isRetryableStatus(response.status)
3273
+ });
3274
+ }
3275
+ return response.json();
3276
+ },
3277
+ fetch: environment.fetch,
3278
+ method: "POST",
3279
+ headers: {
3280
+ ...context.headers,
3281
+ "Content-Type": "application/json"
3282
+ },
3283
+ body: JSON.stringify({})
3284
+ }).pipe(timeout({
3285
+ first: REQUEST_TIMEOUT_MS$1,
3286
+ with: () => {
3287
+ throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
3288
+ }
3289
+ }), map((data) => {
3290
+ if (typeof data.joinToken !== "string" || data.joinToken.length === 0) throw new Error("missing joinToken");
3291
+ if (typeof data.joinCode !== "string" || data.joinCode.length === 0) throw new Error("missing joinCode");
3292
+ return memoryRestEvents.credentialsSucceeded({
3293
+ sessionId,
3294
+ joinToken: data.joinToken,
3295
+ joinCode: data.joinCode
3296
+ });
3297
+ }), catchError((error) => {
3298
+ if (error instanceof MemoryRouteUnavailableError) return of(memoryRestEvents.credentialsUnavailable({ sessionId }));
3299
+ return of(memoryRestEvents.credentialsFailed({
3300
+ sessionId,
3301
+ error: error instanceof Error ? error : new Error(String(error))
3302
+ }));
3303
+ })));
3304
+ }
3305
+ /** Projects a REST mutation response to the public {@link Memory} shape. */
3306
+ function responseToMemory(data) {
3307
+ return {
3308
+ id: data.id,
3309
+ kind: data.kind,
3310
+ scope: data.scope,
3311
+ content: data.content,
3312
+ sourceThreadIds: data.sourceThreadIds,
3313
+ invalidatedAt: data.invalidatedAt
3314
+ };
3315
+ }
3316
+ const MEMORY_KINDS = new Set([
3317
+ "topical",
3318
+ "episodic",
3319
+ "operational"
3320
+ ]);
3321
+ const MEMORY_SCOPES = new Set(["user", "project"]);
3322
+ /**
3323
+ * Validates the required fields of a create/supersede REST response before it is
3324
+ * projected to a {@link Memory}. Returns an `Error` describing the first
3325
+ * missing/invalid field, or `null` when the body is well-formed. Without this a
3326
+ * malformed 200 body yields a Memory with undefined fields that gets upserted.
3327
+ */
3328
+ function validateMutationResponse(data) {
3329
+ if (!data || typeof data !== "object") return /* @__PURE__ */ new Error("memory mutation response missing/invalid body");
3330
+ if (typeof data.id !== "string" || data.id.length === 0) return /* @__PURE__ */ new Error("memory mutation response missing/invalid id");
3331
+ if (typeof data.kind !== "string" || !MEMORY_KINDS.has(data.kind)) return /* @__PURE__ */ new Error("memory mutation response missing/invalid kind");
3332
+ if (typeof data.scope !== "string" || !MEMORY_SCOPES.has(data.scope)) return /* @__PURE__ */ new Error("memory mutation response missing/invalid scope");
3333
+ if (typeof data.content !== "string") return /* @__PURE__ */ new Error("memory mutation response missing/invalid content");
3334
+ if (!Array.isArray(data.sourceThreadIds) || !data.sourceThreadIds.every((id) => typeof id === "string")) return /* @__PURE__ */ new Error("memory mutation response missing/invalid sourceThreadIds");
3335
+ if (data.invalidatedAt !== null && typeof data.invalidatedAt !== "string") return /* @__PURE__ */ new Error("memory mutation response missing/invalid invalidatedAt");
3336
+ return null;
3337
+ }
3338
+ /**
3339
+ * Request body for create/supersede. `scope` is forwarded only when the caller
3340
+ * supplies it: the platform owns the default (`scope` defaults to `"user"` in
3341
+ * the `/api/memories` schema), so the store does not second-guess it here —
3342
+ * one default, at the contract owner. `sourceThreadIds` defaults to `[]`.
3343
+ */
3344
+ function toMutationBody(input) {
3345
+ return {
3346
+ content: input.content,
3347
+ kind: input.kind,
3348
+ ...input.scope !== void 0 ? { scope: input.scope } : {},
3349
+ sourceThreadIds: input.sourceThreadIds ?? []
3350
+ };
3351
+ }
3352
+ /**
3353
+ * Builds the actions a successful mutation dispatches (server-authoritative):
3354
+ * the REST response is applied to local state immediately, and the realtime
3355
+ * event reconciles idempotently (upsert-by-id). `mutationFinished` resolves the
3356
+ * caller's promise.
3357
+ */
3358
+ function buildMutationSuccessActions(request, data) {
3359
+ const { requestId, sessionId } = request;
3360
+ if (request.kind === "remove") return [memoryDomainEvents.memoryInvalidated({
3361
+ sessionId,
3362
+ memoryId: request.id
3363
+ }), memoryRestEvents.mutationFinished({ outcome: {
3364
+ requestId,
3365
+ sessionId,
3366
+ ok: true,
3367
+ memory: null
3368
+ } })];
3369
+ const validationError = validateMutationResponse(data);
3370
+ if (validationError) return [memoryRestEvents.mutationFinished({ outcome: {
3371
+ requestId,
3372
+ sessionId,
3373
+ ok: false,
3374
+ error: validationError
3375
+ } })];
3376
+ const memory = responseToMemory(data);
3377
+ if (request.kind === "update") {
3378
+ const retiredId = data.retiredId;
3379
+ if (typeof retiredId !== "string" || retiredId.length === 0) return [memoryRestEvents.mutationFinished({ outcome: {
3380
+ requestId,
3381
+ sessionId,
3382
+ ok: false,
3383
+ error: /* @__PURE__ */ new Error("supersede response missing retiredId")
3384
+ } })];
3385
+ return [
3386
+ memoryDomainEvents.memoryInvalidated({
3387
+ sessionId,
3388
+ memoryId: retiredId
3389
+ }),
3390
+ memoryDomainEvents.memoryUpserted({
3391
+ sessionId,
3392
+ memory
3393
+ }),
3394
+ memoryRestEvents.mutationFinished({ outcome: {
3395
+ requestId,
3396
+ sessionId,
3397
+ ok: true,
3398
+ memory
3399
+ } })
3400
+ ];
3401
+ }
3402
+ return [memoryDomainEvents.memoryUpserted({
3403
+ sessionId,
3404
+ memory
3405
+ }), memoryRestEvents.mutationFinished({ outcome: {
3406
+ requestId,
3407
+ sessionId,
3408
+ ok: true,
3409
+ memory
3410
+ } })];
3411
+ }
3412
+ /** Performs a create/supersede/retire HTTP call and emits its resulting actions. */
3413
+ function createMemoryMutationObservable(environment, context, request) {
3414
+ const method = request.kind === "add" ? "POST" : request.kind === "update" ? "PATCH" : "DELETE";
3415
+ const path = request.kind === "add" ? MEMORIES_PATH : `${MEMORIES_PATH}/${encodeURIComponent(request.id)}`;
3416
+ return defer(() => memoryFromFetch(`${context.runtimeUrl}${path}`, {
3417
+ selector: async (response) => {
3418
+ if (!response.ok) throw new MemoryError("MEMORY_MUTATION_FAILED", {
3419
+ message: `Request failed: ${response.status}`,
3420
+ retryable: isRetryableStatus(response.status)
3421
+ });
3422
+ return request.kind === "remove" ? null : await response.json();
3423
+ },
3424
+ fetch: environment.fetch,
3425
+ method,
3426
+ headers: {
3427
+ ...context.headers,
3428
+ "Content-Type": "application/json"
3429
+ },
3430
+ body: request.kind === "remove" ? void 0 : JSON.stringify(request.body)
3431
+ }).pipe(timeout({
3432
+ first: REQUEST_TIMEOUT_MS$1,
3433
+ with: () => {
3434
+ throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
3435
+ }
3436
+ }), mergeMap((data) => of(...buildMutationSuccessActions(request, data))), catchError((error) => of(memoryRestEvents.mutationFinished({ outcome: {
3437
+ requestId: request.requestId,
3438
+ sessionId: request.sessionId,
3439
+ ok: false,
3440
+ error: error instanceof Error ? error : new Error(String(error))
3441
+ } })))));
3442
+ }
3443
+ /**
3444
+ * Creates the framework-agnostic memory store: a REST snapshot on `setContext`,
3445
+ * server-authoritative add/update/remove mutations, and realtime
3446
+ * `memory_metadata` deltas off the injected `user_meta` event source — all
3447
+ * reduced into observable state.
3448
+ */
3449
+ function createMemoryStore(environment) {
3450
+ let memoryRequestId = 0;
3451
+ const createMemoryRequestId = () => {
3452
+ memoryRequestId += 1;
3453
+ return `memory-request-${memoryRequestId}`;
3454
+ };
3455
+ const bootstrapEffect = createEffect((actions$, state$) => actions$.pipe(ofType(memoryAdapterEvents.contextChanged), withLatestFrom(state$), filter(([, state]) => Boolean(state.context)), map(([, state]) => memoryRestEvents.listRequested({ sessionId: state.sessionId }))));
3456
+ const credentialsBootstrapEffect = createEffect((actions$, state$) => actions$.pipe(ofType(memoryAdapterEvents.contextChanged), withLatestFrom(state$), filter(([, state]) => Boolean(state.context)), map(([, state]) => memoryRestEvents.credentialsRequested({ sessionId: state.sessionId }))));
3457
+ const credentialsFetchEffect = createEffect((actions$, state$) => actions$.pipe(ofType(memoryRestEvents.credentialsRequested), switchMap$1((action) => state$.pipe(map((state) => state.context), filter((context) => Boolean(context)), take(1), map((context) => ({
3458
+ action,
3459
+ context
3460
+ })), takeUntil(actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped))), switchMap$1(({ action: currentAction, context }) => createMemoryCredentialsFetchObservable(environment, context, currentAction.sessionId))))));
3461
+ const store = createStore({
3462
+ reducer: memoryReducer,
3463
+ effects: [
3464
+ bootstrapEffect,
3465
+ credentialsBootstrapEffect,
3466
+ createEffect((actions$, state$) => actions$.pipe(ofType(memoryRestEvents.listRequested), switchMap$1((action) => state$.pipe(map((state) => state.context), filter((context) => Boolean(context)), take(1), map((context) => ({
3467
+ action,
3468
+ context
3469
+ })), takeUntil(actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped))), switchMap$1(({ action: currentAction, context }) => createMemoryFetchObservable(environment, context, currentAction.sessionId)))))),
3470
+ credentialsFetchEffect,
3471
+ createEffect((actions$, state$) => actions$.pipe(ofType(memoryAdapterEvents.addRequested, memoryAdapterEvents.updateRequested, memoryAdapterEvents.removeRequested), withLatestFrom(state$), mergeMap(([action, state]) => {
3472
+ const context = state.context;
3473
+ const sessionId = state.sessionId;
3474
+ if (!context?.runtimeUrl) return of(memoryRestEvents.mutationFinished({ outcome: {
3475
+ requestId: action.requestId,
3476
+ sessionId,
3477
+ ok: false,
3478
+ error: /* @__PURE__ */ new Error("Runtime URL is not configured")
3479
+ } }));
3480
+ if (memoryAdapterEvents.addRequested.match(action)) return createMemoryMutationObservable(environment, context, {
3481
+ requestId: action.requestId,
3482
+ sessionId,
3483
+ kind: "add",
3484
+ body: toMutationBody(action.input)
3485
+ });
3486
+ if (memoryAdapterEvents.updateRequested.match(action)) return createMemoryMutationObservable(environment, context, {
3487
+ requestId: action.requestId,
3488
+ sessionId,
3489
+ kind: "update",
3490
+ id: action.id,
3491
+ body: toMutationBody(action.changes)
3492
+ });
3493
+ return createMemoryMutationObservable(environment, context, {
3494
+ requestId: action.requestId,
3495
+ sessionId,
3496
+ kind: "remove",
3497
+ id: action.id
3498
+ });
3499
+ }))),
3500
+ createEffect((actions$, state$) => actions$.pipe(ofType(memoryRestEvents.credentialsSucceeded), withLatestFrom(state$), filter(([action, state]) => {
3501
+ return action.sessionId === state.sessionId && Boolean(state.context?.wsUrl);
3502
+ }), switchMap$1(([action, state]) => {
3503
+ const context = state.context;
3504
+ const { joinToken, joinCode } = action;
3505
+ const sessionId = action.sessionId;
3506
+ const shutdown$ = actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped));
3507
+ return defer(() => {
3508
+ const socket$ = ɵphoenixSocket$({
3509
+ url: context.wsUrl,
3510
+ options: {
3511
+ params: { join_token: joinToken },
3512
+ reconnectAfterMs: phoenixExponentialBackoff(100, 1e4),
3513
+ rejoinAfterMs: phoenixExponentialBackoff(1e3, 3e4)
3514
+ }
3515
+ }).pipe(shareReplay({
3516
+ bufferSize: 1,
3517
+ refCount: true
3518
+ }));
3519
+ const channel$ = ɵphoenixChannel$({
3520
+ socket$,
3521
+ topic: `user_meta:memories:${joinCode}`
3522
+ }).pipe(shareReplay({
3523
+ bufferSize: 1,
3524
+ refCount: true
3525
+ }));
3526
+ const fatalSocketShutdown$ = ɵobservePhoenixSocketHealth$(ɵobservePhoenixSocketSignals$(socket$).pipe(share()), MAX_SOCKET_RETRIES$1).pipe(catchError(() => {
3527
+ console.warn(`[memory] WebSocket failed after ${MAX_SOCKET_RETRIES$1} attempts, giving up`);
3528
+ return of(void 0);
3529
+ }), share());
3530
+ const fatalStatus$ = fatalSocketShutdown$.pipe(map(() => memoryDomainEvents.realtimeUnavailable({ sessionId })));
3531
+ const metadata$ = channel$.pipe(switchMap$1(({ channel }) => ɵobservePhoenixEvent$(channel, MEMORY_METADATA_EVENT)), map((event) => mapMemoryMetadataEvent(event, action.sessionId)));
3532
+ const join$ = ɵjoinPhoenixChannel$(channel$).pipe(concatWith(of(memoryDomainEvents.realtimeConnected({ sessionId }))), catchError((error) => {
3533
+ console.warn(`[memory] failed to join user_meta:memories:${joinCode}`, error);
3534
+ return of(memoryDomainEvents.realtimeUnavailable({ sessionId }));
3535
+ }));
3536
+ return merge(of(memoryDomainEvents.realtimeConnecting({ sessionId })), metadata$, join$, fatalStatus$).pipe(takeUntil(merge(shutdown$, fatalSocketShutdown$.pipe(observeOn(asapScheduler)))), finalize(() => {}));
3537
+ });
3538
+ })))
3539
+ ]
3540
+ });
3541
+ function trackMutation(dispatchAction, extract) {
3542
+ const { requestId } = dispatchAction;
3543
+ const resultPromise = firstValueFrom(merge(store.actions$.pipe(ofType(memoryRestEvents.mutationFinished), filter((action) => action.outcome.requestId === requestId), map((action) => action.outcome)), store.actions$.pipe(ofType(memoryAdapterEvents.stopped), map(() => ({
3544
+ requestId,
3545
+ sessionId: store.getState().sessionId,
3546
+ ok: false,
3547
+ error: /* @__PURE__ */ new Error("Memory store stopped before mutation completed")
3548
+ })))).pipe(take(1))).then((outcome) => {
3549
+ if (!outcome.ok) throw outcome.error;
3550
+ return extract(outcome);
3551
+ });
3552
+ store.dispatch(dispatchAction);
3553
+ return resultPromise;
3554
+ }
3555
+ return {
3556
+ start() {
3557
+ store.init();
3558
+ store.dispatch(memoryAdapterEvents.started());
3559
+ },
3560
+ stop() {
3561
+ store.dispatch(memoryAdapterEvents.stopped());
3562
+ store.stop();
3563
+ },
3564
+ setContext(context) {
3565
+ store.dispatch(memoryAdapterEvents.contextChanged({ context }));
3566
+ },
3567
+ refresh() {
3568
+ const { sessionId, context } = store.getState();
3569
+ if (!context) return Promise.resolve();
3570
+ const done = firstValueFrom(merge(store.actions$.pipe(ofType(memoryRestEvents.listSucceeded, memoryRestEvents.listFailed, memoryRestEvents.listUnavailable), filter((action) => action.sessionId === sessionId)), store.actions$.pipe(ofType(memoryAdapterEvents.stopped)), store.actions$.pipe(ofType(memoryAdapterEvents.contextChanged))).pipe(take(1))).then((action) => {
3571
+ if (memoryRestEvents.listFailed.match(action)) throw action.error;
3572
+ if (memoryAdapterEvents.stopped.match(action)) throw new Error("Memory store stopped before refresh completed");
3573
+ if (memoryAdapterEvents.contextChanged.match(action)) return;
3574
+ });
3575
+ store.dispatch(memoryRestEvents.listRequested({ sessionId }));
3576
+ return done;
3577
+ },
3578
+ addMemory(input) {
3579
+ return trackMutation(memoryAdapterEvents.addRequested({
3580
+ requestId: createMemoryRequestId(),
3581
+ input
3582
+ }), (outcome) => {
3583
+ if (outcome.memory == null) throw new Error("add resolved without a memory");
3584
+ return outcome.memory;
3585
+ });
3586
+ },
3587
+ updateMemory(id, changes) {
3588
+ return trackMutation(memoryAdapterEvents.updateRequested({
3589
+ requestId: createMemoryRequestId(),
3590
+ id,
3591
+ changes
3592
+ }), (outcome) => {
3593
+ if (outcome.memory == null) throw new Error("update resolved without a memory");
3594
+ return outcome.memory;
3595
+ });
3596
+ },
3597
+ removeMemory(id) {
3598
+ return trackMutation(memoryAdapterEvents.removeRequested({
3599
+ requestId: createMemoryRequestId(),
3600
+ id
3601
+ }), () => void 0);
3602
+ },
3603
+ getState() {
3604
+ return store.getState();
3605
+ },
3606
+ getServerState() {
3607
+ return initialMemoryState;
3608
+ },
3609
+ select: store.select.bind(store)
3610
+ };
3611
+ }
3612
+ const ɵmemoryAdapterEvents = memoryAdapterEvents;
3613
+ const ɵmemoryRestEvents = memoryRestEvents;
3614
+ const ɵmemoryDomainEvents = memoryDomainEvents;
3615
+ const ɵmemoryReducer = memoryReducer;
3616
+ const ɵmapMemoryMetadataEvent = mapMemoryMetadataEvent;
3617
+ const ɵselectMemories = selectMemories;
3618
+ const ɵselectMemoriesIsLoading = selectMemoriesIsLoading;
3619
+ const ɵselectMemoriesError = selectMemoriesError;
3620
+ const ɵselectMemoriesIsMutating = selectMemoriesIsMutating;
3621
+ const ɵselectMemoriesAvailable = selectMemoriesAvailable;
3622
+ const ɵselectMemoriesRealtimeStatus = selectMemoriesRealtimeStatus;
3623
+
3624
+ //#endregion
3625
+ //#region src/core/core.ts
3626
+ let CopilotKitCoreErrorCode = /* @__PURE__ */ function(CopilotKitCoreErrorCode) {
3627
+ CopilotKitCoreErrorCode["RUNTIME_INFO_FETCH_FAILED"] = "runtime_info_fetch_failed";
3628
+ CopilotKitCoreErrorCode["AGENT_CONNECT_FAILED"] = "agent_connect_failed";
3629
+ CopilotKitCoreErrorCode["AGENT_RUN_FAILED"] = "agent_run_failed";
3630
+ CopilotKitCoreErrorCode["AGENT_RUN_FAILED_EVENT"] = "agent_run_failed_event";
3631
+ CopilotKitCoreErrorCode["AGENT_RUN_ERROR_EVENT"] = "agent_run_error_event";
3632
+ CopilotKitCoreErrorCode["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
3633
+ CopilotKitCoreErrorCode["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
3634
+ CopilotKitCoreErrorCode["TOOL_NOT_FOUND"] = "tool_not_found";
3635
+ CopilotKitCoreErrorCode["AGENT_NOT_FOUND"] = "agent_not_found";
3636
+ /**
3637
+ * Emitted when an agent run fails because the thread is already locked
3638
+ * by another active run.
3639
+ *
3640
+ * @example
3641
+ * ```tsx
3642
+ * <CopilotKitProvider
3643
+ * onError={({ code, error, context }) => {
3644
+ * if (code === "agent_thread_locked") {
3645
+ * // Show "Agent is busy, retry?" UI
3646
+ * }
3647
+ * }}
3648
+ * />
3649
+ * ```
3650
+ */
3651
+ CopilotKitCoreErrorCode["AGENT_THREAD_LOCKED"] = "agent_thread_locked";
3652
+ CopilotKitCoreErrorCode["TRANSCRIPTION_FAILED"] = "transcription_failed";
3653
+ CopilotKitCoreErrorCode["TRANSCRIPTION_SERVICE_NOT_CONFIGURED"] = "transcription_service_not_configured";
3654
+ CopilotKitCoreErrorCode["TRANSCRIPTION_INVALID_AUDIO"] = "transcription_invalid_audio";
3655
+ CopilotKitCoreErrorCode["TRANSCRIPTION_RATE_LIMITED"] = "transcription_rate_limited";
3656
+ CopilotKitCoreErrorCode["TRANSCRIPTION_AUTH_FAILED"] = "transcription_auth_failed";
3657
+ CopilotKitCoreErrorCode["TRANSCRIPTION_NETWORK_ERROR"] = "transcription_network_error";
3658
+ CopilotKitCoreErrorCode["SUBSCRIBER_CALLBACK_FAILED"] = "subscriber_callback_failed";
3659
+ return CopilotKitCoreErrorCode;
3660
+ }({});
3661
+ /**
3662
+ * Runtime allowlist derived from {@link SUBSCRIBE_TO_AGENT_KEYS}. Hoisted
3663
+ * to module scope so the Set is allocated once, not per-subscription.
3664
+ */
3665
+ const ALLOWED_KEYS = new Set([
3666
+ "onMessagesChanged",
3667
+ "onStateChanged",
3668
+ "onRunInitialized",
3669
+ "onRunFinalized",
3670
+ "onRunFailed",
3671
+ "onRunErrorEvent"
3672
+ ]);
3673
+ let CopilotKitCoreRuntimeConnectionStatus = /* @__PURE__ */ function(CopilotKitCoreRuntimeConnectionStatus) {
3674
+ CopilotKitCoreRuntimeConnectionStatus["Disconnected"] = "disconnected";
3675
+ CopilotKitCoreRuntimeConnectionStatus["Connected"] = "connected";
3676
+ CopilotKitCoreRuntimeConnectionStatus["Connecting"] = "connecting";
3677
+ CopilotKitCoreRuntimeConnectionStatus["Error"] = "error";
3678
+ return CopilotKitCoreRuntimeConnectionStatus;
3679
+ }({});
3680
+ /**
3681
+ * Normalize a header map to the internal invariant: a `Record<string, string>`
3682
+ * with no `null`/`undefined` values. Entries whose value is `null`/`undefined`
3683
+ * are dropped (this is how a header is cleared). Shared by the constructor and
3684
+ * `setHeaders` so both write paths into `_headers` enforce the same invariant.
3685
+ */
3686
+ function normalizeHeaders(headers) {
3687
+ return Object.fromEntries(Object.entries(headers).filter((entry) => entry[1] != null));
3688
+ }
3689
+ var CopilotKitCore = class {
3690
+ _headers;
3691
+ _credentials;
3692
+ _properties;
3693
+ _defaultThrottleMs;
3694
+ _debug;
3695
+ subscribers = /* @__PURE__ */ new Set();
3696
+ agentRegistry;
3697
+ contextStore;
3698
+ suggestionEngine;
3699
+ runHandler;
3700
+ stateManager;
3701
+ threadStoreRegistry;
3702
+ /**
3703
+ * The single core-owned memory store, created lazily on first
3704
+ * `getMemoryStore()` and kept user-scoped for the lifetime of the core.
3705
+ * Its runtime context is wired by the core itself (see `syncMemoryContext`),
3706
+ * so callers never register or look it up by `agentId`.
3707
+ */
3708
+ _memoryStore;
3709
+ /**
3710
+ * Tracks the agent IDs from the most recent `onAgentsChanged` notification.
3711
+ * Used to gate thread-store auto-unregister so the FIRST empty-agents
3712
+ * notification (before published agents are merged in) does not rip out a
3713
+ * store that was registered prior to that initial notification.
3714
+ */
3715
+ previousAgentIds = /* @__PURE__ */ new Set();
3716
+ constructor({ runtimeUrl, runtimeTransport = "auto", deferInitialConnection = false, headers = {}, credentials, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [], debug }) {
3717
+ this._headers = normalizeHeaders(headers);
3718
+ this._credentials = credentials;
3719
+ this._properties = properties;
3720
+ this._debug = debug;
3721
+ this.agentRegistry = new AgentRegistry(this);
3722
+ this.contextStore = new ContextStore(this);
3723
+ this.suggestionEngine = new SuggestionEngine(this);
3724
+ this.runHandler = new RunHandler(this);
3725
+ this.stateManager = new StateManager(this);
3726
+ this.threadStoreRegistry = new ThreadStoreRegistry(this);
3727
+ this.agentRegistry.initialize(agents__unsafe_dev_only);
3728
+ this.runHandler.initialize(tools);
3729
+ this.suggestionEngine.initialize(suggestionsConfig);
3730
+ this.stateManager.initialize();
3731
+ this.agentRegistry.setRuntimeTransport(runtimeTransport);
3732
+ this.agentRegistry.setRuntimeUrl(runtimeUrl, { deferConnection: deferInitialConnection });
3733
+ this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));
3734
+ this.subscribe({
3735
+ onRuntimeConnectionStatusChanged: () => {
3736
+ if (this._memoryStore) this.syncMemoryContext();
3737
+ },
3738
+ onAgentsChanged: ({ agents }) => {
3739
+ Object.values(agents).forEach((agent) => {
3740
+ if (agent.agentId) this.stateManager.subscribeToAgent(agent);
3741
+ });
3742
+ const currentAgentIds = new Set(Object.keys(agents));
3743
+ for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
3744
+ this.threadStoreRegistry.unregister(agentId);
3745
+ } catch (err) {
3746
+ console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
3747
+ }
3748
+ for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) try {
3749
+ this.stateManager.unsubscribeFromAgent(agentId);
3750
+ } catch (err) {
3751
+ console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
3752
+ }
3753
+ this.previousAgentIds = currentAgentIds;
3754
+ }
3755
+ });
3756
+ }
3757
+ /**
3758
+ * Internal method used by delegate classes and subclasses to notify subscribers
3759
+ */
3760
+ async notifySubscribers(handler, errorMessage) {
3761
+ await Promise.all(Array.from(this.subscribers).map(async (subscriber) => {
3762
+ try {
3763
+ await handler(subscriber);
3764
+ } catch (error) {
3765
+ console.error(errorMessage, error);
3766
+ }
3767
+ }));
3768
+ }
3769
+ /**
3770
+ * Internal method used by delegate classes to emit errors
3771
+ */
3772
+ async emitError({ error, code, context = {} }) {
3773
+ await this.notifySubscribers((subscriber) => subscriber.onError?.({
3774
+ copilotkit: this,
3775
+ error,
3776
+ code,
3777
+ context
3778
+ }), "Subscriber onError error:");
3779
+ }
3780
+ /**
3781
+ * Log a message to the console and emit an error to subscribers.
3782
+ * Catches failures from `emitError` itself to prevent unhandled rejections.
3783
+ */
2714
3784
  logAndEmitError(message, params, logLevel = "error") {
2715
3785
  console[logLevel](message, params.error);
2716
3786
  this.emitError(params).catch((emitErr) => {
@@ -2735,6 +3805,18 @@ var CopilotKitCore = class {
2735
3805
  setRuntimeUrl(runtimeUrl) {
2736
3806
  this.agentRegistry.setRuntimeUrl(runtimeUrl);
2737
3807
  }
3808
+ /**
3809
+ * Start the runtime `/info` connection if it has not been started yet.
3810
+ *
3811
+ * Intended to be driven from a host's commit-phase effect when the core was
3812
+ * constructed with {@link CopilotKitCoreConfig.deferInitialConnection}. Safe
3813
+ * to call repeatedly — it is a no-op once a connection is in progress or
3814
+ * settled, so a double-invoked mount effect (React StrictMode) collapses to a
3815
+ * single request. See #5801.
3816
+ */
3817
+ connect() {
3818
+ this.agentRegistry.connectRuntime();
3819
+ }
2738
3820
  get runtimeTransport() {
2739
3821
  return this.agentRegistry.runtimeTransport;
2740
3822
  }
@@ -2803,6 +3885,9 @@ var CopilotKitCore = class {
2803
3885
  get threadEndpoints() {
2804
3886
  return this.agentRegistry.threadEndpoints;
2805
3887
  }
3888
+ get suggestions() {
3889
+ return this.agentRegistry.suggestions;
3890
+ }
2806
3891
  get a2uiEnabled() {
2807
3892
  return this.agentRegistry.a2uiEnabled;
2808
3893
  }
@@ -2856,6 +3941,7 @@ var CopilotKitCore = class {
2856
3941
  */
2857
3942
  setHeaders(headers) {
2858
3943
  this._headers = normalizeHeaders(headers);
3944
+ if (this._memoryStore) this.syncMemoryContext();
2859
3945
  this.agentRegistry.applyHeadersToAgents(this.agentRegistry.agents);
2860
3946
  this.notifySubscribers((subscriber) => subscriber.onHeadersChanged?.({
2861
3947
  copilotkit: this,
@@ -2961,6 +4047,46 @@ var CopilotKitCore = class {
2961
4047
  return this.threadStoreRegistry.getAll();
2962
4048
  }
2963
4049
  /**
4050
+ * Returns the single core-owned, user-scoped memory store, creating and
4051
+ * starting it on first access. Unlike thread stores, memory is not scoped per
4052
+ * agent: there is exactly one store whose runtime context the core wires
4053
+ * itself (see `syncMemoryContext`), so consumers (e.g. a `useMemories`
4054
+ * binding) just read this store rather than registering one.
4055
+ */
4056
+ getMemoryStore() {
4057
+ return this.ensureMemoryStore();
4058
+ }
4059
+ /**
4060
+ * Lazily creates, starts, and context-syncs the core-owned memory store on
4061
+ * first access, then returns it. Subsequent calls return the existing store.
4062
+ * The store is constructed with a bound `globalThis.fetch` and immediately
4063
+ * has its runtime context synced from the current connection state.
4064
+ */
4065
+ ensureMemoryStore() {
4066
+ if (!this._memoryStore) {
4067
+ this._memoryStore = createMemoryStore({ fetch: globalThis.fetch.bind(globalThis) });
4068
+ this._memoryStore.start();
4069
+ this.syncMemoryContext();
4070
+ }
4071
+ return this._memoryStore;
4072
+ }
4073
+ /**
4074
+ * Pushes the current runtime wiring into the memory store. When the runtime
4075
+ * is connected and both the intelligence WebSocket URL and runtime URL are
4076
+ * available, the store receives a context (runtime URL, WebSocket URL, and a
4077
+ * copy of the current headers); otherwise its context is cleared. No-op when
4078
+ * the store has not been created yet.
4079
+ */
4080
+ syncMemoryContext() {
4081
+ if (!this._memoryStore) return;
4082
+ if (this.runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Connected && this.intelligence?.wsUrl && this.runtimeUrl) this._memoryStore.setContext({
4083
+ runtimeUrl: this.runtimeUrl,
4084
+ wsUrl: this.intelligence.wsUrl,
4085
+ headers: { ...this.headers }
4086
+ });
4087
+ else this._memoryStore.setContext(null);
4088
+ }
4089
+ /**
2964
4090
  * Suggestions management (delegated to SuggestionEngine)
2965
4091
  */
2966
4092
  addSuggestionsConfig(config) {
@@ -3123,510 +4249,253 @@ var CopilotKitCore = class {
3123
4249
  throttler.maybeExecute();
3124
4250
  };
3125
4251
  if (subscriber.onStateChanged) wrappedSubscriber.onStateChanged = (params) => {
3126
- latestStateParams = params;
3127
- throttler.maybeExecute();
3128
- };
3129
- const subscription = agent.subscribe(wrappedSubscriber);
3130
- return { unsubscribe: () => {
3131
- active = false;
3132
- throttler.cancel();
3133
- subscription.unsubscribe();
3134
- } };
3135
- }
3136
- /**
3137
- * Agent connectivity (delegated to RunHandler)
3138
- */
3139
- async connectAgent(params) {
3140
- return this.runHandler.connectAgent(params);
3141
- }
3142
- stopAgent(params) {
3143
- this.runHandler.abortCurrentRun();
3144
- params.agent.abortRun();
3145
- }
3146
- async runAgent(params) {
3147
- return this.runHandler.runAgent(params);
3148
- }
3149
- /**
3150
- * Programmatically execute a registered frontend tool without going through an LLM turn.
3151
- * The handler runs, render components show up in the UI, and both the tool call and
3152
- * result messages are added to `agent.messages`.
3153
- */
3154
- async runTool(params) {
3155
- return this.runHandler.runTool(params);
3156
- }
3157
- /**
3158
- * State management (delegated to StateManager)
3159
- */
3160
- getStateByRun(agentId, threadId, runId) {
3161
- return this.stateManager.getStateByRun(agentId, threadId, runId);
3162
- }
3163
- getRunIdForMessage(agentId, threadId, messageId) {
3164
- return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);
3165
- }
3166
- getRunIdsForThread(agentId, threadId) {
3167
- return this.stateManager.getRunIdsForThread(agentId, threadId);
3168
- }
3169
- /**
3170
- * Internal method used by RunHandler to build frontend tools
3171
- */
3172
- buildFrontendTools(agentId) {
3173
- return this.runHandler.buildFrontendTools(agentId);
3174
- }
3175
- /**
3176
- * Called before each follow-up agent run (after tool execution).
3177
- *
3178
- * When a frontend tool handler calls framework state setters (e.g. React's
3179
- * setState), those updates are batched and deferred — they do not take effect
3180
- * until the framework's scheduler runs (React uses MessageChannel).
3181
- * useAgentContext registers context via useLayoutEffect, which runs
3182
- * synchronously after React commits that deferred batch.
3183
- *
3184
- * Without yielding here, the follow-up runAgent reads the context store
3185
- * synchronously while the deferred updates are still pending, producing stale
3186
- * context for the next agent turn.
3187
- *
3188
- * Override in framework-specific subclasses to yield to the framework
3189
- * scheduler before the follow-up run. The base implementation is a no-op
3190
- * because non-React environments have no deferred state to flush.
3191
- */
3192
- async waitForPendingFrameworkUpdates() {}
3193
- };
3194
-
3195
- //#endregion
3196
- //#region src/types.ts
3197
- /**
3198
- * Status of a tool call execution
3199
- */
3200
- let ToolCallStatus = /* @__PURE__ */ function(ToolCallStatus) {
3201
- ToolCallStatus["InProgress"] = "inProgress";
3202
- ToolCallStatus["Executing"] = "executing";
3203
- ToolCallStatus["Complete"] = "complete";
3204
- return ToolCallStatus;
3205
- }({});
3206
-
3207
- //#endregion
3208
- //#region src/utils/markdown.ts
3209
- function completePartialMarkdown(input) {
3210
- let s = input;
3211
- const fenceMatches = Array.from(s.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
3212
- if (fenceMatches.length % 2 === 1) {
3213
- const [, indent, fence] = fenceMatches[0];
3214
- s += `\n${indent}${fence}`;
3215
- }
3216
- if (s.match(/\[([^\]]*)\]\(([^)]*)$/)) s += ")";
3217
- const openElements = [];
3218
- const chars = Array.from(s);
3219
- const codeBlockRanges = [];
3220
- const inlineCodeRanges = [];
3221
- let tempCodeFenceCount = 0;
3222
- let currentCodeBlockStart = -1;
3223
- for (let i = 0; i < chars.length; i++) if (i === 0 || chars[i - 1] === "\n") {
3224
- const lineMatch = s.substring(i).match(/^(\s*)(`{3,}|~{3,})/);
3225
- if (lineMatch) {
3226
- tempCodeFenceCount++;
3227
- if (tempCodeFenceCount % 2 === 1) currentCodeBlockStart = i;
3228
- else if (currentCodeBlockStart !== -1) {
3229
- codeBlockRanges.push({
3230
- start: currentCodeBlockStart,
3231
- end: i + lineMatch[0].length
3232
- });
3233
- currentCodeBlockStart = -1;
3234
- }
3235
- i += lineMatch[0].length - 1;
3236
- }
3237
- }
3238
- for (let i = 0; i < chars.length; i++) if (chars[i] === "`") {
3239
- let backslashCount = 0;
3240
- for (let j = i - 1; j >= 0 && chars[j] === "\\"; j--) backslashCount++;
3241
- if (backslashCount % 2 === 0) {
3242
- for (let j = i + 1; j < chars.length; j++) if (chars[j] === "`") {
3243
- let closingBackslashCount = 0;
3244
- for (let k = j - 1; k >= 0 && chars[k] === "\\"; k--) closingBackslashCount++;
3245
- if (closingBackslashCount % 2 === 0) {
3246
- inlineCodeRanges.push({
3247
- start: i,
3248
- end: j + 1
3249
- });
3250
- i = j;
3251
- break;
3252
- }
3253
- }
3254
- }
3255
- }
3256
- const isInCode = (pos) => {
3257
- return codeBlockRanges.some((range) => pos >= range.start && pos < range.end) || inlineCodeRanges.some((range) => pos >= range.start && pos < range.end);
3258
- };
3259
- for (let i = 0; i < chars.length; i++) {
3260
- const char = chars[i];
3261
- const nextChar = chars[i + 1];
3262
- const prevChar = chars[i - 1];
3263
- if (isInCode(i)) continue;
3264
- if (char === "[") {
3265
- let isCompleteLink = false;
3266
- let bracketDepth = 1;
3267
- let j = i + 1;
3268
- while (j < chars.length && bracketDepth > 0) {
3269
- if (chars[j] === "[" && !isInCode(j)) bracketDepth++;
3270
- if (chars[j] === "]" && !isInCode(j)) bracketDepth--;
3271
- j++;
3272
- }
3273
- if (bracketDepth === 0 && chars[j] === "(") {
3274
- let parenDepth = 1;
3275
- j++;
3276
- while (j < chars.length && parenDepth > 0) {
3277
- if (chars[j] === "(" && !isInCode(j)) parenDepth++;
3278
- if (chars[j] === ")" && !isInCode(j)) parenDepth--;
3279
- j++;
3280
- }
3281
- if (parenDepth === 0) {
3282
- isCompleteLink = true;
3283
- i = j - 1;
3284
- continue;
3285
- }
3286
- }
3287
- if (!isCompleteLink) {
3288
- const existingIndex = openElements.findIndex((el) => el.type === "bracket");
3289
- if (existingIndex !== -1) openElements.splice(existingIndex, 1);
3290
- else openElements.push({
3291
- type: "bracket",
3292
- marker: "[",
3293
- position: i
3294
- });
3295
- }
3296
- } else if (char === "*" && nextChar === "*") {
3297
- const existingIndex = openElements.findIndex((el) => el.type === "bold_star");
3298
- if (existingIndex !== -1) openElements.splice(existingIndex, 1);
3299
- else openElements.push({
3300
- type: "bold_star",
3301
- marker: "**",
3302
- position: i
3303
- });
3304
- i++;
3305
- } else if (char === "_" && nextChar === "_") {
3306
- const existingIndex = openElements.findIndex((el) => el.type === "bold_underscore");
3307
- if (existingIndex !== -1) openElements.splice(existingIndex, 1);
3308
- else openElements.push({
3309
- type: "bold_underscore",
3310
- marker: "__",
3311
- position: i
3312
- });
3313
- i++;
3314
- } else if (char === "~" && nextChar === "~") {
3315
- const existingIndex = openElements.findIndex((el) => el.type === "strike");
3316
- if (existingIndex !== -1) openElements.splice(existingIndex, 1);
3317
- else openElements.push({
3318
- type: "strike",
3319
- marker: "~~",
3320
- position: i
3321
- });
3322
- i++;
3323
- } else if (char === "*" && prevChar !== "*" && nextChar !== "*") {
3324
- const existingIndex = openElements.findIndex((el) => el.type === "italic_star");
3325
- if (existingIndex !== -1) openElements.splice(existingIndex, 1);
3326
- else openElements.push({
3327
- type: "italic_star",
3328
- marker: "*",
3329
- position: i
3330
- });
3331
- } else if (char === "_" && prevChar !== "_" && nextChar !== "_") {
3332
- const existingIndex = openElements.findIndex((el) => el.type === "italic_underscore");
3333
- if (existingIndex !== -1) openElements.splice(existingIndex, 1);
3334
- else openElements.push({
3335
- type: "italic_underscore",
3336
- marker: "_",
3337
- position: i
3338
- });
3339
- }
4252
+ latestStateParams = params;
4253
+ throttler.maybeExecute();
4254
+ };
4255
+ const subscription = agent.subscribe(wrappedSubscriber);
4256
+ return { unsubscribe: () => {
4257
+ active = false;
4258
+ throttler.cancel();
4259
+ subscription.unsubscribe();
4260
+ } };
3340
4261
  }
3341
- let backtickCount = 0;
3342
- for (let i = 0; i < chars.length; i++) if (chars[i] === "`" && !isInCode(i)) backtickCount++;
3343
- if (backtickCount % 2 === 1) s += "`";
3344
- openElements.sort((a, b) => b.position - a.position);
3345
- const closers = openElements.map((el) => {
3346
- switch (el.type) {
3347
- case "bracket": return "]";
3348
- case "bold_star": return "**";
3349
- case "bold_underscore": return "__";
3350
- case "strike": return "~~";
3351
- case "italic_star": return "*";
3352
- case "italic_underscore": return "_";
3353
- default: return "";
3354
- }
3355
- });
3356
- let result = s + closers.join("");
3357
- const finalFenceMatches = Array.from(result.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
3358
- const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;
3359
- const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;
3360
- let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;
3361
- if (shouldCloseParens) {
3362
- const lastOpenParen = result.lastIndexOf("(");
3363
- if (lastOpenParen !== -1) {
3364
- if ((result.substring(0, lastOpenParen).match(/`/g) || []).length % 2 === 1) shouldCloseParens = false;
3365
- }
4262
+ /**
4263
+ * Agent connectivity (delegated to RunHandler)
4264
+ */
4265
+ async connectAgent(params) {
4266
+ return this.runHandler.connectAgent(params);
3366
4267
  }
3367
- if (shouldCloseParens) {
3368
- const openParens = (result.match(/\(/g) || []).length;
3369
- const closeParens = (result.match(/\)/g) || []).length;
3370
- if (openParens > closeParens) result += ")".repeat(openParens - closeParens);
4268
+ stopAgent(params) {
4269
+ this.runHandler.abortCurrentRun();
4270
+ params.agent.abortRun();
3371
4271
  }
3372
- return result;
3373
- }
3374
-
3375
- //#endregion
3376
- //#region src/utils/micro-redux.ts
3377
- const INTERNAL_ACTION_TYPES = {
3378
- boot: "@@micro-redux/boot",
3379
- init: "@@micro-redux/init",
3380
- stop: "@@micro-redux/stop"
3381
- };
3382
- const INTERNAL_BOOT_ACTION = { type: INTERNAL_ACTION_TYPES.boot };
3383
- /**
3384
- * Builds a typed action creator from a type string and payload factory.
3385
- */
3386
- function createTypedActionCreator(type, factory) {
3387
- const creator = ((...args) => ({
3388
- ...factory(...args),
3389
- type
3390
- }));
3391
- creator.type = type;
3392
- creator.match = (action) => action.type === type;
3393
- return creator;
3394
- }
3395
- /**
3396
- * Declares a payload-based action config for `createActionGroup`.
3397
- *
3398
- * @example
3399
- * ```ts
3400
- * const actions = createActionGroup("User", {
3401
- * loaded: props<{ id: string }>(),
3402
- * });
3403
- * ```
3404
- */
3405
- function props() {
3406
- return { kind: "props" };
3407
- }
3408
- /**
3409
- * Declares a no-payload action config for `createActionGroup`.
3410
- *
3411
- * @example
3412
- * ```ts
3413
- * const actions = createActionGroup("User", {
3414
- * reset: empty(),
3415
- * });
3416
- * ```
3417
- */
3418
- function empty() {
3419
- return { kind: "empty" };
3420
- }
3421
- /**
3422
- * Creates a namespaced group of typed action creators.
3423
- *
3424
- * Action types are formatted as: `[Source] actionName`.
3425
- */
3426
- function createActionGroup(source, config) {
3427
- const group = {};
3428
- for (const eventName of Object.keys(config)) {
3429
- const eventConfig = config[eventName];
3430
- if (!eventConfig) continue;
3431
- const actionType = `[${source}] ${eventName}`;
3432
- if (eventConfig.kind === "props") {
3433
- group[eventName] = createTypedActionCreator(actionType, (payload) => ({ ...payload }));
3434
- continue;
3435
- }
3436
- group[eventName] = createTypedActionCreator(actionType, () => ({}));
4272
+ async runAgent(params) {
4273
+ return this.runHandler.runAgent(params);
3437
4274
  }
3438
- return group;
3439
- }
3440
- /**
3441
- * Registers one reducer handler for one or more action creators.
3442
- *
3443
- * @throws Error when called without at least one action creator and reducer.
3444
- */
3445
- function on(...args) {
3446
- if (args.length < 2) throw new Error("on requires at least one action creator and one reducer");
3447
- const reducer = args[args.length - 1];
3448
- return {
3449
- creators: args.slice(0, -1),
3450
- reducer
3451
- };
3452
- }
3453
- /**
3454
- * Creates a reducer from an initial state and `on(...)` handler entries.
3455
- *
3456
- * Unknown action types return the current state unchanged.
3457
- */
3458
- function createReducer(initialState, ...entries) {
3459
- const reducerMap = /* @__PURE__ */ new Map();
3460
- for (const entry of entries) for (const creator of entry.creators) {
3461
- const handlers = reducerMap.get(creator.type) ?? [];
3462
- handlers.push(entry.reducer);
3463
- reducerMap.set(creator.type, handlers);
4275
+ /**
4276
+ * Programmatically execute a registered frontend tool without going through an LLM turn.
4277
+ * The handler runs, render components show up in the UI, and both the tool call and
4278
+ * result messages are added to `agent.messages`.
4279
+ */
4280
+ async runTool(params) {
4281
+ return this.runHandler.runTool(params);
3464
4282
  }
3465
- return (state, action) => {
3466
- const currentState = state ?? initialState;
3467
- const handlers = reducerMap.get(action.type);
3468
- if (!handlers || handlers.length === 0) return currentState;
3469
- let nextState = currentState;
3470
- for (const handler of handlers) nextState = handler(nextState, action);
3471
- return nextState;
3472
- };
3473
- }
3474
- /**
3475
- * Creates a selector that caches and reuses the last computed result
3476
- * when all input references are unchanged.
3477
- */
3478
- function createSelector(...args) {
3479
- if (args.length === 1) {
3480
- const projector = args[0];
3481
- let hasCached = false;
3482
- let lastState;
3483
- let lastResult;
3484
- return (state) => {
3485
- if (hasCached && state === lastState) return lastResult;
3486
- lastState = state;
3487
- lastResult = projector(state);
3488
- hasCached = true;
3489
- return lastResult;
3490
- };
4283
+ /**
4284
+ * State management (delegated to StateManager)
4285
+ */
4286
+ getStateByRun(agentId, threadId, runId) {
4287
+ return this.stateManager.getStateByRun(agentId, threadId, runId);
3491
4288
  }
3492
- const projector = args[args.length - 1];
3493
- const selectors = args.slice(0, -1);
3494
- let hasCached = false;
3495
- let lastInputs = [];
3496
- let lastResult;
3497
- return (state) => {
3498
- const inputs = selectors.map((selector) => selector(state));
3499
- if (hasCached && inputs.length === lastInputs.length && inputs.every((value, index) => value === lastInputs[index])) return lastResult;
3500
- lastInputs = inputs;
3501
- lastResult = projector(...inputs);
3502
- hasCached = true;
3503
- return lastResult;
3504
- };
3505
- }
3506
- /**
3507
- * RxJS operator that maps state emissions through a selector and suppresses
3508
- * unchanged projected values via reference equality.
3509
- */
3510
- function select(selector) {
3511
- return (source$) => source$.pipe(map(selector), distinctUntilChanged());
3512
- }
3513
- /**
3514
- * RxJS operator that filters an action stream by action creators and narrows
3515
- * the output action type to the matched creator union.
3516
- *
3517
- * @throws Error when called without at least one action creator.
3518
- */
3519
- function ofType(...creators) {
3520
- if (creators.length === 0) throw new Error("ofType requires at least one action creator");
3521
- const actionTypes = new Set(creators.map((creator) => creator.type));
3522
- return (source$) => {
3523
- return source$.pipe(filter((action) => {
3524
- return actionTypes.has(action.type);
3525
- }));
3526
- };
3527
- }
3528
- /**
3529
- * Creates an effect descriptor consumed by `createStore`.
3530
- */
3531
- function createEffect(factory, options = {}) {
3532
- if (options.dispatch === false) return {
3533
- run: factory,
3534
- dispatch: false
3535
- };
3536
- return {
3537
- run: factory,
3538
- dispatch: true
3539
- };
3540
- }
4289
+ getRunIdForMessage(agentId, threadId, messageId) {
4290
+ return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);
4291
+ }
4292
+ getRunIdsForThread(agentId, threadId) {
4293
+ return this.stateManager.getRunIdsForThread(agentId, threadId);
4294
+ }
4295
+ /**
4296
+ * Internal method used by RunHandler to build frontend tools
4297
+ */
4298
+ buildFrontendTools(agentId) {
4299
+ return this.runHandler.buildFrontendTools(agentId);
4300
+ }
4301
+ /**
4302
+ * Called before each follow-up agent run (after tool execution).
4303
+ *
4304
+ * When a frontend tool handler calls framework state setters (e.g. React's
4305
+ * setState), those updates are batched and deferred — they do not take effect
4306
+ * until the framework's scheduler runs (React uses MessageChannel).
4307
+ * useAgentContext registers context via useLayoutEffect, which runs
4308
+ * synchronously after React commits that deferred batch.
4309
+ *
4310
+ * Without yielding here, the follow-up runAgent reads the context store
4311
+ * synchronously while the deferred updates are still pending, producing stale
4312
+ * context for the next agent turn.
4313
+ *
4314
+ * Override in framework-specific subclasses to yield to the framework
4315
+ * scheduler before the follow-up run. The base implementation is a no-op
4316
+ * because non-React environments have no deferred state to flush.
4317
+ */
4318
+ async waitForPendingFrameworkUpdates() {}
4319
+ };
4320
+
4321
+ //#endregion
4322
+ //#region src/types.ts
3541
4323
  /**
3542
- * Creates a small observable store with reducer + effects.
3543
- *
3544
- * Behavior:
3545
- * - `init()` starts effects and dispatches `@@micro-redux/init`.
3546
- * - `stop()` dispatches `@@micro-redux/stop` and unsubscribes all effects.
3547
- * - Effect action observation is scheduled on `asapScheduler` to avoid
3548
- * synchronous re-entrancy in the effect loop.
3549
- * - Any effect error triggers fail-fast teardown and errors both `actions$`
3550
- * and `state$`.
4324
+ * Status of a tool call execution
3551
4325
  */
3552
- function createStore(options) {
3553
- const reducer = options.reducer;
3554
- const effects = options.effects ?? [];
3555
- let hasFatalError = false;
3556
- let isRunning = false;
3557
- let effectSubscriptions = new Subscription();
3558
- let currentState = reducer(void 0, INTERNAL_BOOT_ACTION);
3559
- const stateSubject = new BehaviorSubject(currentState);
3560
- const actionsSubject = new Subject();
3561
- const dispatchInternal = (action) => {
3562
- if (hasFatalError) throw new Error("Store is in a failed state due to an effect error");
3563
- currentState = reducer(currentState, action);
3564
- stateSubject.next(currentState);
3565
- actionsSubject.next(action);
3566
- };
3567
- const failFast = (error) => {
3568
- if (hasFatalError) return;
3569
- hasFatalError = true;
3570
- isRunning = false;
3571
- effectSubscriptions.unsubscribe();
3572
- effectSubscriptions = new Subscription();
3573
- actionsSubject.error(error);
3574
- stateSubject.error(error);
3575
- };
3576
- const startEffects = () => {
3577
- for (const effect of effects) {
3578
- const scheduledActions$ = actionsSubject.asObservable().pipe(observeOn(asapScheduler));
3579
- const state$ = stateSubject.asObservable();
3580
- if (effect.dispatch) {
3581
- const subscription = effect.run(scheduledActions$, state$).subscribe({
3582
- next: (effectAction) => {
3583
- if (hasFatalError) return;
3584
- dispatchInternal(effectAction);
3585
- },
3586
- error: (error) => {
3587
- failFast(error);
3588
- }
4326
+ let ToolCallStatus = /* @__PURE__ */ function(ToolCallStatus) {
4327
+ ToolCallStatus["InProgress"] = "inProgress";
4328
+ ToolCallStatus["Executing"] = "executing";
4329
+ ToolCallStatus["Complete"] = "complete";
4330
+ return ToolCallStatus;
4331
+ }({});
4332
+
4333
+ //#endregion
4334
+ //#region src/utils/markdown.ts
4335
+ function completePartialMarkdown(input) {
4336
+ let s = input;
4337
+ const fenceMatches = Array.from(s.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
4338
+ if (fenceMatches.length % 2 === 1) {
4339
+ const [, indent, fence] = fenceMatches[0];
4340
+ s += `\n${indent}${fence}`;
4341
+ }
4342
+ if (s.match(/\[([^\]]*)\]\(([^)]*)$/)) s += ")";
4343
+ const openElements = [];
4344
+ const chars = Array.from(s);
4345
+ const codeBlockRanges = [];
4346
+ const inlineCodeRanges = [];
4347
+ let tempCodeFenceCount = 0;
4348
+ let currentCodeBlockStart = -1;
4349
+ for (let i = 0; i < chars.length; i++) if (i === 0 || chars[i - 1] === "\n") {
4350
+ const lineMatch = s.substring(i).match(/^(\s*)(`{3,}|~{3,})/);
4351
+ if (lineMatch) {
4352
+ tempCodeFenceCount++;
4353
+ if (tempCodeFenceCount % 2 === 1) currentCodeBlockStart = i;
4354
+ else if (currentCodeBlockStart !== -1) {
4355
+ codeBlockRanges.push({
4356
+ start: currentCodeBlockStart,
4357
+ end: i + lineMatch[0].length
3589
4358
  });
3590
- effectSubscriptions.add(subscription);
3591
- continue;
4359
+ currentCodeBlockStart = -1;
3592
4360
  }
3593
- const subscription = effect.run(scheduledActions$, state$).subscribe({ error: (error) => {
3594
- failFast(error);
3595
- } });
3596
- effectSubscriptions.add(subscription);
4361
+ i += lineMatch[0].length - 1;
3597
4362
  }
3598
- };
3599
- return {
3600
- dispatch(action) {
3601
- dispatchInternal(action);
3602
- },
3603
- getState() {
3604
- return currentState;
3605
- },
3606
- get state$() {
3607
- return stateSubject.asObservable();
3608
- },
3609
- get actions$() {
3610
- return actionsSubject.asObservable();
3611
- },
3612
- select(selector) {
3613
- return stateSubject.asObservable().pipe(select(selector));
3614
- },
3615
- init() {
3616
- if (hasFatalError || isRunning) return;
3617
- isRunning = true;
3618
- startEffects();
3619
- if (hasFatalError) return;
3620
- dispatchInternal({ type: INTERNAL_ACTION_TYPES.init });
3621
- },
3622
- stop() {
3623
- if (hasFatalError || !isRunning) return;
3624
- dispatchInternal({ type: INTERNAL_ACTION_TYPES.stop });
3625
- effectSubscriptions.unsubscribe();
3626
- effectSubscriptions = new Subscription();
3627
- isRunning = false;
4363
+ }
4364
+ for (let i = 0; i < chars.length; i++) if (chars[i] === "`") {
4365
+ let backslashCount = 0;
4366
+ for (let j = i - 1; j >= 0 && chars[j] === "\\"; j--) backslashCount++;
4367
+ if (backslashCount % 2 === 0) {
4368
+ for (let j = i + 1; j < chars.length; j++) if (chars[j] === "`") {
4369
+ let closingBackslashCount = 0;
4370
+ for (let k = j - 1; k >= 0 && chars[k] === "\\"; k--) closingBackslashCount++;
4371
+ if (closingBackslashCount % 2 === 0) {
4372
+ inlineCodeRanges.push({
4373
+ start: i,
4374
+ end: j + 1
4375
+ });
4376
+ i = j;
4377
+ break;
4378
+ }
4379
+ }
3628
4380
  }
4381
+ }
4382
+ const isInCode = (pos) => {
4383
+ return codeBlockRanges.some((range) => pos >= range.start && pos < range.end) || inlineCodeRanges.some((range) => pos >= range.start && pos < range.end);
3629
4384
  };
4385
+ for (let i = 0; i < chars.length; i++) {
4386
+ const char = chars[i];
4387
+ const nextChar = chars[i + 1];
4388
+ const prevChar = chars[i - 1];
4389
+ if (isInCode(i)) continue;
4390
+ if (char === "[") {
4391
+ let isCompleteLink = false;
4392
+ let bracketDepth = 1;
4393
+ let j = i + 1;
4394
+ while (j < chars.length && bracketDepth > 0) {
4395
+ if (chars[j] === "[" && !isInCode(j)) bracketDepth++;
4396
+ if (chars[j] === "]" && !isInCode(j)) bracketDepth--;
4397
+ j++;
4398
+ }
4399
+ if (bracketDepth === 0 && chars[j] === "(") {
4400
+ let parenDepth = 1;
4401
+ j++;
4402
+ while (j < chars.length && parenDepth > 0) {
4403
+ if (chars[j] === "(" && !isInCode(j)) parenDepth++;
4404
+ if (chars[j] === ")" && !isInCode(j)) parenDepth--;
4405
+ j++;
4406
+ }
4407
+ if (parenDepth === 0) {
4408
+ isCompleteLink = true;
4409
+ i = j - 1;
4410
+ continue;
4411
+ }
4412
+ }
4413
+ if (!isCompleteLink) {
4414
+ const existingIndex = openElements.findIndex((el) => el.type === "bracket");
4415
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
4416
+ else openElements.push({
4417
+ type: "bracket",
4418
+ marker: "[",
4419
+ position: i
4420
+ });
4421
+ }
4422
+ } else if (char === "*" && nextChar === "*") {
4423
+ const existingIndex = openElements.findIndex((el) => el.type === "bold_star");
4424
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
4425
+ else openElements.push({
4426
+ type: "bold_star",
4427
+ marker: "**",
4428
+ position: i
4429
+ });
4430
+ i++;
4431
+ } else if (char === "_" && nextChar === "_") {
4432
+ const existingIndex = openElements.findIndex((el) => el.type === "bold_underscore");
4433
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
4434
+ else openElements.push({
4435
+ type: "bold_underscore",
4436
+ marker: "__",
4437
+ position: i
4438
+ });
4439
+ i++;
4440
+ } else if (char === "~" && nextChar === "~") {
4441
+ const existingIndex = openElements.findIndex((el) => el.type === "strike");
4442
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
4443
+ else openElements.push({
4444
+ type: "strike",
4445
+ marker: "~~",
4446
+ position: i
4447
+ });
4448
+ i++;
4449
+ } else if (char === "*" && prevChar !== "*" && nextChar !== "*") {
4450
+ const existingIndex = openElements.findIndex((el) => el.type === "italic_star");
4451
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
4452
+ else openElements.push({
4453
+ type: "italic_star",
4454
+ marker: "*",
4455
+ position: i
4456
+ });
4457
+ } else if (char === "_" && prevChar !== "_" && nextChar !== "_") {
4458
+ const existingIndex = openElements.findIndex((el) => el.type === "italic_underscore");
4459
+ if (existingIndex !== -1) openElements.splice(existingIndex, 1);
4460
+ else openElements.push({
4461
+ type: "italic_underscore",
4462
+ marker: "_",
4463
+ position: i
4464
+ });
4465
+ }
4466
+ }
4467
+ let backtickCount = 0;
4468
+ for (let i = 0; i < chars.length; i++) if (chars[i] === "`" && !isInCode(i)) backtickCount++;
4469
+ if (backtickCount % 2 === 1) s += "`";
4470
+ openElements.sort((a, b) => b.position - a.position);
4471
+ const closers = openElements.map((el) => {
4472
+ switch (el.type) {
4473
+ case "bracket": return "]";
4474
+ case "bold_star": return "**";
4475
+ case "bold_underscore": return "__";
4476
+ case "strike": return "~~";
4477
+ case "italic_star": return "*";
4478
+ case "italic_underscore": return "_";
4479
+ default: return "";
4480
+ }
4481
+ });
4482
+ let result = s + closers.join("");
4483
+ const finalFenceMatches = Array.from(result.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
4484
+ const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;
4485
+ const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;
4486
+ let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;
4487
+ if (shouldCloseParens) {
4488
+ const lastOpenParen = result.lastIndexOf("(");
4489
+ if (lastOpenParen !== -1) {
4490
+ if ((result.substring(0, lastOpenParen).match(/`/g) || []).length % 2 === 1) shouldCloseParens = false;
4491
+ }
4492
+ }
4493
+ if (shouldCloseParens) {
4494
+ const openParens = (result.match(/\(/g) || []).length;
4495
+ const closeParens = (result.match(/\)/g) || []).length;
4496
+ if (openParens > closeParens) result += ")".repeat(openParens - closeParens);
4497
+ }
4498
+ return result;
3630
4499
  }
3631
4500
 
3632
4501
  //#endregion
@@ -3641,6 +4510,7 @@ const initialThreadState = {
3641
4510
  isLoading: false,
3642
4511
  isFetchingNextPage: false,
3643
4512
  error: null,
4513
+ fetchMoreError: null,
3644
4514
  context: null,
3645
4515
  sessionId: 0,
3646
4516
  metadataCredentialsRequested: false,
@@ -3726,6 +4596,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
3726
4596
  isLoading: Boolean(context),
3727
4597
  isFetchingNextPage: false,
3728
4598
  error: null,
4599
+ fetchMoreError: null,
3729
4600
  metadataCredentialsRequested: false,
3730
4601
  metadataJoinCode: null,
3731
4602
  nextCursor: null,
@@ -3737,6 +4608,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
3737
4608
  isLoading: false,
3738
4609
  isFetchingNextPage: false,
3739
4610
  error: null,
4611
+ fetchMoreError: null,
3740
4612
  metadataCredentialsRequested: false,
3741
4613
  metadataJoinCode: null,
3742
4614
  nextCursor: null,
@@ -3747,7 +4619,8 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
3747
4619
  return {
3748
4620
  ...state,
3749
4621
  isLoading: true,
3750
- error: null
4622
+ error: null,
4623
+ fetchMoreError: null
3751
4624
  };
3752
4625
  }), on(threadRestEvents.listSucceeded, (state, { sessionId, threads, joinCode, nextCursor }) => {
3753
4626
  if (sessionId !== state.sessionId) return state;
@@ -3757,6 +4630,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
3757
4630
  threads: sortThreadsByRecency(threads),
3758
4631
  isLoading: false,
3759
4632
  error: null,
4633
+ fetchMoreError: null,
3760
4634
  metadataJoinCode: joinCode,
3761
4635
  metadataCredentialsRequested: joinCodeChanged ? false : state.metadataCredentialsRequested,
3762
4636
  nextCursor
@@ -3776,6 +4650,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
3776
4650
  ...state,
3777
4651
  threads: merged,
3778
4652
  isFetchingNextPage: false,
4653
+ fetchMoreError: null,
3779
4654
  nextCursor
3780
4655
  };
3781
4656
  }), on(threadRestEvents.nextPageFailed, (state, { sessionId, error }) => {
@@ -3783,7 +4658,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
3783
4658
  return {
3784
4659
  ...state,
3785
4660
  isFetchingNextPage: false,
3786
- error
4661
+ fetchMoreError: error
3787
4662
  };
3788
4663
  }), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId }) => {
3789
4664
  if (sessionId !== state.sessionId) return state;
@@ -3801,7 +4676,8 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
3801
4676
  if (!state.nextCursor || state.isFetchingNextPage) return state;
3802
4677
  return {
3803
4678
  ...state,
3804
- isFetchingNextPage: true
4679
+ isFetchingNextPage: true,
4680
+ fetchMoreError: null
3805
4681
  };
3806
4682
  }), on(threadAdapterEvents.renameRequested, (state, { threadId, name }) => {
3807
4683
  const existing = state.threads.find((thread) => thread.id === threadId);
@@ -3930,6 +4806,7 @@ function createThreadSelectors() {
3930
4806
  threads: createSelector((state) => state.threads),
3931
4807
  isLoading: createSelector((state) => state.isLoading),
3932
4808
  error: createSelector((state) => state.error),
4809
+ fetchMoreError: createSelector((state) => state.fetchMoreError),
3933
4810
  hasNextPage: createSelector((state) => state.nextCursor != null),
3934
4811
  isFetchingNextPage: createSelector((state) => state.isFetchingNextPage),
3935
4812
  isMutating: createSelector((state) => state.inFlightMutationCount > 0)
@@ -3939,6 +4816,7 @@ const standaloneSelectors = createThreadSelectors();
3939
4816
  const selectThreads = standaloneSelectors.threads;
3940
4817
  const selectThreadsIsLoading = standaloneSelectors.isLoading;
3941
4818
  const selectThreadsError = standaloneSelectors.error;
4819
+ const selectFetchMoreError = standaloneSelectors.fetchMoreError;
3942
4820
  const selectHasNextPage = standaloneSelectors.hasNextPage;
3943
4821
  const selectIsFetchingNextPage = standaloneSelectors.isFetchingNextPage;
3944
4822
  const selectIsMutating = standaloneSelectors.isMutating;
@@ -4312,6 +5190,7 @@ const ɵcreateThreadSelectors = createThreadSelectors;
4312
5190
  const ɵselectThreads = selectThreads;
4313
5191
  const ɵselectThreadsIsLoading = selectThreadsIsLoading;
4314
5192
  const ɵselectThreadsError = selectThreadsError;
5193
+ const ɵselectFetchMoreError = selectFetchMoreError;
4315
5194
  const ɵselectHasNextPage = selectHasNextPage;
4316
5195
  const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;
4317
5196
  const ɵselectIsMutating = selectIsMutating;
@@ -4369,5 +5248,5 @@ function ɵisCopilotKitFeature(name) {
4369
5248
  }
4370
5249
 
4371
5250
  //#endregion
4372
- export { AgentRegistry, AgentThreadLockedError, ContextStore, CopilotKitCore, CopilotKitCoreErrorCode, CopilotKitCoreRuntimeConnectionStatus, IntelligenceAgent, ProxiedCopilotRuntimeAgent, RunHandler, StateManager, SuggestionEngine, ToolCallStatus, completePartialMarkdown, createActionGroup, createEffect, createReducer, createSelector, createStore, empty, ensureObjectArgs, isRunCompletionAware, ofType, on, parseToolArguments, props, select, ɵCOPILOTKIT_FEATURES, ɵMAX_SOCKET_RETRIES, ɵcreateThreadSelectors, createThreadStore as ɵcreateThreadStore, ɵisCopilotKitFeature, ɵjoinPhoenixChannel$, ɵobservePhoenixEvent$, ɵobservePhoenixJoinOutcome$, ɵobservePhoenixSocketHealth$, ɵobservePhoenixSocketSignals$, ɵphoenixChannel$, ɵphoenixSocket$, ɵselectHasNextPage, ɵselectIsFetchingNextPage, ɵselectIsMutating, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading, ɵthreadAdapterEvents };
5251
+ export { AgentRegistry, AgentThreadLockedError, ContextStore, CopilotKitCore, CopilotKitCoreErrorCode, CopilotKitCoreRuntimeConnectionStatus, IntelligenceAgent, MEMORY_ERROR_REGISTRY, MemoryError, ProxiedCopilotRuntimeAgent, RunHandler, StateManager, SuggestionEngine, ToolCallStatus, completePartialMarkdown, createActionGroup, createEffect, createReducer, createSelector, createStore, empty, ensureObjectArgs, isAbortError, isRunCompletionAware, ofType, on, parseToolArguments, props, select, ɵCOPILOTKIT_FEATURES, ɵMAX_SOCKET_RETRIES, createMemoryStore as ɵcreateMemoryStore, ɵcreateThreadSelectors, createThreadStore as ɵcreateThreadStore, ɵisCopilotKitFeature, isRetryableStatus as ɵisRetryableMemoryStatus, ɵjoinPhoenixChannel$, ɵmapMemoryMetadataEvent, ɵmemoryAdapterEvents, ɵmemoryDomainEvents, ɵmemoryReducer, ɵmemoryRestEvents, ɵobservePhoenixEvent$, ɵobservePhoenixJoinOutcome$, ɵobservePhoenixSocketHealth$, ɵobservePhoenixSocketSignals$, ɵphoenixChannel$, ɵphoenixSocket$, ɵselectFetchMoreError, ɵselectHasNextPage, ɵselectIsFetchingNextPage, ɵselectIsMutating, ɵselectMemories, ɵselectMemoriesAvailable, ɵselectMemoriesError, ɵselectMemoriesIsLoading, ɵselectMemoriesIsMutating, ɵselectMemoriesRealtimeStatus, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading, ɵthreadAdapterEvents };
4373
5252
  //# sourceMappingURL=index.mjs.map