@epam/ai-dial-chat-hooks 1.2.0-dev.98 → 1.2.0-rc.0

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 (84) hide show
  1. package/api-error/api-error.js +7 -4
  2. package/catalog/catalog-derivations.js +1 -1
  3. package/catalog/deployment-id.js +8 -2
  4. package/catalog/map-deployment-limits-to-catalog.js +16 -24
  5. package/catalog/map-deployment-limits-to-input.js +81 -9
  6. package/catalog/map-deployment-to-catalog-item.js +34 -34
  7. package/catalog/map-entity-details-to-catalog.js +237 -192
  8. package/catalog/map-skill-to-catalog-item.js +61 -54
  9. package/catalog/publish.js +4 -4
  10. package/catalog/useCatalogEditNavigation/useCatalogEditNavigation.js +122 -101
  11. package/catalog/useCatalogItemDetails.js +9 -8
  12. package/catalog/usePublishFolders/usePublishFolders.js +1 -1
  13. package/catalog.d.ts +171 -34
  14. package/catalog.js +23 -23
  15. package/conversation/conversation-transfer/export-conversation.js +24 -16
  16. package/conversation/conversation-transfer/import-conversation.js +80 -31
  17. package/conversation/create-chat-stream-api.js +85 -49
  18. package/conversation/get-model-id-from-conversation-id.js +15 -9
  19. package/conversation/message-utils.js +44 -2
  20. package/conversation/stage.js +6 -2
  21. package/conversation/useActiveConversationSync/useActiveConversationSync.js +7 -8
  22. package/conversation/useConversationExport/useConversationExport.js +9 -9
  23. package/conversation/useConversationHandlers/message-utils.js +8 -5
  24. package/conversation/useConversationHandlers/useConversationHandlers.js +181 -167
  25. package/conversation/useConversationImport/useConversationImport.js +123 -121
  26. package/conversation/useConversationPanelItems/useConversationPanelItems.js +49 -31
  27. package/conversation/useConversationStream/frame-scheduler.js +39 -0
  28. package/conversation/useConversationStream/generation-resume.js +122 -64
  29. package/conversation/useConversationStream/useConversationStream.js +277 -118
  30. package/conversation/useMessageSelectionReply/useMessageSelectionReply.js +189 -0
  31. package/conversation-sources/useConversationSources/useConversationSources.js +31 -24
  32. package/conversation-sources.d.ts +1 -1
  33. package/conversation-transfer.d.ts +2 -1
  34. package/conversation.d.ts +205 -22
  35. package/conversation.js +32 -31
  36. package/file-manager-canvas.d.ts +27 -7
  37. package/file-manager.d.ts +87 -32
  38. package/file-manager.js +25 -24
  39. package/files/attachment-canvas.js +67 -44
  40. package/files/dial-file-manager-copy-move.util.js +9 -8
  41. package/files/dial-file-manager-mapping.util.js +2 -1
  42. package/files/dial-file-manager-path.util.js +24 -2
  43. package/files/dial-file-manager.model.js +23 -19
  44. package/files/dial-file-manager.types.js +3 -3
  45. package/files/file-manager-variant.js +1 -1
  46. package/files/resolve-dial-file-api-path.js +11 -12
  47. package/files/useDialFileListing/useDialFileListing.js +140 -127
  48. package/files/useDialFileManager/useDialFileManager.js +139 -135
  49. package/files/useDialFileManagerSections/useDialFileManagerSections.js +155 -0
  50. package/files/useDialFileManagerTabConfig/useDialFileManagerTabConfig.js +20 -15
  51. package/files/useDialFileMutations/useDialFileMutations.js +65 -60
  52. package/files/useDialFileUploadBatch/useDialFileUploadBatch.js +117 -110
  53. package/files/useFileAttachmentPicker/useFileAttachmentPicker.js +28 -23
  54. package/index.d.ts +630 -128
  55. package/index.js +136 -134
  56. package/mcp-apps/useMcpAppTools/useMcpAppTools.js +1 -1
  57. package/oauth/authorize-url.js +3 -3
  58. package/oauth/toolset-id.js +5 -3
  59. package/oauth/useToolsetLogin/useToolsetLogin.js +8 -8
  60. package/oauth.d.ts +34 -2
  61. package/oauth.js +9 -9
  62. package/package.json +19 -23
  63. package/scheduled-task/scheduled-task-description.js +43 -39
  64. package/scheduled-task/scheduled-task-trigger.js +74 -71
  65. package/scheduled-task/use-scheduled-task-runs.js +162 -50
  66. package/scheduled-task/use-scheduled-tasks.js +52 -48
  67. package/scheduled-tasks.d.ts +27 -6
  68. package/scheduled-tasks.js +2 -2
  69. package/shared/application-schema.js +5 -2
  70. package/shared/cron-day-of-month.js +13 -0
  71. package/skill/skill-archive.js +19 -0
  72. package/skill/skill-types.js +8 -7
  73. package/skill/skill.js +52 -29
  74. package/skill/useSkillArchiveImport/useSkillArchiveImport.js +38 -34
  75. package/skill/useSkillEditorLoad.js +65 -59
  76. package/skill/useSkillEditorSubmit.js +105 -93
  77. package/skill/useSkillFileActions.js +70 -58
  78. package/skill-editor.d.ts +62 -13
  79. package/skill-editor.js +9 -9
  80. package/usage/map-user-usage-to-model-limits.js +137 -95
  81. package/usage.d.ts +8 -3
  82. package/usePageFileDrag/usePageFileDrag.js +3 -3
  83. package/utils.d.ts +26 -6
  84. package/utils.js +10 -10
@@ -0,0 +1,189 @@
1
+ import { useCallback as e, useEffect as t, useLayoutEffect as n, useMemo as r, useRef as i, useState as a } from "react";
2
+ //#region src/conversation/useMessageSelectionReply/useMessageSelectionReply.ts
3
+ var o = "button,input,textarea,select,iframe,[role=\"button\"],[contenteditable=\"true\"],[hidden],[inert],[aria-hidden=\"true\"]", s = [], c = (e, t) => e?.startContainer === t.startContainer && e.startOffset === t.startOffset && e.endContainer === t.endContainer && e.endOffset === t.endOffset, l = (e, t) => {
4
+ let n = window.visualViewport, r = n?.offsetLeft ?? 0, i = n?.offsetTop ?? 0, a = r + (n?.width ?? document.documentElement.clientWidth), o = i + (n?.height ?? document.documentElement.clientHeight);
5
+ for (let e = t; e; e = e.parentElement) {
6
+ let t = getComputedStyle(e);
7
+ if (t.display === "none" || t.visibility === "hidden") return;
8
+ let n = e.getBoundingClientRect();
9
+ /(hidden|clip|auto|scroll)/.test(t.overflowX) && (r = Math.max(r, n.left), a = Math.min(a, n.right)), /(hidden|clip|auto|scroll)/.test(t.overflowY) && (i = Math.max(i, n.top), o = Math.min(o, n.bottom));
10
+ }
11
+ return Array.from(e.getClientRects()).find((e) => e.width > 0 && e.height > 0 && e.left < a && e.right > r && e.top < o && e.bottom > i);
12
+ }, u = ({ conversationId: u, enabled: d, droppedFiles: f, onDroppedFilesConsumed: p }) => {
13
+ let m = i(/* @__PURE__ */ new Set()), h = i(null), g = i(null), _ = i(null), [v, y] = a(null), [b, x] = a({
14
+ conversationId: u,
15
+ files: []
16
+ }), [S, C] = a(), [w, T] = a(0), E = i(/* @__PURE__ */ new WeakSet()), D = i({
17
+ conversationId: u,
18
+ enabled: d
19
+ });
20
+ n(() => {
21
+ D.current = {
22
+ conversationId: u,
23
+ enabled: d
24
+ };
25
+ }, [u, d]);
26
+ let O = e(() => {
27
+ _.current = g.current?.range.cloneRange() ?? null, g.current = null, y(null);
28
+ }, []), k = e((e) => {
29
+ if (e) return m.current.add(e), () => {
30
+ m.current.delete(e), g.current?.body === e && O();
31
+ };
32
+ }, [O]);
33
+ t(() => {
34
+ O(), _.current = null, E.current = /* @__PURE__ */ new WeakSet(), x({
35
+ conversationId: u,
36
+ files: []
37
+ }), T(0), C(void 0);
38
+ }, [u, O]), t(() => {
39
+ if (!d) {
40
+ O(), x({
41
+ conversationId: u,
42
+ files: []
43
+ });
44
+ return;
45
+ }
46
+ let e = 0, t = !1, n = !1, r = !1, i = () => {
47
+ if (e = 0, t || n || r || h.current?.contains(document.activeElement)) return;
48
+ let i = window.getSelection();
49
+ if (!i || i.rangeCount !== 1 || i.isCollapsed || !i.toString().trim()) {
50
+ O();
51
+ return;
52
+ }
53
+ let a = i.getRangeAt(0);
54
+ if (c(_.current, a)) return;
55
+ let s = [...m.current].find((e) => e.contains(a.startContainer) && e.contains(a.endContainer));
56
+ if (!s || !s.isConnected) {
57
+ O();
58
+ return;
59
+ }
60
+ let d = a.cloneContents();
61
+ d.querySelectorAll(o).forEach((e) => e.remove());
62
+ let f = a.commonAncestorContainer;
63
+ if ((f instanceof Element ? f : f.parentElement)?.closest(o) || !d.textContent?.trim()) {
64
+ O();
65
+ return;
66
+ }
67
+ let p = l(a, s);
68
+ if (!p) {
69
+ O();
70
+ return;
71
+ }
72
+ let v = {
73
+ conversationId: u,
74
+ body: s,
75
+ range: a.cloneRange(),
76
+ text: i.toString(),
77
+ rect: p
78
+ };
79
+ g.current = v, y(v);
80
+ }, a = () => {
81
+ e && cancelAnimationFrame(e), e = requestAnimationFrame(i);
82
+ }, s = () => {
83
+ e && cancelAnimationFrame(e), e = requestAnimationFrame(() => {
84
+ e = 0;
85
+ let t = g.current;
86
+ if (!t) return;
87
+ let n = l(t.range, t.body);
88
+ if (!n) O();
89
+ else {
90
+ let e = {
91
+ ...t,
92
+ rect: n
93
+ };
94
+ g.current = e, y(e);
95
+ }
96
+ });
97
+ }, f = (e) => {
98
+ t = h.current?.contains(e.target) ?? !1, n = !t, t || (O(), [...m.current].some((t) => t.contains(e.target)) && (_.current = null));
99
+ }, p = () => {
100
+ n = !1, t || a(), t = !1;
101
+ }, v = () => {
102
+ n = !1, r = !1, t = !1, O();
103
+ let e = window.getSelection();
104
+ _.current = e?.rangeCount ? e.getRangeAt(0).cloneRange() : null;
105
+ }, b = (e) => {
106
+ if (!h.current?.contains(document.activeElement) && (e.shiftKey && [
107
+ "ArrowLeft",
108
+ "ArrowRight",
109
+ "ArrowUp",
110
+ "ArrowDown",
111
+ "Home",
112
+ "End",
113
+ "PageUp",
114
+ "PageDown"
115
+ ].includes(e.key) || (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a")) {
116
+ r = !0, O(), _.current = null;
117
+ return;
118
+ }
119
+ if (g.current) {
120
+ if (e.key === "Escape") {
121
+ O();
122
+ return;
123
+ }
124
+ if (e.key === "Tab" && !e.shiftKey && !h.current?.contains(document.activeElement)) {
125
+ let t = h.current?.querySelector("button");
126
+ t && (e.preventDefault(), t.focus());
127
+ }
128
+ }
129
+ }, S = (e) => {
130
+ r && !e.shiftKey && (r = !1), e.key !== "Escape" && e.key !== "Tab" && a();
131
+ }, C = new MutationObserver((e) => {
132
+ let t = g.current;
133
+ t && (!t.body.isConnected || e.some((e) => t.body.contains(e.target))) && O();
134
+ });
135
+ return C.observe(document.body, {
136
+ subtree: !0,
137
+ childList: !0,
138
+ characterData: !0,
139
+ attributes: !0,
140
+ attributeFilter: [
141
+ "class",
142
+ "style",
143
+ "hidden",
144
+ "inert"
145
+ ]
146
+ }), document.addEventListener("selectionchange", a), document.addEventListener("pointerdown", f, !0), document.addEventListener("pointerup", p, !0), document.addEventListener("pointercancel", v, !0), window.addEventListener("blur", v), document.addEventListener("keydown", b), document.addEventListener("keyup", S), document.addEventListener("scroll", s, !0), window.addEventListener("resize", s), window.visualViewport?.addEventListener("resize", s), window.visualViewport?.addEventListener("scroll", s), () => {
147
+ cancelAnimationFrame(e), C.disconnect(), document.removeEventListener("selectionchange", a), document.removeEventListener("pointerdown", f, !0), document.removeEventListener("pointerup", p, !0), document.removeEventListener("pointercancel", v, !0), window.removeEventListener("blur", v), document.removeEventListener("keydown", b), document.removeEventListener("keyup", S), document.removeEventListener("scroll", s, !0), window.removeEventListener("resize", s), window.visualViewport?.removeEventListener("resize", s), window.visualViewport?.removeEventListener("scroll", s);
148
+ };
149
+ }, [
150
+ u,
151
+ O,
152
+ d
153
+ ]);
154
+ let A = e(() => {
155
+ let e = g.current;
156
+ if (!D.current.enabled || !e || e.conversationId !== D.current.conversationId || !e.body.isConnected || !l(e.range, e.body)) return;
157
+ let t = new File([e.text], `reply-${crypto.randomUUID()}.txt`, { type: "text/plain" });
158
+ E.current.add(t), T(0), x((n) => ({
159
+ conversationId: e.conversationId,
160
+ files: [...n.conversationId === e.conversationId ? n.files : [], t]
161
+ })), C((e) => (e ?? 0) + 1), O(), window.getSelection()?.removeAllRanges();
162
+ }, [O]), j = d && b.conversationId === u ? b.files : s, M = r(() => [...f, ...j], [f, j]), N = e(() => {
163
+ f.length && p(), x((e) => ({
164
+ ...e,
165
+ files: e.files.filter((e) => !j.includes(e))
166
+ }));
167
+ }, [
168
+ f,
169
+ p,
170
+ j
171
+ ]), P = e((e) => {
172
+ let t = e.filter((e) => e.file && E.current.has(e.file));
173
+ t.length && (t.forEach((e) => E.current.delete(e.file)), T((e) => e + 1));
174
+ }, []);
175
+ return {
176
+ contentRef: k,
177
+ actionRef: h,
178
+ selection: d && v?.conversationId === u ? v : null,
179
+ onReply: A,
180
+ dismiss: O,
181
+ pendingFiles: M,
182
+ onFilesConsumed: N,
183
+ focusRequestId: S,
184
+ onAttachmentsChange: P,
185
+ addedRevision: w
186
+ };
187
+ };
188
+ //#endregion
189
+ export { u as useMessageSelectionReply };
@@ -1,35 +1,42 @@
1
1
  import { MessageRole as e, messageAttachmentToDisplayAttachment as t } from "@epam/ai-dial-chat-shared";
2
- import { isReferenceOnlyAttachment as n, resolveMessageAnnotations as r } from "@epam/ai-dial-quotations";
3
- import { useMemo as i } from "react";
2
+ import { getAnnotationPdfPage as n, isReferenceOnlyAttachment as r, parsePdfPageReference as i, resolveMessageAnnotations as a } from "@epam/ai-dial-quotations";
3
+ import { useMemo as o } from "react";
4
4
  //#region src/conversation-sources/useConversationSources/useConversationSources.ts
5
- var a = {}, o = (o, s = a) => i(() => {
6
- let i = [], a = [], c = [], l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set();
7
- for (let f of o) {
8
- let o = f.custom_content?.attachments;
9
- if (f.role === e.User) for (let e of o ?? []) {
10
- let n = t(e, s);
11
- u.has(n.id) || (u.add(n.id), i.push(n));
5
+ var s = {}, c = (e, t) => {
6
+ let r = n(e);
7
+ if (r == null) return t;
8
+ let a = i(t);
9
+ return a == null || a.page != null ? t : `${t}#page=${r}`;
10
+ }, l = (n, i = s) => o(() => {
11
+ let o = [], s = [], l = [], u = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set(), f = /* @__PURE__ */ new Set();
12
+ for (let p of n) {
13
+ let n = p.custom_content?.attachments;
14
+ if (p.role === e.User) for (let e of n ?? []) {
15
+ let n = t(e, i);
16
+ d.has(n.id) || (d.add(n.id), o.push(n));
12
17
  }
13
- else if (f.role === e.Assistant) {
14
- let e = o?.filter((e) => !n(e));
18
+ else if (p.role === e.Assistant) {
19
+ let e = n?.filter((e) => !r(e));
15
20
  for (let n of e ?? []) {
16
- let e = t(n, s);
17
- d.has(e.id) || (d.add(e.id), a.push(e));
21
+ let e = t(n, i);
22
+ f.has(e.id) || (f.add(e.id), s.push(e));
18
23
  }
19
- for (let e of o ?? []) {
20
- if (!n(e)) continue;
24
+ for (let e of n ?? []) {
25
+ if (!r(e)) continue;
21
26
  let t = e.reference_url;
22
- l.has(t) || (l.add(t), c.push({
27
+ u.has(t) || (u.add(t), l.push({
23
28
  url: t,
24
29
  title: e.title ?? t,
25
30
  contentType: e.reference_type ?? e.type ?? "",
26
31
  quote: e.data
27
32
  }));
28
33
  }
29
- for (let e of r(f)) {
34
+ for (let e of a(p)) {
30
35
  let t = e?.body?.source?.attachment, n = t?.url;
31
- !n || l.has(n) || (l.add(n), c.push({
32
- url: n,
36
+ if (!n) continue;
37
+ let r = c(e, n);
38
+ u.has(r) || (u.add(r), l.push({
39
+ url: r,
33
40
  title: t?.title ?? n.split("/").pop() ?? n,
34
41
  contentType: t?.type ?? "",
35
42
  quote: e.body?.quote
@@ -38,10 +45,10 @@ var a = {}, o = (o, s = a) => i(() => {
38
45
  }
39
46
  }
40
47
  return {
41
- uploaded: i,
42
- generated: a,
43
- sources: c
48
+ uploaded: o,
49
+ generated: s,
50
+ sources: l
44
51
  };
45
- }, [o, s]);
52
+ }, [n, i]);
46
53
  //#endregion
47
- export { o as useConversationSources };
54
+ export { l as useConversationSources };
@@ -18,7 +18,7 @@ export declare interface UseConversationSourcesResult {
18
18
  uploaded: DisplayAttachment[];
19
19
  /** Deduplicated attachments the assistant generated across the conversation. */
20
20
  generated: DisplayAttachment[];
21
- /** Quotation sources referenced by assistant messages, deduplicated by URL. */
21
+ /** Quotation sources referenced by assistant messages, deduplicated by URL; PDF sources are qualified with `#page=N`. */
22
22
  sources: QuotationSource[];
23
23
  }
24
24
 
@@ -139,7 +139,8 @@ export declare interface UseConversationExportResult {
139
139
  * `.dial`/`.zip`, v5 envelope, old- or new-chat origin) once per file, then
140
140
  * re-uploads any archive attachments to `uploads/<YYYY-MM>/` —
141
141
  * disambiguating a name collision with a ` (n)` suffix instead of rejecting
142
- * it — rewrites attachment references (and renamed titles), regenerates each
142
+ * it — rewrites attachment references (and renamed titles), drops any
143
+ * reference still pointing into another user's bucket, regenerates each
143
144
  * conversation's id/path with a fresh UUID (collision-free save, no replace
144
145
  * dialog), and persists every conversation through the injected
145
146
  * `conversationsApi`. One job per imported file, not per conversation.