taskmeld 0.1.1
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/LICENSE +18 -0
- package/README.md +172 -0
- package/README.zh-CN.md +172 -0
- package/dist/src/app/app-context-env.js +51 -0
- package/dist/src/app/create-app-context.js +127 -0
- package/dist/src/app/data-dir.js +29 -0
- package/dist/src/app/pipeline-config.js +105 -0
- package/dist/src/app/pipeline-plugin-config.js +2 -0
- package/dist/src/app/pipeline-registry.js +502 -0
- package/dist/src/app/pipeline-runtime.js +202 -0
- package/dist/src/app/runtime-store.js +151 -0
- package/dist/src/app/user-config.js +37 -0
- package/dist/src/artifacts/artifact-cleanup.js +192 -0
- package/dist/src/artifacts/artifact-index.js +262 -0
- package/dist/src/artifacts/artifact-rebuilder.js +120 -0
- package/dist/src/artifacts/storage-service.js +371 -0
- package/dist/src/cli/bootstrap.js +226 -0
- package/dist/src/cli/commands/agent.js +126 -0
- package/dist/src/cli/commands/artifact.js +175 -0
- package/dist/src/cli/commands/init.js +150 -0
- package/dist/src/cli/commands/pipeline/errors.js +37 -0
- package/dist/src/cli/commands/pipeline/result.js +179 -0
- package/dist/src/cli/commands/pipeline/selector.js +51 -0
- package/dist/src/cli/commands/pipeline/types.js +2 -0
- package/dist/src/cli/commands/pipeline/watch.js +67 -0
- package/dist/src/cli/commands/pipeline.js +339 -0
- package/dist/src/cli/commands/scheduler.js +81 -0
- package/dist/src/cli/commands/server.js +70 -0
- package/dist/src/cli/commands/system.js +21 -0
- package/dist/src/cli/errors.js +71 -0
- package/dist/src/cli/help.js +184 -0
- package/dist/src/cli/index.js +65 -0
- package/dist/src/cli/output.js +19 -0
- package/dist/src/cli/renderers/engine/json.js +67 -0
- package/dist/src/cli/renderers/engine/markdown.js +95 -0
- package/dist/src/cli/renderers/engine/types.js +2 -0
- package/dist/src/cli/renderers/engine/utils.js +32 -0
- package/dist/src/cli/renderers/index.js +27 -0
- package/dist/src/cli/renderers/specs/agent.js +78 -0
- package/dist/src/cli/renderers/specs/artifact.js +32 -0
- package/dist/src/cli/renderers/specs/index.js +36 -0
- package/dist/src/cli/renderers/specs/init.js +25 -0
- package/dist/src/cli/renderers/specs/pipeline.js +561 -0
- package/dist/src/cli/renderers/specs/scheduler.js +46 -0
- package/dist/src/cli/renderers/specs/server.js +38 -0
- package/dist/src/cli/renderers/specs/system.js +36 -0
- package/dist/src/cli/router.js +199 -0
- package/dist/src/cli/server-runtime-client.js +780 -0
- package/dist/src/cli/types.js +2 -0
- package/dist/src/gateway/frame-sanitizer.js +78 -0
- package/dist/src/gateway/gateway-client.js +462 -0
- package/dist/src/gateway/index.js +18 -0
- package/dist/src/gateway/types.js +2 -0
- package/dist/src/index.js +123 -0
- package/dist/src/logs/run-log-reader.js +141 -0
- package/dist/src/logs/run-log-service.js +42 -0
- package/dist/src/logs/run-log-types.js +2 -0
- package/dist/src/pipeline/agent-activity.js +191 -0
- package/dist/src/pipeline/artifact-storage.js +208 -0
- package/dist/src/pipeline/diagnostics/dependency-diagnostic.js +105 -0
- package/dist/src/pipeline/diagnostics/index.js +6 -0
- package/dist/src/pipeline/dispatch/pipeline-inbound-queue.js +215 -0
- package/dist/src/pipeline/dispatch/pipeline-link-dispatcher.js +66 -0
- package/dist/src/pipeline/dispatch/pipeline-link-store.js +94 -0
- package/dist/src/pipeline/dispatch/pipeline-queue-drainer.js +71 -0
- package/dist/src/pipeline/execution/dependency-check.js +52 -0
- package/dist/src/pipeline/execution/execution-result.js +2 -0
- package/dist/src/pipeline/execution/group-item-executor.js +128 -0
- package/dist/src/pipeline/execution/index.js +5 -0
- package/dist/src/pipeline/execution/node-item-executor.js +58 -0
- package/dist/src/pipeline/execution/node-runner.js +159 -0
- package/dist/src/pipeline/execution/readiness-state.js +10 -0
- package/dist/src/pipeline/execution/reject-handler.js +94 -0
- package/dist/src/pipeline/execution/rejected-artifact-archiver.js +45 -0
- package/dist/src/pipeline/execution/route-item-manager.js +253 -0
- package/dist/src/pipeline/execution/run-abort-controller.js +66 -0
- package/dist/src/pipeline/execution/run-state-helpers.js +257 -0
- package/dist/src/pipeline/execution/service.js +165 -0
- package/dist/src/pipeline/execution/session-registry.js +96 -0
- package/dist/src/pipeline/execution/structured-node-runner.js +411 -0
- package/dist/src/pipeline/execution-status.js +96 -0
- package/dist/src/pipeline/execution-timeout.js +21 -0
- package/dist/src/pipeline/identity/index.js +32 -0
- package/dist/src/pipeline/identity/types.js +2 -0
- package/dist/src/pipeline/item-batch-controller.js +227 -0
- package/dist/src/pipeline/output/pipeline-output-resolver.js +91 -0
- package/dist/src/pipeline/output/pipeline-output-store.js +60 -0
- package/dist/src/pipeline/runtime-model.js +173 -0
- package/dist/src/pipeline/scheduler/dependency-state.js +144 -0
- package/dist/src/pipeline/scheduler-service.js +314 -0
- package/dist/src/pipeline/state/group-item-state.js +50 -0
- package/dist/src/pipeline/state/group-run-state.js +41 -0
- package/dist/src/pipeline/state/index.js +20 -0
- package/dist/src/pipeline/state/node-item-state.js +67 -0
- package/dist/src/pipeline/state/node-run-state.js +51 -0
- package/dist/src/pipeline/state/types.js +2 -0
- package/dist/src/pipeline/state-machine.js +101 -0
- package/dist/src/pipeline/structured-output/contract.js +133 -0
- package/dist/src/pipeline/structured-output/index.js +22 -0
- package/dist/src/pipeline/structured-output/parser.js +214 -0
- package/dist/src/pipeline/structured-output/prompt.js +290 -0
- package/dist/src/pipeline/structured-output/waiter.js +139 -0
- package/dist/src/pipeline/template.js +135 -0
- package/dist/src/pipeline/timeline-log-store.js +57 -0
- package/dist/src/pipeline/tool-activity.js +94 -0
- package/dist/src/pipeline/types/pipeline-link.js +7 -0
- package/dist/src/pipeline/types/pipeline-output.js +11 -0
- package/dist/src/pipeline/types/workflow.js +2 -0
- package/dist/src/pipeline/workflow/branch-rules.js +74 -0
- package/dist/src/pipeline/workflow/defaults.js +48 -0
- package/dist/src/pipeline/workflow/io.js +89 -0
- package/dist/src/pipeline/workflow/normalize.js +347 -0
- package/dist/src/pipeline/workflow/routes.js +16 -0
- package/dist/src/pipeline/workflow/template-mapper.js +113 -0
- package/dist/src/pipeline/workflow/validate.js +312 -0
- package/dist/src/pipeline/workflow-graph.js +165 -0
- package/dist/src/server/api-handler.js +163 -0
- package/dist/src/server/http-utils.js +34 -0
- package/dist/src/server/middleware.js +61 -0
- package/dist/src/server/router.js +105 -0
- package/dist/src/server/routes/agents.js +189 -0
- package/dist/src/server/routes/artifacts.js +163 -0
- package/dist/src/server/routes/gateway.js +18 -0
- package/dist/src/server/routes/health.js +16 -0
- package/dist/src/server/routes/logs.js +73 -0
- package/dist/src/server/routes/pipeline-batch.js +163 -0
- package/dist/src/server/routes/pipeline-diagnostics.js +33 -0
- package/dist/src/server/routes/pipeline-identity.js +24 -0
- package/dist/src/server/routes/pipeline-links.js +117 -0
- package/dist/src/server/routes/pipeline-outputs.js +27 -0
- package/dist/src/server/routes/pipeline-queue.js +62 -0
- package/dist/src/server/routes/pipeline-runtime.js +162 -0
- package/dist/src/server/routes/pipeline-scheduler.js +69 -0
- package/dist/src/server/routes/pipeline-workflow.js +180 -0
- package/dist/src/server/routes/pipelines.js +96 -0
- package/dist/src/server/routes/sessions.js +244 -0
- package/dist/src/server/routes/timeline.js +14 -0
- package/dist/src/server/serve-static.js +42 -0
- package/dist/src/server/types.js +2 -0
- package/dist/src/services/agent-service.js +79 -0
- package/dist/src/services/artifact-service.js +74 -0
- package/dist/src/services/gateway-read-helpers.js +10 -0
- package/dist/src/services/index.js +23 -0
- package/dist/src/services/pipeline-service.js +529 -0
- package/dist/src/services/pipeline-status.js +93 -0
- package/dist/src/services/read-services.js +60 -0
- package/dist/src/services/scheduler-service.js +37 -0
- package/dist/src/services/session-service.js +227 -0
- package/dist/src/services/system-service.js +26 -0
- package/dist/src/transport/ws-broker.js +48 -0
- package/dist/src/utils/array.js +17 -0
- package/dist/src/utils/guards.js +5 -0
- package/dist/src/utils/session.js +60 -0
- package/dist/src/version.js +5 -0
- package/package.json +61 -0
- package/web/dist/assets/index-CWnfhkn-.js +65 -0
- package/web/dist/assets/index-gZ0xOfSO.css +1 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-700-normal-BWTpRfYl.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-700-normal-CEoEElIJ.woff +0 -0
- package/web/dist/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/web/dist/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
- package/web/dist/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-greek-700-normal-C6CZE3T8.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-greek-700-normal-DEigVDxa.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-700-normal-CZipNAKV.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-700-normal-CxPITLHs.woff +0 -0
- package/web/dist/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/web/dist/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
- package/web/dist/assets/jetbrains-mono-vietnamese-700-normal-BDLVIk2r.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-400-normal-BnQMeOim.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-400-normal-CJ-V5oYT.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-500-normal-CNSSEhBt.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-700-normal-CwsQ-cCU.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-700-normal-RjhwGPKo.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-400-normal-CfP_5XZW.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-400-normal-DRPE3kg4.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-500-normal-3dgZTiw9.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-500-normal-DUe3BAxM.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-700-normal-BQnZhY3m.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-700-normal-HVCqSBdx.woff +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-400-normal-B7xT_GF5.woff2 +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-400-normal-BIWiOVfw.woff +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-500-normal-BTqKIpxg.woff +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-500-normal-BmEvtly_.woff2 +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-700-normal-DMty7AZE.woff2 +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-700-normal-Duxec5Rn.woff +0 -0
- package/web/dist/favicon.svg +10 -0
- package/web/dist/index.html +14 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.markGroupReset = exports.markGroupWaiting = exports.markGroupBlocked = exports.markGroupFailed = exports.markGroupSuccess = exports.markGroupRunning = exports.markGroupQueued = void 0;
|
|
4
|
+
const state_machine_1 = require("../state-machine");
|
|
5
|
+
const now = (ctx) => ctx.now ?? new Date().toISOString();
|
|
6
|
+
const markGroupQueued = (group, ctx) => {
|
|
7
|
+
group.status = (0, state_machine_1.transitionStatus)(group.status, "queued", ctx.command);
|
|
8
|
+
};
|
|
9
|
+
exports.markGroupQueued = markGroupQueued;
|
|
10
|
+
const markGroupRunning = (group, ctx) => {
|
|
11
|
+
group.status = (0, state_machine_1.transitionStatus)(group.status, "running", ctx.command);
|
|
12
|
+
group.startedAt = now(ctx);
|
|
13
|
+
};
|
|
14
|
+
exports.markGroupRunning = markGroupRunning;
|
|
15
|
+
const markGroupSuccess = (group, ctx) => {
|
|
16
|
+
group.status = (0, state_machine_1.transitionStatus)(group.status, "success", ctx.command);
|
|
17
|
+
group.finishedAt = now(ctx);
|
|
18
|
+
group.lastError = null;
|
|
19
|
+
};
|
|
20
|
+
exports.markGroupSuccess = markGroupSuccess;
|
|
21
|
+
const markGroupFailed = (group, ctx) => {
|
|
22
|
+
group.status = (0, state_machine_1.transitionStatus)(group.status, "failed", ctx.command);
|
|
23
|
+
group.finishedAt = now(ctx);
|
|
24
|
+
group.lastError = ctx.error ?? null;
|
|
25
|
+
};
|
|
26
|
+
exports.markGroupFailed = markGroupFailed;
|
|
27
|
+
const markGroupBlocked = (group, ctx) => {
|
|
28
|
+
group.status = (0, state_machine_1.transitionStatus)(group.status, "blocked", ctx.command);
|
|
29
|
+
};
|
|
30
|
+
exports.markGroupBlocked = markGroupBlocked;
|
|
31
|
+
const markGroupWaiting = (group, ctx) => {
|
|
32
|
+
group.status = (0, state_machine_1.transitionStatus)(group.status, "waiting", ctx.command);
|
|
33
|
+
};
|
|
34
|
+
exports.markGroupWaiting = markGroupWaiting;
|
|
35
|
+
const markGroupReset = (group, targetStatus, ctx) => {
|
|
36
|
+
group.status = (0, state_machine_1.transitionStatus)(group.status, targetStatus, ctx.command);
|
|
37
|
+
group.startedAt = null;
|
|
38
|
+
group.finishedAt = null;
|
|
39
|
+
group.lastError = null;
|
|
40
|
+
};
|
|
41
|
+
exports.markGroupReset = markGroupReset;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./node-item-state"), exports);
|
|
18
|
+
__exportStar(require("./node-run-state"), exports);
|
|
19
|
+
__exportStar(require("./group-item-state"), exports);
|
|
20
|
+
__exportStar(require("./group-run-state"), exports);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.markItemReset = exports.markItemWakeSuccess = exports.markItemBlocked = exports.markItemWaiting = exports.markItemSkipped = exports.markItemRejected = exports.markItemFailed = exports.markItemSuccess = exports.markItemRunning = exports.markItemQueued = void 0;
|
|
4
|
+
const state_machine_1 = require("../state-machine");
|
|
5
|
+
const now = (ctx) => ctx.now ?? new Date().toISOString();
|
|
6
|
+
const markItemQueued = (item, ctx) => {
|
|
7
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, "queued", ctx.command);
|
|
8
|
+
};
|
|
9
|
+
exports.markItemQueued = markItemQueued;
|
|
10
|
+
const markItemRunning = (item, ctx) => {
|
|
11
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, "running", ctx.command);
|
|
12
|
+
item.attempt += 1;
|
|
13
|
+
item.startedAt = now(ctx);
|
|
14
|
+
item.finishedAt = null;
|
|
15
|
+
item.lastError = null;
|
|
16
|
+
item.wakeAt = null;
|
|
17
|
+
};
|
|
18
|
+
exports.markItemRunning = markItemRunning;
|
|
19
|
+
const markItemSuccess = (item, ctx) => {
|
|
20
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, "success", ctx.command);
|
|
21
|
+
item.finishedAt = now(ctx);
|
|
22
|
+
item.lastError = null;
|
|
23
|
+
};
|
|
24
|
+
exports.markItemSuccess = markItemSuccess;
|
|
25
|
+
const markItemFailed = (item, ctx) => {
|
|
26
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, "failed", ctx.command);
|
|
27
|
+
item.finishedAt = now(ctx);
|
|
28
|
+
item.lastError = ctx.error ?? null;
|
|
29
|
+
};
|
|
30
|
+
exports.markItemFailed = markItemFailed;
|
|
31
|
+
const markItemRejected = (item, ctx) => {
|
|
32
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, "rejected", ctx.command);
|
|
33
|
+
item.finishedAt = now(ctx);
|
|
34
|
+
item.lastError = ctx.error ?? null;
|
|
35
|
+
};
|
|
36
|
+
exports.markItemRejected = markItemRejected;
|
|
37
|
+
const markItemSkipped = (item, ctx) => {
|
|
38
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, "skipped", ctx.command);
|
|
39
|
+
item.wakeAt = null;
|
|
40
|
+
item.finishedAt = now(ctx);
|
|
41
|
+
item.lastError = null;
|
|
42
|
+
};
|
|
43
|
+
exports.markItemSkipped = markItemSkipped;
|
|
44
|
+
const markItemWaiting = (item, ctx) => {
|
|
45
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, "waiting", ctx.command);
|
|
46
|
+
if (ctx.wakeAt)
|
|
47
|
+
item.wakeAt = ctx.wakeAt;
|
|
48
|
+
};
|
|
49
|
+
exports.markItemWaiting = markItemWaiting;
|
|
50
|
+
const markItemBlocked = (item, ctx) => {
|
|
51
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, "blocked", ctx.command);
|
|
52
|
+
};
|
|
53
|
+
exports.markItemBlocked = markItemBlocked;
|
|
54
|
+
const markItemWakeSuccess = (item, ctx) => {
|
|
55
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, "success", ctx.command);
|
|
56
|
+
item.wakeAt = null;
|
|
57
|
+
item.finishedAt = now(ctx);
|
|
58
|
+
};
|
|
59
|
+
exports.markItemWakeSuccess = markItemWakeSuccess;
|
|
60
|
+
const markItemReset = (item, targetStatus, ctx) => {
|
|
61
|
+
item.status = (0, state_machine_1.transitionStatus)(item.status, targetStatus, ctx.command);
|
|
62
|
+
item.startedAt = null;
|
|
63
|
+
item.finishedAt = targetStatus === "skipped" ? now(ctx) : null;
|
|
64
|
+
item.lastError = null;
|
|
65
|
+
item.wakeAt = null;
|
|
66
|
+
};
|
|
67
|
+
exports.markItemReset = markItemReset;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.markNodeWaiting = exports.markNodeBlocked = exports.markNodeSkipped = exports.markNodeRejected = exports.markNodeFailed = exports.markNodeSuccess = exports.markNodeRunning = exports.markNodeQueued = void 0;
|
|
4
|
+
const state_machine_1 = require("../state-machine");
|
|
5
|
+
const now = (ctx) => ctx.now ?? new Date().toISOString();
|
|
6
|
+
const markNodeQueued = (node, ctx) => {
|
|
7
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, "queued", ctx.command);
|
|
8
|
+
};
|
|
9
|
+
exports.markNodeQueued = markNodeQueued;
|
|
10
|
+
const markNodeRunning = (node, ctx) => {
|
|
11
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, "running", ctx.command);
|
|
12
|
+
node.attempt += 1;
|
|
13
|
+
node.startedAt = now(ctx);
|
|
14
|
+
node.finishedAt = null;
|
|
15
|
+
node.lastError = null;
|
|
16
|
+
};
|
|
17
|
+
exports.markNodeRunning = markNodeRunning;
|
|
18
|
+
const markNodeSuccess = (node, ctx) => {
|
|
19
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, "success", ctx.command);
|
|
20
|
+
node.finishedAt = now(ctx);
|
|
21
|
+
node.lastError = null;
|
|
22
|
+
if (ctx.artifacts)
|
|
23
|
+
node.artifacts = ctx.artifacts;
|
|
24
|
+
};
|
|
25
|
+
exports.markNodeSuccess = markNodeSuccess;
|
|
26
|
+
const markNodeFailed = (node, ctx) => {
|
|
27
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, "failed", ctx.command);
|
|
28
|
+
node.finishedAt = now(ctx);
|
|
29
|
+
node.lastError = ctx.error ?? null;
|
|
30
|
+
};
|
|
31
|
+
exports.markNodeFailed = markNodeFailed;
|
|
32
|
+
const markNodeRejected = (node, ctx) => {
|
|
33
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, "rejected", ctx.command);
|
|
34
|
+
node.finishedAt = now(ctx);
|
|
35
|
+
node.lastError = ctx.error ?? null;
|
|
36
|
+
};
|
|
37
|
+
exports.markNodeRejected = markNodeRejected;
|
|
38
|
+
const markNodeSkipped = (node, ctx) => {
|
|
39
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, "skipped", ctx.command);
|
|
40
|
+
node.finishedAt = now(ctx);
|
|
41
|
+
node.lastError = null;
|
|
42
|
+
};
|
|
43
|
+
exports.markNodeSkipped = markNodeSkipped;
|
|
44
|
+
const markNodeBlocked = (node, ctx) => {
|
|
45
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, "blocked", ctx.command);
|
|
46
|
+
};
|
|
47
|
+
exports.markNodeBlocked = markNodeBlocked;
|
|
48
|
+
const markNodeWaiting = (node, ctx) => {
|
|
49
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, "waiting", ctx.command);
|
|
50
|
+
};
|
|
51
|
+
exports.markNodeWaiting = markNodeWaiting;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transitionStatus = exports.IllegalStateTransitionError = exports.VALID_TRANSITIONS = void 0;
|
|
4
|
+
exports.VALID_TRANSITIONS = {
|
|
5
|
+
queued: {
|
|
6
|
+
execute: ["running", "failed"],
|
|
7
|
+
dependency: ["waiting", "blocked", "skipped"],
|
|
8
|
+
group_aggregate: ["running", "failed", "waiting", "blocked", "skipped"],
|
|
9
|
+
retry_reset: ["queued"],
|
|
10
|
+
reject_reset: ["queued"],
|
|
11
|
+
route_backfill: ["running", "success", "failed", "rejected", "waiting", "skipped", "blocked"],
|
|
12
|
+
},
|
|
13
|
+
running: {
|
|
14
|
+
execute: ["success", "failed", "rejected", "waiting"],
|
|
15
|
+
group_aggregate: ["success", "failed", "rejected", "waiting", "queued", "blocked", "skipped"],
|
|
16
|
+
retry_reset: ["queued", "blocked", "skipped"],
|
|
17
|
+
reject_reset: ["queued", "blocked", "skipped"],
|
|
18
|
+
},
|
|
19
|
+
waiting: {
|
|
20
|
+
sleep: ["success"],
|
|
21
|
+
dependency: ["queued", "skipped", "blocked"],
|
|
22
|
+
group_aggregate: ["success", "queued", "skipped", "blocked"],
|
|
23
|
+
retry_reset: ["queued"],
|
|
24
|
+
reject_reset: ["queued"],
|
|
25
|
+
},
|
|
26
|
+
blocked: {
|
|
27
|
+
dependency: ["queued", "waiting", "skipped"],
|
|
28
|
+
group_aggregate: ["running", "success", "failed", "rejected", "queued", "waiting", "blocked"],
|
|
29
|
+
route_backfill: ["running", "success", "failed", "rejected", "skipped", "queued", "waiting", "blocked"],
|
|
30
|
+
retry_reset: ["queued", "skipped"],
|
|
31
|
+
reject_reset: ["queued", "skipped"],
|
|
32
|
+
},
|
|
33
|
+
success: {
|
|
34
|
+
sleep: ["waiting"],
|
|
35
|
+
dependency: ["queued", "blocked", "skipped"],
|
|
36
|
+
group_aggregate: ["queued", "blocked", "skipped", "waiting"],
|
|
37
|
+
retry_reset: ["queued", "blocked", "skipped"],
|
|
38
|
+
reject_reset: ["queued", "blocked", "skipped"],
|
|
39
|
+
route_backfill: ["success", "running", "failed", "rejected", "queued", "blocked", "skipped", "waiting"],
|
|
40
|
+
},
|
|
41
|
+
failed: {
|
|
42
|
+
dependency: ["queued", "blocked", "skipped"],
|
|
43
|
+
group_aggregate: ["queued", "blocked", "skipped"],
|
|
44
|
+
retry_reset: ["queued", "blocked", "running"],
|
|
45
|
+
reject_reset: ["queued", "blocked"],
|
|
46
|
+
sleep: ["waiting"],
|
|
47
|
+
route_backfill: ["success"],
|
|
48
|
+
},
|
|
49
|
+
rejected: {
|
|
50
|
+
dependency: ["queued", "blocked", "skipped"],
|
|
51
|
+
group_aggregate: ["queued", "blocked", "skipped"],
|
|
52
|
+
retry_reset: ["queued", "blocked"],
|
|
53
|
+
reject_reset: ["queued", "blocked"],
|
|
54
|
+
sleep: ["waiting"],
|
|
55
|
+
route_backfill: ["success"],
|
|
56
|
+
},
|
|
57
|
+
skipped: {
|
|
58
|
+
dependency: ["queued", "blocked"],
|
|
59
|
+
group_aggregate: ["queued", "blocked"],
|
|
60
|
+
retry_reset: ["queued", "blocked"],
|
|
61
|
+
route_backfill: ["running", "success", "failed", "rejected", "queued", "blocked", "skipped", "waiting"],
|
|
62
|
+
},
|
|
63
|
+
stopped: {
|
|
64
|
+
retry_reset: ["queued", "blocked", "skipped"],
|
|
65
|
+
reject_reset: ["queued", "blocked", "skipped"],
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
class IllegalStateTransitionError extends Error {
|
|
69
|
+
current;
|
|
70
|
+
next;
|
|
71
|
+
command;
|
|
72
|
+
constructor(current, next, command) {
|
|
73
|
+
const cmdInfo = command ? ` (command: ${command})` : "";
|
|
74
|
+
super(`Illegal state transition: "${current}" -> "${next}"${cmdInfo}`);
|
|
75
|
+
this.name = "IllegalStateTransitionError";
|
|
76
|
+
this.current = current;
|
|
77
|
+
this.next = next;
|
|
78
|
+
this.command = command;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.IllegalStateTransitionError = IllegalStateTransitionError;
|
|
82
|
+
const transitionStatus = (current, next, command) => {
|
|
83
|
+
if (current === next)
|
|
84
|
+
return current;
|
|
85
|
+
const allowedByCommand = exports.VALID_TRANSITIONS[current];
|
|
86
|
+
// 未指定 command 时仅允许 execute + dependency 权限(安全默认值),
|
|
87
|
+
// 特殊权限(route_backfill/retry_reset/reject_reset/sleep/group_aggregate)必须显式传 command。
|
|
88
|
+
const allowed = command
|
|
89
|
+
? (allowedByCommand[command] ?? [])
|
|
90
|
+
: [
|
|
91
|
+
...new Set([
|
|
92
|
+
...(allowedByCommand["execute"] ?? []),
|
|
93
|
+
...(allowedByCommand["dependency"] ?? []),
|
|
94
|
+
]),
|
|
95
|
+
];
|
|
96
|
+
if (!allowed.includes(next)) {
|
|
97
|
+
throw new IllegalStateTransitionError(current, next, command);
|
|
98
|
+
}
|
|
99
|
+
return next;
|
|
100
|
+
};
|
|
101
|
+
exports.transitionStatus = transitionStatus;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateEnvelope = exports.normalizeAllowedRoute = exports.normalizeSchemaVersion = exports.isRecord = void 0;
|
|
4
|
+
const guards_1 = require("../../utils/guards");
|
|
5
|
+
Object.defineProperty(exports, "isRecord", { enumerable: true, get: function () { return guards_1.isRecord; } });
|
|
6
|
+
const normalizeSchemaVersion = (value) => {
|
|
7
|
+
if (typeof value === "number") {
|
|
8
|
+
if (Number.isFinite(value) && Number.isSafeInteger(value))
|
|
9
|
+
return value;
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
if (typeof value !== "string")
|
|
13
|
+
return null;
|
|
14
|
+
const trimmed = value.trim();
|
|
15
|
+
// 兼容模型把 schemaVersion 输出成字符串数字(例如 "1")的场景。
|
|
16
|
+
if (!/^\d+$/.test(trimmed))
|
|
17
|
+
return null;
|
|
18
|
+
const parsed = Number(trimmed);
|
|
19
|
+
if (!Number.isFinite(parsed) || !Number.isSafeInteger(parsed))
|
|
20
|
+
return null;
|
|
21
|
+
return parsed;
|
|
22
|
+
};
|
|
23
|
+
exports.normalizeSchemaVersion = normalizeSchemaVersion;
|
|
24
|
+
const normalizeAllowedRoute = (rawRoute, allowedRoutes) => {
|
|
25
|
+
if (typeof rawRoute !== "string")
|
|
26
|
+
return null;
|
|
27
|
+
const trimmed = rawRoute.trim();
|
|
28
|
+
if (!trimmed)
|
|
29
|
+
return null;
|
|
30
|
+
if (!allowedRoutes || allowedRoutes.length === 0)
|
|
31
|
+
return trimmed;
|
|
32
|
+
const direct = allowedRoutes.find((route) => route === trimmed);
|
|
33
|
+
if (direct)
|
|
34
|
+
return direct;
|
|
35
|
+
const lower = trimmed.toLowerCase();
|
|
36
|
+
// 允许大小写不一致,统一纠正为工作流里声明的 route,避免无意义失败。
|
|
37
|
+
const insensitive = allowedRoutes.find((route) => route.toLowerCase() === lower);
|
|
38
|
+
return insensitive ?? null;
|
|
39
|
+
};
|
|
40
|
+
exports.normalizeAllowedRoute = normalizeAllowedRoute;
|
|
41
|
+
const isJsonValue = (value, depth = 0) => {
|
|
42
|
+
if (depth > 20)
|
|
43
|
+
return false;
|
|
44
|
+
if (value === null)
|
|
45
|
+
return true;
|
|
46
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
|
47
|
+
return true;
|
|
48
|
+
if (Array.isArray(value)) {
|
|
49
|
+
return value.every((item) => isJsonValue(item, depth + 1));
|
|
50
|
+
}
|
|
51
|
+
if (!(0, guards_1.isRecord)(value))
|
|
52
|
+
return false;
|
|
53
|
+
return Object.values(value).every((item) => isJsonValue(item, depth + 1));
|
|
54
|
+
};
|
|
55
|
+
const isEmptyArtifactContent = (value) => {
|
|
56
|
+
if (value === null)
|
|
57
|
+
return true;
|
|
58
|
+
if (typeof value === "string")
|
|
59
|
+
return value.trim().length === 0;
|
|
60
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
61
|
+
return false;
|
|
62
|
+
if (Array.isArray(value))
|
|
63
|
+
return value.length === 0 || value.every((item) => isEmptyArtifactContent(item));
|
|
64
|
+
const entries = Object.values(value);
|
|
65
|
+
return entries.length === 0 || entries.every((item) => isEmptyArtifactContent(item));
|
|
66
|
+
};
|
|
67
|
+
const validateEnvelope = (envelope, ctx) => {
|
|
68
|
+
if (envelope.runId !== ctx.runId)
|
|
69
|
+
return { ok: false, code: "run_id_mismatch" };
|
|
70
|
+
if (envelope.nodeId !== ctx.nodeId)
|
|
71
|
+
return { ok: false, code: "node_id_mismatch" };
|
|
72
|
+
if (envelope.requestId !== ctx.requestId)
|
|
73
|
+
return { ok: false, code: "request_id_mismatch" };
|
|
74
|
+
if (envelope.sessionId !== ctx.sessionId)
|
|
75
|
+
return { ok: false, code: "session_id_mismatch" };
|
|
76
|
+
if (!Array.isArray(envelope.artifacts))
|
|
77
|
+
return { ok: false, code: "artifacts_invalid" };
|
|
78
|
+
if (envelope.status === "success" && envelope.artifacts.length === 0) {
|
|
79
|
+
return { ok: false, code: "artifacts_required" };
|
|
80
|
+
}
|
|
81
|
+
const spec = ctx.outputSpec;
|
|
82
|
+
for (const artifact of envelope.artifacts) {
|
|
83
|
+
if (!(0, guards_1.isRecord)(artifact))
|
|
84
|
+
return { ok: false, code: "artifact_invalid" };
|
|
85
|
+
if (typeof artifact.type !== "string" || !artifact.type)
|
|
86
|
+
return { ok: false, code: "artifact_type_invalid" };
|
|
87
|
+
const normalizedSchemaVersion = (0, exports.normalizeSchemaVersion)(artifact.schemaVersion);
|
|
88
|
+
if (normalizedSchemaVersion === null)
|
|
89
|
+
return { ok: false, code: "artifact_schema_invalid" };
|
|
90
|
+
artifact.schemaVersion = normalizedSchemaVersion;
|
|
91
|
+
if (!isJsonValue(artifact.content))
|
|
92
|
+
return { ok: false, code: "artifact_content_invalid" };
|
|
93
|
+
if (envelope.status === "success" && isEmptyArtifactContent(artifact.content))
|
|
94
|
+
return { ok: false, code: "artifact_content_invalid" };
|
|
95
|
+
if (artifact.type !== spec.type || artifact.schemaVersion !== spec.schemaVersion) {
|
|
96
|
+
return { ok: false, code: "artifact_spec_mismatch" };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// 兼容历史/冗余字段:顶层 route、decisions 不再作为硬失败条件,忽略即可。
|
|
100
|
+
if (envelope.control !== undefined) {
|
|
101
|
+
if (!(0, guards_1.isRecord)(envelope.control))
|
|
102
|
+
return { ok: false, code: "hold_control_invalid" };
|
|
103
|
+
const sleepUntil = envelope.control.sleepUntil;
|
|
104
|
+
if (sleepUntil !== undefined && sleepUntil !== null) {
|
|
105
|
+
if (typeof sleepUntil !== "string" || !sleepUntil.trim() || !Number.isFinite(Date.parse(sleepUntil))) {
|
|
106
|
+
return { ok: false, code: "hold_control_invalid" };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (ctx.requireRouteContent && envelope.status === "success") {
|
|
111
|
+
const primaryArtifact = envelope.artifacts[0];
|
|
112
|
+
if (!primaryArtifact) {
|
|
113
|
+
return { ok: false, code: "route_content_invalid" };
|
|
114
|
+
}
|
|
115
|
+
if (!Array.isArray(primaryArtifact.content) && (0, guards_1.isRecord)(primaryArtifact.content)) {
|
|
116
|
+
// 兼容单对象输出,统一纠正为数组,后续分流逻辑保持一致。
|
|
117
|
+
primaryArtifact.content = [primaryArtifact.content];
|
|
118
|
+
}
|
|
119
|
+
if (!Array.isArray(primaryArtifact.content) || primaryArtifact.content.length === 0) {
|
|
120
|
+
return { ok: false, code: "route_content_invalid" };
|
|
121
|
+
}
|
|
122
|
+
for (const entry of primaryArtifact.content) {
|
|
123
|
+
if (!(0, guards_1.isRecord)(entry))
|
|
124
|
+
return { ok: false, code: "route_content_invalid" };
|
|
125
|
+
const route = (0, exports.normalizeAllowedRoute)(entry.route, ctx.allowedRoutes);
|
|
126
|
+
if (!route)
|
|
127
|
+
return { ok: false, code: "route_content_invalid" };
|
|
128
|
+
entry.route = route;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { ok: true };
|
|
132
|
+
};
|
|
133
|
+
exports.validateEnvelope = validateEnvelope;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// 目录出口:调用方继续从 structured-output 子模块导入,内部文件按职责拆分。
|
|
18
|
+
// 统一从这里 re-export,避免后续再次拆分时把外部 import 路径扩散到实现细节。
|
|
19
|
+
__exportStar(require("./contract"), exports);
|
|
20
|
+
__exportStar(require("./parser"), exports);
|
|
21
|
+
__exportStar(require("./prompt"), exports);
|
|
22
|
+
__exportStar(require("./waiter"), exports);
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.collectEnvelopeCandidates = exports.detectFenceLanguage = exports.toPromptContentText = void 0;
|
|
4
|
+
const guards_1 = require("../../utils/guards");
|
|
5
|
+
const contract_1 = require("./contract");
|
|
6
|
+
const truncateText = (text, maxChars) => text.length > maxChars ? `${text.slice(0, maxChars)}\n...[truncated]` : text;
|
|
7
|
+
const toPromptContentText = (content) => {
|
|
8
|
+
if (typeof content === "string")
|
|
9
|
+
return truncateText(content, 8_000);
|
|
10
|
+
try {
|
|
11
|
+
return truncateText(JSON.stringify(content, null, 2), 8_000);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return truncateText(String(content), 8_000);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
exports.toPromptContentText = toPromptContentText;
|
|
18
|
+
const detectFenceLanguage = (content) => {
|
|
19
|
+
const trimmed = content.trim();
|
|
20
|
+
if (!trimmed)
|
|
21
|
+
return "text";
|
|
22
|
+
try {
|
|
23
|
+
JSON.parse(trimmed);
|
|
24
|
+
return "json";
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return "text";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
exports.detectFenceLanguage = detectFenceLanguage;
|
|
31
|
+
const extractBalancedJsonObjectCandidates = (text) => {
|
|
32
|
+
const candidates = [];
|
|
33
|
+
const seen = new Set();
|
|
34
|
+
// 流式输出常出现“说明文字 + JSON”拼接在同一段文本中的情况。
|
|
35
|
+
// 这里通过括号平衡扫描抽取内嵌 JSON 对象,避免整段 JSON.parse 直接失败。
|
|
36
|
+
for (let start = text.indexOf("{"); start >= 0; start = text.indexOf("{", start + 1)) {
|
|
37
|
+
let depth = 0;
|
|
38
|
+
let inString = false;
|
|
39
|
+
let escaped = false;
|
|
40
|
+
for (let i = start; i < text.length; i += 1) {
|
|
41
|
+
const char = text[i];
|
|
42
|
+
if (inString) {
|
|
43
|
+
if (escaped) {
|
|
44
|
+
escaped = false;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (char === "\\") {
|
|
48
|
+
escaped = true;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (char === "\"") {
|
|
52
|
+
inString = false;
|
|
53
|
+
}
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (char === "\"") {
|
|
57
|
+
inString = true;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (char === "{") {
|
|
61
|
+
depth += 1;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (char !== "}")
|
|
65
|
+
continue;
|
|
66
|
+
depth -= 1;
|
|
67
|
+
if (depth !== 0)
|
|
68
|
+
continue;
|
|
69
|
+
const candidate = text.slice(start, i + 1).trim();
|
|
70
|
+
if (!candidate || seen.has(candidate))
|
|
71
|
+
break;
|
|
72
|
+
seen.add(candidate);
|
|
73
|
+
candidates.push(candidate);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return candidates;
|
|
78
|
+
};
|
|
79
|
+
const extractTextCandidates = (payload) => {
|
|
80
|
+
const texts = [];
|
|
81
|
+
const seen = new Set();
|
|
82
|
+
let nodesVisited = 0;
|
|
83
|
+
const walk = (value, depth) => {
|
|
84
|
+
if (depth > 6)
|
|
85
|
+
return;
|
|
86
|
+
nodesVisited += 1;
|
|
87
|
+
if (nodesVisited > 2_000)
|
|
88
|
+
return;
|
|
89
|
+
if (typeof value === "string") {
|
|
90
|
+
const trimmed = value.trim();
|
|
91
|
+
if (trimmed && trimmed.length <= 60_000 && !seen.has(trimmed)) {
|
|
92
|
+
seen.add(trimmed);
|
|
93
|
+
texts.push(trimmed);
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (Array.isArray(value)) {
|
|
98
|
+
for (const item of value)
|
|
99
|
+
walk(item, depth + 1);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (!(0, guards_1.isRecord)(value))
|
|
103
|
+
return;
|
|
104
|
+
for (const item of Object.values(value)) {
|
|
105
|
+
walk(item, depth + 1);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
walk(payload, 0);
|
|
109
|
+
return texts;
|
|
110
|
+
};
|
|
111
|
+
const tryParseEnvelopeObject = (value) => {
|
|
112
|
+
if (!(0, guards_1.isRecord)(value))
|
|
113
|
+
return null;
|
|
114
|
+
if (value.version !== "2.0")
|
|
115
|
+
return null;
|
|
116
|
+
if (value.status !== "success" && value.status !== "failed")
|
|
117
|
+
return null;
|
|
118
|
+
if (!Array.isArray(value.artifacts))
|
|
119
|
+
return null;
|
|
120
|
+
if (typeof value.runId !== "string" || !value.runId)
|
|
121
|
+
return null;
|
|
122
|
+
if (typeof value.nodeId !== "string" || !value.nodeId)
|
|
123
|
+
return null;
|
|
124
|
+
if (typeof value.requestId !== "string" || !value.requestId)
|
|
125
|
+
return null;
|
|
126
|
+
if (typeof value.sessionId !== "string" || !value.sessionId)
|
|
127
|
+
return null;
|
|
128
|
+
for (const rawArtifact of value.artifacts) {
|
|
129
|
+
if (!(0, guards_1.isRecord)(rawArtifact))
|
|
130
|
+
continue;
|
|
131
|
+
const normalized = (0, contract_1.normalizeSchemaVersion)(rawArtifact.schemaVersion);
|
|
132
|
+
if (normalized !== null) {
|
|
133
|
+
// 解析阶段先做宽松纠正,后续统一走 number 语义校验与持久化。
|
|
134
|
+
rawArtifact.schemaVersion = normalized;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
};
|
|
139
|
+
const mayContainResultEnvelopeText = (text) => text.includes('"version"') &&
|
|
140
|
+
text.includes('"requestId"') &&
|
|
141
|
+
text.includes('"artifacts"');
|
|
142
|
+
const tryParseEnvelopeText = (text) => {
|
|
143
|
+
if (!mayContainResultEnvelopeText(text))
|
|
144
|
+
return null;
|
|
145
|
+
const ENVELOPE_TEXT_SCAN_TAIL_CHARS = 64_000;
|
|
146
|
+
let scanText = text;
|
|
147
|
+
if (text.length > ENVELOPE_TEXT_SCAN_TAIL_CHARS) {
|
|
148
|
+
const headLen = text.length - ENVELOPE_TEXT_SCAN_TAIL_CHARS;
|
|
149
|
+
const headPart = text.slice(0, headLen);
|
|
150
|
+
// 向前回溯到最近的 {,防止 JSON 起始被窗口切断
|
|
151
|
+
const lastBrace = headPart.lastIndexOf("{");
|
|
152
|
+
scanText = lastBrace >= 0 ? text.slice(lastBrace) : text.slice(-ENVELOPE_TEXT_SCAN_TAIL_CHARS);
|
|
153
|
+
}
|
|
154
|
+
const fenced = scanText.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
155
|
+
const candidate = fenced?.[1]?.trim() || scanText.trim();
|
|
156
|
+
try {
|
|
157
|
+
const parsed = JSON.parse(candidate);
|
|
158
|
+
return tryParseEnvelopeObject(parsed);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
const embeddedCandidates = extractBalancedJsonObjectCandidates(candidate);
|
|
162
|
+
for (const embedded of embeddedCandidates) {
|
|
163
|
+
try {
|
|
164
|
+
const parsed = JSON.parse(embedded);
|
|
165
|
+
const envelope = tryParseEnvelopeObject(parsed);
|
|
166
|
+
if (envelope)
|
|
167
|
+
return envelope;
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// 继续尝试后续候选
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const collectEnvelopeCandidates = (payload) => {
|
|
177
|
+
const envelopes = [];
|
|
178
|
+
const seenKeys = new Set();
|
|
179
|
+
const pushEnvelope = (envelope) => {
|
|
180
|
+
const key = `${envelope.runId}|${envelope.nodeId}|${envelope.requestId}|${envelope.sessionId}|${envelope.status}|${envelope.artifacts.length}`;
|
|
181
|
+
if (seenKeys.has(key))
|
|
182
|
+
return;
|
|
183
|
+
seenKeys.add(key);
|
|
184
|
+
envelopes.push(envelope);
|
|
185
|
+
};
|
|
186
|
+
const textCandidates = extractTextCandidates(payload);
|
|
187
|
+
for (const text of textCandidates) {
|
|
188
|
+
const parsed = tryParseEnvelopeText(text);
|
|
189
|
+
if (parsed)
|
|
190
|
+
pushEnvelope(parsed);
|
|
191
|
+
}
|
|
192
|
+
const walk = (value, depth) => {
|
|
193
|
+
if (depth > 6)
|
|
194
|
+
return;
|
|
195
|
+
const parsed = tryParseEnvelopeObject(value);
|
|
196
|
+
if (parsed) {
|
|
197
|
+
pushEnvelope(parsed);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (Array.isArray(value)) {
|
|
201
|
+
for (const item of value)
|
|
202
|
+
walk(item, depth + 1);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (!(0, guards_1.isRecord)(value))
|
|
206
|
+
return;
|
|
207
|
+
for (const item of Object.values(value)) {
|
|
208
|
+
walk(item, depth + 1);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
walk(payload, 0);
|
|
212
|
+
return envelopes;
|
|
213
|
+
};
|
|
214
|
+
exports.collectEnvelopeCandidates = collectEnvelopeCandidates;
|