fix: smooth caserun trace and uart hints
This commit is contained in:
@@ -354,9 +354,9 @@ test("case run orchestrates agent prompt, diff capture, and compile evidence wit
|
||||
assert.equal(result.payload.agent.stageStatus, "completed");
|
||||
assert.equal(result.payload.agent.traceId.startsWith("trc_case_"), true);
|
||||
assert.equal(result.payload.agent.timeoutMs, 234000);
|
||||
assert.equal(result.payload.traceLookup.commands.trace, `hwlab-cli client agent trace ${result.payload.agent.traceId} --base-url http://web.test --render web`);
|
||||
assert.equal(result.payload.traceLookup.commands.result, `hwlab-cli client agent result ${result.payload.agent.traceId} --base-url http://web.test`);
|
||||
assert.equal(result.payload.traceLookup.commands.inspect, `hwlab-cli client agent inspect --trace-id ${result.payload.agent.traceId} --base-url http://web.test`);
|
||||
assert.equal(result.payload.traceLookup.commands.trace, `hwlab-cli client agent trace ${result.payload.agent.traceId} --render web`);
|
||||
assert.equal(result.payload.traceLookup.commands.result, `hwlab-cli client agent result ${result.payload.agent.traceId}`);
|
||||
assert.equal(result.payload.traceLookup.commands.inspect, `hwlab-cli client agent inspect --trace-id ${result.payload.agent.traceId}`);
|
||||
assert.equal(result.payload.agentTrace.source, "hwlab-cli.client.agent.trace");
|
||||
assert.equal(result.payload.agentTrace.lookupOnly, undefined);
|
||||
assert.equal(result.payload.agentTrace.commandCount, 1);
|
||||
@@ -645,7 +645,7 @@ test("case run status reports latest run stage when async control stage is stale
|
||||
assert.equal(result.exitCode, 0);
|
||||
assert.equal(result.payload.ready, false);
|
||||
assert.equal(result.payload.stage, "agent-diff-collected");
|
||||
assert.equal(result.payload.traceLookup.commands.trace, "hwlab-cli client agent trace trc_case --base-url http://web.test --render web");
|
||||
assert.equal(result.payload.traceLookup.commands.trace, "hwlab-cli client agent trace trc_case --render web");
|
||||
assert.equal(result.payload.staleControlWarning.code, "stale_control_stage");
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true });
|
||||
|
||||
@@ -170,6 +170,11 @@ test("hwpod-cli dry-run invokes hwpod-compiler-cli and exposes hwpod-node-ops pl
|
||||
assert.equal(insert.payload.plan.ops[0].args.line, " /* MARKER_OK */");
|
||||
assert.equal(insert.payload.plan.ops[0].args.expectedSha, "abc123");
|
||||
|
||||
const insertAliases = await runHwpodCli(["workspace", "insert-after", "--spec", specPath, "--path", "projects/01_baseline/User/main.c", "--marker", "device-pod LCD bring-up", "--content", " /* MARKER_ALIAS */", "--dry-run"], { now: () => NOW });
|
||||
assert.equal(insertAliases.exitCode, 0);
|
||||
assert.equal(insertAliases.payload.plan.ops[0].args.anchor, "device-pod LCD bring-up");
|
||||
assert.equal(insertAliases.payload.plan.ops[0].args.line, " /* MARKER_ALIAS */");
|
||||
|
||||
const replace = await runHwpodCli(["workspace", "replace", "--spec", specPath, "--path", "projects/01_baseline/User/main.c", "--find", " /* MARKER_OK */", "--replace", "", "--dry-run"], { now: () => NOW });
|
||||
assert.equal(replace.exitCode, 0);
|
||||
assert.equal(replace.payload.plan.ops[0].op, "workspace.replace");
|
||||
@@ -192,6 +197,13 @@ test("hwpod-cli dry-run invokes hwpod-compiler-cli and exposes hwpod-node-ops pl
|
||||
const uartSequence = JSON.parse(uart.payload.plan.ops[0].args.argv[2]);
|
||||
assert.deepEqual(uartSequence[0], ["bun", "scripts/serial-monitor-cli.ts", "monitor", "start", "-p", "COM9", "-b", "115200"]);
|
||||
assert.deepEqual(uartSequence[1].slice(0, 5), ["bun", "scripts/serial-monitor-cli.ts", "fetch", "-l", "7"]);
|
||||
assert.equal(uartSequence[1].includes("--session-only"), false);
|
||||
assert.equal(uart.payload.plan.ops[0].args.commandBinding.sessionOnly, false);
|
||||
|
||||
const uartSessionOnly = await runHwpodCli(["uart", "read", "--spec", specPath, "--port", "uart1", "--max-bytes", "512", "--session-only", "--dry-run"], { now: () => NOW });
|
||||
const uartSessionSequence = JSON.parse(uartSessionOnly.payload.plan.ops[0].args.argv[2]);
|
||||
assert.equal(uartSessionSequence[1].includes("--session-only"), true);
|
||||
assert.equal(uartSessionOnly.payload.plan.ops[0].args.commandBinding.sessionOnly, true);
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
@@ -876,11 +876,11 @@ function agentTraceLookup(input: { baseUrl: string; traceId: string; sessionId?:
|
||||
const traceId = input.traceId;
|
||||
const base = input.baseUrl;
|
||||
const commands = clean({
|
||||
result: `hwlab-cli client agent result ${traceId} --base-url ${base}`,
|
||||
trace: `hwlab-cli client agent trace ${traceId} --base-url ${base} --render web`,
|
||||
traceFull: `hwlab-cli client agent trace ${traceId} --base-url ${base} --render web --full`,
|
||||
inspect: `hwlab-cli client agent inspect --trace-id ${traceId} --base-url ${base}`,
|
||||
sessionStatus: input.sessionId ? `hwlab-cli client agent session status ${input.sessionId} --base-url ${base}` : undefined
|
||||
result: `hwlab-cli client agent result ${traceId}`,
|
||||
trace: `hwlab-cli client agent trace ${traceId} --render web`,
|
||||
traceFull: `hwlab-cli client agent trace ${traceId} --render web --full`,
|
||||
inspect: `hwlab-cli client agent inspect --trace-id ${traceId}`,
|
||||
sessionStatus: input.sessionId ? `hwlab-cli client agent session status ${input.sessionId}` : undefined
|
||||
});
|
||||
return clean({
|
||||
source: "hwlab-cli.client.agent",
|
||||
|
||||
@@ -14,7 +14,7 @@ const COMPILER_NAME = "hwpod-compiler-cli";
|
||||
const CTL_NAME = "hwpod-ctl";
|
||||
const CLI_NAME = "hwpod-cli";
|
||||
const DEFAULT_TIMEOUT_MS = 30000;
|
||||
const BOOLEAN_OPTIONS = new Set(["all", "allowMultiple", "dryRun", "finalNewline", "force", "full", "help", "h", "json", "noAuth", "wait"]);
|
||||
const BOOLEAN_OPTIONS = new Set(["all", "allowMultiple", "dryRun", "finalNewline", "force", "full", "help", "h", "json", "noAuth", "sessionOnly", "wait"]);
|
||||
const DEFAULT_KEIL_COMMAND_TIMEOUT_MS = 30000;
|
||||
type EnvLike = Record<string, string | undefined>;
|
||||
type ParsedArgs = Record<string, unknown> & { _: string[] };
|
||||
@@ -424,7 +424,7 @@ function commandToIntent(parsed: ParsedArgs, stdinText?: string) {
|
||||
if (subcommand === "apply-patch") return { intent: "workspace.apply-patch", args: { patch: patchText(parsed.patch ?? parsed.patchText ?? stdinText), patchBase64: text(parsed.patchBase64), reason: text(parsed.reason) } };
|
||||
if (subcommand === "write") return { intent: "workspace.write", args: clean({ path: requiredWorkspacePath(parsed, 2), content: patchText(parsed.content ?? parsed.contentText ?? stdinText), contentBase64: text(parsed.contentBase64), expectedSha: text(parsed.expectedSha), lineEnding: text(parsed.lineEnding), finalNewline: parsed.finalNewline === true, dryRun: parsed.dryRun === true, reason: text(parsed.reason) }) };
|
||||
if (subcommand === "replace") return { intent: "workspace.replace", args: cleanTextEditArgs({ path: requiredWorkspacePath(parsed, 2), find: requiredRawString(parsed.find ?? parsed._[3], "find"), replace: rawString(parsed.replace ?? parsed.replacement ?? parsed._[4]), expectedSha: text(parsed.expectedSha), all: parsed.all === true, dryRun: parsed.dryRun === true, reason: text(parsed.reason) }) };
|
||||
if (subcommand === "insert-after") return { intent: "workspace.insert-after", args: cleanTextEditArgs({ path: requiredWorkspacePath(parsed, 2), anchor: requiredRawString(parsed.anchor ?? parsed._[3], "anchor"), line: requiredRawString(parsed.line ?? parsed.insert ?? parsed.text ?? parsed._[4], "line"), expectedSha: text(parsed.expectedSha), allowMultiple: parsed.allowMultiple === true, dryRun: parsed.dryRun === true, reason: text(parsed.reason) }) };
|
||||
if (subcommand === "insert-after") return { intent: "workspace.insert-after", args: cleanTextEditArgs({ path: requiredWorkspacePath(parsed, 2), anchor: requiredRawString(parsed.anchor ?? parsed.marker ?? parsed._[3], "anchor"), line: requiredRawString(parsed.line ?? parsed.content ?? parsed.insert ?? parsed.text ?? parsed._[4], "line"), expectedSha: text(parsed.expectedSha), allowMultiple: parsed.allowMultiple === true, dryRun: parsed.dryRun === true, reason: text(parsed.reason) }) };
|
||||
throw cliError("unsupported_workspace_command", `unsupported workspace command: ${subcommand}`);
|
||||
}
|
||||
if (command === "build") return { intent: "debug.build", args: clean({ target: text(parsed.target), command: text(parsed.command ?? parsed.commandLine), wait: parsed.wait === true, timeoutMs: numberValue(parsed.timeoutMs), reason: text(parsed.reason) }) };
|
||||
@@ -437,7 +437,7 @@ function commandToIntent(parsed: ParsedArgs, stdinText?: string) {
|
||||
if (command === "reset") return { intent: "debug.reset", args: clean({ mode: text(parsed.mode ?? parsed._[1]), command: text(parsed.command ?? parsed.commandLine), reason: text(parsed.reason) }) };
|
||||
if (command === "uart") {
|
||||
const subcommand = parsed._[1] || "read";
|
||||
if (subcommand === "read") return { intent: "io.uart.read", args: clean({ port: text(parsed.port ?? parsed._[2] ?? "uart1"), maxBytes: numberValue(parsed.maxBytes), limit: numberValue(parsed.limit), since: text(parsed.since), timeoutMs: numberValue(parsed.timeoutMs), serialMonitorDir: text(parsed.serialMonitorDir), serialMonitorCommand: text(parsed.serialMonitorCommand), reason: text(parsed.reason) }) };
|
||||
if (subcommand === "read") return { intent: "io.uart.read", args: clean({ port: text(parsed.port ?? parsed._[2] ?? "uart1"), maxBytes: numberValue(parsed.maxBytes), limit: numberValue(parsed.limit), since: text(parsed.since), sessionOnly: parsed.sessionOnly === true, timeoutMs: numberValue(parsed.timeoutMs), serialMonitorDir: text(parsed.serialMonitorDir), serialMonitorCommand: text(parsed.serialMonitorCommand), reason: text(parsed.reason) }) };
|
||||
if (subcommand === "write") return { intent: "io.uart.write", args: clean({ port: text(parsed.port ?? parsed._[2] ?? "uart1"), data: requiredText(parsed.data ?? parsed._[3] ?? stdinText, "data") }) };
|
||||
throw cliError("unsupported_uart_command", `unsupported uart command: ${subcommand}`);
|
||||
}
|
||||
@@ -685,7 +685,7 @@ function serialMonitorReadCommand(args: any, document: any) {
|
||||
const commandBase = serialMonitorCommandBaseForCompiler(args, tooling, ioProbe);
|
||||
const timeoutMs = numberValue(args.timeoutMs) ?? 30000;
|
||||
const limit = Math.max(1, Math.min(numberValue(args.limit) ?? Math.ceil((numberValue(args.maxBytes) ?? 4096) / 80), 200));
|
||||
const fetchArgs = ["fetch", "-l", String(limit), "--session-only", ...(text(args.since) ? ["-s", text(args.since)] : [])];
|
||||
const fetchArgs = ["fetch", "-l", String(limit), ...(args.sessionOnly === true ? ["--session-only"] : []), ...(text(args.since) ? ["-s", text(args.since)] : [])];
|
||||
const sequenceRun = jsonCliSequenceCommandRun([
|
||||
[...commandBase, "monitor", "start", "-p", physicalPort, "-b", String(baudRate)],
|
||||
[...commandBase, ...fetchArgs]
|
||||
@@ -695,7 +695,7 @@ function serialMonitorReadCommand(args: any, document: any) {
|
||||
command: sequenceRun.commandLine,
|
||||
commandRun: sequenceRun.commandRun,
|
||||
timeoutMs,
|
||||
binding: clean({ kind: "serial-monitor-cli", source: "hwpod-compiler.serial-monitor", action: "uart-read", requestedPort, physicalPort, baudRate, serialMonitorDir })
|
||||
binding: clean({ kind: "serial-monitor-cli", source: "hwpod-compiler.serial-monitor", action: "uart-read", requestedPort, physicalPort, baudRate, serialMonitorDir, sessionOnly: args.sessionOnly === true })
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user