#!/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();