@copilotkit/react-core 1.59.2 → 1.59.4

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.
@@ -234,9 +234,9 @@ const useCopilotChatConfiguration = () => {
234
234
 
235
235
  //#endregion
236
236
  //#region src/v2/lib/utils.ts
237
- const twMerge$7 = (0, tailwind_merge.extendTailwindMerge)({ prefix: "cpk" });
237
+ const twMerge$8 = (0, tailwind_merge.extendTailwindMerge)({ prefix: "cpk" });
238
238
  function cn(...inputs) {
239
- return twMerge$7((0, clsx.clsx)(inputs));
239
+ return twMerge$8((0, clsx.clsx)(inputs));
240
240
  }
241
241
 
242
242
  //#endregion
@@ -794,7 +794,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
794
794
  }
795
795
  if (e.key === "Enter" && !e.shiftKey) {
796
796
  e.preventDefault();
797
- if (isProcessing) onStop?.();
797
+ if (isProcessing && !canSend) onStop?.();
798
798
  else send();
799
799
  }
800
800
  };
@@ -4811,6 +4811,175 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4811
4811
  };
4812
4812
  }
4813
4813
 
4814
+ //#endregion
4815
+ //#region src/v2/lib/record-annotation.ts
4816
+ /**
4817
+ * Low-level function that posts an arbitrary annotation to the CopilotKit
4818
+ * runtime's general annotation endpoint (`POST /annotate`).
4819
+ *
4820
+ * This is the single transport entry point for all annotation types. Higher-
4821
+ * level hooks (e.g. `useLearnFromUserAction`) build the `type`/`payload` pair
4822
+ * for their specific annotation shape and delegate the HTTP call here.
4823
+ *
4824
+ * The function uses the same transport as `useLearnFromUserAction`:
4825
+ * - `runtimeUrl` from `copilotkit.runtimeUrl` (BFF proxies to the platform)
4826
+ * - `headers` from `copilotkit.headers` (customer auth forwarded to BFF)
4827
+ * - `clientEventId` auto-generated via `randomUUID()` when omitted
4828
+ * - `userId` is resolved server-side by the runtime; the client never sends it
4829
+ * - Errors propagate to the caller (fire-and-propagate, not fire-and-forget)
4830
+ *
4831
+ * @param args - Transport dependencies plus annotation fields.
4832
+ * @returns The platform result containing the annotation row `id` and a
4833
+ * `duplicate` flag.
4834
+ * @throws When the network request fails or the runtime returns a non-2xx
4835
+ * status. Callers that want fire-and-forget behavior should `.catch`
4836
+ * at the call site.
4837
+ */
4838
+ async function recordAnnotation(args) {
4839
+ const { runtimeUrl, headers, type, payload, threadId, occurredAt } = args;
4840
+ const body = {
4841
+ type,
4842
+ threadId,
4843
+ clientEventId: args.clientEventId ?? (0, _copilotkit_shared.randomUUID)(),
4844
+ ...payload !== void 0 ? { payload } : {},
4845
+ ...occurredAt !== void 0 ? { occurredAt } : {}
4846
+ };
4847
+ const response = await fetch(`${runtimeUrl}/annotate`, {
4848
+ method: "POST",
4849
+ headers: {
4850
+ "Content-Type": "application/json",
4851
+ ...headers
4852
+ },
4853
+ body: JSON.stringify(body)
4854
+ });
4855
+ if (!response.ok) {
4856
+ const text = await response.text().catch(() => "");
4857
+ throw new Error(`recordAnnotation: request failed (${response.status})${text ? `: ${text}` : ""}`);
4858
+ }
4859
+ const text = await response.text();
4860
+ if (!text) throw new Error(`recordAnnotation: runtime ${runtimeUrl}/annotate returned ${response.status} with an empty body`);
4861
+ try {
4862
+ return JSON.parse(text);
4863
+ } catch {
4864
+ throw new Error(`recordAnnotation: runtime ${runtimeUrl}/annotate returned a non-JSON body (status ${response.status})`);
4865
+ }
4866
+ }
4867
+
4868
+ //#endregion
4869
+ //#region src/v2/hooks/use-learn-from-user-action.tsx
4870
+ /**
4871
+ * Record a user UI interaction in the Intelligence platform's user-actions
4872
+ * stream. The platform's auto-curated knowledge base agent reads these
4873
+ * (alongside finished agent runs) and writes free-form Obsidian-flavored
4874
+ * markdown to `/project`, where any agent in the same project can later
4875
+ * read it via the `copilotkit_knowledge_base_shell` MCP tool.
4876
+ *
4877
+ * The hook returns a stable function. Calling it issues a request to the
4878
+ * customer's CopilotKit runtime (`POST ${runtimeUrl}/annotate`), which
4879
+ * resolves the Intel user from the BFF's auth and forwards to the
4880
+ * platform — the Intel API key never reaches the browser.
4881
+ *
4882
+ * If `clientEventId` is omitted `recordAnnotation` generates a UUID per call,
4883
+ * so a naive double-call (e.g. React 18 strict-mode double-mount, or a retry
4884
+ * after a network blip on a fresh Promise) is naturally safe. Supply your
4885
+ * own key when a single semantic event must remain idempotent across
4886
+ * multiple `learnFromUserAction(...)` calls.
4887
+ *
4888
+ * @example
4889
+ * ```tsx
4890
+ * import { useLearnFromUserAction } from "@copilotkit/react-core";
4891
+ *
4892
+ * function SettingsPage({ threadId }) {
4893
+ * const learnFromUserAction = useLearnFromUserAction();
4894
+ *
4895
+ * const onRename = (oldName: string, newName: string) => {
4896
+ * void learnFromUserAction({
4897
+ * threadId,
4898
+ * title: "Renamed project",
4899
+ * data: { previous: { name: oldName }, next: { name: newName } },
4900
+ * });
4901
+ * };
4902
+ * }
4903
+ * ```
4904
+ */
4905
+ function useLearnFromUserAction() {
4906
+ const { copilotkit } = useCopilotKit();
4907
+ return (0, react.useCallback)(async (input) => {
4908
+ const runtimeUrl = copilotkit.runtimeUrl;
4909
+ if (!runtimeUrl) throw new Error("useLearnFromUserAction: runtimeUrl is not configured. Set it on <CopilotKitProvider runtimeUrl=...>.");
4910
+ const payload = {
4911
+ ...input.title !== void 0 ? { title: input.title } : {},
4912
+ ...input.description !== void 0 ? { description: input.description } : {},
4913
+ ...input.data !== void 0 ? { data: input.data } : {}
4914
+ };
4915
+ return recordAnnotation({
4916
+ runtimeUrl,
4917
+ headers: copilotkit.headers ?? {},
4918
+ type: "user_action",
4919
+ payload: Object.keys(payload).length > 0 ? payload : void 0,
4920
+ threadId: input.threadId,
4921
+ clientEventId: input.clientEventId,
4922
+ occurredAt: input.occurredAt
4923
+ });
4924
+ }, [copilotkit]);
4925
+ }
4926
+
4927
+ //#endregion
4928
+ //#region src/v2/hooks/use-learn-from-user-action-in-current-thread.tsx
4929
+ /**
4930
+ * Record a user UI interaction against the **current chat's** thread. The
4931
+ * `threadId` is sourced from the surrounding
4932
+ * `<CopilotChatConfigurationProvider>` (the same provider `<CopilotChat>`,
4933
+ * `<CopilotSidebar>`, and friends set up), so callers in a chat-aware
4934
+ * subtree don't need to thread an id through manually.
4935
+ *
4936
+ * Throws on **call** (not on mount) when there is no chat-config provider
4937
+ * in scope — matches the "throw on call when runtimeUrl is missing"
4938
+ * behavior of {@link useLearnFromUserAction}. Mounting the hook in a branch
4939
+ * that never fires is harmless.
4940
+ *
4941
+ * The recorder does NOT accept a `threadId` override. If you need to
4942
+ * record against an explicit thread, use {@link useLearnFromUserAction}
4943
+ * directly — two hooks, two crisp contracts, no mode confusion.
4944
+ *
4945
+ * This hook always uses `config.threadId`, regardless of whether the
4946
+ * surrounding chat config minted it internally or received one from
4947
+ * the caller. Auto-minted threads simply mean the action lands under
4948
+ * a thread the platform never saw — the writer agent still distills
4949
+ * user-action-only threads (it does not require the thread to exist
4950
+ * in `cpki.threads`), so the loop keeps learning.
4951
+ *
4952
+ * @example
4953
+ * ```tsx
4954
+ * import { useLearnFromUserActionInCurrentThread } from "@copilotkit/react-core";
4955
+ *
4956
+ * function SettingsPanel() {
4957
+ * const learnFromUserAction = useLearnFromUserActionInCurrentThread();
4958
+ *
4959
+ * const onRename = (oldName: string, newName: string) => {
4960
+ * void learnFromUserAction({
4961
+ * title: "Renamed project",
4962
+ * data: { previous: { name: oldName }, next: { name: newName } },
4963
+ * });
4964
+ * };
4965
+ *
4966
+ * // ...
4967
+ * }
4968
+ * ```
4969
+ */
4970
+ function useLearnFromUserActionInCurrentThread() {
4971
+ const config = useCopilotChatConfiguration();
4972
+ const learnFromUserAction = useLearnFromUserAction();
4973
+ return (0, react.useCallback)(async (input) => {
4974
+ const threadId = config?.threadId;
4975
+ if (!threadId) throw new Error("useLearnFromUserActionInCurrentThread: no CopilotChatConfigurationProvider in scope. Wrap the call site in <CopilotChat>, <CopilotSidebar>, or <CopilotChatConfigurationProvider>, or use `useLearnFromUserAction()` and pass `threadId` explicitly.");
4976
+ return learnFromUserAction({
4977
+ ...input,
4978
+ threadId
4979
+ });
4980
+ }, [config?.threadId, learnFromUserAction]);
4981
+ }
4982
+
4814
4983
  //#endregion
4815
4984
  //#region src/v2/hooks/use-attachments.tsx
4816
4985
  /**
@@ -4969,6 +5138,153 @@ function useAttachments({ config }) {
4969
5138
  };
4970
5139
  }
4971
5140
 
5141
+ //#endregion
5142
+ //#region src/v2/hooks/use-learning-containers.tsx
5143
+ /** The default learning containers value. Matches the backend default. */
5144
+ const DEFAULT_CONTAINERS = ["project"];
5145
+ /**
5146
+ * Declaratively keeps a thread's learning containers in sync by emitting
5147
+ * `set_learning_containers` annotations via the CopilotKit runtime annotate
5148
+ * endpoint (`POST ${runtimeUrl}/annotate`).
5149
+ *
5150
+ * **Emit rules:**
5151
+ * - On mount with `["project"]` (the backend default) → does NOT emit.
5152
+ * Absence of an annotation equals the default, so the round-trip is skipped.
5153
+ * - On mount with any other value → emits immediately.
5154
+ * - On any subsequent content change (including a switch back to
5155
+ * `["project"]`) → emits (a deliberate switch is always recorded).
5156
+ * - On unmount or threadId change → emits a reset to `["project"]`
5157
+ * so the backend is left in a clean state for the next consumer.
5158
+ * Changing `learningContainers` within the same thread does NOT reset the
5159
+ * thread; only the new value is emitted.
5160
+ *
5161
+ * Content-equality is evaluated via `JSON.stringify` so a fresh array literal
5162
+ * with the same items does NOT trigger a redundant emit.
5163
+ *
5164
+ * If `runtimeUrl` is absent, all emits are silently skipped.
5165
+ *
5166
+ * @example
5167
+ * ```tsx
5168
+ * function ThreadPane({ threadId, userScope }: Props) {
5169
+ * useLearningContainers({
5170
+ * threadId,
5171
+ * learningContainers: [userScope],
5172
+ * });
5173
+ * // ...
5174
+ * }
5175
+ * ```
5176
+ */
5177
+ function useLearningContainers({ threadId, learningContainers }) {
5178
+ const { copilotkit } = useCopilotKit();
5179
+ /**
5180
+ * Tracks the last-synced container list so content-identical rerenders
5181
+ * (fresh array, same values) do not fire a redundant emit.
5182
+ * `null` = nothing synced yet (initial state or after a threadId reset).
5183
+ */
5184
+ const lastSyncedRef = (0, react.useRef)(null);
5185
+ /** Guards the missing-runtimeUrl warning so it fires at most once per hook instance. */
5186
+ const warnedMissingUrlRef = (0, react.useRef)(false);
5187
+ const runtimeUrlRef = (0, react.useRef)(copilotkit.runtimeUrl);
5188
+ const headersRef = (0, react.useRef)(copilotkit.headers ?? {});
5189
+ runtimeUrlRef.current = copilotkit.runtimeUrl;
5190
+ headersRef.current = copilotkit.headers ?? {};
5191
+ const key = JSON.stringify(learningContainers);
5192
+ const defaultKey = JSON.stringify(DEFAULT_CONTAINERS);
5193
+ (0, react.useEffect)(() => {
5194
+ const runtimeUrl = copilotkit.runtimeUrl;
5195
+ const headers = copilotkit.headers ?? {};
5196
+ /**
5197
+ * Fire-and-forget emit; errors must not surface in render.
5198
+ * Failures are logged as warnings so they are diagnosable without
5199
+ * propagating into the React render cycle.
5200
+ */
5201
+ const emit = (containers) => {
5202
+ if (!runtimeUrl) {
5203
+ if (!warnedMissingUrlRef.current) {
5204
+ warnedMissingUrlRef.current = true;
5205
+ console.warn("useLearningContainers: runtimeUrl not configured; learning-container sync disabled");
5206
+ }
5207
+ return;
5208
+ }
5209
+ recordAnnotation({
5210
+ runtimeUrl,
5211
+ headers,
5212
+ type: "set_learning_containers",
5213
+ payload: { containers },
5214
+ threadId
5215
+ }).catch((err) => {
5216
+ console.warn("useLearningContainers: failed to record set_learning_containers", err);
5217
+ });
5218
+ };
5219
+ if (lastSyncedRef.current === null) {
5220
+ if (key === defaultKey) {
5221
+ lastSyncedRef.current = learningContainers;
5222
+ return;
5223
+ }
5224
+ emit(learningContainers);
5225
+ lastSyncedRef.current = learningContainers;
5226
+ } else if (key !== JSON.stringify(lastSyncedRef.current)) {
5227
+ emit(learningContainers);
5228
+ lastSyncedRef.current = learningContainers;
5229
+ }
5230
+ }, [threadId, key]);
5231
+ (0, react.useEffect)(() => {
5232
+ const capturedThreadId = threadId;
5233
+ return () => {
5234
+ const capturedRuntimeUrl = runtimeUrlRef.current;
5235
+ const capturedHeaders = headersRef.current;
5236
+ if (capturedRuntimeUrl) recordAnnotation({
5237
+ runtimeUrl: capturedRuntimeUrl,
5238
+ headers: capturedHeaders,
5239
+ type: "set_learning_containers",
5240
+ payload: { containers: DEFAULT_CONTAINERS },
5241
+ threadId: capturedThreadId
5242
+ }).catch((err) => {
5243
+ console.warn("useLearningContainers: failed to record set_learning_containers", err);
5244
+ });
5245
+ lastSyncedRef.current = null;
5246
+ };
5247
+ }, [threadId]);
5248
+ }
5249
+
5250
+ //#endregion
5251
+ //#region src/v2/hooks/use-learning-containers-in-current-thread.tsx
5252
+ /**
5253
+ * Declaratively keeps the **current chat thread's** learning containers in
5254
+ * sync. The `threadId` is sourced from the surrounding
5255
+ * `<CopilotChatConfigurationProvider>` (the same provider `<CopilotChat>`,
5256
+ * `<CopilotSidebar>`, and friends set up), so callers in a chat-aware
5257
+ * subtree don't need to thread an id through manually.
5258
+ *
5259
+ * **Throws on render** when there is no chat-config provider in scope or
5260
+ * when the provider does not yet have an active `threadId`. Mount the hook
5261
+ * inside a subtree that is guaranteed to have a thread context.
5262
+ *
5263
+ * If you need to manage an explicit thread, use {@link useLearningContainers}
5264
+ * directly — two hooks, two crisp contracts, no mode confusion.
5265
+ *
5266
+ * @throws When no `CopilotChatConfigurationProvider` is in scope or when the
5267
+ * active `threadId` is absent/empty.
5268
+ *
5269
+ * @example
5270
+ * ```tsx
5271
+ * function ThreadPanel({ scope }: Props) {
5272
+ * useLearningContainersInCurrentThread({
5273
+ * learningContainers: [scope],
5274
+ * });
5275
+ * // ...
5276
+ * }
5277
+ * ```
5278
+ */
5279
+ function useLearningContainersInCurrentThread({ learningContainers }) {
5280
+ const threadId = useCopilotChatConfiguration()?.threadId;
5281
+ if (!threadId) throw new Error("useLearningContainersInCurrentThread must be used within a thread context (no active threadId). Wrap the component in <CopilotChat>, <CopilotSidebar>, or <CopilotChatConfigurationProvider>, or use `useLearningContainers()` and pass `threadId` explicitly.");
5282
+ useLearningContainers({
5283
+ threadId,
5284
+ learningContainers
5285
+ });
5286
+ }
5287
+
4972
5288
  //#endregion
4973
5289
  //#region src/v2/components/chat/CopilotChatToolCallsView.tsx
4974
5290
  function CopilotChatToolCallsView({ message, messages = [] }) {
@@ -5741,33 +6057,174 @@ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
5741
6057
  */
5742
6058
  const ScrollElementContext = react.default.createContext(null);
5743
6059
 
6060
+ //#endregion
6061
+ //#region src/v2/components/intelligence-indicator/IntelligenceIndicatorView.tsx
6062
+ /**
6063
+ * The presentational "CopilotKit Intelligence" face — the default
6064
+ * rendered by the {@link IntelligenceIndicator} brain and the default
6065
+ * value for the `intelligenceIndicator` slot.
6066
+ *
6067
+ * Single-element three-stage design:
6068
+ * 1. **In-progress.** Glassmorphism pill chrome around a 270° arc icon
6069
+ * and the label. The arc has a single continuous visible stroke
6070
+ * (one `stroke-dasharray` dash + one gap, summing to the path
6071
+ * length) and the whole SVG rotates — so the viewer sees one
6072
+ * C-shaped arc spinning around the visual center.
6073
+ * 2. **Icon morph (~250 ms).** On status flip the single icon path
6074
+ * interpolates from the arc to a checkmark via CSS `d:` while the
6075
+ * dashed stroke transitions to solid (filling in the gap that was
6076
+ * the spinner's open portion). The SVG rotation animation is
6077
+ * removed; the snap back to identity is masked by the simultaneous
6078
+ * shape change. Chrome and text stay at full opacity throughout.
6079
+ * 3. **Settle (~400 ms, starts at +250 ms).** Chrome (background,
6080
+ * border, shadow, backdrop-blur) fades to zero opacity. The label
6081
+ * and icon stroke color transitions from saturated purple to a
6082
+ * true-neutral gray at 0.8 alpha — no hue cast, reads as "settled
6083
+ * history metadata." The label simultaneously skews to ~10° (a
6084
+ * transform-based italic feel that interpolates smoothly with the
6085
+ * color, rather than the discrete `font-style: italic` snap that
6086
+ * would cause a layout pop). The label text stays put — only its
6087
+ * color and slant change — so there is no "bump" where the brand
6088
+ * text disappears and reappears.
6089
+ *
6090
+ * Hard sequence: stage 3 has a 250 ms transition-delay so it waits
6091
+ * for stage 2 to finish. Total settle time ~650 ms in production.
6092
+ *
6093
+ * Both shapes are 3-segment cubic Bézier paths with matched command
6094
+ * structure (one `M` plus three `C`s), which is what makes the d
6095
+ * morph interpolate as a continuous shape change rather than snapping.
6096
+ *
6097
+ * The label is identical in both states (default "CopilotKit
6098
+ * Intelligence"). The static check icon carries the "done" semantic;
6099
+ * the color + slant transition does the "settle" work without needing
6100
+ * any wording change.
6101
+ *
6102
+ * Customize via the `intelligenceIndicator` slot on `CopilotChat`:
6103
+ * a className string restyles the wrapper, a props object tweaks
6104
+ * the default (`{ label }`), and a component replaces it entirely
6105
+ * with full control over visuals and timing.
6106
+ */
6107
+ function IntelligenceIndicatorView({ message, status, label, className, ...rest }) {
6108
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6109
+ className: (0, tailwind_merge.twMerge)("cpk-intelligence-indicator", className),
6110
+ role: "status",
6111
+ "aria-live": "polite",
6112
+ "data-testid": `cpk-intelligence-indicator-${message.id}`,
6113
+ "data-status": status,
6114
+ title: label,
6115
+ ...rest,
6116
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6117
+ className: "cpk-intelligence-indicator__chrome",
6118
+ "aria-hidden": "true"
6119
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6120
+ className: "cpk-intelligence-indicator__content",
6121
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
6122
+ className: "cpk-intelligence-indicator__icon",
6123
+ viewBox: "0 0 24 24",
6124
+ width: "14",
6125
+ height: "14",
6126
+ "aria-hidden": "true",
6127
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { className: "cpk-intelligence-indicator__icon-path" })
6128
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6129
+ className: "cpk-intelligence-indicator__label",
6130
+ children: label
6131
+ })]
6132
+ })]
6133
+ });
6134
+ }
6135
+
5744
6136
  //#endregion
5745
6137
  //#region src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx
5746
6138
  /**
5747
6139
  * Grace window before showing the spinner. A matching tool call must
5748
6140
  * remain unresolved (no `tool`-role result message in `agent.messages`)
5749
- * for at least this long before the pill appears. This filters out
5750
- * history-replay flashes — during `connectAgent` replay, tool calls and
5751
- * their results arrive back-to-back in sub-millisecond bursts, so the
5752
- * timer is cancelled before it fires. Live runs cross the threshold
5753
- * easily because the tool actually has to execute.
6141
+ * for at least this long before the indicator transitions out of
6142
+ * `hidden`. This filters out history-replay flashes — during
6143
+ * `connectAgent` replay, tool calls and their results arrive
6144
+ * back-to-back in sub-millisecond bursts, so the timer is cancelled
6145
+ * before it fires. Live runs cross the threshold easily because the
6146
+ * tool actually has to execute.
5754
6147
  */
5755
6148
  const PENDING_THRESHOLD_MS = 100;
5756
- /** Hold the checkmark briefly before fading out. */
5757
- const CHECK_HOLD_MS = 800;
5758
6149
  /**
5759
- * Duration of the fade-out animation. Must match
5760
- * `cpk-intelligence-pill-fade-out` keyframes in `v2/styles/globals.css`.
6150
+ * Tool-name regex patterns that trigger the indicator. Matches any tool
6151
+ * name *containing* the Intelligence MCP server's canonical tool name, so
6152
+ * both the bare `copilotkit_knowledge_base_shell` and the namespaced
6153
+ * `mcp__<server>__copilotkit_knowledge_base_shell` form (emitted by
6154
+ * `@ag-ui/mcp-middleware`) light up the pill. If we add per-instance
6155
+ * customization later (e.g. a `CopilotKitProvider` prop or a runtime-info
6156
+ * field), this constant becomes the fallback.
5761
6157
  */
5762
- const FADE_OUT_ANIMATION_MS = 480;
6158
+ const DEFAULT_TOOL_PATTERNS = [/copilotkit_knowledge_base_shell/];
5763
6159
  /**
5764
- * Tool-name regex patterns that trigger the indicator. Currently
5765
- * hardcoded to the Intelligence MCP server's canonical tool name. If
5766
- * we add per-instance customization later (e.g. a `CopilotKitProvider`
5767
- * prop or a runtime-info field), this constant becomes the fallback.
6160
+ * Phase to start in when an indicator first mounts. A turn that is already
6161
+ * complete at mount jumps straight to `finished` no `hidden` flash, no
6162
+ * spinner blip — which is what makes scrolled-back / replayed history render
6163
+ * its indicators directly in the finished state.
6164
+ *
6165
+ * Pure and timing-free on purpose: the grace window ({@link
6166
+ * PENDING_THRESHOLD_MS}) only controls *when* the live transition is applied;
6167
+ * these functions decide *what* it resolves to, so the decision can be unit
6168
+ * tested deterministically without any timers.
5768
6169
  */
5769
- const DEFAULT_TOOL_PATTERNS = [/^copilotkit_knowledge_base_shell$/];
6170
+ function initialIndicatorPhase(turnComplete) {
6171
+ return turnComplete ? "finished" : "hidden";
6172
+ }
6173
+ /**
6174
+ * Phase the grace window resolves to once it elapses:
6175
+ * - completed turn → `finished` (replay-flash suppression: a tool whose
6176
+ * result lands within the window skips the spinner entirely),
6177
+ * - a still-pending matching tool call → `spinner`,
6178
+ * - otherwise stay `hidden` (the matching tool call hasn't landed yet).
6179
+ */
6180
+ function resolveGracePhase(turnComplete, hasPending) {
6181
+ if (turnComplete) return "finished";
6182
+ if (hasPending) return "spinner";
6183
+ return "hidden";
6184
+ }
5770
6185
  const isMatchingToolCallName = (name) => typeof name === "string" && DEFAULT_TOOL_PATTERNS.some((p) => p.test(name));
6186
+ const messageHasMatchingToolCall = (m) => {
6187
+ if (m.role !== "assistant") return false;
6188
+ return (Array.isArray(m.toolCalls) ? m.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name));
6189
+ };
6190
+ /**
6191
+ * Stable turn id for the messages that precede the first user message (a turn
6192
+ * with no opening user message of its own). Used as the React key so the
6193
+ * indicator for that turn never collides with a real user-message id.
6194
+ */
6195
+ const INTELLIGENCE_TURN_HEAD = "__cpk_turn_head__";
6196
+ /**
6197
+ * Map each Intelligence-using turn to its anchor message — the FIRST bash-using
6198
+ * assistant message of the turn — and a stable turn id (the id of the user
6199
+ * message that opened the turn, or {@link INTELLIGENCE_TURN_HEAD} for the
6200
+ * pre-first-user turn). Returns `Map<anchorMessageId, turnId>`.
6201
+ *
6202
+ * Anchoring to the FIRST (not last) bash-using message keeps the indicator
6203
+ * fixed in place for the whole turn: later bash steps don't reposition it, so
6204
+ * the spinner never abruptly jumps mid-turn (bug 1). `CopilotChatMessageView`
6205
+ * emits exactly one `IntelligenceIndicator` per entry, keyed by the turn id and
6206
+ * positioned at the anchor; the per-turn key also lets every past turn keep its
6207
+ * own indicator in scroll-back.
6208
+ */
6209
+ function getIntelligenceTurnAnchors(messages) {
6210
+ const anchors = /* @__PURE__ */ new Map();
6211
+ let turnId = INTELLIGENCE_TURN_HEAD;
6212
+ let anchorId = null;
6213
+ const commit = () => {
6214
+ if (anchorId !== null) anchors.set(anchorId, turnId);
6215
+ anchorId = null;
6216
+ };
6217
+ for (const m of messages) {
6218
+ if (m.role === "user") {
6219
+ commit();
6220
+ turnId = m.id;
6221
+ continue;
6222
+ }
6223
+ if (anchorId === null && messageHasMatchingToolCall(m)) anchorId = m.id;
6224
+ }
6225
+ commit();
6226
+ return anchors;
6227
+ }
5771
6228
  /**
5772
6229
  * "Tool-call-like" messages do NOT count as a real follow-up: tool
5773
6230
  * result messages, assistant messages that carry tool calls, and
@@ -5786,45 +6243,51 @@ const isToolCallLikeMessage = (m) => {
5786
6243
  return false;
5787
6244
  };
5788
6245
  /**
5789
- * The "Using CopilotKit Intelligence" pill. Auto-mounted by
5790
- * `CopilotChatMessageView` for every message slot when
5791
- * `copilotkit.intelligence` is configured callers do not register
5792
- * this themselves. Self-gates so only the canonical message renders a
5793
- * pill.
6246
+ * The "Using CopilotKit Intelligence" indicator brain. Auto-mounted by
6247
+ * `CopilotChatMessageView` once per Intelligence-using turn, at that
6248
+ * turn's anchor message and keyed by the turn id (see
6249
+ * {@link getIntelligenceTurnAnchors}). Callers do not register this
6250
+ * themselves. It owns the run subscription and the phase machine and
6251
+ * renders its swappable face via the `intelligenceIndicator` slot.
6252
+ *
6253
+ * Placement (which message anchors the turn) is decided by the view, so
6254
+ * this component does not self-gate its own placement; it only derives
6255
+ * in-progress/finished for the turn it was mounted on.
5794
6256
  *
5795
6257
  * Render gates (all must hold):
5796
6258
  * 1. `copilotkit.intelligence !== undefined`
5797
- * 2. The message is an assistant message with at least one tool call
5798
- * whose name matches {@link DEFAULT_TOOL_PATTERNS}
5799
- * 3. The message is the *latest* such matching-assistant message in
5800
- * `agent.messages` — tool-result messages and prose-only assistant
5801
- * messages don't invalidate the slot, so the pill stays
5802
- * continuously through a multi-step tool chain.
5803
- * 4. The phase machine is past `idle` (the pending-grace timer fired)
5804
- * and not yet `hidden`.
6259
+ * 2. The (anchor) message is an assistant message with at least one
6260
+ * tool call whose name matches {@link DEFAULT_TOOL_PATTERNS}.
6261
+ * 3. The phase machine is past `hidden`.
6262
+ *
6263
+ * Because the view keys each indicator by its turn id, the instance moves
6264
+ * with the anchor across a hand-off (no remount, no spinner restart), and
6265
+ * every prior Intelligence-using turn keeps its own persistent indicator
6266
+ * in chat history.
5805
6267
  *
5806
6268
  * Phase machine (per-instance, all timers local):
5807
- * - Starts in `idle` nothing rendered.
5808
- * - `idle spinner` once a matching tool call has been pending
6269
+ * - Starts in `hidden`, unless the message mounts onto an
6270
+ * already-completed turn (no pending work, agent stopped or a
6271
+ * real follow-up already present), in which case the lazy
6272
+ * `useState` initializer starts directly in `finished`. This is
6273
+ * what avoids a "hidden flash" on history replay.
6274
+ * - `hidden → spinner` once a matching tool call has been pending
5809
6275
  * (no `tool`-role result with a matching `toolCallId`) for
5810
6276
  * {@link PENDING_THRESHOLD_MS}. Replay flashes (tool call + result
5811
6277
  * in the same tick) never cross this threshold.
5812
- * - `spinnercheck` as soon as EITHER `agent.isRunning` flips
6278
+ * - `hiddenfinished` if after the grace window the turn is
6279
+ * already complete (no pending work AND
6280
+ * `sawRealFollowup || !agent.isRunning`). Handles very fast tools
6281
+ * whose result lands within the grace window.
6282
+ * - `spinner → finished` as soon as EITHER `agent.isRunning` flips
5813
6283
  * false OR a non-tool-call-like message appears later in
5814
- * `agent.messages` (i.e. the agent has produced a "real"
5815
- * follow-up — prose answer or a new user turn).
5816
- * - `check fading` after {@link CHECK_HOLD_MS}.
5817
- * - `fading hidden` after {@link FADE_OUT_ANIMATION_MS}.
5818
- *
5819
- * Once `hidden`, the phase is sticky — a finished pill never re-spawns
5820
- * on the same message. New runs mount fresh indicator instances on
5821
- * their own assistant messages.
5822
- *
5823
- * The "exactly one pill at a time" guarantee is structural: only one
5824
- * message satisfies the latest-matching-assistant gate at any moment.
6284
+ * `agent.messages` (i.e. the agent produced a "real" follow-up —
6285
+ * prose answer or a new user turn).
6286
+ * - `finished` is terminal: the indicator settles into its
6287
+ * persistent tag form and stays mounted.
5825
6288
  */
5826
6289
  function IntelligenceIndicator(props) {
5827
- const { message, agentId, label = "Using CopilotKit Intelligence" } = props;
6290
+ const { message, agentId, label = "CopilotKit Intelligence", intelligenceIndicator } = props;
5828
6291
  const { copilotkit } = useCopilotKit();
5829
6292
  const config = useCopilotChatConfiguration();
5830
6293
  const { agent } = useAgent({
@@ -5844,84 +6307,37 @@ function IntelligenceIndicator(props) {
5844
6307
  for (const m of agent.messages) if (m.role === "tool" && m.toolCallId) resolved.add(m.toolCallId);
5845
6308
  return matchingToolCallIds.some((id) => !resolved.has(id));
5846
6309
  }, [matchingToolCallIds, agent.messages]);
5847
- const sawRealFollowup = (0, react.useMemo)(() => {
6310
+ const turnComplete = (0, react.useMemo)(() => {
5848
6311
  const idx = agent.messages.findIndex((m) => m.id === message.id);
5849
6312
  if (idx < 0) return false;
5850
6313
  for (let i = idx + 1; i < agent.messages.length; i += 1) if (!isToolCallLikeMessage(agent.messages[i])) return true;
5851
6314
  return false;
5852
- }, [agent.messages, message.id]);
5853
- const [phase, setPhase] = (0, react.useState)("idle");
6315
+ }, [agent.messages, message.id]) || !agent.isRunning;
6316
+ const [phase, setPhase] = (0, react.useState)(() => initialIndicatorPhase(turnComplete));
5854
6317
  (0, react.useEffect)(() => {
5855
- if (phase !== "idle") return void 0;
5856
- if (!hasPending) return void 0;
5857
- const t = setTimeout(() => setPhase("spinner"), PENDING_THRESHOLD_MS);
6318
+ if (phase !== "hidden") return void 0;
6319
+ const t = setTimeout(() => {
6320
+ setPhase(resolveGracePhase(turnComplete, hasPending));
6321
+ }, PENDING_THRESHOLD_MS);
5858
6322
  return () => clearTimeout(t);
5859
- }, [phase, hasPending]);
5860
- (0, react.useEffect)(() => {
5861
- if (phase !== "spinner") return void 0;
5862
- if (!agent.isRunning || sawRealFollowup) setPhase("check");
5863
6323
  }, [
5864
6324
  phase,
5865
- agent.isRunning,
5866
- sawRealFollowup
6325
+ hasPending,
6326
+ turnComplete
5867
6327
  ]);
5868
6328
  (0, react.useEffect)(() => {
5869
- if (phase !== "check") return void 0;
5870
- const t = setTimeout(() => setPhase("fading"), CHECK_HOLD_MS);
5871
- return () => clearTimeout(t);
5872
- }, [phase]);
5873
- (0, react.useEffect)(() => {
5874
- if (phase !== "fading") return void 0;
5875
- const t = setTimeout(() => setPhase("hidden"), FADE_OUT_ANIMATION_MS);
5876
- return () => clearTimeout(t);
5877
- }, [phase]);
6329
+ if (phase !== "spinner") return void 0;
6330
+ if (turnComplete) setPhase("finished");
6331
+ }, [phase, turnComplete]);
5878
6332
  if (copilotkit.intelligence === void 0) return null;
5879
6333
  if (!config) return null;
5880
- if (phase === "idle" || phase === "hidden") return null;
6334
+ if (phase === "hidden") return null;
5881
6335
  if (message.role !== "assistant") return null;
5882
- if (!(Array.isArray(message.toolCalls) ? message.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) return null;
5883
- let latestMatchingAssistantId;
5884
- for (let i = agent.messages.length - 1; i >= 0; i -= 1) {
5885
- const m = agent.messages[i];
5886
- if (m.role !== "assistant") continue;
5887
- if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) {
5888
- latestMatchingAssistantId = m.id;
5889
- break;
5890
- }
5891
- }
5892
- if (latestMatchingAssistantId !== message.id) return null;
5893
- const showSpinner = phase === "spinner";
5894
- const isFading = phase === "fading";
5895
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5896
- className: "cpk-intelligence-pill" + (isFading ? " cpk-intelligence-pill--fading" : ""),
5897
- role: "status",
5898
- "aria-live": "polite",
5899
- "aria-hidden": isFading || void 0,
5900
- "data-testid": `cpk-intelligence-pill-${message.id}`,
5901
- title: label,
5902
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
5903
- className: "cpk-intelligence-pill__icon",
5904
- viewBox: "0 0 24 24",
5905
- width: "14",
5906
- height: "14",
5907
- "aria-hidden": "true",
5908
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
5909
- cx: "12",
5910
- cy: "12",
5911
- r: "9",
5912
- fill: "none",
5913
- strokeWidth: "2.5",
5914
- strokeLinecap: "round",
5915
- className: "cpk-intelligence-pill__ring" + (showSpinner ? "" : " cpk-intelligence-pill__ring--done")
5916
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
5917
- d: "M8 12.5l3 3 5-6",
5918
- fill: "none",
5919
- strokeWidth: "2.5",
5920
- strokeLinecap: "round",
5921
- strokeLinejoin: "round",
5922
- className: "cpk-intelligence-pill__check" + (showSpinner ? "" : " cpk-intelligence-pill__check--shown")
5923
- })]
5924
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })]
6336
+ if (!messageHasMatchingToolCall(message)) return null;
6337
+ return renderSlot(intelligenceIndicator, IntelligenceIndicatorView, {
6338
+ message,
6339
+ status: phase === "finished" ? "finished" : "in-progress",
6340
+ label
5925
6341
  });
5926
6342
  }
5927
6343
 
@@ -6074,7 +6490,7 @@ function deduplicateMessages(messages) {
6074
6490
  return [...acc.values()];
6075
6491
  }
6076
6492
  const VIRTUALIZE_THRESHOLD = 50;
6077
- function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, isRunning = false, children, className, ...props }) {
6493
+ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, isRunning = false, children, className, ...props }) {
6078
6494
  const renderCustomMessage = useRenderCustomMessages();
6079
6495
  const { renderActivityMessage } = useRenderActivityMessage();
6080
6496
  const { copilotkit } = useCopilotKit();
@@ -6132,6 +6548,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
6132
6548
  if (!shouldVirtualize || !deduplicatedMessages.length) return;
6133
6549
  virtualizer.scrollToIndex(deduplicatedMessages.length - 1, { align: "end" });
6134
6550
  }, [shouldVirtualize, firstMessageId]);
6551
+ const intelligenceTurnAnchors = (0, react.useMemo)(() => getIntelligenceTurnAnchors(deduplicatedMessages), [deduplicatedMessages]);
6135
6552
  const renderMessageBlock = (message) => {
6136
6553
  const elements = [];
6137
6554
  const stateSnapshot = getStateSnapshotForMessage(message.id);
@@ -6170,10 +6587,12 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
6170
6587
  renderCustomMessage,
6171
6588
  stateSnapshot
6172
6589
  }, `${message.id}-custom-after`));
6173
- if (copilotkit.intelligence !== void 0 && message.role === "assistant") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IntelligenceIndicator, {
6590
+ const intelligenceTurnId = intelligenceTurnAnchors.get(message.id);
6591
+ if (intelligenceTurnId !== void 0) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IntelligenceIndicator, {
6174
6592
  message,
6175
- agentId: config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID
6176
- }, `${message.id}-intelligence`));
6593
+ agentId: config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID,
6594
+ intelligenceIndicator
6595
+ }, `intelligence-${intelligenceTurnId}`));
6177
6596
  return elements.filter(Boolean);
6178
6597
  };
6179
6598
  const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
@@ -6610,7 +7029,7 @@ function DropOverlay() {
6610
7029
  })
6611
7030
  });
6612
7031
  }
6613
- function CopilotChatView({ messageView, input, scrollView, suggestionView, welcomeScreen, messages = [], autoScroll = true, isRunning = false, suggestions, suggestionLoadingIndexes, onSelectSuggestion, onSubmitMessage, onStop, inputMode, inputValue, onInputChange, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, attachments, onRemoveAttachment, onAddFile, dragOver, onDragOver, onDragLeave, onDrop, isConnecting = false, hasExplicitThreadId = false, disclaimer, children, className, ...props }) {
7032
+ function CopilotChatView({ messageView, input, scrollView, suggestionView, welcomeScreen, messages = [], autoScroll = true, isRunning = false, suggestions, suggestionLoadingIndexes, onSelectSuggestion, onSubmitMessage, onStop, inputMode, inputValue, onInputChange, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, attachments, onRemoveAttachment, onAddFile, dragOver, onDragOver, onDragLeave, onDrop, isConnecting = false, hasExplicitThreadId = false, disclaimer, intelligenceIndicator, children, className, ...props }) {
6614
7033
  const [inputContainerEl, setInputContainerEl] = (0, react.useState)(null);
6615
7034
  const [inputContainerHeight, setInputContainerHeight] = (0, react.useState)(0);
6616
7035
  const [isResizing, setIsResizing] = (0, react.useState)(false);
@@ -6647,7 +7066,8 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
6647
7066
  }, [inputContainerEl]);
6648
7067
  const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {
6649
7068
  messages,
6650
- isRunning
7069
+ isRunning,
7070
+ intelligenceIndicator
6651
7071
  });
6652
7072
  const BoundInput = renderSlot(input, CopilotChatInput_default, {
6653
7073
  onSubmitMessage,
@@ -7153,6 +7573,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7153
7573
  const [transcriptionError, setTranscriptionError] = (0, react.useState)(null);
7154
7574
  const [isTranscribing, setIsTranscribing] = (0, react.useState)(false);
7155
7575
  const { attachments: selectedAttachments, enabled: attachmentsEnabled, dragOver, fileInputRef, containerRef: chatContainerRef, handleFileUpload, handleDragOver, handleDragLeave, handleDrop, removeAttachment, consumeAttachments } = useAttachments({ config: attachmentsConfig });
7576
+ const selectedAttachmentsRef = (0, react.useRef)(selectedAttachments);
7577
+ (0, react.useEffect)(() => {
7578
+ selectedAttachmentsRef.current = selectedAttachments;
7579
+ }, [selectedAttachments]);
7156
7580
  const isTranscriptionEnabled = copilotkit.audioFileTranscriptionEnabled;
7157
7581
  const isMediaRecorderSupported = typeof window !== "undefined" && typeof MediaRecorder !== "undefined";
7158
7582
  const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
@@ -7188,9 +7612,25 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7188
7612
  resolvedAgentId,
7189
7613
  hasExplicitThreadId
7190
7614
  ]);
7615
+ const waitForActiveRunToSettle = (0, react.useCallback)(async () => {
7616
+ if (agent.isRunning && (0, _copilotkit_core.isRunCompletionAware)(agent) && agent.activeRunCompletionPromise) try {
7617
+ await agent.activeRunCompletionPromise;
7618
+ } catch (error) {
7619
+ console.error("CopilotChat: in-flight run rejected while queuing send", error);
7620
+ }
7621
+ }, [agent]);
7191
7622
  const onSubmitInput = (0, react.useCallback)(async (value) => {
7192
- if (selectedAttachments.some((a) => a.status === "uploading")) {
7193
- console.error("[CopilotKit] Cannot send while attachments are uploading");
7623
+ if (selectedAttachmentsRef.current.some((a) => a.status === "uploading")) {
7624
+ console.error("[CopilotKit] Cannot send while attachments are uploading (pre-await guard)");
7625
+ setTranscriptionError("Cannot send while attachments are uploading.");
7626
+ return;
7627
+ }
7628
+ setInputValue("");
7629
+ await waitForActiveRunToSettle();
7630
+ if (selectedAttachmentsRef.current.some((a) => a.status === "uploading")) {
7631
+ console.error("[CopilotKit] Cannot send while attachments are uploading (post-await re-check)");
7632
+ setTranscriptionError("Cannot send while attachments are uploading.");
7633
+ setInputValue(value);
7194
7634
  return;
7195
7635
  }
7196
7636
  const readyAttachments = consumeAttachments();
@@ -7218,7 +7658,6 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7218
7658
  role: "user",
7219
7659
  content: value
7220
7660
  });
7221
- setInputValue("");
7222
7661
  try {
7223
7662
  await copilotkit.runAgent({ agent });
7224
7663
  } catch (error) {
@@ -7226,10 +7665,11 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7226
7665
  }
7227
7666
  }, [
7228
7667
  agent,
7229
- selectedAttachments,
7230
- consumeAttachments
7668
+ consumeAttachments,
7669
+ waitForActiveRunToSettle
7231
7670
  ]);
7232
7671
  const handleSelectSuggestion = (0, react.useCallback)(async (suggestion) => {
7672
+ await waitForActiveRunToSettle();
7233
7673
  agent.addMessage({
7234
7674
  id: (0, _copilotkit_shared.randomUUID)(),
7235
7675
  role: "user",
@@ -7240,7 +7680,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7240
7680
  } catch (error) {
7241
7681
  console.error("CopilotChat: runAgent failed after selecting suggestion", error);
7242
7682
  }
7243
- }, [agent]);
7683
+ }, [agent, waitForActiveRunToSettle]);
7244
7684
  const stopCurrentRun = (0, react.useCallback)(() => {
7245
7685
  try {
7246
7686
  copilotkit.stopAgent({ agent });
@@ -10308,12 +10748,24 @@ Object.defineProperty(exports, 'DefaultOpenIcon', {
10308
10748
  return DefaultOpenIcon;
10309
10749
  }
10310
10750
  });
10751
+ Object.defineProperty(exports, 'INTELLIGENCE_TURN_HEAD', {
10752
+ enumerable: true,
10753
+ get: function () {
10754
+ return INTELLIGENCE_TURN_HEAD;
10755
+ }
10756
+ });
10311
10757
  Object.defineProperty(exports, 'IntelligenceIndicator', {
10312
10758
  enumerable: true,
10313
10759
  get: function () {
10314
10760
  return IntelligenceIndicator;
10315
10761
  }
10316
10762
  });
10763
+ Object.defineProperty(exports, 'IntelligenceIndicatorView', {
10764
+ enumerable: true,
10765
+ get: function () {
10766
+ return IntelligenceIndicatorView;
10767
+ }
10768
+ });
10317
10769
  Object.defineProperty(exports, 'MCPAppsActivityContentSchema', {
10318
10770
  enumerable: true,
10319
10771
  get: function () {
@@ -10386,6 +10838,12 @@ Object.defineProperty(exports, 'defineToolCallRenderer', {
10386
10838
  return defineToolCallRenderer;
10387
10839
  }
10388
10840
  });
10841
+ Object.defineProperty(exports, 'getIntelligenceTurnAnchors', {
10842
+ enumerable: true,
10843
+ get: function () {
10844
+ return getIntelligenceTurnAnchors;
10845
+ }
10846
+ });
10389
10847
  Object.defineProperty(exports, 'shouldShowDevConsole', {
10390
10848
  enumerable: true,
10391
10849
  get: function () {
@@ -10488,6 +10946,30 @@ Object.defineProperty(exports, 'useInterrupt', {
10488
10946
  return useInterrupt;
10489
10947
  }
10490
10948
  });
10949
+ Object.defineProperty(exports, 'useLearnFromUserAction', {
10950
+ enumerable: true,
10951
+ get: function () {
10952
+ return useLearnFromUserAction;
10953
+ }
10954
+ });
10955
+ Object.defineProperty(exports, 'useLearnFromUserActionInCurrentThread', {
10956
+ enumerable: true,
10957
+ get: function () {
10958
+ return useLearnFromUserActionInCurrentThread;
10959
+ }
10960
+ });
10961
+ Object.defineProperty(exports, 'useLearningContainers', {
10962
+ enumerable: true,
10963
+ get: function () {
10964
+ return useLearningContainers;
10965
+ }
10966
+ });
10967
+ Object.defineProperty(exports, 'useLearningContainersInCurrentThread', {
10968
+ enumerable: true,
10969
+ get: function () {
10970
+ return useLearningContainersInCurrentThread;
10971
+ }
10972
+ });
10491
10973
  Object.defineProperty(exports, 'useRenderActivityMessage', {
10492
10974
  enumerable: true,
10493
10975
  get: function () {
@@ -10542,4 +11024,4 @@ Object.defineProperty(exports, 'useToast', {
10542
11024
  return useToast;
10543
11025
  }
10544
11026
  });
10545
- //# sourceMappingURL=copilotkit-IQO0VDZb.cjs.map
11027
+ //# sourceMappingURL=copilotkit-LdQ8w20l.cjs.map