@copilotkit/react-core 1.59.4 → 1.59.5-canary.1781104893
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-D42EuTt0.d.mts → copilotkit-B83H_vWJ.d.mts} +67 -42
- package/dist/copilotkit-B83H_vWJ.d.mts.map +1 -0
- package/dist/{copilotkit-CtqalfG8.d.cts → copilotkit-CD3EqiJ4.d.cts} +67 -42
- package/dist/copilotkit-CD3EqiJ4.d.cts.map +1 -0
- package/dist/{copilotkit-LdQ8w20l.cjs → copilotkit-CWGR3Ict.cjs} +433 -246
- package/dist/copilotkit-CWGR3Ict.cjs.map +1 -0
- package/dist/{copilotkit-DoIlZQqa.mjs → copilotkit-DBOofUYQ.mjs} +433 -246
- package/dist/copilotkit-DBOofUYQ.mjs.map +1 -0
- package/dist/index.cjs +10 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +10 -7
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +350 -210
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/index.cjs +1 -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 +1 -1
- package/dist/v2/index.umd.js +432 -245
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +8 -8
- package/dist/copilotkit-CtqalfG8.d.cts.map +0 -1
- package/dist/copilotkit-D42EuTt0.d.mts.map +0 -1
- package/dist/copilotkit-DoIlZQqa.mjs.map +0 -1
- package/dist/copilotkit-LdQ8w20l.cjs.map +0 -1
|
@@ -1995,7 +1995,7 @@ function LicenseWarningBanner({ type, featureName, expiryDate, graceRemaining, o
|
|
|
1995
1995
|
severity: "warning",
|
|
1996
1996
|
message: `Your CopilotKit license expires in ${graceRemaining} day${graceRemaining !== 1 ? "s" : ""}. Please renew.`,
|
|
1997
1997
|
actionLabel: "Renew",
|
|
1998
|
-
actionUrl: "https://
|
|
1998
|
+
actionUrl: "https://dashboard.operations.copilotkit.ai",
|
|
1999
1999
|
onDismiss
|
|
2000
2000
|
});
|
|
2001
2001
|
case "expired": return /* @__PURE__ */ jsx(BannerShell, {
|
|
@@ -2924,210 +2924,110 @@ const OpenGenerativeUIToolRenderer = function OpenGenerativeUIToolRenderer(props
|
|
|
2924
2924
|
};
|
|
2925
2925
|
|
|
2926
2926
|
//#endregion
|
|
2927
|
-
//#region src/v2/a2ui/
|
|
2927
|
+
//#region src/v2/a2ui/A2UIRecoveryStates.tsx
|
|
2928
2928
|
/**
|
|
2929
|
-
* The
|
|
2930
|
-
*
|
|
2929
|
+
* The pre-paint lifecycle fields the middleware stamps onto the `a2ui-surface`
|
|
2930
|
+
* activity content (alongside `a2ui_operations` on paint). `.passthrough()` keeps
|
|
2931
|
+
* `a2ui_operations` and any future fields intact.
|
|
2931
2932
|
*/
|
|
2932
|
-
const
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
lastContentRef.current = content;
|
|
2954
|
-
const incoming = content?.[A2UI_OPERATIONS_KEY];
|
|
2955
|
-
if (!content || !Array.isArray(incoming)) {
|
|
2956
|
-
setOperations([]);
|
|
2957
|
-
return;
|
|
2958
|
-
}
|
|
2959
|
-
setOperations(incoming);
|
|
2960
|
-
}, [content]);
|
|
2961
|
-
const groupedOperations = useMemo(() => {
|
|
2962
|
-
const groups = /* @__PURE__ */ new Map();
|
|
2963
|
-
for (const operation of operations) {
|
|
2964
|
-
const surfaceId = getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;
|
|
2965
|
-
if (!groups.has(surfaceId)) groups.set(surfaceId, []);
|
|
2966
|
-
groups.get(surfaceId).push(operation);
|
|
2967
|
-
}
|
|
2968
|
-
return groups;
|
|
2969
|
-
}, [operations]);
|
|
2970
|
-
if (!groupedOperations.size) return /* @__PURE__ */ jsx(loadingComponent ?? DefaultA2UILoading, {});
|
|
2971
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2972
|
-
className: "cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6",
|
|
2973
|
-
children: Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => /* @__PURE__ */ jsx(ReactSurfaceHost, {
|
|
2974
|
-
surfaceId,
|
|
2975
|
-
operations: ops,
|
|
2976
|
-
theme,
|
|
2977
|
-
agent,
|
|
2978
|
-
copilotkit,
|
|
2979
|
-
catalog
|
|
2980
|
-
}, surfaceId))
|
|
2981
|
-
});
|
|
2982
|
-
}
|
|
2983
|
-
};
|
|
2984
|
-
}
|
|
2985
|
-
/**
|
|
2986
|
-
* Renders a single A2UI surface using the React renderer.
|
|
2987
|
-
* Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
|
|
2988
|
-
*/
|
|
2989
|
-
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit, catalog }) {
|
|
2990
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2991
|
-
className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
|
|
2992
|
-
children: /* @__PURE__ */ jsxs(A2UIProvider, {
|
|
2993
|
-
onAction: useCallback(async (message) => {
|
|
2994
|
-
if (!agent) return;
|
|
2995
|
-
message.userAction;
|
|
2996
|
-
try {
|
|
2997
|
-
copilotkit.setProperties({
|
|
2998
|
-
...copilotkit.properties,
|
|
2999
|
-
a2uiAction: message
|
|
3000
|
-
});
|
|
3001
|
-
await copilotkit.runAgent({ agent });
|
|
3002
|
-
} finally {
|
|
3003
|
-
if (copilotkit.properties) {
|
|
3004
|
-
const { a2uiAction, ...rest } = copilotkit.properties;
|
|
3005
|
-
copilotkit.setProperties(rest);
|
|
3006
|
-
}
|
|
3007
|
-
}
|
|
3008
|
-
}, [agent, copilotkit]),
|
|
3009
|
-
theme,
|
|
3010
|
-
catalog,
|
|
3011
|
-
children: [/* @__PURE__ */ jsx(SurfaceMessageProcessor, {
|
|
3012
|
-
surfaceId,
|
|
3013
|
-
operations
|
|
3014
|
-
}), /* @__PURE__ */ jsx(A2UISurfaceOrError, { surfaceId })]
|
|
3015
|
-
})
|
|
3016
|
-
});
|
|
2933
|
+
const A2UILifecycleFields = {
|
|
2934
|
+
status: z.enum([
|
|
2935
|
+
"building",
|
|
2936
|
+
"retrying",
|
|
2937
|
+
"failed"
|
|
2938
|
+
]).optional(),
|
|
2939
|
+
attempt: z.number().optional(),
|
|
2940
|
+
maxAttempts: z.number().optional(),
|
|
2941
|
+
progressTokens: z.number().optional(),
|
|
2942
|
+
error: z.string().optional(),
|
|
2943
|
+
errors: z.array(z.any()).optional(),
|
|
2944
|
+
attempts: z.array(z.any()).optional(),
|
|
2945
|
+
debugExposure: z.enum([
|
|
2946
|
+
"hidden",
|
|
2947
|
+
"collapsed",
|
|
2948
|
+
"verbose"
|
|
2949
|
+
]).optional()
|
|
2950
|
+
};
|
|
2951
|
+
/** Server-stamped debugExposure wins; else the client option; else "collapsed". */
|
|
2952
|
+
function resolveDebugExposure(content, optionDebugExposure) {
|
|
2953
|
+
return content?.debugExposure ?? optionDebugExposure;
|
|
3017
2954
|
}
|
|
3018
|
-
/**
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
const error = useA2UIError();
|
|
3024
|
-
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
3025
|
-
className: "cpk:rounded-lg cpk:border cpk:border-red-200 cpk:bg-red-50 cpk:p-3 cpk:text-sm cpk:text-red-700",
|
|
3026
|
-
children: ["A2UI render error: ", error]
|
|
3027
|
-
});
|
|
3028
|
-
return /* @__PURE__ */ jsx(A2UIRenderer, {
|
|
3029
|
-
surfaceId,
|
|
3030
|
-
className: "cpk:flex cpk:flex-1"
|
|
2955
|
+
/** building: the generic skeleton + optional live token count. */
|
|
2956
|
+
function A2UIBuildingState({ content }) {
|
|
2957
|
+
return /* @__PURE__ */ jsx(A2UIGeneratingSkeleton, {
|
|
2958
|
+
label: "Building interface",
|
|
2959
|
+
tokens: typeof content?.progressTokens === "number" ? content.progressTokens : void 0
|
|
3031
2960
|
});
|
|
3032
2961
|
}
|
|
3033
2962
|
/**
|
|
3034
|
-
*
|
|
3035
|
-
*
|
|
2963
|
+
* retrying: stays the generic skeleton through fast/transient retries; only once
|
|
2964
|
+
* the retry is perceptible (after `showAfterMs`, or once `attempt` crosses
|
|
2965
|
+
* `showAfterAttempts`) does the sub-label reveal "Retrying generation… (N/M)".
|
|
3036
2966
|
*/
|
|
3037
|
-
function
|
|
3038
|
-
const
|
|
3039
|
-
const
|
|
2967
|
+
function A2UIRetryingState({ content, showAfterMs, showAfterAttempts, debugExposure }) {
|
|
2968
|
+
const attempt = typeof content?.attempt === "number" ? content.attempt : void 0;
|
|
2969
|
+
const maxAttempts = typeof content?.maxAttempts === "number" ? content.maxAttempts : void 0;
|
|
2970
|
+
const immediate = attempt !== void 0 && attempt >= showAfterAttempts;
|
|
2971
|
+
const [revealed, setRevealed] = useState(immediate);
|
|
3040
2972
|
useEffect(() => {
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
2973
|
+
if (immediate) {
|
|
2974
|
+
setRevealed(true);
|
|
2975
|
+
return;
|
|
2976
|
+
}
|
|
2977
|
+
const timer = setTimeout(() => setRevealed(true), showAfterMs);
|
|
2978
|
+
return () => clearTimeout(timer);
|
|
2979
|
+
}, [immediate, showAfterMs]);
|
|
2980
|
+
const tokens = typeof content?.progressTokens === "number" ? content.progressTokens : void 0;
|
|
2981
|
+
if (!revealed) return /* @__PURE__ */ jsx(A2UIGeneratingSkeleton, {
|
|
2982
|
+
label: "Building interface",
|
|
2983
|
+
tokens
|
|
2984
|
+
});
|
|
2985
|
+
const label = attempt !== void 0 && maxAttempts !== void 0 ? `Retrying generation… (${attempt}/${maxAttempts} attempts)` : "Retrying generation…";
|
|
2986
|
+
const errors = Array.isArray(content?.errors) ? content.errors : [];
|
|
2987
|
+
return /* @__PURE__ */ jsx(A2UIGeneratingSkeleton, {
|
|
2988
|
+
label,
|
|
2989
|
+
tokens,
|
|
2990
|
+
children: debugExposure !== "hidden" && errors.length > 0 && /* @__PURE__ */ jsx(A2UIDebugDetails, {
|
|
2991
|
+
label: "validation issues",
|
|
2992
|
+
open: debugExposure === "verbose",
|
|
2993
|
+
payload: {
|
|
2994
|
+
attempt: content?.attempt,
|
|
2995
|
+
errors
|
|
2996
|
+
}
|
|
2997
|
+
})
|
|
2998
|
+
});
|
|
3052
2999
|
}
|
|
3053
|
-
/**
|
|
3054
|
-
|
|
3055
|
-
* Displays an animated shimmer skeleton.
|
|
3056
|
-
*/
|
|
3057
|
-
function DefaultA2UILoading() {
|
|
3000
|
+
/** failed: a clean hard-failure card that replaces the skeleton in place. */
|
|
3001
|
+
function A2UIRecoveryFailure({ content, debugExposure }) {
|
|
3058
3002
|
return /* @__PURE__ */ jsxs("div", {
|
|
3059
|
-
className: "cpk:
|
|
3060
|
-
style: { minHeight: 120 },
|
|
3003
|
+
className: "cpk:rounded-lg cpk:border cpk:border-amber-200 cpk:bg-amber-50 cpk:p-3 cpk:text-sm cpk:text-amber-800",
|
|
3061
3004
|
children: [
|
|
3062
|
-
/* @__PURE__ */
|
|
3063
|
-
className: "cpk:
|
|
3064
|
-
children:
|
|
3065
|
-
className: "cpk:h-3 cpk:w-3 cpk:rounded-full cpk:bg-gray-200",
|
|
3066
|
-
style: { animation: "cpk-a2ui-pulse 1.5s ease-in-out infinite" }
|
|
3067
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
3068
|
-
className: "cpk:text-xs cpk:font-medium cpk:text-gray-400",
|
|
3069
|
-
children: "Generating UI..."
|
|
3070
|
-
})]
|
|
3005
|
+
/* @__PURE__ */ jsx("div", {
|
|
3006
|
+
className: "cpk:font-medium",
|
|
3007
|
+
children: "Couldn't generate the UI"
|
|
3071
3008
|
}),
|
|
3072
3009
|
/* @__PURE__ */ jsx("div", {
|
|
3073
|
-
className: "cpk:
|
|
3074
|
-
children:
|
|
3075
|
-
.8,
|
|
3076
|
-
.6,
|
|
3077
|
-
.4
|
|
3078
|
-
].map((width, i) => /* @__PURE__ */ jsx("div", {
|
|
3079
|
-
className: "cpk:h-3 cpk:rounded cpk:bg-gray-200/70",
|
|
3080
|
-
style: {
|
|
3081
|
-
width: `${width * 100}%`,
|
|
3082
|
-
animation: `cpk-a2ui-pulse 1.5s ease-in-out ${i * .15}s infinite`
|
|
3083
|
-
}
|
|
3084
|
-
}, i))
|
|
3010
|
+
className: "cpk:mt-1 cpk:text-xs cpk:text-amber-700",
|
|
3011
|
+
children: "Something went wrong rendering this. You can keep chatting and try again."
|
|
3085
3012
|
}),
|
|
3086
|
-
/* @__PURE__ */ jsx(
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3013
|
+
debugExposure !== "hidden" && /* @__PURE__ */ jsx(A2UIDebugDetails, {
|
|
3014
|
+
label: "developer details",
|
|
3015
|
+
open: debugExposure === "verbose",
|
|
3016
|
+
payload: {
|
|
3017
|
+
error: content?.error,
|
|
3018
|
+
attempts: content?.attempts
|
|
3019
|
+
}
|
|
3020
|
+
})
|
|
3092
3021
|
]
|
|
3093
3022
|
});
|
|
3094
3023
|
}
|
|
3095
|
-
function getOperationSurfaceId(operation) {
|
|
3096
|
-
if (!operation || typeof operation !== "object") return null;
|
|
3097
|
-
if (typeof operation.surfaceId === "string") return operation.surfaceId;
|
|
3098
|
-
return operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
|
|
3099
|
-
}
|
|
3100
|
-
|
|
3101
|
-
//#endregion
|
|
3102
|
-
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
3103
3024
|
/**
|
|
3104
|
-
*
|
|
3105
|
-
*
|
|
3025
|
+
* Animated wireframe skeleton with a label, an optional live token count, and an
|
|
3026
|
+
* optional debug-detail slot below it. Pure CSS animation (no data dependency).
|
|
3027
|
+
* The `tokens` count drives a progressive reveal of skeleton rows.
|
|
3106
3028
|
*/
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
* Built-in progress indicator for dynamic A2UI generation.
|
|
3110
|
-
* Shows a skeleton wireframe that progressively reveals as tokens stream in.
|
|
3111
|
-
*
|
|
3112
|
-
* Registered automatically when A2UI is enabled. Users can override by
|
|
3113
|
-
* providing their own `useRenderTool({ name: "render_a2ui", ... })`.
|
|
3114
|
-
*/
|
|
3115
|
-
function A2UIProgressIndicator({ parameters }) {
|
|
3116
|
-
const lastRef = useRef({
|
|
3117
|
-
time: 0,
|
|
3118
|
-
tokens: 0
|
|
3119
|
-
});
|
|
3120
|
-
const now = Date.now();
|
|
3121
|
-
let { tokens } = lastRef.current;
|
|
3122
|
-
if (now - lastRef.current.time > 200) {
|
|
3123
|
-
const chars = JSON.stringify(parameters ?? {}).length;
|
|
3124
|
-
tokens = Math.round(chars / 4);
|
|
3125
|
-
lastRef.current = {
|
|
3126
|
-
time: now,
|
|
3127
|
-
tokens
|
|
3128
|
-
};
|
|
3129
|
-
}
|
|
3130
|
-
const phase = tokens < 50 ? 0 : tokens < 200 ? 1 : tokens < 400 ? 2 : 3;
|
|
3029
|
+
function A2UIGeneratingSkeleton({ label, tokens, children }) {
|
|
3030
|
+
const phase = tokens == null ? 3 : tokens < 50 ? 0 : tokens < 200 ? 1 : tokens < 400 ? 2 : 3;
|
|
3131
3031
|
return /* @__PURE__ */ jsxs("div", {
|
|
3132
3032
|
style: {
|
|
3133
3033
|
margin: "12px 0",
|
|
@@ -3335,8 +3235,8 @@ function A2UIProgressIndicator({ parameters }) {
|
|
|
3335
3235
|
color: "#a1a1aa",
|
|
3336
3236
|
letterSpacing: "0.025em"
|
|
3337
3237
|
},
|
|
3338
|
-
children:
|
|
3339
|
-
}), tokens > 0 && /* @__PURE__ */ jsxs("span", {
|
|
3238
|
+
children: label
|
|
3239
|
+
}), typeof tokens === "number" && tokens > 0 && /* @__PURE__ */ jsxs("span", {
|
|
3340
3240
|
style: {
|
|
3341
3241
|
fontSize: 11,
|
|
3342
3242
|
color: "#d4d4d8",
|
|
@@ -3349,6 +3249,7 @@ function A2UIProgressIndicator({ parameters }) {
|
|
|
3349
3249
|
]
|
|
3350
3250
|
})]
|
|
3351
3251
|
}),
|
|
3252
|
+
children,
|
|
3352
3253
|
/* @__PURE__ */ jsx("style", { children: `
|
|
3353
3254
|
@keyframes cpk-a2ui-fade {
|
|
3354
3255
|
0%, 100% { opacity: 1; }
|
|
@@ -3362,6 +3263,20 @@ function A2UIProgressIndicator({ parameters }) {
|
|
|
3362
3263
|
]
|
|
3363
3264
|
});
|
|
3364
3265
|
}
|
|
3266
|
+
function A2UIDebugDetails({ label, open, payload }) {
|
|
3267
|
+
return /* @__PURE__ */ jsxs("details", {
|
|
3268
|
+
open,
|
|
3269
|
+
className: "cpk:mt-2 cpk:text-xs",
|
|
3270
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
3271
|
+
className: "cpk:cursor-pointer cpk:text-gray-500",
|
|
3272
|
+
children: label
|
|
3273
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
3274
|
+
className: "cpk:mt-1 cpk:overflow-auto cpk:rounded cpk:bg-gray-100 cpk:p-2 cpk:text-gray-700",
|
|
3275
|
+
style: { fontSize: 11 },
|
|
3276
|
+
children: JSON.stringify(payload, null, 2)
|
|
3277
|
+
})]
|
|
3278
|
+
});
|
|
3279
|
+
}
|
|
3365
3280
|
function Dot() {
|
|
3366
3281
|
return /* @__PURE__ */ jsx("div", { style: {
|
|
3367
3282
|
width: 7,
|
|
@@ -3397,13 +3312,242 @@ function Row({ children, show, delay = 0 }) {
|
|
|
3397
3312
|
children
|
|
3398
3313
|
});
|
|
3399
3314
|
}
|
|
3315
|
+
|
|
3316
|
+
//#endregion
|
|
3317
|
+
//#region src/v2/a2ui/A2UIMessageRenderer.tsx
|
|
3318
|
+
/**
|
|
3319
|
+
* The container key used to wrap A2UI operations for explicit detection.
|
|
3320
|
+
* Must match A2UI_OPERATIONS_KEY in @ag-ui/a2ui-middleware and copilotkit.a2ui (Python).
|
|
3321
|
+
*/
|
|
3322
|
+
const A2UI_OPERATIONS_KEY = "a2ui_operations";
|
|
3323
|
+
let initialized = false;
|
|
3324
|
+
function ensureInitialized() {
|
|
3325
|
+
if (!initialized) {
|
|
3326
|
+
initializeDefaultCatalog();
|
|
3327
|
+
injectStyles();
|
|
3328
|
+
initialized = true;
|
|
3329
|
+
}
|
|
3330
|
+
}
|
|
3331
|
+
/**
|
|
3332
|
+
* The `a2ui-surface` activity carries the WHOLE generative-UI lifecycle on one
|
|
3333
|
+
* stable messageId (OSS-162): pre-paint `status` ("building" | "retrying" |
|
|
3334
|
+
* "failed") with recovery detail, then `a2ui_operations` on paint. The states
|
|
3335
|
+
* swap in place, so the painted surface replaces the skeleton with no extra
|
|
3336
|
+
* coordination. `.passthrough()` preserves operations + any future fields.
|
|
3337
|
+
*/
|
|
3338
|
+
const A2UISurfaceContentSchema = z.object({
|
|
3339
|
+
a2ui_operations: z.array(z.any()).optional(),
|
|
3340
|
+
...A2UILifecycleFields
|
|
3341
|
+
}).passthrough();
|
|
3342
|
+
function createA2UIMessageRenderer(options) {
|
|
3343
|
+
const { theme, catalog, loadingComponent, recovery } = options;
|
|
3344
|
+
const showAfterMs = recovery?.showAfterMs ?? 2e3;
|
|
3345
|
+
const showAfterAttempts = recovery?.showAfterAttempts ?? 2;
|
|
3346
|
+
const optionDebugExposure = recovery?.debugExposure ?? "collapsed";
|
|
3347
|
+
return {
|
|
3348
|
+
activityType: "a2ui-surface",
|
|
3349
|
+
content: A2UISurfaceContentSchema,
|
|
3350
|
+
render: ({ content, agent }) => {
|
|
3351
|
+
ensureInitialized();
|
|
3352
|
+
const [operations, setOperations] = useState([]);
|
|
3353
|
+
const { copilotkit } = useCopilotKit();
|
|
3354
|
+
const lastContentRef = useRef(null);
|
|
3355
|
+
useEffect(() => {
|
|
3356
|
+
if (content === lastContentRef.current) return;
|
|
3357
|
+
lastContentRef.current = content;
|
|
3358
|
+
const incoming = content?.[A2UI_OPERATIONS_KEY];
|
|
3359
|
+
if (!content || !Array.isArray(incoming)) {
|
|
3360
|
+
setOperations([]);
|
|
3361
|
+
return;
|
|
3362
|
+
}
|
|
3363
|
+
setOperations(incoming);
|
|
3364
|
+
}, [content]);
|
|
3365
|
+
const groupedOperations = useMemo(() => {
|
|
3366
|
+
const groups = /* @__PURE__ */ new Map();
|
|
3367
|
+
for (const operation of operations) {
|
|
3368
|
+
const surfaceId = getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;
|
|
3369
|
+
if (!groups.has(surfaceId)) groups.set(surfaceId, []);
|
|
3370
|
+
groups.get(surfaceId).push(operation);
|
|
3371
|
+
}
|
|
3372
|
+
return groups;
|
|
3373
|
+
}, [operations]);
|
|
3374
|
+
const hasOps = groupedOperations.size > 0;
|
|
3375
|
+
const renderLifecycle = (c) => {
|
|
3376
|
+
const status = c?.status;
|
|
3377
|
+
const debugExposure = resolveDebugExposure(c, optionDebugExposure);
|
|
3378
|
+
if (status === "failed") return /* @__PURE__ */ jsx(A2UIRecoveryFailure, {
|
|
3379
|
+
content: c,
|
|
3380
|
+
debugExposure
|
|
3381
|
+
});
|
|
3382
|
+
if (status === "retrying") return /* @__PURE__ */ jsx(A2UIRetryingState, {
|
|
3383
|
+
content: c,
|
|
3384
|
+
showAfterMs,
|
|
3385
|
+
showAfterAttempts,
|
|
3386
|
+
debugExposure
|
|
3387
|
+
});
|
|
3388
|
+
if (loadingComponent) return /* @__PURE__ */ jsx(loadingComponent, {});
|
|
3389
|
+
return /* @__PURE__ */ jsx(A2UIBuildingState, { content: c });
|
|
3390
|
+
};
|
|
3391
|
+
const lastLoaderContentRef = useRef(null);
|
|
3392
|
+
if (!(Array.isArray(content?.[A2UI_OPERATIONS_KEY]) && content[A2UI_OPERATIONS_KEY].length > 0)) lastLoaderContentRef.current = content;
|
|
3393
|
+
const [surfaceReady, setSurfaceReady] = useState(false);
|
|
3394
|
+
const readyRef = useRef(false);
|
|
3395
|
+
const markSurfaceReady = useCallback(() => {
|
|
3396
|
+
if (readyRef.current) return;
|
|
3397
|
+
readyRef.current = true;
|
|
3398
|
+
requestAnimationFrame(() => setSurfaceReady(true));
|
|
3399
|
+
}, []);
|
|
3400
|
+
useEffect(() => {
|
|
3401
|
+
if (!hasOps) {
|
|
3402
|
+
setSurfaceReady(false);
|
|
3403
|
+
readyRef.current = false;
|
|
3404
|
+
return;
|
|
3405
|
+
}
|
|
3406
|
+
const t = setTimeout(() => setSurfaceReady(true), 8e3);
|
|
3407
|
+
return () => clearTimeout(t);
|
|
3408
|
+
}, [hasOps]);
|
|
3409
|
+
if (!hasOps) return renderLifecycle(content);
|
|
3410
|
+
const surfaces = /* @__PURE__ */ jsx("div", {
|
|
3411
|
+
className: "cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6",
|
|
3412
|
+
children: Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => /* @__PURE__ */ jsx(ReactSurfaceHost, {
|
|
3413
|
+
surfaceId,
|
|
3414
|
+
operations: ops,
|
|
3415
|
+
theme,
|
|
3416
|
+
agent,
|
|
3417
|
+
copilotkit,
|
|
3418
|
+
catalog,
|
|
3419
|
+
onReady: markSurfaceReady
|
|
3420
|
+
}, surfaceId))
|
|
3421
|
+
});
|
|
3422
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3423
|
+
style: { position: "relative" },
|
|
3424
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3425
|
+
"aria-hidden": !surfaceReady,
|
|
3426
|
+
style: surfaceReady ? void 0 : {
|
|
3427
|
+
position: "absolute",
|
|
3428
|
+
inset: 0,
|
|
3429
|
+
opacity: 0,
|
|
3430
|
+
pointerEvents: "none"
|
|
3431
|
+
},
|
|
3432
|
+
children: surfaces
|
|
3433
|
+
}), !surfaceReady && renderLifecycle(lastLoaderContentRef.current ?? content)]
|
|
3434
|
+
});
|
|
3435
|
+
}
|
|
3436
|
+
};
|
|
3437
|
+
}
|
|
3438
|
+
/**
|
|
3439
|
+
* Renders a single A2UI surface using the React renderer.
|
|
3440
|
+
* Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
|
|
3441
|
+
*/
|
|
3442
|
+
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit, catalog, onReady }) {
|
|
3443
|
+
return /* @__PURE__ */ jsx("div", {
|
|
3444
|
+
className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
|
|
3445
|
+
children: /* @__PURE__ */ jsxs(A2UIProvider, {
|
|
3446
|
+
onAction: useCallback(async (message) => {
|
|
3447
|
+
if (!agent) return;
|
|
3448
|
+
message.userAction;
|
|
3449
|
+
try {
|
|
3450
|
+
copilotkit.setProperties({
|
|
3451
|
+
...copilotkit.properties,
|
|
3452
|
+
a2uiAction: message
|
|
3453
|
+
});
|
|
3454
|
+
await copilotkit.runAgent({ agent });
|
|
3455
|
+
} finally {
|
|
3456
|
+
if (copilotkit.properties) {
|
|
3457
|
+
const { a2uiAction, ...rest } = copilotkit.properties;
|
|
3458
|
+
copilotkit.setProperties(rest);
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
}, [agent, copilotkit]),
|
|
3462
|
+
theme,
|
|
3463
|
+
catalog,
|
|
3464
|
+
children: [/* @__PURE__ */ jsx(SurfaceMessageProcessor, {
|
|
3465
|
+
surfaceId,
|
|
3466
|
+
operations,
|
|
3467
|
+
onReady
|
|
3468
|
+
}), /* @__PURE__ */ jsx(A2UISurfaceOrError, { surfaceId })]
|
|
3469
|
+
})
|
|
3470
|
+
});
|
|
3471
|
+
}
|
|
3472
|
+
/**
|
|
3473
|
+
* Renders the A2UI surface, or an error message if processing failed.
|
|
3474
|
+
* Must be a child of A2UIProvider to access the error state.
|
|
3475
|
+
*/
|
|
3476
|
+
function A2UISurfaceOrError({ surfaceId }) {
|
|
3477
|
+
const error = useA2UIError();
|
|
3478
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
3479
|
+
className: "cpk:rounded-lg cpk:border cpk:border-red-200 cpk:bg-red-50 cpk:p-3 cpk:text-sm cpk:text-red-700",
|
|
3480
|
+
children: ["A2UI render error: ", error]
|
|
3481
|
+
});
|
|
3482
|
+
return /* @__PURE__ */ jsx(A2UIRenderer, {
|
|
3483
|
+
surfaceId,
|
|
3484
|
+
className: "cpk:flex cpk:flex-1"
|
|
3485
|
+
});
|
|
3486
|
+
}
|
|
3400
3487
|
/**
|
|
3401
|
-
*
|
|
3402
|
-
*
|
|
3488
|
+
* Processes A2UI operations into the provider's message processor.
|
|
3489
|
+
* Must be a child of A2UIProvider to access the actions context.
|
|
3490
|
+
*/
|
|
3491
|
+
function SurfaceMessageProcessor({ surfaceId, operations, onReady }) {
|
|
3492
|
+
const { processMessages, getSurface } = useA2UIActions();
|
|
3493
|
+
const lastHashRef = useRef("");
|
|
3494
|
+
useEffect(() => {
|
|
3495
|
+
const hash = JSON.stringify(operations);
|
|
3496
|
+
if (hash === lastHashRef.current) return;
|
|
3497
|
+
lastHashRef.current = hash;
|
|
3498
|
+
processMessages(getSurface(surfaceId) ? operations.filter((op) => !op?.createSurface) : operations);
|
|
3499
|
+
if (onReady && surfaceHasRenderableContent(operations)) onReady();
|
|
3500
|
+
}, [
|
|
3501
|
+
processMessages,
|
|
3502
|
+
getSurface,
|
|
3503
|
+
surfaceId,
|
|
3504
|
+
operations,
|
|
3505
|
+
onReady
|
|
3506
|
+
]);
|
|
3507
|
+
return null;
|
|
3508
|
+
}
|
|
3509
|
+
/**
|
|
3510
|
+
* Whether the surface's operations are enough to paint a visible card yet.
|
|
3511
|
+
* A data-bound surface references its data via `path` and renders nothing until
|
|
3512
|
+
* the data model has ≥1 value; a static surface (no path refs) paints from its
|
|
3513
|
+
* components alone. Used to time the loader→surface cross-over to actual content
|
|
3514
|
+
* arrival rather than a fixed delay. (OSS-162)
|
|
3515
|
+
*/
|
|
3516
|
+
function surfaceHasRenderableContent(operations) {
|
|
3517
|
+
const componentOps = operations.filter((o) => o?.updateComponents);
|
|
3518
|
+
if (!componentOps.length) return false;
|
|
3519
|
+
if (!JSON.stringify(componentOps).includes("\"path\"")) return true;
|
|
3520
|
+
return operations.some((o) => {
|
|
3521
|
+
const v = o?.updateDataModel?.value;
|
|
3522
|
+
if (!v || typeof v !== "object") return false;
|
|
3523
|
+
return Object.values(v).some((x) => Array.isArray(x) ? x.length > 0 : x !== null && x !== void 0 && x !== "");
|
|
3524
|
+
});
|
|
3525
|
+
}
|
|
3526
|
+
function getOperationSurfaceId(operation) {
|
|
3527
|
+
if (!operation || typeof operation !== "object") return null;
|
|
3528
|
+
if (typeof operation.surfaceId === "string") return operation.surfaceId;
|
|
3529
|
+
return operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3532
|
+
//#endregion
|
|
3533
|
+
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
3534
|
+
/**
|
|
3535
|
+
* Tool name used by the dynamic A2UI generation secondary LLM.
|
|
3536
|
+
*/
|
|
3537
|
+
const RENDER_A2UI_TOOL_NAME = "render_a2ui";
|
|
3538
|
+
/**
|
|
3539
|
+
* Registers a no-op renderer for the `render_a2ui` tool call so its raw streamed
|
|
3540
|
+
* args are never surfaced in the transcript.
|
|
3541
|
+
*
|
|
3542
|
+
* The generation skeleton / retry / failure UX is NO LONGER owned here (OSS-162):
|
|
3543
|
+
* the A2UI middleware drives the whole lifecycle on the `a2ui-surface` activity
|
|
3544
|
+
* (one stable messageId, building → retrying → failed → painted), rendered in
|
|
3545
|
+
* place by `createA2UIMessageRenderer`. Owning a skeleton per tool call caused a
|
|
3546
|
+
* duplicate skeleton on retries / multi-call generations and a skeleton that
|
|
3547
|
+
* lingered after the surface painted — both fixed by retiring it here.
|
|
3403
3548
|
*
|
|
3404
|
-
*
|
|
3405
|
-
*
|
|
3406
|
-
* react-core.ts gives hook-based entries priority over prop-based entries.
|
|
3549
|
+
* Users can still override with their own `useRenderTool({ name: "render_a2ui" })`
|
|
3550
|
+
* (hook-based entries take priority over this prop-based registration).
|
|
3407
3551
|
*/
|
|
3408
3552
|
function A2UIBuiltInToolCallRenderer() {
|
|
3409
3553
|
const { copilotkit } = useCopilotKit();
|
|
@@ -3411,15 +3555,7 @@ function A2UIBuiltInToolCallRenderer() {
|
|
|
3411
3555
|
const renderer = defineToolCallRenderer({
|
|
3412
3556
|
name: RENDER_A2UI_TOOL_NAME,
|
|
3413
3557
|
args: z.any(),
|
|
3414
|
-
render: (
|
|
3415
|
-
if (status === "complete") return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
3416
|
-
const params = parameters;
|
|
3417
|
-
const items = params?.items;
|
|
3418
|
-
if (Array.isArray(items) && items.length > 0) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
3419
|
-
const components = params?.components;
|
|
3420
|
-
if (Array.isArray(components) && components.length > 2) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
3421
|
-
return /* @__PURE__ */ jsx(A2UIProgressIndicator, { parameters });
|
|
3422
|
-
}
|
|
3558
|
+
render: () => /* @__PURE__ */ jsx(Fragment$1, {})
|
|
3423
3559
|
});
|
|
3424
3560
|
const existing = copilotkit._renderToolCalls ?? [];
|
|
3425
3561
|
copilotkit.setRenderToolCalls([...existing.filter((rc) => rc.name !== RENDER_A2UI_TOOL_NAME), renderer]);
|
|
@@ -3556,7 +3692,8 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3556
3692
|
if (runtimeA2UIEnabled) renderers.unshift(createA2UIMessageRenderer({
|
|
3557
3693
|
theme: a2ui?.theme ?? viewerTheme,
|
|
3558
3694
|
catalog: a2ui?.catalog,
|
|
3559
|
-
loadingComponent: a2ui?.loadingComponent
|
|
3695
|
+
loadingComponent: a2ui?.loadingComponent,
|
|
3696
|
+
recovery: a2ui?.recovery
|
|
3560
3697
|
}));
|
|
3561
3698
|
return renderers;
|
|
3562
3699
|
}, [
|
|
@@ -6034,40 +6171,28 @@ const ScrollElementContext = React.createContext(null);
|
|
|
6034
6171
|
* rendered by the {@link IntelligenceIndicator} brain and the default
|
|
6035
6172
|
* value for the `intelligenceIndicator` slot.
|
|
6036
6173
|
*
|
|
6037
|
-
*
|
|
6038
|
-
*
|
|
6039
|
-
*
|
|
6040
|
-
*
|
|
6041
|
-
* length) and the whole SVG rotates — so the viewer sees one
|
|
6042
|
-
* C-shaped arc spinning around the visual center.
|
|
6043
|
-
* 2. **Icon morph (~250 ms).** On status flip the single icon path
|
|
6044
|
-
* interpolates from the arc to a checkmark via CSS `d:` while the
|
|
6045
|
-
* dashed stroke transitions to solid (filling in the gap that was
|
|
6046
|
-
* the spinner's open portion). The SVG rotation animation is
|
|
6047
|
-
* removed; the snap back to identity is masked by the simultaneous
|
|
6048
|
-
* shape change. Chrome and text stay at full opacity throughout.
|
|
6049
|
-
* 3. **Settle (~400 ms, starts at +250 ms).** Chrome (background,
|
|
6050
|
-
* border, shadow, backdrop-blur) fades to zero opacity. The label
|
|
6051
|
-
* and icon stroke color transitions from saturated purple to a
|
|
6052
|
-
* true-neutral gray at 0.8 alpha — no hue cast, reads as "settled
|
|
6053
|
-
* history metadata." The label simultaneously skews to ~10° (a
|
|
6054
|
-
* transform-based italic feel that interpolates smoothly with the
|
|
6055
|
-
* color, rather than the discrete `font-style: italic` snap that
|
|
6056
|
-
* would cause a layout pop). The label text stays put — only its
|
|
6057
|
-
* color and slant change — so there is no "bump" where the brand
|
|
6058
|
-
* text disappears and reappears.
|
|
6059
|
-
*
|
|
6060
|
-
* Hard sequence: stage 3 has a 250 ms transition-delay so it waits
|
|
6061
|
-
* for stage 2 to finish. Total settle time ~650 ms in production.
|
|
6174
|
+
* Layout: a glassmorphism pill (the `__chrome` layer) wrapping an icon
|
|
6175
|
+
* and a label. The icon is two overlaid SVG paths — a spinner arc and a
|
|
6176
|
+
* checkmark — whose geometry lives in each path's `d` ATTRIBUTE so it
|
|
6177
|
+
* renders in every browser (the CSS `d:` property is Chrome-only).
|
|
6062
6178
|
*
|
|
6063
|
-
*
|
|
6064
|
-
*
|
|
6065
|
-
*
|
|
6179
|
+
* Two states, driven by the `data-status` attribute (see globals.css
|
|
6180
|
+
* for the exact timing):
|
|
6181
|
+
* 1. **In-progress.** The arc spins (CSS rotation) inside the pill and
|
|
6182
|
+
* the checkmark is hidden. Label + icon are a saturated purple.
|
|
6183
|
+
* 2. **Finished.** The arc fades out mid-spin while the checkmark draws
|
|
6184
|
+
* itself in upright (animated `stroke-dashoffset`); the pill chrome
|
|
6185
|
+
* fades away; and the label + icon settle from purple to a neutral
|
|
6186
|
+
* gray, with the label slanting slightly (a `transform: skewX`
|
|
6187
|
+
* faux-italic, so it interpolates with the color instead of snapping
|
|
6188
|
+
* and never reflows). The result reads as quiet "history metadata"
|
|
6189
|
+
* rather than an active spinner. The label text itself never changes
|
|
6190
|
+
* — the static check plus the color/slant shift carry the "done"
|
|
6191
|
+
* meaning, so no wording change is needed.
|
|
6066
6192
|
*
|
|
6067
|
-
*
|
|
6068
|
-
*
|
|
6069
|
-
*
|
|
6070
|
-
* any wording change.
|
|
6193
|
+
* All motion is gated behind `prefers-reduced-motion` (globals.css):
|
|
6194
|
+
* when reduced motion is requested the arc does not spin and the two
|
|
6195
|
+
* states swap instantly, without transitions.
|
|
6071
6196
|
*
|
|
6072
6197
|
* Customize via the `intelligenceIndicator` slot on `CopilotChat`:
|
|
6073
6198
|
* a className string restyles the wrapper, a props object tweaks
|
|
@@ -6088,13 +6213,21 @@ function IntelligenceIndicatorView({ message, status, label, className, ...rest
|
|
|
6088
6213
|
"aria-hidden": "true"
|
|
6089
6214
|
}), /* @__PURE__ */ jsxs("span", {
|
|
6090
6215
|
className: "cpk-intelligence-indicator__content",
|
|
6091
|
-
children: [/* @__PURE__ */
|
|
6216
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
6092
6217
|
className: "cpk-intelligence-indicator__icon",
|
|
6093
6218
|
viewBox: "0 0 24 24",
|
|
6094
6219
|
width: "14",
|
|
6095
6220
|
height: "14",
|
|
6096
6221
|
"aria-hidden": "true",
|
|
6097
|
-
children: /* @__PURE__ */ jsx("path", {
|
|
6222
|
+
children: [/* @__PURE__ */ jsx("path", {
|
|
6223
|
+
className: "cpk-intelligence-indicator__icon-arc",
|
|
6224
|
+
pathLength: 1,
|
|
6225
|
+
d: "M 12 3 C 17 3 21 7 21 12 C 21 17 17 21 12 21 C 7 21 3 17 3 12 C 3 7 7 3 12 3"
|
|
6226
|
+
}), /* @__PURE__ */ jsx("path", {
|
|
6227
|
+
className: "cpk-intelligence-indicator__icon-check",
|
|
6228
|
+
pathLength: 1,
|
|
6229
|
+
d: "M 5 12.5 L 9 16.5 L 19 6.5"
|
|
6230
|
+
})]
|
|
6098
6231
|
}), /* @__PURE__ */ jsx("span", {
|
|
6099
6232
|
className: "cpk-intelligence-indicator__label",
|
|
6100
6233
|
children: label
|
|
@@ -6314,6 +6447,58 @@ function IntelligenceIndicator(props) {
|
|
|
6314
6447
|
//#endregion
|
|
6315
6448
|
//#region src/v2/components/chat/CopilotChatMessageView.tsx
|
|
6316
6449
|
/**
|
|
6450
|
+
* Builds a map of message.id → stable per-row React key for an entire message
|
|
6451
|
+
* list. A message's canonical `id` is not stable within a turn: some backends
|
|
6452
|
+
* re-key a message mid-stream (e.g. LangChain replaces its transient
|
|
6453
|
+
* `lc_run--…` streaming id with the provider's final `resp_…` id in the
|
|
6454
|
+
* MESSAGES_SNAPSHOT). Keying rows by `id` made React unmount/remount the row
|
|
6455
|
+
* on that swap — the visible HITL chat flash. Tool-call ids survive the
|
|
6456
|
+
* rename, so an assistant message anchored by a tool call is keyed by its
|
|
6457
|
+
* first tool-call id (`tc:<anchorToolCallId>`); everything else falls back to
|
|
6458
|
+
* `id`.
|
|
6459
|
+
*
|
|
6460
|
+
* Load-bearing assumption: this only helps when the first tool-call id itself
|
|
6461
|
+
* is stable across the rename; backends that re-key tool-call ids mid-stream
|
|
6462
|
+
* still remount.
|
|
6463
|
+
*
|
|
6464
|
+
* Collision rule: two distinct assistant messages can occasionally share a
|
|
6465
|
+
* first-tool-call id (e.g. due to upstream bugs or replayed state). First
|
|
6466
|
+
* occurrence (in list order) claims `tc:<id>`; later collisions fall back to
|
|
6467
|
+
* `message.id`. Every assigned key is checked against the claimed set, so
|
|
6468
|
+
* keys are unique even for pathological ids (e.g. a raw message id beginning
|
|
6469
|
+
* with "tc:"); collisions disambiguate with a deterministic numeric suffix.
|
|
6470
|
+
*
|
|
6471
|
+
* Precondition: callers must pass a deduplicated list (see
|
|
6472
|
+
* `deduplicateMessages`); duplicate message ids would silently overwrite map
|
|
6473
|
+
* entries.
|
|
6474
|
+
*
|
|
6475
|
+
* Order caveat: the collision rule is order-sensitive — if two messages
|
|
6476
|
+
* sharing a first tool-call id swap list positions across renders, the
|
|
6477
|
+
* claimant changes and both rows remount. Acceptable: that situation already
|
|
6478
|
+
* indicates an upstream id bug, and keys remain unique.
|
|
6479
|
+
*/
|
|
6480
|
+
function buildRowRenderKeys(messages) {
|
|
6481
|
+
const keys = /* @__PURE__ */ new Map();
|
|
6482
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
6483
|
+
for (const message of messages) {
|
|
6484
|
+
let candidate;
|
|
6485
|
+
if (message.role === "assistant") {
|
|
6486
|
+
const anchorToolCallId = message.toolCalls?.[0]?.id;
|
|
6487
|
+
if (anchorToolCallId) candidate = `tc:${anchorToolCallId}`;
|
|
6488
|
+
}
|
|
6489
|
+
let assigned = message.id;
|
|
6490
|
+
if (candidate && !claimed.has(candidate)) assigned = candidate;
|
|
6491
|
+
else if (claimed.has(assigned)) {
|
|
6492
|
+
let n = 2;
|
|
6493
|
+
while (claimed.has(`${assigned}:${n}`)) n += 1;
|
|
6494
|
+
assigned = `${assigned}:${n}`;
|
|
6495
|
+
}
|
|
6496
|
+
keys.set(message.id, assigned);
|
|
6497
|
+
claimed.add(assigned);
|
|
6498
|
+
}
|
|
6499
|
+
return keys;
|
|
6500
|
+
}
|
|
6501
|
+
/**
|
|
6317
6502
|
* Resolves a slot value into a { Component, slotProps } pair, handling the three
|
|
6318
6503
|
* slot forms: a component type, a className string, or a partial-props object.
|
|
6319
6504
|
*/
|
|
@@ -6492,6 +6677,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
6492
6677
|
return copilotkit.getStateByRun(config.agentId, config.threadId, resolvedRunId);
|
|
6493
6678
|
};
|
|
6494
6679
|
const deduplicatedMessages = useMemo(() => deduplicateMessages(messages), [messages]);
|
|
6680
|
+
const rowRenderKeys = useMemo(() => buildRowRenderKeys(deduplicatedMessages), [deduplicatedMessages]);
|
|
6495
6681
|
if (process.env.NODE_ENV === "development" && deduplicatedMessages.length < messages.length) console.warn(`CopilotChatMessageView: Merged ${messages.length - deduplicatedMessages.length} message(s) with duplicate IDs.`);
|
|
6496
6682
|
const { Component: AssistantComponent, slotProps: assistantSlotProps } = useMemo(() => resolveSlotComponent(assistantMessage, CopilotChatAssistantMessage_default), [assistantMessage]);
|
|
6497
6683
|
const { Component: UserComponent, slotProps: userSlotProps } = useMemo(() => resolveSlotComponent(userMessage, CopilotChatUserMessage_default), [userMessage]);
|
|
@@ -6522,41 +6708,42 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
6522
6708
|
const renderMessageBlock = (message) => {
|
|
6523
6709
|
const elements = [];
|
|
6524
6710
|
const stateSnapshot = getStateSnapshotForMessage(message.id);
|
|
6711
|
+
const rowKey = rowRenderKeys.get(message.id) ?? message.id;
|
|
6525
6712
|
if (renderCustomMessage) elements.push(/* @__PURE__ */ jsx(MemoizedCustomMessage, {
|
|
6526
6713
|
message,
|
|
6527
6714
|
position: "before",
|
|
6528
6715
|
renderCustomMessage,
|
|
6529
6716
|
stateSnapshot
|
|
6530
|
-
}, `${
|
|
6717
|
+
}, `${rowKey}-custom-before`));
|
|
6531
6718
|
if (message.role === "assistant") elements.push(/* @__PURE__ */ jsx(MemoizedAssistantMessage, {
|
|
6532
6719
|
message,
|
|
6533
6720
|
messages,
|
|
6534
6721
|
isRunning,
|
|
6535
6722
|
AssistantMessageComponent: AssistantComponent,
|
|
6536
6723
|
slotProps: assistantSlotProps
|
|
6537
|
-
},
|
|
6724
|
+
}, rowKey));
|
|
6538
6725
|
else if (message.role === "user") elements.push(/* @__PURE__ */ jsx(MemoizedUserMessage, {
|
|
6539
6726
|
message,
|
|
6540
6727
|
UserMessageComponent: UserComponent,
|
|
6541
6728
|
slotProps: userSlotProps
|
|
6542
|
-
},
|
|
6729
|
+
}, rowKey));
|
|
6543
6730
|
else if (message.role === "activity") elements.push(/* @__PURE__ */ jsx(MemoizedActivityMessage, {
|
|
6544
6731
|
message,
|
|
6545
6732
|
renderActivityMessage
|
|
6546
|
-
},
|
|
6733
|
+
}, rowKey));
|
|
6547
6734
|
else if (message.role === "reasoning") elements.push(/* @__PURE__ */ jsx(MemoizedReasoningMessage, {
|
|
6548
6735
|
message,
|
|
6549
6736
|
messages,
|
|
6550
6737
|
isRunning,
|
|
6551
6738
|
ReasoningMessageComponent: ReasoningComponent,
|
|
6552
6739
|
slotProps: reasoningSlotProps
|
|
6553
|
-
},
|
|
6740
|
+
}, rowKey));
|
|
6554
6741
|
if (renderCustomMessage) elements.push(/* @__PURE__ */ jsx(MemoizedCustomMessage, {
|
|
6555
6742
|
message,
|
|
6556
6743
|
position: "after",
|
|
6557
6744
|
renderCustomMessage,
|
|
6558
6745
|
stateSnapshot
|
|
6559
|
-
}, `${
|
|
6746
|
+
}, `${rowKey}-custom-after`));
|
|
6560
6747
|
const intelligenceTurnId = intelligenceTurnAnchors.get(message.id);
|
|
6561
6748
|
if (intelligenceTurnId !== void 0) elements.push(/* @__PURE__ */ jsx(IntelligenceIndicator, {
|
|
6562
6749
|
message,
|
|
@@ -6602,7 +6789,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
6602
6789
|
transform: `translateY(${virtualItem.start}px)`
|
|
6603
6790
|
},
|
|
6604
6791
|
children: renderMessageBlock(message)
|
|
6605
|
-
}, message.id);
|
|
6792
|
+
}, rowRenderKeys.get(message.id) ?? message.id);
|
|
6606
6793
|
})
|
|
6607
6794
|
}) : messageElements,
|
|
6608
6795
|
interruptElement,
|
|
@@ -9319,7 +9506,7 @@ const getErrorActions = (error) => {
|
|
|
9319
9506
|
} };
|
|
9320
9507
|
case CopilotKitErrorCode.UPGRADE_REQUIRED_ERROR: return { primary: {
|
|
9321
9508
|
label: "Upgrade",
|
|
9322
|
-
onClick: () => window.open("https://
|
|
9509
|
+
onClick: () => window.open("https://dashboard.operations.copilotkit.ai", "_blank", "noopener,noreferrer")
|
|
9323
9510
|
} };
|
|
9324
9511
|
default: return;
|
|
9325
9512
|
}
|
|
@@ -10527,4 +10714,4 @@ function validateProps(props) {
|
|
|
10527
10714
|
|
|
10528
10715
|
//#endregion
|
|
10529
10716
|
export { useHumanInTheLoop as $, INTELLIGENCE_TURN_HEAD as A, CopilotChatToolCallsView as B, CopilotChatToggleButton as C, useCopilotChatConfiguration as Ct, CopilotChatView_default as D, CopilotChat as E, CopilotChatSuggestionPill as F, useLearnFromUserAction as G, useLearningContainers as H, CopilotChatReasoningMessage_default as I, useConfigureSuggestions as J, useThreads$1 as K, CopilotChatUserMessage_default as L, getIntelligenceTurnAnchors as M, IntelligenceIndicatorView as N, CopilotChatAttachmentQueue as O, CopilotChatSuggestionView as P, useAgent as Q, CopilotChatAttachmentRenderer as R, CopilotModalHeader as S, CopilotChatConfigurationProvider as St, DefaultOpenIcon as T, useAttachments as U, useLearningContainersInCurrentThread as V, useLearnFromUserActionInCurrentThread as W, useCapabilities as X, useSuggestions as Y, UseAgentUpdate as Z, WildcardToolCallRender as _, useCopilotKit as _t, ThreadsProvider as a, useAgentContext as at, CopilotPopupView as b, AudioRecorderError as bt, CoAgentStateRendersProvider as c, useSandboxFunctions as ct, shouldShowDevConsole as d, MCPAppsActivityType as dt, useComponent as et, useToast as f, CopilotKitInspector as ft, useCopilotContext as g, defineToolCallRenderer as gt, CopilotContext as h, useRenderTool as ht, ThreadsContext as i, CopilotKitProvider as it, IntelligenceIndicator as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, MCPAppsActivityContentSchema as lt, useCopilotMessagesContext as m, useDefaultRenderTool as mt, defaultCopilotContextCategories as n, useRenderActivityMessage as nt, useThreads as o, createA2UIMessageRenderer as ot, CopilotMessagesContext as p, useRenderToolCall as pt, useInterrupt as q, CoAgentStateRenderBridge as r, useRenderCustomMessages as rt, CoAgentStateRendersContext as s, SandboxFunctionsContext as st, CopilotKit as t, useFrontendTool as tt, useAsyncCallback as u, MCPAppsActivityRenderer as ut, CopilotPopup as v, CopilotKitCoreReact as vt, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotChatAudioRecorder as xt, CopilotSidebar as y, CopilotChatInput_default as yt, CopilotChatAssistantMessage_default as z };
|
|
10530
|
-
//# sourceMappingURL=copilotkit-
|
|
10717
|
+
//# sourceMappingURL=copilotkit-DBOofUYQ.mjs.map
|