@athenaintel/react 0.23.1 → 0.23.3

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.
Files changed (87) hide show
  1. package/README.md +45 -2
  2. package/dist/chat/AthenaChat.cjs +132 -39
  3. package/dist/chat/AthenaChat.cjs.map +1 -1
  4. package/dist/chat/AthenaChat.d.ts +37 -4
  5. package/dist/chat/AthenaChat.js +133 -40
  6. package/dist/chat/AthenaChat.js.map +1 -1
  7. package/dist/chat/athena-composer-controls.js +1 -1
  8. package/dist/chat/statewire-client-tools.cjs +20 -0
  9. package/dist/chat/statewire-client-tools.cjs.map +1 -1
  10. package/dist/chat/statewire-client-tools.d.ts +27 -0
  11. package/dist/chat/statewire-client-tools.js +20 -0
  12. package/dist/chat/statewire-client-tools.js.map +1 -1
  13. package/dist/chat/use-athena-run-live.cjs.map +1 -1
  14. package/dist/chat/use-athena-run-live.d.ts +7 -0
  15. package/dist/chat/use-athena-run-live.js.map +1 -1
  16. package/dist/chat-ui/composer/tiptap-composer.cjs +16 -1
  17. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  18. package/dist/chat-ui/composer/tiptap-composer.js +16 -1
  19. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  20. package/dist/composer/composer-handoff.cjs +121 -0
  21. package/dist/composer/composer-handoff.cjs.map +1 -0
  22. package/dist/composer/composer-handoff.d.ts +89 -0
  23. package/dist/composer/composer-handoff.js +121 -0
  24. package/dist/composer/composer-handoff.js.map +1 -0
  25. package/dist/composer/index.d.ts +2 -0
  26. package/dist/composer/useAppendToComposer.cjs +19 -7
  27. package/dist/composer/useAppendToComposer.cjs.map +1 -1
  28. package/dist/composer/useAppendToComposer.d.ts +22 -4
  29. package/dist/composer/useAppendToComposer.js +20 -8
  30. package/dist/composer/useAppendToComposer.js.map +1 -1
  31. package/dist/composer/useSendMessage.cjs +26 -8
  32. package/dist/composer/useSendMessage.cjs.map +1 -1
  33. package/dist/composer/useSendMessage.d.ts +8 -0
  34. package/dist/composer/useSendMessage.js +27 -9
  35. package/dist/composer/useSendMessage.js.map +1 -1
  36. package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
  37. package/dist/diagnostics/athena-diagnostics.d.ts +1 -1
  38. package/dist/diagnostics/athena-diagnostics.js.map +1 -1
  39. package/dist/diagnostics/errors.cjs +2 -0
  40. package/dist/diagnostics/errors.cjs.map +1 -1
  41. package/dist/diagnostics/errors.d.ts +2 -0
  42. package/dist/diagnostics/errors.js +2 -0
  43. package/dist/diagnostics/errors.js.map +1 -1
  44. package/dist/dictation/DictationStrip.cjs +60 -0
  45. package/dist/dictation/DictationStrip.cjs.map +1 -0
  46. package/dist/dictation/DictationStrip.d.ts +25 -0
  47. package/dist/dictation/DictationStrip.js +60 -0
  48. package/dist/dictation/DictationStrip.js.map +1 -0
  49. package/dist/dictation/audio-level-history.cjs +68 -0
  50. package/dist/dictation/audio-level-history.cjs.map +1 -0
  51. package/dist/dictation/audio-level-history.d.ts +27 -0
  52. package/dist/dictation/audio-level-history.js +68 -0
  53. package/dist/dictation/audio-level-history.js.map +1 -0
  54. package/dist/dictation/dictation-controls.cjs +60 -0
  55. package/dist/dictation/dictation-controls.cjs.map +1 -0
  56. package/dist/dictation/dictation-controls.d.ts +15 -0
  57. package/dist/dictation/dictation-controls.js +60 -0
  58. package/dist/dictation/dictation-controls.js.map +1 -0
  59. package/dist/dictation/dictation-engine.cjs +128 -0
  60. package/dist/dictation/dictation-engine.cjs.map +1 -0
  61. package/dist/dictation/dictation-engine.d.ts +87 -0
  62. package/dist/dictation/dictation-engine.js +128 -0
  63. package/dist/dictation/dictation-engine.js.map +1 -0
  64. package/dist/dictation/dictation-state.cjs +68 -0
  65. package/dist/dictation/dictation-state.cjs.map +1 -0
  66. package/dist/dictation/dictation-state.d.ts +58 -0
  67. package/dist/dictation/dictation-state.js +68 -0
  68. package/dist/dictation/dictation-state.js.map +1 -0
  69. package/dist/dictation/use-dictation.cjs +204 -0
  70. package/dist/dictation/use-dictation.cjs.map +1 -0
  71. package/dist/dictation/use-dictation.d.ts +47 -0
  72. package/dist/dictation/use-dictation.js +204 -0
  73. package/dist/dictation/use-dictation.js.map +1 -0
  74. package/dist/index.cjs +13 -0
  75. package/dist/index.cjs.map +1 -1
  76. package/dist/index.d.ts +11 -0
  77. package/dist/index.js +13 -0
  78. package/dist/index.js.map +1 -1
  79. package/dist/packages/react/package.json.cjs +1 -1
  80. package/dist/packages/react/package.json.js +1 -1
  81. package/dist/provider/AthenaProvider.cjs +42 -3
  82. package/dist/provider/AthenaProvider.cjs.map +1 -1
  83. package/dist/provider/AthenaProvider.d.ts +1 -1
  84. package/dist/provider/AthenaProvider.js +43 -4
  85. package/dist/provider/AthenaProvider.js.map +1 -1
  86. package/dist/styles.css +1 -1
  87. package/package.json +1 -1
package/README.md CHANGED
@@ -459,6 +459,17 @@ Both use the same bearer / API key as session creation. The full recipe
459
459
  template skill `voice-session-guide.md`. `createAthenaVoiceSession` is also
460
460
  exported if you hold the bridge state yourself.
461
461
 
462
+ ## What's new in 0.23.3
463
+
464
+ **Dictation in the composer.** `<AthenaChat>` now has a microphone left of Send. Click it and the editor row becomes a live waveform; Stop puts the spoken words into the draft for review, Send sends them (queued while a run is live). The default engine is the browser's Web Speech API (Chrome, Edge, Safari) — no backend, no extra dependency; the mic hides itself where the engine is missing (Firefox). Pass `dictation={false}` to remove it, or `dictation={{ lang, engine }}` to set the language or plug in another speech engine (`DictationEngine` interface, `useDictation()` hook, `DictationStrip` component are exported for custom composers).
465
+
466
+ **Composer slots.** New `composer` prop on `<AthenaChat>`: `toolbarStart` renders after the attach button, `toolbarEnd` before the mic and Send, and `onBeforeSend` runs host bookkeeping before every submit (dictated sends included). Slot components render inside the chat's thread scope, so `useAthenaRunLive()` works in them; the template's model-picker portal is no longer needed.
467
+
468
+ **Frontend tools bind reliably.** Two fixes to the `frontendTools` run config: (1) tools with an `execute()` no longer also ride `enabled_tools` — doing so switched on any backend toolkit owning a tool of the same name, and the backend won the collision, so the client tool was silently dropped (a frontend `notify_user` ran the backend notification cascade instead); (2) declaring executable frontend tools without a recognised `appId` now emits an `sdk.config.warning` error through diagnostics and `onError`, because the deep-agent runtime drops every client tool for an unknown `app_id` without telling the client.
469
+ ## What's new in 0.23.2
470
+
471
+ - Assistant turns no longer draw the grey vertical rule down their left edge. `AthenaChat` renders the lead column only when the host passes an `AvatarComponent`; without one the reply sits flush with the thread column and is told apart from the right-aligned user bubbles by alignment alone.
472
+
462
473
  ## What's new in 0.23.1
463
474
 
464
475
  - Hotfix: 0.23.0 crashed `AthenaChat` on mount in published apps ("The chat hit an error", `Cannot read properties of undefined (reading 'status')`). The message-window hook shipped in 0.23.0 reads `connection` from the statewire extras, which exists in `@assistant-ui/react-statewire` 0.29 / `statewire` 0.19 — the versions the monorepo resolves and tests against — but the package still pinned 0.28.1 / 0.18.2 for consumers. The pins now match the tested versions, and a test fails the build if they drift again.
@@ -1151,7 +1162,7 @@ Hosts that already run **Tailwind v4** (like the athena-app template) may instea
1151
1162
 
1152
1163
  Importing `styles.css` alongside a host Tailwind build is harmless (utilities are identical and layered). One caveat for themed Tailwind hosts: token values set on the `.athena-sdk` element shadow values inherited from `:root`, so define your app's token overrides on `.athena-sdk` too (`:root, .athena-sdk { --primary: …; }`) — or use the `theme` prop below, which always wins.
1153
1164
 
1154
- The thread's reading column defaults to a 46rem measure (set it with `<AthenaChat maxWidth>`; the chat passes that value to the thread, so the `threadMaxWidth` theme token does not reach it), 15px body text on a relaxed leading, and the `--font-sans` stack (`Inter, ui-sans-serif, system-ui, …` — a stack only, the SDK downloads no webfont). Override the face with `theme.fontFamily`, or `.athena-sdk { --font-sans: …; }`. Assistant turns carry a quiet 2px leading rule (replace it with `components.AssistantAvatar`); every message shows its time on hover beside its action bar, and a day separator marks the first message of a new calendar day.
1165
+ The thread's reading column defaults to a 46rem measure (set it with `<AthenaChat maxWidth>`; the chat passes that value to the thread, so the `threadMaxWidth` theme token does not reach it), 15px body text on a relaxed leading, and the `--font-sans` stack (`Inter, ui-sans-serif, system-ui, …` — a stack only, the SDK downloads no webfont). Override the face with `theme.fontFamily`, or `.athena-sdk { --font-sans: …; }`. Assistant turns sit flush with the column and carry no leading rule (pass `components.AssistantAvatar` to add a lead column); every message shows its time on hover beside its action bar, and a day separator marks the first message of a new calendar day.
1155
1166
 
1156
1167
  ## Theming
1157
1168
 
@@ -1201,8 +1212,40 @@ Dedicated tool UIs built on `ToolCard` follow the provider automatically; `useTo
1201
1212
  ## Composer Hooks
1202
1213
 
1203
1214
  Use `useAppendToComposer()` when you want to prefill a draft without sending it.
1215
+ Pass `{ focus: true }` to put the caret after the text once the editor shows it,
1216
+ so the user can finish the draft by typing or dictating (an agenda card that
1217
+ prefills "Here is what happened in this meeting:", for example):
1218
+
1219
+ ```tsx
1220
+ import { useAppendToComposer } from '@athenaintel/react';
1221
+
1222
+ function MeetingCard({ block }: { block: string }) {
1223
+ const append = useAppendToComposer();
1224
+ return (
1225
+ <button onClick={() => append(block, { replace: true, focus: true })}>
1226
+ Brief the agent
1227
+ </button>
1228
+ );
1229
+ }
1230
+ ```
1204
1231
 
1205
- Use `useSendMessage()` for workflow buttons, sidebar shortcuts, and other UI that lives outside `<AthenaChat>` but still needs to submit a prompt.
1232
+ Both hooks are safe to call at any time. A write made before the chat is
1233
+ ready — with `enableThreadList`, while the list is still resolving the active
1234
+ thread, or while the thread's history is still loading — waits in the provider
1235
+ and lands once the composer is ready, instead of being lost with the mount it
1236
+ was written into (the provider keys its statewire subtree by thread). Readiness
1237
+ is not the socket: a never-started chat sits in `standby` until its first send
1238
+ and still takes a prefill. Early writes keep their order (two early sends both
1239
+ go out, first then second; adjacent plain appends fold into one draft), and
1240
+ each is bound to the thread it was made for: if the user switches threads, the
1241
+ identity changes, or the provider unmounts before it lands, it is dropped —
1242
+ `useSendMessage` rejects with an `AthenaSdkError` (`composer_write_dropped`)
1243
+ and a `composer.handoff` diagnostic says why — never written into another
1244
+ thread. `useComposerReady()` exposes the readiness for UI that wants to show a
1245
+ "loading" state; `composer.handoff` records each deferred, applied and dropped
1246
+ write.
1247
+
1248
+ Use `useSendMessage()` for workflow buttons, sidebar shortcuts, and other UI that lives outside `<AthenaChat>` but still needs to submit a prompt. Its promise settles once the send has been dispatched, including a send that waited for the connection.
1206
1249
 
1207
1250
  ```tsx
1208
1251
  import { useSendMessage } from '@athenaintel/react';
@@ -39,6 +39,12 @@ const chatThreadShell = require("../chat-ui/thread/chat-thread-shell.cjs");
39
39
  const statewireHistoryEdge = require("../chat-ui/thread/statewire-history-edge.cjs");
40
40
  const threadLoadingOverlay = require("../chat-ui/thread/thread-loading-overlay.cjs");
41
41
  const composerSendOrStop = require("../chat-ui/thread/composer-send-or-stop.cjs");
42
+ const composerAction = require("../chat-ui/composer/composer-action.cjs");
43
+ const athenaDiagnostics = require("../diagnostics/athena-diagnostics.cjs");
44
+ const useDictation = require("../dictation/use-dictation.cjs");
45
+ const DictationStrip = require("../dictation/DictationStrip.cjs");
46
+ const dictationControls = require("../dictation/dictation-controls.cjs");
47
+ const dictationState = require("../dictation/dictation-state.cjs");
42
48
  const tiptapComposer = require("../chat-ui/composer/tiptap-composer.cjs");
43
49
  const apiClient = require("../chat-ui/mentions/suggestions/data/api-client.cjs");
44
50
  const messageComponents = require("../chat-ui/messages/message-components.cjs");
@@ -144,7 +150,9 @@ const AthenaChat = ({
144
150
  mentionTools,
145
151
  welcomeSuggestions = athenaChatWelcome.DEFAULT_WELCOME_SUGGESTIONS,
146
152
  components,
147
- groupToolCalls = true
153
+ groupToolCalls = true,
154
+ composer: composerSlots,
155
+ dictation = true
148
156
  }) => {
149
157
  var _a, _b, _c;
150
158
  const athenaConfig = AthenaContext.useAthenaConfig();
@@ -252,6 +260,8 @@ const AthenaChat = ({
252
260
  AthenaChatComposer,
253
261
  {
254
262
  tools,
263
+ slots: composerSlots,
264
+ dictation,
255
265
  welcomeSuggestionCount: welcomeSuggestions.length
256
266
  }
257
267
  ) })
@@ -310,7 +320,7 @@ const ATHENA_CHAT_MENTION_CATEGORIES = [
310
320
  "projects",
311
321
  "folders"
312
322
  ];
313
- const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
323
+ const AthenaChatComposer = ({ tools, slots, dictation, welcomeSuggestionCount }) => {
314
324
  const aui = react.useAui();
315
325
  const threadId = threadIdContext.useAthenaStatewireThreadId();
316
326
  const { appUrl } = AthenaContext.useAthenaConfig();
@@ -319,6 +329,10 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
319
329
  const { attachFiles } = useAttachFiles.useAttachFiles();
320
330
  const composerRef = react$1.useRef(null);
321
331
  const [hasText, setHasText] = react$1.useState(false);
332
+ const isRunning = react.useAuiState((state) => {
333
+ var _a;
334
+ return ((_a = state.optional.thread) == null ? void 0 : _a.isRunning) ?? false;
335
+ });
322
336
  const [dragActive, setDragActive] = react$1.useState(false);
323
337
  const keyboardHint = composerKeyboardHint.useComposerKeyboardHint();
324
338
  const reducedMotion = usePrefersReducedMotion.usePrefersReducedMotion();
@@ -328,6 +342,28 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
328
342
  athenaChatWelcome.welcomeComposerDelayMs(welcomeSuggestionCount),
329
343
  reducedMotion || !mountedEmpty
330
344
  );
345
+ const dictationEnabled = dictation !== false;
346
+ const dictationOptions = typeof dictation === "object" ? dictation : void 0;
347
+ const appendSpokenText = react$1.useCallback(
348
+ (spoken) => {
349
+ if (!spoken) return;
350
+ aui.composer.setText(dictationState.composeDictationDraft(aui.composer.getState().text ?? "", spoken));
351
+ },
352
+ [aui]
353
+ );
354
+ const dictationCtl = useDictation.useDictation({
355
+ engine: dictationOptions == null ? void 0 : dictationOptions.engine,
356
+ lang: dictationOptions == null ? void 0 : dictationOptions.lang,
357
+ // A recognizer that gives up on its own (silence window) still hands
358
+ // over what it heard instead of dropping the words with the session.
359
+ onAutoEnd: appendSpokenText
360
+ });
361
+ const recording = dictationEnabled && dictationCtl.isActive;
362
+ const showMic = dictationEnabled && dictationCtl.isSupported;
363
+ const { isActive: dictationActive, cancel: cancelDictation } = dictationCtl;
364
+ react$1.useEffect(() => {
365
+ if (!dictationEnabled && dictationActive) cancelDictation();
366
+ }, [cancelDictation, dictationActive, dictationEnabled]);
331
367
  const rootCategories = react$1.useMemo(() => {
332
368
  const categories = [...ATHENA_CHAT_MENTION_CATEGORIES];
333
369
  if (tools.some((tool) => tool.type === "toolkit")) categories.push("toolkits");
@@ -383,6 +419,36 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
383
419
  }),
384
420
  [attachFiles]
385
421
  );
422
+ const stopDictation = react$1.useCallback(async () => {
423
+ appendSpokenText(await dictationCtl.stop());
424
+ }, [appendSpokenText, dictationCtl]);
425
+ const sendDictation = react$1.useCallback(async () => {
426
+ var _a;
427
+ const spoken = await dictationCtl.stop();
428
+ const text = dictationState.composeDictationDraft(aui.composer.getState().text ?? "", spoken);
429
+ const extras = attachmentsRef.current.length > 0 || quoteRef.current !== null;
430
+ if (!text && !extras) return;
431
+ aui.composer.setText(text);
432
+ const action = composerAction.resolveComposerAction({ hasDraft: true, isRunning });
433
+ if (action === "stop") return;
434
+ try {
435
+ await ((_a = slots == null ? void 0 : slots.onBeforeSend) == null ? void 0 : _a.call(slots, { action }));
436
+ } catch (error) {
437
+ athenaDiagnostics.athenaDiagnostics.emit("composer.dictation", {
438
+ level: "warn",
439
+ data: {
440
+ phase: "before_send_rejected",
441
+ error: error instanceof Error ? error.message : String(error)
442
+ }
443
+ });
444
+ return;
445
+ }
446
+ if (extras) {
447
+ sendComposed(text);
448
+ return;
449
+ }
450
+ aui.composer.send({ steer: false });
451
+ }, [aui, dictationCtl, isRunning, sendComposed, slots]);
386
452
  return /* @__PURE__ */ jsxRuntime.jsx(ComposerDropZone.ComposerDropZone, { onDragActiveChange: setDragActive, children: /* @__PURE__ */ jsxRuntime.jsx(
387
453
  "div",
388
454
  {
@@ -399,23 +465,34 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
399
465
  /* @__PURE__ */ jsxRuntime.jsx(ComposerQuotePreview.ComposerQuotePreview, {}),
400
466
  /* @__PURE__ */ jsxRuntime.jsx(ComposerAttachmentPreview.ComposerAttachmentPreview, {})
401
467
  ] }),
402
- editor: /* @__PURE__ */ jsxRuntime.jsx(
403
- tiptapComposer.TiptapComposer,
404
- {
405
- ref: composerRef,
406
- threadId,
407
- appearance: "paper",
408
- placeholder: "Type @ to tag an asset",
409
- tools,
410
- rootCategories,
411
- onDraftStateChange: setHasText,
412
- waitForHostUploads,
413
- interceptSubmit,
414
- fileIntake,
415
- onSubmitted: keyboardHint.onSubmitted
416
- }
417
- ),
418
- toolbarStart: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
468
+ editor: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
469
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cnfast.cn(recording && "hidden"), children: /* @__PURE__ */ jsxRuntime.jsx(
470
+ tiptapComposer.TiptapComposer,
471
+ {
472
+ ref: composerRef,
473
+ threadId,
474
+ appearance: "paper",
475
+ placeholder: "Type @ to tag an asset",
476
+ tools,
477
+ rootCategories,
478
+ onDraftStateChange: setHasText,
479
+ waitForHostUploads,
480
+ interceptSubmit,
481
+ fileIntake,
482
+ onSubmitted: keyboardHint.onSubmitted
483
+ }
484
+ ) }),
485
+ recording && /* @__PURE__ */ jsxRuntime.jsx(
486
+ DictationStrip.DictationStrip,
487
+ {
488
+ status: dictationCtl.status,
489
+ transcript: dictationCtl.transcript,
490
+ stream: dictationCtl.stream
491
+ }
492
+ ),
493
+ dictationEnabled && dictationCtl.status === dictationState.DICTATION_STATUSES.error && dictationCtl.error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "aui-dictation-error px-1.5 pb-1 text-destructive text-xs", role: "alert", children: dictationCtl.error.message })
494
+ ] }),
495
+ toolbarStart: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: recording ? /* @__PURE__ */ jsxRuntime.jsx(dictationControls.DictationCancelButton, { onClick: dictationCtl.cancel }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
419
496
  /* @__PURE__ */ jsxRuntime.jsx(FileUploadButton.FileUploadButton, { className: "aui-composer-attach size-8 rounded-full p-0 disabled:opacity-30" }),
420
497
  /* @__PURE__ */ jsxRuntime.jsx(
421
498
  athenaComposerControls.AthenaComposerMentionButton,
@@ -425,17 +502,40 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
425
502
  return (_b = (_a = composerRef.current) == null ? void 0 : _a.openMentionMenu) == null ? void 0 : _b.call(_a);
426
503
  }
427
504
  }
505
+ ),
506
+ slots == null ? void 0 : slots.toolbarStart
507
+ ] }) }),
508
+ toolbarEnd: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: recording ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
509
+ /* @__PURE__ */ jsxRuntime.jsx(
510
+ dictationControls.DictationStopButton,
511
+ {
512
+ onClick: () => void stopDictation(),
513
+ disabled: dictationCtl.status === dictationState.DICTATION_STATUSES.stopping
514
+ }
515
+ ),
516
+ /* @__PURE__ */ jsxRuntime.jsx(
517
+ athenaComposerControls.AthenaComposerSendButton,
518
+ {
519
+ action: isRunning ? "queue" : "send",
520
+ onSend: () => void sendDictation(),
521
+ disabled: dictationCtl.status !== dictationState.DICTATION_STATUSES.listening || isUploading,
522
+ title: isUploading ? "Upload in progress..." : void 0
523
+ }
428
524
  )
429
- ] }),
430
- toolbarEnd: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxRuntime.jsx(
431
- composerSendOrStop.ComposerSendOrStop,
432
- {
433
- composerRef,
434
- hasDraft: hasText || hasExtras,
435
- sendBlockedReason: isUploading ? "Upload in progress..." : null,
436
- components: athenaComposerControls.ATHENA_COMPOSER_COMPONENTS
437
- }
438
- ) }),
525
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
526
+ slots == null ? void 0 : slots.toolbarEnd,
527
+ showMic && /* @__PURE__ */ jsxRuntime.jsx(dictationControls.DictationMicButton, { onClick: dictationCtl.start, disabled: isUploading }),
528
+ /* @__PURE__ */ jsxRuntime.jsx(
529
+ composerSendOrStop.ComposerSendOrStop,
530
+ {
531
+ composerRef,
532
+ hasDraft: hasText || hasExtras,
533
+ sendBlockedReason: isUploading ? "Upload in progress..." : null,
534
+ onBeforeSend: slots == null ? void 0 : slots.onBeforeSend,
535
+ components: athenaComposerControls.ATHENA_COMPOSER_COMPONENTS
536
+ }
537
+ )
538
+ ] }) }),
439
539
  belowSurface: /* @__PURE__ */ jsxRuntime.jsx(composerKeyboardHint.ComposerKeyboardHint, { visible: keyboardHint.visible })
440
540
  }
441
541
  )
@@ -706,21 +806,14 @@ const AthenaAssistantMessage = ({
706
806
  children: [
707
807
  /* @__PURE__ */ jsxRuntime.jsx(MessageDaySeparator, {}),
708
808
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
709
- /* @__PURE__ */ jsxRuntime.jsx(
809
+ AvatarComponent ? /* @__PURE__ */ jsxRuntime.jsx(
710
810
  "div",
711
811
  {
712
812
  "data-slot": "assistant-lead",
713
813
  className: "aui-assistant-message-lead flex shrink-0 justify-center",
714
- children: AvatarComponent ? /* @__PURE__ */ jsxRuntime.jsx(AvatarComponent, {}) : /* @__PURE__ */ jsxRuntime.jsx(
715
- "span",
716
- {
717
- "aria-hidden": "true",
718
- "data-slot": "assistant-rule",
719
- className: "aui-assistant-message-rule w-0.5 self-stretch rounded-full bg-border"
720
- }
721
- )
814
+ children: /* @__PURE__ */ jsxRuntime.jsx(AvatarComponent, {})
722
815
  }
723
- ),
816
+ ) : null,
724
817
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
725
818
  /* @__PURE__ */ jsxRuntime.jsx(AthenaReasoningTextComponentContext.Provider, { value: TextComponent, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
726
819
  /* @__PURE__ */ jsxRuntime.jsx(NestedPtcMessages.NestedPtcComponentsProvider, { components: nestedPtcComponents, children: groupToolCalls ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [