fix: pipe AgentRun bridge stdin directly
This commit is contained in:
@@ -111,7 +111,7 @@ UniDesk 不能作为以下内容的事实来源:
|
||||
|
||||
AgentRun `v0.1` 的指挥官任务面已经按 AgentRun issue #105 完成真实运行面验收,可作为新任务派发、Queue commander、trace/output、steer、turn/reuse、read 和 cancel 的 AgentRun 侧标准路径。长期使用时仍以 AgentRun 仓库自身 SPEC 为能力事实来源;UniDesk 只记录该路径已经通过 G14 `agentrun-v01` 运行面和 `hy` profile + `gpt-5.5` 验证。
|
||||
|
||||
UniDesk 指挥官新任务入口固定使用 `bun scripts/cli.ts agentrun v01 queue|sessions`。该入口是 G14 `/root/agentrun-v01` 中官方 `./scripts/agentrun --manager-url auto` CLI 的直接 bridge;本地 `--json-file`、`--json-stdin`、`--prompt-file`、`--prompt-stdin`、`--runner-json-file` 和 `--runner-json-stdin` 只会被 materialize 到 G14 临时文件后传给官方 CLI,不在 UniDesk 内实现 AgentRun queue 协议,也不把任务 double-write 回旧 Code Queue。日常派单、dispatch、turn 和 steer 优先用 heredoc/stdin,避免为了 JSON 或 prompt 输入先落 dump 文件。
|
||||
UniDesk 指挥官新任务入口固定使用 `bun scripts/cli.ts agentrun v01 queue|sessions`。该入口是 G14 `/root/agentrun-v01` 中官方 `./scripts/agentrun --manager-url auto` CLI 的直接 bridge;本地 `--json-file`、`--prompt-file` 和 `--runner-json-file` 会被 materialize 到 G14 临时文件后传给官方 CLI,`--json-stdin`、`--prompt-stdin`、`--runner-json-stdin` 和 `--*-file -` 则通过管道直通官方 CLI 的 stdin,不在 UniDesk 内实现 AgentRun queue 协议,也不把任务 double-write 回旧 Code Queue。日常派单、dispatch、turn 和 steer 优先用 heredoc/stdin,避免为了 JSON 或 prompt 输入先落 dump 文件。
|
||||
|
||||
AgentRun Queue 任务如果需要调用 UniDesk 维护桥,例如 `trans` / `unidesk-ssh`,长期契约以 AgentRun 仓库 `docs/reference/spec-v01-runtime-assembly.md` 和 `docs/reference/spec-v01-secret-distribution.md` 为准:调用方通过 `executionPolicy.secretScope.toolCredentials[].tool=unidesk-ssh` 请求 `UNIDESK_SSH_CLIENT_TOKEN` SecretRef;非敏感 endpoint 由 runner-job `transientEnv` 显式提供,或由 manager 受控默认值自动补齐。UniDesk bridge 提交 Queue payload 时不得在 prompt、payload 或 `transientEnv` 中携带 token,也不得使用 HWLAB runtime Web 入口冒充 UniDesk frontend。若 dispatcher 已正确请求 `unidesk-ssh` 但 trace 的 `runner-job-created.transientEnv.names` 没有 `UNIDESK_MAIN_SERVER_IP`、`UNIDESK_MAIN_SERVER_HOST` 或 `UNIDESK_FRONTEND_URL`,归为 AgentRun assembly 问题;若 endpoint env 已存在但 route denied/timeout,再按 UniDesk frontend/token scope 或 provider session 排查。
|
||||
|
||||
|
||||
+60
-7
@@ -1445,15 +1445,23 @@ interface AgentRunCliMaterializedFile {
|
||||
base64: string;
|
||||
}
|
||||
|
||||
interface AgentRunCliForwardedStdin {
|
||||
flag: string;
|
||||
source: string;
|
||||
bytes: number;
|
||||
base64: string;
|
||||
}
|
||||
|
||||
interface PreparedAgentRunCliArgs {
|
||||
args: string[];
|
||||
materializedFiles: AgentRunCliMaterializedFile[];
|
||||
stdinPayload: AgentRunCliForwardedStdin | null;
|
||||
}
|
||||
|
||||
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 bridge = agentRunQueueBridgeMetadata(prepared.materializedFiles, prepared.stdinPayload);
|
||||
const script = officialAgentRunCliScript(prepared);
|
||||
const result = await capture(config, g14SourceRoute, ["script", "--", script]);
|
||||
const payload = captureJsonPayload(result);
|
||||
@@ -1489,6 +1497,7 @@ function prepareOfficialAgentRunCliArgs(args: string[]): PreparedAgentRunCliArgs
|
||||
const materializedFiles: AgentRunCliMaterializedFile[] = [];
|
||||
const prepared: string[] = [];
|
||||
let stdinBuffer: Buffer | null = null;
|
||||
let stdinPayload: AgentRunCliForwardedStdin | null = null;
|
||||
|
||||
const stdin = (): Buffer => {
|
||||
if (stdinBuffer === null) stdinBuffer = readFileSync(0);
|
||||
@@ -1507,6 +1516,23 @@ function prepareOfficialAgentRunCliArgs(args: string[]): PreparedAgentRunCliArgs
|
||||
return remotePath;
|
||||
};
|
||||
|
||||
const forwardStdin = (flag: string, source: string, buffer: Buffer): void => {
|
||||
if (stdinPayload !== null) throw new Error(`${flag} cannot be combined with ${stdinPayload.flag}; pass one stdin payload per AgentRun CLI call`);
|
||||
stdinPayload = {
|
||||
flag,
|
||||
source,
|
||||
bytes: buffer.length,
|
||||
base64: buffer.toString("base64"),
|
||||
};
|
||||
};
|
||||
|
||||
const stdinFlagForFileFlag = (flag: string): string | null => {
|
||||
if (flag === "--json-file") return "--json-stdin";
|
||||
if (flag === "--prompt-file") return "--prompt-stdin";
|
||||
if (flag === "--runner-json-file") return "--runner-json-stdin";
|
||||
return null;
|
||||
};
|
||||
|
||||
for (let i = 0; i < args.length; i += 1) {
|
||||
const arg = args[i] ?? "";
|
||||
const equalsFlag = Array.from(fileFlags).find((flag) => arg.startsWith(`${flag}=`));
|
||||
@@ -1514,6 +1540,13 @@ function prepareOfficialAgentRunCliArgs(args: string[]): PreparedAgentRunCliArgs
|
||||
const source = arg.slice(equalsFlag.length + 1);
|
||||
if (source.length === 0) throw new Error(`${equalsFlag} requires a path`);
|
||||
const buffer = source === "-" ? stdin() : readFileSync(source);
|
||||
if (source === "-") {
|
||||
const stdinFlag = stdinFlagForFileFlag(equalsFlag);
|
||||
if (!stdinFlag) throw new Error(`${equalsFlag} does not support stdin`);
|
||||
forwardStdin(stdinFlag, "stdin", buffer);
|
||||
prepared.push(stdinFlag);
|
||||
continue;
|
||||
}
|
||||
prepared.push(equalsFlag, materialize(equalsFlag, source === "-" ? "stdin" : source, buffer));
|
||||
continue;
|
||||
}
|
||||
@@ -1521,26 +1554,37 @@ function prepareOfficialAgentRunCliArgs(args: string[]): PreparedAgentRunCliArgs
|
||||
const source = args[i + 1];
|
||||
if (source === undefined || source.length === 0) throw new Error(`${arg} requires a path`);
|
||||
const buffer = source === "-" ? stdin() : readFileSync(source);
|
||||
if (source === "-") {
|
||||
const stdinFlag = stdinFlagForFileFlag(arg);
|
||||
if (!stdinFlag) throw new Error(`${arg} does not support stdin`);
|
||||
forwardStdin(stdinFlag, "stdin", buffer);
|
||||
prepared.push(stdinFlag);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
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()));
|
||||
forwardStdin("--prompt-stdin", "stdin", stdin());
|
||||
prepared.push("--prompt-stdin");
|
||||
continue;
|
||||
}
|
||||
if (arg === "--json-stdin") {
|
||||
prepared.push("--json-file", materialize("--json-stdin", "stdin", stdin()));
|
||||
forwardStdin("--json-stdin", "stdin", stdin());
|
||||
prepared.push("--json-stdin");
|
||||
continue;
|
||||
}
|
||||
if (arg === "--runner-json-stdin") {
|
||||
prepared.push("--runner-json-file", materialize("--runner-json-stdin", "stdin", stdin()));
|
||||
forwardStdin("--runner-json-stdin", "stdin", stdin());
|
||||
prepared.push("--runner-json-stdin");
|
||||
continue;
|
||||
}
|
||||
prepared.push(arg);
|
||||
}
|
||||
|
||||
return { args: prepared, materializedFiles };
|
||||
return { args: prepared, materializedFiles, stdinPayload };
|
||||
}
|
||||
|
||||
function officialAgentRunCliScript(prepared: PreparedAgentRunCliArgs): string {
|
||||
@@ -1552,11 +1596,15 @@ function officialAgentRunCliScript(prepared: PreparedAgentRunCliArgs): string {
|
||||
"trap 'rm -rf \"$tmp_dir\"' EXIT",
|
||||
...prepared.materializedFiles.map((file) => `printf %s ${shQuote(file.base64)} | base64 -d > ${shQuote(file.remotePath)}`),
|
||||
];
|
||||
const cliCommand = `./scripts/agentrun --manager-url auto ${prepared.args.map(shQuote).join(" ")}`;
|
||||
const invocation = prepared.stdinPayload
|
||||
? `printf %s ${shQuote(prepared.stdinPayload.base64)} | base64 -d | ${cliCommand}`
|
||||
: cliCommand;
|
||||
return [
|
||||
"set -euo pipefail",
|
||||
...setup,
|
||||
"cd /root/agentrun-v01",
|
||||
`./scripts/agentrun --manager-url auto ${prepared.args.map(shQuote).join(" ")}`,
|
||||
invocation,
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
@@ -1565,7 +1613,7 @@ function parentDir(pathValue: string): string {
|
||||
return index > 0 ? pathValue.slice(0, index) : ".";
|
||||
}
|
||||
|
||||
function agentRunQueueBridgeMetadata(materializedFiles: AgentRunCliMaterializedFile[]): Record<string, unknown> {
|
||||
function agentRunQueueBridgeMetadata(materializedFiles: AgentRunCliMaterializedFile[], stdinPayload: AgentRunCliForwardedStdin | null): Record<string, unknown> {
|
||||
return {
|
||||
route: g14SourceRoute,
|
||||
sourceWorktree: "/root/agentrun-v01",
|
||||
@@ -1574,6 +1622,11 @@ function agentRunQueueBridgeMetadata(materializedFiles: AgentRunCliMaterializedF
|
||||
officialCli: "./scripts/agentrun",
|
||||
mode: "direct-official-cli",
|
||||
compatibility: "no-code-queue-adapter-no-double-write",
|
||||
stdinForwarded: stdinPayload ? {
|
||||
flag: stdinPayload.flag,
|
||||
source: stdinPayload.source,
|
||||
bytes: stdinPayload.bytes,
|
||||
} : null,
|
||||
fileFlagsMaterialized: materializedFiles.map((file) => ({
|
||||
flag: file.flag,
|
||||
source: file.source,
|
||||
|
||||
Reference in New Issue
Block a user