From 81d7f660f70c09ba290f86e0b1443cfbba4f1b2d Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Sat, 19 Sep 2026 14:20:44 -0400 Subject: [PATCH] =?UTF-8?q?=E2=8F=B1=EF=B8=8F=20feat:=20Advertise=20Worksp?= =?UTF-8?q?ace=20Command=20Timeout=20Ceiling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code/src/protocol.ts | 2 ++ service/src/bridge/index.ts | 1 + service/src/bridge/router.test.ts | 54 ++++++++++++++++++++++++++++++- service/src/bridge/router.ts | 15 +++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/packages/code/src/protocol.ts b/packages/code/src/protocol.ts index c5353ae2..27220735 100644 --- a/packages/code/src/protocol.ts +++ b/packages/code/src/protocol.ts @@ -712,6 +712,8 @@ export interface BridgeWorkerStatusResponse { online: boolean; ready: boolean; leaseExpiresInMs?: number; + /** Server-owned execution ceiling for workspace commands. Omitted by legacy servers. */ + maxCommandTimeoutMs?: number; capabilities?: BridgeWorkerCapabilities; } diff --git a/service/src/bridge/index.ts b/service/src/bridge/index.ts index a1ec5d78..16857fad 100644 --- a/service/src/bridge/index.ts +++ b/service/src/bridge/index.ts @@ -21,4 +21,5 @@ export default createBridgeRouter({ adminToken: env.BRIDGE_TOKEN, configuredWorkerId: env.BRIDGE_WORKER_ID, allowDynamicWorkers: env.BRIDGE_DYNAMIC_WORKERS, + maxCommandTimeoutMs: env.JOB_TIMEOUT, }); diff --git a/service/src/bridge/router.test.ts b/service/src/bridge/router.test.ts index af0e765c..63640111 100644 --- a/service/src/bridge/router.test.ts +++ b/service/src/bridge/router.test.ts @@ -10,7 +10,10 @@ import { createBridgeIdentity, signBridgeRequest, } from '../../../packages/code/src/identity'; -import { BRIDGE_PROTOCOL_VERSION } from '../../../packages/code/src/protocol'; +import { + BRIDGE_PROTOCOL_VERSION, + BRIDGE_WORKSPACE_COMMAND_MAX_TIMEOUT_MS, +} from '../../../packages/code/src/protocol'; import { RedisBridgePairingStore } from './pairing'; import { createBridgeRouter } from './router'; import { RedisBridgeStore } from './store'; @@ -115,6 +118,55 @@ describe('paired bridge HTTP API', () => { expect(unauthorized.status).toBe(401); }); + test('advertises the effective server command timeout for command-capable workers', async () => { + const store = new RedisBridgeStore(redis); + const app = express(); + app.use(json()); + app.use( + '/v1/bridge', + createBridgeRouter({ + store, + pairings: new RedisBridgePairingStore(redis), + authMode: 'static', + adminToken: 'strong-administrator-bootstrap-token', + configuredWorkerId: 'command-worker', + maxCommandTimeoutMs: 900_000, + }), + ); + server = createServer(app); + await new Promise((resolve) => server?.listen(0, '127.0.0.1', resolve)); + const address = server.address(); + if (address == null || typeof address === 'string') { + throw new Error('Expected TCP listener'); + } + await store.register({ + protocolVersion: BRIDGE_PROTOCOL_VERSION, + workerId: 'command-worker', + incarnationId: 'incarnation-00000001', + capabilities: { + statefulWorkspace: false, + sandboxProfile: 'native-srt', + runtimes: [], + workspaceTools: { + protocolVersion: BRIDGE_PROTOCOL_VERSION, + operations: ['execute_command'], + workspaces: [{ id: 'primary' }], + }, + }, + }); + + const response = await fetch( + `http://127.0.0.1:${address.port}/v1/bridge/workers/command-worker/status`, + { headers: { Authorization: 'Bearer strong-administrator-bootstrap-token' } }, + ); + + expect(response.status).toBe(200); + await expect(response.json()).resolves.toMatchObject({ + workerId: 'command-worker', + maxCommandTimeoutMs: BRIDGE_WORKSPACE_COMMAND_MAX_TIMEOUT_MS, + }); + }); + test('rejects a malformed optional binding for a configured worker', async () => { const app = express(); app.use(json()); diff --git a/service/src/bridge/router.ts b/service/src/bridge/router.ts index 369b306c..73870772 100644 --- a/service/src/bridge/router.ts +++ b/service/src/bridge/router.ts @@ -7,6 +7,7 @@ import type { BridgePrincipalType, BridgeWorkerBinding } from './pairing'; import type { CodeBridgeAssignment, CodeBridgeSettlement } from './store'; import { + BRIDGE_WORKSPACE_COMMAND_MAX_TIMEOUT_MS, BRIDGE_PROTOCOL_VERSION, isValidBridgeWorkerCapabilities, isValidBridgeWorkerId, @@ -36,6 +37,7 @@ export interface BridgeRouterOptions { adminToken: string; configuredWorkerId?: string; allowDynamicWorkers?: boolean; + maxCommandTimeoutMs?: number; } function sameToken(left: string, right: string): boolean { @@ -132,6 +134,16 @@ function isSettlement(value: unknown): value is CodeBridgeSettlement { export function createBridgeRouter(options: BridgeRouterOptions): Router { const router = Router(); if (options.enabled === false) return router; + if ( + options.maxCommandTimeoutMs !== undefined && + (!Number.isSafeInteger(options.maxCommandTimeoutMs) || options.maxCommandTimeoutMs < 1) + ) { + throw new RangeError('Workspace command timeout must be a positive safe integer'); + } + const maxCommandTimeoutMs = + options.maxCommandTimeoutMs == null + ? undefined + : Math.min(options.maxCommandTimeoutMs, BRIDGE_WORKSPACE_COMMAND_MAX_TIMEOUT_MS); const configuredWorker = (workerId: string): boolean => options.allowDynamicWorkers === true || @@ -324,10 +336,13 @@ export function createBridgeRouter(options: BridgeRouterOptions): Router { return; } const status = await options.store.workerStatus(workerId); + const supportsCommands = + status.capabilities?.workspaceTools?.operations.includes('execute_command') === true; res.json({ protocolVersion: BRIDGE_PROTOCOL_VERSION, workerId, ...status, + ...(supportsCommands && maxCommandTimeoutMs != null ? { maxCommandTimeoutMs } : {}), }); }), );