veryfront 0.0.3 → 0.0.5
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 +209 -2
- package/bin/veryfront.js +7 -0
- package/dist/ai/client.js +7 -0
- package/dist/ai/client.js.map +7 -0
- package/dist/ai/components.js +713 -0
- package/dist/ai/components.js.map +7 -0
- package/dist/ai/dev.js +840 -0
- package/dist/ai/dev.js.map +7 -0
- package/dist/ai/index.js +7343 -0
- package/dist/ai/index.js.map +7 -0
- package/dist/ai/primitives.js +314 -0
- package/dist/ai/primitives.js.map +7 -0
- package/dist/ai/production.js +922 -0
- package/dist/ai/production.js.map +7 -0
- package/dist/ai/react.js +455 -0
- package/dist/ai/react.js.map +7 -0
- package/dist/cli.js +38552 -0
- package/dist/components.js +9411 -0
- package/dist/components.js.map +7 -0
- package/dist/config.js +655 -0
- package/dist/config.js.map +7 -0
- package/dist/data.js +1132 -0
- package/dist/data.js.map +7 -0
- package/dist/index.js +11504 -0
- package/dist/index.js.map +7 -0
- package/package.json +114 -30
- package/bin/veryfront +0 -0
- package/scripts/postinstall.js +0 -109
package/dist/ai/dev.js
ADDED
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
// src/ai/dev/testing/agent-tester.ts
|
|
2
|
+
async function testAgent(agent, testCases) {
|
|
3
|
+
const suite = {
|
|
4
|
+
name: agent.id,
|
|
5
|
+
results: [],
|
|
6
|
+
passed: true,
|
|
7
|
+
totalTime: 0
|
|
8
|
+
};
|
|
9
|
+
const suiteStartTime = Date.now();
|
|
10
|
+
for (const testCase of testCases) {
|
|
11
|
+
const result = await runTestCase(agent, testCase);
|
|
12
|
+
suite.results.push(result);
|
|
13
|
+
if (!result.passed) {
|
|
14
|
+
suite.passed = false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
suite.totalTime = Date.now() - suiteStartTime;
|
|
18
|
+
return suite;
|
|
19
|
+
}
|
|
20
|
+
async function runTestCase(agent, testCase) {
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
try {
|
|
23
|
+
const timeout = testCase.timeout || 3e4;
|
|
24
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
25
|
+
setTimeout(() => reject(new Error("Test timeout")), timeout);
|
|
26
|
+
});
|
|
27
|
+
const responsePromise = agent.generate({
|
|
28
|
+
input: testCase.input
|
|
29
|
+
});
|
|
30
|
+
const response = await Promise.race([responsePromise, timeoutPromise]);
|
|
31
|
+
const executionTime = Date.now() - startTime;
|
|
32
|
+
const toolCalls = response.toolCalls.map((tc) => tc.name);
|
|
33
|
+
let passed = true;
|
|
34
|
+
let error;
|
|
35
|
+
if (testCase.expected) {
|
|
36
|
+
if (testCase.expected instanceof RegExp) {
|
|
37
|
+
passed = testCase.expected.test(response.text);
|
|
38
|
+
if (!passed) {
|
|
39
|
+
error = `Output "${response.text}" does not match pattern ${testCase.expected}`;
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
passed = response.text.includes(testCase.expected);
|
|
43
|
+
if (!passed) {
|
|
44
|
+
error = `Output does not contain expected text: "${testCase.expected}"`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (passed && testCase.expectToolCalls) {
|
|
49
|
+
const expectedTools = testCase.expectToolCalls;
|
|
50
|
+
const missingTools = expectedTools.filter((t) => !toolCalls.includes(t));
|
|
51
|
+
if (missingTools.length > 0) {
|
|
52
|
+
passed = false;
|
|
53
|
+
error = `Expected tool calls not found: ${missingTools.join(", ")}`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (passed && testCase.validate) {
|
|
57
|
+
try {
|
|
58
|
+
passed = await testCase.validate(response);
|
|
59
|
+
if (!passed) {
|
|
60
|
+
error = "Custom validation failed";
|
|
61
|
+
}
|
|
62
|
+
} catch (err) {
|
|
63
|
+
passed = false;
|
|
64
|
+
error = `Custom validation error: ${err instanceof Error ? err.message : String(err)}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
name: testCase.name,
|
|
69
|
+
passed,
|
|
70
|
+
response,
|
|
71
|
+
error,
|
|
72
|
+
executionTime,
|
|
73
|
+
toolCalls
|
|
74
|
+
};
|
|
75
|
+
} catch (err) {
|
|
76
|
+
return {
|
|
77
|
+
name: testCase.name,
|
|
78
|
+
passed: false,
|
|
79
|
+
error: err instanceof Error ? err.message : String(err),
|
|
80
|
+
executionTime: Date.now() - startTime,
|
|
81
|
+
toolCalls: []
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function printTestResults(suite) {
|
|
86
|
+
console.log(`
|
|
87
|
+
=== Test Suite: ${suite.name} ===
|
|
88
|
+
`);
|
|
89
|
+
const passed = suite.results.filter((r) => r.passed).length;
|
|
90
|
+
const total = suite.results.length;
|
|
91
|
+
suite.results.forEach((result, index) => {
|
|
92
|
+
const icon = result.passed ? "\u2705" : "\u274C";
|
|
93
|
+
console.log(`${icon} ${index + 1}. ${result.name}`);
|
|
94
|
+
if (!result.passed && result.error) {
|
|
95
|
+
console.log(` Error: ${result.error}`);
|
|
96
|
+
}
|
|
97
|
+
if (result.toolCalls.length > 0) {
|
|
98
|
+
console.log(` Tools used: ${result.toolCalls.join(", ")}`);
|
|
99
|
+
}
|
|
100
|
+
console.log(` Time: ${result.executionTime}ms
|
|
101
|
+
`);
|
|
102
|
+
});
|
|
103
|
+
console.log(`Results: ${passed}/${total} passed`);
|
|
104
|
+
console.log(`Total time: ${suite.totalTime}ms`);
|
|
105
|
+
console.log(`Status: ${suite.passed ? "\u2705 PASSED" : "\u274C FAILED"}
|
|
106
|
+
`);
|
|
107
|
+
}
|
|
108
|
+
function assertContains(response, text) {
|
|
109
|
+
return response.text.toLowerCase().includes(text.toLowerCase());
|
|
110
|
+
}
|
|
111
|
+
function assertToolCalled(response, toolName) {
|
|
112
|
+
return response.toolCalls.some((tc) => tc.name === toolName);
|
|
113
|
+
}
|
|
114
|
+
function assertCompleted(response) {
|
|
115
|
+
return response.status === "completed";
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/ai/dev/testing/tool-tester.ts
|
|
119
|
+
async function testTool(tool, testCases) {
|
|
120
|
+
const results = [];
|
|
121
|
+
for (const testCase of testCases) {
|
|
122
|
+
const result = await runToolTest(tool, testCase);
|
|
123
|
+
results.push(result);
|
|
124
|
+
}
|
|
125
|
+
return results;
|
|
126
|
+
}
|
|
127
|
+
async function runToolTest(tool, testCase) {
|
|
128
|
+
const startTime = Date.now();
|
|
129
|
+
try {
|
|
130
|
+
const result = await tool.execute(testCase.input);
|
|
131
|
+
const executionTime = Date.now() - startTime;
|
|
132
|
+
if (testCase.shouldThrow) {
|
|
133
|
+
return {
|
|
134
|
+
name: testCase.name,
|
|
135
|
+
passed: false,
|
|
136
|
+
error: "Expected tool to throw error but it succeeded",
|
|
137
|
+
executionTime
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
let passed = true;
|
|
141
|
+
let error;
|
|
142
|
+
if (testCase.expectedOutput !== void 0) {
|
|
143
|
+
passed = deepMatch(result, testCase.expectedOutput);
|
|
144
|
+
if (!passed) {
|
|
145
|
+
error = `Output mismatch. Expected: ${JSON.stringify(testCase.expectedOutput)}, Got: ${JSON.stringify(result)}`;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (passed && testCase.validate) {
|
|
149
|
+
try {
|
|
150
|
+
passed = await testCase.validate(result);
|
|
151
|
+
if (!passed) {
|
|
152
|
+
error = "Custom validation failed";
|
|
153
|
+
}
|
|
154
|
+
} catch (err) {
|
|
155
|
+
passed = false;
|
|
156
|
+
error = `Validation error: ${err instanceof Error ? err.message : String(err)}`;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
name: testCase.name,
|
|
161
|
+
passed,
|
|
162
|
+
result,
|
|
163
|
+
error,
|
|
164
|
+
executionTime
|
|
165
|
+
};
|
|
166
|
+
} catch (err) {
|
|
167
|
+
const executionTime = Date.now() - startTime;
|
|
168
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
169
|
+
if (testCase.shouldThrow) {
|
|
170
|
+
let passed = true;
|
|
171
|
+
let error;
|
|
172
|
+
if (testCase.expectedError) {
|
|
173
|
+
if (testCase.expectedError instanceof RegExp) {
|
|
174
|
+
passed = testCase.expectedError.test(errorMessage);
|
|
175
|
+
} else {
|
|
176
|
+
passed = errorMessage.includes(testCase.expectedError);
|
|
177
|
+
}
|
|
178
|
+
if (!passed) {
|
|
179
|
+
error = `Error message mismatch. Expected pattern: ${testCase.expectedError}, Got: ${errorMessage}`;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
name: testCase.name,
|
|
184
|
+
passed,
|
|
185
|
+
error,
|
|
186
|
+
executionTime
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
name: testCase.name,
|
|
191
|
+
passed: false,
|
|
192
|
+
error: `Unexpected error: ${errorMessage}`,
|
|
193
|
+
executionTime
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function deepMatch(actual, expected) {
|
|
198
|
+
if (expected === actual)
|
|
199
|
+
return true;
|
|
200
|
+
if (typeof expected !== "object" || expected === null)
|
|
201
|
+
return false;
|
|
202
|
+
if (typeof actual !== "object" || actual === null)
|
|
203
|
+
return false;
|
|
204
|
+
for (const key in expected) {
|
|
205
|
+
if (!(key in actual))
|
|
206
|
+
return false;
|
|
207
|
+
const expectedValue = expected[key];
|
|
208
|
+
const actualValue = actual[key];
|
|
209
|
+
if (typeof expectedValue === "object" && expectedValue !== null) {
|
|
210
|
+
if (!deepMatch(actualValue, expectedValue))
|
|
211
|
+
return false;
|
|
212
|
+
} else {
|
|
213
|
+
if (actualValue !== expectedValue)
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
function printToolTestResults(toolId, results) {
|
|
220
|
+
console.log(`
|
|
221
|
+
=== Tool Tests: ${toolId} ===
|
|
222
|
+
`);
|
|
223
|
+
const passed = results.filter((r) => r.passed).length;
|
|
224
|
+
const total = results.length;
|
|
225
|
+
results.forEach((result, index) => {
|
|
226
|
+
const icon = result.passed ? "\u2705" : "\u274C";
|
|
227
|
+
console.log(`${icon} ${index + 1}. ${result.name}`);
|
|
228
|
+
if (!result.passed && result.error) {
|
|
229
|
+
console.log(` Error: ${result.error}`);
|
|
230
|
+
}
|
|
231
|
+
if (result.result !== void 0) {
|
|
232
|
+
console.log(` Result: ${JSON.stringify(result.result)}`);
|
|
233
|
+
}
|
|
234
|
+
console.log(` Time: ${result.executionTime}ms
|
|
235
|
+
`);
|
|
236
|
+
});
|
|
237
|
+
console.log(`Results: ${passed}/${total} passed`);
|
|
238
|
+
console.log(`Status: ${passed === total ? "\u2705 ALL PASSED" : "\u274C SOME FAILED"}
|
|
239
|
+
`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/ai/utils/zod-json-schema.ts
|
|
243
|
+
import { ZodFirstPartyTypeKind } from "zod";
|
|
244
|
+
function zodToJsonSchema(schema) {
|
|
245
|
+
if (!schema || typeof schema !== "object" || !("_def" in schema)) {
|
|
246
|
+
throw new Error("Invalid Zod schema: missing _def property");
|
|
247
|
+
}
|
|
248
|
+
const details = unwrapSchema(schema);
|
|
249
|
+
const json = convert(details.schema);
|
|
250
|
+
if (details.nullable) {
|
|
251
|
+
return { anyOf: [json, { type: "null" }] };
|
|
252
|
+
}
|
|
253
|
+
return json;
|
|
254
|
+
}
|
|
255
|
+
function isOptionalSchema(schema) {
|
|
256
|
+
const { optional } = unwrapSchema(schema);
|
|
257
|
+
return optional;
|
|
258
|
+
}
|
|
259
|
+
function convert(schema) {
|
|
260
|
+
switch (schema._def.typeName) {
|
|
261
|
+
case ZodFirstPartyTypeKind.ZodString:
|
|
262
|
+
return { type: "string" };
|
|
263
|
+
case ZodFirstPartyTypeKind.ZodNumber:
|
|
264
|
+
return { type: "number" };
|
|
265
|
+
case ZodFirstPartyTypeKind.ZodBoolean:
|
|
266
|
+
return { type: "boolean" };
|
|
267
|
+
case ZodFirstPartyTypeKind.ZodBigInt:
|
|
268
|
+
return { type: "integer" };
|
|
269
|
+
case ZodFirstPartyTypeKind.ZodLiteral: {
|
|
270
|
+
const literal = schema._def.value;
|
|
271
|
+
return {
|
|
272
|
+
const: literal,
|
|
273
|
+
type: typeof literal === "string" ? "string" : typeof literal === "number" ? "number" : typeof literal === "boolean" ? "boolean" : void 0
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
case ZodFirstPartyTypeKind.ZodEnum:
|
|
277
|
+
return {
|
|
278
|
+
type: "string",
|
|
279
|
+
enum: schema._def.values
|
|
280
|
+
};
|
|
281
|
+
case ZodFirstPartyTypeKind.ZodNativeEnum:
|
|
282
|
+
return {
|
|
283
|
+
enum: Object.values(schema._def.values).filter(
|
|
284
|
+
(value) => typeof value !== "number"
|
|
285
|
+
)
|
|
286
|
+
};
|
|
287
|
+
case ZodFirstPartyTypeKind.ZodObject: {
|
|
288
|
+
const obj = schema;
|
|
289
|
+
const properties = {};
|
|
290
|
+
const required = [];
|
|
291
|
+
const shape = typeof obj._def.shape === "function" ? obj._def.shape() : obj._def.shape;
|
|
292
|
+
for (const [key, value] of Object.entries(shape || {})) {
|
|
293
|
+
const zodSchema = value;
|
|
294
|
+
properties[key] = zodToJsonSchema(zodSchema);
|
|
295
|
+
if (!isOptionalSchema(zodSchema)) {
|
|
296
|
+
required.push(key);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const json = { type: "object", properties };
|
|
300
|
+
if (required.length > 0) {
|
|
301
|
+
json.required = required;
|
|
302
|
+
}
|
|
303
|
+
return json;
|
|
304
|
+
}
|
|
305
|
+
case ZodFirstPartyTypeKind.ZodArray: {
|
|
306
|
+
const array = schema;
|
|
307
|
+
return {
|
|
308
|
+
type: "array",
|
|
309
|
+
items: zodToJsonSchema(array._def.type)
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
case ZodFirstPartyTypeKind.ZodTuple: {
|
|
313
|
+
const tuple = schema;
|
|
314
|
+
return {
|
|
315
|
+
type: "array",
|
|
316
|
+
prefixItems: tuple._def.items.map((item) => zodToJsonSchema(item)),
|
|
317
|
+
minItems: tuple._def.items.length,
|
|
318
|
+
maxItems: tuple._def.items.length
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
case ZodFirstPartyTypeKind.ZodUnion: {
|
|
322
|
+
const union = schema;
|
|
323
|
+
return {
|
|
324
|
+
anyOf: union._def.options.map((option) => zodToJsonSchema(option))
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
case ZodFirstPartyTypeKind.ZodDiscriminatedUnion: {
|
|
328
|
+
const union = schema;
|
|
329
|
+
return {
|
|
330
|
+
anyOf: Array.from(union._def.options.values()).map((option) => zodToJsonSchema(option))
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
case ZodFirstPartyTypeKind.ZodRecord:
|
|
334
|
+
return {
|
|
335
|
+
type: "object",
|
|
336
|
+
additionalProperties: zodToJsonSchema(schema._def.valueType)
|
|
337
|
+
};
|
|
338
|
+
case ZodFirstPartyTypeKind.ZodDefault: {
|
|
339
|
+
const def = schema;
|
|
340
|
+
const inner = zodToJsonSchema(def._def.innerType);
|
|
341
|
+
const defaultValue = def._def.defaultValue();
|
|
342
|
+
if (typeof inner === "object" && !("anyOf" in inner)) {
|
|
343
|
+
inner.default = defaultValue;
|
|
344
|
+
}
|
|
345
|
+
return inner;
|
|
346
|
+
}
|
|
347
|
+
case ZodFirstPartyTypeKind.ZodLazy:
|
|
348
|
+
return convert(schema._def.getter());
|
|
349
|
+
case ZodFirstPartyTypeKind.ZodEffects:
|
|
350
|
+
return convert(schema._def.schema);
|
|
351
|
+
default:
|
|
352
|
+
return { type: "object" };
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function unwrapSchema(schema) {
|
|
356
|
+
let current = schema;
|
|
357
|
+
let nullable = false;
|
|
358
|
+
let optional = false;
|
|
359
|
+
while (true) {
|
|
360
|
+
switch (current._def.typeName) {
|
|
361
|
+
case ZodFirstPartyTypeKind.ZodNullable:
|
|
362
|
+
nullable = true;
|
|
363
|
+
current = current._def.innerType;
|
|
364
|
+
continue;
|
|
365
|
+
case ZodFirstPartyTypeKind.ZodOptional:
|
|
366
|
+
optional = true;
|
|
367
|
+
current = current._def.innerType;
|
|
368
|
+
continue;
|
|
369
|
+
case ZodFirstPartyTypeKind.ZodEffects:
|
|
370
|
+
current = current._def.schema;
|
|
371
|
+
continue;
|
|
372
|
+
default:
|
|
373
|
+
return { schema: current, nullable, optional };
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/core/utils/runtime-guards.ts
|
|
379
|
+
function hasDenoRuntime(global) {
|
|
380
|
+
return typeof global === "object" && global !== null && "Deno" in global && typeof global.Deno?.env?.get === "function";
|
|
381
|
+
}
|
|
382
|
+
function hasNodeProcess(global) {
|
|
383
|
+
return typeof global === "object" && global !== null && "process" in global && typeof global.process?.env === "object";
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// src/core/utils/logger/env.ts
|
|
387
|
+
function getEnvironmentVariable(name) {
|
|
388
|
+
try {
|
|
389
|
+
if (typeof Deno !== "undefined" && hasDenoRuntime(globalThis)) {
|
|
390
|
+
const value = globalThis.Deno?.env.get(name);
|
|
391
|
+
return value === "" ? void 0 : value;
|
|
392
|
+
}
|
|
393
|
+
if (hasNodeProcess(globalThis)) {
|
|
394
|
+
const value = globalThis.process?.env[name];
|
|
395
|
+
return value === "" ? void 0 : value;
|
|
396
|
+
}
|
|
397
|
+
} catch (error) {
|
|
398
|
+
console.debug(`Failed to get environment variable ${name}:`, error);
|
|
399
|
+
return void 0;
|
|
400
|
+
}
|
|
401
|
+
return void 0;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// src/core/utils/logger/logger.ts
|
|
405
|
+
var cachedLogLevel;
|
|
406
|
+
function resolveLogLevel(force = false) {
|
|
407
|
+
if (force || cachedLogLevel === void 0) {
|
|
408
|
+
cachedLogLevel = getDefaultLevel();
|
|
409
|
+
}
|
|
410
|
+
return cachedLogLevel;
|
|
411
|
+
}
|
|
412
|
+
var ConsoleLogger = class {
|
|
413
|
+
constructor(prefix, level = resolveLogLevel()) {
|
|
414
|
+
this.prefix = prefix;
|
|
415
|
+
this.level = level;
|
|
416
|
+
}
|
|
417
|
+
setLevel(level) {
|
|
418
|
+
this.level = level;
|
|
419
|
+
}
|
|
420
|
+
getLevel() {
|
|
421
|
+
return this.level;
|
|
422
|
+
}
|
|
423
|
+
debug(message, ...args) {
|
|
424
|
+
if (this.level <= 0 /* DEBUG */) {
|
|
425
|
+
console.debug(`[${this.prefix}] DEBUG: ${message}`, ...args);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
info(message, ...args) {
|
|
429
|
+
if (this.level <= 1 /* INFO */) {
|
|
430
|
+
console.log(`[${this.prefix}] ${message}`, ...args);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
warn(message, ...args) {
|
|
434
|
+
if (this.level <= 2 /* WARN */) {
|
|
435
|
+
console.warn(`[${this.prefix}] WARN: ${message}`, ...args);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
error(message, ...args) {
|
|
439
|
+
if (this.level <= 3 /* ERROR */) {
|
|
440
|
+
console.error(`[${this.prefix}] ERROR: ${message}`, ...args);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
async time(label, fn) {
|
|
444
|
+
const start = performance.now();
|
|
445
|
+
try {
|
|
446
|
+
const result = await fn();
|
|
447
|
+
const end = performance.now();
|
|
448
|
+
this.debug(`${label} completed in ${(end - start).toFixed(2)}ms`);
|
|
449
|
+
return result;
|
|
450
|
+
} catch (_error) {
|
|
451
|
+
const end = performance.now();
|
|
452
|
+
this.error(`${label} failed after ${(end - start).toFixed(2)}ms`, _error);
|
|
453
|
+
throw _error;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
function parseLogLevel(levelString) {
|
|
458
|
+
if (!levelString)
|
|
459
|
+
return void 0;
|
|
460
|
+
const upper = levelString.toUpperCase();
|
|
461
|
+
switch (upper) {
|
|
462
|
+
case "DEBUG":
|
|
463
|
+
return 0 /* DEBUG */;
|
|
464
|
+
case "WARN":
|
|
465
|
+
return 2 /* WARN */;
|
|
466
|
+
case "ERROR":
|
|
467
|
+
return 3 /* ERROR */;
|
|
468
|
+
case "INFO":
|
|
469
|
+
return 1 /* INFO */;
|
|
470
|
+
default:
|
|
471
|
+
return void 0;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
var getDefaultLevel = () => {
|
|
475
|
+
const envLevel = getEnvironmentVariable("LOG_LEVEL");
|
|
476
|
+
const parsedLevel = parseLogLevel(envLevel);
|
|
477
|
+
if (parsedLevel !== void 0)
|
|
478
|
+
return parsedLevel;
|
|
479
|
+
const debugFlag = getEnvironmentVariable("VERYFRONT_DEBUG");
|
|
480
|
+
if (debugFlag === "1" || debugFlag === "true")
|
|
481
|
+
return 0 /* DEBUG */;
|
|
482
|
+
return 1 /* INFO */;
|
|
483
|
+
};
|
|
484
|
+
var trackedLoggers = /* @__PURE__ */ new Set();
|
|
485
|
+
function createLogger(prefix) {
|
|
486
|
+
const logger2 = new ConsoleLogger(prefix);
|
|
487
|
+
trackedLoggers.add(logger2);
|
|
488
|
+
return logger2;
|
|
489
|
+
}
|
|
490
|
+
var cliLogger = createLogger("CLI");
|
|
491
|
+
var serverLogger = createLogger("SERVER");
|
|
492
|
+
var rendererLogger = createLogger("RENDERER");
|
|
493
|
+
var bundlerLogger = createLogger("BUNDLER");
|
|
494
|
+
var agentLogger = createLogger("AGENT");
|
|
495
|
+
var logger = createLogger("VERYFRONT");
|
|
496
|
+
|
|
497
|
+
// src/core/errors/veryfront-error.ts
|
|
498
|
+
function createError(error) {
|
|
499
|
+
return error;
|
|
500
|
+
}
|
|
501
|
+
function toError(veryfrontError) {
|
|
502
|
+
const error = new Error(veryfrontError.message);
|
|
503
|
+
error.name = `VeryfrontError[${veryfrontError.type}]`;
|
|
504
|
+
Object.defineProperty(error, "context", {
|
|
505
|
+
value: veryfrontError,
|
|
506
|
+
enumerable: false,
|
|
507
|
+
configurable: true
|
|
508
|
+
});
|
|
509
|
+
return error;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// src/ai/utils/tool.ts
|
|
513
|
+
var ToolRegistryClass = class {
|
|
514
|
+
constructor() {
|
|
515
|
+
this.tools = /* @__PURE__ */ new Map();
|
|
516
|
+
}
|
|
517
|
+
register(id, toolInstance) {
|
|
518
|
+
if (this.tools.has(id)) {
|
|
519
|
+
agentLogger.warn(`Tool "${id}" is already registered. Overwriting.`);
|
|
520
|
+
}
|
|
521
|
+
this.tools.set(id, toolInstance);
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Get a tool by ID
|
|
525
|
+
*/
|
|
526
|
+
get(id) {
|
|
527
|
+
return this.tools.get(id);
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Check if a tool exists
|
|
531
|
+
*/
|
|
532
|
+
has(id) {
|
|
533
|
+
return this.tools.has(id);
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Get all tool IDs
|
|
537
|
+
*/
|
|
538
|
+
getAllIds() {
|
|
539
|
+
return Array.from(this.tools.keys());
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Get all tools
|
|
543
|
+
*/
|
|
544
|
+
getAll() {
|
|
545
|
+
return new Map(this.tools);
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Clear all tools (for testing)
|
|
549
|
+
*/
|
|
550
|
+
clear() {
|
|
551
|
+
this.tools.clear();
|
|
552
|
+
}
|
|
553
|
+
getToolsForProvider() {
|
|
554
|
+
return Array.from(this.tools.values()).map(toolToProviderDefinition);
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
var toolRegistry = new ToolRegistryClass();
|
|
558
|
+
function toolToProviderDefinition(tool) {
|
|
559
|
+
const jsonSchema = tool.inputSchemaJson || zodToJsonSchema(tool.inputSchema);
|
|
560
|
+
agentLogger.info(
|
|
561
|
+
`[TOOL] Using ${tool.inputSchemaJson ? "pre-converted" : "runtime-converted"} schema for "${tool.id}"`
|
|
562
|
+
);
|
|
563
|
+
return {
|
|
564
|
+
name: tool.id,
|
|
565
|
+
description: tool.description,
|
|
566
|
+
parameters: jsonSchema
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// src/ai/mcp/resource.ts
|
|
571
|
+
var ResourceRegistryClass = class {
|
|
572
|
+
constructor() {
|
|
573
|
+
this.resources = /* @__PURE__ */ new Map();
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Register a resource
|
|
577
|
+
*/
|
|
578
|
+
register(id, resourceInstance) {
|
|
579
|
+
if (this.resources.has(id)) {
|
|
580
|
+
agentLogger.warn(`Resource "${id}" is already registered. Overwriting.`);
|
|
581
|
+
}
|
|
582
|
+
this.resources.set(id, resourceInstance);
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Get a resource by ID
|
|
586
|
+
*/
|
|
587
|
+
get(id) {
|
|
588
|
+
return this.resources.get(id);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Get resource by pattern matching
|
|
592
|
+
*/
|
|
593
|
+
findByPattern(uri) {
|
|
594
|
+
for (const resource of this.resources.values()) {
|
|
595
|
+
if (this.matchesPattern(uri, resource.pattern)) {
|
|
596
|
+
return resource;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
return void 0;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Check if URI matches pattern
|
|
603
|
+
* Uses regex-based pattern matching with named capture groups.
|
|
604
|
+
* Supports Express-style patterns like "/users/:userId/profile"
|
|
605
|
+
*/
|
|
606
|
+
matchesPattern(uri, pattern) {
|
|
607
|
+
const patternRegex = new RegExp(
|
|
608
|
+
"^" + pattern.replace(/:(\w+)/g, "(?<$1>[^/]+)") + "$"
|
|
609
|
+
);
|
|
610
|
+
return patternRegex.test(uri);
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Extract params from URI using pattern
|
|
614
|
+
*/
|
|
615
|
+
extractParams(uri, pattern) {
|
|
616
|
+
const patternRegex = new RegExp(
|
|
617
|
+
"^" + pattern.replace(/:(\w+)/g, "(?<$1>[^/]+)") + "$"
|
|
618
|
+
);
|
|
619
|
+
const match = uri.match(patternRegex);
|
|
620
|
+
return match?.groups || {};
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Get all resources
|
|
624
|
+
*/
|
|
625
|
+
getAll() {
|
|
626
|
+
return new Map(this.resources);
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Clear all resources
|
|
630
|
+
*/
|
|
631
|
+
clear() {
|
|
632
|
+
this.resources.clear();
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
var resourceRegistry = new ResourceRegistryClass();
|
|
636
|
+
|
|
637
|
+
// src/ai/mcp/prompt.ts
|
|
638
|
+
var PromptRegistryClass = class {
|
|
639
|
+
constructor() {
|
|
640
|
+
this.prompts = /* @__PURE__ */ new Map();
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Register a prompt
|
|
644
|
+
*/
|
|
645
|
+
register(id, promptInstance) {
|
|
646
|
+
if (this.prompts.has(id)) {
|
|
647
|
+
agentLogger.warn(`Prompt "${id}" is already registered. Overwriting.`);
|
|
648
|
+
}
|
|
649
|
+
this.prompts.set(id, promptInstance);
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Get a prompt by ID
|
|
653
|
+
*/
|
|
654
|
+
get(id) {
|
|
655
|
+
return this.prompts.get(id);
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Get prompt content by ID
|
|
659
|
+
*/
|
|
660
|
+
async getContent(id, variables) {
|
|
661
|
+
const promptInstance = this.get(id);
|
|
662
|
+
if (!promptInstance) {
|
|
663
|
+
throw toError(createError({
|
|
664
|
+
type: "agent",
|
|
665
|
+
message: `Prompt "${id}" not found`
|
|
666
|
+
}));
|
|
667
|
+
}
|
|
668
|
+
return await promptInstance.getContent(variables);
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Get all prompts
|
|
672
|
+
*/
|
|
673
|
+
getAll() {
|
|
674
|
+
return new Map(this.prompts);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Clear all prompts
|
|
678
|
+
*/
|
|
679
|
+
clear() {
|
|
680
|
+
this.prompts.clear();
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
var promptRegistry = new PromptRegistryClass();
|
|
684
|
+
|
|
685
|
+
// src/ai/mcp/registry.ts
|
|
686
|
+
function getMCPRegistry() {
|
|
687
|
+
return {
|
|
688
|
+
tools: toolRegistry.getAll(),
|
|
689
|
+
resources: resourceRegistry.getAll(),
|
|
690
|
+
prompts: promptRegistry.getAll()
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
function getMCPStats() {
|
|
694
|
+
const registry = getMCPRegistry();
|
|
695
|
+
return {
|
|
696
|
+
tools: registry.tools.size,
|
|
697
|
+
resources: registry.resources.size,
|
|
698
|
+
prompts: registry.prompts.size,
|
|
699
|
+
total: registry.tools.size + registry.resources.size + registry.prompts.size
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// src/ai/dev/debug/inspector.ts
|
|
704
|
+
async function inspectAgent(agent, input) {
|
|
705
|
+
const startTime = Date.now();
|
|
706
|
+
const _memoryStatsBefore = await agent.getMemoryStats();
|
|
707
|
+
const response = await agent.generate({ input });
|
|
708
|
+
const executionTime = Date.now() - startTime;
|
|
709
|
+
const memoryStatsAfter = await agent.getMemoryStats();
|
|
710
|
+
const availableTools = agent.config.tools ? Object.keys(agent.config.tools) : [];
|
|
711
|
+
return {
|
|
712
|
+
agent: {
|
|
713
|
+
id: agent.id,
|
|
714
|
+
model: agent.config.model,
|
|
715
|
+
maxSteps: agent.config.maxSteps || 20,
|
|
716
|
+
memoryType: agent.config.memory?.type || "conversation"
|
|
717
|
+
},
|
|
718
|
+
execution: {
|
|
719
|
+
input,
|
|
720
|
+
output: response.text,
|
|
721
|
+
status: response.status,
|
|
722
|
+
steps: response.toolCalls.length + 1,
|
|
723
|
+
// Tool calls + final response
|
|
724
|
+
executionTime
|
|
725
|
+
},
|
|
726
|
+
tools: {
|
|
727
|
+
called: response.toolCalls.map((tc) => ({
|
|
728
|
+
name: tc.name,
|
|
729
|
+
args: tc.args,
|
|
730
|
+
result: tc.result,
|
|
731
|
+
executionTime: tc.executionTime,
|
|
732
|
+
status: tc.status
|
|
733
|
+
})),
|
|
734
|
+
available: availableTools
|
|
735
|
+
},
|
|
736
|
+
memory: {
|
|
737
|
+
messagesCount: memoryStatsAfter.totalMessages,
|
|
738
|
+
estimatedTokens: memoryStatsAfter.estimatedTokens
|
|
739
|
+
},
|
|
740
|
+
usage: response.usage
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
function printInspectionReport(report) {
|
|
744
|
+
agentLogger.info("\n=== Agent Inspection Report ===\n");
|
|
745
|
+
agentLogger.info("Agent:");
|
|
746
|
+
agentLogger.info(` ID: ${report.agent.id}`);
|
|
747
|
+
agentLogger.info(` Model: ${report.agent.model}`);
|
|
748
|
+
agentLogger.info(` Max Steps: ${report.agent.maxSteps}`);
|
|
749
|
+
agentLogger.info(` Memory: ${report.agent.memoryType}
|
|
750
|
+
`);
|
|
751
|
+
agentLogger.info("Execution:");
|
|
752
|
+
agentLogger.info(
|
|
753
|
+
` Input: ${typeof report.execution.input === "string" ? report.execution.input : `${report.execution.input.length} messages`}`
|
|
754
|
+
);
|
|
755
|
+
agentLogger.info(` Output: ${report.execution.output.substring(0, 100)}...`);
|
|
756
|
+
agentLogger.info(` Status: ${report.execution.status}`);
|
|
757
|
+
agentLogger.info(` Steps: ${report.execution.steps}`);
|
|
758
|
+
agentLogger.info(` Time: ${report.execution.executionTime}ms
|
|
759
|
+
`);
|
|
760
|
+
agentLogger.info("Tools:");
|
|
761
|
+
agentLogger.info(
|
|
762
|
+
` Available: ${report.tools.available.length} (${report.tools.available.join(", ")})`
|
|
763
|
+
);
|
|
764
|
+
agentLogger.info(` Called: ${report.tools.called.length}`);
|
|
765
|
+
if (report.tools.called.length > 0) {
|
|
766
|
+
report.tools.called.forEach((tool, i) => {
|
|
767
|
+
agentLogger.info(` ${i + 1}. ${tool.name}(${JSON.stringify(tool.args)})`);
|
|
768
|
+
agentLogger.info(` Status: ${tool.status}`);
|
|
769
|
+
agentLogger.info(` Time: ${tool.executionTime}ms`);
|
|
770
|
+
agentLogger.info(` Result: ${JSON.stringify(tool.result).substring(0, 100)}...`);
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
agentLogger.info("");
|
|
774
|
+
agentLogger.info("Memory:");
|
|
775
|
+
agentLogger.info(` Messages: ${report.memory.messagesCount}`);
|
|
776
|
+
agentLogger.info(` Estimated Tokens: ${report.memory.estimatedTokens}
|
|
777
|
+
`);
|
|
778
|
+
if (report.usage) {
|
|
779
|
+
agentLogger.info("Token Usage:");
|
|
780
|
+
agentLogger.info(` Prompt: ${report.usage.promptTokens}`);
|
|
781
|
+
agentLogger.info(` Completion: ${report.usage.completionTokens}`);
|
|
782
|
+
agentLogger.info(` Total: ${report.usage.totalTokens}
|
|
783
|
+
`);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
function getRegistryOverview() {
|
|
787
|
+
const registry = getMCPRegistry();
|
|
788
|
+
const stats = getMCPStats();
|
|
789
|
+
return {
|
|
790
|
+
tools: Array.from(registry.tools.values()).map((t) => ({
|
|
791
|
+
id: t.id,
|
|
792
|
+
description: t.description
|
|
793
|
+
})),
|
|
794
|
+
resources: Array.from(registry.resources.values()).map((r) => ({
|
|
795
|
+
id: r.id,
|
|
796
|
+
pattern: r.pattern,
|
|
797
|
+
description: r.description
|
|
798
|
+
})),
|
|
799
|
+
prompts: Array.from(registry.prompts.values()).map((p) => ({
|
|
800
|
+
id: p.id,
|
|
801
|
+
description: p.description
|
|
802
|
+
})),
|
|
803
|
+
stats
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
function printRegistryOverview() {
|
|
807
|
+
const overview = getRegistryOverview();
|
|
808
|
+
agentLogger.info("\n=== MCP Registry Overview ===\n");
|
|
809
|
+
agentLogger.info(`Total: ${overview.stats.total} items
|
|
810
|
+
`);
|
|
811
|
+
agentLogger.info(`Tools (${overview.stats.tools}):`);
|
|
812
|
+
overview.tools.forEach((t) => {
|
|
813
|
+
agentLogger.info(` \u2022 ${t.id}: ${t.description}`);
|
|
814
|
+
});
|
|
815
|
+
agentLogger.info("");
|
|
816
|
+
agentLogger.info(`Resources (${overview.stats.resources}):`);
|
|
817
|
+
overview.resources.forEach((r) => {
|
|
818
|
+
agentLogger.info(` \u2022 ${r.id} (${r.pattern}): ${r.description}`);
|
|
819
|
+
});
|
|
820
|
+
agentLogger.info("");
|
|
821
|
+
agentLogger.info(`Prompts (${overview.stats.prompts}):`);
|
|
822
|
+
overview.prompts.forEach((p) => {
|
|
823
|
+
agentLogger.info(` \u2022 ${p.id}: ${p.description}`);
|
|
824
|
+
});
|
|
825
|
+
agentLogger.info("");
|
|
826
|
+
}
|
|
827
|
+
export {
|
|
828
|
+
assertCompleted,
|
|
829
|
+
assertContains,
|
|
830
|
+
assertToolCalled,
|
|
831
|
+
getRegistryOverview,
|
|
832
|
+
inspectAgent,
|
|
833
|
+
printInspectionReport,
|
|
834
|
+
printRegistryOverview,
|
|
835
|
+
printTestResults,
|
|
836
|
+
printToolTestResults,
|
|
837
|
+
testAgent,
|
|
838
|
+
testTool
|
|
839
|
+
};
|
|
840
|
+
//# sourceMappingURL=dev.js.map
|