@epam/ai-dial-chat-hooks 1.2.0-dev.12 → 1.2.0-dev.123

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 (59) hide show
  1. package/api-error/api-error.js +5 -4
  2. package/attachment/useAttachmentValidation/useAttachmentValidation.js +26 -19
  3. package/attachments.d.ts +10 -4
  4. package/catalog/map-deployment-to-catalog-item.js +2 -2
  5. package/catalog/map-skill-to-catalog-item.js +30 -27
  6. package/catalog/publish.js +2 -1
  7. package/catalog/useApplicationCredentials/useApplicationCredentials.js +39 -0
  8. package/catalog/useSkillDetailsPanelData/useSkillDetailsPanelData.js +39 -39
  9. package/catalog/useSkillItemDetails.js +17 -13
  10. package/catalog.d.ts +42 -5
  11. package/catalog.js +6 -5
  12. package/conversation/conversation-transfer/queue.js +8 -5
  13. package/conversation/create-chat-stream-api.js +18 -14
  14. package/conversation/stage.js +23 -0
  15. package/conversation/useAttachmentUpload/useAttachmentUpload.js +12 -5
  16. package/conversation/useConversationHandlers/useConversationHandlers.js +13 -17
  17. package/conversation/useConversationImport/useConversationImport.js +1 -1
  18. package/conversation/useConversationScroll/useConversationScroll.js +68 -64
  19. package/conversation/useConversationStream/apply-chunk.js +1 -1
  20. package/conversation/useConversationStream/useConversationStream.js +87 -78
  21. package/conversation-overlay.d.ts +7 -0
  22. package/conversation-overlay.js +2 -0
  23. package/conversation.d.ts +127 -6
  24. package/conversation.js +30 -29
  25. package/file-manager-canvas.d.ts +398 -0
  26. package/file-manager-canvas.js +2 -0
  27. package/file-manager.d.ts +71 -330
  28. package/file-manager.js +15 -15
  29. package/files/attachment-canvas.js +51 -13
  30. package/files/attachment-types.js +14 -13
  31. package/files/useDialFileManagerTabConfig/useDialFileManagerTabConfig.js +1 -5
  32. package/files/useFileAttachmentPicker/useFileAttachmentPicker.js +43 -0
  33. package/index.d.ts +736 -32
  34. package/index.js +123 -111
  35. package/mcp-apps/useMcpAppHostAdapter/useMcpAppHostAdapter.js +7 -5
  36. package/mcp-apps/useMcpAppHostContext/useMcpAppHostContext.js +1 -1
  37. package/mcp-apps/useMcpAppTools/useMcpAppTools.js +1 -1
  38. package/mcp-apps/useOpenMcpAppCanvas/useOpenMcpAppCanvas.js +25 -23
  39. package/mcp-apps.d.ts +8 -6
  40. package/package.json +37 -18
  41. package/scheduled-task/scheduled-task-description.js +77 -0
  42. package/scheduled-task/scheduled-task-preparation.js +24 -0
  43. package/scheduled-task/scheduled-task-trigger.js +7 -2
  44. package/scheduled-task/scheduled-tasks-api-client.js +19 -0
  45. package/scheduled-task/use-scheduled-task-runs.js +82 -0
  46. package/scheduled-task/use-scheduled-tasks.js +93 -0
  47. package/scheduled-tasks.d.ts +180 -3
  48. package/scheduled-tasks.js +7 -2
  49. package/skill/skill.js +10 -7
  50. package/skill/useSkillArchiveImport/useSkillArchiveImport.js +75 -0
  51. package/skill/useSkillEditorLoad.js +29 -28
  52. package/skill/useSkillEditorSubmit.js +92 -75
  53. package/skill-editor.d.ts +107 -0
  54. package/skill-editor.js +9 -8
  55. package/usage/map-usage-data-to-dashboard.js +66 -0
  56. package/usage/map-user-usage-to-model-limits.js +160 -0
  57. package/usage.d.ts +120 -0
  58. package/usage.js +3 -0
  59. package/utils.d.ts +3 -1
@@ -26,19 +26,20 @@ var e = (e) => typeof e == "object" && !!e, t = (t) => {
26
26
  }
27
27
  return e instanceof Error && e.message ? e.message : null;
28
28
  }, d = async (t) => {
29
- let r = s(t), i = r?.status, a = null, c, l = !1;
29
+ let r = s(t), i = r?.status, a = null, c, l = !1, u;
30
30
  if (r) try {
31
31
  let t = await (typeof r.clone == "function" ? r.clone() : r).json();
32
- a = n(t), e(t) && (c = o(t.traceparent));
32
+ a = n(t), e(t) && (u = typeof t.code == "string" ? t.code : void 0, c = o(t.traceparent));
33
33
  } catch {
34
34
  l = !0;
35
35
  }
36
36
  !l && a === null && t instanceof Error && t.message && (a = t.message);
37
- let u = c ?? o(typeof r?.headers?.get == "function" ? r.headers.get("traceparent") : void 0);
37
+ let d = c ?? o(typeof r?.headers?.get == "function" ? r.headers.get("traceparent") : void 0);
38
38
  return {
39
39
  status: i,
40
40
  message: a,
41
- traceId: u
41
+ traceId: d,
42
+ ...u ? { code: u } : {}
42
43
  };
43
44
  };
44
45
  //#endregion
@@ -4,31 +4,38 @@ import { useCallback as n, useEffect as r, useMemo as i, useRef as a } from "rea
4
4
  import { isMimeTypeAllowed as o, mimeTypesToExtensionLabels as s } from "@epam/ai-dial-attachment-input";
5
5
  //#region src/attachment/useAttachmentValidation/useAttachmentValidation.ts
6
6
  var c = 100, l = /* @__PURE__ */ function(e) {
7
- return e.NoTypesAllowed = "noTypesAllowed", e.UnsupportedType = "unsupportedType", e;
8
- }({}), u = ({ allowedMimeTypes: l, onValidationError: u, debounceMs: d = c }) => {
9
- let f = a(l);
10
- (f.current.length !== l.length || f.current.some((e, t) => e !== l[t])) && (f.current = l);
11
- let p = f.current, m = p.length > 0, h = i(() => e(p), [p]), g = a(null);
7
+ return e.NoTypesAllowed = "noTypesAllowed", e.UnsupportedType = "unsupportedType", e.FileTooLarge = "fileTooLarge", e;
8
+ }({}), u = ({ allowedMimeTypes: l, maxFileSizeBytes: u, onValidationError: d, debounceMs: f = c }) => {
9
+ let p = a(l);
10
+ (p.current.length !== l.length || p.current.some((e, t) => e !== l[t])) && (p.current = l);
11
+ let m = p.current, h = m.length > 0, g = i(() => e(m), [m]), _ = a(null), v = a(null);
12
12
  return r(() => () => {
13
- g.current != null && clearTimeout(g.current);
13
+ _.current != null && clearTimeout(_.current), v.current != null && clearTimeout(v.current);
14
14
  }, []), {
15
- inputAttachmentTypes: p,
16
- isAttachmentsAllowed: m,
15
+ inputAttachmentTypes: m,
16
+ isAttachmentsAllowed: h,
17
17
  validateAttachment: n((e) => {
18
- if (!o(e.contentType, p)) return g.current != null && clearTimeout(g.current), g.current = setTimeout(() => {
19
- let e = p.length === 0;
20
- u?.({
18
+ if (!o(e.contentType, m)) return _.current != null && clearTimeout(_.current), _.current = setTimeout(() => {
19
+ let e = m.length === 0;
20
+ d?.({
21
21
  reason: e ? "noTypesAllowed" : "unsupportedType",
22
- allowedMimeTypes: p,
23
- ...e ? {} : { formats: s(p) }
24
- }), g.current = null;
25
- }, d), t.UnsupportedType;
22
+ allowedMimeTypes: m,
23
+ ...e ? {} : { formats: s(m) }
24
+ }), _.current = null;
25
+ }, f), t.UnsupportedType;
26
+ if (u != null && e.file.size > u) return v.current != null && clearTimeout(v.current), v.current = setTimeout(() => {
27
+ d?.({
28
+ reason: "fileTooLarge",
29
+ maxFileSizeBytes: u
30
+ }), v.current = null;
31
+ }, f), t.FileTooLarge;
26
32
  }, [
27
- p,
28
- d,
29
- u
33
+ m,
34
+ u,
35
+ f,
36
+ d
30
37
  ]),
31
- fileAccept: h
38
+ fileAccept: g
32
39
  };
33
40
  };
34
41
  //#endregion
package/attachments.d.ts CHANGED
@@ -6,10 +6,12 @@ import { DisplayAttachment } from '@epam/ai-dial-chat-shared';
6
6
  export declare interface AttachmentValidationErrorEvent {
7
7
  /** Why the attachment(s) were rejected. */
8
8
  reason: AttachmentValidationErrorReason;
9
- /** The resolved MIME types the caller currently allows (possibly empty). */
10
- allowedMimeTypes: string[];
9
+ /** The resolved MIME types the caller currently allows (possibly empty). Present only when `reason` is `NoTypesAllowed` or `UnsupportedType`. */
10
+ allowedMimeTypes?: string[];
11
11
  /** Already-formatted, non-translated extension list (e.g. ".png, .jpg"), present only when `reason` is `UnsupportedType`. */
12
12
  formats?: string;
13
+ /** The size limit, in bytes, that was exceeded. Present only when `reason` is `FileTooLarge`. */
14
+ maxFileSizeBytes?: number;
13
15
  }
14
16
 
15
17
  /** Reason a rejected attachment failed validation. */
@@ -17,7 +19,9 @@ export declare enum AttachmentValidationErrorReason {
17
19
  /** No MIME types are allowed at all — attachments are disabled entirely. */
18
20
  NoTypesAllowed = "noTypesAllowed",
19
21
  /** The attachment's content type is not among the allowed MIME types. */
20
- UnsupportedType = "unsupportedType"
22
+ UnsupportedType = "unsupportedType",
23
+ /** The attachment's file size exceeds `maxFileSizeBytes`. */
24
+ FileTooLarge = "fileTooLarge"
21
25
  }
22
26
 
23
27
  /**
@@ -61,12 +65,14 @@ export declare interface UseAttachmentActionResult {
61
65
  * MIME types, debouncing a burst of rejected files into a single
62
66
  * `onValidationError` call rather than firing one per file.
63
67
  */
64
- export declare const useAttachmentValidation: ({ allowedMimeTypes, onValidationError, debounceMs, }: UseAttachmentValidationParams) => UseAttachmentValidationResult;
68
+ export declare const useAttachmentValidation: ({ allowedMimeTypes, maxFileSizeBytes, onValidationError, debounceMs, }: UseAttachmentValidationParams) => UseAttachmentValidationResult;
65
69
 
66
70
  /** Parameters for {@link useAttachmentValidation}. */
67
71
  export declare interface UseAttachmentValidationParams {
68
72
  /** Resolved MIME types currently allowed for attachments. */
69
73
  allowedMimeTypes: string[];
74
+ /** Maximum attachment file size, in bytes. When omitted, no file is rejected for size. */
75
+ maxFileSizeBytes?: number;
70
76
  /** Called with a structured event when a rejected attachment is reported, at most once per debounce window. */
71
77
  onValidationError?: (event: AttachmentValidationErrorEvent) => void;
72
78
  /** Debounce window, in ms, before firing `onValidationError` for a rejected file. Defaults to `100`. */
@@ -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 }) => {
@@ -10,8 +10,11 @@ var c = {
10
10
  [r.Personal]: "personal",
11
11
  [r.SharedWithMe]: "shared",
12
12
  [r.Public]: "public"
13
- }, l = (t, n, r) => [r[c[n]], ...(t ?? "").split("/").filter(Boolean).map(e)], u = (e, { folderLabels: t, source: n, favoriteIds: o }) => {
14
- let s = o.has(e.url), c = n === r.Public, u = n === r.Personal;
13
+ }, l = (t, n) => {
14
+ let r = (n ?? "").split("/").filter(Boolean), i = t.split("/").filter(Boolean).slice(2, -1);
15
+ return i.length === r.length ? i.map(e) : r;
16
+ }, u = (e, t, n) => [n[c[t]], ...l(e.url, e.parentPath)], d = (e, { folderLabels: t, source: n, favoriteIds: o }) => {
17
+ let s = o.has(e.url), c = n === r.Public, l = n === r.Personal;
15
18
  return {
16
19
  id: e.url,
17
20
  type: i.Skill,
@@ -26,12 +29,12 @@ var c = {
26
29
  topics: [],
27
30
  isUserFavorite: s,
28
31
  isStarred: s,
29
- isMyApp: u && (e.isMy ?? !0),
32
+ isMyApp: l && (e.isMy ?? !0),
30
33
  sharedWithMe: e.sharedWithMe ?? n === r.SharedWithMe,
31
- isEditable: !c && (e.canEdit ?? u),
32
- folder: l(e.parentPath, n, t)
34
+ isEditable: !c && (e.canEdit ?? l),
35
+ folder: u(e, n, t)
33
36
  };
34
- }, d = (e) => e.join(" · "), f = (e, t) => {
37
+ }, f = (e) => e.join(" · "), p = (e, t) => {
35
38
  if (e == null) return null;
36
39
  let n = [];
37
40
  return e.whenToUse != null && n.push({
@@ -39,25 +42,25 @@ var c = {
39
42
  value: e.whenToUse
40
43
  }), e.allowedTools?.length && n.push({
41
44
  label: t.allowedToolsLabel,
42
- value: d(e.allowedTools)
45
+ value: f(e.allowedTools)
43
46
  }), e.bundledResources?.length && n.push({
44
47
  label: t.bundledResourcesLabel,
45
- value: d(e.bundledResources)
48
+ value: f(e.bundledResources)
46
49
  }), n.length === 0 ? null : {
47
50
  title: t.specificationSectionTitle,
48
51
  specs: n
49
52
  };
50
- }, p = (e) => e.filter((e) => e.nodeType === s.Item), m = (e, n) => {
53
+ }, m = (e) => e.filter((e) => e.nodeType === s.Item), h = (e, n) => {
51
54
  let r = t(n), i = r ? `${r}/files` : "files";
52
- return p(e).find((e) => {
55
+ return m(e).find((e) => {
53
56
  let n = t(e.path);
54
57
  return n === "SKILL.md" || n === "files/SKILL.md" || n === `${i}/SKILL.md`;
55
58
  })?.path ?? "SKILL.md";
56
- }, h = (e, n) => {
59
+ }, g = (e, n) => {
57
60
  let r = t(e), i = t(n), a = i ? `${i}/files` : "files";
58
61
  return r === "" || r === "files" || r === a ? null : r.startsWith(`${a}/`) ? r.slice(a.length + 1) : r.startsWith("files/") ? r.slice(6) : r;
59
- }, g = (e, t) => h(e, t), _ = (e, t, r, i) => {
60
- let a = [], o = f(r, i);
62
+ }, _ = (e, t) => g(e, t), v = (e, t, r, i) => {
63
+ let a = [], o = p(r, i);
61
64
  o != null && a.push(o);
62
65
  let s = [];
63
66
  return e?.author && s.push({
@@ -68,23 +71,23 @@ var c = {
68
71
  value: e?.updatedAt ? n(e.updatedAt) : ""
69
72
  }), s.push({
70
73
  label: i.fileCountLabel,
71
- value: String(p(t).length)
74
+ value: String(m(t).length)
72
75
  }), a.push({
73
76
  title: i.detailsSectionTitle,
74
77
  specs: s
75
78
  }), { sections: a };
76
- }, v = (e, t, n) => {
79
+ }, y = (e, t, n) => {
77
80
  if (e === "") return n;
78
81
  let r = t.get(e);
79
82
  if (r != null) return r.items;
80
- let i = e.split("/"), a = v(i.slice(0, -1).join("/"), t, n), s = {
83
+ let i = e.split("/"), a = y(i.slice(0, -1).join("/"), t, n), s = {
81
84
  type: o.Folder,
82
85
  id: e,
83
86
  name: i[i.length - 1],
84
87
  items: []
85
88
  };
86
89
  return t.set(e, s), a.push(s), s.items;
87
- }, y = (e, t) => {
90
+ }, b = (e, t) => {
88
91
  e.sort((e, n) => {
89
92
  if (t) {
90
93
  if (e.name === "SKILL.md") return -1;
@@ -92,32 +95,32 @@ var c = {
92
95
  }
93
96
  return e.name.localeCompare(n.name);
94
97
  });
95
- for (let t of e) t.type === o.Folder && y(t.items, !1);
96
- }, b = (e, t) => {
98
+ for (let t of e) t.type === o.Folder && b(t.items, !1);
99
+ }, x = (e, t) => {
97
100
  let n = /* @__PURE__ */ new Map(), r = [];
98
101
  for (let i of e) {
99
- let e = h(i.path, t);
102
+ let e = g(i.path, t);
100
103
  if (e == null) continue;
101
104
  if (i.nodeType === s.Folder) {
102
- v(e, n, r);
105
+ y(e, n, r);
103
106
  continue;
104
107
  }
105
108
  let a = e.lastIndexOf("/");
106
- v(a === -1 ? "" : e.slice(0, a), n, r).push({
109
+ y(a === -1 ? "" : e.slice(0, a), n, r).push({
107
110
  type: o.File,
108
111
  id: i.path,
109
112
  name: i.name
110
113
  });
111
114
  }
112
- return y(r, !0), r;
113
- }, x = async (e) => {
115
+ return b(r, !0), r;
116
+ }, S = async (e) => {
114
117
  let t = Number(e.headers.get("content-length"));
115
118
  if (Number.isFinite(t) && t > 262144) return null;
116
119
  let n = await e.arrayBuffer();
117
120
  return n.byteLength > 262144 ? null : new Uint8Array(n);
118
- }, S = async (e) => new Uint8Array(await e.arrayBuffer()), C = async (e) => {
119
- let t = await x(e);
121
+ }, C = async (e) => new Uint8Array(await e.arrayBuffer()), w = async (e) => {
122
+ let t = await S(e);
120
123
  return t == null ? null : new TextDecoder().decode(t);
121
124
  };
122
125
  //#endregion
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 };
126
+ export { x as buildSkillContentTree, v as buildSkillOverview, d as mapSkillToCatalogItem, S as readSkillFileBytes, C as readSkillFilePreviewBytes, w as readSkillManifest, _ as resolveSkillFileDownloadPath, h as resolveSkillManifestFileId };
@@ -10,7 +10,8 @@ var n = {
10
10
  }, r = (e) => n[e], i = "public", a = (e) => e.split("/")[1] === i, o = (t) => a(t) ? t.split("/").slice(2, -1).map(e) : [], s = (e) => ({
11
11
  version: e.version,
12
12
  publishedAt: Date.parse(e.publishedAt),
13
- folderPath: e.folderPath.split("/").filter(Boolean)
13
+ folderPath: e.folderPath.split("/").filter(Boolean),
14
+ publishCredentials: e.publishCredentials
14
15
  }), c = (e) => ({
15
16
  publishedAt: Date.parse(e.publishedAt),
16
17
  folderPath: e.folderPath.split("/").filter(Boolean)
@@ -0,0 +1,39 @@
1
+ import { useCallback as e, useEffect as t, useRef as n, useState as r } from "react";
2
+ //#region src/catalog/useApplicationCredentials/useApplicationCredentials.ts
3
+ var i = ({ appId: i, externalServicesClient: a, offlineCredentialsClient: o }) => {
4
+ let [s, c] = r([]), [l, u] = r(!1), [d, f] = r(!0), [p, m] = r(!1), h = n(0), g = n(null), _ = e(async () => {
5
+ if (g.current !== i) return;
6
+ let e = ++h.current;
7
+ f(!0), m(!1);
8
+ try {
9
+ let t = await a.listExternalServices({ appId: i });
10
+ if (h.current !== e) return;
11
+ let n = t.some((e) => e.authenticationType === "DIAL_NATIVE") ? await o.getOfflineCredentials() : void 0;
12
+ if (h.current !== e) return;
13
+ c(t.filter((e) => e.authenticationType !== "NONE")), u(n?.connected ?? !1);
14
+ } catch {
15
+ h.current === e && m(!0);
16
+ } finally {
17
+ h.current === e && f(!1);
18
+ }
19
+ }, [
20
+ i,
21
+ a,
22
+ o
23
+ ]), v = e(() => {
24
+ g.current = null, h.current++;
25
+ }, []);
26
+ return t(() => (g.current = i, c([]), f(!0), u(!1), _(), v), [
27
+ i,
28
+ _,
29
+ v
30
+ ]), {
31
+ services: s,
32
+ isOfflineConnected: l,
33
+ isLoading: d,
34
+ hasError: p,
35
+ refresh: _
36
+ };
37
+ };
38
+ //#endregion
39
+ export { i as useApplicationCredentials };
@@ -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 };
@@ -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,
package/catalog.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ApplicationExternalServiceDto } from '@epam/ai-dial-chat-api-client';
1
2
  import { CatalogContentTreeNode } from '@epam/ai-dial-catalog';
2
3
  import { CatalogEntityType } from '@epam/ai-dial-chat-shared';
3
4
  import { CatalogItem } from '@epam/ai-dial-catalog';
@@ -14,8 +15,10 @@ import { DeploymentLimitsResponseDto } from '@epam/ai-dial-chat-api-client';
14
15
  import { DialToolsetAuthSettingsDto } from '@epam/ai-dial-chat-api-client';
15
16
  import { DialToolsetDto } from '@epam/ai-dial-chat-api-client';
16
17
  import { DropdownItem } from '@epam/ai-dial-ui-kit';
18
+ import { ExternalServicesApi } from '@epam/ai-dial-chat-api-client';
17
19
  import { ListFilesResponseDto } from '@epam/ai-dial-chat-api-client';
18
20
  import { NotificationVariant } from '@epam/ai-dial-ui-kit';
21
+ import { OfflineCredentialsApi } from '@epam/ai-dial-chat-api-client';
19
22
  import { PromptResponseDto } from '@epam/ai-dial-chat-api-client';
20
23
  import { PublicationRule } from '@epam/ai-dial-publish-panel';
21
24
  import { PublishApi } from '@epam/ai-dial-chat-api-client';
@@ -132,6 +135,13 @@ export declare const buildSkillContentTree: (files: SkillMetadataItemDto[], skil
132
135
  * authored it, when it last changed, and its file inventory. Grouping folders
133
136
  * in the file listing are excluded from both the count and the rows. Sizes are
134
137
  * not shown — the skill metadata carries no content-length field.
138
+ *
139
+ * `skill` is the authoritative `getSkillMetadata` response when that request
140
+ * fulfilled; the caller falls back to the catalog listing entry only when it
141
+ * rejected (`useSkillItemDetails`'s `onFetchSkillDetails`). Either way, this
142
+ * function never fills a gap in one source from the other — an absent
143
+ * `author` omits the row and an absent `updatedAt` leaves the updated row's
144
+ * value empty, exactly as `skill` carries it.
135
145
  */
136
146
  export declare const buildSkillOverview: (skill: SkillMetadataItemDto | undefined, files: SkillMetadataItemDto[], about: SkillAboutDetails | undefined, labels: SkillOverviewLabels) => CatalogItemOverview;
137
147
 
@@ -699,7 +709,8 @@ export declare const reconcileFilterTopics: (persistedTopics: ReadonlySet<string
699
709
  */
700
710
  export declare const resolveCatalogPrimaryAction: (item: CatalogItem, fetchPrompt: (item: CatalogItem) => Promise<PromptResponseDto>) => Promise<CatalogPrimaryActionResult>;
701
711
 
702
- export declare const resolveDeploymentFolder: (deployment: Pick<DeploymentItemDto, "isMy" | "sharedWithMe" | "applicationFolder">, labels: DeploymentFolderLabels) => string[];
712
+ /** Resolves a deployment's display folder, including organization applications without a folder path. */
713
+ export declare const resolveDeploymentFolder: (deployment: Pick<DeploymentItemDto, "isMy" | "sharedWithMe" | "applicationFolder"> & Partial<Pick<DeploymentItemDto, "type">>, labels: DeploymentFolderLabels) => string[];
703
714
 
704
715
  /** Returns the MCP resource kind a catalog item's Connect endpoint belongs to, or `null` when the item exposes no MCP endpoint. */
705
716
  export declare const resolveMcpResourceKind: (type: CatalogEntityType, supportsMcp?: boolean) => McpResourceKind | null;
@@ -756,6 +767,12 @@ export declare interface SkillDetailsApi {
756
767
  limit?: number;
757
768
  recursive?: boolean;
758
769
  }, signal?: AbortSignal): Promise<SkillFileListResponseDto>;
770
+ /**
771
+ * Fetches a single skill's own authoritative metadata (`author`,
772
+ * `updatedAt`, and the rest of `SkillMetadataItemDto`) — not the catalog
773
+ * listing entry, which may be sparse for a shared skill.
774
+ */
775
+ getSkillMetadata(bucket: string, path: string, signal?: AbortSignal): Promise<SkillMetadataItemDto>;
759
776
  }
760
777
 
761
778
  /** A skill's parsed manifest details. */
@@ -898,6 +915,25 @@ export declare const toPublishEntityType: (type: CatalogEntityType) => CatalogPu
898
915
  */
899
916
  export declare const toPublishRuleDto: (rule: PublicationRule) => PublishRuleDto;
900
917
 
918
+ /** Loads fresh service statuses without coupling proactive credentials to a live completion. */
919
+ export declare const useApplicationCredentials: ({ appId, externalServicesClient, offlineCredentialsClient, }: UseApplicationCredentialsParams) => {
920
+ services: ApplicationExternalServiceDto[];
921
+ isOfflineConnected: boolean;
922
+ isLoading: boolean;
923
+ hasError: boolean;
924
+ refresh: () => Promise<void>;
925
+ };
926
+
927
+ /** Configured operations for loading application credential metadata. */
928
+ export declare interface UseApplicationCredentialsParams {
929
+ /** Application identifier passed through to the configured client. */
930
+ appId: string;
931
+ /** Host-configured external-services API. */
932
+ externalServicesClient: Pick<ExternalServicesApi, 'listExternalServices'>;
933
+ /** Host-configured offline-credentials API. */
934
+ offlineCredentialsClient: Pick<OfflineCredentialsApi, 'getOfflineCredentials'>;
935
+ }
936
+
901
937
  /**
902
938
  * Owns the catalog's edit/delete/create-menu navigation: routing the details
903
939
  * panel's Edit action to the right editor URL for each item type, deleting an
@@ -1217,10 +1253,11 @@ export declare interface UseSkillFilePreviewResult {
1217
1253
 
1218
1254
  /**
1219
1255
  * Headless hook that encapsulates skill detail fetching: manifest download and
1220
- * parse, package file listing, overview construction, and in-package file
1221
- * loads. `useCatalogItemDetails` delegates its skill branch here; hosts that
1222
- * only surface skill details consume this hook directly, without the
1223
- * deployment and prompt ports the full catalog pipeline requires.
1256
+ * parse, package file listing, authoritative metadata fetching, overview
1257
+ * construction, and in-package file loads. `useCatalogItemDetails` delegates
1258
+ * its skill branch here; hosts that only surface skill details consume this
1259
+ * hook directly, without the deployment and prompt ports the full catalog
1260
+ * pipeline requires.
1224
1261
  */
1225
1262
  export declare const useSkillItemDetails: ({ api, skills, skillOverviewLabels, }: UseSkillItemDetailsOptions) => UseSkillItemDetailsResult;
1226
1263
 
package/catalog.js CHANGED
@@ -17,8 +17,9 @@ import { useCatalogEditNavigation as Z } from "./catalog/useCatalogEditNavigatio
17
17
  import { useSkillItemDetails as Q } from "./catalog/useSkillItemDetails.js";
18
18
  import { useCatalogItemDetails as $ } from "./catalog/useCatalogItemDetails.js";
19
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 };
20
+ import { useApplicationCredentials as te } from "./catalog/useApplicationCredentials/useApplicationCredentials.js";
21
+ import { useSkillDetailsPanelData as ne } from "./catalog/useSkillDetailsPanelData/useSkillDetailsPanelData.js";
22
+ import { FavoriteEntityType as re, useFavoriteEntitiesState as ie } from "./catalog/useFavoriteEntitiesState/useFavoriteEntitiesState.js";
23
+ import { usePublishFolders as ae } from "./catalog/usePublishFolders/usePublishFolders.js";
24
+ import { SkillPreviewErrorKind as oe, useSkillFilePreview as se } from "./skill/useSkillFilePreview.js";
25
+ export { s as AuthenticationType, Y as CatalogPrimaryActionType, re 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, oe 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, te as useApplicationCredentials, Z as useCatalogEditNavigation, $ as useCatalogItemDetails, ee as useCatalogToolsetCredentials, ie as useFavoriteEntitiesState, ae as usePublishFolders, ne as useSkillDetailsPanelData, se as useSkillFilePreview, Q as useSkillItemDetails };
@@ -27,13 +27,14 @@ var o = () => {
27
27
  progress: { percent: 100 },
28
28
  errorCode: void 0
29
29
  });
30
- }, [u]), m = n((t, n) => {
31
- s((r) => r.map((r) => r.id !== t || r.status !== e.InProgress ? r : {
32
- ...r,
30
+ }, [u]), m = n((t, n, r) => {
31
+ s((i) => i.map((i) => i.id !== t || i.status !== e.InProgress ? i : {
32
+ ...i,
33
33
  status: e.Warning,
34
34
  progress: { percent: 100 },
35
35
  errorCode: void 0,
36
- warningCode: n
36
+ warningCode: n,
37
+ warningNames: r
37
38
  }));
38
39
  }, []), h = n((t, n) => {
39
40
  u(t, {
@@ -57,7 +58,9 @@ var o = () => {
57
58
  return l.current.set(t, () => (u(t, {
58
59
  status: e.InProgress,
59
60
  progress: { percent: 0 },
60
- errorCode: void 0
61
+ errorCode: void 0,
62
+ warningCode: void 0,
63
+ warningNames: void 0
61
64
  }), r())), r();
62
65
  }, [u]);
63
66
  return r(() => {