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

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.
@@ -31,11 +31,11 @@ var c = {
31
31
  }, f = "applications/", p = "toolsets/", m = "public", h = (t, n) => (t.startsWith(n) ? t.slice(n.length) : t).split("/").filter(Boolean).map(e), g = (e, t) => {
32
32
  if (e.isMy) return [t.personal];
33
33
  let n = h(e.applicationFolder ?? "", f);
34
- return e.sharedWithMe ? [t.shared, ...n.slice(1)] : n[0]?.toLowerCase() === m ? [t.public, ...n.slice(1)] : n;
34
+ return e.sharedWithMe ? [t.shared, ...n.slice(1)] : n.length === 0 && e.type?.toLowerCase() === "application" ? [t.public] : n[0]?.toLowerCase() === m ? [t.public, ...n.slice(1)] : n;
35
35
  }, _ = (e, t) => {
36
36
  if (e.isMy && t != null) return [t.personal];
37
37
  let n = e.toolset || e.id;
38
- if (!n.startsWith(p)) return [];
38
+ if (!n.startsWith(p)) return t == null ? [] : e.sharedWithMe ? [t.shared] : n.length > 0 && !n.includes("/") ? [t.public] : [];
39
39
  let r = h(n, p).slice(0, -1);
40
40
  return e.sharedWithMe && t != null ? [t.shared, ...r.slice(1)] : r[0]?.toLowerCase() === m && t != null ? [t.public, ...r.slice(1)] : r.slice(1);
41
41
  }, v = (e, { favoriteIds: t = /* @__PURE__ */ new Set(), entityDetails: o, folderLabels: s, editableSchemaIds: c = [], isCustomAppsEditable: l = !1, activeLocale: u, primaryLocale: f, resolveIconUrl: p }) => {
@@ -115,9 +115,9 @@ var c = {
115
115
  if (Number.isFinite(t) && t > 262144) return null;
116
116
  let n = await e.arrayBuffer();
117
117
  return n.byteLength > 262144 ? null : new Uint8Array(n);
118
- }, S = async (e) => {
118
+ }, S = async (e) => new Uint8Array(await e.arrayBuffer()), C = async (e) => {
119
119
  let t = await x(e);
120
120
  return t == null ? null : new TextDecoder().decode(t);
121
121
  };
122
122
  //#endregion
123
- export { b as buildSkillContentTree, _ as buildSkillOverview, u as mapSkillToCatalogItem, x as readSkillFileBytes, S as readSkillManifest, g as resolveSkillFileDownloadPath, m as resolveSkillManifestFileId };
123
+ export { b as buildSkillContentTree, _ as buildSkillOverview, u as mapSkillToCatalogItem, x as readSkillFileBytes, S as readSkillFilePreviewBytes, C as readSkillManifest, g as resolveSkillFileDownloadPath, m as resolveSkillManifestFileId };
@@ -1,59 +1,59 @@
1
1
  import { SkillSource as e } from "../../skill/skill-types.js";
2
2
  import { mapSkillToCatalogItem as t } from "../map-skill-to-catalog-item.js";
3
3
  import { useSkillItemDetails as n } from "../useSkillItemDetails.js";
4
- import { useEffect as r, useMemo as i, useState as a } from "react";
4
+ import { useEffect as r, useMemo as i, useRef as a, useState as o } from "react";
5
5
  //#region src/catalog/useSkillDetailsPanelData/useSkillDetailsPanelData.ts
6
- var o = ({ api: o, skills: s, sharedWithMe: c, publicSkills: l, skillId: u, folderLabels: d, skillOverviewLabels: f, favoriteIds: p }) => {
7
- let m = i(() => [
8
- ...s,
9
- ...c ?? [],
10
- ...l ?? []
6
+ var s = ({ api: s, skills: c, sharedWithMe: l, publicSkills: u, skillId: d, folderLabels: f, skillOverviewLabels: p, favoriteIds: m }) => {
7
+ let h = i(() => [
8
+ ...c,
9
+ ...l ?? [],
10
+ ...u ?? []
11
11
  ], [
12
- s,
13
- c,
14
- l
15
- ]), { onFetchSkillDetails: h, onLoadSkillDetailsFile: g } = n({
16
- api: o,
17
- skills: m,
18
- skillOverviewLabels: f
19
- }), _ = i(() => m.find((e) => e.url === u) ?? null, [m, u]), v = i(() => s.some((e) => e.url === u) ? e.Personal : c?.some((e) => e.url === u) ? e.SharedWithMe : e.Public, [
20
- s,
21
12
  c,
13
+ l,
22
14
  u
23
- ]), y = i(() => _ == null ? null : t(_, {
24
- folderLabels: d,
25
- source: v,
26
- favoriteIds: p
15
+ ]), { onFetchSkillDetails: g, onLoadSkillDetailsFile: _ } = n({
16
+ api: s,
17
+ skills: h,
18
+ skillOverviewLabels: p
19
+ }), v = i(() => h.find((e) => e.url === d) ?? null, [h, d]), y = i(() => c.some((e) => e.url === d) ? e.Personal : l?.some((e) => e.url === d) ? e.SharedWithMe : e.Public, [
20
+ c,
21
+ l,
22
+ d
23
+ ]), b = i(() => v == null ? null : t(v, {
24
+ folderLabels: f,
25
+ source: y,
26
+ favoriteIds: m
27
27
  }), [
28
- _,
29
28
  v,
30
- d,
31
- p
32
- ]), [b, x] = a(null), [S, C] = a(!1);
29
+ y,
30
+ f,
31
+ m
32
+ ]), [x, S] = o(null), [C, w] = o(!1), T = a(0);
33
33
  return r(() => {
34
- if (y == null) return;
35
- C(!0), x(null);
36
- let e = !1;
37
- return h(y).then((t) => {
38
- e || (x(t ?? null), C(!1));
34
+ if (b == null) return;
35
+ w(!0), S(null);
36
+ let e = !1, t = ++T.current;
37
+ return g(b).then((n) => {
38
+ e || T.current !== t || (S(n ?? null), w(!1));
39
39
  }), () => {
40
40
  e = !0;
41
41
  };
42
- }, [y?.id]), {
42
+ }, [b?.id]), {
43
43
  detailsPanelItem: i(() => {
44
- if (y == null) return null;
45
- if (b == null) return y;
46
- let { credentials: e, ...t } = b;
44
+ if (b == null) return null;
45
+ if (x == null) return b;
46
+ let { credentials: e, ...t } = x;
47
47
  return {
48
- ...y,
48
+ ...b,
49
49
  details: t,
50
- credentials: e ?? y.credentials
50
+ credentials: e ?? b.credentials
51
51
  };
52
- }, [y, b]),
53
- isDetailsLoading: S,
54
- isStarred: y != null && p.has(y.id),
55
- onLoadSkillDetailsFile: g
52
+ }, [b, x]),
53
+ isDetailsLoading: C,
54
+ isStarred: b != null && m.has(b.id),
55
+ onLoadSkillDetailsFile: _
56
56
  };
57
57
  };
58
58
  //#endregion
59
- export { o as useSkillDetailsPanelData };
59
+ export { s as useSkillDetailsPanelData };
@@ -1,6 +1,6 @@
1
1
  import { SKILL_MANIFEST_FILE as e } from "../skill/skill.js";
2
2
  import { parseSkillResourceUrl as t } from "../skill/skill-types.js";
3
- import { buildSkillContentTree as n, buildSkillOverview as r, readSkillFileBytes as i, readSkillManifest as a, resolveSkillFileDownloadPath as o, resolveSkillManifestFileId as s } from "./map-skill-to-catalog-item.js";
3
+ import { buildSkillContentTree as n, buildSkillOverview as r, readSkillFilePreviewBytes as i, readSkillManifest as a, resolveSkillFileDownloadPath as o, resolveSkillManifestFileId as s } from "./map-skill-to-catalog-item.js";
4
4
  import { parseSkillManifestDocument as c } from "../skill/skill-manifest.js";
5
5
  import { useCallback as l, useRef as u } from "react";
6
6
  //#region src/catalog/useSkillItemDetails.ts
@@ -12,20 +12,24 @@ var d = ({ api: d, skills: f, skillOverviewLabels: p }) => {
12
12
  if (o == null) return;
13
13
  let { bucket: l, path: u } = o;
14
14
  m.current = o;
15
- let [h, g] = await Promise.allSettled([d.downloadSkillFile(l, u, e).then(a), d.listSkillFiles({
16
- bucket: l,
17
- path: u,
18
- filePath: "",
19
- recursive: !0
20
- })]), _ = h.status === "fulfilled" && h.value != null ? c(h.value) : void 0, v = f.find((e) => e.url === i.id), y = g.status === "fulfilled" ? r(v, g.value.items, _?.about, p) : void 0, b = g.status === "fulfilled" ? n(g.value.items, u) : [], x = g.status === "fulfilled" ? s(g.value.items, u) : e;
21
- if (!(_ == null && y == null)) return {
22
- ..._ == null ? {} : { promptContent: {
23
- content: _.body,
24
- ..._.description == null ? {} : { description: _.description },
25
- files: b,
26
- selectedFileId: x
15
+ let [h, g, _] = await Promise.allSettled([
16
+ d.downloadSkillFile(l, u, e).then(a),
17
+ d.listSkillFiles({
18
+ bucket: l,
19
+ path: u,
20
+ filePath: "",
21
+ recursive: !0
22
+ }),
23
+ d.getSkillMetadata(l, u)
24
+ ]), v = h.status === "fulfilled" && h.value != null ? c(h.value) : void 0, y = _.status === "fulfilled" ? _.value : f.find((e) => e.url === i.id), b = g.status === "fulfilled" ? r(y, g.value.items, v?.about, p) : void 0, x = g.status === "fulfilled" ? n(g.value.items, u) : [], S = g.status === "fulfilled" ? s(g.value.items, u) : e;
25
+ if (!(v == null && b == null)) return {
26
+ ...v == null ? {} : { promptContent: {
27
+ content: v.body,
28
+ ...v.description == null ? {} : { description: v.description },
29
+ files: x,
30
+ selectedFileId: S
27
31
  } },
28
- ...y == null ? {} : { overview: y }
32
+ ...b == null ? {} : { overview: b }
29
33
  };
30
34
  }, [
31
35
  d,
@@ -47,9 +51,7 @@ var d = ({ api: d, skills: f, skillOverviewLabels: p }) => {
47
51
  if (n == null) throw Error("A folder cannot be previewed");
48
52
  let r = await d.downloadSkillFile(t.bucket, t.path, n);
49
53
  if (!r.ok) throw Object.assign(/* @__PURE__ */ Error(`File preview failed with status ${r.status}`), { status: r.status });
50
- let a = await i(r);
51
- if (a == null) throw Error("File exceeds the preview size limit");
52
- let s = r.headers.get("content-type")?.split(";")[0].trim() || void 0;
54
+ let a = await i(r), s = r.headers.get("content-type")?.split(";")[0].trim() || void 0;
53
55
  return {
54
56
  bytes: a,
55
57
  mimeType: s === "application/octet-stream" ? void 0 : s
package/catalog.d.ts CHANGED
@@ -132,6 +132,13 @@ export declare const buildSkillContentTree: (files: SkillMetadataItemDto[], skil
132
132
  * authored it, when it last changed, and its file inventory. Grouping folders
133
133
  * in the file listing are excluded from both the count and the rows. Sizes are
134
134
  * not shown — the skill metadata carries no content-length field.
135
+ *
136
+ * `skill` is the authoritative `getSkillMetadata` response when that request
137
+ * fulfilled; the caller falls back to the catalog listing entry only when it
138
+ * rejected (`useSkillItemDetails`'s `onFetchSkillDetails`). Either way, this
139
+ * function never fills a gap in one source from the other — an absent
140
+ * `author` omits the row and an absent `updatedAt` leaves the updated row's
141
+ * value empty, exactly as `skill` carries it.
135
142
  */
136
143
  export declare const buildSkillOverview: (skill: SkillMetadataItemDto | undefined, files: SkillMetadataItemDto[], about: SkillAboutDetails | undefined, labels: SkillOverviewLabels) => CatalogItemOverview;
137
144
 
@@ -652,6 +659,24 @@ export declare interface PublishApiClient {
652
659
  */
653
660
  export declare const readSkillFileBytes: (response: Response) => Promise<Uint8Array | null>;
654
661
 
662
+ /**
663
+ * Reads a skill file response as raw bytes with no size ceiling, for the
664
+ * supporting-file **preview** path.
665
+ *
666
+ * Previews are user-initiated, one file at a time, and a realistic binary
667
+ * (a PDF, an image) routinely exceeds `SKILL_MANIFEST_MAX_BYTES` — a cap
668
+ * sized for `SKILL.md` frontmatter, not for binaries — so applying that cap
669
+ * here rejected virtually every real PDF before it was ever decoded. This
670
+ * reader therefore never returns `null`: file size is not a failure class on
671
+ * the preview path.
672
+ *
673
+ * `readSkillFileBytes` and `readSkillManifest` keep their
674
+ * `SKILL_MANIFEST_MAX_BYTES` ceiling, because they feed the manifest parse
675
+ * and the textual Content-tab read, where an oversized body must never be
676
+ * decoded into a string.
677
+ */
678
+ export declare const readSkillFilePreviewBytes: (response: Response) => Promise<Uint8Array>;
679
+
655
680
  /**
656
681
  * Reads a skill manifest response as text, or `null` when the body is larger
657
682
  * than `SKILL_MANIFEST_MAX_BYTES`. The size is checked before decoding, so an
@@ -681,7 +706,8 @@ export declare const reconcileFilterTopics: (persistedTopics: ReadonlySet<string
681
706
  */
682
707
  export declare const resolveCatalogPrimaryAction: (item: CatalogItem, fetchPrompt: (item: CatalogItem) => Promise<PromptResponseDto>) => Promise<CatalogPrimaryActionResult>;
683
708
 
684
- export declare const resolveDeploymentFolder: (deployment: Pick<DeploymentItemDto, "isMy" | "sharedWithMe" | "applicationFolder">, labels: DeploymentFolderLabels) => string[];
709
+ /** Resolves a deployment's display folder, including organization applications without a folder path. */
710
+ export declare const resolveDeploymentFolder: (deployment: Pick<DeploymentItemDto, "isMy" | "sharedWithMe" | "applicationFolder"> & Partial<Pick<DeploymentItemDto, "type">>, labels: DeploymentFolderLabels) => string[];
685
711
 
686
712
  /** Returns the MCP resource kind a catalog item's Connect endpoint belongs to, or `null` when the item exposes no MCP endpoint. */
687
713
  export declare const resolveMcpResourceKind: (type: CatalogEntityType, supportsMcp?: boolean) => McpResourceKind | null;
@@ -738,6 +764,12 @@ export declare interface SkillDetailsApi {
738
764
  limit?: number;
739
765
  recursive?: boolean;
740
766
  }, signal?: AbortSignal): Promise<SkillFileListResponseDto>;
767
+ /**
768
+ * Fetches a single skill's own authoritative metadata (`author`,
769
+ * `updatedAt`, and the rest of `SkillMetadataItemDto`) — not the catalog
770
+ * listing entry, which may be sparse for a shared skill.
771
+ */
772
+ getSkillMetadata(bucket: string, path: string, signal?: AbortSignal): Promise<SkillMetadataItemDto>;
741
773
  }
742
774
 
743
775
  /** A skill's parsed manifest details. */
@@ -1199,10 +1231,11 @@ export declare interface UseSkillFilePreviewResult {
1199
1231
 
1200
1232
  /**
1201
1233
  * Headless hook that encapsulates skill detail fetching: manifest download and
1202
- * parse, package file listing, overview construction, and in-package file
1203
- * loads. `useCatalogItemDetails` delegates its skill branch here; hosts that
1204
- * only surface skill details consume this hook directly, without the
1205
- * deployment and prompt ports the full catalog pipeline requires.
1234
+ * parse, package file listing, authoritative metadata fetching, overview
1235
+ * construction, and in-package file loads. `useCatalogItemDetails` delegates
1236
+ * its skill branch here; hosts that only surface skill details consume this
1237
+ * hook directly, without the deployment and prompt ports the full catalog
1238
+ * pipeline requires.
1206
1239
  */
1207
1240
  export declare const useSkillItemDetails: ({ api, skills, skillOverviewLabels, }: UseSkillItemDetailsOptions) => UseSkillItemDetailsResult;
1208
1241
 
package/catalog.js CHANGED
@@ -8,17 +8,17 @@ import { mapDeploymentDetailsDtoToEntityDetails as u, mapEntityDetailsToCatalogD
8
8
  import { mapDeploymentToCatalogItem as p, mapDeploymentToolsetCredentials as m, mapToolsetToCatalogItem as h, resolveDeploymentFolder as g } from "./catalog/map-deployment-to-catalog-item.js";
9
9
  import { buildPromptOverview as _, isOrganisationPromptItem as v, mapPromptToCatalogItem as y } from "./catalog/map-prompt-to-catalog-item.js";
10
10
  import { PUBLIC_SKILL_BUCKET as b, SKILL_LISTING_MAX_PAGES as x, SKILL_LISTING_PAGE_SIZE as S, SKILL_MANIFEST_MAX_BYTES as C, SkillSource as w, parseSkillResourceUrl as T } from "./skill/skill-types.js";
11
- import { buildSkillContentTree as E, buildSkillOverview as D, mapSkillToCatalogItem as O, readSkillFileBytes as k, readSkillManifest as A, resolveSkillFileDownloadPath as j, resolveSkillManifestFileId as M } from "./catalog/map-skill-to-catalog-item.js";
12
- import { McpResourceKind as N, buildApplicationMcpUrl as P, buildConnectApi as F, buildToolsetMcpUrl as I, resolveMcpResourceKind as L } from "./catalog/mcp-endpoint-url.js";
13
- import { getPublicCatalogEntityFolderPath as R, isPublicCatalogEntityId as z, mapPublishConversationResultDto as B, mapPublishHistoryEntryDto as V, toPublishEntityType as H } from "./catalog/publish.js";
14
- import { deriveAvailableTabIds as U, deriveFavoriteItems as W, filterCatalogItemsBySelector as G, filterHiddenOwnedItems as K, reconcileFilterTopics as q } from "./catalog/catalog-derivations.js";
15
- import { CatalogPrimaryActionType as J, resolveCatalogPrimaryAction as Y } from "./catalog/catalog-primary-action.js";
16
- import { useCatalogEditNavigation as X } from "./catalog/useCatalogEditNavigation/useCatalogEditNavigation.js";
17
- import { useSkillItemDetails as Z } from "./catalog/useSkillItemDetails.js";
18
- import { useCatalogItemDetails as Q } from "./catalog/useCatalogItemDetails.js";
19
- import { useCatalogToolsetCredentials as $ } from "./catalog/useCatalogToolsetCredentials/useCatalogToolsetCredentials.js";
20
- import { useSkillDetailsPanelData as ee } from "./catalog/useSkillDetailsPanelData/useSkillDetailsPanelData.js";
21
- import { FavoriteEntityType as te, useFavoriteEntitiesState as ne } from "./catalog/useFavoriteEntitiesState/useFavoriteEntitiesState.js";
22
- import { usePublishFolders as re } from "./catalog/usePublishFolders/usePublishFolders.js";
23
- import { SkillPreviewErrorKind as ie, useSkillFilePreview as ae } from "./skill/useSkillFilePreview.js";
24
- export { s as AuthenticationType, J as CatalogPrimaryActionType, te as FavoriteEntityType, N as McpResourceKind, b as PUBLIC_SKILL_BUCKET, x as SKILL_LISTING_MAX_PAGES, S as SKILL_LISTING_PAGE_SIZE, C as SKILL_MANIFEST_MAX_BYTES, ie as SkillPreviewErrorKind, w as SkillSource, P as buildApplicationMcpUrl, n as buildChatCompletionsUrl, F as buildConnectApi, r as buildDeploymentConnectApi, _ as buildPromptOverview, i as buildResponsesUrl, E as buildSkillContentTree, D as buildSkillOverview, I as buildToolsetMcpUrl, e as createPublishApiClient, U as deriveAvailableTabIds, W as deriveFavoriteItems, a as encodeDeploymentId, G as filterCatalogItemsBySelector, K as filterHiddenOwnedItems, o as findDeploymentByIdOrReference, R as getPublicCatalogEntityFolderPath, v as isOrganisationPromptItem, z as isPublicCatalogEntityId, u as mapDeploymentDetailsDtoToEntityDetails, c as mapDeploymentLimitsDtoToCatalogLimits, l as mapDeploymentLimitsToInput, p as mapDeploymentToCatalogItem, m as mapDeploymentToolsetCredentials, d as mapEntityDetailsToCatalogDetails, y as mapPromptToCatalogItem, B as mapPublishConversationResultDto, V as mapPublishHistoryEntryDto, O as mapSkillToCatalogItem, f as mapToolsetCredentials, h as mapToolsetToCatalogItem, T as parseSkillResourceUrl, k as readSkillFileBytes, A as readSkillManifest, q as reconcileFilterTopics, Y as resolveCatalogPrimaryAction, g as resolveDeploymentFolder, L as resolveMcpResourceKind, j as resolveSkillFileDownloadPath, M as resolveSkillManifestFileId, H as toPublishEntityType, t as toPublishRuleDto, X as useCatalogEditNavigation, Q as useCatalogItemDetails, $ as useCatalogToolsetCredentials, ne as useFavoriteEntitiesState, re as usePublishFolders, ee as useSkillDetailsPanelData, ae as useSkillFilePreview, Z as useSkillItemDetails };
11
+ import { buildSkillContentTree as E, buildSkillOverview as D, mapSkillToCatalogItem as O, readSkillFileBytes as k, readSkillFilePreviewBytes as A, readSkillManifest as j, resolveSkillFileDownloadPath as M, resolveSkillManifestFileId as N } from "./catalog/map-skill-to-catalog-item.js";
12
+ import { McpResourceKind as P, buildApplicationMcpUrl as F, buildConnectApi as I, buildToolsetMcpUrl as L, resolveMcpResourceKind as R } from "./catalog/mcp-endpoint-url.js";
13
+ import { getPublicCatalogEntityFolderPath as z, isPublicCatalogEntityId as B, mapPublishConversationResultDto as V, mapPublishHistoryEntryDto as H, toPublishEntityType as U } from "./catalog/publish.js";
14
+ import { deriveAvailableTabIds as W, deriveFavoriteItems as G, filterCatalogItemsBySelector as K, filterHiddenOwnedItems as q, reconcileFilterTopics as J } from "./catalog/catalog-derivations.js";
15
+ import { CatalogPrimaryActionType as Y, resolveCatalogPrimaryAction as X } from "./catalog/catalog-primary-action.js";
16
+ import { useCatalogEditNavigation as Z } from "./catalog/useCatalogEditNavigation/useCatalogEditNavigation.js";
17
+ import { useSkillItemDetails as Q } from "./catalog/useSkillItemDetails.js";
18
+ import { useCatalogItemDetails as $ } from "./catalog/useCatalogItemDetails.js";
19
+ import { useCatalogToolsetCredentials as ee } from "./catalog/useCatalogToolsetCredentials/useCatalogToolsetCredentials.js";
20
+ import { useSkillDetailsPanelData as te } from "./catalog/useSkillDetailsPanelData/useSkillDetailsPanelData.js";
21
+ import { FavoriteEntityType as ne, useFavoriteEntitiesState as re } from "./catalog/useFavoriteEntitiesState/useFavoriteEntitiesState.js";
22
+ import { usePublishFolders as ie } from "./catalog/usePublishFolders/usePublishFolders.js";
23
+ import { SkillPreviewErrorKind as ae, useSkillFilePreview as oe } from "./skill/useSkillFilePreview.js";
24
+ export { s as AuthenticationType, Y as CatalogPrimaryActionType, ne as FavoriteEntityType, P as McpResourceKind, b as PUBLIC_SKILL_BUCKET, x as SKILL_LISTING_MAX_PAGES, S as SKILL_LISTING_PAGE_SIZE, C as SKILL_MANIFEST_MAX_BYTES, ae as SkillPreviewErrorKind, w as SkillSource, F as buildApplicationMcpUrl, n as buildChatCompletionsUrl, I as buildConnectApi, r as buildDeploymentConnectApi, _ as buildPromptOverview, i as buildResponsesUrl, E as buildSkillContentTree, D as buildSkillOverview, L as buildToolsetMcpUrl, e as createPublishApiClient, W as deriveAvailableTabIds, G as deriveFavoriteItems, a as encodeDeploymentId, K as filterCatalogItemsBySelector, q as filterHiddenOwnedItems, o as findDeploymentByIdOrReference, z as getPublicCatalogEntityFolderPath, v as isOrganisationPromptItem, B as isPublicCatalogEntityId, u as mapDeploymentDetailsDtoToEntityDetails, c as mapDeploymentLimitsDtoToCatalogLimits, l as mapDeploymentLimitsToInput, p as mapDeploymentToCatalogItem, m as mapDeploymentToolsetCredentials, d as mapEntityDetailsToCatalogDetails, y as mapPromptToCatalogItem, V as mapPublishConversationResultDto, H as mapPublishHistoryEntryDto, O as mapSkillToCatalogItem, f as mapToolsetCredentials, h as mapToolsetToCatalogItem, T as parseSkillResourceUrl, k as readSkillFileBytes, A as readSkillFilePreviewBytes, j as readSkillManifest, J as reconcileFilterTopics, X as resolveCatalogPrimaryAction, g as resolveDeploymentFolder, R as resolveMcpResourceKind, M as resolveSkillFileDownloadPath, N as resolveSkillManifestFileId, U as toPublishEntityType, t as toPublishRuleDto, Z as useCatalogEditNavigation, $ as useCatalogItemDetails, ee as useCatalogToolsetCredentials, re as useFavoriteEntitiesState, ie as usePublishFolders, te as useSkillDetailsPanelData, oe as useSkillFilePreview, Q as useSkillItemDetails };
@@ -34,9 +34,20 @@ var t = {
34
34
  e.addHook("afterSanitizeAttributes", (e) => {
35
35
  e.tagName === "A" && e.getAttribute("target") === "_blank" && e.setAttribute("rel", "noopener noreferrer");
36
36
  });
37
- var r = (n) => e.sanitize(n, t), i = (t) => e.sanitize(t, n), a = (e) => typeof e == "string" && e.length > 0, o = ({ title: e, description: t }) => a(e) || a(t), s = (e) => o(e) || a(e.html), c = (e) => o(e) ? JSON.stringify({
38
- title: e.title ?? "",
39
- description: e.description ?? ""
40
- }) : e.html ?? "";
37
+ var r = (n) => e.sanitize(n, t), i = (t) => e.sanitize(t, n), a = (e) => typeof e == "string" && e.length > 0, o = ({ title: e, description: t }) => a(e) || a(t), s = (e) => o(e) || a(e.html), c = (e) => e.map((e) => ({
38
+ title: e.title,
39
+ description: e.description ?? "",
40
+ link: e.link ? {
41
+ label: e.link.label,
42
+ href: e.link.href
43
+ } : null
44
+ })), l = (e) => {
45
+ if (!o(e)) return e.html ?? "";
46
+ let t = {
47
+ title: e.title ?? "",
48
+ description: e.description ?? ""
49
+ }, n = e.items ?? [];
50
+ return n.length > 0 && (t.items = c(n)), JSON.stringify(t);
51
+ };
41
52
  //#endregion
42
- export { c as buildAnnouncementSignature, s as hasAnnouncementContent, o as hasStructuredAnnouncement, r as sanitizeAnnouncementHtml, i as sanitizeAnnouncementMessageHtml };
53
+ export { l as buildAnnouncementSignature, s as hasAnnouncementContent, o as hasStructuredAnnouncement, r as sanitizeAnnouncementHtml, i as sanitizeAnnouncementMessageHtml };
@@ -26,9 +26,16 @@ var o = 700, s = 5, c = (e) => t(e.split("/").filter(Boolean).pop() ?? "file").r
26
26
  })).url,
27
27
  name: a.fileName
28
28
  };
29
- } catch (t) {
30
- if (l(t)) {
29
+ } catch (c) {
30
+ if (l(c)) {
31
31
  if (i.markTaken(a.fileName), o < s) {
32
+ if (t.listFiles) try {
33
+ let e = await t.listFiles({
34
+ bucket: u,
35
+ path: a.path.slice(0, a.path.lastIndexOf("/"))
36
+ });
37
+ for (let t of e.items) i.markTaken(t.name);
38
+ } catch {}
32
39
  a = i.allocate(n);
33
40
  continue;
34
41
  }
@@ -38,10 +45,10 @@ var o = 700, s = 5, c = (e) => t(e.split("/").filter(Boolean).pop() ?? "file").r
38
45
  let e = p.current.splice(0);
39
46
  d?.(e), m.current = null;
40
47
  }, f);
41
- let n = t instanceof Error ? t : /* @__PURE__ */ Error("Network upload failed");
42
- throw n.errorReason = r.Network, n;
48
+ let t = c instanceof Error ? c : /* @__PURE__ */ Error("Network upload failed");
49
+ throw t.errorReason = r.Network, t;
43
50
  }
44
- throw t;
51
+ throw c;
45
52
  }
46
53
  }, [
47
54
  u,
@@ -44,23 +44,19 @@ var p = ({ conversation: p, conversationId: m, bucket: h, isStreaming: g, startS
44
44
  if (g || !m || !p || e === -1 || p.messages[e]?.role !== c.Assistant) return;
45
45
  let t = p.messages[e - 1];
46
46
  if (!t || t.role !== c.User) return;
47
- let n = C();
48
- v((t) => {
49
- if (!t) return t;
50
- let r = {
51
- ...t.messages[e],
52
- content: "",
53
- custom_content: void 0,
54
- wasStoppedByUser: void 0,
55
- stoppedWithoutContent: void 0,
56
- streamErrorMessage: void 0,
57
- deploymentId: n
58
- }, i = {
59
- ...t,
60
- messages: [...t.messages.slice(0, e), r]
61
- };
62
- return y.current = i, i;
63
- }), A((t) => new Set([...t].filter((t) => t < e))), _(m, t.content, e, n, t.custom_content, l(), f.Regenerate);
47
+ let n = C(), r = {
48
+ ...p.messages[e],
49
+ content: "",
50
+ custom_content: void 0,
51
+ wasStoppedByUser: void 0,
52
+ stoppedWithoutContent: void 0,
53
+ streamErrorMessage: void 0,
54
+ deploymentId: n
55
+ }, i = {
56
+ ...p,
57
+ messages: [...p.messages.slice(0, e), r]
58
+ };
59
+ y.current = i, v(i), A((t) => new Set([...t].filter((t) => t < e))), _(m, t.content, e, n, t.custom_content, l(), f.Regenerate);
64
60
  }, [
65
61
  p,
66
62
  m,
@@ -86,7 +86,11 @@ var m = 2e4, h = ({ conversationId: h, state: { setConversation: g, conversation
86
86
  };
87
87
  (async () => {
88
88
  try {
89
- let e = x?.channelId ?? await x?.waitForChannel(m) ?? void 0;
89
+ let e = x?.channelId ?? await x?.waitForChannel(m) ?? void 0, t = N.current.has(h);
90
+ if (D.signal.aborted || E() || t) {
91
+ M.current.get(C)?.generationId === h && M.current.delete(C), E() || R(C), k.current === h && (k.current = null, A.current = null, O(null)), b(C, h), x?.notifyGenerationSettled?.(), t ? N.current.delete(h) : E() || S?.notifyGenerationEnd?.();
92
+ return;
93
+ }
90
94
  v.streamCompletion(C, o, l, F, u, h, f, T, e);
91
95
  } catch (e) {
92
96
  F.onError(e instanceof Error ? e : Error(String(e)));
@@ -1,6 +1,6 @@
1
1
  import { AudioTranscriptionError as e, AudioTranscriptionErrorReason as t } from "./audio-transcription-error.js";
2
2
  //#region src/conversation/useTranscribeAudio/transcription-retry.ts
3
- var n = 2, r = 9e4, i = (e, t) => (t.throwIfAborted(), new Promise((n, r) => {
3
+ var n = 2, r = 6e3, i = (e, t) => (t.throwIfAborted(), new Promise((n, r) => {
4
4
  let i = () => {
5
5
  clearTimeout(a), r(t.reason);
6
6
  }, a = setTimeout(() => {
@@ -28,9 +28,10 @@ var n = 2, r = 9e4, i = (e, t) => (t.throwIfAborted(), new Promise((n, r) => {
28
28
  503,
29
29
  504
30
30
  ].includes(u.status)) throw o;
31
- let d = [429, 503].includes(u.status) ? 3e4 : 2e3, f = Math.max(1e3, a(u.headers.get("retry-after")) ?? d * 2 ** l);
32
- if (l >= n || c + f > r) throw new e(t.Busy);
33
- c += f, await i(f, s);
31
+ if ([429, 503].includes(u.status)) throw new e(t.Busy);
32
+ let d = Math.max(1e3, a(u.headers.get("retry-after")) ?? 2e3 * 2 ** l);
33
+ if (l >= n || c + d > r) throw new e(t.Busy);
34
+ c += d, await i(d, s);
34
35
  }
35
36
  }
36
37
  };
@@ -0,0 +1,7 @@
1
+ import { Message } from '@epam/ai-dial-chat-shared';
2
+ import { OverlayChatMessage } from '@epam/ai-dial-chat-overlay';
3
+
4
+ /** Maps chat messages to the DIAL Chat Overlay protocol's message shape. */
5
+ export declare const toOverlayMessages: (messages: Message[]) => OverlayChatMessage[];
6
+
7
+ export { }
@@ -0,0 +1,2 @@
1
+ import { toOverlayMessages as e } from "./conversation/overlay-messages.js";
2
+ export { e as toOverlayMessages };
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';
@@ -36,6 +35,26 @@ export declare interface AnnouncementContent {
36
35
  title: string | null;
37
36
  description: string | null;
38
37
  html: string | null;
38
+ /** Entries of the popover the banner opens. */
39
+ items?: readonly AnnouncementListItem[];
40
+ }
41
+
42
+ /** One entry of the announcements popover behind the banner's `+N` pill. */
43
+ export declare interface AnnouncementListItem {
44
+ /** Plain-text heading of the entry. */
45
+ title: string;
46
+ /** Supporting copy of the entry, sanitized before it is rendered. */
47
+ description?: string | null;
48
+ /** Optional call to action shown at the end of the entry. */
49
+ link?: AnnouncementListItemLink | null;
50
+ }
51
+
52
+ /** A link rendered as the call to action of an announcements-popover entry. */
53
+ export declare interface AnnouncementListItemLink {
54
+ /** Visible text of the call to action. */
55
+ label: string;
56
+ /** Absolute `http`/`https` target the call to action opens. */
57
+ href: string;
39
58
  }
40
59
 
41
60
  /** State and controls returned by `useAsyncConfirmDialog`. */
@@ -95,7 +114,7 @@ export declare enum AudioTranscriptionErrorReason {
95
114
  Unavailable = "unavailable",
96
115
  /** The recording exceeds the caller's configured size limit. */
97
116
  TooLarge = "tooLarge",
98
- /** The upstream ASR provider stayed rate-limited or unavailable after retrying. */
117
+ /** Recognition is rate-limited, unavailable, or exhausted short gateway retries. */
99
118
  Busy = "busy",
100
119
  /** Recognition failed for any other reason. */
101
120
  Failed = "failed"
@@ -107,9 +126,18 @@ export declare enum AudioTranscriptionErrorReason {
107
126
  * hidden only while the current announcement produces the same signature, so
108
127
  * editing any part of it brings the banner back with no version counter.
109
128
  *
129
+ * Every piece of content the banner surface renders feeds the signature — the
130
+ * title, the description, and the popover entries behind the pill, which live
131
+ * inside the banner and are hidden along with it. Publishing a new entry in
132
+ * that list therefore invalidates an earlier dismissal on its own, even when
133
+ * the banner line itself is untouched.
134
+ *
110
135
  * A legacy-only announcement returns the raw HTML string — byte-identical to
111
136
  * what shipped before the structured fields existed — so dismissals recorded
112
- * by older builds keep working without a storage migration.
137
+ * by older builds keep working without a storage migration. `items` is left
138
+ * out of the payload entirely when the list is empty for the same reason: a
139
+ * deployment that never configured the popover keeps matching the signatures
140
+ * its users already have stored.
113
141
  */
114
142
  export declare const buildAnnouncementSignature: (content: AnnouncementContent) => string;
115
143
 
@@ -633,9 +661,6 @@ export declare interface StreamCompletionOptions {
633
661
  signal: AbortSignal;
634
662
  }
635
663
 
636
- /** Maps chat messages to the DIAL Chat Overlay protocol's message shape. */
637
- export declare const toOverlayMessages: (messages: Message[]) => OverlayChatMessage[];
638
-
639
664
  /** Request shape the host's selected-deployment recognition call accepts. */
640
665
  export declare interface TranscribeWithDeploymentParams {
641
666
  audioUrl: string;
@@ -699,8 +724,8 @@ export declare const useAttachmentUpload: ({ filesApi, bucket, onNetworkError, d
699
724
 
700
725
  /** Parameters for {@link useAttachmentUpload}. */
701
726
  export declare interface UseAttachmentUploadParams {
702
- /** Already-configured generated-client instance used to upload the file. */
703
- filesApi: Pick<FilesApi, 'uploadFile'>;
727
+ /** Already-configured client; optional listing skips stored names after a conflict. */
728
+ filesApi: Pick<FilesApi, 'uploadFile'> & Partial<Pick<FilesApi, 'listFiles'>>;
704
729
  /** DIAL Core bucket the file is uploaded into. */
705
730
  bucket: string | undefined;
706
731
  /** Called with batched filenames after a burst of network-error upload failures. */
package/conversation.js CHANGED
@@ -6,26 +6,25 @@ import { getModelIdFromConversationId as d } from "./conversation/get-model-id-f
6
6
  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
- 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 };
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 };