@epam/ai-dial-chat-hooks 1.2.0-dev.3 → 1.2.0-dev.303

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 (104) hide show
  1. package/api-error/api-error.js +7 -4
  2. package/attachment/useAttachmentValidation/useAttachmentValidation.js +26 -19
  3. package/attachments.d.ts +10 -4
  4. package/catalog/catalog-derivations.js +1 -1
  5. package/catalog/deployment-id.js +8 -2
  6. package/catalog/map-deployment-limits-to-catalog.js +16 -24
  7. package/catalog/map-deployment-limits-to-input.js +81 -9
  8. package/catalog/map-deployment-to-catalog-item.js +34 -34
  9. package/catalog/map-entity-details-to-catalog.js +7 -0
  10. package/catalog/map-skill-to-catalog-item.js +55 -48
  11. package/catalog/publish.js +6 -5
  12. package/catalog/useApplicationCredentials/useApplicationCredentials.js +39 -0
  13. package/catalog/useCatalogEditNavigation/useCatalogEditNavigation.js +122 -101
  14. package/catalog/usePublishFolders/usePublishFolders.js +1 -1
  15. package/catalog/useSkillDetailsPanelData/useSkillDetailsPanelData.js +39 -39
  16. package/catalog/useSkillItemDetails.js +19 -17
  17. package/catalog.d.ts +159 -35
  18. package/catalog.js +23 -22
  19. package/conversation/announcement-message.js +16 -5
  20. package/conversation/conversation-transfer/export-conversation.js +24 -16
  21. package/conversation/conversation-transfer/import-conversation.js +80 -31
  22. package/conversation/conversation-transfer/queue.js +8 -5
  23. package/conversation/create-chat-stream-api.js +85 -49
  24. package/conversation/message-utils.js +44 -2
  25. package/conversation/stage.js +27 -0
  26. package/conversation/useActiveConversationSync/useActiveConversationSync.js +7 -8
  27. package/conversation/useAttachmentUpload/useAttachmentUpload.js +12 -5
  28. package/conversation/useConversationExport/useConversationExport.js +9 -9
  29. package/conversation/useConversationHandlers/message-utils.js +8 -5
  30. package/conversation/useConversationHandlers/useConversationHandlers.js +187 -177
  31. package/conversation/useConversationImport/useConversationImport.js +123 -121
  32. package/conversation/useConversationPanelItems/useConversationPanelItems.js +50 -32
  33. package/conversation/useConversationScroll/useConversationScroll.js +68 -64
  34. package/conversation/useConversationStream/apply-chunk.js +1 -1
  35. package/conversation/useConversationStream/frame-scheduler.js +39 -0
  36. package/conversation/useConversationStream/generation-resume.js +122 -64
  37. package/conversation/useConversationStream/useConversationStream.js +279 -116
  38. package/conversation/useMessageSelectionReply/useMessageSelectionReply.js +189 -0
  39. package/conversation/useTranscribeAudio/transcription-retry.js +5 -4
  40. package/conversation-overlay.d.ts +7 -0
  41. package/conversation-overlay.js +2 -0
  42. package/conversation-sources/useConversationSources/useConversationSources.js +31 -24
  43. package/conversation-sources.d.ts +1 -1
  44. package/conversation-transfer.d.ts +2 -1
  45. package/conversation.d.ts +328 -25
  46. package/conversation.js +32 -30
  47. package/file-manager-canvas.d.ts +418 -0
  48. package/file-manager-canvas.js +2 -0
  49. package/file-manager.d.ts +155 -359
  50. package/file-manager.js +25 -24
  51. package/files/attachment-canvas.js +116 -55
  52. package/files/attachment-types.js +14 -13
  53. package/files/dial-file-manager-copy-move.util.js +9 -8
  54. package/files/dial-file-manager-mapping.util.js +2 -1
  55. package/files/dial-file-manager-path.util.js +24 -2
  56. package/files/dial-file-manager.model.js +23 -19
  57. package/files/dial-file-manager.types.js +3 -3
  58. package/files/file-manager-variant.js +1 -1
  59. package/files/resolve-dial-file-api-path.js +11 -12
  60. package/files/useDialFileListing/useDialFileListing.js +140 -127
  61. package/files/useDialFileManager/useDialFileManager.js +139 -135
  62. package/files/useDialFileManagerSections/useDialFileManagerSections.js +155 -0
  63. package/files/useDialFileManagerTabConfig/useDialFileManagerTabConfig.js +20 -19
  64. package/files/useDialFileMutations/useDialFileMutations.js +65 -60
  65. package/files/useDialFileUploadBatch/useDialFileUploadBatch.js +117 -110
  66. package/files/useFileAttachmentPicker/useFileAttachmentPicker.js +48 -0
  67. package/index.d.ts +1281 -136
  68. package/index.js +136 -122
  69. package/mcp-apps/useMcpAppHostAdapter/useMcpAppHostAdapter.js +7 -5
  70. package/mcp-apps/useMcpAppHostContext/useMcpAppHostContext.js +1 -1
  71. package/mcp-apps/useMcpAppTools/useMcpAppTools.js +1 -1
  72. package/mcp-apps/useOpenMcpAppCanvas/useOpenMcpAppCanvas.js +25 -23
  73. package/mcp-apps.d.ts +8 -6
  74. package/oauth/toolset-id.js +5 -3
  75. package/oauth/useToolsetLogin/useToolsetLogin.js +8 -8
  76. package/oauth.d.ts +32 -0
  77. package/oauth.js +9 -9
  78. package/package.json +38 -23
  79. package/scheduled-task/scheduled-task-description.js +81 -0
  80. package/scheduled-task/scheduled-task-preparation.js +24 -0
  81. package/scheduled-task/scheduled-task-trigger.js +74 -71
  82. package/scheduled-task/scheduled-tasks-api-client.js +19 -0
  83. package/scheduled-task/use-scheduled-task-runs.js +194 -0
  84. package/scheduled-task/use-scheduled-tasks.js +93 -0
  85. package/scheduled-tasks.d.ts +197 -3
  86. package/scheduled-tasks.js +7 -2
  87. package/shared/application-schema.js +5 -2
  88. package/shared/cron-day-of-month.js +13 -0
  89. package/skill/skill-archive.js +19 -0
  90. package/skill/skill-types.js +8 -7
  91. package/skill/skill.js +53 -27
  92. package/skill/useSkillArchiveImport/useSkillArchiveImport.js +79 -0
  93. package/skill/useSkillEditorLoad.js +65 -59
  94. package/skill/useSkillEditorSubmit.js +108 -84
  95. package/skill/useSkillFileActions.js +70 -58
  96. package/skill-editor.d.ts +160 -8
  97. package/skill-editor.js +9 -8
  98. package/usage/map-usage-data-to-dashboard.js +66 -0
  99. package/usage/map-user-usage-to-model-limits.js +202 -0
  100. package/usage.d.ts +125 -0
  101. package/usage.js +3 -0
  102. package/usePageFileDrag/usePageFileDrag.js +3 -3
  103. package/utils.d.ts +26 -6
  104. package/utils.js +10 -10
package/conversation.d.ts CHANGED
@@ -15,7 +15,6 @@ import { Message } from '@epam/ai-dial-chat-shared';
15
15
  import { MessageCustomContent } from '@epam/ai-dial-chat-shared';
16
16
  import { MessageRating } from '@epam/ai-dial-chat-shared';
17
17
  import { MutableRefObject } from 'react';
18
- import { OverlayChatMessage } from '@epam/ai-dial-chat-overlay';
19
18
  import { PublishHistoryEntry } from '@epam/ai-dial-publish-panel';
20
19
  import { RateApi } from '@epam/ai-dial-chat-api-client';
21
20
  import { ReactNode } from 'react';
@@ -24,6 +23,7 @@ import { RequestSkill } from '@epam/ai-dial-chat-shared';
24
23
  import { ResponseFormat } from '@epam/ai-dial-chat-shared';
25
24
  import { SendCompletionDtoModeEnum } from '@epam/ai-dial-chat-api-client';
26
25
  import { SetStateAction } from 'react';
26
+ import { Stage } from '@epam/ai-dial-chat-shared';
27
27
  import { StarterOption } from '@epam/ai-dial-chat-shared';
28
28
  import { StatusMessage } from '@epam/ai-dial-chat-shared';
29
29
  import { StreamChunk } from '@epam/ai-dial-chat-shared';
@@ -36,8 +36,47 @@ export declare interface AnnouncementContent {
36
36
  title: string | null;
37
37
  description: string | null;
38
38
  html: string | null;
39
+ /** Entries of the popover the banner opens. */
40
+ items?: readonly AnnouncementListItem[];
39
41
  }
40
42
 
43
+ /** One entry of the announcements popover behind the banner's `+N` pill. */
44
+ export declare interface AnnouncementListItem {
45
+ /** Plain-text heading of the entry. */
46
+ title: string;
47
+ /** Supporting copy of the entry, sanitized before it is rendered. */
48
+ description?: string | null;
49
+ /** Optional call to action shown at the end of the entry. */
50
+ link?: AnnouncementListItemLink | null;
51
+ }
52
+
53
+ /** A link rendered as the call to action of an announcements-popover entry. */
54
+ export declare interface AnnouncementListItemLink {
55
+ /** Visible text of the call to action. */
56
+ label: string;
57
+ /** Absolute `http`/`https` target the call to action opens. */
58
+ href: string;
59
+ }
60
+
61
+ /**
62
+ * Applies a single SSE stream chunk to the message list.
63
+ *
64
+ *
65
+ * Attachments are accumulated: each chunk's attachments are appended to the
66
+ * existing array rather than replacing it.
67
+ *
68
+ * Annotations are merged by `index`: partial `body.title` and `body.quote`
69
+ * strings are concatenated across chunks, matching the same delta-merge
70
+ * semantics used for stages.
71
+ *
72
+ * `state` is overwritten (not merged) by each chunk that carries one,
73
+ * matching the DIAL stateful-app contract.
74
+ *
75
+ * @returns Updated message array, or `null` when the chunk carries no
76
+ * actionable data (empty content, no form_schema, and no attachments).
77
+ */
78
+ export declare const applyChunkToMessages: (messages: Message[], messageIndex: number, chunk: StreamChunk) => Message[] | null;
79
+
41
80
  /** State and controls returned by `useAsyncConfirmDialog`. */
42
81
  export declare interface AsyncConfirmDialogControls<T> {
43
82
  /**
@@ -95,7 +134,7 @@ export declare enum AudioTranscriptionErrorReason {
95
134
  Unavailable = "unavailable",
96
135
  /** The recording exceeds the caller's configured size limit. */
97
136
  TooLarge = "tooLarge",
98
- /** The upstream ASR provider stayed rate-limited or unavailable after retrying. */
137
+ /** Recognition is rate-limited, unavailable, or exhausted short gateway retries. */
99
138
  Busy = "busy",
100
139
  /** Recognition failed for any other reason. */
101
140
  Failed = "failed"
@@ -107,9 +146,18 @@ export declare enum AudioTranscriptionErrorReason {
107
146
  * hidden only while the current announcement produces the same signature, so
108
147
  * editing any part of it brings the banner back with no version counter.
109
148
  *
149
+ * Every piece of content the banner surface renders feeds the signature — the
150
+ * title, the description, and the popover entries behind the pill, which live
151
+ * inside the banner and are hidden along with it. Publishing a new entry in
152
+ * that list therefore invalidates an earlier dismissal on its own, even when
153
+ * the banner line itself is untouched.
154
+ *
110
155
  * A legacy-only announcement returns the raw HTML string — byte-identical to
111
156
  * what shipped before the structured fields existed — so dismissals recorded
112
- * by older builds keep working without a storage migration.
157
+ * by older builds keep working without a storage migration. `items` is left
158
+ * out of the payload entirely when the list is empty for the same reason: a
159
+ * deployment that never configured the popover keeps matching the signatures
160
+ * its users already have stored.
113
161
  */
114
162
  export declare const buildAnnouncementSignature: (content: AnnouncementContent) => string;
115
163
 
@@ -167,6 +215,7 @@ export declare interface ChatStreamApi {
167
215
  stopCompletion: (dto: {
168
216
  generationId: string;
169
217
  path: string;
218
+ content?: string;
170
219
  }) => Promise<void>;
171
220
  }
172
221
 
@@ -249,7 +298,7 @@ export declare interface ConversationStreamOverlayNotifier {
249
298
  }
250
299
 
251
300
  /** The exact `startStream` shape `useConversationStream` returns. */
252
- export declare type ConversationStreamStarter = (conversationPath: string, userContent: string, messageIndex: number, model: string, customContent?: MessageCustomContent, generationId?: string, mode?: SendCompletionDtoModeEnum) => void;
301
+ export declare type ConversationStreamStarter = (conversationPath: string, userContent: string, messageIndex: number, model: string, customContent?: MessageCustomContent, generationId?: string, mode?: SendCompletionDtoModeEnum, options?: StartStreamOptions) => void;
253
302
 
254
303
  /**
255
304
  * Host-owned transport for the DIAL Core completion protocol. Implemented at
@@ -259,10 +308,14 @@ export declare type ConversationStreamStarter = (conversationPath: string, userC
259
308
  export declare interface ConversationStreamTransport {
260
309
  /** Starts a completion; delivers chunks/completion/error through `options`, aborted via `options.signal`. */
261
310
  streamCompletion(path: string, message: string | undefined, model: string, options: StreamCompletionOptions, customContent?: MessageCustomContent, generationId?: string, mode?: SendCompletionDtoModeEnum, messageIndex?: number, clientChannelId?: string): void;
262
- /** Requests the backend stop an active generation. */
311
+ /**
312
+ * Requests the backend stop an active generation. `content` is the answer text shown
313
+ * so far; the backend saves it for a generation whose text it does not hold.
314
+ */
263
315
  stopCompletion(params: {
264
316
  generationId: string;
265
317
  path: string;
318
+ content?: string;
266
319
  }): Promise<void>;
267
320
  /** Opens a stream of resource-update events for `path`, until aborted via `signal`. */
268
321
  watchConversation(path: string, signal: AbortSignal): Promise<ReadableStream<Uint8Array>>;
@@ -299,6 +352,12 @@ export declare interface CreateChatStreamApiDeps {
299
352
  getTimezone?: () => string | undefined;
300
353
  /** `fetch` implementation to issue requests through. Defaults to the global `fetch`. */
301
354
  fetchImpl?: typeof fetch;
355
+ /**
356
+ * How long an open completion stream may go without receiving a byte
357
+ * (keepalive comments included) before it is reported as a
358
+ * {@link StreamInterruptedError}. Defaults to {@link DEFAULT_STREAM_IDLE_TIMEOUT_MS}.
359
+ */
360
+ idleTimeoutMs?: number;
302
361
  }
303
362
 
304
363
  /**
@@ -313,6 +372,11 @@ export declare const createMessagePair: (content: string, customContent?: Messag
313
372
  /** Fallback text of a {@link GenerationConflictError} when no message is supplied. */
314
373
  export declare const DEFAULT_GENERATION_CONFLICT_MESSAGE = "A response is already being generated in this conversation. Wait for it to finish or stop it before sending another message.";
315
374
 
375
+ /** Safe fallback for hosts that do not supply a translated persistence warning. */
376
+ export declare const DEFAULT_GENERATION_PERSISTENCE_ERROR_MESSAGE = "The response could not be saved. It is still shown here, but may be lost if you reload or leave this page. Copy it before continuing.";
377
+
378
+ export declare const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 45000;
379
+
316
380
  /**
317
381
  * Derives the row-action visibility state for a single conversation item.
318
382
  *
@@ -347,6 +411,12 @@ export declare class GenerationConflictError extends Error {
347
411
  constructor(message?: string);
348
412
  }
349
413
 
414
+ /** Identifies a failed terminal save independently of the model's generation outcome. */
415
+ export declare class GenerationPersistenceError extends Error {
416
+ static readonly type = "conversation_save_failed";
417
+ constructor();
418
+ }
419
+
350
420
  /**
351
421
  * Strips the leading bucket segment from a conversation id and decodes any
352
422
  * already-percent-encoded remainder back to raw, so callers that re-encode
@@ -359,6 +429,21 @@ export declare const getConversationPath: (conversationId: string) => string;
359
429
  */
360
430
  export declare const getConversationSource: (item: Pick<ConversationListItemDto, "sharedWithMe" | "publishedWithMe">) => FilterTab;
361
431
 
432
+ /**
433
+ * Returns the tool values the conversation's last message sets through its
434
+ * `form_schema`, restricted to `toolIds`, plus a key identifying that exact
435
+ * application. `undefined` when the last message is not an assistant message
436
+ * or sets no known tool.
437
+ *
438
+ * Streamed chunks and reloads re-create an identical `form_schema`; comparing
439
+ * keys rather than object identity applies an app's value once and leaves a
440
+ * later user toggle alone until the app sends a different value.
441
+ */
442
+ export declare const getFormSchemaToolSyncKey: (conversationId: string, messages: Message[], toolIds: readonly string[]) => {
443
+ key: string;
444
+ values: Record<string, boolean>;
445
+ } | undefined;
446
+
362
447
  /**
363
448
  * Returns the deployment the conversation was last running on: scanning
364
449
  * backwards, the `new_deployment_id` of a `model_changed` status message or
@@ -369,7 +454,7 @@ export declare const getConversationSource: (item: Pick<ConversationListItemDto,
369
454
  * an edit truncates past one: the marker is appended at the end of the
370
455
  * timeline, so truncating at an earlier message drops it, and the model the
371
456
  * user picked reverted on the next page load even though the answer had been
372
- * regenerated on it (issue #8712). The assistant message the backend writes
457
+ * regenerated on it ([#8712](https://github.com/epam/ai-dial-chat/issues/8712)). The assistant message the backend writes
373
458
  * carries the deployment that produced it, which survives that truncation
374
459
  * because it *is* the regenerated message.
375
460
  */
@@ -382,6 +467,15 @@ export declare const getLastDeploymentId: (messages: Message[]) => string | null
382
467
  */
383
468
  export declare const getLastUserMessageToolConfiguration: (messages: Message[]) => Record<string, unknown> | undefined;
384
469
 
470
+ /**
471
+ * Returns the tool configuration a (re-)loaded conversation should show: the
472
+ * last user message's `configuration_value`, overlaid in order by the
473
+ * `form_schema` values of the assistant messages after it. An app that turned
474
+ * a toggle off in its final response must not see it re-armed on reload just
475
+ * because the user message that started the run had it on.
476
+ */
477
+ export declare const getLatestToolConfiguration: (messages: Message[]) => Record<string, unknown> | undefined;
478
+
385
479
  /**
386
480
  * Extracts the deployment/model ID from a DIAL Core conversation ID.
387
481
  *
@@ -465,6 +559,15 @@ export declare const getStarterSubmitText: (starter: StarterOption, description?
465
559
  */
466
560
  export declare const getTimeOfDayGreeting: (hour: number, translations: GreetingTranslations, firstName?: string) => string;
467
561
 
562
+ /**
563
+ * Returns the boolean values an assistant message's `form_schema` sets, keyed
564
+ * by property name, or `undefined` when no property resolves to a boolean.
565
+ * Lets a DIAL app switch a tools-menu toggle (e.g. `deep_research`) per
566
+ * message — on while a run is in progress, off once its result is delivered.
567
+ * Not filtered by tool id: `restoreToolConfiguration` ignores unknown ids.
568
+ */
569
+ export declare const getToolConfigurationFromFormSchema: (formSchema: DeploymentConfigurationSchema | undefined) => Record<string, boolean> | undefined;
570
+
468
571
  /** Pre-translated greeting phrase strings for each time-of-day period. */
469
572
  export declare interface GreetingTranslations {
470
573
  morningWithName: string;
@@ -498,11 +601,12 @@ export declare const hasStructuredAnnouncement: ({ title, description, }: Announ
498
601
  export declare const isAnswerIncomplete: (answer: Message | undefined) => boolean;
499
602
 
500
603
  /**
501
- * True when the conversation's last message is an unresolved assistant
502
- * placeholder: the backend only persists a conversation at generation start
503
- * (empty placeholder) and at generation end (final content, or a partial
504
- * flagged `streamErrorMessage`/`wasStoppedByUser`), so this shape means a
505
- * generation was still active elsewhere when the conversation was loaded.
604
+ * True when the conversation has a pending background message, or its last
605
+ * message is an unresolved assistant placeholder: the backend only persists a
606
+ * conversation at generation start (empty placeholder) and at generation end
607
+ * (final content, or a partial flagged `streamErrorMessage`/`wasStoppedByUser`).
608
+ * This can mean generation is still active elsewhere, or that its terminal save
609
+ * failed.
506
610
  */
507
611
  export declare const isAwaitingGenerationResume: (conversation: Conversation) => boolean;
508
612
 
@@ -544,6 +648,32 @@ declare interface LocalModeValues {
544
648
  temperature: number;
545
649
  }
546
650
 
651
+ /**
652
+ * Returns the normalized stages of a complete raw stage array or a
653
+ * message-like payload (reading `custom_content.stages`, falling back to
654
+ * `customContent.stages`), or `undefined` when there are none. An entry
655
+ * without an `index` takes its array position — the identity a complete
656
+ * non-streaming array's `parent_stage_index` refers to — while explicit
657
+ * (possibly sparse) indexes are kept. Not for partial stream deltas.
658
+ */
659
+ export declare const mapStages: (source: RawStage[] | RawStageSource | null | undefined) => Stage[] | undefined;
660
+
661
+ /**
662
+ * Merges incoming stage deltas into an existing stage list, keyed by `index`.
663
+ *
664
+ * Partial `name` and `content` strings are concatenated across chunks;
665
+ * attachments are merged by their own `index` (concatenating partial `title`
666
+ * and `data`); every other field on the incoming delta overwrites the
667
+ * accumulated one. A brand-new stage whose first chunk carries `name: null`
668
+ * is normalized to `''`.
669
+ *
670
+ * Exported for hosts that keep a flattened `Stage[]` on the message instead
671
+ * of `Message.custom_content.stages` and therefore cannot reuse
672
+ * {@link applyChunkToMessages}. Prefer `useConversationStream` when the host
673
+ * can delegate the whole stream loop.
674
+ */
675
+ export declare const mergeStages: (existing: Stage[], incoming: Stage[]) => Stage[];
676
+
547
677
  /** True when `message` is an assistant message carrying at least one stage. */
548
678
  export declare const messageHasStages: (message: Message) => boolean;
549
679
 
@@ -553,6 +683,20 @@ export declare interface MessagePair {
553
683
  assistantMessage: Message;
554
684
  }
555
685
 
686
+ /** A stable snapshot of one eligible native text selection. */
687
+ export declare interface MessageSelectionReplySnapshot {
688
+ /** Scope that owned the selection when it was captured. */
689
+ conversationId: string;
690
+ /** Message text root containing the captured range. */
691
+ body: HTMLDivElement;
692
+ /** Captured native range. */
693
+ range: Range;
694
+ /** Native selected text preserved for the generated file. */
695
+ text: string;
696
+ /** Visible fragment of the selected range. */
697
+ rect: DOMRect;
698
+ }
699
+
556
700
  /**
557
701
  * Normalises a stored response-format string to the current enum. Legacy data
558
702
  * may contain `'Markdown'` or `'PlainText'` (capital-first) instead of the
@@ -577,6 +721,68 @@ export declare interface QuickAppConversationStartersSettings {
577
721
  isChatMessageInputDisabled: boolean;
578
722
  }
579
723
 
724
+ /**
725
+ * One stage as it arrives from the REST API or the SSE stream, before
726
+ * normalization. Structurally satisfied by the generated `StageDto` and by a
727
+ * raw stream delta, both of which omit `index`/`name`/`status` on the chunk
728
+ * that opens a stage.
729
+ */
730
+ export declare interface RawStage {
731
+ /** Ordering key. Defaults to `0` when absent. */
732
+ index?: number | null;
733
+ /** Stage title. `null` on the chunk that opens the stage. */
734
+ name?: string | null;
735
+ /** Terminal state as a raw wire string; anything other than `'completed'`/`'failed'` means still running. */
736
+ status?: string | null;
737
+ /** Additional stage text. */
738
+ content?: string | null;
739
+ /** Short source/category label shown beside the stage name. */
740
+ tag?: string | null;
741
+ /** Files produced or referenced by this stage. */
742
+ attachments?: RawStageAttachment[] | null;
743
+ /**
744
+ * `index` of the parent stage (its array position in a complete unindexed
745
+ * array). Nullish means top level; `0` is a valid parent.
746
+ */
747
+ parent_stage_index?: number | null;
748
+ }
749
+
750
+ /**
751
+ * One stage attachment as it arrives from the REST API or the SSE stream,
752
+ * before normalization: every field is optional and may be `null`.
753
+ */
754
+ export declare interface RawStageAttachment {
755
+ /** Zero-based position in the attachment list. */
756
+ index?: number | null;
757
+ /** MIME type of the attachment content. */
758
+ type?: string | null;
759
+ /** Display name shown in the UI. */
760
+ title?: string | null;
761
+ /** Inline base-64 encoded content. */
762
+ data?: string | null;
763
+ /** Remote URL pointing to the attachment content. */
764
+ url?: string | null;
765
+ /** MIME type of the referenced resource. */
766
+ reference_type?: string | null;
767
+ /** URL of an alternate reference resource. */
768
+ reference_url?: string | null;
769
+ }
770
+
771
+ /**
772
+ * Message-like payload carrying stages under either the wire's snake_case
773
+ * `custom_content` or a host's camelCased `customContent`.
774
+ */
775
+ export declare interface RawStageSource {
776
+ /** Custom content as the DIAL wire format spells it. */
777
+ custom_content?: {
778
+ stages?: RawStage[] | null;
779
+ } | null;
780
+ /** Custom content as a camelCasing host spells it. */
781
+ customContent?: {
782
+ stages?: RawStage[] | null;
783
+ } | null;
784
+ }
785
+
580
786
  /** State of one resource's recipient-count lookup. */
581
787
  declare interface RecipientsCountEntry {
582
788
  /** Where the lookup for this resource currently stands. */
@@ -625,6 +831,18 @@ export declare const shouldRerunGenerationOnEdit: (messages: Message[], messageI
625
831
  /** True when the first user/assistant exchange is complete and LLM naming may still run. */
626
832
  export declare const shouldWatchForDisplayNameUpdate: (conversation: Conversation) => boolean;
627
833
 
834
+ /** Per-start options of {@link UseConversationStreamResult.startStream}. */
835
+ export declare interface StartStreamOptions {
836
+ /**
837
+ * Treats a `GenerationConflictError` as "this turn is already being
838
+ * generated" — e.g. a page reloaded before that generation saved its start
839
+ * state — and joins the running generation instead of showing the conflict
840
+ * message, which remains the fallback. Only for a start that sends no new
841
+ * user text; a send the user typed must keep reporting the conflict.
842
+ */
843
+ resumeOnConflict?: boolean;
844
+ }
845
+
628
846
  /** Options accepted by {@link ConversationStreamTransport.streamCompletion}. */
629
847
  export declare interface StreamCompletionOptions {
630
848
  onChunk: (chunk: StreamChunk) => void;
@@ -633,8 +851,36 @@ export declare interface StreamCompletionOptions {
633
851
  signal: AbortSignal;
634
852
  }
635
853
 
636
- /** Maps chat messages to the DIAL Chat Overlay protocol's message shape. */
637
- export declare const toOverlayMessages: (messages: Message[]) => OverlayChatMessage[];
854
+ /**
855
+ * Reported through `onError` when the network connection carrying a
856
+ * completion stream is lost (a rejected `fetch`, or a read that fails after a
857
+ * 2xx response) or goes silent past the idle timeout — what a laptop sleep or
858
+ * a phone lock mid-generation produces. The backend-owned generation may
859
+ * still be running, so the caller can recover it rather than treat the
860
+ * response as failed. `cause` holds the original error, when there is one.
861
+ */
862
+ export declare class StreamInterruptedError extends Error {
863
+ constructor(cause?: unknown);
864
+ }
865
+
866
+ /**
867
+ * Reported through `onError` when DIAL Core itself signals a failure with an
868
+ * in-band `{ error: { message } }` SSE chunk. Its `message` is upstream text
869
+ * intended for the user, unlike a transport failure (failed `fetch`, non-OK
870
+ * status, broken stream), whose message is technical detail. A custom
871
+ * transport raises this for any user-facing upstream error text.
872
+ */
873
+ export declare class StreamUpstreamError extends Error {
874
+ constructor(message: string);
875
+ }
876
+
877
+ /**
878
+ * Returns a renderable `Stage` for one raw payload: `index` defaults to `0`,
879
+ * `name` to `''`, an unrecognized `status` to `null` (still running), and
880
+ * `content`/`tag`/`attachments`/`parent_stage_index` are passed through when
881
+ * present (a parent of `0` included).
882
+ */
883
+ export declare const toStage: (stage: RawStage) => Stage;
638
884
 
639
885
  /** Request shape the host's selected-deployment recognition call accepts. */
640
886
  export declare interface TranscribeWithDeploymentParams {
@@ -652,7 +898,8 @@ export declare interface TranscribeWithDeploymentParams {
652
898
  * 1. If the active conversation is not present in the list, requests a
653
899
  * refresh. The list and refresh callback are intentionally excluded from
654
900
  * the dependency array to avoid a refresh-loop on every list update.
655
- * 2. Marks the active conversation as viewed whenever it or the list changes.
901
+ * 2. Marks the active conversation as viewed when its matching identity becomes
902
+ * available. List refreshes and persistence rollback do not retry the write.
656
903
  */
657
904
  export declare const useActiveConversationSync: ({ activeConversationId, items, refreshConversations, markConversationViewed, conversationIdsMatch, toPanelConversationId, }: UseActiveConversationSyncParams) => string | undefined;
658
905
 
@@ -699,8 +946,8 @@ export declare const useAttachmentUpload: ({ filesApi, bucket, onNetworkError, d
699
946
 
700
947
  /** Parameters for {@link useAttachmentUpload}. */
701
948
  export declare interface UseAttachmentUploadParams {
702
- /** Already-configured generated-client instance used to upload the file. */
703
- filesApi: Pick<FilesApi, 'uploadFile'>;
949
+ /** Already-configured client; optional listing skips stored names after a conflict. */
950
+ filesApi: Pick<FilesApi, 'uploadFile'> & Partial<Pick<FilesApi, 'listFiles'>>;
704
951
  /** DIAL Core bucket the file is uploaded into. */
705
952
  bucket: string | undefined;
706
953
  /** Called with batched filenames after a burst of network-error upload failures. */
@@ -853,10 +1100,14 @@ export declare interface UseConversationLookupMapsParams {
853
1100
  * Returns a memoised array whose shape is compatible with the conversation
854
1101
  * panel's item contract. All app-specific concerns (icon URL resolution,
855
1102
  * route generation, id normalisation) are injected via resolver callbacks.
1103
+ *
1104
+ * While every input except `items` is unchanged, a DTO that is referentially
1105
+ * the same as in the previous render maps to the same item object, so a list
1106
+ * change (or a navigation that re-derives the list) re-renders only the rows
1107
+ * whose DTO actually changed.
856
1108
  */
857
- export declare const useConversationPanelItems: ({ items, deployments, isDeploymentsLoading, toPanelConversationId, resolveIconUrl, resolveIconTooltip, resolveHref, resolveTaskBadge, }: UseConversationPanelItemsParams) => {
858
- showTaskBadge?: boolean | undefined;
859
- taskBadgeLabel?: string | undefined;
1109
+ export declare const useConversationPanelItems: ({ items, deployments, isDeploymentsLoading, toPanelConversationId, resolveIconUrl, resolveIconTooltip, resolveHref, resolveTaskPresentation, }: UseConversationPanelItemsParams) => {
1110
+ leadingIcon?: ReactNode;
860
1111
  isUnread?: boolean | undefined;
861
1112
  id: string;
862
1113
  title: string;
@@ -892,11 +1143,12 @@ export declare interface UseConversationPanelItemsResolvers {
892
1143
  /** Resolves the href to navigate to when the conversation row is clicked. */
893
1144
  resolveHref: (panelConversationId: string) => string;
894
1145
  /**
895
- * Returns badge metadata for a scheduled-task conversation, or `undefined`
896
- * when the item should not show a task badge.
1146
+ * Returns the row presentation for a scheduled-task conversation — a
1147
+ * host-rendered leading icon that replaces the deployment avatar, and the
1148
+ * unread flag — or `undefined` for an ordinary conversation.
897
1149
  */
898
- resolveTaskBadge?: (item: ConversationListItemDto) => {
899
- label: string;
1150
+ resolveTaskPresentation?: (item: ConversationListItemDto) => {
1151
+ leadingIcon?: ReactNode;
900
1152
  isUnread: boolean;
901
1153
  } | undefined;
902
1154
  }
@@ -909,7 +1161,7 @@ export declare interface UseConversationPanelItemsResolvers {
909
1161
  * `transport`/`generation`/`channel`/`overlay` capabilities rather than any
910
1162
  * app context or `server-api` import.
911
1163
  */
912
- export declare const useConversationStream: ({ conversationId, state: { setConversation, conversationRef }, transport, generation: { startGeneration, completeGeneration }, channel, overlay, onStopError, generationConflictMessage, }: UseConversationStreamParams) => UseConversationStreamResult;
1164
+ export declare const useConversationStream: ({ conversationId, state: { setConversation, conversationRef }, transport, generation: { startGeneration, completeGeneration }, channel, overlay, onStopError, generationConflictMessage, generationPersistenceErrorMessage, onStreamError, batchChunksPerFrame, }: UseConversationStreamParams) => UseConversationStreamResult;
913
1165
 
914
1166
  /** Parameters for {@link useConversationStream}. */
915
1167
  export declare interface UseConversationStreamParams {
@@ -927,17 +1179,39 @@ export declare interface UseConversationStreamParams {
927
1179
  * {@link DEFAULT_GENERATION_CONFLICT_MESSAGE}.
928
1180
  */
929
1181
  generationConflictMessage?: string;
1182
+ /** Host-translated warning shown when the received answer could not be saved. */
1183
+ generationPersistenceErrorMessage?: string;
1184
+ /**
1185
+ * Receives the original error of every failed stream. The hook shows only
1186
+ * host-supplied or upstream-supplied text on the message bubble and hides
1187
+ * transport detail (e.g. `Failed to fetch`), so this is where the host can
1188
+ * still log or report the raw error.
1189
+ */
1190
+ onStreamError?: (error: Error) => void;
1191
+ /**
1192
+ * Coalesces the displayed chunk updates into one `setConversation` per
1193
+ * animation frame. Chunks still reach the per-path buffer immediately, and
1194
+ * any pending update is flushed before completion, error, stop, or a
1195
+ * superseding generation. Defaults to `false` (one update per chunk).
1196
+ */
1197
+ batchChunksPerFrame?: boolean;
930
1198
  }
931
1199
 
932
1200
  /** Return value of {@link useConversationStream}. */
933
1201
  export declare interface UseConversationStreamResult {
934
- startStream: (conversationId: string, userContent: string, messageIndex: number, model: string, customContent?: MessageCustomContent, generationId?: string, mode?: SendCompletionDtoModeEnum) => void;
1202
+ startStream: (conversationId: string, userContent: string, messageIndex: number, model: string, customContent?: MessageCustomContent, generationId?: string, mode?: SendCompletionDtoModeEnum, options?: StartStreamOptions) => void;
935
1203
  handleStop: () => void;
936
1204
  resumeIfAwaitingGeneration: (currentConversationId: string, conversation: Conversation) => void;
937
1205
  /** Restores the accumulated live assistant message when its conversation is loaded again before completion. */
938
1206
  restoreBufferedGeneration: (currentConversationId: string, conversation: Conversation) => Conversation;
939
1207
  isStreaming: boolean;
940
1208
  canStopStreaming: boolean;
1209
+ /** Whether the displayed conversation's terminal read failed. */
1210
+ hasConversationReloadError: boolean;
1211
+ /** Whether a retry of that read is in flight. */
1212
+ isReloadingConversation: boolean;
1213
+ /** Retries the failed read without saving or regenerating the answer. */
1214
+ retryConversationReload: () => Promise<void>;
941
1215
  }
942
1216
 
943
1217
  /**
@@ -973,6 +1247,35 @@ export declare interface UseImportFilePickerResult {
973
1247
  handleFileChange: (event: ChangeEvent<HTMLInputElement>) => void;
974
1248
  }
975
1249
 
1250
+ /**
1251
+ * Captures eligible message text and creates Reply files for an existing composer
1252
+ * attachment flow without acquiring host deployment, upload or localization knowledge.
1253
+ */
1254
+ export declare const useMessageSelectionReply: ({ conversationId, enabled, droppedFiles, onDroppedFilesConsumed, }: UseMessageSelectionReplyParams) => {
1255
+ contentRef: (node: HTMLDivElement | null) => (() => void) | undefined;
1256
+ actionRef: RefObject<HTMLDivElement | null>;
1257
+ selection: MessageSelectionReplySnapshot | null;
1258
+ onReply: () => void;
1259
+ dismiss: () => void;
1260
+ pendingFiles: File[];
1261
+ onFilesConsumed: () => void;
1262
+ focusRequestId: number | undefined;
1263
+ onAttachmentsChange: (attachments: Attachment[]) => void;
1264
+ addedRevision: number;
1265
+ };
1266
+
1267
+ /** Parameters accepted by {@link useMessageSelectionReply}. */
1268
+ export declare interface UseMessageSelectionReplyParams {
1269
+ /** Identifier used to discard selection and queued files after a scope change. */
1270
+ conversationId: string;
1271
+ /** Whether the host currently permits a Reply attachment. */
1272
+ enabled: boolean;
1273
+ /** Files from the host's ordinary page-drop queue. */
1274
+ droppedFiles: File[];
1275
+ /** Acknowledges the captured page-drop batch after the composer accepts it. */
1276
+ onDroppedFilesConsumed: () => void;
1277
+ }
1278
+
976
1279
  /**
977
1280
  * Derives the tools submenu from the active deployment's configuration schema:
978
1281
  * every boolean property becomes a toggle. Manages toggle state locally, resets
package/conversation.js CHANGED
@@ -1,31 +1,33 @@
1
1
  import { buildAnnouncementSignature as e, hasAnnouncementContent as t, hasStructuredAnnouncement as n, sanitizeAnnouncementHtml as r, sanitizeAnnouncementMessageHtml as i } from "./conversation/announcement-message.js";
2
- import { DEFAULT_GENERATION_CONFLICT_MESSAGE as a, GenerationConflictError as o, createChatStreamApi as s } from "./conversation/create-chat-stream-api.js";
3
- import { shouldWatchForDisplayNameUpdate as c } from "./conversation/display-name-watch.js";
4
- import { formatAppVersion as l, sanitizeFooterHtml as u } from "./conversation/footer-message.js";
5
- import { getModelIdFromConversationId as d } from "./conversation/get-model-id-from-conversation-id.js";
6
- import { getTimeOfDayGreeting as f } from "./conversation/greeting.js";
7
- import { createDeploymentChangedMessage as p } from "./conversation/message-factory.js";
8
- import { getLastDeploymentId as m, getLastUserMessageToolConfiguration as h, isMessageStreaming as g, messageHasStages as _, normalizeResponseFormat as v } from "./conversation/message-utils.js";
9
- import { toOverlayMessages as y } from "./conversation/overlay-messages.js";
10
- import { getQuickAppConversationStarters as b } from "./conversation/quick-app-conversation-starters.js";
11
- import { getStarterPopulateText as x, getStartersFromSchema as S } from "./conversation/starter-option.js";
12
- import { deriveConversationRowActionState as C } from "./conversation/deriveConversationRowActionState/deriveConversationRowActionState.js";
13
- import { useActiveConversationSync as w } from "./conversation/useActiveConversationSync/useActiveConversationSync.js";
14
- import { useAsyncConfirmDialog as T } from "./conversation/useAsyncConfirmDialog/useAsyncConfirmDialog.js";
15
- import { useConversationLookupMaps as E } from "./conversation/useConversationLookupMaps/useConversationLookupMaps.js";
16
- import { getConversationSource as D, useConversationPanelItems as O } from "./conversation/useConversationPanelItems/useConversationPanelItems.js";
17
- import { useImportFilePicker as k } from "./conversation/useImportFilePicker/useImportFilePicker.js";
18
- import { useAttachmentUpload as A } from "./conversation/useAttachmentUpload/useAttachmentUpload.js";
19
- import { AudioTranscriptionError as j, AudioTranscriptionErrorReason as M } from "./conversation/useTranscribeAudio/audio-transcription-error.js";
20
- import { useTranscribeAudio as N } from "./conversation/useTranscribeAudio/useTranscribeAudio.js";
21
- import { attachmentToDto as P, attachmentsToDtos as F } from "./conversation/useConversationHandlers/attachment-to-dto.js";
22
- import { createMessagePair as I } from "./conversation/useConversationHandlers/message-factory.js";
23
- import { hasActiveToolConfig as L, isAnswerIncomplete as R, isMessageChanged as z, shouldRerunGenerationOnEdit as B } from "./conversation/useConversationHandlers/message-utils.js";
24
- import { getStarterConversationText as V, getStarterDisplayText as H, getStarterSubmitText as U } from "./conversation/useConversationHandlers/starter-option.js";
25
- import { getConversationPath as W } from "./conversation/useConversationStream/conversation-path.js";
26
- import { useConversationHandlers as G } from "./conversation/useConversationHandlers/useConversationHandlers.js";
27
- import { isAwaitingGenerationResume as K } from "./conversation/useConversationStream/generation-resume.js";
28
- import { useConversationStream as q } from "./conversation/useConversationStream/useConversationStream.js";
29
- import { useChatSettingsFormConfig as J } from "./useChatSettingsFormConfig/useChatSettingsFormConfig.js";
30
- import { useToolsMenu as Y } from "./useToolsMenu/useToolsMenu.js";
31
- export { j as AudioTranscriptionError, M as AudioTranscriptionErrorReason, a as DEFAULT_GENERATION_CONFLICT_MESSAGE, o as GenerationConflictError, P as attachmentToDto, F as attachmentsToDtos, e as buildAnnouncementSignature, s as createChatStreamApi, p as createDeploymentChangedMessage, I as createMessagePair, C as deriveConversationRowActionState, l as formatAppVersion, W as getConversationPath, D as getConversationSource, m as getLastDeploymentId, h as getLastUserMessageToolConfiguration, d as getModelIdFromConversationId, b as getQuickAppConversationStarters, V as getStarterConversationText, H as getStarterDisplayText, x as getStarterPopulateText, U as getStarterSubmitText, S as getStartersFromSchema, f as getTimeOfDayGreeting, L as hasActiveToolConfig, t as hasAnnouncementContent, n as hasStructuredAnnouncement, R as isAnswerIncomplete, K as isAwaitingGenerationResume, z as isMessageChanged, g as isMessageStreaming, _ as messageHasStages, v as normalizeResponseFormat, r as sanitizeAnnouncementHtml, i as sanitizeAnnouncementMessageHtml, u as sanitizeFooterHtml, B as shouldRerunGenerationOnEdit, c as shouldWatchForDisplayNameUpdate, y as toOverlayMessages, w as useActiveConversationSync, T as useAsyncConfirmDialog, A as useAttachmentUpload, J as useChatSettingsFormConfig, G as useConversationHandlers, E as useConversationLookupMaps, O as useConversationPanelItems, q as useConversationStream, k as useImportFilePicker, Y as useToolsMenu, N as useTranscribeAudio };
2
+ import { DEFAULT_GENERATION_CONFLICT_MESSAGE as a, DEFAULT_GENERATION_PERSISTENCE_ERROR_MESSAGE as o, DEFAULT_STREAM_IDLE_TIMEOUT_MS as s, GenerationConflictError as c, GenerationPersistenceError as l, StreamInterruptedError as u, StreamUpstreamError as d, createChatStreamApi as f } from "./conversation/create-chat-stream-api.js";
3
+ import { shouldWatchForDisplayNameUpdate as p } from "./conversation/display-name-watch.js";
4
+ import { formatAppVersion as m, sanitizeFooterHtml as h } from "./conversation/footer-message.js";
5
+ import { getModelIdFromConversationId as g } from "./conversation/get-model-id-from-conversation-id.js";
6
+ import { getTimeOfDayGreeting as _ } from "./conversation/greeting.js";
7
+ import { createDeploymentChangedMessage as v } from "./conversation/message-factory.js";
8
+ import { getFormSchemaToolSyncKey as y, getLastDeploymentId as b, getLastUserMessageToolConfiguration as x, getLatestToolConfiguration as S, getToolConfigurationFromFormSchema as C, isMessageStreaming as w, messageHasStages as T, normalizeResponseFormat as E } from "./conversation/message-utils.js";
9
+ import { getQuickAppConversationStarters as D } from "./conversation/quick-app-conversation-starters.js";
10
+ import { mapStages as O, toStage as k } from "./conversation/stage.js";
11
+ import { getStarterPopulateText as A, getStartersFromSchema as j } from "./conversation/starter-option.js";
12
+ import { deriveConversationRowActionState as M } from "./conversation/deriveConversationRowActionState/deriveConversationRowActionState.js";
13
+ import { useActiveConversationSync as N } from "./conversation/useActiveConversationSync/useActiveConversationSync.js";
14
+ import { useAsyncConfirmDialog as P } from "./conversation/useAsyncConfirmDialog/useAsyncConfirmDialog.js";
15
+ import { useConversationLookupMaps as F } from "./conversation/useConversationLookupMaps/useConversationLookupMaps.js";
16
+ import { getConversationSource as I, useConversationPanelItems as L } from "./conversation/useConversationPanelItems/useConversationPanelItems.js";
17
+ import { useImportFilePicker as R } from "./conversation/useImportFilePicker/useImportFilePicker.js";
18
+ import { useMessageSelectionReply as z } from "./conversation/useMessageSelectionReply/useMessageSelectionReply.js";
19
+ import { useAttachmentUpload as B } from "./conversation/useAttachmentUpload/useAttachmentUpload.js";
20
+ import { AudioTranscriptionError as V, AudioTranscriptionErrorReason as H } from "./conversation/useTranscribeAudio/audio-transcription-error.js";
21
+ import { useTranscribeAudio as U } from "./conversation/useTranscribeAudio/useTranscribeAudio.js";
22
+ import { attachmentToDto as W, attachmentsToDtos as G } from "./conversation/useConversationHandlers/attachment-to-dto.js";
23
+ import { createMessagePair as K } from "./conversation/useConversationHandlers/message-factory.js";
24
+ import { hasActiveToolConfig as q, isAnswerIncomplete as J, isMessageChanged as Y, shouldRerunGenerationOnEdit as X } from "./conversation/useConversationHandlers/message-utils.js";
25
+ import { getStarterConversationText as Z, getStarterDisplayText as Q, getStarterSubmitText as $ } from "./conversation/useConversationHandlers/starter-option.js";
26
+ import { getConversationPath as ee } from "./conversation/useConversationStream/conversation-path.js";
27
+ import { useConversationHandlers as te } from "./conversation/useConversationHandlers/useConversationHandlers.js";
28
+ import { applyChunkToMessages as ne, mergeStages as re } from "./conversation/useConversationStream/apply-chunk.js";
29
+ import { isAwaitingGenerationResume as ie } from "./conversation/useConversationStream/generation-resume.js";
30
+ import { useConversationStream as ae } from "./conversation/useConversationStream/useConversationStream.js";
31
+ import { useChatSettingsFormConfig as oe } from "./useChatSettingsFormConfig/useChatSettingsFormConfig.js";
32
+ import { useToolsMenu as se } from "./useToolsMenu/useToolsMenu.js";
33
+ export { V as AudioTranscriptionError, H as AudioTranscriptionErrorReason, a as DEFAULT_GENERATION_CONFLICT_MESSAGE, o as DEFAULT_GENERATION_PERSISTENCE_ERROR_MESSAGE, s as DEFAULT_STREAM_IDLE_TIMEOUT_MS, c as GenerationConflictError, l as GenerationPersistenceError, u as StreamInterruptedError, d as StreamUpstreamError, ne as applyChunkToMessages, W as attachmentToDto, G as attachmentsToDtos, e as buildAnnouncementSignature, f as createChatStreamApi, v as createDeploymentChangedMessage, K as createMessagePair, M as deriveConversationRowActionState, m as formatAppVersion, ee as getConversationPath, I as getConversationSource, y as getFormSchemaToolSyncKey, b as getLastDeploymentId, x as getLastUserMessageToolConfiguration, S as getLatestToolConfiguration, g as getModelIdFromConversationId, D as getQuickAppConversationStarters, Z as getStarterConversationText, Q as getStarterDisplayText, A as getStarterPopulateText, $ as getStarterSubmitText, j as getStartersFromSchema, _ as getTimeOfDayGreeting, C as getToolConfigurationFromFormSchema, q as hasActiveToolConfig, t as hasAnnouncementContent, n as hasStructuredAnnouncement, J as isAnswerIncomplete, ie as isAwaitingGenerationResume, Y as isMessageChanged, w as isMessageStreaming, O as mapStages, re as mergeStages, T as messageHasStages, E as normalizeResponseFormat, r as sanitizeAnnouncementHtml, i as sanitizeAnnouncementMessageHtml, h as sanitizeFooterHtml, X as shouldRerunGenerationOnEdit, p as shouldWatchForDisplayNameUpdate, k as toStage, N as useActiveConversationSync, P as useAsyncConfirmDialog, B as useAttachmentUpload, oe as useChatSettingsFormConfig, te as useConversationHandlers, F as useConversationLookupMaps, L as useConversationPanelItems, ae as useConversationStream, R as useImportFilePicker, z as useMessageSelectionReply, se as useToolsMenu, U as useTranscribeAudio };