feat(toolbridge): integrate upstream SDK#1
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the tool synchronization and invocation logic to use the new 'tool-bridge' Host and Admin SDKs, replacing the previous direct KV-based tree synchronization. It introduces a new '/htbp/platform/toolbridge' endpoint for administrative actions, adds CLI support for calling toolbridge admin methods, and updates the gateway and tests accordingly. Feedback on these changes highlights a potential runtime 'TypeError' in 'convertToolBridgeAdminError' when handling nullish errors, recommends adding an early credential check in 'syncToolBridgeMounts' to prevent unnecessary database queries, and suggests explicitly returning JSON-serializable objects instead of 'undefined' from administrative delete operations.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| export function convertToolBridgeAdminError(error: unknown): WattError { | ||
| if (isWattError(error)) return error; | ||
| const e = error as { status?: number; code?: string; message?: string; retryable?: boolean }; | ||
| const code = | ||
| e.status === 400 | ||
| ? 'invalid_argument' | ||
| : e.status === 401 | ||
| ? 'permission_denied' | ||
| : e.status === 403 | ||
| ? 'permission_denied' | ||
| : e.status === 404 | ||
| ? 'not_found' | ||
| : e.status === 502 || e.status === 503 | ||
| ? 'unavailable' | ||
| : 'internal'; | ||
| return wattError(code, e.message ?? String(error), e.retryable === true); | ||
| } |
There was a problem hiding this comment.
The convertToolBridgeAdminError function casts error to an object type and accesses its properties (like status, message, and retryable) without checking if error is nullish. If error is null or undefined, this will throw a TypeError at runtime. We should safely guard against nullish values before accessing these properties.
| export function convertToolBridgeAdminError(error: unknown): WattError { | |
| if (isWattError(error)) return error; | |
| const e = error as { status?: number; code?: string; message?: string; retryable?: boolean }; | |
| const code = | |
| e.status === 400 | |
| ? 'invalid_argument' | |
| : e.status === 401 | |
| ? 'permission_denied' | |
| : e.status === 403 | |
| ? 'permission_denied' | |
| : e.status === 404 | |
| ? 'not_found' | |
| : e.status === 502 || e.status === 503 | |
| ? 'unavailable' | |
| : 'internal'; | |
| return wattError(code, e.message ?? String(error), e.retryable === true); | |
| } | |
| export function convertToolBridgeAdminError(error: unknown): WattError { | |
| if (isWattError(error)) return error; | |
| const e = (error && typeof error === 'object') ? (error as { status?: number; code?: string; message?: string; retryable?: boolean }) : {}; | |
| const code = | |
| e.status === 400 | |
| ? 'invalid_argument' | |
| : e.status === 401 | |
| ? 'permission_denied' | |
| : e.status === 403 | |
| ? 'permission_denied' | |
| : e.status === 404 | |
| ? 'not_found' | |
| : e.status === 502 || e.status === 503 | |
| ? 'unavailable' | |
| : 'internal'; | |
| return wattError(code, e.message ?? String(error), e.retryable === true); | |
| } |
| async function syncToolBridgeMounts(env: Bindings): Promise<WattError | undefined> { | ||
| const registry = new ToolRegistry(env.DB_PROVIDERS); | ||
| const page = await registry.list({ limit: 200 }); |
There was a problem hiding this comment.
The syncToolBridgeMounts function does not check if hostCredential(env) is configured before proceeding to query the database and call the Tool Bridge SDK. If the key is missing, the SDK calls will fail with unauthenticated errors. Checking for the credential early allows us to return a clear, friendly 'unavailable' error and avoid unnecessary database queries.
| async function syncToolBridgeMounts(env: Bindings): Promise<WattError | undefined> { | |
| const registry = new ToolRegistry(env.DB_PROVIDERS); | |
| const page = await registry.list({ limit: 200 }); | |
| async function syncToolBridgeMounts(env: Bindings): Promise<WattError | undefined> { | |
| if (!hostCredential(env)) { | |
| return wattError('unavailable', 'Tool Bridge key is not configured', false); | |
| } | |
| const registry = new ToolRegistry(env.DB_PROVIDERS); | |
| const page = await registry.list({ limit: 200 }); |
| case 'ProvidersDelete': | ||
| return admin.providers.delete(str(args, 'id')); |
There was a problem hiding this comment.
The delete operations in executeToolBridgeAdmin (such as ProvidersDelete, PublicationsDelete, PlacementsDelete, CommandPoliciesDelete, and ServersDelete) directly return the promise of the SDK delete call, which typically resolves to void (undefined). Returning undefined to Hono's c.json() can cause issues or result in invalid JSON responses. It is safer to explicitly return an object like { deleted: true }.
| case 'ProvidersDelete': | |
| return admin.providers.delete(str(args, 'id')); | |
| case 'ProvidersDelete': | |
| await admin.providers.delete(str(args, 'id')); | |
| return { deleted: true }; |
a132358 to
9f0e4b6
Compare
|
CI currently fails during This branch configures CI/release to use |
9f0e4b6 to
0881741
Compare
0881741 to
aeb1064
Compare
Summary
tool-bridgeSDK worker bridgemounts.sync,tree.help,tree.call)/htbp/platform/toolbridgeand CLIwatt toolbridge callfor Admin SDK coverage across providers, publications, placements, hosts, endpoints, command policies, audit, servers, bridge, and tree operationsWATT_TOOLBRIDGE_KEY, with split host/admin keys remaining optional overridesValidation
pnpm exec biome check ...on touched filespnpm --filter @watt/gateway typecheckpnpm --filter @tokenroll/watt typecheckpnpm --filter watt-toolbridge typecheckpnpm exec tsc --noEmit -p scripts/tsconfig.jsonpnpm --filter @watt/gateway exec vitest run test/tools-proxy.test.ts test/htbp-tools.test.ts test/platform-toolbridge.test.tspnpm --filter @tokenroll/watt testpnpm --filter watt-toolbridge testpnpm --filter @watt/gateway test