197 lines
6.4 KiB
TypeScript
197 lines
6.4 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { test } from "bun:test";
|
|
|
|
import { hwlabRuntimeLaneSpecForNode } from "../hwlab-node-lanes";
|
|
import { parseNodeWebProbeObserveOptions } from "./web-probe-observe";
|
|
|
|
const spec = hwlabRuntimeLaneSpecForNode("v03", "NC01");
|
|
|
|
function parseRealtimeCommand(extra: string[]) {
|
|
return parseNodeWebProbeObserveOptions(
|
|
["command", "--type", "validateRealtimeFanout", ...extra],
|
|
"NC01",
|
|
"v03",
|
|
spec,
|
|
"webobs-fixture",
|
|
null,
|
|
);
|
|
}
|
|
|
|
test("validateRealtimeFanout parses the YAML profile and two independent prompts", () => {
|
|
const options = parseRealtimeCommand([
|
|
"--profile", "pure-kafka-live",
|
|
"--provider", "gpt.pika",
|
|
"--text", "first turn",
|
|
"--second-text", "second turn",
|
|
]);
|
|
|
|
assert.equal(options.commandType, "validateRealtimeFanout");
|
|
assert.equal(options.commandProfile, "pure-kafka-live");
|
|
assert.equal(options.commandProvider, "gpt.pika");
|
|
assert.equal(options.commandText, "first turn");
|
|
assert.equal(options.commandSecondText, "second turn");
|
|
assert.deepEqual(spec.webProbe?.realtimeFanoutProfiles?.["pure-kafka-live"]?.debugStreams, ["stdio", "agentrun", "hwlab"]);
|
|
assert.equal(spec.webProbe?.realtimeFanoutProfiles?.["pure-kafka-live"]?.fromBeginning, false);
|
|
assert.deepEqual(spec.webProbe?.realtimeFanoutProfiles?.["pure-kafka-live"]?.expectedProductSse, {
|
|
deliverySemantics: "kafka-retention-then-live",
|
|
liveOnly: false,
|
|
replay: true,
|
|
replaySupported: true,
|
|
lossPossible: false,
|
|
refreshHandoff: true,
|
|
replayPriorTraceOnReconnect: true,
|
|
});
|
|
assert.deepEqual(spec.webProbe?.realtimeFanoutProfiles?.["pure-kafka-live"]?.requiredEventTypes, {
|
|
agentrun: ["user_message", "assistant_message", "terminal_status"],
|
|
hwlab: ["user", "assistant", "terminal"],
|
|
});
|
|
assert.deepEqual(spec.webProbe?.realtimeFanoutProfiles?.["pure-kafka-live"]?.conditionalEventTypePairs, {
|
|
"tool-call": { agentrun: "tool_call", hwlab: "tool" },
|
|
"command-output": { agentrun: "command_output", hwlab: "status" },
|
|
});
|
|
});
|
|
|
|
test("validateRealtimeFanout refuses body as a substitute for the second prompt", () => {
|
|
assert.throws(
|
|
() => parseRealtimeCommand([
|
|
"--profile", "pure-kafka-live",
|
|
"--provider", "gpt.pika",
|
|
"--text", "first turn",
|
|
"--body", "not a second prompt",
|
|
]),
|
|
/requires --second-text/u,
|
|
);
|
|
});
|
|
|
|
test("validateRealtimeFanout rejects profiles absent from the owning YAML", () => {
|
|
assert.throws(
|
|
() => parseRealtimeCommand([
|
|
"--profile", "projection-mode",
|
|
"--provider", "gpt.pika",
|
|
"--text", "first turn",
|
|
"--second-text", "second turn",
|
|
]),
|
|
/profile is not declared by the owning YAML/u,
|
|
);
|
|
});
|
|
|
|
test("validateExistingSessionRefresh parses an existing session without prompts", () => {
|
|
const options = parseNodeWebProbeObserveOptions(
|
|
["command", "--type", "validateExistingSessionRefresh", "--profile", "pure-kafka-live", "--session-id", "ses_existing"],
|
|
"NC01", "v03", spec, "webobs-fixture", null,
|
|
);
|
|
assert.equal(options.commandType, "validateExistingSessionRefresh");
|
|
assert.equal(options.commandProfile, "pure-kafka-live");
|
|
assert.equal(options.commandSessionId, "ses_existing");
|
|
assert.equal(options.commandText, null);
|
|
});
|
|
|
|
test("validateWorkbenchKafkaDebugReplay is a YAML-enabled argument-free typed command", () => {
|
|
const options = parseNodeWebProbeObserveOptions(
|
|
["command", "--type", "validateWorkbenchKafkaDebugReplay"],
|
|
"NC01",
|
|
"v03",
|
|
spec,
|
|
"webobs-fixture",
|
|
null,
|
|
);
|
|
|
|
assert.equal(options.commandType, "validateWorkbenchKafkaDebugReplay");
|
|
assert.deepEqual(spec.webProbe?.workbenchKafkaDebugReplay, {
|
|
enabled: true,
|
|
topic: "hwlab.event.debug.v1",
|
|
groupPrefix: "hwlab-v03-workbench-isolated-debug",
|
|
completionTimeoutMs: 30_000,
|
|
});
|
|
});
|
|
|
|
test("validateWorkbenchTraceReadability 是由独立 YAML 启用的无参数 typed command", () => {
|
|
const options = parseNodeWebProbeObserveOptions(
|
|
["command", "--type", "validateWorkbenchTraceReadability"],
|
|
"NC01",
|
|
"v03",
|
|
spec,
|
|
"webobs-fixture",
|
|
null,
|
|
);
|
|
|
|
assert.equal(options.commandType, "validateWorkbenchTraceReadability");
|
|
assert.equal(spec.webProbe?.workbenchTraceReadability?.terminalTimeoutMs, 480_000);
|
|
assert.equal(spec.webProbe?.workbenchTraceReadability?.runningCardTimeoutMs, 15_000);
|
|
});
|
|
|
|
test("observe start selects the YAML public origin semantically", () => {
|
|
const options = parseNodeWebProbeObserveOptions(
|
|
["start", "--origin", "public"],
|
|
"NC01",
|
|
"v03",
|
|
spec,
|
|
null,
|
|
null,
|
|
);
|
|
|
|
assert.equal(options.originName, "public");
|
|
assert.equal(options.originMode, "public");
|
|
assert.equal(options.url, spec.publicWebUrl);
|
|
assert.equal(options.browserProxyMode, "auto");
|
|
assert.equal(options.browserProxyModeSource, "yaml-origin");
|
|
});
|
|
|
|
test("observe start refuses URL-based internal/public selection ambiguity", () => {
|
|
assert.throws(
|
|
() => parseNodeWebProbeObserveOptions(
|
|
["start", "--origin", "public", "--url", "http://127.0.0.1:4173"],
|
|
"NC01",
|
|
"v03",
|
|
spec,
|
|
null,
|
|
null,
|
|
),
|
|
/accepts --origin or --url, not both/u,
|
|
);
|
|
});
|
|
|
|
test("observe command inherits the indexed origin and rejects replacement origins", () => {
|
|
const indexed = {
|
|
id: "webobs-fixture",
|
|
node: "NC01",
|
|
lane: "v03",
|
|
workspace: spec.workspace,
|
|
stateDir: ".state/web-observe/NC01/v03/2026/07/10/20260710T000000Z_workbench_webobs-fixture",
|
|
url: "http://10.43.99.7:8080",
|
|
originName: "internal" as const,
|
|
originMode: "k8s-service-cluster-ip" as const,
|
|
originConfigPath: "config/hwlab-node-lanes.yaml#webProbe.origins.internal",
|
|
browserProxyMode: "direct" as const,
|
|
browserProxyModeSource: "yaml-origin" as const,
|
|
targetPath: "/workbench",
|
|
status: "running",
|
|
pid: 42,
|
|
startedAt: "2026-07-10T00:00:00.000Z",
|
|
updatedAt: "2026-07-10T00:00:01.000Z",
|
|
};
|
|
const inherited = parseNodeWebProbeObserveOptions(
|
|
["command", "--type", "mark", "--label", "checkpoint"],
|
|
"NC01",
|
|
"v03",
|
|
spec,
|
|
"webobs-fixture",
|
|
indexed,
|
|
);
|
|
assert.equal(inherited.originName, "internal");
|
|
assert.equal(inherited.url, indexed.url);
|
|
assert.equal(inherited.browserProxyMode, "direct");
|
|
|
|
assert.throws(
|
|
() => parseNodeWebProbeObserveOptions(
|
|
["command", "--origin", "public", "--type", "mark", "--label", "checkpoint"],
|
|
"NC01",
|
|
"v03",
|
|
spec,
|
|
"webobs-fixture",
|
|
indexed,
|
|
),
|
|
/later actions inherit the observer origin/u,
|
|
);
|
|
});
|