feat: 拉通 Workbench 纯 Kafka 实时链路

This commit is contained in:
root
2026-07-10 10:22:28 +02:00
parent d5230cb923
commit 8ad5976a07
59 changed files with 4700 additions and 498 deletions
+13 -1
View File
@@ -390,7 +390,12 @@ function validateDisplayLocale(locale) {
function workbenchRuntimeConfigFromEnv() {
const traceTimeline = {};
const result = {};
const result = {
realtimeFeatures: {
liveKafkaSse: requiredWorkbenchRealtimeFeature(process.env.HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED, "HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED"),
projectionRealtime: requiredWorkbenchRealtimeFeature(process.env.HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED, "HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED")
}
};
const autoExpandRunning = parseEnvBoolean(process.env.HWLAB_WORKBENCH_TRACE_AUTO_EXPAND_RUNNING);
const autoCollapseTerminal = parseEnvBoolean(process.env.HWLAB_WORKBENCH_TRACE_AUTO_COLLAPSE_TERMINAL);
const traceExplorerUrlTemplate = traceExplorerUrlTemplateFromEnv(process.env.HWLAB_WORKBENCH_TRACE_EXPLORER_URL_TEMPLATE);
@@ -401,6 +406,13 @@ function workbenchRuntimeConfigFromEnv() {
return Object.keys(result).length > 0 ? result : null;
}
function requiredWorkbenchRealtimeFeature(value, name) {
const normalized = String(value ?? "").trim().toLowerCase();
if (normalized === "true" || normalized === "1") return true;
if (normalized === "false" || normalized === "0") return false;
throw new Error(`${name} is required and must be explicitly true or false`);
}
function traceExplorerUrlTemplateFromEnv(value) {
if (value === undefined || value === null || value === "") return null;
const template = String(value).trim();
@@ -429,7 +429,9 @@ test("cloud web serves client deep links through the Vue shell", async () => {
const restoreEnv = withEnv({
HWLAB_CLOUD_WEB_DISPLAY_TIME_ZONE: "Asia/Shanghai",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LOCALE: "zh-CN",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LABEL: "北京时间"
HWLAB_CLOUD_WEB_DISPLAY_TIME_LABEL: "北京时间",
HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED: "true",
HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED: "false"
});
const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-cloud-web-runtime-"));
await writeFile(path.join(root, "index.html"), "<div id=\"root\"></div>\n", "utf8");
@@ -484,7 +486,9 @@ test("cloud web injects trace explorer runtime config from env", async () => {
HWLAB_CLOUD_WEB_DISPLAY_TIME_ZONE: "Asia/Shanghai",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LOCALE: "zh-CN",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LABEL: "北京时间",
HWLAB_WORKBENCH_TRACE_EXPLORER_URL_TEMPLATE: "/v1/workbench/traces/{trace_id}/events"
HWLAB_WORKBENCH_TRACE_EXPLORER_URL_TEMPLATE: "/v1/workbench/traces/{trace_id}/events",
HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED: "true",
HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED: "false"
});
const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-cloud-web-runtime-"));
await writeFile(path.join(root, "index.html"), "<html><head></head><body><div id=\"root\"></div></body></html>\n", "utf8");
@@ -588,7 +592,9 @@ test("cloud web OpenCode frame-url endpoint mints traced tickets", async () => {
HWLAB_CLOUD_WEB_DISPLAY_TIME_ZONE: "Asia/Shanghai",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LOCALE: "zh-CN",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LABEL: "北京时间",
HWLAB_CLOUD_WEB_OPENCODE_URL: "https://opencode.example.test"
HWLAB_CLOUD_WEB_OPENCODE_URL: "https://opencode.example.test",
HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED: "true",
HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED: "false"
});
const cloudApiRequests = [];
const opencodeRequests = [];
@@ -1028,7 +1034,9 @@ test("cloud web OpenCode proxy accepts short-lived tickets minted by the shell",
HWLAB_CLOUD_WEB_DISPLAY_TIME_ZONE: "Asia/Shanghai",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LOCALE: "zh-CN",
HWLAB_CLOUD_WEB_DISPLAY_TIME_LABEL: "北京时间",
HWLAB_CLOUD_WEB_OPENCODE_URL: "https://opencode.example.test"
HWLAB_CLOUD_WEB_OPENCODE_URL: "https://opencode.example.test",
HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED: "true",
HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED: "false"
});
const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-cloud-web-runtime-"));
await writeFile(path.join(root, "index.html"), "<html><head></head><body><div id=\"root\"></div></body></html>\n", "utf8");