diff --git a/cmd/hwlab-workbench-api/main.ts b/cmd/hwlab-workbench-api/main.ts index 06ebea33..03915edd 100644 --- a/cmd/hwlab-workbench-api/main.ts +++ b/cmd/hwlab-workbench-api/main.ts @@ -3,7 +3,7 @@ import { createWorkbenchHttpApp } from "../../internal/workbench/http.ts"; import { workbenchRuntime } from "../../internal/workbench/runtime.ts"; import { startHwlabKafkaEventBridge } from "../../internal/cloud/kafka-event-bridge.ts"; -const runtime = workbenchRuntime(); +const runtime = workbenchRuntime(process.env, { eventPublisher: null }); const kafkaEventBridge = runtime.mode === "agentrun-native" ? startHwlabKafkaEventBridge({ env: process.env }) : null; const app = createWorkbenchHttpApp({ dispatch: runtime.dispatch, snapshot: runtime.application.snapshot?.bind(runtime.application), authorization: process.env.WORKBENCH_API_AUTHORIZATION, mode: runtime.mode, kafkaEventBridge, close: async () => { await kafkaEventBridge?.stop?.(); await runtime.close(); } }); const host = process.env.WORKBENCH_API_HOST || "0.0.0.0"; diff --git a/internal/workbench/runtime.ts b/internal/workbench/runtime.ts index f4970e94..1e5ffa13 100644 --- a/internal/workbench/runtime.ts +++ b/internal/workbench/runtime.ts @@ -9,11 +9,15 @@ import { createWorkbenchTemporalGateway } from "./temporal.ts"; import { createWorkbenchKafkaEventPublisher } from "./kafka-event-publisher.ts"; import type { WorkbenchEventPublisher } from "./contracts.ts"; -export function workbenchRuntime(env: Record = process.env, options: { eventPublisher?: WorkbenchEventPublisher } = {}) { +export function workbenchRuntime(env: Record = process.env, options: { eventPublisher?: WorkbenchEventPublisher | null } = {}) { const mode = String(env.WORKBENCH_MODE ?? "").trim(); if (mode !== "native-test" && mode !== "agentrun-native" && mode !== "temporal") throw codedError("workbench_mode_required", "WORKBENCH_MODE must be native-test, agentrun-native, or temporal"); const stateFile = path.resolve(String(env.WORKBENCH_NATIVE_STATE_FILE ?? ".state/workbench-native/state.json")); - const eventPublisher = mode === "native-test" ? null : options.eventPublisher ?? createWorkbenchKafkaEventPublisher({ env }); + const eventPublisher = mode === "native-test" + ? null + : Object.hasOwn(options, "eventPublisher") + ? options.eventPublisher ?? null + : createWorkbenchKafkaEventPublisher({ env }); const application = mode === "native-test" ? createNativeTestWorkbenchApplication({ stateFile }) : mode === "agentrun-native" diff --git a/internal/workbench/workbench.test.ts b/internal/workbench/workbench.test.ts index 00901d8d..f62010fc 100644 --- a/internal/workbench/workbench.test.ts +++ b/internal/workbench/workbench.test.ts @@ -5,8 +5,26 @@ import { createWorkbenchActivities } from "./activities.ts"; import { createWorkbenchDispatcher } from "./dispatcher.ts"; import { createCloudWorkbenchApplication } from "./cloud-application.ts"; import { createWorkbenchHttpApp } from "./http.ts"; +import { workbenchRuntime } from "./runtime.ts"; import { runWorkbenchCli } from "../../tools/src/workbench-cli.ts"; +test("temporal API runtime does not require worker Kafka publisher configuration", async () => { + const runtime = workbenchRuntime({ + WORKBENCH_MODE: "temporal", + WORKBENCH_CLOUD_API_URL: "http://cloud.internal", + WORKBENCH_CLOUD_API_AUTHORIZATION: "internal-key", + WORKBENCH_TEMPORAL_ADDRESS: "127.0.0.1:7233", + WORKBENCH_TEMPORAL_NAMESPACE: "unidesk", + WORKBENCH_TEMPORAL_TASK_QUEUE: "hwlab-v03-workbench", + WORKBENCH_ACTIVITY_START_TO_CLOSE_TIMEOUT_MS: "30000", + WORKBENCH_ACTIVITY_RETRY_INITIAL_INTERVAL_MS: "1000", + WORKBENCH_ACTIVITY_RETRY_MAXIMUM_INTERVAL_MS: "30000", + WORKBENCH_ACTIVITY_RETRY_MAXIMUM_ATTEMPTS: "5" + }, { eventPublisher: null }); + expect(runtime.eventPublisher).toBeNull(); + await runtime.close(); +}); + describe("Workbench dispatcher", () => { test("submits through Temporal without synthesizing terminal state", async () => { const calls: string[] = [];