@copilotkit/react-core 1.62.1 → 1.62.2-canary.1784333495

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.
@@ -3635,12 +3635,13 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3635
3635
  }
3636
3636
  const copilotkit = copilotkitRef.current;
3637
3637
  (0, react.useEffect)(() => {
3638
- setRuntimeA2UIEnabled(copilotkit.a2uiEnabled);
3639
- const subscription = copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
3638
+ const syncRuntimeInfo = () => {
3640
3639
  setRuntimeA2UIEnabled(copilotkit.a2uiEnabled);
3641
3640
  setRuntimeOpenGenUIEnabled(copilotkit.openGenerativeUIEnabled);
3642
3641
  setRuntimeLicenseStatus(copilotkit.licenseStatus);
3643
- } });
3642
+ };
3643
+ const subscription = copilotkit.subscribe({ onRuntimeConnectionStatusChanged: syncRuntimeInfo });
3644
+ syncRuntimeInfo();
3644
3645
  return () => {
3645
3646
  subscription.unsubscribe();
3646
3647
  };
@@ -4366,57 +4367,58 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4366
4367
  UseAgentUpdate.OnRunStatusChanged
4367
4368
  ];
4368
4369
  function useAgent({ agentId, updates, throttleMs } = {}) {
4369
- agentId ?? (agentId = _copilotkit_shared.DEFAULT_AGENT_ID);
4370
+ const chatConfig = useCopilotChatConfiguration();
4371
+ const resolvedAgentId = agentId ?? chatConfig?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
4370
4372
  const { copilotkit } = useCopilotKit();
4371
4373
  const providerThrottleMs = copilotkit.defaultThrottleMs;
4372
4374
  const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
4373
4375
  const updateFlags = (0, react.useMemo)(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
4374
4376
  const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
4375
4377
  const agent = (0, react.useMemo)(() => {
4376
- const existing = copilotkit.getAgent(agentId);
4378
+ const existing = copilotkit.getAgent(resolvedAgentId);
4377
4379
  if (existing) {
4378
- provisionalAgentCache.current.delete(agentId);
4380
+ provisionalAgentCache.current.delete(resolvedAgentId);
4379
4381
  return existing;
4380
4382
  }
4381
4383
  const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
4382
4384
  const status = copilotkit.runtimeConnectionStatus;
4383
4385
  if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
4384
- const cached = provisionalAgentCache.current.get(agentId);
4386
+ const cached = provisionalAgentCache.current.get(resolvedAgentId);
4385
4387
  if (cached) {
4386
4388
  copilotkit.applyHeadersToAgent(cached);
4387
4389
  return cached;
4388
4390
  }
4389
4391
  const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4390
4392
  runtimeUrl: copilotkit.runtimeUrl,
4391
- agentId,
4393
+ agentId: resolvedAgentId,
4392
4394
  transport: copilotkit.runtimeTransport,
4393
4395
  runtimeMode: "pending"
4394
4396
  });
4395
4397
  copilotkit.applyHeadersToAgent(provisional);
4396
- provisionalAgentCache.current.set(agentId, provisional);
4398
+ provisionalAgentCache.current.set(resolvedAgentId, provisional);
4397
4399
  return provisional;
4398
4400
  }
4399
4401
  if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
4400
- const cached = provisionalAgentCache.current.get(agentId);
4402
+ const cached = provisionalAgentCache.current.get(resolvedAgentId);
4401
4403
  if (cached) {
4402
4404
  copilotkit.applyHeadersToAgent(cached);
4403
4405
  return cached;
4404
4406
  }
4405
4407
  const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4406
4408
  runtimeUrl: copilotkit.runtimeUrl,
4407
- agentId,
4409
+ agentId: resolvedAgentId,
4408
4410
  transport: copilotkit.runtimeTransport,
4409
4411
  runtimeMode: "pending"
4410
4412
  });
4411
4413
  copilotkit.applyHeadersToAgent(provisional);
4412
- provisionalAgentCache.current.set(agentId, provisional);
4414
+ provisionalAgentCache.current.set(resolvedAgentId, provisional);
4413
4415
  return provisional;
4414
4416
  }
4415
4417
  const knownAgents = Object.keys(copilotkit.agents ?? {});
4416
4418
  const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
4417
- throw new Error(`useAgent: Agent '${agentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only.");
4419
+ throw new Error(`useAgent: Agent '${resolvedAgentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only.");
4418
4420
  }, [
4419
- agentId,
4421
+ resolvedAgentId,
4420
4422
  copilotkit.agents,
4421
4423
  copilotkit.runtimeConnectionStatus,
4422
4424
  copilotkit.runtimeUrl,
@@ -4461,7 +4463,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4461
4463
  (0, react.useEffect)(() => {
4462
4464
  if (agent instanceof _ag_ui_client.HttpAgent) copilotkit.applyHeadersToAgent(agent);
4463
4465
  }, [agent, JSON.stringify(copilotkit.headers)]);
4464
- const chatConfig = useCopilotChatConfiguration();
4465
4466
  const configThreadId = chatConfig?.threadId;
4466
4467
  const configHasExplicitThreadId = chatConfig?.hasExplicitThreadId;
4467
4468
  (0, react.useEffect)(() => {
@@ -4475,16 +4476,87 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4475
4476
  return { agent };
4476
4477
  }
4477
4478
 
4479
+ //#endregion
4480
+ //#region src/v2/hooks/use-subagent.tsx
4481
+ const warnedAmbiguousNames = /* @__PURE__ */ new Set();
4482
+ function resolveSubagent(subagents, subagentId, subagentName) {
4483
+ if (subagentId) {
4484
+ const match = subagents[subagentId];
4485
+ return match ? { ...match } : void 0;
4486
+ }
4487
+ if (subagentName) {
4488
+ const matches = Object.values(subagents).filter((s) => s.name === subagentName);
4489
+ if (matches.length === 0) return;
4490
+ const chosen = matches[matches.length - 1];
4491
+ return matches.length > 1 ? {
4492
+ ...chosen,
4493
+ isAmbiguous: true,
4494
+ matchCount: matches.length
4495
+ } : { ...chosen };
4496
+ }
4497
+ }
4498
+ /**
4499
+ * Read a subagent's live lifecycle state (name, description, running status)
4500
+ * from the CopilotKit core subagent registry, by id or by declared name.
4501
+ *
4502
+ * @example
4503
+ * const sub = useSubagent({ subagentId: message.subagentId });
4504
+ * // sub?.name, sub?.description, sub?.status
4505
+ */
4506
+ function useSubagent(params) {
4507
+ const { subagentId, subagentName, agentId } = params;
4508
+ const { copilotkit } = useCopilotKit();
4509
+ const config = useCopilotChatConfiguration();
4510
+ const resolvedAgentId = (0, react.useMemo)(() => agentId ?? config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID, [agentId, config?.agentId]);
4511
+ const [subagent, setSubagent] = (0, react.useState)(() => resolveSubagent(copilotkit.getSubagents(resolvedAgentId), subagentId, subagentName));
4512
+ (0, react.useEffect)(() => {
4513
+ setSubagent(resolveSubagent(copilotkit.getSubagents(resolvedAgentId), subagentId, subagentName));
4514
+ }, [
4515
+ copilotkit,
4516
+ resolvedAgentId,
4517
+ subagentId,
4518
+ subagentName
4519
+ ]);
4520
+ (0, react.useEffect)(() => {
4521
+ const subscription = copilotkit.subscribe({ onSubagentsChanged: ({ agentId: changedAgentId, subagents }) => {
4522
+ if (changedAgentId !== resolvedAgentId) return;
4523
+ setSubagent(resolveSubagent(subagents, subagentId, subagentName));
4524
+ } });
4525
+ return () => {
4526
+ subscription.unsubscribe();
4527
+ };
4528
+ }, [
4529
+ copilotkit,
4530
+ resolvedAgentId,
4531
+ subagentId,
4532
+ subagentName
4533
+ ]);
4534
+ (0, react.useEffect)(() => {
4535
+ if (process.env.NODE_ENV === "production" || !subagentName || !subagent?.isAmbiguous) return;
4536
+ const key = `${subagentName}:${subagent.matchCount}`;
4537
+ if (warnedAmbiguousNames.has(key)) return;
4538
+ warnedAmbiguousNames.add(key);
4539
+ console.warn(`[CopilotKit] useSubagent({ subagentName: ${JSON.stringify(subagentName)} }) matched ${subagent.matchCount} subagents. Returning the most recently started one; pass a subagentId for a stable reference.`);
4540
+ }, [
4541
+ subagentName,
4542
+ subagent?.isAmbiguous,
4543
+ subagent?.matchCount
4544
+ ]);
4545
+ return subagent;
4546
+ }
4547
+
4478
4548
  //#endregion
4479
4549
  //#region src/v2/hooks/use-capabilities.tsx
4480
4550
  /**
4481
- * Returns the capabilities declared by the given agent (or the default agent).
4551
+ * Returns the capabilities declared by the given agent (or the agent resolved
4552
+ * from the surrounding chat configuration, falling back to the default agent).
4482
4553
  * Capabilities are populated from the runtime `/info` response at connection
4483
4554
  * time. The hook reads them synchronously from the agent instance — there is
4484
4555
  * no separate loading state, but the value will be `undefined` until the
4485
4556
  * runtime handshake completes.
4486
4557
  *
4487
- * @param agentId - Optional agent ID. If omitted, uses the default agent.
4558
+ * @param agentId - Optional agent ID. If omitted, inherits the surrounding
4559
+ * chat configuration's agent, falling back to the default agent.
4488
4560
  * @returns The agent's capabilities, or `undefined` if the agent doesn't
4489
4561
  * declare capabilities.
4490
4562
  */
@@ -5057,6 +5129,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
5057
5129
  })), [coreThreads]);
5058
5130
  const storeIsLoading = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreadsIsLoading);
5059
5131
  const storeError = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreadsError);
5132
+ const fetchMoreError = useThreadStoreSelector(store, _copilotkit_core.ɵselectFetchMoreError);
5060
5133
  const hasMoreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectHasNextPage);
5061
5134
  const isFetchingMoreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectIsFetchingNextPage);
5062
5135
  const isMutating = useThreadStoreSelector(store, _copilotkit_core.ɵselectIsMutating);
@@ -5162,6 +5235,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
5162
5235
  isLoading,
5163
5236
  error,
5164
5237
  listError,
5238
+ fetchMoreError,
5165
5239
  hasMoreThreads,
5166
5240
  isFetchingMoreThreads,
5167
5241
  isMutating,
@@ -5178,6 +5252,70 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
5178
5252
  };
5179
5253
  }
5180
5254
 
5255
+ //#endregion
5256
+ //#region src/v2/hooks/use-memories.tsx
5257
+ function useMemoryStoreSelector(store, selector) {
5258
+ return (0, react.useSyncExternalStore)((0, react.useCallback)((onStoreChange) => {
5259
+ const subscription = store.select(selector).subscribe(onStoreChange);
5260
+ return () => subscription.unsubscribe();
5261
+ }, [store, selector]), () => selector(store.getState()), () => selector(store.getServerState()));
5262
+ }
5263
+ /**
5264
+ * React hook for listing and managing platform memories.
5265
+ *
5266
+ * Reads the memory store owned and wired by `CopilotKitCore`. On mount the
5267
+ * hook exposes the live list plus stable `addMemory` / `updateMemory` /
5268
+ * `removeMemory` / `refresh` callbacks. Mutations are server-authoritative:
5269
+ * each resolves once the platform confirms the operation and rejects with an
5270
+ * `Error` on failure.
5271
+ *
5272
+ * Realtime updates are automatic: the core's memory store opens its own
5273
+ * `user_meta:memories:<joinCode>` channel and applies `memory_metadata` deltas
5274
+ * to the list. You can still call `refresh()` to re-pull the REST snapshot on
5275
+ * demand.
5276
+ *
5277
+ * @returns Memory list state and stable mutation callbacks.
5278
+ *
5279
+ * @example
5280
+ * ```tsx
5281
+ * import { useMemories } from "@copilotkit/react-core";
5282
+ *
5283
+ * function MemoryList() {
5284
+ * const { memories, isLoading, isAvailable, addMemory, removeMemory } =
5285
+ * useMemories();
5286
+ *
5287
+ * if (!isAvailable) return null;
5288
+ * if (isLoading) return <p>Loading…</p>;
5289
+ *
5290
+ * return (
5291
+ * <ul>
5292
+ * {memories.map((m) => (
5293
+ * <li key={m.id}>
5294
+ * {m.content}
5295
+ * <button onClick={() => removeMemory(m.id)}>Delete</button>
5296
+ * </li>
5297
+ * ))}
5298
+ * </ul>
5299
+ * );
5300
+ * }
5301
+ * ```
5302
+ */
5303
+ function useMemories() {
5304
+ const { copilotkit } = useCopilotKit();
5305
+ const store = copilotkit.getMemoryStore();
5306
+ return {
5307
+ memories: useMemoryStoreSelector(store, _copilotkit_core.ɵselectMemories),
5308
+ isLoading: useMemoryStoreSelector(store, _copilotkit_core.ɵselectMemoriesIsLoading),
5309
+ error: useMemoryStoreSelector(store, _copilotkit_core.ɵselectMemoriesError),
5310
+ isAvailable: useMemoryStoreSelector(store, _copilotkit_core.ɵselectMemoriesAvailable),
5311
+ realtimeStatus: useMemoryStoreSelector(store, _copilotkit_core.ɵselectMemoriesRealtimeStatus),
5312
+ refresh: (0, react.useCallback)(() => store.refresh(), [store]),
5313
+ addMemory: (0, react.useCallback)((input) => store.addMemory(input), [store]),
5314
+ updateMemory: (0, react.useCallback)((id, changes) => store.updateMemory(id, changes), [store]),
5315
+ removeMemory: (0, react.useCallback)((id) => store.removeMemory(id), [store])
5316
+ };
5317
+ }
5318
+
5181
5319
  //#endregion
5182
5320
  //#region src/v2/lib/record-annotation.ts
5183
5321
  /**
@@ -7940,9 +8078,57 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
7940
8078
  const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
7941
8079
  const [lastConnectedThreadId, setLastConnectedThreadId] = (0, react.useState)(null);
7942
8080
  const isConnecting = hasExplicitThreadId && lastConnectedThreadId !== resolvedThreadId;
8081
+ const activeConnectCountRef = (0, react.useRef)(0);
8082
+ const pendingRunActivityReconnectRef = (0, react.useRef)(false);
8083
+ const runActivityReconnectGenerationRef = (0, react.useRef)(0);
8084
+ const activeLocalRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
8085
+ const recentlyLocalRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Map());
8086
+ const activeWakeRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
8087
+ const recentlyWakeRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Map());
8088
+ const pendingWakeRunIdRef = (0, react.useRef)(void 0);
8089
+ const startRunActivityReconnectRef = (0, react.useRef)(null);
8090
+ const runtimeStatus = copilotkit.runtimeConnectionStatus === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected ? "Connected" : copilotkit.runtimeConnectionStatus;
8091
+ const hasNativeIntelligenceRunActivity = hasExplicitThreadId && runtimeStatus === "Connected" && !!copilotkit.intelligence?.wsUrl && copilotkit.threadEndpoints?.realtimeMetadata === true;
8092
+ const [standaloneRunActivityStore] = (0, react.useState)(() => (0, _copilotkit_core.ɵcreateThreadStore)({ fetch: globalThis.fetch }));
7943
8093
  const previousThreadIdRef = (0, react.useRef)(null);
7944
8094
  const hasExplicitThreadIdRef = (0, react.useRef)(hasExplicitThreadId);
7945
8095
  hasExplicitThreadIdRef.current = hasExplicitThreadId;
8096
+ const rememberRecentlyLocalRunId = (0, react.useCallback)((runId) => {
8097
+ const existingTimeout = recentlyLocalRunIdsRef.current.get(runId);
8098
+ if (existingTimeout) clearTimeout(existingTimeout);
8099
+ const timeout = setTimeout(() => {
8100
+ recentlyLocalRunIdsRef.current.delete(runId);
8101
+ }, 3e4);
8102
+ recentlyLocalRunIdsRef.current.set(runId, timeout);
8103
+ }, []);
8104
+ const rememberRecentlyWakeRunId = (0, react.useCallback)((runId) => {
8105
+ const existingTimeout = recentlyWakeRunIdsRef.current.get(runId);
8106
+ if (existingTimeout) clearTimeout(existingTimeout);
8107
+ const timeout = setTimeout(() => {
8108
+ recentlyWakeRunIdsRef.current.delete(runId);
8109
+ }, 3e4);
8110
+ recentlyWakeRunIdsRef.current.set(runId, timeout);
8111
+ }, []);
8112
+ const isLocalActiveRunActivity = (0, react.useCallback)((notification) => {
8113
+ if (notification.agentId && notification.agentId !== resolvedAgentId) return false;
8114
+ if (!notification.runId || !activeLocalRunIdsRef.current.has(notification.runId) && !recentlyLocalRunIdsRef.current.has(notification.runId)) return false;
8115
+ const eventType = notification.eventType.toUpperCase();
8116
+ return eventType === "RUN_STARTED" || eventType === "RUN_FINISHED" || eventType === "RUN_ERROR";
8117
+ }, [resolvedAgentId]);
8118
+ (0, react.useEffect)(() => {
8119
+ const recentlyLocalRunIds = recentlyLocalRunIdsRef.current;
8120
+ const recentlyWakeRunIds = recentlyWakeRunIdsRef.current;
8121
+ return () => {
8122
+ recentlyLocalRunIds.forEach((timeout) => {
8123
+ clearTimeout(timeout);
8124
+ });
8125
+ recentlyLocalRunIds.clear();
8126
+ recentlyWakeRunIds.forEach((timeout) => {
8127
+ clearTimeout(timeout);
8128
+ });
8129
+ recentlyWakeRunIds.clear();
8130
+ };
8131
+ }, []);
7946
8132
  (0, react.useEffect)(() => {
7947
8133
  const threadChanged = previousThreadIdRef.current !== resolvedThreadId;
7948
8134
  previousThreadIdRef.current = resolvedThreadId;
@@ -7955,6 +8141,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
7955
8141
  const connectAbortController = new AbortController();
7956
8142
  if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
7957
8143
  const connect = async (agentToConnect) => {
8144
+ activeConnectCountRef.current += 1;
7958
8145
  try {
7959
8146
  await copilotkit.connectAgent({ agent: agentToConnect });
7960
8147
  } catch (error) {
@@ -7965,6 +8152,14 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
7965
8152
  if (!detached) setLastConnectedThreadId(resolvedThreadId);
7966
8153
  });
7967
8154
  else if (!hasExplicitThreadIdRef.current) agentToConnect.setMessages([]);
8155
+ activeConnectCountRef.current = Math.max(0, activeConnectCountRef.current - 1);
8156
+ if (!detached && activeConnectCountRef.current === 0) {
8157
+ const startReconnect = startRunActivityReconnectRef.current;
8158
+ if (pendingRunActivityReconnectRef.current && startReconnect) {
8159
+ pendingRunActivityReconnectRef.current = false;
8160
+ startReconnect(runActivityReconnectGenerationRef.current);
8161
+ }
8162
+ }
7968
8163
  }
7969
8164
  };
7970
8165
  connect(agent);
@@ -7979,6 +8174,119 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
7979
8174
  resolvedAgentId,
7980
8175
  hasExplicitThreadId
7981
8176
  ]);
8177
+ (0, react.useEffect)(() => {
8178
+ if (!hasNativeIntelligenceRunActivity) return;
8179
+ const registeredThreadStore = copilotkit.getThreadStore(resolvedAgentId);
8180
+ const threadStore = registeredThreadStore ?? standaloneRunActivityStore;
8181
+ if (!threadStore?.subscribeToRunActivity) return;
8182
+ const ownsStandaloneStore = registeredThreadStore === void 0;
8183
+ if (ownsStandaloneStore) {
8184
+ threadStore.start();
8185
+ const context = copilotkit.runtimeUrl ? {
8186
+ runtimeUrl: copilotkit.runtimeUrl,
8187
+ headers: { ...copilotkit.headers },
8188
+ wsUrl: copilotkit.intelligence?.wsUrl,
8189
+ agentId: resolvedAgentId
8190
+ } : null;
8191
+ threadStore.setContext(context);
8192
+ }
8193
+ const generation = runActivityReconnectGenerationRef.current + 1;
8194
+ runActivityReconnectGenerationRef.current = generation;
8195
+ let detached = false;
8196
+ let wakeReconnectActive = false;
8197
+ let pendingAgentIdleDrain = null;
8198
+ const hasActiveAgentRun = () => activeLocalRunIdsRef.current.size > 0 || agent.isRunning;
8199
+ const scheduleAgentIdleDrain = () => {
8200
+ if (pendingAgentIdleDrain !== null) return;
8201
+ pendingAgentIdleDrain = setTimeout(() => {
8202
+ pendingAgentIdleDrain = null;
8203
+ if (detached || runActivityReconnectGenerationRef.current !== generation || !pendingRunActivityReconnectRef.current) return;
8204
+ if (hasActiveAgentRun()) {
8205
+ scheduleAgentIdleDrain();
8206
+ return;
8207
+ }
8208
+ startRunActivityReconnectRef.current?.(generation);
8209
+ }, 10);
8210
+ };
8211
+ const connect = async () => {
8212
+ activeConnectCountRef.current += 1;
8213
+ wakeReconnectActive = true;
8214
+ const wakeRunId = pendingWakeRunIdRef.current;
8215
+ pendingWakeRunIdRef.current = void 0;
8216
+ if (wakeRunId) activeWakeRunIdsRef.current.add(wakeRunId);
8217
+ let didConnect = false;
8218
+ try {
8219
+ await copilotkit.connectAgent({ agent });
8220
+ didConnect = true;
8221
+ } catch (error) {
8222
+ if (!detached) console.error("CopilotChat: run activity reconnect failed", error);
8223
+ } finally {
8224
+ if (wakeRunId) {
8225
+ activeWakeRunIdsRef.current.delete(wakeRunId);
8226
+ if (didConnect) rememberRecentlyWakeRunId(wakeRunId);
8227
+ }
8228
+ activeConnectCountRef.current = Math.max(0, activeConnectCountRef.current - 1);
8229
+ wakeReconnectActive = false;
8230
+ if (!detached && runActivityReconnectGenerationRef.current === generation && activeConnectCountRef.current === 0 && pendingRunActivityReconnectRef.current) {
8231
+ pendingRunActivityReconnectRef.current = false;
8232
+ connect();
8233
+ }
8234
+ }
8235
+ };
8236
+ startRunActivityReconnectRef.current = (requestedGeneration) => {
8237
+ if (detached || requestedGeneration !== generation || runActivityReconnectGenerationRef.current !== generation) return;
8238
+ if (hasActiveAgentRun()) {
8239
+ pendingRunActivityReconnectRef.current = true;
8240
+ scheduleAgentIdleDrain();
8241
+ return;
8242
+ }
8243
+ if (activeConnectCountRef.current > 0) {
8244
+ if (!wakeReconnectActive) pendingRunActivityReconnectRef.current = true;
8245
+ return;
8246
+ }
8247
+ pendingRunActivityReconnectRef.current = false;
8248
+ connect();
8249
+ };
8250
+ const subscription = threadStore.subscribeToRunActivity((notification) => {
8251
+ if (notification.threadId !== resolvedThreadId) return;
8252
+ if (notification.agentId && notification.agentId !== resolvedAgentId) return;
8253
+ if (isLocalActiveRunActivity(notification)) return;
8254
+ if (notification.runId && (activeWakeRunIdsRef.current.has(notification.runId) || recentlyWakeRunIdsRef.current.has(notification.runId))) return;
8255
+ pendingWakeRunIdRef.current = notification.runId;
8256
+ startRunActivityReconnectRef.current?.(generation);
8257
+ });
8258
+ return () => {
8259
+ detached = true;
8260
+ pendingRunActivityReconnectRef.current = false;
8261
+ pendingWakeRunIdRef.current = void 0;
8262
+ if (pendingAgentIdleDrain !== null) {
8263
+ clearTimeout(pendingAgentIdleDrain);
8264
+ pendingAgentIdleDrain = null;
8265
+ }
8266
+ if (startRunActivityReconnectRef.current) startRunActivityReconnectRef.current = null;
8267
+ if (wakeReconnectActive) agent.detachActiveRun().catch(() => {});
8268
+ activeWakeRunIdsRef.current.clear();
8269
+ subscription.unsubscribe();
8270
+ if (ownsStandaloneStore) {
8271
+ threadStore.setContext(null);
8272
+ threadStore.stop();
8273
+ }
8274
+ };
8275
+ }, [
8276
+ agent,
8277
+ resolvedAgentId,
8278
+ resolvedThreadId,
8279
+ hasExplicitThreadId,
8280
+ hasNativeIntelligenceRunActivity,
8281
+ copilotkit.runtimeConnectionStatus,
8282
+ copilotkit.runtimeUrl,
8283
+ copilotkit.headers,
8284
+ copilotkit.intelligence?.wsUrl,
8285
+ copilotkit.threadEndpoints?.realtimeMetadata,
8286
+ standaloneRunActivityStore,
8287
+ isLocalActiveRunActivity,
8288
+ rememberRecentlyWakeRunId
8289
+ ]);
7982
8290
  const waitForActiveRunToSettle = (0, react.useCallback)(async () => {
7983
8291
  const maybeAware = agent;
7984
8292
  const activeRunCompletionPromise = (0, _copilotkit_core.isRunCompletionAware)(maybeAware) ? maybeAware.activeRunCompletionPromise : void 0;
@@ -8027,15 +8335,34 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
8027
8335
  role: "user",
8028
8336
  content: value
8029
8337
  });
8338
+ const localRunId = hasNativeIntelligenceRunActivity ? (0, _copilotkit_shared.randomUUID)() : void 0;
8339
+ if (localRunId) activeLocalRunIdsRef.current.add(localRunId);
8030
8340
  try {
8031
- await copilotkit.runAgent({ agent });
8341
+ await copilotkit.runAgent({
8342
+ agent,
8343
+ ...localRunId !== void 0 ? { runId: localRunId } : {}
8344
+ });
8032
8345
  } catch (error) {
8033
8346
  console.error("CopilotChat: runAgent failed", error);
8347
+ } finally {
8348
+ if (localRunId) {
8349
+ activeLocalRunIdsRef.current.delete(localRunId);
8350
+ rememberRecentlyLocalRunId(localRunId);
8351
+ }
8352
+ if (pendingRunActivityReconnectRef.current && activeLocalRunIdsRef.current.size === 0 && activeConnectCountRef.current === 0) {
8353
+ const startReconnect = startRunActivityReconnectRef.current;
8354
+ if (startReconnect) {
8355
+ pendingRunActivityReconnectRef.current = false;
8356
+ startReconnect(runActivityReconnectGenerationRef.current);
8357
+ }
8358
+ }
8034
8359
  }
8035
8360
  }, [
8036
8361
  agent,
8037
8362
  consumeAttachments,
8038
- waitForActiveRunToSettle
8363
+ waitForActiveRunToSettle,
8364
+ hasNativeIntelligenceRunActivity,
8365
+ rememberRecentlyLocalRunId
8039
8366
  ]);
8040
8367
  const handleSelectSuggestion = (0, react.useCallback)(async (suggestion) => {
8041
8368
  await waitForActiveRunToSettle();
@@ -8044,12 +8371,34 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
8044
8371
  role: "user",
8045
8372
  content: suggestion.message
8046
8373
  });
8374
+ const localRunId = hasNativeIntelligenceRunActivity ? (0, _copilotkit_shared.randomUUID)() : void 0;
8375
+ if (localRunId) activeLocalRunIdsRef.current.add(localRunId);
8047
8376
  try {
8048
- await copilotkit.runAgent({ agent });
8377
+ await copilotkit.runAgent({
8378
+ agent,
8379
+ ...localRunId !== void 0 ? { runId: localRunId } : {}
8380
+ });
8049
8381
  } catch (error) {
8050
8382
  console.error("CopilotChat: runAgent failed after selecting suggestion", error);
8383
+ } finally {
8384
+ if (localRunId) {
8385
+ activeLocalRunIdsRef.current.delete(localRunId);
8386
+ rememberRecentlyLocalRunId(localRunId);
8387
+ }
8388
+ if (pendingRunActivityReconnectRef.current && activeLocalRunIdsRef.current.size === 0 && activeConnectCountRef.current === 0) {
8389
+ const startReconnect = startRunActivityReconnectRef.current;
8390
+ if (startReconnect) {
8391
+ pendingRunActivityReconnectRef.current = false;
8392
+ startReconnect(runActivityReconnectGenerationRef.current);
8393
+ }
8394
+ }
8051
8395
  }
8052
- }, [agent, waitForActiveRunToSettle]);
8396
+ }, [
8397
+ agent,
8398
+ waitForActiveRunToSettle,
8399
+ hasNativeIntelligenceRunActivity,
8400
+ rememberRecentlyLocalRunId
8401
+ ]);
8053
8402
  const stopCurrentRun = (0, react.useCallback)(() => {
8054
8403
  try {
8055
8404
  copilotkit.stopAgent({ agent });
@@ -8828,7 +9177,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
8828
9177
  * during prerender to avoid hydration mismatch).
8829
9178
  * - Feeds the element domain data: `threads`, `loading`, `error`,
8830
9179
  * `activeThreadId`, `licensed`, fetch-more state.
8831
- * - Routes the element's nine outbound events to core thread operations
9180
+ * - Routes the element's outbound events to core thread operations
8832
9181
  * ({@link useThreads}) and chat-configuration changes.
8833
9182
  * - Registers with the surrounding chat configuration so the header
8834
9183
  * thread-list launcher appears, and binds the element `open` state to the
@@ -8855,16 +9204,16 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
8855
9204
  * </CopilotKitProvider>
8856
9205
  * ```
8857
9206
  */
8858
- function CopilotThreadsDrawer({ agentId, onThreadSelect, onNewThread, onLicensed, licenseUrl, renderRow, label, limit, "data-testid": dataTestId = "copilot-threads-drawer" }) {
9207
+ function CopilotThreadsDrawer({ agentId, onThreadSelect, onNewThread, onLicensed, licenseUrl, renderRow, label, recentLabel, collapsible, onCollapseChange, limit, "data-testid": dataTestId = "copilot-threads-drawer" }) {
8859
9208
  const configuration = useCopilotChatConfiguration();
8860
9209
  const { status, checkFeature } = useLicenseContext();
8861
9210
  const licensePresent = status === "valid" || status === "expiring";
8862
9211
  const featureLicensed = checkFeature("threads");
8863
9212
  const licensed = licensePresent && featureLicensed;
8864
9213
  const licensePending = status === null;
8865
- const resolvedAgentId = agentId ?? configuration?.agentId ?? "default";
9214
+ const resolvedAgentId = agentId ?? configuration?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
8866
9215
  const activeThreadId = configuration?.threadId ?? null;
8867
- const { threads, isLoading, listError, hasMoreThreads, isFetchingMoreThreads, archiveThread, unarchiveThread, deleteThread, fetchMoreThreads, refetchThreads, startNewThread } = useThreads({
9216
+ const { threads, isLoading, listError, fetchMoreError, hasMoreThreads, isFetchingMoreThreads, archiveThread, unarchiveThread, deleteThread, fetchMoreThreads, refetchThreads, startNewThread } = useThreads({
8868
9217
  agentId: resolvedAgentId,
8869
9218
  includeArchived: true,
8870
9219
  enabled: licensed,
@@ -8945,6 +9294,9 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
8945
9294
  const handleLoadMore = (0, react.useCallback)(() => {
8946
9295
  fetchMoreThreads();
8947
9296
  }, [fetchMoreThreads]);
9297
+ const handleCollapseChange = (0, react.useCallback)((collapsed) => {
9298
+ onCollapseChange?.(collapsed);
9299
+ }, [onCollapseChange]);
8948
9300
  const handlersRef = (0, react.useRef)({
8949
9301
  handleThreadSelected,
8950
9302
  handleNewThread,
@@ -8955,7 +9307,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
8955
9307
  handleRetry,
8956
9308
  handleOpenChange,
8957
9309
  handleLicensed,
8958
- handleLoadMore
9310
+ handleLoadMore,
9311
+ handleCollapseChange
8959
9312
  });
8960
9313
  handlersRef.current = {
8961
9314
  handleThreadSelected,
@@ -8967,7 +9320,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
8967
9320
  handleRetry,
8968
9321
  handleOpenChange,
8969
9322
  handleLicensed,
8970
- handleLoadMore
9323
+ handleLoadMore,
9324
+ handleCollapseChange
8971
9325
  };
8972
9326
  (0, react.useEffect)(() => {
8973
9327
  const el = elementRef.current;
@@ -9002,6 +9356,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
9002
9356
  };
9003
9357
  const onLicensedEvent = () => handlersRef.current.handleLicensed();
9004
9358
  const onLoadMore = () => handlersRef.current.handleLoadMore();
9359
+ const onCollapseChangeEvent = (event) => {
9360
+ const detail = event.detail;
9361
+ handlersRef.current.handleCollapseChange(detail.collapsed);
9362
+ };
9005
9363
  el.addEventListener("thread-selected", onThreadSelected);
9006
9364
  el.addEventListener("new-thread", onNewThreadEvent);
9007
9365
  el.addEventListener("archive", onArchive);
@@ -9012,6 +9370,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
9012
9370
  el.addEventListener("retry", onRetry);
9013
9371
  el.addEventListener("licensed", onLicensedEvent);
9014
9372
  el.addEventListener("load-more", onLoadMore);
9373
+ el.addEventListener("collapse-change", onCollapseChangeEvent);
9015
9374
  return () => {
9016
9375
  el.removeEventListener("thread-selected", onThreadSelected);
9017
9376
  el.removeEventListener("new-thread", onNewThreadEvent);
@@ -9023,6 +9382,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
9023
9382
  el.removeEventListener("retry", onRetry);
9024
9383
  el.removeEventListener("licensed", onLicensedEvent);
9025
9384
  el.removeEventListener("load-more", onLoadMore);
9385
+ el.removeEventListener("collapse-change", onCollapseChangeEvent);
9026
9386
  };
9027
9387
  }, [mounted]);
9028
9388
  (0, react.useEffect)(() => {
@@ -9039,9 +9399,11 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
9039
9399
  el.licensed = licensed || licensePending;
9040
9400
  el.hasMore = hasMoreThreads;
9041
9401
  el.fetchingMore = isFetchingMoreThreads;
9402
+ el.fetchMoreError = fetchMoreError ? fetchMoreError.message : null;
9042
9403
  }, [
9043
9404
  isLoading,
9044
9405
  listError,
9406
+ fetchMoreError,
9045
9407
  activeThreadId,
9046
9408
  licensed,
9047
9409
  licensePending,
@@ -9064,6 +9426,11 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
9064
9426
  if (!el) return;
9065
9427
  if (licenseUrl !== void 0) el.licenseUrl = licenseUrl;
9066
9428
  }, [licenseUrl, mounted]);
9429
+ (0, react.useEffect)(() => {
9430
+ const el = elementRef.current;
9431
+ if (!el) return;
9432
+ if (collapsible !== void 0) el.collapsible = collapsible;
9433
+ }, [collapsible, mounted]);
9067
9434
  const rowChildren = (0, react.useMemo)(() => {
9068
9435
  if (!renderRow) return null;
9069
9436
  return drawerThreads.map((drawerThread) => {
@@ -9084,7 +9451,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
9084
9451
  if (!mounted) return null;
9085
9452
  return react.default.createElement(_copilotkit_web_components_threads_drawer.COPILOTKIT_THREADS_DRAWER_TAG, {
9086
9453
  ref: elementRef,
9087
- "data-testid": dataTestId
9454
+ "data-testid": dataTestId,
9455
+ ...recentLabel !== void 0 ? { "recent-label": recentLabel } : {}
9088
9456
  }, rowChildren);
9089
9457
  }
9090
9458
  CopilotThreadsDrawer.displayName = "CopilotThreadsDrawer";
@@ -10623,8 +10991,18 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
10623
10991
  }, [agent, getSubscriber]);
10624
10992
  };
10625
10993
  function CopilotListenersAgentSubscription() {
10626
- const resolvedAgentId = useCopilotChatConfiguration()?.agentId;
10627
- const { agent } = useAgent({ agentId: resolvedAgentId });
10994
+ const { copilotkit } = useCopilotKit();
10995
+ const configAgentId = useCopilotChatConfiguration()?.agentId;
10996
+ const { agent } = useAgent({ agentId: (0, react.useMemo)(() => {
10997
+ const requested = configAgentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
10998
+ const registered = copilotkit.agents ?? {};
10999
+ if (registered[requested]) return requested;
11000
+ if (requested === _copilotkit_shared.DEFAULT_AGENT_ID) {
11001
+ const firstRegistered = Object.keys(registered)[0];
11002
+ if (firstRegistered) return firstRegistered;
11003
+ }
11004
+ return requested;
11005
+ }, [configAgentId, copilotkit.agents]) });
10628
11006
  usePredictStateSubscription(agent);
10629
11007
  return null;
10630
11008
  }
@@ -11239,11 +11617,13 @@ exports.useLearnFromUserAction = useLearnFromUserAction;
11239
11617
  exports.useLearnFromUserActionInCurrentThread = useLearnFromUserActionInCurrentThread;
11240
11618
  exports.useLearningContainers = useLearningContainers;
11241
11619
  exports.useLearningContainersInCurrentThread = useLearningContainersInCurrentThread;
11620
+ exports.useMemories = useMemories;
11242
11621
  exports.useRenderActivityMessage = useRenderActivityMessage;
11243
11622
  exports.useRenderCustomMessages = useRenderCustomMessages;
11244
11623
  exports.useRenderTool = useRenderTool;
11245
11624
  exports.useRenderToolCall = useRenderToolCall;
11246
11625
  exports.useSandboxFunctions = useSandboxFunctions;
11626
+ exports.useSubagent = useSubagent;
11247
11627
  exports.useSuggestions = useSuggestions;
11248
11628
  exports.useThreads = useThreads;
11249
11629
  Object.keys(_copilotkit_core).forEach(function (k) {