veryfront 0.0.72 → 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 +593 -52
- package/dist/ai/components.js.map +3 -3
- package/dist/ai/dev.js +121 -18
- package/dist/ai/dev.js.map +2 -2
- package/dist/ai/index.js +732 -236
- package/dist/ai/index.js.map +4 -4
- package/dist/ai/production.js +121 -18
- package/dist/ai/production.js.map +2 -2
- package/dist/ai/react.js +57 -37
- package/dist/ai/react.js.map +2 -2
- package/dist/ai/workflow.js +435 -63
- package/dist/ai/workflow.js.map +4 -4
- package/dist/components.js +3353 -206
- package/dist/components.js.map +4 -4
- package/dist/config.js +377 -40
- 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 +156 -37
- 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 +3463 -282
- package/dist/index.js.map +4 -4
- package/dist/oauth/handlers.js +1 -1
- package/dist/oauth/handlers.js.map +2 -2
- package/dist/oauth/index.js +1 -1
- package/dist/oauth/index.js.map +2 -2
- package/dist/oauth/providers.js +1 -1
- package/dist/oauth/providers.js.map +2 -2
- package/dist/router.d.ts +69 -0
- package/dist/router.js +61 -0
- package/dist/router.js.map +7 -0
- package/dist/templates/ai/app/api/chat/route.ts +106 -3
- package/package.json +19 -2
- package/dist/cli.js +0 -108105
package/dist/ai/workflow.js
CHANGED
|
@@ -392,7 +392,7 @@ function toError(veryfrontError) {
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
// src/platform/compat/runtime.ts
|
|
395
|
-
var isDeno = typeof Deno !== "undefined";
|
|
395
|
+
var isDeno = typeof Deno !== "undefined" && typeof Deno.version === "object";
|
|
396
396
|
var isNode = typeof globalThis.process !== "undefined" && globalThis.process?.versions?.node !== void 0;
|
|
397
397
|
var isBun = typeof globalThis.Bun !== "undefined";
|
|
398
398
|
var isCloudflare = typeof globalThis !== "undefined" && "caches" in globalThis && "WebSocketPair" in globalThis;
|
|
@@ -581,19 +581,69 @@ function getEnvironmentVariable(name) {
|
|
|
581
581
|
}
|
|
582
582
|
return void 0;
|
|
583
583
|
}
|
|
584
|
+
function isProductionEnvironment() {
|
|
585
|
+
return getEnvironmentVariable("NODE_ENV") === "production";
|
|
586
|
+
}
|
|
584
587
|
|
|
585
588
|
// src/core/utils/logger/logger.ts
|
|
586
589
|
var cachedLogLevel;
|
|
590
|
+
var cachedLogFormat;
|
|
587
591
|
function resolveLogLevel(force = false) {
|
|
588
592
|
if (force || cachedLogLevel === void 0) {
|
|
589
593
|
cachedLogLevel = getDefaultLevel();
|
|
590
594
|
}
|
|
591
595
|
return cachedLogLevel;
|
|
592
596
|
}
|
|
593
|
-
|
|
594
|
-
|
|
597
|
+
function resolveLogFormat(force = false) {
|
|
598
|
+
if (force || cachedLogFormat === void 0) {
|
|
599
|
+
cachedLogFormat = getDefaultFormat();
|
|
600
|
+
}
|
|
601
|
+
return cachedLogFormat;
|
|
602
|
+
}
|
|
603
|
+
function getDefaultFormat() {
|
|
604
|
+
const envFormat = getEnvironmentVariable("LOG_FORMAT");
|
|
605
|
+
if (envFormat === "json" || envFormat === "text") {
|
|
606
|
+
return envFormat;
|
|
607
|
+
}
|
|
608
|
+
return isProductionEnvironment() ? "json" : "text";
|
|
609
|
+
}
|
|
610
|
+
function serializeError(err) {
|
|
611
|
+
if (err instanceof Error) {
|
|
612
|
+
return {
|
|
613
|
+
name: err.name,
|
|
614
|
+
message: err.message,
|
|
615
|
+
stack: err.stack
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
if (err !== void 0 && err !== null) {
|
|
619
|
+
return {
|
|
620
|
+
name: "UnknownError",
|
|
621
|
+
message: String(err)
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
return void 0;
|
|
625
|
+
}
|
|
626
|
+
function extractContext(args) {
|
|
627
|
+
let context;
|
|
628
|
+
let error;
|
|
629
|
+
for (const arg of args) {
|
|
630
|
+
if (arg instanceof Error) {
|
|
631
|
+
error = serializeError(arg);
|
|
632
|
+
} else if (typeof arg === "object" && arg !== null && !Array.isArray(arg)) {
|
|
633
|
+
context = { ...context, ...arg };
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
return { context, error };
|
|
637
|
+
}
|
|
638
|
+
var ConsoleLogger = class _ConsoleLogger {
|
|
639
|
+
constructor(prefix, level = resolveLogLevel(), format = resolveLogFormat(), boundContext) {
|
|
595
640
|
this.prefix = prefix;
|
|
596
641
|
this.level = level;
|
|
642
|
+
this.format = format;
|
|
643
|
+
this.boundContext = {};
|
|
644
|
+
if (boundContext) {
|
|
645
|
+
this.boundContext = boundContext;
|
|
646
|
+
}
|
|
597
647
|
}
|
|
598
648
|
setLevel(level) {
|
|
599
649
|
this.level = level;
|
|
@@ -601,36 +651,88 @@ var ConsoleLogger = class {
|
|
|
601
651
|
getLevel() {
|
|
602
652
|
return this.level;
|
|
603
653
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
654
|
+
setFormat(format) {
|
|
655
|
+
this.format = format;
|
|
656
|
+
}
|
|
657
|
+
getFormat() {
|
|
658
|
+
return this.format;
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Create a child logger with additional bound context.
|
|
662
|
+
*/
|
|
663
|
+
child(context) {
|
|
664
|
+
return new _ConsoleLogger(this.prefix, this.level, this.format, {
|
|
665
|
+
...this.boundContext,
|
|
666
|
+
...context
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
formatJson(level, message, args) {
|
|
670
|
+
const { context, error } = extractContext(args);
|
|
671
|
+
const entry = {
|
|
672
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
673
|
+
level,
|
|
674
|
+
service: this.prefix.toLowerCase(),
|
|
675
|
+
message
|
|
676
|
+
};
|
|
677
|
+
const mergedContext = { ...this.boundContext, ...context };
|
|
678
|
+
if (Object.keys(mergedContext).length > 0) {
|
|
679
|
+
if ("requestId" in mergedContext) {
|
|
680
|
+
entry.requestId = String(mergedContext.requestId);
|
|
681
|
+
delete mergedContext.requestId;
|
|
682
|
+
}
|
|
683
|
+
if ("traceId" in mergedContext) {
|
|
684
|
+
entry.traceId = String(mergedContext.traceId);
|
|
685
|
+
delete mergedContext.traceId;
|
|
686
|
+
}
|
|
687
|
+
if ("projectSlug" in mergedContext) {
|
|
688
|
+
entry.projectSlug = String(mergedContext.projectSlug);
|
|
689
|
+
delete mergedContext.projectSlug;
|
|
690
|
+
}
|
|
691
|
+
if ("durationMs" in mergedContext) {
|
|
692
|
+
entry.durationMs = Number(mergedContext.durationMs);
|
|
693
|
+
delete mergedContext.durationMs;
|
|
694
|
+
}
|
|
695
|
+
if (Object.keys(mergedContext).length > 0) {
|
|
696
|
+
entry.context = mergedContext;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
if (error) {
|
|
700
|
+
entry.error = error;
|
|
607
701
|
}
|
|
702
|
+
return JSON.stringify(entry);
|
|
608
703
|
}
|
|
609
|
-
|
|
610
|
-
if (this.level
|
|
611
|
-
|
|
704
|
+
log(level, logLevel, consoleFn, message, args) {
|
|
705
|
+
if (this.level > logLevel)
|
|
706
|
+
return;
|
|
707
|
+
if (this.format === "json") {
|
|
708
|
+
consoleFn(this.formatJson(level, message, args));
|
|
709
|
+
} else {
|
|
710
|
+
const prefix = level === "info" ? "" : ` ${level.toUpperCase()}:`;
|
|
711
|
+
consoleFn(`[${this.prefix}]${prefix} ${message}`, ...args);
|
|
612
712
|
}
|
|
613
713
|
}
|
|
714
|
+
debug(message, ...args) {
|
|
715
|
+
this.log("debug", 0 /* DEBUG */, console.debug, message, args);
|
|
716
|
+
}
|
|
717
|
+
info(message, ...args) {
|
|
718
|
+
this.log("info", 1 /* INFO */, console.log, message, args);
|
|
719
|
+
}
|
|
614
720
|
warn(message, ...args) {
|
|
615
|
-
|
|
616
|
-
console.warn(`[${this.prefix}] WARN: ${message}`, ...args);
|
|
617
|
-
}
|
|
721
|
+
this.log("warn", 2 /* WARN */, console.warn, message, args);
|
|
618
722
|
}
|
|
619
723
|
error(message, ...args) {
|
|
620
|
-
|
|
621
|
-
console.error(`[${this.prefix}] ERROR: ${message}`, ...args);
|
|
622
|
-
}
|
|
724
|
+
this.log("error", 3 /* ERROR */, console.error, message, args);
|
|
623
725
|
}
|
|
624
726
|
async time(label, fn) {
|
|
625
727
|
const start = performance.now();
|
|
626
728
|
try {
|
|
627
729
|
const result = await fn();
|
|
628
|
-
const
|
|
629
|
-
this.debug(`${label} completed
|
|
730
|
+
const durationMs = performance.now() - start;
|
|
731
|
+
this.debug(`${label} completed`, { durationMs: Math.round(durationMs) });
|
|
630
732
|
return result;
|
|
631
733
|
} catch (error) {
|
|
632
|
-
const
|
|
633
|
-
this.error(`${label} failed
|
|
734
|
+
const durationMs = performance.now() - start;
|
|
735
|
+
this.error(`${label} failed`, { durationMs: Math.round(durationMs) }, error);
|
|
634
736
|
throw error;
|
|
635
737
|
}
|
|
636
738
|
}
|
|
@@ -673,6 +775,7 @@ var serverLogger = createLogger("SERVER");
|
|
|
673
775
|
var rendererLogger = createLogger("RENDERER");
|
|
674
776
|
var bundlerLogger = createLogger("BUNDLER");
|
|
675
777
|
var agentLogger = createLogger("AGENT");
|
|
778
|
+
var proxyLogger = createLogger("PROXY");
|
|
676
779
|
var logger = createLogger("VERYFRONT");
|
|
677
780
|
|
|
678
781
|
// src/core/utils/constants/cache.ts
|
|
@@ -698,7 +801,7 @@ var LRU_DEFAULT_MAX_SIZE_BYTES = 50 * 1024 * 1024;
|
|
|
698
801
|
// deno.json
|
|
699
802
|
var deno_default = {
|
|
700
803
|
name: "veryfront",
|
|
701
|
-
version: "0.0.
|
|
804
|
+
version: "0.0.74",
|
|
702
805
|
nodeModulesDir: "auto",
|
|
703
806
|
exclude: [
|
|
704
807
|
"npm/",
|
|
@@ -783,12 +886,12 @@ var deno_default = {
|
|
|
783
886
|
csstype: "https://esm.sh/csstype@3.2.3",
|
|
784
887
|
"@types/react": "https://esm.sh/@types/react@18.3.27?deps=csstype@3.2.3",
|
|
785
888
|
"@types/react-dom": "https://esm.sh/@types/react-dom@18.3.7?deps=csstype@3.2.3",
|
|
786
|
-
react: "
|
|
787
|
-
"react-dom": "
|
|
788
|
-
"react-dom/server": "
|
|
789
|
-
"react-dom/client": "
|
|
790
|
-
"react/jsx-runtime": "
|
|
791
|
-
"react/jsx-dev-runtime": "
|
|
889
|
+
react: "npm:react@18.3.1",
|
|
890
|
+
"react-dom": "npm:react-dom@18.3.1",
|
|
891
|
+
"react-dom/server": "npm:react-dom@18.3.1/server.node",
|
|
892
|
+
"react-dom/client": "npm:react-dom@18.3.1/client",
|
|
893
|
+
"react/jsx-runtime": "npm:react@18.3.1/jsx-runtime",
|
|
894
|
+
"react/jsx-dev-runtime": "npm:react@18.3.1/jsx-dev-runtime",
|
|
792
895
|
"@mdx-js/mdx": "npm:@mdx-js/mdx@3.0.0",
|
|
793
896
|
"@mdx-js/react": "npm:@mdx-js/react@3.0.0",
|
|
794
897
|
"unist-util-visit": "npm:unist-util-visit@5.0.0",
|
|
@@ -798,27 +901,36 @@ var deno_default = {
|
|
|
798
901
|
"remark-frontmatter": "npm:remark-frontmatter@5.0.0",
|
|
799
902
|
"rehype-highlight": "npm:rehype-highlight@7.0.2",
|
|
800
903
|
"rehype-slug": "npm:rehype-slug@6.0.0",
|
|
801
|
-
esbuild: "
|
|
802
|
-
"esbuild/mod.js": "
|
|
904
|
+
esbuild: "npm:esbuild@0.20.2",
|
|
905
|
+
"esbuild/mod.js": "npm:esbuild@0.20.2",
|
|
803
906
|
"es-module-lexer": "npm:es-module-lexer@1.5.0",
|
|
804
|
-
zod: "npm:zod@3.
|
|
907
|
+
zod: "npm:zod@3.25.76",
|
|
805
908
|
"mime-types": "npm:mime-types@2.1.35",
|
|
806
909
|
mdast: "npm:@types/mdast@4.0.3",
|
|
807
910
|
hast: "npm:@types/hast@3.0.3",
|
|
808
911
|
unist: "npm:@types/unist@3.0.2",
|
|
809
912
|
unified: "npm:unified@11.0.5",
|
|
810
|
-
ai: "
|
|
811
|
-
"ai/react": "
|
|
812
|
-
"@ai-sdk/react": "
|
|
913
|
+
ai: "npm:ai@5.0.76",
|
|
914
|
+
"ai/react": "npm:@ai-sdk/react@2.0.1",
|
|
915
|
+
"@ai-sdk/react": "npm:@ai-sdk/react@2.0.1",
|
|
813
916
|
"@ai-sdk/openai": "https://esm.sh/@ai-sdk/openai@2.0.1",
|
|
814
917
|
"@ai-sdk/anthropic": "https://esm.sh/@ai-sdk/anthropic@2.0.1",
|
|
815
918
|
unocss: "https://esm.sh/unocss@0.59.0",
|
|
816
919
|
"@unocss/core": "https://esm.sh/@unocss/core@0.59.0",
|
|
817
920
|
"@unocss/preset-wind": "https://esm.sh/@unocss/preset-wind@0.59.0",
|
|
921
|
+
"next-themes": "npm:next-themes@0.3.0",
|
|
818
922
|
redis: "npm:redis",
|
|
819
923
|
pg: "npm:pg",
|
|
820
924
|
"@opentelemetry/api": "npm:@opentelemetry/api@1",
|
|
821
|
-
"@opentelemetry/core": "npm:@opentelemetry/core@1"
|
|
925
|
+
"@opentelemetry/core": "npm:@opentelemetry/core@1",
|
|
926
|
+
"@opentelemetry/sdk-trace-base": "npm:@opentelemetry/sdk-trace-base@1",
|
|
927
|
+
"@opentelemetry/exporter-trace-otlp-http": "npm:@opentelemetry/exporter-trace-otlp-http@0.57",
|
|
928
|
+
"@opentelemetry/resources": "npm:@opentelemetry/resources@1",
|
|
929
|
+
"@opentelemetry/semantic-conventions": "npm:@opentelemetry/semantic-conventions@1",
|
|
930
|
+
"@babel/parser": "npm:@babel/parser@7.26.3",
|
|
931
|
+
"@babel/traverse": "npm:@babel/traverse@7.26.3",
|
|
932
|
+
"@babel/generator": "npm:@babel/generator@7.26.3",
|
|
933
|
+
"@babel/types": "npm:@babel/types@7.26.3"
|
|
822
934
|
},
|
|
823
935
|
compilerOptions: {
|
|
824
936
|
jsx: "react-jsx",
|
|
@@ -826,7 +938,7 @@ var deno_default = {
|
|
|
826
938
|
strict: true,
|
|
827
939
|
noImplicitAny: true,
|
|
828
940
|
noUncheckedIndexedAccess: true,
|
|
829
|
-
types: [],
|
|
941
|
+
types: ["npm:@types/react@18"],
|
|
830
942
|
lib: [
|
|
831
943
|
"deno.window",
|
|
832
944
|
"dom",
|
|
@@ -841,9 +953,9 @@ var deno_default = {
|
|
|
841
953
|
build: "deno compile --allow-all --output ../../bin/veryfront src/cli/main.ts",
|
|
842
954
|
"build:npm": "deno run -A scripts/build-npm.ts",
|
|
843
955
|
release: "deno run -A scripts/release.ts",
|
|
844
|
-
test: "DENO_JOBS=1 deno test --parallel --fail-fast --allow-all --unstable-worker-options --unstable-net",
|
|
845
|
-
"test:unit": "DENO_JOBS=1 deno test --parallel --allow-all --v8-flags=--max-old-space-size=8192 --ignore=tests --unstable-worker-options --unstable-net",
|
|
846
|
-
"test:integration": "DENO_JOBS=1 deno test --parallel --fail-fast --allow-all tests --unstable-worker-options --unstable-net",
|
|
956
|
+
test: "VF_DISABLE_LRU_INTERVAL=1 DENO_JOBS=1 deno test --parallel --fail-fast --allow-all --unstable-worker-options --unstable-net",
|
|
957
|
+
"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",
|
|
958
|
+
"test:integration": "VF_DISABLE_LRU_INTERVAL=1 DENO_JOBS=1 deno test --parallel --fail-fast --allow-all tests --unstable-worker-options --unstable-net",
|
|
847
959
|
"test:coverage": "rm -rf coverage && DENO_JOBS=1 deno test --parallel --fail-fast --allow-all --coverage=coverage --unstable-worker-options --unstable-net || exit 1",
|
|
848
960
|
"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",
|
|
849
961
|
"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",
|
|
@@ -918,6 +1030,7 @@ function getEnv(key) {
|
|
|
918
1030
|
|
|
919
1031
|
// src/core/utils/version.ts
|
|
920
1032
|
var VERSION = getEnv("VERYFRONT_VERSION") || (typeof deno_default.version === "string" ? deno_default.version : "0.0.0");
|
|
1033
|
+
var SERVER_START_TIME = Date.now();
|
|
921
1034
|
|
|
922
1035
|
// src/core/utils/constants/http.ts
|
|
923
1036
|
var KB_IN_BYTES = 1024;
|
|
@@ -1117,6 +1230,9 @@ var InMemoryBundleManifestStore = class {
|
|
|
1117
1230
|
};
|
|
1118
1231
|
var manifestStore = new InMemoryBundleManifestStore();
|
|
1119
1232
|
|
|
1233
|
+
// src/core/utils/perf-timer.ts
|
|
1234
|
+
var enabled = typeof process !== "undefined" ? process.env?.VERYFRONT_PERF === "1" : typeof Deno !== "undefined" ? Deno.env.get("VERYFRONT_PERF") === "1" : false;
|
|
1235
|
+
|
|
1120
1236
|
// src/ai/workflow/blob/local-storage.ts
|
|
1121
1237
|
var LocalBlobStorage = class {
|
|
1122
1238
|
constructor(rootDir, baseUrl) {
|
|
@@ -3039,9 +3155,16 @@ var DAGExecutor = class {
|
|
|
3039
3155
|
context,
|
|
3040
3156
|
nodeStates
|
|
3041
3157
|
);
|
|
3158
|
+
case "loop":
|
|
3159
|
+
return await this.executeLoopNode(
|
|
3160
|
+
node,
|
|
3161
|
+
config,
|
|
3162
|
+
context,
|
|
3163
|
+
nodeStates
|
|
3164
|
+
);
|
|
3042
3165
|
default:
|
|
3043
3166
|
throw new Error(
|
|
3044
|
-
`Unknown node type "${config.type}" for node "${node.id}". Valid types are: step, parallel, map, branch, wait, subWorkflow`
|
|
3167
|
+
`Unknown node type "${config.type}" for node "${node.id}". Valid types are: step, parallel, map, branch, wait, subWorkflow, loop`
|
|
3045
3168
|
);
|
|
3046
3169
|
}
|
|
3047
3170
|
}
|
|
@@ -3199,6 +3322,155 @@ var DAGExecutor = class {
|
|
|
3199
3322
|
waiting: result.waiting
|
|
3200
3323
|
};
|
|
3201
3324
|
}
|
|
3325
|
+
/**
|
|
3326
|
+
* Execute a loop node
|
|
3327
|
+
*/
|
|
3328
|
+
async executeLoopNode(node, config, context, nodeStates) {
|
|
3329
|
+
const startTime = Date.now();
|
|
3330
|
+
const previousResults = [];
|
|
3331
|
+
let iteration = 0;
|
|
3332
|
+
let exitReason = "condition";
|
|
3333
|
+
let lastError;
|
|
3334
|
+
const existingLoopState = context[`${node.id}_loop_state`];
|
|
3335
|
+
if (existingLoopState) {
|
|
3336
|
+
iteration = existingLoopState.iteration;
|
|
3337
|
+
previousResults.push(...existingLoopState.previousResults);
|
|
3338
|
+
}
|
|
3339
|
+
while (iteration < config.maxIterations) {
|
|
3340
|
+
const loopContext = {
|
|
3341
|
+
iteration,
|
|
3342
|
+
totalIterations: iteration,
|
|
3343
|
+
previousResults: [...previousResults],
|
|
3344
|
+
isFirstIteration: iteration === 0,
|
|
3345
|
+
isLastAllowedIteration: iteration === config.maxIterations - 1
|
|
3346
|
+
};
|
|
3347
|
+
const shouldContinue = await config.while(context, loopContext);
|
|
3348
|
+
if (!shouldContinue) {
|
|
3349
|
+
exitReason = "condition";
|
|
3350
|
+
break;
|
|
3351
|
+
}
|
|
3352
|
+
const steps = typeof config.steps === "function" ? config.steps(context, loopContext) : config.steps;
|
|
3353
|
+
const result = await this.execute(steps, {
|
|
3354
|
+
id: `${node.id}_iter_${iteration}`,
|
|
3355
|
+
workflowId: "",
|
|
3356
|
+
status: "running",
|
|
3357
|
+
input: context.input,
|
|
3358
|
+
nodeStates: {},
|
|
3359
|
+
currentNodes: [],
|
|
3360
|
+
context: { ...context, _loop: loopContext },
|
|
3361
|
+
checkpoints: [],
|
|
3362
|
+
pendingApprovals: [],
|
|
3363
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
3364
|
+
});
|
|
3365
|
+
if (result.waiting) {
|
|
3366
|
+
Object.assign(nodeStates, result.nodeStates);
|
|
3367
|
+
const state2 = {
|
|
3368
|
+
nodeId: node.id,
|
|
3369
|
+
status: "running",
|
|
3370
|
+
output: {
|
|
3371
|
+
iteration,
|
|
3372
|
+
waiting: true,
|
|
3373
|
+
previousResults
|
|
3374
|
+
},
|
|
3375
|
+
attempt: 1,
|
|
3376
|
+
startedAt: new Date(startTime)
|
|
3377
|
+
};
|
|
3378
|
+
return {
|
|
3379
|
+
state: state2,
|
|
3380
|
+
contextUpdates: {
|
|
3381
|
+
...result.context,
|
|
3382
|
+
[`${node.id}_loop_state`]: { iteration, previousResults }
|
|
3383
|
+
},
|
|
3384
|
+
waiting: true
|
|
3385
|
+
};
|
|
3386
|
+
}
|
|
3387
|
+
if (result.error) {
|
|
3388
|
+
lastError = result.error;
|
|
3389
|
+
exitReason = "error";
|
|
3390
|
+
break;
|
|
3391
|
+
}
|
|
3392
|
+
previousResults.push(result.context);
|
|
3393
|
+
Object.assign(context, result.context);
|
|
3394
|
+
Object.assign(nodeStates, result.nodeStates);
|
|
3395
|
+
if (config.delay && iteration < config.maxIterations - 1) {
|
|
3396
|
+
const delayMs = typeof config.delay === "number" ? config.delay : this.parseDuration(config.delay);
|
|
3397
|
+
await this.sleep(delayMs);
|
|
3398
|
+
}
|
|
3399
|
+
iteration++;
|
|
3400
|
+
}
|
|
3401
|
+
if (iteration >= config.maxIterations && exitReason !== "condition") {
|
|
3402
|
+
exitReason = "maxIterations";
|
|
3403
|
+
}
|
|
3404
|
+
const finalLoopContext = {
|
|
3405
|
+
iteration,
|
|
3406
|
+
totalIterations: iteration,
|
|
3407
|
+
previousResults,
|
|
3408
|
+
isFirstIteration: false,
|
|
3409
|
+
isLastAllowedIteration: true
|
|
3410
|
+
};
|
|
3411
|
+
let completionUpdates = {};
|
|
3412
|
+
if (exitReason === "maxIterations" && config.onMaxIterations) {
|
|
3413
|
+
completionUpdates = await config.onMaxIterations(context, finalLoopContext);
|
|
3414
|
+
} else if (exitReason === "condition" && config.onComplete) {
|
|
3415
|
+
completionUpdates = await config.onComplete(context, finalLoopContext);
|
|
3416
|
+
}
|
|
3417
|
+
const output = {
|
|
3418
|
+
exitReason,
|
|
3419
|
+
iterations: iteration,
|
|
3420
|
+
previousResults,
|
|
3421
|
+
...completionUpdates
|
|
3422
|
+
};
|
|
3423
|
+
const state = {
|
|
3424
|
+
nodeId: node.id,
|
|
3425
|
+
status: exitReason === "error" ? "failed" : "completed",
|
|
3426
|
+
output,
|
|
3427
|
+
error: lastError,
|
|
3428
|
+
attempt: 1,
|
|
3429
|
+
startedAt: new Date(startTime),
|
|
3430
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
3431
|
+
};
|
|
3432
|
+
this.config.onNodeComplete?.(node.id, state);
|
|
3433
|
+
return {
|
|
3434
|
+
state,
|
|
3435
|
+
contextUpdates: {
|
|
3436
|
+
[node.id]: output,
|
|
3437
|
+
...completionUpdates
|
|
3438
|
+
},
|
|
3439
|
+
waiting: false
|
|
3440
|
+
};
|
|
3441
|
+
}
|
|
3442
|
+
/**
|
|
3443
|
+
* Parse duration string to milliseconds
|
|
3444
|
+
*/
|
|
3445
|
+
parseDuration(duration) {
|
|
3446
|
+
if (typeof duration === "number")
|
|
3447
|
+
return duration;
|
|
3448
|
+
const match = duration.match(/^(\d+)(ms|s|m|h|d)$/);
|
|
3449
|
+
if (!match)
|
|
3450
|
+
return 0;
|
|
3451
|
+
const value = parseInt(match[1], 10);
|
|
3452
|
+
const unit = match[2];
|
|
3453
|
+
switch (unit) {
|
|
3454
|
+
case "ms":
|
|
3455
|
+
return value;
|
|
3456
|
+
case "s":
|
|
3457
|
+
return value * 1e3;
|
|
3458
|
+
case "m":
|
|
3459
|
+
return value * 60 * 1e3;
|
|
3460
|
+
case "h":
|
|
3461
|
+
return value * 60 * 60 * 1e3;
|
|
3462
|
+
case "d":
|
|
3463
|
+
return value * 24 * 60 * 60 * 1e3;
|
|
3464
|
+
default:
|
|
3465
|
+
return 0;
|
|
3466
|
+
}
|
|
3467
|
+
}
|
|
3468
|
+
/**
|
|
3469
|
+
* Sleep for specified milliseconds
|
|
3470
|
+
*/
|
|
3471
|
+
sleep(ms) {
|
|
3472
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3473
|
+
}
|
|
3202
3474
|
/**
|
|
3203
3475
|
* Execute a step node
|
|
3204
3476
|
*/
|
|
@@ -3593,6 +3865,12 @@ var CheckpointManager = class {
|
|
|
3593
3865
|
};
|
|
3594
3866
|
|
|
3595
3867
|
// src/ai/workflow/executor/step-executor.ts
|
|
3868
|
+
var DEFAULT_RETRY = {
|
|
3869
|
+
maxAttempts: 1,
|
|
3870
|
+
backoff: "exponential",
|
|
3871
|
+
initialDelay: 1e3,
|
|
3872
|
+
maxDelay: 3e4
|
|
3873
|
+
};
|
|
3596
3874
|
var DEFAULT_STEP_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
3597
3875
|
var StepExecutor = class {
|
|
3598
3876
|
constructor(config = {}) {
|
|
@@ -3602,7 +3880,7 @@ var StepExecutor = class {
|
|
|
3602
3880
|
};
|
|
3603
3881
|
}
|
|
3604
3882
|
/**
|
|
3605
|
-
* Execute a step node
|
|
3883
|
+
* Execute a step node with retry support
|
|
3606
3884
|
*/
|
|
3607
3885
|
async execute(node, context) {
|
|
3608
3886
|
const startTime = Date.now();
|
|
@@ -3612,30 +3890,96 @@ var StepExecutor = class {
|
|
|
3612
3890
|
`StepExecutor can only execute 'step' nodes, but node "${node.id}" has type '${config.type}'. This is likely a bug in the DAG executor routing.`
|
|
3613
3891
|
);
|
|
3614
3892
|
}
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3893
|
+
const retryConfig = { ...DEFAULT_RETRY, ...config.retry };
|
|
3894
|
+
const maxAttempts = retryConfig.maxAttempts ?? 1;
|
|
3895
|
+
let lastError;
|
|
3896
|
+
let attempt = 0;
|
|
3897
|
+
while (attempt < maxAttempts) {
|
|
3898
|
+
attempt++;
|
|
3899
|
+
try {
|
|
3900
|
+
const resolvedInput = await this.resolveInput(config.input, context);
|
|
3901
|
+
this.config.onStepStart?.(node.id, resolvedInput);
|
|
3902
|
+
const timeout = config.timeout ? parseDuration(config.timeout) : this.config.defaultTimeout;
|
|
3903
|
+
const output = await this.executeWithTimeout(
|
|
3904
|
+
() => this.executeStep(config, resolvedInput, context),
|
|
3905
|
+
timeout,
|
|
3906
|
+
node.id
|
|
3907
|
+
);
|
|
3908
|
+
this.config.onStepComplete?.(node.id, output);
|
|
3909
|
+
return {
|
|
3910
|
+
success: true,
|
|
3911
|
+
output,
|
|
3912
|
+
executionTime: Date.now() - startTime
|
|
3913
|
+
};
|
|
3914
|
+
} catch (error) {
|
|
3915
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
3916
|
+
const shouldRetry = attempt < maxAttempts && this.isRetryableError(lastError, retryConfig);
|
|
3917
|
+
if (shouldRetry) {
|
|
3918
|
+
const delay2 = this.calculateRetryDelay(attempt, retryConfig);
|
|
3919
|
+
await this.sleep(delay2);
|
|
3920
|
+
continue;
|
|
3921
|
+
}
|
|
3922
|
+
this.config.onStepError?.(node.id, lastError);
|
|
3923
|
+
return {
|
|
3924
|
+
success: false,
|
|
3925
|
+
error: lastError.message,
|
|
3926
|
+
executionTime: Date.now() - startTime
|
|
3927
|
+
};
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
return {
|
|
3931
|
+
success: false,
|
|
3932
|
+
error: lastError?.message ?? "Unknown error",
|
|
3933
|
+
executionTime: Date.now() - startTime
|
|
3934
|
+
};
|
|
3935
|
+
}
|
|
3936
|
+
/**
|
|
3937
|
+
* Check if error is retryable
|
|
3938
|
+
*/
|
|
3939
|
+
isRetryableError(error, config) {
|
|
3940
|
+
if (config.retryIf) {
|
|
3941
|
+
return config.retryIf(error);
|
|
3942
|
+
}
|
|
3943
|
+
const retryablePatterns = [
|
|
3944
|
+
/timeout/i,
|
|
3945
|
+
/ECONNRESET/i,
|
|
3946
|
+
/ECONNREFUSED/i,
|
|
3947
|
+
/ETIMEDOUT/i,
|
|
3948
|
+
/rate limit/i,
|
|
3949
|
+
/429/,
|
|
3950
|
+
/503/,
|
|
3951
|
+
/502/
|
|
3952
|
+
];
|
|
3953
|
+
return retryablePatterns.some((pattern) => pattern.test(error.message));
|
|
3954
|
+
}
|
|
3955
|
+
/**
|
|
3956
|
+
* Calculate retry delay based on backoff strategy
|
|
3957
|
+
*/
|
|
3958
|
+
calculateRetryDelay(attempt, config) {
|
|
3959
|
+
const initialDelay = config.initialDelay ?? 1e3;
|
|
3960
|
+
const maxDelay = config.maxDelay ?? 3e4;
|
|
3961
|
+
let delay2;
|
|
3962
|
+
switch (config.backoff) {
|
|
3963
|
+
case "exponential":
|
|
3964
|
+
delay2 = initialDelay * Math.pow(2, attempt - 1);
|
|
3965
|
+
break;
|
|
3966
|
+
case "linear":
|
|
3967
|
+
delay2 = initialDelay * attempt;
|
|
3968
|
+
break;
|
|
3969
|
+
case "fixed":
|
|
3970
|
+
default:
|
|
3971
|
+
delay2 = initialDelay;
|
|
3972
|
+
break;
|
|
3638
3973
|
}
|
|
3974
|
+
const jitter = delay2 * 0.1 * (Math.random() * 2 - 1);
|
|
3975
|
+
delay2 = Math.min(delay2 + jitter, maxDelay);
|
|
3976
|
+
return Math.floor(delay2);
|
|
3977
|
+
}
|
|
3978
|
+
/**
|
|
3979
|
+
* Sleep for specified milliseconds
|
|
3980
|
+
*/
|
|
3981
|
+
sleep(ms) {
|
|
3982
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3639
3983
|
}
|
|
3640
3984
|
/**
|
|
3641
3985
|
* Resolve step input from context
|
|
@@ -4621,7 +4965,35 @@ var WorkflowClient = class {
|
|
|
4621
4965
|
this.executor = new WorkflowExecutor({
|
|
4622
4966
|
backend: this.backend,
|
|
4623
4967
|
debug: this.debug,
|
|
4624
|
-
...config.executor
|
|
4968
|
+
...config.executor,
|
|
4969
|
+
onWaiting: async (run, nodeId) => {
|
|
4970
|
+
const nodeState = run.nodeStates[nodeId];
|
|
4971
|
+
if (!nodeState?.input) {
|
|
4972
|
+
if (this.debug) {
|
|
4973
|
+
console.log(`[WorkflowClient] No wait config found for node: ${nodeId}`);
|
|
4974
|
+
}
|
|
4975
|
+
return;
|
|
4976
|
+
}
|
|
4977
|
+
const input = nodeState.input;
|
|
4978
|
+
if (input.type !== "approval") {
|
|
4979
|
+
return;
|
|
4980
|
+
}
|
|
4981
|
+
const waitConfig = {
|
|
4982
|
+
type: "wait",
|
|
4983
|
+
waitType: "approval",
|
|
4984
|
+
message: input.message,
|
|
4985
|
+
payload: input.payload
|
|
4986
|
+
};
|
|
4987
|
+
try {
|
|
4988
|
+
await this.approvalManager.createApproval(run, nodeId, waitConfig, run.context);
|
|
4989
|
+
if (this.debug) {
|
|
4990
|
+
console.log(`[WorkflowClient] Created approval for node: ${nodeId}`);
|
|
4991
|
+
}
|
|
4992
|
+
} catch (error) {
|
|
4993
|
+
console.error(`[WorkflowClient] Failed to create approval:`, error);
|
|
4994
|
+
}
|
|
4995
|
+
config.executor?.onWaiting?.(run, nodeId);
|
|
4996
|
+
}
|
|
4625
4997
|
});
|
|
4626
4998
|
this.approvalManager = new ApprovalManager({
|
|
4627
4999
|
backend: this.backend,
|