Files
16gagent/scripts/runtime.mjs
T
2026-06-06 10:40:48 +08:00

87 lines
3.1 KiB
JavaScript

#!/usr/bin/env node
/**
* Agent Runtime CLI — PR-35
*
* Usage:
* echo '{"task":{...},"context":{...}}' | node scripts/runtime.mjs
*
* stdin:
* { task, context: { baselineData?, candidateData?, ... }, options? }
*
* Output: JSON { success, taskResult, report }
* Exit: 0=passed, 1=failed/blocked/error
*/
import { readFileSync } from "node:fs";
import { createTask, createExecutionPlan } from "../src/agent-runtime/domain.mjs";
import { executePipeline, recoverTask } from "../src/agent-runtime/pipeline.mjs";
import { createRuntimeContext, autoGateAdapter, createCertificationAdapter } from "../src/agent-runtime/adapters.mjs";
import { generateRuntimeReport } from "../src/agent-runtime/reporting.mjs";
function readStdin() {
try {
const raw = readFileSync(0, "utf8").trim();
return raw ? JSON.parse(raw) : null;
} catch (e) {
return { _error: `Parse error: ${e.message}` };
}
}
function main() {
const input = readStdin();
if (!input) { console.error("Error: No stdin input."); process.exit(1); }
if (input._error) { console.error(input._error); process.exit(1); }
const { task: rawTask, context: rawCtx = {}, options = {}, action = "execute" } = input;
if (!rawTask) { console.error("Error: 'task' field required."); process.exit(1); }
// 反序列化 Task
const task = createTask({
id: rawTask.id, title: rawTask.title || rawTask.id,
description: rawTask.description, tags: rawTask.tags,
dependsOn: rawTask.dependsOn, parentTaskId: rawTask.parentTaskId,
metadata: rawTask.metadata,
});
task.executionPlan = createExecutionPlan({
taskId: task.id,
steps: (rawTask.steps || []).map(s => ({
id: s.id, name: s.name || s.id, action: s.action || s.name,
dependsOn: s.dependsOn, expectedArtifacts: s.expectedArtifacts, metadata: s.metadata,
})),
strategy: rawTask.strategy,
});
task.maxRetries = rawTask.maxRetries ?? 3;
// 构建 Runtime Context
const rctx = createRuntimeContext({
checklistAdapter: rawCtx.checklist ? (ctx) => ({ status: rawCtx.checklist === "pass" ? "pass" : "fail", blockers: [], warnings: [], confidence: 100 }) : null,
baselineAdapter: rawCtx.baseline ? (_ctx, b, c) => ({ status: "pass", changes: [], blockers: [], warnings: [] }) : null,
gateAdapter: rawCtx.gate ? autoGateAdapter : null,
certificationAdapter: createCertificationAdapter(),
baselineData: rawCtx.baselineData || null,
candidateData: rawCtx.candidateData || null,
pipelineOptions: options,
});
try {
let taskResult;
if (action === "recover") {
task.state = "failed";
task.retryCount = rawTask.retryCount || 0;
taskResult = recoverTask(task, rctx, options);
} else {
taskResult = executePipeline(task, rctx, options);
}
const report = generateRuntimeReport(task, taskResult);
const output = { success: taskResult.status === "passed", taskResult, report };
console.log(JSON.stringify(output, null, 2));
process.exit(taskResult.status === "passed" ? 0 : 1);
} catch (e) {
console.error(`Runtime error: ${e.message}`);
process.exit(1);
}
}
main();