@xinghunm/ai-chat 1.4.4 → 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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/ai-chat/index.tsx
2
- import { useEffect as useEffect11 } from "react";
2
+ import { useEffect as useEffect12 } from "react";
3
3
  import styled17 from "@emotion/styled";
4
4
  import { ConfigProvider } from "@xinghunm/compass-ui";
5
5
 
@@ -49,6 +49,7 @@ var DEFAULT_AI_CHAT_LABELS = {
49
49
  questionnaireMultiSelectHint: "Multiple choice",
50
50
  questionnaireOtherOptionLabel: "Other",
51
51
  questionnaireOtherPlaceholder: "Other",
52
+ questionnaireExpired: "Selection expired.",
52
53
  modelLoading: "Loading models...",
53
54
  modelLoadFailed: "Failed to load models",
54
55
  modelUnavailable: "No model available",
@@ -57,7 +58,9 @@ var DEFAULT_AI_CHAT_LABELS = {
57
58
  removeSkillAriaLabel: "Remove skill",
58
59
  sessionHistoryLoading: "Loading conversations...",
59
60
  sessionHistoryLoadFailed: "Failed to load conversations",
60
- sessionHistoryEmpty: "No conversations yet"
61
+ sessionHistoryEmpty: "No conversations yet",
62
+ questionnaireTitle: "Plan Options",
63
+ questionnaireConfirmInTime: "Please confirm within {{seconds}} seconds"
61
64
  };
62
65
 
63
66
  // src/lib/chat-session.ts
@@ -97,6 +100,42 @@ var mergeOlderHistoryMessages = (sessionId, olderMessages, currentMessages) => {
97
100
  );
98
101
  return [...uniqueOlderMessages, ...currentMessages];
99
102
  };
103
+ var mergeLocalQuestionnaireState = (localMessages, incomingMessages) => {
104
+ if (!localMessages?.length)
105
+ return incomingMessages;
106
+ return incomingMessages.map((incomingMsg) => {
107
+ const localMsg = localMessages.find((lm) => lm.id === incomingMsg.id);
108
+ if (!localMsg)
109
+ return incomingMsg;
110
+ if (localMsg.blocks && !incomingMsg.blocks) {
111
+ return {
112
+ ...incomingMsg,
113
+ blocks: localMsg.blocks
114
+ };
115
+ }
116
+ if (localMsg.blocks && incomingMsg.blocks) {
117
+ const nextBlocks = incomingMsg.blocks.map((incomingBlock, index3) => {
118
+ const localBlock = localMsg.blocks?.[index3];
119
+ const isSameQuestionnaire = incomingBlock.type === "questionnaire" && localBlock?.type === "questionnaire" && (localBlock.questionnaire.questionnaireId === incomingBlock.questionnaire.questionnaireId || Boolean(localBlock.questionnaire.blockKey) && localBlock.questionnaire.blockKey === incomingBlock.questionnaire.blockKey);
120
+ if (isSameQuestionnaire) {
121
+ return {
122
+ ...incomingBlock,
123
+ questionnaire: {
124
+ ...incomingBlock.questionnaire,
125
+ questionnaireId: localBlock.questionnaire.questionnaireId ?? incomingBlock.questionnaire.questionnaireId,
126
+ answers: localBlock.questionnaire.answers ?? incomingBlock.questionnaire.answers,
127
+ status: localBlock.questionnaire.status ?? incomingBlock.questionnaire.status,
128
+ statusMessage: localBlock.questionnaire.statusMessage ?? incomingBlock.questionnaire.statusMessage
129
+ }
130
+ };
131
+ }
132
+ return incomingBlock;
133
+ });
134
+ return { ...incomingMsg, blocks: nextBlocks };
135
+ }
136
+ return incomingMsg;
137
+ });
138
+ };
100
139
  var resolveSessionTitleFromMessage = (message) => {
101
140
  const trimmedContent = message.content.trim();
102
141
  if (trimmedContent) {
@@ -479,10 +518,12 @@ var createChatStore = (initialState) => createStore((set, get) => ({
479
518
  },
480
519
  hydrateHistorySessionMessages: (sessionId, messages) => {
481
520
  const state = get();
521
+ const localMessages = state.messagesBySession[sessionId] ?? [];
522
+ const nextMessages = mergeLocalQuestionnaireState(localMessages, messages);
482
523
  set({
483
524
  messagesBySession: {
484
525
  ...state.messagesBySession,
485
- [sessionId]: normalizeHistoryMessages(sessionId, messages)
526
+ [sessionId]: normalizeHistoryMessages(sessionId, nextMessages)
486
527
  },
487
528
  sessionMessageLoadStatusBySession: {
488
529
  ...state.sessionMessageLoadStatusBySession,
@@ -500,10 +541,12 @@ var createChatStore = (initialState) => createStore((set, get) => ({
500
541
  },
501
542
  hydrateHistorySessionMessagesPage: (sessionId, page) => {
502
543
  const state = get();
544
+ const localMessages = state.messagesBySession[sessionId] ?? [];
545
+ const nextMessages = mergeLocalQuestionnaireState(localMessages, page.messages);
503
546
  set({
504
547
  messagesBySession: {
505
548
  ...state.messagesBySession,
506
- [sessionId]: normalizeHistoryMessages(sessionId, page.messages)
549
+ [sessionId]: normalizeHistoryMessages(sessionId, nextMessages)
507
550
  },
508
551
  sessionMessageLoadStatusBySession: {
509
552
  ...state.sessionMessageLoadStatusBySession,
@@ -662,7 +705,11 @@ var createChatStore = (initialState) => createStore((set, get) => ({
662
705
  hasUpdatedBlock = true;
663
706
  return {
664
707
  ...block,
665
- questionnaire: { ...block.questionnaire, answers: { ...answers } }
708
+ questionnaire: {
709
+ ...block.questionnaire,
710
+ answers: { ...answers },
711
+ status: "submitted"
712
+ }
666
713
  };
667
714
  });
668
715
  if (!hasUpdatedBlock)
@@ -1139,7 +1186,7 @@ var AiChatProvider = (props) => {
1139
1186
  };
1140
1187
 
1141
1188
  // src/components/chat-thread/index.tsx
1142
- import { useCallback as useCallback3, useLayoutEffect as useLayoutEffect3, useMemo as useMemo4, useRef as useRef5, useState as useState4 } from "react";
1189
+ import { useCallback as useCallback3, useLayoutEffect as useLayoutEffect3, useMemo as useMemo4, useRef as useRef5, useState as useState5 } from "react";
1143
1190
  import styled9 from "@emotion/styled";
1144
1191
 
1145
1192
  // src/context/use-chat-context.ts
@@ -1160,7 +1207,7 @@ var useChatStore = (selector) => {
1160
1207
  var CHAT_THREAD_SCROLL_TOP_GAP = 16;
1161
1208
 
1162
1209
  // src/components/chat-thread/components/chat-message-item.tsx
1163
- import { Fragment, memo, useCallback as useCallback2, useLayoutEffect as useLayoutEffect2, useState as useState3 } from "react";
1210
+ import { Fragment, memo, useCallback as useCallback2, useLayoutEffect as useLayoutEffect2, useState as useState4 } from "react";
1164
1211
  import styled7 from "@emotion/styled";
1165
1212
  import { keyframes } from "@emotion/react";
1166
1213
  import ReactMarkdown from "react-markdown";
@@ -1216,11 +1263,23 @@ var getNextDisplayedUnitCount = ({
1216
1263
  var splitMarkdownBlocks = (content) => content.split(/\n{2,}/).map((block) => block.trim()).filter(Boolean);
1217
1264
 
1218
1265
  // src/components/chat-thread/hooks/use-chat-message-reveal.ts
1266
+ var revealedStreamingMessages = /* @__PURE__ */ new Set();
1267
+ var markMessageAsRevealed = (id) => {
1268
+ if (revealedStreamingMessages.size > 500) {
1269
+ const firstKey = revealedStreamingMessages.keys().next().value;
1270
+ if (firstKey !== void 0) {
1271
+ revealedStreamingMessages.delete(firstKey);
1272
+ }
1273
+ }
1274
+ revealedStreamingMessages.add(id);
1275
+ };
1219
1276
  var createRevealState = ({
1220
1277
  isAssistantStreaming,
1221
- targetUnitCount
1278
+ targetUnitCount,
1279
+ messageId
1222
1280
  }) => {
1223
- const initialDisplayedUnitCount = isAssistantStreaming ? 0 : targetUnitCount;
1281
+ const hasBeenRevealed = revealedStreamingMessages.has(messageId);
1282
+ const initialDisplayedUnitCount = isAssistantStreaming && !hasBeenRevealed ? 0 : targetUnitCount;
1224
1283
  return {
1225
1284
  batchedTargetUnitCount: initialDisplayedUnitCount,
1226
1285
  displayedUnitCount: initialDisplayedUnitCount,
@@ -1230,7 +1289,11 @@ var createRevealState = ({
1230
1289
  var revealReducer = (state, action) => {
1231
1290
  switch (action.type) {
1232
1291
  case "reset-message":
1233
- return createRevealState(action);
1292
+ return createRevealState({
1293
+ isAssistantStreaming: action.isAssistantStreaming,
1294
+ targetUnitCount: action.targetUnitCount,
1295
+ messageId: action.messageId
1296
+ });
1234
1297
  case "commit-batched-target": {
1235
1298
  const nextDisplayedUnitCount = action.role === "assistant" ? getNextDisplayedUnitCount({
1236
1299
  currentUnits: state.displayedUnitCount,
@@ -1287,7 +1350,8 @@ var useChatMessageReveal = (message) => {
1287
1350
  revealReducer,
1288
1351
  {
1289
1352
  isAssistantStreaming,
1290
- targetUnitCount: targetUnits.length
1353
+ targetUnitCount: targetUnits.length,
1354
+ messageId: message.id
1291
1355
  },
1292
1356
  createRevealState
1293
1357
  );
@@ -1319,7 +1383,8 @@ var useChatMessageReveal = (message) => {
1319
1383
  dispatch({
1320
1384
  type: "reset-message",
1321
1385
  isAssistantStreaming,
1322
- targetUnitCount: targetUnits.length
1386
+ targetUnitCount: targetUnits.length,
1387
+ messageId: message.id
1323
1388
  });
1324
1389
  }, [isAssistantStreaming, message.id, targetUnits.length]);
1325
1390
  useEffect2(() => {
@@ -1398,6 +1463,11 @@ var useChatMessageReveal = (message) => {
1398
1463
  tone: "settled"
1399
1464
  }
1400
1465
  ];
1466
+ useEffect2(() => {
1467
+ if (isAssistantStreaming && displayedUnitCount > 0) {
1468
+ markMessageAsRevealed(message.id);
1469
+ }
1470
+ }, [isAssistantStreaming, displayedUnitCount, message.id]);
1401
1471
  return {
1402
1472
  isAssistantStreaming,
1403
1473
  isFreshBlockActive,
@@ -1989,12 +2059,99 @@ var Value = styled3.span`
1989
2059
 
1990
2060
  // src/components/chat-thread/components/questionnaire-card.tsx
1991
2061
  import {
1992
- useEffect as useEffect4,
2062
+ useEffect as useEffect5,
1993
2063
  useRef as useRef3,
1994
- useState as useState2
2064
+ useState as useState3
1995
2065
  } from "react";
1996
2066
  import styled4 from "@emotion/styled";
1997
2067
 
2068
+ // src/components/chat-thread/components/use-countdown-seconds.ts
2069
+ import { useEffect as useEffect4, useState as useState2 } from "react";
2070
+ var countdownDeadlineByKey = /* @__PURE__ */ new Map();
2071
+ var countdownCleanupTimerByKey = /* @__PURE__ */ new Map();
2072
+ var countdownMountCountByKey = /* @__PURE__ */ new Map();
2073
+ var clearCountdownEntry = (storageKey) => {
2074
+ const cleanupTimerId = countdownCleanupTimerByKey.get(storageKey);
2075
+ if (cleanupTimerId !== void 0) {
2076
+ window.clearTimeout(cleanupTimerId);
2077
+ countdownCleanupTimerByKey.delete(storageKey);
2078
+ }
2079
+ countdownDeadlineByKey.delete(storageKey);
2080
+ };
2081
+ var scheduleCountdownCleanup = (storageKey, deadline) => {
2082
+ const existingCleanupTimerId = countdownCleanupTimerByKey.get(storageKey);
2083
+ if (existingCleanupTimerId !== void 0) {
2084
+ return;
2085
+ }
2086
+ const delayMs = Math.max(0, deadline - Date.now());
2087
+ const cleanupTimerId = window.setTimeout(() => {
2088
+ if ((countdownMountCountByKey.get(storageKey) ?? 0) > 0) {
2089
+ countdownCleanupTimerByKey.delete(storageKey);
2090
+ return;
2091
+ }
2092
+ clearCountdownEntry(storageKey);
2093
+ }, delayMs);
2094
+ countdownCleanupTimerByKey.set(storageKey, cleanupTimerId);
2095
+ };
2096
+ var getCountdownDeadline = (storageKey, initialSeconds) => {
2097
+ const existingDeadline = countdownDeadlineByKey.get(storageKey);
2098
+ if (existingDeadline !== void 0) {
2099
+ return existingDeadline;
2100
+ }
2101
+ const nextDeadline = Date.now() + Math.max(0, initialSeconds) * 1e3;
2102
+ countdownDeadlineByKey.set(storageKey, nextDeadline);
2103
+ scheduleCountdownCleanup(storageKey, nextDeadline);
2104
+ return nextDeadline;
2105
+ };
2106
+ var getRemainingSeconds = (deadline) => Math.max(0, Math.ceil((deadline - Date.now()) / 1e3));
2107
+ var useCountdownSeconds = ({
2108
+ storageKey,
2109
+ initialSeconds,
2110
+ active
2111
+ }) => {
2112
+ const [remainingSeconds, setRemainingSeconds] = useState2(
2113
+ () => getRemainingSeconds(getCountdownDeadline(storageKey, initialSeconds))
2114
+ );
2115
+ useEffect4(() => {
2116
+ countdownMountCountByKey.set(storageKey, (countdownMountCountByKey.get(storageKey) ?? 0) + 1);
2117
+ return () => {
2118
+ const nextCount = (countdownMountCountByKey.get(storageKey) ?? 1) - 1;
2119
+ if (nextCount <= 0) {
2120
+ countdownMountCountByKey.delete(storageKey);
2121
+ return;
2122
+ }
2123
+ countdownMountCountByKey.set(storageKey, nextCount);
2124
+ };
2125
+ }, [storageKey]);
2126
+ useEffect4(() => {
2127
+ setRemainingSeconds(getRemainingSeconds(getCountdownDeadline(storageKey, initialSeconds)));
2128
+ }, [initialSeconds, storageKey]);
2129
+ useEffect4(() => {
2130
+ if (active) {
2131
+ return;
2132
+ }
2133
+ clearCountdownEntry(storageKey);
2134
+ }, [active, storageKey]);
2135
+ useEffect4(() => {
2136
+ if (remainingSeconds > 0) {
2137
+ return;
2138
+ }
2139
+ clearCountdownEntry(storageKey);
2140
+ }, [remainingSeconds, storageKey]);
2141
+ useEffect4(() => {
2142
+ if (!active || remainingSeconds <= 0) {
2143
+ return;
2144
+ }
2145
+ const timeoutId = window.setTimeout(() => {
2146
+ setRemainingSeconds(getRemainingSeconds(getCountdownDeadline(storageKey, initialSeconds)));
2147
+ }, 1e3);
2148
+ return () => {
2149
+ window.clearTimeout(timeoutId);
2150
+ };
2151
+ }, [active, initialSeconds, remainingSeconds, storageKey]);
2152
+ return remainingSeconds;
2153
+ };
2154
+
1998
2155
  // src/components/chat-thread/components/questionnaire-card-helpers.ts
1999
2156
  var OTHER_OPTION_VALUE = "__other__";
2000
2157
  var getQuestionnaireQuestion = (questionnaire) => questionnaire.question;
@@ -2301,7 +2458,10 @@ var DEFAULT_QUESTIONNAIRE_CARD_LABELS = {
2301
2458
  submitFailed: "Failed to submit. Please try again.",
2302
2459
  multiSelectHint: "Multiple choice",
2303
2460
  otherOptionLabel: "Other",
2304
- otherPlaceholder: "Other"
2461
+ otherPlaceholder: "Other",
2462
+ expired: "Selection expired.",
2463
+ questionnaireTitle: "Plan Options",
2464
+ questionnaireConfirmInTime: "Please confirm within {{seconds}} seconds"
2305
2465
  };
2306
2466
  var stopInputClickPropagation = (event) => {
2307
2467
  event.stopPropagation();
@@ -2363,30 +2523,39 @@ var QuestionnaireCardInner = ({
2363
2523
  }) => {
2364
2524
  const questionnaireRef = useRef3(questionnaire);
2365
2525
  const otherInputRefs = useRef3({});
2366
- const [answers, setAnswers] = useState2(
2526
+ const [answers, setAnswers] = useState3(
2367
2527
  () => createInitialAnswers(questionnaire)
2368
2528
  );
2369
- const [otherDrafts, setOtherDrafts] = useState2(
2529
+ const [otherDrafts, setOtherDrafts] = useState3(
2370
2530
  () => createInitialOtherDrafts(questionnaire)
2371
2531
  );
2372
- const [errorMessage, setErrorMessage] = useState2(null);
2373
- const [isSubmitting, setIsSubmitting] = useState2(false);
2374
- const [isSubmitted, setIsSubmitted] = useState2(false);
2375
- const [pendingFocusQuestionId, setPendingFocusQuestionId] = useState2(null);
2532
+ const [errorMessage, setErrorMessage] = useState3(null);
2533
+ const [isSubmitting, setIsSubmitting] = useState3(false);
2534
+ const [isSubmitted, setIsSubmitted] = useState3(() => questionnaire.status === "submitted");
2535
+ const [pendingFocusQuestionId, setPendingFocusQuestionId] = useState3(null);
2376
2536
  const resolvedLabels = {
2377
2537
  ...DEFAULT_QUESTIONNAIRE_CARD_LABELS,
2378
2538
  ...labels
2379
2539
  };
2380
- const hasExternalFailureStatus = questionnaire.status === "expired" || questionnaire.status === "failed";
2540
+ const remainingSeconds = useCountdownSeconds({
2541
+ storageKey: questionnaire.blockKey ?? `questionnaire:${questionnaire.questionnaireId}`,
2542
+ initialSeconds: questionnaire.timeoutSec ?? 0,
2543
+ active: questionnaire.timeoutSec !== void 0 && questionnaire.timeoutSec > 0 && !isSubmitted && questionnaire.status !== "expired" && questionnaire.status !== "failed" && interactive
2544
+ });
2545
+ const isExpired = questionnaire.status === "expired" || questionnaire.timeoutSec !== void 0 && questionnaire.timeoutSec > 0 && remainingSeconds <= 0;
2546
+ const hasExternalFailureStatus = isExpired || questionnaire.status === "failed";
2381
2547
  const question = getQuestionnaireQuestion(questionnaire);
2382
- const visibleErrorMessage = questionnaire.statusMessage ?? errorMessage;
2383
- const isInteractionLocked = !interactive || isSubmitting || isSubmitted || hasExternalFailureStatus;
2548
+ const visibleErrorMessage = questionnaire.statusMessage ?? (isExpired ? null : errorMessage);
2549
+ const isInteractionLocked = !interactive || isSubmitting || isSubmitted || hasExternalFailureStatus || questionnaire.status === "submitted";
2384
2550
  questionnaireRef.current = questionnaire;
2385
- useEffect4(() => {
2551
+ useEffect5(() => {
2386
2552
  setAnswers(createInitialAnswers(questionnaireRef.current));
2387
2553
  setOtherDrafts(createInitialOtherDrafts(questionnaireRef.current));
2388
- }, [questionnaire.answers]);
2389
- useEffect4(() => {
2554
+ if (questionnaireRef.current.status === "submitted") {
2555
+ setIsSubmitted(true);
2556
+ }
2557
+ }, [questionnaire.answers, questionnaire.status]);
2558
+ useEffect5(() => {
2390
2559
  if (!pendingFocusQuestionId || isInteractionLocked) {
2391
2560
  return;
2392
2561
  }
@@ -2636,42 +2805,69 @@ var QuestionnaireCardInner = ({
2636
2805
  }
2637
2806
  };
2638
2807
  return /* @__PURE__ */ jsxs3(Card4, { "data-testid": "questionnaire-card", children: [
2639
- questionnaire.description ? /* @__PURE__ */ jsx5(Description, { children: questionnaire.description }) : null,
2640
- /* @__PURE__ */ jsx5(QuestionList, { children: /* @__PURE__ */ jsxs3(QuestionCard, { children: [
2641
- /* @__PURE__ */ jsxs3(QuestionLabel, { children: [
2642
- question.label,
2643
- question.required ? /* @__PURE__ */ jsx5(Required, { children: "*" }) : null
2644
- ] }),
2645
- question.kind === "multi_select" ? /* @__PURE__ */ jsx5(QuestionHint, { children: resolvedLabels.multiSelectHint }) : null,
2646
- renderQuestion(question)
2647
- ] }, question.id) }),
2648
- visibleErrorMessage ? /* @__PURE__ */ jsx5(ErrorMessage, { "data-testid": "questionnaire-error", children: visibleErrorMessage }) : null,
2649
- isSubmitted ? /* @__PURE__ */ jsx5(SuccessMessage, { "data-testid": "questionnaire-success", children: resolvedLabels.submitted }) : interactive && !hasExternalFailureStatus ? /* @__PURE__ */ jsx5(
2650
- SubmitButton,
2651
- {
2652
- type: "button",
2653
- "data-testid": "questionnaire-submit",
2654
- disabled: isInteractionLocked,
2655
- onClick: () => {
2656
- void handleSubmit();
2657
- },
2658
- children: isSubmitting ? resolvedLabels.submitting : questionnaire.submitLabel ?? "Submit"
2659
- }
2660
- ) : null
2808
+ /* @__PURE__ */ jsx5(Header2, { children: /* @__PURE__ */ jsx5(Eyebrow2, { children: resolvedLabels.questionnaireTitle }) }),
2809
+ /* @__PURE__ */ jsxs3(Content, { children: [
2810
+ questionnaire.description ? /* @__PURE__ */ jsx5(Description, { children: questionnaire.description }) : null,
2811
+ /* @__PURE__ */ jsx5(QuestionList, { children: /* @__PURE__ */ jsxs3(QuestionCard, { children: [
2812
+ /* @__PURE__ */ jsxs3(QuestionLabel, { children: [
2813
+ question.label,
2814
+ question.required ? /* @__PURE__ */ jsx5(Required, { children: "*" }) : null
2815
+ ] }),
2816
+ question.kind === "multi_select" ? /* @__PURE__ */ jsx5(QuestionHint, { children: resolvedLabels.multiSelectHint }) : null,
2817
+ renderQuestion(question)
2818
+ ] }, question.id) }),
2819
+ visibleErrorMessage ? /* @__PURE__ */ jsx5(ErrorMessage, { "data-testid": "questionnaire-error", children: visibleErrorMessage }) : null,
2820
+ /* @__PURE__ */ jsx5(Footer, { children: isSubmitted ? /* @__PURE__ */ jsx5(SuccessMessage, { "data-testid": "questionnaire-success", children: resolvedLabels.submitted }) : isExpired ? /* @__PURE__ */ jsx5(ExpiredTag, { "data-testid": "questionnaire-expired", children: resolvedLabels.expired }) : interactive ? /* @__PURE__ */ jsxs3(FooterActionRow, { "data-testid": "questionnaire-card-actions", children: [
2821
+ remainingSeconds > 0 && /* @__PURE__ */ jsx5(MetaText, { "data-testid": "questionnaire-countdown", children: resolvedLabels.questionnaireConfirmInTime?.replace(
2822
+ "{{seconds}}",
2823
+ String(remainingSeconds)
2824
+ ) ?? `\u8BF7\u5728 ${remainingSeconds} \u79D2\u5185\u786E\u8BA4` }),
2825
+ /* @__PURE__ */ jsx5(
2826
+ SubmitButton,
2827
+ {
2828
+ type: "button",
2829
+ "data-testid": "questionnaire-submit",
2830
+ disabled: isInteractionLocked,
2831
+ onClick: () => {
2832
+ void handleSubmit();
2833
+ },
2834
+ children: isSubmitting ? resolvedLabels.submitting : questionnaire.submitLabel ?? "Submit"
2835
+ }
2836
+ )
2837
+ ] }) : null })
2838
+ ] })
2661
2839
  ] });
2662
2840
  };
2663
2841
  var QuestionnaireCard = (props) => /* @__PURE__ */ jsx5(QuestionnaireCardInner, { ...props }, getQuestionnaireStateKey(props.questionnaire));
2664
2842
  var Card4 = styled4.section`
2665
- display: grid;
2666
- gap: 14px;
2667
- padding: 16px;
2668
- border-radius: 20px;
2669
- border: 1px solid rgba(255, 255, 255, 0.08);
2670
- background: rgba(255, 255, 255, 0.03);
2843
+ overflow: hidden;
2844
+ background: var(--bg-primary);
2845
+ border-radius: 16px;
2846
+ border: 1px solid var(--border-hover);
2847
+ `;
2848
+ var Header2 = styled4.div`
2849
+ display: flex;
2850
+ flex-wrap: wrap;
2851
+ align-items: center;
2852
+ gap: 10px;
2853
+ padding: 22px 12px 16px;
2854
+ border-bottom: 1px solid var(--border-hover);
2855
+ `;
2856
+ var Eyebrow2 = styled4.div`
2857
+ font-weight: 500;
2858
+ font-size: 16px;
2859
+ color: var(--text-primary);
2860
+ line-height: 22px;
2861
+ `;
2862
+ var Content = styled4.div`
2863
+ display: flex;
2864
+ flex-direction: column;
2865
+ gap: 16px;
2866
+ padding: 16px 12px;
2671
2867
  `;
2672
2868
  var Description = styled4.p`
2673
2869
  margin: 0;
2674
- color: rgba(255, 255, 255, 0.72);
2870
+ color: var(--text-secondary);
2675
2871
  font-size: 13px;
2676
2872
  `;
2677
2873
  var QuestionList = styled4.div`
@@ -2682,11 +2878,11 @@ var QuestionCard = styled4.div`
2682
2878
  display: grid;
2683
2879
  gap: 10px;
2684
2880
  padding: 12px;
2685
- border-radius: 16px;
2686
- background: rgba(255, 255, 255, 0.04);
2881
+ border-radius: 8px;
2882
+ background: rgba(255, 255, 255, 0.02);
2687
2883
  `;
2688
2884
  var QuestionLabel = styled4.div`
2689
- color: rgba(255, 255, 255, 0.9);
2885
+ color: var(--text-primary);
2690
2886
  font-size: 14px;
2691
2887
  font-weight: 600;
2692
2888
  `;
@@ -2713,11 +2909,11 @@ var OptionChoiceItem = styled4.div`
2713
2909
  gap: 12px;
2714
2910
  width: 100%;
2715
2911
  text-align: left;
2716
- border: 1px solid rgba(255, 255, 255, 0.1);
2717
- border-radius: 14px;
2718
- background: rgba(255, 255, 255, 0.03);
2912
+ border: 1px solid var(--border-hover);
2913
+ border-radius: 8px;
2914
+ background: rgba(255, 255, 255, 0.02);
2719
2915
  padding: 2px 12px;
2720
- color: rgba(255, 255, 255, 0.9);
2916
+ color: var(--text-primary);
2721
2917
  cursor: pointer;
2722
2918
  transition:
2723
2919
  border-color 140ms ease,
@@ -2726,8 +2922,8 @@ var OptionChoiceItem = styled4.div`
2726
2922
  outline: none;
2727
2923
 
2728
2924
  &[data-selected='true'] {
2729
- border-color: rgba(126, 160, 255, 0.42);
2730
- background: linear-gradient(180deg, rgba(82, 114, 255, 0.18) 0%, rgba(82, 114, 255, 0.1) 100%);
2925
+ border-color: rgba(51, 133, 255, 0.42);
2926
+ background: linear-gradient(180deg, rgba(51, 133, 255, 0.18) 0%, rgba(51, 133, 255, 0.1) 100%);
2731
2927
  transform: translateY(-1px);
2732
2928
  }
2733
2929
 
@@ -2736,8 +2932,8 @@ var OptionChoiceItem = styled4.div`
2736
2932
  }
2737
2933
 
2738
2934
  &:focus-visible {
2739
- border-color: rgba(126, 160, 255, 0.52);
2740
- box-shadow: 0 0 0 1px rgba(126, 160, 255, 0.18);
2935
+ border-color: rgba(51, 133, 255, 0.52);
2936
+ box-shadow: 0 0 0 1px rgba(51, 133, 255, 0.18);
2741
2937
  }
2742
2938
 
2743
2939
  &[tabindex='-1'] {
@@ -2754,16 +2950,16 @@ var OptionChoiceMarker = styled4.span`
2754
2950
  width: 28px;
2755
2951
  height: 28px;
2756
2952
  border-radius: 8px;
2757
- border: 1px solid rgba(255, 255, 255, 0.14);
2758
- background: rgba(255, 255, 255, 0.04);
2759
- color: rgba(255, 255, 255, 0.65);
2953
+ border: 1px solid var(--border-hover);
2954
+ background: rgba(255, 255, 255, 0.02);
2955
+ color: var(--text-secondary);
2760
2956
  font-size: 12px;
2761
2957
  font-weight: 700;
2762
2958
 
2763
2959
  &[data-selected='true'] {
2764
- border-color: rgba(126, 160, 255, 0.38);
2765
- background: rgba(126, 160, 255, 0.2);
2766
- color: rgba(255, 255, 255, 0.96);
2960
+ border-color: rgba(51, 133, 255, 0.38);
2961
+ background: rgba(51, 133, 255, 0.2);
2962
+ color: var(--text-primary);
2767
2963
  }
2768
2964
  `;
2769
2965
  var OptionChoiceContent = styled4.span`
@@ -2783,47 +2979,41 @@ var OptionChoiceLabel = styled4.span`
2783
2979
  `;
2784
2980
  var TextInput = styled4.input`
2785
2981
  width: 100%;
2786
- border: 1px solid rgba(255, 255, 255, 0.1);
2787
- border-radius: 12px;
2982
+ border: 1px solid var(--border-hover);
2983
+ border-radius: 8px;
2788
2984
  background: rgba(13, 15, 21, 0.55);
2789
- color: rgba(255, 255, 255, 0.92);
2985
+ color: var(--text-primary);
2790
2986
  font-size: 13px;
2791
2987
  padding: 10px 12px;
2792
2988
 
2793
2989
  &::placeholder {
2794
- color: rgba(255, 255, 255, 0.34);
2990
+ color: var(--text-secondary);
2991
+ opacity: 0.5;
2795
2992
  }
2796
2993
  `;
2797
2994
  var InlineOtherInput = styled4.input`
2798
2995
  width: 100%;
2799
- margin-top: 0;
2800
-
2801
- .compass-input-wrapper {
2802
- min-height: 30px;
2803
- border: 1px solid rgba(255, 255, 255, 0.1);
2804
- border-radius: 10px;
2805
- background: rgba(13, 15, 21, 0.55);
2806
- box-shadow: none;
2807
- padding: 2px 9px;
2808
- }
2809
-
2810
- .compass-input-wrapper:hover {
2811
- border-color: rgba(126, 160, 255, 0.28);
2812
- }
2996
+ border: 1px solid var(--border-hover);
2997
+ border-radius: 6px;
2998
+ background: rgba(13, 15, 21, 0.45);
2999
+ color: var(--text-primary);
3000
+ font-size: 13px;
3001
+ padding: 6px 10px;
3002
+ outline: none;
3003
+ transition: border-color 140ms ease;
2813
3004
 
2814
- .compass-input-wrapper:focus-within {
2815
- border-color: rgba(126, 160, 255, 0.42);
2816
- box-shadow: 0 0 0 1px rgba(126, 160, 255, 0.14);
3005
+ &:hover {
3006
+ border-color: rgba(51, 133, 255, 0.28);
2817
3007
  }
2818
3008
 
2819
- .compass-input-input {
2820
- color: rgba(255, 255, 255, 0.92);
2821
- font-size: 13px;
2822
- line-height: 1.2;
3009
+ &:focus {
3010
+ border-color: rgba(51, 133, 255, 0.42);
3011
+ box-shadow: 0 0 0 1px rgba(51, 133, 255, 0.14);
2823
3012
  }
2824
3013
 
2825
- .compass-input-input::placeholder {
2826
- color: rgba(255, 255, 255, 0.34);
3014
+ &::placeholder {
3015
+ color: var(--text-secondary);
3016
+ opacity: 0.5;
2827
3017
  }
2828
3018
  `;
2829
3019
  var NumberInputRow = styled4.div`
@@ -2832,32 +3022,80 @@ var NumberInputRow = styled4.div`
2832
3022
  gap: 10px;
2833
3023
  `;
2834
3024
  var Unit = styled4.span`
2835
- color: rgba(255, 255, 255, 0.58);
3025
+ color: var(--text-secondary);
2836
3026
  font-size: 12px;
2837
3027
  white-space: nowrap;
2838
3028
  `;
2839
3029
  var ErrorMessage = styled4.div`
2840
- color: rgba(255, 145, 145, 0.96);
3030
+ font-size: 13px;
3031
+ line-height: 1.5;
3032
+ color: rgba(255, 207, 207, 0.92);
3033
+ `;
3034
+ var Footer = styled4.div`
3035
+ display: flex;
3036
+ flex-wrap: wrap;
3037
+ align-items: center;
3038
+ justify-content: flex-start;
3039
+ gap: 12px;
3040
+ `;
3041
+ var FooterActionRow = styled4.div`
3042
+ display: flex;
3043
+ align-items: center;
3044
+ flex-wrap: wrap;
3045
+ gap: 8px;
3046
+ margin-left: auto;
3047
+ justify-content: flex-end;
3048
+ `;
3049
+ var MetaText = styled4.span`
3050
+ font-weight: 500;
2841
3051
  font-size: 12px;
3052
+ color: var(--text-secondary);
3053
+ line-height: 17px;
3054
+ `;
3055
+ var ExpiredTag = styled4.span`
3056
+ display: inline-flex;
3057
+ align-items: center;
3058
+ padding: 8px 12px;
3059
+ border-radius: 8px;
3060
+ font-size: 13px;
3061
+ font-weight: 600;
3062
+ background: rgba(255, 255, 255, 0.05);
3063
+ border: 1px solid rgba(255, 255, 255, 0.12);
3064
+ color: rgba(214, 224, 236, 0.9);
2842
3065
  `;
2843
3066
  var SuccessMessage = styled4.div`
2844
- color: rgba(164, 255, 210, 0.96);
2845
- font-size: 12px;
3067
+ display: inline-flex;
3068
+ align-items: center;
3069
+ padding: 8px 12px;
3070
+ border-radius: 8px;
3071
+ font-size: 13px;
3072
+ font-weight: 600;
3073
+ background: rgba(190, 246, 202, 0.14);
3074
+ border: 1px solid rgba(190, 246, 202, 0.24);
3075
+ color: rgba(227, 255, 233, 0.94);
2846
3076
  `;
2847
3077
  var SubmitButton = styled4.button`
2848
- justify-self: flex-start;
2849
- border: none;
2850
- border-radius: 999px;
2851
- background: linear-gradient(180deg, #7ea0ff 0%, #4a6fff 100%);
2852
- color: #081127;
2853
- font-size: 12px;
2854
- font-weight: 700;
2855
- padding: 10px 14px;
3078
+ padding: 9px 16px;
3079
+ border-radius: 8px;
3080
+ border: 1px solid transparent;
3081
+ font-weight: 500;
3082
+ font-size: 14px;
3083
+ color: rgba(255, 255, 255, 0.96);
3084
+ background: linear-gradient(180deg, #3385ff 0%, #1f6ef2 100%);
3085
+ line-height: 14px;
2856
3086
  cursor: pointer;
3087
+ transition:
3088
+ transform 160ms ease,
3089
+ opacity 160ms ease;
2857
3090
 
2858
3091
  &:disabled {
2859
- cursor: default;
2860
- opacity: 0.72;
3092
+ cursor: progress;
3093
+ opacity: 0.68;
3094
+ transform: none;
3095
+ }
3096
+
3097
+ &:not(:disabled):hover {
3098
+ transform: translateY(-1px);
2861
3099
  }
2862
3100
  `;
2863
3101
 
@@ -2865,7 +3103,7 @@ var SubmitButton = styled4.button`
2865
3103
  import styled5 from "@emotion/styled";
2866
3104
  import { jsx as jsx6, jsxs as jsxs4 } from "@emotion/react/jsx-runtime";
2867
3105
  var ResultSummaryCard = ({ summary }) => /* @__PURE__ */ jsxs4(Card5, { "data-testid": "result-summary-card", "data-status": summary.status, children: [
2868
- /* @__PURE__ */ jsx6(Eyebrow2, { children: summary.status }),
3106
+ /* @__PURE__ */ jsx6(Eyebrow3, { children: summary.status }),
2869
3107
  /* @__PURE__ */ jsx6(Headline, { children: summary.headline }),
2870
3108
  /* @__PURE__ */ jsx6(Details, { children: summary.details.map((detail) => /* @__PURE__ */ jsx6(Detail, { children: detail }, detail)) })
2871
3109
  ] });
@@ -2885,7 +3123,7 @@ var Card5 = styled5.section`
2885
3123
  border-color: rgba(255, 122, 122, 0.24);
2886
3124
  }
2887
3125
  `;
2888
- var Eyebrow2 = styled5.span`
3126
+ var Eyebrow3 = styled5.span`
2889
3127
  color: rgba(255, 255, 255, 0.58);
2890
3128
  font-size: 11px;
2891
3129
  font-weight: 700;
@@ -2910,7 +3148,7 @@ var Detail = styled5.li`
2910
3148
 
2911
3149
  // src/components/chat-thread/components/image-viewer.tsx
2912
3150
  import styled6 from "@emotion/styled";
2913
- import { useEffect as useEffect5, useRef as useRef4 } from "react";
3151
+ import { useEffect as useEffect6, useRef as useRef4 } from "react";
2914
3152
  import { jsx as jsx7 } from "@emotion/react/jsx-runtime";
2915
3153
  var Overlay = styled6.div`
2916
3154
  position: fixed;
@@ -2930,7 +3168,7 @@ var Img = styled6.img`
2930
3168
  `;
2931
3169
  var ImageViewer = ({ src, alt, onClose }) => {
2932
3170
  const overlayRef = useRef4(null);
2933
- useEffect5(() => {
3171
+ useEffect6(() => {
2934
3172
  const handleKey = (e) => {
2935
3173
  if (e.key === "Escape")
2936
3174
  onClose();
@@ -2938,7 +3176,7 @@ var ImageViewer = ({ src, alt, onClose }) => {
2938
3176
  document.addEventListener("keydown", handleKey);
2939
3177
  return () => document.removeEventListener("keydown", handleKey);
2940
3178
  }, [onClose]);
2941
- useEffect5(() => {
3179
+ useEffect6(() => {
2942
3180
  overlayRef.current?.focus();
2943
3181
  }, []);
2944
3182
  const stopPropagation = (e) => e.stopPropagation();
@@ -3004,9 +3242,9 @@ var useUserMessageCollapse = ({
3004
3242
  freshContent,
3005
3243
  settledContent
3006
3244
  }) => {
3007
- const [isCollapsible, setIsCollapsible] = useState3(false);
3008
- const [isExpanded, setIsExpanded] = useState3(false);
3009
- const [bodyStackElement, setBodyStackElement] = useState3(null);
3245
+ const [isCollapsible, setIsCollapsible] = useState4(false);
3246
+ const [isExpanded, setIsExpanded] = useState4(false);
3247
+ const [bodyStackElement, setBodyStackElement] = useState4(null);
3010
3248
  const syncCollapseState = useCallback2(
3011
3249
  (element) => {
3012
3250
  const nextCollapsible = enabled && (element?.scrollHeight ?? 0) > USER_MESSAGE_COLLAPSE_HEIGHT_PX;
@@ -3192,7 +3430,7 @@ var ChatMessageItemView = ({
3192
3430
  renderMessageBlock
3193
3431
  }) => {
3194
3432
  const { labels, messageRenderOrder = "blocks-first" } = useChatContext();
3195
- const [activeImage, setActiveImage] = useState3(void 0);
3433
+ const [activeImage, setActiveImage] = useState4(void 0);
3196
3434
  const {
3197
3435
  displayedBlocks,
3198
3436
  displayedContent,
@@ -3209,8 +3447,9 @@ var ChatMessageItemView = ({
3209
3447
  const hasMarkdownOnlyBlocks = hasStructuredBlocks && blocks.every((block) => block.type === "markdown");
3210
3448
  const hasTextContent = Boolean(settledContent || freshContent || displayedContent);
3211
3449
  const shouldRenderStructuredBlocks = hasStructuredBlocks && !(isAssistantStreaming && hasMarkdownOnlyBlocks && hasTextContent);
3212
- const canSubmitConfirmation = typeof onConfirmationSubmit === "function";
3213
- const canSubmitQuestionnaire = typeof onQuestionnaireSubmit === "function";
3450
+ const isInteractionDisabled = message.status === "stopped" || message.status === "error";
3451
+ const canSubmitConfirmation = typeof onConfirmationSubmit === "function" && !isInteractionDisabled;
3452
+ const canSubmitQuestionnaire = typeof onQuestionnaireSubmit === "function" && !isInteractionDisabled;
3214
3453
  const shouldShowStreamingCaret = isAssistantStreaming && (!shouldRenderStructuredBlocks || hasTextContent);
3215
3454
  const isUserMessage = message.role === "user";
3216
3455
  const messageRenderMode = isUserMessage ? "plain-text" : "markdown";
@@ -3291,7 +3530,10 @@ var ChatMessageItemView = ({
3291
3530
  submitFailed: labels.questionnaireSubmitFailed,
3292
3531
  multiSelectHint: labels.questionnaireMultiSelectHint,
3293
3532
  otherOptionLabel: labels.questionnaireOtherOptionLabel,
3294
- otherPlaceholder: labels.questionnaireOtherPlaceholder
3533
+ otherPlaceholder: labels.questionnaireOtherPlaceholder,
3534
+ expired: labels.questionnaireExpired,
3535
+ questionnaireTitle: labels.questionnaireTitle,
3536
+ questionnaireConfirmInTime: labels.questionnaireConfirmInTime
3295
3537
  },
3296
3538
  onSubmit: canSubmitQuestionnaire ? (submission) => onQuestionnaireSubmit({
3297
3539
  ...submission,
@@ -3394,7 +3636,7 @@ var ChatMessageItemView = ({
3394
3636
  })();
3395
3637
  return /* @__PURE__ */ jsxs5(Fragment2, { children: [
3396
3638
  /* @__PURE__ */ jsxs5(Bubble, { "data-role": message.role, "data-status": message.status ?? "done", children: [
3397
- shouldRenderHeader ? /* @__PURE__ */ jsxs5(Header2, { children: [
3639
+ shouldRenderHeader ? /* @__PURE__ */ jsxs5(Header3, { children: [
3398
3640
  isAssistantStreaming ? /* @__PURE__ */ jsxs5(
3399
3641
  StreamingIndicator,
3400
3642
  {
@@ -3419,7 +3661,7 @@ var ChatMessageItemView = ({
3419
3661
  ) : null,
3420
3662
  isStoppedAssistant ? /* @__PURE__ */ jsx8(StatusTag, { "data-testid": "chat-message-stopped-tag", children: labels.stoppedResponse }) : null
3421
3663
  ] }) : null,
3422
- /* @__PURE__ */ jsxs5(Content, { "data-testid": "chat-message-content", children: [
3664
+ /* @__PURE__ */ jsxs5(Content2, { "data-testid": "chat-message-content", children: [
3423
3665
  skills.length ? /* @__PURE__ */ jsx8(SkillTagList, { "data-testid": "chat-message-skill-tags", children: skills.map((skill) => /* @__PURE__ */ jsx8(SkillTag, { children: skill }, skill)) }) : null,
3424
3666
  shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ jsx8(
3425
3667
  ContentStack,
@@ -3499,7 +3741,7 @@ var Bubble = styled7.article`
3499
3741
  border-radius: 16px;
3500
3742
  }
3501
3743
  `;
3502
- var Header2 = styled7.div`
3744
+ var Header3 = styled7.div`
3503
3745
  display: flex;
3504
3746
  align-items: center;
3505
3747
  gap: 10px;
@@ -3541,7 +3783,7 @@ var CollapseToggle = styled7.button`
3541
3783
  color: rgba(255, 255, 255, 0.92);
3542
3784
  }
3543
3785
  `;
3544
- var Content = styled7.div`
3786
+ var Content2 = styled7.div`
3545
3787
  color: rgba(255, 255, 255, 0.92);
3546
3788
  font-size: 14px;
3547
3789
  line-height: 1.6;
@@ -3927,9 +4169,9 @@ var ChatThreadView = ({
3927
4169
  const isPinnedRef = useRef5(true);
3928
4170
  const lastHistoryMessageIdRef = useRef5(latestHistoryMessage?.id);
3929
4171
  const lastStreamingMessageIdRef = useRef5(streamingMessage?.id);
3930
- const [latestTurnMinHeight, setLatestTurnMinHeight] = useState4(0);
3931
- const [isDetached, setIsDetached] = useState4(false);
3932
- const [pendingNewMessageCount, setPendingNewMessageCount] = useState4(0);
4172
+ const [latestTurnMinHeight, setLatestTurnMinHeight] = useState5(0);
4173
+ const [isDetached, setIsDetached] = useState5(false);
4174
+ const [pendingNewMessageCount, setPendingNewMessageCount] = useState5(0);
3933
4175
  const measureLatestTurnMinHeight = useCallback3(() => {
3934
4176
  const container = containerRef.current;
3935
4177
  if (!container)
@@ -4323,13 +4565,14 @@ var ChatThread = () => {
4323
4565
  if (!hasSessions || messages.length === 0 && !streamingMessage) {
4324
4566
  return /* @__PURE__ */ jsx10(ChatThreadEmptyState, {});
4325
4567
  }
4568
+ 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;
4326
4569
  return /* @__PURE__ */ jsx10(
4327
4570
  ChatThreadView,
4328
4571
  {
4329
4572
  activeMode: preferredMode,
4330
4573
  historyMessages: messages,
4331
4574
  streamingMessage,
4332
- error: error2,
4575
+ error: displayError,
4333
4576
  isLoadingPreviousMessages: historyMessagePagination?.isLoadingPrevious,
4334
4577
  previousMessagesError: historyMessagePagination?.error,
4335
4578
  retryButtonLabel: labels.retryButton,
@@ -4478,7 +4721,7 @@ var ScrollToLatestBadge = styled9.span`
4478
4721
  `;
4479
4722
 
4480
4723
  // src/components/chat-composer/index.tsx
4481
- import { useCallback as useCallback8, useEffect as useEffect9, useLayoutEffect as useLayoutEffect6, useRef as useRef11, useState as useState10 } from "react";
4724
+ import { useCallback as useCallback8, useEffect as useEffect10, useLayoutEffect as useLayoutEffect6, useRef as useRef11, useState as useState11 } from "react";
4482
4725
  import styled14 from "@emotion/styled";
4483
4726
 
4484
4727
  // ../../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
@@ -7076,10 +7319,10 @@ var resolveSendSession = ({
7076
7319
  };
7077
7320
 
7078
7321
  // src/components/chat-composer/hooks/use-chat-composer.ts
7079
- import { useCallback as useCallback7, useEffect as useEffect8, useRef as useRef10, useState as useState8 } from "react";
7322
+ import { useCallback as useCallback7, useEffect as useEffect9, useRef as useRef10, useState as useState9 } from "react";
7080
7323
 
7081
7324
  // src/components/chat-composer/hooks/use-composer-attachments.ts
7082
- import { useEffect as useEffect7, useRef as useRef9, useState as useState7 } from "react";
7325
+ import { useEffect as useEffect8, useRef as useRef9, useState as useState8 } from "react";
7083
7326
  var SUPPORTED_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp"]);
7084
7327
  var MAX_COMPOSER_ATTACHMENTS = 10;
7085
7328
  var createObjectUrl = (file) => typeof URL !== "undefined" && typeof URL.createObjectURL === "function" ? URL.createObjectURL(file) : "";
@@ -7093,12 +7336,12 @@ var releaseComposerAttachments = (attachments) => {
7093
7336
  attachments.forEach((attachment) => revokeObjectUrl(attachment.previewUrl));
7094
7337
  };
7095
7338
  var useComposerAttachments = () => {
7096
- const [attachments, setAttachments] = useState7([]);
7339
+ const [attachments, setAttachments] = useState8([]);
7097
7340
  const attachmentsRef = useRef9([]);
7098
- useEffect7(() => {
7341
+ useEffect8(() => {
7099
7342
  attachmentsRef.current = attachments;
7100
7343
  }, [attachments]);
7101
- useEffect7(
7344
+ useEffect8(
7102
7345
  () => () => {
7103
7346
  releaseComposerAttachments(attachmentsRef.current);
7104
7347
  },
@@ -7246,13 +7489,13 @@ var useChatComposer = () => {
7246
7489
  const setSessionError = useChatStore((s) => s.setSessionError);
7247
7490
  const clearSessionError = useChatStore((s) => s.clearSessionError);
7248
7491
  const setPreferredMode = useChatStore((s) => s.setPreferredMode);
7249
- const [availableModels, setAvailableModels] = useState8([]);
7250
- const [isModelsLoading, setIsModelsLoading] = useState8(true);
7251
- const [isModelsError, setIsModelsError] = useState8(false);
7252
- const [availableSkills, setAvailableSkills] = useState8(
7492
+ const [availableModels, setAvailableModels] = useState9([]);
7493
+ const [isModelsLoading, setIsModelsLoading] = useState9(true);
7494
+ const [isModelsError, setIsModelsError] = useState9(false);
7495
+ const [availableSkills, setAvailableSkills] = useState9(
7253
7496
  () => getCachedSkills(skillsLoader).skills
7254
7497
  );
7255
- const [isSkillsLoading, setIsSkillsLoading] = useState8(
7498
+ const [isSkillsLoading, setIsSkillsLoading] = useState9(
7256
7499
  () => Boolean(skillsLoader) && !getCachedSkills(skillsLoader).resolved
7257
7500
  );
7258
7501
  const fetchModels = useCallback7(async () => {
@@ -7267,10 +7510,10 @@ var useChatComposer = () => {
7267
7510
  setIsModelsLoading(false);
7268
7511
  }
7269
7512
  }, [modelsLoader]);
7270
- useEffect8(() => {
7513
+ useEffect9(() => {
7271
7514
  void fetchModels();
7272
7515
  }, [fetchModels]);
7273
- useEffect8(() => {
7516
+ useEffect9(() => {
7274
7517
  activeSkillsLoaderRef.current = skillsLoader;
7275
7518
  const cachedSkills = getCachedSkills(skillsLoader);
7276
7519
  setAvailableSkills(cachedSkills.skills);
@@ -7306,35 +7549,35 @@ var useChatComposer = () => {
7306
7549
  }
7307
7550
  }
7308
7551
  }, [skillsLoader]);
7309
- useEffect8(() => {
7552
+ useEffect9(() => {
7310
7553
  void fetchSkills();
7311
7554
  }, [fetchSkills]);
7312
7555
  const hasModels = availableModels.length > 0;
7313
- const [value, setValue] = useState8("");
7314
- const [selectedModel, setSelectedModel] = useState8("");
7315
- const [selectedMode, setSelectedModeLocal] = useState8(DEFAULT_CHAT_AGENT_MODE);
7316
- const [selectedSkills, setSelectedSkills] = useState8([]);
7317
- const [attachmentNotice, setAttachmentNotice] = useState8(null);
7556
+ const [value, setValue] = useState9("");
7557
+ const [selectedModel, setSelectedModel] = useState9("");
7558
+ const [selectedMode, setSelectedModeLocal] = useState9(DEFAULT_CHAT_AGENT_MODE);
7559
+ const [selectedSkills, setSelectedSkills] = useState9([]);
7560
+ const [attachmentNotice, setAttachmentNotice] = useState9(null);
7318
7561
  const { attachments, appendFiles, removeAttachment, takeMessageAttachments } = useComposerAttachments();
7319
7562
  const abortControllerBySessionRef = useRef10(/* @__PURE__ */ new Map());
7320
7563
  const stopRequestBySessionRef = useRef10(/* @__PURE__ */ new Map());
7321
7564
  const lastRequestBySessionRef = useRef10(/* @__PURE__ */ new Map());
7322
7565
  const previousActiveSessionIdRef = useRef10(activeSessionId);
7323
- useEffect8(() => {
7566
+ useEffect9(() => {
7324
7567
  setSelectedModel(
7325
7568
  (current) => resolveSelectedChatModel({ currentModel: current, availableModels, isModelsLoading })
7326
7569
  );
7327
7570
  }, [availableModels, isModelsLoading]);
7328
- useEffect8(() => {
7571
+ useEffect9(() => {
7329
7572
  setSelectedModeLocal(preferredMode ?? DEFAULT_CHAT_AGENT_MODE);
7330
7573
  }, [preferredMode]);
7331
- useEffect8(() => {
7574
+ useEffect9(() => {
7332
7575
  if (previousActiveSessionIdRef.current !== activeSessionId) {
7333
7576
  setSelectedSkills([]);
7334
7577
  previousActiveSessionIdRef.current = activeSessionId;
7335
7578
  }
7336
7579
  }, [activeSessionId]);
7337
- useEffect8(() => {
7580
+ useEffect9(() => {
7338
7581
  if (!attachmentNotice)
7339
7582
  return;
7340
7583
  const timeoutId = window.setTimeout(
@@ -7718,14 +7961,14 @@ var useChatComposer = () => {
7718
7961
  };
7719
7962
 
7720
7963
  // src/components/chat-composer/components/chat-composer-attachment-list.tsx
7721
- import { useState as useState9 } from "react";
7964
+ import { useState as useState10 } from "react";
7722
7965
  import styled10 from "@emotion/styled";
7723
7966
  import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs9 } from "@emotion/react/jsx-runtime";
7724
7967
  var ChatComposerAttachmentList = ({
7725
7968
  attachments,
7726
7969
  onRemoveAttachment
7727
7970
  }) => {
7728
- const [activeImage, setActiveImage] = useState9(null);
7971
+ const [activeImage, setActiveImage] = useState10(null);
7729
7972
  if (!attachments.length) {
7730
7973
  return null;
7731
7974
  }
@@ -8406,9 +8649,9 @@ var ChatComposerView = ({
8406
8649
  }) => {
8407
8650
  const imageInputRef = useRef11(null);
8408
8651
  const inputRef = useRef11(null);
8409
- const [isComposerExpandable, setIsComposerExpandable] = useState10(false);
8410
- const [isComposerExpanded, setIsComposerExpanded] = useState10(false);
8411
- const [activeSkillNavigation, setActiveSkillNavigation] = useState10({
8652
+ const [isComposerExpandable, setIsComposerExpandable] = useState11(false);
8653
+ const [isComposerExpanded, setIsComposerExpanded] = useState11(false);
8654
+ const [activeSkillNavigation, setActiveSkillNavigation] = useState11({
8412
8655
  queryKey: "",
8413
8656
  index: 0
8414
8657
  });
@@ -8614,7 +8857,7 @@ var ChatComposerView = ({
8614
8857
  }
8615
8858
  )
8616
8859
  ] }),
8617
- /* @__PURE__ */ jsxs11(Footer, { children: [
8860
+ /* @__PURE__ */ jsxs11(Footer2, { children: [
8618
8861
  /* @__PURE__ */ jsxs11(LeadingActions, { "data-testid": "chat-composer-leading-actions", children: [
8619
8862
  enableImageAttachments ? /* @__PURE__ */ jsx16(
8620
8863
  AttachButton,
@@ -8706,7 +8949,7 @@ var ChatComposer = () => {
8706
8949
  const { labels, sendRef, retryRef, stopRef, enableImageAttachments } = useChatContext();
8707
8950
  const { state, actions } = useChatComposer();
8708
8951
  const { send, retry } = actions;
8709
- useEffect9(() => {
8952
+ useEffect10(() => {
8710
8953
  sendRef.current = send;
8711
8954
  retryRef.current = async (sessionId) => {
8712
8955
  retry(sessionId);
@@ -8954,7 +9197,7 @@ var ComposerExpandButton = styled14.button`
8954
9197
  color: rgba(255, 255, 255, 0.92);
8955
9198
  }
8956
9199
  `;
8957
- var Footer = styled14.div`
9200
+ var Footer2 = styled14.div`
8958
9201
  grid-area: footer;
8959
9202
  display: flex;
8960
9203
  align-items: center;
@@ -9035,7 +9278,7 @@ var SkillButton = styled14.button`
9035
9278
  `;
9036
9279
 
9037
9280
  // src/components/chat-conversation-list/index.tsx
9038
- import { useEffect as useEffect10, useRef as useRef12 } from "react";
9281
+ import { useEffect as useEffect11, useRef as useRef12 } from "react";
9039
9282
  import styled16 from "@emotion/styled";
9040
9283
 
9041
9284
  // src/components/chat-conversation-list/components/chat-session-item.tsx
@@ -9138,12 +9381,12 @@ var ChatConversationList = () => {
9138
9381
  );
9139
9382
  const isLoadingMoreRef = useRef12(false);
9140
9383
  const hasSeenLoadingMoreRef = useRef12(false);
9141
- useEffect10(() => {
9384
+ useEffect11(() => {
9142
9385
  if (!historySessionList)
9143
9386
  return;
9144
9387
  hydrateHistorySessions(historySessionList.sessions);
9145
9388
  }, [historySessionList, hydrateHistorySessions]);
9146
- useEffect10(() => {
9389
+ useEffect11(() => {
9147
9390
  if (historySessionList?.isLoading) {
9148
9391
  hasSeenLoadingMoreRef.current = true;
9149
9392
  return;
@@ -9153,7 +9396,7 @@ var ChatConversationList = () => {
9153
9396
  isLoadingMoreRef.current = false;
9154
9397
  }
9155
9398
  }, [historySessionList?.isLoading]);
9156
- useEffect10(() => {
9399
+ useEffect11(() => {
9157
9400
  isLoadingMoreRef.current = false;
9158
9401
  hasSeenLoadingMoreRef.current = false;
9159
9402
  }, [historySessionList?.sessions.length, historySessionList?.hasMore]);
@@ -9352,7 +9595,7 @@ var AiChatWorkspaceContent = ({
9352
9595
  })
9353
9596
  );
9354
9597
  const shouldShowComposerOnly = showComposerOnlyBeforeFirstMessage && !showConversationList && !isConversationStarted;
9355
- useEffect11(() => {
9598
+ useEffect12(() => {
9356
9599
  onConversationStartedChange?.(isConversationStarted);
9357
9600
  }, [isConversationStarted, onConversationStartedChange]);
9358
9601
  return /* @__PURE__ */ jsxs13(Root, { "data-testid": "ai-chat", children: [