Skip to content

feat(toolbridge): integrate upstream SDK#1

Open
evilstar9527 wants to merge 1 commit into
mainfrom
feat/toolbridge-sdk-integration
Open

feat(toolbridge): integrate upstream SDK#1
evilstar9527 wants to merge 1 commit into
mainfrom
feat/toolbridge-sdk-integration

Conversation

@evilstar9527

Copy link
Copy Markdown

Summary

  • replace the vendored Tool Bridge worker entry with the upstream tool-bridge SDK worker bridge
  • route Watt tool execution through the Tool Bridge Host SDK (mounts.sync, tree.help, tree.call)
  • add /htbp/platform/toolbridge and CLI watt toolbridge call for Admin SDK coverage across providers, publications, placements, hosts, endpoints, command policies, audit, servers, bridge, and tree operations
  • simplify runtime config to a single required WATT_TOOLBRIDGE_KEY, with split host/admin keys remaining optional overrides

Validation

  • pnpm exec biome check ... on touched files
  • pnpm --filter @watt/gateway typecheck
  • pnpm --filter @tokenroll/watt typecheck
  • pnpm --filter watt-toolbridge typecheck
  • pnpm exec tsc --noEmit -p scripts/tsconfig.json
  • pnpm --filter @watt/gateway exec vitest run test/tools-proxy.test.ts test/htbp-tools.test.ts test/platform-toolbridge.test.ts
  • pnpm --filter @tokenroll/watt test
  • pnpm --filter watt-toolbridge test
  • pnpm --filter @watt/gateway test

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +89 to +105
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);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

Suggested change
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);
}

Comment on lines +176 to +178
async function syncToolBridgeMounts(env: Bindings): Promise<WattError | undefined> {
const registry = new ToolRegistry(env.DB_PROVIDERS);
const page = await registry.list({ limit: 200 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

Suggested change
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 });

Comment on lines +136 to +137
case 'ProvidersDelete':
return admin.providers.delete(str(args, 'id'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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 }.

Suggested change
case 'ProvidersDelete':
return admin.providers.delete(str(args, 'id'));
case 'ProvidersDelete':
await admin.providers.delete(str(args, 'id'));
return { deleted: true };

@evilstar9527 evilstar9527 force-pushed the feat/toolbridge-sdk-integration branch 2 times, most recently from a132358 to 9f0e4b6 Compare July 5, 2026 05:17
@evilstar9527

Copy link
Copy Markdown
Author

CI currently fails during pnpm install --frozen-lockfile because tool-bridge is resolved from TokenRollAI/tool-bridge and the Watt repo GITHUB_TOKEN cannot read that private repository.

This branch configures CI/release to use secrets.TOOL_BRIDGE_READ_TOKEN for GitHub git dependencies, falling back to github.token. To make CI green, configure TOOL_BRIDGE_READ_TOKEN with read access to TokenRollAI/tool-bridge, or publish tool-bridge to a package registry and replace the git dependency.

@evilstar9527 evilstar9527 force-pushed the feat/toolbridge-sdk-integration branch from 9f0e4b6 to 0881741 Compare July 5, 2026 08:54
@evilstar9527 evilstar9527 force-pushed the feat/toolbridge-sdk-integration branch from 0881741 to aeb1064 Compare July 5, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant