@watermarkinsights/ai-toolbox 0.0.1
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/README.md +5 -0
- package/dist/ai-toolbox.d.ts +112 -0
- package/dist/ai-toolbox.js +276 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# @watermarkinsights/ai-toolbox
|
|
2
|
+
|
|
3
|
+
React component SDK for embedding Watermark AI Toolbox features into your application. Provides pre-built components for authentication and chat interfaces that connect to the AI Toolbox platform.
|
|
4
|
+
|
|
5
|
+
For installation and usage instructions, see the [documentation](https://ds-ai-api-dev.watermarkinsights.com/toolbox/sdk/docs/).
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { JSX } from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { RunAgentResult } from '@copilotkit/react-core/v2';
|
|
4
|
+
import * as z from 'zod/mini';
|
|
5
|
+
|
|
6
|
+
declare type FileAttachment = File | FileAttachmentUrl;
|
|
7
|
+
|
|
8
|
+
declare type FileAttachmentUrl = {
|
|
9
|
+
url: string;
|
|
10
|
+
name: string;
|
|
11
|
+
mimeType: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
declare type SendMessageOptions = {
|
|
15
|
+
files?: FileAttachment[];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
declare const TOOLBOX_CHAT_SCHEMA: z.ZodMiniObject<{
|
|
19
|
+
product: z.ZodMiniString<string>;
|
|
20
|
+
sessionUrl: z.ZodMiniUnion<readonly [z.ZodMiniURL, z.ZodMiniCustom<() => Promise<{
|
|
21
|
+
sessionId: string;
|
|
22
|
+
institutionId: string;
|
|
23
|
+
}>, () => Promise<{
|
|
24
|
+
sessionId: string;
|
|
25
|
+
institutionId: string;
|
|
26
|
+
}>>]>;
|
|
27
|
+
fallback: z.ZodMiniOptional<z.ZodMiniCustom<ReactNode, ReactNode>>;
|
|
28
|
+
featureId: z.ZodMiniString<string>;
|
|
29
|
+
toolboxBaseUrl: z.ZodMiniOptional<z.ZodMiniURL>;
|
|
30
|
+
children: z.ZodMiniCustom<ReactNode, ReactNode>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
|
|
33
|
+
export declare const ToolboxChat: (props: ToolboxChatProps) => JSX.Element;
|
|
34
|
+
|
|
35
|
+
declare type ToolboxChatProps = z.infer<typeof TOOLBOX_CHAT_SCHEMA>;
|
|
36
|
+
|
|
37
|
+
export declare const useAgent: () => {
|
|
38
|
+
sendMessage: (message: string, options?: SendMessageOptions) => Promise<RunAgentResult>;
|
|
39
|
+
isRunning: boolean;
|
|
40
|
+
messages: ({
|
|
41
|
+
role: "developer";
|
|
42
|
+
content: string;
|
|
43
|
+
id: string;
|
|
44
|
+
name?: string | undefined;
|
|
45
|
+
encryptedValue?: string | undefined;
|
|
46
|
+
} | {
|
|
47
|
+
role: "system";
|
|
48
|
+
content: string;
|
|
49
|
+
id: string;
|
|
50
|
+
name?: string | undefined;
|
|
51
|
+
encryptedValue?: string | undefined;
|
|
52
|
+
} | {
|
|
53
|
+
role: "assistant";
|
|
54
|
+
id: string;
|
|
55
|
+
content?: string | undefined;
|
|
56
|
+
name?: string | undefined;
|
|
57
|
+
encryptedValue?: string | undefined;
|
|
58
|
+
toolCalls?: {
|
|
59
|
+
function: {
|
|
60
|
+
name: string;
|
|
61
|
+
arguments: string;
|
|
62
|
+
};
|
|
63
|
+
type: "function";
|
|
64
|
+
id: string;
|
|
65
|
+
encryptedValue?: string | undefined;
|
|
66
|
+
}[] | undefined;
|
|
67
|
+
} | {
|
|
68
|
+
role: "user";
|
|
69
|
+
content: string | ({
|
|
70
|
+
type: "text";
|
|
71
|
+
text: string;
|
|
72
|
+
} | {
|
|
73
|
+
type: "binary";
|
|
74
|
+
mimeType: string;
|
|
75
|
+
id?: string | undefined;
|
|
76
|
+
url?: string | undefined;
|
|
77
|
+
data?: string | undefined;
|
|
78
|
+
filename?: string | undefined;
|
|
79
|
+
})[];
|
|
80
|
+
id: string;
|
|
81
|
+
name?: string | undefined;
|
|
82
|
+
encryptedValue?: string | undefined;
|
|
83
|
+
} | {
|
|
84
|
+
role: "tool";
|
|
85
|
+
toolCallId: string;
|
|
86
|
+
content: string;
|
|
87
|
+
id: string;
|
|
88
|
+
encryptedValue?: string | undefined;
|
|
89
|
+
error?: string | undefined;
|
|
90
|
+
} | {
|
|
91
|
+
role: "activity";
|
|
92
|
+
content: Record<string, any>;
|
|
93
|
+
id: string;
|
|
94
|
+
activityType: string;
|
|
95
|
+
} | {
|
|
96
|
+
role: "reasoning";
|
|
97
|
+
content: string;
|
|
98
|
+
id: string;
|
|
99
|
+
encryptedValue?: string | undefined;
|
|
100
|
+
})[];
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export declare function useLatestToolCall<T = unknown>(toolName: string): T | undefined;
|
|
104
|
+
|
|
105
|
+
export declare function useToolCall<T = unknown>(toolName: string): T[];
|
|
106
|
+
|
|
107
|
+
export declare const useToolResponse: (toolName: string) => {
|
|
108
|
+
isWaiting: boolean;
|
|
109
|
+
respond: (response: unknown) => void;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export { }
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { CopilotKit as e, useCopilotContext as t } from "@copilotkit/react-core";
|
|
2
|
+
import { createContext as n, useCallback as r, useContext as i, useEffect as a, useMemo as o, useReducer as s, useRef as c, useState as l } from "react";
|
|
3
|
+
import * as u from "zod/mini";
|
|
4
|
+
import { z as d } from "zod/mini";
|
|
5
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
6
|
+
import { useAgent as m, useCopilotKit as h } from "@copilotkit/react-core/v2";
|
|
7
|
+
import { parse as g } from "partial-json";
|
|
8
|
+
//#region src/utilities/constants.ts
|
|
9
|
+
var _ = "https://ai-toolbox-qa.watermarkinsights.com", v = n(void 0), y = () => {
|
|
10
|
+
let e = i(v);
|
|
11
|
+
if (!e) throw Error("useAuth must be used in an <Auth/> component");
|
|
12
|
+
return e;
|
|
13
|
+
}, b = async ({ sessionId: e, institutionId: t, product: n, toolboxBaseUrl: r }) => {
|
|
14
|
+
let i = `${r}/api/session/cookie`, a = await fetch(i, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: { "Content-Type": "application/json" },
|
|
17
|
+
credentials: "include",
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
sessionId: e,
|
|
20
|
+
product: n,
|
|
21
|
+
institutionId: t
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
if (!a.ok) {
|
|
25
|
+
let e = await a.json().catch(() => ({ message: "Unknown error" }));
|
|
26
|
+
throw a.status === 400 ? Error(`Invalid session ID: ${e.message}`) : a.status === 404 ? Error(`Session not found: ${e.message}`) : Error(`Failed to set session cookie: ${e.message}`);
|
|
27
|
+
}
|
|
28
|
+
return a.json();
|
|
29
|
+
}, x = async (e) => {
|
|
30
|
+
let t = await fetch(e, {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers: {
|
|
33
|
+
Accept: "application/json",
|
|
34
|
+
"Content-Type": "application/json"
|
|
35
|
+
},
|
|
36
|
+
credentials: "include"
|
|
37
|
+
});
|
|
38
|
+
if (!t.ok) throw Error(`Failed to get toolbox session. Endpoint ${e} returned status ${t.status}.`);
|
|
39
|
+
let n;
|
|
40
|
+
try {
|
|
41
|
+
n = await t.json();
|
|
42
|
+
} catch (t) {
|
|
43
|
+
throw Error(`Could not parse JSON for toolbox session. Requested from ${e}`, { cause: t });
|
|
44
|
+
}
|
|
45
|
+
if (!n.sessionId || typeof n.sessionId != "string") throw Error(`Invalid sessionId received from ${e}. Received ${n.sessionId}`);
|
|
46
|
+
if (!n.institutionId || typeof n.institutionId != "string") throw Error(`Invalid institution received from ${e}. Received ${n.institutionId}`);
|
|
47
|
+
let { sessionId: r, institutionId: i } = n;
|
|
48
|
+
return {
|
|
49
|
+
sessionId: r,
|
|
50
|
+
institutionId: i
|
|
51
|
+
};
|
|
52
|
+
}, S = async (e) => {
|
|
53
|
+
if (typeof e == "function") {
|
|
54
|
+
let t = await e();
|
|
55
|
+
if (!t.sessionId || typeof t.sessionId != "string") throw Error(`Invalid sessionId returned from sessionUrl function. Received ${t.sessionId}`);
|
|
56
|
+
if (!t.institutionId || typeof t.institutionId != "string") throw Error(`Invalid institution returned from sessionUrl function. Received ${t.institutionId}`);
|
|
57
|
+
return {
|
|
58
|
+
sessionId: t.sessionId,
|
|
59
|
+
institutionId: t.institutionId
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
new URL(e);
|
|
64
|
+
} catch (t) {
|
|
65
|
+
throw Error(`sessionUrl is not a valid url: ${e}`, { cause: t });
|
|
66
|
+
}
|
|
67
|
+
return x(e);
|
|
68
|
+
}, C = d.object({
|
|
69
|
+
product: d.string(),
|
|
70
|
+
sessionUrl: d.union([d.url(), d.custom((e) => typeof e == "function")]),
|
|
71
|
+
children: d.custom(),
|
|
72
|
+
fallback: d.optional(d.custom()),
|
|
73
|
+
toolboxBaseUrl: d.optional(d.url())
|
|
74
|
+
}), w = {}, T = (e) => {
|
|
75
|
+
let { product: t, sessionUrl: n, fallback: r, children: s, toolboxBaseUrl: u = _ } = d.parse(C, e), [p, m] = l(null), h = i(v), g = c(n);
|
|
76
|
+
a(() => {
|
|
77
|
+
g.current = n;
|
|
78
|
+
}, [n]);
|
|
79
|
+
let y = o(() => p ?? h, [h, p]);
|
|
80
|
+
return a(() => {
|
|
81
|
+
if (y) return;
|
|
82
|
+
let e = !1, n = g.current, r = u, i = `${t}-${typeof n == "string" ? n : "function"}-${r}`;
|
|
83
|
+
return w[i] || (w[i] = S(n).then(({ sessionId: e, institutionId: n }) => (b({
|
|
84
|
+
sessionId: e,
|
|
85
|
+
institutionId: n,
|
|
86
|
+
product: t,
|
|
87
|
+
toolboxBaseUrl: r
|
|
88
|
+
}), {
|
|
89
|
+
sessionId: e,
|
|
90
|
+
institutionId: n
|
|
91
|
+
}))), w[i].then((t) => {
|
|
92
|
+
e || m(t);
|
|
93
|
+
}), () => {
|
|
94
|
+
e = !0;
|
|
95
|
+
};
|
|
96
|
+
}, [
|
|
97
|
+
t,
|
|
98
|
+
y,
|
|
99
|
+
u
|
|
100
|
+
]), h ? s : y ? /* @__PURE__ */ f(v.Provider, {
|
|
101
|
+
value: y,
|
|
102
|
+
children: s
|
|
103
|
+
}) : r ?? null;
|
|
104
|
+
}, E = "on_interrupt";
|
|
105
|
+
function D(e, t) {
|
|
106
|
+
switch (t.type) {
|
|
107
|
+
case "SET_INTERRUPT": return e.interruptedTool === null || e.interruptedTool.name === t.payload.name ? { interruptedTool: t.payload } : (console.error(`ToolboxInterruptProvider: Received interrupt for tool "${t.payload.name}" but tool "${e.interruptedTool.name}" is already interrupted. Ignoring.`), e);
|
|
108
|
+
case "CLEAR_INTERRUPT": return { interruptedTool: null };
|
|
109
|
+
default: return e;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
var O = n({
|
|
113
|
+
interruptedTool: null,
|
|
114
|
+
dispatch: () => {}
|
|
115
|
+
});
|
|
116
|
+
function k({ children: e }) {
|
|
117
|
+
let [t, n] = s(D, { interruptedTool: null }), { agent: r } = m();
|
|
118
|
+
return a(() => {
|
|
119
|
+
let { unsubscribe: e } = r.subscribe({
|
|
120
|
+
onCustomEvent: ({ event: e }) => {
|
|
121
|
+
let t = e.value;
|
|
122
|
+
e.name === E && n({
|
|
123
|
+
type: "SET_INTERRUPT",
|
|
124
|
+
payload: {
|
|
125
|
+
name: t.tool,
|
|
126
|
+
value: t.toolArgs
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
onRunStartedEvent: () => {
|
|
131
|
+
n({ type: "CLEAR_INTERRUPT" });
|
|
132
|
+
},
|
|
133
|
+
onRunFailed: () => {
|
|
134
|
+
n({ type: "CLEAR_INTERRUPT" });
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
return () => {
|
|
138
|
+
e();
|
|
139
|
+
};
|
|
140
|
+
}, [r]), /* @__PURE__ */ f(O.Provider, {
|
|
141
|
+
value: {
|
|
142
|
+
interruptedTool: t.interruptedTool,
|
|
143
|
+
dispatch: n
|
|
144
|
+
},
|
|
145
|
+
children: e
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
var A = (e) => {
|
|
149
|
+
let { interruptedTool: n, dispatch: a } = i(O), { copilotkit: s } = h(), { copilotApiConfig: c } = t(), { agent: l } = m(), u = n?.name === e, d = r((e) => {
|
|
150
|
+
a({ type: "CLEAR_INTERRUPT" }), s.runAgent({
|
|
151
|
+
agent: l,
|
|
152
|
+
forwardedProps: { command: { resume: JSON.stringify({
|
|
153
|
+
response: e,
|
|
154
|
+
properties: c.properties ?? {}
|
|
155
|
+
}) } }
|
|
156
|
+
});
|
|
157
|
+
}, [
|
|
158
|
+
l,
|
|
159
|
+
c.properties,
|
|
160
|
+
s,
|
|
161
|
+
a
|
|
162
|
+
]);
|
|
163
|
+
return o(() => ({
|
|
164
|
+
isWaiting: u,
|
|
165
|
+
respond: d
|
|
166
|
+
}), [u, d]);
|
|
167
|
+
}, j = u.object({
|
|
168
|
+
featureId: u.string({ error: "invalid feature id" }),
|
|
169
|
+
toolboxBaseUrl: u.optional(u.url()),
|
|
170
|
+
children: u.custom(),
|
|
171
|
+
...u.pick(C, {
|
|
172
|
+
product: !0,
|
|
173
|
+
sessionUrl: !0,
|
|
174
|
+
fallback: !0
|
|
175
|
+
}).shape
|
|
176
|
+
}), M = (e) => {
|
|
177
|
+
let { product: t, sessionUrl: n, fallback: r, featureId: i, children: a, toolboxBaseUrl: o = _ } = u.parse(j, e);
|
|
178
|
+
return /* @__PURE__ */ f(T, {
|
|
179
|
+
product: t,
|
|
180
|
+
sessionUrl: n,
|
|
181
|
+
fallback: r,
|
|
182
|
+
toolboxBaseUrl: o,
|
|
183
|
+
children: /* @__PURE__ */ f(N, {
|
|
184
|
+
featureId: i,
|
|
185
|
+
runtimeUrl: `${o}/api/feature/chat`,
|
|
186
|
+
children: a
|
|
187
|
+
})
|
|
188
|
+
});
|
|
189
|
+
}, N = ({ featureId: t, runtimeUrl: n, children: r }) => {
|
|
190
|
+
let { institutionId: i, sessionId: a } = y();
|
|
191
|
+
return /* @__PURE__ */ p(e, {
|
|
192
|
+
agent: "default",
|
|
193
|
+
showDevConsole: !1,
|
|
194
|
+
runtimeUrl: n,
|
|
195
|
+
properties: {
|
|
196
|
+
featureId: t,
|
|
197
|
+
username: "toolbox-user",
|
|
198
|
+
sessionId: a,
|
|
199
|
+
institutionId: i
|
|
200
|
+
},
|
|
201
|
+
children: [/* @__PURE__ */ f("style", { children: "cpk-web-inspector {\n display: none !important;\n }" }), /* @__PURE__ */ f(k, { children: r })]
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
//#endregion
|
|
205
|
+
//#region src/hooks/use-tool-call.ts
|
|
206
|
+
function P(e) {
|
|
207
|
+
let { agent: t } = m();
|
|
208
|
+
return o(() => {
|
|
209
|
+
let n = t.messages ?? [], r = [];
|
|
210
|
+
for (let t = 0; t < n.length; t++) {
|
|
211
|
+
let i = n[t];
|
|
212
|
+
if (i.role !== "assistant" || !i.toolCalls) continue;
|
|
213
|
+
let a = t === n.length - 1;
|
|
214
|
+
for (let t of i.toolCalls) {
|
|
215
|
+
if (t.function?.name !== e) continue;
|
|
216
|
+
let n = t.function.arguments;
|
|
217
|
+
if (n) try {
|
|
218
|
+
let e = a ? g(n) : JSON.parse(n);
|
|
219
|
+
r.push(e);
|
|
220
|
+
} catch {}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return r;
|
|
224
|
+
}, [t.messages, e]);
|
|
225
|
+
}
|
|
226
|
+
//#endregion
|
|
227
|
+
//#region src/hooks/use-latest-tool-call.ts
|
|
228
|
+
function F(e) {
|
|
229
|
+
let t = P(e);
|
|
230
|
+
return t[t.length - 1];
|
|
231
|
+
}
|
|
232
|
+
//#endregion
|
|
233
|
+
//#region src/hooks/use-agent.ts
|
|
234
|
+
var I = () => {
|
|
235
|
+
let { agent: e } = m(), { copilotkit: t } = h(), n = r(async (n, r) => {
|
|
236
|
+
let i = r?.files ?? [], a;
|
|
237
|
+
if (i.length === 0) a = n;
|
|
238
|
+
else {
|
|
239
|
+
let e = [];
|
|
240
|
+
for (let t of i) if (t instanceof File) {
|
|
241
|
+
let n = await t.arrayBuffer(), r = new Uint8Array(n).reduce((e, t) => e + String.fromCharCode(t), ""), i = btoa(r);
|
|
242
|
+
e.push({
|
|
243
|
+
type: "binary",
|
|
244
|
+
mimeType: t.type,
|
|
245
|
+
data: i,
|
|
246
|
+
filename: t.name
|
|
247
|
+
});
|
|
248
|
+
} else e.push({
|
|
249
|
+
type: "binary",
|
|
250
|
+
mimeType: t.mimeType,
|
|
251
|
+
url: t.url,
|
|
252
|
+
filename: t.name
|
|
253
|
+
});
|
|
254
|
+
a = [{
|
|
255
|
+
type: "text",
|
|
256
|
+
text: n
|
|
257
|
+
}, ...e];
|
|
258
|
+
}
|
|
259
|
+
return e.addMessage({
|
|
260
|
+
id: crypto.randomUUID(),
|
|
261
|
+
role: "user",
|
|
262
|
+
content: a
|
|
263
|
+
}), t.runAgent({ agent: e });
|
|
264
|
+
}, [e, t]);
|
|
265
|
+
return o(() => ({
|
|
266
|
+
sendMessage: n,
|
|
267
|
+
isRunning: e.isRunning,
|
|
268
|
+
messages: e.messages ?? []
|
|
269
|
+
}), [
|
|
270
|
+
e.isRunning,
|
|
271
|
+
e.messages,
|
|
272
|
+
n
|
|
273
|
+
]);
|
|
274
|
+
};
|
|
275
|
+
//#endregion
|
|
276
|
+
export { M as ToolboxChat, I as useAgent, F as useLatestToolCall, P as useToolCall, A as useToolResponse };
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@watermarkinsights/ai-toolbox",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/ai-toolbox.js",
|
|
11
|
+
"types": "./dist/ai-toolbox.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "bunx --bun vite build --watch ",
|
|
19
|
+
"build": "bunx --bun vite build",
|
|
20
|
+
"typecheck": "bunx --bun tsc --noEmit --incremental -p tsconfig.app.json",
|
|
21
|
+
"lint": "bunx --bun eslint --cache .",
|
|
22
|
+
"lint:fix": "bunx --bun eslint --cache --fix .",
|
|
23
|
+
"preview": "vite preview",
|
|
24
|
+
"storybook": "storybook dev -p 6006",
|
|
25
|
+
"build-storybook": "storybook build"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@copilotkit/react-core": "^1.53.0",
|
|
29
|
+
"partial-json": "^0.1.7",
|
|
30
|
+
"zod": "^4.3.6"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"react": ">=18",
|
|
34
|
+
"react-dom": ">=18"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@chromatic-com/storybook": "^5.0.1",
|
|
38
|
+
"@eslint/js": "catalog:",
|
|
39
|
+
"@storybook/addon-a11y": "^10.2.15",
|
|
40
|
+
"@storybook/addon-docs": "^10.2.15",
|
|
41
|
+
"@storybook/addon-onboarding": "^10.2.15",
|
|
42
|
+
"@storybook/addon-vitest": "^10.2.15",
|
|
43
|
+
"@storybook/react-vite": "^10.2.15",
|
|
44
|
+
"@types/node": "^24.10.1",
|
|
45
|
+
"@types/react": "catalog:",
|
|
46
|
+
"@types/react-dom": "catalog:",
|
|
47
|
+
"@vitejs/plugin-react": "catalog:",
|
|
48
|
+
"@vitejs/plugin-react-swc": "^4.2.2",
|
|
49
|
+
"@vitest/browser-playwright": "^4.0.18",
|
|
50
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
51
|
+
"eslint": "catalog:",
|
|
52
|
+
"eslint-plugin-react-hooks": "catalog:",
|
|
53
|
+
"eslint-plugin-react-refresh": "^0.4.24",
|
|
54
|
+
"eslint-plugin-storybook": "^10.2.15",
|
|
55
|
+
"globals": "catalog:",
|
|
56
|
+
"playwright": "^1.58.2",
|
|
57
|
+
"react": "catalog:",
|
|
58
|
+
"react-dom": "catalog:",
|
|
59
|
+
"storybook": "^10.2.15",
|
|
60
|
+
"typescript": "catalog:",
|
|
61
|
+
"typescript-eslint": "catalog:",
|
|
62
|
+
"vite": "^8.0.2",
|
|
63
|
+
"vite-bundle-analyzer": "^1.3.6",
|
|
64
|
+
"vite-plugin-dts": "^4.5.4",
|
|
65
|
+
"vite-plugin-externalize-deps": "^0.10.0",
|
|
66
|
+
"vitest": "^4.0.18"
|
|
67
|
+
}
|
|
68
|
+
}
|