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,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createApiHandler = void 0;
|
|
4
|
+
const node_url_1 = require("node:url");
|
|
5
|
+
const http_utils_1 = require("./http-utils");
|
|
6
|
+
const serve_static_1 = require("./serve-static");
|
|
7
|
+
const router_js_1 = require("./router.js");
|
|
8
|
+
const middleware_js_1 = require("./middleware.js");
|
|
9
|
+
const health_js_1 = require("./routes/health.js");
|
|
10
|
+
const gateway_js_1 = require("./routes/gateway.js");
|
|
11
|
+
const timeline_js_1 = require("./routes/timeline.js");
|
|
12
|
+
const logs_js_1 = require("./routes/logs.js");
|
|
13
|
+
const artifacts_js_1 = require("./routes/artifacts.js");
|
|
14
|
+
const agents_js_1 = require("./routes/agents.js");
|
|
15
|
+
const sessions_js_1 = require("./routes/sessions.js");
|
|
16
|
+
const pipelines_js_1 = require("./routes/pipelines.js");
|
|
17
|
+
const pipeline_workflow_js_1 = require("./routes/pipeline-workflow.js");
|
|
18
|
+
const pipeline_runtime_js_1 = require("./routes/pipeline-runtime.js");
|
|
19
|
+
const pipeline_batch_js_1 = require("./routes/pipeline-batch.js");
|
|
20
|
+
const pipeline_scheduler_js_1 = require("./routes/pipeline-scheduler.js");
|
|
21
|
+
const pipeline_diagnostics_js_1 = require("./routes/pipeline-diagnostics.js");
|
|
22
|
+
const pipeline_outputs_js_1 = require("./routes/pipeline-outputs.js");
|
|
23
|
+
const pipeline_links_js_1 = require("./routes/pipeline-links.js");
|
|
24
|
+
const pipeline_queue_js_1 = require("./routes/pipeline-queue.js");
|
|
25
|
+
const run_log_service_1 = require("../logs/run-log-service");
|
|
26
|
+
const pipeline_service_js_1 = require("../services/pipeline-service.js");
|
|
27
|
+
const scheduler_service_js_1 = require("../services/scheduler-service.js");
|
|
28
|
+
const data_dir_1 = require("../app/data-dir");
|
|
29
|
+
const createApiHandler = (options) => {
|
|
30
|
+
const runLogService = (0, run_log_service_1.createRunLogService)({
|
|
31
|
+
rootDir: (0, data_dir_1.resolveTaskMeldDataPath)("logs", "runs"),
|
|
32
|
+
});
|
|
33
|
+
// Phase 1-5: 基于 Router 的路由迁移(全部路由模块)
|
|
34
|
+
const router = (0, router_js_1.createRouter)();
|
|
35
|
+
(0, health_js_1.registerHealthRoutes)(router);
|
|
36
|
+
(0, gateway_js_1.registerGatewayRoutes)(router);
|
|
37
|
+
(0, timeline_js_1.registerTimelineRoutes)(router);
|
|
38
|
+
(0, logs_js_1.registerLogRoutes)(router);
|
|
39
|
+
(0, artifacts_js_1.registerArtifactsRoutes)(router);
|
|
40
|
+
(0, agents_js_1.registerAgentsRoutes)(router);
|
|
41
|
+
(0, sessions_js_1.registerSessionsRoutes)(router);
|
|
42
|
+
(0, pipelines_js_1.registerPipelinesRoutes)(router);
|
|
43
|
+
(0, pipeline_workflow_js_1.registerPipelineWorkflowRoutes)(router);
|
|
44
|
+
(0, pipeline_runtime_js_1.registerPipelineRuntimeRoutes)(router);
|
|
45
|
+
(0, pipeline_batch_js_1.registerPipelineBatchRoutes)(router);
|
|
46
|
+
(0, pipeline_scheduler_js_1.registerPipelineSchedulerRoutes)(router);
|
|
47
|
+
(0, pipeline_diagnostics_js_1.registerPipelineDiagnosticsRoutes)(router);
|
|
48
|
+
(0, pipeline_outputs_js_1.registerPipelineOutputsRoutes)(router);
|
|
49
|
+
(0, pipeline_links_js_1.registerPipelineLinksRoutes)(router);
|
|
50
|
+
(0, pipeline_queue_js_1.registerPipelineQueueRoutes)(router);
|
|
51
|
+
const pipeline = (0, middleware_js_1.composeMiddleware)(middleware_js_1.errorMiddleware, (0, middleware_js_1.corsMiddleware)(options.webOrigin));
|
|
52
|
+
// 已迁移路由共享的 services
|
|
53
|
+
const pipelineService = (0, pipeline_service_js_1.createPipelineService)(options.app);
|
|
54
|
+
const schedulerService = (0, scheduler_service_js_1.createSchedulerService)(options.app);
|
|
55
|
+
const migratedServices = {
|
|
56
|
+
client: options.app.gateway.client,
|
|
57
|
+
getLatestStatus: options.app.gateway.getLatestStatus,
|
|
58
|
+
getLatestHello: options.app.gateway.getLatestHello,
|
|
59
|
+
getLastFrame: options.app.gateway.getLastFrame,
|
|
60
|
+
getTimeline: options.app.runtime.getCombinedTimeline,
|
|
61
|
+
runLogService,
|
|
62
|
+
pickArray: options.app.gateway.pickArray,
|
|
63
|
+
refreshSessionsFromGateway: options.app.gateway.refreshSessionsFromGateway,
|
|
64
|
+
getSessionCache: options.app.gateway.getSessionCache,
|
|
65
|
+
pushTimeline: (...args) => {
|
|
66
|
+
const primary = options.app.getPrimaryRuntime();
|
|
67
|
+
primary?.runtime.pushTimeline(...args);
|
|
68
|
+
},
|
|
69
|
+
listPipelines: options.app.listPipelines.bind(options.app),
|
|
70
|
+
getPipelineDefinition: options.app.getPipelineDefinition.bind(options.app),
|
|
71
|
+
pipelineService,
|
|
72
|
+
schedulerService,
|
|
73
|
+
};
|
|
74
|
+
return async (req, res) => {
|
|
75
|
+
const method = req.method ?? "GET";
|
|
76
|
+
const reqUrl = req.url ?? "/";
|
|
77
|
+
const url = new node_url_1.URL(reqUrl, `http://127.0.0.1:${options.apiPort}`);
|
|
78
|
+
// 全局 OPTIONS 处理:所有非 router 匹配的 OPTIONS 请求统一在此返回 204
|
|
79
|
+
// (router 匹配的 OPTIONS 由 corsMiddleware 在 pipeline 内处理)
|
|
80
|
+
if (method === "OPTIONS") {
|
|
81
|
+
res.writeHead(204, {
|
|
82
|
+
"Access-Control-Allow-Origin": options.webOrigin,
|
|
83
|
+
"Access-Control-Allow-Methods": "GET,POST,PATCH,DELETE,OPTIONS",
|
|
84
|
+
"Access-Control-Allow-Headers": "Content-Type",
|
|
85
|
+
});
|
|
86
|
+
res.end();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const match = router.match(method, url.pathname);
|
|
90
|
+
if (match) {
|
|
91
|
+
let _bodyPromise = null;
|
|
92
|
+
const migratedCtx = {
|
|
93
|
+
req,
|
|
94
|
+
res,
|
|
95
|
+
method,
|
|
96
|
+
url,
|
|
97
|
+
params: match.params,
|
|
98
|
+
options,
|
|
99
|
+
services: migratedServices,
|
|
100
|
+
sendJson: (code, data) => (0, http_utils_1.sendJson)(res, code, data, options.webOrigin),
|
|
101
|
+
sendRaw: (code, headers, body) => {
|
|
102
|
+
res.writeHead(code, {
|
|
103
|
+
...headers,
|
|
104
|
+
"Access-Control-Allow-Origin": options.webOrigin,
|
|
105
|
+
"Access-Control-Allow-Methods": "GET,POST,PATCH,DELETE,OPTIONS",
|
|
106
|
+
"Access-Control-Allow-Headers": "Content-Type",
|
|
107
|
+
});
|
|
108
|
+
body.pipe(res);
|
|
109
|
+
},
|
|
110
|
+
readBody: () => {
|
|
111
|
+
if (!_bodyPromise)
|
|
112
|
+
_bodyPromise = (0, http_utils_1.readJsonBody)(req);
|
|
113
|
+
return _bodyPromise;
|
|
114
|
+
},
|
|
115
|
+
getPipelineScope: () => {
|
|
116
|
+
const pipelineId = match.params.pipelineId;
|
|
117
|
+
if (!pipelineId)
|
|
118
|
+
return null;
|
|
119
|
+
const runtime = options.app.getPipelineRuntime(pipelineId);
|
|
120
|
+
const definition = options.app.getPipelineDefinition(pipelineId);
|
|
121
|
+
if (!runtime || !definition)
|
|
122
|
+
return null;
|
|
123
|
+
return {
|
|
124
|
+
pipelineId: definition.id,
|
|
125
|
+
workflowFilePath: definition.workflowFilePath,
|
|
126
|
+
pushTimeline: runtime.runtime.pushTimeline,
|
|
127
|
+
touchRun: runtime.runtime.touchRun,
|
|
128
|
+
seedRun: runtime.runtime.seedRun,
|
|
129
|
+
emitPipeline: runtime.runtime.emitPipeline,
|
|
130
|
+
getRun: runtime.runtime.getRun,
|
|
131
|
+
setRun: runtime.runtime.setRun,
|
|
132
|
+
getTemplateNodes: runtime.workflow.getTemplateNodes,
|
|
133
|
+
setTemplateNodes: runtime.workflow.setTemplateNodes,
|
|
134
|
+
getWorkflow: runtime.workflow.getWorkflow,
|
|
135
|
+
setWorkflow: runtime.workflow.setWorkflow,
|
|
136
|
+
getItemRuns: runtime.pipeline.getItemRuns,
|
|
137
|
+
drainPipeline: runtime.pipeline.drainPipeline,
|
|
138
|
+
setSchedulerEnabled: runtime.pipeline.setSchedulerEnabled,
|
|
139
|
+
setSchedulerMode: runtime.pipeline.setSchedulerMode,
|
|
140
|
+
getSchedulerState: runtime.pipeline.getSchedulerState,
|
|
141
|
+
getBatchRunState: runtime.pipeline.getBatchRunState,
|
|
142
|
+
cancelBatchRun: runtime.pipeline.cancelBatchRun,
|
|
143
|
+
executorSessionByAgentId: runtime.gateway.getExecutorSessionByAgentId(),
|
|
144
|
+
getSessionCache: runtime.gateway.getSessionCache,
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
await pipeline(migratedCtx, async () => {
|
|
149
|
+
await match.handler(migratedCtx);
|
|
150
|
+
});
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (url.pathname.startsWith("/api/") || url.pathname === "/api") {
|
|
154
|
+
(0, http_utils_1.sendJson)(res, 404, { error: "not_found" }, options.webOrigin);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// SPA static file serving — falls back to index.html for client-side routing
|
|
158
|
+
if ((0, serve_static_1.serveStatic)(req, res))
|
|
159
|
+
return;
|
|
160
|
+
(0, http_utils_1.sendJson)(res, 404, { error: "not_found" }, options.webOrigin);
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
exports.createApiHandler = createApiHandler;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.firstText = exports.readJsonBody = exports.sendJson = void 0;
|
|
4
|
+
const sendJson = (res, code, data, webOrigin) => {
|
|
5
|
+
res.writeHead(code, {
|
|
6
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
7
|
+
"Access-Control-Allow-Origin": webOrigin,
|
|
8
|
+
"Access-Control-Allow-Methods": "GET,POST,PATCH,OPTIONS",
|
|
9
|
+
"Access-Control-Allow-Headers": "Content-Type",
|
|
10
|
+
});
|
|
11
|
+
res.end(JSON.stringify(data));
|
|
12
|
+
};
|
|
13
|
+
exports.sendJson = sendJson;
|
|
14
|
+
const readJsonBody = async (req) => {
|
|
15
|
+
const chunks = [];
|
|
16
|
+
for await (const chunk of req) {
|
|
17
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
18
|
+
}
|
|
19
|
+
if (chunks.length === 0) {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
23
|
+
};
|
|
24
|
+
exports.readJsonBody = readJsonBody;
|
|
25
|
+
const firstText = (body) => {
|
|
26
|
+
const candidates = [body.text, body.message, body.content, body.input];
|
|
27
|
+
for (const candidate of candidates) {
|
|
28
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
29
|
+
return candidate.trim();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return "";
|
|
33
|
+
};
|
|
34
|
+
exports.firstText = firstText;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.corsMiddleware = exports.errorMiddleware = exports.composeMiddleware = void 0;
|
|
4
|
+
const composeMiddleware = (...middlewares) => {
|
|
5
|
+
return (ctx, handler) => {
|
|
6
|
+
const execute = (index) => {
|
|
7
|
+
if (index >= middlewares.length) {
|
|
8
|
+
return Promise.resolve(handler(ctx)).then(() => { });
|
|
9
|
+
}
|
|
10
|
+
let nextCalled = false;
|
|
11
|
+
const next = () => {
|
|
12
|
+
if (nextCalled) {
|
|
13
|
+
throw new Error("next() called multiple times in middleware");
|
|
14
|
+
}
|
|
15
|
+
nextCalled = true;
|
|
16
|
+
return execute(index + 1);
|
|
17
|
+
};
|
|
18
|
+
const result = middlewares[index](ctx, next);
|
|
19
|
+
return Promise.resolve(result).then(() => { });
|
|
20
|
+
};
|
|
21
|
+
return execute(0);
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
exports.composeMiddleware = composeMiddleware;
|
|
25
|
+
const errorMiddleware = async (ctx, next) => {
|
|
26
|
+
try {
|
|
27
|
+
await next();
|
|
28
|
+
}
|
|
29
|
+
catch (_error) {
|
|
30
|
+
if (!ctx.res.headersSent) {
|
|
31
|
+
ctx.sendJson(500, { error: "internal_error" });
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
try {
|
|
35
|
+
ctx.res.end();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Socket may already be destroyed
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
exports.errorMiddleware = errorMiddleware;
|
|
44
|
+
const corsMiddleware = (webOrigin) => {
|
|
45
|
+
return (ctx, next) => {
|
|
46
|
+
if (ctx.req.method === "OPTIONS") {
|
|
47
|
+
ctx.res.writeHead(204, {
|
|
48
|
+
"Access-Control-Allow-Origin": webOrigin,
|
|
49
|
+
"Access-Control-Allow-Methods": "GET,POST,PATCH,DELETE,OPTIONS",
|
|
50
|
+
"Access-Control-Allow-Headers": "Content-Type",
|
|
51
|
+
});
|
|
52
|
+
ctx.res.end();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
ctx.res.setHeader("Access-Control-Allow-Origin", webOrigin);
|
|
56
|
+
ctx.res.setHeader("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE,OPTIONS");
|
|
57
|
+
ctx.res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
58
|
+
return next();
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
exports.corsMiddleware = corsMiddleware;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRouter = void 0;
|
|
4
|
+
const createNode = () => ({
|
|
5
|
+
staticChildren: new Map(),
|
|
6
|
+
handlers: new Map(),
|
|
7
|
+
});
|
|
8
|
+
const createRouter = () => {
|
|
9
|
+
const root = createNode();
|
|
10
|
+
const register = (method, path, handler) => {
|
|
11
|
+
if (!path.startsWith("/")) {
|
|
12
|
+
throw new Error(`Route path must start with "/": ${path}`);
|
|
13
|
+
}
|
|
14
|
+
const normalizedMethod = method.toUpperCase();
|
|
15
|
+
const segments = path.split("/").slice(1);
|
|
16
|
+
let current = root;
|
|
17
|
+
for (let i = 0; i < segments.length; i++) {
|
|
18
|
+
const segment = segments[i];
|
|
19
|
+
if (!segment)
|
|
20
|
+
continue;
|
|
21
|
+
if (segment.startsWith("*")) {
|
|
22
|
+
const name = segment.slice(1);
|
|
23
|
+
if (!current.wildcardChild) {
|
|
24
|
+
current.wildcardChild = { name, node: createNode() };
|
|
25
|
+
}
|
|
26
|
+
current = current.wildcardChild.node;
|
|
27
|
+
}
|
|
28
|
+
else if (segment.startsWith(":")) {
|
|
29
|
+
const name = segment.slice(1);
|
|
30
|
+
if (!current.paramChild) {
|
|
31
|
+
current.paramChild = { name, node: createNode() };
|
|
32
|
+
}
|
|
33
|
+
current = current.paramChild.node;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
let child = current.staticChildren.get(segment);
|
|
37
|
+
if (!child) {
|
|
38
|
+
child = createNode();
|
|
39
|
+
current.staticChildren.set(segment, child);
|
|
40
|
+
}
|
|
41
|
+
current = child;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (current.handlers.has(normalizedMethod)) {
|
|
45
|
+
throw new Error(`Duplicate route: ${normalizedMethod} ${path}`);
|
|
46
|
+
}
|
|
47
|
+
current.handlers.set(normalizedMethod, handler);
|
|
48
|
+
};
|
|
49
|
+
const match = (method, pathname) => {
|
|
50
|
+
const normalizedMethod = method.toUpperCase();
|
|
51
|
+
const segments = pathname.split("/").slice(1);
|
|
52
|
+
const params = {};
|
|
53
|
+
const matchNode = (node, index) => {
|
|
54
|
+
if (index >= segments.length) {
|
|
55
|
+
return node;
|
|
56
|
+
}
|
|
57
|
+
const segment = segments[index];
|
|
58
|
+
const staticChild = node.staticChildren.get(segment);
|
|
59
|
+
if (staticChild) {
|
|
60
|
+
const result = matchNode(staticChild, index + 1);
|
|
61
|
+
if (result)
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
if (node.paramChild) {
|
|
65
|
+
try {
|
|
66
|
+
const decoded = decodeURIComponent(segment);
|
|
67
|
+
const prevParam = params[node.paramChild.name];
|
|
68
|
+
params[node.paramChild.name] = decoded;
|
|
69
|
+
const result = matchNode(node.paramChild.node, index + 1);
|
|
70
|
+
if (result)
|
|
71
|
+
return result;
|
|
72
|
+
if (prevParam === undefined) {
|
|
73
|
+
delete params[node.paramChild.name];
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
params[node.paramChild.name] = prevParam;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (node.wildcardChild) {
|
|
84
|
+
const rest = segments.slice(index).join("/");
|
|
85
|
+
try {
|
|
86
|
+
params[node.wildcardChild.name] = decodeURIComponent(rest);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
return node.wildcardChild.node;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
};
|
|
95
|
+
const matchedNode = matchNode(root, 0);
|
|
96
|
+
if (!matchedNode)
|
|
97
|
+
return null;
|
|
98
|
+
const handler = matchedNode.handlers.get(normalizedMethod);
|
|
99
|
+
if (!handler)
|
|
100
|
+
return null;
|
|
101
|
+
return { handler, params };
|
|
102
|
+
};
|
|
103
|
+
return { register, match };
|
|
104
|
+
};
|
|
105
|
+
exports.createRouter = createRouter;
|
|
@@ -0,0 +1,189 @@
|
|
|
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;
|