fix: make AgentRun CLI a render-only REST client (#263)
Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
@@ -1,5 +1,50 @@
|
||||
import { readFileSync, rmSync } from "node:fs";
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { stripAgentRunResourceWrapperArgs } from "./agentrun";
|
||||
import { parseAgentRunClientConfigYaml, resolveAgentRunAuth, runAgentRunCommand, stripAgentRunResourceWrapperArgs } from "./agentrun";
|
||||
|
||||
const agentRunClientYaml = [
|
||||
"manager:",
|
||||
" baseUrl: https://agentrun.127-0-0-1.nip.io/",
|
||||
" timeoutMs: 15000",
|
||||
"publicExposure:",
|
||||
" enabled: true",
|
||||
" proxyName: agentrun-v01-frpc",
|
||||
" remotePort: 22880",
|
||||
" publicBaseUrl: https://agentrun.127-0-0-1.nip.io/",
|
||||
" masterBaseUrl: http://127.0.0.1:22880",
|
||||
" masterFrps:",
|
||||
" configPath: /opt/hwlab-frp/frps.dev.toml",
|
||||
" containerName: hwlab-frps-dev",
|
||||
" masterCaddy:",
|
||||
" enabled: true",
|
||||
" domain: agentrun.127-0-0-1.nip.io",
|
||||
" configPath: /etc/caddy/Caddyfile",
|
||||
" serviceName: caddy",
|
||||
" upstreamBaseUrl: http://127.0.0.1:22880",
|
||||
" responseHeaderTimeoutSeconds: 60",
|
||||
"auth:",
|
||||
" env: HWLAB_API_KEY",
|
||||
" file: /tmp/hwlab-api-key.env",
|
||||
" header: Authorization",
|
||||
" scheme: Bearer",
|
||||
"client:",
|
||||
" role: render-only",
|
||||
" transport: direct-http",
|
||||
].join("\n");
|
||||
|
||||
const agentRunMinimalClientYaml = [
|
||||
"manager:",
|
||||
" baseUrl: http://agentrun.example.local:8080",
|
||||
" timeoutMs: 15000",
|
||||
"auth:",
|
||||
" env: HWLAB_API_KEY",
|
||||
" file: /tmp/hwlab-api-key.env",
|
||||
" header: Authorization",
|
||||
" scheme: Bearer",
|
||||
"client:",
|
||||
" role: render-only",
|
||||
" transport: direct-http",
|
||||
].join("\n");
|
||||
|
||||
describe("AgentRun resource bridge argv", () => {
|
||||
test("does not forward UniDesk output flags to create task prompt argv", () => {
|
||||
@@ -38,3 +83,82 @@ describe("AgentRun resource bridge argv", () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("AgentRun render-only REST client config", () => {
|
||||
test("parses explicit YAML config for direct REST render-only client", () => {
|
||||
const config = parseAgentRunClientConfigYaml(agentRunClientYaml, "config/agentrun.yaml");
|
||||
expect(config.manager.baseUrl).toBe("https://agentrun.127-0-0-1.nip.io/");
|
||||
expect(config.publicExposure?.publicBaseUrl).toBe("https://agentrun.127-0-0-1.nip.io/");
|
||||
expect(config.publicExposure?.masterCaddy.domain).toBe("agentrun.127-0-0-1.nip.io");
|
||||
expect(config.auth.env).toBe("HWLAB_API_KEY");
|
||||
expect(config.auth.header).toBe("Authorization");
|
||||
expect(config.auth.scheme).toBe("Bearer");
|
||||
expect(config.client.role).toBe("render-only");
|
||||
expect(config.client.transport).toBe("direct-http");
|
||||
});
|
||||
|
||||
test("uses env auth before configured file auth without exposing the key", () => {
|
||||
const config = parseAgentRunClientConfigYaml(agentRunClientYaml, "config/agentrun.yaml");
|
||||
const auth = resolveAgentRunAuth(config, { HWLAB_API_KEY: "secret-value" });
|
||||
expect(auth.source).toBe("env");
|
||||
expect(auth.value).toBe("secret-value");
|
||||
});
|
||||
|
||||
test("requires explicit render-only direct-http client contract", () => {
|
||||
expect(() => parseAgentRunClientConfigYaml(agentRunClientYaml.replace(" transport: direct-http", " transport: ssh-bridge"), "config/agentrun.yaml")).toThrow("client.transport must be direct-http");
|
||||
expect(() => parseAgentRunClientConfigYaml(agentRunClientYaml.replace(" role: render-only", " role: proxy"), "config/agentrun.yaml")).toThrow("client.role must be render-only");
|
||||
});
|
||||
});
|
||||
|
||||
describe("AgentRun default transport contract", () => {
|
||||
test("server-facing compatibility groups use REST dispatcher, not official SSH CLI wrapper", () => {
|
||||
const source = readFileSync(new URL("./agentrun.ts", import.meta.url), "utf8");
|
||||
const commandRouter = source.slice(source.indexOf("export async function runAgentRunCommand"), source.indexOf("function isAgentRunRestCompatGroup"));
|
||||
expect(commandRouter).toContain("runAgentRunRestCompatCommand");
|
||||
expect(commandRouter).not.toContain("runOfficialAgentRunCli");
|
||||
expect(commandRouter).not.toContain("runPreparedOfficialAgentRunCli");
|
||||
});
|
||||
|
||||
test("resource verbs can use direct REST without UniDesk SSH config", async () => {
|
||||
const server = Bun.serve({
|
||||
port: 0,
|
||||
fetch(request) {
|
||||
const url = new URL(request.url);
|
||||
expect(request.headers.get("authorization")).toBe("Bearer secret-value");
|
||||
expect(url.pathname).toBe("/api/v1/queue/tasks");
|
||||
expect(url.searchParams.get("queue")).toBe("commander");
|
||||
expect(url.searchParams.get("state")).toBe("running");
|
||||
return Response.json({
|
||||
ok: true,
|
||||
data: {
|
||||
items: [
|
||||
{ id: "qt_1", state: "queued", queue: "commander" },
|
||||
],
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
const previousConfig = process.env.AGENTRUN_CLIENT_CONFIG;
|
||||
const previousKey = process.env.HWLAB_API_KEY;
|
||||
process.env.HWLAB_API_KEY = "secret-value";
|
||||
const tempConfigPath = `/tmp/unidesk-agentrun-test-${process.pid}-${Date.now()}.yaml`;
|
||||
try {
|
||||
process.env.AGENTRUN_CLIENT_CONFIG = tempConfigPath;
|
||||
await Bun.write(process.env.AGENTRUN_CLIENT_CONFIG, agentRunMinimalClientYaml.replace("http://agentrun.example.local:8080", server.url.href.replace(/\/$/u, "")));
|
||||
const result = await runAgentRunCommand(null, ["get", "tasks", "--queue", "commander", "-o", "json"]);
|
||||
expect(result.ok).toBe(true);
|
||||
expect("renderedText" in result).toBe(true);
|
||||
if ("renderedText" in result) {
|
||||
expect(result.renderedText).toContain("\"kind\": \"TaskList\"");
|
||||
expect(result.renderedText).toContain("\"name\": \"qt_1\"");
|
||||
}
|
||||
} finally {
|
||||
server.stop(true);
|
||||
if (previousConfig === undefined) delete process.env.AGENTRUN_CLIENT_CONFIG;
|
||||
else process.env.AGENTRUN_CLIENT_CONFIG = previousConfig;
|
||||
if (previousKey === undefined) delete process.env.HWLAB_API_KEY;
|
||||
else process.env.HWLAB_API_KEY = previousKey;
|
||||
rmSync(tempConfigPath, { force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+1017
-314
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user