diff --git a/internal/dev-entrypoint/cloud-web-routes.mjs b/internal/dev-entrypoint/cloud-web-routes.mjs index 1fbb4eb5..95378f99 100644 --- a/internal/dev-entrypoint/cloud-web-routes.mjs +++ b/internal/dev-entrypoint/cloud-web-routes.mjs @@ -8,6 +8,7 @@ const POST_PROXY_ROUTES = new Set([ "/v1/agent/chat/cancel", "/v1/agent/chat/steer", "/v1/agent/sessions", + "/v1/workbench/commands", "/v1/workbench/launches", "/v1/hwpod-node-ops", "/v1/web-performance", diff --git a/internal/dev-entrypoint/cloud-web-routes.test.mjs b/internal/dev-entrypoint/cloud-web-routes.test.mjs index f88d0257..2d5b8067 100644 --- a/internal/dev-entrypoint/cloud-web-routes.test.mjs +++ b/internal/dev-entrypoint/cloud-web-routes.test.mjs @@ -236,3 +236,12 @@ test("cloud web proxies authenticated Workbench launch writes to cloud-api", () routeKey: "POST /v1/workbench/launches" }); }); + +test("cloud web proxies authenticated Workbench commands to cloud-api", () => { + assert.deepEqual(cloudWebProxyRoutePolicy("POST", "/v1/workbench/commands"), { + proxy: true, + authRequired: true, + publicRoute: false, + routeKey: "POST /v1/workbench/commands" + }); +}); diff --git a/internal/dev-entrypoint/cloud-web-runtime.test.mjs b/internal/dev-entrypoint/cloud-web-runtime.test.mjs index f2924882..ba027e7b 100644 --- a/internal/dev-entrypoint/cloud-web-runtime.test.mjs +++ b/internal/dev-entrypoint/cloud-web-runtime.test.mjs @@ -105,7 +105,7 @@ test("cloud web auth requests are proxied once", async () => { } }); -test("cloud web proxies Workbench launches with trace context", async () => { +test("cloud web proxies Workbench writes with trace context", async () => { const upstreamRequests = []; const upstream = createServer(async (request, response) => { let body = ""; @@ -145,27 +145,29 @@ test("cloud web proxies Workbench launches with trace context", async () => { try { const body = JSON.stringify({ projectId: "project_d601", taskRef: "task_2136" }); - const response = await fetch(`${serverUrl(cloudWeb)}/v1/workbench/launches`, { + for (const route of ["/v1/workbench/launches", "/v1/workbench/commands"]) { + const response = await fetch(`${serverUrl(cloudWeb)}${route}`, { + method: "POST", + headers: { + "content-type": "application/json", + cookie: "hwlab_session=session-launch", + traceparent: "00-11111111111111111111111111111111-2222222222222222-01", + "x-hwlab-otel-trace-id": "11111111111111111111111111111111" + }, + body + }); + assert.equal(response.status, 404); + assert.equal(response.headers.get("x-hwlab-otel-trace-id"), "11111111111111111111111111111111"); + assert.deepEqual(await response.json(), { error: "not_found" }); + } + assert.deepEqual(upstreamRequests, ["/v1/workbench/launches", "/v1/workbench/commands"].map((url) => ({ method: "POST", - headers: { - "content-type": "application/json", - cookie: "hwlab_session=session-launch", - traceparent: "00-11111111111111111111111111111111-2222222222222222-01", - "x-hwlab-otel-trace-id": "11111111111111111111111111111111" - }, - body - }); - assert.equal(response.status, 404); - assert.equal(response.headers.get("x-hwlab-otel-trace-id"), "11111111111111111111111111111111"); - assert.deepEqual(await response.json(), { error: "not_found" }); - assert.deepEqual(upstreamRequests, [{ - method: "POST", - url: "/v1/workbench/launches", + url, cookie: "hwlab_session=session-launch", traceparent: "00-11111111111111111111111111111111-2222222222222222-01", otelTraceId: "11111111111111111111111111111111", body - }]); + }))); } finally { await close(cloudWeb); await close(upstream);