@athenaintel/react 0.23.2 → 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.
- package/README.md +40 -1
- package/dist/chat/AthenaChat.cjs +129 -29
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +32 -1
- package/dist/chat/AthenaChat.js +130 -30
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/athena-composer-controls.js +1 -1
- package/dist/chat/statewire-client-tools.cjs +20 -0
- package/dist/chat/statewire-client-tools.cjs.map +1 -1
- package/dist/chat/statewire-client-tools.d.ts +27 -0
- package/dist/chat/statewire-client-tools.js +20 -0
- package/dist/chat/statewire-client-tools.js.map +1 -1
- package/dist/chat/use-athena-run-live.cjs.map +1 -1
- package/dist/chat/use-athena-run-live.d.ts +7 -0
- package/dist/chat/use-athena-run-live.js.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs +16 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.js +16 -1
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/composer/composer-handoff.cjs +121 -0
- package/dist/composer/composer-handoff.cjs.map +1 -0
- package/dist/composer/composer-handoff.d.ts +89 -0
- package/dist/composer/composer-handoff.js +121 -0
- package/dist/composer/composer-handoff.js.map +1 -0
- package/dist/composer/index.d.ts +2 -0
- package/dist/composer/useAppendToComposer.cjs +19 -7
- package/dist/composer/useAppendToComposer.cjs.map +1 -1
- package/dist/composer/useAppendToComposer.d.ts +22 -4
- package/dist/composer/useAppendToComposer.js +20 -8
- package/dist/composer/useAppendToComposer.js.map +1 -1
- package/dist/composer/useSendMessage.cjs +26 -8
- package/dist/composer/useSendMessage.cjs.map +1 -1
- package/dist/composer/useSendMessage.d.ts +8 -0
- package/dist/composer/useSendMessage.js +27 -9
- package/dist/composer/useSendMessage.js.map +1 -1
- package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
- package/dist/diagnostics/athena-diagnostics.d.ts +1 -1
- package/dist/diagnostics/athena-diagnostics.js.map +1 -1
- package/dist/diagnostics/errors.cjs +2 -0
- package/dist/diagnostics/errors.cjs.map +1 -1
- package/dist/diagnostics/errors.d.ts +2 -0
- package/dist/diagnostics/errors.js +2 -0
- package/dist/diagnostics/errors.js.map +1 -1
- package/dist/dictation/DictationStrip.cjs +60 -0
- package/dist/dictation/DictationStrip.cjs.map +1 -0
- package/dist/dictation/DictationStrip.d.ts +25 -0
- package/dist/dictation/DictationStrip.js +60 -0
- package/dist/dictation/DictationStrip.js.map +1 -0
- package/dist/dictation/audio-level-history.cjs +68 -0
- package/dist/dictation/audio-level-history.cjs.map +1 -0
- package/dist/dictation/audio-level-history.d.ts +27 -0
- package/dist/dictation/audio-level-history.js +68 -0
- package/dist/dictation/audio-level-history.js.map +1 -0
- package/dist/dictation/dictation-controls.cjs +60 -0
- package/dist/dictation/dictation-controls.cjs.map +1 -0
- package/dist/dictation/dictation-controls.d.ts +15 -0
- package/dist/dictation/dictation-controls.js +60 -0
- package/dist/dictation/dictation-controls.js.map +1 -0
- package/dist/dictation/dictation-engine.cjs +128 -0
- package/dist/dictation/dictation-engine.cjs.map +1 -0
- package/dist/dictation/dictation-engine.d.ts +87 -0
- package/dist/dictation/dictation-engine.js +128 -0
- package/dist/dictation/dictation-engine.js.map +1 -0
- package/dist/dictation/dictation-state.cjs +68 -0
- package/dist/dictation/dictation-state.cjs.map +1 -0
- package/dist/dictation/dictation-state.d.ts +58 -0
- package/dist/dictation/dictation-state.js +68 -0
- package/dist/dictation/dictation-state.js.map +1 -0
- package/dist/dictation/use-dictation.cjs +204 -0
- package/dist/dictation/use-dictation.cjs.map +1 -0
- package/dist/dictation/use-dictation.d.ts +47 -0
- package/dist/dictation/use-dictation.js +204 -0
- package/dist/dictation/use-dictation.js.map +1 -0
- package/dist/index.cjs +13 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/packages/react/package.json.cjs +1 -1
- package/dist/packages/react/package.json.js +1 -1
- package/dist/provider/AthenaProvider.cjs +42 -3
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +1 -1
- package/dist/provider/AthenaProvider.js +43 -4
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -459,6 +459,13 @@ 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.
|
|
462
469
|
## What's new in 0.23.2
|
|
463
470
|
|
|
464
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.
|
|
@@ -1205,8 +1212,40 @@ Dedicated tool UIs built on `ToolCard` follow the provider automatically; `useTo
|
|
|
1205
1212
|
## Composer Hooks
|
|
1206
1213
|
|
|
1207
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
|
+
```
|
|
1208
1231
|
|
|
1209
|
-
|
|
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.
|
|
1210
1249
|
|
|
1211
1250
|
```tsx
|
|
1212
1251
|
import { useSendMessage } from '@athenaintel/react';
|
package/dist/chat/AthenaChat.cjs
CHANGED
|
@@ -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.
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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
|
)
|