@xinghunm/ai-chat 1.4.3 → 1.5.0

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.js CHANGED
@@ -46,7 +46,7 @@ __export(src_exports, {
46
46
  module.exports = __toCommonJS(src_exports);
47
47
 
48
48
  // src/components/ai-chat/index.tsx
49
- var import_react21 = require("react");
49
+ var import_react22 = require("react");
50
50
  var import_styled17 = __toESM(require("@emotion/styled"));
51
51
  var import_compass_ui4 = require("@xinghunm/compass-ui");
52
52
 
@@ -96,6 +96,7 @@ var DEFAULT_AI_CHAT_LABELS = {
96
96
  questionnaireMultiSelectHint: "Multiple choice",
97
97
  questionnaireOtherOptionLabel: "Other",
98
98
  questionnaireOtherPlaceholder: "Other",
99
+ questionnaireExpired: "Selection expired.",
99
100
  modelLoading: "Loading models...",
100
101
  modelLoadFailed: "Failed to load models",
101
102
  modelUnavailable: "No model available",
@@ -104,7 +105,9 @@ var DEFAULT_AI_CHAT_LABELS = {
104
105
  removeSkillAriaLabel: "Remove skill",
105
106
  sessionHistoryLoading: "Loading conversations...",
106
107
  sessionHistoryLoadFailed: "Failed to load conversations",
107
- sessionHistoryEmpty: "No conversations yet"
108
+ sessionHistoryEmpty: "No conversations yet",
109
+ questionnaireTitle: "Plan Options",
110
+ questionnaireConfirmInTime: "Please confirm within {{seconds}} seconds"
108
111
  };
109
112
 
110
113
  // src/lib/chat-session.ts
@@ -144,6 +147,42 @@ var mergeOlderHistoryMessages = (sessionId, olderMessages, currentMessages) => {
144
147
  );
145
148
  return [...uniqueOlderMessages, ...currentMessages];
146
149
  };
150
+ var mergeLocalQuestionnaireState = (localMessages, incomingMessages) => {
151
+ if (!localMessages?.length)
152
+ return incomingMessages;
153
+ return incomingMessages.map((incomingMsg) => {
154
+ const localMsg = localMessages.find((lm) => lm.id === incomingMsg.id);
155
+ if (!localMsg)
156
+ return incomingMsg;
157
+ if (localMsg.blocks && !incomingMsg.blocks) {
158
+ return {
159
+ ...incomingMsg,
160
+ blocks: localMsg.blocks
161
+ };
162
+ }
163
+ if (localMsg.blocks && incomingMsg.blocks) {
164
+ const nextBlocks = incomingMsg.blocks.map((incomingBlock, index3) => {
165
+ const localBlock = localMsg.blocks?.[index3];
166
+ const isSameQuestionnaire = incomingBlock.type === "questionnaire" && localBlock?.type === "questionnaire" && (localBlock.questionnaire.questionnaireId === incomingBlock.questionnaire.questionnaireId || Boolean(localBlock.questionnaire.blockKey) && localBlock.questionnaire.blockKey === incomingBlock.questionnaire.blockKey);
167
+ if (isSameQuestionnaire) {
168
+ return {
169
+ ...incomingBlock,
170
+ questionnaire: {
171
+ ...incomingBlock.questionnaire,
172
+ questionnaireId: localBlock.questionnaire.questionnaireId ?? incomingBlock.questionnaire.questionnaireId,
173
+ answers: localBlock.questionnaire.answers ?? incomingBlock.questionnaire.answers,
174
+ status: localBlock.questionnaire.status ?? incomingBlock.questionnaire.status,
175
+ statusMessage: localBlock.questionnaire.statusMessage ?? incomingBlock.questionnaire.statusMessage
176
+ }
177
+ };
178
+ }
179
+ return incomingBlock;
180
+ });
181
+ return { ...incomingMsg, blocks: nextBlocks };
182
+ }
183
+ return incomingMsg;
184
+ });
185
+ };
147
186
  var resolveSessionTitleFromMessage = (message) => {
148
187
  const trimmedContent = message.content.trim();
149
188
  if (trimmedContent) {
@@ -262,6 +301,7 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
262
301
  sessionMessageLoadErrorBySession: {},
263
302
  historyMessagePaginationBySession: {},
264
303
  timelineAnchorStateBySession: {},
304
+ newlyCreatedSessionIds: [],
265
305
  // ---- Session management ------------------------------------------------
266
306
  createSession: (session) => {
267
307
  const state = get();
@@ -393,6 +433,7 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
393
433
  delete nextTimelineAnchorStateBySession[previousSessionId];
394
434
  }
395
435
  const nextActiveSessionId = state.activeSessionId === previousSessionId ? nextSessionId : state.activeSessionId;
436
+ const nextNewlyCreatedSessionIds = state.newlyCreatedSessionIds.includes(nextSessionId) ? state.newlyCreatedSessionIds : [...state.newlyCreatedSessionIds.filter((id) => id !== previousSessionId), nextSessionId];
396
437
  set({
397
438
  sessions: nextSessions,
398
439
  messagesBySession: nextMessagesBySession,
@@ -404,7 +445,8 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
404
445
  sessionMessageLoadErrorBySession: nextSessionMessageLoadErrorBySession,
405
446
  historyMessagePaginationBySession: nextHistoryMessagePaginationBySession,
406
447
  timelineAnchorStateBySession: nextTimelineAnchorStateBySession,
407
- activeSessionId: nextActiveSessionId
448
+ activeSessionId: nextActiveSessionId,
449
+ newlyCreatedSessionIds: nextNewlyCreatedSessionIds
408
450
  });
409
451
  },
410
452
  setPreferredMode: (mode) => {
@@ -421,15 +463,28 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
421
463
  const hasActiveInIncoming = sessions.some(
422
464
  (session) => session.sessionId === state.activeSessionId
423
465
  );
424
- const keepActiveSession = activePersistedSession && !hasActiveInIncoming ? [activePersistedSession] : [];
466
+ let prependActiveSession = [];
467
+ let appendActiveSession = [];
468
+ if (activePersistedSession && !hasActiveInIncoming) {
469
+ const isNewlyCreated = state.newlyCreatedSessionIds.includes(
470
+ activePersistedSession.sessionId
471
+ );
472
+ if (isNewlyCreated) {
473
+ prependActiveSession = [activePersistedSession];
474
+ } else {
475
+ appendActiveSession = [activePersistedSession];
476
+ }
477
+ }
425
478
  const excludeIds = /* @__PURE__ */ new Set([
426
479
  ...draftSessions.map((s) => s.sessionId),
427
- ...keepActiveSession.map((s) => s.sessionId)
480
+ ...prependActiveSession.map((s) => s.sessionId),
481
+ ...appendActiveSession.map((s) => s.sessionId)
428
482
  ]);
429
483
  const nextSessions = [
430
484
  ...draftSessions,
485
+ ...prependActiveSession,
431
486
  ...sessions.filter((session) => !excludeIds.has(session.sessionId)),
432
- ...keepActiveSession
487
+ ...appendActiveSession
433
488
  ];
434
489
  const nextMessagesBySession = { ...state.messagesBySession };
435
490
  const nextErrorBySession = { ...state.errorBySession };
@@ -465,6 +520,10 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
465
520
  nextHistoryMessagePaginationBySession[sid] = createHistoryMessagePaginationState();
466
521
  }
467
522
  });
523
+ const incomingSessionIds = new Set(sessions.map((s) => s.sessionId));
524
+ const nextNewlyCreatedSessionIds = state.newlyCreatedSessionIds.filter(
525
+ (id) => !incomingSessionIds.has(id)
526
+ );
468
527
  set({
469
528
  sessions: nextSessions,
470
529
  messagesBySession: nextMessagesBySession,
@@ -474,7 +533,8 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
474
533
  sessionMessageLoadStatusBySession: nextSessionMessageLoadStatusBySession,
475
534
  sessionMessageLoadErrorBySession: nextSessionMessageLoadErrorBySession,
476
535
  historyMessagePaginationBySession: nextHistoryMessagePaginationBySession,
477
- timelineAnchorStateBySession: nextTimelineAnchorStateBySession
536
+ timelineAnchorStateBySession: nextTimelineAnchorStateBySession,
537
+ newlyCreatedSessionIds: nextNewlyCreatedSessionIds
478
538
  });
479
539
  },
480
540
  // ---- Message operations ------------------------------------------------
@@ -505,10 +565,12 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
505
565
  },
506
566
  hydrateHistorySessionMessages: (sessionId, messages) => {
507
567
  const state = get();
568
+ const localMessages = state.messagesBySession[sessionId] ?? [];
569
+ const nextMessages = mergeLocalQuestionnaireState(localMessages, messages);
508
570
  set({
509
571
  messagesBySession: {
510
572
  ...state.messagesBySession,
511
- [sessionId]: normalizeHistoryMessages(sessionId, messages)
573
+ [sessionId]: normalizeHistoryMessages(sessionId, nextMessages)
512
574
  },
513
575
  sessionMessageLoadStatusBySession: {
514
576
  ...state.sessionMessageLoadStatusBySession,
@@ -526,10 +588,12 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
526
588
  },
527
589
  hydrateHistorySessionMessagesPage: (sessionId, page) => {
528
590
  const state = get();
591
+ const localMessages = state.messagesBySession[sessionId] ?? [];
592
+ const nextMessages = mergeLocalQuestionnaireState(localMessages, page.messages);
529
593
  set({
530
594
  messagesBySession: {
531
595
  ...state.messagesBySession,
532
- [sessionId]: normalizeHistoryMessages(sessionId, page.messages)
596
+ [sessionId]: normalizeHistoryMessages(sessionId, nextMessages)
533
597
  },
534
598
  sessionMessageLoadStatusBySession: {
535
599
  ...state.sessionMessageLoadStatusBySession,
@@ -688,7 +752,11 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
688
752
  hasUpdatedBlock = true;
689
753
  return {
690
754
  ...block,
691
- questionnaire: { ...block.questionnaire, answers: { ...answers } }
755
+ questionnaire: {
756
+ ...block.questionnaire,
757
+ answers: { ...answers },
758
+ status: "submitted"
759
+ }
692
760
  };
693
761
  });
694
762
  if (!hasUpdatedBlock)
@@ -1165,7 +1233,7 @@ var AiChatProvider = (props) => {
1165
1233
  };
1166
1234
 
1167
1235
  // src/components/chat-thread/index.tsx
1168
- var import_react11 = require("react");
1236
+ var import_react12 = require("react");
1169
1237
  var import_styled9 = __toESM(require("@emotion/styled"));
1170
1238
 
1171
1239
  // src/context/use-chat-context.ts
@@ -1186,9 +1254,9 @@ var useChatStore = (selector) => {
1186
1254
  var CHAT_THREAD_SCROLL_TOP_GAP = 16;
1187
1255
 
1188
1256
  // src/components/chat-thread/components/chat-message-item.tsx
1189
- var import_react9 = require("react");
1257
+ var import_react10 = require("react");
1190
1258
  var import_styled7 = __toESM(require("@emotion/styled"));
1191
- var import_react10 = require("@emotion/react");
1259
+ var import_react11 = require("@emotion/react");
1192
1260
  var import_react_markdown = __toESM(require("react-markdown"));
1193
1261
  var import_remark_gfm = __toESM(require("remark-gfm"));
1194
1262
  var import_remark_math = __toESM(require("remark-math"));
@@ -1242,11 +1310,23 @@ var getNextDisplayedUnitCount = ({
1242
1310
  var splitMarkdownBlocks = (content) => content.split(/\n{2,}/).map((block) => block.trim()).filter(Boolean);
1243
1311
 
1244
1312
  // src/components/chat-thread/hooks/use-chat-message-reveal.ts
1313
+ var revealedStreamingMessages = /* @__PURE__ */ new Set();
1314
+ var markMessageAsRevealed = (id) => {
1315
+ if (revealedStreamingMessages.size > 500) {
1316
+ const firstKey = revealedStreamingMessages.keys().next().value;
1317
+ if (firstKey !== void 0) {
1318
+ revealedStreamingMessages.delete(firstKey);
1319
+ }
1320
+ }
1321
+ revealedStreamingMessages.add(id);
1322
+ };
1245
1323
  var createRevealState = ({
1246
1324
  isAssistantStreaming,
1247
- targetUnitCount
1325
+ targetUnitCount,
1326
+ messageId
1248
1327
  }) => {
1249
- const initialDisplayedUnitCount = isAssistantStreaming ? 0 : targetUnitCount;
1328
+ const hasBeenRevealed = revealedStreamingMessages.has(messageId);
1329
+ const initialDisplayedUnitCount = isAssistantStreaming && !hasBeenRevealed ? 0 : targetUnitCount;
1250
1330
  return {
1251
1331
  batchedTargetUnitCount: initialDisplayedUnitCount,
1252
1332
  displayedUnitCount: initialDisplayedUnitCount,
@@ -1256,7 +1336,11 @@ var createRevealState = ({
1256
1336
  var revealReducer = (state, action) => {
1257
1337
  switch (action.type) {
1258
1338
  case "reset-message":
1259
- return createRevealState(action);
1339
+ return createRevealState({
1340
+ isAssistantStreaming: action.isAssistantStreaming,
1341
+ targetUnitCount: action.targetUnitCount,
1342
+ messageId: action.messageId
1343
+ });
1260
1344
  case "commit-batched-target": {
1261
1345
  const nextDisplayedUnitCount = action.role === "assistant" ? getNextDisplayedUnitCount({
1262
1346
  currentUnits: state.displayedUnitCount,
@@ -1313,7 +1397,8 @@ var useChatMessageReveal = (message) => {
1313
1397
  revealReducer,
1314
1398
  {
1315
1399
  isAssistantStreaming,
1316
- targetUnitCount: targetUnits.length
1400
+ targetUnitCount: targetUnits.length,
1401
+ messageId: message.id
1317
1402
  },
1318
1403
  createRevealState
1319
1404
  );
@@ -1345,7 +1430,8 @@ var useChatMessageReveal = (message) => {
1345
1430
  dispatch({
1346
1431
  type: "reset-message",
1347
1432
  isAssistantStreaming,
1348
- targetUnitCount: targetUnits.length
1433
+ targetUnitCount: targetUnits.length,
1434
+ messageId: message.id
1349
1435
  });
1350
1436
  }, [isAssistantStreaming, message.id, targetUnits.length]);
1351
1437
  (0, import_react5.useEffect)(() => {
@@ -1424,6 +1510,11 @@ var useChatMessageReveal = (message) => {
1424
1510
  tone: "settled"
1425
1511
  }
1426
1512
  ];
1513
+ (0, import_react5.useEffect)(() => {
1514
+ if (isAssistantStreaming && displayedUnitCount > 0) {
1515
+ markMessageAsRevealed(message.id);
1516
+ }
1517
+ }, [isAssistantStreaming, displayedUnitCount, message.id]);
1427
1518
  return {
1428
1519
  isAssistantStreaming,
1429
1520
  isFreshBlockActive,
@@ -2014,9 +2105,96 @@ var Value = import_styled3.default.span`
2014
2105
  `;
2015
2106
 
2016
2107
  // src/components/chat-thread/components/questionnaire-card.tsx
2017
- var import_react7 = require("react");
2108
+ var import_react8 = require("react");
2018
2109
  var import_styled4 = __toESM(require("@emotion/styled"));
2019
2110
 
2111
+ // src/components/chat-thread/components/use-countdown-seconds.ts
2112
+ var import_react7 = require("react");
2113
+ var countdownDeadlineByKey = /* @__PURE__ */ new Map();
2114
+ var countdownCleanupTimerByKey = /* @__PURE__ */ new Map();
2115
+ var countdownMountCountByKey = /* @__PURE__ */ new Map();
2116
+ var clearCountdownEntry = (storageKey) => {
2117
+ const cleanupTimerId = countdownCleanupTimerByKey.get(storageKey);
2118
+ if (cleanupTimerId !== void 0) {
2119
+ window.clearTimeout(cleanupTimerId);
2120
+ countdownCleanupTimerByKey.delete(storageKey);
2121
+ }
2122
+ countdownDeadlineByKey.delete(storageKey);
2123
+ };
2124
+ var scheduleCountdownCleanup = (storageKey, deadline) => {
2125
+ const existingCleanupTimerId = countdownCleanupTimerByKey.get(storageKey);
2126
+ if (existingCleanupTimerId !== void 0) {
2127
+ return;
2128
+ }
2129
+ const delayMs = Math.max(0, deadline - Date.now());
2130
+ const cleanupTimerId = window.setTimeout(() => {
2131
+ if ((countdownMountCountByKey.get(storageKey) ?? 0) > 0) {
2132
+ countdownCleanupTimerByKey.delete(storageKey);
2133
+ return;
2134
+ }
2135
+ clearCountdownEntry(storageKey);
2136
+ }, delayMs);
2137
+ countdownCleanupTimerByKey.set(storageKey, cleanupTimerId);
2138
+ };
2139
+ var getCountdownDeadline = (storageKey, initialSeconds) => {
2140
+ const existingDeadline = countdownDeadlineByKey.get(storageKey);
2141
+ if (existingDeadline !== void 0) {
2142
+ return existingDeadline;
2143
+ }
2144
+ const nextDeadline = Date.now() + Math.max(0, initialSeconds) * 1e3;
2145
+ countdownDeadlineByKey.set(storageKey, nextDeadline);
2146
+ scheduleCountdownCleanup(storageKey, nextDeadline);
2147
+ return nextDeadline;
2148
+ };
2149
+ var getRemainingSeconds = (deadline) => Math.max(0, Math.ceil((deadline - Date.now()) / 1e3));
2150
+ var useCountdownSeconds = ({
2151
+ storageKey,
2152
+ initialSeconds,
2153
+ active
2154
+ }) => {
2155
+ const [remainingSeconds, setRemainingSeconds] = (0, import_react7.useState)(
2156
+ () => getRemainingSeconds(getCountdownDeadline(storageKey, initialSeconds))
2157
+ );
2158
+ (0, import_react7.useEffect)(() => {
2159
+ countdownMountCountByKey.set(storageKey, (countdownMountCountByKey.get(storageKey) ?? 0) + 1);
2160
+ return () => {
2161
+ const nextCount = (countdownMountCountByKey.get(storageKey) ?? 1) - 1;
2162
+ if (nextCount <= 0) {
2163
+ countdownMountCountByKey.delete(storageKey);
2164
+ return;
2165
+ }
2166
+ countdownMountCountByKey.set(storageKey, nextCount);
2167
+ };
2168
+ }, [storageKey]);
2169
+ (0, import_react7.useEffect)(() => {
2170
+ setRemainingSeconds(getRemainingSeconds(getCountdownDeadline(storageKey, initialSeconds)));
2171
+ }, [initialSeconds, storageKey]);
2172
+ (0, import_react7.useEffect)(() => {
2173
+ if (active) {
2174
+ return;
2175
+ }
2176
+ clearCountdownEntry(storageKey);
2177
+ }, [active, storageKey]);
2178
+ (0, import_react7.useEffect)(() => {
2179
+ if (remainingSeconds > 0) {
2180
+ return;
2181
+ }
2182
+ clearCountdownEntry(storageKey);
2183
+ }, [remainingSeconds, storageKey]);
2184
+ (0, import_react7.useEffect)(() => {
2185
+ if (!active || remainingSeconds <= 0) {
2186
+ return;
2187
+ }
2188
+ const timeoutId = window.setTimeout(() => {
2189
+ setRemainingSeconds(getRemainingSeconds(getCountdownDeadline(storageKey, initialSeconds)));
2190
+ }, 1e3);
2191
+ return () => {
2192
+ window.clearTimeout(timeoutId);
2193
+ };
2194
+ }, [active, initialSeconds, remainingSeconds, storageKey]);
2195
+ return remainingSeconds;
2196
+ };
2197
+
2020
2198
  // src/components/chat-thread/components/questionnaire-card-helpers.ts
2021
2199
  var OTHER_OPTION_VALUE = "__other__";
2022
2200
  var getQuestionnaireQuestion = (questionnaire) => questionnaire.question;
@@ -2323,7 +2501,10 @@ var DEFAULT_QUESTIONNAIRE_CARD_LABELS = {
2323
2501
  submitFailed: "Failed to submit. Please try again.",
2324
2502
  multiSelectHint: "Multiple choice",
2325
2503
  otherOptionLabel: "Other",
2326
- otherPlaceholder: "Other"
2504
+ otherPlaceholder: "Other",
2505
+ expired: "Selection expired.",
2506
+ questionnaireTitle: "Plan Options",
2507
+ questionnaireConfirmInTime: "Please confirm within {{seconds}} seconds"
2327
2508
  };
2328
2509
  var stopInputClickPropagation = (event) => {
2329
2510
  event.stopPropagation();
@@ -2383,32 +2564,41 @@ var QuestionnaireCardInner = ({
2383
2564
  onSubmit,
2384
2565
  labels
2385
2566
  }) => {
2386
- const questionnaireRef = (0, import_react7.useRef)(questionnaire);
2387
- const otherInputRefs = (0, import_react7.useRef)({});
2388
- const [answers, setAnswers] = (0, import_react7.useState)(
2567
+ const questionnaireRef = (0, import_react8.useRef)(questionnaire);
2568
+ const otherInputRefs = (0, import_react8.useRef)({});
2569
+ const [answers, setAnswers] = (0, import_react8.useState)(
2389
2570
  () => createInitialAnswers(questionnaire)
2390
2571
  );
2391
- const [otherDrafts, setOtherDrafts] = (0, import_react7.useState)(
2572
+ const [otherDrafts, setOtherDrafts] = (0, import_react8.useState)(
2392
2573
  () => createInitialOtherDrafts(questionnaire)
2393
2574
  );
2394
- const [errorMessage, setErrorMessage] = (0, import_react7.useState)(null);
2395
- const [isSubmitting, setIsSubmitting] = (0, import_react7.useState)(false);
2396
- const [isSubmitted, setIsSubmitted] = (0, import_react7.useState)(false);
2397
- const [pendingFocusQuestionId, setPendingFocusQuestionId] = (0, import_react7.useState)(null);
2575
+ const [errorMessage, setErrorMessage] = (0, import_react8.useState)(null);
2576
+ const [isSubmitting, setIsSubmitting] = (0, import_react8.useState)(false);
2577
+ const [isSubmitted, setIsSubmitted] = (0, import_react8.useState)(() => questionnaire.status === "submitted");
2578
+ const [pendingFocusQuestionId, setPendingFocusQuestionId] = (0, import_react8.useState)(null);
2398
2579
  const resolvedLabels = {
2399
2580
  ...DEFAULT_QUESTIONNAIRE_CARD_LABELS,
2400
2581
  ...labels
2401
2582
  };
2402
- const hasExternalFailureStatus = questionnaire.status === "expired" || questionnaire.status === "failed";
2583
+ const remainingSeconds = useCountdownSeconds({
2584
+ storageKey: questionnaire.blockKey ?? `questionnaire:${questionnaire.questionnaireId}`,
2585
+ initialSeconds: questionnaire.timeoutSec ?? 0,
2586
+ active: questionnaire.timeoutSec !== void 0 && questionnaire.timeoutSec > 0 && !isSubmitted && questionnaire.status !== "expired" && questionnaire.status !== "failed" && interactive
2587
+ });
2588
+ const isExpired = questionnaire.status === "expired" || questionnaire.timeoutSec !== void 0 && questionnaire.timeoutSec > 0 && remainingSeconds <= 0;
2589
+ const hasExternalFailureStatus = isExpired || questionnaire.status === "failed";
2403
2590
  const question = getQuestionnaireQuestion(questionnaire);
2404
- const visibleErrorMessage = questionnaire.statusMessage ?? errorMessage;
2405
- const isInteractionLocked = !interactive || isSubmitting || isSubmitted || hasExternalFailureStatus;
2591
+ const visibleErrorMessage = questionnaire.statusMessage ?? (isExpired ? null : errorMessage);
2592
+ const isInteractionLocked = !interactive || isSubmitting || isSubmitted || hasExternalFailureStatus || questionnaire.status === "submitted";
2406
2593
  questionnaireRef.current = questionnaire;
2407
- (0, import_react7.useEffect)(() => {
2594
+ (0, import_react8.useEffect)(() => {
2408
2595
  setAnswers(createInitialAnswers(questionnaireRef.current));
2409
2596
  setOtherDrafts(createInitialOtherDrafts(questionnaireRef.current));
2410
- }, [questionnaire.answers]);
2411
- (0, import_react7.useEffect)(() => {
2597
+ if (questionnaireRef.current.status === "submitted") {
2598
+ setIsSubmitted(true);
2599
+ }
2600
+ }, [questionnaire.answers, questionnaire.status]);
2601
+ (0, import_react8.useEffect)(() => {
2412
2602
  if (!pendingFocusQuestionId || isInteractionLocked) {
2413
2603
  return;
2414
2604
  }
@@ -2658,42 +2848,69 @@ var QuestionnaireCardInner = ({
2658
2848
  }
2659
2849
  };
2660
2850
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Card4, { "data-testid": "questionnaire-card", children: [
2661
- questionnaire.description ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Description, { children: questionnaire.description }) : null,
2662
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionList, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionCard, { children: [
2663
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionLabel, { children: [
2664
- question.label,
2665
- question.required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Required, { children: "*" }) : null
2666
- ] }),
2667
- question.kind === "multi_select" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionHint, { children: resolvedLabels.multiSelectHint }) : null,
2668
- renderQuestion(question)
2669
- ] }, question.id) }),
2670
- visibleErrorMessage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ErrorMessage, { "data-testid": "questionnaire-error", children: visibleErrorMessage }) : null,
2671
- isSubmitted ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SuccessMessage, { "data-testid": "questionnaire-success", children: resolvedLabels.submitted }) : interactive && !hasExternalFailureStatus ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2672
- SubmitButton,
2673
- {
2674
- type: "button",
2675
- "data-testid": "questionnaire-submit",
2676
- disabled: isInteractionLocked,
2677
- onClick: () => {
2678
- void handleSubmit();
2679
- },
2680
- children: isSubmitting ? resolvedLabels.submitting : questionnaire.submitLabel ?? "Submit"
2681
- }
2682
- ) : null
2851
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Header2, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Eyebrow2, { children: resolvedLabels.questionnaireTitle }) }),
2852
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Content, { children: [
2853
+ questionnaire.description ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Description, { children: questionnaire.description }) : null,
2854
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionList, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionCard, { children: [
2855
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionLabel, { children: [
2856
+ question.label,
2857
+ question.required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Required, { children: "*" }) : null
2858
+ ] }),
2859
+ question.kind === "multi_select" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionHint, { children: resolvedLabels.multiSelectHint }) : null,
2860
+ renderQuestion(question)
2861
+ ] }, question.id) }),
2862
+ visibleErrorMessage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ErrorMessage, { "data-testid": "questionnaire-error", children: visibleErrorMessage }) : null,
2863
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Footer, { children: isSubmitted ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SuccessMessage, { "data-testid": "questionnaire-success", children: resolvedLabels.submitted }) : isExpired ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExpiredTag, { "data-testid": "questionnaire-expired", children: resolvedLabels.expired }) : interactive ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(FooterActionRow, { "data-testid": "questionnaire-card-actions", children: [
2864
+ remainingSeconds > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MetaText, { "data-testid": "questionnaire-countdown", children: resolvedLabels.questionnaireConfirmInTime?.replace(
2865
+ "{{seconds}}",
2866
+ String(remainingSeconds)
2867
+ ) ?? `\u8BF7\u5728 ${remainingSeconds} \u79D2\u5185\u786E\u8BA4` }),
2868
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2869
+ SubmitButton,
2870
+ {
2871
+ type: "button",
2872
+ "data-testid": "questionnaire-submit",
2873
+ disabled: isInteractionLocked,
2874
+ onClick: () => {
2875
+ void handleSubmit();
2876
+ },
2877
+ children: isSubmitting ? resolvedLabels.submitting : questionnaire.submitLabel ?? "Submit"
2878
+ }
2879
+ )
2880
+ ] }) : null })
2881
+ ] })
2683
2882
  ] });
2684
2883
  };
2685
2884
  var QuestionnaireCard = (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionnaireCardInner, { ...props }, getQuestionnaireStateKey(props.questionnaire));
2686
2885
  var Card4 = import_styled4.default.section`
2687
- display: grid;
2688
- gap: 14px;
2689
- padding: 16px;
2690
- border-radius: 20px;
2691
- border: 1px solid rgba(255, 255, 255, 0.08);
2692
- background: rgba(255, 255, 255, 0.03);
2886
+ overflow: hidden;
2887
+ background: var(--bg-primary);
2888
+ border-radius: 16px;
2889
+ border: 1px solid var(--border-hover);
2890
+ `;
2891
+ var Header2 = import_styled4.default.div`
2892
+ display: flex;
2893
+ flex-wrap: wrap;
2894
+ align-items: center;
2895
+ gap: 10px;
2896
+ padding: 22px 12px 16px;
2897
+ border-bottom: 1px solid var(--border-hover);
2898
+ `;
2899
+ var Eyebrow2 = import_styled4.default.div`
2900
+ font-weight: 500;
2901
+ font-size: 16px;
2902
+ color: var(--text-primary);
2903
+ line-height: 22px;
2904
+ `;
2905
+ var Content = import_styled4.default.div`
2906
+ display: flex;
2907
+ flex-direction: column;
2908
+ gap: 16px;
2909
+ padding: 16px 12px;
2693
2910
  `;
2694
2911
  var Description = import_styled4.default.p`
2695
2912
  margin: 0;
2696
- color: rgba(255, 255, 255, 0.72);
2913
+ color: var(--text-secondary);
2697
2914
  font-size: 13px;
2698
2915
  `;
2699
2916
  var QuestionList = import_styled4.default.div`
@@ -2704,11 +2921,11 @@ var QuestionCard = import_styled4.default.div`
2704
2921
  display: grid;
2705
2922
  gap: 10px;
2706
2923
  padding: 12px;
2707
- border-radius: 16px;
2708
- background: rgba(255, 255, 255, 0.04);
2924
+ border-radius: 8px;
2925
+ background: rgba(255, 255, 255, 0.02);
2709
2926
  `;
2710
2927
  var QuestionLabel = import_styled4.default.div`
2711
- color: rgba(255, 255, 255, 0.9);
2928
+ color: var(--text-primary);
2712
2929
  font-size: 14px;
2713
2930
  font-weight: 600;
2714
2931
  `;
@@ -2735,11 +2952,11 @@ var OptionChoiceItem = import_styled4.default.div`
2735
2952
  gap: 12px;
2736
2953
  width: 100%;
2737
2954
  text-align: left;
2738
- border: 1px solid rgba(255, 255, 255, 0.1);
2739
- border-radius: 14px;
2740
- background: rgba(255, 255, 255, 0.03);
2955
+ border: 1px solid var(--border-hover);
2956
+ border-radius: 8px;
2957
+ background: rgba(255, 255, 255, 0.02);
2741
2958
  padding: 2px 12px;
2742
- color: rgba(255, 255, 255, 0.9);
2959
+ color: var(--text-primary);
2743
2960
  cursor: pointer;
2744
2961
  transition:
2745
2962
  border-color 140ms ease,
@@ -2748,8 +2965,8 @@ var OptionChoiceItem = import_styled4.default.div`
2748
2965
  outline: none;
2749
2966
 
2750
2967
  &[data-selected='true'] {
2751
- border-color: rgba(126, 160, 255, 0.42);
2752
- background: linear-gradient(180deg, rgba(82, 114, 255, 0.18) 0%, rgba(82, 114, 255, 0.1) 100%);
2968
+ border-color: rgba(51, 133, 255, 0.42);
2969
+ background: linear-gradient(180deg, rgba(51, 133, 255, 0.18) 0%, rgba(51, 133, 255, 0.1) 100%);
2753
2970
  transform: translateY(-1px);
2754
2971
  }
2755
2972
 
@@ -2758,8 +2975,8 @@ var OptionChoiceItem = import_styled4.default.div`
2758
2975
  }
2759
2976
 
2760
2977
  &:focus-visible {
2761
- border-color: rgba(126, 160, 255, 0.52);
2762
- box-shadow: 0 0 0 1px rgba(126, 160, 255, 0.18);
2978
+ border-color: rgba(51, 133, 255, 0.52);
2979
+ box-shadow: 0 0 0 1px rgba(51, 133, 255, 0.18);
2763
2980
  }
2764
2981
 
2765
2982
  &[tabindex='-1'] {
@@ -2776,16 +2993,16 @@ var OptionChoiceMarker = import_styled4.default.span`
2776
2993
  width: 28px;
2777
2994
  height: 28px;
2778
2995
  border-radius: 8px;
2779
- border: 1px solid rgba(255, 255, 255, 0.14);
2780
- background: rgba(255, 255, 255, 0.04);
2781
- color: rgba(255, 255, 255, 0.65);
2996
+ border: 1px solid var(--border-hover);
2997
+ background: rgba(255, 255, 255, 0.02);
2998
+ color: var(--text-secondary);
2782
2999
  font-size: 12px;
2783
3000
  font-weight: 700;
2784
3001
 
2785
3002
  &[data-selected='true'] {
2786
- border-color: rgba(126, 160, 255, 0.38);
2787
- background: rgba(126, 160, 255, 0.2);
2788
- color: rgba(255, 255, 255, 0.96);
3003
+ border-color: rgba(51, 133, 255, 0.38);
3004
+ background: rgba(51, 133, 255, 0.2);
3005
+ color: var(--text-primary);
2789
3006
  }
2790
3007
  `;
2791
3008
  var OptionChoiceContent = import_styled4.default.span`
@@ -2805,47 +3022,41 @@ var OptionChoiceLabel = import_styled4.default.span`
2805
3022
  `;
2806
3023
  var TextInput = import_styled4.default.input`
2807
3024
  width: 100%;
2808
- border: 1px solid rgba(255, 255, 255, 0.1);
2809
- border-radius: 12px;
3025
+ border: 1px solid var(--border-hover);
3026
+ border-radius: 8px;
2810
3027
  background: rgba(13, 15, 21, 0.55);
2811
- color: rgba(255, 255, 255, 0.92);
3028
+ color: var(--text-primary);
2812
3029
  font-size: 13px;
2813
3030
  padding: 10px 12px;
2814
3031
 
2815
3032
  &::placeholder {
2816
- color: rgba(255, 255, 255, 0.34);
3033
+ color: var(--text-secondary);
3034
+ opacity: 0.5;
2817
3035
  }
2818
3036
  `;
2819
3037
  var InlineOtherInput = import_styled4.default.input`
2820
3038
  width: 100%;
2821
- margin-top: 0;
2822
-
2823
- .compass-input-wrapper {
2824
- min-height: 30px;
2825
- border: 1px solid rgba(255, 255, 255, 0.1);
2826
- border-radius: 10px;
2827
- background: rgba(13, 15, 21, 0.55);
2828
- box-shadow: none;
2829
- padding: 2px 9px;
2830
- }
2831
-
2832
- .compass-input-wrapper:hover {
2833
- border-color: rgba(126, 160, 255, 0.28);
2834
- }
3039
+ border: 1px solid var(--border-hover);
3040
+ border-radius: 6px;
3041
+ background: rgba(13, 15, 21, 0.45);
3042
+ color: var(--text-primary);
3043
+ font-size: 13px;
3044
+ padding: 6px 10px;
3045
+ outline: none;
3046
+ transition: border-color 140ms ease;
2835
3047
 
2836
- .compass-input-wrapper:focus-within {
2837
- border-color: rgba(126, 160, 255, 0.42);
2838
- box-shadow: 0 0 0 1px rgba(126, 160, 255, 0.14);
3048
+ &:hover {
3049
+ border-color: rgba(51, 133, 255, 0.28);
2839
3050
  }
2840
3051
 
2841
- .compass-input-input {
2842
- color: rgba(255, 255, 255, 0.92);
2843
- font-size: 13px;
2844
- line-height: 1.2;
3052
+ &:focus {
3053
+ border-color: rgba(51, 133, 255, 0.42);
3054
+ box-shadow: 0 0 0 1px rgba(51, 133, 255, 0.14);
2845
3055
  }
2846
3056
 
2847
- .compass-input-input::placeholder {
2848
- color: rgba(255, 255, 255, 0.34);
3057
+ &::placeholder {
3058
+ color: var(--text-secondary);
3059
+ opacity: 0.5;
2849
3060
  }
2850
3061
  `;
2851
3062
  var NumberInputRow = import_styled4.default.div`
@@ -2854,32 +3065,80 @@ var NumberInputRow = import_styled4.default.div`
2854
3065
  gap: 10px;
2855
3066
  `;
2856
3067
  var Unit = import_styled4.default.span`
2857
- color: rgba(255, 255, 255, 0.58);
3068
+ color: var(--text-secondary);
2858
3069
  font-size: 12px;
2859
3070
  white-space: nowrap;
2860
3071
  `;
2861
3072
  var ErrorMessage = import_styled4.default.div`
2862
- color: rgba(255, 145, 145, 0.96);
3073
+ font-size: 13px;
3074
+ line-height: 1.5;
3075
+ color: rgba(255, 207, 207, 0.92);
3076
+ `;
3077
+ var Footer = import_styled4.default.div`
3078
+ display: flex;
3079
+ flex-wrap: wrap;
3080
+ align-items: center;
3081
+ justify-content: flex-start;
3082
+ gap: 12px;
3083
+ `;
3084
+ var FooterActionRow = import_styled4.default.div`
3085
+ display: flex;
3086
+ align-items: center;
3087
+ flex-wrap: wrap;
3088
+ gap: 8px;
3089
+ margin-left: auto;
3090
+ justify-content: flex-end;
3091
+ `;
3092
+ var MetaText = import_styled4.default.span`
3093
+ font-weight: 500;
2863
3094
  font-size: 12px;
3095
+ color: var(--text-secondary);
3096
+ line-height: 17px;
3097
+ `;
3098
+ var ExpiredTag = import_styled4.default.span`
3099
+ display: inline-flex;
3100
+ align-items: center;
3101
+ padding: 8px 12px;
3102
+ border-radius: 8px;
3103
+ font-size: 13px;
3104
+ font-weight: 600;
3105
+ background: rgba(255, 255, 255, 0.05);
3106
+ border: 1px solid rgba(255, 255, 255, 0.12);
3107
+ color: rgba(214, 224, 236, 0.9);
2864
3108
  `;
2865
3109
  var SuccessMessage = import_styled4.default.div`
2866
- color: rgba(164, 255, 210, 0.96);
2867
- font-size: 12px;
3110
+ display: inline-flex;
3111
+ align-items: center;
3112
+ padding: 8px 12px;
3113
+ border-radius: 8px;
3114
+ font-size: 13px;
3115
+ font-weight: 600;
3116
+ background: rgba(190, 246, 202, 0.14);
3117
+ border: 1px solid rgba(190, 246, 202, 0.24);
3118
+ color: rgba(227, 255, 233, 0.94);
2868
3119
  `;
2869
3120
  var SubmitButton = import_styled4.default.button`
2870
- justify-self: flex-start;
2871
- border: none;
2872
- border-radius: 999px;
2873
- background: linear-gradient(180deg, #7ea0ff 0%, #4a6fff 100%);
2874
- color: #081127;
2875
- font-size: 12px;
2876
- font-weight: 700;
2877
- padding: 10px 14px;
3121
+ padding: 9px 16px;
3122
+ border-radius: 8px;
3123
+ border: 1px solid transparent;
3124
+ font-weight: 500;
3125
+ font-size: 14px;
3126
+ color: rgba(255, 255, 255, 0.96);
3127
+ background: linear-gradient(180deg, #3385ff 0%, #1f6ef2 100%);
3128
+ line-height: 14px;
2878
3129
  cursor: pointer;
3130
+ transition:
3131
+ transform 160ms ease,
3132
+ opacity 160ms ease;
2879
3133
 
2880
3134
  &:disabled {
2881
- cursor: default;
2882
- opacity: 0.72;
3135
+ cursor: progress;
3136
+ opacity: 0.68;
3137
+ transform: none;
3138
+ }
3139
+
3140
+ &:not(:disabled):hover {
3141
+ transform: translateY(-1px);
2883
3142
  }
2884
3143
  `;
2885
3144
 
@@ -2887,7 +3146,7 @@ var SubmitButton = import_styled4.default.button`
2887
3146
  var import_styled5 = __toESM(require("@emotion/styled"));
2888
3147
  var import_jsx_runtime6 = require("@emotion/react/jsx-runtime");
2889
3148
  var ResultSummaryCard = ({ summary }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Card5, { "data-testid": "result-summary-card", "data-status": summary.status, children: [
2890
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Eyebrow2, { children: summary.status }),
3149
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Eyebrow3, { children: summary.status }),
2891
3150
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Headline, { children: summary.headline }),
2892
3151
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Details, { children: summary.details.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Detail, { children: detail }, detail)) })
2893
3152
  ] });
@@ -2907,7 +3166,7 @@ var Card5 = import_styled5.default.section`
2907
3166
  border-color: rgba(255, 122, 122, 0.24);
2908
3167
  }
2909
3168
  `;
2910
- var Eyebrow2 = import_styled5.default.span`
3169
+ var Eyebrow3 = import_styled5.default.span`
2911
3170
  color: rgba(255, 255, 255, 0.58);
2912
3171
  font-size: 11px;
2913
3172
  font-weight: 700;
@@ -2932,7 +3191,7 @@ var Detail = import_styled5.default.li`
2932
3191
 
2933
3192
  // src/components/chat-thread/components/image-viewer.tsx
2934
3193
  var import_styled6 = __toESM(require("@emotion/styled"));
2935
- var import_react8 = require("react");
3194
+ var import_react9 = require("react");
2936
3195
  var import_jsx_runtime7 = require("@emotion/react/jsx-runtime");
2937
3196
  var Overlay = import_styled6.default.div`
2938
3197
  position: fixed;
@@ -2951,8 +3210,8 @@ var Img = import_styled6.default.img`
2951
3210
  border-radius: 4px;
2952
3211
  `;
2953
3212
  var ImageViewer = ({ src, alt, onClose }) => {
2954
- const overlayRef = (0, import_react8.useRef)(null);
2955
- (0, import_react8.useEffect)(() => {
3213
+ const overlayRef = (0, import_react9.useRef)(null);
3214
+ (0, import_react9.useEffect)(() => {
2956
3215
  const handleKey = (e) => {
2957
3216
  if (e.key === "Escape")
2958
3217
  onClose();
@@ -2960,7 +3219,7 @@ var ImageViewer = ({ src, alt, onClose }) => {
2960
3219
  document.addEventListener("keydown", handleKey);
2961
3220
  return () => document.removeEventListener("keydown", handleKey);
2962
3221
  }, [onClose]);
2963
- (0, import_react8.useEffect)(() => {
3222
+ (0, import_react9.useEffect)(() => {
2964
3223
  overlayRef.current?.focus();
2965
3224
  }, []);
2966
3225
  const stopPropagation = (e) => e.stopPropagation();
@@ -3026,10 +3285,10 @@ var useUserMessageCollapse = ({
3026
3285
  freshContent,
3027
3286
  settledContent
3028
3287
  }) => {
3029
- const [isCollapsible, setIsCollapsible] = (0, import_react9.useState)(false);
3030
- const [isExpanded, setIsExpanded] = (0, import_react9.useState)(false);
3031
- const [bodyStackElement, setBodyStackElement] = (0, import_react9.useState)(null);
3032
- const syncCollapseState = (0, import_react9.useCallback)(
3288
+ const [isCollapsible, setIsCollapsible] = (0, import_react10.useState)(false);
3289
+ const [isExpanded, setIsExpanded] = (0, import_react10.useState)(false);
3290
+ const [bodyStackElement, setBodyStackElement] = (0, import_react10.useState)(null);
3291
+ const syncCollapseState = (0, import_react10.useCallback)(
3033
3292
  (element) => {
3034
3293
  const nextCollapsible = enabled && (element?.scrollHeight ?? 0) > USER_MESSAGE_COLLAPSE_HEIGHT_PX;
3035
3294
  setIsCollapsible(nextCollapsible);
@@ -3039,14 +3298,14 @@ var useUserMessageCollapse = ({
3039
3298
  },
3040
3299
  [enabled]
3041
3300
  );
3042
- const bodyStackRef = (0, import_react9.useCallback)(
3301
+ const bodyStackRef = (0, import_react10.useCallback)(
3043
3302
  (node) => {
3044
3303
  setBodyStackElement(node);
3045
3304
  syncCollapseState(node);
3046
3305
  },
3047
3306
  [syncCollapseState]
3048
3307
  );
3049
- (0, import_react9.useLayoutEffect)(() => {
3308
+ (0, import_react10.useLayoutEffect)(() => {
3050
3309
  if (!bodyStackElement) {
3051
3310
  return;
3052
3311
  }
@@ -3066,7 +3325,7 @@ var useUserMessageCollapse = ({
3066
3325
  settledContent,
3067
3326
  syncCollapseState
3068
3327
  ]);
3069
- (0, import_react9.useLayoutEffect)(() => {
3328
+ (0, import_react10.useLayoutEffect)(() => {
3070
3329
  if (!bodyStackElement || !enabled || typeof ResizeObserver === "undefined") {
3071
3330
  return;
3072
3331
  }
@@ -3214,7 +3473,7 @@ var ChatMessageItemView = ({
3214
3473
  renderMessageBlock
3215
3474
  }) => {
3216
3475
  const { labels, messageRenderOrder = "blocks-first" } = useChatContext();
3217
- const [activeImage, setActiveImage] = (0, import_react9.useState)(void 0);
3476
+ const [activeImage, setActiveImage] = (0, import_react10.useState)(void 0);
3218
3477
  const {
3219
3478
  displayedBlocks,
3220
3479
  displayedContent,
@@ -3231,8 +3490,9 @@ var ChatMessageItemView = ({
3231
3490
  const hasMarkdownOnlyBlocks = hasStructuredBlocks && blocks.every((block) => block.type === "markdown");
3232
3491
  const hasTextContent = Boolean(settledContent || freshContent || displayedContent);
3233
3492
  const shouldRenderStructuredBlocks = hasStructuredBlocks && !(isAssistantStreaming && hasMarkdownOnlyBlocks && hasTextContent);
3234
- const canSubmitConfirmation = typeof onConfirmationSubmit === "function";
3235
- const canSubmitQuestionnaire = typeof onQuestionnaireSubmit === "function";
3493
+ const isInteractionDisabled = message.status === "stopped" || message.status === "error";
3494
+ const canSubmitConfirmation = typeof onConfirmationSubmit === "function" && !isInteractionDisabled;
3495
+ const canSubmitQuestionnaire = typeof onQuestionnaireSubmit === "function" && !isInteractionDisabled;
3236
3496
  const shouldShowStreamingCaret = isAssistantStreaming && (!shouldRenderStructuredBlocks || hasTextContent);
3237
3497
  const isUserMessage = message.role === "user";
3238
3498
  const messageRenderMode = isUserMessage ? "plain-text" : "markdown";
@@ -3282,11 +3542,11 @@ var ChatMessageItemView = ({
3282
3542
  `markdown-${index3}`
3283
3543
  );
3284
3544
  case "notice":
3285
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(NoticeCard, { text: block.text, tone: block.tone }) }, `notice-${index3}`);
3545
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react10.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(NoticeCard, { text: block.text, tone: block.tone }) }, `notice-${index3}`);
3286
3546
  case "parameter_summary":
3287
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ParameterSummaryCard, { items: block.items }) }, `parameter-summary-${index3}`);
3547
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react10.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ParameterSummaryCard, { items: block.items }) }, `parameter-summary-${index3}`);
3288
3548
  case "confirmation_card":
3289
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3549
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react10.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3290
3550
  ExecutionConfirmationCard,
3291
3551
  {
3292
3552
  proposal: block.proposal,
@@ -3299,9 +3559,9 @@ var ChatMessageItemView = ({
3299
3559
  }
3300
3560
  ) }, `confirmation-card-${index3}`);
3301
3561
  case "result_summary":
3302
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ResultSummaryCard, { summary: block.summary }) }, `result-summary-${index3}`);
3562
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react10.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ResultSummaryCard, { summary: block.summary }) }, `result-summary-${index3}`);
3303
3563
  case "questionnaire":
3304
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3564
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react10.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3305
3565
  QuestionnaireCard,
3306
3566
  {
3307
3567
  questionnaire: block.questionnaire,
@@ -3313,7 +3573,10 @@ var ChatMessageItemView = ({
3313
3573
  submitFailed: labels.questionnaireSubmitFailed,
3314
3574
  multiSelectHint: labels.questionnaireMultiSelectHint,
3315
3575
  otherOptionLabel: labels.questionnaireOtherOptionLabel,
3316
- otherPlaceholder: labels.questionnaireOtherPlaceholder
3576
+ otherPlaceholder: labels.questionnaireOtherPlaceholder,
3577
+ expired: labels.questionnaireExpired,
3578
+ questionnaireTitle: labels.questionnaireTitle,
3579
+ questionnaireConfirmInTime: labels.questionnaireConfirmInTime
3317
3580
  },
3318
3581
  onSubmit: canSubmitQuestionnaire ? (submission) => onQuestionnaireSubmit({
3319
3582
  ...submission,
@@ -3322,7 +3585,7 @@ var ChatMessageItemView = ({
3322
3585
  }
3323
3586
  ) }, block.questionnaire.blockKey ?? `questionnaire-${index3}`);
3324
3587
  case "custom":
3325
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: renderMessageBlock?.({
3588
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react10.Fragment, { children: renderMessageBlock?.({
3326
3589
  block,
3327
3590
  index: index3,
3328
3591
  message,
@@ -3416,7 +3679,7 @@ var ChatMessageItemView = ({
3416
3679
  })();
3417
3680
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
3418
3681
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Bubble, { "data-role": message.role, "data-status": message.status ?? "done", children: [
3419
- shouldRenderHeader ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Header2, { children: [
3682
+ shouldRenderHeader ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Header3, { children: [
3420
3683
  isAssistantStreaming ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3421
3684
  StreamingIndicator,
3422
3685
  {
@@ -3441,7 +3704,7 @@ var ChatMessageItemView = ({
3441
3704
  ) : null,
3442
3705
  isStoppedAssistant ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StatusTag, { "data-testid": "chat-message-stopped-tag", children: labels.stoppedResponse }) : null
3443
3706
  ] }) : null,
3444
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Content, { "data-testid": "chat-message-content", children: [
3707
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Content2, { "data-testid": "chat-message-content", children: [
3445
3708
  skills.length ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SkillTagList, { "data-testid": "chat-message-skill-tags", children: skills.map((skill) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SkillTag, { children: skill }, skill)) }) : null,
3446
3709
  shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3447
3710
  ContentStack,
@@ -3489,7 +3752,7 @@ var ChatMessageItemView = ({
3489
3752
  ) : null
3490
3753
  ] });
3491
3754
  };
3492
- var ChatMessageItem = (0, import_react9.memo)(
3755
+ var ChatMessageItem = (0, import_react10.memo)(
3493
3756
  ChatMessageItemView,
3494
3757
  (previousProps, nextProps) => isSameMessage(
3495
3758
  previousProps.message,
@@ -3521,7 +3784,7 @@ var Bubble = import_styled7.default.article`
3521
3784
  border-radius: 16px;
3522
3785
  }
3523
3786
  `;
3524
- var Header2 = import_styled7.default.div`
3787
+ var Header3 = import_styled7.default.div`
3525
3788
  display: flex;
3526
3789
  align-items: center;
3527
3790
  gap: 10px;
@@ -3563,7 +3826,7 @@ var CollapseToggle = import_styled7.default.button`
3563
3826
  color: rgba(255, 255, 255, 0.92);
3564
3827
  }
3565
3828
  `;
3566
- var Content = import_styled7.default.div`
3829
+ var Content2 = import_styled7.default.div`
3567
3830
  color: rgba(255, 255, 255, 0.92);
3568
3831
  font-size: 14px;
3569
3832
  line-height: 1.6;
@@ -3707,7 +3970,7 @@ var AttachmentImage = import_styled7.default.img`
3707
3970
  var TableWrapper = import_styled7.default.div`
3708
3971
  overflow-x: auto;
3709
3972
  `;
3710
- var caretBlink = import_react10.keyframes`
3973
+ var caretBlink = import_react11.keyframes`
3711
3974
  0%, 49% {
3712
3975
  opacity: 1;
3713
3976
  }
@@ -3716,7 +3979,7 @@ var caretBlink = import_react10.keyframes`
3716
3979
  opacity: 0.2;
3717
3980
  }
3718
3981
  `;
3719
- var shimmer = import_react10.keyframes`
3982
+ var shimmer = import_react11.keyframes`
3720
3983
  0%, 100% {
3721
3984
  transform: scale(0.9) rotate(0deg);
3722
3985
  opacity: 0.55;
@@ -3935,24 +4198,24 @@ var ChatThreadView = ({
3935
4198
  onQuestionnaireSubmit,
3936
4199
  renderMessageBlock
3937
4200
  }) => {
3938
- const containerRef = (0, import_react11.useRef)(null);
3939
- const conversationTurns = (0, import_react11.useMemo)(
4201
+ const containerRef = (0, import_react12.useRef)(null);
4202
+ const conversationTurns = (0, import_react12.useMemo)(
3940
4203
  () => groupConversationTurns(historyMessages, streamingMessage),
3941
4204
  [historyMessages, streamingMessage]
3942
4205
  );
3943
4206
  const latestTurn = conversationTurns[conversationTurns.length - 1];
3944
4207
  const latestUserMessageId = latestTurn?.userMessage?.id;
3945
4208
  const latestHistoryMessage = historyMessages[historyMessages.length - 1];
3946
- const latestTurnRef = (0, import_react11.useRef)(null);
3947
- const reservedSpaceFrameRef = (0, import_react11.useRef)(null);
3948
- const isLoadingPreviousRef = (0, import_react11.useRef)(false);
3949
- const isPinnedRef = (0, import_react11.useRef)(true);
3950
- const lastHistoryMessageIdRef = (0, import_react11.useRef)(latestHistoryMessage?.id);
3951
- const lastStreamingMessageIdRef = (0, import_react11.useRef)(streamingMessage?.id);
3952
- const [latestTurnMinHeight, setLatestTurnMinHeight] = (0, import_react11.useState)(0);
3953
- const [isDetached, setIsDetached] = (0, import_react11.useState)(false);
3954
- const [pendingNewMessageCount, setPendingNewMessageCount] = (0, import_react11.useState)(0);
3955
- const measureLatestTurnMinHeight = (0, import_react11.useCallback)(() => {
4209
+ const latestTurnRef = (0, import_react12.useRef)(null);
4210
+ const reservedSpaceFrameRef = (0, import_react12.useRef)(null);
4211
+ const isLoadingPreviousRef = (0, import_react12.useRef)(false);
4212
+ const isPinnedRef = (0, import_react12.useRef)(true);
4213
+ const lastHistoryMessageIdRef = (0, import_react12.useRef)(latestHistoryMessage?.id);
4214
+ const lastStreamingMessageIdRef = (0, import_react12.useRef)(streamingMessage?.id);
4215
+ const [latestTurnMinHeight, setLatestTurnMinHeight] = (0, import_react12.useState)(0);
4216
+ const [isDetached, setIsDetached] = (0, import_react12.useState)(false);
4217
+ const [pendingNewMessageCount, setPendingNewMessageCount] = (0, import_react12.useState)(0);
4218
+ const measureLatestTurnMinHeight = (0, import_react12.useCallback)(() => {
3956
4219
  const container = containerRef.current;
3957
4220
  if (!container)
3958
4221
  return;
@@ -3962,7 +4225,7 @@ var ChatThreadView = ({
3962
4225
  const nextMinHeight = Math.max(0, container.clientHeight - paddingTop - paddingBottom);
3963
4226
  setLatestTurnMinHeight((current) => current === nextMinHeight ? current : nextMinHeight);
3964
4227
  }, []);
3965
- const scrollToBottom = (0, import_react11.useCallback)((force = false) => {
4228
+ const scrollToBottom = (0, import_react12.useCallback)((force = false) => {
3966
4229
  const container = containerRef.current;
3967
4230
  if (!container)
3968
4231
  return false;
@@ -3978,12 +4241,12 @@ var ChatThreadView = ({
3978
4241
  }
3979
4242
  return true;
3980
4243
  }, []);
3981
- const markThreadPinned = (0, import_react11.useCallback)(() => {
4244
+ const markThreadPinned = (0, import_react12.useCallback)(() => {
3982
4245
  isPinnedRef.current = true;
3983
4246
  setIsDetached(false);
3984
4247
  setPendingNewMessageCount(0);
3985
4248
  }, []);
3986
- const scrollToBottomAndPin = (0, import_react11.useCallback)(
4249
+ const scrollToBottomAndPin = (0, import_react12.useCallback)(
3987
4250
  (force = false) => {
3988
4251
  const didScroll = scrollToBottom(force);
3989
4252
  if (!didScroll)
@@ -3992,7 +4255,7 @@ var ChatThreadView = ({
3992
4255
  },
3993
4256
  [markThreadPinned, scrollToBottom]
3994
4257
  );
3995
- const handleLoadPreviousMessages = (0, import_react11.useCallback)(async () => {
4258
+ const handleLoadPreviousMessages = (0, import_react12.useCallback)(async () => {
3996
4259
  const container = containerRef.current;
3997
4260
  if (!container || !onLoadPreviousMessages || isLoadingPreviousMessages) {
3998
4261
  return;
@@ -4017,7 +4280,7 @@ var ChatThreadView = ({
4017
4280
  nextContainer.scrollTop = nextContainer.scrollHeight - previousScrollHeight + previousScrollTop;
4018
4281
  });
4019
4282
  }, [isLoadingPreviousMessages, onLoadPreviousMessages]);
4020
- const handleContainerScroll = (0, import_react11.useCallback)(() => {
4283
+ const handleContainerScroll = (0, import_react12.useCallback)(() => {
4021
4284
  const container = containerRef.current;
4022
4285
  if (!container)
4023
4286
  return;
@@ -4031,7 +4294,7 @@ var ChatThreadView = ({
4031
4294
  setPendingNewMessageCount(0);
4032
4295
  }
4033
4296
  }, [handleLoadPreviousMessages, onLoadPreviousMessages]);
4034
- (0, import_react11.useLayoutEffect)(() => {
4297
+ (0, import_react12.useLayoutEffect)(() => {
4035
4298
  const nextHistoryMessageId = latestHistoryMessage?.id;
4036
4299
  if (lastHistoryMessageIdRef.current === nextHistoryMessageId) {
4037
4300
  return;
@@ -4055,7 +4318,7 @@ var ChatThreadView = ({
4055
4318
  });
4056
4319
  }
4057
4320
  }, [latestHistoryMessage, markThreadPinned, scrollToBottom]);
4058
- (0, import_react11.useLayoutEffect)(() => {
4321
+ (0, import_react12.useLayoutEffect)(() => {
4059
4322
  const nextStreamingMessageId = streamingMessage?.id;
4060
4323
  if (lastStreamingMessageIdRef.current === nextStreamingMessageId) {
4061
4324
  return;
@@ -4070,7 +4333,7 @@ var ChatThreadView = ({
4070
4333
  });
4071
4334
  }
4072
4335
  }, [streamingMessage]);
4073
- (0, import_react11.useLayoutEffect)(() => {
4336
+ (0, import_react12.useLayoutEffect)(() => {
4074
4337
  if (reservedSpaceFrameRef.current !== null) {
4075
4338
  window.cancelAnimationFrame(reservedSpaceFrameRef.current);
4076
4339
  reservedSpaceFrameRef.current = null;
@@ -4100,7 +4363,7 @@ var ChatThreadView = ({
4100
4363
  }
4101
4364
  };
4102
4365
  }, [latestTurn, latestUserMessageId, error2, measureLatestTurnMinHeight, scrollToBottom]);
4103
- (0, import_react11.useLayoutEffect)(() => {
4366
+ (0, import_react12.useLayoutEffect)(() => {
4104
4367
  if (!latestTurn)
4105
4368
  return;
4106
4369
  const handleResize = () => {
@@ -4126,7 +4389,7 @@ var ChatThreadView = ({
4126
4389
  window.removeEventListener("resize", handleResize);
4127
4390
  };
4128
4391
  }, [latestTurn, latestUserMessageId, measureLatestTurnMinHeight, scrollToBottom]);
4129
- (0, import_react11.useLayoutEffect)(() => {
4392
+ (0, import_react12.useLayoutEffect)(() => {
4130
4393
  const latestTurnElement = latestTurnRef.current;
4131
4394
  if (!latestTurnElement || typeof ResizeObserver === "undefined") {
4132
4395
  return;
@@ -4139,7 +4402,7 @@ var ChatThreadView = ({
4139
4402
  observer.disconnect();
4140
4403
  };
4141
4404
  }, [latestTurn, scrollToBottom]);
4142
- (0, import_react11.useLayoutEffect)(() => {
4405
+ (0, import_react12.useLayoutEffect)(() => {
4143
4406
  const latestTurnElement = latestTurnRef.current;
4144
4407
  if (!latestTurnElement || typeof MutationObserver === "undefined") {
4145
4408
  return;
@@ -4246,13 +4509,13 @@ var ChatThread = () => {
4246
4509
  onLoadMoreHistoryMessages,
4247
4510
  labels
4248
4511
  } = useChatContext();
4249
- const handleRetry = (0, import_react11.useCallback)(() => {
4512
+ const handleRetry = (0, import_react12.useCallback)(() => {
4250
4513
  if (!activeSessionId)
4251
4514
  return;
4252
4515
  clearSessionError(activeSessionId);
4253
4516
  void retryRef.current(activeSessionId);
4254
4517
  }, [activeSessionId, clearSessionError, retryRef]);
4255
- const handleQuestionnaireSubmit = (0, import_react11.useCallback)(
4518
+ const handleQuestionnaireSubmit = (0, import_react12.useCallback)(
4256
4519
  async (submission) => {
4257
4520
  const sourceSessionId = activeSessionId;
4258
4521
  if (customQuestionnaireSubmit) {
@@ -4287,7 +4550,7 @@ var ChatThread = () => {
4287
4550
  },
4288
4551
  [activeSessionId, customQuestionnaireSubmit, preferredMode, sendRef, updateQA]
4289
4552
  );
4290
- const handleConfirmation = (0, import_react11.useCallback)(
4553
+ const handleConfirmation = (0, import_react12.useCallback)(
4291
4554
  async (submission) => {
4292
4555
  const sourceSessionId = activeSessionId;
4293
4556
  if (customConfirmationSubmit) {
@@ -4306,7 +4569,7 @@ var ChatThread = () => {
4306
4569
  },
4307
4570
  [activeSessionId, customConfirmationSubmit, preferredMode, sendRef]
4308
4571
  );
4309
- const handleLoadPreviousMessages = (0, import_react11.useCallback)(async () => {
4572
+ const handleLoadPreviousMessages = (0, import_react12.useCallback)(async () => {
4310
4573
  if (!activeSession || !onLoadMoreHistoryMessages || !historyMessagePagination?.hasMorePrevious || !historyMessagePagination.previousCursor || historyMessagePagination.isLoadingPrevious) {
4311
4574
  return;
4312
4575
  }
@@ -4345,13 +4608,14 @@ var ChatThread = () => {
4345
4608
  if (!hasSessions || messages.length === 0 && !streamingMessage) {
4346
4609
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatThreadEmptyState, {});
4347
4610
  }
4611
+ const displayError = error2 && !(error2.toLowerCase().includes("plan option timeout") || error2.toLowerCase().includes("plan_option_timeout") || error2.toLowerCase().includes("selection expired") || labels.questionnaireExpired && error2.includes(labels.questionnaireExpired)) ? error2 : void 0;
4348
4612
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4349
4613
  ChatThreadView,
4350
4614
  {
4351
4615
  activeMode: preferredMode,
4352
4616
  historyMessages: messages,
4353
4617
  streamingMessage,
4354
- error: error2,
4618
+ error: displayError,
4355
4619
  isLoadingPreviousMessages: historyMessagePagination?.isLoadingPrevious,
4356
4620
  previousMessagesError: historyMessagePagination?.error,
4357
4621
  retryButtonLabel: labels.retryButton,
@@ -4500,7 +4764,7 @@ var ScrollToLatestBadge = import_styled9.default.span`
4500
4764
  `;
4501
4765
 
4502
4766
  // src/components/chat-composer/index.tsx
4503
- var import_react17 = require("react");
4767
+ var import_react18 = require("react");
4504
4768
  var import_styled14 = __toESM(require("@emotion/styled"));
4505
4769
 
4506
4770
  // ../../node_modules/.pnpm/@floating-ui+react@0.27.16_react-dom@18.3.1_react@18.3.1/node_modules/@floating-ui/react/dist/floating-ui.react.mjs
@@ -4662,7 +4926,7 @@ function getFrameElement(win) {
4662
4926
 
4663
4927
  // ../../node_modules/.pnpm/@floating-ui+react@0.27.16_react-dom@18.3.1_react@18.3.1/node_modules/@floating-ui/react/dist/floating-ui.react.utils.mjs
4664
4928
  var React = __toESM(require("react"), 1);
4665
- var import_react12 = require("react");
4929
+ var import_react13 = require("react");
4666
4930
 
4667
4931
  // ../../node_modules/.pnpm/@floating-ui+utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs
4668
4932
  var min = Math.min;
@@ -5149,7 +5413,7 @@ function getDocument(node) {
5149
5413
  var isClient = typeof document !== "undefined";
5150
5414
  var noop = function noop2() {
5151
5415
  };
5152
- var index = isClient ? import_react12.useLayoutEffect : noop;
5416
+ var index = isClient ? import_react13.useLayoutEffect : noop;
5153
5417
  var SafeReact = {
5154
5418
  ...React
5155
5419
  };
@@ -6358,12 +6622,12 @@ var computePosition2 = (reference, floating, options) => {
6358
6622
 
6359
6623
  // ../../node_modules/.pnpm/@floating-ui+react-dom@2.1.6_react-dom@18.3.1_react@18.3.1/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.mjs
6360
6624
  var React2 = __toESM(require("react"), 1);
6361
- var import_react13 = require("react");
6625
+ var import_react14 = require("react");
6362
6626
  var ReactDOM = __toESM(require("react-dom"), 1);
6363
6627
  var isClient2 = typeof document !== "undefined";
6364
6628
  var noop3 = function noop4() {
6365
6629
  };
6366
- var index2 = isClient2 ? import_react13.useLayoutEffect : noop3;
6630
+ var index2 = isClient2 ? import_react14.useLayoutEffect : noop3;
6367
6631
  function deepEqual(a, b) {
6368
6632
  if (a === b) {
6369
6633
  return true;
@@ -7098,10 +7362,10 @@ var resolveSendSession = ({
7098
7362
  };
7099
7363
 
7100
7364
  // src/components/chat-composer/hooks/use-chat-composer.ts
7101
- var import_react15 = require("react");
7365
+ var import_react16 = require("react");
7102
7366
 
7103
7367
  // src/components/chat-composer/hooks/use-composer-attachments.ts
7104
- var import_react14 = require("react");
7368
+ var import_react15 = require("react");
7105
7369
  var SUPPORTED_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp"]);
7106
7370
  var MAX_COMPOSER_ATTACHMENTS = 10;
7107
7371
  var createObjectUrl = (file) => typeof URL !== "undefined" && typeof URL.createObjectURL === "function" ? URL.createObjectURL(file) : "";
@@ -7115,12 +7379,12 @@ var releaseComposerAttachments = (attachments) => {
7115
7379
  attachments.forEach((attachment) => revokeObjectUrl(attachment.previewUrl));
7116
7380
  };
7117
7381
  var useComposerAttachments = () => {
7118
- const [attachments, setAttachments] = (0, import_react14.useState)([]);
7119
- const attachmentsRef = (0, import_react14.useRef)([]);
7120
- (0, import_react14.useEffect)(() => {
7382
+ const [attachments, setAttachments] = (0, import_react15.useState)([]);
7383
+ const attachmentsRef = (0, import_react15.useRef)([]);
7384
+ (0, import_react15.useEffect)(() => {
7121
7385
  attachmentsRef.current = attachments;
7122
7386
  }, [attachments]);
7123
- (0, import_react14.useEffect)(
7387
+ (0, import_react15.useEffect)(
7124
7388
  () => () => {
7125
7389
  releaseComposerAttachments(attachmentsRef.current);
7126
7390
  },
@@ -7246,7 +7510,7 @@ var useChatComposer = () => {
7246
7510
  const { transport, enableImageAttachments, labels, store } = useChatContext();
7247
7511
  const modelsLoader = transport.getModels;
7248
7512
  const skillsLoader = transport.getSkills;
7249
- const activeSkillsLoaderRef = (0, import_react15.useRef)(skillsLoader);
7513
+ const activeSkillsLoaderRef = (0, import_react16.useRef)(skillsLoader);
7250
7514
  const activeSessionId = useChatStore((s) => s.activeSessionId);
7251
7515
  const preferredMode = useChatStore((s) => s.preferredMode);
7252
7516
  const streamingSessionId = useChatStore(
@@ -7268,16 +7532,16 @@ var useChatComposer = () => {
7268
7532
  const setSessionError = useChatStore((s) => s.setSessionError);
7269
7533
  const clearSessionError = useChatStore((s) => s.clearSessionError);
7270
7534
  const setPreferredMode = useChatStore((s) => s.setPreferredMode);
7271
- const [availableModels, setAvailableModels] = (0, import_react15.useState)([]);
7272
- const [isModelsLoading, setIsModelsLoading] = (0, import_react15.useState)(true);
7273
- const [isModelsError, setIsModelsError] = (0, import_react15.useState)(false);
7274
- const [availableSkills, setAvailableSkills] = (0, import_react15.useState)(
7535
+ const [availableModels, setAvailableModels] = (0, import_react16.useState)([]);
7536
+ const [isModelsLoading, setIsModelsLoading] = (0, import_react16.useState)(true);
7537
+ const [isModelsError, setIsModelsError] = (0, import_react16.useState)(false);
7538
+ const [availableSkills, setAvailableSkills] = (0, import_react16.useState)(
7275
7539
  () => getCachedSkills(skillsLoader).skills
7276
7540
  );
7277
- const [isSkillsLoading, setIsSkillsLoading] = (0, import_react15.useState)(
7541
+ const [isSkillsLoading, setIsSkillsLoading] = (0, import_react16.useState)(
7278
7542
  () => Boolean(skillsLoader) && !getCachedSkills(skillsLoader).resolved
7279
7543
  );
7280
- const fetchModels = (0, import_react15.useCallback)(async () => {
7544
+ const fetchModels = (0, import_react16.useCallback)(async () => {
7281
7545
  setIsModelsLoading(true);
7282
7546
  setIsModelsError(false);
7283
7547
  try {
@@ -7289,16 +7553,16 @@ var useChatComposer = () => {
7289
7553
  setIsModelsLoading(false);
7290
7554
  }
7291
7555
  }, [modelsLoader]);
7292
- (0, import_react15.useEffect)(() => {
7556
+ (0, import_react16.useEffect)(() => {
7293
7557
  void fetchModels();
7294
7558
  }, [fetchModels]);
7295
- (0, import_react15.useEffect)(() => {
7559
+ (0, import_react16.useEffect)(() => {
7296
7560
  activeSkillsLoaderRef.current = skillsLoader;
7297
7561
  const cachedSkills = getCachedSkills(skillsLoader);
7298
7562
  setAvailableSkills(cachedSkills.skills);
7299
7563
  setIsSkillsLoading(Boolean(skillsLoader) && !cachedSkills.resolved);
7300
7564
  }, [skillsLoader]);
7301
- const fetchSkills = (0, import_react15.useCallback)(async () => {
7565
+ const fetchSkills = (0, import_react16.useCallback)(async () => {
7302
7566
  if (!skillsLoader) {
7303
7567
  setAvailableSkills([]);
7304
7568
  setIsSkillsLoading(false);
@@ -7328,35 +7592,35 @@ var useChatComposer = () => {
7328
7592
  }
7329
7593
  }
7330
7594
  }, [skillsLoader]);
7331
- (0, import_react15.useEffect)(() => {
7595
+ (0, import_react16.useEffect)(() => {
7332
7596
  void fetchSkills();
7333
7597
  }, [fetchSkills]);
7334
7598
  const hasModels = availableModels.length > 0;
7335
- const [value, setValue] = (0, import_react15.useState)("");
7336
- const [selectedModel, setSelectedModel] = (0, import_react15.useState)("");
7337
- const [selectedMode, setSelectedModeLocal] = (0, import_react15.useState)(DEFAULT_CHAT_AGENT_MODE);
7338
- const [selectedSkills, setSelectedSkills] = (0, import_react15.useState)([]);
7339
- const [attachmentNotice, setAttachmentNotice] = (0, import_react15.useState)(null);
7599
+ const [value, setValue] = (0, import_react16.useState)("");
7600
+ const [selectedModel, setSelectedModel] = (0, import_react16.useState)("");
7601
+ const [selectedMode, setSelectedModeLocal] = (0, import_react16.useState)(DEFAULT_CHAT_AGENT_MODE);
7602
+ const [selectedSkills, setSelectedSkills] = (0, import_react16.useState)([]);
7603
+ const [attachmentNotice, setAttachmentNotice] = (0, import_react16.useState)(null);
7340
7604
  const { attachments, appendFiles, removeAttachment, takeMessageAttachments } = useComposerAttachments();
7341
- const abortControllerBySessionRef = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
7342
- const stopRequestBySessionRef = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
7343
- const lastRequestBySessionRef = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
7344
- const previousActiveSessionIdRef = (0, import_react15.useRef)(activeSessionId);
7345
- (0, import_react15.useEffect)(() => {
7605
+ const abortControllerBySessionRef = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
7606
+ const stopRequestBySessionRef = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
7607
+ const lastRequestBySessionRef = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
7608
+ const previousActiveSessionIdRef = (0, import_react16.useRef)(activeSessionId);
7609
+ (0, import_react16.useEffect)(() => {
7346
7610
  setSelectedModel(
7347
7611
  (current) => resolveSelectedChatModel({ currentModel: current, availableModels, isModelsLoading })
7348
7612
  );
7349
7613
  }, [availableModels, isModelsLoading]);
7350
- (0, import_react15.useEffect)(() => {
7614
+ (0, import_react16.useEffect)(() => {
7351
7615
  setSelectedModeLocal(preferredMode ?? DEFAULT_CHAT_AGENT_MODE);
7352
7616
  }, [preferredMode]);
7353
- (0, import_react15.useEffect)(() => {
7617
+ (0, import_react16.useEffect)(() => {
7354
7618
  if (previousActiveSessionIdRef.current !== activeSessionId) {
7355
7619
  setSelectedSkills([]);
7356
7620
  previousActiveSessionIdRef.current = activeSessionId;
7357
7621
  }
7358
7622
  }, [activeSessionId]);
7359
- (0, import_react15.useEffect)(() => {
7623
+ (0, import_react16.useEffect)(() => {
7360
7624
  if (!attachmentNotice)
7361
7625
  return;
7362
7626
  const timeoutId = window.setTimeout(
@@ -7373,11 +7637,11 @@ var useChatComposer = () => {
7373
7637
  window.clearTimeout(stopRequest.timeoutId);
7374
7638
  stopRequest.timeoutId = null;
7375
7639
  };
7376
- const clearStopRequest = (0, import_react15.useCallback)((sessionId) => {
7640
+ const clearStopRequest = (0, import_react16.useCallback)((sessionId) => {
7377
7641
  clearStopTimeout(sessionId);
7378
7642
  stopRequestBySessionRef.current.delete(sessionId);
7379
7643
  }, []);
7380
- const moveSessionRuntimeState = (0, import_react15.useCallback)(
7644
+ const moveSessionRuntimeState = (0, import_react16.useCallback)(
7381
7645
  (previousSessionId, nextSessionId) => {
7382
7646
  if (previousSessionId === nextSessionId) {
7383
7647
  return;
@@ -7395,7 +7659,7 @@ var useChatComposer = () => {
7395
7659
  },
7396
7660
  []
7397
7661
  );
7398
- const finalizeStop = (0, import_react15.useCallback)(
7662
+ const finalizeStop = (0, import_react16.useCallback)(
7399
7663
  (sessionId) => {
7400
7664
  const stopRequest = stopRequestBySessionRef.current.get(sessionId);
7401
7665
  if (stopRequest) {
@@ -7412,7 +7676,7 @@ var useChatComposer = () => {
7412
7676
  },
7413
7677
  [clearStopRequest, finalizeStoppedStreamingMessage]
7414
7678
  );
7415
- const runStream = (0, import_react15.useCallback)(
7679
+ const runStream = (0, import_react16.useCallback)(
7416
7680
  async ({
7417
7681
  localSessionId,
7418
7682
  sessionId,
@@ -7537,7 +7801,7 @@ var useChatComposer = () => {
7537
7801
  store
7538
7802
  ]
7539
7803
  );
7540
- const send = (0, import_react15.useCallback)(
7804
+ const send = (0, import_react16.useCallback)(
7541
7805
  async (contentOverride, options) => {
7542
7806
  const content = (contentOverride ?? value).trim();
7543
7807
  const includeComposerAttachments = options?.includeComposerAttachments ?? true;
@@ -7617,7 +7881,7 @@ var useChatComposer = () => {
7617
7881
  store
7618
7882
  ]
7619
7883
  );
7620
- const openSkillPicker = (0, import_react15.useCallback)(() => {
7884
+ const openSkillPicker = (0, import_react16.useCallback)(() => {
7621
7885
  setValue((current) => {
7622
7886
  const matchedSkillQuery = current.match(/(^|\s)\/([^\s/]*)$/);
7623
7887
  if (matchedSkillQuery && matchedSkillQuery.index !== void 0) {
@@ -7630,7 +7894,7 @@ var useChatComposer = () => {
7630
7894
  return /\s$/.test(current) ? `${current}/` : `${current} /`;
7631
7895
  });
7632
7896
  }, []);
7633
- const stopSession = (0, import_react15.useCallback)(
7897
+ const stopSession = (0, import_react16.useCallback)(
7634
7898
  async (sessionId) => {
7635
7899
  const storeState = store.getState();
7636
7900
  const isSessionStreaming = storeState.isStreamingBySession[sessionId] ?? false;
@@ -7740,14 +8004,14 @@ var useChatComposer = () => {
7740
8004
  };
7741
8005
 
7742
8006
  // src/components/chat-composer/components/chat-composer-attachment-list.tsx
7743
- var import_react16 = require("react");
8007
+ var import_react17 = require("react");
7744
8008
  var import_styled10 = __toESM(require("@emotion/styled"));
7745
8009
  var import_jsx_runtime12 = require("@emotion/react/jsx-runtime");
7746
8010
  var ChatComposerAttachmentList = ({
7747
8011
  attachments,
7748
8012
  onRemoveAttachment
7749
8013
  }) => {
7750
- const [activeImage, setActiveImage] = (0, import_react16.useState)(null);
8014
+ const [activeImage, setActiveImage] = (0, import_react17.useState)(null);
7751
8015
  if (!attachments.length) {
7752
8016
  return null;
7753
8017
  }
@@ -8426,11 +8690,11 @@ var ChatComposerView = ({
8426
8690
  onStop,
8427
8691
  onSend
8428
8692
  }) => {
8429
- const imageInputRef = (0, import_react17.useRef)(null);
8430
- const inputRef = (0, import_react17.useRef)(null);
8431
- const [isComposerExpandable, setIsComposerExpandable] = (0, import_react17.useState)(false);
8432
- const [isComposerExpanded, setIsComposerExpanded] = (0, import_react17.useState)(false);
8433
- const [activeSkillNavigation, setActiveSkillNavigation] = (0, import_react17.useState)({
8693
+ const imageInputRef = (0, import_react18.useRef)(null);
8694
+ const inputRef = (0, import_react18.useRef)(null);
8695
+ const [isComposerExpandable, setIsComposerExpandable] = (0, import_react18.useState)(false);
8696
+ const [isComposerExpanded, setIsComposerExpanded] = (0, import_react18.useState)(false);
8697
+ const [activeSkillNavigation, setActiveSkillNavigation] = (0, import_react18.useState)({
8434
8698
  queryKey: "",
8435
8699
  index: 0
8436
8700
  });
@@ -8473,20 +8737,20 @@ var ChatComposerView = ({
8473
8737
  ],
8474
8738
  whileElementsMounted: autoUpdate
8475
8739
  });
8476
- const setSkillMenuReference = (0, import_react17.useCallback)(
8740
+ const setSkillMenuReference = (0, import_react18.useCallback)(
8477
8741
  (element) => {
8478
8742
  refs.setReference(element);
8479
8743
  },
8480
8744
  [refs]
8481
8745
  );
8482
- const setSkillMenuFloating = (0, import_react17.useCallback)(
8746
+ const setSkillMenuFloating = (0, import_react18.useCallback)(
8483
8747
  (element) => {
8484
8748
  refs.setFloating(element);
8485
8749
  },
8486
8750
  [refs]
8487
8751
  );
8488
8752
  const activeSkillIndex = activeSkillNavigation.queryKey === activeSkillQueryKey ? activeSkillNavigation.index : 0;
8489
- (0, import_react17.useLayoutEffect)(() => {
8753
+ (0, import_react18.useLayoutEffect)(() => {
8490
8754
  const element = inputRef.current;
8491
8755
  if (!element) {
8492
8756
  return;
@@ -8636,7 +8900,7 @@ var ChatComposerView = ({
8636
8900
  }
8637
8901
  )
8638
8902
  ] }),
8639
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Footer, { children: [
8903
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Footer2, { children: [
8640
8904
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(LeadingActions, { "data-testid": "chat-composer-leading-actions", children: [
8641
8905
  enableImageAttachments ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8642
8906
  AttachButton,
@@ -8728,7 +8992,7 @@ var ChatComposer = () => {
8728
8992
  const { labels, sendRef, retryRef, stopRef, enableImageAttachments } = useChatContext();
8729
8993
  const { state, actions } = useChatComposer();
8730
8994
  const { send, retry } = actions;
8731
- (0, import_react17.useEffect)(() => {
8995
+ (0, import_react18.useEffect)(() => {
8732
8996
  sendRef.current = send;
8733
8997
  retryRef.current = async (sessionId) => {
8734
8998
  retry(sessionId);
@@ -8976,7 +9240,7 @@ var ComposerExpandButton = import_styled14.default.button`
8976
9240
  color: rgba(255, 255, 255, 0.92);
8977
9241
  }
8978
9242
  `;
8979
- var Footer = import_styled14.default.div`
9243
+ var Footer2 = import_styled14.default.div`
8980
9244
  grid-area: footer;
8981
9245
  display: flex;
8982
9246
  align-items: center;
@@ -9057,14 +9321,14 @@ var SkillButton = import_styled14.default.button`
9057
9321
  `;
9058
9322
 
9059
9323
  // src/components/chat-conversation-list/index.tsx
9060
- var import_react20 = require("react");
9324
+ var import_react21 = require("react");
9061
9325
  var import_styled16 = __toESM(require("@emotion/styled"));
9062
9326
 
9063
9327
  // src/components/chat-conversation-list/components/chat-session-item.tsx
9064
- var import_react19 = require("react");
9328
+ var import_react20 = require("react");
9065
9329
  var import_styled15 = __toESM(require("@emotion/styled"));
9066
9330
  var import_jsx_runtime17 = require("@emotion/react/jsx-runtime");
9067
- var ChatSessionItem = (0, import_react19.memo)(({ session, isActive, onClick }) => {
9331
+ var ChatSessionItem = (0, import_react20.memo)(({ session, isActive, onClick }) => {
9068
9332
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
9069
9333
  SessionButton,
9070
9334
  {
@@ -9158,14 +9422,14 @@ var ChatConversationList = () => {
9158
9422
  const setHistorySessionMessageLoadStatus = useChatStore(
9159
9423
  (s) => s.setHistorySessionMessageLoadStatus
9160
9424
  );
9161
- const isLoadingMoreRef = (0, import_react20.useRef)(false);
9162
- const hasSeenLoadingMoreRef = (0, import_react20.useRef)(false);
9163
- (0, import_react20.useEffect)(() => {
9425
+ const isLoadingMoreRef = (0, import_react21.useRef)(false);
9426
+ const hasSeenLoadingMoreRef = (0, import_react21.useRef)(false);
9427
+ (0, import_react21.useEffect)(() => {
9164
9428
  if (!historySessionList)
9165
9429
  return;
9166
9430
  hydrateHistorySessions(historySessionList.sessions);
9167
9431
  }, [historySessionList, hydrateHistorySessions]);
9168
- (0, import_react20.useEffect)(() => {
9432
+ (0, import_react21.useEffect)(() => {
9169
9433
  if (historySessionList?.isLoading) {
9170
9434
  hasSeenLoadingMoreRef.current = true;
9171
9435
  return;
@@ -9175,7 +9439,7 @@ var ChatConversationList = () => {
9175
9439
  isLoadingMoreRef.current = false;
9176
9440
  }
9177
9441
  }, [historySessionList?.isLoading]);
9178
- (0, import_react20.useEffect)(() => {
9442
+ (0, import_react21.useEffect)(() => {
9179
9443
  isLoadingMoreRef.current = false;
9180
9444
  hasSeenLoadingMoreRef.current = false;
9181
9445
  }, [historySessionList?.sessions.length, historySessionList?.hasMore]);
@@ -9374,7 +9638,7 @@ var AiChatWorkspaceContent = ({
9374
9638
  })
9375
9639
  );
9376
9640
  const shouldShowComposerOnly = showComposerOnlyBeforeFirstMessage && !showConversationList && !isConversationStarted;
9377
- (0, import_react21.useEffect)(() => {
9641
+ (0, import_react22.useEffect)(() => {
9378
9642
  onConversationStartedChange?.(isConversationStarted);
9379
9643
  }, [isConversationStarted, onConversationStartedChange]);
9380
9644
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Root, { "data-testid": "ai-chat", children: [