@xinghunm/ai-chat 1.2.2 → 1.3.1

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,6 +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_react20 = require("react");
49
50
  var import_styled17 = __toESM(require("@emotion/styled"));
50
51
  var import_compass_ui4 = require("@xinghunm/compass-ui");
51
52
 
@@ -94,6 +95,9 @@ var DEFAULT_AI_CHAT_LABELS = {
94
95
  questionnaireMultiSelectHint: "Multiple choice",
95
96
  questionnaireOtherOptionLabel: "Other",
96
97
  questionnaireOtherPlaceholder: "Other",
98
+ modelLoading: "Loading models...",
99
+ modelLoadFailed: "Failed to load models",
100
+ modelUnavailable: "No model available",
97
101
  skillLoading: "Loading skills...",
98
102
  skillEmpty: "No matching skills",
99
103
  removeSkillAriaLabel: "Remove skill"
@@ -129,6 +133,9 @@ var resolveSessionTitleFromMessage = (message) => {
129
133
  if (trimmedContent) {
130
134
  return trimmedContent.slice(0, 30);
131
135
  }
136
+ if (message.skills?.length) {
137
+ return message.skills.join(", ").slice(0, 30);
138
+ }
132
139
  if ((message.attachments?.length ?? 0) > 0) {
133
140
  return IMAGE_MESSAGE_SESSION_TITLE;
134
141
  }
@@ -674,7 +681,7 @@ var createDefaultRequestBody = async ({
674
681
  attachments
675
682
  }) => {
676
683
  const hasAttachments = Boolean(attachments?.length);
677
- const skillPayload = skills?.length ? { skill: skills.length === 1 ? skills[0] : skills } : {};
684
+ const skillPayload = skills?.length ? { skills } : {};
678
685
  if (!hasAttachments) {
679
686
  return {
680
687
  model,
@@ -2866,7 +2873,7 @@ var areMessageBlocksEqual = (previousBlocks, nextBlocks) => {
2866
2873
  }
2867
2874
  });
2868
2875
  };
2869
- var isSameMessage = (previousMessage, nextMessage, previousMode, nextMode, previousConfirmationSubmit, nextConfirmationSubmit, previousQuestionnaireSubmit, nextQuestionnaireSubmit, previousRenderMessageBlock, nextRenderMessageBlock) => previousMessage.id === nextMessage.id && previousMessage.sessionId === nextMessage.sessionId && previousMessage.role === nextMessage.role && previousMessage.content === nextMessage.content && areMessageBlocksEqual(previousMessage.blocks, nextMessage.blocks) && previousMessage.localOnly === nextMessage.localOnly && areChatAttachmentsEqual(previousMessage.attachments, nextMessage.attachments) && previousMessage.status === nextMessage.status && previousMessage.createdAt === nextMessage.createdAt && previousMode === nextMode && previousConfirmationSubmit === nextConfirmationSubmit && previousQuestionnaireSubmit === nextQuestionnaireSubmit && previousRenderMessageBlock === nextRenderMessageBlock;
2876
+ var isSameMessage = (previousMessage, nextMessage, previousMode, nextMode, previousConfirmationSubmit, nextConfirmationSubmit, previousQuestionnaireSubmit, nextQuestionnaireSubmit, previousRenderMessageBlock, nextRenderMessageBlock) => previousMessage.id === nextMessage.id && previousMessage.sessionId === nextMessage.sessionId && previousMessage.role === nextMessage.role && previousMessage.content === nextMessage.content && areStringArraysEqual(previousMessage.skills ?? [], nextMessage.skills ?? []) && areMessageBlocksEqual(previousMessage.blocks, nextMessage.blocks) && previousMessage.localOnly === nextMessage.localOnly && areChatAttachmentsEqual(previousMessage.attachments, nextMessage.attachments) && previousMessage.status === nextMessage.status && previousMessage.createdAt === nextMessage.createdAt && previousMode === nextMode && previousConfirmationSubmit === nextConfirmationSubmit && previousQuestionnaireSubmit === nextQuestionnaireSubmit && previousRenderMessageBlock === nextRenderMessageBlock;
2870
2877
  var ChatMessageItemView = ({
2871
2878
  message,
2872
2879
  mode = "agent",
@@ -2886,6 +2893,7 @@ var ChatMessageItemView = ({
2886
2893
  } = useChatMessageReveal(message);
2887
2894
  const isStoppedAssistant = message.role === "assistant" && message.status === "stopped";
2888
2895
  const attachments = message.attachments ?? [];
2896
+ const skills = message.skills ?? [];
2889
2897
  const blocks = message.blocks ?? [];
2890
2898
  const hasStructuredBlocks = blocks.length > 0;
2891
2899
  const hasMarkdownOnlyBlocks = hasStructuredBlocks && blocks.every((block) => block.type === "markdown");
@@ -2927,6 +2935,7 @@ var ChatMessageItemView = ({
2927
2935
  freshContent,
2928
2936
  settledContent
2929
2937
  });
2938
+ const shouldRenderHeader = isAssistantStreaming || isUserMessageCollapsible || isStoppedAssistant;
2930
2939
  const renderMessageContent = (content) => messageRenderMode === "plain-text" ? renderPlainTextContent(content) : renderMarkdownContent(content);
2931
2940
  const renderChatMessageBlock = (block, index3) => {
2932
2941
  switch (block.type) {
@@ -3076,7 +3085,7 @@ var ChatMessageItemView = ({
3076
3085
  })();
3077
3086
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
3078
3087
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Bubble, { "data-role": message.role, "data-status": message.status ?? "done", children: [
3079
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Header2, { children: [
3088
+ shouldRenderHeader ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Header2, { children: [
3080
3089
  isAssistantStreaming ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3081
3090
  StreamingIndicator,
3082
3091
  {
@@ -3088,7 +3097,6 @@ var ChatMessageItemView = ({
3088
3097
  ]
3089
3098
  }
3090
3099
  ) : null,
3091
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Role, { children: message.role === "user" ? labels.userRoleLabel : labels.assistantRoleLabel }),
3092
3100
  isUserMessageCollapsible ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3093
3101
  CollapseToggle,
3094
3102
  {
@@ -3101,8 +3109,9 @@ var ChatMessageItemView = ({
3101
3109
  }
3102
3110
  ) : null,
3103
3111
  isStoppedAssistant ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StatusTag, { "data-testid": "chat-message-stopped-tag", children: labels.stoppedResponse }) : null
3104
- ] }),
3112
+ ] }) : null,
3105
3113
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Content, { "data-testid": "chat-message-content", children: [
3114
+ 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,
3106
3115
  shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3107
3116
  ContentStack,
3108
3117
  {
@@ -3167,19 +3176,22 @@ var ChatMessageItem = (0, import_react9.memo)(
3167
3176
  var Bubble = import_styled7.default.article`
3168
3177
  width: 100%;
3169
3178
  max-width: 100%;
3170
- padding: 14px 16px;
3171
- border-radius: 22px;
3172
- background: rgba(255, 255, 255, 0.04);
3173
- border: 1px solid rgba(255, 255, 255, 0.07);
3174
- box-shadow:
3175
- inset 0 1px 0 rgba(255, 255, 255, 0.03),
3176
- 0 12px 30px rgba(0, 0, 0, 0.18);
3179
+ padding: 0;
3180
+ background: transparent;
3181
+ border: none;
3182
+ box-shadow: none;
3177
3183
 
3178
3184
  &[data-role='user'] {
3179
3185
  width: auto;
3180
3186
  max-width: min(760px, 100%);
3181
3187
  margin-left: auto;
3188
+ padding: 14px 16px;
3189
+ border-radius: 22px;
3182
3190
  background: linear-gradient(180deg, rgba(59, 59, 63, 0.9) 0%, rgba(42, 43, 46, 0.92) 100%);
3191
+ border: 1px solid rgba(255, 255, 255, 0.07);
3192
+ box-shadow:
3193
+ inset 0 1px 0 rgba(255, 255, 255, 0.03),
3194
+ 0 12px 30px rgba(0, 0, 0, 0.18);
3183
3195
  }
3184
3196
  `;
3185
3197
  var Header2 = import_styled7.default.div`
@@ -3188,12 +3200,6 @@ var Header2 = import_styled7.default.div`
3188
3200
  gap: 10px;
3189
3201
  margin-bottom: 10px;
3190
3202
  `;
3191
- var Role = import_styled7.default.div`
3192
- font-size: 12px;
3193
- color: rgba(255, 255, 255, 0.42);
3194
- text-transform: capitalize;
3195
- letter-spacing: 0.08em;
3196
- `;
3197
3203
  var StatusTag = import_styled7.default.span`
3198
3204
  display: inline-flex;
3199
3205
  align-items: center;
@@ -3300,6 +3306,23 @@ var Content = import_styled7.default.div`
3300
3306
  margin: 0 0 8px;
3301
3307
  }
3302
3308
  `;
3309
+ var SkillTagList = import_styled7.default.div`
3310
+ display: flex;
3311
+ flex-wrap: wrap;
3312
+ gap: 8px;
3313
+ margin-bottom: 12px;
3314
+ `;
3315
+ var SkillTag = import_styled7.default.span`
3316
+ display: inline-flex;
3317
+ align-items: center;
3318
+ max-width: 100%;
3319
+ padding: 10px 18px;
3320
+ border-radius: 999px;
3321
+ background: rgba(65, 65, 63, 0.6);
3322
+ color: #c5c1ba;
3323
+ font-size: 14px;
3324
+ line-height: 1;
3325
+ `;
3303
3326
  var ContentStack = import_styled7.default.div`
3304
3327
  display: flex;
3305
3328
  flex-direction: column;
@@ -6558,6 +6581,7 @@ function useFloating2(options) {
6558
6581
  var createUserMessage = ({
6559
6582
  sessionId,
6560
6583
  content,
6584
+ skills,
6561
6585
  attachments,
6562
6586
  localOnly,
6563
6587
  createdAt,
@@ -6567,6 +6591,7 @@ var createUserMessage = ({
6567
6591
  sessionId,
6568
6592
  role: "user",
6569
6593
  content,
6594
+ skills,
6570
6595
  attachments,
6571
6596
  localOnly,
6572
6597
  createdAt
@@ -6586,16 +6611,20 @@ var createAssistantStreamingMessage = ({
6586
6611
  var canSendChatMessage = ({
6587
6612
  value,
6588
6613
  attachmentCount = 0,
6614
+ skillCount = 0,
6589
6615
  isModelsLoading,
6590
6616
  isModelsError,
6591
6617
  hasModels
6592
6618
  }) => {
6593
6619
  const hasText = Boolean(value.trim());
6594
6620
  const hasAttachments = attachmentCount > 0;
6595
- if (!hasText && !hasAttachments)
6621
+ const hasSkills = skillCount > 0;
6622
+ if (!hasText && !hasAttachments && !hasSkills)
6596
6623
  return false;
6597
6624
  if (!hasText && hasAttachments)
6598
6625
  return true;
6626
+ if (!hasText && !hasAttachments && hasSkills)
6627
+ return !isModelsLoading && !isModelsError && hasModels;
6599
6628
  return !isModelsLoading && !isModelsError && hasModels;
6600
6629
  };
6601
6630
  var shouldSubmitChatComposer = ({
@@ -6891,6 +6920,7 @@ var useChatComposer = () => {
6891
6920
  const abortControllerBySessionRef = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
6892
6921
  const stopRequestBySessionRef = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
6893
6922
  const lastRequestBySessionRef = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
6923
+ const previousActiveSessionIdRef = (0, import_react15.useRef)(activeSessionId);
6894
6924
  (0, import_react15.useEffect)(() => {
6895
6925
  setSelectedModel(
6896
6926
  (current) => resolveSelectedChatModel({ currentModel: current, availableModels, isModelsLoading })
@@ -6903,6 +6933,12 @@ var useChatComposer = () => {
6903
6933
  }
6904
6934
  setSelectedModeLocal(preferredMode ?? DEFAULT_CHAT_AGENT_MODE);
6905
6935
  }, [activeSession, preferredMode]);
6936
+ (0, import_react15.useEffect)(() => {
6937
+ if (previousActiveSessionIdRef.current !== activeSessionId) {
6938
+ setSelectedSkills([]);
6939
+ previousActiveSessionIdRef.current = activeSessionId;
6940
+ }
6941
+ }, [activeSessionId]);
6906
6942
  (0, import_react15.useEffect)(() => {
6907
6943
  if (!attachmentNotice)
6908
6944
  return;
@@ -7094,6 +7130,7 @@ var useChatComposer = () => {
7094
7130
  if (!canSendChatMessage({
7095
7131
  value: content,
7096
7132
  attachmentCount: composerAttachmentCount,
7133
+ skillCount: messageSkills?.length ?? 0,
7097
7134
  isModelsLoading,
7098
7135
  isModelsError,
7099
7136
  hasModels
@@ -7121,6 +7158,7 @@ var useChatComposer = () => {
7121
7158
  const userMessage = createUserMessage({
7122
7159
  sessionId: localSessionId,
7123
7160
  content,
7161
+ skills: messageSkills,
7124
7162
  attachments: messageAttachments,
7125
7163
  localOnly: false,
7126
7164
  createdAt: nowIso(),
@@ -7163,6 +7201,19 @@ var useChatComposer = () => {
7163
7201
  store
7164
7202
  ]
7165
7203
  );
7204
+ const openSkillPicker = (0, import_react15.useCallback)(() => {
7205
+ setValue((current) => {
7206
+ const matchedSkillQuery = current.match(/(^|\s)\/([^\s/]*)$/);
7207
+ if (matchedSkillQuery && matchedSkillQuery.index !== void 0) {
7208
+ const queryStart = matchedSkillQuery.index + matchedSkillQuery[1].length;
7209
+ return current.slice(0, queryStart).replace(/\s+$/, "");
7210
+ }
7211
+ if (!current.trim()) {
7212
+ return "/";
7213
+ }
7214
+ return /\s$/.test(current) ? `${current}/` : `${current} /`;
7215
+ });
7216
+ }, []);
7166
7217
  const stopSession = (0, import_react15.useCallback)(
7167
7218
  async (sessionId) => {
7168
7219
  const storeState = store.getState();
@@ -7237,6 +7288,7 @@ var useChatComposer = () => {
7237
7288
  removeSkill: (skill) => {
7238
7289
  setSelectedSkills((current) => current.filter((item) => item !== skill));
7239
7290
  },
7291
+ openSkillPicker,
7240
7292
  setSelectedModel,
7241
7293
  setSelectedMode: (mode) => {
7242
7294
  setSelectedModeLocal(mode);
@@ -7431,12 +7483,42 @@ var CloseGlyph = import_styled10.default.span`
7431
7483
  var import_styled11 = __toESM(require("@emotion/styled"));
7432
7484
  var import_compass_ui = require("@xinghunm/compass-ui");
7433
7485
  var import_jsx_runtime13 = require("@emotion/react/jsx-runtime");
7486
+ var ModelIcon = () => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7487
+ "svg",
7488
+ {
7489
+ "aria-hidden": "true",
7490
+ width: "14",
7491
+ height: "14",
7492
+ viewBox: "0 0 14 14",
7493
+ fill: "none",
7494
+ style: { display: "block" },
7495
+ xmlns: "http://www.w3.org/2000/svg",
7496
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
7497
+ "g",
7498
+ {
7499
+ transform: "translate(1.6545 1.0182)",
7500
+ stroke: "currentColor",
7501
+ strokeLinecap: "round",
7502
+ strokeLinejoin: "round",
7503
+ strokeWidth: "1.22181818",
7504
+ children: [
7505
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M4.80808081 11.8021107C5.17998715 12.0158424 5.63819467 12.0158424 6.01010101 11.8021107L10.2171717 9.40913806C10.588697 9.19562567 10.8177418 8.8012024 10.8181818 8.37417739V3.58823209C10.8177418 3.16120709 10.588697 2.76678381 10.2171717 2.55327142L6.01010101 0.160298772C5.63819467 -0.0534329241 5.17998715 -0.0534329241 4.80808081 0.160298772L0.601010101 2.55327142C0.229484841 2.76678381 0.000440028788 3.16120709 0 3.58823209V8.37417739C0.000440028788 8.8012024 0.229484841 9.19562567 0.601010101 9.40913806L4.80808081 11.8021107Z" }),
7506
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M5.40909091 11.9636364V5.98120474" }),
7507
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M0.174292929 2.98998893L5.40909091 5.98120474L10.6438889 2.98998893" })
7508
+ ]
7509
+ }
7510
+ )
7511
+ }
7512
+ );
7434
7513
  var ChatModelControl = ({
7435
7514
  selectedModel,
7436
7515
  availableModels,
7437
7516
  isModelsLoading,
7438
7517
  isModelsError,
7439
7518
  hasModels,
7519
+ loadingLabel,
7520
+ loadFailedLabel,
7521
+ unavailableLabel,
7440
7522
  onSelectedModelChange,
7441
7523
  onReloadModels
7442
7524
  }) => {
@@ -7449,7 +7531,7 @@ var ChatModelControl = ({
7449
7531
  "aria-label": "Reload",
7450
7532
  onClick: onReloadModels,
7451
7533
  children: [
7452
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Failed to load models" }),
7534
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: loadFailedLabel }),
7453
7535
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
7454
7536
  ReloadIcon,
7455
7537
  {
@@ -7471,29 +7553,32 @@ var ChatModelControl = ({
7471
7553
  );
7472
7554
  }
7473
7555
  if (isModelsLoading) {
7474
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ModelBadge, { children: "Loading models..." });
7556
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ModelBadge, { "data-testid": "chat-model-loading", children: loadingLabel });
7475
7557
  }
7476
7558
  if (hasModels && selectedModel) {
7477
- if (availableModels.length > 1) {
7478
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7479
- ModelSelect,
7480
- {
7481
- "data-testid": "chat-model-select",
7482
- "aria-label": "Select model",
7483
- value: selectedModel,
7484
- onChange: (value) => onSelectedModelChange(String(value)),
7485
- options: availableModels.map((model) => ({
7486
- label: model.id,
7487
- value: model.id
7488
- }))
7489
- }
7490
- );
7491
- }
7492
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ModelBadge, { children: selectedModel });
7559
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7560
+ ModelSelect,
7561
+ {
7562
+ "data-testid": "chat-model-select",
7563
+ "aria-label": "Select model",
7564
+ value: selectedModel,
7565
+ onChange: (value) => onSelectedModelChange(String(value)),
7566
+ options: availableModels.map((model) => ({
7567
+ label: model.id,
7568
+ value: model.id
7569
+ })),
7570
+ labelRender: () => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ModelIcon, {})
7571
+ }
7572
+ );
7493
7573
  }
7494
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ModelBadge, { children: "No model available" });
7574
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ModelBadge, { "data-testid": "chat-model-unavailable", children: unavailableLabel });
7495
7575
  };
7496
7576
  var ModelBadge = import_styled11.default.span`
7577
+ display: inline-flex;
7578
+ align-items: center;
7579
+ min-width: 0;
7580
+ max-width: 100%;
7581
+ overflow: hidden;
7497
7582
  border-radius: 999px;
7498
7583
  border: 1px solid var(--border-hover);
7499
7584
  padding: 5px 12px;
@@ -7501,6 +7586,9 @@ var ModelBadge = import_styled11.default.span`
7501
7586
  font-size: 12px;
7502
7587
  color: var(--text-secondary);
7503
7588
  line-height: 12px;
7589
+ white-space: nowrap;
7590
+ text-overflow: ellipsis;
7591
+ flex-shrink: 1;
7504
7592
  `;
7505
7593
  var ModelReloadButton = import_styled11.default.button`
7506
7594
  display: inline-flex;
@@ -7532,20 +7620,55 @@ var ReloadIcon = import_styled11.default.svg`
7532
7620
  `;
7533
7621
  var ModelSelect = (0, import_styled11.default)(import_compass_ui.Select)`
7534
7622
  && {
7535
- width: auto;
7623
+ width: 24px;
7624
+ min-width: 24px;
7625
+ max-width: 24px;
7626
+ flex: 0 0 24px;
7627
+ }
7628
+
7629
+ && .compass-select-selector {
7630
+ justify-content: center;
7631
+ border-radius: 999px;
7632
+ min-height: 24px;
7633
+ height: 24px;
7634
+ width: 24px;
7635
+ padding: 0;
7636
+ background: rgba(255, 255, 255, 0.06);
7637
+ border-color: rgba(255, 255, 255, 0.14);
7638
+ color: #c5c1ba;
7639
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
7640
+ margin-right: 0;
7641
+ }
7642
+
7643
+ && .compass-select-selector:hover {
7644
+ background: rgba(255, 255, 255, 0.1);
7645
+ border-color: rgba(255, 255, 255, 0.2);
7646
+ }
7647
+
7648
+ && .compass-select-selection-item {
7649
+ display: flex;
7650
+ width: 100%;
7651
+ margin-right: 0;
7536
7652
  min-width: 0;
7537
- max-width: 100%;
7653
+ min-height: 24px;
7654
+ align-items: center;
7655
+ justify-content: center;
7656
+ }
7538
7657
 
7539
- .compass-select-selector {
7540
- line-height: 1;
7541
- border-radius: 999px;
7542
- min-height: 24px;
7543
- height: 24px;
7544
- background: rgba(255, 255, 255, 0.04);
7545
- border-color: rgba(255, 255, 255, 0.12);
7546
- color: rgba(255, 255, 255, 0.82);
7547
- padding: 4px 12px;
7548
- }
7658
+ && .compass-select-selector > div:first-of-type {
7659
+ display: flex;
7660
+ width: 100%;
7661
+ align-items: center;
7662
+ justify-content: center;
7663
+ margin-right: 0;
7664
+ }
7665
+
7666
+ && .compass-select-selection-item svg {
7667
+ display: block;
7668
+ }
7669
+
7670
+ && .compass-select-selector > span:last-child {
7671
+ display: none;
7549
7672
  }
7550
7673
  `;
7551
7674
 
@@ -7576,21 +7699,27 @@ var ChatModeControl = ({
7576
7699
  };
7577
7700
  var ModeSelect = (0, import_styled12.default)(import_compass_ui2.Select)`
7578
7701
  && {
7579
- flex: 0 1 auto;
7580
- width: auto;
7581
- min-width: 0;
7582
- max-width: 100%;
7702
+ flex: 0 0 auto;
7703
+ width: fit-content;
7704
+ min-width: fit-content;
7705
+ max-width: none;
7706
+ }
7583
7707
 
7584
- .compass-select-selector {
7585
- line-height: 1;
7586
- border-radius: 999px;
7587
- min-height: 24px;
7588
- height: 24px;
7589
- background: rgba(255, 255, 255, 0.04);
7590
- border-color: rgba(255, 255, 255, 0.12);
7591
- color: rgba(255, 255, 255, 0.82);
7592
- padding: 4px 12px;
7593
- }
7708
+ && .compass-select-selector {
7709
+ width: fit-content;
7710
+ line-height: 1;
7711
+ border-radius: 999px;
7712
+ min-height: 24px;
7713
+ height: 24px;
7714
+ background: rgba(255, 255, 255, 0.04);
7715
+ border-color: rgba(255, 255, 255, 0.12);
7716
+ color: rgba(255, 255, 255, 0.82);
7717
+ padding: 4px 12px;
7718
+ }
7719
+
7720
+ && .compass-select-selector > div:first-of-type {
7721
+ width: auto;
7722
+ min-width: max-content;
7594
7723
  }
7595
7724
  `;
7596
7725
 
@@ -7765,6 +7894,31 @@ var PlusIcon = () => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7765
7894
  children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M8 3v10M3 8h10", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" })
7766
7895
  }
7767
7896
  );
7897
+ var SkillIcon = () => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7898
+ "svg",
7899
+ {
7900
+ "aria-hidden": "true",
7901
+ width: "14",
7902
+ height: "14",
7903
+ viewBox: "0 0 14 14",
7904
+ fill: "none",
7905
+ xmlns: "http://www.w3.org/2000/svg",
7906
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7907
+ "g",
7908
+ {
7909
+ transform: "translate(1.7818 2.2909)",
7910
+ stroke: "currentColor",
7911
+ strokeLinecap: "round",
7912
+ strokeLinejoin: "round",
7913
+ strokeWidth: "1.22181818",
7914
+ children: [
7915
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M5.28181818 2.12121212V9.54545455" }),
7916
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M0.528181818 7.95454545C0.236475055 7.95454545 0 7.7171207 0 7.42424242V0.53030303C0 0.237424754 0.236475055 0 0.528181818 0H3.16909091C4.33591796 0 5.28181818 0.949699016 5.28181818 2.12121212C5.28181818 0.949699016 6.2277184 0 7.39454545 0H10.0354545C10.3271613 0 10.5636364 0.237424754 10.5636364 0.53030303V7.42424242C10.5636364 7.7171207 10.3271613 7.95454545 10.0354545 7.95454545H6.86636364C5.99124335 7.95454545 5.28181818 8.66681972 5.28181818 9.54545455C5.28181818 8.66681972 4.57239302 7.95454545 3.69727273 7.95454545H0.528181818Z" })
7917
+ ]
7918
+ }
7919
+ )
7920
+ }
7921
+ );
7768
7922
  var ComposerExpandIcon = ({ expanded }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7769
7923
  "svg",
7770
7924
  {
@@ -7839,6 +7993,9 @@ var ChatComposerView = ({
7839
7993
  skillLoadingLabel,
7840
7994
  skillEmptyLabel,
7841
7995
  removeSkillAriaLabel,
7996
+ modelLoadingLabel,
7997
+ modelLoadFailedLabel,
7998
+ modelUnavailableLabel,
7842
7999
  onValueChange,
7843
8000
  onPickImages,
7844
8001
  onPasteImages,
@@ -7848,6 +8005,7 @@ var ChatComposerView = ({
7848
8005
  onSelectedModelChange,
7849
8006
  onSelectedModeChange,
7850
8007
  onReloadModels,
8008
+ onOpenSkillPicker,
7851
8009
  onStop,
7852
8010
  onSend
7853
8011
  }) => {
@@ -7862,6 +8020,7 @@ var ChatComposerView = ({
7862
8020
  const canSend = canSendChatMessage({
7863
8021
  value,
7864
8022
  attachmentCount: attachments.length,
8023
+ skillCount: selectedSkills.length,
7865
8024
  isModelsLoading,
7866
8025
  isModelsError,
7867
8026
  hasModels
@@ -7878,11 +8037,12 @@ var ChatComposerView = ({
7878
8037
  }) : [];
7879
8038
  const showSkillMenu = Boolean(skillQueryMatch);
7880
8039
  const activeSkillQueryKey = skillQueryMatch ? `${skillQueryMatch.start}:${skillQueryMatch.end}:${skillQueryMatch.query}:${selectedSkills.join("\0")}` : "";
7881
- const { refs, floatingStyles } = useFloating2({
8040
+ const { refs, floatingStyles, placement } = useFloating2({
7882
8041
  open: showSkillMenu,
7883
8042
  placement: "bottom-start",
8043
+ strategy: "fixed",
7884
8044
  middleware: [
7885
- offset3(8),
8045
+ offset3(3),
7886
8046
  flip3({ padding: 8 }),
7887
8047
  shift3({ padding: 8 }),
7888
8048
  size3({
@@ -7988,8 +8148,14 @@ var ChatComposerView = ({
7988
8148
  event.preventDefault();
7989
8149
  onPasteImages(imageFiles);
7990
8150
  };
8151
+ const handleOpenSkillPicker = () => {
8152
+ onOpenSkillPicker();
8153
+ requestAnimationFrame(() => {
8154
+ inputRef.current?.focus();
8155
+ });
8156
+ };
7991
8157
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Container2, { children: [
7992
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Surface, { "data-testid": "chat-composer-surface", children: [
8158
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Surface, { ref: setSkillMenuReference, "data-testid": "chat-composer-surface", children: [
7993
8159
  enableImageAttachments ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7994
8160
  "input",
7995
8161
  {
@@ -8010,7 +8176,7 @@ var ChatComposerView = ({
8010
8176
  }
8011
8177
  ),
8012
8178
  attachmentNotice === "limit_reached" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AttachmentNotice, { "data-testid": "chat-composer-attachment-notice", children: attachmentLimitNotice }) : null,
8013
- selectedSkills.length ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SkillTagList, { "data-testid": "chat-composer-skill-tags", children: selectedSkills.map((skill) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(SkillTag, { children: [
8179
+ selectedSkills.length ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SkillTagList2, { "data-testid": "chat-composer-skill-tags", children: selectedSkills.map((skill) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(SkillTag2, { children: [
8014
8180
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: skill }),
8015
8181
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8016
8182
  SkillTagRemoveButton,
@@ -8023,7 +8189,7 @@ var ChatComposerView = ({
8023
8189
  }
8024
8190
  )
8025
8191
  ] }, skill)) }) : null,
8026
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(InputArea, { ref: setSkillMenuReference, "data-testid": "chat-composer-input-area", children: [
8192
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(InputArea, { "data-testid": "chat-composer-input-area", children: [
8027
8193
  isComposerExpanded || isComposerExpandable ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8028
8194
  ComposerExpandButton,
8029
8195
  {
@@ -8050,17 +8216,27 @@ var ChatComposerView = ({
8050
8216
  )
8051
8217
  ] }),
8052
8218
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Footer, { children: [
8053
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(LeadingActions, { "data-testid": "chat-composer-leading-actions", children: enableImageAttachments ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8054
- AttachButton,
8055
- {
8056
- type: "button",
8057
- "data-testid": "chat-composer-attach-image",
8058
- "aria-label": "Attach image",
8059
- onClick: () => imageInputRef.current?.click(),
8060
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PlusIcon, {})
8061
- }
8062
- ) : null }),
8063
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(TrailingActions, { "data-testid": "chat-composer-trailing-actions", children: [
8219
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(LeadingActions, { "data-testid": "chat-composer-leading-actions", children: [
8220
+ enableImageAttachments ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8221
+ AttachButton,
8222
+ {
8223
+ type: "button",
8224
+ "data-testid": "chat-composer-attach-image",
8225
+ "aria-label": "Attach image",
8226
+ onClick: () => imageInputRef.current?.click(),
8227
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PlusIcon, {})
8228
+ }
8229
+ ) : null,
8230
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8231
+ SkillButton,
8232
+ {
8233
+ type: "button",
8234
+ "data-testid": "chat-composer-skill-trigger",
8235
+ "aria-label": "Open skill picker",
8236
+ onClick: handleOpenSkillPicker,
8237
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SkillIcon, {})
8238
+ }
8239
+ ),
8064
8240
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8065
8241
  ChatModeControl,
8066
8242
  {
@@ -8069,7 +8245,9 @@ var ChatComposerView = ({
8069
8245
  labels: modeLabels,
8070
8246
  onChange: onSelectedModeChange
8071
8247
  }
8072
- ),
8248
+ )
8249
+ ] }),
8250
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(TrailingActions, { "data-testid": "chat-composer-trailing-actions", children: [
8073
8251
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8074
8252
  ChatModelControl,
8075
8253
  {
@@ -8078,6 +8256,9 @@ var ChatComposerView = ({
8078
8256
  isModelsLoading,
8079
8257
  isModelsError,
8080
8258
  hasModels,
8259
+ loadingLabel: modelLoadingLabel,
8260
+ loadFailedLabel: modelLoadFailedLabel,
8261
+ unavailableLabel: modelUnavailableLabel,
8081
8262
  onSelectedModelChange,
8082
8263
  onReloadModels
8083
8264
  }
@@ -8101,6 +8282,8 @@ var ChatComposerView = ({
8101
8282
  ref: setSkillMenuFloating,
8102
8283
  style: floatingStyles,
8103
8284
  "data-testid": "chat-composer-skill-menu",
8285
+ "data-placement": placement,
8286
+ "data-floating-strategy": "fixed",
8104
8287
  role: "listbox",
8105
8288
  children: isSkillsLoading ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SkillMenuState, { "data-testid": "chat-composer-skill-loading", children: skillLoadingLabel }) : filteredSkills.length ? filteredSkills.map((skill, index3) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8106
8289
  SkillMenuItem,
@@ -8162,6 +8345,9 @@ var ChatComposer = () => {
8162
8345
  skillLoadingLabel: labels.skillLoading,
8163
8346
  skillEmptyLabel: labels.skillEmpty,
8164
8347
  removeSkillAriaLabel: labels.removeSkillAriaLabel,
8348
+ modelLoadingLabel: labels.modelLoading,
8349
+ modelLoadFailedLabel: labels.modelLoadFailed,
8350
+ modelUnavailableLabel: labels.modelUnavailable,
8165
8351
  onValueChange: actions.setValue,
8166
8352
  onPickImages: actions.pickImages,
8167
8353
  onPasteImages: actions.pasteImages,
@@ -8171,6 +8357,7 @@ var ChatComposer = () => {
8171
8357
  onSelectedModelChange: actions.setSelectedModel,
8172
8358
  onSelectedModeChange: actions.setSelectedMode,
8173
8359
  onReloadModels: actions.reloadModels,
8360
+ onOpenSkillPicker: actions.openSkillPicker,
8174
8361
  onStop: actions.stop,
8175
8362
  onSend: send
8176
8363
  }
@@ -8209,31 +8396,55 @@ var AttachmentNotice = import_styled14.default.div`
8209
8396
  font-size: 12px;
8210
8397
  line-height: 1.4;
8211
8398
  `;
8212
- var SkillTagList = import_styled14.default.div`
8399
+ var SkillTagList2 = import_styled14.default.div`
8213
8400
  display: flex;
8214
8401
  flex-wrap: wrap;
8215
- gap: 8px;
8216
- padding: 12px 12px 0;
8402
+ gap: 9px;
8403
+ padding: 11px 16px;
8217
8404
  `;
8218
- var SkillTag = import_styled14.default.span`
8405
+ var SkillTag2 = import_styled14.default.span`
8406
+ position: relative;
8219
8407
  display: inline-flex;
8220
8408
  align-items: center;
8221
- gap: 6px;
8222
8409
  max-width: 100%;
8223
- border-radius: 999px;
8224
- padding: 8px 12px;
8225
- background: rgba(255, 255, 255, 0.06);
8226
- color: var(--text-primary);
8227
- font-size: 13px;
8410
+ padding: 11px 16px;
8411
+ background: rgba(65, 65, 63, 0.35);
8412
+ border-radius: 18px;
8413
+ font-weight: 400;
8414
+ font-size: 14px;
8415
+ color: #c5c1ba;
8228
8416
  line-height: 1;
8417
+
8418
+ :hover {
8419
+ background: #41413f;
8420
+ }
8421
+
8422
+ &:hover > button,
8423
+ &:focus-within > button {
8424
+ opacity: 1;
8425
+ pointer-events: auto;
8426
+ }
8229
8427
  `;
8230
8428
  var SkillTagRemoveButton = import_styled14.default.button`
8429
+ position: absolute;
8430
+ top: 0;
8431
+ right: 0;
8432
+ width: 14px;
8433
+ height: 14px;
8434
+ border-radius: 50%;
8435
+ background: #000000;
8436
+ display: grid;
8437
+ place-items: center;
8231
8438
  border: none;
8232
8439
  padding: 0;
8233
- background: transparent;
8234
8440
  color: inherit;
8235
8441
  cursor: pointer;
8236
8442
  line-height: 1;
8443
+ opacity: 0;
8444
+ pointer-events: none;
8445
+ transition:
8446
+ opacity 120ms ease,
8447
+ background-color 120ms ease;
8237
8448
  `;
8238
8449
  var InputArea = import_styled14.default.div`
8239
8450
  grid-area: input;
@@ -8294,18 +8505,21 @@ var SkillMenu = import_styled14.default.div`
8294
8505
  gap: 4px;
8295
8506
  max-height: 240px;
8296
8507
  overflow-y: auto;
8297
- padding: 8px;
8298
- border: 1px solid rgba(255, 255, 255, 0.12);
8299
- border-radius: 16px;
8508
+ padding: 4px;
8509
+ border-radius: 12px;
8300
8510
  background: rgba(28, 28, 28, 0.98);
8301
8511
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.28);
8302
8512
  z-index: 1000;
8513
+ background: #1c1c1c;
8514
+ box-shadow: 0px 4px 6px 0px rgba(14, 14, 14, 0.3);
8515
+ border-radius: 12px;
8516
+ border: 1px solid #282825;
8303
8517
  `;
8304
8518
  var SkillMenuItem = import_styled14.default.button`
8305
8519
  width: 100%;
8306
8520
  border: none;
8307
- border-radius: 12px;
8308
- padding: 12px 14px;
8521
+ border-radius: 8px;
8522
+ padding: 12px;
8309
8523
  background: transparent;
8310
8524
  color: var(--text-primary);
8311
8525
  text-align: left;
@@ -8313,7 +8527,7 @@ var SkillMenuItem = import_styled14.default.button`
8313
8527
 
8314
8528
  &[data-active='true'],
8315
8529
  &:hover {
8316
- background: rgba(255, 255, 255, 0.12);
8530
+ background: #41413f;
8317
8531
  }
8318
8532
  `;
8319
8533
  var SkillMenuState = import_styled14.default.div`
@@ -8343,9 +8557,8 @@ var ComposerExpandButton = import_styled14.default.button`
8343
8557
  `;
8344
8558
  var Footer = import_styled14.default.div`
8345
8559
  grid-area: footer;
8346
- display: grid;
8347
- grid-template-columns: auto minmax(0, 1fr);
8348
- align-items: flex-end;
8560
+ display: flex;
8561
+ align-items: center;
8349
8562
  gap: 8px;
8350
8563
  padding: 0 14px 14px;
8351
8564
  `;
@@ -8353,33 +8566,72 @@ var LeadingActions = import_styled14.default.div`
8353
8566
  display: flex;
8354
8567
  align-items: center;
8355
8568
  justify-content: flex-start;
8356
- gap: 8px;
8569
+ gap: 4px;
8357
8570
  min-width: 0;
8358
8571
  `;
8359
8572
  var TrailingActions = import_styled14.default.div`
8360
8573
  display: flex;
8361
8574
  align-items: center;
8362
- flex-wrap: wrap;
8575
+ flex-wrap: nowrap;
8363
8576
  min-width: 0;
8364
- width: fit-content;
8365
- max-width: 100%;
8366
- justify-self: end;
8577
+ margin-left: auto;
8367
8578
  justify-content: flex-end;
8368
8579
  gap: 8px;
8369
8580
  `;
8370
8581
  var AttachButton = import_styled14.default.button`
8371
- width: 28px;
8372
- height: 28px;
8582
+ width: 24px;
8583
+ height: 24px;
8373
8584
  display: grid;
8374
8585
  place-items: center;
8375
- border: none;
8376
8586
  border-radius: 999px;
8377
- background: transparent;
8378
- color: rgba(255, 255, 255, 0.82);
8587
+ border: 1px solid rgba(255, 255, 255, 0.14);
8588
+ background: rgba(255, 255, 255, 0.06);
8589
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
8590
+ padding: 0;
8591
+ color: #c5c1ba;
8379
8592
  cursor: pointer;
8593
+ flex: 0 0 24px;
8594
+
8595
+ transition:
8596
+ background 160ms ease,
8597
+ border-color 160ms ease,
8598
+ color 160ms ease;
8380
8599
 
8381
8600
  &:hover {
8382
- background: rgba(255, 255, 255, 0.08);
8601
+ background: rgba(255, 255, 255, 0.1);
8602
+ border-color: rgba(255, 255, 255, 0.2);
8603
+ }
8604
+
8605
+ svg {
8606
+ display: block;
8607
+ }
8608
+ `;
8609
+ var SkillButton = import_styled14.default.button`
8610
+ width: 24px;
8611
+ height: 24px;
8612
+ display: grid;
8613
+ place-items: center;
8614
+ border-radius: 999px;
8615
+ border: 1px solid rgba(255, 255, 255, 0.14);
8616
+ background: rgba(255, 255, 255, 0.06);
8617
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
8618
+ padding: 0;
8619
+ color: #c5c1ba;
8620
+ cursor: pointer;
8621
+ flex: 0 0 24px;
8622
+
8623
+ transition:
8624
+ background 160ms ease,
8625
+ border-color 160ms ease,
8626
+ color 160ms ease;
8627
+
8628
+ &:hover {
8629
+ background: rgba(255, 255, 255, 0.1);
8630
+ border-color: rgba(255, 255, 255, 0.2);
8631
+ }
8632
+
8633
+ svg {
8634
+ display: block;
8383
8635
  }
8384
8636
  `;
8385
8637
 
@@ -8512,6 +8764,76 @@ var List2 = import_styled16.default.div`
8512
8764
 
8513
8765
  // src/components/ai-chat/index.tsx
8514
8766
  var import_jsx_runtime19 = require("@emotion/react/jsx-runtime");
8767
+ var NewTalkIcon = () => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
8768
+ "svg",
8769
+ {
8770
+ "aria-hidden": "true",
8771
+ width: "16",
8772
+ height: "16",
8773
+ viewBox: "0 0 16 16",
8774
+ fill: "none",
8775
+ style: { display: "block" },
8776
+ xmlns: "http://www.w3.org/2000/svg",
8777
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
8778
+ "g",
8779
+ {
8780
+ transform: "translate(1.8909 2.0364)",
8781
+ stroke: "currentColor",
8782
+ strokeLinecap: "round",
8783
+ strokeLinejoin: "round",
8784
+ strokeWidth: "1.36533333",
8785
+ children: [
8786
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("g", { transform: "translate(9.8909 2.3273) rotate(-315) translate(-9.8909 -2.3273) translate(8.2909 0.7273)", children: [
8787
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M0 0C0 0 1.06666667 1.06666667 3.2 3.2" }),
8788
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M3.2 0C3.2 0 2.13333333 1.06666667 0 3.2" })
8789
+ ] }),
8790
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M12.2181818 6.15099432V7.31151515C12.2181818 8.25408112 11.4540811 9.01818182 10.5115152 9.01818182H4.19089868C4.07080994 9.01818182 3.95380126 9.05618401 3.85662972 9.12674601L0.903157852 11.2714364C0.648927541 11.4560481 0.293175841 11.399611 0.10856419 11.1453807C0.0380021898 11.0482092 0 10.9312005 0 10.8111117V1.70666667C0 0.764100694 0.764100694 0 1.70666667 0H6.07111268" })
8791
+ ]
8792
+ }
8793
+ )
8794
+ }
8795
+ );
8796
+ var hasStartedConversation = ({
8797
+ activeSessionId,
8798
+ messagesBySession,
8799
+ streamingMessageBySession,
8800
+ errorBySession
8801
+ }) => {
8802
+ if (!activeSessionId) {
8803
+ return false;
8804
+ }
8805
+ return Boolean(
8806
+ (messagesBySession[activeSessionId]?.length ?? 0) > 0 || streamingMessageBySession[activeSessionId] || errorBySession[activeSessionId]
8807
+ );
8808
+ };
8809
+ var AiChatWorkspaceContent = ({
8810
+ showConversationList,
8811
+ showNewChatButton,
8812
+ renderNewChatTrigger,
8813
+ showComposerOnlyBeforeFirstMessage = false,
8814
+ onConversationStartedChange
8815
+ }) => {
8816
+ const isConversationStarted = useChatStore(
8817
+ (state) => hasStartedConversation({
8818
+ activeSessionId: state.activeSessionId,
8819
+ messagesBySession: state.messagesBySession,
8820
+ streamingMessageBySession: state.streamingMessageBySession,
8821
+ errorBySession: state.errorBySession
8822
+ })
8823
+ );
8824
+ const shouldShowComposerOnly = showComposerOnlyBeforeFirstMessage && !showConversationList && !isConversationStarted;
8825
+ (0, import_react20.useEffect)(() => {
8826
+ onConversationStartedChange?.(isConversationStarted);
8827
+ }, [isConversationStarted, onConversationStartedChange]);
8828
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Root, { "data-testid": "ai-chat", children: [
8829
+ showConversationList ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ChatConversationList, {}) : null,
8830
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Workspace, { children: [
8831
+ showNewChatButton && !showConversationList && !shouldShowComposerOnly ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(QuickActions, { renderNewChatTrigger }) : null,
8832
+ shouldShowComposerOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ChatThread, {}),
8833
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ChatComposer, {})
8834
+ ] })
8835
+ ] });
8836
+ };
8515
8837
  var QuickActions = ({ renderNewChatTrigger }) => {
8516
8838
  const { labels, stopRef, store } = useChatContext();
8517
8839
  const startNewChat = useChatStore((state) => state.startNewChat);
@@ -8565,9 +8887,11 @@ var QuickActions = ({ renderNewChatTrigger }) => {
8565
8887
  {
8566
8888
  type: "button",
8567
8889
  "data-testid": "chat-start-new-session",
8890
+ "aria-label": labels.newChat,
8891
+ title: labels.newChat,
8568
8892
  onClick: () => void handleStartNewChat(),
8569
8893
  disabled: isActiveSessionStopping,
8570
- children: labels.newChat
8894
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(NewTalkIcon, {})
8571
8895
  }
8572
8896
  ) });
8573
8897
  };
@@ -8579,6 +8903,8 @@ var AiChat = ({
8579
8903
  showConversationList = false,
8580
8904
  showNewChatButton = false,
8581
8905
  renderNewChatTrigger,
8906
+ showComposerOnlyBeforeFirstMessage = false,
8907
+ onConversationStartedChange,
8582
8908
  ...providerProps
8583
8909
  }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
8584
8910
  import_compass_ui4.ConfigProvider,
@@ -8615,14 +8941,16 @@ var AiChat = ({
8615
8941
  }
8616
8942
  }
8617
8943
  },
8618
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(AiChatProvider, { ...providerProps, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Root, { "data-testid": "ai-chat", children: [
8619
- showConversationList ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ChatConversationList, {}) : null,
8620
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Workspace, { children: [
8621
- showNewChatButton && !showConversationList ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(QuickActions, { renderNewChatTrigger }) : null,
8622
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ChatThread, {}),
8623
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ChatComposer, {})
8624
- ] })
8625
- ] }) })
8944
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(AiChatProvider, { ...providerProps, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
8945
+ AiChatWorkspaceContent,
8946
+ {
8947
+ showConversationList,
8948
+ showNewChatButton,
8949
+ renderNewChatTrigger,
8950
+ showComposerOnlyBeforeFirstMessage,
8951
+ onConversationStartedChange
8952
+ }
8953
+ ) })
8626
8954
  }
8627
8955
  );
8628
8956
  var Root = import_styled17.default.div`
@@ -8646,12 +8974,26 @@ var QuickActionsRow = import_styled17.default.div`
8646
8974
  padding: 12px 12px 0;
8647
8975
  `;
8648
8976
  var QuickActionButton = import_styled17.default.button`
8649
- border: none;
8650
- border-radius: 12px;
8651
- padding: 10px 14px;
8977
+ width: 48px;
8978
+ height: 48px;
8979
+ display: grid;
8980
+ place-items: center;
8981
+ padding: 0;
8982
+ border: 1px solid rgba(255, 255, 255, 0.14);
8983
+ border-radius: 999px;
8652
8984
  background: rgba(255, 255, 255, 0.08);
8985
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
8653
8986
  color: var(--text-primary, #fcfbf8);
8654
8987
  cursor: pointer;
8988
+ transition:
8989
+ background 160ms ease,
8990
+ border-color 160ms ease,
8991
+ color 160ms ease;
8992
+
8993
+ &:hover:not(:disabled) {
8994
+ background: rgba(255, 255, 255, 0.12);
8995
+ border-color: rgba(255, 255, 255, 0.2);
8996
+ }
8655
8997
 
8656
8998
  &:disabled {
8657
8999
  opacity: 0.5;