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