@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 CHANGED
@@ -854,8 +854,8 @@ var ChatSender_default = React10.forwardRef(
854
854
  const isFocusedRef = React10.useRef(false);
855
855
  const commandConfigRef = React10.useRef(commandConfig);
856
856
  commandConfigRef.current = commandConfig;
857
- const inputComponent = React10.useCallback(
858
- (inputProps) => /* @__PURE__ */ jsxRuntime.jsx(ChatInput_default, { ...inputProps, commandConfig: commandConfigRef.current }),
857
+ const inputComponent = React10.useMemo(
858
+ () => React10.forwardRef((inputProps, ref2) => /* @__PURE__ */ jsxRuntime.jsx(ChatInput_default, { ...inputProps, ref: ref2, commandConfig: commandConfigRef.current })),
859
859
  []
860
860
  );
861
861
  React10.useEffect(() => {
@@ -3291,6 +3291,135 @@ var A2uiComponents = {
3291
3291
  ReportViewer
3292
3292
  };
3293
3293
 
3294
+ // src/components/CustomComponents/A2uiRuntime/controller/extract.ts
3295
+ var A2UI_TAG_REGEX = /<A2UI\s+id="([^"]*)"\s*>([\s\S]*?)<\/A2UI>/g;
3296
+ function hasA2uiTag(text) {
3297
+ return typeof text === "string" && text.includes("<A2UI");
3298
+ }
3299
+ function parseA2uiTagsFromText(text) {
3300
+ if (!hasA2uiTag(text)) return [];
3301
+ const tags = [];
3302
+ const regex = new RegExp(A2UI_TAG_REGEX);
3303
+ let match;
3304
+ while ((match = regex.exec(text)) !== null) {
3305
+ const tagId = match[1];
3306
+ const json = match[2].trim();
3307
+ if (!json) continue;
3308
+ try {
3309
+ const parsed = JSON.parse(json);
3310
+ const commands = Array.isArray(parsed) ? parsed : [parsed];
3311
+ if (commands.length) tags.push({ tagId, commands });
3312
+ } catch {
3313
+ }
3314
+ }
3315
+ return tags;
3316
+ }
3317
+ function stripA2uiTags(text) {
3318
+ if (!hasA2uiTag(text)) return text;
3319
+ let result = text.replace(A2UI_TAG_REGEX, "");
3320
+ result = result.replace(/<A2UI\b[\s\S]*$/, "");
3321
+ return result.trim();
3322
+ }
3323
+ function splitA2uiTextSegments(text) {
3324
+ if (typeof text !== "string" || !text.includes("<A2UI")) {
3325
+ return text ? [{ type: "text", content: text }] : [];
3326
+ }
3327
+ const segments = [];
3328
+ const regex = new RegExp(A2UI_TAG_REGEX);
3329
+ let lastIndex = 0;
3330
+ let match;
3331
+ while ((match = regex.exec(text)) !== null) {
3332
+ if (match.index > lastIndex) {
3333
+ const before = text.slice(lastIndex, match.index);
3334
+ if (before) segments.push({ type: "text", content: before });
3335
+ }
3336
+ const json = match[2].trim();
3337
+ if (json) {
3338
+ try {
3339
+ const parsed = JSON.parse(json);
3340
+ const commands = Array.isArray(parsed) ? parsed : [parsed];
3341
+ const surfaceIds = commands.map((cmd) => String(cmd?.createSurface?.surfaceId || "").trim()).filter(Boolean);
3342
+ if (surfaceIds.length) {
3343
+ segments.push({ type: "a2ui", surfaceIds });
3344
+ }
3345
+ } catch {
3346
+ }
3347
+ }
3348
+ lastIndex = regex.lastIndex;
3349
+ }
3350
+ if (lastIndex < text.length) {
3351
+ let remaining = text.slice(lastIndex);
3352
+ remaining = remaining.replace(/<A2UI\b[\s\S]*$/, "");
3353
+ if (remaining) segments.push({ type: "text", content: remaining });
3354
+ }
3355
+ return segments.length ? segments : [];
3356
+ }
3357
+ function extractInlineSurfaceIdsFromMessage(message2) {
3358
+ const surfaceIds = /* @__PURE__ */ new Set();
3359
+ const items = Array.isArray(message2?.content) ? message2.content : [];
3360
+ for (const item of items) {
3361
+ if (item?.type !== "text") continue;
3362
+ const text = item.messageContent || item.text || "";
3363
+ if (typeof text !== "string" || !text.includes("<A2UI")) continue;
3364
+ const tags = parseA2uiTagsFromText(text);
3365
+ for (const tag of tags) {
3366
+ for (const cmd of tag.commands) {
3367
+ const sid = String(cmd?.createSurface?.surfaceId || "").trim();
3368
+ if (sid) surfaceIds.add(sid);
3369
+ }
3370
+ }
3371
+ }
3372
+ return surfaceIds;
3373
+ }
3374
+ function extractDismissedSurfaceIdsFromMessages(messages) {
3375
+ const lastCreateIndexBySurface = /* @__PURE__ */ new Map();
3376
+ const lastActionIndexBySurface = /* @__PURE__ */ new Map();
3377
+ for (let messageIndex = 0; messageIndex < messages.length; messageIndex++) {
3378
+ const message2 = messages[messageIndex];
3379
+ const items = Array.isArray(message2?.content) ? message2.content : [];
3380
+ for (const item of items) {
3381
+ if (message2?.role !== 1) {
3382
+ if (item?.type === "a2uiCommand" && item.command) {
3383
+ const surfaceId = String(item.command?.createSurface?.surfaceId || "").trim();
3384
+ if (surfaceId) lastCreateIndexBySurface.set(surfaceId, messageIndex);
3385
+ }
3386
+ if (item?.type === "text") {
3387
+ const text = item.messageContent || item.text || "";
3388
+ if (typeof text === "string" && text.includes("<A2UI")) {
3389
+ const tags = parseA2uiTagsFromText(text);
3390
+ for (const tag of tags) {
3391
+ for (const cmd of tag.commands) {
3392
+ const surfaceId = String(cmd?.createSurface?.surfaceId || "").trim();
3393
+ if (surfaceId) lastCreateIndexBySurface.set(surfaceId, messageIndex);
3394
+ }
3395
+ }
3396
+ }
3397
+ }
3398
+ }
3399
+ if (message2?.role === 1 && item?.type === "text") {
3400
+ const text = item.messageContent || item.text || "";
3401
+ if (typeof text !== "string" || !text.includes("a2ui_action.v1")) continue;
3402
+ try {
3403
+ const parsed = JSON.parse(text.trim());
3404
+ if (parsed?.type !== "a2ui_action.v1") continue;
3405
+ const surfaceId = String(parsed.surfaceId || "").trim();
3406
+ if (!surfaceId) continue;
3407
+ lastActionIndexBySurface.set(surfaceId, messageIndex);
3408
+ } catch {
3409
+ }
3410
+ }
3411
+ }
3412
+ }
3413
+ const dismissed = [];
3414
+ for (const [surfaceId, actionIndex] of lastActionIndexBySurface) {
3415
+ const createIndex = lastCreateIndexBySurface.get(surfaceId);
3416
+ if (createIndex === void 0 || actionIndex > createIndex) {
3417
+ dismissed.push(surfaceId);
3418
+ }
3419
+ }
3420
+ return dismissed;
3421
+ }
3422
+
3294
3423
  // src/components/CustomComponents/A2uiRuntime/controller/meta.ts
3295
3424
  function readProp(current, props, key) {
3296
3425
  return current[key] ?? props?.[key];
@@ -3458,19 +3587,8 @@ function inferModelPathFromSurfaceCommands(surfaceId, commands) {
3458
3587
  });
3459
3588
  return commonParentPath(paths);
3460
3589
  }
3461
- function isSubmitLikeActionName(name) {
3462
- const trimmed = typeof name === "string" ? name.trim() : "";
3463
- return trimmed === "submit" || trimmed === "confirm" || trimmed.startsWith("submit_") || trimmed.endsWith(".confirm");
3464
- }
3465
- function isCancelLikeActionName(name) {
3466
- const trimmed = typeof name === "string" ? name.trim() : "";
3467
- return trimmed === "cancel" || trimmed === "qf.cancel" || trimmed.endsWith(".cancel");
3468
- }
3469
3590
  function shouldOptimisticallyDismissSurface(actionName, context) {
3470
- if (isSubmitLikeActionName(actionName) || isCancelLikeActionName(actionName)) return true;
3471
- if (actionName === "qf.submit" || actionName === "qf.cancel") return true;
3472
- const submitFlag = context?.submit;
3473
- return submitFlag === true;
3591
+ return true;
3474
3592
  }
3475
3593
  function buildDispatchContext(surfaceId, rawContext, commands) {
3476
3594
  let normalizedContext = normalizeActionContext(rawContext);
@@ -3769,6 +3887,7 @@ function buildWizardUpdateComponentsCommand(schema, stepId) {
3769
3887
  function createA2uiRuntimeState() {
3770
3888
  return {
3771
3889
  processedMessageCursors: [],
3890
+ processedTagIds: [],
3772
3891
  serverCommands: [],
3773
3892
  localCommands: [],
3774
3893
  anchorIndexBySurface: {},
@@ -3790,6 +3909,15 @@ function extractSurfaceId2(command) {
3790
3909
  function getA2uiRuntimeCommands(state) {
3791
3910
  return [...state.serverCommands, ...state.localCommands];
3792
3911
  }
3912
+ function sanitizeA2uiCommands(commands) {
3913
+ return commands.map((cmd) => {
3914
+ if (!cmd || typeof cmd !== "object" || !cmd.updateDataModel) return cmd;
3915
+ const { path } = cmd.updateDataModel;
3916
+ if (typeof path === "string" && path.trim()) return cmd;
3917
+ const { updateDataModel: _, ...rest } = cmd;
3918
+ return rest;
3919
+ });
3920
+ }
3793
3921
  function diffConversationMessages(messages, prevCursors) {
3794
3922
  if (messages.length < prevCursors.length) {
3795
3923
  return { shouldReplayAll: true, nextCursors: [], pendingItems: [] };
@@ -3828,6 +3956,57 @@ function initializeWizardSurface(state, surfaceId, effects, nextWizardSteps) {
3828
3956
  nextWizardSteps[surfaceId] = firstStepId.trim();
3829
3957
  }
3830
3958
  }
3959
+ function processA2uiCommand(cmd, messageIndex, messageId, nextState, effects, deletedSurfaceIds, nextWizardSteps) {
3960
+ nextState.serverCommands.push(cmd);
3961
+ nextState.lastA2uiHost = { id: messageId, index: messageIndex };
3962
+ const surfaceId = extractSurfaceId2(cmd);
3963
+ if (!surfaceId) return;
3964
+ if (cmd?.createSurface) {
3965
+ nextState.anchorIndexBySurface[surfaceId] = messageIndex;
3966
+ } else if (nextState.anchorIndexBySurface[surfaceId] === void 0 && !cmd?.deleteSurface) {
3967
+ nextState.anchorIndexBySurface[surfaceId] = messageIndex;
3968
+ }
3969
+ if (cmd?.createSurface) {
3970
+ nextState.latestCreateCommandIndexBySurface[surfaceId] = nextState.serverCommands.length - 1;
3971
+ nextState.optimisticallyDismissedSurfaceIds = nextState.optimisticallyDismissedSurfaceIds.filter((id) => id !== surfaceId);
3972
+ initializeWizardSurface(nextState, surfaceId, effects, nextWizardSteps);
3973
+ }
3974
+ if (cmd?.updateDataModel) {
3975
+ const { path, value } = cmd.updateDataModel;
3976
+ if (typeof path === "string" && path.trim() && value && typeof value === "object" && !Array.isArray(value)) {
3977
+ effects.push({ type: "write-model", modelPath: path, values: value });
3978
+ }
3979
+ }
3980
+ if (cmd?.deleteSurface) {
3981
+ deletedSurfaceIds.add(surfaceId);
3982
+ const modelPath = nextState.modelPathBySurface[surfaceId];
3983
+ if (modelPath) effects.push({ type: "clear-model", modelPath });
3984
+ delete nextState.initializedWizardRevisionBySurface[surfaceId];
3985
+ delete nextState.modelPathBySurface[surfaceId];
3986
+ }
3987
+ }
3988
+ function scanA2uiTagsFromMessages(messages, processedTagIds) {
3989
+ const newTags = [];
3990
+ const newTagIds = [];
3991
+ for (let messageIndex = 0; messageIndex < messages.length; messageIndex += 1) {
3992
+ const message2 = messages[messageIndex];
3993
+ const messageId = String(message2?.messageId ?? messageIndex);
3994
+ const items = Array.isArray(message2?.content) ? message2.content : [];
3995
+ for (const item of items) {
3996
+ if (item?.type !== "text") continue;
3997
+ const text = item.messageContent || item.text || "";
3998
+ if (typeof text !== "string" || !text.includes("<A2UI")) continue;
3999
+ const tags = parseA2uiTagsFromText(text);
4000
+ for (const tag of tags) {
4001
+ if (processedTagIds.has(tag.tagId)) continue;
4002
+ processedTagIds.add(tag.tagId);
4003
+ newTagIds.push(tag.tagId);
4004
+ newTags.push({ commands: tag.commands, messageIndex, messageId });
4005
+ }
4006
+ }
4007
+ }
4008
+ return { newTags, newTagIds };
4009
+ }
3831
4010
  function reduceA2uiRuntimeMessages(state, messages) {
3832
4011
  const { shouldReplayAll, pendingItems, nextCursors } = diffConversationMessages(messages || [], state.processedMessageCursors);
3833
4012
  const itemsToProcess = shouldReplayAll ? messages.flatMap((message2, messageIndex) => {
@@ -3835,11 +4014,14 @@ function reduceA2uiRuntimeMessages(state, messages) {
3835
4014
  const items = Array.isArray(message2?.content) ? message2.content : [];
3836
4015
  return items.map((item) => ({ messageIndex, messageId, item }));
3837
4016
  }) : pendingItems;
3838
- if (!shouldReplayAll && itemsToProcess.length === 0) {
4017
+ const tagProcessedSet = new Set(shouldReplayAll ? [] : state.processedTagIds);
4018
+ const { newTags, newTagIds } = scanA2uiTagsFromMessages(messages || [], tagProcessedSet);
4019
+ if (!shouldReplayAll && itemsToProcess.length === 0 && newTags.length === 0) {
3839
4020
  return { state, effects: [] };
3840
4021
  }
3841
4022
  const nextState = shouldReplayAll ? createA2uiRuntimeState() : { ...state };
3842
4023
  nextState.processedMessageCursors = shouldReplayAll ? [] : [...state.processedMessageCursors];
4024
+ nextState.processedTagIds = shouldReplayAll ? [] : [...state.processedTagIds, ...newTagIds];
3843
4025
  nextState.serverCommands = shouldReplayAll ? [] : [...state.serverCommands];
3844
4026
  nextState.localCommands = shouldReplayAll ? [] : [...state.localCommands];
3845
4027
  nextState.anchorIndexBySurface = shouldReplayAll ? {} : { ...state.anchorIndexBySurface };
@@ -3862,24 +4044,13 @@ function reduceA2uiRuntimeMessages(state, messages) {
3862
4044
  }
3863
4045
  return;
3864
4046
  }
3865
- if (item?.type !== "a2uiCommand" || !item.command) return;
3866
- nextState.serverCommands.push(item.command);
3867
- nextState.lastA2uiHost = { id: messageId, index: messageIndex };
3868
- const surfaceId = extractSurfaceId2(item.command);
3869
- if (!surfaceId) return;
3870
- if (nextState.anchorIndexBySurface[surfaceId] === void 0 && !item.command?.deleteSurface) {
3871
- nextState.anchorIndexBySurface[surfaceId] = messageIndex;
3872
- }
3873
- if (item.command?.createSurface) {
3874
- nextState.latestCreateCommandIndexBySurface[surfaceId] = nextState.serverCommands.length - 1;
3875
- initializeWizardSurface(nextState, surfaceId, effects, nextWizardSteps);
3876
- }
3877
- if (item.command?.deleteSurface) {
3878
- deletedSurfaceIds.add(surfaceId);
3879
- const modelPath = nextState.modelPathBySurface[surfaceId];
3880
- if (modelPath) effects.push({ type: "clear-model", modelPath });
3881
- delete nextState.initializedWizardRevisionBySurface[surfaceId];
3882
- delete nextState.modelPathBySurface[surfaceId];
4047
+ if (item?.type === "a2uiCommand" && item.command) {
4048
+ processA2uiCommand(item.command, messageIndex, messageId, nextState, effects, deletedSurfaceIds, nextWizardSteps);
4049
+ }
4050
+ });
4051
+ newTags.forEach(({ commands, messageIndex, messageId }) => {
4052
+ for (const cmd of commands) {
4053
+ processA2uiCommand(cmd, messageIndex, messageId, nextState, effects, deletedSurfaceIds, nextWizardSteps);
3883
4054
  }
3884
4055
  });
3885
4056
  nextState.processedMessageCursors = shouldReplayAll ? messages.map((message2, messageIndex) => ({
@@ -3899,7 +4070,7 @@ function reduceA2uiRuntimeMessages(state, messages) {
3899
4070
  return { state: nextState, effects };
3900
4071
  }
3901
4072
  function reduceA2uiRuntimeAction(state, input) {
3902
- const { surfaceId, actionName, rawContext } = input;
4073
+ const { surfaceId, actionName} = input;
3903
4074
  if (!surfaceId) {
3904
4075
  return { state, handled: actionName === "wizard.next" || actionName === "wizard.back" };
3905
4076
  }
@@ -3929,9 +4100,6 @@ function reduceA2uiRuntimeAction(state, input) {
3929
4100
  if (actionName === "wizard.next" || actionName === "wizard.back") {
3930
4101
  return { state, handled: true };
3931
4102
  }
3932
- if (!shouldOptimisticallyDismissSurface(actionName, rawContext)) {
3933
- return { state, handled: false };
3934
- }
3935
4103
  if (state.optimisticallyDismissedSurfaceIds.includes(surfaceId)) {
3936
4104
  return { state, handled: false };
3937
4105
  }
@@ -3947,7 +4115,7 @@ function selectA2uiRuntimeView(state, dismissedSurfaceIds) {
3947
4115
  const mergedDismissedSurfaceIds = Array.from(
3948
4116
  new Set([...dismissedSurfaceIds || [], ...state.optimisticallyDismissedSurfaceIds].filter((surfaceId) => surfaceId?.trim?.()))
3949
4117
  );
3950
- const commands = getA2uiRuntimeCommands(state);
4118
+ const commands = sanitizeA2uiCommands(getA2uiRuntimeCommands(state));
3951
4119
  const visibleSurfaceIds = resolveVisibleSurfaceIds(commands, mergedDismissedSurfaceIds);
3952
4120
  const anchoredSurfaceIdsByMessageIndex = {};
3953
4121
  visibleSurfaceIds.forEach((surfaceId) => {
@@ -3996,12 +4164,20 @@ function useA2uiController(params) {
3996
4164
  applyA2uiRuntimeEffects(result.effects);
3997
4165
  setRuntimeState(result.state);
3998
4166
  }, [conversationMessages, conversationId]);
3999
- const view = React10.useMemo(() => selectA2uiRuntimeView(runtimeState, dismissedSurfaceIds), [runtimeState, dismissedSurfaceIds]);
4167
+ const permanentDismissedSurfaceIds = React10.useMemo(
4168
+ () => extractDismissedSurfaceIdsFromMessages(conversationMessages || []),
4169
+ [conversationMessages]
4170
+ );
4171
+ const mergedDismissedSurfaceIds = React10.useMemo(
4172
+ () => Array.from(/* @__PURE__ */ new Set([...dismissedSurfaceIds || [], ...permanentDismissedSurfaceIds])),
4173
+ [dismissedSurfaceIds, permanentDismissedSurfaceIds]
4174
+ );
4175
+ const view = React10.useMemo(() => selectA2uiRuntimeView(runtimeState, mergedDismissedSurfaceIds), [runtimeState, mergedDismissedSurfaceIds]);
4000
4176
  const handleRuntimeAction = React10.useCallback((payload) => {
4001
4177
  const surfaceId = String(payload?.surfaceId || payload?.cardId || "");
4002
4178
  const name = String(payload?.name || payload?.event?.name || "").trim();
4003
4179
  const rawContext = payload?.context || payload?.event?.context || {};
4004
- const runtimeActionResult = reduceA2uiRuntimeAction(runtimeRef.current, { surfaceId, actionName: name, rawContext });
4180
+ const runtimeActionResult = reduceA2uiRuntimeAction(runtimeRef.current, { surfaceId, actionName: name});
4005
4181
  if (runtimeActionResult.state !== runtimeRef.current) {
4006
4182
  runtimeRef.current = runtimeActionResult.state;
4007
4183
  setRuntimeState(runtimeActionResult.state);
@@ -4028,26 +4204,26 @@ var A2uiRuntimeContext = React10__namespace.default.createContext({
4028
4204
  function useA2uiRuntimeView() {
4029
4205
  return React10__namespace.default.useContext(A2uiRuntimeContext);
4030
4206
  }
4031
- function A2uiMessageCards({ messageIndex }) {
4207
+ function A2uiMessageCards({ messageIndex, message: message2 }) {
4032
4208
  const { surfaceIdsByMessageIndex } = useA2uiRuntimeView();
4033
- const surfaceIds = surfaceIdsByMessageIndex[messageIndex] || [];
4209
+ const allSurfaceIds = surfaceIdsByMessageIndex[messageIndex] || [];
4210
+ const inlineSurfaceIds = message2 ? extractInlineSurfaceIdsFromMessage(message2) : /* @__PURE__ */ new Set();
4211
+ const surfaceIds = allSurfaceIds.filter((id) => !inlineSurfaceIds.has(id));
4034
4212
  if (!surfaceIds.length) return null;
4035
4213
  return /* @__PURE__ */ jsxRuntime.jsx("div", { children: surfaceIds.map((surfaceId) => /* @__PURE__ */ jsxRuntime.jsx(XCard.Card, { id: surfaceId }, surfaceId)) });
4036
4214
  }
4037
4215
 
4038
4216
  // src/components/CustomComponents/A2uiRuntime/renderer/protocol.ts
4039
- function isSubmitLikeActionName2(name) {
4217
+ function isSubmitLikeActionName(name) {
4040
4218
  const normalized = String(name || "").trim();
4041
4219
  return normalized === "submit" || normalized === "confirm" || normalized.startsWith("submit_") || normalized.endsWith(".confirm");
4042
4220
  }
4043
- function isCancelLikeActionName2(name) {
4221
+ function isCancelLikeActionName(name) {
4044
4222
  const normalized = String(name || "").trim();
4045
4223
  return normalized === "cancel" || normalized === "qf.cancel" || normalized.endsWith(".cancel");
4046
4224
  }
4047
4225
  function shouldDismissA2uiSurface(name, context) {
4048
- if (isSubmitLikeActionName2(name) || isCancelLikeActionName2(name)) return true;
4049
- if (name === "qf.submit" || name === "qf.cancel") return true;
4050
- return context?.submit === true;
4226
+ return true;
4051
4227
  }
4052
4228
  function normalizeA2uiActionPayload(payload) {
4053
4229
  return {
@@ -4081,7 +4257,7 @@ function isQuestionActionPayload(payload) {
4081
4257
  const mode = payload.context?.form_mode;
4082
4258
  if (payload.name === "qf.submit" || payload.name === "qf.cancel") return true;
4083
4259
  if (payload.name.startsWith("qf.")) return true;
4084
- return typeof mode === "string" && mode.toLowerCase() === "ephemeral" ? isSubmitLikeActionName2(payload.name) || isCancelLikeActionName2(payload.name) : false;
4260
+ return typeof mode === "string" && mode.toLowerCase() === "ephemeral" ? isSubmitLikeActionName(payload.name) || isCancelLikeActionName(payload.name) : false;
4085
4261
  }
4086
4262
  function formatActionValue(value, displayOverride) {
4087
4263
  if (typeof displayOverride === "string" && displayOverride.trim()) return displayOverride.trim();
@@ -4091,7 +4267,7 @@ function formatActionValue(value, displayOverride) {
4091
4267
  return String(value);
4092
4268
  }
4093
4269
  function buildQuestionSummary(payload) {
4094
- if (isCancelLikeActionName2(payload.name)) return "Question: \u5DF2\u53D6\u6D88";
4270
+ if (isCancelLikeActionName(payload.name)) return "Question: \u5DF2\u53D6\u6D88";
4095
4271
  const values = payload.context.values && typeof payload.context.values === "object" && !Array.isArray(payload.context.values) ? payload.context.values : payload.context;
4096
4272
  const labels = payload.context.labels && typeof payload.context.labels === "object" && !Array.isArray(payload.context.labels) ? payload.context.labels : {};
4097
4273
  const valueLabels = payload.context.valueLabels && typeof payload.context.valueLabels === "object" && !Array.isArray(payload.context.valueLabels) ? payload.context.valueLabels : {};
@@ -4113,10 +4289,22 @@ function formatA2uiActionDisplayText(payload) {
4113
4289
  back_to_params: "\u5DF2\u8FD4\u56DE\u4FEE\u6539\u53C2\u6570",
4114
4290
  confirm: "\u5DF2\u786E\u8BA4\u521B\u5EFA"
4115
4291
  };
4116
- const actionLabel = actionLabels[payload.name] || `\u5DF2\u63D0\u4EA4\u52A8\u4F5C (${payload.name})`;
4292
+ let actionLabel = actionLabels[payload.name];
4293
+ if (!actionLabel) {
4294
+ if (payload.name.startsWith("confirm_")) {
4295
+ actionLabel = "\u5DF2\u9009\u62E9";
4296
+ } else if (payload.name.startsWith("submit_")) {
4297
+ actionLabel = "\u5DF2\u63D0\u4EA4";
4298
+ } else {
4299
+ actionLabel = `\u5DF2\u63D0\u4EA4\u52A8\u4F5C (${payload.name})`;
4300
+ }
4301
+ }
4302
+ const isConfirmLike = payload.name.startsWith("confirm_");
4117
4303
  const details = Object.entries(values).filter(([, value]) => value !== null && value !== void 0 && value !== "").map(([key, value]) => {
4304
+ const formatted = formatActionValue(value, valueLabels[key]);
4305
+ if (isConfirmLike) return formatted;
4118
4306
  const label = typeof labels[key] === "string" && String(labels[key]).trim() ? String(labels[key]).trim() : key;
4119
- return `${label}: ${formatActionValue(value, valueLabels[key])}`;
4307
+ return `${label}: ${formatted}`;
4120
4308
  });
4121
4309
  return details.length ? `${actionLabel}\uFF1A${details.join("\uFF1B ")}` : actionLabel;
4122
4310
  }
@@ -4214,66 +4402,46 @@ function readContextModelPath(context) {
4214
4402
  const path = context?.model && typeof context.model === "object" ? context.model.path : "";
4215
4403
  return typeof path === "string" ? path.trim() : "";
4216
4404
  }
4217
- function diffMessages(messages, prevCursors) {
4218
- if (messages.length < prevCursors.length) {
4219
- return { shouldReplayAll: true, nextCursors: [], pendingItems: [] };
4220
- }
4221
- const nextCursors = [];
4222
- const pendingItems = [];
4223
- for (let messageIndex = 0; messageIndex < messages.length; messageIndex += 1) {
4224
- const message2 = messages[messageIndex];
4225
- const messageId = String(message2?.messageId ?? messageIndex);
4405
+ function buildLatestCommandIndexBySurface(messages) {
4406
+ const indexBySurface = {};
4407
+ let commandIndex = -1;
4408
+ for (const message2 of messages) {
4226
4409
  const items = Array.isArray(message2?.content) ? message2.content : [];
4227
- const prevCursor = prevCursors[messageIndex];
4228
- const startIndex = prevCursor ? prevCursor.contentLength : 0;
4229
- if (prevCursor && (prevCursor.messageId !== messageId || items.length < prevCursor.contentLength)) {
4230
- return { shouldReplayAll: true, nextCursors: [], pendingItems: [] };
4231
- }
4232
- for (let itemIndex = startIndex; itemIndex < items.length; itemIndex += 1) {
4233
- pendingItems.push({ item: items[itemIndex] });
4410
+ for (const item of items) {
4411
+ if (item?.type === "a2uiCommand" && item.command) {
4412
+ commandIndex += 1;
4413
+ const surfaceId = extractSurfaceId3(item.command);
4414
+ if (surfaceId) indexBySurface[surfaceId] = commandIndex;
4415
+ continue;
4416
+ }
4417
+ if (item?.type === "text") {
4418
+ const text = item.messageContent || item.text || "";
4419
+ if (typeof text !== "string" || !text.includes("<A2UI")) continue;
4420
+ const tags = parseA2uiTagsFromText(text);
4421
+ for (const tag of tags) {
4422
+ for (const cmd of tag.commands) {
4423
+ commandIndex += 1;
4424
+ const surfaceId = extractSurfaceId3(cmd);
4425
+ if (surfaceId) indexBySurface[surfaceId] = commandIndex;
4426
+ }
4427
+ }
4428
+ }
4234
4429
  }
4235
- nextCursors.push({ messageId, contentLength: items.length });
4236
4430
  }
4237
- return { shouldReplayAll: false, nextCursors, pendingItems };
4431
+ return indexBySurface;
4238
4432
  }
4239
4433
  function A2uiRuntimeProvider({ messages, children }) {
4240
4434
  const chatStore = useChatStore();
4241
4435
  const conversationState = valtio.useSnapshot(chatStore.conversation);
4242
4436
  const conversationId = conversationState.active.id;
4243
- const processedMessageCursorsRef = React10__namespace.default.useRef([]);
4244
- const latestCommandIndexBySurfaceRef = React10__namespace.default.useRef({});
4245
- const commandIndexRef = React10__namespace.default.useRef(-1);
4246
4437
  const [latestCommandIndexBySurface, setLatestCommandIndexBySurface] = React10__namespace.default.useState({});
4247
4438
  const [dismissedAtBySurface, setDismissedAtBySurface] = React10__namespace.default.useState({});
4248
4439
  React10__namespace.default.useEffect(() => {
4249
- processedMessageCursorsRef.current = [];
4250
- latestCommandIndexBySurfaceRef.current = {};
4251
- commandIndexRef.current = -1;
4252
4440
  setLatestCommandIndexBySurface({});
4253
4441
  setDismissedAtBySurface({});
4254
4442
  }, [conversationId]);
4255
4443
  React10__namespace.default.useEffect(() => {
4256
- const { shouldReplayAll, nextCursors, pendingItems } = diffMessages(messages, processedMessageCursorsRef.current);
4257
- const itemsToProcess = shouldReplayAll ? messages.flatMap((message2) => {
4258
- const items = Array.isArray(message2?.content) ? message2.content : [];
4259
- return items.map((item) => ({ item }));
4260
- }) : pendingItems;
4261
- if (!shouldReplayAll && itemsToProcess.length === 0) return;
4262
- const nextLatestCommandIndexBySurface = shouldReplayAll ? {} : { ...latestCommandIndexBySurfaceRef.current };
4263
- let nextCommandIndex = shouldReplayAll ? -1 : commandIndexRef.current;
4264
- itemsToProcess.forEach(({ item }) => {
4265
- if (item?.type !== "a2uiCommand" || !item.command) return;
4266
- nextCommandIndex += 1;
4267
- const surfaceId = extractSurfaceId3(item.command);
4268
- if (surfaceId) nextLatestCommandIndexBySurface[surfaceId] = nextCommandIndex;
4269
- });
4270
- processedMessageCursorsRef.current = shouldReplayAll ? messages.map((message2, messageIndex) => ({
4271
- messageId: String(message2?.messageId ?? messageIndex),
4272
- contentLength: Array.isArray(message2?.content) ? message2.content.length : 0
4273
- })) : nextCursors;
4274
- latestCommandIndexBySurfaceRef.current = nextLatestCommandIndexBySurface;
4275
- commandIndexRef.current = nextCommandIndex;
4276
- setLatestCommandIndexBySurface(nextLatestCommandIndexBySurface);
4444
+ setLatestCommandIndexBySurface(buildLatestCommandIndexBySurface(messages));
4277
4445
  }, [messages]);
4278
4446
  const dismissedSurfaceIds = React10__namespace.default.useMemo(() => {
4279
4447
  return Object.entries(dismissedAtBySurface).filter(([surfaceId, dismissedAt]) => (latestCommandIndexBySurface[surfaceId] ?? -1) <= dismissedAt).map(([surfaceId]) => surfaceId);
@@ -4402,14 +4570,37 @@ function QuestionSummary({ content }) {
4402
4570
  ] });
4403
4571
  }
4404
4572
  var TextNode2 = React10__namespace.default.memo(
4405
- ({ item, role, customComponents, message: message2 }) => {
4406
- const content = toA2uiDisplayText(role, item?.messageContent);
4407
- if (typeof content === "string" && content.startsWith("Question:")) {
4408
- return /* @__PURE__ */ jsxRuntime.jsx(QuestionSummary, { content });
4573
+ ({
4574
+ item,
4575
+ role,
4576
+ customComponents,
4577
+ message: message2,
4578
+ messageIndex = -1
4579
+ }) => {
4580
+ const { surfaceIdsByMessageIndex } = useA2uiRuntimeView();
4581
+ const rawContent = toA2uiDisplayText(role, item?.messageContent);
4582
+ const segments = splitA2uiTextSegments(rawContent);
4583
+ const visibleSurfaceIds = messageIndex >= 0 ? new Set(surfaceIdsByMessageIndex[messageIndex] || []) : null;
4584
+ const firstSeg = segments[0];
4585
+ const isPureText = segments.length === 0 || segments.length === 1 && firstSeg.type === "text";
4586
+ if (isPureText) {
4587
+ const content = firstSeg && firstSeg.type === "text" ? firstSeg.content : "";
4588
+ if (typeof content === "string" && content.startsWith("Question:")) {
4589
+ return /* @__PURE__ */ jsxRuntime.jsx(QuestionSummary, { content });
4590
+ }
4591
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4592
+ !!item.reasoningContent && /* @__PURE__ */ jsxRuntime.jsx(xV2.Think, { title: "\u6DF1\u5EA6\u601D\u8003", children: item.reasoningContent }),
4593
+ !!content && /* @__PURE__ */ jsxRuntime.jsx(XMarkdown_default, { message: message2, components: customComponents, content })
4594
+ ] });
4409
4595
  }
4410
4596
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4411
4597
  !!item.reasoningContent && /* @__PURE__ */ jsxRuntime.jsx(xV2.Think, { title: "\u6DF1\u5EA6\u601D\u8003", children: item.reasoningContent }),
4412
- !!content && /* @__PURE__ */ jsxRuntime.jsx(XMarkdown_default, { message: message2, components: customComponents, content })
4598
+ segments.map((seg, i) => {
4599
+ if (seg.type === "text") {
4600
+ return seg.content.trim() ? /* @__PURE__ */ jsxRuntime.jsx(XMarkdown_default, { message: message2, components: customComponents, content: seg.content }, `text-${i}`) : null;
4601
+ }
4602
+ return seg.surfaceIds.filter((sid) => !visibleSurfaceIds || visibleSurfaceIds.has(sid)).map((sid) => /* @__PURE__ */ jsxRuntime.jsx(XCard.Card, { id: sid }, `a2ui-${i}-${sid}`));
4603
+ })
4413
4604
  ] });
4414
4605
  }
4415
4606
  );
@@ -4637,6 +4828,12 @@ var MessageRender_default = React10__namespace.default.memo(({ role, message: me
4637
4828
  if (item.type === "plan") {
4638
4829
  return !shouldHideA2uiPlan(item);
4639
4830
  }
4831
+ if (item.type === "text") {
4832
+ const rawText = item.messageContent || item.text || "";
4833
+ const visibleText = stripA2uiTags(rawText);
4834
+ const hasA2uiTag2 = typeof rawText === "string" && rawText.includes("<A2UI");
4835
+ return !!visibleText.trim() || !!item.reasoningContent || hasA2uiTag2;
4836
+ }
4640
4837
  return true;
4641
4838
  });
4642
4839
  }, [loading, message2.content]);
@@ -4665,7 +4862,7 @@ var MessageRender_default = React10__namespace.default.memo(({ role, message: me
4665
4862
  content: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4666
4863
  item.type === "runStarted" && /* @__PURE__ */ jsxRuntime.jsx(RunStartedNode, { loading }, `flow-start-${index}`),
4667
4864
  (item.type === "toolCall" || item.type === "toolResult") && /* @__PURE__ */ jsxRuntime.jsx(tool_call_item_default, { item }, `tool-call-${item.toolCallId || index}`),
4668
- item.type === "text" && /* @__PURE__ */ jsxRuntime.jsx(TextNode2, { item, role: message2.role, customComponents, message: message2 }, `message-${index}`),
4865
+ item.type === "text" && /* @__PURE__ */ jsxRuntime.jsx(TextNode2, { item, role: message2.role, customComponents, message: message2, messageIndex }, `message-${index}`),
4669
4866
  item.type === "stepError" && (item.errorMessage ? /* @__PURE__ */ jsxRuntime.jsx(XMarkdown_default, { message: message2, components: customComponents, content: item.errorMessage }) : null),
4670
4867
  item.type === "files" && /* @__PURE__ */ jsxRuntime.jsx(FilesNode, { item }, `files-${index}`),
4671
4868
  item.type === "plan" && /* @__PURE__ */ jsxRuntime.jsx(A2uiPlanNode, { item }, `plan-${index}`)
@@ -4675,7 +4872,7 @@ var MessageRender_default = React10__namespace.default.memo(({ role, message: me
4675
4872
  );
4676
4873
  }),
4677
4874
  quoteMsg && /* @__PURE__ */ jsxRuntime.jsx(QuoteMsgNode, { quoteMsg, role }),
4678
- messageIndex >= 0 ? /* @__PURE__ */ jsxRuntime.jsx(A2uiMessageCards, { messageIndex }) : null
4875
+ messageIndex >= 0 ? /* @__PURE__ */ jsxRuntime.jsx(A2uiMessageCards, { messageIndex, message: message2 }) : null
4679
4876
  ] });
4680
4877
  });
4681
4878
  var WelcomeItem_default = ({ icon = true, title = true, description = true, prompts = true }) => {