@epam/ai-dial-chat-hooks 1.2.0-dev.101 → 1.2.0-dev.102

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.
package/index.d.ts CHANGED
@@ -6079,6 +6079,10 @@ export declare interface UseSkillEditorSubmitResult {
6079
6079
  errors: SkillEditorErrors;
6080
6080
  /** General submit-time error, distinct from a stale-edit `conflict`. */
6081
6081
  submitError: string | undefined;
6082
+ /** Whether `submitError` was caused by something a plain re-send can clear, rather than by the submission itself. */
6083
+ isSubmitErrorRetryable: boolean;
6084
+ /** Re-submits the values of the attempt that produced `submitError`. No-op before the first submit. */
6085
+ retrySubmit: () => void;
6082
6086
  /** Present when the last save hit a stale-ETag conflict. */
6083
6087
  conflict: {
6084
6088
  message: string;
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.101",
4
+ "version": "1.2.0-dev.102",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "./index.js",
@@ -111,7 +111,7 @@
111
111
  }
112
112
  },
113
113
  "dependencies": {
114
- "@epam/ai-dial-chat-api-client": "1.2.0-dev.101",
114
+ "@epam/ai-dial-chat-api-client": "1.2.0-dev.102",
115
115
  "dompurify": "3.4.15",
116
116
  "fflate": "^0.8.3",
117
117
  "lru-cache": "^10.4.3",
@@ -120,22 +120,22 @@
120
120
  },
121
121
  "peerDependencies": {
122
122
  "react": "^19.2.8",
123
- "@epam/ai-dial-attachment-canvas": "1.2.0-dev.101",
124
- "@epam/ai-dial-attachment-input": "1.2.0-dev.101",
125
- "@epam/ai-dial-builder-form": "1.2.0-dev.101",
126
- "@epam/ai-dial-catalog": "1.2.0-dev.101",
127
- "@epam/ai-dial-chat-overlay": "1.2.0-dev.101",
128
- "@epam/ai-dial-chat-shared": "1.2.0-dev.101",
129
- "@epam/ai-dial-mcp-apps": "1.2.0-dev.101",
130
- "@epam/ai-dial-publish-panel": "1.2.0-dev.101",
131
- "@epam/ai-dial-quotations": "1.2.0-dev.101",
123
+ "@epam/ai-dial-attachment-canvas": "1.2.0-dev.102",
124
+ "@epam/ai-dial-attachment-input": "1.2.0-dev.102",
125
+ "@epam/ai-dial-builder-form": "1.2.0-dev.102",
126
+ "@epam/ai-dial-catalog": "1.2.0-dev.102",
127
+ "@epam/ai-dial-chat-overlay": "1.2.0-dev.102",
128
+ "@epam/ai-dial-chat-shared": "1.2.0-dev.102",
129
+ "@epam/ai-dial-mcp-apps": "1.2.0-dev.102",
130
+ "@epam/ai-dial-publish-panel": "1.2.0-dev.102",
131
+ "@epam/ai-dial-quotations": "1.2.0-dev.102",
132
132
  "@epam/ai-dial-react-file-manager": "^0.3.0-dev.4",
133
- "@epam/ai-dial-scheduled-tasks": "1.2.0-dev.101",
134
- "@epam/ai-dial-share": "1.2.0-dev.101",
135
- "@epam/ai-dial-skill-editor": "1.2.0-dev.101",
136
- "@epam/ai-dial-source-panel": "1.2.0-dev.101",
133
+ "@epam/ai-dial-scheduled-tasks": "1.2.0-dev.102",
134
+ "@epam/ai-dial-share": "1.2.0-dev.102",
135
+ "@epam/ai-dial-skill-editor": "1.2.0-dev.102",
136
+ "@epam/ai-dial-source-panel": "1.2.0-dev.102",
137
137
  "@epam/ai-dial-ui-kit": "^0.15.0-dev.12",
138
- "@epam/ai-dial-usage-dashboard": "1.2.0-dev.101",
138
+ "@epam/ai-dial-usage-dashboard": "1.2.0-dev.102",
139
139
  "@modelcontextprotocol/sdk": "^1.29.0",
140
140
  "@epam/pdf-highlighter-kit": "^0.0.19",
141
141
  "@mcp-ui/client": "^7.1.1"
@@ -6,12 +6,12 @@ import { SkillFileNodeKind as u } from "@epam/ai-dial-skill-editor";
6
6
  //#region src/skill/useSkillEditorLoad.ts
7
7
  var d = /* @__PURE__ */ function(e) {
8
8
  return e.Loading = "loading", e.Loaded = "loaded", e.Error = "error", e.Forbidden = "forbidden", e.NotFound = "not-found", e;
9
- }({}), f = class extends Error {}, p = (e, r) => {
9
+ }({}), f = class extends Error {}, p = class extends Error {}, m = (e, r) => {
10
10
  let i = e.parentPath ? t(e.parentPath) : "", a = `${n(r)}/files`;
11
11
  return i === a ? e.name : i.startsWith(`${a}/`) ? `${i.slice(a.length + 1)}/${e.name}` : i === "files" ? e.name : i.startsWith("files/") ? `${i.slice(6)}/${e.name}` : null;
12
- }, m = async (e, t, n) => {
12
+ }, h = async (e, t, n) => {
13
13
  let r = await e.downloadSkill(t, n), i = r.headers.get("etag");
14
- if (!i) throw new f("Skill ETag is missing");
14
+ if (!i) throw new p("Skill ETag is missing");
15
15
  try {
16
16
  let e = await r.arrayBuffer(), { manifestText: t, files: n } = o(new Uint8Array(e));
17
17
  return {
@@ -22,17 +22,17 @@ var d = /* @__PURE__ */ function(e) {
22
22
  } catch {
23
23
  throw new f("Skill ZIP is invalid");
24
24
  }
25
- }, h = async (e, t, n) => {
25
+ }, g = async (e, t, n) => {
26
26
  let [i, a] = await Promise.all([e.downloadSkillFile(t, n, r), e.listSkillFiles({
27
27
  bucket: t,
28
28
  path: n,
29
29
  filePath: "",
30
30
  recursive: !0
31
- })]), o = a.items.find((e) => e.nodeType === "item" && p(e, n) === "SKILL.md"), s = i.headers.get("etag") ?? o?.etag;
32
- if (!s) throw Error("Skill ETag is missing");
31
+ })]), o = a.items.find((e) => e.nodeType === "item" && m(e, n) === "SKILL.md"), s = i.headers.get("etag") ?? o?.etag;
32
+ if (!s) throw new p("Skill ETag is missing");
33
33
  let c = a.items.filter((e) => e.nodeType === "item").map((e) => ({
34
34
  item: e,
35
- path: p(e, n)
35
+ path: m(e, n)
36
36
  })).filter((e) => e.path != null && e.path !== "SKILL.md"), l = await Promise.all(c.map(async ({ path: r }) => {
37
37
  let i = await e.downloadSkillFile(t, n, r);
38
38
  return [r, new Uint8Array(await i.arrayBuffer())];
@@ -42,40 +42,41 @@ var d = /* @__PURE__ */ function(e) {
42
42
  manifestText: await i.text(),
43
43
  files: new Map(l)
44
44
  };
45
- }, g = ({ isEditMode: t, bucket: n, skillPath: r, client: o }) => {
46
- let [d, p] = l(t ? "loading" : "loaded"), [g, _] = l(0), [v, y] = l(), b = c(void 0), x = c({}), S = c(void 0), [C, w] = l([]), T = c(/* @__PURE__ */ new Map());
45
+ }, _ = ({ isEditMode: t, bucket: n, skillPath: r, client: o }) => {
46
+ let [d, m] = l(t ? "loading" : "loaded"), [_, v] = l(0), [y, b] = l(), x = c(void 0), S = c({}), C = c(void 0), [w, T] = l([]), E = c(/* @__PURE__ */ new Map());
47
47
  return s(() => {
48
48
  if (!t || !n) return;
49
49
  if (r == null) {
50
- p("error");
50
+ m("error");
51
51
  return;
52
52
  }
53
53
  let s = !1;
54
- return p("loading"), (async () => {
54
+ return m("loading"), (async () => {
55
55
  if (await Promise.resolve(), !s) try {
56
56
  let t;
57
57
  try {
58
- t = await m(o, n, r);
58
+ t = await h(o, n, r);
59
59
  } catch (i) {
60
+ if (i instanceof p) throw i;
60
61
  let a = e(i);
61
62
  if (!(i instanceof f) && a !== 400) throw i;
62
- t = await h(o, n, r);
63
+ t = await g(o, n, r);
63
64
  }
64
65
  let { frontmatter: c, instructions: l } = a(t.manifestText);
65
66
  if (s) return;
66
- b.current = t.etag, x.current = c, S.current = r, T.current = new Map([...t.files].map(([e, t]) => [e, { bytes: t }])), w([...t.files.keys()].map((e) => ({
67
+ x.current = t.etag, S.current = c, C.current = r, E.current = new Map([...t.files].map(([e, t]) => [e, { bytes: t }])), T([...t.files.keys()].map((e) => ({
67
68
  path: e,
68
69
  name: i(e),
69
70
  kind: u.File
70
- }))), y({
71
+ }))), b({
71
72
  name: typeof c.name == "string" ? c.name : "",
72
73
  description: typeof c.description == "string" ? c.description : "",
73
74
  instructions: l
74
- }), p("loaded");
75
+ }), m("loaded");
75
76
  } catch (t) {
76
77
  if (s) return;
77
78
  let n = e(t);
78
- p(n === 403 ? "forbidden" : n === 404 ? "not-found" : "error");
79
+ m(n === 403 ? "forbidden" : n === 404 ? "not-found" : "error");
79
80
  }
80
81
  })(), () => {
81
82
  s = !0;
@@ -84,20 +85,20 @@ var d = /* @__PURE__ */ function(e) {
84
85
  t,
85
86
  n,
86
87
  r,
87
- g,
88
+ _,
88
89
  o
89
90
  ]), {
90
91
  loadState: d,
91
- loadedValues: v,
92
- setLoadedValues: y,
93
- files: C,
94
- setFiles: w,
95
- filesContentRef: T,
96
- frontmatterRef: x,
97
- etagRef: b,
98
- loadedPathRef: S,
99
- retryLoad: () => _((e) => e + 1)
92
+ loadedValues: y,
93
+ setLoadedValues: b,
94
+ files: w,
95
+ setFiles: T,
96
+ filesContentRef: E,
97
+ frontmatterRef: S,
98
+ etagRef: x,
99
+ loadedPathRef: C,
100
+ retryLoad: () => v((e) => e + 1)
100
101
  };
101
102
  };
102
103
  //#endregion
103
- export { d as SkillEditorLoadState, g as useSkillEditorLoad };
104
+ export { d as SkillEditorLoadState, _ as useSkillEditorLoad };
@@ -7,7 +7,7 @@ var d = (e, t) => JSON.stringify({
7
7
  values: e,
8
8
  files: [...t].sort((e, t) => e.path.localeCompare(t.path))
9
9
  }), f = ({ bucket: f, isEditMode: p, files: m, filesContentRef: h, frontmatterRef: g, loadedPathRef: _, etagRef: v, returnUrl: y, refetchSkills: b, client: x, messages: S, onNavigate: C, onNotify: w }) => {
10
- let [T, E] = l({}), [D, O] = l(), [k, A] = l(), [j, M] = l("idle"), N = c(null), P = s(async (n) => {
10
+ let [T, E] = l({}), [D, O] = l(), [k, A] = l(!1), [j, M] = l(), [N, P] = l("idle"), F = c(null), I = c(null), L = s(async (n) => {
11
11
  switch (t(n)) {
12
12
  case 409:
13
13
  E({ name: S.nameConflict });
@@ -19,7 +19,7 @@ var d = (e, t) => JSON.stringify({
19
19
  O(S.archiveTooLarge);
20
20
  return;
21
21
  case 503:
22
- O(S.serviceUnavailable);
22
+ O(S.serviceUnavailable), A(!0);
23
23
  return;
24
24
  case 400: {
25
25
  let { message: t } = await e(n);
@@ -35,14 +35,14 @@ var d = (e, t) => JSON.stringify({
35
35
  });
36
36
  }
37
37
  }
38
- }, [S, w]), F = s(async (e) => {
38
+ }, [S, w]), R = s(async (e) => {
39
39
  let t = a(e.name);
40
40
  if (!t || !i(t)) {
41
41
  E({ name: S.nameInvalid });
42
42
  return;
43
43
  }
44
- let o = d(e, m), s = N.current, c = s != null && s.fingerprint === o, l = t, p, _, v;
45
- c ? {skillManifest: p, filePaths: _, files: v} = s : (p = r(g.current, t, e.description, e.instructions), {filePaths: _, files: v} = n(m, h.current)), M("submitting"), N.current = {
44
+ let o = d(e, m), s = F.current, c = s != null && s.fingerprint === o, l = t, p, _, v;
45
+ c ? {skillManifest: p, filePaths: _, files: v} = s : (p = r(g.current, t, e.description, e.instructions), {filePaths: _, files: v} = n(m, h.current)), P("submitting"), F.current = {
46
46
  fingerprint: o,
47
47
  bucket: f,
48
48
  path: l,
@@ -51,13 +51,13 @@ var d = (e, t) => JSON.stringify({
51
51
  files: v
52
52
  };
53
53
  try {
54
- await x.createSkill(f, l, p, _, v), await b(), M("success"), w({
54
+ await x.createSkill(f, l, p, _, v), await b(), P("success"), w({
55
55
  variant: u.Success,
56
56
  title: S.saveSuccessTitle,
57
57
  message: S.createSuccess(t)
58
58
  }), C(y);
59
59
  } catch (e) {
60
- M("failure"), await P(e);
60
+ P("failure"), await L(e);
61
61
  }
62
62
  }, [
63
63
  f,
@@ -70,27 +70,27 @@ var d = (e, t) => JSON.stringify({
70
70
  C,
71
71
  y,
72
72
  b,
73
- P
74
- ]), I = s(async (e) => {
73
+ L
74
+ ]), z = s(async (e) => {
75
75
  let i = _.current, a = v.current;
76
76
  if (!i || !a) {
77
77
  O(S.saveError);
78
78
  return;
79
79
  }
80
80
  let o = r(g.current, e.name, e.description, e.instructions), { filePaths: s, files: c } = n(m, h.current);
81
- M("submitting");
81
+ P("submitting");
82
82
  try {
83
- v.current = (await x.updateSkill(f, i, o, s, c, a)).etag ?? a, await b(), M("success"), w({
83
+ v.current = (await x.updateSkill(f, i, o, s, c, a)).etag ?? a, await b(), P("success"), w({
84
84
  variant: u.Success,
85
85
  title: S.updateSuccessTitle,
86
86
  message: S.updateSuccess(e.name)
87
87
  }), C(y);
88
88
  } catch (e) {
89
- if (M("failure"), t(e) === 412) {
90
- A({ message: S.conflictMessage });
89
+ if (P("failure"), t(e) === 412) {
90
+ M({ message: S.conflictMessage });
91
91
  return;
92
92
  }
93
- await P(e);
93
+ await L(e);
94
94
  }
95
95
  }, [
96
96
  f,
@@ -105,8 +105,8 @@ var d = (e, t) => JSON.stringify({
105
105
  C,
106
106
  y,
107
107
  b,
108
- P
109
- ]), L = s((e) => {
108
+ L
109
+ ]), B = s((e) => {
110
110
  let t = o(e.instructions);
111
111
  E((e) => {
112
112
  if (t === (e.instructions === S.instructionsFrontmatter)) return e;
@@ -117,30 +117,35 @@ var d = (e, t) => JSON.stringify({
117
117
  let n = { ...e };
118
118
  return delete n.instructions, n;
119
119
  });
120
- }, [S]);
120
+ }, [S]), V = s(async (e) => {
121
+ if (N === "submitting" || !f) return;
122
+ let t = {};
123
+ if (e.name.trim() || (t.name = S.required), e.description.trim() || (t.description = S.required), e.instructions.trim() ? o(e.instructions) && (t.instructions = S.instructionsFrontmatter) : t.instructions = S.required, Object.keys(t).length > 0) {
124
+ E(t);
125
+ return;
126
+ }
127
+ E({}), O(void 0), A(!1), M(void 0), I.current = e, p ? await z(e) : await R(e);
128
+ }, [
129
+ N,
130
+ f,
131
+ S,
132
+ p,
133
+ z,
134
+ R
135
+ ]);
121
136
  return {
122
- phase: j,
137
+ phase: N,
123
138
  errors: T,
124
139
  submitError: D,
125
- conflict: k,
126
- clearConflict: () => A(void 0),
127
- handleSubmit: s(async (e) => {
128
- if (j === "submitting" || !f) return;
129
- let t = {};
130
- if (e.name.trim() || (t.name = S.required), e.description.trim() || (t.description = S.required), e.instructions.trim() ? o(e.instructions) && (t.instructions = S.instructionsFrontmatter) : t.instructions = S.required, Object.keys(t).length > 0) {
131
- E(t);
132
- return;
133
- }
134
- E({}), O(void 0), A(void 0), p ? await I(e) : await F(e);
135
- }, [
136
- j,
137
- f,
138
- S,
139
- p,
140
- I,
141
- F
142
- ]),
143
- handleValuesChange: L
140
+ isSubmitErrorRetryable: k,
141
+ retrySubmit: s(() => {
142
+ let e = I.current;
143
+ e != null && V(e);
144
+ }, [V]),
145
+ conflict: j,
146
+ clearConflict: () => M(void 0),
147
+ handleSubmit: V,
148
+ handleValuesChange: B
144
149
  };
145
150
  };
146
151
  //#endregion
package/skill-editor.d.ts CHANGED
@@ -534,6 +534,10 @@ export declare interface UseSkillEditorSubmitResult {
534
534
  errors: SkillEditorErrors;
535
535
  /** General submit-time error, distinct from a stale-edit `conflict`. */
536
536
  submitError: string | undefined;
537
+ /** Whether `submitError` was caused by something a plain re-send can clear, rather than by the submission itself. */
538
+ isSubmitErrorRetryable: boolean;
539
+ /** Re-submits the values of the attempt that produced `submitError`. No-op before the first submit. */
540
+ retrySubmit: () => void;
537
541
  /** Present when the last save hit a stale-ETag conflict. */
538
542
  conflict: {
539
543
  message: string;