@zero-library/chat-copilot 3.1.6 → 3.1.8
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/index.cjs.js +300 -103
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +301 -104
- package/dist/index.esm.js.map +1 -1
- package/package.json +3 -3
package/dist/index.esm.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Attachments, Sender, FileCard, Bubble, Think, XProvider, Mermaid, CodeH
|
|
|
3
3
|
import { useRefState, useDebounce, createTokenManager, useSyncInput, isEmptyObj, markdownToText, RenderWrapper, shouldRender, isFunction, downloadFile, LuyaFilePreview, MarkdownEditor, useDeepEffect, isObject, useWebSocket, isNullOrUnDef, isNumber, getFileSuffixName, FileIcon, copyText, LazyComponent, isBoolean, UserAvatar, htmlToMarkdown, buildUrlParams, isExternal, deepCopy, transforms, deepMerge, createRequest, HttpStatus, isArray, isString, transform, emit, getWebSocketUrl, safeParseJson } from '@zero-library/common';
|
|
4
4
|
import { App, Badge, Button, Flex, Typography, Tooltip, Layout, Tag, Spin, Splitter, Image as Image$1, Popover, Skeleton, Alert, theme, Collapse, Divider as Divider$1, Select as Select$1, Avatar, Space, Drawer, Empty, Modal, Checkbox, Input, message, List, Card, Table, Progress as Progress$1, Switch as Switch$1 } from 'antd';
|
|
5
5
|
import * as React10 from 'react';
|
|
6
|
-
import React10__default, { createContext, forwardRef, useRef, useEffect, useImperativeHandle, useMemo,
|
|
6
|
+
import React10__default, { createContext, forwardRef, useRef, useEffect, useImperativeHandle, useMemo, memo, useState, useContext, useCallback, useLayoutEffect } from 'react';
|
|
7
7
|
import { useSnapshot, proxy } from 'valtio';
|
|
8
8
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
9
9
|
import { LexicalComposer } from '@lexical/react/LexicalComposer';
|
|
@@ -825,8 +825,8 @@ var ChatSender_default = forwardRef(
|
|
|
825
825
|
const isFocusedRef = useRef(false);
|
|
826
826
|
const commandConfigRef = useRef(commandConfig);
|
|
827
827
|
commandConfigRef.current = commandConfig;
|
|
828
|
-
const inputComponent =
|
|
829
|
-
(inputProps) => /* @__PURE__ */ jsx(ChatInput_default, { ...inputProps, commandConfig: commandConfigRef.current }),
|
|
828
|
+
const inputComponent = useMemo(
|
|
829
|
+
() => forwardRef((inputProps, ref2) => /* @__PURE__ */ jsx(ChatInput_default, { ...inputProps, ref: ref2, commandConfig: commandConfigRef.current })),
|
|
830
830
|
[]
|
|
831
831
|
);
|
|
832
832
|
useEffect(() => {
|
|
@@ -3262,6 +3262,135 @@ var A2uiComponents = {
|
|
|
3262
3262
|
ReportViewer
|
|
3263
3263
|
};
|
|
3264
3264
|
|
|
3265
|
+
// src/components/CustomComponents/A2uiRuntime/controller/extract.ts
|
|
3266
|
+
var A2UI_TAG_REGEX = /<A2UI\s+id="([^"]*)"\s*>([\s\S]*?)<\/A2UI>/g;
|
|
3267
|
+
function hasA2uiTag(text) {
|
|
3268
|
+
return typeof text === "string" && text.includes("<A2UI");
|
|
3269
|
+
}
|
|
3270
|
+
function parseA2uiTagsFromText(text) {
|
|
3271
|
+
if (!hasA2uiTag(text)) return [];
|
|
3272
|
+
const tags = [];
|
|
3273
|
+
const regex = new RegExp(A2UI_TAG_REGEX);
|
|
3274
|
+
let match;
|
|
3275
|
+
while ((match = regex.exec(text)) !== null) {
|
|
3276
|
+
const tagId = match[1];
|
|
3277
|
+
const json = match[2].trim();
|
|
3278
|
+
if (!json) continue;
|
|
3279
|
+
try {
|
|
3280
|
+
const parsed = JSON.parse(json);
|
|
3281
|
+
const commands = Array.isArray(parsed) ? parsed : [parsed];
|
|
3282
|
+
if (commands.length) tags.push({ tagId, commands });
|
|
3283
|
+
} catch {
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3286
|
+
return tags;
|
|
3287
|
+
}
|
|
3288
|
+
function stripA2uiTags(text) {
|
|
3289
|
+
if (!hasA2uiTag(text)) return text;
|
|
3290
|
+
let result = text.replace(A2UI_TAG_REGEX, "");
|
|
3291
|
+
result = result.replace(/<A2UI\b[\s\S]*$/, "");
|
|
3292
|
+
return result.trim();
|
|
3293
|
+
}
|
|
3294
|
+
function splitA2uiTextSegments(text) {
|
|
3295
|
+
if (typeof text !== "string" || !text.includes("<A2UI")) {
|
|
3296
|
+
return text ? [{ type: "text", content: text }] : [];
|
|
3297
|
+
}
|
|
3298
|
+
const segments = [];
|
|
3299
|
+
const regex = new RegExp(A2UI_TAG_REGEX);
|
|
3300
|
+
let lastIndex = 0;
|
|
3301
|
+
let match;
|
|
3302
|
+
while ((match = regex.exec(text)) !== null) {
|
|
3303
|
+
if (match.index > lastIndex) {
|
|
3304
|
+
const before = text.slice(lastIndex, match.index);
|
|
3305
|
+
if (before) segments.push({ type: "text", content: before });
|
|
3306
|
+
}
|
|
3307
|
+
const json = match[2].trim();
|
|
3308
|
+
if (json) {
|
|
3309
|
+
try {
|
|
3310
|
+
const parsed = JSON.parse(json);
|
|
3311
|
+
const commands = Array.isArray(parsed) ? parsed : [parsed];
|
|
3312
|
+
const surfaceIds = commands.map((cmd) => String(cmd?.createSurface?.surfaceId || "").trim()).filter(Boolean);
|
|
3313
|
+
if (surfaceIds.length) {
|
|
3314
|
+
segments.push({ type: "a2ui", surfaceIds });
|
|
3315
|
+
}
|
|
3316
|
+
} catch {
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
lastIndex = regex.lastIndex;
|
|
3320
|
+
}
|
|
3321
|
+
if (lastIndex < text.length) {
|
|
3322
|
+
let remaining = text.slice(lastIndex);
|
|
3323
|
+
remaining = remaining.replace(/<A2UI\b[\s\S]*$/, "");
|
|
3324
|
+
if (remaining) segments.push({ type: "text", content: remaining });
|
|
3325
|
+
}
|
|
3326
|
+
return segments.length ? segments : [];
|
|
3327
|
+
}
|
|
3328
|
+
function extractInlineSurfaceIdsFromMessage(message2) {
|
|
3329
|
+
const surfaceIds = /* @__PURE__ */ new Set();
|
|
3330
|
+
const items = Array.isArray(message2?.content) ? message2.content : [];
|
|
3331
|
+
for (const item of items) {
|
|
3332
|
+
if (item?.type !== "text") continue;
|
|
3333
|
+
const text = item.messageContent || item.text || "";
|
|
3334
|
+
if (typeof text !== "string" || !text.includes("<A2UI")) continue;
|
|
3335
|
+
const tags = parseA2uiTagsFromText(text);
|
|
3336
|
+
for (const tag of tags) {
|
|
3337
|
+
for (const cmd of tag.commands) {
|
|
3338
|
+
const sid = String(cmd?.createSurface?.surfaceId || "").trim();
|
|
3339
|
+
if (sid) surfaceIds.add(sid);
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
return surfaceIds;
|
|
3344
|
+
}
|
|
3345
|
+
function extractDismissedSurfaceIdsFromMessages(messages) {
|
|
3346
|
+
const lastCreateIndexBySurface = /* @__PURE__ */ new Map();
|
|
3347
|
+
const lastActionIndexBySurface = /* @__PURE__ */ new Map();
|
|
3348
|
+
for (let messageIndex = 0; messageIndex < messages.length; messageIndex++) {
|
|
3349
|
+
const message2 = messages[messageIndex];
|
|
3350
|
+
const items = Array.isArray(message2?.content) ? message2.content : [];
|
|
3351
|
+
for (const item of items) {
|
|
3352
|
+
if (message2?.role !== 1) {
|
|
3353
|
+
if (item?.type === "a2uiCommand" && item.command) {
|
|
3354
|
+
const surfaceId = String(item.command?.createSurface?.surfaceId || "").trim();
|
|
3355
|
+
if (surfaceId) lastCreateIndexBySurface.set(surfaceId, messageIndex);
|
|
3356
|
+
}
|
|
3357
|
+
if (item?.type === "text") {
|
|
3358
|
+
const text = item.messageContent || item.text || "";
|
|
3359
|
+
if (typeof text === "string" && text.includes("<A2UI")) {
|
|
3360
|
+
const tags = parseA2uiTagsFromText(text);
|
|
3361
|
+
for (const tag of tags) {
|
|
3362
|
+
for (const cmd of tag.commands) {
|
|
3363
|
+
const surfaceId = String(cmd?.createSurface?.surfaceId || "").trim();
|
|
3364
|
+
if (surfaceId) lastCreateIndexBySurface.set(surfaceId, messageIndex);
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
if (message2?.role === 1 && item?.type === "text") {
|
|
3371
|
+
const text = item.messageContent || item.text || "";
|
|
3372
|
+
if (typeof text !== "string" || !text.includes("a2ui_action.v1")) continue;
|
|
3373
|
+
try {
|
|
3374
|
+
const parsed = JSON.parse(text.trim());
|
|
3375
|
+
if (parsed?.type !== "a2ui_action.v1") continue;
|
|
3376
|
+
const surfaceId = String(parsed.surfaceId || "").trim();
|
|
3377
|
+
if (!surfaceId) continue;
|
|
3378
|
+
lastActionIndexBySurface.set(surfaceId, messageIndex);
|
|
3379
|
+
} catch {
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
const dismissed = [];
|
|
3385
|
+
for (const [surfaceId, actionIndex] of lastActionIndexBySurface) {
|
|
3386
|
+
const createIndex = lastCreateIndexBySurface.get(surfaceId);
|
|
3387
|
+
if (createIndex === void 0 || actionIndex > createIndex) {
|
|
3388
|
+
dismissed.push(surfaceId);
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
return dismissed;
|
|
3392
|
+
}
|
|
3393
|
+
|
|
3265
3394
|
// src/components/CustomComponents/A2uiRuntime/controller/meta.ts
|
|
3266
3395
|
function readProp(current, props, key) {
|
|
3267
3396
|
return current[key] ?? props?.[key];
|
|
@@ -3429,19 +3558,8 @@ function inferModelPathFromSurfaceCommands(surfaceId, commands) {
|
|
|
3429
3558
|
});
|
|
3430
3559
|
return commonParentPath(paths);
|
|
3431
3560
|
}
|
|
3432
|
-
function isSubmitLikeActionName(name) {
|
|
3433
|
-
const trimmed = typeof name === "string" ? name.trim() : "";
|
|
3434
|
-
return trimmed === "submit" || trimmed === "confirm" || trimmed.startsWith("submit_") || trimmed.endsWith(".confirm");
|
|
3435
|
-
}
|
|
3436
|
-
function isCancelLikeActionName(name) {
|
|
3437
|
-
const trimmed = typeof name === "string" ? name.trim() : "";
|
|
3438
|
-
return trimmed === "cancel" || trimmed === "qf.cancel" || trimmed.endsWith(".cancel");
|
|
3439
|
-
}
|
|
3440
3561
|
function shouldOptimisticallyDismissSurface(actionName, context) {
|
|
3441
|
-
|
|
3442
|
-
if (actionName === "qf.submit" || actionName === "qf.cancel") return true;
|
|
3443
|
-
const submitFlag = context?.submit;
|
|
3444
|
-
return submitFlag === true;
|
|
3562
|
+
return true;
|
|
3445
3563
|
}
|
|
3446
3564
|
function buildDispatchContext(surfaceId, rawContext, commands) {
|
|
3447
3565
|
let normalizedContext = normalizeActionContext(rawContext);
|
|
@@ -3740,6 +3858,7 @@ function buildWizardUpdateComponentsCommand(schema, stepId) {
|
|
|
3740
3858
|
function createA2uiRuntimeState() {
|
|
3741
3859
|
return {
|
|
3742
3860
|
processedMessageCursors: [],
|
|
3861
|
+
processedTagIds: [],
|
|
3743
3862
|
serverCommands: [],
|
|
3744
3863
|
localCommands: [],
|
|
3745
3864
|
anchorIndexBySurface: {},
|
|
@@ -3761,6 +3880,15 @@ function extractSurfaceId2(command) {
|
|
|
3761
3880
|
function getA2uiRuntimeCommands(state) {
|
|
3762
3881
|
return [...state.serverCommands, ...state.localCommands];
|
|
3763
3882
|
}
|
|
3883
|
+
function sanitizeA2uiCommands(commands) {
|
|
3884
|
+
return commands.map((cmd) => {
|
|
3885
|
+
if (!cmd || typeof cmd !== "object" || !cmd.updateDataModel) return cmd;
|
|
3886
|
+
const { path } = cmd.updateDataModel;
|
|
3887
|
+
if (typeof path === "string" && path.trim()) return cmd;
|
|
3888
|
+
const { updateDataModel: _, ...rest } = cmd;
|
|
3889
|
+
return rest;
|
|
3890
|
+
});
|
|
3891
|
+
}
|
|
3764
3892
|
function diffConversationMessages(messages, prevCursors) {
|
|
3765
3893
|
if (messages.length < prevCursors.length) {
|
|
3766
3894
|
return { shouldReplayAll: true, nextCursors: [], pendingItems: [] };
|
|
@@ -3799,6 +3927,57 @@ function initializeWizardSurface(state, surfaceId, effects, nextWizardSteps) {
|
|
|
3799
3927
|
nextWizardSteps[surfaceId] = firstStepId.trim();
|
|
3800
3928
|
}
|
|
3801
3929
|
}
|
|
3930
|
+
function processA2uiCommand(cmd, messageIndex, messageId, nextState, effects, deletedSurfaceIds, nextWizardSteps) {
|
|
3931
|
+
nextState.serverCommands.push(cmd);
|
|
3932
|
+
nextState.lastA2uiHost = { id: messageId, index: messageIndex };
|
|
3933
|
+
const surfaceId = extractSurfaceId2(cmd);
|
|
3934
|
+
if (!surfaceId) return;
|
|
3935
|
+
if (cmd?.createSurface) {
|
|
3936
|
+
nextState.anchorIndexBySurface[surfaceId] = messageIndex;
|
|
3937
|
+
} else if (nextState.anchorIndexBySurface[surfaceId] === void 0 && !cmd?.deleteSurface) {
|
|
3938
|
+
nextState.anchorIndexBySurface[surfaceId] = messageIndex;
|
|
3939
|
+
}
|
|
3940
|
+
if (cmd?.createSurface) {
|
|
3941
|
+
nextState.latestCreateCommandIndexBySurface[surfaceId] = nextState.serverCommands.length - 1;
|
|
3942
|
+
nextState.optimisticallyDismissedSurfaceIds = nextState.optimisticallyDismissedSurfaceIds.filter((id) => id !== surfaceId);
|
|
3943
|
+
initializeWizardSurface(nextState, surfaceId, effects, nextWizardSteps);
|
|
3944
|
+
}
|
|
3945
|
+
if (cmd?.updateDataModel) {
|
|
3946
|
+
const { path, value } = cmd.updateDataModel;
|
|
3947
|
+
if (typeof path === "string" && path.trim() && value && typeof value === "object" && !Array.isArray(value)) {
|
|
3948
|
+
effects.push({ type: "write-model", modelPath: path, values: value });
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
if (cmd?.deleteSurface) {
|
|
3952
|
+
deletedSurfaceIds.add(surfaceId);
|
|
3953
|
+
const modelPath = nextState.modelPathBySurface[surfaceId];
|
|
3954
|
+
if (modelPath) effects.push({ type: "clear-model", modelPath });
|
|
3955
|
+
delete nextState.initializedWizardRevisionBySurface[surfaceId];
|
|
3956
|
+
delete nextState.modelPathBySurface[surfaceId];
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
function scanA2uiTagsFromMessages(messages, processedTagIds) {
|
|
3960
|
+
const newTags = [];
|
|
3961
|
+
const newTagIds = [];
|
|
3962
|
+
for (let messageIndex = 0; messageIndex < messages.length; messageIndex += 1) {
|
|
3963
|
+
const message2 = messages[messageIndex];
|
|
3964
|
+
const messageId = String(message2?.messageId ?? messageIndex);
|
|
3965
|
+
const items = Array.isArray(message2?.content) ? message2.content : [];
|
|
3966
|
+
for (const item of items) {
|
|
3967
|
+
if (item?.type !== "text") continue;
|
|
3968
|
+
const text = item.messageContent || item.text || "";
|
|
3969
|
+
if (typeof text !== "string" || !text.includes("<A2UI")) continue;
|
|
3970
|
+
const tags = parseA2uiTagsFromText(text);
|
|
3971
|
+
for (const tag of tags) {
|
|
3972
|
+
if (processedTagIds.has(tag.tagId)) continue;
|
|
3973
|
+
processedTagIds.add(tag.tagId);
|
|
3974
|
+
newTagIds.push(tag.tagId);
|
|
3975
|
+
newTags.push({ commands: tag.commands, messageIndex, messageId });
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
}
|
|
3979
|
+
return { newTags, newTagIds };
|
|
3980
|
+
}
|
|
3802
3981
|
function reduceA2uiRuntimeMessages(state, messages) {
|
|
3803
3982
|
const { shouldReplayAll, pendingItems, nextCursors } = diffConversationMessages(messages || [], state.processedMessageCursors);
|
|
3804
3983
|
const itemsToProcess = shouldReplayAll ? messages.flatMap((message2, messageIndex) => {
|
|
@@ -3806,11 +3985,14 @@ function reduceA2uiRuntimeMessages(state, messages) {
|
|
|
3806
3985
|
const items = Array.isArray(message2?.content) ? message2.content : [];
|
|
3807
3986
|
return items.map((item) => ({ messageIndex, messageId, item }));
|
|
3808
3987
|
}) : pendingItems;
|
|
3809
|
-
|
|
3988
|
+
const tagProcessedSet = new Set(shouldReplayAll ? [] : state.processedTagIds);
|
|
3989
|
+
const { newTags, newTagIds } = scanA2uiTagsFromMessages(messages || [], tagProcessedSet);
|
|
3990
|
+
if (!shouldReplayAll && itemsToProcess.length === 0 && newTags.length === 0) {
|
|
3810
3991
|
return { state, effects: [] };
|
|
3811
3992
|
}
|
|
3812
3993
|
const nextState = shouldReplayAll ? createA2uiRuntimeState() : { ...state };
|
|
3813
3994
|
nextState.processedMessageCursors = shouldReplayAll ? [] : [...state.processedMessageCursors];
|
|
3995
|
+
nextState.processedTagIds = shouldReplayAll ? [] : [...state.processedTagIds, ...newTagIds];
|
|
3814
3996
|
nextState.serverCommands = shouldReplayAll ? [] : [...state.serverCommands];
|
|
3815
3997
|
nextState.localCommands = shouldReplayAll ? [] : [...state.localCommands];
|
|
3816
3998
|
nextState.anchorIndexBySurface = shouldReplayAll ? {} : { ...state.anchorIndexBySurface };
|
|
@@ -3833,24 +4015,13 @@ function reduceA2uiRuntimeMessages(state, messages) {
|
|
|
3833
4015
|
}
|
|
3834
4016
|
return;
|
|
3835
4017
|
}
|
|
3836
|
-
if (item?.type
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
nextState
|
|
3843
|
-
}
|
|
3844
|
-
if (item.command?.createSurface) {
|
|
3845
|
-
nextState.latestCreateCommandIndexBySurface[surfaceId] = nextState.serverCommands.length - 1;
|
|
3846
|
-
initializeWizardSurface(nextState, surfaceId, effects, nextWizardSteps);
|
|
3847
|
-
}
|
|
3848
|
-
if (item.command?.deleteSurface) {
|
|
3849
|
-
deletedSurfaceIds.add(surfaceId);
|
|
3850
|
-
const modelPath = nextState.modelPathBySurface[surfaceId];
|
|
3851
|
-
if (modelPath) effects.push({ type: "clear-model", modelPath });
|
|
3852
|
-
delete nextState.initializedWizardRevisionBySurface[surfaceId];
|
|
3853
|
-
delete nextState.modelPathBySurface[surfaceId];
|
|
4018
|
+
if (item?.type === "a2uiCommand" && item.command) {
|
|
4019
|
+
processA2uiCommand(item.command, messageIndex, messageId, nextState, effects, deletedSurfaceIds, nextWizardSteps);
|
|
4020
|
+
}
|
|
4021
|
+
});
|
|
4022
|
+
newTags.forEach(({ commands, messageIndex, messageId }) => {
|
|
4023
|
+
for (const cmd of commands) {
|
|
4024
|
+
processA2uiCommand(cmd, messageIndex, messageId, nextState, effects, deletedSurfaceIds, nextWizardSteps);
|
|
3854
4025
|
}
|
|
3855
4026
|
});
|
|
3856
4027
|
nextState.processedMessageCursors = shouldReplayAll ? messages.map((message2, messageIndex) => ({
|
|
@@ -3870,7 +4041,7 @@ function reduceA2uiRuntimeMessages(state, messages) {
|
|
|
3870
4041
|
return { state: nextState, effects };
|
|
3871
4042
|
}
|
|
3872
4043
|
function reduceA2uiRuntimeAction(state, input) {
|
|
3873
|
-
const { surfaceId, actionName
|
|
4044
|
+
const { surfaceId, actionName} = input;
|
|
3874
4045
|
if (!surfaceId) {
|
|
3875
4046
|
return { state, handled: actionName === "wizard.next" || actionName === "wizard.back" };
|
|
3876
4047
|
}
|
|
@@ -3900,9 +4071,6 @@ function reduceA2uiRuntimeAction(state, input) {
|
|
|
3900
4071
|
if (actionName === "wizard.next" || actionName === "wizard.back") {
|
|
3901
4072
|
return { state, handled: true };
|
|
3902
4073
|
}
|
|
3903
|
-
if (!shouldOptimisticallyDismissSurface(actionName, rawContext)) {
|
|
3904
|
-
return { state, handled: false };
|
|
3905
|
-
}
|
|
3906
4074
|
if (state.optimisticallyDismissedSurfaceIds.includes(surfaceId)) {
|
|
3907
4075
|
return { state, handled: false };
|
|
3908
4076
|
}
|
|
@@ -3918,7 +4086,7 @@ function selectA2uiRuntimeView(state, dismissedSurfaceIds) {
|
|
|
3918
4086
|
const mergedDismissedSurfaceIds = Array.from(
|
|
3919
4087
|
new Set([...dismissedSurfaceIds || [], ...state.optimisticallyDismissedSurfaceIds].filter((surfaceId) => surfaceId?.trim?.()))
|
|
3920
4088
|
);
|
|
3921
|
-
const commands = getA2uiRuntimeCommands(state);
|
|
4089
|
+
const commands = sanitizeA2uiCommands(getA2uiRuntimeCommands(state));
|
|
3922
4090
|
const visibleSurfaceIds = resolveVisibleSurfaceIds(commands, mergedDismissedSurfaceIds);
|
|
3923
4091
|
const anchoredSurfaceIdsByMessageIndex = {};
|
|
3924
4092
|
visibleSurfaceIds.forEach((surfaceId) => {
|
|
@@ -3967,12 +4135,20 @@ function useA2uiController(params) {
|
|
|
3967
4135
|
applyA2uiRuntimeEffects(result.effects);
|
|
3968
4136
|
setRuntimeState(result.state);
|
|
3969
4137
|
}, [conversationMessages, conversationId]);
|
|
3970
|
-
const
|
|
4138
|
+
const permanentDismissedSurfaceIds = useMemo(
|
|
4139
|
+
() => extractDismissedSurfaceIdsFromMessages(conversationMessages || []),
|
|
4140
|
+
[conversationMessages]
|
|
4141
|
+
);
|
|
4142
|
+
const mergedDismissedSurfaceIds = useMemo(
|
|
4143
|
+
() => Array.from(/* @__PURE__ */ new Set([...dismissedSurfaceIds || [], ...permanentDismissedSurfaceIds])),
|
|
4144
|
+
[dismissedSurfaceIds, permanentDismissedSurfaceIds]
|
|
4145
|
+
);
|
|
4146
|
+
const view = useMemo(() => selectA2uiRuntimeView(runtimeState, mergedDismissedSurfaceIds), [runtimeState, mergedDismissedSurfaceIds]);
|
|
3971
4147
|
const handleRuntimeAction = useCallback((payload) => {
|
|
3972
4148
|
const surfaceId = String(payload?.surfaceId || payload?.cardId || "");
|
|
3973
4149
|
const name = String(payload?.name || payload?.event?.name || "").trim();
|
|
3974
4150
|
const rawContext = payload?.context || payload?.event?.context || {};
|
|
3975
|
-
const runtimeActionResult = reduceA2uiRuntimeAction(runtimeRef.current, { surfaceId, actionName: name
|
|
4151
|
+
const runtimeActionResult = reduceA2uiRuntimeAction(runtimeRef.current, { surfaceId, actionName: name});
|
|
3976
4152
|
if (runtimeActionResult.state !== runtimeRef.current) {
|
|
3977
4153
|
runtimeRef.current = runtimeActionResult.state;
|
|
3978
4154
|
setRuntimeState(runtimeActionResult.state);
|
|
@@ -3999,26 +4175,26 @@ var A2uiRuntimeContext = React10__default.createContext({
|
|
|
3999
4175
|
function useA2uiRuntimeView() {
|
|
4000
4176
|
return React10__default.useContext(A2uiRuntimeContext);
|
|
4001
4177
|
}
|
|
4002
|
-
function A2uiMessageCards({ messageIndex }) {
|
|
4178
|
+
function A2uiMessageCards({ messageIndex, message: message2 }) {
|
|
4003
4179
|
const { surfaceIdsByMessageIndex } = useA2uiRuntimeView();
|
|
4004
|
-
const
|
|
4180
|
+
const allSurfaceIds = surfaceIdsByMessageIndex[messageIndex] || [];
|
|
4181
|
+
const inlineSurfaceIds = message2 ? extractInlineSurfaceIdsFromMessage(message2) : /* @__PURE__ */ new Set();
|
|
4182
|
+
const surfaceIds = allSurfaceIds.filter((id) => !inlineSurfaceIds.has(id));
|
|
4005
4183
|
if (!surfaceIds.length) return null;
|
|
4006
4184
|
return /* @__PURE__ */ jsx("div", { children: surfaceIds.map((surfaceId) => /* @__PURE__ */ jsx(XCard.Card, { id: surfaceId }, surfaceId)) });
|
|
4007
4185
|
}
|
|
4008
4186
|
|
|
4009
4187
|
// src/components/CustomComponents/A2uiRuntime/renderer/protocol.ts
|
|
4010
|
-
function
|
|
4188
|
+
function isSubmitLikeActionName(name) {
|
|
4011
4189
|
const normalized = String(name || "").trim();
|
|
4012
4190
|
return normalized === "submit" || normalized === "confirm" || normalized.startsWith("submit_") || normalized.endsWith(".confirm");
|
|
4013
4191
|
}
|
|
4014
|
-
function
|
|
4192
|
+
function isCancelLikeActionName(name) {
|
|
4015
4193
|
const normalized = String(name || "").trim();
|
|
4016
4194
|
return normalized === "cancel" || normalized === "qf.cancel" || normalized.endsWith(".cancel");
|
|
4017
4195
|
}
|
|
4018
4196
|
function shouldDismissA2uiSurface(name, context) {
|
|
4019
|
-
|
|
4020
|
-
if (name === "qf.submit" || name === "qf.cancel") return true;
|
|
4021
|
-
return context?.submit === true;
|
|
4197
|
+
return true;
|
|
4022
4198
|
}
|
|
4023
4199
|
function normalizeA2uiActionPayload(payload) {
|
|
4024
4200
|
return {
|
|
@@ -4052,7 +4228,7 @@ function isQuestionActionPayload(payload) {
|
|
|
4052
4228
|
const mode = payload.context?.form_mode;
|
|
4053
4229
|
if (payload.name === "qf.submit" || payload.name === "qf.cancel") return true;
|
|
4054
4230
|
if (payload.name.startsWith("qf.")) return true;
|
|
4055
|
-
return typeof mode === "string" && mode.toLowerCase() === "ephemeral" ?
|
|
4231
|
+
return typeof mode === "string" && mode.toLowerCase() === "ephemeral" ? isSubmitLikeActionName(payload.name) || isCancelLikeActionName(payload.name) : false;
|
|
4056
4232
|
}
|
|
4057
4233
|
function formatActionValue(value, displayOverride) {
|
|
4058
4234
|
if (typeof displayOverride === "string" && displayOverride.trim()) return displayOverride.trim();
|
|
@@ -4062,7 +4238,7 @@ function formatActionValue(value, displayOverride) {
|
|
|
4062
4238
|
return String(value);
|
|
4063
4239
|
}
|
|
4064
4240
|
function buildQuestionSummary(payload) {
|
|
4065
|
-
if (
|
|
4241
|
+
if (isCancelLikeActionName(payload.name)) return "Question: \u5DF2\u53D6\u6D88";
|
|
4066
4242
|
const values = payload.context.values && typeof payload.context.values === "object" && !Array.isArray(payload.context.values) ? payload.context.values : payload.context;
|
|
4067
4243
|
const labels = payload.context.labels && typeof payload.context.labels === "object" && !Array.isArray(payload.context.labels) ? payload.context.labels : {};
|
|
4068
4244
|
const valueLabels = payload.context.valueLabels && typeof payload.context.valueLabels === "object" && !Array.isArray(payload.context.valueLabels) ? payload.context.valueLabels : {};
|
|
@@ -4084,10 +4260,22 @@ function formatA2uiActionDisplayText(payload) {
|
|
|
4084
4260
|
back_to_params: "\u5DF2\u8FD4\u56DE\u4FEE\u6539\u53C2\u6570",
|
|
4085
4261
|
confirm: "\u5DF2\u786E\u8BA4\u521B\u5EFA"
|
|
4086
4262
|
};
|
|
4087
|
-
|
|
4263
|
+
let actionLabel = actionLabels[payload.name];
|
|
4264
|
+
if (!actionLabel) {
|
|
4265
|
+
if (payload.name.startsWith("confirm_")) {
|
|
4266
|
+
actionLabel = "\u5DF2\u9009\u62E9";
|
|
4267
|
+
} else if (payload.name.startsWith("submit_")) {
|
|
4268
|
+
actionLabel = "\u5DF2\u63D0\u4EA4";
|
|
4269
|
+
} else {
|
|
4270
|
+
actionLabel = `\u5DF2\u63D0\u4EA4\u52A8\u4F5C (${payload.name})`;
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
const isConfirmLike = payload.name.startsWith("confirm_");
|
|
4088
4274
|
const details = Object.entries(values).filter(([, value]) => value !== null && value !== void 0 && value !== "").map(([key, value]) => {
|
|
4275
|
+
const formatted = formatActionValue(value, valueLabels[key]);
|
|
4276
|
+
if (isConfirmLike) return formatted;
|
|
4089
4277
|
const label = typeof labels[key] === "string" && String(labels[key]).trim() ? String(labels[key]).trim() : key;
|
|
4090
|
-
return `${label}: ${
|
|
4278
|
+
return `${label}: ${formatted}`;
|
|
4091
4279
|
});
|
|
4092
4280
|
return details.length ? `${actionLabel}\uFF1A${details.join("\uFF1B ")}` : actionLabel;
|
|
4093
4281
|
}
|
|
@@ -4185,66 +4373,46 @@ function readContextModelPath(context) {
|
|
|
4185
4373
|
const path = context?.model && typeof context.model === "object" ? context.model.path : "";
|
|
4186
4374
|
return typeof path === "string" ? path.trim() : "";
|
|
4187
4375
|
}
|
|
4188
|
-
function
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
const nextCursors = [];
|
|
4193
|
-
const pendingItems = [];
|
|
4194
|
-
for (let messageIndex = 0; messageIndex < messages.length; messageIndex += 1) {
|
|
4195
|
-
const message2 = messages[messageIndex];
|
|
4196
|
-
const messageId = String(message2?.messageId ?? messageIndex);
|
|
4376
|
+
function buildLatestCommandIndexBySurface(messages) {
|
|
4377
|
+
const indexBySurface = {};
|
|
4378
|
+
let commandIndex = -1;
|
|
4379
|
+
for (const message2 of messages) {
|
|
4197
4380
|
const items = Array.isArray(message2?.content) ? message2.content : [];
|
|
4198
|
-
const
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4381
|
+
for (const item of items) {
|
|
4382
|
+
if (item?.type === "a2uiCommand" && item.command) {
|
|
4383
|
+
commandIndex += 1;
|
|
4384
|
+
const surfaceId = extractSurfaceId3(item.command);
|
|
4385
|
+
if (surfaceId) indexBySurface[surfaceId] = commandIndex;
|
|
4386
|
+
continue;
|
|
4387
|
+
}
|
|
4388
|
+
if (item?.type === "text") {
|
|
4389
|
+
const text = item.messageContent || item.text || "";
|
|
4390
|
+
if (typeof text !== "string" || !text.includes("<A2UI")) continue;
|
|
4391
|
+
const tags = parseA2uiTagsFromText(text);
|
|
4392
|
+
for (const tag of tags) {
|
|
4393
|
+
for (const cmd of tag.commands) {
|
|
4394
|
+
commandIndex += 1;
|
|
4395
|
+
const surfaceId = extractSurfaceId3(cmd);
|
|
4396
|
+
if (surfaceId) indexBySurface[surfaceId] = commandIndex;
|
|
4397
|
+
}
|
|
4398
|
+
}
|
|
4399
|
+
}
|
|
4205
4400
|
}
|
|
4206
|
-
nextCursors.push({ messageId, contentLength: items.length });
|
|
4207
4401
|
}
|
|
4208
|
-
return
|
|
4402
|
+
return indexBySurface;
|
|
4209
4403
|
}
|
|
4210
4404
|
function A2uiRuntimeProvider({ messages, children }) {
|
|
4211
4405
|
const chatStore = useChatStore();
|
|
4212
4406
|
const conversationState = useSnapshot(chatStore.conversation);
|
|
4213
4407
|
const conversationId = conversationState.active.id;
|
|
4214
|
-
const processedMessageCursorsRef = React10__default.useRef([]);
|
|
4215
|
-
const latestCommandIndexBySurfaceRef = React10__default.useRef({});
|
|
4216
|
-
const commandIndexRef = React10__default.useRef(-1);
|
|
4217
4408
|
const [latestCommandIndexBySurface, setLatestCommandIndexBySurface] = React10__default.useState({});
|
|
4218
4409
|
const [dismissedAtBySurface, setDismissedAtBySurface] = React10__default.useState({});
|
|
4219
4410
|
React10__default.useEffect(() => {
|
|
4220
|
-
processedMessageCursorsRef.current = [];
|
|
4221
|
-
latestCommandIndexBySurfaceRef.current = {};
|
|
4222
|
-
commandIndexRef.current = -1;
|
|
4223
4411
|
setLatestCommandIndexBySurface({});
|
|
4224
4412
|
setDismissedAtBySurface({});
|
|
4225
4413
|
}, [conversationId]);
|
|
4226
4414
|
React10__default.useEffect(() => {
|
|
4227
|
-
|
|
4228
|
-
const itemsToProcess = shouldReplayAll ? messages.flatMap((message2) => {
|
|
4229
|
-
const items = Array.isArray(message2?.content) ? message2.content : [];
|
|
4230
|
-
return items.map((item) => ({ item }));
|
|
4231
|
-
}) : pendingItems;
|
|
4232
|
-
if (!shouldReplayAll && itemsToProcess.length === 0) return;
|
|
4233
|
-
const nextLatestCommandIndexBySurface = shouldReplayAll ? {} : { ...latestCommandIndexBySurfaceRef.current };
|
|
4234
|
-
let nextCommandIndex = shouldReplayAll ? -1 : commandIndexRef.current;
|
|
4235
|
-
itemsToProcess.forEach(({ item }) => {
|
|
4236
|
-
if (item?.type !== "a2uiCommand" || !item.command) return;
|
|
4237
|
-
nextCommandIndex += 1;
|
|
4238
|
-
const surfaceId = extractSurfaceId3(item.command);
|
|
4239
|
-
if (surfaceId) nextLatestCommandIndexBySurface[surfaceId] = nextCommandIndex;
|
|
4240
|
-
});
|
|
4241
|
-
processedMessageCursorsRef.current = shouldReplayAll ? messages.map((message2, messageIndex) => ({
|
|
4242
|
-
messageId: String(message2?.messageId ?? messageIndex),
|
|
4243
|
-
contentLength: Array.isArray(message2?.content) ? message2.content.length : 0
|
|
4244
|
-
})) : nextCursors;
|
|
4245
|
-
latestCommandIndexBySurfaceRef.current = nextLatestCommandIndexBySurface;
|
|
4246
|
-
commandIndexRef.current = nextCommandIndex;
|
|
4247
|
-
setLatestCommandIndexBySurface(nextLatestCommandIndexBySurface);
|
|
4415
|
+
setLatestCommandIndexBySurface(buildLatestCommandIndexBySurface(messages));
|
|
4248
4416
|
}, [messages]);
|
|
4249
4417
|
const dismissedSurfaceIds = React10__default.useMemo(() => {
|
|
4250
4418
|
return Object.entries(dismissedAtBySurface).filter(([surfaceId, dismissedAt]) => (latestCommandIndexBySurface[surfaceId] ?? -1) <= dismissedAt).map(([surfaceId]) => surfaceId);
|
|
@@ -4373,14 +4541,37 @@ function QuestionSummary({ content }) {
|
|
|
4373
4541
|
] });
|
|
4374
4542
|
}
|
|
4375
4543
|
var TextNode2 = React10__default.memo(
|
|
4376
|
-
({
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4544
|
+
({
|
|
4545
|
+
item,
|
|
4546
|
+
role,
|
|
4547
|
+
customComponents,
|
|
4548
|
+
message: message2,
|
|
4549
|
+
messageIndex = -1
|
|
4550
|
+
}) => {
|
|
4551
|
+
const { surfaceIdsByMessageIndex } = useA2uiRuntimeView();
|
|
4552
|
+
const rawContent = toA2uiDisplayText(role, item?.messageContent);
|
|
4553
|
+
const segments = splitA2uiTextSegments(rawContent);
|
|
4554
|
+
const visibleSurfaceIds = messageIndex >= 0 ? new Set(surfaceIdsByMessageIndex[messageIndex] || []) : null;
|
|
4555
|
+
const firstSeg = segments[0];
|
|
4556
|
+
const isPureText = segments.length === 0 || segments.length === 1 && firstSeg.type === "text";
|
|
4557
|
+
if (isPureText) {
|
|
4558
|
+
const content = firstSeg && firstSeg.type === "text" ? firstSeg.content : "";
|
|
4559
|
+
if (typeof content === "string" && content.startsWith("Question:")) {
|
|
4560
|
+
return /* @__PURE__ */ jsx(QuestionSummary, { content });
|
|
4561
|
+
}
|
|
4562
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4563
|
+
!!item.reasoningContent && /* @__PURE__ */ jsx(Think, { title: "\u6DF1\u5EA6\u601D\u8003", children: item.reasoningContent }),
|
|
4564
|
+
!!content && /* @__PURE__ */ jsx(XMarkdown_default, { message: message2, components: customComponents, content })
|
|
4565
|
+
] });
|
|
4380
4566
|
}
|
|
4381
4567
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4382
4568
|
!!item.reasoningContent && /* @__PURE__ */ jsx(Think, { title: "\u6DF1\u5EA6\u601D\u8003", children: item.reasoningContent }),
|
|
4383
|
-
|
|
4569
|
+
segments.map((seg, i) => {
|
|
4570
|
+
if (seg.type === "text") {
|
|
4571
|
+
return seg.content.trim() ? /* @__PURE__ */ jsx(XMarkdown_default, { message: message2, components: customComponents, content: seg.content }, `text-${i}`) : null;
|
|
4572
|
+
}
|
|
4573
|
+
return seg.surfaceIds.filter((sid) => !visibleSurfaceIds || visibleSurfaceIds.has(sid)).map((sid) => /* @__PURE__ */ jsx(XCard.Card, { id: sid }, `a2ui-${i}-${sid}`));
|
|
4574
|
+
})
|
|
4384
4575
|
] });
|
|
4385
4576
|
}
|
|
4386
4577
|
);
|
|
@@ -4608,6 +4799,12 @@ var MessageRender_default = React10__default.memo(({ role, message: message2, me
|
|
|
4608
4799
|
if (item.type === "plan") {
|
|
4609
4800
|
return !shouldHideA2uiPlan(item);
|
|
4610
4801
|
}
|
|
4802
|
+
if (item.type === "text") {
|
|
4803
|
+
const rawText = item.messageContent || item.text || "";
|
|
4804
|
+
const visibleText = stripA2uiTags(rawText);
|
|
4805
|
+
const hasA2uiTag2 = typeof rawText === "string" && rawText.includes("<A2UI");
|
|
4806
|
+
return !!visibleText.trim() || !!item.reasoningContent || hasA2uiTag2;
|
|
4807
|
+
}
|
|
4611
4808
|
return true;
|
|
4612
4809
|
});
|
|
4613
4810
|
}, [loading, message2.content]);
|
|
@@ -4636,7 +4833,7 @@ var MessageRender_default = React10__default.memo(({ role, message: message2, me
|
|
|
4636
4833
|
content: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4637
4834
|
item.type === "runStarted" && /* @__PURE__ */ jsx(RunStartedNode, { loading }, `flow-start-${index}`),
|
|
4638
4835
|
(item.type === "toolCall" || item.type === "toolResult") && /* @__PURE__ */ jsx(tool_call_item_default, { item }, `tool-call-${item.toolCallId || index}`),
|
|
4639
|
-
item.type === "text" && /* @__PURE__ */ jsx(TextNode2, { item, role: message2.role, customComponents, message: message2 }, `message-${index}`),
|
|
4836
|
+
item.type === "text" && /* @__PURE__ */ jsx(TextNode2, { item, role: message2.role, customComponents, message: message2, messageIndex }, `message-${index}`),
|
|
4640
4837
|
item.type === "stepError" && (item.errorMessage ? /* @__PURE__ */ jsx(XMarkdown_default, { message: message2, components: customComponents, content: item.errorMessage }) : null),
|
|
4641
4838
|
item.type === "files" && /* @__PURE__ */ jsx(FilesNode, { item }, `files-${index}`),
|
|
4642
4839
|
item.type === "plan" && /* @__PURE__ */ jsx(A2uiPlanNode, { item }, `plan-${index}`)
|
|
@@ -4646,7 +4843,7 @@ var MessageRender_default = React10__default.memo(({ role, message: message2, me
|
|
|
4646
4843
|
);
|
|
4647
4844
|
}),
|
|
4648
4845
|
quoteMsg && /* @__PURE__ */ jsx(QuoteMsgNode, { quoteMsg, role }),
|
|
4649
|
-
messageIndex >= 0 ? /* @__PURE__ */ jsx(A2uiMessageCards, { messageIndex }) : null
|
|
4846
|
+
messageIndex >= 0 ? /* @__PURE__ */ jsx(A2uiMessageCards, { messageIndex, message: message2 }) : null
|
|
4650
4847
|
] });
|
|
4651
4848
|
});
|
|
4652
4849
|
var WelcomeItem_default = ({ icon = true, title = true, description = true, prompts = true }) => {
|