@epam/ai-dial-chat-hooks 1.2.0-dev.28 → 1.2.0-dev.282

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 (94) hide show
  1. package/api-error/api-error.js +7 -4
  2. package/attachment/useAttachmentValidation/useAttachmentValidation.js +26 -19
  3. package/attachments.d.ts +10 -4
  4. package/catalog/catalog-derivations.js +1 -1
  5. package/catalog/deployment-id.js +8 -2
  6. package/catalog/map-deployment-limits-to-catalog.js +16 -24
  7. package/catalog/map-deployment-limits-to-input.js +81 -9
  8. package/catalog/map-deployment-to-catalog-item.js +34 -34
  9. package/catalog/map-entity-details-to-catalog.js +7 -0
  10. package/catalog/map-skill-to-catalog-item.js +55 -48
  11. package/catalog/publish.js +6 -5
  12. package/catalog/useApplicationCredentials/useApplicationCredentials.js +39 -0
  13. package/catalog/useCatalogEditNavigation/useCatalogEditNavigation.js +122 -101
  14. package/catalog/usePublishFolders/usePublishFolders.js +1 -1
  15. package/catalog/useSkillDetailsPanelData/useSkillDetailsPanelData.js +39 -39
  16. package/catalog/useSkillItemDetails.js +17 -13
  17. package/catalog.d.ts +139 -34
  18. package/catalog.js +23 -22
  19. package/conversation/conversation-transfer/export-conversation.js +24 -16
  20. package/conversation/conversation-transfer/import-conversation.js +80 -31
  21. package/conversation/conversation-transfer/queue.js +8 -5
  22. package/conversation/create-chat-stream-api.js +85 -49
  23. package/conversation/message-utils.js +44 -2
  24. package/conversation/stage.js +27 -0
  25. package/conversation/useActiveConversationSync/useActiveConversationSync.js +7 -8
  26. package/conversation/useConversationExport/useConversationExport.js +9 -9
  27. package/conversation/useConversationHandlers/useConversationHandlers.js +73 -57
  28. package/conversation/useConversationImport/useConversationImport.js +123 -121
  29. package/conversation/useConversationPanelItems/useConversationPanelItems.js +50 -32
  30. package/conversation/useConversationScroll/useConversationScroll.js +68 -64
  31. package/conversation/useConversationStream/apply-chunk.js +1 -1
  32. package/conversation/useConversationStream/frame-scheduler.js +39 -0
  33. package/conversation/useConversationStream/generation-resume.js +122 -64
  34. package/conversation/useConversationStream/useConversationStream.js +265 -116
  35. package/conversation/useMessageSelectionReply/useMessageSelectionReply.js +189 -0
  36. package/conversation-sources/useConversationSources/useConversationSources.js +31 -24
  37. package/conversation-sources.d.ts +1 -1
  38. package/conversation-transfer.d.ts +2 -1
  39. package/conversation.d.ts +295 -17
  40. package/conversation.js +32 -29
  41. package/file-manager-canvas.d.ts +53 -5
  42. package/file-manager.d.ts +156 -26
  43. package/file-manager.js +25 -23
  44. package/files/attachment-canvas.js +74 -40
  45. package/files/attachment-types.js +14 -13
  46. package/files/dial-file-manager-mapping.util.js +2 -1
  47. package/files/dial-file-manager-path.util.js +23 -1
  48. package/files/dial-file-manager.model.js +23 -19
  49. package/files/dial-file-manager.types.js +3 -3
  50. package/files/useDialFileListing/useDialFileListing.js +139 -127
  51. package/files/useDialFileManager/useDialFileManager.js +132 -128
  52. package/files/useDialFileManagerSections/useDialFileManagerSections.js +155 -0
  53. package/files/useDialFileManagerTabConfig/useDialFileManagerTabConfig.js +20 -19
  54. package/files/useDialFileMutations/useDialFileMutations.js +33 -32
  55. package/files/useDialFileUploadBatch/useDialFileUploadBatch.js +117 -110
  56. package/files/useFileAttachmentPicker/useFileAttachmentPicker.js +49 -0
  57. package/index.d.ts +1178 -112
  58. package/index.js +136 -122
  59. package/mcp-apps/useMcpAppHostAdapter/useMcpAppHostAdapter.js +7 -5
  60. package/mcp-apps/useMcpAppHostContext/useMcpAppHostContext.js +1 -1
  61. package/mcp-apps/useMcpAppTools/useMcpAppTools.js +1 -1
  62. package/mcp-apps/useOpenMcpAppCanvas/useOpenMcpAppCanvas.js +25 -23
  63. package/mcp-apps.d.ts +8 -6
  64. package/oauth/toolset-id.js +5 -3
  65. package/oauth/useToolsetLogin/useToolsetLogin.js +8 -8
  66. package/oauth.d.ts +32 -0
  67. package/oauth.js +9 -9
  68. package/package.json +26 -21
  69. package/scheduled-task/scheduled-task-description.js +81 -0
  70. package/scheduled-task/scheduled-task-preparation.js +24 -0
  71. package/scheduled-task/scheduled-task-trigger.js +74 -71
  72. package/scheduled-task/scheduled-tasks-api-client.js +19 -0
  73. package/scheduled-task/use-scheduled-task-runs.js +194 -0
  74. package/scheduled-task/use-scheduled-tasks.js +93 -0
  75. package/scheduled-tasks.d.ts +197 -3
  76. package/scheduled-tasks.js +7 -2
  77. package/shared/application-schema.js +5 -2
  78. package/shared/cron-day-of-month.js +13 -0
  79. package/skill/skill-archive.js +19 -0
  80. package/skill/skill-types.js +8 -7
  81. package/skill/skill.js +53 -27
  82. package/skill/useSkillArchiveImport/useSkillArchiveImport.js +79 -0
  83. package/skill/useSkillEditorLoad.js +65 -59
  84. package/skill/useSkillEditorSubmit.js +108 -84
  85. package/skill/useSkillFileActions.js +70 -58
  86. package/skill-editor.d.ts +160 -8
  87. package/skill-editor.js +9 -8
  88. package/usage/map-usage-data-to-dashboard.js +66 -0
  89. package/usage/map-user-usage-to-model-limits.js +202 -0
  90. package/usage.d.ts +125 -0
  91. package/usage.js +3 -0
  92. package/usePageFileDrag/usePageFileDrag.js +3 -3
  93. package/utils.d.ts +26 -6
  94. package/utils.js +10 -10
@@ -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.28",
4
+ "version": "1.2.0-dev.282",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "./index.js",
@@ -99,6 +99,11 @@
99
99
  "import": "./utils.js",
100
100
  "default": "./utils.js"
101
101
  },
102
+ "./usage": {
103
+ "types": "./usage.d.ts",
104
+ "import": "./usage.js",
105
+ "default": "./usage.js"
106
+ },
102
107
  "./mcp-apps": {
103
108
  "types": "./mcp-apps.d.ts",
104
109
  "import": "./mcp-apps.js",
@@ -106,8 +111,8 @@
106
111
  }
107
112
  },
108
113
  "dependencies": {
109
- "@epam/ai-dial-chat-api-client": "1.2.0-dev.28",
110
- "dompurify": "3.4.15",
114
+ "@epam/ai-dial-chat-api-client": "1.2.0-dev.282",
115
+ "dompurify": "3.4.16",
111
116
  "fflate": "^0.8.3",
112
117
  "lru-cache": "^10.4.3",
113
118
  "mime-types": "^3.0.2",
@@ -115,21 +120,21 @@
115
120
  },
116
121
  "peerDependencies": {
117
122
  "react": "^19.2.8",
118
- "@epam/ai-dial-attachment-canvas": "1.2.0-dev.28",
119
- "@epam/ai-dial-attachment-input": "1.2.0-dev.28",
120
- "@epam/ai-dial-builder-form": "1.2.0-dev.28",
121
- "@epam/ai-dial-catalog": "1.2.0-dev.28",
122
- "@epam/ai-dial-chat-overlay": "1.2.0-dev.28",
123
- "@epam/ai-dial-chat-shared": "1.2.0-dev.28",
124
- "@epam/ai-dial-mcp-apps": "1.2.0-dev.28",
125
- "@epam/ai-dial-publish-panel": "1.2.0-dev.28",
126
- "@epam/ai-dial-quotations": "1.2.0-dev.28",
127
- "@epam/ai-dial-react-file-manager": "^0.2.0",
128
- "@epam/ai-dial-scheduled-tasks": "1.2.0-dev.28",
129
- "@epam/ai-dial-share": "1.2.0-dev.28",
130
- "@epam/ai-dial-skill-editor": "1.2.0-dev.28",
131
- "@epam/ai-dial-source-panel": "1.2.0-dev.28",
132
- "@epam/ai-dial-ui-kit": "^0.14.2",
123
+ "@epam/ai-dial-attachment-canvas": "1.2.0-dev.282",
124
+ "@epam/ai-dial-attachment-input": "1.2.0-dev.282",
125
+ "@epam/ai-dial-catalog": "1.2.0-dev.282",
126
+ "@epam/ai-dial-chat-overlay": "1.2.0-dev.282",
127
+ "@epam/ai-dial-chat-shared": "1.2.0-dev.282",
128
+ "@epam/ai-dial-mcp-apps": "1.2.0-dev.282",
129
+ "@epam/ai-dial-publish-panel": "1.2.0-dev.282",
130
+ "@epam/ai-dial-quotations": "1.2.0-dev.282",
131
+ "@epam/ai-dial-react-file-manager": "^0.3.0-dev.25",
132
+ "@epam/ai-dial-scheduled-tasks": "1.2.0-dev.282",
133
+ "@epam/ai-dial-share": "1.2.0-dev.282",
134
+ "@epam/ai-dial-skill-editor": "1.2.0-dev.282",
135
+ "@epam/ai-dial-source-panel": "1.2.0-dev.282",
136
+ "@epam/ai-dial-ui-kit": "^0.15.0-dev.36",
137
+ "@epam/ai-dial-usage-dashboard": "1.2.0-dev.282",
133
138
  "@modelcontextprotocol/sdk": "^1.29.0",
134
139
  "@epam/pdf-highlighter-kit": "^0.0.19",
135
140
  "@mcp-ui/client": "^7.1.1"
@@ -141,9 +146,6 @@
141
146
  "@epam/ai-dial-attachment-input": {
142
147
  "optional": true
143
148
  },
144
- "@epam/ai-dial-builder-form": {
145
- "optional": true
146
- },
147
149
  "@epam/ai-dial-catalog": {
148
150
  "optional": true
149
151
  },
@@ -180,6 +182,9 @@
180
182
  "@epam/ai-dial-ui-kit": {
181
183
  "optional": true
182
184
  },
185
+ "@epam/ai-dial-usage-dashboard": {
186
+ "optional": true
187
+ },
183
188
  "@mcp-ui/client": {
184
189
  "optional": true
185
190
  },
@@ -0,0 +1,81 @@
1
+ import { CRON_LAST_DAY_OF_MONTH as e } from "../shared/cron-day-of-month.js";
2
+ //#region src/scheduled-task/scheduled-task-description.ts
3
+ var t = /* @__PURE__ */ function(e) {
4
+ 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;
5
+ }({}), n = (t, { timeZone: n = "UTC", referenceDate: r = /* @__PURE__ */ new Date() } = {}) => {
6
+ let i = (e, t = {}) => ({
7
+ kind: e,
8
+ sourceTimezone: "utc",
9
+ ...t
10
+ });
11
+ if (t.date && t.cron) return i("invalid");
12
+ if (t.date) {
13
+ let e = new Date(t.date);
14
+ return Number.isNaN(e.getTime()) ? i("invalid") : i("oneTime", { date: e });
15
+ }
16
+ let a = t.cron?.fields;
17
+ if (!a || Object.keys(a).length === 0) return i("invalid");
18
+ let o = () => i("custom", { expression: JSON.stringify(a) }), s = {
19
+ hour: [0, 23],
20
+ minute: [0, 59],
21
+ day: [1, 31],
22
+ day_of_week: [0, 6],
23
+ month: [1, 12],
24
+ second: [0, 59]
25
+ };
26
+ for (let [e, t] of Object.entries(a)) {
27
+ if (t == null) continue;
28
+ if (!t.trim()) return i("invalid");
29
+ let n = s[e];
30
+ if (n && /^-?\d+$/.test(t) && (Number(t) < n[0] || Number(t) > n[1])) return i("invalid");
31
+ if (e === "second" && t !== "0" || ![
32
+ "hour",
33
+ "minute",
34
+ "day",
35
+ "day_of_week"
36
+ ].includes(e) && t !== "*" && !(e === "second" && t === "0")) return o();
37
+ }
38
+ let c = a.hour, l = a.minute, u = a.day === "*" ? void 0 : a.day, d = u === e, f = a.day_of_week === "*" ? void 0 : a.day_of_week, p = f ? [
39
+ "monday",
40
+ "tuesday",
41
+ "wednesday",
42
+ "thursday",
43
+ "friday",
44
+ "saturday",
45
+ "sunday"
46
+ ].findIndex((e) => e === f.toLowerCase() || e.slice(0, 3) === f.toLowerCase()) : -1, m = p >= 0 ? String(p) : f;
47
+ if (u && m || u && !d && !/^\d+$/.test(u) || m && !/^\d+$/.test(m)) return o();
48
+ let h = c == null || c === "*", g = l?.match(/^\*\/(\d+)$/);
49
+ if (h && g && !u && !m) {
50
+ let e = Number(g[1]);
51
+ return e > 0 && e <= 59 ? i("everyNMinutes", { intervalMinutes: e }) : i("invalid");
52
+ }
53
+ if (!l || !/^\d+$/.test(l) || !h && !/^\d+$/.test(c) || h && (u || m)) return o();
54
+ let _ = new Date(r);
55
+ if (Number.isNaN(_.getTime())) return i("invalid");
56
+ if (_.setUTCHours(h ? 0 : Number(c), Number(l), 0, 0), m) {
57
+ let e = (Number(m) + 1) % 7;
58
+ _.setUTCDate(_.getUTCDate() + (e - _.getUTCDay() + 7) % 7);
59
+ }
60
+ let v = new Intl.DateTimeFormat("en-GB", {
61
+ timeZone: n,
62
+ hourCycle: "h23",
63
+ year: "numeric",
64
+ month: "2-digit",
65
+ day: "2-digit",
66
+ hour: "2-digit",
67
+ minute: "2-digit"
68
+ }).formatToParts(_), y = (e) => v.find((t) => t.type === e)?.value ?? "", b = new Date(Date.UTC(Number(y("year")), Number(y("month")) - 1, Number(y("day")))), x = Date.UTC(_.getUTCFullYear(), _.getUTCMonth(), _.getUTCDate()), S = Math.round((b.getTime() - x) / 864e5), C = y("hour") + ":" + y("minute");
69
+ return h ? i("hourly", { time: y("minute") }) : m ? i("weekly", {
70
+ time: C,
71
+ dayOfWeek: String((Number(m) + S + 7) % 7)
72
+ }) : d ? S === 1 ? i("monthly", {
73
+ time: C,
74
+ dayOfMonth: "1"
75
+ }) : o() : u ? S === 0 || Number(u) <= 28 && Number(u) + S >= 1 && Number(u) + S <= 28 ? i("monthly", {
76
+ time: C,
77
+ dayOfMonth: String(Number(u) + S)
78
+ }) : o() : i("daily", { time: C });
79
+ };
80
+ //#endregion
81
+ export { t as ScheduledTaskTriggerDescriptionKind, n 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 };
@@ -1,59 +1,64 @@
1
1
  import { padTwoDigits as e } from "../shared/formatting.js";
2
2
  import { UnsupportedTriggerReason as t } from "./scheduled-task-mapping.js";
3
- import { apSchedulerDayToJsDay as n, jsDayToApSchedulerDay as r } from "../shared/cron-weekday.js";
4
- import { ScheduledTaskRepeat as i } from "@epam/ai-dial-scheduled-tasks";
3
+ import { getUtcDayShift as n, toLocalDayOfMonth as r, toUtcCronDayOfMonth as i } from "../shared/cron-day-of-month.js";
4
+ import { apSchedulerDayToJsDay as a, jsDayToApSchedulerDay as o } from "../shared/cron-weekday.js";
5
+ import { ScheduledTaskRepeat as s } from "@epam/ai-dial-scheduled-tasks";
5
6
  //#region src/scheduled-task/scheduled-task-trigger.ts
6
- var a = new Set([
7
+ var c = new Set([
7
8
  "hour",
8
9
  "minute",
9
10
  "day_of_week",
10
11
  "day"
11
- ]), o = "09:00", s = (e) => {
12
- if (e.repeat === i.Hourly) {
12
+ ]), l = "09:00", u = (e) => {
13
+ if (e.repeat === s.Hourly) {
13
14
  let t = /* @__PURE__ */ new Date();
14
15
  return t.setHours(0, Number(e.minute), 0, 0), {
15
16
  hour: "*",
16
17
  minute: String(t.getUTCMinutes())
17
18
  };
18
19
  }
19
- let [t, a] = e.time.split(":"), o = Number(t), s = Number(a), c = /* @__PURE__ */ new Date();
20
- c.setHours(o, s, 0, 0);
21
- let l = e.repeat === i.Weekly && !!e.dayOfWeek, u = e.repeat === i.Monthly && !!e.dayOfMonth;
22
- if (l) {
23
- let t = (n(Number(e.dayOfWeek)) - c.getDay() + 7) % 7;
24
- c.setDate(c.getDate() + t);
25
- } else u && c.setDate(Number(e.dayOfMonth));
26
- let d = {
27
- hour: String(c.getUTCHours()),
28
- minute: String(c.getUTCMinutes())
20
+ let [t, r] = e.time.split(":"), c = Number(t), l = Number(r), u = /* @__PURE__ */ new Date();
21
+ u.setHours(c, l, 0, 0);
22
+ let d = e.repeat === s.Weekly && !!e.dayOfWeek, f = e.repeat === s.Monthly && !!e.dayOfMonth;
23
+ if (d) {
24
+ let t = (a(Number(e.dayOfWeek)) - u.getDay() + 7) % 7;
25
+ u.setDate(u.getDate() + t);
26
+ }
27
+ let p = {
28
+ hour: String(u.getUTCHours()),
29
+ minute: String(u.getUTCMinutes())
29
30
  };
30
- return l && (d.day_of_week = String(r(c.getUTCDay()))), u && (d.day = String(c.getUTCDate())), d;
31
- }, c = (e, t) => {
31
+ return d && (p.day_of_week = String(o(u.getUTCDay()))), f && (p.day = i(Number(e.dayOfMonth), n(u))), p;
32
+ }, d = (e, t) => {
32
33
  let [n, r, i] = e.split("-").map(Number), a = new Date(n, r - 1, i);
33
34
  return t === "start" ? a.setHours(0, 0, 0, 0) : a.setHours(23, 59, 59, 999), a.toISOString();
34
- }, l = (e) => {
35
- let t = e.repeat === i.OneTime ? { date: new Date(e.runAt ?? "").toISOString() } : { cron: {
36
- fields: s(e),
37
- ...e.startDate ? { startDate: c(e.startDate, "start") } : {},
38
- ...e.endDate ? { endDate: c(e.endDate, "end") } : {}
35
+ }, f = (e) => {
36
+ let t = e.repeat === s.OneTime ? { date: new Date(e.runAt ?? "").toISOString() } : { cron: {
37
+ fields: u(e),
38
+ ...e.startDate ? { startDate: d(e.startDate, "start") } : {},
39
+ ...e.endDate ? { endDate: d(e.endDate, "end") } : {}
39
40
  } }, n = e.description?.trim();
40
41
  return {
41
42
  displayName: e.displayName.trim(),
42
43
  trigger: t,
43
44
  model: e.modelId,
44
45
  prompt: e.prompt.trim(),
46
+ ...e.skillUrls?.length ? { skillUrls: [...new Set(e.skillUrls)] } : {},
45
47
  ...n ? { description: n } : {}
46
48
  };
47
- }, u = (e) => l(e), d = (t) => {
49
+ }, p = (e) => ({
50
+ ...f(e),
51
+ skillUrls: [...new Set(e.skillUrls ?? [])]
52
+ }), m = (t) => {
48
53
  let n = new Date(t);
49
54
  return `${n.getFullYear()}-${e(n.getMonth() + 1)}-${e(n.getDate())}T${e(n.getHours())}:${e(n.getMinutes())}`;
50
- }, f = (t) => {
55
+ }, h = (t) => {
51
56
  let n = new Date(t);
52
57
  return `${n.getFullYear()}-${e(n.getMonth() + 1)}-${e(n.getDate())}`;
53
- }, p = (t) => {
54
- let i = new Set(Object.entries(t).filter(([, e]) => e != null).map(([e]) => e)), o = [...i].filter((e) => !a.has(e)), s = i.has("day_of_week"), c = i.has("day");
55
- if (o.length > 0 || s && c || !i.has("hour") || !i.has("minute")) return { ok: !1 };
56
- if (t.hour === "*" && /^\d+$/.test(String(t.minute)) && !s && !c) {
58
+ }, g = (t) => {
59
+ let i = new Set(Object.entries(t).filter(([, e]) => e != null).map(([e]) => e)), s = [...i].filter((e) => !c.has(e)), l = i.has("day_of_week"), u = i.has("day");
60
+ if (s.length > 0 || l && u || !i.has("hour") || !i.has("minute")) return { ok: !1 };
61
+ if (t.hour === "*" && /^\d+$/.test(String(t.minute)) && !l && !u) {
57
62
  let e = /* @__PURE__ */ new Date();
58
63
  return e.setUTCHours(0, Number(t.minute), 0, 0), {
59
64
  ok: !0,
@@ -61,84 +66,82 @@ var a = new Set([
61
66
  minute: String(e.getMinutes())
62
67
  };
63
68
  }
64
- let l = Number(t.hour), u = Number(t.minute);
65
- if (Number.isNaN(l) || Number.isNaN(u)) return { ok: !1 };
66
- let d = /* @__PURE__ */ new Date();
67
- if (d.setUTCHours(l, u, 0, 0), s) {
69
+ let d = Number(t.hour), f = Number(t.minute);
70
+ if (Number.isNaN(d) || Number.isNaN(f)) return { ok: !1 };
71
+ let p = /* @__PURE__ */ new Date();
72
+ if (p.setUTCHours(d, f, 0, 0), l) {
68
73
  let e = Number(t.day_of_week);
69
74
  if (Number.isNaN(e)) return { ok: !1 };
70
- let r = (n(e) - d.getUTCDay() + 7) % 7;
71
- d.setUTCDate(d.getUTCDate() + r);
72
- } else if (c) {
73
- let e = Number(t.day);
74
- if (Number.isNaN(e)) return { ok: !1 };
75
- d.setUTCDate(e);
75
+ let n = (a(e) - p.getUTCDay() + 7) % 7;
76
+ p.setUTCDate(p.getUTCDate() + n);
76
77
  }
77
- return {
78
+ let m = u ? r(String(t.day), n(p)) : void 0;
79
+ return u && !m ? { ok: !1 } : {
78
80
  ok: !0,
79
81
  isHourly: !1,
80
- time: `${e(d.getHours())}:${e(d.getMinutes())}`,
81
- ...s ? { dayOfWeek: String(r(d.getDay())) } : {},
82
- ...c ? { dayOfMonth: String(d.getDate()) } : {}
82
+ time: `${e(p.getHours())}:${e(p.getMinutes())}`,
83
+ ...l ? { dayOfWeek: String(o(p.getDay())) } : {},
84
+ ...m ? { dayOfMonth: m } : {}
83
85
  };
84
- }, m = (e) => {
85
- if (!e.model || !e.prompt) return {
86
+ }, _ = (e) => {
87
+ if (!e.model || typeof e.prompt != "string" || !e.prompt.trim() && !e.skillUrls?.length) return {
86
88
  ok: !1,
87
89
  reason: t.MissingRequiredFields
88
90
  };
89
- let { date: n, cron: r } = e.trigger, a = !!n;
90
- if (a === !!r) return {
91
+ let { date: n, cron: r } = e.trigger, i = !!n;
92
+ if (i === !!r) return {
91
93
  ok: !1,
92
94
  reason: t.UnsupportedTriggerType
93
95
  };
94
- let s = {
96
+ let a = {
95
97
  displayName: e.displayName,
96
98
  modelId: e.model,
97
99
  prompt: e.prompt,
100
+ skillUrls: [...new Set(e.skillUrls ?? [])],
98
101
  ...e.description ? { description: e.description } : {}
99
102
  };
100
- if (a) return {
103
+ if (i) return {
101
104
  ok: !0,
102
105
  values: {
103
- ...s,
104
- repeat: i.OneTime,
105
- runAt: d(n),
106
- time: o
106
+ ...a,
107
+ repeat: s.OneTime,
108
+ runAt: m(n),
109
+ time: l
107
110
  }
108
111
  };
109
112
  if (!r) return {
110
113
  ok: !1,
111
114
  reason: t.UnsupportedTriggerType
112
115
  };
113
- let c = p(r.fields);
114
- if (!c.ok) return {
116
+ let o = g(r.fields);
117
+ if (!o.ok) return {
115
118
  ok: !1,
116
119
  reason: t.UnsupportedCronShape
117
120
  };
118
- if (c.isHourly) return {
121
+ if (o.isHourly) return {
119
122
  ok: !0,
120
123
  values: {
121
- ...s,
122
- repeat: i.Hourly,
123
- time: o,
124
- minute: c.minute,
125
- ...r.startDate ? { startDate: f(r.startDate) } : {},
126
- ...r.endDate ? { endDate: f(r.endDate) } : {}
124
+ ...a,
125
+ repeat: s.Hourly,
126
+ time: l,
127
+ minute: o.minute,
128
+ ...r.startDate ? { startDate: h(r.startDate) } : {},
129
+ ...r.endDate ? { endDate: h(r.endDate) } : {}
127
130
  }
128
131
  };
129
- let l = i.Daily;
130
- return c.dayOfWeek ? l = i.Weekly : c.dayOfMonth && (l = i.Monthly), {
132
+ let c = s.Daily;
133
+ return o.dayOfWeek ? c = s.Weekly : o.dayOfMonth && (c = s.Monthly), {
131
134
  ok: !0,
132
135
  values: {
133
- ...s,
134
- repeat: l,
135
- time: c.time,
136
- ...c.dayOfWeek ? { dayOfWeek: c.dayOfWeek } : {},
137
- ...c.dayOfMonth ? { dayOfMonth: c.dayOfMonth } : {},
138
- ...r.startDate ? { startDate: f(r.startDate) } : {},
139
- ...r.endDate ? { endDate: f(r.endDate) } : {}
136
+ ...a,
137
+ repeat: c,
138
+ time: o.time,
139
+ ...o.dayOfWeek ? { dayOfWeek: o.dayOfWeek } : {},
140
+ ...o.dayOfMonth ? { dayOfMonth: o.dayOfMonth } : {},
141
+ ...r.startDate ? { startDate: h(r.startDate) } : {},
142
+ ...r.endDate ? { endDate: h(r.endDate) } : {}
140
143
  }
141
144
  };
142
145
  };
143
146
  //#endregion
144
- export { l as mapFormValuesToCreateBody, u as mapFormValuesToUpdateBody, m as mapScheduledTaskDtoToFormValues };
147
+ export { f as mapFormValuesToCreateBody, p as mapFormValuesToUpdateBody, _ as mapScheduledTaskDtoToFormValues };
@@ -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 };