From f8a090b66616e1c647f8bab22bffd706860a41b7 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 1 Jun 2026 21:37:17 +0800 Subject: [PATCH] fix(workbench): proxy workspace writes through cloud web --- internal/dev-entrypoint/cloud-web-routes.mjs | 15 ++++++++- .../dev-entrypoint/cloud-web-routes.test.mjs | 33 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/internal/dev-entrypoint/cloud-web-routes.mjs b/internal/dev-entrypoint/cloud-web-routes.mjs index 1428afcf..575eeb17 100644 --- a/internal/dev-entrypoint/cloud-web-routes.mjs +++ b/internal/dev-entrypoint/cloud-web-routes.mjs @@ -42,7 +42,12 @@ export function isCloudApiProxyRoute(method, pathname) { GET_PROXY_PREFIXES.some((prefix) => normalizedPath.startsWith(prefix)); } if (normalizedMethod === "POST") { - return POST_PROXY_ROUTES.has(normalizedPath) || isDevicePodPostProxyRoute(normalizedPath); + return POST_PROXY_ROUTES.has(normalizedPath) || + isDevicePodPostProxyRoute(normalizedPath) || + isWorkbenchWorkspaceWriteProxyRoute(normalizedMethod, normalizedPath); + } + if (normalizedMethod === "PATCH" || normalizedMethod === "PUT") { + return isWorkbenchWorkspaceWriteProxyRoute(normalizedMethod, normalizedPath); } return false; } @@ -56,6 +61,14 @@ function isDevicePodPostProxyRoute(pathname) { return false; } +function isWorkbenchWorkspaceWriteProxyRoute(method, pathname) { + const parts = pathname.split("/").filter(Boolean); + if (parts.length < 4 || parts[0] !== "v1" || parts[1] !== "workbench" || parts[2] !== "workspace") return false; + if ((method === "PATCH" || method === "PUT") && parts.length === 4) return true; + if (method === "POST" && parts.length === 5) return parts[4] === "select-conversation" || parts[4] === "reset"; + return false; +} + function isPublicCodeAgentPollRoute(method, pathname) { return method === "GET" && ( pathname.startsWith("/v1/agent/chat/result/") || diff --git a/internal/dev-entrypoint/cloud-web-routes.test.mjs b/internal/dev-entrypoint/cloud-web-routes.test.mjs index f9c0224c..5c995778 100644 --- a/internal/dev-entrypoint/cloud-web-routes.test.mjs +++ b/internal/dev-entrypoint/cloud-web-routes.test.mjs @@ -56,3 +56,36 @@ test("cloud web proxies only supported authenticated device-pod write routes", ( routeKey: "POST /v1/device-pods/D601-F103-V2/jobs/job_1/output" }); }); + +test("cloud web proxies authenticated account workbench write routes", () => { + assert.deepEqual(cloudWebProxyRoutePolicy("PATCH", "/v1/workbench/workspace/ws_default"), { + proxy: true, + authRequired: true, + publicRoute: false, + routeKey: "PATCH /v1/workbench/workspace/ws_default" + }); + assert.deepEqual(cloudWebProxyRoutePolicy("PUT", "/v1/workbench/workspace/ws_default"), { + proxy: true, + authRequired: true, + publicRoute: false, + routeKey: "PUT /v1/workbench/workspace/ws_default" + }); + assert.deepEqual(cloudWebProxyRoutePolicy("POST", "/v1/workbench/workspace/ws_default/select-conversation"), { + proxy: true, + authRequired: true, + publicRoute: false, + routeKey: "POST /v1/workbench/workspace/ws_default/select-conversation" + }); + assert.deepEqual(cloudWebProxyRoutePolicy("POST", "/v1/workbench/workspace/ws_default/reset"), { + proxy: true, + authRequired: true, + publicRoute: false, + routeKey: "POST /v1/workbench/workspace/ws_default/reset" + }); + assert.deepEqual(cloudWebProxyRoutePolicy("POST", "/v1/workbench/workspace/ws_default/events"), { + proxy: false, + authRequired: false, + publicRoute: false, + routeKey: "POST /v1/workbench/workspace/ws_default/events" + }); +});