feat: freeze legacy code queue entry
This commit is contained in:
+153
-3
@@ -1,3 +1,4 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import type { UniDeskConfig } from "./config";
|
||||
import { runSshCommandCapture, type SshCaptureResult } from "./ssh";
|
||||
import { startJob } from "./jobs";
|
||||
@@ -22,9 +23,17 @@ const mirrorToolsImage = "127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine
|
||||
|
||||
export function agentRunHelp(): unknown {
|
||||
return {
|
||||
command: "agentrun v01 control-plane status|trigger-current|refresh|cleanup-runs|cleanup-released-pvs | git-mirror status|sync|flush",
|
||||
command: "agentrun v01 control-plane status|trigger-current|refresh|cleanup-runs|cleanup-released-pvs | git-mirror status|sync|flush | queue submit|list|show|stats|commander|read|cancel|dispatch|refresh | sessions ps|show|turn|steer|cancel|output|trace|read",
|
||||
output: "json",
|
||||
usage: [
|
||||
"bun scripts/cli.ts agentrun v01 queue commander --reader-id cli",
|
||||
"bun scripts/cli.ts agentrun v01 queue submit --json-file <task.json>",
|
||||
"bun scripts/cli.ts agentrun v01 queue dispatch <taskId> --json-file <dispatch.json>",
|
||||
"bun scripts/cli.ts agentrun v01 queue cancel <taskId> --reason <text>",
|
||||
"bun scripts/cli.ts agentrun v01 sessions trace <sessionId> --after-seq 0 --limit 100",
|
||||
"bun scripts/cli.ts agentrun v01 sessions output <sessionId> --after-seq 0 --limit 100",
|
||||
"bun scripts/cli.ts agentrun v01 sessions steer <sessionId> --prompt-file <path>",
|
||||
"bun scripts/cli.ts agentrun v01 sessions read <sessionId> --reader-id cli",
|
||||
"bun scripts/cli.ts agentrun v01 control-plane status",
|
||||
"bun scripts/cli.ts agentrun v01 control-plane status --full",
|
||||
"bun scripts/cli.ts agentrun v01 control-plane trigger-current --dry-run",
|
||||
@@ -40,7 +49,7 @@ export function agentRunHelp(): unknown {
|
||||
"bun scripts/cli.ts agentrun v01 git-mirror sync --confirm",
|
||||
"bun scripts/cli.ts agentrun v01 git-mirror flush --confirm",
|
||||
],
|
||||
description: "Operate AgentRun v0.1 Tekton/Argo control plane and devops-infra git mirror through G14 routes; status is read-only, trigger-current pre-syncs mirror refs before creating the PipelineRun, and cleanup-runs/cleanup-released-pvs provide controlled completed CI workspace retention.",
|
||||
description: "Operate AgentRun v0.1 Queue and Sessions through the official G14 /root/agentrun-v01 CLI, plus bounded Tekton/Argo control-plane and devops-infra git mirror actions through UniDesk routes. Queue/session commands are direct AgentRun CLI calls, not a UniDesk Code Queue adapter or double-write path.",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,6 +71,9 @@ export async function runAgentRunCommand(config: UniDeskConfig, args: string[]):
|
||||
return await runGitMirrorJob(config, action, options);
|
||||
}
|
||||
}
|
||||
if (group === "queue" || group === "sessions") {
|
||||
return await runOfficialAgentRunCli(config, group, args.slice(2));
|
||||
}
|
||||
return unsupported(args);
|
||||
}
|
||||
|
||||
@@ -1420,6 +1432,144 @@ function startAsyncAgentRunJob(name: string, command: string[], note: string): R
|
||||
};
|
||||
}
|
||||
|
||||
interface AgentRunCliMaterializedFile {
|
||||
flag: string;
|
||||
source: string;
|
||||
remotePath: string;
|
||||
bytes: number;
|
||||
base64: string;
|
||||
}
|
||||
|
||||
interface PreparedAgentRunCliArgs {
|
||||
args: string[];
|
||||
materializedFiles: AgentRunCliMaterializedFile[];
|
||||
}
|
||||
|
||||
async function runOfficialAgentRunCli(config: UniDeskConfig, group: "queue" | "sessions", args: string[]): Promise<Record<string, unknown>> {
|
||||
const prepared = prepareOfficialAgentRunCliArgs([group, ...args]);
|
||||
const command = `agentrun v01 ${prepared.args.join(" ")}`.trim();
|
||||
const bridge = agentRunQueueBridgeMetadata(prepared.materializedFiles);
|
||||
const script = officialAgentRunCliScript(prepared);
|
||||
const result = await capture(config, g14SourceRoute, ["script", "--", script]);
|
||||
const payload = captureJsonPayload(result);
|
||||
if (result.exitCode === 0 && Object.keys(payload).length > 0) {
|
||||
return {
|
||||
...payload,
|
||||
command,
|
||||
bridge,
|
||||
};
|
||||
}
|
||||
if (result.exitCode === 0) {
|
||||
return {
|
||||
ok: true,
|
||||
command,
|
||||
bridge,
|
||||
stdout: result.stdout.trim(),
|
||||
remote: compactCapture(result, { full: true, stdoutTailChars: 4000, stderrTailChars: 2000 }),
|
||||
};
|
||||
}
|
||||
return {
|
||||
ok: false,
|
||||
command,
|
||||
degradedReason: "agentrun-cli-bridge-failed",
|
||||
bridge,
|
||||
agentrun: payload,
|
||||
remote: compactCapture(result, { full: true, stdoutTailChars: 8000, stderrTailChars: 4000 }),
|
||||
};
|
||||
}
|
||||
|
||||
function prepareOfficialAgentRunCliArgs(args: string[]): PreparedAgentRunCliArgs {
|
||||
const fileFlags = new Set(["--json-file", "--prompt-file", "--runner-json-file"]);
|
||||
const remoteTmpDir = `/tmp/unidesk-agentrun-cli-${Date.now()}-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
||||
const materializedFiles: AgentRunCliMaterializedFile[] = [];
|
||||
const prepared: string[] = [];
|
||||
let stdinBuffer: Buffer | null = null;
|
||||
|
||||
const stdin = (): Buffer => {
|
||||
if (stdinBuffer === null) stdinBuffer = readFileSync(0);
|
||||
return stdinBuffer;
|
||||
};
|
||||
|
||||
const materialize = (flag: string, source: string, buffer: Buffer): string => {
|
||||
const remotePath = `${remoteTmpDir}/input-${materializedFiles.length}`;
|
||||
materializedFiles.push({
|
||||
flag,
|
||||
source,
|
||||
remotePath,
|
||||
bytes: buffer.length,
|
||||
base64: buffer.toString("base64"),
|
||||
});
|
||||
return remotePath;
|
||||
};
|
||||
|
||||
for (let i = 0; i < args.length; i += 1) {
|
||||
const arg = args[i] ?? "";
|
||||
const equalsFlag = Array.from(fileFlags).find((flag) => arg.startsWith(`${flag}=`));
|
||||
if (equalsFlag !== undefined) {
|
||||
const source = arg.slice(equalsFlag.length + 1);
|
||||
if (source.length === 0) throw new Error(`${equalsFlag} requires a path`);
|
||||
const buffer = source === "-" ? stdin() : readFileSync(source);
|
||||
prepared.push(equalsFlag, materialize(equalsFlag, source === "-" ? "stdin" : source, buffer));
|
||||
continue;
|
||||
}
|
||||
if (fileFlags.has(arg)) {
|
||||
const source = args[i + 1];
|
||||
if (source === undefined || source.length === 0) throw new Error(`${arg} requires a path`);
|
||||
const buffer = source === "-" ? stdin() : readFileSync(source);
|
||||
prepared.push(arg, materialize(arg, source === "-" ? "stdin" : source, buffer));
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--prompt-stdin" || arg === "--stdin") {
|
||||
prepared.push("--prompt-file", materialize("--prompt-stdin", "stdin", stdin()));
|
||||
continue;
|
||||
}
|
||||
prepared.push(arg);
|
||||
}
|
||||
|
||||
return { args: prepared, materializedFiles };
|
||||
}
|
||||
|
||||
function officialAgentRunCliScript(prepared: PreparedAgentRunCliArgs): string {
|
||||
const setup = prepared.materializedFiles.length === 0
|
||||
? []
|
||||
: [
|
||||
`tmp_dir=${shQuote(parentDir(prepared.materializedFiles[0]?.remotePath ?? "/tmp/unidesk-agentrun-cli"))}`,
|
||||
"mkdir -p \"$tmp_dir\"",
|
||||
"trap 'rm -rf \"$tmp_dir\"' EXIT",
|
||||
...prepared.materializedFiles.map((file) => `printf %s ${shQuote(file.base64)} | base64 -d > ${shQuote(file.remotePath)}`),
|
||||
];
|
||||
return [
|
||||
"set -euo pipefail",
|
||||
...setup,
|
||||
"cd /root/agentrun-v01",
|
||||
`./scripts/agentrun --manager-url auto ${prepared.args.map(shQuote).join(" ")}`,
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
function parentDir(pathValue: string): string {
|
||||
const index = pathValue.lastIndexOf("/");
|
||||
return index > 0 ? pathValue.slice(0, index) : ".";
|
||||
}
|
||||
|
||||
function agentRunQueueBridgeMetadata(materializedFiles: AgentRunCliMaterializedFile[]): Record<string, unknown> {
|
||||
return {
|
||||
route: g14SourceRoute,
|
||||
sourceWorktree: "/root/agentrun-v01",
|
||||
sourceBranch,
|
||||
managerUrl: "auto",
|
||||
officialCli: "./scripts/agentrun",
|
||||
mode: "direct-official-cli",
|
||||
compatibility: "no-code-queue-adapter-no-double-write",
|
||||
fileFlagsMaterialized: materializedFiles.map((file) => ({
|
||||
flag: file.flag,
|
||||
source: file.source,
|
||||
remotePath: file.remotePath,
|
||||
bytes: file.bytes,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
async function capture(config: UniDeskConfig, target: string, args: string[]): Promise<SshCaptureResult> {
|
||||
return await runSshCommandCapture(config, target, args);
|
||||
}
|
||||
@@ -1568,6 +1718,6 @@ function unsupported(args: string[]): Record<string, unknown> {
|
||||
ok: false,
|
||||
command: `agentrun ${args.join(" ")}`.trim(),
|
||||
degradedReason: "unsupported-command",
|
||||
message: "supported commands: agentrun v01 control-plane status|trigger-current|refresh; agentrun v01 git-mirror status|sync|flush",
|
||||
message: "supported commands: agentrun v01 queue submit|list|show|stats|commander|read|cancel|dispatch|refresh; agentrun v01 sessions ps|show|turn|steer|cancel|output|trace|read; agentrun v01 control-plane status|trigger-current|refresh; agentrun v01 git-mirror status|sync|flush",
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user