@yh-ui/ai-sdk 1.0.51 → 1.0.53
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/dist/agent-enhanced.cjs +11 -1
- package/dist/agent-enhanced.d.ts +2 -0
- package/dist/agent-enhanced.mjs +11 -1
- package/dist/cache-adapter.cjs +6 -0
- package/dist/cache-adapter.mjs +6 -0
- package/dist/future.cjs +50 -4
- package/dist/future.mjs +50 -4
- package/dist/langchain.cjs +35 -6
- package/dist/langchain.mjs +31 -6
- package/dist/mcp.cjs +6 -9
- package/dist/mcp.mjs +6 -6
- package/dist/vue/index.cjs +55 -25
- package/dist/vue/index.mjs +56 -25
- package/package.json +3 -3
package/dist/agent-enhanced.cjs
CHANGED
|
@@ -159,7 +159,17 @@ ${reflections2.join("\n")}
|
|
|
159
159
|
return `Attempt ${steps.value.length}: ${score < 5 ? "Need to try different approach" : "Making progress"}`;
|
|
160
160
|
}
|
|
161
161
|
async function evaluateOutput(output) {
|
|
162
|
-
|
|
162
|
+
if (config.scorer) {
|
|
163
|
+
return await config.scorer(output);
|
|
164
|
+
}
|
|
165
|
+
let score = 0;
|
|
166
|
+
if (output.length > 10) score += 2;
|
|
167
|
+
if (output.length > 50) score += 1;
|
|
168
|
+
if (output.includes("Thought:")) score += 2;
|
|
169
|
+
if (output.includes("Action:")) score += 1;
|
|
170
|
+
if (output.includes("Action Input:")) score += 1;
|
|
171
|
+
if (output.includes("Observation:")) score += 1;
|
|
172
|
+
return score;
|
|
163
173
|
}
|
|
164
174
|
function checkStop(iterationOutput, bestOutput) {
|
|
165
175
|
for (const cond of stopConditions) {
|
package/dist/agent-enhanced.d.ts
CHANGED
|
@@ -65,6 +65,8 @@ export interface ReflexionConfig extends Omit<EnhancedAgentConfig, 'mode'> {
|
|
|
65
65
|
mode: 'reflexion';
|
|
66
66
|
/** 记忆上下文窗口大小 */
|
|
67
67
|
memoryWindow?: number;
|
|
68
|
+
/** 可注入的评估函数 (scorer) */
|
|
69
|
+
scorer?: (output: string) => number | Promise<number>;
|
|
68
70
|
}
|
|
69
71
|
/**
|
|
70
72
|
* 创建 Reflexion Agent
|
package/dist/agent-enhanced.mjs
CHANGED
|
@@ -146,7 +146,17 @@ ${reflections2.join("\n")}
|
|
|
146
146
|
return `Attempt ${steps.value.length}: ${score < 5 ? "Need to try different approach" : "Making progress"}`;
|
|
147
147
|
}
|
|
148
148
|
async function evaluateOutput(output) {
|
|
149
|
-
|
|
149
|
+
if (config.scorer) {
|
|
150
|
+
return await config.scorer(output);
|
|
151
|
+
}
|
|
152
|
+
let score = 0;
|
|
153
|
+
if (output.length > 10) score += 2;
|
|
154
|
+
if (output.length > 50) score += 1;
|
|
155
|
+
if (output.includes("Thought:")) score += 2;
|
|
156
|
+
if (output.includes("Action:")) score += 1;
|
|
157
|
+
if (output.includes("Action Input:")) score += 1;
|
|
158
|
+
if (output.includes("Observation:")) score += 1;
|
|
159
|
+
return score;
|
|
150
160
|
}
|
|
151
161
|
function checkStop(iterationOutput, bestOutput) {
|
|
152
162
|
for (const cond of stopConditions) {
|
package/dist/cache-adapter.cjs
CHANGED
|
@@ -36,6 +36,7 @@ function createMemoryCache() {
|
|
|
36
36
|
function createLocalStorageCache(prefix = "yh-ai-cache-") {
|
|
37
37
|
return {
|
|
38
38
|
get(key) {
|
|
39
|
+
if (typeof localStorage === "undefined") return null;
|
|
39
40
|
try {
|
|
40
41
|
const raw = localStorage.getItem(prefix + key);
|
|
41
42
|
if (!raw) return null;
|
|
@@ -50,6 +51,7 @@ function createLocalStorageCache(prefix = "yh-ai-cache-") {
|
|
|
50
51
|
}
|
|
51
52
|
},
|
|
52
53
|
set(key, value, ttlMs) {
|
|
54
|
+
if (typeof localStorage === "undefined") return;
|
|
53
55
|
try {
|
|
54
56
|
const item = {
|
|
55
57
|
data: value,
|
|
@@ -59,6 +61,7 @@ function createLocalStorageCache(prefix = "yh-ai-cache-") {
|
|
|
59
61
|
} catch {}
|
|
60
62
|
},
|
|
61
63
|
delete(key) {
|
|
64
|
+
if (typeof localStorage === "undefined") return;
|
|
62
65
|
try {
|
|
63
66
|
localStorage.removeItem(prefix + key);
|
|
64
67
|
} catch {}
|
|
@@ -68,6 +71,7 @@ function createLocalStorageCache(prefix = "yh-ai-cache-") {
|
|
|
68
71
|
function createSessionStorageCache(prefix = "yh-ai-cache-") {
|
|
69
72
|
return {
|
|
70
73
|
get(key) {
|
|
74
|
+
if (typeof sessionStorage === "undefined") return null;
|
|
71
75
|
try {
|
|
72
76
|
const raw = sessionStorage.getItem(prefix + key);
|
|
73
77
|
if (!raw) return null;
|
|
@@ -82,6 +86,7 @@ function createSessionStorageCache(prefix = "yh-ai-cache-") {
|
|
|
82
86
|
}
|
|
83
87
|
},
|
|
84
88
|
set(key, value, ttlMs) {
|
|
89
|
+
if (typeof sessionStorage === "undefined") return;
|
|
85
90
|
try {
|
|
86
91
|
const item = {
|
|
87
92
|
data: value,
|
|
@@ -91,6 +96,7 @@ function createSessionStorageCache(prefix = "yh-ai-cache-") {
|
|
|
91
96
|
} catch {}
|
|
92
97
|
},
|
|
93
98
|
delete(key) {
|
|
99
|
+
if (typeof sessionStorage === "undefined") return;
|
|
94
100
|
try {
|
|
95
101
|
sessionStorage.removeItem(prefix + key);
|
|
96
102
|
} catch {}
|
package/dist/cache-adapter.mjs
CHANGED
|
@@ -28,6 +28,7 @@ export function createMemoryCache() {
|
|
|
28
28
|
export function createLocalStorageCache(prefix = "yh-ai-cache-") {
|
|
29
29
|
return {
|
|
30
30
|
get(key) {
|
|
31
|
+
if (typeof localStorage === "undefined") return null;
|
|
31
32
|
try {
|
|
32
33
|
const raw = localStorage.getItem(prefix + key);
|
|
33
34
|
if (!raw) return null;
|
|
@@ -42,6 +43,7 @@ export function createLocalStorageCache(prefix = "yh-ai-cache-") {
|
|
|
42
43
|
}
|
|
43
44
|
},
|
|
44
45
|
set(key, value, ttlMs) {
|
|
46
|
+
if (typeof localStorage === "undefined") return;
|
|
45
47
|
try {
|
|
46
48
|
const item = {
|
|
47
49
|
data: value,
|
|
@@ -52,6 +54,7 @@ export function createLocalStorageCache(prefix = "yh-ai-cache-") {
|
|
|
52
54
|
}
|
|
53
55
|
},
|
|
54
56
|
delete(key) {
|
|
57
|
+
if (typeof localStorage === "undefined") return;
|
|
55
58
|
try {
|
|
56
59
|
localStorage.removeItem(prefix + key);
|
|
57
60
|
} catch {
|
|
@@ -62,6 +65,7 @@ export function createLocalStorageCache(prefix = "yh-ai-cache-") {
|
|
|
62
65
|
export function createSessionStorageCache(prefix = "yh-ai-cache-") {
|
|
63
66
|
return {
|
|
64
67
|
get(key) {
|
|
68
|
+
if (typeof sessionStorage === "undefined") return null;
|
|
65
69
|
try {
|
|
66
70
|
const raw = sessionStorage.getItem(prefix + key);
|
|
67
71
|
if (!raw) return null;
|
|
@@ -76,6 +80,7 @@ export function createSessionStorageCache(prefix = "yh-ai-cache-") {
|
|
|
76
80
|
}
|
|
77
81
|
},
|
|
78
82
|
set(key, value, ttlMs) {
|
|
83
|
+
if (typeof sessionStorage === "undefined") return;
|
|
79
84
|
try {
|
|
80
85
|
const item = {
|
|
81
86
|
data: value,
|
|
@@ -86,6 +91,7 @@ export function createSessionStorageCache(prefix = "yh-ai-cache-") {
|
|
|
86
91
|
}
|
|
87
92
|
},
|
|
88
93
|
delete(key) {
|
|
94
|
+
if (typeof sessionStorage === "undefined") return;
|
|
89
95
|
try {
|
|
90
96
|
sessionStorage.removeItem(prefix + key);
|
|
91
97
|
} catch {
|
package/dist/future.cjs
CHANGED
|
@@ -310,13 +310,55 @@ function createRAGSystem(config) {
|
|
|
310
310
|
strategy = "similarity"
|
|
311
311
|
} = config;
|
|
312
312
|
const vectorStore = /* @__PURE__ */new Map();
|
|
313
|
+
const calculateSimilarity = (q, t) => {
|
|
314
|
+
const tokenize = str => {
|
|
315
|
+
const tokens = [];
|
|
316
|
+
const words = str.toLowerCase().split(/[\s,.<>?/;:'"[{}]|`~!@#$%^&*()_\-+=,。!?;:‘’“”【】『』]+/g);
|
|
317
|
+
for (const w of words) {
|
|
318
|
+
if (!w) continue;
|
|
319
|
+
if (/[\u4e00-\u9fa5]/.test(w)) {
|
|
320
|
+
for (const char of w) {
|
|
321
|
+
tokens.push(char);
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
tokens.push(w);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return tokens;
|
|
328
|
+
};
|
|
329
|
+
const qTokens = tokenize(q);
|
|
330
|
+
const tTokens = tokenize(t);
|
|
331
|
+
if (qTokens.length === 0 || tTokens.length === 0) return 0;
|
|
332
|
+
const qMap = /* @__PURE__ */new Map();
|
|
333
|
+
const tMap = /* @__PURE__ */new Map();
|
|
334
|
+
const allTokens = /* @__PURE__ */new Set();
|
|
335
|
+
for (const tok of qTokens) {
|
|
336
|
+
qMap.set(tok, (qMap.get(tok) || 0) + 1);
|
|
337
|
+
allTokens.add(tok);
|
|
338
|
+
}
|
|
339
|
+
for (const tok of tTokens) {
|
|
340
|
+
tMap.set(tok, (tMap.get(tok) || 0) + 1);
|
|
341
|
+
allTokens.add(tok);
|
|
342
|
+
}
|
|
343
|
+
let dotProduct = 0;
|
|
344
|
+
let qNorm = 0;
|
|
345
|
+
let tNorm = 0;
|
|
346
|
+
for (const tok of allTokens) {
|
|
347
|
+
const qVal = qMap.get(tok) || 0;
|
|
348
|
+
const tVal = tMap.get(tok) || 0;
|
|
349
|
+
dotProduct += qVal * tVal;
|
|
350
|
+
qNorm += qVal * qVal;
|
|
351
|
+
tNorm += tVal * tVal;
|
|
352
|
+
}
|
|
353
|
+
if (qNorm === 0 || tNorm === 0) return 0;
|
|
354
|
+
return dotProduct / (Math.sqrt(qNorm) * Math.sqrt(tNorm));
|
|
355
|
+
};
|
|
313
356
|
const addDocuments = async documents => {
|
|
314
357
|
const chunks = documents.map((doc, i) => ({
|
|
315
358
|
id: `chunk-${Date.now()}-${i}`,
|
|
316
359
|
content: doc.content,
|
|
317
360
|
metadata: doc.metadata || {},
|
|
318
|
-
|
|
319
|
-
score: Math.random()
|
|
361
|
+
score: 1
|
|
320
362
|
}));
|
|
321
363
|
if (knowledgeBaseId) {
|
|
322
364
|
const existing = vectorStore.get(knowledgeBaseId) || [];
|
|
@@ -327,8 +369,12 @@ function createRAGSystem(config) {
|
|
|
327
369
|
const retrieve = async (query2, k = topK) => {
|
|
328
370
|
if (!knowledgeBaseId) return [];
|
|
329
371
|
const chunks = vectorStore.get(knowledgeBaseId) || [];
|
|
330
|
-
const
|
|
331
|
-
|
|
372
|
+
const scoredChunks = chunks.map(chunk => ({
|
|
373
|
+
...chunk,
|
|
374
|
+
score: calculateSimilarity(query2, chunk.content)
|
|
375
|
+
}));
|
|
376
|
+
const sorted = [...scoredChunks].sort((a, b) => b.score - a.score).slice(0, k);
|
|
377
|
+
return sorted.filter(c => c.score >= similarityThreshold);
|
|
332
378
|
};
|
|
333
379
|
const query = async (question, llm) => {
|
|
334
380
|
const relevantDocs = await retrieve(question);
|
package/dist/future.mjs
CHANGED
|
@@ -275,13 +275,55 @@ export function createRAGSystem(config) {
|
|
|
275
275
|
strategy = "similarity"
|
|
276
276
|
} = config;
|
|
277
277
|
const vectorStore = /* @__PURE__ */ new Map();
|
|
278
|
+
const calculateSimilarity = (q, t) => {
|
|
279
|
+
const tokenize = (str) => {
|
|
280
|
+
const tokens = [];
|
|
281
|
+
const words = str.toLowerCase().split(/[\s,.<>?/;:'"[{}]|`~!@#$%^&*()_\-+=,。!?;:‘’“”【】『』]+/g);
|
|
282
|
+
for (const w of words) {
|
|
283
|
+
if (!w) continue;
|
|
284
|
+
if (/[\u4e00-\u9fa5]/.test(w)) {
|
|
285
|
+
for (const char of w) {
|
|
286
|
+
tokens.push(char);
|
|
287
|
+
}
|
|
288
|
+
} else {
|
|
289
|
+
tokens.push(w);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return tokens;
|
|
293
|
+
};
|
|
294
|
+
const qTokens = tokenize(q);
|
|
295
|
+
const tTokens = tokenize(t);
|
|
296
|
+
if (qTokens.length === 0 || tTokens.length === 0) return 0;
|
|
297
|
+
const qMap = /* @__PURE__ */ new Map();
|
|
298
|
+
const tMap = /* @__PURE__ */ new Map();
|
|
299
|
+
const allTokens = /* @__PURE__ */ new Set();
|
|
300
|
+
for (const tok of qTokens) {
|
|
301
|
+
qMap.set(tok, (qMap.get(tok) || 0) + 1);
|
|
302
|
+
allTokens.add(tok);
|
|
303
|
+
}
|
|
304
|
+
for (const tok of tTokens) {
|
|
305
|
+
tMap.set(tok, (tMap.get(tok) || 0) + 1);
|
|
306
|
+
allTokens.add(tok);
|
|
307
|
+
}
|
|
308
|
+
let dotProduct = 0;
|
|
309
|
+
let qNorm = 0;
|
|
310
|
+
let tNorm = 0;
|
|
311
|
+
for (const tok of allTokens) {
|
|
312
|
+
const qVal = qMap.get(tok) || 0;
|
|
313
|
+
const tVal = tMap.get(tok) || 0;
|
|
314
|
+
dotProduct += qVal * tVal;
|
|
315
|
+
qNorm += qVal * qVal;
|
|
316
|
+
tNorm += tVal * tVal;
|
|
317
|
+
}
|
|
318
|
+
if (qNorm === 0 || tNorm === 0) return 0;
|
|
319
|
+
return dotProduct / (Math.sqrt(qNorm) * Math.sqrt(tNorm));
|
|
320
|
+
};
|
|
278
321
|
const addDocuments = async (documents) => {
|
|
279
322
|
const chunks = documents.map((doc, i) => ({
|
|
280
323
|
id: `chunk-${Date.now()}-${i}`,
|
|
281
324
|
content: doc.content,
|
|
282
325
|
metadata: doc.metadata || {},
|
|
283
|
-
|
|
284
|
-
score: Math.random()
|
|
326
|
+
score: 1
|
|
285
327
|
}));
|
|
286
328
|
if (knowledgeBaseId) {
|
|
287
329
|
const existing = vectorStore.get(knowledgeBaseId) || [];
|
|
@@ -292,8 +334,12 @@ export function createRAGSystem(config) {
|
|
|
292
334
|
const retrieve = async (query2, k = topK) => {
|
|
293
335
|
if (!knowledgeBaseId) return [];
|
|
294
336
|
const chunks = vectorStore.get(knowledgeBaseId) || [];
|
|
295
|
-
const
|
|
296
|
-
|
|
337
|
+
const scoredChunks = chunks.map((chunk) => ({
|
|
338
|
+
...chunk,
|
|
339
|
+
score: calculateSimilarity(query2, chunk.content)
|
|
340
|
+
}));
|
|
341
|
+
const sorted = [...scoredChunks].sort((a, b) => b.score - a.score).slice(0, k);
|
|
342
|
+
return sorted.filter((c) => c.score >= similarityThreshold);
|
|
297
343
|
};
|
|
298
344
|
const query = async (question, llm) => {
|
|
299
345
|
const relevantDocs = await retrieve(question);
|
package/dist/langchain.cjs
CHANGED
|
@@ -91,6 +91,8 @@ const langChainRuntime = exports.langChainRuntime = {
|
|
|
91
91
|
const stream = await modelWithTools.stream(messages);
|
|
92
92
|
let fullContent = "";
|
|
93
93
|
const toolCalls = [];
|
|
94
|
+
const toolCallArgumentsMap = /* @__PURE__ */new Map();
|
|
95
|
+
const toolCallInfoMap = /* @__PURE__ */new Map();
|
|
94
96
|
for await (const chunk of stream) {
|
|
95
97
|
const content = String(chunk?.content || "");
|
|
96
98
|
if (content) {
|
|
@@ -101,10 +103,25 @@ const langChainRuntime = exports.langChainRuntime = {
|
|
|
101
103
|
if (additionalKwargs?.tool_calls) {
|
|
102
104
|
for (const tc of additionalKwargs.tool_calls) {
|
|
103
105
|
toolCalls.push(tc);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
const idx = tc.index ?? 0;
|
|
107
|
+
if (tc.id) {
|
|
108
|
+
toolCallInfoMap.set(idx, {
|
|
109
|
+
id: tc.id,
|
|
110
|
+
name: tc.function?.name
|
|
111
|
+
});
|
|
112
|
+
toolCallArgumentsMap.set(idx, tc.function?.arguments || "");
|
|
113
|
+
} else {
|
|
114
|
+
const currentArgs = toolCallArgumentsMap.get(idx) || "";
|
|
115
|
+
toolCallArgumentsMap.set(idx, currentArgs + (tc.function?.arguments || ""));
|
|
116
|
+
}
|
|
117
|
+
const rawArgs = toolCallArgumentsMap.get(idx) || "";
|
|
118
|
+
try {
|
|
119
|
+
const parsedArgs = JSON.parse(rawArgs);
|
|
120
|
+
options?.onToolCall?.({
|
|
121
|
+
name: toolCallInfoMap.get(idx)?.name || tc.function?.name || "",
|
|
122
|
+
args: parsedArgs
|
|
123
|
+
});
|
|
124
|
+
} catch {}
|
|
108
125
|
}
|
|
109
126
|
}
|
|
110
127
|
}
|
|
@@ -244,6 +261,7 @@ function useLangChainStream(options) {
|
|
|
244
261
|
error.value = null;
|
|
245
262
|
isStreaming.value = true;
|
|
246
263
|
content.value = "";
|
|
264
|
+
abortController = new AbortController();
|
|
247
265
|
try {
|
|
248
266
|
const messages = [];
|
|
249
267
|
if (systemMessage) {
|
|
@@ -263,8 +281,13 @@ function useLangChainStream(options) {
|
|
|
263
281
|
}
|
|
264
282
|
}
|
|
265
283
|
messages.push(new _messages.HumanMessage(prompt));
|
|
266
|
-
const stream = await model.stream(messages
|
|
284
|
+
const stream = await model.stream(messages, {
|
|
285
|
+
signal: abortController.signal
|
|
286
|
+
});
|
|
267
287
|
for await (const chunk of stream) {
|
|
288
|
+
if (abortController?.signal.aborted) {
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
268
291
|
const chunkContent = String(chunk?.content || "");
|
|
269
292
|
content.value += chunkContent;
|
|
270
293
|
}
|
|
@@ -275,6 +298,7 @@ function useLangChainStream(options) {
|
|
|
275
298
|
}
|
|
276
299
|
} finally {
|
|
277
300
|
isStreaming.value = false;
|
|
301
|
+
abortController = null;
|
|
278
302
|
}
|
|
279
303
|
};
|
|
280
304
|
const stop = () => {
|
|
@@ -340,7 +364,12 @@ function createLangChainChain(model, config) {
|
|
|
340
364
|
if (toolCalls && toolCalls.length > 0 && toolHandler) {
|
|
341
365
|
for (const tc of toolCalls) {
|
|
342
366
|
const toolName = tc.function?.name || "";
|
|
343
|
-
|
|
367
|
+
let args = {};
|
|
368
|
+
try {
|
|
369
|
+
args = tc.function?.arguments ? JSON.parse(tc.function.arguments) : {};
|
|
370
|
+
} catch {
|
|
371
|
+
args = {};
|
|
372
|
+
}
|
|
344
373
|
const toolResult = await toolHandler(toolName, args);
|
|
345
374
|
messages.push(response);
|
|
346
375
|
messages.push(new _messages.ToolMessage({
|
package/dist/langchain.mjs
CHANGED
|
@@ -56,6 +56,8 @@ export const langChainRuntime = {
|
|
|
56
56
|
const stream = await modelWithTools.stream(messages);
|
|
57
57
|
let fullContent = "";
|
|
58
58
|
const toolCalls = [];
|
|
59
|
+
const toolCallArgumentsMap = /* @__PURE__ */ new Map();
|
|
60
|
+
const toolCallInfoMap = /* @__PURE__ */ new Map();
|
|
59
61
|
for await (const chunk of stream) {
|
|
60
62
|
const content = String(chunk?.content || "");
|
|
61
63
|
if (content) {
|
|
@@ -66,10 +68,23 @@ export const langChainRuntime = {
|
|
|
66
68
|
if (additionalKwargs?.tool_calls) {
|
|
67
69
|
for (const tc of additionalKwargs.tool_calls) {
|
|
68
70
|
toolCalls.push(tc);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
const idx = tc.index ?? 0;
|
|
72
|
+
if (tc.id) {
|
|
73
|
+
toolCallInfoMap.set(idx, { id: tc.id, name: tc.function?.name });
|
|
74
|
+
toolCallArgumentsMap.set(idx, tc.function?.arguments || "");
|
|
75
|
+
} else {
|
|
76
|
+
const currentArgs = toolCallArgumentsMap.get(idx) || "";
|
|
77
|
+
toolCallArgumentsMap.set(idx, currentArgs + (tc.function?.arguments || ""));
|
|
78
|
+
}
|
|
79
|
+
const rawArgs = toolCallArgumentsMap.get(idx) || "";
|
|
80
|
+
try {
|
|
81
|
+
const parsedArgs = JSON.parse(rawArgs);
|
|
82
|
+
options?.onToolCall?.({
|
|
83
|
+
name: toolCallInfoMap.get(idx)?.name || tc.function?.name || "",
|
|
84
|
+
args: parsedArgs
|
|
85
|
+
});
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
73
88
|
}
|
|
74
89
|
}
|
|
75
90
|
}
|
|
@@ -199,6 +214,7 @@ export function useLangChainStream(options) {
|
|
|
199
214
|
error.value = null;
|
|
200
215
|
isStreaming.value = true;
|
|
201
216
|
content.value = "";
|
|
217
|
+
abortController = new AbortController();
|
|
202
218
|
try {
|
|
203
219
|
const messages = [];
|
|
204
220
|
if (systemMessage) {
|
|
@@ -218,8 +234,11 @@ export function useLangChainStream(options) {
|
|
|
218
234
|
}
|
|
219
235
|
}
|
|
220
236
|
messages.push(new HumanMessage(prompt));
|
|
221
|
-
const stream = await model.stream(messages);
|
|
237
|
+
const stream = await model.stream(messages, { signal: abortController.signal });
|
|
222
238
|
for await (const chunk of stream) {
|
|
239
|
+
if (abortController?.signal.aborted) {
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
223
242
|
const chunkContent = String(chunk?.content || "");
|
|
224
243
|
content.value += chunkContent;
|
|
225
244
|
}
|
|
@@ -230,6 +249,7 @@ export function useLangChainStream(options) {
|
|
|
230
249
|
}
|
|
231
250
|
} finally {
|
|
232
251
|
isStreaming.value = false;
|
|
252
|
+
abortController = null;
|
|
233
253
|
}
|
|
234
254
|
};
|
|
235
255
|
const stop = () => {
|
|
@@ -293,7 +313,12 @@ export function createLangChainChain(model, config) {
|
|
|
293
313
|
if (toolCalls && toolCalls.length > 0 && toolHandler) {
|
|
294
314
|
for (const tc of toolCalls) {
|
|
295
315
|
const toolName = tc.function?.name || "";
|
|
296
|
-
|
|
316
|
+
let args = {};
|
|
317
|
+
try {
|
|
318
|
+
args = tc.function?.arguments ? JSON.parse(tc.function.arguments) : {};
|
|
319
|
+
} catch {
|
|
320
|
+
args = {};
|
|
321
|
+
}
|
|
297
322
|
const toolResult = await toolHandler(toolName, args);
|
|
298
323
|
messages.push(response);
|
|
299
324
|
messages.push(
|
package/dist/mcp.cjs
CHANGED
|
@@ -57,11 +57,11 @@ class MCPStdioTransport {
|
|
|
57
57
|
this.initialized = this.init();
|
|
58
58
|
}
|
|
59
59
|
init() {
|
|
60
|
-
return new Promise((resolve, reject) => {
|
|
60
|
+
return new Promise(async (resolve, reject) => {
|
|
61
61
|
try {
|
|
62
62
|
const {
|
|
63
63
|
spawn
|
|
64
|
-
} = require("child_process");
|
|
64
|
+
} = await Promise.resolve().then(() => require("child_process"));
|
|
65
65
|
this.process = spawn(this.command, this.args, {
|
|
66
66
|
env: {
|
|
67
67
|
...process.env,
|
|
@@ -313,7 +313,8 @@ function useMCPTools(options) {
|
|
|
313
313
|
return client.state.value;
|
|
314
314
|
},
|
|
315
315
|
connect: client.connect,
|
|
316
|
-
disconnect: client.disconnect
|
|
316
|
+
disconnect: client.disconnect,
|
|
317
|
+
callTool: client.callTool
|
|
317
318
|
});
|
|
318
319
|
}
|
|
319
320
|
function updateAllTools() {
|
|
@@ -347,12 +348,8 @@ function useMCPTools(options) {
|
|
|
347
348
|
const tool = server.tools.find(t => t.name === name);
|
|
348
349
|
if (tool) {
|
|
349
350
|
const clientIndex = serverStates.value.indexOf(server);
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
config: server.config,
|
|
353
|
-
autoConnect: false
|
|
354
|
-
});
|
|
355
|
-
return mcpClient.callTool(name, args);
|
|
351
|
+
const client = clients[clientIndex];
|
|
352
|
+
return client.callTool(name, args);
|
|
356
353
|
}
|
|
357
354
|
}
|
|
358
355
|
throw new Error(`Tool not found: ${name}`);
|
package/dist/mcp.mjs
CHANGED
|
@@ -50,9 +50,9 @@ class MCPStdioTransport {
|
|
|
50
50
|
this.initialized = this.init();
|
|
51
51
|
}
|
|
52
52
|
init() {
|
|
53
|
-
return new Promise((resolve, reject) => {
|
|
53
|
+
return new Promise(async (resolve, reject) => {
|
|
54
54
|
try {
|
|
55
|
-
const { spawn } =
|
|
55
|
+
const { spawn } = await import("child_process");
|
|
56
56
|
this.process = spawn(this.command, this.args, {
|
|
57
57
|
env: { ...process.env, ...this.env },
|
|
58
58
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -300,7 +300,8 @@ export function useMCPTools(options) {
|
|
|
300
300
|
return client.state.value;
|
|
301
301
|
},
|
|
302
302
|
connect: client.connect,
|
|
303
|
-
disconnect: client.disconnect
|
|
303
|
+
disconnect: client.disconnect,
|
|
304
|
+
callTool: client.callTool
|
|
304
305
|
});
|
|
305
306
|
}
|
|
306
307
|
function updateAllTools() {
|
|
@@ -334,9 +335,8 @@ export function useMCPTools(options) {
|
|
|
334
335
|
const tool = server.tools.find((t) => t.name === name);
|
|
335
336
|
if (tool) {
|
|
336
337
|
const clientIndex = serverStates.value.indexOf(server);
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
return mcpClient.callTool(name, args);
|
|
338
|
+
const client = clients[clientIndex];
|
|
339
|
+
return client.callTool(name, args);
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
throw new Error(`Tool not found: ${name}`);
|
package/dist/vue/index.cjs
CHANGED
|
@@ -136,7 +136,7 @@ async function XRequest(config, callbacks, options) {
|
|
|
136
136
|
const retryDelay = retry.retryDelay || 1e3;
|
|
137
137
|
const retryCondition = retry.retryCondition || (error => {
|
|
138
138
|
const msg = error.message.toLowerCase();
|
|
139
|
-
return msg.includes("fetch") || msg.includes("network");
|
|
139
|
+
return msg.includes("fetch") || msg.includes("network") || /http error: 5\d\d/.test(msg);
|
|
140
140
|
});
|
|
141
141
|
let lastError = null;
|
|
142
142
|
let attempt = 0;
|
|
@@ -153,6 +153,9 @@ async function XRequest(config, callbacks, options) {
|
|
|
153
153
|
signal: finalConfig.timeout ? AbortSignal.timeout(finalConfig.timeout) : void 0
|
|
154
154
|
});
|
|
155
155
|
mergedCallbacks.onResponse?.(response);
|
|
156
|
+
if (!response.ok) {
|
|
157
|
+
throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
|
|
158
|
+
}
|
|
156
159
|
if (finalConfig.stream && response.body) {
|
|
157
160
|
const reader = response.body.getReader();
|
|
158
161
|
const decoder = new TextDecoder();
|
|
@@ -234,7 +237,7 @@ function useConversation(config = {}) {
|
|
|
234
237
|
} = config;
|
|
235
238
|
const messages = (0, _vue.ref)([]);
|
|
236
239
|
const loadHistory = () => {
|
|
237
|
-
if (persist) {
|
|
240
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
238
241
|
const stored = localStorage.getItem(storageKey);
|
|
239
242
|
if (stored) {
|
|
240
243
|
try {
|
|
@@ -246,7 +249,7 @@ function useConversation(config = {}) {
|
|
|
246
249
|
}
|
|
247
250
|
};
|
|
248
251
|
const saveHistory = () => {
|
|
249
|
-
if (persist) {
|
|
252
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
250
253
|
localStorage.setItem(storageKey, JSON.stringify(messages.value));
|
|
251
254
|
}
|
|
252
255
|
};
|
|
@@ -262,11 +265,13 @@ function useConversation(config = {}) {
|
|
|
262
265
|
};
|
|
263
266
|
const clearHistory = () => {
|
|
264
267
|
messages.value = [];
|
|
265
|
-
if (persist) {
|
|
268
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
266
269
|
localStorage.removeItem(storageKey);
|
|
267
270
|
}
|
|
268
271
|
};
|
|
269
|
-
|
|
272
|
+
if (typeof localStorage !== "undefined") {
|
|
273
|
+
loadHistory();
|
|
274
|
+
}
|
|
270
275
|
return {
|
|
271
276
|
messages,
|
|
272
277
|
addMessage,
|
|
@@ -302,7 +307,7 @@ function useConversations(options = {}) {
|
|
|
302
307
|
return currentConversation.value?.messages || [];
|
|
303
308
|
});
|
|
304
309
|
const loadConversations = () => {
|
|
305
|
-
if (persist) {
|
|
310
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
306
311
|
try {
|
|
307
312
|
const stored = localStorage.getItem(storageKey);
|
|
308
313
|
if (stored) {
|
|
@@ -320,7 +325,7 @@ function useConversations(options = {}) {
|
|
|
320
325
|
}
|
|
321
326
|
};
|
|
322
327
|
const saveConversations = () => {
|
|
323
|
-
if (persist) {
|
|
328
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
324
329
|
localStorage.setItem(storageKey, JSON.stringify({
|
|
325
330
|
conversations: conversations.value,
|
|
326
331
|
currentId: currentId.value
|
|
@@ -393,9 +398,11 @@ function useConversations(options = {}) {
|
|
|
393
398
|
saveConversations();
|
|
394
399
|
}
|
|
395
400
|
};
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
401
|
+
if (typeof localStorage !== "undefined") {
|
|
402
|
+
loadConversations();
|
|
403
|
+
if (conversations.value.length === 0) {
|
|
404
|
+
create();
|
|
405
|
+
}
|
|
399
406
|
}
|
|
400
407
|
return {
|
|
401
408
|
conversations,
|
|
@@ -555,6 +562,7 @@ function useAIChat(options) {
|
|
|
555
562
|
const decoder = new TextDecoder();
|
|
556
563
|
let fullContent = "";
|
|
557
564
|
let currentToolCalls = [];
|
|
565
|
+
const toolCallArguments = {};
|
|
558
566
|
while (true) {
|
|
559
567
|
const {
|
|
560
568
|
done,
|
|
@@ -588,26 +596,38 @@ function useAIChat(options) {
|
|
|
588
596
|
if (parsed.choices?.[0]?.delta?.tool_calls) {
|
|
589
597
|
const toolCalls = parsed.choices[0].delta.tool_calls;
|
|
590
598
|
for (const tc of toolCalls) {
|
|
591
|
-
const
|
|
592
|
-
if (
|
|
593
|
-
currentToolCalls[
|
|
594
|
-
...currentToolCalls[existingIndex],
|
|
595
|
-
arguments: {
|
|
596
|
-
...currentToolCalls[existingIndex].arguments,
|
|
597
|
-
...(tc.function?.arguments && JSON.parse(tc.function.arguments))
|
|
598
|
-
}
|
|
599
|
-
};
|
|
600
|
-
} else if (tc.id && tc.function?.name) {
|
|
601
|
-
currentToolCalls.push({
|
|
599
|
+
const idx = tc.index ?? 0;
|
|
600
|
+
if (tc.id) {
|
|
601
|
+
currentToolCalls[idx] = {
|
|
602
602
|
id: tc.id,
|
|
603
603
|
type: "function",
|
|
604
|
-
name: tc.function
|
|
605
|
-
arguments:
|
|
606
|
-
}
|
|
604
|
+
name: tc.function?.name || "",
|
|
605
|
+
arguments: {}
|
|
606
|
+
};
|
|
607
|
+
toolCallArguments[idx] = tc.function?.arguments || "";
|
|
608
|
+
} else {
|
|
609
|
+
if (!currentToolCalls[idx]) {
|
|
610
|
+
currentToolCalls[idx] = {
|
|
611
|
+
id: "",
|
|
612
|
+
type: "function",
|
|
613
|
+
name: "",
|
|
614
|
+
arguments: {}
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
if (tc.function?.arguments) {
|
|
618
|
+
toolCallArguments[idx] = (toolCallArguments[idx] || "") + tc.function.arguments;
|
|
619
|
+
}
|
|
607
620
|
}
|
|
608
621
|
}
|
|
622
|
+
for (let i = 0; i < currentToolCalls.length; i++) {
|
|
623
|
+
if (!currentToolCalls[i]) continue;
|
|
624
|
+
const rawArgs = toolCallArguments[i] || "";
|
|
625
|
+
try {
|
|
626
|
+
currentToolCalls[i].arguments = rawArgs ? JSON.parse(rawArgs) : {};
|
|
627
|
+
} catch {}
|
|
628
|
+
}
|
|
609
629
|
updateLastMessage({
|
|
610
|
-
toolCalls: [...currentToolCalls]
|
|
630
|
+
toolCalls: [...currentToolCalls].filter(Boolean)
|
|
611
631
|
});
|
|
612
632
|
}
|
|
613
633
|
} catch {}
|
|
@@ -617,6 +637,16 @@ function useAIChat(options) {
|
|
|
617
637
|
await new Promise(resolve => setTimeout(resolve, streamInterval));
|
|
618
638
|
}
|
|
619
639
|
}
|
|
640
|
+
for (let i = 0; i < currentToolCalls.length; i++) {
|
|
641
|
+
if (!currentToolCalls[i]) continue;
|
|
642
|
+
const rawArgs = toolCallArguments[i] || "";
|
|
643
|
+
try {
|
|
644
|
+
currentToolCalls[i].arguments = rawArgs ? JSON.parse(rawArgs) : {};
|
|
645
|
+
} catch {
|
|
646
|
+
currentToolCalls[i].arguments = {};
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
currentToolCalls = currentToolCalls.filter(Boolean);
|
|
620
650
|
if (currentToolCalls.length > 0) {
|
|
621
651
|
updateLastMessage({
|
|
622
652
|
toolCalls: currentToolCalls
|
package/dist/vue/index.mjs
CHANGED
|
@@ -95,7 +95,7 @@ export async function XRequest(config, callbacks, options) {
|
|
|
95
95
|
const retryDelay = retry.retryDelay || 1e3;
|
|
96
96
|
const retryCondition = retry.retryCondition || ((error) => {
|
|
97
97
|
const msg = error.message.toLowerCase();
|
|
98
|
-
return msg.includes("fetch") || msg.includes("network");
|
|
98
|
+
return msg.includes("fetch") || msg.includes("network") || /http error: 5\d\d/.test(msg);
|
|
99
99
|
});
|
|
100
100
|
let lastError = null;
|
|
101
101
|
let attempt = 0;
|
|
@@ -112,6 +112,9 @@ export async function XRequest(config, callbacks, options) {
|
|
|
112
112
|
signal: finalConfig.timeout ? AbortSignal.timeout(finalConfig.timeout) : void 0
|
|
113
113
|
});
|
|
114
114
|
mergedCallbacks.onResponse?.(response);
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
|
|
117
|
+
}
|
|
115
118
|
if (finalConfig.stream && response.body) {
|
|
116
119
|
const reader = response.body.getReader();
|
|
117
120
|
const decoder = new TextDecoder();
|
|
@@ -177,7 +180,7 @@ export function useConversation(config = {}) {
|
|
|
177
180
|
const { maxHistory = 50, persist = false, storageKey = "yh-ai-conversation" } = config;
|
|
178
181
|
const messages = ref([]);
|
|
179
182
|
const loadHistory = () => {
|
|
180
|
-
if (persist) {
|
|
183
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
181
184
|
const stored = localStorage.getItem(storageKey);
|
|
182
185
|
if (stored) {
|
|
183
186
|
try {
|
|
@@ -189,7 +192,7 @@ export function useConversation(config = {}) {
|
|
|
189
192
|
}
|
|
190
193
|
};
|
|
191
194
|
const saveHistory = () => {
|
|
192
|
-
if (persist) {
|
|
195
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
193
196
|
localStorage.setItem(storageKey, JSON.stringify(messages.value));
|
|
194
197
|
}
|
|
195
198
|
};
|
|
@@ -205,11 +208,13 @@ export function useConversation(config = {}) {
|
|
|
205
208
|
};
|
|
206
209
|
const clearHistory = () => {
|
|
207
210
|
messages.value = [];
|
|
208
|
-
if (persist) {
|
|
211
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
209
212
|
localStorage.removeItem(storageKey);
|
|
210
213
|
}
|
|
211
214
|
};
|
|
212
|
-
|
|
215
|
+
if (typeof localStorage !== "undefined") {
|
|
216
|
+
loadHistory();
|
|
217
|
+
}
|
|
213
218
|
return {
|
|
214
219
|
messages,
|
|
215
220
|
addMessage,
|
|
@@ -245,7 +250,7 @@ export function useConversations(options = {}) {
|
|
|
245
250
|
return currentConversation.value?.messages || [];
|
|
246
251
|
});
|
|
247
252
|
const loadConversations = () => {
|
|
248
|
-
if (persist) {
|
|
253
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
249
254
|
try {
|
|
250
255
|
const stored = localStorage.getItem(storageKey);
|
|
251
256
|
if (stored) {
|
|
@@ -263,7 +268,7 @@ export function useConversations(options = {}) {
|
|
|
263
268
|
}
|
|
264
269
|
};
|
|
265
270
|
const saveConversations = () => {
|
|
266
|
-
if (persist) {
|
|
271
|
+
if (persist && typeof localStorage !== "undefined") {
|
|
267
272
|
localStorage.setItem(
|
|
268
273
|
storageKey,
|
|
269
274
|
JSON.stringify({
|
|
@@ -339,9 +344,11 @@ export function useConversations(options = {}) {
|
|
|
339
344
|
saveConversations();
|
|
340
345
|
}
|
|
341
346
|
};
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
347
|
+
if (typeof localStorage !== "undefined") {
|
|
348
|
+
loadConversations();
|
|
349
|
+
if (conversations.value.length === 0) {
|
|
350
|
+
create();
|
|
351
|
+
}
|
|
345
352
|
}
|
|
346
353
|
return {
|
|
347
354
|
conversations,
|
|
@@ -493,6 +500,7 @@ export function useAIChat(options) {
|
|
|
493
500
|
const decoder = new TextDecoder();
|
|
494
501
|
let fullContent = "";
|
|
495
502
|
let currentToolCalls = [];
|
|
503
|
+
const toolCallArguments = {};
|
|
496
504
|
while (true) {
|
|
497
505
|
const { done, value } = await reader.read();
|
|
498
506
|
if (done) break;
|
|
@@ -516,25 +524,38 @@ export function useAIChat(options) {
|
|
|
516
524
|
if (parsed.choices?.[0]?.delta?.tool_calls) {
|
|
517
525
|
const toolCalls = parsed.choices[0].delta.tool_calls;
|
|
518
526
|
for (const tc of toolCalls) {
|
|
519
|
-
const
|
|
520
|
-
if (
|
|
521
|
-
currentToolCalls[
|
|
522
|
-
...currentToolCalls[existingIndex],
|
|
523
|
-
arguments: {
|
|
524
|
-
...currentToolCalls[existingIndex].arguments,
|
|
525
|
-
...tc.function?.arguments && JSON.parse(tc.function.arguments)
|
|
526
|
-
}
|
|
527
|
-
};
|
|
528
|
-
} else if (tc.id && tc.function?.name) {
|
|
529
|
-
currentToolCalls.push({
|
|
527
|
+
const idx = tc.index ?? 0;
|
|
528
|
+
if (tc.id) {
|
|
529
|
+
currentToolCalls[idx] = {
|
|
530
530
|
id: tc.id,
|
|
531
531
|
type: "function",
|
|
532
|
-
name: tc.function
|
|
533
|
-
arguments:
|
|
534
|
-
}
|
|
532
|
+
name: tc.function?.name || "",
|
|
533
|
+
arguments: {}
|
|
534
|
+
};
|
|
535
|
+
toolCallArguments[idx] = tc.function?.arguments || "";
|
|
536
|
+
} else {
|
|
537
|
+
if (!currentToolCalls[idx]) {
|
|
538
|
+
currentToolCalls[idx] = {
|
|
539
|
+
id: "",
|
|
540
|
+
type: "function",
|
|
541
|
+
name: "",
|
|
542
|
+
arguments: {}
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
if (tc.function?.arguments) {
|
|
546
|
+
toolCallArguments[idx] = (toolCallArguments[idx] || "") + tc.function.arguments;
|
|
547
|
+
}
|
|
535
548
|
}
|
|
536
549
|
}
|
|
537
|
-
|
|
550
|
+
for (let i = 0; i < currentToolCalls.length; i++) {
|
|
551
|
+
if (!currentToolCalls[i]) continue;
|
|
552
|
+
const rawArgs = toolCallArguments[i] || "";
|
|
553
|
+
try {
|
|
554
|
+
currentToolCalls[i].arguments = rawArgs ? JSON.parse(rawArgs) : {};
|
|
555
|
+
} catch {
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
updateLastMessage({ toolCalls: [...currentToolCalls].filter(Boolean) });
|
|
538
559
|
}
|
|
539
560
|
} catch {
|
|
540
561
|
}
|
|
@@ -544,6 +565,16 @@ export function useAIChat(options) {
|
|
|
544
565
|
await new Promise((resolve) => setTimeout(resolve, streamInterval));
|
|
545
566
|
}
|
|
546
567
|
}
|
|
568
|
+
for (let i = 0; i < currentToolCalls.length; i++) {
|
|
569
|
+
if (!currentToolCalls[i]) continue;
|
|
570
|
+
const rawArgs = toolCallArguments[i] || "";
|
|
571
|
+
try {
|
|
572
|
+
currentToolCalls[i].arguments = rawArgs ? JSON.parse(rawArgs) : {};
|
|
573
|
+
} catch {
|
|
574
|
+
currentToolCalls[i].arguments = {};
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
currentToolCalls = currentToolCalls.filter(Boolean);
|
|
547
578
|
if (currentToolCalls.length > 0) {
|
|
548
579
|
updateLastMessage({ toolCalls: currentToolCalls });
|
|
549
580
|
const toolResults = await executeTools(currentToolCalls);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yh-ui/ai-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.53",
|
|
4
4
|
"description": "YH-UI AI SDK integration for Vercel AI SDK and LangChain",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"vue": "^3.5.35",
|
|
48
|
-
"@yh-ui/components": "^1.0.
|
|
48
|
+
"@yh-ui/components": "^1.0.53",
|
|
49
49
|
"@langchain/core": ">=0.3.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependenciesMeta": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@langchain/core": ">=0.3.0",
|
|
58
|
-
"@yh-ui/components": "^1.0.
|
|
58
|
+
"@yh-ui/components": "^1.0.53",
|
|
59
59
|
"typescript": "^5.7.3",
|
|
60
60
|
"unbuild": "^3.3.1",
|
|
61
61
|
"vitest": "^4.0.18",
|