fix: simplify agentrun cli entrypoints

This commit is contained in:
Codex
2026-06-11 00:41:20 +00:00
parent 4068d64555
commit 23e2a6e3e2
22 changed files with 342 additions and 199 deletions
+176 -94
View File
@@ -23,76 +23,113 @@ 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 | aipod-specs list|show|render|apply|delete | queue submit|list|show|stats|commander|read|cancel|dispatch|refresh | sessions ps|show|turn|steer|cancel|output|trace|read",
command: "agentrun control-plane status|trigger-current|refresh|cleanup-runs|cleanup-released-pvs | git-mirror status|sync|flush | aipod-specs list|show|render|apply|delete | queue submit|list|show|stats|commander|read|cancel|dispatch|refresh | runs show|events|result | commands show|result | runner jobs|job-status | 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 commander --reader-id cli --limit 20",
"bun scripts/cli.ts agentrun v01 aipod-specs list",
"bun scripts/cli.ts agentrun v01 aipod-specs show Artificer",
"bun scripts/cli.ts agentrun v01 aipod-specs render Artificer --prompt-stdin",
"bun scripts/cli.ts agentrun v01 aipod-specs apply --yaml-stdin --dry-run",
"bun scripts/cli.ts agentrun v01 queue submit --json-stdin <<'JSON'",
"bun scripts/cli.ts agentrun v01 queue submit --json-stdin --dry-run <<'JSON'",
"bun scripts/cli.ts agentrun v01 queue submit --aipod Artificer --prompt-stdin --idempotency-key <key>",
"bun scripts/cli.ts agentrun v01 queue submit --aipod Artificer --prompt-stdin --dry-run",
"bun scripts/cli.ts agentrun v01 queue submit --json-file <task.json> # reusable reviewed file fallback",
"bun scripts/cli.ts agentrun v01 queue dispatch <taskId> --json-stdin <<'JSON'",
"bun scripts/cli.ts agentrun v01 queue dispatch <taskId> --json-stdin --dry-run <<'JSON'",
"bun scripts/cli.ts agentrun v01 queue dispatch <taskId> --json-file <dispatch.json> # reusable reviewed file fallback",
"bun scripts/cli.ts agentrun v01 queue cancel <taskId> --reason <text> --dry-run",
"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 turn --aipod Artificer --prompt-stdin",
"bun scripts/cli.ts agentrun v01 sessions steer <sessionId> --prompt-stdin",
"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 status --pipeline-run agentrun-v01-ci-<short-sha>",
"bun scripts/cli.ts agentrun v01 control-plane status --source-commit <full-sha>",
"bun scripts/cli.ts agentrun v01 control-plane trigger-current --dry-run",
"bun scripts/cli.ts agentrun v01 control-plane trigger-current --confirm",
"bun scripts/cli.ts agentrun v01 control-plane refresh --dry-run",
"bun scripts/cli.ts agentrun v01 control-plane refresh --confirm",
"bun scripts/cli.ts agentrun v01 control-plane cleanup-runs --min-age-minutes 30 --limit 200 --dry-run",
"bun scripts/cli.ts agentrun v01 control-plane cleanup-runs --min-age-minutes 30 --limit 200 --confirm",
"bun scripts/cli.ts agentrun v01 control-plane cleanup-released-pvs --limit 200 --dry-run",
"bun scripts/cli.ts agentrun v01 control-plane cleanup-released-pvs --limit 200 --confirm",
"bun scripts/cli.ts agentrun v01 git-mirror status",
"bun scripts/cli.ts agentrun v01 git-mirror status --full",
"bun scripts/cli.ts agentrun v01 git-mirror sync --confirm",
"bun scripts/cli.ts agentrun v01 git-mirror flush --confirm",
"bun scripts/cli.ts agentrun queue commander --reader-id cli",
"bun scripts/cli.ts agentrun queue commander --reader-id cli --limit 20",
"bun scripts/cli.ts agentrun queue commander --reader-id cli --full",
"bun scripts/cli.ts agentrun queue commander --reader-id cli --raw",
"bun scripts/cli.ts agentrun aipod-specs list",
"bun scripts/cli.ts agentrun aipod-specs show Artificer",
"bun scripts/cli.ts agentrun aipod-specs render Artificer --prompt-stdin",
"bun scripts/cli.ts agentrun aipod-specs apply --yaml-stdin --dry-run",
"bun scripts/cli.ts agentrun queue submit --json-stdin <<'JSON'",
"bun scripts/cli.ts agentrun queue submit --json-stdin --dry-run <<'JSON'",
"bun scripts/cli.ts agentrun queue submit --aipod Artificer --prompt-stdin --idempotency-key <key>",
"bun scripts/cli.ts agentrun queue submit --aipod Artificer --prompt-stdin --dry-run",
"bun scripts/cli.ts agentrun queue submit --json-file <task.json> # reusable reviewed file fallback",
"bun scripts/cli.ts agentrun queue show <taskId>",
"bun scripts/cli.ts agentrun queue show <taskId> --full",
"bun scripts/cli.ts agentrun queue show <taskId> --raw",
"bun scripts/cli.ts agentrun queue dispatch <taskId> --json-stdin <<'JSON'",
"bun scripts/cli.ts agentrun queue dispatch <taskId> --json-stdin --dry-run <<'JSON'",
"bun scripts/cli.ts agentrun queue dispatch <taskId> --json-file <dispatch.json> # reusable reviewed file fallback",
"bun scripts/cli.ts agentrun queue cancel <taskId> --reason <text> --dry-run",
"bun scripts/cli.ts agentrun runs show <runId>",
"bun scripts/cli.ts agentrun runs show <runId> --full",
"bun scripts/cli.ts agentrun runs result <runId> --command-id <commandId>",
"bun scripts/cli.ts agentrun runs events <runId> --after-seq 0 --limit 100 --tail-summary",
"bun scripts/cli.ts agentrun commands show <commandId> --run-id <runId>",
"bun scripts/cli.ts agentrun commands show <commandId> --run-id <runId> --full",
"bun scripts/cli.ts agentrun commands result <commandId> --run-id <runId>",
"bun scripts/cli.ts agentrun runner jobs --run-id <runId> --command-id <commandId>",
"bun scripts/cli.ts agentrun runner job-status <runnerJobId> --run-id <runId>",
"bun scripts/cli.ts agentrun sessions trace <sessionId> --after-seq 0 --limit 100",
"bun scripts/cli.ts agentrun sessions output <sessionId> --after-seq 0 --limit 100",
"bun scripts/cli.ts agentrun sessions turn --aipod Artificer --prompt-stdin",
"bun scripts/cli.ts agentrun sessions steer <sessionId> --prompt-stdin",
"bun scripts/cli.ts agentrun sessions read <sessionId> --reader-id cli",
"bun scripts/cli.ts agentrun control-plane status",
"bun scripts/cli.ts agentrun control-plane status --full",
"bun scripts/cli.ts agentrun control-plane status --pipeline-run agentrun-v01-ci-<short-sha>",
"bun scripts/cli.ts agentrun control-plane status --source-commit <full-sha>",
"bun scripts/cli.ts agentrun control-plane trigger-current --dry-run",
"bun scripts/cli.ts agentrun control-plane trigger-current --confirm",
"bun scripts/cli.ts agentrun control-plane refresh --dry-run",
"bun scripts/cli.ts agentrun control-plane refresh --confirm",
"bun scripts/cli.ts agentrun control-plane cleanup-runs --min-age-minutes 30 --limit 200 --dry-run",
"bun scripts/cli.ts agentrun control-plane cleanup-runs --min-age-minutes 30 --limit 200 --confirm",
"bun scripts/cli.ts agentrun control-plane cleanup-released-pvs --limit 200 --dry-run",
"bun scripts/cli.ts agentrun control-plane cleanup-released-pvs --limit 200 --confirm",
"bun scripts/cli.ts agentrun git-mirror status",
"bun scripts/cli.ts agentrun git-mirror status --full",
"bun scripts/cli.ts agentrun git-mirror sync --confirm",
"bun scripts/cli.ts agentrun git-mirror flush --confirm",
],
description: "Operate AgentRun v0.1 Queue, Sessions, and AipodSpec 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/aipod-spec commands are direct AgentRun CLI calls, not a UniDesk Code Queue adapter or double-write path.",
description: "Operate AgentRun v0.1 Queue, Sessions, Runs, Commands, Runner job status, and AipodSpec 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/aipod-spec/run/command/runner-read commands are direct AgentRun CLI calls, not a UniDesk Code Queue adapter or double-write path.",
};
}
export async function runAgentRunCommand(config: UniDeskConfig, args: string[]): Promise<Record<string, unknown>> {
const [lane, group, action] = args;
if (lane !== "v01") return unsupported(args);
const route = normalizeAgentRunCommandArgs(args);
const { group, action, actionArgs } = route;
if (group === "control-plane") {
if (action === "status") return await status(config, parseStatusOptions(args.slice(3)));
if (action === "trigger-current") return await triggerCurrent(config, parseTriggerOptions(args.slice(3)));
if (action === "refresh") return await refresh(config, parseConfirmOptions(args.slice(3)));
if (action === "cleanup-runs") return await cleanupRuns(config, parseCleanupRunsOptions(args.slice(3)));
if (action === "cleanup-released-pvs") return await cleanupReleasedPvs(config, parseCleanupReleasedPvOptions(args.slice(3)));
if (action === "status") return await status(config, parseStatusOptions(actionArgs));
if (action === "trigger-current") return await triggerCurrent(config, parseTriggerOptions(actionArgs));
if (action === "refresh") return await refresh(config, parseConfirmOptions(actionArgs));
if (action === "cleanup-runs") return await cleanupRuns(config, parseCleanupRunsOptions(actionArgs));
if (action === "cleanup-released-pvs") return await cleanupReleasedPvs(config, parseCleanupReleasedPvOptions(actionArgs));
}
if (group === "git-mirror") {
if (action === "status") return await gitMirrorStatus(config, parseDisclosureOptions(args.slice(3)));
if (action === "status") return await gitMirrorStatus(config, parseDisclosureOptions(actionArgs));
if (action === "sync" || action === "flush") {
const options = parseGitMirrorOptions(args.slice(3));
if (options.confirm && !options.wait) return startAsyncAgentRunJob(`agentrun_v01_git_mirror_${action}`, ["bun", "scripts/cli.ts", "agentrun", "v01", "git-mirror", action, "--confirm", "--wait", "--timeout-seconds", String(options.timeoutSeconds)], `Run AgentRun v0.1 git mirror ${action} on G14`);
const options = parseGitMirrorOptions(actionArgs);
if (options.confirm && !options.wait) return startAsyncAgentRunJob(`agentrun_v01_git_mirror_${action}`, ["bun", "scripts/cli.ts", "agentrun", "git-mirror", action, "--confirm", "--wait", "--timeout-seconds", String(options.timeoutSeconds)], `Run AgentRun v0.1 git mirror ${action} on G14`);
return await runGitMirrorJob(config, action, options);
}
}
if (isOfficialAgentRunCliBridgeGroup(group)) {
return await runOfficialAgentRunCli(config, group, args.slice(2));
if (group === "runner" && (action === "jobs" || action === "job-status")) {
return await runOfficialAgentRunCli(config, group, route.forwardArgs);
}
return unsupported(args);
if (isOfficialAgentRunCliBridgeGroup(group)) {
return await runOfficialAgentRunCli(config, group, route.forwardArgs);
}
return unsupported(route.canonicalArgs);
}
function isOfficialAgentRunCliBridgeGroup(group: string | undefined): group is AgentRunOfficialCliBridgeGroup {
return group === "queue" || group === "sessions" || group === "aipod-specs" || group === "aipods";
return group === "queue" || group === "sessions" || group === "aipod-specs" || group === "aipods" || group === "runs" || group === "commands";
}
interface AgentRunCommandRoute {
canonicalArgs: string[];
group: string | undefined;
action: string | undefined;
actionArgs: string[];
forwardArgs: string[];
}
function normalizeAgentRunCommandArgs(args: string[]): AgentRunCommandRoute {
const canonicalArgs = args[0] === "v01" ? args.slice(1) : args;
const [group, action, ...actionArgs] = canonicalArgs;
return {
canonicalArgs,
group,
action,
actionArgs,
forwardArgs: canonicalArgs.slice(1),
};
}
interface TriggerOptions {
@@ -189,6 +226,7 @@ function parseStatusOptions(args: string[]): StatusOptions {
};
}
function parseTriggerOptions(args: string[]): TriggerOptions {
return parseConfirmOptions(args);
}
@@ -360,7 +398,7 @@ async function status(config: UniDeskConfig, options: StatusOptions): Promise<Re
};
return {
ok: source.exitCode === 0 && k3s.exitCode === 0 && mirror.ok === true,
command: "agentrun v01 control-plane status",
command: "agentrun control-plane status",
lane: "v0.1",
summary,
target,
@@ -397,16 +435,16 @@ async function status(config: UniDeskConfig, options: StatusOptions): Promise<Re
raw: options.raw,
stdoutTailOmitted: !(options.full || options.raw),
rawGitMirrorOmitted: !options.raw,
expandWith: `bun scripts/cli.ts agentrun v01 control-plane status${statusTargetArg(options, target)} --full`,
rawWith: `bun scripts/cli.ts agentrun v01 control-plane status${statusTargetArg(options, target)} --raw`,
expandWith: `bun scripts/cli.ts agentrun control-plane status${statusTargetArg(options, target)} --full`,
rawWith: `bun scripts/cli.ts agentrun control-plane status${statusTargetArg(options, target)} --raw`,
},
next: {
statusByPipelineRun: pipelineRun ? `bun scripts/cli.ts agentrun v01 control-plane status --pipeline-run ${pipelineRun} --full` : null,
statusBySourceCommit: sourceCommit ? `bun scripts/cli.ts agentrun v01 control-plane status --source-commit ${sourceCommit} --full` : null,
statusByPipelineRun: pipelineRun ? `bun scripts/cli.ts agentrun control-plane status --pipeline-run ${pipelineRun} --full` : null,
statusBySourceCommit: sourceCommit ? `bun scripts/cli.ts agentrun control-plane status --source-commit ${sourceCommit} --full` : null,
taskRuns: pipelineRun ? `trans G14:k3s kubectl get taskrun -n ${ciNamespace} -l tekton.dev/pipelineRun=${pipelineRun} -o wide` : null,
logs: pipelineRun ? `trans G14:k3s logs -n ${ciNamespace} -l tekton.dev/pipelineRun=${pipelineRun} --tail 120` : null,
triggerCurrent: "bun scripts/cli.ts agentrun v01 control-plane trigger-current --confirm",
refresh: "bun scripts/cli.ts agentrun v01 control-plane refresh --confirm",
triggerCurrent: "bun scripts/cli.ts agentrun control-plane trigger-current --confirm",
refresh: "bun scripts/cli.ts agentrun control-plane refresh --confirm",
},
};
}
@@ -446,7 +484,7 @@ async function triggerCurrent(config: UniDeskConfig, options: TriggerOptions): P
const sourceCommit = matchLine(source.stdout, "sourceCommit=");
const pipelineRun = sourceCommit ? pipelineRunName(sourceCommit) : null;
if (source.exitCode !== 0 || !sourceCommit || !isGitSha(sourceCommit) || !pipelineRun) {
return { ok: false, command: "agentrun v01 control-plane trigger-current", degradedReason: "source-head-unresolved", source: compactCapture(source) };
return { ok: false, command: "agentrun control-plane trigger-current", degradedReason: "source-head-unresolved", source: compactCapture(source) };
}
const plan = {
lane: "v0.1",
@@ -466,7 +504,7 @@ async function triggerCurrent(config: UniDeskConfig, options: TriggerOptions): P
if (options.dryRun || !options.confirm) {
return {
ok: true,
command: "agentrun v01 control-plane trigger-current",
command: "agentrun control-plane trigger-current",
dryRun: true,
plan,
gitMirrorPreSync: {
@@ -474,7 +512,7 @@ async function triggerCurrent(config: UniDeskConfig, options: TriggerOptions): P
reason: mirrorRequirement.reason,
before: mirrorBefore.summary,
},
next: { confirm: "bun scripts/cli.ts agentrun v01 control-plane trigger-current --confirm" },
next: { confirm: "bun scripts/cli.ts agentrun control-plane trigger-current --confirm" },
};
}
let gitMirrorPreSync: Record<string, unknown> = {
@@ -490,7 +528,7 @@ async function triggerCurrent(config: UniDeskConfig, options: TriggerOptions): P
if (synced.ok !== true || afterRequirement.required !== false) {
return {
ok: false,
command: "agentrun v01 control-plane trigger-current",
command: "agentrun control-plane trigger-current",
dryRun: false,
degradedReason: "git-mirror-local-v01-not-current-after-sync",
plan,
@@ -501,13 +539,13 @@ async function triggerCurrent(config: UniDeskConfig, options: TriggerOptions): P
const created = await capture(config, g14K3sRoute, ["script", "--", triggerScript(sourceCommit, pipelineRun)]);
return {
ok: created.exitCode === 0,
command: "agentrun v01 control-plane trigger-current",
command: "agentrun control-plane trigger-current",
dryRun: false,
plan,
gitMirrorPreSync,
created: compactCapture(created),
next: {
status: "bun scripts/cli.ts agentrun v01 control-plane status",
status: "bun scripts/cli.ts agentrun control-plane status",
logs: `trans G14:k3s logs -n ${ciNamespace} -l tekton.dev/pipelineRun=${pipelineRun} --tail 120`,
},
};
@@ -530,21 +568,21 @@ async function refresh(config: UniDeskConfig, options: ConfirmOptions): Promise<
if (options.dryRun || !options.confirm) {
return {
ok: true,
command: "agentrun v01 control-plane refresh",
command: "agentrun control-plane refresh",
dryRun: true,
plan,
next: { confirm: "bun scripts/cli.ts agentrun v01 control-plane refresh --confirm" },
next: { confirm: "bun scripts/cli.ts agentrun control-plane refresh --confirm" },
};
}
const refreshed = await capture(config, g14K3sRoute, ["script", "--", refreshScript()]);
return {
ok: source.exitCode === 0 && refreshed.exitCode === 0,
command: "agentrun v01 control-plane refresh",
command: "agentrun control-plane refresh",
dryRun: false,
plan,
source: compactCapture(source),
refreshed: compactCapture(refreshed),
next: { status: "bun scripts/cli.ts agentrun v01 control-plane status" },
next: { status: "bun scripts/cli.ts agentrun control-plane status" },
};
}
@@ -555,7 +593,7 @@ async function cleanupRuns(config: UniDeskConfig, options: CleanupRunsOptions):
const base = {
...payload,
ok,
command: "agentrun v01 control-plane cleanup-runs",
command: "agentrun control-plane cleanup-runs",
mode: options.dryRun || !options.confirm ? "dry-run" : "confirmed-cleanup",
namespace: ciNamespace,
minAgeMinutes: options.minAgeMinutes,
@@ -568,7 +606,7 @@ async function cleanupRuns(config: UniDeskConfig, options: CleanupRunsOptions):
dryRun: true,
mutation: false,
next: {
confirm: `bun scripts/cli.ts agentrun v01 control-plane cleanup-runs --min-age-minutes ${options.minAgeMinutes} --limit ${options.limit} --confirm`,
confirm: `bun scripts/cli.ts agentrun control-plane cleanup-runs --min-age-minutes ${options.minAgeMinutes} --limit ${options.limit} --confirm`,
},
};
}
@@ -577,8 +615,8 @@ async function cleanupRuns(config: UniDeskConfig, options: CleanupRunsOptions):
dryRun: false,
mutation: true,
followUp: {
status: "bun scripts/cli.ts agentrun v01 control-plane status",
releasedPvs: `bun scripts/cli.ts agentrun v01 control-plane cleanup-released-pvs --limit ${options.limit} --dry-run`,
status: "bun scripts/cli.ts agentrun control-plane status",
releasedPvs: `bun scripts/cli.ts agentrun control-plane cleanup-released-pvs --limit ${options.limit} --dry-run`,
diskPressure: "trans G14:k3s kubectl get node ubuntu-rog-zephyrus-g14-ga401iv-ga401iv -o jsonpath='{range .status.conditions[*]}{.type}{\"=\"}{.status}{\" \"}{.reason}{\"\\n\"}{end}'",
},
};
@@ -591,7 +629,7 @@ async function cleanupReleasedPvs(config: UniDeskConfig, options: CleanupRelease
const base = {
...payload,
ok,
command: "agentrun v01 control-plane cleanup-released-pvs",
command: "agentrun control-plane cleanup-released-pvs",
mode: options.dryRun || !options.confirm ? "dry-run" : "confirmed-cleanup",
namespace: ciNamespace,
limit: options.limit,
@@ -603,7 +641,7 @@ async function cleanupReleasedPvs(config: UniDeskConfig, options: CleanupRelease
dryRun: true,
mutation: false,
next: {
confirm: `bun scripts/cli.ts agentrun v01 control-plane cleanup-released-pvs --limit ${options.limit} --confirm`,
confirm: `bun scripts/cli.ts agentrun control-plane cleanup-released-pvs --limit ${options.limit} --confirm`,
},
};
}
@@ -612,7 +650,7 @@ async function cleanupReleasedPvs(config: UniDeskConfig, options: CleanupRelease
dryRun: false,
mutation: true,
followUp: {
cleanupRuns: `bun scripts/cli.ts agentrun v01 control-plane cleanup-runs --min-age-minutes 30 --limit ${options.limit} --dry-run`,
cleanupRuns: `bun scripts/cli.ts agentrun control-plane cleanup-runs --min-age-minutes 30 --limit ${options.limit} --dry-run`,
diskPressure: "trans G14:k3s kubectl get node ubuntu-rog-zephyrus-g14-ga401iv-ga401iv -o jsonpath='{range .status.conditions[*]}{.type}{\"=\"}{.status}{\" \"}{.reason}{\"\\n\"}{end}'",
},
};
@@ -1167,7 +1205,7 @@ async function gitMirrorStatus(config: UniDeskConfig, options: DisclosureOptions
const summary = observation.summary;
return {
ok: observation.ok,
command: "agentrun v01 git-mirror status",
command: "agentrun git-mirror status",
namespace: gitMirrorNamespace,
readUrl: gitMirrorReadUrl,
writeUrl: gitMirrorWriteUrl,
@@ -1180,12 +1218,12 @@ async function gitMirrorStatus(config: UniDeskConfig, options: DisclosureOptions
raw: options.raw,
rawOmitted: !options.raw,
probeTailOmitted: !(options.full || options.raw),
expandWith: "bun scripts/cli.ts agentrun v01 git-mirror status --full",
rawWith: "bun scripts/cli.ts agentrun v01 git-mirror status --raw",
expandWith: "bun scripts/cli.ts agentrun git-mirror status --full",
rawWith: "bun scripts/cli.ts agentrun git-mirror status --raw",
},
next: {
sync: "bun scripts/cli.ts agentrun v01 git-mirror sync --confirm",
flush: summary.pendingFlush === true ? "bun scripts/cli.ts agentrun v01 git-mirror flush --confirm" : null,
sync: "bun scripts/cli.ts agentrun git-mirror sync --confirm",
flush: summary.pendingFlush === true ? "bun scripts/cli.ts agentrun git-mirror flush --confirm" : null,
},
};
}
@@ -1218,7 +1256,7 @@ async function runGitMirrorJob(config: UniDeskConfig, action: "sync" | "flush",
const jobName = `${action === "sync" ? gitMirrorSyncJobPrefix : gitMirrorFlushJobPrefix}-${Date.now().toString(36)}`.slice(0, 63);
const manifest = gitMirrorJobManifest(action, jobName);
const manifestB64 = Buffer.from(JSON.stringify(manifest), "utf8").toString("base64");
const command = `agentrun v01 git-mirror ${action}`;
const command = `agentrun git-mirror ${action}`;
if (options.dryRun || !options.confirm) {
return {
ok: true,
@@ -1243,8 +1281,8 @@ async function runGitMirrorJob(config: UniDeskConfig, action: "sync" | "flush",
result: compactCapture(created),
status,
next: {
status: "bun scripts/cli.ts agentrun v01 git-mirror status",
wait: `bun scripts/cli.ts agentrun v01 git-mirror ${action} --confirm --wait`,
status: "bun scripts/cli.ts agentrun git-mirror status",
wait: `bun scripts/cli.ts agentrun git-mirror ${action} --confirm --wait`,
},
};
}
@@ -1261,8 +1299,8 @@ async function runGitMirrorJob(config: UniDeskConfig, action: "sync" | "flush",
wait,
status,
next: {
status: "bun scripts/cli.ts agentrun v01 git-mirror status",
flush: action === "sync" && status.summary && record(status.summary).pendingFlush === true ? "bun scripts/cli.ts agentrun v01 git-mirror flush --confirm" : null,
status: "bun scripts/cli.ts agentrun git-mirror status",
flush: action === "sync" && status.summary && record(status.summary).pendingFlush === true ? "bun scripts/cli.ts agentrun git-mirror flush --confirm" : null,
},
};
}
@@ -1511,7 +1549,7 @@ function gitMirrorStatusSummary(raw: string): Record<string, unknown> {
gitopsInSync: Boolean(localGitops && githubGitops && localGitops === githubGitops),
githubInSync: Boolean(localV01 && githubV01 && localV01 === githubV01 && (!localGitops || localGitops === githubGitops)),
flushNeeded: pendingFlush === true,
flushCommand: pendingFlush === true ? "bun scripts/cli.ts agentrun v01 git-mirror flush --confirm" : null,
flushCommand: pendingFlush === true ? "bun scripts/cli.ts agentrun git-mirror flush --confirm" : null,
exactFetch: record(refs).exactFetch ?? null,
lastSync,
lastFlush,
@@ -1565,18 +1603,18 @@ interface PreparedAgentRunCliArgs {
stdinPayload: AgentRunCliForwardedStdin | null;
}
type AgentRunOfficialCliBridgeGroup = "queue" | "sessions" | "aipod-specs" | "aipods";
type AgentRunOfficialCliBridgeGroup = "queue" | "sessions" | "aipod-specs" | "aipods" | "runs" | "commands" | "runner";
async function runOfficialAgentRunCli(config: UniDeskConfig, group: AgentRunOfficialCliBridgeGroup, args: string[]): Promise<Record<string, unknown>> {
const prepared = prepareOfficialAgentRunCliArgs([group, ...args]);
const command = `agentrun v01 ${prepared.args.join(" ")}`.trim();
const command = `agentrun ${prepared.args.join(" ")}`.trim();
const bridge = agentRunQueueBridgeMetadata(prepared.materializedFiles, prepared.stdinPayload);
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,
...rewriteOfficialAgentRunCliDrillDown(payload),
command,
bridge,
};
@@ -1600,6 +1638,50 @@ async function runOfficialAgentRunCli(config: UniDeskConfig, group: AgentRunOffi
};
}
function rewriteOfficialAgentRunCliDrillDown(value: Record<string, unknown>): Record<string, unknown> {
return rewriteRecordCommands(value);
}
function rewriteRecordCommands(value: unknown): Record<string, unknown> {
return record(rewriteOfficialCommandValue(value));
}
function rewriteOfficialCommandValue(value: unknown): unknown {
if (Array.isArray(value)) return value.map((item) => rewriteOfficialCommandValue(item));
if (typeof value !== "object" || value === null) return value;
const rewritten: Record<string, unknown> = {};
for (const [key, item] of Object.entries(value)) {
rewritten[key] = shouldRewriteOfficialCommandField(key) ? rewriteOfficialCommandFieldValue(item) : rewriteOfficialCommandValue(item);
}
return rewritten;
}
function rewriteOfficialCommandFieldValue(value: unknown): unknown {
if (typeof value === "string") return rewriteOfficialCommandString(value);
if (Array.isArray(value)) return value.map((item) => rewriteOfficialCommandFieldValue(item));
if (typeof value !== "object" || value === null) return value;
const rewritten: Record<string, unknown> = {};
for (const [key, item] of Object.entries(value)) {
rewritten[key] = rewriteOfficialCommandFieldValue(item);
}
return rewritten;
}
function shouldRewriteOfficialCommandField(key: string): boolean {
return key === "pollCommands" || key === "drillDownCommands" || key === "recoveryActions" || key === "logPath";
}
function rewriteOfficialCommandString(value: string): string {
const trimmed = value.trim();
if (trimmed.startsWith("./scripts/agentrun ")) {
return `bun scripts/cli.ts agentrun ${trimmed.slice("./scripts/agentrun ".length)}`;
}
if (trimmed.startsWith("kubectl ") || trimmed.includes(" kubectl ")) {
return "Use bun scripts/cli.ts agentrun runner jobs --run-id <runId> --command-id <commandId> or runner job-status <runnerJobId> --run-id <runId>; direct kubectl is intentionally hidden behind the AgentRun CLI bridge.";
}
return value;
}
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)}`;
@@ -1871,9 +1953,9 @@ function buildAgentRunTargetValidation(input: {
warnings,
interruptedOrUnknown: state === "pipeline-status-unknown" || state === "missing-pipelinerun",
nextActions: {
inspectPipelineRun: input.pipelineRun ? `bun scripts/cli.ts agentrun v01 control-plane status --pipeline-run ${input.pipelineRun} --full` : null,
inspectSourceCommit: input.sourceCommit ? `bun scripts/cli.ts agentrun v01 control-plane status --source-commit ${input.sourceCommit} --full` : null,
triggerCurrent: "bun scripts/cli.ts agentrun v01 control-plane trigger-current --confirm",
inspectPipelineRun: input.pipelineRun ? `bun scripts/cli.ts agentrun control-plane status --pipeline-run ${input.pipelineRun} --full` : null,
inspectSourceCommit: input.sourceCommit ? `bun scripts/cli.ts agentrun control-plane status --source-commit ${input.sourceCommit} --full` : null,
triggerCurrent: "bun scripts/cli.ts agentrun control-plane trigger-current --confirm",
},
};
}
@@ -1966,6 +2048,6 @@ function unsupported(args: string[]): Record<string, unknown> {
ok: false,
command: `agentrun ${args.join(" ")}`.trim(),
degradedReason: "unsupported-command",
message: "supported commands: agentrun v01 aipod-specs list|show|render|apply|delete; 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",
message: "supported commands: agentrun aipod-specs list|show|render|apply|delete; agentrun queue submit|list|show|stats|commander|read|cancel|dispatch|refresh; agentrun runs show|events|result; agentrun commands show|result; agentrun runner jobs|job-status; agentrun sessions ps|show|turn|steer|cancel|output|trace|read; agentrun control-plane status|trigger-current|refresh; agentrun git-mirror status|sync|flush",
};
}