import type { WorkbenchApplication } from "./contracts.ts"; export function createCloudWorkbenchApplication(options: { baseUrl: string; authorization: string; fetchImpl?: typeof fetch; }): WorkbenchApplication { if (!options.baseUrl) throw codedError("workbench_cloud_api_url_required", "WORKBENCH_CLOUD_API_URL is required"); if (!options.authorization) throw codedError("workbench_cloud_api_auth_required", "WORKBENCH_CLOUD_API_AUTHORIZATION is required"); const fetchImpl = options.fetchImpl ?? fetch; const request = async (method: string, route: string, body: Record | undefined, actor: { id: string; role?: string | null }) => { const response = await fetchImpl(`${options.baseUrl.replace(/\/$/u, "")}${route}`, { method, headers: { authorization: options.authorization, "content-type": "application/json", "x-workbench-activity-dispatch": "1", "x-hwlab-actor-id": actor.id, "x-hwlab-actor-role": actor.role ?? "user" }, body: body ? JSON.stringify(body) : undefined }); const payload = await response.json().catch(() => null) as Record | null; if (!response.ok || !payload) throw codedError(String((payload?.error as any)?.code ?? "workbench_cloud_api_failed"), String((payload?.error as any)?.message ?? `Cloud API returned ${response.status}`), { status: response.status, route }); return payload; }; return { async health() { return { serviceId: "hwlab-workbench", status: "ready", cloudApi: "configured" }; }, async createSession(input) { return request("POST", "/v1/agent/sessions", input.params, input.actor); }, async admitTurn(input) { await request("POST", "/v1/internal/workbench/admit", { ...input.params, traceId: input.traceId, sessionId: input.sessionId }, input.actor); return input; }, async dispatchTurn(input) { return request("POST", "/v1/agent/chat", { ...input.params, traceId: input.traceId, sessionId: input.sessionId, shortConnection: true }, input.actor); }, async cancelTurn(input) { return request("POST", "/v1/agent/chat/cancel", { ...input.params, traceId: input.traceId }, input.actor); } }; } function codedError(code: string, message: string, details?: unknown) { return Object.assign(new Error(message), { code, details }); }