taskmeld 0.1.2 → 0.1.41
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 +176 -176
- package/README.zh-CN.md +176 -176
- package/dist/src/app/app-context-env.js +1 -1
- package/dist/src/app/create-app-context.js +3 -3
- package/dist/src/app/data-dir.js +13 -3
- package/dist/src/app/pipeline-config.js +4 -4
- package/dist/src/app/pipeline-registry.js +11 -11
- package/dist/src/app/pipeline-runtime.js +6 -9
- package/dist/src/app/runtime-store.js +3 -3
- package/dist/src/artifacts/artifact-cleanup.js +17 -17
- package/dist/src/artifacts/artifact-index.js +14 -14
- package/dist/src/artifacts/artifact-rebuilder.js +3 -3
- package/dist/src/artifacts/storage-service.js +18 -18
- package/dist/src/cli/bootstrap.js +7 -7
- package/dist/src/cli/commands/agent.js +12 -11
- package/dist/src/cli/commands/artifact.js +31 -30
- package/dist/src/cli/commands/init.js +49 -47
- package/dist/src/cli/commands/pipeline/result.js +9 -8
- package/dist/src/cli/commands/pipeline/selector.js +1 -1
- package/dist/src/cli/commands/pipeline/watch.js +2 -2
- package/dist/src/cli/commands/pipeline.js +54 -53
- package/dist/src/cli/commands/scheduler.js +9 -8
- package/dist/src/cli/commands/server.js +12 -11
- package/dist/src/cli/commands/system.js +4 -3
- package/dist/src/cli/errors.js +2 -2
- package/dist/src/cli/help.js +18 -17
- package/dist/src/cli/i18n.js +46 -0
- package/dist/src/cli/locales/en.json +244 -0
- package/dist/src/cli/locales/zh.json +244 -0
- package/dist/src/cli/output.js +3 -3
- package/dist/src/cli/renderers/engine/markdown.js +1 -1
- package/dist/src/cli/renderers/specs/index.js +1 -1
- package/dist/src/cli/router.js +1 -1
- package/dist/src/cli/server-runtime-client.js +54 -95
- package/dist/src/cli/ui-prompts.js +96 -0
- package/dist/src/cli/ws-runtime-client.js +51 -0
- package/dist/src/gateway/gateway-client.js +4 -4
- package/dist/src/index.js +28 -2
- package/dist/src/logs/run-log-reader.js +1 -1
- package/dist/src/pipeline/agent-activity.js +2 -2
- package/dist/src/pipeline/artifact-storage.js +11 -11
- package/dist/src/pipeline/diagnostics/dependency-diagnostic.js +11 -11
- package/dist/src/pipeline/dispatch/pipeline-inbound-queue.js +2 -2
- package/dist/src/pipeline/execution/group-item-executor.js +1 -1
- package/dist/src/pipeline/execution/node-item-executor.js +3 -3
- package/dist/src/pipeline/execution/node-runner.js +7 -7
- package/dist/src/pipeline/execution/readiness-state.js +1 -1
- package/dist/src/pipeline/execution/reject-handler.js +5 -5
- package/dist/src/pipeline/execution/rejected-artifact-archiver.js +1 -1
- package/dist/src/pipeline/execution/route-item-manager.js +4 -4
- package/dist/src/pipeline/execution/run-abort-controller.js +5 -5
- package/dist/src/pipeline/execution/run-state-helpers.js +2 -2
- package/dist/src/pipeline/execution/service.js +4 -4
- package/dist/src/pipeline/execution/structured-node-runner.js +24 -24
- package/dist/src/pipeline/execution-timeout.js +3 -3
- package/dist/src/pipeline/identity/index.js +3 -3
- package/dist/src/pipeline/item-batch-controller.js +6 -6
- package/dist/src/pipeline/scheduler/dependency-state.js +5 -5
- package/dist/src/pipeline/scheduler-service.js +24 -24
- package/dist/src/pipeline/state-machine.js +2 -2
- package/dist/src/pipeline/structured-output/contract.js +4 -4
- package/dist/src/pipeline/structured-output/index.js +2 -2
- package/dist/src/pipeline/structured-output/parser.js +5 -5
- package/dist/src/pipeline/structured-output/prompt.js +38 -38
- package/dist/src/pipeline/structured-output/waiter.js +6 -6
- package/dist/src/pipeline/template.js +5 -5
- package/dist/src/pipeline/timeline-log-store.js +5 -5
- package/dist/src/pipeline/tool-activity.js +3 -3
- package/dist/src/pipeline/types/pipeline-output.js +1 -1
- package/dist/src/pipeline/workflow/branch-rules.js +19 -19
- package/dist/src/pipeline/workflow/io.js +1 -1
- package/dist/src/pipeline/workflow/normalize.js +18 -18
- package/dist/src/pipeline/workflow/template-mapper.js +3 -3
- package/dist/src/pipeline/workflow/validate.js +39 -39
- package/dist/src/pipeline/workflow-graph.js +10 -10
- package/dist/src/server/http-handler.js +74 -0
- package/dist/src/services/agent-service.js +2 -2
- package/dist/src/services/gateway-read-helpers.js +1 -1
- package/dist/src/services/pipeline-service.js +19 -19
- package/dist/src/services/pipeline-status.js +4 -4
- package/dist/src/services/read-services.js +1 -1
- package/dist/src/services/session-service.js +6 -6
- package/dist/src/services/system-service.js +1 -1
- package/dist/src/transport/ws-broker.js +12 -1
- package/dist/src/transport/ws-handler.js +60 -0
- package/dist/src/transport/ws-methods/agents.js +144 -0
- package/dist/src/transport/ws-methods/artifacts.js +171 -0
- package/dist/src/transport/ws-methods/gateway.js +16 -0
- package/dist/src/transport/ws-methods/logs.js +43 -0
- package/dist/src/transport/ws-methods/pipeline-batch.js +68 -0
- package/dist/src/transport/ws-methods/pipeline-links.js +100 -0
- package/dist/src/transport/ws-methods/pipeline-queue.js +51 -0
- package/dist/src/transport/ws-methods/pipeline-runtime.js +151 -0
- package/dist/src/transport/ws-methods/pipeline-scheduler.js +48 -0
- package/dist/src/transport/ws-methods/pipeline-workflow.js +127 -0
- package/dist/src/transport/ws-methods/pipelines.js +56 -0
- package/dist/src/transport/ws-methods/register-all.js +32 -0
- package/dist/src/transport/ws-methods/sessions.js +154 -0
- package/dist/src/transport/ws-methods/timeline.js +10 -0
- package/dist/src/{server/routes/pipeline-identity.js → transport/ws-methods/utils.js} +14 -9
- package/dist/src/version.js +1 -1
- package/package.json +15 -7
- package/web/dist/assets/agent-DP6TMcLj.js +1 -0
- package/web/dist/assets/agent-DmJHzLyj.js +1 -0
- package/web/dist/assets/artifact-BqnoZy2M.js +1 -0
- package/web/dist/assets/artifact-DfDkgkno.js +1 -0
- package/web/dist/assets/common-DRMTVwE9.js +1 -0
- package/web/dist/assets/common-DeXccbr2.js +1 -0
- package/web/dist/assets/dispatch-CBskGCQI.js +1 -0
- package/web/dist/assets/dispatch-sk4Wp30e.js +1 -0
- package/web/dist/assets/index-C8wTjZvH.css +1 -0
- package/web/dist/assets/index-DYDQZRLk.js +58 -0
- package/web/dist/assets/log-DN8cjb0w.js +1 -0
- package/web/dist/assets/log-HSeA_dYy.js +1 -0
- package/web/dist/assets/modal-BdNai9jf.js +1 -0
- package/web/dist/assets/modal-D9_KDpFD.js +1 -0
- package/web/dist/assets/nav-BmF7oAKg.js +1 -0
- package/web/dist/assets/nav-IjC2xqXQ.js +1 -0
- package/web/dist/assets/node-detail-CENRXcrh.js +1 -0
- package/web/dist/assets/node-detail-bndPr0IM.js +1 -0
- package/web/dist/assets/overview-B87zWAxq.js +1 -0
- package/web/dist/assets/overview-gQvk-NOK.js +1 -0
- package/web/dist/assets/pipeline-D4dSJRDz.js +1 -0
- package/web/dist/assets/pipeline-DZzyOqQa.js +1 -0
- package/web/dist/assets/session-CUWvU14v.js +5 -0
- package/web/dist/assets/session-DQ6UuCaJ.js +5 -0
- package/web/dist/assets/timeline-8y_2_0Em.js +1 -0
- package/web/dist/assets/timeline-CAPsXUTC.js +1 -0
- package/web/dist/index.html +3 -3
- package/dist/src/app/pipeline-plugin-config.js +0 -2
- package/dist/src/server/api-handler.js +0 -163
- package/dist/src/server/http-utils.js +0 -34
- package/dist/src/server/middleware.js +0 -61
- package/dist/src/server/router.js +0 -105
- package/dist/src/server/routes/agents.js +0 -189
- package/dist/src/server/routes/artifacts.js +0 -163
- package/dist/src/server/routes/gateway.js +0 -18
- package/dist/src/server/routes/health.js +0 -16
- package/dist/src/server/routes/logs.js +0 -73
- package/dist/src/server/routes/pipeline-batch.js +0 -163
- package/dist/src/server/routes/pipeline-diagnostics.js +0 -33
- package/dist/src/server/routes/pipeline-links.js +0 -117
- package/dist/src/server/routes/pipeline-outputs.js +0 -27
- package/dist/src/server/routes/pipeline-queue.js +0 -62
- package/dist/src/server/routes/pipeline-runtime.js +0 -162
- package/dist/src/server/routes/pipeline-scheduler.js +0 -69
- package/dist/src/server/routes/pipeline-workflow.js +0 -180
- package/dist/src/server/routes/pipelines.js +0 -96
- package/dist/src/server/routes/sessions.js +0 -244
- package/dist/src/server/routes/timeline.js +0 -14
- package/dist/src/server/serve-static.js +0 -42
- package/web/dist/assets/index-CWnfhkn-.js +0 -65
- package/web/dist/assets/index-gZ0xOfSO.css +0 -1
- /package/dist/src/{server → transport/ws-methods}/types.js +0 -0
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerAgentsRoutes = void 0;
|
|
4
|
-
const asRecord = (value) => value && typeof value === "object" && !Array.isArray(value)
|
|
5
|
-
? value
|
|
6
|
-
: null;
|
|
7
|
-
const toEpochMs = (value) => {
|
|
8
|
-
if (typeof value === "number" && Number.isFinite(value))
|
|
9
|
-
return value;
|
|
10
|
-
if (typeof value === "string" && value.trim()) {
|
|
11
|
-
const asNum = Number(value);
|
|
12
|
-
if (Number.isFinite(asNum))
|
|
13
|
-
return asNum;
|
|
14
|
-
const asDate = Date.parse(value);
|
|
15
|
-
if (Number.isFinite(asDate))
|
|
16
|
-
return asDate;
|
|
17
|
-
}
|
|
18
|
-
return null;
|
|
19
|
-
};
|
|
20
|
-
const readSessionActivityMs = (raw) => {
|
|
21
|
-
const candidates = [
|
|
22
|
-
raw.updatedAt,
|
|
23
|
-
raw.endedAt,
|
|
24
|
-
raw.startedAt,
|
|
25
|
-
raw.timestamp,
|
|
26
|
-
raw.ts,
|
|
27
|
-
];
|
|
28
|
-
let best = null;
|
|
29
|
-
for (const candidate of candidates) {
|
|
30
|
-
const ms = toEpochMs(candidate);
|
|
31
|
-
if (ms === null)
|
|
32
|
-
continue;
|
|
33
|
-
if (best === null || ms > best)
|
|
34
|
-
best = ms;
|
|
35
|
-
}
|
|
36
|
-
return best;
|
|
37
|
-
};
|
|
38
|
-
const inferAgentIdsFromSession = (session) => {
|
|
39
|
-
const out = new Set();
|
|
40
|
-
const id = session.id.trim();
|
|
41
|
-
if (id) {
|
|
42
|
-
const match = id.match(/^agent:([^:]+):/i);
|
|
43
|
-
if (match?.[1])
|
|
44
|
-
out.add(match[1]);
|
|
45
|
-
}
|
|
46
|
-
const raw = session.raw;
|
|
47
|
-
const directKeys = [
|
|
48
|
-
raw.agentId,
|
|
49
|
-
raw.agent_id,
|
|
50
|
-
raw.executorAgentId,
|
|
51
|
-
raw.ownerAgentId,
|
|
52
|
-
];
|
|
53
|
-
for (const value of directKeys) {
|
|
54
|
-
if (typeof value === "string" && value.trim())
|
|
55
|
-
out.add(value.trim());
|
|
56
|
-
}
|
|
57
|
-
return [...out];
|
|
58
|
-
};
|
|
59
|
-
const registerAgentsRoutes = (router) => {
|
|
60
|
-
router.register("GET", "/api/agents", async (ctx) => {
|
|
61
|
-
const services = ctx.services;
|
|
62
|
-
try {
|
|
63
|
-
const payload = await services.client.sendReq("agents.list");
|
|
64
|
-
const rawItems = services.pickArray(payload);
|
|
65
|
-
let sessionItems = services.getSessionCache();
|
|
66
|
-
try {
|
|
67
|
-
const refreshed = await services.refreshSessionsFromGateway();
|
|
68
|
-
sessionItems = refreshed.items;
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
// 即使 session 列表刷新临时失败,仍保持 /api/agents 可用
|
|
72
|
-
}
|
|
73
|
-
const lastActiveByAgentId = new Map();
|
|
74
|
-
for (const session of sessionItems) {
|
|
75
|
-
const activityMs = readSessionActivityMs(session.raw);
|
|
76
|
-
if (activityMs === null)
|
|
77
|
-
continue;
|
|
78
|
-
const agentIds = inferAgentIdsFromSession(session);
|
|
79
|
-
for (const agentId of agentIds) {
|
|
80
|
-
const prev = lastActiveByAgentId.get(agentId);
|
|
81
|
-
if (prev === undefined || activityMs > prev) {
|
|
82
|
-
lastActiveByAgentId.set(agentId, activityMs);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const items = rawItems
|
|
87
|
-
.map((item) => {
|
|
88
|
-
const obj = asRecord(item);
|
|
89
|
-
if (!obj)
|
|
90
|
-
return item;
|
|
91
|
-
const agentId = String(obj.id ?? obj.name ?? obj.key ?? "").trim();
|
|
92
|
-
const activeMs = agentId
|
|
93
|
-
? (lastActiveByAgentId.get(agentId) ?? null)
|
|
94
|
-
: null;
|
|
95
|
-
return {
|
|
96
|
-
...obj,
|
|
97
|
-
lastActiveAtMs: activeMs,
|
|
98
|
-
lastActiveAt: activeMs ? new Date(activeMs).toISOString() : null,
|
|
99
|
-
};
|
|
100
|
-
})
|
|
101
|
-
.sort((a, b) => {
|
|
102
|
-
const aObj = asRecord(a);
|
|
103
|
-
const bObj = asRecord(b);
|
|
104
|
-
const aMs = toEpochMs(aObj?.lastActiveAtMs ?? aObj?.lastActiveAt) ?? -1;
|
|
105
|
-
const bMs = toEpochMs(bObj?.lastActiveAtMs ?? bObj?.lastActiveAt) ?? -1;
|
|
106
|
-
if (aMs !== bMs)
|
|
107
|
-
return bMs - aMs;
|
|
108
|
-
const aId = String(aObj?.id ?? aObj?.name ?? "");
|
|
109
|
-
const bId = String(bObj?.id ?? bObj?.name ?? "");
|
|
110
|
-
return aId.localeCompare(bId);
|
|
111
|
-
});
|
|
112
|
-
ctx.sendJson(200, { items, raw: payload });
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
ctx.sendJson(503, { error: String(error) });
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
router.register("GET", "/api/agents/:agentId/files", async (ctx) => {
|
|
119
|
-
const services = ctx.services;
|
|
120
|
-
try {
|
|
121
|
-
const agentId = ctx.params.agentId;
|
|
122
|
-
if (!agentId) {
|
|
123
|
-
ctx.sendJson(400, { error: "invalid_agent_id" });
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const payload = await services.client.sendReq("agents.files.list", {
|
|
127
|
-
agentId,
|
|
128
|
-
});
|
|
129
|
-
const obj = (payload ?? {});
|
|
130
|
-
const files = Array.isArray(obj.files)
|
|
131
|
-
? obj.files
|
|
132
|
-
: services.pickArray(payload);
|
|
133
|
-
ctx.sendJson(200, { items: files, raw: payload });
|
|
134
|
-
}
|
|
135
|
-
catch (error) {
|
|
136
|
-
ctx.sendJson(503, { error: String(error) });
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
router.register("GET", "/api/agents/:agentId/files/*name", async (ctx) => {
|
|
140
|
-
const services = ctx.services;
|
|
141
|
-
try {
|
|
142
|
-
const agentId = ctx.params.agentId;
|
|
143
|
-
const name = ctx.params.name;
|
|
144
|
-
if (!agentId) {
|
|
145
|
-
ctx.sendJson(400, { error: "invalid_agent_id" });
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
if (!name) {
|
|
149
|
-
ctx.sendJson(400, { error: "invalid_file_name" });
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const payload = await services.client.sendReq("agents.files.get", {
|
|
153
|
-
agentId,
|
|
154
|
-
name,
|
|
155
|
-
});
|
|
156
|
-
const obj = (payload ?? {});
|
|
157
|
-
const file = (obj.file ?? payload);
|
|
158
|
-
ctx.sendJson(200, { item: file ?? null, raw: payload });
|
|
159
|
-
}
|
|
160
|
-
catch (error) {
|
|
161
|
-
ctx.sendJson(503, { error: String(error) });
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
router.register("POST", "/api/agents/:agentId/files/*name", async (ctx) => {
|
|
165
|
-
const services = ctx.services;
|
|
166
|
-
try {
|
|
167
|
-
const agentId = ctx.params.agentId;
|
|
168
|
-
const name = ctx.params.name;
|
|
169
|
-
if (!agentId) {
|
|
170
|
-
ctx.sendJson(400, { error: "invalid_agent_id" });
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
if (!name) {
|
|
174
|
-
ctx.sendJson(400, { error: "invalid_file_name" });
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
const body = await ctx.readBody();
|
|
178
|
-
const content = typeof body.content === "string" ? body.content : "";
|
|
179
|
-
const payload = await services.client.sendReq("agents.files.set", { agentId, name, content }, { sideEffect: true });
|
|
180
|
-
const obj = (payload ?? {});
|
|
181
|
-
const file = (obj.file ?? payload);
|
|
182
|
-
ctx.sendJson(200, { item: file ?? null, raw: payload });
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
ctx.sendJson(503, { error: String(error) });
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
};
|
|
189
|
-
exports.registerAgentsRoutes = registerAgentsRoutes;
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerArtifactsRoutes = void 0;
|
|
4
|
-
const storage_service_js_1 = require("../../artifacts/storage-service.js");
|
|
5
|
-
const artifact_index_js_1 = require("../../artifacts/artifact-index.js");
|
|
6
|
-
const artifact_cleanup_js_1 = require("../../artifacts/artifact-cleanup.js");
|
|
7
|
-
const storage_service_js_2 = require("../../artifacts/storage-service.js");
|
|
8
|
-
const parseCsvParam = (value) => value
|
|
9
|
-
? value
|
|
10
|
-
.split(",")
|
|
11
|
-
.map((item) => item.trim())
|
|
12
|
-
.filter(Boolean)
|
|
13
|
-
: [];
|
|
14
|
-
const registerArtifactsRoutes = (router) => {
|
|
15
|
-
router.register("GET", "/api/artifacts", async (ctx) => {
|
|
16
|
-
const services = ctx.services;
|
|
17
|
-
const pipelineIds = parseCsvParam(ctx.url.searchParams.get("pipelineId"));
|
|
18
|
-
const nodeIds = parseCsvParam(ctx.url.searchParams.get("nodeId"));
|
|
19
|
-
const statuses = parseCsvParam(ctx.url.searchParams.get("status"));
|
|
20
|
-
const kinds = parseCsvParam(ctx.url.searchParams.get("kind"));
|
|
21
|
-
const dateFrom = String(ctx.url.searchParams.get("dateFrom") ?? "").trim() || null;
|
|
22
|
-
const dateTo = String(ctx.url.searchParams.get("dateTo") ?? "").trim() || null;
|
|
23
|
-
const cursor = String(ctx.url.searchParams.get("cursor") ?? "").trim() || undefined;
|
|
24
|
-
const batchRunId = String(ctx.url.searchParams.get("batchRunId") ?? "").trim() || undefined;
|
|
25
|
-
const runId = String(ctx.url.searchParams.get("runId") ?? "").trim() || undefined;
|
|
26
|
-
const limitRaw = Number(ctx.url.searchParams.get("limit") ?? 100);
|
|
27
|
-
const result = await (0, storage_service_js_1.listStoredArtifacts)(services.listPipelines(), {
|
|
28
|
-
pipelineIds,
|
|
29
|
-
nodeIds,
|
|
30
|
-
dateFrom,
|
|
31
|
-
dateTo,
|
|
32
|
-
limit: Number.isFinite(limitRaw) ? limitRaw : 100,
|
|
33
|
-
cursor,
|
|
34
|
-
statuses: statuses.length ? statuses : undefined,
|
|
35
|
-
kinds: kinds.length ? kinds : undefined,
|
|
36
|
-
batchRunId,
|
|
37
|
-
runId,
|
|
38
|
-
});
|
|
39
|
-
ctx.sendJson(200, {
|
|
40
|
-
items: result.items,
|
|
41
|
-
nextCursor: result.nextCursor,
|
|
42
|
-
source: result.source,
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
router.register("GET", "/api/artifacts/content", async (ctx) => {
|
|
46
|
-
const services = ctx.services;
|
|
47
|
-
const pipelineId = String(ctx.url.searchParams.get("pipelineId") ?? "").trim();
|
|
48
|
-
const relativePath = String(ctx.url.searchParams.get("relativePath") ?? "").trim();
|
|
49
|
-
const artifactId = String(ctx.url.searchParams.get("artifactId") ?? "").trim();
|
|
50
|
-
if (!pipelineId || (!relativePath && !artifactId)) {
|
|
51
|
-
ctx.sendJson(400, { error: "invalid_artifact_query" });
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const definition = services.getPipelineDefinition(pipelineId);
|
|
55
|
-
if (!definition) {
|
|
56
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId });
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
// artifactId 查询:从索引/扫描列表中查找对应 relativePath
|
|
60
|
-
let resolvedPath = relativePath || undefined;
|
|
61
|
-
if (!resolvedPath && artifactId) {
|
|
62
|
-
const listResult = await (0, storage_service_js_1.listStoredArtifacts)(services.listPipelines(), {
|
|
63
|
-
pipelineIds: [pipelineId],
|
|
64
|
-
limit: 5000,
|
|
65
|
-
});
|
|
66
|
-
const match = listResult.items.find((item) => item.artifactId === artifactId);
|
|
67
|
-
resolvedPath = match?.relativePath ?? undefined;
|
|
68
|
-
}
|
|
69
|
-
if (!resolvedPath) {
|
|
70
|
-
ctx.sendJson(404, { error: "artifact_not_found", pipelineId, artifactId: artifactId || null });
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
const content = await (0, storage_service_js_1.readStoredArtifactContent)(definition, resolvedPath);
|
|
74
|
-
if (!content) {
|
|
75
|
-
ctx.sendJson(404, {
|
|
76
|
-
error: "artifact_not_found",
|
|
77
|
-
pipelineId,
|
|
78
|
-
relativePath: resolvedPath,
|
|
79
|
-
});
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
ctx.sendJson(200, {
|
|
83
|
-
pipelineId,
|
|
84
|
-
relativePath: resolvedPath,
|
|
85
|
-
artifactId: artifactId || null,
|
|
86
|
-
content,
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
router.register("GET", "/api/artifacts/export", async (ctx) => {
|
|
90
|
-
const services = ctx.services;
|
|
91
|
-
const pipelineIds = parseCsvParam(ctx.url.searchParams.get("pipelineId"));
|
|
92
|
-
const nodeIds = parseCsvParam(ctx.url.searchParams.get("nodeId"));
|
|
93
|
-
const dateFrom = String(ctx.url.searchParams.get("dateFrom") ?? "").trim() || null;
|
|
94
|
-
const dateTo = String(ctx.url.searchParams.get("dateTo") ?? "").trim() || null;
|
|
95
|
-
const limitRaw = Number(ctx.url.searchParams.get("limit") ?? 20000);
|
|
96
|
-
const kinds = parseCsvParam(ctx.url.searchParams.get("kind"));
|
|
97
|
-
// 默认排除 envelope,避免同一业务内容在 envelope 和 artifact 文件中重复出现
|
|
98
|
-
const effectiveKinds = kinds.length > 0 ? kinds : ["artifact", "adapter", "group"];
|
|
99
|
-
const data = await (0, storage_service_js_1.exportStoredArtifactContents)(services.listPipelines(), {
|
|
100
|
-
pipelineIds,
|
|
101
|
-
nodeIds,
|
|
102
|
-
dateFrom,
|
|
103
|
-
dateTo,
|
|
104
|
-
limit: Number.isFinite(limitRaw) ? limitRaw : 20000,
|
|
105
|
-
kinds: effectiveKinds,
|
|
106
|
-
});
|
|
107
|
-
ctx.sendJson(200, { data });
|
|
108
|
-
});
|
|
109
|
-
router.register("POST", "/api/artifacts/cleanup", async (ctx) => {
|
|
110
|
-
const services = ctx.services;
|
|
111
|
-
const pipelineId = String(ctx.url.searchParams.get("pipelineId") ?? "").trim() || undefined;
|
|
112
|
-
const olderThanDays = parseInt(ctx.url.searchParams.get("olderThanDays") ?? "0", 10) || undefined;
|
|
113
|
-
const statusParam = ctx.url.searchParams.get("status") ?? "";
|
|
114
|
-
const statuses = statusParam ? statusParam.split(",").map((s) => s.trim()).filter(Boolean) : undefined;
|
|
115
|
-
const confirm = ctx.url.searchParams.get("confirm") === "true";
|
|
116
|
-
const definitions = pipelineId
|
|
117
|
-
? [services.getPipelineDefinition(pipelineId)].filter(Boolean)
|
|
118
|
-
: services.listPipelines();
|
|
119
|
-
if (definitions.length === 0) {
|
|
120
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId });
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
let totalFiles = 0;
|
|
124
|
-
let totalSizeBytes = 0;
|
|
125
|
-
let deleted = 0;
|
|
126
|
-
let failed = 0;
|
|
127
|
-
const allWarnings = [];
|
|
128
|
-
for (const definition of definitions) {
|
|
129
|
-
const plan = await (0, artifact_cleanup_js_1.planCleanup)(definition, { olderThanDays, statuses });
|
|
130
|
-
totalFiles += plan.files.length;
|
|
131
|
-
totalSizeBytes += plan.totalSizeBytes;
|
|
132
|
-
if (confirm) {
|
|
133
|
-
const execResult = await (0, artifact_cleanup_js_1.executeCleanup)(definition, plan);
|
|
134
|
-
deleted += execResult.deleted;
|
|
135
|
-
failed += execResult.failed;
|
|
136
|
-
allWarnings.push(...execResult.warnings);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
ctx.sendJson(200, { totalFiles, totalSizeBytes, deleted, failed, dryRun: !confirm, warnings: allWarnings });
|
|
140
|
-
});
|
|
141
|
-
router.register("POST", "/api/artifacts/rebuild-index", async (ctx) => {
|
|
142
|
-
const services = ctx.services;
|
|
143
|
-
const pipelineId = String(ctx.url.searchParams.get("pipelineId") ?? "").trim() || undefined;
|
|
144
|
-
const definitions = pipelineId
|
|
145
|
-
? [services.getPipelineDefinition(pipelineId)].filter(Boolean)
|
|
146
|
-
: services.listPipelines();
|
|
147
|
-
if (definitions.length === 0) {
|
|
148
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId });
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
let indexed = 0;
|
|
152
|
-
let skipped = 0;
|
|
153
|
-
const warnings = [];
|
|
154
|
-
for (const definition of definitions) {
|
|
155
|
-
const result = await (0, artifact_index_js_1.rebuildArtifactIndex)(definition, (d) => (0, storage_service_js_2.scanStoredArtifacts)([d]));
|
|
156
|
-
indexed += result.indexed;
|
|
157
|
-
skipped += result.skipped;
|
|
158
|
-
warnings.push(...result.warnings);
|
|
159
|
-
}
|
|
160
|
-
ctx.sendJson(200, { indexed, skipped, warnings });
|
|
161
|
-
});
|
|
162
|
-
};
|
|
163
|
-
exports.registerArtifactsRoutes = registerArtifactsRoutes;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerGatewayRoutes = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* 注册 GET /api/gateway/status 路由。
|
|
6
|
-
* 返回网关连接状态、最新 hello 消息和最后帧数据。
|
|
7
|
-
*/
|
|
8
|
-
const registerGatewayRoutes = (router) => {
|
|
9
|
-
router.register("GET", "/api/gateway/status", (ctx) => {
|
|
10
|
-
const services = ctx.services;
|
|
11
|
-
ctx.sendJson(200, {
|
|
12
|
-
status: services.getLatestStatus() ?? services.client.getStatus(),
|
|
13
|
-
hello: services.getLatestHello(),
|
|
14
|
-
lastFrame: services.getLastFrame(),
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
exports.registerGatewayRoutes = registerGatewayRoutes;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerHealthRoutes = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* 注册 GET /api/health 路由。
|
|
6
|
-
* 返回服务端存活状态及当前 owner 摘要,供 CLI 校验 runtime metadata 是否仍指向同一实例。
|
|
7
|
-
*/
|
|
8
|
-
const registerHealthRoutes = (router) => {
|
|
9
|
-
router.register("GET", "/api/health", (ctx) => {
|
|
10
|
-
ctx.sendJson(200, {
|
|
11
|
-
ok: true,
|
|
12
|
-
...ctx.options.serverRuntimeIdentity,
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
};
|
|
16
|
-
exports.registerHealthRoutes = registerHealthRoutes;
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerLogRoutes = void 0;
|
|
4
|
-
const node_fs_1 = require("node:fs");
|
|
5
|
-
const promises_1 = require("node:fs/promises");
|
|
6
|
-
const registerLogRoutes = (router) => {
|
|
7
|
-
router.register("GET", "/api/logs/runs", async (ctx) => {
|
|
8
|
-
const services = ctx.services;
|
|
9
|
-
const items = await services.runLogService.listRuns();
|
|
10
|
-
ctx.sendJson(200, { items });
|
|
11
|
-
});
|
|
12
|
-
router.register("GET", "/api/logs/runs/:runId/timeline", async (ctx) => {
|
|
13
|
-
try {
|
|
14
|
-
const services = ctx.services;
|
|
15
|
-
const runId = ctx.params.runId;
|
|
16
|
-
if (!runId) {
|
|
17
|
-
ctx.sendJson(400, { error: "invalid_run_id" });
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
const levelParam = String(ctx.url.searchParams.get("level") ?? "").trim();
|
|
21
|
-
const levels = levelParam
|
|
22
|
-
? levelParam
|
|
23
|
-
.split(",")
|
|
24
|
-
.map((item) => item.trim())
|
|
25
|
-
.filter((item) => item === "info" || item === "warn" || item === "error")
|
|
26
|
-
: undefined;
|
|
27
|
-
const offsetRaw = Number(ctx.url.searchParams.get("offset") ?? 0);
|
|
28
|
-
const limitParam = ctx.url.searchParams.get("limit");
|
|
29
|
-
const limitRaw = limitParam === null ? undefined : Number(limitParam);
|
|
30
|
-
const keyword = String(ctx.url.searchParams.get("keyword") ?? "").trim() || undefined;
|
|
31
|
-
const order = ctx.url.searchParams.get("order") === "asc" ? "asc" : "desc";
|
|
32
|
-
const page = await services.runLogService.queryTimeline({
|
|
33
|
-
runId,
|
|
34
|
-
offset: Number.isFinite(offsetRaw) ? offsetRaw : 0,
|
|
35
|
-
limit: typeof limitRaw === "number" && Number.isFinite(limitRaw)
|
|
36
|
-
? limitRaw
|
|
37
|
-
: undefined,
|
|
38
|
-
keyword,
|
|
39
|
-
levels,
|
|
40
|
-
order,
|
|
41
|
-
});
|
|
42
|
-
ctx.sendJson(200, page);
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
ctx.sendJson(404, { error: "run_log_not_found", detail: String(error) });
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
router.register("GET", "/api/logs/runs/:runId/timeline/raw", async (ctx) => {
|
|
49
|
-
try {
|
|
50
|
-
const services = ctx.services;
|
|
51
|
-
const runId = ctx.params.runId;
|
|
52
|
-
if (!runId) {
|
|
53
|
-
ctx.sendJson(400, { error: "invalid_run_id" });
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const logFile = await services.runLogService.readRawTimeline(runId);
|
|
57
|
-
const fileStat = await (0, promises_1.stat)(logFile);
|
|
58
|
-
const stream = (0, node_fs_1.createReadStream)(logFile);
|
|
59
|
-
ctx.sendRaw(200, {
|
|
60
|
-
"Content-Type": "application/x-ndjson; charset=utf-8",
|
|
61
|
-
"Content-Length": String(fileStat.size),
|
|
62
|
-
"Content-Disposition": `inline; filename="${runId}-timeline.log"`,
|
|
63
|
-
}, stream);
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
ctx.sendJson(404, {
|
|
67
|
-
error: "run_log_not_found",
|
|
68
|
-
detail: String(error),
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
};
|
|
73
|
-
exports.registerLogRoutes = registerLogRoutes;
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerPipelineBatchRoutes = void 0;
|
|
4
|
-
const pipeline_service_js_1 = require("../../services/pipeline-service.js");
|
|
5
|
-
const item_batch_controller_js_1 = require("../../pipeline/item-batch-controller.js");
|
|
6
|
-
const pipeline_identity_js_1 = require("./pipeline-identity.js");
|
|
7
|
-
/**
|
|
8
|
-
* 注册 Pipeline Batch Run 路由:
|
|
9
|
-
* GET /api/pipelines/:pipelineId/items — Item Run 列表
|
|
10
|
-
* GET /api/pipelines/:pipelineId/batch-run/status — Batch Run 状态
|
|
11
|
-
* POST /api/pipelines/:pipelineId/batch-run/start — 启动本地 Batch Run
|
|
12
|
-
* POST /api/pipelines/:pipelineId/batch-run/start-remote — 启动远程 Batch Run
|
|
13
|
-
* POST /api/pipelines/:pipelineId/batch-run/stop — 停止 Batch Run
|
|
14
|
-
*/
|
|
15
|
-
const registerPipelineBatchRoutes = (router) => {
|
|
16
|
-
// GET /api/pipelines/:pipelineId/items
|
|
17
|
-
router.register("GET", "/api/pipelines/:pipelineId/items", (ctx) => {
|
|
18
|
-
const scope = ctx.getPipelineScope();
|
|
19
|
-
if (!scope) {
|
|
20
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId: ctx.params.pipelineId });
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (!scope.getItemRuns) {
|
|
24
|
-
ctx.sendJson(501, { error: "item_run_api_not_enabled" });
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
ctx.sendJson(200, { items: scope.getItemRuns(), pipelineId: scope.pipelineId });
|
|
28
|
-
});
|
|
29
|
-
// GET /api/pipelines/:pipelineId/batch-run/status
|
|
30
|
-
router.register("GET", "/api/pipelines/:pipelineId/batch-run/status", (ctx) => {
|
|
31
|
-
const scope = ctx.getPipelineScope();
|
|
32
|
-
if (!scope) {
|
|
33
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId: ctx.params.pipelineId });
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if (!scope.getBatchRunState) {
|
|
37
|
-
ctx.sendJson(501, { error: "batch_run_api_not_enabled" });
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
const batchRunState = scope.getBatchRunState();
|
|
41
|
-
const identity = (0, pipeline_service_js_1.readPipelineIdentitySnapshot)(scope.pipelineId, scope.getRun(), batchRunState);
|
|
42
|
-
ctx.sendJson(200, { ok: true, state: batchRunState, ...identity });
|
|
43
|
-
});
|
|
44
|
-
// POST /api/pipelines/:pipelineId/batch-run/start
|
|
45
|
-
router.register("POST", "/api/pipelines/:pipelineId/batch-run/start", async (ctx) => {
|
|
46
|
-
const scope = ctx.getPipelineScope();
|
|
47
|
-
if (!scope) {
|
|
48
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId: ctx.params.pipelineId });
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const { pipelineService } = ctx.services;
|
|
52
|
-
const body = await ctx.readBody();
|
|
53
|
-
const items = (0, item_batch_controller_js_1.normalizePoolItems)(body.items ?? body.keywords ?? body.pool ?? body);
|
|
54
|
-
const batchSize = typeof body.batchSize === "number"
|
|
55
|
-
? body.batchSize
|
|
56
|
-
: typeof body.size === "number"
|
|
57
|
-
? body.size
|
|
58
|
-
: typeof body.chunkSize === "number"
|
|
59
|
-
? body.chunkSize
|
|
60
|
-
: undefined;
|
|
61
|
-
const startIndex = typeof body.startIndex === "number" ? body.startIndex : undefined;
|
|
62
|
-
const startBatch = typeof body.startBatch === "number" ? body.startBatch : undefined;
|
|
63
|
-
const started = pipelineService.startBatchRun({
|
|
64
|
-
pipelineId: scope.pipelineId,
|
|
65
|
-
items,
|
|
66
|
-
batchSize,
|
|
67
|
-
startIndex,
|
|
68
|
-
startBatch,
|
|
69
|
-
});
|
|
70
|
-
if (started.ok === false && started.error === "batch_items_empty") {
|
|
71
|
-
ctx.sendJson(400, { error: started.error });
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (!started.ok) {
|
|
75
|
-
ctx.sendJson(409, { ok: false, error: started.error, state: started.state });
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
ctx.sendJson(200, { ok: true, state: started.state, pipelineId: scope.pipelineId });
|
|
79
|
-
});
|
|
80
|
-
// POST /api/pipelines/:pipelineId/batch-run/start-remote
|
|
81
|
-
router.register("POST", "/api/pipelines/:pipelineId/batch-run/start-remote", async (ctx) => {
|
|
82
|
-
const scope = ctx.getPipelineScope();
|
|
83
|
-
if (!scope) {
|
|
84
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId: ctx.params.pipelineId });
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
const { pipelineService } = ctx.services;
|
|
88
|
-
const body = await ctx.readBody();
|
|
89
|
-
const remoteUrl = typeof body.url === "string" ? body.url : undefined;
|
|
90
|
-
const batchSize = typeof body.batchSize === "number"
|
|
91
|
-
? body.batchSize
|
|
92
|
-
: typeof body.size === "number"
|
|
93
|
-
? body.size
|
|
94
|
-
: typeof body.chunkSize === "number"
|
|
95
|
-
? body.chunkSize
|
|
96
|
-
: undefined;
|
|
97
|
-
const startIndex = typeof body.startIndex === "number" ? body.startIndex : undefined;
|
|
98
|
-
const startBatch = typeof body.startBatch === "number" ? body.startBatch : undefined;
|
|
99
|
-
const started = await pipelineService.startRemoteBatchRun({
|
|
100
|
-
pipelineId: scope.pipelineId,
|
|
101
|
-
url: remoteUrl,
|
|
102
|
-
batchSize,
|
|
103
|
-
startIndex,
|
|
104
|
-
startBatch,
|
|
105
|
-
});
|
|
106
|
-
// 保持 remote pool 相关错误状态码语义:400 / 403 / 409 / 502
|
|
107
|
-
if (started.ok === false && started.error === "pipeline_plugin_disabled") {
|
|
108
|
-
ctx.sendJson(403, { error: started.error, plugin: started.plugin, pipelineId: scope.pipelineId });
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
if (started.ok === false &&
|
|
112
|
-
(started.error === "remote_pool_url_empty" || started.error === "remote_batch_items_empty")) {
|
|
113
|
-
ctx.sendJson(400, { error: started.error, remoteUrl: started.remoteUrl });
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
if (started.ok === false &&
|
|
117
|
-
(started.error === "remote_pool_fetch_failed" || started.error === "remote_pool_fetch_error")) {
|
|
118
|
-
ctx.sendJson(502, {
|
|
119
|
-
error: started.error,
|
|
120
|
-
status: started.status,
|
|
121
|
-
remoteUrl: started.remoteUrl,
|
|
122
|
-
detail: started.detail,
|
|
123
|
-
});
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
if (!started.ok) {
|
|
127
|
-
ctx.sendJson(409, { ok: false, error: started.error, state: started.state, remoteUrl: started.remoteUrl });
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
ctx.sendJson(200, {
|
|
131
|
-
ok: true,
|
|
132
|
-
state: started.state,
|
|
133
|
-
remoteUrl: started.remoteUrl,
|
|
134
|
-
totalFetched: started.totalFetched,
|
|
135
|
-
pipelineId: scope.pipelineId,
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
// POST /api/pipelines/:pipelineId/batch-run/stop
|
|
139
|
-
// 与 /stop 共享同一业务逻辑,通过 pipelineService.stopPipeline 统一处理
|
|
140
|
-
router.register("POST", "/api/pipelines/:pipelineId/batch-run/stop", async (ctx) => {
|
|
141
|
-
const scope = ctx.getPipelineScope();
|
|
142
|
-
if (!scope) {
|
|
143
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId: ctx.params.pipelineId });
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const { pipelineService } = ctx.services;
|
|
147
|
-
const body = await ctx.readBody();
|
|
148
|
-
const target = (0, pipeline_identity_js_1.mergeIdentityTargets)((0, pipeline_identity_js_1.readIdentityTargetFromBody)(body), (0, pipeline_identity_js_1.readIdentityTargetFromUrl)(ctx.url));
|
|
149
|
-
const stopped = pipelineService.stopPipeline(scope.pipelineId, target);
|
|
150
|
-
if (stopped.ok === false && stopped.error === "run_not_found") {
|
|
151
|
-
ctx.sendJson(404, stopped);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
if (stopped.ok === false) {
|
|
155
|
-
ctx.sendJson(409, stopped);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
ctx.sendJson(200, {
|
|
159
|
-
...stopped,
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
};
|
|
163
|
-
exports.registerPipelineBatchRoutes = registerPipelineBatchRoutes;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerPipelineDiagnosticsRoutes = void 0;
|
|
4
|
-
const index_js_1 = require("../../pipeline/diagnostics/index.js");
|
|
5
|
-
/**
|
|
6
|
-
* 注册 Pipeline 节点诊断路由:
|
|
7
|
-
* GET /api/pipelines/:pipelineId/nodes/:nodeId/diagnostics?itemKey=xxx
|
|
8
|
-
*/
|
|
9
|
-
const registerPipelineDiagnosticsRoutes = (router) => {
|
|
10
|
-
router.register("GET", "/api/pipelines/:pipelineId/nodes/:nodeId/diagnostics", (ctx) => {
|
|
11
|
-
const scope = ctx.getPipelineScope();
|
|
12
|
-
if (!scope) {
|
|
13
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId: ctx.params.pipelineId });
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
const nodeId = ctx.params.nodeId;
|
|
17
|
-
const itemKey = ctx.url.searchParams.get("itemKey") ?? undefined;
|
|
18
|
-
const runtime = ctx.options.app.getPipelineRuntime(scope.pipelineId);
|
|
19
|
-
if (!runtime) {
|
|
20
|
-
ctx.sendJson(404, { error: "pipeline_not_found", pipelineId: scope.pipelineId });
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
const run = scope.getRun();
|
|
24
|
-
const workflowNode = runtime.workflow.getWorkflowNodeById(nodeId);
|
|
25
|
-
if (!workflowNode) {
|
|
26
|
-
ctx.sendJson(404, { error: "node_not_found", pipelineId: scope.pipelineId, nodeId });
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const diagnostics = (0, index_js_1.diagnoseNodeDependency)(run, runtime.workflow, nodeId, itemKey);
|
|
30
|
-
ctx.sendJson(200, { nodeId, itemKey: itemKey ?? null, diagnostics });
|
|
31
|
-
});
|
|
32
|
-
};
|
|
33
|
-
exports.registerPipelineDiagnosticsRoutes = registerPipelineDiagnosticsRoutes;
|