@epam/ai-dial-chat-hooks 1.2.0-dev.20 → 1.2.0-dev.207

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 (89) 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/catalog-derivations.js +1 -1
  5. package/catalog/deployment-id.js +8 -2
  6. package/catalog/map-deployment-limits-to-input.js +81 -9
  7. package/catalog/map-deployment-to-catalog-item.js +34 -34
  8. package/catalog/map-entity-details-to-catalog.js +7 -0
  9. package/catalog/map-skill-to-catalog-item.js +30 -27
  10. package/catalog/publish.js +6 -5
  11. package/catalog/useApplicationCredentials/useApplicationCredentials.js +39 -0
  12. package/catalog/useSkillDetailsPanelData/useSkillDetailsPanelData.js +39 -39
  13. package/catalog/useSkillItemDetails.js +17 -13
  14. package/catalog.d.ts +116 -20
  15. package/catalog.js +23 -22
  16. package/conversation/conversation-transfer/export-conversation.js +24 -16
  17. package/conversation/conversation-transfer/import-conversation.js +80 -31
  18. package/conversation/conversation-transfer/queue.js +8 -5
  19. package/conversation/create-chat-stream-api.js +85 -49
  20. package/conversation/message-utils.js +44 -2
  21. package/conversation/stage.js +23 -0
  22. package/conversation/useConversationExport/useConversationExport.js +9 -9
  23. package/conversation/useConversationHandlers/useConversationHandlers.js +16 -5
  24. package/conversation/useConversationImport/useConversationImport.js +123 -121
  25. package/conversation/useConversationPanelItems/useConversationPanelItems.js +2 -3
  26. package/conversation/useConversationScroll/useConversationScroll.js +68 -64
  27. package/conversation/useConversationStream/apply-chunk.js +1 -1
  28. package/conversation/useConversationStream/generation-resume.js +104 -63
  29. package/conversation/useConversationStream/useConversationStream.js +183 -108
  30. package/conversation/useMessageSelectionReply/useMessageSelectionReply.js +189 -0
  31. package/conversation-overlay.d.ts +7 -0
  32. package/conversation-overlay.js +2 -0
  33. package/conversation-sources/useConversationSources/useConversationSources.js +31 -24
  34. package/conversation-sources.d.ts +1 -1
  35. package/conversation-transfer.d.ts +2 -1
  36. package/conversation.d.ts +241 -13
  37. package/conversation.js +32 -30
  38. package/file-manager-canvas.d.ts +398 -0
  39. package/file-manager-canvas.js +2 -0
  40. package/file-manager.d.ts +153 -350
  41. package/file-manager.js +25 -24
  42. package/files/attachment-canvas.js +40 -1
  43. package/files/attachment-types.js +14 -13
  44. package/files/dial-file-manager-mapping.util.js +2 -1
  45. package/files/dial-file-manager-path.util.js +23 -1
  46. package/files/dial-file-manager.model.js +23 -19
  47. package/files/dial-file-manager.types.js +3 -3
  48. package/files/useDialFileListing/useDialFileListing.js +157 -145
  49. package/files/useDialFileManager/useDialFileManager.js +132 -128
  50. package/files/useDialFileManagerSections/useDialFileManagerSections.js +155 -0
  51. package/files/useDialFileManagerTabConfig/useDialFileManagerTabConfig.js +20 -19
  52. package/files/useDialFileMutations/useDialFileMutations.js +33 -32
  53. package/files/useDialFileUploadBatch/useDialFileUploadBatch.js +117 -110
  54. package/files/useFileAttachmentPicker/useFileAttachmentPicker.js +43 -0
  55. package/index.d.ts +1068 -81
  56. package/index.js +136 -122
  57. package/mcp-apps/useMcpAppHostAdapter/useMcpAppHostAdapter.js +7 -5
  58. package/mcp-apps/useMcpAppHostContext/useMcpAppHostContext.js +1 -1
  59. package/mcp-apps/useMcpAppTools/useMcpAppTools.js +1 -1
  60. package/mcp-apps/useOpenMcpAppCanvas/useOpenMcpAppCanvas.js +25 -23
  61. package/mcp-apps.d.ts +8 -6
  62. package/oauth/toolset-id.js +5 -3
  63. package/oauth/useToolsetLogin/useToolsetLogin.js +8 -8
  64. package/oauth.d.ts +32 -0
  65. package/oauth.js +9 -9
  66. package/package.json +36 -21
  67. package/scheduled-task/scheduled-task-description.js +77 -0
  68. package/scheduled-task/scheduled-task-preparation.js +24 -0
  69. package/scheduled-task/scheduled-task-trigger.js +7 -2
  70. package/scheduled-task/scheduled-tasks-api-client.js +19 -0
  71. package/scheduled-task/use-scheduled-task-runs.js +194 -0
  72. package/scheduled-task/use-scheduled-tasks.js +93 -0
  73. package/scheduled-tasks.d.ts +195 -3
  74. package/scheduled-tasks.js +7 -2
  75. package/skill/skill-archive.js +19 -0
  76. package/skill/skill-types.js +8 -7
  77. package/skill/skill.js +42 -27
  78. package/skill/useSkillArchiveImport/useSkillArchiveImport.js +79 -0
  79. package/skill/useSkillEditorLoad.js +29 -28
  80. package/skill/useSkillEditorSubmit.js +108 -84
  81. package/skill/useSkillFileActions.js +70 -58
  82. package/skill-editor.d.ts +133 -3
  83. package/skill-editor.js +9 -8
  84. package/usage/map-usage-data-to-dashboard.js +66 -0
  85. package/usage/map-user-usage-to-model-limits.js +202 -0
  86. package/usage.d.ts +125 -0
  87. package/usage.js +3 -0
  88. package/usePageFileDrag/usePageFileDrag.js +3 -3
  89. package/utils.d.ts +8 -6
@@ -1,4 +1,5 @@
1
- import { OAuthResourceKind as e, ToolsetAuthStatus as t, ToolsetAuthTypes as n, ToolsetCredentialsLevel as r, ToolsetOAuthInitiationResultType as i, ToolsetOAuthResultType as a } from "../types.js";
1
+ import { OAuthResourceKind as e, ToolsetAuthStatus as t, ToolsetAuthTypes as n, ToolsetOAuthInitiationResultType as r, ToolsetOAuthResultType as i } from "../types.js";
2
+ import { selectToolsetAuthStatus as a } from "../toolset-id.js";
2
3
  import { emitToolsetLoginSuccess as o } from "../../shared/toolset-login-events.js";
3
4
  import { waitForToolsetOAuthResult as s } from "../handshake.js";
4
5
  import { initiateOAuthLogin as c, navigateToolsetOAuthPopup as l, openToolsetOAuthPopup as u } from "../popup.js";
@@ -24,23 +25,22 @@ var f = /* @__PURE__ */ function(e) {
24
25
  codeChallengeMethod: _?.codeChallengeMethod
25
26
  }, x = v ? await (async () => {
26
27
  let t = u();
27
- return t ? (await g(p, m, n.OAuth), l(t, b, p, f, m, e.Toolset, y)) : { type: i.Blocked };
28
+ return t ? (await g(p, m, n.OAuth), l(t, b, p, f, m, e.Toolset, y)) : { type: r.Blocked };
28
29
  })() : c(b, p, f, m, y);
29
- if (x.type === i.Blocked) return { type: "popup-blocked" };
30
- if (x.type !== i.Started) return { type: "failure" };
30
+ if (x.type === r.Blocked) return { type: "popup-blocked" };
31
+ if (x.type !== r.Started) return { type: "failure" };
31
32
  let S = await s(x.popup, x.flowId, {
32
33
  toolsetId: p,
33
34
  credentialsLevel: m,
34
35
  callbackPath: f
35
36
  });
36
- if (S.type === a.Success) return o({
37
+ if (S.type === i.Success) return o({
37
38
  toolsetId: p,
38
39
  credentialsLevel: m
39
40
  }), { type: "success" };
40
- if (S.type === a.Failure) return { type: "failure" };
41
+ if (S.type === i.Failure) return { type: "failure" };
41
42
  try {
42
- let e = await h(p);
43
- if ((m === r.User ? e.authSettings?.userLevelAuthStatus : e.authSettings?.globalAuthStatus) === t.SignedIn) return o({
43
+ if (a((await h(p)).authSettings, m) === t.SignedIn) return o({
44
44
  toolsetId: p,
45
45
  credentialsLevel: m
46
46
  }), { type: "success" };
package/oauth.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { DialToolsetAuthSettingsDto } from '@epam/ai-dial-chat-api-client';
1
2
  import { DialToolsetDto } from '@epam/ai-dial-chat-api-client';
2
3
  import { ToolsetLoginBodyDto } from '@epam/ai-dial-chat-api-client';
3
4
  import { ToolsetLogoutBodyDto } from '@epam/ai-dial-chat-api-client';
@@ -74,6 +75,19 @@ export declare const isPublicToolsetId: (toolsetId: string) => boolean;
74
75
  */
75
76
  export declare const navigateToolsetOAuthPopup: (popup: Window, auth: ToolsetOAuthSettings, toolsetId: string, callbackPath: string, credentialsLevel?: ToolsetCredentialsLevel, resourceKind?: OAuthResourceKind, offlineUsageConsent?: boolean) => ToolsetOAuthInitiationResult;
76
77
 
78
+ /**
79
+ * Encodes a toolset id to its single-encoded form regardless of whether the
80
+ * value received it in was already percent-encoded or the raw,
81
+ * human-readable form — decoding first then re-encoding once is idempotent
82
+ * either way, since `decodeToolsetId` on a raw (unencoded) id is a no-op.
83
+ * Use this instead of `encodeToolsetId` at a boundary that cannot guarantee
84
+ * which form it receives, such as a `postMessage` payload from an embedded
85
+ * iframe: calling `encodeToolsetId` directly on a value the sender already
86
+ * encoded escapes the existing `%` characters a second time (`%20` becomes
87
+ * `%2520`), which the backend only ever undoes once and so 404s on.
88
+ */
89
+ export declare const normalizeToolsetId: (toolsetId: string) => string;
90
+
77
91
  /** Arguments handed to the host's exchange callback. */
78
92
  export declare interface OAuthExchangeParams {
79
93
  /** One-time authorization code the provider returned. */
@@ -115,6 +129,24 @@ export declare enum OAuthResourceKind {
115
129
  */
116
130
  export declare const openToolsetOAuthPopup: () => Window | null;
117
131
 
132
+ /**
133
+ * Resolves which credentials level a toolset's login applies to, per DIAL
134
+ * Core's public/private toolset convention: a `public`-bucket toolset is
135
+ * shared credentials-wise at `User` level, while a private/workspace toolset
136
+ * is scoped at `Global` level. Every surface that drives a toolset login
137
+ * (the sign-in-interrupt dialog, the QuickApps editor iframe bridge,
138
+ * `useToolsetLogin`) must resolve the level this way rather than assuming one.
139
+ */
140
+ export declare const resolveToolsetCredentialsLevel: (toolsetId: string) => ToolsetCredentialsLevel.User | ToolsetCredentialsLevel.Global;
141
+
142
+ /**
143
+ * Picks the auth-status field matching one credentials level out of a
144
+ * toolset's `authSettings` — DIAL Core reports `userLevelAuthStatus` and
145
+ * `globalAuthStatus` as independent fields rather than one status keyed by
146
+ * level.
147
+ */
148
+ export declare const selectToolsetAuthStatus: (authSettings: Pick<DialToolsetAuthSettingsDto, "userLevelAuthStatus" | "globalAuthStatus"> | undefined, credentialsLevel: ToolsetCredentialsLevel) => string | undefined;
149
+
118
150
  export declare const subscribeToolsetLoginSuccess: <T>(listener: (detail: ToolsetLoginSuccessDetail<T>) => void) => (() => void);
119
151
 
120
152
  /** `sessionStorage` key the flow writes its `ToolsetRedirectState` under, in the popup it opens. */
package/oauth.js CHANGED
@@ -1,9 +1,9 @@
1
- import { decodeToolsetId as e, encodeToolsetId as t, isPublicToolsetId as n } from "./oauth/toolset-id.js";
2
- import { OAuthResourceKind as r, TOOLSET_REDIRECT_STATE_KEY as i, ToolsetAuthStatus as a, ToolsetAuthTypes as o, ToolsetCredentialsLevel as s, ToolsetOAuthCallbackQuery as c, ToolsetOAuthChannelControlType as l, ToolsetOAuthFailureReason as u, ToolsetOAuthInitiationResultType as d, ToolsetOAuthResultType as f, WithLogin as p } from "./oauth/types.js";
3
- import { emitToolsetLoginSuccess as m, subscribeToolsetLoginSuccess as h } from "./shared/toolset-login-events.js";
4
- import { getToolsetOAuthChannelName as g, waitForToolsetOAuthResult as _ } from "./oauth/handshake.js";
5
- import { buildToolsetAuthorizeUrl as v, getToolsetRedirectUri as y } from "./oauth/authorize-url.js";
6
- import { initiateOAuthLogin as b, navigateToolsetOAuthPopup as x, openToolsetOAuthPopup as S } from "./oauth/popup.js";
7
- import { ToolsetLoginOutcomeType as C, useToolsetLogin as w } from "./oauth/useToolsetLogin/useToolsetLogin.js";
8
- import { useOAuthCallbackCompletion as T } from "./oauth/useOAuthCallbackCompletion/useOAuthCallbackCompletion.js";
9
- export { r as OAuthResourceKind, i as TOOLSET_REDIRECT_STATE_KEY, a as ToolsetAuthStatus, o as ToolsetAuthTypes, s as ToolsetCredentialsLevel, C as ToolsetLoginOutcomeType, c as ToolsetOAuthCallbackQuery, l as ToolsetOAuthChannelControlType, u as ToolsetOAuthFailureReason, d as ToolsetOAuthInitiationResultType, f as ToolsetOAuthResultType, p as WithLogin, v as buildToolsetAuthorizeUrl, e as decodeToolsetId, m as emitToolsetLoginSuccess, t as encodeToolsetId, g as getToolsetOAuthChannelName, y as getToolsetRedirectUri, b as initiateOAuthLogin, n as isPublicToolsetId, x as navigateToolsetOAuthPopup, S as openToolsetOAuthPopup, h as subscribeToolsetLoginSuccess, T as useOAuthCallbackCompletion, w as useToolsetLogin, _ as waitForToolsetOAuthResult };
1
+ import { OAuthResourceKind as e, TOOLSET_REDIRECT_STATE_KEY as t, ToolsetAuthStatus as n, ToolsetAuthTypes as r, ToolsetCredentialsLevel as i, ToolsetOAuthCallbackQuery as a, ToolsetOAuthChannelControlType as o, ToolsetOAuthFailureReason as s, ToolsetOAuthInitiationResultType as c, ToolsetOAuthResultType as l, WithLogin as u } from "./oauth/types.js";
2
+ import { decodeToolsetId as d, encodeToolsetId as f, isPublicToolsetId as p, normalizeToolsetId as m, resolveToolsetCredentialsLevel as h, selectToolsetAuthStatus as g } from "./oauth/toolset-id.js";
3
+ import { emitToolsetLoginSuccess as _, subscribeToolsetLoginSuccess as v } from "./shared/toolset-login-events.js";
4
+ import { getToolsetOAuthChannelName as y, waitForToolsetOAuthResult as b } from "./oauth/handshake.js";
5
+ import { buildToolsetAuthorizeUrl as x, getToolsetRedirectUri as S } from "./oauth/authorize-url.js";
6
+ import { initiateOAuthLogin as C, navigateToolsetOAuthPopup as w, openToolsetOAuthPopup as T } from "./oauth/popup.js";
7
+ import { ToolsetLoginOutcomeType as E, useToolsetLogin as D } from "./oauth/useToolsetLogin/useToolsetLogin.js";
8
+ import { useOAuthCallbackCompletion as O } from "./oauth/useOAuthCallbackCompletion/useOAuthCallbackCompletion.js";
9
+ export { e as OAuthResourceKind, t as TOOLSET_REDIRECT_STATE_KEY, n as ToolsetAuthStatus, r as ToolsetAuthTypes, i as ToolsetCredentialsLevel, E as ToolsetLoginOutcomeType, a as ToolsetOAuthCallbackQuery, o as ToolsetOAuthChannelControlType, s as ToolsetOAuthFailureReason, c as ToolsetOAuthInitiationResultType, l as ToolsetOAuthResultType, u as WithLogin, x as buildToolsetAuthorizeUrl, d as decodeToolsetId, _ as emitToolsetLoginSuccess, f as encodeToolsetId, y as getToolsetOAuthChannelName, S as getToolsetRedirectUri, C as initiateOAuthLogin, p as isPublicToolsetId, w as navigateToolsetOAuthPopup, m as normalizeToolsetId, T as openToolsetOAuthPopup, h as resolveToolsetCredentialsLevel, g as selectToolsetAuthStatus, v as subscribeToolsetLoginSuccess, O as useOAuthCallbackCompletion, D as useToolsetLogin, b as waitForToolsetOAuthResult };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@epam/ai-dial-chat-hooks",
3
3
  "description": "Framework-level React hooks extracted from AI DIAL Chat for building custom chat interfaces",
4
- "version": "1.2.0-dev.20",
4
+ "version": "1.2.0-dev.207",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "./index.js",
@@ -29,6 +29,11 @@
29
29
  "import": "./conversation.js",
30
30
  "default": "./conversation.js"
31
31
  },
32
+ "./conversation-overlay": {
33
+ "types": "./conversation-overlay.d.ts",
34
+ "import": "./conversation-overlay.js",
35
+ "default": "./conversation-overlay.js"
36
+ },
32
37
  "./conversation-transfer": {
33
38
  "types": "./conversation-transfer.d.ts",
34
39
  "import": "./conversation-transfer.js",
@@ -44,6 +49,11 @@
44
49
  "import": "./file-manager.js",
45
50
  "default": "./file-manager.js"
46
51
  },
52
+ "./file-manager-canvas": {
53
+ "types": "./file-manager-canvas.d.ts",
54
+ "import": "./file-manager-canvas.js",
55
+ "default": "./file-manager-canvas.js"
56
+ },
47
57
  "./source-content": {
48
58
  "types": "./source-content.d.ts",
49
59
  "import": "./source-content.js",
@@ -89,6 +99,11 @@
89
99
  "import": "./utils.js",
90
100
  "default": "./utils.js"
91
101
  },
102
+ "./usage": {
103
+ "types": "./usage.d.ts",
104
+ "import": "./usage.js",
105
+ "default": "./usage.js"
106
+ },
92
107
  "./mcp-apps": {
93
108
  "types": "./mcp-apps.d.ts",
94
109
  "import": "./mcp-apps.js",
@@ -96,7 +111,7 @@
96
111
  }
97
112
  },
98
113
  "dependencies": {
99
- "@epam/ai-dial-chat-api-client": "1.2.0-dev.20",
114
+ "@epam/ai-dial-chat-api-client": "1.2.0-dev.207",
100
115
  "dompurify": "3.4.15",
101
116
  "fflate": "^0.8.3",
102
117
  "lru-cache": "^10.4.3",
@@ -105,21 +120,21 @@
105
120
  },
106
121
  "peerDependencies": {
107
122
  "react": "^19.2.8",
108
- "@epam/ai-dial-attachment-canvas": "1.2.0-dev.20",
109
- "@epam/ai-dial-attachment-input": "1.2.0-dev.20",
110
- "@epam/ai-dial-builder-form": "1.2.0-dev.20",
111
- "@epam/ai-dial-catalog": "1.2.0-dev.20",
112
- "@epam/ai-dial-chat-overlay": "1.2.0-dev.20",
113
- "@epam/ai-dial-chat-shared": "1.2.0-dev.20",
114
- "@epam/ai-dial-mcp-apps": "1.2.0-dev.20",
115
- "@epam/ai-dial-publish-panel": "1.2.0-dev.20",
116
- "@epam/ai-dial-quotations": "1.2.0-dev.20",
117
- "@epam/ai-dial-react-file-manager": "^0.2.0",
118
- "@epam/ai-dial-scheduled-tasks": "1.2.0-dev.20",
119
- "@epam/ai-dial-share": "1.2.0-dev.20",
120
- "@epam/ai-dial-skill-editor": "1.2.0-dev.20",
121
- "@epam/ai-dial-source-panel": "1.2.0-dev.20",
122
- "@epam/ai-dial-ui-kit": "^0.14.2",
123
+ "@epam/ai-dial-attachment-canvas": "1.2.0-dev.207",
124
+ "@epam/ai-dial-attachment-input": "1.2.0-dev.207",
125
+ "@epam/ai-dial-catalog": "1.2.0-dev.207",
126
+ "@epam/ai-dial-chat-overlay": "1.2.0-dev.207",
127
+ "@epam/ai-dial-chat-shared": "1.2.0-dev.207",
128
+ "@epam/ai-dial-mcp-apps": "1.2.0-dev.207",
129
+ "@epam/ai-dial-publish-panel": "1.2.0-dev.207",
130
+ "@epam/ai-dial-quotations": "1.2.0-dev.207",
131
+ "@epam/ai-dial-react-file-manager": "^0.3.0-dev.16",
132
+ "@epam/ai-dial-scheduled-tasks": "1.2.0-dev.207",
133
+ "@epam/ai-dial-share": "1.2.0-dev.207",
134
+ "@epam/ai-dial-skill-editor": "1.2.0-dev.207",
135
+ "@epam/ai-dial-source-panel": "1.2.0-dev.207",
136
+ "@epam/ai-dial-ui-kit": "^0.15.0-dev.23",
137
+ "@epam/ai-dial-usage-dashboard": "1.2.0-dev.207",
123
138
  "@modelcontextprotocol/sdk": "^1.29.0",
124
139
  "@epam/pdf-highlighter-kit": "^0.0.19",
125
140
  "@mcp-ui/client": "^7.1.1"
@@ -131,9 +146,6 @@
131
146
  "@epam/ai-dial-attachment-input": {
132
147
  "optional": true
133
148
  },
134
- "@epam/ai-dial-builder-form": {
135
- "optional": true
136
- },
137
149
  "@epam/ai-dial-catalog": {
138
150
  "optional": true
139
151
  },
@@ -170,6 +182,9 @@
170
182
  "@epam/ai-dial-ui-kit": {
171
183
  "optional": true
172
184
  },
185
+ "@epam/ai-dial-usage-dashboard": {
186
+ "optional": true
187
+ },
173
188
  "@mcp-ui/client": {
174
189
  "optional": true
175
190
  },
@@ -182,7 +197,7 @@
182
197
  },
183
198
  "sideEffects": [
184
199
  "./oauth.js",
185
- "./file-manager.js",
200
+ "./file-manager-canvas.js",
186
201
  "./shared/toolset-login-events.js",
187
202
  "./files/attachment-canvas.js"
188
203
  ],
@@ -0,0 +1,77 @@
1
+ //#region src/scheduled-task/scheduled-task-description.ts
2
+ var e = /* @__PURE__ */ function(e) {
3
+ return e.OneTime = "oneTime", e.Hourly = "hourly", e.EveryNMinutes = "everyNMinutes", e.Daily = "daily", e.Weekly = "weekly", e.Monthly = "monthly", e.Custom = "custom", e.Invalid = "invalid", e;
4
+ }({}), t = (e, { timeZone: t = "UTC", referenceDate: n = /* @__PURE__ */ new Date() } = {}) => {
5
+ let r = (e, t = {}) => ({
6
+ kind: e,
7
+ sourceTimezone: "utc",
8
+ ...t
9
+ });
10
+ if (e.date && e.cron) return r("invalid");
11
+ if (e.date) {
12
+ let t = new Date(e.date);
13
+ return Number.isNaN(t.getTime()) ? r("invalid") : r("oneTime", { date: t });
14
+ }
15
+ let i = e.cron?.fields;
16
+ if (!i || Object.keys(i).length === 0) return r("invalid");
17
+ let a = () => r("custom", { expression: JSON.stringify(i) }), o = {
18
+ hour: [0, 23],
19
+ minute: [0, 59],
20
+ day: [1, 31],
21
+ day_of_week: [0, 6],
22
+ month: [1, 12],
23
+ second: [0, 59]
24
+ };
25
+ for (let [e, t] of Object.entries(i)) {
26
+ if (t == null) continue;
27
+ if (!t.trim()) return r("invalid");
28
+ let n = o[e];
29
+ if (n && /^-?\d+$/.test(t) && (Number(t) < n[0] || Number(t) > n[1])) return r("invalid");
30
+ if (e === "second" && t !== "0" || ![
31
+ "hour",
32
+ "minute",
33
+ "day",
34
+ "day_of_week"
35
+ ].includes(e) && t !== "*" && !(e === "second" && t === "0")) return a();
36
+ }
37
+ let s = i.hour, c = i.minute, l = i.day === "*" ? void 0 : i.day, u = i.day_of_week === "*" ? void 0 : i.day_of_week, d = u ? [
38
+ "monday",
39
+ "tuesday",
40
+ "wednesday",
41
+ "thursday",
42
+ "friday",
43
+ "saturday",
44
+ "sunday"
45
+ ].findIndex((e) => e === u.toLowerCase() || e.slice(0, 3) === u.toLowerCase()) : -1, f = d >= 0 ? String(d) : u;
46
+ if (l && f || l && !/^\d+$/.test(l) || f && !/^\d+$/.test(f)) return a();
47
+ let p = s == null || s === "*", m = c?.match(/^\*\/(\d+)$/);
48
+ if (p && m && !l && !f) {
49
+ let e = Number(m[1]);
50
+ return e > 0 && e <= 59 ? r("everyNMinutes", { intervalMinutes: e }) : r("invalid");
51
+ }
52
+ if (!c || !/^\d+$/.test(c) || !p && !/^\d+$/.test(s) || p && (l || f)) return a();
53
+ let h = new Date(n);
54
+ if (Number.isNaN(h.getTime())) return r("invalid");
55
+ if (h.setUTCHours(p ? 0 : Number(s), Number(c), 0, 0), f) {
56
+ let e = (Number(f) + 1) % 7;
57
+ h.setUTCDate(h.getUTCDate() + (e - h.getUTCDay() + 7) % 7);
58
+ }
59
+ let g = new Intl.DateTimeFormat("en-GB", {
60
+ timeZone: t,
61
+ hourCycle: "h23",
62
+ year: "numeric",
63
+ month: "2-digit",
64
+ day: "2-digit",
65
+ hour: "2-digit",
66
+ minute: "2-digit"
67
+ }).formatToParts(h), _ = (e) => g.find((t) => t.type === e)?.value ?? "", v = new Date(Date.UTC(Number(_("year")), Number(_("month")) - 1, Number(_("day")))), y = Date.UTC(h.getUTCFullYear(), h.getUTCMonth(), h.getUTCDate()), b = Math.round((v.getTime() - y) / 864e5), x = _("hour") + ":" + _("minute");
68
+ return p ? r("hourly", { time: _("minute") }) : f ? r("weekly", {
69
+ time: x,
70
+ dayOfWeek: String((Number(f) + b + 7) % 7)
71
+ }) : l ? b === 0 || Number(l) <= 28 && Number(l) + b >= 1 && Number(l) + b <= 28 ? r("monthly", {
72
+ time: x,
73
+ dayOfMonth: String(Number(l) + b)
74
+ }) : a() : r("daily", { time: x });
75
+ };
76
+ //#endregion
77
+ export { e as ScheduledTaskTriggerDescriptionKind, t as describeScheduledTaskTrigger };
@@ -0,0 +1,24 @@
1
+ import { mapFormValuesToCreateBody as e, mapFormValuesToUpdateBody as t } from "./scheduled-task-trigger.js";
2
+ import { validateScheduledTaskFormValues as n } from "@epam/ai-dial-scheduled-tasks/validation";
3
+ //#region src/scheduled-task/scheduled-task-preparation.ts
4
+ var r = (t, r) => {
5
+ let i = n(t, r);
6
+ return Object.keys(i).length > 0 ? {
7
+ ok: !1,
8
+ errors: i
9
+ } : {
10
+ ok: !0,
11
+ body: e(t)
12
+ };
13
+ }, i = (e, r) => {
14
+ let i = n(e, r);
15
+ return Object.keys(i).length > 0 ? {
16
+ ok: !1,
17
+ errors: i
18
+ } : {
19
+ ok: !0,
20
+ body: t(e)
21
+ };
22
+ };
23
+ //#endregion
24
+ export { r as prepareScheduledTaskCreateBody, i as prepareScheduledTaskUpdateBody };
@@ -42,9 +42,13 @@ var a = new Set([
42
42
  trigger: t,
43
43
  model: e.modelId,
44
44
  prompt: e.prompt.trim(),
45
+ ...e.skillUrl ? { skillUrl: e.skillUrl } : {},
45
46
  ...n ? { description: n } : {}
46
47
  };
47
- }, u = (e) => l(e), d = (t) => {
48
+ }, u = (e) => ({
49
+ ...l(e),
50
+ skillUrl: e.skillUrl || null
51
+ }), d = (t) => {
48
52
  let n = new Date(t);
49
53
  return `${n.getFullYear()}-${e(n.getMonth() + 1)}-${e(n.getDate())}T${e(n.getHours())}:${e(n.getMinutes())}`;
50
54
  }, f = (t) => {
@@ -82,7 +86,7 @@ var a = new Set([
82
86
  ...c ? { dayOfMonth: String(d.getDate()) } : {}
83
87
  };
84
88
  }, m = (e) => {
85
- if (!e.model || !e.prompt) return {
89
+ if (!e.model || typeof e.prompt != "string" || !e.prompt.trim() && !e.skillUrl) return {
86
90
  ok: !1,
87
91
  reason: t.MissingRequiredFields
88
92
  };
@@ -95,6 +99,7 @@ var a = new Set([
95
99
  displayName: e.displayName,
96
100
  modelId: e.model,
97
101
  prompt: e.prompt,
102
+ ...e.skillUrl ? { skillUrl: e.skillUrl } : {},
98
103
  ...e.description ? { description: e.description } : {}
99
104
  };
100
105
  if (a) return {
@@ -0,0 +1,19 @@
1
+ //#region src/scheduled-task/scheduled-tasks-api-client.ts
2
+ var e = (e) => {
3
+ if (!Array.isArray(e.items)) throw TypeError("Scheduled tasks API returned a malformed page response");
4
+ return e;
5
+ }, t = (t) => ({
6
+ listScheduledTasks: async ({ signal: n, ...r } = {}) => e(await t.listScheduledTasks(r, n ? { signal: n } : void 0)),
7
+ listScheduledTaskRuns: async ({ signal: n, ...r }) => e(await t.listScheduledTaskRuns(r, n ? { signal: n } : void 0)),
8
+ createScheduledTask: (e) => t.createScheduledTask({ createScheduledTaskBodyDto: e }),
9
+ getScheduledTask: (e) => t.getScheduledTask({ scheduleId: e }),
10
+ updateScheduledTask: (e, n) => t.updateScheduledTask({
11
+ scheduleId: e,
12
+ updateScheduledTaskBodyDto: n
13
+ }),
14
+ pauseScheduledTask: (e) => t.pauseScheduledTask({ scheduleId: e }),
15
+ resumeScheduledTask: (e) => t.resumeScheduledTask({ scheduleId: e }),
16
+ deleteScheduledTask: (e) => t.deleteScheduledTask({ scheduleId: e })
17
+ });
18
+ //#endregion
19
+ export { t as createScheduledTasksApiClient };
@@ -0,0 +1,194 @@
1
+ import { useCallback as e, useEffect as t, useRef as n, useState as r } from "react";
2
+ import { ScheduledTaskRunDtoStatusEnum as i } from "@epam/ai-dial-chat-api-client";
3
+ //#region src/scheduled-task/use-scheduled-task-runs.ts
4
+ var a = 15e3, o = 20, s = 5e3, c = 2147483647, l = (e, t) => {
5
+ if (e <= c) {
6
+ let n = setTimeout(t, Math.max(e, 0));
7
+ return () => clearTimeout(n);
8
+ }
9
+ let n, r = setTimeout(() => {
10
+ n = l(e - c, t);
11
+ }, c);
12
+ return n = () => clearTimeout(r), () => n();
13
+ }, u = (e, t) => {
14
+ let n = new Map(t.map((e) => [e.id, e])), r = new Set(e.map((e) => e.id)), i = e.map((e) => n.get(e.id) ?? e);
15
+ return [...t.filter((e) => !r.has(e.id)), ...i];
16
+ }, d = (e, t) => {
17
+ if (e.length !== t.length) return !0;
18
+ let n = new Map(e.map((e) => [e.id, e]));
19
+ return t.some((e) => {
20
+ let t = n.get(e.id);
21
+ return !t || JSON.stringify(t) !== JSON.stringify(e);
22
+ });
23
+ }, f = (c, { scheduleId: f, enabled: p = !0, pageSize: m = 10, nextRunTime: h }) => {
24
+ let [g, _] = r([]), [v, y] = r(p), [b, x] = r(!1), [S, C] = r(null), [w, T] = r(null), [E, D] = r(!1), [O, k] = r(0), A = n(0), j = n(0), M = n(!1), N = n(null), P = n(g), F = n(v), I = n(b), L = n(null), R = n(0), z = n(null), B = n(!1);
25
+ P.current = g, F.current = v, I.current = b;
26
+ let V = g.some((e) => e.status === i.InProgress);
27
+ t(() => {
28
+ let e = ++A.current, t = new AbortController();
29
+ N.current?.abort(), N.current = null, L.current?.abort(), L.current = null, M.current = !1, R.current = 0, z.current = null, B.current = !1, x(!1), C(null), T(null), _([]), D(!1), j.current = 0;
30
+ let n = () => {
31
+ ++A.current, t.abort(), N.current?.abort(), N.current = null, L.current?.abort(), L.current = null;
32
+ };
33
+ return !p || !f ? (y(!1), _([]), D(!1), n) : ((async () => {
34
+ y(!0);
35
+ try {
36
+ let n = await c.listScheduledTaskRuns({
37
+ scheduleId: f,
38
+ limit: m,
39
+ offset: 0,
40
+ signal: t.signal
41
+ });
42
+ if (A.current !== e) return;
43
+ _(n.items), j.current = n.items.length, D(n.next != null || (n.count == null ? n.items.length === m : n.items.length < n.count));
44
+ } catch (t) {
45
+ A.current === e && C(t instanceof Error ? t : /* @__PURE__ */ Error("Failed to load scheduled task runs"));
46
+ } finally {
47
+ A.current === e && y(!1);
48
+ }
49
+ })(), n);
50
+ }, [
51
+ c,
52
+ p,
53
+ m,
54
+ O,
55
+ f
56
+ ]);
57
+ let H = e(() => {
58
+ if (!p || !f || !E || v || M.current) return;
59
+ M.current = !0;
60
+ let e = new AbortController();
61
+ N.current = e;
62
+ let t = A.current, n = j.current;
63
+ (async () => {
64
+ x(!0), T(null);
65
+ try {
66
+ let r = await c.listScheduledTaskRuns({
67
+ scheduleId: f,
68
+ limit: m,
69
+ offset: n,
70
+ signal: e.signal
71
+ });
72
+ if (A.current !== t) return;
73
+ _((e) => {
74
+ let t = new Set(e.map(({ id: e }) => e));
75
+ return [...e, ...r.items.filter(({ id: e }) => t.has(e) ? !1 : (t.add(e), !0))];
76
+ }), j.current = n + r.items.length, D(r.next != null || (r.count == null ? r.items.length === m : n + r.items.length < r.count));
77
+ } catch (e) {
78
+ A.current === t && T(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load more scheduled task runs"));
79
+ } finally {
80
+ A.current === t && (x(!1), M.current = !1, N.current = null);
81
+ }
82
+ })();
83
+ }, [
84
+ c,
85
+ p,
86
+ E,
87
+ v,
88
+ m,
89
+ f
90
+ ]), U = e(async () => {
91
+ if (F.current || I.current) return "skipped";
92
+ let e = A.current, t = new AbortController();
93
+ L.current?.abort(), L.current = t;
94
+ try {
95
+ let n = await c.listScheduledTaskRuns({
96
+ scheduleId: f,
97
+ limit: m,
98
+ offset: 0,
99
+ signal: t.signal
100
+ });
101
+ if (A.current !== e || F.current || I.current) return "skipped";
102
+ let r = P.current, i = u(r, n.items), a = d(r, i);
103
+ return a && (P.current = i, _(i)), a ? "changed" : "unchanged";
104
+ } catch {
105
+ return "error";
106
+ } finally {
107
+ L.current === t && (L.current = null);
108
+ }
109
+ }, [
110
+ c,
111
+ f,
112
+ m
113
+ ]), W = e(() => {
114
+ if (document.visibilityState !== "visible") {
115
+ B.current = !0;
116
+ return;
117
+ }
118
+ U();
119
+ }, [U]);
120
+ return t(() => {
121
+ if (!p || !f || !V) return;
122
+ R.current = 0;
123
+ let e = setInterval(() => {
124
+ if (document.visibilityState !== "visible") {
125
+ B.current = !0;
126
+ return;
127
+ }
128
+ (async () => {
129
+ let t = await U();
130
+ if (t === "changed") {
131
+ R.current = 0;
132
+ return;
133
+ }
134
+ (t === "unchanged" || t === "error") && (R.current += 1, R.current >= o && e !== null && (clearInterval(e), e = null));
135
+ })();
136
+ }, a);
137
+ return () => {
138
+ e !== null && clearInterval(e);
139
+ };
140
+ }, [
141
+ p,
142
+ f,
143
+ V,
144
+ U
145
+ ]), t(() => {
146
+ if (!p || !f || !h) return;
147
+ let e = new Date(h).getTime();
148
+ if (!(Number.isNaN(e) || e <= Date.now())) return l(e - Date.now() + s, () => {
149
+ z.current = h, W();
150
+ });
151
+ }, [
152
+ p,
153
+ f,
154
+ h,
155
+ W
156
+ ]), t(() => {
157
+ if (!p || !f) return;
158
+ let e = () => {
159
+ document.visibilityState !== "visible" || !B.current || (async () => {
160
+ await U() !== "skipped" && (B.current = !1);
161
+ })();
162
+ };
163
+ return document.addEventListener("visibilitychange", e), () => {
164
+ document.removeEventListener("visibilitychange", e);
165
+ };
166
+ }, [
167
+ p,
168
+ f,
169
+ U
170
+ ]), t(() => {
171
+ if (!p || !f || !h || v || b) return;
172
+ let e = new Date(h).getTime();
173
+ Number.isNaN(e) || e > Date.now() || z.current !== h && (z.current = h, W());
174
+ }, [
175
+ p,
176
+ f,
177
+ h,
178
+ v,
179
+ b,
180
+ W
181
+ ]), {
182
+ items: g,
183
+ isLoading: v,
184
+ isLoadingMore: b,
185
+ initialError: S,
186
+ loadMoreError: w,
187
+ hasMore: E,
188
+ loadMore: H,
189
+ retryLoadMore: H,
190
+ refetch: e(() => k((e) => e + 1), [])
191
+ };
192
+ };
193
+ //#endregion
194
+ export { u as mergeRunsById, f as useScheduledTaskRuns };
@@ -0,0 +1,93 @@
1
+ import { useCallback as e, useEffect as t, useRef as n, useState as r } from "react";
2
+ //#region src/scheduled-task/use-scheduled-tasks.ts
3
+ var i = (i, { enabled: a = !0, pageSize: o = 20, debounceMs: s = 300, initialSearch: c = "", initialSort: l = "first_to_run" } = {}) => {
4
+ let [u, d] = r([]), [f, p] = r(c), [m, h] = r(l), [g, _] = r(a), [v, y] = r(!1), [b, x] = r(null), [S, C] = r(null), [w, T] = r(!1), [E, D] = r(0), O = n(0), k = n(0), A = n(!1), j = n(null), [M, N] = r(c);
5
+ t(() => {
6
+ let e = setTimeout(() => N(f), s);
7
+ return () => clearTimeout(e);
8
+ }, [s, f]), t(() => {
9
+ let e = ++O.current, t = new AbortController();
10
+ j.current?.abort(), j.current = null, A.current = !1, y(!1), x(null), C(null), d([]), T(!1), k.current = 0;
11
+ let n = () => {
12
+ ++O.current, t.abort(), j.current?.abort(), j.current = null;
13
+ };
14
+ return a ? ((async () => {
15
+ _(!0);
16
+ try {
17
+ let n = await i.listScheduledTasks({
18
+ limit: o,
19
+ offset: 0,
20
+ search: M,
21
+ sort: m,
22
+ signal: t.signal
23
+ });
24
+ if (O.current !== e) return;
25
+ d(n.items), k.current = n.items.length, T(n.next != null);
26
+ } catch (t) {
27
+ O.current === e && x(t instanceof Error ? t : /* @__PURE__ */ Error("Failed to load scheduled tasks"));
28
+ } finally {
29
+ O.current === e && _(!1);
30
+ }
31
+ })(), n) : (_(!1), d([]), T(!1), n);
32
+ }, [
33
+ i,
34
+ M,
35
+ a,
36
+ o,
37
+ E,
38
+ m
39
+ ]);
40
+ let P = e(() => {
41
+ if (!a || !w || g || A.current) return;
42
+ A.current = !0;
43
+ let e = new AbortController();
44
+ j.current = e;
45
+ let t = O.current, n = k.current;
46
+ (async () => {
47
+ y(!0), C(null);
48
+ try {
49
+ let r = await i.listScheduledTasks({
50
+ limit: o,
51
+ offset: n,
52
+ signal: e.signal,
53
+ search: M,
54
+ sort: m
55
+ });
56
+ if (O.current !== t) return;
57
+ d((e) => {
58
+ let t = new Set(e.map(({ id: e }) => e));
59
+ return [...e, ...r.items.filter(({ id: e }) => t.has(e) ? !1 : (t.add(e), !0))];
60
+ }), k.current = n + r.items.length, T(r.next != null);
61
+ } catch (e) {
62
+ O.current === t && C(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load more scheduled tasks"));
63
+ } finally {
64
+ O.current === t && (y(!1), A.current = !1, j.current = null);
65
+ }
66
+ })();
67
+ }, [
68
+ i,
69
+ M,
70
+ a,
71
+ w,
72
+ g,
73
+ o,
74
+ m
75
+ ]);
76
+ return {
77
+ items: u,
78
+ searchQuery: f,
79
+ setSearchQuery: p,
80
+ sortKey: m,
81
+ setSortKey: h,
82
+ isLoading: g,
83
+ isLoadingMore: v,
84
+ initialError: b,
85
+ loadMoreError: S,
86
+ hasMore: w,
87
+ loadMore: P,
88
+ retryLoadMore: P,
89
+ refetch: e(() => D((e) => e + 1), [])
90
+ };
91
+ };
92
+ //#endregion
93
+ export { i as useScheduledTasks };