@copilotkit/react-core 1.59.3 → 1.59.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{copilotkit-DhONbYmz.cjs → copilotkit-CFfEVdV4.cjs} +933 -326
- package/dist/copilotkit-CFfEVdV4.cjs.map +1 -0
- package/dist/{copilotkit-D16eCFkt.d.cts → copilotkit-Ctvinul7.d.cts} +419 -59
- package/dist/copilotkit-Ctvinul7.d.cts.map +1 -0
- package/dist/{copilotkit-BRNy5UvX.mjs → copilotkit-DEGlMWM0.mjs} +891 -326
- package/dist/copilotkit-DEGlMWM0.mjs.map +1 -0
- package/dist/{copilotkit-CEJz6krE.d.mts → copilotkit-DqDT5RLa.d.mts} +419 -59
- package/dist/copilotkit-DqDT5RLa.d.mts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.umd.js +339 -202
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/index.cjs +8 -1
- package/dist/v2/index.css +1 -1
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/index.mjs +2 -2
- package/dist/v2/index.umd.js +897 -325
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +6 -6
- package/dist/copilotkit-BRNy5UvX.mjs.map +0 -1
- package/dist/copilotkit-CEJz6krE.d.mts.map +0 -1
- package/dist/copilotkit-D16eCFkt.d.cts.map +0 -1
- package/dist/copilotkit-DhONbYmz.cjs.map +0 -1
package/dist/v2/index.umd.js
CHANGED
|
@@ -220,9 +220,9 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
220
220
|
|
|
221
221
|
//#endregion
|
|
222
222
|
//#region src/v2/lib/utils.ts
|
|
223
|
-
const twMerge$
|
|
223
|
+
const twMerge$8 = (0, tailwind_merge.extendTailwindMerge)({ prefix: "cpk" });
|
|
224
224
|
function cn(...inputs) {
|
|
225
|
-
return twMerge$
|
|
225
|
+
return twMerge$8((0, clsx.clsx)(inputs));
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
//#endregion
|
|
@@ -2940,210 +2940,110 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2940
2940
|
};
|
|
2941
2941
|
|
|
2942
2942
|
//#endregion
|
|
2943
|
-
//#region src/v2/a2ui/
|
|
2943
|
+
//#region src/v2/a2ui/A2UIRecoveryStates.tsx
|
|
2944
2944
|
/**
|
|
2945
|
-
* The
|
|
2946
|
-
*
|
|
2947
|
-
|
|
2948
|
-
const A2UI_OPERATIONS_KEY = "a2ui_operations";
|
|
2949
|
-
let initialized = false;
|
|
2950
|
-
function ensureInitialized() {
|
|
2951
|
-
if (!initialized) {
|
|
2952
|
-
(0, _copilotkit_a2ui_renderer.initializeDefaultCatalog)();
|
|
2953
|
-
(0, _copilotkit_a2ui_renderer.injectStyles)();
|
|
2954
|
-
initialized = true;
|
|
2955
|
-
}
|
|
2956
|
-
}
|
|
2957
|
-
function createA2UIMessageRenderer(options) {
|
|
2958
|
-
const { theme, catalog, loadingComponent } = options;
|
|
2959
|
-
return {
|
|
2960
|
-
activityType: "a2ui-surface",
|
|
2961
|
-
content: zod.z.any(),
|
|
2962
|
-
render: ({ content, agent }) => {
|
|
2963
|
-
ensureInitialized();
|
|
2964
|
-
const [operations, setOperations] = (0, react.useState)([]);
|
|
2965
|
-
const { copilotkit } = useCopilotKit();
|
|
2966
|
-
const lastContentRef = (0, react.useRef)(null);
|
|
2967
|
-
(0, react.useEffect)(() => {
|
|
2968
|
-
if (content === lastContentRef.current) return;
|
|
2969
|
-
lastContentRef.current = content;
|
|
2970
|
-
const incoming = content?.[A2UI_OPERATIONS_KEY];
|
|
2971
|
-
if (!content || !Array.isArray(incoming)) {
|
|
2972
|
-
setOperations([]);
|
|
2973
|
-
return;
|
|
2974
|
-
}
|
|
2975
|
-
setOperations(incoming);
|
|
2976
|
-
}, [content]);
|
|
2977
|
-
const groupedOperations = (0, react.useMemo)(() => {
|
|
2978
|
-
const groups = /* @__PURE__ */ new Map();
|
|
2979
|
-
for (const operation of operations) {
|
|
2980
|
-
const surfaceId = getOperationSurfaceId(operation) ?? _copilotkit_a2ui_renderer.DEFAULT_SURFACE_ID;
|
|
2981
|
-
if (!groups.has(surfaceId)) groups.set(surfaceId, []);
|
|
2982
|
-
groups.get(surfaceId).push(operation);
|
|
2983
|
-
}
|
|
2984
|
-
return groups;
|
|
2985
|
-
}, [operations]);
|
|
2986
|
-
if (!groupedOperations.size) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(loadingComponent ?? DefaultA2UILoading, {});
|
|
2987
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2988
|
-
className: "cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6",
|
|
2989
|
-
children: Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReactSurfaceHost, {
|
|
2990
|
-
surfaceId,
|
|
2991
|
-
operations: ops,
|
|
2992
|
-
theme,
|
|
2993
|
-
agent,
|
|
2994
|
-
copilotkit,
|
|
2995
|
-
catalog
|
|
2996
|
-
}, surfaceId))
|
|
2997
|
-
});
|
|
2998
|
-
}
|
|
2999
|
-
};
|
|
3000
|
-
}
|
|
3001
|
-
/**
|
|
3002
|
-
* Renders a single A2UI surface using the React renderer.
|
|
3003
|
-
* Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
|
|
2945
|
+
* The pre-paint lifecycle fields the middleware stamps onto the `a2ui-surface`
|
|
2946
|
+
* activity content (alongside `a2ui_operations` on paint). `.passthrough()` keeps
|
|
2947
|
+
* `a2ui_operations` and any future fields intact.
|
|
3004
2948
|
*/
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
catalog,
|
|
3027
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SurfaceMessageProcessor, {
|
|
3028
|
-
surfaceId,
|
|
3029
|
-
operations
|
|
3030
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UISurfaceOrError, { surfaceId })]
|
|
3031
|
-
})
|
|
3032
|
-
});
|
|
2949
|
+
const A2UILifecycleFields = {
|
|
2950
|
+
status: zod.z.enum([
|
|
2951
|
+
"building",
|
|
2952
|
+
"retrying",
|
|
2953
|
+
"failed"
|
|
2954
|
+
]).optional(),
|
|
2955
|
+
attempt: zod.z.number().optional(),
|
|
2956
|
+
maxAttempts: zod.z.number().optional(),
|
|
2957
|
+
progressTokens: zod.z.number().optional(),
|
|
2958
|
+
error: zod.z.string().optional(),
|
|
2959
|
+
errors: zod.z.array(zod.z.any()).optional(),
|
|
2960
|
+
attempts: zod.z.array(zod.z.any()).optional(),
|
|
2961
|
+
debugExposure: zod.z.enum([
|
|
2962
|
+
"hidden",
|
|
2963
|
+
"collapsed",
|
|
2964
|
+
"verbose"
|
|
2965
|
+
]).optional()
|
|
2966
|
+
};
|
|
2967
|
+
/** Server-stamped debugExposure wins; else the client option; else "collapsed". */
|
|
2968
|
+
function resolveDebugExposure(content, optionDebugExposure) {
|
|
2969
|
+
return content?.debugExposure ?? optionDebugExposure;
|
|
3033
2970
|
}
|
|
3034
|
-
/**
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
const error = (0, _copilotkit_a2ui_renderer.useA2UIError)();
|
|
3040
|
-
if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3041
|
-
className: "cpk:rounded-lg cpk:border cpk:border-red-200 cpk:bg-red-50 cpk:p-3 cpk:text-sm cpk:text-red-700",
|
|
3042
|
-
children: ["A2UI render error: ", error]
|
|
3043
|
-
});
|
|
3044
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_copilotkit_a2ui_renderer.A2UIRenderer, {
|
|
3045
|
-
surfaceId,
|
|
3046
|
-
className: "cpk:flex cpk:flex-1"
|
|
2971
|
+
/** building: the generic skeleton + optional live token count. */
|
|
2972
|
+
function A2UIBuildingState({ content }) {
|
|
2973
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIGeneratingSkeleton, {
|
|
2974
|
+
label: "Building interface",
|
|
2975
|
+
tokens: typeof content?.progressTokens === "number" ? content.progressTokens : void 0
|
|
3047
2976
|
});
|
|
3048
2977
|
}
|
|
3049
2978
|
/**
|
|
3050
|
-
*
|
|
3051
|
-
*
|
|
2979
|
+
* retrying: stays the generic skeleton through fast/transient retries; only once
|
|
2980
|
+
* the retry is perceptible (after `showAfterMs`, or once `attempt` crosses
|
|
2981
|
+
* `showAfterAttempts`) does the sub-label reveal "Retrying generation… (N/M)".
|
|
3052
2982
|
*/
|
|
3053
|
-
function
|
|
3054
|
-
const
|
|
3055
|
-
const
|
|
2983
|
+
function A2UIRetryingState({ content, showAfterMs, showAfterAttempts, debugExposure }) {
|
|
2984
|
+
const attempt = typeof content?.attempt === "number" ? content.attempt : void 0;
|
|
2985
|
+
const maxAttempts = typeof content?.maxAttempts === "number" ? content.maxAttempts : void 0;
|
|
2986
|
+
const immediate = attempt !== void 0 && attempt >= showAfterAttempts;
|
|
2987
|
+
const [revealed, setRevealed] = (0, react.useState)(immediate);
|
|
3056
2988
|
(0, react.useEffect)(() => {
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
2989
|
+
if (immediate) {
|
|
2990
|
+
setRevealed(true);
|
|
2991
|
+
return;
|
|
2992
|
+
}
|
|
2993
|
+
const timer = setTimeout(() => setRevealed(true), showAfterMs);
|
|
2994
|
+
return () => clearTimeout(timer);
|
|
2995
|
+
}, [immediate, showAfterMs]);
|
|
2996
|
+
const tokens = typeof content?.progressTokens === "number" ? content.progressTokens : void 0;
|
|
2997
|
+
if (!revealed) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIGeneratingSkeleton, {
|
|
2998
|
+
label: "Building interface",
|
|
2999
|
+
tokens
|
|
3000
|
+
});
|
|
3001
|
+
const label = attempt !== void 0 && maxAttempts !== void 0 ? `Retrying generation… (${attempt}/${maxAttempts} attempts)` : "Retrying generation…";
|
|
3002
|
+
const errors = Array.isArray(content?.errors) ? content.errors : [];
|
|
3003
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIGeneratingSkeleton, {
|
|
3004
|
+
label,
|
|
3005
|
+
tokens,
|
|
3006
|
+
children: debugExposure !== "hidden" && errors.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIDebugDetails, {
|
|
3007
|
+
label: "validation issues",
|
|
3008
|
+
open: debugExposure === "verbose",
|
|
3009
|
+
payload: {
|
|
3010
|
+
attempt: content?.attempt,
|
|
3011
|
+
errors
|
|
3012
|
+
}
|
|
3013
|
+
})
|
|
3014
|
+
});
|
|
3068
3015
|
}
|
|
3069
|
-
/**
|
|
3070
|
-
|
|
3071
|
-
* Displays an animated shimmer skeleton.
|
|
3072
|
-
*/
|
|
3073
|
-
function DefaultA2UILoading() {
|
|
3016
|
+
/** failed: a clean hard-failure card that replaces the skeleton in place. */
|
|
3017
|
+
function A2UIRecoveryFailure({ content, debugExposure }) {
|
|
3074
3018
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3075
|
-
className: "cpk:
|
|
3076
|
-
style: { minHeight: 120 },
|
|
3019
|
+
className: "cpk:rounded-lg cpk:border cpk:border-amber-200 cpk:bg-amber-50 cpk:p-3 cpk:text-sm cpk:text-amber-800",
|
|
3077
3020
|
children: [
|
|
3078
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
3079
|
-
className: "cpk:
|
|
3080
|
-
children:
|
|
3081
|
-
className: "cpk:h-3 cpk:w-3 cpk:rounded-full cpk:bg-gray-200",
|
|
3082
|
-
style: { animation: "cpk-a2ui-pulse 1.5s ease-in-out infinite" }
|
|
3083
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3084
|
-
className: "cpk:text-xs cpk:font-medium cpk:text-gray-400",
|
|
3085
|
-
children: "Generating UI..."
|
|
3086
|
-
})]
|
|
3021
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3022
|
+
className: "cpk:font-medium",
|
|
3023
|
+
children: "Couldn't generate the UI"
|
|
3087
3024
|
}),
|
|
3088
3025
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3089
|
-
className: "cpk:
|
|
3090
|
-
children:
|
|
3091
|
-
.8,
|
|
3092
|
-
.6,
|
|
3093
|
-
.4
|
|
3094
|
-
].map((width, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3095
|
-
className: "cpk:h-3 cpk:rounded cpk:bg-gray-200/70",
|
|
3096
|
-
style: {
|
|
3097
|
-
width: `${width * 100}%`,
|
|
3098
|
-
animation: `cpk-a2ui-pulse 1.5s ease-in-out ${i * .15}s infinite`
|
|
3099
|
-
}
|
|
3100
|
-
}, i))
|
|
3026
|
+
className: "cpk:mt-1 cpk:text-xs cpk:text-amber-700",
|
|
3027
|
+
children: "Something went wrong rendering this. You can keep chatting and try again."
|
|
3101
3028
|
}),
|
|
3102
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3029
|
+
debugExposure !== "hidden" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIDebugDetails, {
|
|
3030
|
+
label: "developer details",
|
|
3031
|
+
open: debugExposure === "verbose",
|
|
3032
|
+
payload: {
|
|
3033
|
+
error: content?.error,
|
|
3034
|
+
attempts: content?.attempts
|
|
3035
|
+
}
|
|
3036
|
+
})
|
|
3108
3037
|
]
|
|
3109
3038
|
});
|
|
3110
3039
|
}
|
|
3111
|
-
function getOperationSurfaceId(operation) {
|
|
3112
|
-
if (!operation || typeof operation !== "object") return null;
|
|
3113
|
-
if (typeof operation.surfaceId === "string") return operation.surfaceId;
|
|
3114
|
-
return operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
|
|
3115
|
-
}
|
|
3116
|
-
|
|
3117
|
-
//#endregion
|
|
3118
|
-
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
3119
|
-
/**
|
|
3120
|
-
* Tool name used by the dynamic A2UI generation secondary LLM.
|
|
3121
|
-
* This renderer is auto-registered when A2UI is enabled.
|
|
3122
|
-
*/
|
|
3123
|
-
const RENDER_A2UI_TOOL_NAME = "render_a2ui";
|
|
3124
3040
|
/**
|
|
3125
|
-
*
|
|
3126
|
-
*
|
|
3127
|
-
*
|
|
3128
|
-
* Registered automatically when A2UI is enabled. Users can override by
|
|
3129
|
-
* providing their own `useRenderTool({ name: "render_a2ui", ... })`.
|
|
3041
|
+
* Animated wireframe skeleton with a label, an optional live token count, and an
|
|
3042
|
+
* optional debug-detail slot below it. Pure CSS animation (no data dependency).
|
|
3043
|
+
* The `tokens` count drives a progressive reveal of skeleton rows.
|
|
3130
3044
|
*/
|
|
3131
|
-
function
|
|
3132
|
-
const
|
|
3133
|
-
time: 0,
|
|
3134
|
-
tokens: 0
|
|
3135
|
-
});
|
|
3136
|
-
const now = Date.now();
|
|
3137
|
-
let { tokens } = lastRef.current;
|
|
3138
|
-
if (now - lastRef.current.time > 200) {
|
|
3139
|
-
const chars = JSON.stringify(parameters ?? {}).length;
|
|
3140
|
-
tokens = Math.round(chars / 4);
|
|
3141
|
-
lastRef.current = {
|
|
3142
|
-
time: now,
|
|
3143
|
-
tokens
|
|
3144
|
-
};
|
|
3145
|
-
}
|
|
3146
|
-
const phase = tokens < 50 ? 0 : tokens < 200 ? 1 : tokens < 400 ? 2 : 3;
|
|
3045
|
+
function A2UIGeneratingSkeleton({ label, tokens, children }) {
|
|
3046
|
+
const phase = tokens == null ? 3 : tokens < 50 ? 0 : tokens < 200 ? 1 : tokens < 400 ? 2 : 3;
|
|
3147
3047
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3148
3048
|
style: {
|
|
3149
3049
|
margin: "12px 0",
|
|
@@ -3351,8 +3251,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3351
3251
|
color: "#a1a1aa",
|
|
3352
3252
|
letterSpacing: "0.025em"
|
|
3353
3253
|
},
|
|
3354
|
-
children:
|
|
3355
|
-
}), tokens > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3254
|
+
children: label
|
|
3255
|
+
}), typeof tokens === "number" && tokens > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3356
3256
|
style: {
|
|
3357
3257
|
fontSize: 11,
|
|
3358
3258
|
color: "#d4d4d8",
|
|
@@ -3365,6 +3265,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3365
3265
|
]
|
|
3366
3266
|
})]
|
|
3367
3267
|
}),
|
|
3268
|
+
children,
|
|
3368
3269
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `
|
|
3369
3270
|
@keyframes cpk-a2ui-fade {
|
|
3370
3271
|
0%, 100% { opacity: 1; }
|
|
@@ -3378,6 +3279,20 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3378
3279
|
]
|
|
3379
3280
|
});
|
|
3380
3281
|
}
|
|
3282
|
+
function A2UIDebugDetails({ label, open, payload }) {
|
|
3283
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
3284
|
+
open,
|
|
3285
|
+
className: "cpk:mt-2 cpk:text-xs",
|
|
3286
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
|
|
3287
|
+
className: "cpk:cursor-pointer cpk:text-gray-500",
|
|
3288
|
+
children: label
|
|
3289
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
3290
|
+
className: "cpk:mt-1 cpk:overflow-auto cpk:rounded cpk:bg-gray-100 cpk:p-2 cpk:text-gray-700",
|
|
3291
|
+
style: { fontSize: 11 },
|
|
3292
|
+
children: JSON.stringify(payload, null, 2)
|
|
3293
|
+
})]
|
|
3294
|
+
});
|
|
3295
|
+
}
|
|
3381
3296
|
function Dot() {
|
|
3382
3297
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
3383
3298
|
width: 7,
|
|
@@ -3413,13 +3328,242 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3413
3328
|
children
|
|
3414
3329
|
});
|
|
3415
3330
|
}
|
|
3331
|
+
|
|
3332
|
+
//#endregion
|
|
3333
|
+
//#region src/v2/a2ui/A2UIMessageRenderer.tsx
|
|
3334
|
+
/**
|
|
3335
|
+
* The container key used to wrap A2UI operations for explicit detection.
|
|
3336
|
+
* Must match A2UI_OPERATIONS_KEY in @ag-ui/a2ui-middleware and copilotkit.a2ui (Python).
|
|
3337
|
+
*/
|
|
3338
|
+
const A2UI_OPERATIONS_KEY = "a2ui_operations";
|
|
3339
|
+
let initialized = false;
|
|
3340
|
+
function ensureInitialized() {
|
|
3341
|
+
if (!initialized) {
|
|
3342
|
+
(0, _copilotkit_a2ui_renderer.initializeDefaultCatalog)();
|
|
3343
|
+
(0, _copilotkit_a2ui_renderer.injectStyles)();
|
|
3344
|
+
initialized = true;
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
/**
|
|
3348
|
+
* The `a2ui-surface` activity carries the WHOLE generative-UI lifecycle on one
|
|
3349
|
+
* stable messageId (OSS-162): pre-paint `status` ("building" | "retrying" |
|
|
3350
|
+
* "failed") with recovery detail, then `a2ui_operations` on paint. The states
|
|
3351
|
+
* swap in place, so the painted surface replaces the skeleton with no extra
|
|
3352
|
+
* coordination. `.passthrough()` preserves operations + any future fields.
|
|
3353
|
+
*/
|
|
3354
|
+
const A2UISurfaceContentSchema = zod.z.object({
|
|
3355
|
+
a2ui_operations: zod.z.array(zod.z.any()).optional(),
|
|
3356
|
+
...A2UILifecycleFields
|
|
3357
|
+
}).passthrough();
|
|
3358
|
+
function createA2UIMessageRenderer(options) {
|
|
3359
|
+
const { theme, catalog, loadingComponent, recovery } = options;
|
|
3360
|
+
const showAfterMs = recovery?.showAfterMs ?? 2e3;
|
|
3361
|
+
const showAfterAttempts = recovery?.showAfterAttempts ?? 2;
|
|
3362
|
+
const optionDebugExposure = recovery?.debugExposure ?? "collapsed";
|
|
3363
|
+
return {
|
|
3364
|
+
activityType: "a2ui-surface",
|
|
3365
|
+
content: A2UISurfaceContentSchema,
|
|
3366
|
+
render: ({ content, agent }) => {
|
|
3367
|
+
ensureInitialized();
|
|
3368
|
+
const [operations, setOperations] = (0, react.useState)([]);
|
|
3369
|
+
const { copilotkit } = useCopilotKit();
|
|
3370
|
+
const lastContentRef = (0, react.useRef)(null);
|
|
3371
|
+
(0, react.useEffect)(() => {
|
|
3372
|
+
if (content === lastContentRef.current) return;
|
|
3373
|
+
lastContentRef.current = content;
|
|
3374
|
+
const incoming = content?.[A2UI_OPERATIONS_KEY];
|
|
3375
|
+
if (!content || !Array.isArray(incoming)) {
|
|
3376
|
+
setOperations([]);
|
|
3377
|
+
return;
|
|
3378
|
+
}
|
|
3379
|
+
setOperations(incoming);
|
|
3380
|
+
}, [content]);
|
|
3381
|
+
const groupedOperations = (0, react.useMemo)(() => {
|
|
3382
|
+
const groups = /* @__PURE__ */ new Map();
|
|
3383
|
+
for (const operation of operations) {
|
|
3384
|
+
const surfaceId = getOperationSurfaceId(operation) ?? _copilotkit_a2ui_renderer.DEFAULT_SURFACE_ID;
|
|
3385
|
+
if (!groups.has(surfaceId)) groups.set(surfaceId, []);
|
|
3386
|
+
groups.get(surfaceId).push(operation);
|
|
3387
|
+
}
|
|
3388
|
+
return groups;
|
|
3389
|
+
}, [operations]);
|
|
3390
|
+
const hasOps = groupedOperations.size > 0;
|
|
3391
|
+
const renderLifecycle = (c) => {
|
|
3392
|
+
const status = c?.status;
|
|
3393
|
+
const debugExposure = resolveDebugExposure(c, optionDebugExposure);
|
|
3394
|
+
if (status === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIRecoveryFailure, {
|
|
3395
|
+
content: c,
|
|
3396
|
+
debugExposure
|
|
3397
|
+
});
|
|
3398
|
+
if (status === "retrying") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIRetryingState, {
|
|
3399
|
+
content: c,
|
|
3400
|
+
showAfterMs,
|
|
3401
|
+
showAfterAttempts,
|
|
3402
|
+
debugExposure
|
|
3403
|
+
});
|
|
3404
|
+
if (loadingComponent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(loadingComponent, {});
|
|
3405
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuildingState, { content: c });
|
|
3406
|
+
};
|
|
3407
|
+
const lastLoaderContentRef = (0, react.useRef)(null);
|
|
3408
|
+
if (!(Array.isArray(content?.[A2UI_OPERATIONS_KEY]) && content[A2UI_OPERATIONS_KEY].length > 0)) lastLoaderContentRef.current = content;
|
|
3409
|
+
const [surfaceReady, setSurfaceReady] = (0, react.useState)(false);
|
|
3410
|
+
const readyRef = (0, react.useRef)(false);
|
|
3411
|
+
const markSurfaceReady = (0, react.useCallback)(() => {
|
|
3412
|
+
if (readyRef.current) return;
|
|
3413
|
+
readyRef.current = true;
|
|
3414
|
+
requestAnimationFrame(() => setSurfaceReady(true));
|
|
3415
|
+
}, []);
|
|
3416
|
+
(0, react.useEffect)(() => {
|
|
3417
|
+
if (!hasOps) {
|
|
3418
|
+
setSurfaceReady(false);
|
|
3419
|
+
readyRef.current = false;
|
|
3420
|
+
return;
|
|
3421
|
+
}
|
|
3422
|
+
const t = setTimeout(() => setSurfaceReady(true), 8e3);
|
|
3423
|
+
return () => clearTimeout(t);
|
|
3424
|
+
}, [hasOps]);
|
|
3425
|
+
if (!hasOps) return renderLifecycle(content);
|
|
3426
|
+
const surfaces = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3427
|
+
className: "cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6",
|
|
3428
|
+
children: Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReactSurfaceHost, {
|
|
3429
|
+
surfaceId,
|
|
3430
|
+
operations: ops,
|
|
3431
|
+
theme,
|
|
3432
|
+
agent,
|
|
3433
|
+
copilotkit,
|
|
3434
|
+
catalog,
|
|
3435
|
+
onReady: markSurfaceReady
|
|
3436
|
+
}, surfaceId))
|
|
3437
|
+
});
|
|
3438
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3439
|
+
style: { position: "relative" },
|
|
3440
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3441
|
+
"aria-hidden": !surfaceReady,
|
|
3442
|
+
style: surfaceReady ? void 0 : {
|
|
3443
|
+
position: "absolute",
|
|
3444
|
+
inset: 0,
|
|
3445
|
+
opacity: 0,
|
|
3446
|
+
pointerEvents: "none"
|
|
3447
|
+
},
|
|
3448
|
+
children: surfaces
|
|
3449
|
+
}), !surfaceReady && renderLifecycle(lastLoaderContentRef.current ?? content)]
|
|
3450
|
+
});
|
|
3451
|
+
}
|
|
3452
|
+
};
|
|
3453
|
+
}
|
|
3454
|
+
/**
|
|
3455
|
+
* Renders a single A2UI surface using the React renderer.
|
|
3456
|
+
* Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
|
|
3457
|
+
*/
|
|
3458
|
+
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit, catalog, onReady }) {
|
|
3459
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3460
|
+
className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
|
|
3461
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_copilotkit_a2ui_renderer.A2UIProvider, {
|
|
3462
|
+
onAction: (0, react.useCallback)(async (message) => {
|
|
3463
|
+
if (!agent) return;
|
|
3464
|
+
message.userAction;
|
|
3465
|
+
try {
|
|
3466
|
+
copilotkit.setProperties({
|
|
3467
|
+
...copilotkit.properties,
|
|
3468
|
+
a2uiAction: message
|
|
3469
|
+
});
|
|
3470
|
+
await copilotkit.runAgent({ agent });
|
|
3471
|
+
} finally {
|
|
3472
|
+
if (copilotkit.properties) {
|
|
3473
|
+
const { a2uiAction, ...rest } = copilotkit.properties;
|
|
3474
|
+
copilotkit.setProperties(rest);
|
|
3475
|
+
}
|
|
3476
|
+
}
|
|
3477
|
+
}, [agent, copilotkit]),
|
|
3478
|
+
theme,
|
|
3479
|
+
catalog,
|
|
3480
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SurfaceMessageProcessor, {
|
|
3481
|
+
surfaceId,
|
|
3482
|
+
operations,
|
|
3483
|
+
onReady
|
|
3484
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UISurfaceOrError, { surfaceId })]
|
|
3485
|
+
})
|
|
3486
|
+
});
|
|
3487
|
+
}
|
|
3488
|
+
/**
|
|
3489
|
+
* Renders the A2UI surface, or an error message if processing failed.
|
|
3490
|
+
* Must be a child of A2UIProvider to access the error state.
|
|
3491
|
+
*/
|
|
3492
|
+
function A2UISurfaceOrError({ surfaceId }) {
|
|
3493
|
+
const error = (0, _copilotkit_a2ui_renderer.useA2UIError)();
|
|
3494
|
+
if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3495
|
+
className: "cpk:rounded-lg cpk:border cpk:border-red-200 cpk:bg-red-50 cpk:p-3 cpk:text-sm cpk:text-red-700",
|
|
3496
|
+
children: ["A2UI render error: ", error]
|
|
3497
|
+
});
|
|
3498
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_copilotkit_a2ui_renderer.A2UIRenderer, {
|
|
3499
|
+
surfaceId,
|
|
3500
|
+
className: "cpk:flex cpk:flex-1"
|
|
3501
|
+
});
|
|
3502
|
+
}
|
|
3503
|
+
/**
|
|
3504
|
+
* Processes A2UI operations into the provider's message processor.
|
|
3505
|
+
* Must be a child of A2UIProvider to access the actions context.
|
|
3506
|
+
*/
|
|
3507
|
+
function SurfaceMessageProcessor({ surfaceId, operations, onReady }) {
|
|
3508
|
+
const { processMessages, getSurface } = (0, _copilotkit_a2ui_renderer.useA2UIActions)();
|
|
3509
|
+
const lastHashRef = (0, react.useRef)("");
|
|
3510
|
+
(0, react.useEffect)(() => {
|
|
3511
|
+
const hash = JSON.stringify(operations);
|
|
3512
|
+
if (hash === lastHashRef.current) return;
|
|
3513
|
+
lastHashRef.current = hash;
|
|
3514
|
+
processMessages(getSurface(surfaceId) ? operations.filter((op) => !op?.createSurface) : operations);
|
|
3515
|
+
if (onReady && surfaceHasRenderableContent(operations)) onReady();
|
|
3516
|
+
}, [
|
|
3517
|
+
processMessages,
|
|
3518
|
+
getSurface,
|
|
3519
|
+
surfaceId,
|
|
3520
|
+
operations,
|
|
3521
|
+
onReady
|
|
3522
|
+
]);
|
|
3523
|
+
return null;
|
|
3524
|
+
}
|
|
3416
3525
|
/**
|
|
3417
|
-
*
|
|
3418
|
-
* `
|
|
3526
|
+
* Whether the surface's operations are enough to paint a visible card yet.
|
|
3527
|
+
* A data-bound surface references its data via `path` and renders nothing until
|
|
3528
|
+
* the data model has ≥1 value; a static surface (no path refs) paints from its
|
|
3529
|
+
* components alone. Used to time the loader→surface cross-over to actual content
|
|
3530
|
+
* arrival rather than a fixed delay. (OSS-162)
|
|
3531
|
+
*/
|
|
3532
|
+
function surfaceHasRenderableContent(operations) {
|
|
3533
|
+
const componentOps = operations.filter((o) => o?.updateComponents);
|
|
3534
|
+
if (!componentOps.length) return false;
|
|
3535
|
+
if (!JSON.stringify(componentOps).includes("\"path\"")) return true;
|
|
3536
|
+
return operations.some((o) => {
|
|
3537
|
+
const v = o?.updateDataModel?.value;
|
|
3538
|
+
if (!v || typeof v !== "object") return false;
|
|
3539
|
+
return Object.values(v).some((x) => Array.isArray(x) ? x.length > 0 : x !== null && x !== void 0 && x !== "");
|
|
3540
|
+
});
|
|
3541
|
+
}
|
|
3542
|
+
function getOperationSurfaceId(operation) {
|
|
3543
|
+
if (!operation || typeof operation !== "object") return null;
|
|
3544
|
+
if (typeof operation.surfaceId === "string") return operation.surfaceId;
|
|
3545
|
+
return operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
|
|
3546
|
+
}
|
|
3547
|
+
|
|
3548
|
+
//#endregion
|
|
3549
|
+
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
3550
|
+
/**
|
|
3551
|
+
* Tool name used by the dynamic A2UI generation secondary LLM.
|
|
3552
|
+
*/
|
|
3553
|
+
const RENDER_A2UI_TOOL_NAME = "render_a2ui";
|
|
3554
|
+
/**
|
|
3555
|
+
* Registers a no-op renderer for the `render_a2ui` tool call so its raw streamed
|
|
3556
|
+
* args are never surfaced in the transcript.
|
|
3419
3557
|
*
|
|
3420
|
-
*
|
|
3421
|
-
*
|
|
3422
|
-
*
|
|
3558
|
+
* The generation skeleton / retry / failure UX is NO LONGER owned here (OSS-162):
|
|
3559
|
+
* the A2UI middleware drives the whole lifecycle on the `a2ui-surface` activity
|
|
3560
|
+
* (one stable messageId, building → retrying → failed → painted), rendered in
|
|
3561
|
+
* place by `createA2UIMessageRenderer`. Owning a skeleton per tool call caused a
|
|
3562
|
+
* duplicate skeleton on retries / multi-call generations and a skeleton that
|
|
3563
|
+
* lingered after the surface painted — both fixed by retiring it here.
|
|
3564
|
+
*
|
|
3565
|
+
* Users can still override with their own `useRenderTool({ name: "render_a2ui" })`
|
|
3566
|
+
* (hook-based entries take priority over this prop-based registration).
|
|
3423
3567
|
*/
|
|
3424
3568
|
function A2UIBuiltInToolCallRenderer() {
|
|
3425
3569
|
const { copilotkit } = useCopilotKit();
|
|
@@ -3427,15 +3571,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3427
3571
|
const renderer = defineToolCallRenderer({
|
|
3428
3572
|
name: RENDER_A2UI_TOOL_NAME,
|
|
3429
3573
|
args: zod.z.any(),
|
|
3430
|
-
render: (
|
|
3431
|
-
if (status === "complete") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {});
|
|
3432
|
-
const params = parameters;
|
|
3433
|
-
const items = params?.items;
|
|
3434
|
-
if (Array.isArray(items) && items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {});
|
|
3435
|
-
const components = params?.components;
|
|
3436
|
-
if (Array.isArray(components) && components.length > 2) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {});
|
|
3437
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIProgressIndicator, { parameters });
|
|
3438
|
-
}
|
|
3574
|
+
render: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {})
|
|
3439
3575
|
});
|
|
3440
3576
|
const existing = copilotkit._renderToolCalls ?? [];
|
|
3441
3577
|
copilotkit.setRenderToolCalls([...existing.filter((rc) => rc.name !== RENDER_A2UI_TOOL_NAME), renderer]);
|
|
@@ -3572,7 +3708,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3572
3708
|
if (runtimeA2UIEnabled) renderers.unshift(createA2UIMessageRenderer({
|
|
3573
3709
|
theme: a2ui?.theme ?? _copilotkit_a2ui_renderer.viewerTheme,
|
|
3574
3710
|
catalog: a2ui?.catalog,
|
|
3575
|
-
loadingComponent: a2ui?.loadingComponent
|
|
3711
|
+
loadingComponent: a2ui?.loadingComponent,
|
|
3712
|
+
recovery: a2ui?.recovery
|
|
3576
3713
|
}));
|
|
3577
3714
|
return renderers;
|
|
3578
3715
|
}, [
|
|
@@ -4797,6 +4934,175 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4797
4934
|
};
|
|
4798
4935
|
}
|
|
4799
4936
|
|
|
4937
|
+
//#endregion
|
|
4938
|
+
//#region src/v2/lib/record-annotation.ts
|
|
4939
|
+
/**
|
|
4940
|
+
* Low-level function that posts an arbitrary annotation to the CopilotKit
|
|
4941
|
+
* runtime's general annotation endpoint (`POST /annotate`).
|
|
4942
|
+
*
|
|
4943
|
+
* This is the single transport entry point for all annotation types. Higher-
|
|
4944
|
+
* level hooks (e.g. `useLearnFromUserAction`) build the `type`/`payload` pair
|
|
4945
|
+
* for their specific annotation shape and delegate the HTTP call here.
|
|
4946
|
+
*
|
|
4947
|
+
* The function uses the same transport as `useLearnFromUserAction`:
|
|
4948
|
+
* - `runtimeUrl` from `copilotkit.runtimeUrl` (BFF proxies to the platform)
|
|
4949
|
+
* - `headers` from `copilotkit.headers` (customer auth forwarded to BFF)
|
|
4950
|
+
* - `clientEventId` auto-generated via `randomUUID()` when omitted
|
|
4951
|
+
* - `userId` is resolved server-side by the runtime; the client never sends it
|
|
4952
|
+
* - Errors propagate to the caller (fire-and-propagate, not fire-and-forget)
|
|
4953
|
+
*
|
|
4954
|
+
* @param args - Transport dependencies plus annotation fields.
|
|
4955
|
+
* @returns The platform result containing the annotation row `id` and a
|
|
4956
|
+
* `duplicate` flag.
|
|
4957
|
+
* @throws When the network request fails or the runtime returns a non-2xx
|
|
4958
|
+
* status. Callers that want fire-and-forget behavior should `.catch`
|
|
4959
|
+
* at the call site.
|
|
4960
|
+
*/
|
|
4961
|
+
async function recordAnnotation(args) {
|
|
4962
|
+
const { runtimeUrl, headers, type, payload, threadId, occurredAt } = args;
|
|
4963
|
+
const body = {
|
|
4964
|
+
type,
|
|
4965
|
+
threadId,
|
|
4966
|
+
clientEventId: args.clientEventId ?? (0, _copilotkit_shared.randomUUID)(),
|
|
4967
|
+
...payload !== void 0 ? { payload } : {},
|
|
4968
|
+
...occurredAt !== void 0 ? { occurredAt } : {}
|
|
4969
|
+
};
|
|
4970
|
+
const response = await fetch(`${runtimeUrl}/annotate`, {
|
|
4971
|
+
method: "POST",
|
|
4972
|
+
headers: {
|
|
4973
|
+
"Content-Type": "application/json",
|
|
4974
|
+
...headers
|
|
4975
|
+
},
|
|
4976
|
+
body: JSON.stringify(body)
|
|
4977
|
+
});
|
|
4978
|
+
if (!response.ok) {
|
|
4979
|
+
const text = await response.text().catch(() => "");
|
|
4980
|
+
throw new Error(`recordAnnotation: request failed (${response.status})${text ? `: ${text}` : ""}`);
|
|
4981
|
+
}
|
|
4982
|
+
const text = await response.text();
|
|
4983
|
+
if (!text) throw new Error(`recordAnnotation: runtime ${runtimeUrl}/annotate returned ${response.status} with an empty body`);
|
|
4984
|
+
try {
|
|
4985
|
+
return JSON.parse(text);
|
|
4986
|
+
} catch {
|
|
4987
|
+
throw new Error(`recordAnnotation: runtime ${runtimeUrl}/annotate returned a non-JSON body (status ${response.status})`);
|
|
4988
|
+
}
|
|
4989
|
+
}
|
|
4990
|
+
|
|
4991
|
+
//#endregion
|
|
4992
|
+
//#region src/v2/hooks/use-learn-from-user-action.tsx
|
|
4993
|
+
/**
|
|
4994
|
+
* Record a user UI interaction in the Intelligence platform's user-actions
|
|
4995
|
+
* stream. The platform's auto-curated knowledge base agent reads these
|
|
4996
|
+
* (alongside finished agent runs) and writes free-form Obsidian-flavored
|
|
4997
|
+
* markdown to `/project`, where any agent in the same project can later
|
|
4998
|
+
* read it via the `copilotkit_knowledge_base_shell` MCP tool.
|
|
4999
|
+
*
|
|
5000
|
+
* The hook returns a stable function. Calling it issues a request to the
|
|
5001
|
+
* customer's CopilotKit runtime (`POST ${runtimeUrl}/annotate`), which
|
|
5002
|
+
* resolves the Intel user from the BFF's auth and forwards to the
|
|
5003
|
+
* platform — the Intel API key never reaches the browser.
|
|
5004
|
+
*
|
|
5005
|
+
* If `clientEventId` is omitted `recordAnnotation` generates a UUID per call,
|
|
5006
|
+
* so a naive double-call (e.g. React 18 strict-mode double-mount, or a retry
|
|
5007
|
+
* after a network blip on a fresh Promise) is naturally safe. Supply your
|
|
5008
|
+
* own key when a single semantic event must remain idempotent across
|
|
5009
|
+
* multiple `learnFromUserAction(...)` calls.
|
|
5010
|
+
*
|
|
5011
|
+
* @example
|
|
5012
|
+
* ```tsx
|
|
5013
|
+
* import { useLearnFromUserAction } from "@copilotkit/react-core";
|
|
5014
|
+
*
|
|
5015
|
+
* function SettingsPage({ threadId }) {
|
|
5016
|
+
* const learnFromUserAction = useLearnFromUserAction();
|
|
5017
|
+
*
|
|
5018
|
+
* const onRename = (oldName: string, newName: string) => {
|
|
5019
|
+
* void learnFromUserAction({
|
|
5020
|
+
* threadId,
|
|
5021
|
+
* title: "Renamed project",
|
|
5022
|
+
* data: { previous: { name: oldName }, next: { name: newName } },
|
|
5023
|
+
* });
|
|
5024
|
+
* };
|
|
5025
|
+
* }
|
|
5026
|
+
* ```
|
|
5027
|
+
*/
|
|
5028
|
+
function useLearnFromUserAction() {
|
|
5029
|
+
const { copilotkit } = useCopilotKit();
|
|
5030
|
+
return (0, react.useCallback)(async (input) => {
|
|
5031
|
+
const runtimeUrl = copilotkit.runtimeUrl;
|
|
5032
|
+
if (!runtimeUrl) throw new Error("useLearnFromUserAction: runtimeUrl is not configured. Set it on <CopilotKitProvider runtimeUrl=...>.");
|
|
5033
|
+
const payload = {
|
|
5034
|
+
...input.title !== void 0 ? { title: input.title } : {},
|
|
5035
|
+
...input.description !== void 0 ? { description: input.description } : {},
|
|
5036
|
+
...input.data !== void 0 ? { data: input.data } : {}
|
|
5037
|
+
};
|
|
5038
|
+
return recordAnnotation({
|
|
5039
|
+
runtimeUrl,
|
|
5040
|
+
headers: copilotkit.headers ?? {},
|
|
5041
|
+
type: "user_action",
|
|
5042
|
+
payload: Object.keys(payload).length > 0 ? payload : void 0,
|
|
5043
|
+
threadId: input.threadId,
|
|
5044
|
+
clientEventId: input.clientEventId,
|
|
5045
|
+
occurredAt: input.occurredAt
|
|
5046
|
+
});
|
|
5047
|
+
}, [copilotkit]);
|
|
5048
|
+
}
|
|
5049
|
+
|
|
5050
|
+
//#endregion
|
|
5051
|
+
//#region src/v2/hooks/use-learn-from-user-action-in-current-thread.tsx
|
|
5052
|
+
/**
|
|
5053
|
+
* Record a user UI interaction against the **current chat's** thread. The
|
|
5054
|
+
* `threadId` is sourced from the surrounding
|
|
5055
|
+
* `<CopilotChatConfigurationProvider>` (the same provider `<CopilotChat>`,
|
|
5056
|
+
* `<CopilotSidebar>`, and friends set up), so callers in a chat-aware
|
|
5057
|
+
* subtree don't need to thread an id through manually.
|
|
5058
|
+
*
|
|
5059
|
+
* Throws on **call** (not on mount) when there is no chat-config provider
|
|
5060
|
+
* in scope — matches the "throw on call when runtimeUrl is missing"
|
|
5061
|
+
* behavior of {@link useLearnFromUserAction}. Mounting the hook in a branch
|
|
5062
|
+
* that never fires is harmless.
|
|
5063
|
+
*
|
|
5064
|
+
* The recorder does NOT accept a `threadId` override. If you need to
|
|
5065
|
+
* record against an explicit thread, use {@link useLearnFromUserAction}
|
|
5066
|
+
* directly — two hooks, two crisp contracts, no mode confusion.
|
|
5067
|
+
*
|
|
5068
|
+
* This hook always uses `config.threadId`, regardless of whether the
|
|
5069
|
+
* surrounding chat config minted it internally or received one from
|
|
5070
|
+
* the caller. Auto-minted threads simply mean the action lands under
|
|
5071
|
+
* a thread the platform never saw — the writer agent still distills
|
|
5072
|
+
* user-action-only threads (it does not require the thread to exist
|
|
5073
|
+
* in `cpki.threads`), so the loop keeps learning.
|
|
5074
|
+
*
|
|
5075
|
+
* @example
|
|
5076
|
+
* ```tsx
|
|
5077
|
+
* import { useLearnFromUserActionInCurrentThread } from "@copilotkit/react-core";
|
|
5078
|
+
*
|
|
5079
|
+
* function SettingsPanel() {
|
|
5080
|
+
* const learnFromUserAction = useLearnFromUserActionInCurrentThread();
|
|
5081
|
+
*
|
|
5082
|
+
* const onRename = (oldName: string, newName: string) => {
|
|
5083
|
+
* void learnFromUserAction({
|
|
5084
|
+
* title: "Renamed project",
|
|
5085
|
+
* data: { previous: { name: oldName }, next: { name: newName } },
|
|
5086
|
+
* });
|
|
5087
|
+
* };
|
|
5088
|
+
*
|
|
5089
|
+
* // ...
|
|
5090
|
+
* }
|
|
5091
|
+
* ```
|
|
5092
|
+
*/
|
|
5093
|
+
function useLearnFromUserActionInCurrentThread() {
|
|
5094
|
+
const config = useCopilotChatConfiguration();
|
|
5095
|
+
const learnFromUserAction = useLearnFromUserAction();
|
|
5096
|
+
return (0, react.useCallback)(async (input) => {
|
|
5097
|
+
const threadId = config?.threadId;
|
|
5098
|
+
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.");
|
|
5099
|
+
return learnFromUserAction({
|
|
5100
|
+
...input,
|
|
5101
|
+
threadId
|
|
5102
|
+
});
|
|
5103
|
+
}, [config?.threadId, learnFromUserAction]);
|
|
5104
|
+
}
|
|
5105
|
+
|
|
4800
5106
|
//#endregion
|
|
4801
5107
|
//#region src/v2/hooks/use-attachments.tsx
|
|
4802
5108
|
/**
|
|
@@ -4955,6 +5261,153 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4955
5261
|
};
|
|
4956
5262
|
}
|
|
4957
5263
|
|
|
5264
|
+
//#endregion
|
|
5265
|
+
//#region src/v2/hooks/use-learning-containers.tsx
|
|
5266
|
+
/** The default learning containers value. Matches the backend default. */
|
|
5267
|
+
const DEFAULT_CONTAINERS = ["project"];
|
|
5268
|
+
/**
|
|
5269
|
+
* Declaratively keeps a thread's learning containers in sync by emitting
|
|
5270
|
+
* `set_learning_containers` annotations via the CopilotKit runtime annotate
|
|
5271
|
+
* endpoint (`POST ${runtimeUrl}/annotate`).
|
|
5272
|
+
*
|
|
5273
|
+
* **Emit rules:**
|
|
5274
|
+
* - On mount with `["project"]` (the backend default) → does NOT emit.
|
|
5275
|
+
* Absence of an annotation equals the default, so the round-trip is skipped.
|
|
5276
|
+
* - On mount with any other value → emits immediately.
|
|
5277
|
+
* - On any subsequent content change (including a switch back to
|
|
5278
|
+
* `["project"]`) → emits (a deliberate switch is always recorded).
|
|
5279
|
+
* - On unmount or threadId change → emits a reset to `["project"]`
|
|
5280
|
+
* so the backend is left in a clean state for the next consumer.
|
|
5281
|
+
* Changing `learningContainers` within the same thread does NOT reset the
|
|
5282
|
+
* thread; only the new value is emitted.
|
|
5283
|
+
*
|
|
5284
|
+
* Content-equality is evaluated via `JSON.stringify` so a fresh array literal
|
|
5285
|
+
* with the same items does NOT trigger a redundant emit.
|
|
5286
|
+
*
|
|
5287
|
+
* If `runtimeUrl` is absent, all emits are silently skipped.
|
|
5288
|
+
*
|
|
5289
|
+
* @example
|
|
5290
|
+
* ```tsx
|
|
5291
|
+
* function ThreadPane({ threadId, userScope }: Props) {
|
|
5292
|
+
* useLearningContainers({
|
|
5293
|
+
* threadId,
|
|
5294
|
+
* learningContainers: [userScope],
|
|
5295
|
+
* });
|
|
5296
|
+
* // ...
|
|
5297
|
+
* }
|
|
5298
|
+
* ```
|
|
5299
|
+
*/
|
|
5300
|
+
function useLearningContainers({ threadId, learningContainers }) {
|
|
5301
|
+
const { copilotkit } = useCopilotKit();
|
|
5302
|
+
/**
|
|
5303
|
+
* Tracks the last-synced container list so content-identical rerenders
|
|
5304
|
+
* (fresh array, same values) do not fire a redundant emit.
|
|
5305
|
+
* `null` = nothing synced yet (initial state or after a threadId reset).
|
|
5306
|
+
*/
|
|
5307
|
+
const lastSyncedRef = (0, react.useRef)(null);
|
|
5308
|
+
/** Guards the missing-runtimeUrl warning so it fires at most once per hook instance. */
|
|
5309
|
+
const warnedMissingUrlRef = (0, react.useRef)(false);
|
|
5310
|
+
const runtimeUrlRef = (0, react.useRef)(copilotkit.runtimeUrl);
|
|
5311
|
+
const headersRef = (0, react.useRef)(copilotkit.headers ?? {});
|
|
5312
|
+
runtimeUrlRef.current = copilotkit.runtimeUrl;
|
|
5313
|
+
headersRef.current = copilotkit.headers ?? {};
|
|
5314
|
+
const key = JSON.stringify(learningContainers);
|
|
5315
|
+
const defaultKey = JSON.stringify(DEFAULT_CONTAINERS);
|
|
5316
|
+
(0, react.useEffect)(() => {
|
|
5317
|
+
const runtimeUrl = copilotkit.runtimeUrl;
|
|
5318
|
+
const headers = copilotkit.headers ?? {};
|
|
5319
|
+
/**
|
|
5320
|
+
* Fire-and-forget emit; errors must not surface in render.
|
|
5321
|
+
* Failures are logged as warnings so they are diagnosable without
|
|
5322
|
+
* propagating into the React render cycle.
|
|
5323
|
+
*/
|
|
5324
|
+
const emit = (containers) => {
|
|
5325
|
+
if (!runtimeUrl) {
|
|
5326
|
+
if (!warnedMissingUrlRef.current) {
|
|
5327
|
+
warnedMissingUrlRef.current = true;
|
|
5328
|
+
console.warn("useLearningContainers: runtimeUrl not configured; learning-container sync disabled");
|
|
5329
|
+
}
|
|
5330
|
+
return;
|
|
5331
|
+
}
|
|
5332
|
+
recordAnnotation({
|
|
5333
|
+
runtimeUrl,
|
|
5334
|
+
headers,
|
|
5335
|
+
type: "set_learning_containers",
|
|
5336
|
+
payload: { containers },
|
|
5337
|
+
threadId
|
|
5338
|
+
}).catch((err) => {
|
|
5339
|
+
console.warn("useLearningContainers: failed to record set_learning_containers", err);
|
|
5340
|
+
});
|
|
5341
|
+
};
|
|
5342
|
+
if (lastSyncedRef.current === null) {
|
|
5343
|
+
if (key === defaultKey) {
|
|
5344
|
+
lastSyncedRef.current = learningContainers;
|
|
5345
|
+
return;
|
|
5346
|
+
}
|
|
5347
|
+
emit(learningContainers);
|
|
5348
|
+
lastSyncedRef.current = learningContainers;
|
|
5349
|
+
} else if (key !== JSON.stringify(lastSyncedRef.current)) {
|
|
5350
|
+
emit(learningContainers);
|
|
5351
|
+
lastSyncedRef.current = learningContainers;
|
|
5352
|
+
}
|
|
5353
|
+
}, [threadId, key]);
|
|
5354
|
+
(0, react.useEffect)(() => {
|
|
5355
|
+
const capturedThreadId = threadId;
|
|
5356
|
+
return () => {
|
|
5357
|
+
const capturedRuntimeUrl = runtimeUrlRef.current;
|
|
5358
|
+
const capturedHeaders = headersRef.current;
|
|
5359
|
+
if (capturedRuntimeUrl) recordAnnotation({
|
|
5360
|
+
runtimeUrl: capturedRuntimeUrl,
|
|
5361
|
+
headers: capturedHeaders,
|
|
5362
|
+
type: "set_learning_containers",
|
|
5363
|
+
payload: { containers: DEFAULT_CONTAINERS },
|
|
5364
|
+
threadId: capturedThreadId
|
|
5365
|
+
}).catch((err) => {
|
|
5366
|
+
console.warn("useLearningContainers: failed to record set_learning_containers", err);
|
|
5367
|
+
});
|
|
5368
|
+
lastSyncedRef.current = null;
|
|
5369
|
+
};
|
|
5370
|
+
}, [threadId]);
|
|
5371
|
+
}
|
|
5372
|
+
|
|
5373
|
+
//#endregion
|
|
5374
|
+
//#region src/v2/hooks/use-learning-containers-in-current-thread.tsx
|
|
5375
|
+
/**
|
|
5376
|
+
* Declaratively keeps the **current chat thread's** learning containers in
|
|
5377
|
+
* sync. The `threadId` is sourced from the surrounding
|
|
5378
|
+
* `<CopilotChatConfigurationProvider>` (the same provider `<CopilotChat>`,
|
|
5379
|
+
* `<CopilotSidebar>`, and friends set up), so callers in a chat-aware
|
|
5380
|
+
* subtree don't need to thread an id through manually.
|
|
5381
|
+
*
|
|
5382
|
+
* **Throws on render** when there is no chat-config provider in scope or
|
|
5383
|
+
* when the provider does not yet have an active `threadId`. Mount the hook
|
|
5384
|
+
* inside a subtree that is guaranteed to have a thread context.
|
|
5385
|
+
*
|
|
5386
|
+
* If you need to manage an explicit thread, use {@link useLearningContainers}
|
|
5387
|
+
* directly — two hooks, two crisp contracts, no mode confusion.
|
|
5388
|
+
*
|
|
5389
|
+
* @throws When no `CopilotChatConfigurationProvider` is in scope or when the
|
|
5390
|
+
* active `threadId` is absent/empty.
|
|
5391
|
+
*
|
|
5392
|
+
* @example
|
|
5393
|
+
* ```tsx
|
|
5394
|
+
* function ThreadPanel({ scope }: Props) {
|
|
5395
|
+
* useLearningContainersInCurrentThread({
|
|
5396
|
+
* learningContainers: [scope],
|
|
5397
|
+
* });
|
|
5398
|
+
* // ...
|
|
5399
|
+
* }
|
|
5400
|
+
* ```
|
|
5401
|
+
*/
|
|
5402
|
+
function useLearningContainersInCurrentThread({ learningContainers }) {
|
|
5403
|
+
const threadId = useCopilotChatConfiguration()?.threadId;
|
|
5404
|
+
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.");
|
|
5405
|
+
useLearningContainers({
|
|
5406
|
+
threadId,
|
|
5407
|
+
learningContainers
|
|
5408
|
+
});
|
|
5409
|
+
}
|
|
5410
|
+
|
|
4958
5411
|
//#endregion
|
|
4959
5412
|
//#region src/v2/components/chat/CopilotChatToolCallsView.tsx
|
|
4960
5413
|
function CopilotChatToolCallsView({ message, messages = [] }) {
|
|
@@ -5727,33 +6180,174 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
5727
6180
|
*/
|
|
5728
6181
|
const ScrollElementContext = react.default.createContext(null);
|
|
5729
6182
|
|
|
6183
|
+
//#endregion
|
|
6184
|
+
//#region src/v2/components/intelligence-indicator/IntelligenceIndicatorView.tsx
|
|
6185
|
+
/**
|
|
6186
|
+
* The presentational "CopilotKit Intelligence" face — the default
|
|
6187
|
+
* rendered by the {@link IntelligenceIndicator} brain and the default
|
|
6188
|
+
* value for the `intelligenceIndicator` slot.
|
|
6189
|
+
*
|
|
6190
|
+
* Single-element three-stage design:
|
|
6191
|
+
* 1. **In-progress.** Glassmorphism pill chrome around a 270° arc icon
|
|
6192
|
+
* and the label. The arc has a single continuous visible stroke
|
|
6193
|
+
* (one `stroke-dasharray` dash + one gap, summing to the path
|
|
6194
|
+
* length) and the whole SVG rotates — so the viewer sees one
|
|
6195
|
+
* C-shaped arc spinning around the visual center.
|
|
6196
|
+
* 2. **Icon morph (~250 ms).** On status flip the single icon path
|
|
6197
|
+
* interpolates from the arc to a checkmark via CSS `d:` while the
|
|
6198
|
+
* dashed stroke transitions to solid (filling in the gap that was
|
|
6199
|
+
* the spinner's open portion). The SVG rotation animation is
|
|
6200
|
+
* removed; the snap back to identity is masked by the simultaneous
|
|
6201
|
+
* shape change. Chrome and text stay at full opacity throughout.
|
|
6202
|
+
* 3. **Settle (~400 ms, starts at +250 ms).** Chrome (background,
|
|
6203
|
+
* border, shadow, backdrop-blur) fades to zero opacity. The label
|
|
6204
|
+
* and icon stroke color transitions from saturated purple to a
|
|
6205
|
+
* true-neutral gray at 0.8 alpha — no hue cast, reads as "settled
|
|
6206
|
+
* history metadata." The label simultaneously skews to ~10° (a
|
|
6207
|
+
* transform-based italic feel that interpolates smoothly with the
|
|
6208
|
+
* color, rather than the discrete `font-style: italic` snap that
|
|
6209
|
+
* would cause a layout pop). The label text stays put — only its
|
|
6210
|
+
* color and slant change — so there is no "bump" where the brand
|
|
6211
|
+
* text disappears and reappears.
|
|
6212
|
+
*
|
|
6213
|
+
* Hard sequence: stage 3 has a 250 ms transition-delay so it waits
|
|
6214
|
+
* for stage 2 to finish. Total settle time ~650 ms in production.
|
|
6215
|
+
*
|
|
6216
|
+
* Both shapes are 3-segment cubic Bézier paths with matched command
|
|
6217
|
+
* structure (one `M` plus three `C`s), which is what makes the d
|
|
6218
|
+
* morph interpolate as a continuous shape change rather than snapping.
|
|
6219
|
+
*
|
|
6220
|
+
* The label is identical in both states (default "CopilotKit
|
|
6221
|
+
* Intelligence"). The static check icon carries the "done" semantic;
|
|
6222
|
+
* the color + slant transition does the "settle" work without needing
|
|
6223
|
+
* any wording change.
|
|
6224
|
+
*
|
|
6225
|
+
* Customize via the `intelligenceIndicator` slot on `CopilotChat`:
|
|
6226
|
+
* a className string restyles the wrapper, a props object tweaks
|
|
6227
|
+
* the default (`{ label }`), and a component replaces it entirely
|
|
6228
|
+
* with full control over visuals and timing.
|
|
6229
|
+
*/
|
|
6230
|
+
function IntelligenceIndicatorView({ message, status, label, className, ...rest }) {
|
|
6231
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6232
|
+
className: (0, tailwind_merge.twMerge)("cpk-intelligence-indicator", className),
|
|
6233
|
+
role: "status",
|
|
6234
|
+
"aria-live": "polite",
|
|
6235
|
+
"data-testid": `cpk-intelligence-indicator-${message.id}`,
|
|
6236
|
+
"data-status": status,
|
|
6237
|
+
title: label,
|
|
6238
|
+
...rest,
|
|
6239
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6240
|
+
className: "cpk-intelligence-indicator__chrome",
|
|
6241
|
+
"aria-hidden": "true"
|
|
6242
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6243
|
+
className: "cpk-intelligence-indicator__content",
|
|
6244
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
6245
|
+
className: "cpk-intelligence-indicator__icon",
|
|
6246
|
+
viewBox: "0 0 24 24",
|
|
6247
|
+
width: "14",
|
|
6248
|
+
height: "14",
|
|
6249
|
+
"aria-hidden": "true",
|
|
6250
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { className: "cpk-intelligence-indicator__icon-path" })
|
|
6251
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6252
|
+
className: "cpk-intelligence-indicator__label",
|
|
6253
|
+
children: label
|
|
6254
|
+
})]
|
|
6255
|
+
})]
|
|
6256
|
+
});
|
|
6257
|
+
}
|
|
6258
|
+
|
|
5730
6259
|
//#endregion
|
|
5731
6260
|
//#region src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx
|
|
5732
6261
|
/**
|
|
5733
6262
|
* Grace window before showing the spinner. A matching tool call must
|
|
5734
6263
|
* remain unresolved (no `tool`-role result message in `agent.messages`)
|
|
5735
|
-
* for at least this long before the
|
|
5736
|
-
* history-replay flashes — during
|
|
5737
|
-
*
|
|
5738
|
-
*
|
|
5739
|
-
*
|
|
6264
|
+
* for at least this long before the indicator transitions out of
|
|
6265
|
+
* `hidden`. This filters out history-replay flashes — during
|
|
6266
|
+
* `connectAgent` replay, tool calls and their results arrive
|
|
6267
|
+
* back-to-back in sub-millisecond bursts, so the timer is cancelled
|
|
6268
|
+
* before it fires. Live runs cross the threshold easily because the
|
|
6269
|
+
* tool actually has to execute.
|
|
5740
6270
|
*/
|
|
5741
6271
|
const PENDING_THRESHOLD_MS = 100;
|
|
5742
|
-
/** Hold the checkmark briefly before fading out. */
|
|
5743
|
-
const CHECK_HOLD_MS = 800;
|
|
5744
6272
|
/**
|
|
5745
|
-
*
|
|
5746
|
-
*
|
|
6273
|
+
* Tool-name regex patterns that trigger the indicator. Matches any tool
|
|
6274
|
+
* name *containing* the Intelligence MCP server's canonical tool name, so
|
|
6275
|
+
* both the bare `copilotkit_knowledge_base_shell` and the namespaced
|
|
6276
|
+
* `mcp__<server>__copilotkit_knowledge_base_shell` form (emitted by
|
|
6277
|
+
* `@ag-ui/mcp-middleware`) light up the pill. If we add per-instance
|
|
6278
|
+
* customization later (e.g. a `CopilotKitProvider` prop or a runtime-info
|
|
6279
|
+
* field), this constant becomes the fallback.
|
|
5747
6280
|
*/
|
|
5748
|
-
const
|
|
6281
|
+
const DEFAULT_TOOL_PATTERNS = [/copilotkit_knowledge_base_shell/];
|
|
5749
6282
|
/**
|
|
5750
|
-
*
|
|
5751
|
-
*
|
|
5752
|
-
*
|
|
5753
|
-
*
|
|
6283
|
+
* Phase to start in when an indicator first mounts. A turn that is already
|
|
6284
|
+
* complete at mount jumps straight to `finished` — no `hidden` flash, no
|
|
6285
|
+
* spinner blip — which is what makes scrolled-back / replayed history render
|
|
6286
|
+
* its indicators directly in the finished state.
|
|
6287
|
+
*
|
|
6288
|
+
* Pure and timing-free on purpose: the grace window ({@link
|
|
6289
|
+
* PENDING_THRESHOLD_MS}) only controls *when* the live transition is applied;
|
|
6290
|
+
* these functions decide *what* it resolves to, so the decision can be unit
|
|
6291
|
+
* tested deterministically without any timers.
|
|
5754
6292
|
*/
|
|
5755
|
-
|
|
6293
|
+
function initialIndicatorPhase(turnComplete) {
|
|
6294
|
+
return turnComplete ? "finished" : "hidden";
|
|
6295
|
+
}
|
|
6296
|
+
/**
|
|
6297
|
+
* Phase the grace window resolves to once it elapses:
|
|
6298
|
+
* - completed turn → `finished` (replay-flash suppression: a tool whose
|
|
6299
|
+
* result lands within the window skips the spinner entirely),
|
|
6300
|
+
* - a still-pending matching tool call → `spinner`,
|
|
6301
|
+
* - otherwise stay `hidden` (the matching tool call hasn't landed yet).
|
|
6302
|
+
*/
|
|
6303
|
+
function resolveGracePhase(turnComplete, hasPending) {
|
|
6304
|
+
if (turnComplete) return "finished";
|
|
6305
|
+
if (hasPending) return "spinner";
|
|
6306
|
+
return "hidden";
|
|
6307
|
+
}
|
|
5756
6308
|
const isMatchingToolCallName = (name) => typeof name === "string" && DEFAULT_TOOL_PATTERNS.some((p) => p.test(name));
|
|
6309
|
+
const messageHasMatchingToolCall = (m) => {
|
|
6310
|
+
if (m.role !== "assistant") return false;
|
|
6311
|
+
return (Array.isArray(m.toolCalls) ? m.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name));
|
|
6312
|
+
};
|
|
6313
|
+
/**
|
|
6314
|
+
* Stable turn id for the messages that precede the first user message (a turn
|
|
6315
|
+
* with no opening user message of its own). Used as the React key so the
|
|
6316
|
+
* indicator for that turn never collides with a real user-message id.
|
|
6317
|
+
*/
|
|
6318
|
+
const INTELLIGENCE_TURN_HEAD = "__cpk_turn_head__";
|
|
6319
|
+
/**
|
|
6320
|
+
* Map each Intelligence-using turn to its anchor message — the FIRST bash-using
|
|
6321
|
+
* assistant message of the turn — and a stable turn id (the id of the user
|
|
6322
|
+
* message that opened the turn, or {@link INTELLIGENCE_TURN_HEAD} for the
|
|
6323
|
+
* pre-first-user turn). Returns `Map<anchorMessageId, turnId>`.
|
|
6324
|
+
*
|
|
6325
|
+
* Anchoring to the FIRST (not last) bash-using message keeps the indicator
|
|
6326
|
+
* fixed in place for the whole turn: later bash steps don't reposition it, so
|
|
6327
|
+
* the spinner never abruptly jumps mid-turn (bug 1). `CopilotChatMessageView`
|
|
6328
|
+
* emits exactly one `IntelligenceIndicator` per entry, keyed by the turn id and
|
|
6329
|
+
* positioned at the anchor; the per-turn key also lets every past turn keep its
|
|
6330
|
+
* own indicator in scroll-back.
|
|
6331
|
+
*/
|
|
6332
|
+
function getIntelligenceTurnAnchors(messages) {
|
|
6333
|
+
const anchors = /* @__PURE__ */ new Map();
|
|
6334
|
+
let turnId = INTELLIGENCE_TURN_HEAD;
|
|
6335
|
+
let anchorId = null;
|
|
6336
|
+
const commit = () => {
|
|
6337
|
+
if (anchorId !== null) anchors.set(anchorId, turnId);
|
|
6338
|
+
anchorId = null;
|
|
6339
|
+
};
|
|
6340
|
+
for (const m of messages) {
|
|
6341
|
+
if (m.role === "user") {
|
|
6342
|
+
commit();
|
|
6343
|
+
turnId = m.id;
|
|
6344
|
+
continue;
|
|
6345
|
+
}
|
|
6346
|
+
if (anchorId === null && messageHasMatchingToolCall(m)) anchorId = m.id;
|
|
6347
|
+
}
|
|
6348
|
+
commit();
|
|
6349
|
+
return anchors;
|
|
6350
|
+
}
|
|
5757
6351
|
/**
|
|
5758
6352
|
* "Tool-call-like" messages do NOT count as a real follow-up: tool
|
|
5759
6353
|
* result messages, assistant messages that carry tool calls, and
|
|
@@ -5772,45 +6366,51 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
5772
6366
|
return false;
|
|
5773
6367
|
};
|
|
5774
6368
|
/**
|
|
5775
|
-
* The "Using CopilotKit Intelligence"
|
|
5776
|
-
* `CopilotChatMessageView`
|
|
5777
|
-
*
|
|
5778
|
-
*
|
|
5779
|
-
*
|
|
6369
|
+
* The "Using CopilotKit Intelligence" indicator brain. Auto-mounted by
|
|
6370
|
+
* `CopilotChatMessageView` — once per Intelligence-using turn, at that
|
|
6371
|
+
* turn's anchor message and keyed by the turn id (see
|
|
6372
|
+
* {@link getIntelligenceTurnAnchors}). Callers do not register this
|
|
6373
|
+
* themselves. It owns the run subscription and the phase machine and
|
|
6374
|
+
* renders its swappable face via the `intelligenceIndicator` slot.
|
|
6375
|
+
*
|
|
6376
|
+
* Placement (which message anchors the turn) is decided by the view, so
|
|
6377
|
+
* this component does not self-gate its own placement; it only derives
|
|
6378
|
+
* in-progress/finished for the turn it was mounted on.
|
|
5780
6379
|
*
|
|
5781
6380
|
* Render gates (all must hold):
|
|
5782
6381
|
* 1. `copilotkit.intelligence !== undefined`
|
|
5783
|
-
* 2. The message is an assistant message with at least one
|
|
5784
|
-
* whose name matches {@link DEFAULT_TOOL_PATTERNS}
|
|
5785
|
-
* 3. The
|
|
5786
|
-
*
|
|
5787
|
-
*
|
|
5788
|
-
*
|
|
5789
|
-
*
|
|
5790
|
-
*
|
|
6382
|
+
* 2. The (anchor) message is an assistant message with at least one
|
|
6383
|
+
* tool call whose name matches {@link DEFAULT_TOOL_PATTERNS}.
|
|
6384
|
+
* 3. The phase machine is past `hidden`.
|
|
6385
|
+
*
|
|
6386
|
+
* Because the view keys each indicator by its turn id, the instance moves
|
|
6387
|
+
* with the anchor across a hand-off (no remount, no spinner restart), and
|
|
6388
|
+
* every prior Intelligence-using turn keeps its own persistent indicator
|
|
6389
|
+
* in chat history.
|
|
5791
6390
|
*
|
|
5792
6391
|
* Phase machine (per-instance, all timers local):
|
|
5793
|
-
* - Starts in `
|
|
5794
|
-
*
|
|
6392
|
+
* - Starts in `hidden`, unless the message mounts onto an
|
|
6393
|
+
* already-completed turn (no pending work, agent stopped or a
|
|
6394
|
+
* real follow-up already present), in which case the lazy
|
|
6395
|
+
* `useState` initializer starts directly in `finished`. This is
|
|
6396
|
+
* what avoids a "hidden flash" on history replay.
|
|
6397
|
+
* - `hidden → spinner` once a matching tool call has been pending
|
|
5795
6398
|
* (no `tool`-role result with a matching `toolCallId`) for
|
|
5796
6399
|
* {@link PENDING_THRESHOLD_MS}. Replay flashes (tool call + result
|
|
5797
6400
|
* in the same tick) never cross this threshold.
|
|
5798
|
-
* - `
|
|
6401
|
+
* - `hidden → finished` if after the grace window the turn is
|
|
6402
|
+
* already complete (no pending work AND
|
|
6403
|
+
* `sawRealFollowup || !agent.isRunning`). Handles very fast tools
|
|
6404
|
+
* whose result lands within the grace window.
|
|
6405
|
+
* - `spinner → finished` as soon as EITHER `agent.isRunning` flips
|
|
5799
6406
|
* false OR a non-tool-call-like message appears later in
|
|
5800
|
-
* `agent.messages` (i.e. the agent
|
|
5801
|
-
*
|
|
5802
|
-
* - `
|
|
5803
|
-
*
|
|
5804
|
-
*
|
|
5805
|
-
* Once `hidden`, the phase is sticky — a finished pill never re-spawns
|
|
5806
|
-
* on the same message. New runs mount fresh indicator instances on
|
|
5807
|
-
* their own assistant messages.
|
|
5808
|
-
*
|
|
5809
|
-
* The "exactly one pill at a time" guarantee is structural: only one
|
|
5810
|
-
* message satisfies the latest-matching-assistant gate at any moment.
|
|
6407
|
+
* `agent.messages` (i.e. the agent produced a "real" follow-up —
|
|
6408
|
+
* prose answer or a new user turn).
|
|
6409
|
+
* - `finished` is terminal: the indicator settles into its
|
|
6410
|
+
* persistent tag form and stays mounted.
|
|
5811
6411
|
*/
|
|
5812
6412
|
function IntelligenceIndicator(props) {
|
|
5813
|
-
const { message, agentId, label = "
|
|
6413
|
+
const { message, agentId, label = "CopilotKit Intelligence", intelligenceIndicator } = props;
|
|
5814
6414
|
const { copilotkit } = useCopilotKit();
|
|
5815
6415
|
const config = useCopilotChatConfiguration();
|
|
5816
6416
|
const { agent } = useAgent({
|
|
@@ -5830,84 +6430,37 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
5830
6430
|
for (const m of agent.messages) if (m.role === "tool" && m.toolCallId) resolved.add(m.toolCallId);
|
|
5831
6431
|
return matchingToolCallIds.some((id) => !resolved.has(id));
|
|
5832
6432
|
}, [matchingToolCallIds, agent.messages]);
|
|
5833
|
-
const
|
|
6433
|
+
const turnComplete = (0, react.useMemo)(() => {
|
|
5834
6434
|
const idx = agent.messages.findIndex((m) => m.id === message.id);
|
|
5835
6435
|
if (idx < 0) return false;
|
|
5836
6436
|
for (let i = idx + 1; i < agent.messages.length; i += 1) if (!isToolCallLikeMessage(agent.messages[i])) return true;
|
|
5837
6437
|
return false;
|
|
5838
|
-
}, [agent.messages, message.id]);
|
|
5839
|
-
const [phase, setPhase] = (0, react.useState)(
|
|
6438
|
+
}, [agent.messages, message.id]) || !agent.isRunning;
|
|
6439
|
+
const [phase, setPhase] = (0, react.useState)(() => initialIndicatorPhase(turnComplete));
|
|
5840
6440
|
(0, react.useEffect)(() => {
|
|
5841
|
-
if (phase !== "
|
|
5842
|
-
|
|
5843
|
-
|
|
6441
|
+
if (phase !== "hidden") return void 0;
|
|
6442
|
+
const t = setTimeout(() => {
|
|
6443
|
+
setPhase(resolveGracePhase(turnComplete, hasPending));
|
|
6444
|
+
}, PENDING_THRESHOLD_MS);
|
|
5844
6445
|
return () => clearTimeout(t);
|
|
5845
|
-
}, [phase, hasPending]);
|
|
5846
|
-
(0, react.useEffect)(() => {
|
|
5847
|
-
if (phase !== "spinner") return void 0;
|
|
5848
|
-
if (!agent.isRunning || sawRealFollowup) setPhase("check");
|
|
5849
6446
|
}, [
|
|
5850
6447
|
phase,
|
|
5851
|
-
|
|
5852
|
-
|
|
6448
|
+
hasPending,
|
|
6449
|
+
turnComplete
|
|
5853
6450
|
]);
|
|
5854
6451
|
(0, react.useEffect)(() => {
|
|
5855
|
-
if (phase !== "
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
}, [phase]);
|
|
5859
|
-
(0, react.useEffect)(() => {
|
|
5860
|
-
if (phase !== "fading") return void 0;
|
|
5861
|
-
const t = setTimeout(() => setPhase("hidden"), FADE_OUT_ANIMATION_MS);
|
|
5862
|
-
return () => clearTimeout(t);
|
|
5863
|
-
}, [phase]);
|
|
6452
|
+
if (phase !== "spinner") return void 0;
|
|
6453
|
+
if (turnComplete) setPhase("finished");
|
|
6454
|
+
}, [phase, turnComplete]);
|
|
5864
6455
|
if (copilotkit.intelligence === void 0) return null;
|
|
5865
6456
|
if (!config) return null;
|
|
5866
|
-
if (phase === "
|
|
6457
|
+
if (phase === "hidden") return null;
|
|
5867
6458
|
if (message.role !== "assistant") return null;
|
|
5868
|
-
if (!(
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) {
|
|
5874
|
-
latestMatchingAssistantId = m.id;
|
|
5875
|
-
break;
|
|
5876
|
-
}
|
|
5877
|
-
}
|
|
5878
|
-
if (latestMatchingAssistantId !== message.id) return null;
|
|
5879
|
-
const showSpinner = phase === "spinner";
|
|
5880
|
-
const isFading = phase === "fading";
|
|
5881
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5882
|
-
className: "cpk-intelligence-pill" + (isFading ? " cpk-intelligence-pill--fading" : ""),
|
|
5883
|
-
role: "status",
|
|
5884
|
-
"aria-live": "polite",
|
|
5885
|
-
"aria-hidden": isFading || void 0,
|
|
5886
|
-
"data-testid": `cpk-intelligence-pill-${message.id}`,
|
|
5887
|
-
title: label,
|
|
5888
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
5889
|
-
className: "cpk-intelligence-pill__icon",
|
|
5890
|
-
viewBox: "0 0 24 24",
|
|
5891
|
-
width: "14",
|
|
5892
|
-
height: "14",
|
|
5893
|
-
"aria-hidden": "true",
|
|
5894
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
5895
|
-
cx: "12",
|
|
5896
|
-
cy: "12",
|
|
5897
|
-
r: "9",
|
|
5898
|
-
fill: "none",
|
|
5899
|
-
strokeWidth: "2.5",
|
|
5900
|
-
strokeLinecap: "round",
|
|
5901
|
-
className: "cpk-intelligence-pill__ring" + (showSpinner ? "" : " cpk-intelligence-pill__ring--done")
|
|
5902
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
5903
|
-
d: "M8 12.5l3 3 5-6",
|
|
5904
|
-
fill: "none",
|
|
5905
|
-
strokeWidth: "2.5",
|
|
5906
|
-
strokeLinecap: "round",
|
|
5907
|
-
strokeLinejoin: "round",
|
|
5908
|
-
className: "cpk-intelligence-pill__check" + (showSpinner ? "" : " cpk-intelligence-pill__check--shown")
|
|
5909
|
-
})]
|
|
5910
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })]
|
|
6459
|
+
if (!messageHasMatchingToolCall(message)) return null;
|
|
6460
|
+
return renderSlot(intelligenceIndicator, IntelligenceIndicatorView, {
|
|
6461
|
+
message,
|
|
6462
|
+
status: phase === "finished" ? "finished" : "in-progress",
|
|
6463
|
+
label
|
|
5911
6464
|
});
|
|
5912
6465
|
}
|
|
5913
6466
|
|
|
@@ -6060,7 +6613,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6060
6613
|
return [...acc.values()];
|
|
6061
6614
|
}
|
|
6062
6615
|
const VIRTUALIZE_THRESHOLD = 50;
|
|
6063
|
-
function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, isRunning = false, children, className, ...props }) {
|
|
6616
|
+
function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, isRunning = false, children, className, ...props }) {
|
|
6064
6617
|
const renderCustomMessage = useRenderCustomMessages();
|
|
6065
6618
|
const { renderActivityMessage } = useRenderActivityMessage();
|
|
6066
6619
|
const { copilotkit } = useCopilotKit();
|
|
@@ -6118,6 +6671,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6118
6671
|
if (!shouldVirtualize || !deduplicatedMessages.length) return;
|
|
6119
6672
|
virtualizer.scrollToIndex(deduplicatedMessages.length - 1, { align: "end" });
|
|
6120
6673
|
}, [shouldVirtualize, firstMessageId]);
|
|
6674
|
+
const intelligenceTurnAnchors = (0, react.useMemo)(() => getIntelligenceTurnAnchors(deduplicatedMessages), [deduplicatedMessages]);
|
|
6121
6675
|
const renderMessageBlock = (message) => {
|
|
6122
6676
|
const elements = [];
|
|
6123
6677
|
const stateSnapshot = getStateSnapshotForMessage(message.id);
|
|
@@ -6156,10 +6710,12 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6156
6710
|
renderCustomMessage,
|
|
6157
6711
|
stateSnapshot
|
|
6158
6712
|
}, `${message.id}-custom-after`));
|
|
6159
|
-
|
|
6713
|
+
const intelligenceTurnId = intelligenceTurnAnchors.get(message.id);
|
|
6714
|
+
if (intelligenceTurnId !== void 0) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IntelligenceIndicator, {
|
|
6160
6715
|
message,
|
|
6161
|
-
agentId: config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID
|
|
6162
|
-
|
|
6716
|
+
agentId: config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID,
|
|
6717
|
+
intelligenceIndicator
|
|
6718
|
+
}, `intelligence-${intelligenceTurnId}`));
|
|
6163
6719
|
return elements.filter(Boolean);
|
|
6164
6720
|
};
|
|
6165
6721
|
const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
|
|
@@ -6596,7 +7152,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6596
7152
|
})
|
|
6597
7153
|
});
|
|
6598
7154
|
}
|
|
6599
|
-
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 }) {
|
|
7155
|
+
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 }) {
|
|
6600
7156
|
const [inputContainerEl, setInputContainerEl] = (0, react.useState)(null);
|
|
6601
7157
|
const [inputContainerHeight, setInputContainerHeight] = (0, react.useState)(0);
|
|
6602
7158
|
const [isResizing, setIsResizing] = (0, react.useState)(false);
|
|
@@ -6633,7 +7189,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6633
7189
|
}, [inputContainerEl]);
|
|
6634
7190
|
const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {
|
|
6635
7191
|
messages,
|
|
6636
|
-
isRunning
|
|
7192
|
+
isRunning,
|
|
7193
|
+
intelligenceIndicator
|
|
6637
7194
|
});
|
|
6638
7195
|
const BoundInput = renderSlot(input, CopilotChatInput_default, {
|
|
6639
7196
|
onSubmitMessage,
|
|
@@ -7178,6 +7735,13 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7178
7735
|
resolvedAgentId,
|
|
7179
7736
|
hasExplicitThreadId
|
|
7180
7737
|
]);
|
|
7738
|
+
const waitForActiveRunToSettle = (0, react.useCallback)(async () => {
|
|
7739
|
+
if (agent.isRunning && (0, _copilotkit_core.isRunCompletionAware)(agent) && agent.activeRunCompletionPromise) try {
|
|
7740
|
+
await agent.activeRunCompletionPromise;
|
|
7741
|
+
} catch (error) {
|
|
7742
|
+
console.error("CopilotChat: in-flight run rejected while queuing send", error);
|
|
7743
|
+
}
|
|
7744
|
+
}, [agent]);
|
|
7181
7745
|
const onSubmitInput = (0, react.useCallback)(async (value) => {
|
|
7182
7746
|
if (selectedAttachmentsRef.current.some((a) => a.status === "uploading")) {
|
|
7183
7747
|
console.error("[CopilotKit] Cannot send while attachments are uploading (pre-await guard)");
|
|
@@ -7185,11 +7749,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7185
7749
|
return;
|
|
7186
7750
|
}
|
|
7187
7751
|
setInputValue("");
|
|
7188
|
-
|
|
7189
|
-
await agent.activeRunCompletionPromise;
|
|
7190
|
-
} catch (error) {
|
|
7191
|
-
console.error("CopilotChat: in-flight run rejected while queuing send", error);
|
|
7192
|
-
}
|
|
7752
|
+
await waitForActiveRunToSettle();
|
|
7193
7753
|
if (selectedAttachmentsRef.current.some((a) => a.status === "uploading")) {
|
|
7194
7754
|
console.error("[CopilotKit] Cannot send while attachments are uploading (post-await re-check)");
|
|
7195
7755
|
setTranscriptionError("Cannot send while attachments are uploading.");
|
|
@@ -7226,8 +7786,13 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7226
7786
|
} catch (error) {
|
|
7227
7787
|
console.error("CopilotChat: runAgent failed", error);
|
|
7228
7788
|
}
|
|
7229
|
-
}, [
|
|
7789
|
+
}, [
|
|
7790
|
+
agent,
|
|
7791
|
+
consumeAttachments,
|
|
7792
|
+
waitForActiveRunToSettle
|
|
7793
|
+
]);
|
|
7230
7794
|
const handleSelectSuggestion = (0, react.useCallback)(async (suggestion) => {
|
|
7795
|
+
await waitForActiveRunToSettle();
|
|
7231
7796
|
agent.addMessage({
|
|
7232
7797
|
id: (0, _copilotkit_shared.randomUUID)(),
|
|
7233
7798
|
role: "user",
|
|
@@ -7238,7 +7803,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7238
7803
|
} catch (error) {
|
|
7239
7804
|
console.error("CopilotChat: runAgent failed after selecting suggestion", error);
|
|
7240
7805
|
}
|
|
7241
|
-
}, [agent]);
|
|
7806
|
+
}, [agent, waitForActiveRunToSettle]);
|
|
7242
7807
|
const stopCurrentRun = (0, react.useCallback)(() => {
|
|
7243
7808
|
try {
|
|
7244
7809
|
copilotkit.stopAgent({ agent });
|
|
@@ -10047,7 +10612,9 @@ Object.defineProperty(exports, 'CopilotSidebarView', {
|
|
|
10047
10612
|
return CopilotSidebarView;
|
|
10048
10613
|
}
|
|
10049
10614
|
});
|
|
10615
|
+
exports.INTELLIGENCE_TURN_HEAD = INTELLIGENCE_TURN_HEAD;
|
|
10050
10616
|
exports.IntelligenceIndicator = IntelligenceIndicator;
|
|
10617
|
+
exports.IntelligenceIndicatorView = IntelligenceIndicatorView;
|
|
10051
10618
|
exports.MCPAppsActivityContentSchema = MCPAppsActivityContentSchema;
|
|
10052
10619
|
exports.MCPAppsActivityRenderer = MCPAppsActivityRenderer;
|
|
10053
10620
|
exports.MCPAppsActivityType = MCPAppsActivityType;
|
|
@@ -10062,6 +10629,7 @@ Object.defineProperty(exports, 'a2uiDefaultTheme', {
|
|
|
10062
10629
|
});
|
|
10063
10630
|
exports.createA2UIMessageRenderer = createA2UIMessageRenderer;
|
|
10064
10631
|
exports.defineToolCallRenderer = defineToolCallRenderer;
|
|
10632
|
+
exports.getIntelligenceTurnAnchors = getIntelligenceTurnAnchors;
|
|
10065
10633
|
exports.useAgent = useAgent;
|
|
10066
10634
|
exports.useAgentContext = useAgentContext;
|
|
10067
10635
|
exports.useAttachments = useAttachments;
|
|
@@ -10074,6 +10642,10 @@ exports.useDefaultRenderTool = useDefaultRenderTool;
|
|
|
10074
10642
|
exports.useFrontendTool = useFrontendTool;
|
|
10075
10643
|
exports.useHumanInTheLoop = useHumanInTheLoop;
|
|
10076
10644
|
exports.useInterrupt = useInterrupt;
|
|
10645
|
+
exports.useLearnFromUserAction = useLearnFromUserAction;
|
|
10646
|
+
exports.useLearnFromUserActionInCurrentThread = useLearnFromUserActionInCurrentThread;
|
|
10647
|
+
exports.useLearningContainers = useLearningContainers;
|
|
10648
|
+
exports.useLearningContainersInCurrentThread = useLearningContainersInCurrentThread;
|
|
10077
10649
|
exports.useRenderActivityMessage = useRenderActivityMessage;
|
|
10078
10650
|
exports.useRenderCustomMessages = useRenderCustomMessages;
|
|
10079
10651
|
exports.useRenderTool = useRenderTool;
|