@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
@@ -37,13 +37,19 @@ import { ChatThreadShell } from "../chat-ui/thread/chat-thread-shell.js";
37
37
  import { StatewireHistoryEdge } from "../chat-ui/thread/statewire-history-edge.js";
38
38
  import { ThreadLoadingOverlay } from "../chat-ui/thread/thread-loading-overlay.js";
39
39
  import { ComposerSendOrStop } from "../chat-ui/thread/composer-send-or-stop.js";
40
+ import { resolveComposerAction } from "../chat-ui/composer/composer-action.js";
41
+ import { athenaDiagnostics } from "../diagnostics/athena-diagnostics.js";
42
+ import { useDictation } from "../dictation/use-dictation.js";
43
+ import { DictationStrip } from "../dictation/DictationStrip.js";
44
+ import { DictationStopButton, DictationMicButton, DictationCancelButton } from "../dictation/dictation-controls.js";
45
+ import { composeDictationDraft, DICTATION_STATUSES } from "../dictation/dictation-state.js";
40
46
  import { TiptapComposer } from "../chat-ui/composer/tiptap-composer.js";
41
47
  import { MentionAuthCtx } from "../chat-ui/mentions/suggestions/data/api-client.js";
42
48
  import { ACTION_BAR_REVEAL_CLASS, BranchPicker } from "../chat-ui/messages/message-components.js";
43
49
  import { useMessageActionsReadOnly } from "../chat-ui/messages/message-actions-config.js";
44
50
  import { useAthenaRunLive } from "./use-athena-run-live.js";
45
51
  import { DEFAULT_WELCOME_SUGGESTIONS, AthenaChatWelcomeSuggestions, AthenaChatWelcome, welcomeEntrance, welcomeComposerDelayMs } from "./athena-chat-welcome.js";
46
- import { ATHENA_COMPOSER_COMPONENTS, AthenaComposerMentionButton } from "./athena-composer-controls.js";
52
+ import { AthenaComposerSendButton, ATHENA_COMPOSER_COMPONENTS, AthenaComposerMentionButton } from "./athena-composer-controls.js";
47
53
  import { useComposerKeyboardHint, ComposerKeyboardHint } from "./composer-keyboard-hint.js";
48
54
  import { usePrefersReducedMotion } from "../lib/use-prefers-reduced-motion.js";
49
55
  import { useAuiState, ActionBarPrimitive, ActionBarMorePrimitive, MessagePrimitive, ThreadPrimitive, AuiIf, ErrorPrimitive, useAui } from "@assistant-ui/react";
@@ -142,7 +148,9 @@ const AthenaChat = ({
142
148
  mentionTools,
143
149
  welcomeSuggestions = DEFAULT_WELCOME_SUGGESTIONS,
144
150
  components,
145
- groupToolCalls = true
151
+ groupToolCalls = true,
152
+ composer: composerSlots,
153
+ dictation = true
146
154
  }) => {
147
155
  var _a, _b, _c;
148
156
  const athenaConfig = useAthenaConfig();
@@ -250,6 +258,8 @@ const AthenaChat = ({
250
258
  AthenaChatComposer,
251
259
  {
252
260
  tools,
261
+ slots: composerSlots,
262
+ dictation,
253
263
  welcomeSuggestionCount: welcomeSuggestions.length
254
264
  }
255
265
  ) })
@@ -308,7 +318,7 @@ const ATHENA_CHAT_MENTION_CATEGORIES = [
308
318
  "projects",
309
319
  "folders"
310
320
  ];
311
- const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
321
+ const AthenaChatComposer = ({ tools, slots, dictation, welcomeSuggestionCount }) => {
312
322
  const aui = useAui();
313
323
  const threadId = useAthenaStatewireThreadId();
314
324
  const { appUrl } = useAthenaConfig();
@@ -317,6 +327,10 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
317
327
  const { attachFiles } = useAttachFiles();
318
328
  const composerRef = useRef(null);
319
329
  const [hasText, setHasText] = useState(false);
330
+ const isRunning = useAuiState((state) => {
331
+ var _a;
332
+ return ((_a = state.optional.thread) == null ? void 0 : _a.isRunning) ?? false;
333
+ });
320
334
  const [dragActive, setDragActive] = useState(false);
321
335
  const keyboardHint = useComposerKeyboardHint();
322
336
  const reducedMotion = usePrefersReducedMotion();
@@ -326,6 +340,28 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
326
340
  welcomeComposerDelayMs(welcomeSuggestionCount),
327
341
  reducedMotion || !mountedEmpty
328
342
  );
343
+ const dictationEnabled = dictation !== false;
344
+ const dictationOptions = typeof dictation === "object" ? dictation : void 0;
345
+ const appendSpokenText = useCallback(
346
+ (spoken) => {
347
+ if (!spoken) return;
348
+ aui.composer.setText(composeDictationDraft(aui.composer.getState().text ?? "", spoken));
349
+ },
350
+ [aui]
351
+ );
352
+ const dictationCtl = useDictation({
353
+ engine: dictationOptions == null ? void 0 : dictationOptions.engine,
354
+ lang: dictationOptions == null ? void 0 : dictationOptions.lang,
355
+ // A recognizer that gives up on its own (silence window) still hands
356
+ // over what it heard instead of dropping the words with the session.
357
+ onAutoEnd: appendSpokenText
358
+ });
359
+ const recording = dictationEnabled && dictationCtl.isActive;
360
+ const showMic = dictationEnabled && dictationCtl.isSupported;
361
+ const { isActive: dictationActive, cancel: cancelDictation } = dictationCtl;
362
+ useEffect(() => {
363
+ if (!dictationEnabled && dictationActive) cancelDictation();
364
+ }, [cancelDictation, dictationActive, dictationEnabled]);
329
365
  const rootCategories = useMemo(() => {
330
366
  const categories = [...ATHENA_CHAT_MENTION_CATEGORIES];
331
367
  if (tools.some((tool) => tool.type === "toolkit")) categories.push("toolkits");
@@ -381,6 +417,36 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
381
417
  }),
382
418
  [attachFiles]
383
419
  );
420
+ const stopDictation = useCallback(async () => {
421
+ appendSpokenText(await dictationCtl.stop());
422
+ }, [appendSpokenText, dictationCtl]);
423
+ const sendDictation = useCallback(async () => {
424
+ var _a;
425
+ const spoken = await dictationCtl.stop();
426
+ const text = composeDictationDraft(aui.composer.getState().text ?? "", spoken);
427
+ const extras = attachmentsRef.current.length > 0 || quoteRef.current !== null;
428
+ if (!text && !extras) return;
429
+ aui.composer.setText(text);
430
+ const action = resolveComposerAction({ hasDraft: true, isRunning });
431
+ if (action === "stop") return;
432
+ try {
433
+ await ((_a = slots == null ? void 0 : slots.onBeforeSend) == null ? void 0 : _a.call(slots, { action }));
434
+ } catch (error) {
435
+ athenaDiagnostics.emit("composer.dictation", {
436
+ level: "warn",
437
+ data: {
438
+ phase: "before_send_rejected",
439
+ error: error instanceof Error ? error.message : String(error)
440
+ }
441
+ });
442
+ return;
443
+ }
444
+ if (extras) {
445
+ sendComposed(text);
446
+ return;
447
+ }
448
+ aui.composer.send({ steer: false });
449
+ }, [aui, dictationCtl, isRunning, sendComposed, slots]);
384
450
  return /* @__PURE__ */ jsx(ComposerDropZone, { onDragActiveChange: setDragActive, children: /* @__PURE__ */ jsx(
385
451
  "div",
386
452
  {
@@ -397,23 +463,34 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
397
463
  /* @__PURE__ */ jsx(ComposerQuotePreview, {}),
398
464
  /* @__PURE__ */ jsx(ComposerAttachmentPreview, {})
399
465
  ] }),
400
- editor: /* @__PURE__ */ jsx(
401
- TiptapComposer,
402
- {
403
- ref: composerRef,
404
- threadId,
405
- appearance: "paper",
406
- placeholder: "Type @ to tag an asset",
407
- tools,
408
- rootCategories,
409
- onDraftStateChange: setHasText,
410
- waitForHostUploads,
411
- interceptSubmit,
412
- fileIntake,
413
- onSubmitted: keyboardHint.onSubmitted
414
- }
415
- ),
416
- toolbarStart: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
466
+ editor: /* @__PURE__ */ jsxs(Fragment, { children: [
467
+ /* @__PURE__ */ jsx("div", { className: cn(recording && "hidden"), children: /* @__PURE__ */ jsx(
468
+ TiptapComposer,
469
+ {
470
+ ref: composerRef,
471
+ threadId,
472
+ appearance: "paper",
473
+ placeholder: "Type @ to tag an asset",
474
+ tools,
475
+ rootCategories,
476
+ onDraftStateChange: setHasText,
477
+ waitForHostUploads,
478
+ interceptSubmit,
479
+ fileIntake,
480
+ onSubmitted: keyboardHint.onSubmitted
481
+ }
482
+ ) }),
483
+ recording && /* @__PURE__ */ jsx(
484
+ DictationStrip,
485
+ {
486
+ status: dictationCtl.status,
487
+ transcript: dictationCtl.transcript,
488
+ stream: dictationCtl.stream
489
+ }
490
+ ),
491
+ dictationEnabled && dictationCtl.status === DICTATION_STATUSES.error && dictationCtl.error && /* @__PURE__ */ jsx("p", { className: "aui-dictation-error px-1.5 pb-1 text-destructive text-xs", role: "alert", children: dictationCtl.error.message })
492
+ ] }),
493
+ toolbarStart: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: recording ? /* @__PURE__ */ jsx(DictationCancelButton, { onClick: dictationCtl.cancel }) : /* @__PURE__ */ jsxs(Fragment, { children: [
417
494
  /* @__PURE__ */ jsx(FileUploadButton, { className: "aui-composer-attach size-8 rounded-full p-0 disabled:opacity-30" }),
418
495
  /* @__PURE__ */ jsx(
419
496
  AthenaComposerMentionButton,
@@ -423,17 +500,40 @@ const AthenaChatComposer = ({ tools, welcomeSuggestionCount }) => {
423
500
  return (_b = (_a = composerRef.current) == null ? void 0 : _a.openMentionMenu) == null ? void 0 : _b.call(_a);
424
501
  }
425
502
  }
503
+ ),
504
+ slots == null ? void 0 : slots.toolbarStart
505
+ ] }) }),
506
+ toolbarEnd: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: recording ? /* @__PURE__ */ jsxs(Fragment, { children: [
507
+ /* @__PURE__ */ jsx(
508
+ DictationStopButton,
509
+ {
510
+ onClick: () => void stopDictation(),
511
+ disabled: dictationCtl.status === DICTATION_STATUSES.stopping
512
+ }
513
+ ),
514
+ /* @__PURE__ */ jsx(
515
+ AthenaComposerSendButton,
516
+ {
517
+ action: isRunning ? "queue" : "send",
518
+ onSend: () => void sendDictation(),
519
+ disabled: dictationCtl.status !== DICTATION_STATUSES.listening || isUploading,
520
+ title: isUploading ? "Upload in progress..." : void 0
521
+ }
426
522
  )
427
- ] }),
428
- toolbarEnd: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsx(
429
- ComposerSendOrStop,
430
- {
431
- composerRef,
432
- hasDraft: hasText || hasExtras,
433
- sendBlockedReason: isUploading ? "Upload in progress..." : null,
434
- components: ATHENA_COMPOSER_COMPONENTS
435
- }
436
- ) }),
523
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
524
+ slots == null ? void 0 : slots.toolbarEnd,
525
+ showMic && /* @__PURE__ */ jsx(DictationMicButton, { onClick: dictationCtl.start, disabled: isUploading }),
526
+ /* @__PURE__ */ jsx(
527
+ ComposerSendOrStop,
528
+ {
529
+ composerRef,
530
+ hasDraft: hasText || hasExtras,
531
+ sendBlockedReason: isUploading ? "Upload in progress..." : null,
532
+ onBeforeSend: slots == null ? void 0 : slots.onBeforeSend,
533
+ components: ATHENA_COMPOSER_COMPONENTS
534
+ }
535
+ )
536
+ ] }) }),
437
537
  belowSurface: /* @__PURE__ */ jsx(ComposerKeyboardHint, { visible: keyboardHint.visible })
438
538
  }
439
539
  )
@@ -704,21 +804,14 @@ const AthenaAssistantMessage = ({
704
804
  children: [
705
805
  /* @__PURE__ */ jsx(MessageDaySeparator, {}),
706
806
  /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
707
- /* @__PURE__ */ jsx(
807
+ AvatarComponent ? /* @__PURE__ */ jsx(
708
808
  "div",
709
809
  {
710
810
  "data-slot": "assistant-lead",
711
811
  className: "aui-assistant-message-lead flex shrink-0 justify-center",
712
- children: AvatarComponent ? /* @__PURE__ */ jsx(AvatarComponent, {}) : /* @__PURE__ */ jsx(
713
- "span",
714
- {
715
- "aria-hidden": "true",
716
- "data-slot": "assistant-rule",
717
- className: "aui-assistant-message-rule w-0.5 self-stretch rounded-full bg-border"
718
- }
719
- )
812
+ children: /* @__PURE__ */ jsx(AvatarComponent, {})
720
813
  }
721
- ),
814
+ ) : null,
722
815
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
723
816
  /* @__PURE__ */ jsx(AthenaReasoningTextComponentContext.Provider, { value: TextComponent, children: /* @__PURE__ */ jsxs("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
724
817
  /* @__PURE__ */ jsx(NestedPtcComponentsProvider, { components: nestedPtcComponents, children: groupToolCalls ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-2", children: [