52 lines
3.5 KiB
TypeScript
52 lines
3.5 KiB
TypeScript
import path from "node:path";
|
|
|
|
import { createCloudWorkbenchApplication } from "./cloud-application.ts";
|
|
import { createWorkbenchDispatcher } from "./dispatcher.ts";
|
|
import { createNativeTestWorkbenchApplication } from "./native-application.ts";
|
|
import { createNativeAgentRunWorkbenchApplication } from "./native-agentrun-application.ts";
|
|
import { createNativeTestTemporalGateway } from "./native-temporal.ts";
|
|
import { createWorkbenchTemporalGateway } from "./temporal.ts";
|
|
import { createWorkbenchKafkaEventPublisher } from "./kafka-event-publisher.ts";
|
|
import type { WorkbenchEventPublisher } from "./contracts.ts";
|
|
|
|
export function workbenchRuntime(env: Record<string, string | undefined> = 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
|
|
: Object.hasOwn(options, "eventPublisher")
|
|
? options.eventPublisher ?? null
|
|
: createWorkbenchKafkaEventPublisher({ env });
|
|
const application = mode === "native-test"
|
|
? createNativeTestWorkbenchApplication({ stateFile })
|
|
: mode === "agentrun-native"
|
|
? createNativeAgentRunWorkbenchApplication({ stateFile, env, eventPublisher })
|
|
: createCloudWorkbenchApplication({ baseUrl: String(env.WORKBENCH_CLOUD_API_URL ?? ""), authorization: String(env.WORKBENCH_CLOUD_API_AUTHORIZATION ?? ""), eventPublisher });
|
|
const temporalAddress = String(env.WORKBENCH_TEMPORAL_ADDRESS ?? env.TEMPORAL_ADDRESS ?? "");
|
|
const temporalNamespace = String(env.WORKBENCH_TEMPORAL_NAMESPACE ?? "unidesk");
|
|
const taskQueue = String(env.WORKBENCH_TEMPORAL_TASK_QUEUE ?? "hwlab-v03-workbench");
|
|
const activity = mode === "native-test" ? null : {
|
|
startToCloseTimeoutMs: requiredPositiveInteger(env.WORKBENCH_ACTIVITY_START_TO_CLOSE_TIMEOUT_MS, "WORKBENCH_ACTIVITY_START_TO_CLOSE_TIMEOUT_MS"),
|
|
retryInitialIntervalMs: requiredPositiveInteger(env.WORKBENCH_ACTIVITY_RETRY_INITIAL_INTERVAL_MS, "WORKBENCH_ACTIVITY_RETRY_INITIAL_INTERVAL_MS"),
|
|
retryMaximumIntervalMs: requiredPositiveInteger(env.WORKBENCH_ACTIVITY_RETRY_MAXIMUM_INTERVAL_MS, "WORKBENCH_ACTIVITY_RETRY_MAXIMUM_INTERVAL_MS"),
|
|
retryMaximumAttempts: requiredPositiveInteger(env.WORKBENCH_ACTIVITY_RETRY_MAXIMUM_ATTEMPTS, "WORKBENCH_ACTIVITY_RETRY_MAXIMUM_ATTEMPTS")
|
|
};
|
|
const temporal = mode === "native-test" ? createNativeTestTemporalGateway(application) : createWorkbenchTemporalGateway({ address: temporalAddress, namespace: temporalNamespace, taskQueue, activity: activity! });
|
|
return {
|
|
mode,
|
|
stateFile,
|
|
temporalAddress,
|
|
temporalNamespace,
|
|
taskQueue, activity,
|
|
eventPublisher,
|
|
application,
|
|
temporal,
|
|
dispatch: createWorkbenchDispatcher({ application, temporal, mode }),
|
|
async close() { await temporal.close(); await application.close?.(); }
|
|
};
|
|
}
|
|
|
|
function codedError(code: string, message: string) { return Object.assign(new Error(message), { code }); }
|
|
function requiredPositiveInteger(value: string | undefined, name: string) { const parsed = Number.parseInt(String(value ?? ""), 10); if (!Number.isSafeInteger(parsed) || parsed <= 0) throw codedError("workbench_temporal_config_invalid", `${name} must be a positive integer`); return parsed; }
|