@epam/ai-dial-chat-hooks 1.1.2 → 1.2.0-dev.101

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 (44) hide show
  1. package/attachment/useAttachmentValidation/useAttachmentValidation.js +26 -19
  2. package/attachments.d.ts +10 -4
  3. package/catalog/map-skill-to-catalog-item.js +48 -48
  4. package/catalog/publish.js +2 -1
  5. package/catalog/useApplicationCredentials/useApplicationCredentials.js +39 -0
  6. package/catalog.d.ts +22 -0
  7. package/catalog.js +6 -5
  8. package/conversation/conversation-transfer/queue.js +8 -5
  9. package/conversation/stage.js +23 -0
  10. package/conversation/useConversationImport/useConversationImport.js +1 -1
  11. package/conversation/useConversationScroll/useConversationScroll.js +68 -64
  12. package/conversation/useConversationStream/apply-chunk.js +1 -1
  13. package/conversation-sources/useConversationSources/useConversationSources.js +24 -31
  14. package/conversation-sources.d.ts +1 -1
  15. package/conversation.d.ts +107 -0
  16. package/conversation.js +23 -21
  17. package/file-manager.d.ts +71 -5
  18. package/file-manager.js +3 -2
  19. package/files/attachment-types.js +14 -13
  20. package/files/useDialFileManagerTabConfig/useDialFileManagerTabConfig.js +1 -5
  21. package/files/useFileAttachmentPicker/useFileAttachmentPicker.js +43 -0
  22. package/index.d.ts +614 -16
  23. package/index.js +123 -111
  24. package/mcp-apps/useMcpAppHostAdapter/useMcpAppHostAdapter.js +7 -5
  25. package/mcp-apps/useMcpAppHostContext/useMcpAppHostContext.js +1 -1
  26. package/mcp-apps/useOpenMcpAppCanvas/useOpenMcpAppCanvas.js +25 -23
  27. package/mcp-apps.d.ts +8 -6
  28. package/package.json +26 -17
  29. package/scheduled-task/scheduled-task-description.js +77 -0
  30. package/scheduled-task/scheduled-task-preparation.js +24 -0
  31. package/scheduled-task/scheduled-tasks-api-client.js +19 -0
  32. package/scheduled-task/use-scheduled-task-runs.js +82 -0
  33. package/scheduled-task/use-scheduled-tasks.js +93 -0
  34. package/scheduled-tasks.d.ts +178 -0
  35. package/scheduled-tasks.js +7 -2
  36. package/skill/skill.js +10 -7
  37. package/skill/useSkillArchiveImport/useSkillArchiveImport.js +75 -0
  38. package/skill/useSkillEditorSubmit.js +83 -71
  39. package/skill-editor.d.ts +103 -0
  40. package/skill-editor.js +9 -8
  41. package/usage/map-usage-data-to-dashboard.js +66 -0
  42. package/usage/map-user-usage-to-model-limits.js +160 -0
  43. package/usage.d.ts +120 -0
  44. package/usage.js +3 -0
@@ -1,42 +1,35 @@
1
1
  import { MessageRole as e, messageAttachmentToDisplayAttachment as t } from "@epam/ai-dial-chat-shared";
2
- import { getAnnotationPdfPage as n, isReferenceOnlyAttachment as r, parsePdfPageReference as i, resolveMessageAnnotations as a } from "@epam/ai-dial-quotations";
3
- import { useMemo as o } from "react";
2
+ import { isReferenceOnlyAttachment as n, resolveMessageAnnotations as r } from "@epam/ai-dial-quotations";
3
+ import { useMemo as i } from "react";
4
4
  //#region src/conversation-sources/useConversationSources/useConversationSources.ts
5
- var s = {}, c = (e, t) => {
6
- let r = n(e);
7
- if (r == null) return t;
8
- let a = i(t);
9
- return a == null || a.page != null ? t : `${t}#page=${r}`;
10
- }, l = (n, i = s) => o(() => {
11
- let o = [], s = [], l = [], u = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set(), f = /* @__PURE__ */ new Set();
12
- for (let p of n) {
13
- let n = p.custom_content?.attachments;
14
- if (p.role === e.User) for (let e of n ?? []) {
15
- let n = t(e, i);
16
- d.has(n.id) || (d.add(n.id), o.push(n));
5
+ var a = {}, o = (o, s = a) => i(() => {
6
+ let i = [], a = [], c = [], l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set();
7
+ for (let f of o) {
8
+ let o = f.custom_content?.attachments;
9
+ if (f.role === e.User) for (let e of o ?? []) {
10
+ let n = t(e, s);
11
+ u.has(n.id) || (u.add(n.id), i.push(n));
17
12
  }
18
- else if (p.role === e.Assistant) {
19
- let e = n?.filter((e) => !r(e));
13
+ else if (f.role === e.Assistant) {
14
+ let e = o?.filter((e) => !n(e));
20
15
  for (let n of e ?? []) {
21
- let e = t(n, i);
22
- f.has(e.id) || (f.add(e.id), s.push(e));
16
+ let e = t(n, s);
17
+ d.has(e.id) || (d.add(e.id), a.push(e));
23
18
  }
24
- for (let e of n ?? []) {
25
- if (!r(e)) continue;
19
+ for (let e of o ?? []) {
20
+ if (!n(e)) continue;
26
21
  let t = e.reference_url;
27
- u.has(t) || (u.add(t), l.push({
22
+ l.has(t) || (l.add(t), c.push({
28
23
  url: t,
29
24
  title: e.title ?? t,
30
25
  contentType: e.reference_type ?? e.type ?? "",
31
26
  quote: e.data
32
27
  }));
33
28
  }
34
- for (let e of a(p)) {
29
+ for (let e of r(f)) {
35
30
  let t = e?.body?.source?.attachment, n = t?.url;
36
- if (!n) continue;
37
- let r = c(e, n);
38
- u.has(r) || (u.add(r), l.push({
39
- url: r,
31
+ !n || l.has(n) || (l.add(n), c.push({
32
+ url: n,
40
33
  title: t?.title ?? n.split("/").pop() ?? n,
41
34
  contentType: t?.type ?? "",
42
35
  quote: e.body?.quote
@@ -45,10 +38,10 @@ var s = {}, c = (e, t) => {
45
38
  }
46
39
  }
47
40
  return {
48
- uploaded: o,
49
- generated: s,
50
- sources: l
41
+ uploaded: i,
42
+ generated: a,
43
+ sources: c
51
44
  };
52
- }, [n, i]);
45
+ }, [o, s]);
53
46
  //#endregion
54
- export { l as useConversationSources };
47
+ export { o as useConversationSources };
@@ -18,7 +18,7 @@ export declare interface UseConversationSourcesResult {
18
18
  uploaded: DisplayAttachment[];
19
19
  /** Deduplicated attachments the assistant generated across the conversation. */
20
20
  generated: DisplayAttachment[];
21
- /** Quotation sources referenced by assistant messages, deduplicated by URL; PDF sources are qualified with `#page=N`. */
21
+ /** Quotation sources referenced by assistant messages, deduplicated by URL. */
22
22
  sources: QuotationSource[];
23
23
  }
24
24
 
package/conversation.d.ts CHANGED
@@ -23,6 +23,7 @@ import { RequestSkill } from '@epam/ai-dial-chat-shared';
23
23
  import { ResponseFormat } from '@epam/ai-dial-chat-shared';
24
24
  import { SendCompletionDtoModeEnum } from '@epam/ai-dial-chat-api-client';
25
25
  import { SetStateAction } from 'react';
26
+ import { Stage } from '@epam/ai-dial-chat-shared';
26
27
  import { StarterOption } from '@epam/ai-dial-chat-shared';
27
28
  import { StatusMessage } from '@epam/ai-dial-chat-shared';
28
29
  import { StreamChunk } from '@epam/ai-dial-chat-shared';
@@ -57,6 +58,25 @@ export declare interface AnnouncementListItemLink {
57
58
  href: string;
58
59
  }
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
+
60
80
  /** State and controls returned by `useAsyncConfirmDialog`. */
61
81
  export declare interface AsyncConfirmDialogControls<T> {
62
82
  /**
@@ -572,6 +592,29 @@ declare interface LocalModeValues {
572
592
  temperature: number;
573
593
  }
574
594
 
595
+ /**
596
+ * Returns the normalized stages of a raw stage array or a message-like
597
+ * payload (reading `custom_content.stages`, falling back to
598
+ * `customContent.stages`), or `undefined` when there are none.
599
+ */
600
+ export declare const mapStages: (source: RawStage[] | RawStageSource | null | undefined) => Stage[] | undefined;
601
+
602
+ /**
603
+ * Merges incoming stage deltas into an existing stage list, keyed by `index`.
604
+ *
605
+ * Partial `name` and `content` strings are concatenated across chunks;
606
+ * attachments are merged by their own `index` (concatenating partial `title`
607
+ * and `data`); every other field on the incoming delta overwrites the
608
+ * accumulated one. A brand-new stage whose first chunk carries `name: null`
609
+ * is normalized to `''`.
610
+ *
611
+ * Exported for hosts that keep a flattened `Stage[]` on the message instead
612
+ * of `Message.custom_content.stages` and therefore cannot reuse
613
+ * {@link applyChunkToMessages}. Prefer `useConversationStream` when the host
614
+ * can delegate the whole stream loop.
615
+ */
616
+ export declare const mergeStages: (existing: Stage[], incoming: Stage[]) => Stage[];
617
+
575
618
  /** True when `message` is an assistant message carrying at least one stage. */
576
619
  export declare const messageHasStages: (message: Message) => boolean;
577
620
 
@@ -605,6 +648,63 @@ export declare interface QuickAppConversationStartersSettings {
605
648
  isChatMessageInputDisabled: boolean;
606
649
  }
607
650
 
651
+ /**
652
+ * One stage as it arrives from the REST API or the SSE stream, before
653
+ * normalization. Structurally satisfied by the generated `StageDto` and by a
654
+ * raw stream delta, both of which omit `index`/`name`/`status` on the chunk
655
+ * that opens a stage.
656
+ */
657
+ export declare interface RawStage {
658
+ /** Ordering key. Defaults to `0` when absent. */
659
+ index?: number | null;
660
+ /** Stage title. `null` on the chunk that opens the stage. */
661
+ name?: string | null;
662
+ /** Terminal state as a raw wire string; anything other than `'completed'`/`'failed'` means still running. */
663
+ status?: string | null;
664
+ /** Additional stage text. */
665
+ content?: string | null;
666
+ /** Short source/category label shown beside the stage name. */
667
+ tag?: string | null;
668
+ /** Files produced or referenced by this stage. */
669
+ attachments?: RawStageAttachment[] | null;
670
+ }
671
+
672
+ /**
673
+ * One stage attachment as it arrives from the REST API or the SSE stream,
674
+ * before normalization: every field is optional and may be `null`.
675
+ */
676
+ export declare interface RawStageAttachment {
677
+ /** Zero-based position in the attachment list. */
678
+ index?: number | null;
679
+ /** MIME type of the attachment content. */
680
+ type?: string | null;
681
+ /** Display name shown in the UI. */
682
+ title?: string | null;
683
+ /** Inline base-64 encoded content. */
684
+ data?: string | null;
685
+ /** Remote URL pointing to the attachment content. */
686
+ url?: string | null;
687
+ /** MIME type of the referenced resource. */
688
+ reference_type?: string | null;
689
+ /** URL of an alternate reference resource. */
690
+ reference_url?: string | null;
691
+ }
692
+
693
+ /**
694
+ * Message-like payload carrying stages under either the wire's snake_case
695
+ * `custom_content` or a host's camelCased `customContent`.
696
+ */
697
+ export declare interface RawStageSource {
698
+ /** Custom content as the DIAL wire format spells it. */
699
+ custom_content?: {
700
+ stages?: RawStage[] | null;
701
+ } | null;
702
+ /** Custom content as a camelCasing host spells it. */
703
+ customContent?: {
704
+ stages?: RawStage[] | null;
705
+ } | null;
706
+ }
707
+
608
708
  /** State of one resource's recipient-count lookup. */
609
709
  declare interface RecipientsCountEntry {
610
710
  /** Where the lookup for this resource currently stands. */
@@ -661,6 +761,13 @@ export declare interface StreamCompletionOptions {
661
761
  signal: AbortSignal;
662
762
  }
663
763
 
764
+ /**
765
+ * Returns a renderable `Stage` for one raw payload: `index` defaults to `0`,
766
+ * `name` to `''`, an unrecognized `status` to `null` (still running), and
767
+ * `content`/`tag`/`attachments` are passed through when present.
768
+ */
769
+ export declare const toStage: (stage: RawStage) => Stage;
770
+
664
771
  /** Request shape the host's selected-deployment recognition call accepts. */
665
772
  export declare interface TranscribeWithDeploymentParams {
666
773
  audioUrl: string;
package/conversation.js CHANGED
@@ -7,24 +7,26 @@ import { getTimeOfDayGreeting as f } from "./conversation/greeting.js";
7
7
  import { createDeploymentChangedMessage as p } from "./conversation/message-factory.js";
8
8
  import { getLastDeploymentId as m, getLastUserMessageToolConfiguration as h, isMessageStreaming as g, messageHasStages as _, normalizeResponseFormat as v } from "./conversation/message-utils.js";
9
9
  import { getQuickAppConversationStarters as y } from "./conversation/quick-app-conversation-starters.js";
10
- import { getStarterPopulateText as b, getStartersFromSchema as x } from "./conversation/starter-option.js";
11
- import { deriveConversationRowActionState as S } from "./conversation/deriveConversationRowActionState/deriveConversationRowActionState.js";
12
- import { useActiveConversationSync as C } from "./conversation/useActiveConversationSync/useActiveConversationSync.js";
13
- import { useAsyncConfirmDialog as w } from "./conversation/useAsyncConfirmDialog/useAsyncConfirmDialog.js";
14
- import { useConversationLookupMaps as T } from "./conversation/useConversationLookupMaps/useConversationLookupMaps.js";
15
- import { getConversationSource as E, useConversationPanelItems as D } from "./conversation/useConversationPanelItems/useConversationPanelItems.js";
16
- import { useImportFilePicker as O } from "./conversation/useImportFilePicker/useImportFilePicker.js";
17
- import { useAttachmentUpload as k } from "./conversation/useAttachmentUpload/useAttachmentUpload.js";
18
- import { AudioTranscriptionError as A, AudioTranscriptionErrorReason as j } from "./conversation/useTranscribeAudio/audio-transcription-error.js";
19
- import { useTranscribeAudio as M } from "./conversation/useTranscribeAudio/useTranscribeAudio.js";
20
- import { attachmentToDto as N, attachmentsToDtos as P } from "./conversation/useConversationHandlers/attachment-to-dto.js";
21
- import { createMessagePair as F } from "./conversation/useConversationHandlers/message-factory.js";
22
- import { hasActiveToolConfig as I, isAnswerIncomplete as L, isMessageChanged as R, shouldRerunGenerationOnEdit as z } from "./conversation/useConversationHandlers/message-utils.js";
23
- import { getStarterConversationText as B, getStarterDisplayText as V, getStarterSubmitText as H } from "./conversation/useConversationHandlers/starter-option.js";
24
- import { getConversationPath as U } from "./conversation/useConversationStream/conversation-path.js";
25
- import { useConversationHandlers as W } from "./conversation/useConversationHandlers/useConversationHandlers.js";
26
- import { isAwaitingGenerationResume as G } from "./conversation/useConversationStream/generation-resume.js";
27
- import { useConversationStream as K } from "./conversation/useConversationStream/useConversationStream.js";
28
- import { useChatSettingsFormConfig as q } from "./useChatSettingsFormConfig/useChatSettingsFormConfig.js";
29
- import { useToolsMenu as J } from "./useToolsMenu/useToolsMenu.js";
30
- export { A as AudioTranscriptionError, j as AudioTranscriptionErrorReason, a as DEFAULT_GENERATION_CONFLICT_MESSAGE, o as GenerationConflictError, N as attachmentToDto, P as attachmentsToDtos, e as buildAnnouncementSignature, s as createChatStreamApi, p as createDeploymentChangedMessage, F as createMessagePair, S as deriveConversationRowActionState, l as formatAppVersion, U as getConversationPath, E as getConversationSource, m as getLastDeploymentId, h as getLastUserMessageToolConfiguration, d as getModelIdFromConversationId, y as getQuickAppConversationStarters, B as getStarterConversationText, V as getStarterDisplayText, b as getStarterPopulateText, H as getStarterSubmitText, x as getStartersFromSchema, f as getTimeOfDayGreeting, I as hasActiveToolConfig, t as hasAnnouncementContent, n as hasStructuredAnnouncement, L as isAnswerIncomplete, G as isAwaitingGenerationResume, R as isMessageChanged, g as isMessageStreaming, _ as messageHasStages, v as normalizeResponseFormat, r as sanitizeAnnouncementHtml, i as sanitizeAnnouncementMessageHtml, u as sanitizeFooterHtml, z as shouldRerunGenerationOnEdit, c as shouldWatchForDisplayNameUpdate, C as useActiveConversationSync, w as useAsyncConfirmDialog, k as useAttachmentUpload, q as useChatSettingsFormConfig, W as useConversationHandlers, T as useConversationLookupMaps, D as useConversationPanelItems, K as useConversationStream, O as useImportFilePicker, J as useToolsMenu, M as useTranscribeAudio };
10
+ import { mapStages as b, toStage as x } from "./conversation/stage.js";
11
+ import { getStarterPopulateText as S, getStartersFromSchema as C } from "./conversation/starter-option.js";
12
+ import { deriveConversationRowActionState as w } from "./conversation/deriveConversationRowActionState/deriveConversationRowActionState.js";
13
+ import { useActiveConversationSync as T } from "./conversation/useActiveConversationSync/useActiveConversationSync.js";
14
+ import { useAsyncConfirmDialog as E } from "./conversation/useAsyncConfirmDialog/useAsyncConfirmDialog.js";
15
+ import { useConversationLookupMaps as D } from "./conversation/useConversationLookupMaps/useConversationLookupMaps.js";
16
+ import { getConversationSource as O, useConversationPanelItems as k } from "./conversation/useConversationPanelItems/useConversationPanelItems.js";
17
+ import { useImportFilePicker as A } from "./conversation/useImportFilePicker/useImportFilePicker.js";
18
+ import { useAttachmentUpload as j } from "./conversation/useAttachmentUpload/useAttachmentUpload.js";
19
+ import { AudioTranscriptionError as M, AudioTranscriptionErrorReason as N } from "./conversation/useTranscribeAudio/audio-transcription-error.js";
20
+ import { useTranscribeAudio as P } from "./conversation/useTranscribeAudio/useTranscribeAudio.js";
21
+ import { attachmentToDto as F, attachmentsToDtos as I } from "./conversation/useConversationHandlers/attachment-to-dto.js";
22
+ import { createMessagePair as L } from "./conversation/useConversationHandlers/message-factory.js";
23
+ import { hasActiveToolConfig as R, isAnswerIncomplete as z, isMessageChanged as B, shouldRerunGenerationOnEdit as V } from "./conversation/useConversationHandlers/message-utils.js";
24
+ import { getStarterConversationText as H, getStarterDisplayText as U, getStarterSubmitText as W } from "./conversation/useConversationHandlers/starter-option.js";
25
+ import { getConversationPath as G } from "./conversation/useConversationStream/conversation-path.js";
26
+ import { useConversationHandlers as K } from "./conversation/useConversationHandlers/useConversationHandlers.js";
27
+ import { applyChunkToMessages as q, mergeStages as J } from "./conversation/useConversationStream/apply-chunk.js";
28
+ import { isAwaitingGenerationResume as Y } from "./conversation/useConversationStream/generation-resume.js";
29
+ import { useConversationStream as X } from "./conversation/useConversationStream/useConversationStream.js";
30
+ import { useChatSettingsFormConfig as Z } from "./useChatSettingsFormConfig/useChatSettingsFormConfig.js";
31
+ import { useToolsMenu as Q } from "./useToolsMenu/useToolsMenu.js";
32
+ export { M as AudioTranscriptionError, N as AudioTranscriptionErrorReason, a as DEFAULT_GENERATION_CONFLICT_MESSAGE, o as GenerationConflictError, q as applyChunkToMessages, F as attachmentToDto, I as attachmentsToDtos, e as buildAnnouncementSignature, s as createChatStreamApi, p as createDeploymentChangedMessage, L as createMessagePair, w as deriveConversationRowActionState, l as formatAppVersion, G as getConversationPath, O as getConversationSource, m as getLastDeploymentId, h as getLastUserMessageToolConfiguration, d as getModelIdFromConversationId, y as getQuickAppConversationStarters, H as getStarterConversationText, U as getStarterDisplayText, S as getStarterPopulateText, W as getStarterSubmitText, C as getStartersFromSchema, f as getTimeOfDayGreeting, R as hasActiveToolConfig, t as hasAnnouncementContent, n as hasStructuredAnnouncement, z as isAnswerIncomplete, Y as isAwaitingGenerationResume, B as isMessageChanged, g as isMessageStreaming, b as mapStages, J as mergeStages, _ as messageHasStages, v as normalizeResponseFormat, r as sanitizeAnnouncementHtml, i as sanitizeAnnouncementMessageHtml, u as sanitizeFooterHtml, V as shouldRerunGenerationOnEdit, c as shouldWatchForDisplayNameUpdate, x as toStage, T as useActiveConversationSync, E as useAsyncConfirmDialog, j as useAttachmentUpload, Z as useChatSettingsFormConfig, K as useConversationHandlers, D as useConversationLookupMaps, k as useConversationPanelItems, X as useConversationStream, A as useImportFilePicker, Q as useToolsMenu, P as useTranscribeAudio };
package/file-manager.d.ts CHANGED
@@ -24,13 +24,16 @@ import { DiscardSharedItemDto } from '@epam/ai-dial-chat-api-client';
24
24
  import { DiscardSharedResponseDto } from '@epam/ai-dial-chat-api-client';
25
25
  import { DisplayAttachment } from '@epam/ai-dial-chat-shared';
26
26
  import { FileManagerColumnKey } from '@epam/ai-dial-react-file-manager';
27
+ import { FileManagerSelectableNode } from '@epam/ai-dial-chat-shared';
27
28
  import { FileMetadataResponseDto } from '@epam/ai-dial-chat-api-client';
28
29
  import { FilesApi } from '@epam/ai-dial-chat-api-client';
30
+ import { FileTreeOptions } from '@epam/ai-dial-react-file-manager';
29
31
  import { FileUploadBatchState } from '@epam/ai-dial-chat-shared';
30
32
  import { FileUploadEntry } from '@epam/ai-dial-chat-shared';
31
33
  import { FileUploadResponseDto } from '@epam/ai-dial-chat-api-client';
32
34
  import { FileUploadStatus } from '@epam/ai-dial-chat-shared';
33
35
  import { FileUploadValidationResult } from '@epam/ai-dial-chat-shared';
36
+ import { FilterChipItem } from '@epam/ai-dial-ui-kit';
34
37
  import { getParentFolderPath } from '@epam/ai-dial-chat-shared';
35
38
  import { ListFilesItemDto } from '@epam/ai-dial-chat-api-client';
36
39
  import { ListFilesResponseDto } from '@epam/ai-dial-chat-api-client';
@@ -44,8 +47,6 @@ import { RenameFilesResponseDto } from '@epam/ai-dial-chat-api-client';
44
47
  import { RenameItemDto } from '@epam/ai-dial-chat-api-client';
45
48
  import { RevokeAccessItemDto } from '@epam/ai-dial-chat-api-client';
46
49
  import { RevokeAccessResponseDto } from '@epam/ai-dial-chat-api-client';
47
- import { TabModel } from '@epam/ai-dial-ui-kit';
48
- import { ToolbarOptions } from '@epam/ai-dial-react-file-manager';
49
50
  import { UploadArchiveResponseDto } from '@epam/ai-dial-chat-api-client';
50
51
  import { useGridEditingScroll } from '@epam/ai-dial-chat-shared';
51
52
  import { UseGridEditingScrollOptions } from '@epam/ai-dial-chat-shared';
@@ -521,7 +522,14 @@ export declare const mergeCreatedFolderIntoCache: (cache: Map<string, ListFilesI
521
522
  /** Formats MIME types as a human-readable, comma-separated list of dotted extensions (or the MIME type itself for wildcards). */
522
523
  export declare const mimeTypesToAttachmentExtensionLabels: (types: string[]) => string;
523
524
 
524
- /** Normalizes `*` to the all-files wildcard and drops any value that is not a valid `DialFileAcceptType`. */
525
+ /**
526
+ * Normalizes `*` to the all-files wildcard, canonicalizes MIME aliases, and drops
527
+ * any value that is not a valid `DialFileAcceptType`.
528
+ *
529
+ * Aliases are resolved because a file picker matches an `accept` entry against its
530
+ * own MIME table: a declared `text/json` offers no `.json` file, while the
531
+ * `application/json` it denotes does.
532
+ */
525
533
  export declare const mimeTypesToDialFileAcceptTypes: (types?: string[]) => DialFileAcceptType[] | undefined;
526
534
 
527
535
  /**
@@ -933,11 +941,11 @@ export declare interface UseDialFileManagerResult {
933
941
  * current one becomes excluded. A `fileManagerTabs` of `undefined` means no
934
942
  * restriction — every tab in `allTabs` stays enabled and no reset ever fires.
935
943
  */
936
- export declare const useDialFileManagerTabConfig: (activeTab: DialFileManagerTabs, onTabChange: (tab: DialFileManagerTabs) => void, allTabs: TabModel[] | undefined, fileManagerTabs: string[] | undefined) => UseDialFileManagerTabConfigResult;
944
+ export declare const useDialFileManagerTabConfig: (activeTab: DialFileManagerTabs, onTabChange: (tab: DialFileManagerTabs) => void, allTabs: FilterChipItem<DialFileManagerTabs>[] | undefined, fileManagerTabs: string[] | undefined) => UseDialFileManagerTabConfigResult;
937
945
 
938
946
  /** Values returned by `useDialFileManagerTabConfig`. */
939
947
  export declare interface UseDialFileManagerTabConfigResult {
940
- tabs: ToolbarOptions['tabs'];
948
+ tabs: FileTreeOptions['tabs'];
941
949
  }
942
950
 
943
951
  /**
@@ -1101,6 +1109,64 @@ export declare interface UseDialFileUploadBatchResult {
1101
1109
  clearUploadBatch: () => void;
1102
1110
  }
1103
1111
 
1112
+ /**
1113
+ * Composes the file-manager tab/listing hooks into the stateful part of an attachment picker:
1114
+ * active tab, selected paths, and hidden-path/MIME/size/folder row eligibility. Returns the
1115
+ * existing `useDialFileManager` controller unchanged and the selection/tab/eligibility fields
1116
+ * `FileManagerAttachModal` already consumes — it composes that modal, it does not replace it.
1117
+ * Final attachment filtering, deduplication, and count enforcement stay owned by the modal.
1118
+ */
1119
+ export declare const useFileAttachmentPicker: ({ fileManagerOptions, bucket, forbiddenSymbolsRegExp, tabLabels, allowedTabs, initialTab, allowedTypes, maxSelectableFileSize, canAttachFolders, }: UseFileAttachmentPickerOptions) => UseFileAttachmentPickerResult;
1120
+
1121
+ /** Options accepted by {@link useFileAttachmentPicker}. */
1122
+ export declare interface UseFileAttachmentPickerOptions {
1123
+ /**
1124
+ * Configured `useDialFileManager` options besides the values this hook derives:
1125
+ * `bucket`, `activeTab`, `rootLabel`, `variant`, and `forbiddenSymbolsRegExp`.
1126
+ */
1127
+ fileManagerOptions: Omit<UseDialFileManagerOptions, 'bucket' | 'activeTab' | 'rootLabel' | 'variant' | 'forbiddenSymbolsRegExp'>;
1128
+ /** DIAL Core bucket to browse. */
1129
+ bucket: string;
1130
+ /** Regexp of characters forbidden in file/folder names, forwarded to `useDialFileManager`. */
1131
+ forbiddenSymbolsRegExp?: RegExp;
1132
+ /** Host-translated label per tab; also supplies the active tab's root-folder label. */
1133
+ tabLabels: Record<DialFileManagerTabs, string>;
1134
+ /** Tab ids the host's configuration allows. `undefined` allows every tab. */
1135
+ allowedTabs?: string[];
1136
+ /** Initial active tab. Defaults to `DialFileManagerTabs.MyFiles`. */
1137
+ initialTab?: DialFileManagerTabs;
1138
+ /** MIME types eligible for selection/upload. Empty or absent allows every type. */
1139
+ allowedTypes?: string[];
1140
+ /** Files at or below this size (bytes) remain eligible; absent allows any size. */
1141
+ maxSelectableFileSize?: number;
1142
+ /** Whether folder rows are eligible for selection. Defaults to `false`. */
1143
+ canAttachFolders?: boolean;
1144
+ }
1145
+
1146
+ /** Result returned by {@link useFileAttachmentPicker}. */
1147
+ export declare interface UseFileAttachmentPickerResult {
1148
+ /** The composed file-manager controller; forward to `FileManagerAttachModal`'s `controller` prop. */
1149
+ controller: UseDialFileManagerResult;
1150
+ /** Active tab. */
1151
+ activeTab: DialFileManagerTabs;
1152
+ /** Tab list filtered to `allowedTabs`; forward to `FileManagerAttachModal`'s `tabs` prop. */
1153
+ tabs: FileTreeOptions['tabs'];
1154
+ /** Switches the active tab and clears the current selection. */
1155
+ onTabChange: (tab: DialFileManagerTabs) => void;
1156
+ /** Currently selected paths. */
1157
+ selectedPaths: Set<string>;
1158
+ /** Replaces the selection with a defensive copy of the given set. */
1159
+ onSelectedPathsChange: (paths: Set<string>) => void;
1160
+ /** Row eligibility predicate; forward to `FileManagerAttachModal`'s `isRowSelectable` prop. */
1161
+ isRowSelectable: (node: {
1162
+ data?: FileManagerSelectableNode | null;
1163
+ }) => boolean;
1164
+ /** MIME eligibility predicate; forward to `FileManagerAttachModal`'s `isFileTypeAllowed` prop. */
1165
+ isFileTypeAllowed: (contentType: string) => boolean;
1166
+ /** Accepted upload MIME types; forward to `FileManagerAttachModal`'s `allowedFileTypes` prop. */
1167
+ allowedFileTypes: DialFileAcceptType[] | undefined;
1168
+ }
1169
+
1104
1170
  export { useGridEditingScroll }
1105
1171
 
1106
1172
  export { UseGridEditingScrollOptions }
package/file-manager.js CHANGED
@@ -24,5 +24,6 @@ import { useDialFileSharing as me } from "./files/useDialFileSharing/useDialFile
24
24
  import { useDialFileUploadBatch as he } from "./files/useDialFileUploadBatch/useDialFileUploadBatch.js";
25
25
  import { useDialFileManager as ge } from "./files/useDialFileManager/useDialFileManager.js";
26
26
  import { useDialFileManagerTabConfig as _e } from "./files/useDialFileManagerTabConfig/useDialFileManagerTabConfig.js";
27
- import { useGridEditingScroll as ve } from "@epam/ai-dial-chat-shared";
28
- export { m as COLUMNS_WITHOUT_AUTHOR, h as COLUMNS_WITH_AUTHOR, g as CORE_PERMISSION_MAP, _ as DATE_OPTIONS, x as DialFileManagerActionProfile, S as DialFileManagerVariant, u as DialFilesApiUploadMode, le as DownloadDestinationType, d as FileManagerNotificationReason, f as FileNameValidationErrorReason, p as FileOperationKind, v as PATH_SEPARATOR_REGEXP, y as RESERVED_MARKER_NAME, b as UPLOAD_CONCURRENCY, re as annotationToDisplayAttachment, ie as attachmentDtoToDisplayAttachment, ae as attachmentDtosToDisplayAttachments, H as buildFromCache, w as buildSharedItemVirtualPath, Z as createFilesApiClient, Q as createUploadFileWithProgress, C as deriveActionProfile, T as dialCorePathToRelative, oe as dialFileToAttachment, se as dialFilesToAttachments, ce as dialFolderPathToAttachment, U as fetchByTab, W as fetchForSearch, E as findDialFileByPath, G as findFirstSuccessfulCopyMoveItem, D as findFolderByVirtualPath, O as formatOperationFolderName, L as getParentFolderPath, ee as getUrlFileName, k as getVirtualPathName, A as hasDialFileWritePermission, j as hasForbiddenNameSymbols, M as isCopyMoveDuplicateAllowed, r as isDialFileAcceptType, e as isDialFileId, te as isExternalSourcePreviewable, N as isShareActionsAllowed, K as mapCorePermissions, q as mapFileMetadataToDialFile, J as mapSearchItem, Y as mergeCreatedFolderIntoCache, i as mimeTypesToAttachmentExtensionLabels, a as mimeTypesToDialFileAcceptTypes, o as mimeTypesToFileAccept, P as normalizeVirtualPath, $ as openAnnotationAttachment, F as parseNewFolderVirtualPath, B as prepareCopyItems, ue as prepareDownloadDestination, V as prepareMoveRenameItems, R as resolveDialFileApiPath, t as resolveDialFileBucketAndPath, ne as resolveExternalSourceContentType, I as resolveOwnerCoords, n as resolveRelativeDialFilePath, s as sanitizeFileName, c as splitFileNameExtension, l as trimFileNameToByteLimit, X as updateEntry, de as useDialFileListing, ge as useDialFileManager, _e as useDialFileManagerTabConfig, fe as useDialFileMetadata, pe as useDialFileMutations, me as useDialFileSharing, he as useDialFileUploadBatch, ve as useGridEditingScroll, z as virtualPathToApiPath };
27
+ import { useFileAttachmentPicker as ve } from "./files/useFileAttachmentPicker/useFileAttachmentPicker.js";
28
+ import { useGridEditingScroll as ye } from "@epam/ai-dial-chat-shared";
29
+ export { m as COLUMNS_WITHOUT_AUTHOR, h as COLUMNS_WITH_AUTHOR, g as CORE_PERMISSION_MAP, _ as DATE_OPTIONS, x as DialFileManagerActionProfile, S as DialFileManagerVariant, u as DialFilesApiUploadMode, le as DownloadDestinationType, d as FileManagerNotificationReason, f as FileNameValidationErrorReason, p as FileOperationKind, v as PATH_SEPARATOR_REGEXP, y as RESERVED_MARKER_NAME, b as UPLOAD_CONCURRENCY, re as annotationToDisplayAttachment, ie as attachmentDtoToDisplayAttachment, ae as attachmentDtosToDisplayAttachments, H as buildFromCache, w as buildSharedItemVirtualPath, Z as createFilesApiClient, Q as createUploadFileWithProgress, C as deriveActionProfile, T as dialCorePathToRelative, oe as dialFileToAttachment, se as dialFilesToAttachments, ce as dialFolderPathToAttachment, U as fetchByTab, W as fetchForSearch, E as findDialFileByPath, G as findFirstSuccessfulCopyMoveItem, D as findFolderByVirtualPath, O as formatOperationFolderName, L as getParentFolderPath, ee as getUrlFileName, k as getVirtualPathName, A as hasDialFileWritePermission, j as hasForbiddenNameSymbols, M as isCopyMoveDuplicateAllowed, r as isDialFileAcceptType, e as isDialFileId, te as isExternalSourcePreviewable, N as isShareActionsAllowed, K as mapCorePermissions, q as mapFileMetadataToDialFile, J as mapSearchItem, Y as mergeCreatedFolderIntoCache, i as mimeTypesToAttachmentExtensionLabels, a as mimeTypesToDialFileAcceptTypes, o as mimeTypesToFileAccept, P as normalizeVirtualPath, $ as openAnnotationAttachment, F as parseNewFolderVirtualPath, B as prepareCopyItems, ue as prepareDownloadDestination, V as prepareMoveRenameItems, R as resolveDialFileApiPath, t as resolveDialFileBucketAndPath, ne as resolveExternalSourceContentType, I as resolveOwnerCoords, n as resolveRelativeDialFilePath, s as sanitizeFileName, c as splitFileNameExtension, l as trimFileNameToByteLimit, X as updateEntry, de as useDialFileListing, ge as useDialFileManager, _e as useDialFileManagerTabConfig, fe as useDialFileMetadata, pe as useDialFileMutations, me as useDialFileSharing, he as useDialFileUploadBatch, ve as useFileAttachmentPicker, ye as useGridEditingScroll, z as virtualPathToApiPath };
@@ -1,16 +1,17 @@
1
- import { extension as e } from "mime-types";
1
+ import { normalizeMimeType as e } from "@epam/ai-dial-chat-shared";
2
+ import { extension as t } from "mime-types";
2
3
  //#region src/files/attachment-types.ts
3
- var t = "*/*", n = (e) => e.startsWith(".") || e.includes("/"), r = (e) => {
4
- if (e != null) return e.map((e) => e === "*" ? t : e).filter(n);
5
- }, i = (e) => {
6
- let n = r(e);
7
- if (!(n == null || n.length === 0) && !n.some((e) => e === t)) return n.join(",");
8
- }, a = (t) => t.map((t) => {
9
- if (t.endsWith("/*")) return t;
10
- let n = e(t);
11
- if (n !== !1) return `.${n}`;
12
- let r = t.split("/")[1];
13
- return r == null ? t : `.${r.toLowerCase()}`;
4
+ var n = "*/*", r = (e) => e.startsWith(".") || e.includes("/"), i = (t) => {
5
+ if (t != null) return t.map((t) => t === "*" ? n : t.startsWith(".") ? t : e(t)).filter(r);
6
+ }, a = (e) => {
7
+ let t = i(e);
8
+ if (!(t == null || t.length === 0) && !t.some((e) => e === n)) return t.join(",");
9
+ }, o = (n) => n.map((n) => {
10
+ if (n.endsWith("/*")) return n;
11
+ let r = e(n), i = t(r);
12
+ if (i !== !1) return `.${i}`;
13
+ let a = r.split("/")[1];
14
+ return a == null ? n : `.${a.toLowerCase()}`;
14
15
  }).join(", ");
15
16
  //#endregion
16
- export { n as isDialFileAcceptType, a as mimeTypesToAttachmentExtensionLabels, r as mimeTypesToDialFileAcceptTypes, i as mimeTypesToFileAccept };
17
+ export { r as isDialFileAcceptType, o as mimeTypesToAttachmentExtensionLabels, i as mimeTypesToDialFileAcceptTypes, a as mimeTypesToFileAccept };
@@ -6,11 +6,7 @@ var i = [
6
6
  r.Shared,
7
7
  r.Organization
8
8
  ], a = (a, o, s, c) => {
9
- let l = e((e) => c == null || c.includes(e), [c]), u = n(() => s?.filter((e) => l(e.id)).flatMap(({ id: e, label: t, disabled: n }) => typeof t == "string" ? [{
10
- id: e,
11
- label: t,
12
- disabled: n
13
- }] : []), [s, l]);
9
+ let l = e((e) => c == null || c.includes(e), [c]), u = n(() => s?.filter((e) => l(e.value)), [s, l]);
14
10
  return t(() => {
15
11
  l(a) || o(i.find((e) => l(e)) ?? r.MyFiles);
16
12
  }, [
@@ -0,0 +1,43 @@
1
+ import { mimeTypesToDialFileAcceptTypes as e } from "../attachment-types.js";
2
+ import { DialFileManagerVariant as t } from "../file-manager-variant.js";
3
+ import { useDialFileManager as n } from "../useDialFileManager/useDialFileManager.js";
4
+ import { useDialFileManagerTabConfig as r } from "../useDialFileManagerTabConfig/useDialFileManagerTabConfig.js";
5
+ import { isHiddenPath as i } from "@epam/ai-dial-chat-shared";
6
+ import { useCallback as a, useMemo as o, useState as s } from "react";
7
+ import { isMimeTypeAllowed as c } from "@epam/ai-dial-attachment-input";
8
+ import { DialFileManagerTabs as l, DialFileNodeType as u, useDialFileManagerTabs as d } from "@epam/ai-dial-react-file-manager";
9
+ //#region src/files/useFileAttachmentPicker/useFileAttachmentPicker.ts
10
+ var f = ({ fileManagerOptions: f, bucket: p, forbiddenSymbolsRegExp: m, tabLabels: h, allowedTabs: g, initialTab: _, allowedTypes: v, maxSelectableFileSize: y, canAttachFolders: b = !1 }) => {
11
+ let { activeTab: x, handleTabChange: S, tabs: C } = d(h, _), [w, T] = s(() => /* @__PURE__ */ new Set()), E = a((e) => {
12
+ T(new Set(e));
13
+ }, []), D = a((e) => {
14
+ T(/* @__PURE__ */ new Set()), S(e);
15
+ }, [S]), { tabs: O } = r(x, D, C, g), k = h[x] || h[l.MyFiles], A = n({
16
+ ...f,
17
+ bucket: p,
18
+ activeTab: x,
19
+ rootLabel: k,
20
+ variant: t.Attach,
21
+ forbiddenSymbolsRegExp: m
22
+ }), j = a((e) => v == null || v.length === 0 ? !0 : c(e, v), [v]);
23
+ return {
24
+ controller: A,
25
+ activeTab: x,
26
+ tabs: O,
27
+ onTabChange: D,
28
+ selectedPaths: w,
29
+ onSelectedPathsChange: E,
30
+ isRowSelectable: a((e) => {
31
+ let t = e.data;
32
+ return t == null || i(t.path) ? !1 : t.nodeType === u.FOLDER ? b : t.nodeType === u.ITEM ? !(t.contentType != null && !j(t.contentType) || y != null && t.contentLength != null && t.contentLength > y) : !1;
33
+ }, [
34
+ b,
35
+ j,
36
+ y
37
+ ]),
38
+ isFileTypeAllowed: j,
39
+ allowedFileTypes: o(() => e(v), [v])
40
+ };
41
+ };
42
+ //#endregion
43
+ export { f as useFileAttachmentPicker };