@copilotkit/react-core 1.57.0 → 1.57.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/{copilotkit-DFaI4j2r.d.mts → copilotkit-BN4I_y1n.d.mts} +64 -8
  2. package/dist/copilotkit-BN4I_y1n.d.mts.map +1 -0
  3. package/dist/{copilotkit-DGbvw8n2.cjs → copilotkit-C3k13WZn.cjs} +572 -435
  4. package/dist/copilotkit-C3k13WZn.cjs.map +1 -0
  5. package/dist/{copilotkit-CPe2-340.mjs → copilotkit-DjxXMYHG.mjs} +571 -440
  6. package/dist/copilotkit-DjxXMYHG.mjs.map +1 -0
  7. package/dist/{copilotkit-Dg4r4Gi_.d.cts → copilotkit-sQWiKtxA.d.cts} +64 -8
  8. package/dist/copilotkit-sQWiKtxA.d.cts.map +1 -0
  9. package/dist/index.cjs +2 -5
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +1 -1
  12. package/dist/index.d.mts +1 -1
  13. package/dist/index.mjs +2 -5
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/index.umd.js +449 -502
  16. package/dist/index.umd.js.map +1 -1
  17. package/dist/v2/context.cjs +135 -0
  18. package/dist/v2/context.cjs.map +1 -0
  19. package/dist/v2/context.d.cts +148 -0
  20. package/dist/v2/context.d.cts.map +1 -0
  21. package/dist/v2/context.d.mts +148 -0
  22. package/dist/v2/context.d.mts.map +1 -0
  23. package/dist/v2/context.mjs +129 -0
  24. package/dist/v2/context.mjs.map +1 -0
  25. package/dist/v2/headless.cjs +1043 -0
  26. package/dist/v2/headless.cjs.map +1 -0
  27. package/dist/v2/headless.d.cts +605 -0
  28. package/dist/v2/headless.d.cts.map +1 -0
  29. package/dist/v2/headless.d.mts +512 -0
  30. package/dist/v2/headless.d.mts.map +1 -0
  31. package/dist/v2/headless.mjs +997 -0
  32. package/dist/v2/headless.mjs.map +1 -0
  33. package/dist/v2/index.cjs +2 -1
  34. package/dist/v2/index.css +1 -1
  35. package/dist/v2/index.d.cts +2 -2
  36. package/dist/v2/index.d.mts +2 -2
  37. package/dist/v2/index.mjs +2 -2
  38. package/dist/v2/index.umd.js +584 -441
  39. package/dist/v2/index.umd.js.map +1 -1
  40. package/package.json +14 -6
  41. package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +5 -6
  42. package/src/hooks/use-copilot-chat_internal.ts +0 -1
  43. package/src/v2/components/chat/CopilotChat.tsx +2 -1
  44. package/src/v2/components/chat/CopilotChatMessageView.tsx +24 -9
  45. package/src/v2/components/chat/CopilotChatView.tsx +2 -2
  46. package/src/v2/components/chat/__tests__/CopilotChat.welcomeGate.test.tsx +1 -3
  47. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +29 -25
  48. package/src/v2/components/chat/__tests__/MCPAppsUiMessage.e2e.test.tsx +5 -60
  49. package/src/v2/components/index.ts +1 -0
  50. package/src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx +286 -0
  51. package/src/v2/components/intelligence-indicator/__tests__/IntelligenceIndicator.e2e.test.tsx +464 -0
  52. package/src/v2/components/intelligence-indicator/index.ts +2 -0
  53. package/src/v2/context.ts +62 -0
  54. package/src/v2/headless.ts +42 -0
  55. package/src/v2/hooks/__tests__/standard-schema.test.tsx +2 -2
  56. package/src/v2/hooks/__tests__/use-agent-context.test.tsx +3 -3
  57. package/src/v2/hooks/__tests__/use-agent-stability.test.tsx +3 -3
  58. package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +85 -85
  59. package/src/v2/hooks/__tests__/use-interrupt.test.tsx +2 -2
  60. package/src/v2/hooks/__tests__/use-render-tool.test.tsx +2 -2
  61. package/src/v2/hooks/__tests__/use-threads.test.tsx +2 -2
  62. package/src/v2/hooks/__tests__/zod-regression.test.tsx +2 -2
  63. package/src/v2/hooks/use-agent-context.tsx +1 -1
  64. package/src/v2/hooks/use-agent.tsx +9 -118
  65. package/src/v2/hooks/use-configure-suggestions.tsx +1 -1
  66. package/src/v2/hooks/use-frontend-tool.tsx +2 -2
  67. package/src/v2/hooks/use-human-in-the-loop.tsx +1 -1
  68. package/src/v2/hooks/use-interrupt.tsx +1 -1
  69. package/src/v2/hooks/use-render-activity-message.tsx +3 -11
  70. package/src/v2/hooks/use-render-custom-messages.tsx +1 -6
  71. package/src/v2/hooks/use-render-tool-call.tsx +1 -1
  72. package/src/v2/hooks/use-render-tool.tsx +2 -2
  73. package/src/v2/hooks/use-suggestions.tsx +1 -1
  74. package/src/v2/hooks/use-threads.tsx +1 -1
  75. package/src/v2/providers/CopilotKitProvider.tsx +19 -59
  76. package/src/v2/styles/globals.css +118 -0
  77. package/tsdown.config.ts +75 -0
  78. package/dist/copilotkit-CPe2-340.mjs.map +0 -1
  79. package/dist/copilotkit-DFaI4j2r.d.mts.map +0 -1
  80. package/dist/copilotkit-DGbvw8n2.cjs.map +0 -1
  81. package/dist/copilotkit-Dg4r4Gi_.d.cts.map +0 -1
  82. package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx +0 -333
@@ -1294,6 +1294,197 @@ function useKatexStyles() {
1294
1294
  }, []);
1295
1295
  }
1296
1296
 
1297
+ //#endregion
1298
+ //#region src/v2/lib/react-core.ts
1299
+ var CopilotKitCoreReact = class extends CopilotKitCore {
1300
+ constructor(config) {
1301
+ super(config);
1302
+ this._renderToolCalls = [];
1303
+ this._hookRenderToolCalls = /* @__PURE__ */ new Map();
1304
+ this._cachedMergedRenderToolCalls = null;
1305
+ this._renderCustomMessages = [];
1306
+ this._renderActivityMessages = [];
1307
+ this._interruptElement = null;
1308
+ this._renderToolCalls = config.renderToolCalls ?? [];
1309
+ this._renderCustomMessages = config.renderCustomMessages ?? [];
1310
+ this._renderActivityMessages = config.renderActivityMessages ?? [];
1311
+ }
1312
+ get renderCustomMessages() {
1313
+ return this._renderCustomMessages;
1314
+ }
1315
+ get renderActivityMessages() {
1316
+ return this._renderActivityMessages;
1317
+ }
1318
+ get renderToolCalls() {
1319
+ if (this._hookRenderToolCalls.size === 0) return this._renderToolCalls;
1320
+ if (this._cachedMergedRenderToolCalls) return this._cachedMergedRenderToolCalls;
1321
+ const merged = /* @__PURE__ */ new Map();
1322
+ for (const rc of this._renderToolCalls) merged.set(`${rc.agentId ?? ""}:${rc.name}`, rc);
1323
+ for (const [key, rc] of this._hookRenderToolCalls) merged.set(key, rc);
1324
+ this._cachedMergedRenderToolCalls = Array.from(merged.values());
1325
+ return this._cachedMergedRenderToolCalls;
1326
+ }
1327
+ setRenderActivityMessages(renderers) {
1328
+ this._renderActivityMessages = renderers;
1329
+ }
1330
+ setRenderCustomMessages(renderers) {
1331
+ this._renderCustomMessages = renderers;
1332
+ }
1333
+ setRenderToolCalls(renderToolCalls) {
1334
+ this._renderToolCalls = renderToolCalls;
1335
+ this._cachedMergedRenderToolCalls = null;
1336
+ this._notifyRenderToolCallsChanged();
1337
+ }
1338
+ addHookRenderToolCall(entry) {
1339
+ const key = `${entry.agentId ?? ""}:${entry.name}`;
1340
+ this._hookRenderToolCalls.set(key, entry);
1341
+ this._cachedMergedRenderToolCalls = null;
1342
+ this._notifyRenderToolCallsChanged();
1343
+ }
1344
+ removeHookRenderToolCall(name, agentId) {
1345
+ const key = `${agentId ?? ""}:${name}`;
1346
+ if (this._hookRenderToolCalls.delete(key)) {
1347
+ this._cachedMergedRenderToolCalls = null;
1348
+ this._notifyRenderToolCallsChanged();
1349
+ }
1350
+ }
1351
+ _notifyRenderToolCallsChanged() {
1352
+ this.notifySubscribers((subscriber) => {
1353
+ const reactSubscriber = subscriber;
1354
+ if (reactSubscriber.onRenderToolCallsChanged) reactSubscriber.onRenderToolCallsChanged({
1355
+ copilotkit: this,
1356
+ renderToolCalls: this.renderToolCalls
1357
+ });
1358
+ }, "Subscriber onRenderToolCallsChanged error:");
1359
+ }
1360
+ get interruptElement() {
1361
+ return this._interruptElement;
1362
+ }
1363
+ setInterruptElement(element) {
1364
+ this._interruptElement = element;
1365
+ this.notifySubscribers((subscriber) => {
1366
+ subscriber.onInterruptElementChanged?.({
1367
+ copilotkit: this,
1368
+ interruptElement: this._interruptElement
1369
+ });
1370
+ }, "Subscriber onInterruptElementChanged error:");
1371
+ }
1372
+ subscribe(subscriber) {
1373
+ return super.subscribe(subscriber);
1374
+ }
1375
+ /**
1376
+ * Wait for pending React state updates before the follow-up agent run.
1377
+ *
1378
+ * When a frontend tool handler calls setState(), React 18 batches the update
1379
+ * and schedules a commit via its internal scheduler (MessageChannel). The
1380
+ * useAgentContext hook registers context via useLayoutEffect, which runs
1381
+ * synchronously after React commits that batch.
1382
+ *
1383
+ * Awaiting a zero-delay timeout yields to the macrotask queue. React's
1384
+ * MessageChannel task runs first, committing the pending state and running
1385
+ * useLayoutEffect (which updates the context store). The follow-up runAgent
1386
+ * call then reads fresh context.
1387
+ */
1388
+ async waitForPendingFrameworkUpdates() {
1389
+ await new Promise((resolve) => setTimeout(resolve, 0));
1390
+ }
1391
+ };
1392
+
1393
+ //#endregion
1394
+ //#region src/v2/context.ts
1395
+ const CopilotKitContext = createContext(null);
1396
+ const useCopilotKit = () => {
1397
+ const context = useContext(CopilotKitContext);
1398
+ const [, forceUpdate] = useReducer((x) => x + 1, 0);
1399
+ if (!context) throw new Error("useCopilotKit must be used within CopilotKitProvider");
1400
+ useEffect(() => {
1401
+ const subscription = context.copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
1402
+ forceUpdate();
1403
+ } });
1404
+ return () => {
1405
+ subscription.unsubscribe();
1406
+ };
1407
+ }, []);
1408
+ return context;
1409
+ };
1410
+ const LicenseContext = createContext({
1411
+ status: null,
1412
+ license: null,
1413
+ checkFeature: () => true,
1414
+ getLimit: () => null
1415
+ });
1416
+ const useLicenseContext = () => useContext(LicenseContext);
1417
+
1418
+ //#endregion
1419
+ //#region src/v2/hooks/use-render-tool-call.tsx
1420
+ /**
1421
+ * Memoized component that renders a single tool call.
1422
+ * This prevents unnecessary re-renders when parent components update
1423
+ * but the tool call data hasn't changed.
1424
+ */
1425
+ const ToolCallRenderer = React.memo(function ToolCallRenderer({ toolCall, toolMessage, RenderComponent, isExecuting }) {
1426
+ const args = useMemo(() => partialJSONParse(toolCall.function.arguments), [toolCall.function.arguments]);
1427
+ const toolName = toolCall.function.name;
1428
+ if (toolMessage) return /* @__PURE__ */ jsx(RenderComponent, {
1429
+ name: toolName,
1430
+ toolCallId: toolCall.id,
1431
+ args,
1432
+ status: ToolCallStatus.Complete,
1433
+ result: toolMessage.content
1434
+ });
1435
+ else if (isExecuting) return /* @__PURE__ */ jsx(RenderComponent, {
1436
+ name: toolName,
1437
+ toolCallId: toolCall.id,
1438
+ args,
1439
+ status: ToolCallStatus.Executing,
1440
+ result: void 0
1441
+ });
1442
+ else return /* @__PURE__ */ jsx(RenderComponent, {
1443
+ name: toolName,
1444
+ toolCallId: toolCall.id,
1445
+ args,
1446
+ status: ToolCallStatus.InProgress,
1447
+ result: void 0
1448
+ });
1449
+ }, (prevProps, nextProps) => {
1450
+ if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
1451
+ if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
1452
+ if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
1453
+ if (prevProps.toolMessage?.content !== nextProps.toolMessage?.content) return false;
1454
+ if (prevProps.isExecuting !== nextProps.isExecuting) return false;
1455
+ if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
1456
+ return true;
1457
+ });
1458
+ /**
1459
+ * Hook that returns a function to render tool calls based on the render functions
1460
+ * defined in CopilotKitProvider.
1461
+ *
1462
+ * @returns A function that takes a tool call and optional tool message and returns the rendered component
1463
+ */
1464
+ function useRenderToolCall() {
1465
+ const { copilotkit, executingToolCallIds } = useCopilotKit();
1466
+ const agentId = useCopilotChatConfiguration()?.agentId ?? DEFAULT_AGENT_ID;
1467
+ const renderToolCalls = useSyncExternalStore((callback) => {
1468
+ return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
1469
+ }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
1470
+ return useCallback(({ toolCall, toolMessage }) => {
1471
+ const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
1472
+ const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
1473
+ if (!renderConfig) return null;
1474
+ const RenderComponent = renderConfig.render;
1475
+ return /* @__PURE__ */ jsx(ToolCallRenderer, {
1476
+ toolCall,
1477
+ toolMessage,
1478
+ RenderComponent,
1479
+ isExecuting: executingToolCallIds.has(toolCall.id)
1480
+ }, toolCall.id);
1481
+ }, [
1482
+ renderToolCalls,
1483
+ executingToolCallIds,
1484
+ agentId
1485
+ ]);
1486
+ }
1487
+
1297
1488
  //#endregion
1298
1489
  //#region src/v2/components/CopilotKitInspector.tsx
1299
1490
  const CopilotKitInspector = ({ core, ...rest }) => {
@@ -2937,102 +3128,6 @@ function A2UICatalogContext({ catalog, includeSchema }) {
2937
3128
  return null;
2938
3129
  }
2939
3130
 
2940
- //#endregion
2941
- //#region src/v2/lib/react-core.ts
2942
- var CopilotKitCoreReact = class extends CopilotKitCore {
2943
- constructor(config) {
2944
- super(config);
2945
- this._renderToolCalls = [];
2946
- this._hookRenderToolCalls = /* @__PURE__ */ new Map();
2947
- this._cachedMergedRenderToolCalls = null;
2948
- this._renderCustomMessages = [];
2949
- this._renderActivityMessages = [];
2950
- this._interruptElement = null;
2951
- this._renderToolCalls = config.renderToolCalls ?? [];
2952
- this._renderCustomMessages = config.renderCustomMessages ?? [];
2953
- this._renderActivityMessages = config.renderActivityMessages ?? [];
2954
- }
2955
- get renderCustomMessages() {
2956
- return this._renderCustomMessages;
2957
- }
2958
- get renderActivityMessages() {
2959
- return this._renderActivityMessages;
2960
- }
2961
- get renderToolCalls() {
2962
- if (this._hookRenderToolCalls.size === 0) return this._renderToolCalls;
2963
- if (this._cachedMergedRenderToolCalls) return this._cachedMergedRenderToolCalls;
2964
- const merged = /* @__PURE__ */ new Map();
2965
- for (const rc of this._renderToolCalls) merged.set(`${rc.agentId ?? ""}:${rc.name}`, rc);
2966
- for (const [key, rc] of this._hookRenderToolCalls) merged.set(key, rc);
2967
- this._cachedMergedRenderToolCalls = Array.from(merged.values());
2968
- return this._cachedMergedRenderToolCalls;
2969
- }
2970
- setRenderActivityMessages(renderers) {
2971
- this._renderActivityMessages = renderers;
2972
- }
2973
- setRenderCustomMessages(renderers) {
2974
- this._renderCustomMessages = renderers;
2975
- }
2976
- setRenderToolCalls(renderToolCalls) {
2977
- this._renderToolCalls = renderToolCalls;
2978
- this._cachedMergedRenderToolCalls = null;
2979
- this._notifyRenderToolCallsChanged();
2980
- }
2981
- addHookRenderToolCall(entry) {
2982
- const key = `${entry.agentId ?? ""}:${entry.name}`;
2983
- this._hookRenderToolCalls.set(key, entry);
2984
- this._cachedMergedRenderToolCalls = null;
2985
- this._notifyRenderToolCallsChanged();
2986
- }
2987
- removeHookRenderToolCall(name, agentId) {
2988
- const key = `${agentId ?? ""}:${name}`;
2989
- if (this._hookRenderToolCalls.delete(key)) {
2990
- this._cachedMergedRenderToolCalls = null;
2991
- this._notifyRenderToolCallsChanged();
2992
- }
2993
- }
2994
- _notifyRenderToolCallsChanged() {
2995
- this.notifySubscribers((subscriber) => {
2996
- const reactSubscriber = subscriber;
2997
- if (reactSubscriber.onRenderToolCallsChanged) reactSubscriber.onRenderToolCallsChanged({
2998
- copilotkit: this,
2999
- renderToolCalls: this.renderToolCalls
3000
- });
3001
- }, "Subscriber onRenderToolCallsChanged error:");
3002
- }
3003
- get interruptElement() {
3004
- return this._interruptElement;
3005
- }
3006
- setInterruptElement(element) {
3007
- this._interruptElement = element;
3008
- this.notifySubscribers((subscriber) => {
3009
- subscriber.onInterruptElementChanged?.({
3010
- copilotkit: this,
3011
- interruptElement: this._interruptElement
3012
- });
3013
- }, "Subscriber onInterruptElementChanged error:");
3014
- }
3015
- subscribe(subscriber) {
3016
- return super.subscribe(subscriber);
3017
- }
3018
- /**
3019
- * Wait for pending React state updates before the follow-up agent run.
3020
- *
3021
- * When a frontend tool handler calls setState(), React 18 batches the update
3022
- * and schedules a commit via its internal scheduler (MessageChannel). The
3023
- * useAgentContext hook registers context via useLayoutEffect, which runs
3024
- * synchronously after React commits that batch.
3025
- *
3026
- * Awaiting a zero-delay timeout yields to the macrotask queue. React's
3027
- * MessageChannel task runs first, committing the pending state and running
3028
- * useLayoutEffect (which updates the context store). The follow-up runAgent
3029
- * call then reads fresh context.
3030
- */
3031
- async waitForPendingFrameworkUpdates() {
3032
- await new Promise((resolve) => setTimeout(resolve, 0));
3033
- }
3034
- };
3035
-
3036
3131
  //#endregion
3037
3132
  //#region src/v2/providers/CopilotKitProvider.tsx
3038
3133
  const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
@@ -3048,12 +3143,6 @@ const DEFAULT_DESIGN_SKILL = `When generating UI with generateSandboxedUi, follo
3048
3143
  - Minimal transitions (150ms) for hover/focus states only. No decorative animations.
3049
3144
  - Keep the UI focused and dense — avoid excessive padding. Use compact spacing (8–12px gaps, 10–14px padding in controls).`;
3050
3145
  const GENERATE_SANDBOXED_UI_DESCRIPTION = "Generate sandboxed UI. IMPORTANT: The generated code runs in a sandboxed iframe WITHOUT same-origin access. Do NOT use localStorage, sessionStorage, document.cookie, IndexedDB, or fetch/XMLHttpRequest to same-origin URLs. To communicate with the host application, use Websandbox.connection.remote.<functionName>(args) which returns a Promise.\n\nYou CAN use external libraries from CDNs by including <script> or <link> tags in the HTML <head> (e.g., Chart.js, D3, Three.js, x-data-spreadsheet, etc.). CDN resources load normally inside the sandbox.\n\nPARAMETER ORDER IS CRITICAL — generate parameters in exactly this order:\n1. initialHeight + placeholderMessages (shown to user while generating)\n2. css (all styles FIRST — the user sees a placeholder until CSS is complete)\n3. html (streams in live — the user watches the UI build as HTML is generated)\n4. jsFunctions (reusable helper functions)\n5. jsExpressions (applied one-by-one — the user sees each expression take effect)";
3051
- const CopilotKitContext = createContext({
3052
- copilotkit: null,
3053
- executingToolCallIds: /* @__PURE__ */ new Set()
3054
- });
3055
- const LicenseContext = createContext(createLicenseContextValue(null));
3056
- const useLicenseContext = () => useContext(LicenseContext);
3057
3146
  function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
3058
3147
  const empty = useMemo(() => [], []);
3059
3148
  const value = prop ?? empty;
@@ -3275,13 +3364,9 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
3275
3364
  onErrorRef.current = onError;
3276
3365
  }, [onError]);
3277
3366
  useEffect(() => {
3278
- if (!onErrorRef.current) return;
3279
3367
  const subscription = copilotkit.subscribe({ onError: (event) => {
3280
- onErrorRef.current?.({
3281
- error: event.error,
3282
- code: event.code,
3283
- context: event.context
3284
- });
3368
+ if (onErrorRef.current) onErrorRef.current(event);
3369
+ else console.error(`[CopilotKit] Error (${event.code}):`, event.error, event.context ?? {});
3285
3370
  } });
3286
3371
  return () => {
3287
3372
  subscription.unsubscribe();
@@ -3321,327 +3406,81 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
3321
3406
  useEffect(() => {
3322
3407
  if (!didMountRef.current) return;
3323
3408
  copilotkit.setRenderCustomMessages(renderCustomMessagesList);
3324
- }, [copilotkit, renderCustomMessagesList]);
3325
- useEffect(() => {
3326
- didMountRef.current = true;
3327
- }, []);
3328
- useEffect(() => {
3329
- copilotkit.setDefaultThrottleMs(defaultThrottleMs);
3330
- }, [copilotkit, defaultThrottleMs]);
3331
- const designSkill = openGenerativeUI?.designSkill ?? DEFAULT_DESIGN_SKILL;
3332
- useLayoutEffect(() => {
3333
- if (!copilotkit || !openGenUIActive) return;
3334
- const id = copilotkit.addContext({
3335
- description: "Design guidelines for the generateSandboxedUi tool. Follow these when building UI.",
3336
- value: designSkill
3337
- });
3338
- return () => {
3339
- copilotkit.removeContext(id);
3340
- };
3341
- }, [
3342
- copilotkit,
3343
- designSkill,
3344
- openGenUIActive
3345
- ]);
3346
- const sandboxFunctionsDescriptors = useMemo(() => {
3347
- if (sandboxFunctionsList.length === 0) return null;
3348
- return JSON.stringify(sandboxFunctionsList.map((fn) => ({
3349
- name: fn.name,
3350
- description: fn.description,
3351
- parameters: schemaToJsonSchema(fn.parameters, { zodToJsonSchema })
3352
- })));
3353
- }, [sandboxFunctionsList]);
3354
- useLayoutEffect(() => {
3355
- if (!copilotkit || !sandboxFunctionsDescriptors || !openGenUIActive) return;
3356
- const id = copilotkit.addContext({
3357
- description: "Sandbox functions available in generated sandboxed UI code. Call via: await Websandbox.connection.remote.<functionName>(args)",
3358
- value: sandboxFunctionsDescriptors
3359
- });
3360
- return () => {
3361
- copilotkit.removeContext(id);
3362
- };
3363
- }, [
3364
- copilotkit,
3365
- sandboxFunctionsDescriptors,
3366
- openGenUIActive
3367
- ]);
3368
- const contextValue = useMemo(() => ({
3369
- copilotkit,
3370
- executingToolCallIds
3371
- }), [copilotkit, executingToolCallIds]);
3372
- const licenseContextValue = useMemo(() => createLicenseContextValue(null), []);
3373
- return /* @__PURE__ */ jsx(SandboxFunctionsContext.Provider, {
3374
- value: sandboxFunctionsList,
3375
- children: /* @__PURE__ */ jsx(CopilotKitContext.Provider, {
3376
- value: contextValue,
3377
- children: /* @__PURE__ */ jsxs(LicenseContext.Provider, {
3378
- value: licenseContextValue,
3379
- children: [
3380
- runtimeA2UIEnabled && /* @__PURE__ */ jsx(A2UIBuiltInToolCallRenderer, {}),
3381
- runtimeA2UIEnabled && /* @__PURE__ */ jsx(A2UICatalogContext, {
3382
- catalog: a2ui?.catalog,
3383
- includeSchema: a2ui?.includeSchema
3384
- }),
3385
- children,
3386
- shouldRenderInspector ? /* @__PURE__ */ jsx(CopilotKitInspector, {
3387
- core: copilotkit,
3388
- defaultAnchor: inspectorDefaultAnchor
3389
- }) : null,
3390
- runtimeLicenseStatus === "none" && !resolvedPublicKey && /* @__PURE__ */ jsx(LicenseWarningBanner, { type: "no_license" }),
3391
- runtimeLicenseStatus === "expired" && /* @__PURE__ */ jsx(LicenseWarningBanner, { type: "expired" }),
3392
- runtimeLicenseStatus === "invalid" && /* @__PURE__ */ jsx(LicenseWarningBanner, { type: "invalid" }),
3393
- runtimeLicenseStatus === "expiring" && /* @__PURE__ */ jsx(LicenseWarningBanner, { type: "expiring" })
3394
- ]
3395
- })
3396
- })
3397
- });
3398
- };
3399
- const useCopilotKit = () => {
3400
- const context = useContext(CopilotKitContext);
3401
- const [, forceUpdate] = useReducer((x) => x + 1, 0);
3402
- if (!context) throw new Error("useCopilotKit must be used within CopilotKitProvider");
3403
- useEffect(() => {
3404
- const subscription = context.copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
3405
- forceUpdate();
3406
- } });
3407
- return () => {
3408
- subscription.unsubscribe();
3409
- };
3410
- }, []);
3411
- return context;
3412
- };
3413
-
3414
- //#endregion
3415
- //#region src/v2/hooks/use-render-tool-call.tsx
3416
- /**
3417
- * Memoized component that renders a single tool call.
3418
- * This prevents unnecessary re-renders when parent components update
3419
- * but the tool call data hasn't changed.
3420
- */
3421
- const ToolCallRenderer = React.memo(function ToolCallRenderer({ toolCall, toolMessage, RenderComponent, isExecuting }) {
3422
- const args = useMemo(() => partialJSONParse(toolCall.function.arguments), [toolCall.function.arguments]);
3423
- const toolName = toolCall.function.name;
3424
- if (toolMessage) return /* @__PURE__ */ jsx(RenderComponent, {
3425
- name: toolName,
3426
- toolCallId: toolCall.id,
3427
- args,
3428
- status: ToolCallStatus.Complete,
3429
- result: toolMessage.content
3430
- });
3431
- else if (isExecuting) return /* @__PURE__ */ jsx(RenderComponent, {
3432
- name: toolName,
3433
- toolCallId: toolCall.id,
3434
- args,
3435
- status: ToolCallStatus.Executing,
3436
- result: void 0
3437
- });
3438
- else return /* @__PURE__ */ jsx(RenderComponent, {
3439
- name: toolName,
3440
- toolCallId: toolCall.id,
3441
- args,
3442
- status: ToolCallStatus.InProgress,
3443
- result: void 0
3444
- });
3445
- }, (prevProps, nextProps) => {
3446
- if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
3447
- if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
3448
- if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
3449
- if (prevProps.toolMessage?.content !== nextProps.toolMessage?.content) return false;
3450
- if (prevProps.isExecuting !== nextProps.isExecuting) return false;
3451
- if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
3452
- return true;
3453
- });
3454
- /**
3455
- * Hook that returns a function to render tool calls based on the render functions
3456
- * defined in CopilotKitProvider.
3457
- *
3458
- * @returns A function that takes a tool call and optional tool message and returns the rendered component
3459
- */
3460
- function useRenderToolCall() {
3461
- const { copilotkit, executingToolCallIds } = useCopilotKit();
3462
- const agentId = useCopilotChatConfiguration()?.agentId ?? DEFAULT_AGENT_ID;
3463
- const renderToolCalls = useSyncExternalStore((callback) => {
3464
- return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
3465
- }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
3466
- return useCallback(({ toolCall, toolMessage }) => {
3467
- const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
3468
- const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
3469
- if (!renderConfig) return null;
3470
- const RenderComponent = renderConfig.render;
3471
- return /* @__PURE__ */ jsx(ToolCallRenderer, {
3472
- toolCall,
3473
- toolMessage,
3474
- RenderComponent,
3475
- isExecuting: executingToolCallIds.has(toolCall.id)
3476
- }, toolCall.id);
3477
- }, [
3478
- renderToolCalls,
3479
- executingToolCallIds,
3480
- agentId
3481
- ]);
3482
- }
3483
-
3484
- //#endregion
3485
- //#region src/v2/hooks/use-agent.tsx
3486
- let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
3487
- UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
3488
- UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
3489
- UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
3490
- return UseAgentUpdate;
3491
- }({});
3492
- const ALL_UPDATES = [
3493
- UseAgentUpdate.OnMessagesChanged,
3494
- UseAgentUpdate.OnStateChanged,
3495
- UseAgentUpdate.OnRunStatusChanged
3496
- ];
3497
- /**
3498
- * Clone a registry agent for per-thread isolation.
3499
- * Copies agent configuration (transport, headers, etc.) but resets conversation
3500
- * state (messages, threadId, state) so each thread starts fresh.
3501
- */
3502
- function cloneForThread(source, threadId, headers) {
3503
- const clone = source.clone();
3504
- if (clone === source) throw new Error(`useAgent: ${source.constructor.name}.clone() returned the same instance. clone() must return a new, independent object.`);
3505
- clone.threadId = threadId;
3506
- clone.setMessages([]);
3507
- clone.setState({});
3508
- if (clone instanceof HttpAgent) clone.headers = { ...headers };
3509
- return clone;
3510
- }
3511
- /**
3512
- * Module-level WeakMap: registryAgent → (threadId → clone).
3513
- * Shared across all useAgent() calls so that every component using the same
3514
- * (agentId, threadId) pair receives the same agent instance. Using WeakMap
3515
- * ensures the clone map is garbage-collected when the registry agent is
3516
- * replaced (e.g. after reconnect or hot-reload).
3517
- */
3518
- const globalThreadCloneMap = /* @__PURE__ */ new WeakMap();
3519
- /**
3520
- * Look up an existing per-thread clone without creating one.
3521
- * Returns undefined when no clone has been created yet for this pair.
3522
- */
3523
- function getThreadClone(registryAgent, threadId) {
3524
- if (!registryAgent || !threadId) return void 0;
3525
- return globalThreadCloneMap.get(registryAgent)?.get(threadId);
3526
- }
3527
- function getOrCreateThreadClone(existing, threadId, headers) {
3528
- let byThread = globalThreadCloneMap.get(existing);
3529
- if (!byThread) {
3530
- byThread = /* @__PURE__ */ new Map();
3531
- globalThreadCloneMap.set(existing, byThread);
3532
- }
3533
- const cached = byThread.get(threadId);
3534
- if (cached) return cached;
3535
- const clone = cloneForThread(existing, threadId, headers);
3536
- byThread.set(threadId, clone);
3537
- return clone;
3538
- }
3539
- function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
3540
- agentId ??= DEFAULT_AGENT_ID;
3541
- const { copilotkit } = useCopilotKit();
3542
- const providerThrottleMs = copilotkit.defaultThrottleMs;
3543
- const chatConfig = useCopilotChatConfiguration();
3544
- threadId ??= chatConfig?.threadId;
3545
- const [, forceUpdate] = useReducer((x) => x + 1, 0);
3546
- const updateFlags = useMemo(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
3547
- const provisionalAgentCache = useRef(/* @__PURE__ */ new Map());
3548
- const agent = useMemo(() => {
3549
- const cacheKey = threadId ? `${agentId}:${threadId}` : agentId;
3550
- const existing = copilotkit.getAgent(agentId);
3551
- if (existing) {
3552
- provisionalAgentCache.current.delete(cacheKey);
3553
- provisionalAgentCache.current.delete(agentId);
3554
- if (!threadId) return existing;
3555
- return getOrCreateThreadClone(existing, threadId, copilotkit.headers);
3556
- }
3557
- const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
3558
- const status = copilotkit.runtimeConnectionStatus;
3559
- if (isRuntimeConfigured && (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
3560
- const cached = provisionalAgentCache.current.get(cacheKey);
3561
- if (cached) {
3562
- cached.headers = { ...copilotkit.headers };
3563
- return cached;
3564
- }
3565
- const provisional = new ProxiedCopilotRuntimeAgent({
3566
- runtimeUrl: copilotkit.runtimeUrl,
3567
- agentId,
3568
- transport: copilotkit.runtimeTransport,
3569
- runtimeMode: "pending"
3570
- });
3571
- provisional.headers = { ...copilotkit.headers };
3572
- if (threadId) provisional.threadId = threadId;
3573
- provisionalAgentCache.current.set(cacheKey, provisional);
3574
- return provisional;
3575
- }
3576
- if (isRuntimeConfigured && status === CopilotKitCoreRuntimeConnectionStatus.Error) {
3577
- const cached = provisionalAgentCache.current.get(cacheKey);
3578
- if (cached) {
3579
- cached.headers = { ...copilotkit.headers };
3580
- return cached;
3581
- }
3582
- const provisional = new ProxiedCopilotRuntimeAgent({
3583
- runtimeUrl: copilotkit.runtimeUrl,
3584
- agentId,
3585
- transport: copilotkit.runtimeTransport,
3586
- runtimeMode: "pending"
3587
- });
3588
- provisional.headers = { ...copilotkit.headers };
3589
- if (threadId) provisional.threadId = threadId;
3590
- provisionalAgentCache.current.set(cacheKey, provisional);
3591
- return provisional;
3592
- }
3593
- const knownAgents = Object.keys(copilotkit.agents ?? {});
3594
- const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
3595
- 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.");
3596
- }, [
3597
- agentId,
3598
- threadId,
3599
- copilotkit.agents,
3600
- copilotkit.runtimeConnectionStatus,
3601
- copilotkit.runtimeUrl,
3602
- copilotkit.runtimeTransport,
3603
- JSON.stringify(copilotkit.headers)
3604
- ]);
3409
+ }, [copilotkit, renderCustomMessagesList]);
3605
3410
  useEffect(() => {
3606
- if (updateFlags.length === 0) return;
3607
- let active = true;
3608
- const handlers = {};
3609
- let batchScheduled = false;
3610
- const batchedForceUpdate = () => {
3611
- if (!active) return;
3612
- if (!batchScheduled) {
3613
- batchScheduled = true;
3614
- queueMicrotask(() => {
3615
- batchScheduled = false;
3616
- if (active) forceUpdate();
3617
- });
3618
- }
3411
+ didMountRef.current = true;
3412
+ }, []);
3413
+ useEffect(() => {
3414
+ copilotkit.setDefaultThrottleMs(defaultThrottleMs);
3415
+ }, [copilotkit, defaultThrottleMs]);
3416
+ const designSkill = openGenerativeUI?.designSkill ?? DEFAULT_DESIGN_SKILL;
3417
+ useLayoutEffect(() => {
3418
+ if (!copilotkit || !openGenUIActive) return;
3419
+ const id = copilotkit.addContext({
3420
+ description: "Design guidelines for the generateSandboxedUi tool. Follow these when building UI.",
3421
+ value: designSkill
3422
+ });
3423
+ return () => {
3424
+ copilotkit.removeContext(id);
3619
3425
  };
3620
- if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
3621
- if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
3622
- if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
3623
- handlers.onRunInitialized = batchedForceUpdate;
3624
- handlers.onRunFinalized = batchedForceUpdate;
3625
- handlers.onRunFailed = batchedForceUpdate;
3626
- handlers.onRunErrorEvent = batchedForceUpdate;
3627
- }
3628
- const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
3426
+ }, [
3427
+ copilotkit,
3428
+ designSkill,
3429
+ openGenUIActive
3430
+ ]);
3431
+ const sandboxFunctionsDescriptors = useMemo(() => {
3432
+ if (sandboxFunctionsList.length === 0) return null;
3433
+ return JSON.stringify(sandboxFunctionsList.map((fn) => ({
3434
+ name: fn.name,
3435
+ description: fn.description,
3436
+ parameters: schemaToJsonSchema(fn.parameters, { zodToJsonSchema })
3437
+ })));
3438
+ }, [sandboxFunctionsList]);
3439
+ useLayoutEffect(() => {
3440
+ if (!copilotkit || !sandboxFunctionsDescriptors || !openGenUIActive) return;
3441
+ const id = copilotkit.addContext({
3442
+ description: "Sandbox functions available in generated sandboxed UI code. Call via: await Websandbox.connection.remote.<functionName>(args)",
3443
+ value: sandboxFunctionsDescriptors
3444
+ });
3629
3445
  return () => {
3630
- active = false;
3631
- subscription.unsubscribe();
3446
+ copilotkit.removeContext(id);
3632
3447
  };
3633
3448
  }, [
3634
- agent,
3635
- forceUpdate,
3636
- throttleMs,
3637
- providerThrottleMs,
3638
- updateFlags
3449
+ copilotkit,
3450
+ sandboxFunctionsDescriptors,
3451
+ openGenUIActive
3639
3452
  ]);
3640
- useEffect(() => {
3641
- if (agent instanceof HttpAgent) agent.headers = { ...copilotkit.headers };
3642
- }, [agent, JSON.stringify(copilotkit.headers)]);
3643
- return { agent };
3644
- }
3453
+ const contextValue = useMemo(() => ({
3454
+ copilotkit,
3455
+ executingToolCallIds
3456
+ }), [copilotkit, executingToolCallIds]);
3457
+ const licenseContextValue = useMemo(() => createLicenseContextValue(null), []);
3458
+ return /* @__PURE__ */ jsx(SandboxFunctionsContext.Provider, {
3459
+ value: sandboxFunctionsList,
3460
+ children: /* @__PURE__ */ jsx(CopilotKitContext.Provider, {
3461
+ value: contextValue,
3462
+ children: /* @__PURE__ */ jsxs(LicenseContext.Provider, {
3463
+ value: licenseContextValue,
3464
+ children: [
3465
+ runtimeA2UIEnabled && /* @__PURE__ */ jsx(A2UIBuiltInToolCallRenderer, {}),
3466
+ runtimeA2UIEnabled && /* @__PURE__ */ jsx(A2UICatalogContext, {
3467
+ catalog: a2ui?.catalog,
3468
+ includeSchema: a2ui?.includeSchema
3469
+ }),
3470
+ children,
3471
+ shouldRenderInspector ? /* @__PURE__ */ jsx(CopilotKitInspector, {
3472
+ core: copilotkit,
3473
+ defaultAnchor: inspectorDefaultAnchor
3474
+ }) : null,
3475
+ runtimeLicenseStatus === "none" && !resolvedPublicKey && /* @__PURE__ */ jsx(LicenseWarningBanner, { type: "no_license" }),
3476
+ runtimeLicenseStatus === "expired" && /* @__PURE__ */ jsx(LicenseWarningBanner, { type: "expired" }),
3477
+ runtimeLicenseStatus === "invalid" && /* @__PURE__ */ jsx(LicenseWarningBanner, { type: "invalid" }),
3478
+ runtimeLicenseStatus === "expiring" && /* @__PURE__ */ jsx(LicenseWarningBanner, { type: "expiring" })
3479
+ ]
3480
+ })
3481
+ })
3482
+ });
3483
+ };
3645
3484
 
3646
3485
  //#endregion
3647
3486
  //#region src/v2/hooks/use-render-custom-messages.tsx
@@ -3660,8 +3499,7 @@ function useRenderCustomMessages() {
3660
3499
  const { message, position } = params;
3661
3500
  const resolvedRunId = copilotkit.getRunIdForMessage(agentId, threadId, message.id) ?? copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
3662
3501
  const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
3663
- const registryAgent = copilotkit.getAgent(agentId);
3664
- const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
3502
+ const agent = copilotkit.getAgent(agentId);
3665
3503
  if (!agent) return null;
3666
3504
  const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
3667
3505
  const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
@@ -3693,8 +3531,7 @@ function useRenderCustomMessages() {
3693
3531
  //#region src/v2/hooks/use-render-activity-message.tsx
3694
3532
  function useRenderActivityMessage() {
3695
3533
  const { copilotkit } = useCopilotKit();
3696
- const config = useCopilotChatConfiguration();
3697
- const agentId = config?.agentId ?? DEFAULT_AGENT_ID;
3534
+ const agentId = useCopilotChatConfiguration()?.agentId ?? DEFAULT_AGENT_ID;
3698
3535
  const renderers = copilotkit.renderActivityMessages;
3699
3536
  const findRenderer = useCallback((activityType) => {
3700
3537
  if (!renderers.length) return null;
@@ -3710,8 +3547,7 @@ function useRenderActivityMessage() {
3710
3547
  return null;
3711
3548
  }
3712
3549
  const Component = renderer.render;
3713
- const registryAgent = copilotkit.getAgent(agentId);
3714
- const agent = getThreadClone(registryAgent, config?.threadId) ?? registryAgent;
3550
+ const agent = copilotkit.getAgent(agentId);
3715
3551
  return /* @__PURE__ */ jsx(Component, {
3716
3552
  activityType: message.activityType,
3717
3553
  content: parseResult.data,
@@ -3720,7 +3556,6 @@ function useRenderActivityMessage() {
3720
3556
  }, message.id);
3721
3557
  }, [
3722
3558
  agentId,
3723
- config?.threadId,
3724
3559
  copilotkit,
3725
3560
  findRenderer
3726
3561
  ]);
@@ -3759,8 +3594,7 @@ function useFrontendTool(tool, deps) {
3759
3594
  tool.name,
3760
3595
  tool.available,
3761
3596
  copilotkit,
3762
- extraDeps.length,
3763
- ...extraDeps
3597
+ JSON.stringify(extraDeps)
3764
3598
  ]);
3765
3599
  }
3766
3600
 
@@ -3899,8 +3733,7 @@ function useRenderTool(config, deps) {
3899
3733
  }, [
3900
3734
  config.name,
3901
3735
  copilotkit,
3902
- extraDeps.length,
3903
- ...extraDeps
3736
+ JSON.stringify(extraDeps)
3904
3737
  ]);
3905
3738
  }
3906
3739
 
@@ -4160,6 +3993,118 @@ function useHumanInTheLoop(tool, deps) {
4160
3993
  ]);
4161
3994
  }
4162
3995
 
3996
+ //#endregion
3997
+ //#region src/v2/hooks/use-agent.tsx
3998
+ let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
3999
+ UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
4000
+ UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
4001
+ UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
4002
+ return UseAgentUpdate;
4003
+ }({});
4004
+ const ALL_UPDATES = [
4005
+ UseAgentUpdate.OnMessagesChanged,
4006
+ UseAgentUpdate.OnStateChanged,
4007
+ UseAgentUpdate.OnRunStatusChanged
4008
+ ];
4009
+ function useAgent({ agentId, updates, throttleMs } = {}) {
4010
+ agentId ??= DEFAULT_AGENT_ID;
4011
+ const { copilotkit } = useCopilotKit();
4012
+ const providerThrottleMs = copilotkit.defaultThrottleMs;
4013
+ const [, forceUpdate] = useReducer((x) => x + 1, 0);
4014
+ const updateFlags = useMemo(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
4015
+ const provisionalAgentCache = useRef(/* @__PURE__ */ new Map());
4016
+ const agent = useMemo(() => {
4017
+ const existing = copilotkit.getAgent(agentId);
4018
+ if (existing) {
4019
+ provisionalAgentCache.current.delete(agentId);
4020
+ return existing;
4021
+ }
4022
+ const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
4023
+ const status = copilotkit.runtimeConnectionStatus;
4024
+ if (isRuntimeConfigured && (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
4025
+ const cached = provisionalAgentCache.current.get(agentId);
4026
+ if (cached) {
4027
+ cached.headers = { ...copilotkit.headers };
4028
+ return cached;
4029
+ }
4030
+ const provisional = new ProxiedCopilotRuntimeAgent({
4031
+ runtimeUrl: copilotkit.runtimeUrl,
4032
+ agentId,
4033
+ transport: copilotkit.runtimeTransport,
4034
+ runtimeMode: "pending"
4035
+ });
4036
+ provisional.headers = { ...copilotkit.headers };
4037
+ provisionalAgentCache.current.set(agentId, provisional);
4038
+ return provisional;
4039
+ }
4040
+ if (isRuntimeConfigured && status === CopilotKitCoreRuntimeConnectionStatus.Error) {
4041
+ const cached = provisionalAgentCache.current.get(agentId);
4042
+ if (cached) {
4043
+ cached.headers = { ...copilotkit.headers };
4044
+ return cached;
4045
+ }
4046
+ const provisional = new ProxiedCopilotRuntimeAgent({
4047
+ runtimeUrl: copilotkit.runtimeUrl,
4048
+ agentId,
4049
+ transport: copilotkit.runtimeTransport,
4050
+ runtimeMode: "pending"
4051
+ });
4052
+ provisional.headers = { ...copilotkit.headers };
4053
+ provisionalAgentCache.current.set(agentId, provisional);
4054
+ return provisional;
4055
+ }
4056
+ const knownAgents = Object.keys(copilotkit.agents ?? {});
4057
+ const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
4058
+ 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.");
4059
+ }, [
4060
+ agentId,
4061
+ copilotkit.agents,
4062
+ copilotkit.runtimeConnectionStatus,
4063
+ copilotkit.runtimeUrl,
4064
+ copilotkit.runtimeTransport,
4065
+ JSON.stringify(copilotkit.headers)
4066
+ ]);
4067
+ useEffect(() => {
4068
+ if (updateFlags.length === 0) return;
4069
+ let active = true;
4070
+ const handlers = {};
4071
+ let batchScheduled = false;
4072
+ const batchedForceUpdate = () => {
4073
+ if (!active) return;
4074
+ if (!batchScheduled) {
4075
+ batchScheduled = true;
4076
+ queueMicrotask(() => {
4077
+ batchScheduled = false;
4078
+ if (active) forceUpdate();
4079
+ });
4080
+ }
4081
+ };
4082
+ if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = batchedForceUpdate;
4083
+ if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
4084
+ if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
4085
+ handlers.onRunInitialized = batchedForceUpdate;
4086
+ handlers.onRunFinalized = batchedForceUpdate;
4087
+ handlers.onRunFailed = batchedForceUpdate;
4088
+ handlers.onRunErrorEvent = batchedForceUpdate;
4089
+ }
4090
+ const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
4091
+ return () => {
4092
+ active = false;
4093
+ subscription.unsubscribe();
4094
+ };
4095
+ }, [
4096
+ agent,
4097
+ forceUpdate,
4098
+ throttleMs,
4099
+ providerThrottleMs,
4100
+ updateFlags
4101
+ ]);
4102
+ useEffect(() => {
4103
+ if (agent instanceof HttpAgent) agent.headers = { ...copilotkit.headers };
4104
+ }, [agent, JSON.stringify(copilotkit.headers)]);
4105
+ return { agent };
4106
+ }
4107
+
4163
4108
  //#endregion
4164
4109
  //#region src/v2/hooks/use-capabilities.tsx
4165
4110
  /**
@@ -5625,6 +5570,190 @@ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
5625
5570
  */
5626
5571
  const ScrollElementContext = React.createContext(null);
5627
5572
 
5573
+ //#endregion
5574
+ //#region src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx
5575
+ /**
5576
+ * Grace window before showing the spinner. A matching tool call must
5577
+ * remain unresolved (no `tool`-role result message in `agent.messages`)
5578
+ * for at least this long before the pill appears. This filters out
5579
+ * history-replay flashes — during `connectAgent` replay, tool calls and
5580
+ * their results arrive back-to-back in sub-millisecond bursts, so the
5581
+ * timer is cancelled before it fires. Live runs cross the threshold
5582
+ * easily because the tool actually has to execute.
5583
+ */
5584
+ const PENDING_THRESHOLD_MS = 100;
5585
+ /** Hold the checkmark briefly before fading out. */
5586
+ const CHECK_HOLD_MS = 800;
5587
+ /**
5588
+ * Duration of the fade-out animation. Must match
5589
+ * `cpk-intelligence-pill-fade-out` keyframes in `v2/styles/globals.css`.
5590
+ */
5591
+ const FADE_OUT_ANIMATION_MS = 480;
5592
+ /**
5593
+ * Tool-name regex patterns that trigger the indicator. Currently
5594
+ * hardcoded to the Intelligence MCP server's canonical tool name. If
5595
+ * we add per-instance customization later (e.g. a `CopilotKitProvider`
5596
+ * prop or a runtime-info field), this constant becomes the fallback.
5597
+ */
5598
+ const DEFAULT_TOOL_PATTERNS = [/^copilotkit_knowledge_base_shell$/];
5599
+ const isMatchingToolCallName = (name) => typeof name === "string" && DEFAULT_TOOL_PATTERNS.some((p) => p.test(name));
5600
+ /**
5601
+ * "Tool-call-like" messages do NOT count as a real follow-up: tool
5602
+ * result messages, assistant messages that carry tool calls, and
5603
+ * empty-content assistant messages (which some providers emit as a
5604
+ * standalone wrapper around a batch of tool calls). A real follow-up
5605
+ * is anything else — most importantly an assistant message with prose
5606
+ * content, or a fresh user message.
5607
+ */
5608
+ const isToolCallLikeMessage = (m) => {
5609
+ if (m.role === "tool") return true;
5610
+ if (m.role === "assistant") {
5611
+ if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).length > 0) return true;
5612
+ const content = m.content;
5613
+ return typeof content !== "string" || content.trim().length === 0;
5614
+ }
5615
+ return false;
5616
+ };
5617
+ /**
5618
+ * The "Using CopilotKit Intelligence" pill. Auto-mounted by
5619
+ * `CopilotChatMessageView` for every message slot when
5620
+ * `copilotkit.intelligence` is configured — callers do not register
5621
+ * this themselves. Self-gates so only the canonical message renders a
5622
+ * pill.
5623
+ *
5624
+ * Render gates (all must hold):
5625
+ * 1. `copilotkit.intelligence !== undefined`
5626
+ * 2. The message is an assistant message with at least one tool call
5627
+ * whose name matches {@link DEFAULT_TOOL_PATTERNS}
5628
+ * 3. The message is the *latest* such matching-assistant message in
5629
+ * `agent.messages` — tool-result messages and prose-only assistant
5630
+ * messages don't invalidate the slot, so the pill stays
5631
+ * continuously through a multi-step tool chain.
5632
+ * 4. The phase machine is past `idle` (the pending-grace timer fired)
5633
+ * and not yet `hidden`.
5634
+ *
5635
+ * Phase machine (per-instance, all timers local):
5636
+ * - Starts in `idle` — nothing rendered.
5637
+ * - `idle → spinner` once a matching tool call has been pending
5638
+ * (no `tool`-role result with a matching `toolCallId`) for
5639
+ * {@link PENDING_THRESHOLD_MS}. Replay flashes (tool call + result
5640
+ * in the same tick) never cross this threshold.
5641
+ * - `spinner → check` as soon as EITHER `agent.isRunning` flips
5642
+ * false OR a non-tool-call-like message appears later in
5643
+ * `agent.messages` (i.e. the agent has produced a "real"
5644
+ * follow-up — prose answer or a new user turn).
5645
+ * - `check → fading` after {@link CHECK_HOLD_MS}.
5646
+ * - `fading → hidden` after {@link FADE_OUT_ANIMATION_MS}.
5647
+ *
5648
+ * Once `hidden`, the phase is sticky — a finished pill never re-spawns
5649
+ * on the same message. New runs mount fresh indicator instances on
5650
+ * their own assistant messages.
5651
+ *
5652
+ * The "exactly one pill at a time" guarantee is structural: only one
5653
+ * message satisfies the latest-matching-assistant gate at any moment.
5654
+ */
5655
+ function IntelligenceIndicator(props) {
5656
+ const { message, agentId, label = "Using CopilotKit Intelligence" } = props;
5657
+ const { copilotkit } = useCopilotKit();
5658
+ const config = useCopilotChatConfiguration();
5659
+ const { agent } = useAgent({
5660
+ agentId,
5661
+ updates: [UseAgentUpdate.OnRunStatusChanged, UseAgentUpdate.OnMessagesChanged]
5662
+ });
5663
+ const matchingToolCallIds = useMemo(() => {
5664
+ if (message.role !== "assistant") return [];
5665
+ const tcs = Array.isArray(message.toolCalls) ? message.toolCalls : [];
5666
+ const ids = [];
5667
+ for (const tc of tcs) if (isMatchingToolCallName(tc?.function?.name) && tc?.id) ids.push(tc.id);
5668
+ return ids;
5669
+ }, [message]);
5670
+ const hasPending = useMemo(() => {
5671
+ if (matchingToolCallIds.length === 0) return false;
5672
+ const resolved = /* @__PURE__ */ new Set();
5673
+ for (const m of agent.messages) if (m.role === "tool" && m.toolCallId) resolved.add(m.toolCallId);
5674
+ return matchingToolCallIds.some((id) => !resolved.has(id));
5675
+ }, [matchingToolCallIds, agent.messages]);
5676
+ const sawRealFollowup = useMemo(() => {
5677
+ const idx = agent.messages.findIndex((m) => m.id === message.id);
5678
+ if (idx < 0) return false;
5679
+ for (let i = idx + 1; i < agent.messages.length; i += 1) if (!isToolCallLikeMessage(agent.messages[i])) return true;
5680
+ return false;
5681
+ }, [agent.messages, message.id]);
5682
+ const [phase, setPhase] = useState("idle");
5683
+ useEffect(() => {
5684
+ if (phase !== "idle") return void 0;
5685
+ if (!hasPending) return void 0;
5686
+ const t = setTimeout(() => setPhase("spinner"), PENDING_THRESHOLD_MS);
5687
+ return () => clearTimeout(t);
5688
+ }, [phase, hasPending]);
5689
+ useEffect(() => {
5690
+ if (phase !== "spinner") return void 0;
5691
+ if (!agent.isRunning || sawRealFollowup) setPhase("check");
5692
+ }, [
5693
+ phase,
5694
+ agent.isRunning,
5695
+ sawRealFollowup
5696
+ ]);
5697
+ useEffect(() => {
5698
+ if (phase !== "check") return void 0;
5699
+ const t = setTimeout(() => setPhase("fading"), CHECK_HOLD_MS);
5700
+ return () => clearTimeout(t);
5701
+ }, [phase]);
5702
+ useEffect(() => {
5703
+ if (phase !== "fading") return void 0;
5704
+ const t = setTimeout(() => setPhase("hidden"), FADE_OUT_ANIMATION_MS);
5705
+ return () => clearTimeout(t);
5706
+ }, [phase]);
5707
+ if (copilotkit.intelligence === void 0) return null;
5708
+ if (!config) return null;
5709
+ if (phase === "idle" || phase === "hidden") return null;
5710
+ if (message.role !== "assistant") return null;
5711
+ if (!(Array.isArray(message.toolCalls) ? message.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) return null;
5712
+ let latestMatchingAssistantId;
5713
+ for (let i = agent.messages.length - 1; i >= 0; i -= 1) {
5714
+ const m = agent.messages[i];
5715
+ if (m.role !== "assistant") continue;
5716
+ if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) {
5717
+ latestMatchingAssistantId = m.id;
5718
+ break;
5719
+ }
5720
+ }
5721
+ if (latestMatchingAssistantId !== message.id) return null;
5722
+ const showSpinner = phase === "spinner";
5723
+ const isFading = phase === "fading";
5724
+ return /* @__PURE__ */ jsxs("span", {
5725
+ className: "cpk-intelligence-pill" + (isFading ? " cpk-intelligence-pill--fading" : ""),
5726
+ role: "status",
5727
+ "aria-live": "polite",
5728
+ "aria-hidden": isFading || void 0,
5729
+ "data-testid": `cpk-intelligence-pill-${message.id}`,
5730
+ title: label,
5731
+ children: [/* @__PURE__ */ jsxs("svg", {
5732
+ className: "cpk-intelligence-pill__icon",
5733
+ viewBox: "0 0 24 24",
5734
+ width: "14",
5735
+ height: "14",
5736
+ "aria-hidden": "true",
5737
+ children: [/* @__PURE__ */ jsx("circle", {
5738
+ cx: "12",
5739
+ cy: "12",
5740
+ r: "9",
5741
+ fill: "none",
5742
+ strokeWidth: "2.5",
5743
+ strokeLinecap: "round",
5744
+ className: "cpk-intelligence-pill__ring" + (showSpinner ? "" : " cpk-intelligence-pill__ring--done")
5745
+ }), /* @__PURE__ */ jsx("path", {
5746
+ d: "M8 12.5l3 3 5-6",
5747
+ fill: "none",
5748
+ strokeWidth: "2.5",
5749
+ strokeLinecap: "round",
5750
+ strokeLinejoin: "round",
5751
+ className: "cpk-intelligence-pill__check" + (showSpinner ? "" : " cpk-intelligence-pill__check--shown")
5752
+ })]
5753
+ }), /* @__PURE__ */ jsx("span", { children: label })]
5754
+ });
5755
+ }
5756
+
5628
5757
  //#endregion
5629
5758
  //#region src/v2/components/chat/CopilotChatMessageView.tsx
5630
5759
  /**
@@ -5782,14 +5911,12 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5782
5911
  const [, forceUpdate] = useReducer((x) => x + 1, 0);
5783
5912
  useEffect(() => {
5784
5913
  if (!config?.agentId) return;
5785
- const registryAgent = copilotkit.getAgent(config.agentId);
5786
- const agent = getThreadClone(registryAgent, config.threadId) ?? registryAgent;
5914
+ const agent = copilotkit.getAgent(config.agentId);
5787
5915
  if (!agent) return;
5788
5916
  const subscription = agent.subscribe({ onStateChanged: forceUpdate });
5789
5917
  return () => subscription.unsubscribe();
5790
5918
  }, [
5791
5919
  config?.agentId,
5792
- config?.threadId,
5793
5920
  copilotkit,
5794
5921
  forceUpdate
5795
5922
  ]);
@@ -5872,6 +5999,10 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5872
5999
  renderCustomMessage,
5873
6000
  stateSnapshot
5874
6001
  }, `${message.id}-custom-after`));
6002
+ if (copilotkit.intelligence !== void 0 && message.role === "assistant") elements.push(/* @__PURE__ */ jsx(IntelligenceIndicator, {
6003
+ message,
6004
+ agentId: config?.agentId ?? DEFAULT_AGENT_ID
6005
+ }, `${message.id}-intelligence`));
5875
6006
  return elements.filter(Boolean);
5876
6007
  };
5877
6008
  const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
@@ -6820,7 +6951,6 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6820
6951
  const hasExplicitThreadId = !!threadId || !!existingConfig?.hasExplicitThreadId;
6821
6952
  const { agent } = useAgent({
6822
6953
  agentId: resolvedAgentId,
6823
- threadId: resolvedThreadId,
6824
6954
  throttleMs
6825
6955
  });
6826
6956
  const { copilotkit } = useCopilotKit();
@@ -6862,6 +6992,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6862
6992
  let detached = false;
6863
6993
  const connectAbortController = new AbortController();
6864
6994
  if (agent instanceof HttpAgent) agent.abortController = connectAbortController;
6995
+ agent.threadId = resolvedThreadId;
6865
6996
  const connect = async (agent) => {
6866
6997
  try {
6867
6998
  await copilotkit.connectAgent({ agent });
@@ -9802,5 +9933,5 @@ function validateProps(props) {
9802
9933
  }
9803
9934
 
9804
9935
  //#endregion
9805
- export { CopilotKitProvider as $, CopilotChatSuggestionView as A, useConfigureSuggestions as B, CopilotChatToggleButton as C, CopilotChatView_default as D, CopilotChat as E, CopilotChatAssistantMessage_default as F, useRenderTool as G, useCapabilities as H, CopilotChatToolCallsView as I, useRenderActivityMessage as J, useComponent as K, useAttachments as L, CopilotChatReasoningMessage_default as M, CopilotChatUserMessage_default as N, CopilotChatAttachmentQueue as O, CopilotChatAttachmentRenderer as P, useRenderToolCall as Q, useThreads$1 as R, CopilotModalHeader as S, DefaultOpenIcon as T, useHumanInTheLoop as U, useSuggestions as V, useDefaultRenderTool as W, UseAgentUpdate as X, useRenderCustomMessages as Y, useAgent as Z, WildcardToolCallRender as _, ThreadsProvider as a, SandboxFunctionsContext as at, CopilotPopupView as b, CoAgentStateRendersProvider as c, MCPAppsActivityRenderer as ct, shouldShowDevConsole as d, CopilotChatInput_default as dt, useCopilotKit as et, useToast as f, AudioRecorderError as ft, useCopilotContext as g, CopilotContext as h, useCopilotChatConfiguration as ht, ThreadsContext as i, createA2UIMessageRenderer as it, CopilotChatSuggestionPill as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, MCPAppsActivityType as lt, useCopilotMessagesContext as m, CopilotChatConfigurationProvider as mt, defaultCopilotContextCategories as n, useAgentContext as nt, useThreads as o, useSandboxFunctions as ot, CopilotMessagesContext as p, CopilotChatAudioRecorder as pt, useFrontendTool as q, CoAgentStateRenderBridge as r, defineToolCallRenderer as rt, CoAgentStateRendersContext as s, MCPAppsActivityContentSchema as st, CopilotKit as t, CopilotKitCoreReact as tt, useAsyncCallback as u, CopilotKitInspector as ut, CopilotPopup as v, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotSidebar as y, useInterrupt as z };
9806
- //# sourceMappingURL=copilotkit-CPe2-340.mjs.map
9936
+ export { CopilotKitProvider as $, IntelligenceIndicator as A, useInterrupt as B, CopilotChatToggleButton as C, CopilotChatView_default as D, CopilotChat as E, CopilotChatAttachmentRenderer as F, useAgent as G, useSuggestions as H, CopilotChatAssistantMessage_default as I, useRenderTool as J, useHumanInTheLoop as K, CopilotChatToolCallsView as L, CopilotChatSuggestionPill as M, CopilotChatReasoningMessage_default as N, CopilotChatAttachmentQueue as O, CopilotChatUserMessage_default as P, useRenderCustomMessages as Q, useAttachments as R, CopilotModalHeader as S, DefaultOpenIcon as T, useCapabilities as U, useConfigureSuggestions as V, UseAgentUpdate as W, useFrontendTool as X, useComponent as Y, useRenderActivityMessage as Z, WildcardToolCallRender as _, ThreadsProvider as a, MCPAppsActivityContentSchema as at, CopilotPopupView as b, CoAgentStateRendersProvider as c, CopilotKitInspector as ct, shouldShowDevConsole as d, CopilotKitCoreReact as dt, useAgentContext as et, useToast as f, CopilotChatInput_default as ft, useCopilotContext as g, useCopilotChatConfiguration as gt, CopilotContext as h, CopilotChatConfigurationProvider as ht, ThreadsContext as i, useSandboxFunctions as it, CopilotChatSuggestionView as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, useRenderToolCall as lt, useCopilotMessagesContext as m, CopilotChatAudioRecorder as mt, defaultCopilotContextCategories as n, createA2UIMessageRenderer as nt, useThreads as o, MCPAppsActivityRenderer as ot, CopilotMessagesContext as p, AudioRecorderError as pt, useDefaultRenderTool as q, CoAgentStateRenderBridge as r, SandboxFunctionsContext as rt, CoAgentStateRendersContext as s, MCPAppsActivityType as st, CopilotKit as t, defineToolCallRenderer as tt, useAsyncCallback as u, useCopilotKit as ut, CopilotPopup as v, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotSidebar as y, useThreads$1 as z };
9937
+ //# sourceMappingURL=copilotkit-DjxXMYHG.mjs.map