@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
@@ -1324,6 +1324,197 @@ function useKatexStyles() {
1324
1324
  }, []);
1325
1325
  }
1326
1326
 
1327
+ //#endregion
1328
+ //#region src/v2/lib/react-core.ts
1329
+ var CopilotKitCoreReact = class extends _copilotkit_core.CopilotKitCore {
1330
+ constructor(config) {
1331
+ super(config);
1332
+ this._renderToolCalls = [];
1333
+ this._hookRenderToolCalls = /* @__PURE__ */ new Map();
1334
+ this._cachedMergedRenderToolCalls = null;
1335
+ this._renderCustomMessages = [];
1336
+ this._renderActivityMessages = [];
1337
+ this._interruptElement = null;
1338
+ this._renderToolCalls = config.renderToolCalls ?? [];
1339
+ this._renderCustomMessages = config.renderCustomMessages ?? [];
1340
+ this._renderActivityMessages = config.renderActivityMessages ?? [];
1341
+ }
1342
+ get renderCustomMessages() {
1343
+ return this._renderCustomMessages;
1344
+ }
1345
+ get renderActivityMessages() {
1346
+ return this._renderActivityMessages;
1347
+ }
1348
+ get renderToolCalls() {
1349
+ if (this._hookRenderToolCalls.size === 0) return this._renderToolCalls;
1350
+ if (this._cachedMergedRenderToolCalls) return this._cachedMergedRenderToolCalls;
1351
+ const merged = /* @__PURE__ */ new Map();
1352
+ for (const rc of this._renderToolCalls) merged.set(`${rc.agentId ?? ""}:${rc.name}`, rc);
1353
+ for (const [key, rc] of this._hookRenderToolCalls) merged.set(key, rc);
1354
+ this._cachedMergedRenderToolCalls = Array.from(merged.values());
1355
+ return this._cachedMergedRenderToolCalls;
1356
+ }
1357
+ setRenderActivityMessages(renderers) {
1358
+ this._renderActivityMessages = renderers;
1359
+ }
1360
+ setRenderCustomMessages(renderers) {
1361
+ this._renderCustomMessages = renderers;
1362
+ }
1363
+ setRenderToolCalls(renderToolCalls) {
1364
+ this._renderToolCalls = renderToolCalls;
1365
+ this._cachedMergedRenderToolCalls = null;
1366
+ this._notifyRenderToolCallsChanged();
1367
+ }
1368
+ addHookRenderToolCall(entry) {
1369
+ const key = `${entry.agentId ?? ""}:${entry.name}`;
1370
+ this._hookRenderToolCalls.set(key, entry);
1371
+ this._cachedMergedRenderToolCalls = null;
1372
+ this._notifyRenderToolCallsChanged();
1373
+ }
1374
+ removeHookRenderToolCall(name, agentId) {
1375
+ const key = `${agentId ?? ""}:${name}`;
1376
+ if (this._hookRenderToolCalls.delete(key)) {
1377
+ this._cachedMergedRenderToolCalls = null;
1378
+ this._notifyRenderToolCallsChanged();
1379
+ }
1380
+ }
1381
+ _notifyRenderToolCallsChanged() {
1382
+ this.notifySubscribers((subscriber) => {
1383
+ const reactSubscriber = subscriber;
1384
+ if (reactSubscriber.onRenderToolCallsChanged) reactSubscriber.onRenderToolCallsChanged({
1385
+ copilotkit: this,
1386
+ renderToolCalls: this.renderToolCalls
1387
+ });
1388
+ }, "Subscriber onRenderToolCallsChanged error:");
1389
+ }
1390
+ get interruptElement() {
1391
+ return this._interruptElement;
1392
+ }
1393
+ setInterruptElement(element) {
1394
+ this._interruptElement = element;
1395
+ this.notifySubscribers((subscriber) => {
1396
+ subscriber.onInterruptElementChanged?.({
1397
+ copilotkit: this,
1398
+ interruptElement: this._interruptElement
1399
+ });
1400
+ }, "Subscriber onInterruptElementChanged error:");
1401
+ }
1402
+ subscribe(subscriber) {
1403
+ return super.subscribe(subscriber);
1404
+ }
1405
+ /**
1406
+ * Wait for pending React state updates before the follow-up agent run.
1407
+ *
1408
+ * When a frontend tool handler calls setState(), React 18 batches the update
1409
+ * and schedules a commit via its internal scheduler (MessageChannel). The
1410
+ * useAgentContext hook registers context via useLayoutEffect, which runs
1411
+ * synchronously after React commits that batch.
1412
+ *
1413
+ * Awaiting a zero-delay timeout yields to the macrotask queue. React's
1414
+ * MessageChannel task runs first, committing the pending state and running
1415
+ * useLayoutEffect (which updates the context store). The follow-up runAgent
1416
+ * call then reads fresh context.
1417
+ */
1418
+ async waitForPendingFrameworkUpdates() {
1419
+ await new Promise((resolve) => setTimeout(resolve, 0));
1420
+ }
1421
+ };
1422
+
1423
+ //#endregion
1424
+ //#region src/v2/context.ts
1425
+ const CopilotKitContext = (0, react.createContext)(null);
1426
+ const useCopilotKit = () => {
1427
+ const context = (0, react.useContext)(CopilotKitContext);
1428
+ const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
1429
+ if (!context) throw new Error("useCopilotKit must be used within CopilotKitProvider");
1430
+ (0, react.useEffect)(() => {
1431
+ const subscription = context.copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
1432
+ forceUpdate();
1433
+ } });
1434
+ return () => {
1435
+ subscription.unsubscribe();
1436
+ };
1437
+ }, []);
1438
+ return context;
1439
+ };
1440
+ const LicenseContext = (0, react.createContext)({
1441
+ status: null,
1442
+ license: null,
1443
+ checkFeature: () => true,
1444
+ getLimit: () => null
1445
+ });
1446
+ const useLicenseContext = () => (0, react.useContext)(LicenseContext);
1447
+
1448
+ //#endregion
1449
+ //#region src/v2/hooks/use-render-tool-call.tsx
1450
+ /**
1451
+ * Memoized component that renders a single tool call.
1452
+ * This prevents unnecessary re-renders when parent components update
1453
+ * but the tool call data hasn't changed.
1454
+ */
1455
+ const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall, toolMessage, RenderComponent, isExecuting }) {
1456
+ const args = (0, react.useMemo)(() => (0, _copilotkit_shared.partialJSONParse)(toolCall.function.arguments), [toolCall.function.arguments]);
1457
+ const toolName = toolCall.function.name;
1458
+ if (toolMessage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
1459
+ name: toolName,
1460
+ toolCallId: toolCall.id,
1461
+ args,
1462
+ status: _copilotkit_core.ToolCallStatus.Complete,
1463
+ result: toolMessage.content
1464
+ });
1465
+ else if (isExecuting) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
1466
+ name: toolName,
1467
+ toolCallId: toolCall.id,
1468
+ args,
1469
+ status: _copilotkit_core.ToolCallStatus.Executing,
1470
+ result: void 0
1471
+ });
1472
+ else return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
1473
+ name: toolName,
1474
+ toolCallId: toolCall.id,
1475
+ args,
1476
+ status: _copilotkit_core.ToolCallStatus.InProgress,
1477
+ result: void 0
1478
+ });
1479
+ }, (prevProps, nextProps) => {
1480
+ if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
1481
+ if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
1482
+ if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
1483
+ if (prevProps.toolMessage?.content !== nextProps.toolMessage?.content) return false;
1484
+ if (prevProps.isExecuting !== nextProps.isExecuting) return false;
1485
+ if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
1486
+ return true;
1487
+ });
1488
+ /**
1489
+ * Hook that returns a function to render tool calls based on the render functions
1490
+ * defined in CopilotKitProvider.
1491
+ *
1492
+ * @returns A function that takes a tool call and optional tool message and returns the rendered component
1493
+ */
1494
+ function useRenderToolCall() {
1495
+ const { copilotkit, executingToolCallIds } = useCopilotKit();
1496
+ const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
1497
+ const renderToolCalls = (0, react.useSyncExternalStore)((callback) => {
1498
+ return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
1499
+ }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
1500
+ return (0, react.useCallback)(({ toolCall, toolMessage }) => {
1501
+ const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
1502
+ const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
1503
+ if (!renderConfig) return null;
1504
+ const RenderComponent = renderConfig.render;
1505
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallRenderer, {
1506
+ toolCall,
1507
+ toolMessage,
1508
+ RenderComponent,
1509
+ isExecuting: executingToolCallIds.has(toolCall.id)
1510
+ }, toolCall.id);
1511
+ }, [
1512
+ renderToolCalls,
1513
+ executingToolCallIds,
1514
+ agentId
1515
+ ]);
1516
+ }
1517
+
1327
1518
  //#endregion
1328
1519
  //#region src/v2/components/CopilotKitInspector.tsx
1329
1520
  const CopilotKitInspector = ({ core, ...rest }) => {
@@ -2967,102 +3158,6 @@ function A2UICatalogContext({ catalog, includeSchema }) {
2967
3158
  return null;
2968
3159
  }
2969
3160
 
2970
- //#endregion
2971
- //#region src/v2/lib/react-core.ts
2972
- var CopilotKitCoreReact = class extends _copilotkit_core.CopilotKitCore {
2973
- constructor(config) {
2974
- super(config);
2975
- this._renderToolCalls = [];
2976
- this._hookRenderToolCalls = /* @__PURE__ */ new Map();
2977
- this._cachedMergedRenderToolCalls = null;
2978
- this._renderCustomMessages = [];
2979
- this._renderActivityMessages = [];
2980
- this._interruptElement = null;
2981
- this._renderToolCalls = config.renderToolCalls ?? [];
2982
- this._renderCustomMessages = config.renderCustomMessages ?? [];
2983
- this._renderActivityMessages = config.renderActivityMessages ?? [];
2984
- }
2985
- get renderCustomMessages() {
2986
- return this._renderCustomMessages;
2987
- }
2988
- get renderActivityMessages() {
2989
- return this._renderActivityMessages;
2990
- }
2991
- get renderToolCalls() {
2992
- if (this._hookRenderToolCalls.size === 0) return this._renderToolCalls;
2993
- if (this._cachedMergedRenderToolCalls) return this._cachedMergedRenderToolCalls;
2994
- const merged = /* @__PURE__ */ new Map();
2995
- for (const rc of this._renderToolCalls) merged.set(`${rc.agentId ?? ""}:${rc.name}`, rc);
2996
- for (const [key, rc] of this._hookRenderToolCalls) merged.set(key, rc);
2997
- this._cachedMergedRenderToolCalls = Array.from(merged.values());
2998
- return this._cachedMergedRenderToolCalls;
2999
- }
3000
- setRenderActivityMessages(renderers) {
3001
- this._renderActivityMessages = renderers;
3002
- }
3003
- setRenderCustomMessages(renderers) {
3004
- this._renderCustomMessages = renderers;
3005
- }
3006
- setRenderToolCalls(renderToolCalls) {
3007
- this._renderToolCalls = renderToolCalls;
3008
- this._cachedMergedRenderToolCalls = null;
3009
- this._notifyRenderToolCallsChanged();
3010
- }
3011
- addHookRenderToolCall(entry) {
3012
- const key = `${entry.agentId ?? ""}:${entry.name}`;
3013
- this._hookRenderToolCalls.set(key, entry);
3014
- this._cachedMergedRenderToolCalls = null;
3015
- this._notifyRenderToolCallsChanged();
3016
- }
3017
- removeHookRenderToolCall(name, agentId) {
3018
- const key = `${agentId ?? ""}:${name}`;
3019
- if (this._hookRenderToolCalls.delete(key)) {
3020
- this._cachedMergedRenderToolCalls = null;
3021
- this._notifyRenderToolCallsChanged();
3022
- }
3023
- }
3024
- _notifyRenderToolCallsChanged() {
3025
- this.notifySubscribers((subscriber) => {
3026
- const reactSubscriber = subscriber;
3027
- if (reactSubscriber.onRenderToolCallsChanged) reactSubscriber.onRenderToolCallsChanged({
3028
- copilotkit: this,
3029
- renderToolCalls: this.renderToolCalls
3030
- });
3031
- }, "Subscriber onRenderToolCallsChanged error:");
3032
- }
3033
- get interruptElement() {
3034
- return this._interruptElement;
3035
- }
3036
- setInterruptElement(element) {
3037
- this._interruptElement = element;
3038
- this.notifySubscribers((subscriber) => {
3039
- subscriber.onInterruptElementChanged?.({
3040
- copilotkit: this,
3041
- interruptElement: this._interruptElement
3042
- });
3043
- }, "Subscriber onInterruptElementChanged error:");
3044
- }
3045
- subscribe(subscriber) {
3046
- return super.subscribe(subscriber);
3047
- }
3048
- /**
3049
- * Wait for pending React state updates before the follow-up agent run.
3050
- *
3051
- * When a frontend tool handler calls setState(), React 18 batches the update
3052
- * and schedules a commit via its internal scheduler (MessageChannel). The
3053
- * useAgentContext hook registers context via useLayoutEffect, which runs
3054
- * synchronously after React commits that batch.
3055
- *
3056
- * Awaiting a zero-delay timeout yields to the macrotask queue. React's
3057
- * MessageChannel task runs first, committing the pending state and running
3058
- * useLayoutEffect (which updates the context store). The follow-up runAgent
3059
- * call then reads fresh context.
3060
- */
3061
- async waitForPendingFrameworkUpdates() {
3062
- await new Promise((resolve) => setTimeout(resolve, 0));
3063
- }
3064
- };
3065
-
3066
3161
  //#endregion
3067
3162
  //#region src/v2/providers/CopilotKitProvider.tsx
3068
3163
  const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
@@ -3078,12 +3173,6 @@ const DEFAULT_DESIGN_SKILL = `When generating UI with generateSandboxedUi, follo
3078
3173
  - Minimal transitions (150ms) for hover/focus states only. No decorative animations.
3079
3174
  - Keep the UI focused and dense — avoid excessive padding. Use compact spacing (8–12px gaps, 10–14px padding in controls).`;
3080
3175
  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)";
3081
- const CopilotKitContext = (0, react.createContext)({
3082
- copilotkit: null,
3083
- executingToolCallIds: /* @__PURE__ */ new Set()
3084
- });
3085
- const LicenseContext = (0, react.createContext)((0, _copilotkit_shared.createLicenseContextValue)(null));
3086
- const useLicenseContext = () => (0, react.useContext)(LicenseContext);
3087
3176
  function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
3088
3177
  const empty = (0, react.useMemo)(() => [], []);
3089
3178
  const value = prop ?? empty;
@@ -3305,13 +3394,9 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
3305
3394
  onErrorRef.current = onError;
3306
3395
  }, [onError]);
3307
3396
  (0, react.useEffect)(() => {
3308
- if (!onErrorRef.current) return;
3309
3397
  const subscription = copilotkit.subscribe({ onError: (event) => {
3310
- onErrorRef.current?.({
3311
- error: event.error,
3312
- code: event.code,
3313
- context: event.context
3314
- });
3398
+ if (onErrorRef.current) onErrorRef.current(event);
3399
+ else console.error(`[CopilotKit] Error (${event.code}):`, event.error, event.context ?? {});
3315
3400
  } });
3316
3401
  return () => {
3317
3402
  subscription.unsubscribe();
@@ -3356,322 +3441,76 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
3356
3441
  didMountRef.current = true;
3357
3442
  }, []);
3358
3443
  (0, react.useEffect)(() => {
3359
- copilotkit.setDefaultThrottleMs(defaultThrottleMs);
3360
- }, [copilotkit, defaultThrottleMs]);
3361
- const designSkill = openGenerativeUI?.designSkill ?? DEFAULT_DESIGN_SKILL;
3362
- (0, react.useLayoutEffect)(() => {
3363
- if (!copilotkit || !openGenUIActive) return;
3364
- const id = copilotkit.addContext({
3365
- description: "Design guidelines for the generateSandboxedUi tool. Follow these when building UI.",
3366
- value: designSkill
3367
- });
3368
- return () => {
3369
- copilotkit.removeContext(id);
3370
- };
3371
- }, [
3372
- copilotkit,
3373
- designSkill,
3374
- openGenUIActive
3375
- ]);
3376
- const sandboxFunctionsDescriptors = (0, react.useMemo)(() => {
3377
- if (sandboxFunctionsList.length === 0) return null;
3378
- return JSON.stringify(sandboxFunctionsList.map((fn) => ({
3379
- name: fn.name,
3380
- description: fn.description,
3381
- parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zod_to_json_schema.zodToJsonSchema })
3382
- })));
3383
- }, [sandboxFunctionsList]);
3384
- (0, react.useLayoutEffect)(() => {
3385
- if (!copilotkit || !sandboxFunctionsDescriptors || !openGenUIActive) return;
3386
- const id = copilotkit.addContext({
3387
- description: "Sandbox functions available in generated sandboxed UI code. Call via: await Websandbox.connection.remote.<functionName>(args)",
3388
- value: sandboxFunctionsDescriptors
3389
- });
3390
- return () => {
3391
- copilotkit.removeContext(id);
3392
- };
3393
- }, [
3394
- copilotkit,
3395
- sandboxFunctionsDescriptors,
3396
- openGenUIActive
3397
- ]);
3398
- const contextValue = (0, react.useMemo)(() => ({
3399
- copilotkit,
3400
- executingToolCallIds
3401
- }), [copilotkit, executingToolCallIds]);
3402
- const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(null), []);
3403
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SandboxFunctionsContext.Provider, {
3404
- value: sandboxFunctionsList,
3405
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
3406
- value: contextValue,
3407
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
3408
- value: licenseContextValue,
3409
- children: [
3410
- runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
3411
- runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
3412
- catalog: a2ui?.catalog,
3413
- includeSchema: a2ui?.includeSchema
3414
- }),
3415
- children,
3416
- shouldRenderInspector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitInspector, {
3417
- core: copilotkit,
3418
- defaultAnchor: inspectorDefaultAnchor
3419
- }) : null,
3420
- runtimeLicenseStatus === "none" && !resolvedPublicKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "no_license" }),
3421
- runtimeLicenseStatus === "expired" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expired" }),
3422
- runtimeLicenseStatus === "invalid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "invalid" }),
3423
- runtimeLicenseStatus === "expiring" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expiring" })
3424
- ]
3425
- })
3426
- })
3427
- });
3428
- };
3429
- const useCopilotKit = () => {
3430
- const context = (0, react.useContext)(CopilotKitContext);
3431
- const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
3432
- if (!context) throw new Error("useCopilotKit must be used within CopilotKitProvider");
3433
- (0, react.useEffect)(() => {
3434
- const subscription = context.copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
3435
- forceUpdate();
3436
- } });
3437
- return () => {
3438
- subscription.unsubscribe();
3439
- };
3440
- }, []);
3441
- return context;
3442
- };
3443
-
3444
- //#endregion
3445
- //#region src/v2/hooks/use-render-tool-call.tsx
3446
- /**
3447
- * Memoized component that renders a single tool call.
3448
- * This prevents unnecessary re-renders when parent components update
3449
- * but the tool call data hasn't changed.
3450
- */
3451
- const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall, toolMessage, RenderComponent, isExecuting }) {
3452
- const args = (0, react.useMemo)(() => (0, _copilotkit_shared.partialJSONParse)(toolCall.function.arguments), [toolCall.function.arguments]);
3453
- const toolName = toolCall.function.name;
3454
- if (toolMessage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
3455
- name: toolName,
3456
- toolCallId: toolCall.id,
3457
- args,
3458
- status: _copilotkit_core.ToolCallStatus.Complete,
3459
- result: toolMessage.content
3460
- });
3461
- else if (isExecuting) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
3462
- name: toolName,
3463
- toolCallId: toolCall.id,
3464
- args,
3465
- status: _copilotkit_core.ToolCallStatus.Executing,
3466
- result: void 0
3467
- });
3468
- else return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
3469
- name: toolName,
3470
- toolCallId: toolCall.id,
3471
- args,
3472
- status: _copilotkit_core.ToolCallStatus.InProgress,
3473
- result: void 0
3474
- });
3475
- }, (prevProps, nextProps) => {
3476
- if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
3477
- if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
3478
- if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
3479
- if (prevProps.toolMessage?.content !== nextProps.toolMessage?.content) return false;
3480
- if (prevProps.isExecuting !== nextProps.isExecuting) return false;
3481
- if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
3482
- return true;
3483
- });
3484
- /**
3485
- * Hook that returns a function to render tool calls based on the render functions
3486
- * defined in CopilotKitProvider.
3487
- *
3488
- * @returns A function that takes a tool call and optional tool message and returns the rendered component
3489
- */
3490
- function useRenderToolCall() {
3491
- const { copilotkit, executingToolCallIds } = useCopilotKit();
3492
- const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3493
- const renderToolCalls = (0, react.useSyncExternalStore)((callback) => {
3494
- return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
3495
- }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
3496
- return (0, react.useCallback)(({ toolCall, toolMessage }) => {
3497
- const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
3498
- const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
3499
- if (!renderConfig) return null;
3500
- const RenderComponent = renderConfig.render;
3501
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallRenderer, {
3502
- toolCall,
3503
- toolMessage,
3504
- RenderComponent,
3505
- isExecuting: executingToolCallIds.has(toolCall.id)
3506
- }, toolCall.id);
3507
- }, [
3508
- renderToolCalls,
3509
- executingToolCallIds,
3510
- agentId
3511
- ]);
3512
- }
3513
-
3514
- //#endregion
3515
- //#region src/v2/hooks/use-agent.tsx
3516
- let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
3517
- UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
3518
- UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
3519
- UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
3520
- return UseAgentUpdate;
3521
- }({});
3522
- const ALL_UPDATES = [
3523
- UseAgentUpdate.OnMessagesChanged,
3524
- UseAgentUpdate.OnStateChanged,
3525
- UseAgentUpdate.OnRunStatusChanged
3526
- ];
3527
- /**
3528
- * Clone a registry agent for per-thread isolation.
3529
- * Copies agent configuration (transport, headers, etc.) but resets conversation
3530
- * state (messages, threadId, state) so each thread starts fresh.
3531
- */
3532
- function cloneForThread(source, threadId, headers) {
3533
- const clone = source.clone();
3534
- if (clone === source) throw new Error(`useAgent: ${source.constructor.name}.clone() returned the same instance. clone() must return a new, independent object.`);
3535
- clone.threadId = threadId;
3536
- clone.setMessages([]);
3537
- clone.setState({});
3538
- if (clone instanceof _ag_ui_client.HttpAgent) clone.headers = { ...headers };
3539
- return clone;
3540
- }
3541
- /**
3542
- * Module-level WeakMap: registryAgent → (threadId → clone).
3543
- * Shared across all useAgent() calls so that every component using the same
3544
- * (agentId, threadId) pair receives the same agent instance. Using WeakMap
3545
- * ensures the clone map is garbage-collected when the registry agent is
3546
- * replaced (e.g. after reconnect or hot-reload).
3547
- */
3548
- const globalThreadCloneMap = /* @__PURE__ */ new WeakMap();
3549
- /**
3550
- * Look up an existing per-thread clone without creating one.
3551
- * Returns undefined when no clone has been created yet for this pair.
3552
- */
3553
- function getThreadClone(registryAgent, threadId) {
3554
- if (!registryAgent || !threadId) return void 0;
3555
- return globalThreadCloneMap.get(registryAgent)?.get(threadId);
3556
- }
3557
- function getOrCreateThreadClone(existing, threadId, headers) {
3558
- let byThread = globalThreadCloneMap.get(existing);
3559
- if (!byThread) {
3560
- byThread = /* @__PURE__ */ new Map();
3561
- globalThreadCloneMap.set(existing, byThread);
3562
- }
3563
- const cached = byThread.get(threadId);
3564
- if (cached) return cached;
3565
- const clone = cloneForThread(existing, threadId, headers);
3566
- byThread.set(threadId, clone);
3567
- return clone;
3568
- }
3569
- function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
3570
- agentId ??= _copilotkit_shared.DEFAULT_AGENT_ID;
3571
- const { copilotkit } = useCopilotKit();
3572
- const providerThrottleMs = copilotkit.defaultThrottleMs;
3573
- const chatConfig = useCopilotChatConfiguration();
3574
- threadId ??= chatConfig?.threadId;
3575
- const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
3576
- const updateFlags = (0, react.useMemo)(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
3577
- const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
3578
- const agent = (0, react.useMemo)(() => {
3579
- const cacheKey = threadId ? `${agentId}:${threadId}` : agentId;
3580
- const existing = copilotkit.getAgent(agentId);
3581
- if (existing) {
3582
- provisionalAgentCache.current.delete(cacheKey);
3583
- provisionalAgentCache.current.delete(agentId);
3584
- if (!threadId) return existing;
3585
- return getOrCreateThreadClone(existing, threadId, copilotkit.headers);
3586
- }
3587
- const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
3588
- const status = copilotkit.runtimeConnectionStatus;
3589
- if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
3590
- const cached = provisionalAgentCache.current.get(cacheKey);
3591
- if (cached) {
3592
- cached.headers = { ...copilotkit.headers };
3593
- return cached;
3594
- }
3595
- const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
3596
- runtimeUrl: copilotkit.runtimeUrl,
3597
- agentId,
3598
- transport: copilotkit.runtimeTransport,
3599
- runtimeMode: "pending"
3600
- });
3601
- provisional.headers = { ...copilotkit.headers };
3602
- if (threadId) provisional.threadId = threadId;
3603
- provisionalAgentCache.current.set(cacheKey, provisional);
3604
- return provisional;
3605
- }
3606
- if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
3607
- const cached = provisionalAgentCache.current.get(cacheKey);
3608
- if (cached) {
3609
- cached.headers = { ...copilotkit.headers };
3610
- return cached;
3611
- }
3612
- const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
3613
- runtimeUrl: copilotkit.runtimeUrl,
3614
- agentId,
3615
- transport: copilotkit.runtimeTransport,
3616
- runtimeMode: "pending"
3617
- });
3618
- provisional.headers = { ...copilotkit.headers };
3619
- if (threadId) provisional.threadId = threadId;
3620
- provisionalAgentCache.current.set(cacheKey, provisional);
3621
- return provisional;
3622
- }
3623
- const knownAgents = Object.keys(copilotkit.agents ?? {});
3624
- const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
3625
- 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.");
3626
- }, [
3627
- agentId,
3628
- threadId,
3629
- copilotkit.agents,
3630
- copilotkit.runtimeConnectionStatus,
3631
- copilotkit.runtimeUrl,
3632
- copilotkit.runtimeTransport,
3633
- JSON.stringify(copilotkit.headers)
3634
- ]);
3635
- (0, react.useEffect)(() => {
3636
- if (updateFlags.length === 0) return;
3637
- let active = true;
3638
- const handlers = {};
3639
- let batchScheduled = false;
3640
- const batchedForceUpdate = () => {
3641
- if (!active) return;
3642
- if (!batchScheduled) {
3643
- batchScheduled = true;
3644
- queueMicrotask(() => {
3645
- batchScheduled = false;
3646
- if (active) forceUpdate();
3647
- });
3648
- }
3444
+ copilotkit.setDefaultThrottleMs(defaultThrottleMs);
3445
+ }, [copilotkit, defaultThrottleMs]);
3446
+ const designSkill = openGenerativeUI?.designSkill ?? DEFAULT_DESIGN_SKILL;
3447
+ (0, react.useLayoutEffect)(() => {
3448
+ if (!copilotkit || !openGenUIActive) return;
3449
+ const id = copilotkit.addContext({
3450
+ description: "Design guidelines for the generateSandboxedUi tool. Follow these when building UI.",
3451
+ value: designSkill
3452
+ });
3453
+ return () => {
3454
+ copilotkit.removeContext(id);
3649
3455
  };
3650
- if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
3651
- if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
3652
- if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
3653
- handlers.onRunInitialized = batchedForceUpdate;
3654
- handlers.onRunFinalized = batchedForceUpdate;
3655
- handlers.onRunFailed = batchedForceUpdate;
3656
- handlers.onRunErrorEvent = batchedForceUpdate;
3657
- }
3658
- const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
3456
+ }, [
3457
+ copilotkit,
3458
+ designSkill,
3459
+ openGenUIActive
3460
+ ]);
3461
+ const sandboxFunctionsDescriptors = (0, react.useMemo)(() => {
3462
+ if (sandboxFunctionsList.length === 0) return null;
3463
+ return JSON.stringify(sandboxFunctionsList.map((fn) => ({
3464
+ name: fn.name,
3465
+ description: fn.description,
3466
+ parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zod_to_json_schema.zodToJsonSchema })
3467
+ })));
3468
+ }, [sandboxFunctionsList]);
3469
+ (0, react.useLayoutEffect)(() => {
3470
+ if (!copilotkit || !sandboxFunctionsDescriptors || !openGenUIActive) return;
3471
+ const id = copilotkit.addContext({
3472
+ description: "Sandbox functions available in generated sandboxed UI code. Call via: await Websandbox.connection.remote.<functionName>(args)",
3473
+ value: sandboxFunctionsDescriptors
3474
+ });
3659
3475
  return () => {
3660
- active = false;
3661
- subscription.unsubscribe();
3476
+ copilotkit.removeContext(id);
3662
3477
  };
3663
3478
  }, [
3664
- agent,
3665
- forceUpdate,
3666
- throttleMs,
3667
- providerThrottleMs,
3668
- updateFlags
3479
+ copilotkit,
3480
+ sandboxFunctionsDescriptors,
3481
+ openGenUIActive
3669
3482
  ]);
3670
- (0, react.useEffect)(() => {
3671
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
3672
- }, [agent, JSON.stringify(copilotkit.headers)]);
3673
- return { agent };
3674
- }
3483
+ const contextValue = (0, react.useMemo)(() => ({
3484
+ copilotkit,
3485
+ executingToolCallIds
3486
+ }), [copilotkit, executingToolCallIds]);
3487
+ const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(null), []);
3488
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SandboxFunctionsContext.Provider, {
3489
+ value: sandboxFunctionsList,
3490
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
3491
+ value: contextValue,
3492
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
3493
+ value: licenseContextValue,
3494
+ children: [
3495
+ runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
3496
+ runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
3497
+ catalog: a2ui?.catalog,
3498
+ includeSchema: a2ui?.includeSchema
3499
+ }),
3500
+ children,
3501
+ shouldRenderInspector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitInspector, {
3502
+ core: copilotkit,
3503
+ defaultAnchor: inspectorDefaultAnchor
3504
+ }) : null,
3505
+ runtimeLicenseStatus === "none" && !resolvedPublicKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "no_license" }),
3506
+ runtimeLicenseStatus === "expired" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expired" }),
3507
+ runtimeLicenseStatus === "invalid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "invalid" }),
3508
+ runtimeLicenseStatus === "expiring" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expiring" })
3509
+ ]
3510
+ })
3511
+ })
3512
+ });
3513
+ };
3675
3514
 
3676
3515
  //#endregion
3677
3516
  //#region src/v2/hooks/use-render-custom-messages.tsx
@@ -3690,8 +3529,7 @@ function useRenderCustomMessages() {
3690
3529
  const { message, position } = params;
3691
3530
  const resolvedRunId = copilotkit.getRunIdForMessage(agentId, threadId, message.id) ?? copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
3692
3531
  const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
3693
- const registryAgent = copilotkit.getAgent(agentId);
3694
- const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
3532
+ const agent = copilotkit.getAgent(agentId);
3695
3533
  if (!agent) return null;
3696
3534
  const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
3697
3535
  const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
@@ -3723,8 +3561,7 @@ function useRenderCustomMessages() {
3723
3561
  //#region src/v2/hooks/use-render-activity-message.tsx
3724
3562
  function useRenderActivityMessage() {
3725
3563
  const { copilotkit } = useCopilotKit();
3726
- const config = useCopilotChatConfiguration();
3727
- const agentId = config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3564
+ const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3728
3565
  const renderers = copilotkit.renderActivityMessages;
3729
3566
  const findRenderer = (0, react.useCallback)((activityType) => {
3730
3567
  if (!renderers.length) return null;
@@ -3740,8 +3577,7 @@ function useRenderActivityMessage() {
3740
3577
  return null;
3741
3578
  }
3742
3579
  const Component = renderer.render;
3743
- const registryAgent = copilotkit.getAgent(agentId);
3744
- const agent = getThreadClone(registryAgent, config?.threadId) ?? registryAgent;
3580
+ const agent = copilotkit.getAgent(agentId);
3745
3581
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
3746
3582
  activityType: message.activityType,
3747
3583
  content: parseResult.data,
@@ -3750,7 +3586,6 @@ function useRenderActivityMessage() {
3750
3586
  }, message.id);
3751
3587
  }, [
3752
3588
  agentId,
3753
- config?.threadId,
3754
3589
  copilotkit,
3755
3590
  findRenderer
3756
3591
  ]);
@@ -3789,8 +3624,7 @@ function useFrontendTool(tool, deps) {
3789
3624
  tool.name,
3790
3625
  tool.available,
3791
3626
  copilotkit,
3792
- extraDeps.length,
3793
- ...extraDeps
3627
+ JSON.stringify(extraDeps)
3794
3628
  ]);
3795
3629
  }
3796
3630
 
@@ -3929,8 +3763,7 @@ function useRenderTool(config, deps) {
3929
3763
  }, [
3930
3764
  config.name,
3931
3765
  copilotkit,
3932
- extraDeps.length,
3933
- ...extraDeps
3766
+ JSON.stringify(extraDeps)
3934
3767
  ]);
3935
3768
  }
3936
3769
 
@@ -4190,6 +4023,118 @@ function useHumanInTheLoop(tool, deps) {
4190
4023
  ]);
4191
4024
  }
4192
4025
 
4026
+ //#endregion
4027
+ //#region src/v2/hooks/use-agent.tsx
4028
+ let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
4029
+ UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
4030
+ UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
4031
+ UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
4032
+ return UseAgentUpdate;
4033
+ }({});
4034
+ const ALL_UPDATES = [
4035
+ UseAgentUpdate.OnMessagesChanged,
4036
+ UseAgentUpdate.OnStateChanged,
4037
+ UseAgentUpdate.OnRunStatusChanged
4038
+ ];
4039
+ function useAgent({ agentId, updates, throttleMs } = {}) {
4040
+ agentId ??= _copilotkit_shared.DEFAULT_AGENT_ID;
4041
+ const { copilotkit } = useCopilotKit();
4042
+ const providerThrottleMs = copilotkit.defaultThrottleMs;
4043
+ const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
4044
+ const updateFlags = (0, react.useMemo)(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
4045
+ const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
4046
+ const agent = (0, react.useMemo)(() => {
4047
+ const existing = copilotkit.getAgent(agentId);
4048
+ if (existing) {
4049
+ provisionalAgentCache.current.delete(agentId);
4050
+ return existing;
4051
+ }
4052
+ const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
4053
+ const status = copilotkit.runtimeConnectionStatus;
4054
+ if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
4055
+ const cached = provisionalAgentCache.current.get(agentId);
4056
+ if (cached) {
4057
+ cached.headers = { ...copilotkit.headers };
4058
+ return cached;
4059
+ }
4060
+ const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4061
+ runtimeUrl: copilotkit.runtimeUrl,
4062
+ agentId,
4063
+ transport: copilotkit.runtimeTransport,
4064
+ runtimeMode: "pending"
4065
+ });
4066
+ provisional.headers = { ...copilotkit.headers };
4067
+ provisionalAgentCache.current.set(agentId, provisional);
4068
+ return provisional;
4069
+ }
4070
+ if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
4071
+ const cached = provisionalAgentCache.current.get(agentId);
4072
+ if (cached) {
4073
+ cached.headers = { ...copilotkit.headers };
4074
+ return cached;
4075
+ }
4076
+ const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4077
+ runtimeUrl: copilotkit.runtimeUrl,
4078
+ agentId,
4079
+ transport: copilotkit.runtimeTransport,
4080
+ runtimeMode: "pending"
4081
+ });
4082
+ provisional.headers = { ...copilotkit.headers };
4083
+ provisionalAgentCache.current.set(agentId, provisional);
4084
+ return provisional;
4085
+ }
4086
+ const knownAgents = Object.keys(copilotkit.agents ?? {});
4087
+ const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
4088
+ 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.");
4089
+ }, [
4090
+ agentId,
4091
+ copilotkit.agents,
4092
+ copilotkit.runtimeConnectionStatus,
4093
+ copilotkit.runtimeUrl,
4094
+ copilotkit.runtimeTransport,
4095
+ JSON.stringify(copilotkit.headers)
4096
+ ]);
4097
+ (0, react.useEffect)(() => {
4098
+ if (updateFlags.length === 0) return;
4099
+ let active = true;
4100
+ const handlers = {};
4101
+ let batchScheduled = false;
4102
+ const batchedForceUpdate = () => {
4103
+ if (!active) return;
4104
+ if (!batchScheduled) {
4105
+ batchScheduled = true;
4106
+ queueMicrotask(() => {
4107
+ batchScheduled = false;
4108
+ if (active) forceUpdate();
4109
+ });
4110
+ }
4111
+ };
4112
+ if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = batchedForceUpdate;
4113
+ if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
4114
+ if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
4115
+ handlers.onRunInitialized = batchedForceUpdate;
4116
+ handlers.onRunFinalized = batchedForceUpdate;
4117
+ handlers.onRunFailed = batchedForceUpdate;
4118
+ handlers.onRunErrorEvent = batchedForceUpdate;
4119
+ }
4120
+ const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
4121
+ return () => {
4122
+ active = false;
4123
+ subscription.unsubscribe();
4124
+ };
4125
+ }, [
4126
+ agent,
4127
+ forceUpdate,
4128
+ throttleMs,
4129
+ providerThrottleMs,
4130
+ updateFlags
4131
+ ]);
4132
+ (0, react.useEffect)(() => {
4133
+ if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
4134
+ }, [agent, JSON.stringify(copilotkit.headers)]);
4135
+ return { agent };
4136
+ }
4137
+
4193
4138
  //#endregion
4194
4139
  //#region src/v2/hooks/use-capabilities.tsx
4195
4140
  /**
@@ -5655,6 +5600,190 @@ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
5655
5600
  */
5656
5601
  const ScrollElementContext = react.default.createContext(null);
5657
5602
 
5603
+ //#endregion
5604
+ //#region src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx
5605
+ /**
5606
+ * Grace window before showing the spinner. A matching tool call must
5607
+ * remain unresolved (no `tool`-role result message in `agent.messages`)
5608
+ * for at least this long before the pill appears. This filters out
5609
+ * history-replay flashes — during `connectAgent` replay, tool calls and
5610
+ * their results arrive back-to-back in sub-millisecond bursts, so the
5611
+ * timer is cancelled before it fires. Live runs cross the threshold
5612
+ * easily because the tool actually has to execute.
5613
+ */
5614
+ const PENDING_THRESHOLD_MS = 100;
5615
+ /** Hold the checkmark briefly before fading out. */
5616
+ const CHECK_HOLD_MS = 800;
5617
+ /**
5618
+ * Duration of the fade-out animation. Must match
5619
+ * `cpk-intelligence-pill-fade-out` keyframes in `v2/styles/globals.css`.
5620
+ */
5621
+ const FADE_OUT_ANIMATION_MS = 480;
5622
+ /**
5623
+ * Tool-name regex patterns that trigger the indicator. Currently
5624
+ * hardcoded to the Intelligence MCP server's canonical tool name. If
5625
+ * we add per-instance customization later (e.g. a `CopilotKitProvider`
5626
+ * prop or a runtime-info field), this constant becomes the fallback.
5627
+ */
5628
+ const DEFAULT_TOOL_PATTERNS = [/^copilotkit_knowledge_base_shell$/];
5629
+ const isMatchingToolCallName = (name) => typeof name === "string" && DEFAULT_TOOL_PATTERNS.some((p) => p.test(name));
5630
+ /**
5631
+ * "Tool-call-like" messages do NOT count as a real follow-up: tool
5632
+ * result messages, assistant messages that carry tool calls, and
5633
+ * empty-content assistant messages (which some providers emit as a
5634
+ * standalone wrapper around a batch of tool calls). A real follow-up
5635
+ * is anything else — most importantly an assistant message with prose
5636
+ * content, or a fresh user message.
5637
+ */
5638
+ const isToolCallLikeMessage = (m) => {
5639
+ if (m.role === "tool") return true;
5640
+ if (m.role === "assistant") {
5641
+ if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).length > 0) return true;
5642
+ const content = m.content;
5643
+ return typeof content !== "string" || content.trim().length === 0;
5644
+ }
5645
+ return false;
5646
+ };
5647
+ /**
5648
+ * The "Using CopilotKit Intelligence" pill. Auto-mounted by
5649
+ * `CopilotChatMessageView` for every message slot when
5650
+ * `copilotkit.intelligence` is configured — callers do not register
5651
+ * this themselves. Self-gates so only the canonical message renders a
5652
+ * pill.
5653
+ *
5654
+ * Render gates (all must hold):
5655
+ * 1. `copilotkit.intelligence !== undefined`
5656
+ * 2. The message is an assistant message with at least one tool call
5657
+ * whose name matches {@link DEFAULT_TOOL_PATTERNS}
5658
+ * 3. The message is the *latest* such matching-assistant message in
5659
+ * `agent.messages` — tool-result messages and prose-only assistant
5660
+ * messages don't invalidate the slot, so the pill stays
5661
+ * continuously through a multi-step tool chain.
5662
+ * 4. The phase machine is past `idle` (the pending-grace timer fired)
5663
+ * and not yet `hidden`.
5664
+ *
5665
+ * Phase machine (per-instance, all timers local):
5666
+ * - Starts in `idle` — nothing rendered.
5667
+ * - `idle → spinner` once a matching tool call has been pending
5668
+ * (no `tool`-role result with a matching `toolCallId`) for
5669
+ * {@link PENDING_THRESHOLD_MS}. Replay flashes (tool call + result
5670
+ * in the same tick) never cross this threshold.
5671
+ * - `spinner → check` as soon as EITHER `agent.isRunning` flips
5672
+ * false OR a non-tool-call-like message appears later in
5673
+ * `agent.messages` (i.e. the agent has produced a "real"
5674
+ * follow-up — prose answer or a new user turn).
5675
+ * - `check → fading` after {@link CHECK_HOLD_MS}.
5676
+ * - `fading → hidden` after {@link FADE_OUT_ANIMATION_MS}.
5677
+ *
5678
+ * Once `hidden`, the phase is sticky — a finished pill never re-spawns
5679
+ * on the same message. New runs mount fresh indicator instances on
5680
+ * their own assistant messages.
5681
+ *
5682
+ * The "exactly one pill at a time" guarantee is structural: only one
5683
+ * message satisfies the latest-matching-assistant gate at any moment.
5684
+ */
5685
+ function IntelligenceIndicator(props) {
5686
+ const { message, agentId, label = "Using CopilotKit Intelligence" } = props;
5687
+ const { copilotkit } = useCopilotKit();
5688
+ const config = useCopilotChatConfiguration();
5689
+ const { agent } = useAgent({
5690
+ agentId,
5691
+ updates: [UseAgentUpdate.OnRunStatusChanged, UseAgentUpdate.OnMessagesChanged]
5692
+ });
5693
+ const matchingToolCallIds = (0, react.useMemo)(() => {
5694
+ if (message.role !== "assistant") return [];
5695
+ const tcs = Array.isArray(message.toolCalls) ? message.toolCalls : [];
5696
+ const ids = [];
5697
+ for (const tc of tcs) if (isMatchingToolCallName(tc?.function?.name) && tc?.id) ids.push(tc.id);
5698
+ return ids;
5699
+ }, [message]);
5700
+ const hasPending = (0, react.useMemo)(() => {
5701
+ if (matchingToolCallIds.length === 0) return false;
5702
+ const resolved = /* @__PURE__ */ new Set();
5703
+ for (const m of agent.messages) if (m.role === "tool" && m.toolCallId) resolved.add(m.toolCallId);
5704
+ return matchingToolCallIds.some((id) => !resolved.has(id));
5705
+ }, [matchingToolCallIds, agent.messages]);
5706
+ const sawRealFollowup = (0, react.useMemo)(() => {
5707
+ const idx = agent.messages.findIndex((m) => m.id === message.id);
5708
+ if (idx < 0) return false;
5709
+ for (let i = idx + 1; i < agent.messages.length; i += 1) if (!isToolCallLikeMessage(agent.messages[i])) return true;
5710
+ return false;
5711
+ }, [agent.messages, message.id]);
5712
+ const [phase, setPhase] = (0, react.useState)("idle");
5713
+ (0, react.useEffect)(() => {
5714
+ if (phase !== "idle") return void 0;
5715
+ if (!hasPending) return void 0;
5716
+ const t = setTimeout(() => setPhase("spinner"), PENDING_THRESHOLD_MS);
5717
+ return () => clearTimeout(t);
5718
+ }, [phase, hasPending]);
5719
+ (0, react.useEffect)(() => {
5720
+ if (phase !== "spinner") return void 0;
5721
+ if (!agent.isRunning || sawRealFollowup) setPhase("check");
5722
+ }, [
5723
+ phase,
5724
+ agent.isRunning,
5725
+ sawRealFollowup
5726
+ ]);
5727
+ (0, react.useEffect)(() => {
5728
+ if (phase !== "check") return void 0;
5729
+ const t = setTimeout(() => setPhase("fading"), CHECK_HOLD_MS);
5730
+ return () => clearTimeout(t);
5731
+ }, [phase]);
5732
+ (0, react.useEffect)(() => {
5733
+ if (phase !== "fading") return void 0;
5734
+ const t = setTimeout(() => setPhase("hidden"), FADE_OUT_ANIMATION_MS);
5735
+ return () => clearTimeout(t);
5736
+ }, [phase]);
5737
+ if (copilotkit.intelligence === void 0) return null;
5738
+ if (!config) return null;
5739
+ if (phase === "idle" || phase === "hidden") return null;
5740
+ if (message.role !== "assistant") return null;
5741
+ if (!(Array.isArray(message.toolCalls) ? message.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) return null;
5742
+ let latestMatchingAssistantId;
5743
+ for (let i = agent.messages.length - 1; i >= 0; i -= 1) {
5744
+ const m = agent.messages[i];
5745
+ if (m.role !== "assistant") continue;
5746
+ if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) {
5747
+ latestMatchingAssistantId = m.id;
5748
+ break;
5749
+ }
5750
+ }
5751
+ if (latestMatchingAssistantId !== message.id) return null;
5752
+ const showSpinner = phase === "spinner";
5753
+ const isFading = phase === "fading";
5754
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5755
+ className: "cpk-intelligence-pill" + (isFading ? " cpk-intelligence-pill--fading" : ""),
5756
+ role: "status",
5757
+ "aria-live": "polite",
5758
+ "aria-hidden": isFading || void 0,
5759
+ "data-testid": `cpk-intelligence-pill-${message.id}`,
5760
+ title: label,
5761
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
5762
+ className: "cpk-intelligence-pill__icon",
5763
+ viewBox: "0 0 24 24",
5764
+ width: "14",
5765
+ height: "14",
5766
+ "aria-hidden": "true",
5767
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
5768
+ cx: "12",
5769
+ cy: "12",
5770
+ r: "9",
5771
+ fill: "none",
5772
+ strokeWidth: "2.5",
5773
+ strokeLinecap: "round",
5774
+ className: "cpk-intelligence-pill__ring" + (showSpinner ? "" : " cpk-intelligence-pill__ring--done")
5775
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
5776
+ d: "M8 12.5l3 3 5-6",
5777
+ fill: "none",
5778
+ strokeWidth: "2.5",
5779
+ strokeLinecap: "round",
5780
+ strokeLinejoin: "round",
5781
+ className: "cpk-intelligence-pill__check" + (showSpinner ? "" : " cpk-intelligence-pill__check--shown")
5782
+ })]
5783
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })]
5784
+ });
5785
+ }
5786
+
5658
5787
  //#endregion
5659
5788
  //#region src/v2/components/chat/CopilotChatMessageView.tsx
5660
5789
  /**
@@ -5812,14 +5941,12 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5812
5941
  const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
5813
5942
  (0, react.useEffect)(() => {
5814
5943
  if (!config?.agentId) return;
5815
- const registryAgent = copilotkit.getAgent(config.agentId);
5816
- const agent = getThreadClone(registryAgent, config.threadId) ?? registryAgent;
5944
+ const agent = copilotkit.getAgent(config.agentId);
5817
5945
  if (!agent) return;
5818
5946
  const subscription = agent.subscribe({ onStateChanged: forceUpdate });
5819
5947
  return () => subscription.unsubscribe();
5820
5948
  }, [
5821
5949
  config?.agentId,
5822
- config?.threadId,
5823
5950
  copilotkit,
5824
5951
  forceUpdate
5825
5952
  ]);
@@ -5902,6 +6029,10 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5902
6029
  renderCustomMessage,
5903
6030
  stateSnapshot
5904
6031
  }, `${message.id}-custom-after`));
6032
+ if (copilotkit.intelligence !== void 0 && message.role === "assistant") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IntelligenceIndicator, {
6033
+ message,
6034
+ agentId: config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID
6035
+ }, `${message.id}-intelligence`));
5905
6036
  return elements.filter(Boolean);
5906
6037
  };
5907
6038
  const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
@@ -6850,7 +6981,6 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6850
6981
  const hasExplicitThreadId = !!threadId || !!existingConfig?.hasExplicitThreadId;
6851
6982
  const { agent } = useAgent({
6852
6983
  agentId: resolvedAgentId,
6853
- threadId: resolvedThreadId,
6854
6984
  throttleMs
6855
6985
  });
6856
6986
  const { copilotkit } = useCopilotKit();
@@ -6892,6 +7022,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6892
7022
  let detached = false;
6893
7023
  const connectAbortController = new AbortController();
6894
7024
  if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
7025
+ agent.threadId = resolvedThreadId;
6895
7026
  const connect = async (agent) => {
6896
7027
  try {
6897
7028
  await copilotkit.connectAgent({ agent });
@@ -10024,6 +10155,12 @@ Object.defineProperty(exports, 'DefaultOpenIcon', {
10024
10155
  return DefaultOpenIcon;
10025
10156
  }
10026
10157
  });
10158
+ Object.defineProperty(exports, 'IntelligenceIndicator', {
10159
+ enumerable: true,
10160
+ get: function () {
10161
+ return IntelligenceIndicator;
10162
+ }
10163
+ });
10027
10164
  Object.defineProperty(exports, 'MCPAppsActivityContentSchema', {
10028
10165
  enumerable: true,
10029
10166
  get: function () {
@@ -10252,4 +10389,4 @@ Object.defineProperty(exports, 'useToast', {
10252
10389
  return useToast;
10253
10390
  }
10254
10391
  });
10255
- //# sourceMappingURL=copilotkit-DGbvw8n2.cjs.map
10392
+ //# sourceMappingURL=copilotkit-C3k13WZn.cjs.map