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.
Files changed (204) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +172 -0
  3. package/README.zh-CN.md +172 -0
  4. package/dist/src/app/app-context-env.js +51 -0
  5. package/dist/src/app/create-app-context.js +127 -0
  6. package/dist/src/app/data-dir.js +29 -0
  7. package/dist/src/app/pipeline-config.js +105 -0
  8. package/dist/src/app/pipeline-plugin-config.js +2 -0
  9. package/dist/src/app/pipeline-registry.js +502 -0
  10. package/dist/src/app/pipeline-runtime.js +202 -0
  11. package/dist/src/app/runtime-store.js +151 -0
  12. package/dist/src/app/user-config.js +37 -0
  13. package/dist/src/artifacts/artifact-cleanup.js +192 -0
  14. package/dist/src/artifacts/artifact-index.js +262 -0
  15. package/dist/src/artifacts/artifact-rebuilder.js +120 -0
  16. package/dist/src/artifacts/storage-service.js +371 -0
  17. package/dist/src/cli/bootstrap.js +226 -0
  18. package/dist/src/cli/commands/agent.js +126 -0
  19. package/dist/src/cli/commands/artifact.js +175 -0
  20. package/dist/src/cli/commands/init.js +150 -0
  21. package/dist/src/cli/commands/pipeline/errors.js +37 -0
  22. package/dist/src/cli/commands/pipeline/result.js +179 -0
  23. package/dist/src/cli/commands/pipeline/selector.js +51 -0
  24. package/dist/src/cli/commands/pipeline/types.js +2 -0
  25. package/dist/src/cli/commands/pipeline/watch.js +67 -0
  26. package/dist/src/cli/commands/pipeline.js +339 -0
  27. package/dist/src/cli/commands/scheduler.js +81 -0
  28. package/dist/src/cli/commands/server.js +70 -0
  29. package/dist/src/cli/commands/system.js +21 -0
  30. package/dist/src/cli/errors.js +71 -0
  31. package/dist/src/cli/help.js +184 -0
  32. package/dist/src/cli/index.js +65 -0
  33. package/dist/src/cli/output.js +19 -0
  34. package/dist/src/cli/renderers/engine/json.js +67 -0
  35. package/dist/src/cli/renderers/engine/markdown.js +95 -0
  36. package/dist/src/cli/renderers/engine/types.js +2 -0
  37. package/dist/src/cli/renderers/engine/utils.js +32 -0
  38. package/dist/src/cli/renderers/index.js +27 -0
  39. package/dist/src/cli/renderers/specs/agent.js +78 -0
  40. package/dist/src/cli/renderers/specs/artifact.js +32 -0
  41. package/dist/src/cli/renderers/specs/index.js +36 -0
  42. package/dist/src/cli/renderers/specs/init.js +25 -0
  43. package/dist/src/cli/renderers/specs/pipeline.js +561 -0
  44. package/dist/src/cli/renderers/specs/scheduler.js +46 -0
  45. package/dist/src/cli/renderers/specs/server.js +38 -0
  46. package/dist/src/cli/renderers/specs/system.js +36 -0
  47. package/dist/src/cli/router.js +199 -0
  48. package/dist/src/cli/server-runtime-client.js +780 -0
  49. package/dist/src/cli/types.js +2 -0
  50. package/dist/src/gateway/frame-sanitizer.js +78 -0
  51. package/dist/src/gateway/gateway-client.js +462 -0
  52. package/dist/src/gateway/index.js +18 -0
  53. package/dist/src/gateway/types.js +2 -0
  54. package/dist/src/index.js +123 -0
  55. package/dist/src/logs/run-log-reader.js +141 -0
  56. package/dist/src/logs/run-log-service.js +42 -0
  57. package/dist/src/logs/run-log-types.js +2 -0
  58. package/dist/src/pipeline/agent-activity.js +191 -0
  59. package/dist/src/pipeline/artifact-storage.js +208 -0
  60. package/dist/src/pipeline/diagnostics/dependency-diagnostic.js +105 -0
  61. package/dist/src/pipeline/diagnostics/index.js +6 -0
  62. package/dist/src/pipeline/dispatch/pipeline-inbound-queue.js +215 -0
  63. package/dist/src/pipeline/dispatch/pipeline-link-dispatcher.js +66 -0
  64. package/dist/src/pipeline/dispatch/pipeline-link-store.js +94 -0
  65. package/dist/src/pipeline/dispatch/pipeline-queue-drainer.js +71 -0
  66. package/dist/src/pipeline/execution/dependency-check.js +52 -0
  67. package/dist/src/pipeline/execution/execution-result.js +2 -0
  68. package/dist/src/pipeline/execution/group-item-executor.js +128 -0
  69. package/dist/src/pipeline/execution/index.js +5 -0
  70. package/dist/src/pipeline/execution/node-item-executor.js +58 -0
  71. package/dist/src/pipeline/execution/node-runner.js +159 -0
  72. package/dist/src/pipeline/execution/readiness-state.js +10 -0
  73. package/dist/src/pipeline/execution/reject-handler.js +94 -0
  74. package/dist/src/pipeline/execution/rejected-artifact-archiver.js +45 -0
  75. package/dist/src/pipeline/execution/route-item-manager.js +253 -0
  76. package/dist/src/pipeline/execution/run-abort-controller.js +66 -0
  77. package/dist/src/pipeline/execution/run-state-helpers.js +257 -0
  78. package/dist/src/pipeline/execution/service.js +165 -0
  79. package/dist/src/pipeline/execution/session-registry.js +96 -0
  80. package/dist/src/pipeline/execution/structured-node-runner.js +411 -0
  81. package/dist/src/pipeline/execution-status.js +96 -0
  82. package/dist/src/pipeline/execution-timeout.js +21 -0
  83. package/dist/src/pipeline/identity/index.js +32 -0
  84. package/dist/src/pipeline/identity/types.js +2 -0
  85. package/dist/src/pipeline/item-batch-controller.js +227 -0
  86. package/dist/src/pipeline/output/pipeline-output-resolver.js +91 -0
  87. package/dist/src/pipeline/output/pipeline-output-store.js +60 -0
  88. package/dist/src/pipeline/runtime-model.js +173 -0
  89. package/dist/src/pipeline/scheduler/dependency-state.js +144 -0
  90. package/dist/src/pipeline/scheduler-service.js +314 -0
  91. package/dist/src/pipeline/state/group-item-state.js +50 -0
  92. package/dist/src/pipeline/state/group-run-state.js +41 -0
  93. package/dist/src/pipeline/state/index.js +20 -0
  94. package/dist/src/pipeline/state/node-item-state.js +67 -0
  95. package/dist/src/pipeline/state/node-run-state.js +51 -0
  96. package/dist/src/pipeline/state/types.js +2 -0
  97. package/dist/src/pipeline/state-machine.js +101 -0
  98. package/dist/src/pipeline/structured-output/contract.js +133 -0
  99. package/dist/src/pipeline/structured-output/index.js +22 -0
  100. package/dist/src/pipeline/structured-output/parser.js +214 -0
  101. package/dist/src/pipeline/structured-output/prompt.js +290 -0
  102. package/dist/src/pipeline/structured-output/waiter.js +139 -0
  103. package/dist/src/pipeline/template.js +135 -0
  104. package/dist/src/pipeline/timeline-log-store.js +57 -0
  105. package/dist/src/pipeline/tool-activity.js +94 -0
  106. package/dist/src/pipeline/types/pipeline-link.js +7 -0
  107. package/dist/src/pipeline/types/pipeline-output.js +11 -0
  108. package/dist/src/pipeline/types/workflow.js +2 -0
  109. package/dist/src/pipeline/workflow/branch-rules.js +74 -0
  110. package/dist/src/pipeline/workflow/defaults.js +48 -0
  111. package/dist/src/pipeline/workflow/io.js +89 -0
  112. package/dist/src/pipeline/workflow/normalize.js +347 -0
  113. package/dist/src/pipeline/workflow/routes.js +16 -0
  114. package/dist/src/pipeline/workflow/template-mapper.js +113 -0
  115. package/dist/src/pipeline/workflow/validate.js +312 -0
  116. package/dist/src/pipeline/workflow-graph.js +165 -0
  117. package/dist/src/server/api-handler.js +163 -0
  118. package/dist/src/server/http-utils.js +34 -0
  119. package/dist/src/server/middleware.js +61 -0
  120. package/dist/src/server/router.js +105 -0
  121. package/dist/src/server/routes/agents.js +189 -0
  122. package/dist/src/server/routes/artifacts.js +163 -0
  123. package/dist/src/server/routes/gateway.js +18 -0
  124. package/dist/src/server/routes/health.js +16 -0
  125. package/dist/src/server/routes/logs.js +73 -0
  126. package/dist/src/server/routes/pipeline-batch.js +163 -0
  127. package/dist/src/server/routes/pipeline-diagnostics.js +33 -0
  128. package/dist/src/server/routes/pipeline-identity.js +24 -0
  129. package/dist/src/server/routes/pipeline-links.js +117 -0
  130. package/dist/src/server/routes/pipeline-outputs.js +27 -0
  131. package/dist/src/server/routes/pipeline-queue.js +62 -0
  132. package/dist/src/server/routes/pipeline-runtime.js +162 -0
  133. package/dist/src/server/routes/pipeline-scheduler.js +69 -0
  134. package/dist/src/server/routes/pipeline-workflow.js +180 -0
  135. package/dist/src/server/routes/pipelines.js +96 -0
  136. package/dist/src/server/routes/sessions.js +244 -0
  137. package/dist/src/server/routes/timeline.js +14 -0
  138. package/dist/src/server/serve-static.js +42 -0
  139. package/dist/src/server/types.js +2 -0
  140. package/dist/src/services/agent-service.js +79 -0
  141. package/dist/src/services/artifact-service.js +74 -0
  142. package/dist/src/services/gateway-read-helpers.js +10 -0
  143. package/dist/src/services/index.js +23 -0
  144. package/dist/src/services/pipeline-service.js +529 -0
  145. package/dist/src/services/pipeline-status.js +93 -0
  146. package/dist/src/services/read-services.js +60 -0
  147. package/dist/src/services/scheduler-service.js +37 -0
  148. package/dist/src/services/session-service.js +227 -0
  149. package/dist/src/services/system-service.js +26 -0
  150. package/dist/src/transport/ws-broker.js +48 -0
  151. package/dist/src/utils/array.js +17 -0
  152. package/dist/src/utils/guards.js +5 -0
  153. package/dist/src/utils/session.js +60 -0
  154. package/dist/src/version.js +5 -0
  155. package/package.json +61 -0
  156. package/web/dist/assets/index-CWnfhkn-.js +65 -0
  157. package/web/dist/assets/index-gZ0xOfSO.css +1 -0
  158. package/web/dist/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  159. package/web/dist/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  160. package/web/dist/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
  161. package/web/dist/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
  162. package/web/dist/assets/jetbrains-mono-cyrillic-700-normal-BWTpRfYl.woff2 +0 -0
  163. package/web/dist/assets/jetbrains-mono-cyrillic-700-normal-CEoEElIJ.woff +0 -0
  164. package/web/dist/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  165. package/web/dist/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  166. package/web/dist/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
  167. package/web/dist/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
  168. package/web/dist/assets/jetbrains-mono-greek-700-normal-C6CZE3T8.woff2 +0 -0
  169. package/web/dist/assets/jetbrains-mono-greek-700-normal-DEigVDxa.woff +0 -0
  170. package/web/dist/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  171. package/web/dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  172. package/web/dist/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  173. package/web/dist/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  174. package/web/dist/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
  175. package/web/dist/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
  176. package/web/dist/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  177. package/web/dist/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  178. package/web/dist/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
  179. package/web/dist/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
  180. package/web/dist/assets/jetbrains-mono-latin-ext-700-normal-CZipNAKV.woff2 +0 -0
  181. package/web/dist/assets/jetbrains-mono-latin-ext-700-normal-CxPITLHs.woff +0 -0
  182. package/web/dist/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  183. package/web/dist/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
  184. package/web/dist/assets/jetbrains-mono-vietnamese-700-normal-BDLVIk2r.woff +0 -0
  185. package/web/dist/assets/space-grotesk-latin-400-normal-BnQMeOim.woff +0 -0
  186. package/web/dist/assets/space-grotesk-latin-400-normal-CJ-V5oYT.woff2 +0 -0
  187. package/web/dist/assets/space-grotesk-latin-500-normal-CNSSEhBt.woff +0 -0
  188. package/web/dist/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
  189. package/web/dist/assets/space-grotesk-latin-700-normal-CwsQ-cCU.woff +0 -0
  190. package/web/dist/assets/space-grotesk-latin-700-normal-RjhwGPKo.woff2 +0 -0
  191. package/web/dist/assets/space-grotesk-latin-ext-400-normal-CfP_5XZW.woff2 +0 -0
  192. package/web/dist/assets/space-grotesk-latin-ext-400-normal-DRPE3kg4.woff +0 -0
  193. package/web/dist/assets/space-grotesk-latin-ext-500-normal-3dgZTiw9.woff +0 -0
  194. package/web/dist/assets/space-grotesk-latin-ext-500-normal-DUe3BAxM.woff2 +0 -0
  195. package/web/dist/assets/space-grotesk-latin-ext-700-normal-BQnZhY3m.woff2 +0 -0
  196. package/web/dist/assets/space-grotesk-latin-ext-700-normal-HVCqSBdx.woff +0 -0
  197. package/web/dist/assets/space-grotesk-vietnamese-400-normal-B7xT_GF5.woff2 +0 -0
  198. package/web/dist/assets/space-grotesk-vietnamese-400-normal-BIWiOVfw.woff +0 -0
  199. package/web/dist/assets/space-grotesk-vietnamese-500-normal-BTqKIpxg.woff +0 -0
  200. package/web/dist/assets/space-grotesk-vietnamese-500-normal-BmEvtly_.woff2 +0 -0
  201. package/web/dist/assets/space-grotesk-vietnamese-700-normal-DMty7AZE.woff2 +0 -0
  202. package/web/dist/assets/space-grotesk-vietnamese-700-normal-Duxec5Rn.woff +0 -0
  203. package/web/dist/favicon.svg +10 -0
  204. package/web/dist/index.html +14 -0
@@ -0,0 +1,163 @@
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;
@@ -0,0 +1,18 @@
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;
@@ -0,0 +1,16 @@
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;
@@ -0,0 +1,73 @@
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;
@@ -0,0 +1,163 @@
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;
@@ -0,0 +1,33 @@
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;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeIdentityTargets = exports.readIdentityTargetFromBody = exports.readIdentityTargetFromUrl = void 0;
4
+ // 从 URL 查询参数提取 runId / batchRunId
5
+ const readIdentityTargetFromUrl = (url) => ({
6
+ runId: String(url.searchParams.get("runId") ?? "").trim() || undefined,
7
+ batchRunId: String(url.searchParams.get("batchRunId") ?? "").trim() || undefined,
8
+ });
9
+ exports.readIdentityTargetFromUrl = readIdentityTargetFromUrl;
10
+ // 从请求体提取 runId / batchRunId
11
+ const readIdentityTargetFromBody = (body) => ({
12
+ runId: typeof body.runId === "string" && body.runId.trim() ? body.runId.trim() : undefined,
13
+ batchRunId: typeof body.batchRunId === "string" && body.batchRunId.trim() ? body.batchRunId.trim() : undefined,
14
+ });
15
+ exports.readIdentityTargetFromBody = readIdentityTargetFromBody;
16
+ // 合并两组 IdentityTarget,primary 优先
17
+ const mergeIdentityTargets = (primary, fallback) => {
18
+ const runId = primary?.runId ?? fallback?.runId;
19
+ const batchRunId = primary?.batchRunId ?? fallback?.batchRunId;
20
+ if (!runId && !batchRunId)
21
+ return undefined;
22
+ return { runId, batchRunId };
23
+ };
24
+ exports.mergeIdentityTargets = mergeIdentityTargets;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerPipelineLinksRoutes = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const pipeline_link_js_1 = require("../../pipeline/types/pipeline-link.js");
6
+ const registerPipelineLinksRoutes = (router) => {
7
+ // GET /api/pipeline-links
8
+ router.register("GET", "/api/pipeline-links", async (ctx) => {
9
+ const { app } = ctx.options;
10
+ const links = await app.dispatch.listLinks();
11
+ ctx.sendJson(200, { ok: true, items: links });
12
+ });
13
+ // POST /api/pipeline-links
14
+ router.register("POST", "/api/pipeline-links", async (ctx) => {
15
+ const { app } = ctx.options;
16
+ const body = await ctx.readBody();
17
+ const id = typeof body.id === "string" ? body.id.trim() : `link:${(0, node_crypto_1.randomUUID)()}`;
18
+ if (!(0, pipeline_link_js_1.isValidLinkId)(id)) {
19
+ ctx.sendJson(400, { ok: false, error: "pipeline_link_invalid_id" });
20
+ return;
21
+ }
22
+ const fromPipelineId = typeof body.fromPipelineId === "string" ? body.fromPipelineId.trim() : "";
23
+ const toPipelineId = typeof body.toPipelineId === "string" ? body.toPipelineId.trim() : "";
24
+ if (!fromPipelineId || !toPipelineId) {
25
+ ctx.sendJson(400, { ok: false, error: "pipeline_link_missing_pipelines" });
26
+ return;
27
+ }
28
+ if (!app.getPipelineDefinition(fromPipelineId)) {
29
+ ctx.sendJson(400, { ok: false, error: "pipeline_not_found", detail: `上游流水线 ${fromPipelineId} 不存在` });
30
+ return;
31
+ }
32
+ if (!app.getPipelineDefinition(toPipelineId)) {
33
+ ctx.sendJson(400, { ok: false, error: "pipeline_not_found", detail: `下游流水线 ${toPipelineId} 不存在` });
34
+ return;
35
+ }
36
+ const contract = body.inputContract && typeof body.inputContract === "object"
37
+ ? {
38
+ requireType: typeof body.inputContract.requireType === "string"
39
+ ? body.inputContract.requireType
40
+ : undefined,
41
+ requireSchemaVersion: typeof body.inputContract.requireSchemaVersion === "number"
42
+ ? body.inputContract.requireSchemaVersion
43
+ : undefined,
44
+ }
45
+ : null;
46
+ const maxPendingJobs = typeof body.maxPendingJobs === "number" && Number.isFinite(body.maxPendingJobs)
47
+ ? Math.min(10000, Math.max(1, Math.trunc(body.maxPendingJobs)))
48
+ : 100;
49
+ const onJobFailed = body.onJobFailed === "pause" ? "pause" : "continue";
50
+ const now = new Date().toISOString();
51
+ const link = {
52
+ schemaVersion: 1,
53
+ id,
54
+ enabled: body.enabled !== false,
55
+ fromPipelineId,
56
+ toPipelineId,
57
+ trigger: "on_success",
58
+ dispatchPolicy: "fifo",
59
+ inputContract: contract,
60
+ onJobFailed,
61
+ maxPendingJobs,
62
+ createdAt: now,
63
+ updatedAt: now,
64
+ };
65
+ const result = await app.dispatch.createLink(link);
66
+ if (!result.ok) {
67
+ const statusCode = result.error === "pipeline_link_duplicate" ? 409 : 400;
68
+ ctx.sendJson(statusCode, { ok: false, error: result.error });
69
+ return;
70
+ }
71
+ ctx.sendJson(201, { ok: true, link: result.link });
72
+ });
73
+ // PATCH /api/pipeline-links/:linkId
74
+ router.register("PATCH", "/api/pipeline-links/:linkId", async (ctx) => {
75
+ const { app } = ctx.options;
76
+ const { linkId } = ctx.params;
77
+ const body = await ctx.readBody();
78
+ const patch = {};
79
+ if (typeof body.enabled === "boolean")
80
+ patch.enabled = body.enabled;
81
+ if (body.inputContract !== undefined) {
82
+ patch.inputContract = body.inputContract && typeof body.inputContract === "object"
83
+ ? {
84
+ requireType: typeof body.inputContract.requireType === "string"
85
+ ? body.inputContract.requireType
86
+ : undefined,
87
+ requireSchemaVersion: typeof body.inputContract.requireSchemaVersion === "number"
88
+ ? body.inputContract.requireSchemaVersion
89
+ : undefined,
90
+ }
91
+ : null;
92
+ }
93
+ if (body.onJobFailed === "continue" || body.onJobFailed === "pause")
94
+ patch.onJobFailed = body.onJobFailed;
95
+ if (typeof body.maxPendingJobs === "number" && Number.isFinite(body.maxPendingJobs)) {
96
+ patch.maxPendingJobs = Math.min(10000, Math.max(1, Math.trunc(body.maxPendingJobs)));
97
+ }
98
+ const result = await app.dispatch.updateLink(linkId, patch);
99
+ if (!result.ok) {
100
+ ctx.sendJson(404, { ok: false, error: result.error });
101
+ return;
102
+ }
103
+ ctx.sendJson(200, { ok: true, link: result.link });
104
+ });
105
+ // DELETE /api/pipeline-links/:linkId
106
+ router.register("DELETE", "/api/pipeline-links/:linkId", async (ctx) => {
107
+ const { app } = ctx.options;
108
+ const { linkId } = ctx.params;
109
+ const result = await app.dispatch.deleteLink(linkId);
110
+ if (!result.ok) {
111
+ ctx.sendJson(404, { ok: false, error: result.error });
112
+ return;
113
+ }
114
+ ctx.sendJson(200, { ok: true });
115
+ });
116
+ };
117
+ exports.registerPipelineLinksRoutes = registerPipelineLinksRoutes;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerPipelineOutputsRoutes = void 0;
4
+ const registerPipelineOutputsRoutes = (router) => {
5
+ // GET /api/pipelines/:pipelineId/outputs
6
+ router.register("GET", "/api/pipelines/:pipelineId/outputs", async (ctx) => {
7
+ const { app } = ctx.options;
8
+ const { pipelineId } = ctx.params;
9
+ const runtime = app.getPipelineRuntime(pipelineId);
10
+ if (!runtime) {
11
+ ctx.sendJson(404, { ok: false, error: "pipeline_not_found", pipelineId });
12
+ return;
13
+ }
14
+ const runId = ctx.url.searchParams.get("runId")?.trim() || undefined;
15
+ const batchRunId = ctx.url.searchParams.get("batchRunId")?.trim() || undefined;
16
+ const outputs = await runtime.output.list();
17
+ let filtered = outputs;
18
+ if (runId)
19
+ filtered = filtered.filter((o) => o.runId === runId);
20
+ if (batchRunId)
21
+ filtered = filtered.filter((o) => o.batchRunId === batchRunId);
22
+ // Sort newest first
23
+ filtered.sort((a, b) => b.producedAt.localeCompare(a.producedAt));
24
+ ctx.sendJson(200, { ok: true, pipelineId, items: filtered });
25
+ });
26
+ };
27
+ exports.registerPipelineOutputsRoutes = registerPipelineOutputsRoutes;