Files
pikasTech-HWLAB/skills/hwlab-agent-runtime/scripts/m3-io-skill-client.test.mjs
T
Lyon 997b96dc65 fix: add structured Code Agent blockers
Add structured Code Agent blocker taxonomy across /v1/agent/chat, runner/session/tool, and HWLAB M3 Skill CLI paths.\n\nValidated with npm run check and focused server/session/Skill CLI/web tests.
2026-05-23 23:17:13 +08:00

222 lines
7.5 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import {
HWLAB_M3_IO_API_BASE_URL_ENV,
HWLAB_M3_IO_CAPABILITY_LEVELS,
HWLAB_M3_IO_DEV_SERVICE_BASE_URL,
HWLAB_M3_IO_API_ROUTE,
runM3IoSkillCommand,
validateCloudApiTarget
} from "./src/m3-io-skill-client.mjs";
test("M3 Skill CLI posts only to HWLAB API /v1/m3/io for DO1 writes", async () => {
const calls = [];
const result = await runM3IoSkillCommand(
[
"m3",
"io",
"--action",
"do.write",
"--value",
"false",
"--api-base-url",
"http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667",
"--trace-id",
"trc_skill_cli_write_false",
"--request-id",
"req_skill_cli_write_false"
],
{
now: () => "2026-05-23T00:08:00.000Z",
requestJson: async (url, request) => {
calls.push({ url, request });
assert.equal(url, `http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667${HWLAB_M3_IO_API_ROUTE}`);
assert.equal(request.method, "POST");
assert.equal(request.body.action, "do.write");
assert.equal(request.body.resourceId, "res_boxsimu_1");
assert.equal(request.body.boxId, "boxsimu_1");
assert.equal(request.body.port, "DO1");
assert.equal(request.body.value, false);
assert.equal(request.body.source, "hwlab-agent-runtime.m3-io");
return {
ok: true,
status: 200,
body: {
status: "succeeded",
accepted: true,
traceId: "trc_skill_cli_write_false",
operationId: "op_m3_do_write_cli",
auditId: "aud_m3_do_write_cli_succeeded",
evidenceId: "evd_m3_do_write_cli_succeeded",
auditState: {
status: "written_non_durable"
},
evidenceState: {
status: "blocked",
sourceKind: "BLOCKED",
blocker: "runtime_durable_not_green",
writeStatus: "written_non_durable"
},
durableStatus: {
status: "degraded",
durable: false,
blocker: "runtime_durable_not_green"
},
result: {
value: false,
targetReadback: {
value: false
}
},
controlPath: {
cloudApi: true,
gatewaySimu: true,
boxSimu: true,
patchPanel: true,
frontendBypass: false
}
}
};
}
}
);
assert.equal(result.ok, true);
assert.equal(result.route, HWLAB_M3_IO_API_ROUTE);
assert.equal(result.capabilityLevel, HWLAB_M3_IO_CAPABILITY_LEVELS.ready);
assert.equal(result.controlReady, true);
assert.equal(result.readiness.status, "ready");
assert.equal(result.accepted, true);
assert.equal(result.status, "succeeded");
assert.equal(result.operationId, "op_m3_do_write_cli");
assert.equal(result.audit.auditId, "aud_m3_do_write_cli_succeeded");
assert.equal(result.evidence.evidenceId, "evd_m3_do_write_cli_succeeded");
assert.equal(result.durable.blocker, "runtime_durable_not_green");
assert.equal(result.trustBlocker.code, "runtime_durable_not_green");
assert.equal(result.blockers.some((blocker) => blocker.code === "runtime_durable_not_green"), true);
assert.equal(result.safety.directGatewayCalls, false);
assert.equal(result.safety.directBoxCalls, false);
assert.equal(result.safety.directPatchPanelCalls, false);
assert.equal(result.safety.fallbackUsed, false);
assert.equal(calls.length, 1);
});
test("M3 Skill CLI rejects direct gateway, box, and patch-panel targets before request", async () => {
for (const url of [
"http://hwlab-gateway-simu-1.hwlab-dev.svc.cluster.local:7101",
"http://hwlab-box-simu-1.hwlab-dev.svc.cluster.local:7201",
"http://hwlab-patch-panel.hwlab-dev.svc.cluster.local:7301"
]) {
const result = await runM3IoSkillCommand(
[
"m3",
"io",
"--action",
"di.read",
"--api-base-url",
url,
"--trace-id",
"trc_skill_cli_direct_blocked"
],
{
requestJson: async () => {
throw new Error("direct hardware target must be blocked before network call");
}
}
);
assert.equal(result.ok, false);
assert.equal(result.status, "blocked");
assert.equal(result.capabilityLevel, HWLAB_M3_IO_CAPABILITY_LEVELS.blocked);
assert.equal(result.controlReady, false);
assert.equal(result.readiness.status, "blocked");
assert.equal(result.accepted, false);
assert.equal(result.blocker.code, "direct_hardware_target_blocked");
assert.equal(result.capabilityBlocker.code, "direct_hardware_target_blocked");
assert.equal(result.operationId, null);
assert.equal(result.safety.directGatewayCalls, false);
assert.equal(result.safety.directBoxCalls, false);
assert.equal(result.safety.directPatchPanelCalls, false);
}
});
test("M3 Skill CLI validates exact API route contract", () => {
const invalid = validateCloudApiTarget({
url: "http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667/v1/rpc/m3.io.di.read"
});
assert.equal(invalid.code, "invalid_hwlab_api_route");
});
test("M3 Skill CLI reports missing API base as safe structured config blocker", async () => {
const result = await runM3IoSkillCommand(
[
"m3",
"io",
"--action",
"di.read",
"--trace-id",
"trc_skill_cli_api_base_missing"
],
{
env: {
PATH: process.env.PATH
},
requestJson: async () => {
throw new Error("missing API base must be blocked before request");
}
}
);
assert.equal(result.ok, false);
assert.equal(result.status, "blocked");
assert.equal(result.blocker.code, "skill_cli_api_base_missing");
assert.equal(result.blocker.layer, "skill-cli-config");
assert.equal(result.blocker.retryable, false);
assert.equal(result.error.code, "skill_cli_api_base_missing");
assert.equal(result.capabilityLevel, HWLAB_M3_IO_CAPABILITY_LEVELS.blocked);
assert.equal(result.accepted, false);
assert.equal(result.operationId, null);
assert.equal(result.audit.status, "not_written");
assert.equal(result.hwlabApi.source, "missing-config");
assert.equal(result.hwlabApi.redactedUrl, null);
assert.deepEqual(result.error.missingConfig, [
"HWLAB_CODE_AGENT_HWLAB_API_BASE_URL",
"HWLAB_API_BASE_URL",
"HWLAB_CLOUD_API_BASE_URL",
"contract:hwlab-agent-runtime.m3-io.apiBaseUrl"
]);
assert.equal(JSON.stringify(result).includes("://"), false);
});
test("M3 Skill CLI reports HWLAB API unavailable as retryable structured blocker", async () => {
const result = await runM3IoSkillCommand(
[
"m3",
"io",
"--action",
"di.read",
"--api-base-url",
"http://hwlab-cloud-api.hwlab-dev.svc.cluster.local:6667",
"--trace-id",
"trc_skill_cli_hwlab_api_unavailable"
],
{
requestJson: async () => ({
ok: false,
status: 503,
body: null,
error: "service unavailable"
})
}
);
assert.equal(result.ok, false);
assert.equal(result.status, "blocked");
assert.equal(result.blocker.code, "hwlab_api_unavailable");
assert.equal(result.blocker.layer, "hwlab-api");
assert.equal(result.blocker.retryable, true);
assert.equal(result.error.code, "hwlab_api_unavailable");
assert.equal(result.error.retryable, true);
assert.equal(result.error.route, HWLAB_M3_IO_API_ROUTE);
assert.equal(result.error.toolName, "hwlab-agent-runtime.m3-io");
});