veryfront 0.0.73 → 0.0.74
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 +3 -0
- package/dist/ai/components.js +3 -3
- package/dist/ai/components.js.map +1 -1
- package/dist/ai/dev.js +130 -21
- package/dist/ai/dev.js.map +2 -2
- package/dist/ai/index.js +895 -418
- package/dist/ai/index.js.map +4 -4
- package/dist/ai/production.js +135 -38
- package/dist/ai/production.js.map +2 -2
- package/dist/ai/react.js +8 -7
- package/dist/ai/react.js.map +2 -2
- package/dist/ai/workflow.js +468 -110
- package/dist/ai/workflow.js.map +4 -4
- package/dist/components.js +8178 -1164
- package/dist/components.js.map +4 -4
- package/dist/config.js +377 -39
- package/dist/config.js.map +3 -3
- package/dist/context.d.ts +44 -0
- package/dist/context.js +52 -0
- package/dist/context.js.map +7 -0
- package/dist/data.js +176 -62
- package/dist/data.js.map +3 -3
- package/dist/fonts.d.ts +24 -0
- package/dist/fonts.js +45 -0
- package/dist/fonts.js.map +7 -0
- package/dist/head.d.ts +21 -0
- package/dist/head.js +34 -0
- package/dist/head.js.map +7 -0
- package/dist/index.js +8098 -1048
- package/dist/index.js.map +4 -4
- package/dist/oauth/handlers.js +6 -7
- package/dist/oauth/handlers.js.map +1 -1
- package/dist/oauth/index.js +6 -7
- package/dist/oauth/index.js.map +1 -1
- package/dist/oauth/providers.js +0 -3
- package/dist/oauth/providers.js.map +1 -1
- package/dist/oauth/token-store.js +6 -4
- package/dist/oauth/token-store.js.map +1 -1
- package/dist/router.d.ts +69 -0
- package/dist/router.js +61 -0
- package/dist/router.js.map +7 -0
- package/package.json +19 -2
- package/dist/cli.js +0 -107694
package/dist/ai/index.js
CHANGED
|
@@ -79,19 +79,69 @@ function getEnvironmentVariable(name) {
|
|
|
79
79
|
}
|
|
80
80
|
return void 0;
|
|
81
81
|
}
|
|
82
|
+
function isProductionEnvironment() {
|
|
83
|
+
return getEnvironmentVariable("NODE_ENV") === "production";
|
|
84
|
+
}
|
|
82
85
|
|
|
83
86
|
// src/core/utils/logger/logger.ts
|
|
84
87
|
var cachedLogLevel;
|
|
88
|
+
var cachedLogFormat;
|
|
85
89
|
function resolveLogLevel(force = false) {
|
|
86
90
|
if (force || cachedLogLevel === void 0) {
|
|
87
91
|
cachedLogLevel = getDefaultLevel();
|
|
88
92
|
}
|
|
89
93
|
return cachedLogLevel;
|
|
90
94
|
}
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
function resolveLogFormat(force = false) {
|
|
96
|
+
if (force || cachedLogFormat === void 0) {
|
|
97
|
+
cachedLogFormat = getDefaultFormat();
|
|
98
|
+
}
|
|
99
|
+
return cachedLogFormat;
|
|
100
|
+
}
|
|
101
|
+
function getDefaultFormat() {
|
|
102
|
+
const envFormat = getEnvironmentVariable("LOG_FORMAT");
|
|
103
|
+
if (envFormat === "json" || envFormat === "text") {
|
|
104
|
+
return envFormat;
|
|
105
|
+
}
|
|
106
|
+
return isProductionEnvironment() ? "json" : "text";
|
|
107
|
+
}
|
|
108
|
+
function serializeError(err) {
|
|
109
|
+
if (err instanceof Error) {
|
|
110
|
+
return {
|
|
111
|
+
name: err.name,
|
|
112
|
+
message: err.message,
|
|
113
|
+
stack: err.stack
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (err !== void 0 && err !== null) {
|
|
117
|
+
return {
|
|
118
|
+
name: "UnknownError",
|
|
119
|
+
message: String(err)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return void 0;
|
|
123
|
+
}
|
|
124
|
+
function extractContext(args) {
|
|
125
|
+
let context;
|
|
126
|
+
let error;
|
|
127
|
+
for (const arg of args) {
|
|
128
|
+
if (arg instanceof Error) {
|
|
129
|
+
error = serializeError(arg);
|
|
130
|
+
} else if (typeof arg === "object" && arg !== null && !Array.isArray(arg)) {
|
|
131
|
+
context = { ...context, ...arg };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return { context, error };
|
|
135
|
+
}
|
|
136
|
+
var ConsoleLogger = class _ConsoleLogger {
|
|
137
|
+
constructor(prefix, level = resolveLogLevel(), format = resolveLogFormat(), boundContext) {
|
|
93
138
|
this.prefix = prefix;
|
|
94
139
|
this.level = level;
|
|
140
|
+
this.format = format;
|
|
141
|
+
this.boundContext = {};
|
|
142
|
+
if (boundContext) {
|
|
143
|
+
this.boundContext = boundContext;
|
|
144
|
+
}
|
|
95
145
|
}
|
|
96
146
|
setLevel(level) {
|
|
97
147
|
this.level = level;
|
|
@@ -99,36 +149,88 @@ var ConsoleLogger = class {
|
|
|
99
149
|
getLevel() {
|
|
100
150
|
return this.level;
|
|
101
151
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
152
|
+
setFormat(format) {
|
|
153
|
+
this.format = format;
|
|
154
|
+
}
|
|
155
|
+
getFormat() {
|
|
156
|
+
return this.format;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Create a child logger with additional bound context.
|
|
160
|
+
*/
|
|
161
|
+
child(context) {
|
|
162
|
+
return new _ConsoleLogger(this.prefix, this.level, this.format, {
|
|
163
|
+
...this.boundContext,
|
|
164
|
+
...context
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
formatJson(level, message, args) {
|
|
168
|
+
const { context, error } = extractContext(args);
|
|
169
|
+
const entry = {
|
|
170
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
171
|
+
level,
|
|
172
|
+
service: this.prefix.toLowerCase(),
|
|
173
|
+
message
|
|
174
|
+
};
|
|
175
|
+
const mergedContext = { ...this.boundContext, ...context };
|
|
176
|
+
if (Object.keys(mergedContext).length > 0) {
|
|
177
|
+
if ("requestId" in mergedContext) {
|
|
178
|
+
entry.requestId = String(mergedContext.requestId);
|
|
179
|
+
delete mergedContext.requestId;
|
|
180
|
+
}
|
|
181
|
+
if ("traceId" in mergedContext) {
|
|
182
|
+
entry.traceId = String(mergedContext.traceId);
|
|
183
|
+
delete mergedContext.traceId;
|
|
184
|
+
}
|
|
185
|
+
if ("projectSlug" in mergedContext) {
|
|
186
|
+
entry.projectSlug = String(mergedContext.projectSlug);
|
|
187
|
+
delete mergedContext.projectSlug;
|
|
188
|
+
}
|
|
189
|
+
if ("durationMs" in mergedContext) {
|
|
190
|
+
entry.durationMs = Number(mergedContext.durationMs);
|
|
191
|
+
delete mergedContext.durationMs;
|
|
192
|
+
}
|
|
193
|
+
if (Object.keys(mergedContext).length > 0) {
|
|
194
|
+
entry.context = mergedContext;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (error) {
|
|
198
|
+
entry.error = error;
|
|
105
199
|
}
|
|
200
|
+
return JSON.stringify(entry);
|
|
106
201
|
}
|
|
107
|
-
|
|
108
|
-
if (this.level
|
|
109
|
-
|
|
202
|
+
log(level, logLevel, consoleFn, message, args) {
|
|
203
|
+
if (this.level > logLevel)
|
|
204
|
+
return;
|
|
205
|
+
if (this.format === "json") {
|
|
206
|
+
consoleFn(this.formatJson(level, message, args));
|
|
207
|
+
} else {
|
|
208
|
+
const prefix = level === "info" ? "" : ` ${level.toUpperCase()}:`;
|
|
209
|
+
consoleFn(`[${this.prefix}]${prefix} ${message}`, ...args);
|
|
110
210
|
}
|
|
111
211
|
}
|
|
212
|
+
debug(message, ...args) {
|
|
213
|
+
this.log("debug", 0 /* DEBUG */, console.debug, message, args);
|
|
214
|
+
}
|
|
215
|
+
info(message, ...args) {
|
|
216
|
+
this.log("info", 1 /* INFO */, console.log, message, args);
|
|
217
|
+
}
|
|
112
218
|
warn(message, ...args) {
|
|
113
|
-
|
|
114
|
-
console.warn(`[${this.prefix}] WARN: ${message}`, ...args);
|
|
115
|
-
}
|
|
219
|
+
this.log("warn", 2 /* WARN */, console.warn, message, args);
|
|
116
220
|
}
|
|
117
221
|
error(message, ...args) {
|
|
118
|
-
|
|
119
|
-
console.error(`[${this.prefix}] ERROR: ${message}`, ...args);
|
|
120
|
-
}
|
|
222
|
+
this.log("error", 3 /* ERROR */, console.error, message, args);
|
|
121
223
|
}
|
|
122
224
|
async time(label, fn) {
|
|
123
225
|
const start = performance.now();
|
|
124
226
|
try {
|
|
125
227
|
const result = await fn();
|
|
126
|
-
const
|
|
127
|
-
this.debug(`${label} completed
|
|
228
|
+
const durationMs = performance.now() - start;
|
|
229
|
+
this.debug(`${label} completed`, { durationMs: Math.round(durationMs) });
|
|
128
230
|
return result;
|
|
129
231
|
} catch (error) {
|
|
130
|
-
const
|
|
131
|
-
this.error(`${label} failed
|
|
232
|
+
const durationMs = performance.now() - start;
|
|
233
|
+
this.error(`${label} failed`, { durationMs: Math.round(durationMs) }, error);
|
|
132
234
|
throw error;
|
|
133
235
|
}
|
|
134
236
|
}
|
|
@@ -171,6 +273,7 @@ var serverLogger = createLogger("SERVER");
|
|
|
171
273
|
var rendererLogger = createLogger("RENDERER");
|
|
172
274
|
var bundlerLogger = createLogger("BUNDLER");
|
|
173
275
|
var agentLogger = createLogger("AGENT");
|
|
276
|
+
var proxyLogger = createLogger("PROXY");
|
|
174
277
|
var logger = createLogger("VERYFRONT");
|
|
175
278
|
|
|
176
279
|
// src/ai/providers/base.ts
|
|
@@ -191,8 +294,30 @@ var OpenAIStreamChunkSchema = z.object({
|
|
|
191
294
|
finish_reason: z.string().nullable()
|
|
192
295
|
})).min(1)
|
|
193
296
|
});
|
|
297
|
+
var OpenAICompletionResponseSchema = z.object({
|
|
298
|
+
id: z.string(),
|
|
299
|
+
choices: z.array(z.object({
|
|
300
|
+
message: z.object({
|
|
301
|
+
role: z.string(),
|
|
302
|
+
content: z.string().nullable().optional(),
|
|
303
|
+
tool_calls: z.array(z.object({
|
|
304
|
+
id: z.string(),
|
|
305
|
+
type: z.literal("function"),
|
|
306
|
+
function: z.object({
|
|
307
|
+
name: z.string(),
|
|
308
|
+
arguments: z.string()
|
|
309
|
+
})
|
|
310
|
+
})).optional()
|
|
311
|
+
}),
|
|
312
|
+
finish_reason: z.string().nullable()
|
|
313
|
+
})).min(1),
|
|
314
|
+
usage: z.object({
|
|
315
|
+
prompt_tokens: z.number(),
|
|
316
|
+
completion_tokens: z.number(),
|
|
317
|
+
total_tokens: z.number()
|
|
318
|
+
}).optional()
|
|
319
|
+
});
|
|
194
320
|
var BaseProvider = class {
|
|
195
|
-
config;
|
|
196
321
|
constructor(config) {
|
|
197
322
|
this.config = config;
|
|
198
323
|
this.validateConfig();
|
|
@@ -231,7 +356,17 @@ var BaseProvider = class {
|
|
|
231
356
|
}));
|
|
232
357
|
}
|
|
233
358
|
const data = await response.json();
|
|
234
|
-
|
|
359
|
+
const parseResult = OpenAICompletionResponseSchema.safeParse(data);
|
|
360
|
+
if (!parseResult.success) {
|
|
361
|
+
agentLogger.warn(`${this.name}: Invalid response structure`, {
|
|
362
|
+
errors: parseResult.error.flatten()
|
|
363
|
+
});
|
|
364
|
+
throw toError(createError({
|
|
365
|
+
type: "agent",
|
|
366
|
+
message: `${this.name}: Invalid response structure from provider`
|
|
367
|
+
}));
|
|
368
|
+
}
|
|
369
|
+
return this.transformResponse(parseResult.data);
|
|
235
370
|
}
|
|
236
371
|
/**
|
|
237
372
|
* Stream a completion
|
|
@@ -407,12 +542,9 @@ var OpenAIResponseSchema = z2.object({
|
|
|
407
542
|
}).optional()
|
|
408
543
|
});
|
|
409
544
|
var OpenAIProvider = class extends BaseProvider {
|
|
410
|
-
name = "openai";
|
|
411
|
-
apiKey;
|
|
412
|
-
baseURL;
|
|
413
|
-
organizationId;
|
|
414
545
|
constructor(config) {
|
|
415
546
|
super(config);
|
|
547
|
+
this.name = "openai";
|
|
416
548
|
this.apiKey = config.apiKey;
|
|
417
549
|
this.baseURL = config.baseURL || "https://api.openai.com/v1";
|
|
418
550
|
this.organizationId = config.organizationId;
|
|
@@ -515,11 +647,9 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
515
647
|
|
|
516
648
|
// src/ai/providers/anthropic.ts
|
|
517
649
|
var AnthropicProvider = class extends BaseProvider {
|
|
518
|
-
name = "anthropic";
|
|
519
|
-
apiKey;
|
|
520
|
-
baseURL;
|
|
521
650
|
constructor(config) {
|
|
522
651
|
super(config);
|
|
652
|
+
this.name = "anthropic";
|
|
523
653
|
this.apiKey = config.apiKey;
|
|
524
654
|
this.baseURL = config.baseURL || "https://api.anthropic.com";
|
|
525
655
|
}
|
|
@@ -817,11 +947,9 @@ var GoogleResponseSchema = z3.object({
|
|
|
817
947
|
}).optional()
|
|
818
948
|
});
|
|
819
949
|
var GoogleProvider = class extends BaseProvider {
|
|
820
|
-
name = "google";
|
|
821
|
-
apiKey;
|
|
822
|
-
baseURL;
|
|
823
950
|
constructor(config) {
|
|
824
951
|
super(config);
|
|
952
|
+
this.name = "google";
|
|
825
953
|
this.apiKey = config.apiKey;
|
|
826
954
|
this.baseURL = config.baseURL || "https://generativelanguage.googleapis.com/v1beta";
|
|
827
955
|
}
|
|
@@ -943,9 +1071,11 @@ function getEnv(key) {
|
|
|
943
1071
|
|
|
944
1072
|
// src/ai/providers/factory.ts
|
|
945
1073
|
var ProviderRegistry = class {
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1074
|
+
constructor() {
|
|
1075
|
+
this.providers = /* @__PURE__ */ new Map();
|
|
1076
|
+
this.config = {};
|
|
1077
|
+
this.autoInitialized = false;
|
|
1078
|
+
}
|
|
949
1079
|
/**
|
|
950
1080
|
* Auto-initialize providers from environment variables
|
|
951
1081
|
* This is called lazily when a provider is first requested
|
|
@@ -1369,7 +1499,9 @@ function generateToolId() {
|
|
|
1369
1499
|
return `tool_${Date.now()}_${toolIdCounter++}`;
|
|
1370
1500
|
}
|
|
1371
1501
|
var ToolRegistryClass = class {
|
|
1372
|
-
|
|
1502
|
+
constructor() {
|
|
1503
|
+
this.tools = /* @__PURE__ */ new Map();
|
|
1504
|
+
}
|
|
1373
1505
|
register(id, toolInstance) {
|
|
1374
1506
|
if (this.tools.has(id)) {
|
|
1375
1507
|
agentLogger.debug(`Tool "${id}" is already registered. Overwriting.`);
|
|
@@ -1629,7 +1761,9 @@ function patternToId(pattern) {
|
|
|
1629
1761
|
return pattern.replace(/^\//, "").replace(/\//g, "_").replace(/:/g, "");
|
|
1630
1762
|
}
|
|
1631
1763
|
var ResourceRegistryClass = class {
|
|
1632
|
-
|
|
1764
|
+
constructor() {
|
|
1765
|
+
this.resources = /* @__PURE__ */ new Map();
|
|
1766
|
+
}
|
|
1633
1767
|
/**
|
|
1634
1768
|
* Register a resource
|
|
1635
1769
|
*/
|
|
@@ -1725,7 +1859,9 @@ function interpolateVariables(template, variables) {
|
|
|
1725
1859
|
});
|
|
1726
1860
|
}
|
|
1727
1861
|
var PromptRegistryClass = class {
|
|
1728
|
-
|
|
1862
|
+
constructor() {
|
|
1863
|
+
this.prompts = /* @__PURE__ */ new Map();
|
|
1864
|
+
}
|
|
1729
1865
|
/**
|
|
1730
1866
|
* Register a prompt
|
|
1731
1867
|
*/
|
|
@@ -1856,7 +1992,9 @@ function createWorkflow(config) {
|
|
|
1856
1992
|
};
|
|
1857
1993
|
}
|
|
1858
1994
|
var AgentRegistryClass = class {
|
|
1859
|
-
|
|
1995
|
+
constructor() {
|
|
1996
|
+
this.agents = /* @__PURE__ */ new Map();
|
|
1997
|
+
}
|
|
1860
1998
|
/**
|
|
1861
1999
|
* Register an agent
|
|
1862
2000
|
*/
|
|
@@ -1931,6 +2069,9 @@ var veryfrontConfigSchema = z5.object({
|
|
|
1931
2069
|
}).partial().optional(),
|
|
1932
2070
|
router: z5.enum(["app", "pages"]).optional(),
|
|
1933
2071
|
defaultLayout: z5.string().optional(),
|
|
2072
|
+
layout: z5.string().optional(),
|
|
2073
|
+
provider: z5.string().optional(),
|
|
2074
|
+
app: z5.string().optional(),
|
|
1934
2075
|
theme: z5.object({ colors: z5.record(z5.string()).optional() }).partial().optional(),
|
|
1935
2076
|
build: z5.object({
|
|
1936
2077
|
outDir: z5.string().optional(),
|
|
@@ -2026,6 +2167,8 @@ var veryfrontConfigSchema = z5.object({
|
|
|
2026
2167
|
apiBaseUrl: z5.string().url(),
|
|
2027
2168
|
apiToken: z5.string(),
|
|
2028
2169
|
projectSlug: z5.string(),
|
|
2170
|
+
proxyMode: z5.boolean().optional(),
|
|
2171
|
+
productionMode: z5.boolean().optional(),
|
|
2029
2172
|
cache: z5.object({
|
|
2030
2173
|
enabled: z5.boolean().optional(),
|
|
2031
2174
|
ttl: z5.number().int().positive().optional(),
|
|
@@ -2087,6 +2230,9 @@ function findUnknownTopLevelKeys(input) {
|
|
|
2087
2230
|
"experimental",
|
|
2088
2231
|
"router",
|
|
2089
2232
|
"defaultLayout",
|
|
2233
|
+
"layout",
|
|
2234
|
+
"provider",
|
|
2235
|
+
"app",
|
|
2090
2236
|
"theme",
|
|
2091
2237
|
"build",
|
|
2092
2238
|
"cache",
|
|
@@ -2104,12 +2250,12 @@ function findUnknownTopLevelKeys(input) {
|
|
|
2104
2250
|
}
|
|
2105
2251
|
|
|
2106
2252
|
// src/core/config/loader.ts
|
|
2107
|
-
import { join } from "node:path";
|
|
2253
|
+
import { dirname, join } from "node:path";
|
|
2108
2254
|
|
|
2109
2255
|
// deno.json
|
|
2110
2256
|
var deno_default = {
|
|
2111
2257
|
name: "veryfront",
|
|
2112
|
-
version: "0.0.
|
|
2258
|
+
version: "0.0.74",
|
|
2113
2259
|
nodeModulesDir: "auto",
|
|
2114
2260
|
exclude: [
|
|
2115
2261
|
"npm/",
|
|
@@ -2194,12 +2340,12 @@ var deno_default = {
|
|
|
2194
2340
|
csstype: "https://esm.sh/csstype@3.2.3",
|
|
2195
2341
|
"@types/react": "https://esm.sh/@types/react@18.3.27?deps=csstype@3.2.3",
|
|
2196
2342
|
"@types/react-dom": "https://esm.sh/@types/react-dom@18.3.7?deps=csstype@3.2.3",
|
|
2197
|
-
react: "
|
|
2198
|
-
"react-dom": "
|
|
2199
|
-
"react-dom/server": "
|
|
2200
|
-
"react-dom/client": "
|
|
2201
|
-
"react/jsx-runtime": "
|
|
2202
|
-
"react/jsx-dev-runtime": "
|
|
2343
|
+
react: "npm:react@18.3.1",
|
|
2344
|
+
"react-dom": "npm:react-dom@18.3.1",
|
|
2345
|
+
"react-dom/server": "npm:react-dom@18.3.1/server.node",
|
|
2346
|
+
"react-dom/client": "npm:react-dom@18.3.1/client",
|
|
2347
|
+
"react/jsx-runtime": "npm:react@18.3.1/jsx-runtime",
|
|
2348
|
+
"react/jsx-dev-runtime": "npm:react@18.3.1/jsx-dev-runtime",
|
|
2203
2349
|
"@mdx-js/mdx": "npm:@mdx-js/mdx@3.0.0",
|
|
2204
2350
|
"@mdx-js/react": "npm:@mdx-js/react@3.0.0",
|
|
2205
2351
|
"unist-util-visit": "npm:unist-util-visit@5.0.0",
|
|
@@ -2209,27 +2355,36 @@ var deno_default = {
|
|
|
2209
2355
|
"remark-frontmatter": "npm:remark-frontmatter@5.0.0",
|
|
2210
2356
|
"rehype-highlight": "npm:rehype-highlight@7.0.2",
|
|
2211
2357
|
"rehype-slug": "npm:rehype-slug@6.0.0",
|
|
2212
|
-
esbuild: "
|
|
2213
|
-
"esbuild/mod.js": "
|
|
2358
|
+
esbuild: "npm:esbuild@0.20.2",
|
|
2359
|
+
"esbuild/mod.js": "npm:esbuild@0.20.2",
|
|
2214
2360
|
"es-module-lexer": "npm:es-module-lexer@1.5.0",
|
|
2215
|
-
zod: "npm:zod@3.
|
|
2361
|
+
zod: "npm:zod@3.25.76",
|
|
2216
2362
|
"mime-types": "npm:mime-types@2.1.35",
|
|
2217
2363
|
mdast: "npm:@types/mdast@4.0.3",
|
|
2218
2364
|
hast: "npm:@types/hast@3.0.3",
|
|
2219
2365
|
unist: "npm:@types/unist@3.0.2",
|
|
2220
2366
|
unified: "npm:unified@11.0.5",
|
|
2221
|
-
ai: "
|
|
2222
|
-
"ai/react": "
|
|
2223
|
-
"@ai-sdk/react": "
|
|
2367
|
+
ai: "npm:ai@5.0.76",
|
|
2368
|
+
"ai/react": "npm:@ai-sdk/react@2.0.1",
|
|
2369
|
+
"@ai-sdk/react": "npm:@ai-sdk/react@2.0.1",
|
|
2224
2370
|
"@ai-sdk/openai": "https://esm.sh/@ai-sdk/openai@2.0.1",
|
|
2225
2371
|
"@ai-sdk/anthropic": "https://esm.sh/@ai-sdk/anthropic@2.0.1",
|
|
2226
2372
|
unocss: "https://esm.sh/unocss@0.59.0",
|
|
2227
2373
|
"@unocss/core": "https://esm.sh/@unocss/core@0.59.0",
|
|
2228
2374
|
"@unocss/preset-wind": "https://esm.sh/@unocss/preset-wind@0.59.0",
|
|
2375
|
+
"next-themes": "npm:next-themes@0.3.0",
|
|
2229
2376
|
redis: "npm:redis",
|
|
2230
2377
|
pg: "npm:pg",
|
|
2231
2378
|
"@opentelemetry/api": "npm:@opentelemetry/api@1",
|
|
2232
|
-
"@opentelemetry/core": "npm:@opentelemetry/core@1"
|
|
2379
|
+
"@opentelemetry/core": "npm:@opentelemetry/core@1",
|
|
2380
|
+
"@opentelemetry/sdk-trace-base": "npm:@opentelemetry/sdk-trace-base@1",
|
|
2381
|
+
"@opentelemetry/exporter-trace-otlp-http": "npm:@opentelemetry/exporter-trace-otlp-http@0.57",
|
|
2382
|
+
"@opentelemetry/resources": "npm:@opentelemetry/resources@1",
|
|
2383
|
+
"@opentelemetry/semantic-conventions": "npm:@opentelemetry/semantic-conventions@1",
|
|
2384
|
+
"@babel/parser": "npm:@babel/parser@7.26.3",
|
|
2385
|
+
"@babel/traverse": "npm:@babel/traverse@7.26.3",
|
|
2386
|
+
"@babel/generator": "npm:@babel/generator@7.26.3",
|
|
2387
|
+
"@babel/types": "npm:@babel/types@7.26.3"
|
|
2233
2388
|
},
|
|
2234
2389
|
compilerOptions: {
|
|
2235
2390
|
jsx: "react-jsx",
|
|
@@ -2237,7 +2392,7 @@ var deno_default = {
|
|
|
2237
2392
|
strict: true,
|
|
2238
2393
|
noImplicitAny: true,
|
|
2239
2394
|
noUncheckedIndexedAccess: true,
|
|
2240
|
-
types: [],
|
|
2395
|
+
types: ["npm:@types/react@18"],
|
|
2241
2396
|
lib: [
|
|
2242
2397
|
"deno.window",
|
|
2243
2398
|
"dom",
|
|
@@ -2252,9 +2407,9 @@ var deno_default = {
|
|
|
2252
2407
|
build: "deno compile --allow-all --output ../../bin/veryfront src/cli/main.ts",
|
|
2253
2408
|
"build:npm": "deno run -A scripts/build-npm.ts",
|
|
2254
2409
|
release: "deno run -A scripts/release.ts",
|
|
2255
|
-
test: "DENO_JOBS=1 deno test --parallel --fail-fast --allow-all --unstable-worker-options --unstable-net",
|
|
2256
|
-
"test:unit": "DENO_JOBS=1 deno test --parallel --allow-all --v8-flags=--max-old-space-size=8192 --ignore=tests --unstable-worker-options --unstable-net",
|
|
2257
|
-
"test:integration": "DENO_JOBS=1 deno test --parallel --fail-fast --allow-all tests --unstable-worker-options --unstable-net",
|
|
2410
|
+
test: "VF_DISABLE_LRU_INTERVAL=1 DENO_JOBS=1 deno test --parallel --fail-fast --allow-all --unstable-worker-options --unstable-net",
|
|
2411
|
+
"test:unit": "VF_DISABLE_LRU_INTERVAL=1 DENO_JOBS=1 deno test --parallel --allow-all --v8-flags=--max-old-space-size=8192 --ignore=tests,src/ai/workflow/__tests__ --unstable-worker-options --unstable-net",
|
|
2412
|
+
"test:integration": "VF_DISABLE_LRU_INTERVAL=1 DENO_JOBS=1 deno test --parallel --fail-fast --allow-all tests --unstable-worker-options --unstable-net",
|
|
2258
2413
|
"test:coverage": "rm -rf coverage && DENO_JOBS=1 deno test --parallel --fail-fast --allow-all --coverage=coverage --unstable-worker-options --unstable-net || exit 1",
|
|
2259
2414
|
"test:coverage:unit": "rm -rf coverage && DENO_JOBS=1 deno test --parallel --fail-fast --allow-all --coverage=coverage --ignore=tests --unstable-worker-options --unstable-net || exit 1",
|
|
2260
2415
|
"test:coverage:integration": "rm -rf coverage && DENO_JOBS=1 deno test --parallel --fail-fast --allow-all --coverage=coverage tests --unstable-worker-options --unstable-net || exit 1",
|
|
@@ -2316,6 +2471,7 @@ var deno_default = {
|
|
|
2316
2471
|
|
|
2317
2472
|
// src/core/utils/version.ts
|
|
2318
2473
|
var VERSION = getEnv("VERYFRONT_VERSION") || (typeof deno_default.version === "string" ? deno_default.version : "0.0.0");
|
|
2474
|
+
var SERVER_START_TIME = Date.now();
|
|
2319
2475
|
|
|
2320
2476
|
// src/core/utils/constants/cdn.ts
|
|
2321
2477
|
var ESM_CDN_BASE = "https://esm.sh";
|
|
@@ -2431,6 +2587,166 @@ var DEV_SERVER_ENDPOINTS = {
|
|
|
2431
2587
|
ERROR_OVERLAY: INTERNAL_ENDPOINTS.ERROR_OVERLAY
|
|
2432
2588
|
};
|
|
2433
2589
|
|
|
2590
|
+
// src/platform/compat/fs.ts
|
|
2591
|
+
var NodeFileSystem = class {
|
|
2592
|
+
constructor() {
|
|
2593
|
+
this.fs = null;
|
|
2594
|
+
this.os = null;
|
|
2595
|
+
this.path = null;
|
|
2596
|
+
this.initialized = false;
|
|
2597
|
+
}
|
|
2598
|
+
async ensureInitialized() {
|
|
2599
|
+
if (this.initialized)
|
|
2600
|
+
return;
|
|
2601
|
+
if (!isNode) {
|
|
2602
|
+
throw toError(createError({
|
|
2603
|
+
type: "not_supported",
|
|
2604
|
+
message: "Node.js fs modules not available",
|
|
2605
|
+
feature: "Node.js"
|
|
2606
|
+
}));
|
|
2607
|
+
}
|
|
2608
|
+
const [fsModule, osModule, pathModule] = await Promise.all([
|
|
2609
|
+
import("node:fs/promises"),
|
|
2610
|
+
import("node:os"),
|
|
2611
|
+
import("node:path")
|
|
2612
|
+
]);
|
|
2613
|
+
this.fs = fsModule;
|
|
2614
|
+
this.os = osModule;
|
|
2615
|
+
this.path = pathModule;
|
|
2616
|
+
this.initialized = true;
|
|
2617
|
+
}
|
|
2618
|
+
async readTextFile(path) {
|
|
2619
|
+
await this.ensureInitialized();
|
|
2620
|
+
return await this.fs.readFile(path, { encoding: "utf8" });
|
|
2621
|
+
}
|
|
2622
|
+
async readFile(path) {
|
|
2623
|
+
await this.ensureInitialized();
|
|
2624
|
+
return await this.fs.readFile(path);
|
|
2625
|
+
}
|
|
2626
|
+
async writeTextFile(path, data) {
|
|
2627
|
+
await this.ensureInitialized();
|
|
2628
|
+
await this.fs.writeFile(path, data, { encoding: "utf8" });
|
|
2629
|
+
}
|
|
2630
|
+
async writeFile(path, data) {
|
|
2631
|
+
await this.ensureInitialized();
|
|
2632
|
+
await this.fs.writeFile(path, data);
|
|
2633
|
+
}
|
|
2634
|
+
async exists(path) {
|
|
2635
|
+
await this.ensureInitialized();
|
|
2636
|
+
try {
|
|
2637
|
+
await this.fs.access(path);
|
|
2638
|
+
return true;
|
|
2639
|
+
} catch (error) {
|
|
2640
|
+
if (error.code === "ENOENT") {
|
|
2641
|
+
return false;
|
|
2642
|
+
}
|
|
2643
|
+
throw error;
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
async stat(path) {
|
|
2647
|
+
await this.ensureInitialized();
|
|
2648
|
+
const stat = await this.fs.stat(path);
|
|
2649
|
+
return {
|
|
2650
|
+
isFile: stat.isFile(),
|
|
2651
|
+
isDirectory: stat.isDirectory(),
|
|
2652
|
+
isSymlink: stat.isSymbolicLink(),
|
|
2653
|
+
size: stat.size,
|
|
2654
|
+
mtime: stat.mtime
|
|
2655
|
+
};
|
|
2656
|
+
}
|
|
2657
|
+
async mkdir(path, options) {
|
|
2658
|
+
await this.ensureInitialized();
|
|
2659
|
+
await this.fs.mkdir(path, { recursive: options?.recursive ?? false });
|
|
2660
|
+
}
|
|
2661
|
+
async *readDir(path) {
|
|
2662
|
+
await this.ensureInitialized();
|
|
2663
|
+
const entries = await this.fs.readdir(path, { withFileTypes: true });
|
|
2664
|
+
for (const entry of entries) {
|
|
2665
|
+
yield {
|
|
2666
|
+
name: entry.name,
|
|
2667
|
+
isFile: entry.isFile(),
|
|
2668
|
+
isDirectory: entry.isDirectory()
|
|
2669
|
+
};
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
async remove(path, options) {
|
|
2673
|
+
await this.ensureInitialized();
|
|
2674
|
+
await this.fs.rm(path, {
|
|
2675
|
+
recursive: options?.recursive ?? false,
|
|
2676
|
+
force: options?.recursive ?? false
|
|
2677
|
+
});
|
|
2678
|
+
}
|
|
2679
|
+
async makeTempDir(options) {
|
|
2680
|
+
await this.ensureInitialized();
|
|
2681
|
+
const tempDir = this.path.join(
|
|
2682
|
+
this.os.tmpdir(),
|
|
2683
|
+
`${options?.prefix ?? "tmp-"}${Math.random().toString(36).substring(2, 8)}`
|
|
2684
|
+
);
|
|
2685
|
+
await this.fs.mkdir(tempDir, { recursive: true });
|
|
2686
|
+
return tempDir;
|
|
2687
|
+
}
|
|
2688
|
+
};
|
|
2689
|
+
var DenoFileSystem = class {
|
|
2690
|
+
async readTextFile(path) {
|
|
2691
|
+
return await Deno.readTextFile(path);
|
|
2692
|
+
}
|
|
2693
|
+
async readFile(path) {
|
|
2694
|
+
return await Deno.readFile(path);
|
|
2695
|
+
}
|
|
2696
|
+
async writeTextFile(path, data) {
|
|
2697
|
+
await Deno.writeTextFile(path, data);
|
|
2698
|
+
}
|
|
2699
|
+
async writeFile(path, data) {
|
|
2700
|
+
await Deno.writeFile(path, data);
|
|
2701
|
+
}
|
|
2702
|
+
async exists(path) {
|
|
2703
|
+
try {
|
|
2704
|
+
await Deno.stat(path);
|
|
2705
|
+
return true;
|
|
2706
|
+
} catch (error) {
|
|
2707
|
+
if (error instanceof Deno.errors.NotFound) {
|
|
2708
|
+
return false;
|
|
2709
|
+
}
|
|
2710
|
+
throw error;
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
async stat(path) {
|
|
2714
|
+
const stat = await Deno.stat(path);
|
|
2715
|
+
return {
|
|
2716
|
+
isFile: stat.isFile,
|
|
2717
|
+
isDirectory: stat.isDirectory,
|
|
2718
|
+
isSymlink: stat.isSymlink,
|
|
2719
|
+
size: stat.size,
|
|
2720
|
+
mtime: stat.mtime
|
|
2721
|
+
};
|
|
2722
|
+
}
|
|
2723
|
+
async mkdir(path, options) {
|
|
2724
|
+
await Deno.mkdir(path, { recursive: options?.recursive ?? false });
|
|
2725
|
+
}
|
|
2726
|
+
async *readDir(path) {
|
|
2727
|
+
for await (const entry of Deno.readDir(path)) {
|
|
2728
|
+
yield {
|
|
2729
|
+
name: entry.name,
|
|
2730
|
+
isFile: entry.isFile,
|
|
2731
|
+
isDirectory: entry.isDirectory
|
|
2732
|
+
};
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
async remove(path, options) {
|
|
2736
|
+
await Deno.remove(path, { recursive: options?.recursive ?? false });
|
|
2737
|
+
}
|
|
2738
|
+
async makeTempDir(options) {
|
|
2739
|
+
return await Deno.makeTempDir({ prefix: options?.prefix });
|
|
2740
|
+
}
|
|
2741
|
+
};
|
|
2742
|
+
function createFileSystem() {
|
|
2743
|
+
if (isDeno) {
|
|
2744
|
+
return new DenoFileSystem();
|
|
2745
|
+
} else {
|
|
2746
|
+
return new NodeFileSystem();
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2434
2750
|
// src/core/config/loader.ts
|
|
2435
2751
|
function getDefaultImportMapForConfig() {
|
|
2436
2752
|
return { imports: getReactImportMap(REACT_DEFAULT_VERSION) };
|
|
@@ -2567,7 +2883,62 @@ var ConfigValidationError = class extends Error {
|
|
|
2567
2883
|
this.name = "ConfigValidationError";
|
|
2568
2884
|
}
|
|
2569
2885
|
};
|
|
2570
|
-
|
|
2886
|
+
function isVirtualFilesystem(adapter) {
|
|
2887
|
+
const wrappedAdapter = adapter?.fs?.fsAdapter;
|
|
2888
|
+
const adapterName = wrappedAdapter?.constructor?.name;
|
|
2889
|
+
return adapterName === "VeryfrontFSAdapter";
|
|
2890
|
+
}
|
|
2891
|
+
async function loadConfigFromVirtualFS(configPath, projectDir, adapter) {
|
|
2892
|
+
const fs2 = createFileSystem();
|
|
2893
|
+
const content = await adapter.fs.readFile(configPath);
|
|
2894
|
+
const source = typeof content === "string" ? content : new TextDecoder().decode(content);
|
|
2895
|
+
serverLogger.debug(`[CONFIG] Loading config from virtual FS: ${configPath}`);
|
|
2896
|
+
const isTsx = configPath.endsWith(".tsx");
|
|
2897
|
+
const loader = isTsx ? "tsx" : configPath.endsWith(".ts") ? "ts" : "js";
|
|
2898
|
+
const { build } = await import("esbuild");
|
|
2899
|
+
const result = await build({
|
|
2900
|
+
bundle: false,
|
|
2901
|
+
// Config files shouldn't need bundling
|
|
2902
|
+
write: false,
|
|
2903
|
+
format: "esm",
|
|
2904
|
+
platform: "neutral",
|
|
2905
|
+
target: "es2022",
|
|
2906
|
+
stdin: {
|
|
2907
|
+
contents: source,
|
|
2908
|
+
loader,
|
|
2909
|
+
resolveDir: dirname(configPath),
|
|
2910
|
+
sourcefile: configPath
|
|
2911
|
+
}
|
|
2912
|
+
});
|
|
2913
|
+
if (result.errors && result.errors.length > 0) {
|
|
2914
|
+
const first = result.errors[0]?.text || "unknown error";
|
|
2915
|
+
throw new ConfigValidationError(`Failed to transpile config: ${first}`);
|
|
2916
|
+
}
|
|
2917
|
+
const js = result.outputFiles?.[0]?.text ?? "export default {}";
|
|
2918
|
+
const tempDir = await fs2.makeTempDir({ prefix: "vf-config-" });
|
|
2919
|
+
const tempFile = join(tempDir, "config.mjs");
|
|
2920
|
+
try {
|
|
2921
|
+
await fs2.writeTextFile(tempFile, js);
|
|
2922
|
+
const configModule = await import(`file://${tempFile}?v=${Date.now()}`);
|
|
2923
|
+
const userConfig = configModule.default || configModule;
|
|
2924
|
+
if (userConfig === null || typeof userConfig !== "object" || Array.isArray(userConfig)) {
|
|
2925
|
+
throw new ConfigValidationError(
|
|
2926
|
+
`Expected object, received ${userConfig === null ? "null" : typeof userConfig}`
|
|
2927
|
+
);
|
|
2928
|
+
}
|
|
2929
|
+
validateCorsConfig(userConfig);
|
|
2930
|
+
validateConfigShape(userConfig);
|
|
2931
|
+
const merged = mergeConfigs(userConfig);
|
|
2932
|
+
configCacheByProject.set(projectDir, { revision: cacheRevision, config: merged });
|
|
2933
|
+
return merged;
|
|
2934
|
+
} finally {
|
|
2935
|
+
await fs2.remove(tempDir, { recursive: true });
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
async function loadAndMergeConfig(configPath, projectDir, adapter) {
|
|
2939
|
+
if (isVirtualFilesystem(adapter)) {
|
|
2940
|
+
return loadConfigFromVirtualFS(configPath, projectDir, adapter);
|
|
2941
|
+
}
|
|
2571
2942
|
try {
|
|
2572
2943
|
const configUrl = `file://${configPath}?t=${Date.now()}-${crypto.randomUUID()}`;
|
|
2573
2944
|
const configModule = await import(configUrl);
|
|
@@ -2603,7 +2974,7 @@ async function getConfig(projectDir, adapter) {
|
|
|
2603
2974
|
if (!exists)
|
|
2604
2975
|
continue;
|
|
2605
2976
|
try {
|
|
2606
|
-
const merged = await loadAndMergeConfig(configPath, projectDir);
|
|
2977
|
+
const merged = await loadAndMergeConfig(configPath, projectDir, adapter);
|
|
2607
2978
|
if (merged)
|
|
2608
2979
|
return merged;
|
|
2609
2980
|
} catch (error) {
|
|
@@ -2672,266 +3043,108 @@ function createMockAdapter() {
|
|
|
2672
3043
|
throw toError(createError({
|
|
2673
3044
|
type: "file",
|
|
2674
3045
|
message: `File not found: ${path}`
|
|
2675
|
-
}));
|
|
2676
|
-
}
|
|
2677
|
-
return Promise.resolve(new TextEncoder().encode(content));
|
|
2678
|
-
},
|
|
2679
|
-
writeFile: (path, content) => {
|
|
2680
|
-
files.set(path, content);
|
|
2681
|
-
return Promise.resolve();
|
|
2682
|
-
},
|
|
2683
|
-
exists: (path) => {
|
|
2684
|
-
if (files.has(path))
|
|
2685
|
-
return Promise.resolve(true);
|
|
2686
|
-
if (directories.has(path))
|
|
2687
|
-
return Promise.resolve(true);
|
|
2688
|
-
for (const filePath of files.keys()) {
|
|
2689
|
-
if (filePath.startsWith(path + "/"))
|
|
2690
|
-
return Promise.resolve(true);
|
|
2691
|
-
}
|
|
2692
|
-
return Promise.resolve(false);
|
|
2693
|
-
},
|
|
2694
|
-
readDir: async function* (path) {
|
|
2695
|
-
const entries = /* @__PURE__ */ new Map();
|
|
2696
|
-
for (const filePath of files.keys()) {
|
|
2697
|
-
if (filePath.startsWith(path + "/")) {
|
|
2698
|
-
const relativePath = filePath.slice(path.length + 1);
|
|
2699
|
-
const parts = relativePath.split("/");
|
|
2700
|
-
const name = parts[0];
|
|
2701
|
-
if (!entries.has(name)) {
|
|
2702
|
-
entries.set(name, {
|
|
2703
|
-
isFile: parts.length === 1,
|
|
2704
|
-
isDirectory: parts.length > 1
|
|
2705
|
-
});
|
|
2706
|
-
}
|
|
2707
|
-
}
|
|
2708
|
-
}
|
|
2709
|
-
for (const [name, meta] of entries.entries()) {
|
|
2710
|
-
yield { name, ...meta, isSymlink: false };
|
|
2711
|
-
}
|
|
2712
|
-
},
|
|
2713
|
-
stat: (path) => {
|
|
2714
|
-
if (files.has(path)) {
|
|
2715
|
-
const content = files.get(path);
|
|
2716
|
-
return Promise.resolve({
|
|
2717
|
-
size: content.length,
|
|
2718
|
-
isFile: true,
|
|
2719
|
-
isDirectory: false,
|
|
2720
|
-
isSymlink: false,
|
|
2721
|
-
mtime: /* @__PURE__ */ new Date()
|
|
2722
|
-
});
|
|
2723
|
-
}
|
|
2724
|
-
if (directories.has(path)) {
|
|
2725
|
-
return Promise.resolve({
|
|
2726
|
-
size: 0,
|
|
2727
|
-
isFile: false,
|
|
2728
|
-
isDirectory: true,
|
|
2729
|
-
isSymlink: false,
|
|
2730
|
-
mtime: /* @__PURE__ */ new Date()
|
|
2731
|
-
});
|
|
2732
|
-
}
|
|
2733
|
-
for (const filePath of files.keys()) {
|
|
2734
|
-
if (filePath.startsWith(path + "/")) {
|
|
2735
|
-
return Promise.resolve({
|
|
2736
|
-
size: 0,
|
|
2737
|
-
isFile: false,
|
|
2738
|
-
isDirectory: true,
|
|
2739
|
-
isSymlink: false,
|
|
2740
|
-
mtime: /* @__PURE__ */ new Date()
|
|
2741
|
-
});
|
|
2742
|
-
}
|
|
2743
|
-
}
|
|
2744
|
-
return Promise.reject(new Error(`Path not found: ${path}`));
|
|
2745
|
-
},
|
|
2746
|
-
mkdir: (_path) => Promise.resolve(),
|
|
2747
|
-
remove: (_path) => Promise.resolve(),
|
|
2748
|
-
makeTempDir: (prefix) => Promise.resolve(`/tmp/${prefix}-${Math.random().toString(36).slice(2)}`),
|
|
2749
|
-
watch: () => ({
|
|
2750
|
-
async *[Symbol.asyncIterator]() {
|
|
2751
|
-
yield { kind: "any", paths: [] };
|
|
2752
|
-
},
|
|
2753
|
-
close: () => {
|
|
2754
|
-
}
|
|
2755
|
-
})
|
|
2756
|
-
},
|
|
2757
|
-
env: {
|
|
2758
|
-
get: (key) => envVars.get(key),
|
|
2759
|
-
set: (key, value) => envVars.set(key, value),
|
|
2760
|
-
toObject: () => Object.fromEntries(envVars)
|
|
2761
|
-
},
|
|
2762
|
-
server: {
|
|
2763
|
-
upgradeWebSocket: (_request) => {
|
|
2764
|
-
throw new Error(
|
|
2765
|
-
"WebSocket upgrade not available in mock adapter. The mock adapter is designed for unit testing filesystem and environment operations. For WebSocket testing, use integration tests with the actual Deno/Node/Bun adapter, or mock the WebSocket behavior at a higher level in your tests."
|
|
2766
|
-
);
|
|
2767
|
-
}
|
|
2768
|
-
},
|
|
2769
|
-
features: {
|
|
2770
|
-
websocket: false,
|
|
2771
|
-
http2: false,
|
|
2772
|
-
workers: false,
|
|
2773
|
-
jsx: false,
|
|
2774
|
-
typescript: false
|
|
2775
|
-
}
|
|
2776
|
-
};
|
|
2777
|
-
}
|
|
2778
|
-
|
|
2779
|
-
// src/platform/compat/fs.ts
|
|
2780
|
-
var NodeFileSystem = class {
|
|
2781
|
-
fs = null;
|
|
2782
|
-
os = null;
|
|
2783
|
-
path = null;
|
|
2784
|
-
initialized = false;
|
|
2785
|
-
async ensureInitialized() {
|
|
2786
|
-
if (this.initialized)
|
|
2787
|
-
return;
|
|
2788
|
-
if (!isNode) {
|
|
2789
|
-
throw toError(createError({
|
|
2790
|
-
type: "not_supported",
|
|
2791
|
-
message: "Node.js fs modules not available",
|
|
2792
|
-
feature: "Node.js"
|
|
2793
|
-
}));
|
|
2794
|
-
}
|
|
2795
|
-
const [fsModule, osModule, pathModule] = await Promise.all([
|
|
2796
|
-
import("node:fs/promises"),
|
|
2797
|
-
import("node:os"),
|
|
2798
|
-
import("node:path")
|
|
2799
|
-
]);
|
|
2800
|
-
this.fs = fsModule;
|
|
2801
|
-
this.os = osModule;
|
|
2802
|
-
this.path = pathModule;
|
|
2803
|
-
this.initialized = true;
|
|
2804
|
-
}
|
|
2805
|
-
async readTextFile(path) {
|
|
2806
|
-
await this.ensureInitialized();
|
|
2807
|
-
return await this.fs.readFile(path, { encoding: "utf8" });
|
|
2808
|
-
}
|
|
2809
|
-
async readFile(path) {
|
|
2810
|
-
await this.ensureInitialized();
|
|
2811
|
-
return await this.fs.readFile(path);
|
|
2812
|
-
}
|
|
2813
|
-
async writeTextFile(path, data) {
|
|
2814
|
-
await this.ensureInitialized();
|
|
2815
|
-
await this.fs.writeFile(path, data, { encoding: "utf8" });
|
|
2816
|
-
}
|
|
2817
|
-
async writeFile(path, data) {
|
|
2818
|
-
await this.ensureInitialized();
|
|
2819
|
-
await this.fs.writeFile(path, data);
|
|
2820
|
-
}
|
|
2821
|
-
async exists(path) {
|
|
2822
|
-
await this.ensureInitialized();
|
|
2823
|
-
try {
|
|
2824
|
-
await this.fs.access(path);
|
|
2825
|
-
return true;
|
|
2826
|
-
} catch (error) {
|
|
2827
|
-
if (error.code === "ENOENT") {
|
|
2828
|
-
return false;
|
|
2829
|
-
}
|
|
2830
|
-
throw error;
|
|
2831
|
-
}
|
|
2832
|
-
}
|
|
2833
|
-
async stat(path) {
|
|
2834
|
-
await this.ensureInitialized();
|
|
2835
|
-
const stat = await this.fs.stat(path);
|
|
2836
|
-
return {
|
|
2837
|
-
isFile: stat.isFile(),
|
|
2838
|
-
isDirectory: stat.isDirectory(),
|
|
2839
|
-
isSymlink: stat.isSymbolicLink(),
|
|
2840
|
-
size: stat.size,
|
|
2841
|
-
mtime: stat.mtime
|
|
2842
|
-
};
|
|
2843
|
-
}
|
|
2844
|
-
async mkdir(path, options) {
|
|
2845
|
-
await this.ensureInitialized();
|
|
2846
|
-
await this.fs.mkdir(path, { recursive: options?.recursive ?? false });
|
|
2847
|
-
}
|
|
2848
|
-
async *readDir(path) {
|
|
2849
|
-
await this.ensureInitialized();
|
|
2850
|
-
const entries = await this.fs.readdir(path, { withFileTypes: true });
|
|
2851
|
-
for (const entry of entries) {
|
|
2852
|
-
yield {
|
|
2853
|
-
name: entry.name,
|
|
2854
|
-
isFile: entry.isFile(),
|
|
2855
|
-
isDirectory: entry.isDirectory()
|
|
2856
|
-
};
|
|
2857
|
-
}
|
|
2858
|
-
}
|
|
2859
|
-
async remove(path, options) {
|
|
2860
|
-
await this.ensureInitialized();
|
|
2861
|
-
await this.fs.rm(path, {
|
|
2862
|
-
recursive: options?.recursive ?? false,
|
|
2863
|
-
force: options?.recursive ?? false
|
|
2864
|
-
});
|
|
2865
|
-
}
|
|
2866
|
-
async makeTempDir(options) {
|
|
2867
|
-
await this.ensureInitialized();
|
|
2868
|
-
const tempDir = this.path.join(
|
|
2869
|
-
this.os.tmpdir(),
|
|
2870
|
-
`${options?.prefix ?? "tmp-"}${Math.random().toString(36).substring(2, 8)}`
|
|
2871
|
-
);
|
|
2872
|
-
await this.fs.mkdir(tempDir, { recursive: true });
|
|
2873
|
-
return tempDir;
|
|
2874
|
-
}
|
|
2875
|
-
};
|
|
2876
|
-
var DenoFileSystem = class {
|
|
2877
|
-
async readTextFile(path) {
|
|
2878
|
-
return await Deno.readTextFile(path);
|
|
2879
|
-
}
|
|
2880
|
-
async readFile(path) {
|
|
2881
|
-
return await Deno.readFile(path);
|
|
2882
|
-
}
|
|
2883
|
-
async writeTextFile(path, data) {
|
|
2884
|
-
await Deno.writeTextFile(path, data);
|
|
2885
|
-
}
|
|
2886
|
-
async writeFile(path, data) {
|
|
2887
|
-
await Deno.writeFile(path, data);
|
|
2888
|
-
}
|
|
2889
|
-
async exists(path) {
|
|
2890
|
-
try {
|
|
2891
|
-
await Deno.stat(path);
|
|
2892
|
-
return true;
|
|
2893
|
-
} catch (error) {
|
|
2894
|
-
if (error instanceof Deno.errors.NotFound) {
|
|
2895
|
-
return false;
|
|
3046
|
+
}));
|
|
3047
|
+
}
|
|
3048
|
+
return Promise.resolve(new TextEncoder().encode(content));
|
|
3049
|
+
},
|
|
3050
|
+
writeFile: (path, content) => {
|
|
3051
|
+
files.set(path, content);
|
|
3052
|
+
return Promise.resolve();
|
|
3053
|
+
},
|
|
3054
|
+
exists: (path) => {
|
|
3055
|
+
if (files.has(path))
|
|
3056
|
+
return Promise.resolve(true);
|
|
3057
|
+
if (directories.has(path))
|
|
3058
|
+
return Promise.resolve(true);
|
|
3059
|
+
for (const filePath of files.keys()) {
|
|
3060
|
+
if (filePath.startsWith(path + "/"))
|
|
3061
|
+
return Promise.resolve(true);
|
|
3062
|
+
}
|
|
3063
|
+
return Promise.resolve(false);
|
|
3064
|
+
},
|
|
3065
|
+
readDir: async function* (path) {
|
|
3066
|
+
const entries = /* @__PURE__ */ new Map();
|
|
3067
|
+
for (const filePath of files.keys()) {
|
|
3068
|
+
if (filePath.startsWith(path + "/")) {
|
|
3069
|
+
const relativePath = filePath.slice(path.length + 1);
|
|
3070
|
+
const parts = relativePath.split("/");
|
|
3071
|
+
const name = parts[0];
|
|
3072
|
+
if (!entries.has(name)) {
|
|
3073
|
+
entries.set(name, {
|
|
3074
|
+
isFile: parts.length === 1,
|
|
3075
|
+
isDirectory: parts.length > 1
|
|
3076
|
+
});
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
for (const [name, meta] of entries.entries()) {
|
|
3081
|
+
yield { name, ...meta, isSymlink: false };
|
|
3082
|
+
}
|
|
3083
|
+
},
|
|
3084
|
+
stat: (path) => {
|
|
3085
|
+
if (files.has(path)) {
|
|
3086
|
+
const content = files.get(path);
|
|
3087
|
+
return Promise.resolve({
|
|
3088
|
+
size: content.length,
|
|
3089
|
+
isFile: true,
|
|
3090
|
+
isDirectory: false,
|
|
3091
|
+
isSymlink: false,
|
|
3092
|
+
mtime: /* @__PURE__ */ new Date()
|
|
3093
|
+
});
|
|
3094
|
+
}
|
|
3095
|
+
if (directories.has(path)) {
|
|
3096
|
+
return Promise.resolve({
|
|
3097
|
+
size: 0,
|
|
3098
|
+
isFile: false,
|
|
3099
|
+
isDirectory: true,
|
|
3100
|
+
isSymlink: false,
|
|
3101
|
+
mtime: /* @__PURE__ */ new Date()
|
|
3102
|
+
});
|
|
3103
|
+
}
|
|
3104
|
+
for (const filePath of files.keys()) {
|
|
3105
|
+
if (filePath.startsWith(path + "/")) {
|
|
3106
|
+
return Promise.resolve({
|
|
3107
|
+
size: 0,
|
|
3108
|
+
isFile: false,
|
|
3109
|
+
isDirectory: true,
|
|
3110
|
+
isSymlink: false,
|
|
3111
|
+
mtime: /* @__PURE__ */ new Date()
|
|
3112
|
+
});
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
return Promise.reject(new Error(`Path not found: ${path}`));
|
|
3116
|
+
},
|
|
3117
|
+
mkdir: (_path) => Promise.resolve(),
|
|
3118
|
+
remove: (_path) => Promise.resolve(),
|
|
3119
|
+
makeTempDir: (prefix) => Promise.resolve(`/tmp/${prefix}-${Math.random().toString(36).slice(2)}`),
|
|
3120
|
+
watch: () => ({
|
|
3121
|
+
async *[Symbol.asyncIterator]() {
|
|
3122
|
+
yield { kind: "any", paths: [] };
|
|
3123
|
+
},
|
|
3124
|
+
close: () => {
|
|
3125
|
+
}
|
|
3126
|
+
})
|
|
3127
|
+
},
|
|
3128
|
+
env: {
|
|
3129
|
+
get: (key) => envVars.get(key),
|
|
3130
|
+
set: (key, value) => envVars.set(key, value),
|
|
3131
|
+
toObject: () => Object.fromEntries(envVars)
|
|
3132
|
+
},
|
|
3133
|
+
server: {
|
|
3134
|
+
upgradeWebSocket: (_request) => {
|
|
3135
|
+
throw new Error(
|
|
3136
|
+
"WebSocket upgrade not available in mock adapter. The mock adapter is designed for unit testing filesystem and environment operations. For WebSocket testing, use integration tests with the actual Deno/Node/Bun adapter, or mock the WebSocket behavior at a higher level in your tests."
|
|
3137
|
+
);
|
|
2896
3138
|
}
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
isDirectory: stat.isDirectory,
|
|
2905
|
-
isSymlink: stat.isSymlink,
|
|
2906
|
-
size: stat.size,
|
|
2907
|
-
mtime: stat.mtime
|
|
2908
|
-
};
|
|
2909
|
-
}
|
|
2910
|
-
async mkdir(path, options) {
|
|
2911
|
-
await Deno.mkdir(path, { recursive: options?.recursive ?? false });
|
|
2912
|
-
}
|
|
2913
|
-
async *readDir(path) {
|
|
2914
|
-
for await (const entry of Deno.readDir(path)) {
|
|
2915
|
-
yield {
|
|
2916
|
-
name: entry.name,
|
|
2917
|
-
isFile: entry.isFile,
|
|
2918
|
-
isDirectory: entry.isDirectory
|
|
2919
|
-
};
|
|
3139
|
+
},
|
|
3140
|
+
features: {
|
|
3141
|
+
websocket: false,
|
|
3142
|
+
http2: false,
|
|
3143
|
+
workers: false,
|
|
3144
|
+
jsx: false,
|
|
3145
|
+
typescript: false
|
|
2920
3146
|
}
|
|
2921
|
-
}
|
|
2922
|
-
async remove(path, options) {
|
|
2923
|
-
await Deno.remove(path, { recursive: options?.recursive ?? false });
|
|
2924
|
-
}
|
|
2925
|
-
async makeTempDir(options) {
|
|
2926
|
-
return await Deno.makeTempDir({ prefix: options?.prefix });
|
|
2927
|
-
}
|
|
2928
|
-
};
|
|
2929
|
-
function createFileSystem() {
|
|
2930
|
-
if (isDeno) {
|
|
2931
|
-
return new DenoFileSystem();
|
|
2932
|
-
} else {
|
|
2933
|
-
return new NodeFileSystem();
|
|
2934
|
-
}
|
|
3147
|
+
};
|
|
2935
3148
|
}
|
|
2936
3149
|
|
|
2937
3150
|
// src/platform/compat/path-helper.ts
|
|
@@ -2949,7 +3162,7 @@ function getPathMod() {
|
|
|
2949
3162
|
return pathMod;
|
|
2950
3163
|
return nodePath;
|
|
2951
3164
|
}
|
|
2952
|
-
var
|
|
3165
|
+
var dirname2 = (path) => getPathMod().dirname(path);
|
|
2953
3166
|
var join2 = (...paths) => getPathMod().join(...paths);
|
|
2954
3167
|
var resolve = (...paths) => getPathMod().resolve(...paths);
|
|
2955
3168
|
var extname = (path) => getPathMod().extname(path);
|
|
@@ -2996,7 +3209,7 @@ function createFsAdapterPlugin(fsAdapter) {
|
|
|
2996
3209
|
build.onResolve(
|
|
2997
3210
|
{ filter: /^\.\.?\// },
|
|
2998
3211
|
async (args) => {
|
|
2999
|
-
const importerDir = args.importer ?
|
|
3212
|
+
const importerDir = args.importer ? dirname2(args.importer) : args.resolveDir;
|
|
3000
3213
|
const basePath = resolve(importerDir, args.path);
|
|
3001
3214
|
const resolvedPath = await resolveWithExtensions(basePath);
|
|
3002
3215
|
if (resolvedPath) {
|
|
@@ -3023,7 +3236,7 @@ function createFsAdapterPlugin(fsAdapter) {
|
|
|
3023
3236
|
contents: content,
|
|
3024
3237
|
loader,
|
|
3025
3238
|
// Set resolveDir for nested imports from this file
|
|
3026
|
-
resolveDir:
|
|
3239
|
+
resolveDir: dirname2(args.path)
|
|
3027
3240
|
};
|
|
3028
3241
|
} catch (error) {
|
|
3029
3242
|
return {
|
|
@@ -3058,7 +3271,7 @@ async function importModule(file, context) {
|
|
|
3058
3271
|
const isJsx = filePath.endsWith(".jsx");
|
|
3059
3272
|
const loader = isTsx ? "tsx" : isJsx ? "jsx" : filePath.endsWith(".ts") ? "ts" : "js";
|
|
3060
3273
|
const { build } = await import("esbuild");
|
|
3061
|
-
const fileDir =
|
|
3274
|
+
const fileDir = dirname2(filePath);
|
|
3062
3275
|
const relativeImports = [];
|
|
3063
3276
|
if (isDeno) {
|
|
3064
3277
|
const relativeImportPattern = /from\s+["'](\.\.[^"']+)["']/g;
|
|
@@ -3522,9 +3735,8 @@ function generateId(prefix) {
|
|
|
3522
3735
|
|
|
3523
3736
|
// src/ai/agent/memory.ts
|
|
3524
3737
|
var ConversationMemory = class {
|
|
3525
|
-
messages = [];
|
|
3526
|
-
config;
|
|
3527
3738
|
constructor(config) {
|
|
3739
|
+
this.messages = [];
|
|
3528
3740
|
this.config = config;
|
|
3529
3741
|
}
|
|
3530
3742
|
async add(message) {
|
|
@@ -3569,10 +3781,8 @@ var ConversationMemory = class {
|
|
|
3569
3781
|
}
|
|
3570
3782
|
};
|
|
3571
3783
|
var BufferMemory = class {
|
|
3572
|
-
messages = [];
|
|
3573
|
-
config;
|
|
3574
|
-
bufferSize;
|
|
3575
3784
|
constructor(config) {
|
|
3785
|
+
this.messages = [];
|
|
3576
3786
|
this.config = config;
|
|
3577
3787
|
this.bufferSize = config.maxMessages || 10;
|
|
3578
3788
|
}
|
|
@@ -3606,11 +3816,9 @@ var BufferMemory = class {
|
|
|
3606
3816
|
}
|
|
3607
3817
|
};
|
|
3608
3818
|
var SummaryMemory = class {
|
|
3609
|
-
messages = [];
|
|
3610
|
-
summary = "";
|
|
3611
|
-
config;
|
|
3612
|
-
summaryThreshold;
|
|
3613
3819
|
constructor(config) {
|
|
3820
|
+
this.messages = [];
|
|
3821
|
+
this.summary = "";
|
|
3614
3822
|
this.config = config;
|
|
3615
3823
|
this.summaryThreshold = config.maxMessages || 20;
|
|
3616
3824
|
}
|
|
@@ -3719,9 +3927,11 @@ var VERYFRONT_PATHS = {
|
|
|
3719
3927
|
|
|
3720
3928
|
// src/core/utils/bundle-manifest.ts
|
|
3721
3929
|
var InMemoryBundleManifestStore = class {
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3930
|
+
constructor() {
|
|
3931
|
+
this.metadata = /* @__PURE__ */ new Map();
|
|
3932
|
+
this.code = /* @__PURE__ */ new Map();
|
|
3933
|
+
this.sourceIndex = /* @__PURE__ */ new Map();
|
|
3934
|
+
}
|
|
3725
3935
|
getBundleMetadata(key) {
|
|
3726
3936
|
const entry = this.metadata.get(key);
|
|
3727
3937
|
if (!entry)
|
|
@@ -3812,6 +4022,9 @@ var InMemoryBundleManifestStore = class {
|
|
|
3812
4022
|
};
|
|
3813
4023
|
var manifestStore = new InMemoryBundleManifestStore();
|
|
3814
4024
|
|
|
4025
|
+
// src/core/utils/perf-timer.ts
|
|
4026
|
+
var enabled = typeof process !== "undefined" ? process.env?.VERYFRONT_PERF === "1" : typeof Deno !== "undefined" ? Deno.env.get("VERYFRONT_PERF") === "1" : false;
|
|
4027
|
+
|
|
3815
4028
|
// src/observability/tracing/config.ts
|
|
3816
4029
|
var DEFAULT_CONFIG2 = {
|
|
3817
4030
|
enabled: false,
|
|
@@ -4013,14 +4226,16 @@ var ContextPropagation = class {
|
|
|
4013
4226
|
|
|
4014
4227
|
// src/observability/tracing/manager.ts
|
|
4015
4228
|
var TracingManager = class {
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4229
|
+
constructor() {
|
|
4230
|
+
this.state = {
|
|
4231
|
+
initialized: false,
|
|
4232
|
+
tracer: null,
|
|
4233
|
+
api: null,
|
|
4234
|
+
propagator: null
|
|
4235
|
+
};
|
|
4236
|
+
this.spanOps = null;
|
|
4237
|
+
this.contextProp = null;
|
|
4238
|
+
}
|
|
4024
4239
|
async initialize(config = {}, adapter) {
|
|
4025
4240
|
if (this.state.initialized) {
|
|
4026
4241
|
serverLogger.debug("[tracing] Already initialized");
|
|
@@ -4106,7 +4321,27 @@ async function withSpan(name, fn, options = {}) {
|
|
|
4106
4321
|
);
|
|
4107
4322
|
}
|
|
4108
4323
|
|
|
4109
|
-
// src/ai/
|
|
4324
|
+
// src/ai/config/defaults.ts
|
|
4325
|
+
var AGENT_DEFAULTS = {
|
|
4326
|
+
/** Maximum tokens for completion */
|
|
4327
|
+
maxTokens: 4096,
|
|
4328
|
+
/** Default temperature for generation */
|
|
4329
|
+
temperature: 0.7,
|
|
4330
|
+
/** Maximum agent loop steps */
|
|
4331
|
+
maxSteps: 20,
|
|
4332
|
+
/** Default memory type */
|
|
4333
|
+
memoryType: "conversation",
|
|
4334
|
+
/** Default memory max tokens */
|
|
4335
|
+
memoryMaxTokens: 4e3
|
|
4336
|
+
};
|
|
4337
|
+
var STREAMING_DEFAULTS = {
|
|
4338
|
+
/** Maximum buffer size for streaming (1MB) */
|
|
4339
|
+
maxBufferSize: 1024 * 1024,
|
|
4340
|
+
/** Chunk size for stream processing */
|
|
4341
|
+
chunkSize: 16384
|
|
4342
|
+
};
|
|
4343
|
+
|
|
4344
|
+
// src/ai/agent/streaming/stream-events.ts
|
|
4110
4345
|
import { z as z6 } from "zod";
|
|
4111
4346
|
var AgentStreamEventSchema = z6.discriminatedUnion("type", [
|
|
4112
4347
|
z6.object({
|
|
@@ -4146,8 +4381,8 @@ var AgentStreamEventSchema = z6.discriminatedUnion("type", [
|
|
|
4146
4381
|
})
|
|
4147
4382
|
})
|
|
4148
4383
|
]);
|
|
4149
|
-
|
|
4150
|
-
|
|
4384
|
+
|
|
4385
|
+
// src/ai/agent/message-converter.ts
|
|
4151
4386
|
function convertMessageToProvider(msg) {
|
|
4152
4387
|
const content = getTextFromParts(msg.parts);
|
|
4153
4388
|
const providerMsg = {
|
|
@@ -4177,12 +4412,14 @@ function convertMessageToProvider(msg) {
|
|
|
4177
4412
|
}
|
|
4178
4413
|
return providerMsg;
|
|
4179
4414
|
}
|
|
4415
|
+
|
|
4416
|
+
// src/ai/agent/runtime.ts
|
|
4417
|
+
var DEFAULT_MAX_TOKENS = AGENT_DEFAULTS.maxTokens;
|
|
4418
|
+
var DEFAULT_TEMPERATURE = AGENT_DEFAULTS.temperature;
|
|
4419
|
+
var MAX_STREAM_BUFFER_SIZE = STREAMING_DEFAULTS.maxBufferSize;
|
|
4180
4420
|
var AgentRuntime = class {
|
|
4181
|
-
id;
|
|
4182
|
-
config;
|
|
4183
|
-
memory;
|
|
4184
|
-
status = "idle";
|
|
4185
4421
|
constructor(id, config) {
|
|
4422
|
+
this.status = "idle";
|
|
4186
4423
|
this.id = id;
|
|
4187
4424
|
this.config = config;
|
|
4188
4425
|
const memoryConfig = config.memory || { type: "conversation", maxTokens: 4e3 };
|
|
@@ -4610,6 +4847,10 @@ var AgentRuntime = class {
|
|
|
4610
4847
|
if (done)
|
|
4611
4848
|
break;
|
|
4612
4849
|
partial += decoder.decode(value, { stream: true });
|
|
4850
|
+
if (partial.length > MAX_STREAM_BUFFER_SIZE) {
|
|
4851
|
+
serverLogger.warn("[AGENT] Stream buffer exceeded max size, truncating");
|
|
4852
|
+
partial = partial.slice(-MAX_STREAM_BUFFER_SIZE / 2);
|
|
4853
|
+
}
|
|
4613
4854
|
const segments = partial.split("\n");
|
|
4614
4855
|
partial = segments.pop() ?? "";
|
|
4615
4856
|
const lines = segments.filter((line) => line.trim());
|
|
@@ -5166,7 +5407,6 @@ async function setupAI(options = {}) {
|
|
|
5166
5407
|
|
|
5167
5408
|
// src/ai/mcp/server.ts
|
|
5168
5409
|
var MCPServer = class {
|
|
5169
|
-
config;
|
|
5170
5410
|
constructor(config) {
|
|
5171
5411
|
this.config = config;
|
|
5172
5412
|
}
|
|
@@ -5477,9 +5717,8 @@ import { anthropic } from "@ai-sdk/anthropic";
|
|
|
5477
5717
|
|
|
5478
5718
|
// src/ai/production/rate-limit/limiter.ts
|
|
5479
5719
|
var FixedWindowLimiter = class {
|
|
5480
|
-
requests = /* @__PURE__ */ new Map();
|
|
5481
|
-
config;
|
|
5482
5720
|
constructor(config) {
|
|
5721
|
+
this.requests = /* @__PURE__ */ new Map();
|
|
5483
5722
|
this.config = config;
|
|
5484
5723
|
}
|
|
5485
5724
|
check(identifier) {
|
|
@@ -5520,10 +5759,8 @@ var FixedWindowLimiter = class {
|
|
|
5520
5759
|
}
|
|
5521
5760
|
};
|
|
5522
5761
|
var TokenBucketLimiter = class {
|
|
5523
|
-
buckets = /* @__PURE__ */ new Map();
|
|
5524
|
-
config;
|
|
5525
|
-
refillRate;
|
|
5526
5762
|
constructor(config) {
|
|
5763
|
+
this.buckets = /* @__PURE__ */ new Map();
|
|
5527
5764
|
this.config = config;
|
|
5528
5765
|
this.refillRate = config.maxRequests / config.windowMs;
|
|
5529
5766
|
}
|
|
@@ -5626,7 +5863,9 @@ function rateLimitMiddleware(config) {
|
|
|
5626
5863
|
|
|
5627
5864
|
// src/ai/production/cache/cache.ts
|
|
5628
5865
|
var MemoryCache = class {
|
|
5629
|
-
|
|
5866
|
+
constructor() {
|
|
5867
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
5868
|
+
}
|
|
5630
5869
|
set(key, response) {
|
|
5631
5870
|
this.cache.set(key, {
|
|
5632
5871
|
response,
|
|
@@ -5657,9 +5896,8 @@ var MemoryCache = class {
|
|
|
5657
5896
|
}
|
|
5658
5897
|
};
|
|
5659
5898
|
var LRUCache = class {
|
|
5660
|
-
cache = /* @__PURE__ */ new Map();
|
|
5661
|
-
maxSize;
|
|
5662
5899
|
constructor(maxSize = 100) {
|
|
5900
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
5663
5901
|
this.maxSize = maxSize;
|
|
5664
5902
|
}
|
|
5665
5903
|
set(key, response) {
|
|
@@ -5703,10 +5941,9 @@ var LRUCache = class {
|
|
|
5703
5941
|
}
|
|
5704
5942
|
};
|
|
5705
5943
|
var TTLCache = class {
|
|
5706
|
-
cache = /* @__PURE__ */ new Map();
|
|
5707
|
-
ttl;
|
|
5708
|
-
cleanupInterval = null;
|
|
5709
5944
|
constructor(ttl = 3e5) {
|
|
5945
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
5946
|
+
this.cleanupInterval = null;
|
|
5710
5947
|
this.ttl = ttl;
|
|
5711
5948
|
this.startCleanup();
|
|
5712
5949
|
}
|
|
@@ -5860,14 +6097,13 @@ function cacheMiddleware(config) {
|
|
|
5860
6097
|
|
|
5861
6098
|
// src/ai/production/cost-tracking/tracker.ts
|
|
5862
6099
|
var CostTracker = class {
|
|
5863
|
-
records = [];
|
|
5864
|
-
config;
|
|
5865
|
-
dailyTotal = 0;
|
|
5866
|
-
monthlyTotal = 0;
|
|
5867
|
-
lastDayReset = Date.now();
|
|
5868
|
-
lastMonthReset = Date.now();
|
|
5869
|
-
resetInterval = null;
|
|
5870
6100
|
constructor(config) {
|
|
6101
|
+
this.records = [];
|
|
6102
|
+
this.dailyTotal = 0;
|
|
6103
|
+
this.monthlyTotal = 0;
|
|
6104
|
+
this.lastDayReset = Date.now();
|
|
6105
|
+
this.lastMonthReset = Date.now();
|
|
6106
|
+
this.resetInterval = null;
|
|
5871
6107
|
this.config = config;
|
|
5872
6108
|
this.startPeriodicReset();
|
|
5873
6109
|
}
|
|
@@ -6130,7 +6366,6 @@ var PII_PATTERNS = {
|
|
|
6130
6366
|
creditCard: /\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g
|
|
6131
6367
|
};
|
|
6132
6368
|
var InputValidator = class {
|
|
6133
|
-
config;
|
|
6134
6369
|
constructor(config) {
|
|
6135
6370
|
this.config = config || {};
|
|
6136
6371
|
}
|
|
@@ -6190,7 +6425,6 @@ var InputValidator = class {
|
|
|
6190
6425
|
}
|
|
6191
6426
|
};
|
|
6192
6427
|
var OutputFilter = class {
|
|
6193
|
-
config;
|
|
6194
6428
|
constructor(config) {
|
|
6195
6429
|
this.config = config || {};
|
|
6196
6430
|
}
|
|
@@ -6464,13 +6698,12 @@ function hasLockSupport(backend) {
|
|
|
6464
6698
|
// src/ai/workflow/backends/memory.ts
|
|
6465
6699
|
var DEFAULT_MAX_QUEUE_SIZE = 1e4;
|
|
6466
6700
|
var MemoryBackend = class {
|
|
6467
|
-
runs = /* @__PURE__ */ new Map();
|
|
6468
|
-
checkpoints = /* @__PURE__ */ new Map();
|
|
6469
|
-
approvals = /* @__PURE__ */ new Map();
|
|
6470
|
-
queue = [];
|
|
6471
|
-
locks = /* @__PURE__ */ new Map();
|
|
6472
|
-
config;
|
|
6473
6701
|
constructor(config = {}) {
|
|
6702
|
+
this.runs = /* @__PURE__ */ new Map();
|
|
6703
|
+
this.checkpoints = /* @__PURE__ */ new Map();
|
|
6704
|
+
this.approvals = /* @__PURE__ */ new Map();
|
|
6705
|
+
this.queue = [];
|
|
6706
|
+
this.locks = /* @__PURE__ */ new Map();
|
|
6474
6707
|
this.config = {
|
|
6475
6708
|
prefix: "wf:",
|
|
6476
6709
|
debug: false,
|
|
@@ -6801,7 +7034,6 @@ var MemoryBackend = class {
|
|
|
6801
7034
|
|
|
6802
7035
|
// src/ai/workflow/executor/dag-executor.ts
|
|
6803
7036
|
var DAGExecutor = class {
|
|
6804
|
-
config;
|
|
6805
7037
|
constructor(config) {
|
|
6806
7038
|
this.config = {
|
|
6807
7039
|
maxConcurrency: 10,
|
|
@@ -6944,9 +7176,16 @@ var DAGExecutor = class {
|
|
|
6944
7176
|
context,
|
|
6945
7177
|
nodeStates
|
|
6946
7178
|
);
|
|
7179
|
+
case "loop":
|
|
7180
|
+
return await this.executeLoopNode(
|
|
7181
|
+
node,
|
|
7182
|
+
config,
|
|
7183
|
+
context,
|
|
7184
|
+
nodeStates
|
|
7185
|
+
);
|
|
6947
7186
|
default:
|
|
6948
7187
|
throw new Error(
|
|
6949
|
-
`Unknown node type "${config.type}" for node "${node.id}". Valid types are: step, parallel, map, branch, wait, subWorkflow`
|
|
7188
|
+
`Unknown node type "${config.type}" for node "${node.id}". Valid types are: step, parallel, map, branch, wait, subWorkflow, loop`
|
|
6950
7189
|
);
|
|
6951
7190
|
}
|
|
6952
7191
|
}
|
|
@@ -7104,6 +7343,155 @@ var DAGExecutor = class {
|
|
|
7104
7343
|
waiting: result.waiting
|
|
7105
7344
|
};
|
|
7106
7345
|
}
|
|
7346
|
+
/**
|
|
7347
|
+
* Execute a loop node
|
|
7348
|
+
*/
|
|
7349
|
+
async executeLoopNode(node, config, context, nodeStates) {
|
|
7350
|
+
const startTime = Date.now();
|
|
7351
|
+
const previousResults = [];
|
|
7352
|
+
let iteration = 0;
|
|
7353
|
+
let exitReason = "condition";
|
|
7354
|
+
let lastError;
|
|
7355
|
+
const existingLoopState = context[`${node.id}_loop_state`];
|
|
7356
|
+
if (existingLoopState) {
|
|
7357
|
+
iteration = existingLoopState.iteration;
|
|
7358
|
+
previousResults.push(...existingLoopState.previousResults);
|
|
7359
|
+
}
|
|
7360
|
+
while (iteration < config.maxIterations) {
|
|
7361
|
+
const loopContext = {
|
|
7362
|
+
iteration,
|
|
7363
|
+
totalIterations: iteration,
|
|
7364
|
+
previousResults: [...previousResults],
|
|
7365
|
+
isFirstIteration: iteration === 0,
|
|
7366
|
+
isLastAllowedIteration: iteration === config.maxIterations - 1
|
|
7367
|
+
};
|
|
7368
|
+
const shouldContinue = await config.while(context, loopContext);
|
|
7369
|
+
if (!shouldContinue) {
|
|
7370
|
+
exitReason = "condition";
|
|
7371
|
+
break;
|
|
7372
|
+
}
|
|
7373
|
+
const steps = typeof config.steps === "function" ? config.steps(context, loopContext) : config.steps;
|
|
7374
|
+
const result = await this.execute(steps, {
|
|
7375
|
+
id: `${node.id}_iter_${iteration}`,
|
|
7376
|
+
workflowId: "",
|
|
7377
|
+
status: "running",
|
|
7378
|
+
input: context.input,
|
|
7379
|
+
nodeStates: {},
|
|
7380
|
+
currentNodes: [],
|
|
7381
|
+
context: { ...context, _loop: loopContext },
|
|
7382
|
+
checkpoints: [],
|
|
7383
|
+
pendingApprovals: [],
|
|
7384
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
7385
|
+
});
|
|
7386
|
+
if (result.waiting) {
|
|
7387
|
+
Object.assign(nodeStates, result.nodeStates);
|
|
7388
|
+
const state2 = {
|
|
7389
|
+
nodeId: node.id,
|
|
7390
|
+
status: "running",
|
|
7391
|
+
output: {
|
|
7392
|
+
iteration,
|
|
7393
|
+
waiting: true,
|
|
7394
|
+
previousResults
|
|
7395
|
+
},
|
|
7396
|
+
attempt: 1,
|
|
7397
|
+
startedAt: new Date(startTime)
|
|
7398
|
+
};
|
|
7399
|
+
return {
|
|
7400
|
+
state: state2,
|
|
7401
|
+
contextUpdates: {
|
|
7402
|
+
...result.context,
|
|
7403
|
+
[`${node.id}_loop_state`]: { iteration, previousResults }
|
|
7404
|
+
},
|
|
7405
|
+
waiting: true
|
|
7406
|
+
};
|
|
7407
|
+
}
|
|
7408
|
+
if (result.error) {
|
|
7409
|
+
lastError = result.error;
|
|
7410
|
+
exitReason = "error";
|
|
7411
|
+
break;
|
|
7412
|
+
}
|
|
7413
|
+
previousResults.push(result.context);
|
|
7414
|
+
Object.assign(context, result.context);
|
|
7415
|
+
Object.assign(nodeStates, result.nodeStates);
|
|
7416
|
+
if (config.delay && iteration < config.maxIterations - 1) {
|
|
7417
|
+
const delayMs = typeof config.delay === "number" ? config.delay : this.parseDuration(config.delay);
|
|
7418
|
+
await this.sleep(delayMs);
|
|
7419
|
+
}
|
|
7420
|
+
iteration++;
|
|
7421
|
+
}
|
|
7422
|
+
if (iteration >= config.maxIterations && exitReason !== "condition") {
|
|
7423
|
+
exitReason = "maxIterations";
|
|
7424
|
+
}
|
|
7425
|
+
const finalLoopContext = {
|
|
7426
|
+
iteration,
|
|
7427
|
+
totalIterations: iteration,
|
|
7428
|
+
previousResults,
|
|
7429
|
+
isFirstIteration: false,
|
|
7430
|
+
isLastAllowedIteration: true
|
|
7431
|
+
};
|
|
7432
|
+
let completionUpdates = {};
|
|
7433
|
+
if (exitReason === "maxIterations" && config.onMaxIterations) {
|
|
7434
|
+
completionUpdates = await config.onMaxIterations(context, finalLoopContext);
|
|
7435
|
+
} else if (exitReason === "condition" && config.onComplete) {
|
|
7436
|
+
completionUpdates = await config.onComplete(context, finalLoopContext);
|
|
7437
|
+
}
|
|
7438
|
+
const output = {
|
|
7439
|
+
exitReason,
|
|
7440
|
+
iterations: iteration,
|
|
7441
|
+
previousResults,
|
|
7442
|
+
...completionUpdates
|
|
7443
|
+
};
|
|
7444
|
+
const state = {
|
|
7445
|
+
nodeId: node.id,
|
|
7446
|
+
status: exitReason === "error" ? "failed" : "completed",
|
|
7447
|
+
output,
|
|
7448
|
+
error: lastError,
|
|
7449
|
+
attempt: 1,
|
|
7450
|
+
startedAt: new Date(startTime),
|
|
7451
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
7452
|
+
};
|
|
7453
|
+
this.config.onNodeComplete?.(node.id, state);
|
|
7454
|
+
return {
|
|
7455
|
+
state,
|
|
7456
|
+
contextUpdates: {
|
|
7457
|
+
[node.id]: output,
|
|
7458
|
+
...completionUpdates
|
|
7459
|
+
},
|
|
7460
|
+
waiting: false
|
|
7461
|
+
};
|
|
7462
|
+
}
|
|
7463
|
+
/**
|
|
7464
|
+
* Parse duration string to milliseconds
|
|
7465
|
+
*/
|
|
7466
|
+
parseDuration(duration) {
|
|
7467
|
+
if (typeof duration === "number")
|
|
7468
|
+
return duration;
|
|
7469
|
+
const match = duration.match(/^(\d+)(ms|s|m|h|d)$/);
|
|
7470
|
+
if (!match)
|
|
7471
|
+
return 0;
|
|
7472
|
+
const value = parseInt(match[1], 10);
|
|
7473
|
+
const unit = match[2];
|
|
7474
|
+
switch (unit) {
|
|
7475
|
+
case "ms":
|
|
7476
|
+
return value;
|
|
7477
|
+
case "s":
|
|
7478
|
+
return value * 1e3;
|
|
7479
|
+
case "m":
|
|
7480
|
+
return value * 60 * 1e3;
|
|
7481
|
+
case "h":
|
|
7482
|
+
return value * 60 * 60 * 1e3;
|
|
7483
|
+
case "d":
|
|
7484
|
+
return value * 24 * 60 * 60 * 1e3;
|
|
7485
|
+
default:
|
|
7486
|
+
return 0;
|
|
7487
|
+
}
|
|
7488
|
+
}
|
|
7489
|
+
/**
|
|
7490
|
+
* Sleep for specified milliseconds
|
|
7491
|
+
*/
|
|
7492
|
+
sleep(ms) {
|
|
7493
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
7494
|
+
}
|
|
7107
7495
|
/**
|
|
7108
7496
|
* Execute a step node
|
|
7109
7497
|
*/
|
|
@@ -7343,7 +7731,6 @@ var DAGExecutor = class {
|
|
|
7343
7731
|
|
|
7344
7732
|
// src/ai/workflow/executor/checkpoint-manager.ts
|
|
7345
7733
|
var CheckpointManager = class {
|
|
7346
|
-
config;
|
|
7347
7734
|
constructor(config) {
|
|
7348
7735
|
this.config = {
|
|
7349
7736
|
debug: false,
|
|
@@ -7499,9 +7886,14 @@ var CheckpointManager = class {
|
|
|
7499
7886
|
};
|
|
7500
7887
|
|
|
7501
7888
|
// src/ai/workflow/executor/step-executor.ts
|
|
7889
|
+
var DEFAULT_RETRY = {
|
|
7890
|
+
maxAttempts: 1,
|
|
7891
|
+
backoff: "exponential",
|
|
7892
|
+
initialDelay: 1e3,
|
|
7893
|
+
maxDelay: 3e4
|
|
7894
|
+
};
|
|
7502
7895
|
var DEFAULT_STEP_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
7503
7896
|
var StepExecutor = class {
|
|
7504
|
-
config;
|
|
7505
7897
|
constructor(config = {}) {
|
|
7506
7898
|
this.config = {
|
|
7507
7899
|
defaultTimeout: DEFAULT_STEP_TIMEOUT_MS,
|
|
@@ -7509,7 +7901,7 @@ var StepExecutor = class {
|
|
|
7509
7901
|
};
|
|
7510
7902
|
}
|
|
7511
7903
|
/**
|
|
7512
|
-
* Execute a step node
|
|
7904
|
+
* Execute a step node with retry support
|
|
7513
7905
|
*/
|
|
7514
7906
|
async execute(node, context) {
|
|
7515
7907
|
const startTime = Date.now();
|
|
@@ -7519,30 +7911,96 @@ var StepExecutor = class {
|
|
|
7519
7911
|
`StepExecutor can only execute 'step' nodes, but node "${node.id}" has type '${config.type}'. This is likely a bug in the DAG executor routing.`
|
|
7520
7912
|
);
|
|
7521
7913
|
}
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7914
|
+
const retryConfig = { ...DEFAULT_RETRY, ...config.retry };
|
|
7915
|
+
const maxAttempts = retryConfig.maxAttempts ?? 1;
|
|
7916
|
+
let lastError;
|
|
7917
|
+
let attempt = 0;
|
|
7918
|
+
while (attempt < maxAttempts) {
|
|
7919
|
+
attempt++;
|
|
7920
|
+
try {
|
|
7921
|
+
const resolvedInput = await this.resolveInput(config.input, context);
|
|
7922
|
+
this.config.onStepStart?.(node.id, resolvedInput);
|
|
7923
|
+
const timeout = config.timeout ? parseDuration(config.timeout) : this.config.defaultTimeout;
|
|
7924
|
+
const output = await this.executeWithTimeout(
|
|
7925
|
+
() => this.executeStep(config, resolvedInput, context),
|
|
7926
|
+
timeout,
|
|
7927
|
+
node.id
|
|
7928
|
+
);
|
|
7929
|
+
this.config.onStepComplete?.(node.id, output);
|
|
7930
|
+
return {
|
|
7931
|
+
success: true,
|
|
7932
|
+
output,
|
|
7933
|
+
executionTime: Date.now() - startTime
|
|
7934
|
+
};
|
|
7935
|
+
} catch (error) {
|
|
7936
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
7937
|
+
const shouldRetry = attempt < maxAttempts && this.isRetryableError(lastError, retryConfig);
|
|
7938
|
+
if (shouldRetry) {
|
|
7939
|
+
const delay2 = this.calculateRetryDelay(attempt, retryConfig);
|
|
7940
|
+
await this.sleep(delay2);
|
|
7941
|
+
continue;
|
|
7942
|
+
}
|
|
7943
|
+
this.config.onStepError?.(node.id, lastError);
|
|
7944
|
+
return {
|
|
7945
|
+
success: false,
|
|
7946
|
+
error: lastError.message,
|
|
7947
|
+
executionTime: Date.now() - startTime
|
|
7948
|
+
};
|
|
7949
|
+
}
|
|
7950
|
+
}
|
|
7951
|
+
return {
|
|
7952
|
+
success: false,
|
|
7953
|
+
error: lastError?.message ?? "Unknown error",
|
|
7954
|
+
executionTime: Date.now() - startTime
|
|
7955
|
+
};
|
|
7956
|
+
}
|
|
7957
|
+
/**
|
|
7958
|
+
* Check if error is retryable
|
|
7959
|
+
*/
|
|
7960
|
+
isRetryableError(error, config) {
|
|
7961
|
+
if (config.retryIf) {
|
|
7962
|
+
return config.retryIf(error);
|
|
7545
7963
|
}
|
|
7964
|
+
const retryablePatterns = [
|
|
7965
|
+
/timeout/i,
|
|
7966
|
+
/ECONNRESET/i,
|
|
7967
|
+
/ECONNREFUSED/i,
|
|
7968
|
+
/ETIMEDOUT/i,
|
|
7969
|
+
/rate limit/i,
|
|
7970
|
+
/429/,
|
|
7971
|
+
/503/,
|
|
7972
|
+
/502/
|
|
7973
|
+
];
|
|
7974
|
+
return retryablePatterns.some((pattern) => pattern.test(error.message));
|
|
7975
|
+
}
|
|
7976
|
+
/**
|
|
7977
|
+
* Calculate retry delay based on backoff strategy
|
|
7978
|
+
*/
|
|
7979
|
+
calculateRetryDelay(attempt, config) {
|
|
7980
|
+
const initialDelay = config.initialDelay ?? 1e3;
|
|
7981
|
+
const maxDelay = config.maxDelay ?? 3e4;
|
|
7982
|
+
let delay2;
|
|
7983
|
+
switch (config.backoff) {
|
|
7984
|
+
case "exponential":
|
|
7985
|
+
delay2 = initialDelay * Math.pow(2, attempt - 1);
|
|
7986
|
+
break;
|
|
7987
|
+
case "linear":
|
|
7988
|
+
delay2 = initialDelay * attempt;
|
|
7989
|
+
break;
|
|
7990
|
+
case "fixed":
|
|
7991
|
+
default:
|
|
7992
|
+
delay2 = initialDelay;
|
|
7993
|
+
break;
|
|
7994
|
+
}
|
|
7995
|
+
const jitter = delay2 * 0.1 * (Math.random() * 2 - 1);
|
|
7996
|
+
delay2 = Math.min(delay2 + jitter, maxDelay);
|
|
7997
|
+
return Math.floor(delay2);
|
|
7998
|
+
}
|
|
7999
|
+
/**
|
|
8000
|
+
* Sleep for specified milliseconds
|
|
8001
|
+
*/
|
|
8002
|
+
sleep(ms) {
|
|
8003
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
7546
8004
|
}
|
|
7547
8005
|
/**
|
|
7548
8006
|
* Resolve step input from context
|
|
@@ -7723,15 +8181,8 @@ var StepExecutor = class {
|
|
|
7723
8181
|
|
|
7724
8182
|
// src/ai/workflow/executor/workflow-executor.ts
|
|
7725
8183
|
var WorkflowExecutor = class _WorkflowExecutor {
|
|
7726
|
-
config;
|
|
7727
|
-
stepExecutor;
|
|
7728
|
-
checkpointManager;
|
|
7729
|
-
dagExecutor;
|
|
7730
|
-
workflows = /* @__PURE__ */ new Map();
|
|
7731
|
-
blobResolver;
|
|
7732
|
-
/** Default lock duration: 30 seconds */
|
|
7733
|
-
static DEFAULT_LOCK_DURATION = 3e4;
|
|
7734
8184
|
constructor(config) {
|
|
8185
|
+
this.workflows = /* @__PURE__ */ new Map();
|
|
7735
8186
|
this.config = {
|
|
7736
8187
|
maxConcurrency: 10,
|
|
7737
8188
|
debug: false,
|
|
@@ -7767,6 +8218,10 @@ var WorkflowExecutor = class _WorkflowExecutor {
|
|
|
7767
8218
|
};
|
|
7768
8219
|
}
|
|
7769
8220
|
}
|
|
8221
|
+
static {
|
|
8222
|
+
/** Default lock duration: 30 seconds */
|
|
8223
|
+
this.DEFAULT_LOCK_DURATION = 3e4;
|
|
8224
|
+
}
|
|
7770
8225
|
/**
|
|
7771
8226
|
* Register a workflow definition
|
|
7772
8227
|
*/
|
|
@@ -8121,10 +8576,8 @@ var WorkflowExecutor = class _WorkflowExecutor {
|
|
|
8121
8576
|
|
|
8122
8577
|
// src/ai/workflow/runtime/approval-manager.ts
|
|
8123
8578
|
var ApprovalManager = class {
|
|
8124
|
-
config;
|
|
8125
|
-
expirationTimer;
|
|
8126
|
-
destroyed = false;
|
|
8127
8579
|
constructor(config) {
|
|
8580
|
+
this.destroyed = false;
|
|
8128
8581
|
this.config = {
|
|
8129
8582
|
expirationCheckInterval: 6e4,
|
|
8130
8583
|
// Check every minute
|
|
@@ -8351,17 +8804,41 @@ var ApprovalManager = class {
|
|
|
8351
8804
|
|
|
8352
8805
|
// src/ai/workflow/api/workflow-client.ts
|
|
8353
8806
|
var WorkflowClient = class {
|
|
8354
|
-
backend;
|
|
8355
|
-
executor;
|
|
8356
|
-
approvalManager;
|
|
8357
|
-
debug;
|
|
8358
8807
|
constructor(config = {}) {
|
|
8359
8808
|
this.debug = config.debug ?? false;
|
|
8360
8809
|
this.backend = config.backend ?? new MemoryBackend({ debug: this.debug });
|
|
8361
8810
|
this.executor = new WorkflowExecutor({
|
|
8362
8811
|
backend: this.backend,
|
|
8363
8812
|
debug: this.debug,
|
|
8364
|
-
...config.executor
|
|
8813
|
+
...config.executor,
|
|
8814
|
+
onWaiting: async (run, nodeId) => {
|
|
8815
|
+
const nodeState = run.nodeStates[nodeId];
|
|
8816
|
+
if (!nodeState?.input) {
|
|
8817
|
+
if (this.debug) {
|
|
8818
|
+
console.log(`[WorkflowClient] No wait config found for node: ${nodeId}`);
|
|
8819
|
+
}
|
|
8820
|
+
return;
|
|
8821
|
+
}
|
|
8822
|
+
const input = nodeState.input;
|
|
8823
|
+
if (input.type !== "approval") {
|
|
8824
|
+
return;
|
|
8825
|
+
}
|
|
8826
|
+
const waitConfig = {
|
|
8827
|
+
type: "wait",
|
|
8828
|
+
waitType: "approval",
|
|
8829
|
+
message: input.message,
|
|
8830
|
+
payload: input.payload
|
|
8831
|
+
};
|
|
8832
|
+
try {
|
|
8833
|
+
await this.approvalManager.createApproval(run, nodeId, waitConfig, run.context);
|
|
8834
|
+
if (this.debug) {
|
|
8835
|
+
console.log(`[WorkflowClient] Created approval for node: ${nodeId}`);
|
|
8836
|
+
}
|
|
8837
|
+
} catch (error) {
|
|
8838
|
+
console.error(`[WorkflowClient] Failed to create approval:`, error);
|
|
8839
|
+
}
|
|
8840
|
+
config.executor?.onWaiting?.(run, nodeId);
|
|
8841
|
+
}
|
|
8365
8842
|
});
|
|
8366
8843
|
this.approvalManager = new ApprovalManager({
|
|
8367
8844
|
backend: this.backend,
|