fix(v02): remove legacy code agent control plane
This commit is contained in:
@@ -1,121 +0,0 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { execFile } from "node:child_process";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
import { createServer } from "node:http";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const bunCommand = process.env.HWLAB_TEST_BUN_COMMAND || process.env.HWLAB_BUN_COMMAND || (process.versions.bun ? process.execPath : "bun");
|
||||
|
||||
test("agent manager CLI reports degraded skills and manages local session lifecycle", async () => {
|
||||
const stateDir = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-mgr-"));
|
||||
try {
|
||||
const health = await runManagerJson(["health", "--state-dir", stateDir]);
|
||||
assert.equal(health.serviceId, "hwlab-agent-mgr");
|
||||
assert.equal(health.ok, true);
|
||||
assert.equal(health.status, "degraded");
|
||||
assert.deepEqual(health.health.skills.manager.missing, ["skillCommitId", "skillVersion"]);
|
||||
|
||||
const created = await runManagerJson([
|
||||
"create",
|
||||
"--agent-session-id", "ags_test",
|
||||
"--project-id", "prj_test",
|
||||
"--goal", "keep behavior",
|
||||
"--prompt", "run dry",
|
||||
"--skill-commit-id", "commit-a",
|
||||
"--skill-version", "1.0.0",
|
||||
"--state-dir", stateDir
|
||||
]);
|
||||
assert.equal(created.agentSessionId, "ags_test");
|
||||
assert.equal(created.status, "ok");
|
||||
assert.equal(created.task.status, "queued");
|
||||
assert.equal(created.traceCount, 1);
|
||||
|
||||
const status = await runManagerJson(["status", "--agent-session-id", "ags_test", "--state-dir", stateDir]);
|
||||
assert.equal(status.agentSession.metadata.skills.commitId, "commit-a");
|
||||
assert.equal(status.workerSession.metadata.expectedSkills.version, "1.0.0");
|
||||
|
||||
const trace = await runManagerJson(["trace", "--agent-session-id", "ags_test", "--state-dir", stateDir]);
|
||||
assert.equal(trace.traceEvents.length, 1);
|
||||
assert.equal(trace.traceEvents[0].metadata.state, "create");
|
||||
|
||||
const evidence = await runManagerJson(["evidence", "--agent-session-id", "ags_test", "--state-dir", stateDir]);
|
||||
assert.equal(evidence.evidenceRecords.length, 0);
|
||||
|
||||
const cleanup = await runManagerJson(["cleanup", "--agent-session-id", "ags_test", "--state-dir", stateDir]);
|
||||
assert.equal(cleanup.serviceId, "hwlab-agent-mgr");
|
||||
assert.equal(cleanup.cleanup.completed, true);
|
||||
assert.equal(cleanup.workspace.cleaned, true);
|
||||
} finally {
|
||||
await rm(stateDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("agent manager server returns health JSON", async () => {
|
||||
const port = await freePort();
|
||||
const server = await startManagerServer(port);
|
||||
try {
|
||||
const response = await fetch(`http://127.0.0.1:${port}/health/live`);
|
||||
assert.equal(response.status, 200);
|
||||
const health = await response.json();
|
||||
assert.equal(health.serviceId, "hwlab-agent-mgr");
|
||||
assert.equal(health.ok, true);
|
||||
assert.equal(health.status, "degraded");
|
||||
} finally {
|
||||
await server.stop();
|
||||
}
|
||||
});
|
||||
|
||||
async function runManagerJson(args) {
|
||||
const { stdout } = await execFileAsync(bunCommand, ["run", "cmd/hwlab-agent-mgr/main.ts", ...args], {
|
||||
cwd: process.cwd(),
|
||||
maxBuffer: 1024 * 1024
|
||||
});
|
||||
return JSON.parse(stdout);
|
||||
}
|
||||
|
||||
async function startManagerServer(port) {
|
||||
const child = execFile(bunCommand, ["run", "cmd/hwlab-agent-mgr/main.ts", "server"], {
|
||||
cwd: process.cwd(),
|
||||
env: {
|
||||
...process.env,
|
||||
PORT: String(port)
|
||||
},
|
||||
maxBuffer: 1024 * 1024
|
||||
});
|
||||
await new Promise((resolve, reject) => {
|
||||
let stderr = "";
|
||||
const timer = setTimeout(() => reject(new Error(`manager server did not start: ${stderr}`)), 5000);
|
||||
child.stderr?.on("data", (chunk) => {
|
||||
stderr += chunk;
|
||||
});
|
||||
child.stdout?.on("data", (chunk) => {
|
||||
if (chunk.toString().includes("listening")) {
|
||||
clearTimeout(timer);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
child.on("exit", (code) => {
|
||||
clearTimeout(timer);
|
||||
reject(new Error(`manager server exited early code=${code}: ${stderr}`));
|
||||
});
|
||||
});
|
||||
return {
|
||||
stop: async () => {
|
||||
if (child.exitCode !== null) return;
|
||||
child.kill("SIGTERM");
|
||||
await new Promise((resolve) => child.once("exit", resolve));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function freePort() {
|
||||
const server = createServer();
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
const port = server.address().port;
|
||||
await new Promise((resolve) => server.close(resolve));
|
||||
return port;
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
import { createServer } from "node:http";
|
||||
|
||||
import { buildMetadataFromEnv } from "../../internal/build-metadata.mjs";
|
||||
import {
|
||||
AGENT_MGR_SERVICE_ID,
|
||||
createSkillsManifest
|
||||
} from "../../internal/agent/index.mjs";
|
||||
import {
|
||||
assessSkillsInjection,
|
||||
cleanupLocalAgentSession,
|
||||
createLocalAgentSession,
|
||||
createRuntimeHealth,
|
||||
getLocalAgentEvidence,
|
||||
getLocalAgentStatus,
|
||||
getLocalAgentTrace,
|
||||
resolveAgentRuntimeStateDir
|
||||
} from "../../internal/agent/runtime.mjs";
|
||||
|
||||
const command = process.argv[2] || process.env.HWLAB_AGENT_MGR_DEFAULT_COMMAND || "server";
|
||||
const options = parseOptions(process.argv.slice(3));
|
||||
|
||||
try {
|
||||
const result = await dispatch(command, options);
|
||||
printJSON(result);
|
||||
} catch (error) {
|
||||
printJSON(
|
||||
{
|
||||
serviceId: AGENT_MGR_SERVICE_ID,
|
||||
ok: false,
|
||||
error: {
|
||||
message: error.message
|
||||
}
|
||||
},
|
||||
{ stderr: true }
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function dispatch(name, opts) {
|
||||
if (name === "help" || opts.help) {
|
||||
return help();
|
||||
}
|
||||
|
||||
if (name === "health") {
|
||||
return createHealthResponse(opts);
|
||||
}
|
||||
|
||||
if (name === "server") {
|
||||
return serveHealth(opts);
|
||||
}
|
||||
|
||||
if (name === "create") {
|
||||
return {
|
||||
ok: true,
|
||||
...(await createLocalAgentSession({
|
||||
stateDir: opts.stateDir,
|
||||
agentSessionId: requireOption(opts, "agentSessionId", "--agent-session-id"),
|
||||
projectId: requireOption(opts, "projectId", "--project-id"),
|
||||
goal: opts.goal || "",
|
||||
prompt: opts.prompt || "",
|
||||
requestedBy: opts.requestedBy || "usr_local",
|
||||
skillCommitId: opts.skillCommitId || null,
|
||||
skillVersion: opts.skillVersion || null
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
if (name === "status") {
|
||||
return {
|
||||
ok: true,
|
||||
...(await getLocalAgentStatus({
|
||||
stateDir: opts.stateDir,
|
||||
agentSessionId: requireOption(opts, "agentSessionId", "--agent-session-id")
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
if (name === "trace") {
|
||||
return {
|
||||
ok: true,
|
||||
...(await getLocalAgentTrace({
|
||||
stateDir: opts.stateDir,
|
||||
agentSessionId: requireOption(opts, "agentSessionId", "--agent-session-id")
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
if (name === "evidence") {
|
||||
return {
|
||||
ok: true,
|
||||
...(await getLocalAgentEvidence({
|
||||
stateDir: opts.stateDir,
|
||||
agentSessionId: requireOption(opts, "agentSessionId", "--agent-session-id")
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
if (name === "cleanup") {
|
||||
return {
|
||||
ok: true,
|
||||
...(await cleanupLocalAgentSession({
|
||||
stateDir: opts.stateDir,
|
||||
agentSessionId: requireOption(opts, "agentSessionId", "--agent-session-id"),
|
||||
actor: AGENT_MGR_SERVICE_ID
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error(`unknown command ${JSON.stringify(name)}`);
|
||||
}
|
||||
|
||||
function parseOptions(argv) {
|
||||
const opts = {
|
||||
stateDir: process.env.HWLAB_AGENT_RUNTIME_STATE_DIR || ""
|
||||
};
|
||||
|
||||
for (let i = 0; i < argv.length; i += 1) {
|
||||
const arg = argv[i];
|
||||
if (arg === "--agent-session-id") opts.agentSessionId = argv[++i] || "";
|
||||
else if (arg === "--project-id") opts.projectId = argv[++i] || "";
|
||||
else if (arg === "--goal") opts.goal = argv[++i] || "";
|
||||
else if (arg === "--prompt") opts.prompt = argv[++i] || "";
|
||||
else if (arg === "--requested-by") opts.requestedBy = argv[++i] || "";
|
||||
else if (arg === "--skill-commit-id") opts.skillCommitId = argv[++i] || "";
|
||||
else if (arg === "--skill-version") opts.skillVersion = argv[++i] || "";
|
||||
else if (arg === "--state-dir") opts.stateDir = argv[++i] || "";
|
||||
else if (arg === "--help" || arg === "-h") opts.help = true;
|
||||
else throw new Error(`unknown option ${JSON.stringify(arg)}`);
|
||||
}
|
||||
|
||||
if (opts.stateDir) {
|
||||
opts.stateDir = resolveAgentRuntimeStateDir(opts.stateDir);
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
function requireOption(opts, key, flag) {
|
||||
if (!opts[key]) {
|
||||
throw new Error(`${flag} is required`);
|
||||
}
|
||||
return opts[key];
|
||||
}
|
||||
|
||||
function createHealthResponse(opts) {
|
||||
const managerSkills = assessSkillsInjection({
|
||||
skillCommitId: opts.skillCommitId,
|
||||
skillVersion: opts.skillVersion,
|
||||
role: "manager"
|
||||
});
|
||||
const health = createRuntimeHealth({
|
||||
stateDir: opts.stateDir,
|
||||
managerSkills
|
||||
});
|
||||
return {
|
||||
serviceId: AGENT_MGR_SERVICE_ID,
|
||||
ok: true,
|
||||
status: health.status,
|
||||
environment: process.env.HWLAB_ENVIRONMENT || "dev",
|
||||
...buildMetadataFromEnv(process.env, { serviceId: AGENT_MGR_SERVICE_ID }),
|
||||
health,
|
||||
skillsManifest: managerSkills.status === "ready"
|
||||
? createSkillsManifest({ commitId: managerSkills.commitId, version: managerSkills.version })
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
async function serveHealth(opts) {
|
||||
const port = Number.parseInt(process.env.PORT || process.env.HWLAB_PORT || "7410", 10);
|
||||
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
||||
throw new Error(`invalid PORT/HWLAB_PORT ${JSON.stringify(process.env.PORT || process.env.HWLAB_PORT)}`);
|
||||
}
|
||||
|
||||
const server = createServer((request, response) => {
|
||||
const url = new URL(request.url || "/", "http://hwlab-agent-mgr.local");
|
||||
if (url.pathname === "/health" || url.pathname === "/health/live") {
|
||||
sendJson(response, 200, createHealthResponse(opts));
|
||||
return;
|
||||
}
|
||||
if (url.pathname === "/" || url.pathname === "/help") {
|
||||
sendJson(response, 200, help());
|
||||
return;
|
||||
}
|
||||
sendJson(response, 404, { serviceId: AGENT_MGR_SERVICE_ID, ok: false, error: "not_found", path: url.pathname });
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
server.once("error", reject);
|
||||
server.listen(port, "0.0.0.0", resolve);
|
||||
});
|
||||
printJSON({ serviceId: AGENT_MGR_SERVICE_ID, ok: true, status: "listening", port });
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
server.once("close", resolve);
|
||||
server.once("error", reject);
|
||||
});
|
||||
}
|
||||
|
||||
function sendJson(response, statusCode, body) {
|
||||
const payload = JSON.stringify(body, null, 2);
|
||||
response.writeHead(statusCode, {
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-length": Buffer.byteLength(payload)
|
||||
});
|
||||
response.end(payload);
|
||||
}
|
||||
|
||||
function help() {
|
||||
return {
|
||||
serviceId: AGENT_MGR_SERVICE_ID,
|
||||
ok: true,
|
||||
usage: [
|
||||
"bun run cmd/hwlab-agent-mgr/main.ts server [--skill-commit-id COMMIT --skill-version VERSION] [--state-dir DIR]",
|
||||
"bun run cmd/hwlab-agent-mgr/main.ts health [--skill-commit-id COMMIT --skill-version VERSION] [--state-dir DIR]",
|
||||
"bun run cmd/hwlab-agent-mgr/main.ts create --agent-session-id ID --project-id ID [--goal TEXT --prompt TEXT] [--skill-commit-id COMMIT --skill-version VERSION] [--state-dir DIR]",
|
||||
"bun run cmd/hwlab-agent-mgr/main.ts status --agent-session-id ID [--state-dir DIR]",
|
||||
"bun run cmd/hwlab-agent-mgr/main.ts trace --agent-session-id ID [--state-dir DIR]",
|
||||
"bun run cmd/hwlab-agent-mgr/main.ts evidence --agent-session-id ID [--state-dir DIR]",
|
||||
"bun run cmd/hwlab-agent-mgr/main.ts cleanup --agent-session-id ID [--state-dir DIR]"
|
||||
],
|
||||
contract: {
|
||||
stateDir: resolveAgentRuntimeStateDir(),
|
||||
output: "json",
|
||||
runtimeMode: "local-dry-run",
|
||||
prodDisabled: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function printJSON(value, { stderr = false } = {}) {
|
||||
const target = stderr ? process.stderr : process.stdout;
|
||||
target.write(`${JSON.stringify(value, null, 2)}\n`);
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { execFile } from "node:child_process";
|
||||
import { access, mkdtemp, rm } from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const bunCommand = process.env.HWLAB_TEST_BUN_COMMAND || process.env.HWLAB_BUN_COMMAND || (process.versions.bun ? process.execPath : "bun");
|
||||
|
||||
test("agent worker health and dry-run preserve session evidence and cleanup behavior", async () => {
|
||||
const stateDir = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-worker-"));
|
||||
try {
|
||||
const health = await runWorkerJson(["health", "--state-dir", stateDir]);
|
||||
assert.equal(health.serviceId, "hwlab-agent-worker");
|
||||
assert.equal(health.ok, true);
|
||||
assert.equal(health.status, "ok");
|
||||
assert.equal(health.skills.status, "degraded");
|
||||
|
||||
await runManagerJson([
|
||||
"create",
|
||||
"--agent-session-id", "ags_worker",
|
||||
"--project-id", "prj_worker",
|
||||
"--skill-commit-id", "commit-worker",
|
||||
"--skill-version", "2.0.0",
|
||||
"--state-dir", stateDir
|
||||
]);
|
||||
|
||||
const dryRun = await runWorkerJson([
|
||||
"dry-run",
|
||||
"--agent-session-id", "ags_worker",
|
||||
"--skill-commit-id", "commit-worker",
|
||||
"--skill-version", "2.0.0",
|
||||
"--state-dir", stateDir
|
||||
]);
|
||||
assert.equal(dryRun.serviceId, "hwlab-agent-worker");
|
||||
assert.equal(dryRun.dryRun, true);
|
||||
assert.equal(dryRun.task.status, "completed");
|
||||
assert.equal(dryRun.health.status, "ok");
|
||||
assert.equal(dryRun.evidenceRecord.evidenceId, "evi_ags_worker");
|
||||
assert.equal(dryRun.cleanup.completed, true);
|
||||
assert.equal(dryRun.workspace.cleaned, true);
|
||||
assert.equal(dryRun.workspace.existsAfterCleanup, false);
|
||||
await assert.rejects(access(dryRun.workspace.path));
|
||||
|
||||
const evidence = await runManagerJson(["evidence", "--agent-session-id", "ags_worker", "--state-dir", stateDir]);
|
||||
assert.equal(evidence.evidenceRecords.length, 1);
|
||||
assert.equal(evidence.evidenceRecords[0].serviceId, "hwlab-agent-worker");
|
||||
} finally {
|
||||
await rm(stateDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("agent worker dry-run requires agent session id", async () => {
|
||||
const result = await execFileAsync(bunCommand, ["run", "cmd/hwlab-agent-worker/main.ts", "dry-run"], {
|
||||
cwd: process.cwd(),
|
||||
maxBuffer: 1024 * 1024
|
||||
}).then(
|
||||
() => ({ code: 0, stderr: "" }),
|
||||
(error) => ({ code: error.code, stderr: error.stderr })
|
||||
);
|
||||
assert.equal(result.code, 1);
|
||||
const payload = JSON.parse(result.stderr);
|
||||
assert.equal(payload.serviceId, "hwlab-agent-worker");
|
||||
assert.match(payload.error.message, /--agent-session-id is required/u);
|
||||
});
|
||||
|
||||
async function runManagerJson(args) {
|
||||
const { stdout } = await execFileAsync(bunCommand, ["run", "cmd/hwlab-agent-mgr/main.ts", ...args], {
|
||||
cwd: process.cwd(),
|
||||
maxBuffer: 1024 * 1024
|
||||
});
|
||||
return JSON.parse(stdout);
|
||||
}
|
||||
|
||||
async function runWorkerJson(args) {
|
||||
const { stdout } = await execFileAsync(bunCommand, ["run", "cmd/hwlab-agent-worker/main.ts", ...args], {
|
||||
cwd: process.cwd(),
|
||||
maxBuffer: 1024 * 1024
|
||||
});
|
||||
return JSON.parse(stdout);
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
import { buildMetadataFromEnv } from "../../internal/build-metadata.mjs";
|
||||
import { AGENT_WORKER_SERVICE_ID } from "../../internal/agent/index.mjs";
|
||||
import {
|
||||
assessSkillsInjection,
|
||||
resolveAgentRuntimeStateDir,
|
||||
runLocalWorkerDryRun
|
||||
} from "../../internal/agent/runtime.mjs";
|
||||
|
||||
const command = process.argv[2] || "help";
|
||||
const options = parseOptions(process.argv.slice(3));
|
||||
|
||||
try {
|
||||
const result = await dispatch(command, options);
|
||||
printJSON(result);
|
||||
} catch (error) {
|
||||
printJSON(
|
||||
{
|
||||
serviceId: AGENT_WORKER_SERVICE_ID,
|
||||
ok: false,
|
||||
error: {
|
||||
message: error.message
|
||||
}
|
||||
},
|
||||
{ stderr: true }
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function dispatch(name, opts) {
|
||||
if (name === "help" || opts.help) {
|
||||
return help();
|
||||
}
|
||||
|
||||
if (name === "health") {
|
||||
return {
|
||||
serviceId: AGENT_WORKER_SERVICE_ID,
|
||||
ok: true,
|
||||
status: "ok",
|
||||
environment: process.env.HWLAB_ENVIRONMENT || "dev",
|
||||
...buildMetadataFromEnv(process.env, { serviceId: AGENT_WORKER_SERVICE_ID }),
|
||||
runtimeMode: "local-dry-run",
|
||||
skills: assessSkillsInjection({
|
||||
skillCommitId: opts.skillCommitId,
|
||||
skillVersion: opts.skillVersion,
|
||||
role: "worker"
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
if (name === "dry-run" || name === "smoke") {
|
||||
return {
|
||||
ok: true,
|
||||
...(await runLocalWorkerDryRun({
|
||||
stateDir: opts.stateDir,
|
||||
agentSessionId: requireOption(opts, "agentSessionId", "--agent-session-id"),
|
||||
skillCommitId: opts.skillCommitId || null,
|
||||
skillVersion: opts.skillVersion || null
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error(`unknown command ${JSON.stringify(name)}`);
|
||||
}
|
||||
|
||||
function parseOptions(argv) {
|
||||
const opts = {
|
||||
stateDir: process.env.HWLAB_AGENT_RUNTIME_STATE_DIR || "",
|
||||
agentSessionId: process.env.HWLAB_AGENT_SESSION_ID || "",
|
||||
skillCommitId: process.env.HWLAB_SKILL_COMMIT_ID || "",
|
||||
skillVersion: process.env.HWLAB_SKILL_VERSION || ""
|
||||
};
|
||||
|
||||
for (let i = 0; i < argv.length; i += 1) {
|
||||
const arg = argv[i];
|
||||
if (arg === "--agent-session-id") opts.agentSessionId = argv[++i] || "";
|
||||
else if (arg === "--skill-commit-id") opts.skillCommitId = argv[++i] || "";
|
||||
else if (arg === "--skill-version") opts.skillVersion = argv[++i] || "";
|
||||
else if (arg === "--state-dir") opts.stateDir = argv[++i] || "";
|
||||
else if (arg === "--help" || arg === "-h") opts.help = true;
|
||||
else throw new Error(`unknown option ${JSON.stringify(arg)}`);
|
||||
}
|
||||
|
||||
if (opts.stateDir) {
|
||||
opts.stateDir = resolveAgentRuntimeStateDir(opts.stateDir);
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
function requireOption(opts, key, flag) {
|
||||
if (!opts[key]) {
|
||||
throw new Error(`${flag} is required`);
|
||||
}
|
||||
return opts[key];
|
||||
}
|
||||
|
||||
function help() {
|
||||
return {
|
||||
serviceId: AGENT_WORKER_SERVICE_ID,
|
||||
ok: true,
|
||||
usage: [
|
||||
"bun run cmd/hwlab-agent-worker/main.ts health [--skill-commit-id COMMIT --skill-version VERSION]",
|
||||
"bun run cmd/hwlab-agent-worker/main.ts dry-run --agent-session-id ID [--skill-commit-id COMMIT --skill-version VERSION] [--state-dir DIR]"
|
||||
],
|
||||
contract: {
|
||||
output: "json",
|
||||
runtimeMode: "local-dry-run",
|
||||
prodDisabled: true,
|
||||
behavior: "claim queued local session, write trace and evidence, cleanup workspace, exit"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function printJSON(value, { stderr = false } = {}) {
|
||||
const target = stderr ? process.stderr : process.stdout;
|
||||
target.write(`${JSON.stringify(value, null, 2)}\n`);
|
||||
}
|
||||
Reference in New Issue
Block a user