Merge pull request #2667 from pikasTech/fix/agentrun-resource-help-lane
修复 AgentRun L1 资源查询入口
This commit is contained in:
@@ -52,6 +52,7 @@ bun scripts/cli.ts agentrun native-development manager start
|
||||
bun scripts/cli.ts agentrun native-development manager status
|
||||
bun scripts/cli.ts agentrun native-development manager logs
|
||||
bun scripts/cli.ts agentrun native-development manager restart
|
||||
bun scripts/cli.ts agentrun result run/<runId> --command <commandId> --native-development
|
||||
```
|
||||
|
||||
- 配置唯一来源是 `config/agentrun.yaml#nativeDevelopment.manager`;
|
||||
|
||||
@@ -53,6 +53,27 @@ export function readAgentRunClientConfig(env: NodeJS.ProcessEnv = process.env):
|
||||
}
|
||||
}
|
||||
|
||||
export function readAgentRunNativeDevelopmentClientConfig(env: NodeJS.ProcessEnv = process.env): AgentRunClientConfig {
|
||||
const config = readAgentRunClientConfig(env);
|
||||
const input = record(Bun.YAML.parse(readFileSync(config.sourcePath, "utf8")) as unknown);
|
||||
const nativeDevelopment = record(input.nativeDevelopment);
|
||||
const manager = record(nativeDevelopment.manager);
|
||||
const probeHost = stringFieldFromRecord(manager, "probeHost", "nativeDevelopment.manager");
|
||||
const port = numberFieldFromRecord(manager, "port", "nativeDevelopment.manager", { min: 1, max: 65_535 });
|
||||
const apiKeySourceRef = stringFieldFromRecord(manager, "apiKeySourceRef", "nativeDevelopment.manager");
|
||||
const apiKeySourceKey = stringFieldFromRecord(manager, "apiKeySourceKey", "nativeDevelopment.manager");
|
||||
if (apiKeySourceRef.includes("..")) throw new Error("nativeDevelopment.manager.apiKeySourceRef must not contain ..");
|
||||
const apiKeyFile = apiKeySourceRef.startsWith("/")
|
||||
? apiKeySourceRef
|
||||
: join("/root/.unidesk/.state/secrets", ...apiKeySourceRef.split("/"));
|
||||
return {
|
||||
...config,
|
||||
manager: { ...config.manager, baseUrl: `http://${probeHost}:${port}/` },
|
||||
auth: { ...config.auth, env: apiKeySourceKey, file: apiKeyFile },
|
||||
publicExposure: null,
|
||||
};
|
||||
}
|
||||
|
||||
export function parseAgentRunClientConfigYaml(raw: string, sourcePath = "config/agentrun.yaml"): AgentRunClientConfig {
|
||||
const input = record(Bun.YAML.parse(raw) as unknown);
|
||||
validateAgentRunConfigEnvelope(input, sourcePath);
|
||||
|
||||
@@ -42,7 +42,7 @@ import { agentRunExplain, isRecord, parseGitMirrorStatusOptions, parseStatusOpti
|
||||
import { renderAgentRunControlPlaneActionSummary, renderAgentRunControlPlanePlanSummary, renderAgentRunControlPlaneStatusSummary } from "./public-exposure";
|
||||
import { providerProfileHelp, runProviderProfileCommand } from "./provider-profile";
|
||||
import { renderedCliResult } from "./render";
|
||||
import { agentRunGetKindHelp, runAgentRunResourceCommand } from "./resource-actions";
|
||||
import { AGENTRUN_RESOURCE_TRANSPORT_SCOPE, agentRunGetKindHelp, runAgentRunResourceCommand } from "./resource-actions";
|
||||
import { runAgentRunRestCompatCommand, runGitMirrorJob, startAsyncAgentRunJob } from "./rest-bridge";
|
||||
import { renderAgentRunSecretSyncResult } from "./secret-sync-output";
|
||||
import { exposeAgentRun, restartYamlLane, secretSync, triggerCurrent } from "./trigger";
|
||||
@@ -269,7 +269,7 @@ export function agentRunHelpText(args: string[]): string {
|
||||
if (verb === "get" && kind !== undefined) return agentRunGetKindHelp(kind);
|
||||
if (verb === "get") {
|
||||
return [
|
||||
"Usage: bun scripts/cli.ts agentrun get <resource> [options]",
|
||||
`Usage: bun scripts/cli.ts agentrun get <resource> [options] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`,
|
||||
"",
|
||||
"Resources: tasks|attempts|sessions|runs|commands|runnerjobs|aipodspecs",
|
||||
"Output: table by default; use -o wide|name|json|yaml.",
|
||||
@@ -296,18 +296,18 @@ export function agentRunHelpText(args: string[]): string {
|
||||
}
|
||||
if (verb === "events") {
|
||||
return [
|
||||
"Usage: bun scripts/cli.ts agentrun events run/<runId> [--after-seq N] [--expect N [--timeout 120s]] [--limit 100] [-o json|yaml] [--full|--raw]",
|
||||
" bun scripts/cli.ts agentrun events run/<runId> --detail-seq <seq> [-o json|yaml]",
|
||||
`Usage: bun scripts/cli.ts agentrun events run/<runId> [--after-seq N] [--expect N [--timeout 120s]] [--limit 100] [-o json|yaml] [--full|--raw] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`,
|
||||
` bun scripts/cli.ts agentrun events run/<runId> --detail-seq <seq> [-o json|yaml] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`,
|
||||
"",
|
||||
"--expect waits in one manager-held request until N new events, target completion, or timeout; --timeout defaults to 120s. --limit remains an independent output budget.",
|
||||
"--detail-seq returns one bounded Secret-safe EventDetail projection. Use the separate --after-seq <seq-1> --limit 1 --full|--raw path only for explicit complete disclosure.",
|
||||
].join("\n");
|
||||
}
|
||||
if (verb === "logs") {
|
||||
return "Usage: bun scripts/cli.ts agentrun logs session/<sessionId> [--tail 100|--after-seq N] [--limit 100] [--full-text] [-o json|yaml] [--raw]";
|
||||
return `Usage: bun scripts/cli.ts agentrun logs session/<sessionId> [--tail 100|--after-seq N] [--limit 100] [--full-text] [-o json|yaml] [--raw] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
|
||||
}
|
||||
if (verb === "result") {
|
||||
return "Usage: bun scripts/cli.ts agentrun result run/<runId> --command <commandId> | agentrun result command/<commandId> --run <runId>";
|
||||
return `Usage: bun scripts/cli.ts agentrun result run/<runId> --command <commandId> ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}\n bun scripts/cli.ts agentrun result command/<commandId> --run <runId> ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
|
||||
}
|
||||
if (verb === "ack") {
|
||||
return "Usage: bun scripts/cli.ts agentrun ack task/<taskId>|session/<sessionId> [--reader-id cli]";
|
||||
|
||||
@@ -34,27 +34,29 @@ import {
|
||||
import { sha256Fingerprint } from "../platform-infra-ops-library";
|
||||
|
||||
import type { AgentRunResourceOptions, AgentRunResourceRef, AgentRunResourceVerb } from "./utils";
|
||||
import { agentRunDryRunPlan } from "./config";
|
||||
import { agentRunDryRunPlan, readAgentRunNativeDevelopmentClientConfig } from "./config";
|
||||
import { renderEventDetail } from "./event-detail";
|
||||
import { isHelpArg, renderAgentRunHelp } from "./entry";
|
||||
import { agentRunExplain, arrayRecords, shortId } from "./options";
|
||||
import { agentRunCancelAuthorityDisclosure, agentRunCancelCascadeScope, agentRunCancelFencingDisclosure, agentRunCancelRunnerAbortDisclosure, compactAipodSpecDescriptionPayload, compactTaskDescriptionPayload, innerData, normalizeAipodSpecItems, normalizeAttemptResources, normalizeEventItems, normalizeLogItems, normalizeQueueAttemptItems, normalizeRunnerJobItems, normalizeSessionItems, normalizeSingleCommand, normalizeTaskItems, parseResourceKind, parseResourceRef, renderAipodSpecDescription, renderDescribe, renderEventLike, renderGenericDescription, renderMachine, renderMutationSummary, renderQueueAttemptList, renderQueueRetrySummary, renderResourceResult, renderResultSummary, renderTaskDescription, renderedCliResult, requiredContext, rerunWithoutDryRun, resolveAgentRunCancelPolicyTarget, resourceApply, resourceCreate, resourceDispatch, resourceSessionPromptCommand, taskInputDescriptionPayload, taskListState, unwrapTaskDetail } from "./render";
|
||||
import { AgentRunRestError, renderAgentRunRestError, resolveAgentRunRestTarget, runAgentRunRestCommand, withAgentRunRestTarget } from "./rest-bridge";
|
||||
import { AgentRunRestError, renderAgentRunRestError, resolveAgentRunRestTarget, runAgentRunRestCommand, withAgentRunNativeClientConfig, withAgentRunRestTarget } from "./rest-bridge";
|
||||
import { renderSessionSendError } from "./session-send-render";
|
||||
import { prepareAgentRunTargetTaskPreflight } from "./target-execution";
|
||||
import { runnerJobObservationScript, type RunnerJobObservationIdentity } from "./runner-observation";
|
||||
import { isChineseTaskTitle, validateChineseTaskTitle, withAgentRunTargetTaskPreflight } from "./target-task";
|
||||
import { capture, captureJsonPayload, compactCapture, nonNegativeIntegerOrNull, record, stringOrNull } from "./utils";
|
||||
|
||||
export const AGENTRUN_RESOURCE_TRANSPORT_SCOPE = "[--native-development | [--target <NODE>|--node <NODE>] [--lane <lane>]]";
|
||||
|
||||
export function agentRunGetKindHelp(kindRaw: string): string {
|
||||
const kind = parseResourceKind(kindRaw);
|
||||
if (kind === "task") return "Usage: bun scripts/cli.ts agentrun get tasks [--queue commander] [--state running,pending,completed,failed] [--unread] [--limit 20] [-o wide|name|json|yaml]";
|
||||
if (kind === "attempt") return "Usage: bun scripts/cli.ts agentrun get attempts --task <taskId> [--cursor <retry-index>] [--limit 20] [--full] [-o json|yaml] [--raw]";
|
||||
if (kind === "session") return "Usage: bun scripts/cli.ts agentrun get sessions [--limit 20] [-o wide|name|json|yaml]";
|
||||
if (kind === "run") return "Usage: bun scripts/cli.ts agentrun get runs --task <taskId> [--limit 20] [-o wide|name|json|yaml]";
|
||||
if (kind === "command") return "Usage: bun scripts/cli.ts agentrun get commands --run <runId> [--command <commandId>] [-o wide|name|json|yaml]";
|
||||
if (kind === "runnerjob") return "Usage: bun scripts/cli.ts agentrun get runnerjobs --run <runId> --command <commandId> [-o wide|name|json|yaml]";
|
||||
if (kind === "aipodspec") return "Usage: bun scripts/cli.ts agentrun get aipodspecs [-o wide|name|json|yaml]";
|
||||
if (kind === "task") return `Usage: bun scripts/cli.ts agentrun get tasks [--queue commander] [--state running,pending,completed,failed] [--unread] [--limit 20] [-o wide|name|json|yaml] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
|
||||
if (kind === "attempt") return `Usage: bun scripts/cli.ts agentrun get attempts --task <taskId> [--cursor <retry-index>] [--limit 20] [--full] [-o json|yaml] [--raw] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
|
||||
if (kind === "session") return `Usage: bun scripts/cli.ts agentrun get sessions [--limit 20] [-o wide|name|json|yaml] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
|
||||
if (kind === "run") return `Usage: bun scripts/cli.ts agentrun get runs --task <taskId> [--limit 20] [-o wide|name|json|yaml] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
|
||||
if (kind === "command") return `Usage: bun scripts/cli.ts agentrun get commands --run <runId> [--command <commandId>] [-o wide|name|json|yaml] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
|
||||
if (kind === "runnerjob") return `Usage: bun scripts/cli.ts agentrun get runnerjobs --run <runId> --command <commandId> [-o wide|name|json|yaml] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
|
||||
if (kind === "aipodspec") return `Usage: bun scripts/cli.ts agentrun get aipodspecs [-o wide|name|json|yaml] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
|
||||
return "Unknown resource. Supported: tasks, attempts, sessions, runs, commands, runnerjobs, aipodspecs.";
|
||||
}
|
||||
|
||||
@@ -76,7 +78,9 @@ export async function runAgentRunResourceCommand(config: UniDeskConfig | null, v
|
||||
const bridgeActionArgs = stripAgentRunResourceWrapperArgs(actionArgs);
|
||||
try {
|
||||
const targetTaskPreflight = await prepareAgentRunTargetTaskPreflight(config, canonicalArgs, options);
|
||||
return await withAgentRunTargetTaskPreflight(targetTaskPreflight, async () => await withAgentRunRestTarget(resolveAgentRunRestTarget(config, options), async () => {
|
||||
const nativeClientConfig = options.nativeDevelopment ? readAgentRunNativeDevelopmentClientConfig() : null;
|
||||
const restTarget = resolveAgentRunRestTarget(options.nativeDevelopment ? null : config, options);
|
||||
return await withAgentRunTargetTaskPreflight(targetTaskPreflight, async () => await withAgentRunNativeClientConfig(nativeClientConfig, async () => await withAgentRunRestTarget(restTarget, async () => {
|
||||
if (verb === "explain") return renderedCliResult(true, command, agentRunExplain(action ?? "task", resourceArgs, options));
|
||||
if (verb === "get") return await resourceGet(config, command, action, bridgeActionArgs, options);
|
||||
if (verb === "describe") return await resourceDescribe(config, command, action, bridgeActionArgs, options);
|
||||
@@ -91,7 +95,7 @@ export async function runAgentRunResourceCommand(config: UniDeskConfig | null, v
|
||||
if (verb === "apply") return await resourceApply(config, command, bridgeActionArgs, options);
|
||||
if (verb === "send") return await resourceSessionPromptCommand(config, command, action, bridgeActionArgs, options);
|
||||
return renderedCliResult(false, command, `Unsupported AgentRun resource command. Try: bun scripts/cli.ts agentrun --help`);
|
||||
}));
|
||||
})));
|
||||
} catch (error) {
|
||||
if (error instanceof AgentRunRestError) {
|
||||
if (verb === "send") return renderSessionSendError(command, error.toPayload(command), options);
|
||||
@@ -157,7 +161,7 @@ export function stripAgentRunResourceWrapperArgs(args: string[]): string[] {
|
||||
}
|
||||
if (arg.startsWith("--output=") || arg.startsWith("-o=")) continue;
|
||||
if (arg.startsWith("--node=") || arg.startsWith("--lane=")) continue;
|
||||
if (arg === "--full" || arg === "--raw" || arg === "--debug" || arg === "--full-text" || arg === "--input") continue;
|
||||
if (arg === "--full" || arg === "--raw" || arg === "--debug" || arg === "--full-text" || arg === "--input" || arg === "--native-development") continue;
|
||||
result.push(arg);
|
||||
}
|
||||
return result;
|
||||
@@ -193,6 +197,7 @@ export function parseResourceOptions(args: string[]): AgentRunResourceOptions {
|
||||
title: null,
|
||||
idempotencyKey: null,
|
||||
promptStdin: false,
|
||||
nativeDevelopment: false,
|
||||
node: null,
|
||||
lane: null,
|
||||
target: null,
|
||||
@@ -203,7 +208,7 @@ export function parseResourceOptions(args: string[]): AgentRunResourceOptions {
|
||||
passthroughArgs: [],
|
||||
};
|
||||
const valueFlags = new Set(["-o", "--output", "--limit", "--cursor", "--queue", "--state", "--reader-id", "--task", "--task-id", "--run", "--run-id", "--command", "--command-id", "--session", "--session-id", "--after-seq", "--expect", "--timeout", "--detail-seq", "--tail", "--reason", "-f", "--file", "--filename", "--aipod", "--title", "--idempotency-key", "--node", "--lane", "--target", "--target-workspace", "--repo", "--ref", "--mdtodo-id"]);
|
||||
const booleanFlags = new Set(["--full", "--raw", "--debug", "--input", "--unread", "--dry-run", "--full-text", "--prompt-stdin", "--stdin"]);
|
||||
const booleanFlags = new Set(["--full", "--raw", "--debug", "--input", "--unread", "--dry-run", "--full-text", "--prompt-stdin", "--stdin", "--native-development"]);
|
||||
for (let index = 0; index < args.length; index += 1) {
|
||||
const arg = args[index] ?? "";
|
||||
if (!arg.startsWith("-")) continue;
|
||||
@@ -284,6 +289,14 @@ export function parseResourceOptions(args: string[]): AgentRunResourceOptions {
|
||||
}
|
||||
|
||||
function validateResourceOptionsForVerb(verb: AgentRunResourceVerb, options: AgentRunResourceOptions): void {
|
||||
if (options.nativeDevelopment) {
|
||||
if (options.node !== null || options.lane !== null || options.target !== null) {
|
||||
throw new AgentRunRestError("validation-failed", "--native-development cannot be combined with --target, --node, or --lane");
|
||||
}
|
||||
if (!new Set<AgentRunResourceVerb>(["get", "describe", "events", "logs", "result"]).has(verb)) {
|
||||
throw new AgentRunRestError("validation-failed", "--native-development is read-only and supports get, describe, events, logs, and result");
|
||||
}
|
||||
}
|
||||
if (options.eventDetailSeq !== null && verb !== "events") {
|
||||
throw new AgentRunRestError(
|
||||
"validation-failed",
|
||||
@@ -328,6 +341,7 @@ export function applyResourceOption(options: AgentRunResourceOptions, flag: stri
|
||||
else if (flag === "--dry-run") options.dryRun = true;
|
||||
else if (flag === "--full-text") options.fullText = true;
|
||||
else if (flag === "--prompt-stdin" || flag === "--stdin") options.promptStdin = true;
|
||||
else if (flag === "--native-development") options.nativeDevelopment = true;
|
||||
else if (flag === "--limit") options.limit = parseNonNegativeInt(value, "--limit", 20, 500);
|
||||
else if (flag === "--cursor") options.cursor = parseNonNegativeInt(value, "--cursor", 0, Number.MAX_SAFE_INTEGER);
|
||||
else if (flag === "--queue") options.queue = requiredValue(value, flag);
|
||||
|
||||
@@ -1220,7 +1220,7 @@ export async function sessionRunnerJobBody(args: string[], defaults: Record<stri
|
||||
}
|
||||
|
||||
export async function agentRunRestRequest(command: string, method: AgentRunHttpMethod, pathValue: string, body?: unknown, requestTimeoutMs?: number): Promise<Record<string, unknown>> {
|
||||
const clientConfig = readAgentRunClientConfig();
|
||||
const clientConfig = activeAgentRunNativeClientConfig ?? readAgentRunClientConfig();
|
||||
const effectiveTimeoutMs = Math.max(clientConfig.manager.timeoutMs, requestTimeoutMs ?? 0);
|
||||
if (activeAgentRunRestTarget !== null) return await agentRunLaneRestRequest(command, method, pathValue, body, clientConfig, activeAgentRunRestTarget, effectiveTimeoutMs);
|
||||
const auth = resolveAgentRunAuth(clientConfig);
|
||||
@@ -1409,6 +1409,16 @@ export async function withAgentRunRestTarget<T>(target: AgentRunRestTarget | nul
|
||||
}
|
||||
}
|
||||
|
||||
export async function withAgentRunNativeClientConfig<T>(config: AgentRunClientConfig | null, action: () => Promise<T>): Promise<T> {
|
||||
const previous = activeAgentRunNativeClientConfig;
|
||||
activeAgentRunNativeClientConfig = config;
|
||||
try {
|
||||
return await action();
|
||||
} finally {
|
||||
activeAgentRunNativeClientConfig = previous;
|
||||
}
|
||||
}
|
||||
|
||||
export function renderAgentRunRestError(command: string, error: AgentRunRestError, options: AgentRunResourceOptions): RenderedCliResult {
|
||||
const rawPayload = error.toPayload(command);
|
||||
if (options.raw) return renderMachine(command, rawPayload, "json", false);
|
||||
@@ -1500,3 +1510,4 @@ export class AgentRunRestError extends Error {
|
||||
}
|
||||
|
||||
export let activeAgentRunRestTarget: AgentRunRestTarget | null = null;
|
||||
export let activeAgentRunNativeClientConfig: AgentRunClientConfig | null = null;
|
||||
|
||||
@@ -88,6 +88,7 @@ export interface AgentRunResourceOptions {
|
||||
title: string | null;
|
||||
idempotencyKey: string | null;
|
||||
promptStdin: boolean;
|
||||
nativeDevelopment: boolean;
|
||||
node: string | null;
|
||||
lane: string | null;
|
||||
target: string | null;
|
||||
|
||||
Reference in New Issue
Block a user