npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

toolplane-typescript-client

v0.1.0

Published

TypeScript gRPC client for the Toolplane control plane

Readme

Toolplane TypeScript Client

This package is the maintained JavaScript-family SDK for Toolplane's durable remote tool-execution control plane. Use it when TypeScript or Node code needs the maintained gRPC control-plane surface plus an explicit provider runtime over the canonical contract in server/proto/service.proto.

Decision Rule

Use Toolplane when one remote tool may outlive the caller, needs inspection or bounded replay after disconnect, needs explicit provider ownership or drain behavior, or is queue-backed enough that request lifecycle control matters. If the work is quick, in-process, same-lifecycle, and not operationally sensitive, direct tool calling is simpler.

A concrete first-offload workload is one sandboxed code-execution worker. TypeScript is the maintained JavaScript-family path for that provider or consumer lifecycle on gRPC; the repository-internal HTTP adapters remain conformance-only.

When To Start Here

  • Your JavaScript-family code needs the maintained gRPC control-plane surface plus an explicit ProviderRuntime.
  • You want a maintained provider or consumer path in TypeScript without treating the internal HTTP conformance adapters as public SDK surface.
  • You want the same provider, request, recovery, and drain model as the broader platform story, but on the TypeScript-maintained path.

Support Status

  • Supported secondary SDK and the maintained JavaScript-family path.
  • The maintained control-plane story is the gRPC surface for session, tool, machine, request, and task lifecycle helpers.
  • This SDK now ships a maintained explicit ProviderRuntime for the gRPC provider lifecycle: session create or attach, machine registration, request claim, heartbeat, chunk append, result submission, and drain-aware shutdown.
  • Repository-internal HTTP adapters still exist under tests/conformance/ so the shared fixture runner can exercise the maintained HTTP gateway. They are not part of the public SDK surface.

Integration Seam Role

This package spans two layers of the maintained agent-runtime seam:

  • Layer 2: the maintained JavaScript-family gRPC projection for session, tool, machine, request, and task lifecycle helpers.
  • Layer 3: the explicit ProviderRuntime packaging for session attach or create, machine registration, tool registration, polling, claim, heartbeat, chunk append, result submission, and drain.

Build foreign-protocol adapters on top of these surfaces instead of reimplementing claim, heartbeat, or drain logic in the adapter itself. Retained-window recovery is available through the public resumeStream() and getRequestChunksWindow() wrappers; capabilities outside the mapped RPC set stay server-side. For the full seam model and current gap caveats, see server/docs/agent-runtime-integration-seam.md.

Features

  • Live grpc-js wrappers for the maintained public helpers.
  • Explicit ProviderRuntime lifecycle management for machine-backed providers.
  • Public executeTool() plus numeric convenience helpers add(), subtract(), multiply(), and divide().
  • Tool discovery helpers listTools(), getToolById(), getToolByName(), and deleteTool().
  • Session, API-key, machine, request, and task lifecycle helpers, including provider-owned request claim and result submission.
  • Promise-based connection management with connect(), disconnect(), isConnected(), and getConnectionStatus().
  • Shared-fixture conformance coverage in tests/conformance/.

Installation

npm install
npm run build

Canonical Flow

The canonical end-to-end path for Toolplane is to offload one painful remote tool first: register a provider, create or attach a session, execute a request, stream or recover results, and drain the machine. The TypeScript SDK ships that provider loop directly through the explicit ProviderRuntime over the maintained gRPC path.

Quick Start

import { ToolplaneClient } from 'toolplane-typescript-client';

const client = ToolplaneClient.createGRPCClient(
  'localhost',
  9001,
  'grpc-session',
  'grpc-user',
  process.env.TOOLPLANE_API_KEY || 'toolplane-conformance-fixture-key',
  {
    enabled: true,
    caCertPath: '../../server/deploy/reference/certs/ca.crt',
    serverName: 'localhost',
  },
);

await client.connect();

const session = await client.createSession(
  'My Session',
  'Session created from the TypeScript client',
  'examples',
);

const machine = await client.registerMachine('', '1.0.0', [
  {
    sessionId: session.id,
    name: 'session_status',
    description: 'Report session context for a connected operator or automation client',
    schema: JSON.stringify({
      type: 'object',
      properties: {
        requester: { type: 'string' },
      },
      required: ['requester'],
    }),
    config: { version: '1.0' },
    tags: ['session', 'status'],
  },
]);

const tools = await client.listTools();
console.log(`Session ${session.id} has ${tools.length} tools on machine ${machine.id}`);

await client.disconnect();

Tool registration is machine-aware, so register a machine first or embed tool definitions in registerMachine(...).

Explicit Provider Runtime

import { ToolplaneClient } from 'toolplane-typescript-client';

const client = ToolplaneClient.createGRPCClient(
  'localhost',
  9001,
  '',
  'provider-user',
  process.env.TOOLPLANE_API_KEY || 'toolplane-conformance-fixture-key',
  {
    enabled: true,
    caCertPath: '../../server/deploy/reference/certs/ca.crt',
    serverName: 'localhost',
  },
);

await client.connect();

const provider = client.providerRuntime({
  pollIntervalMs: 250,
  heartbeatIntervalMs: 30_000,
});

const session = await provider.createSession({
  name: 'TypeScript Provider Session',
  description: 'Maintained provider runtime example',
  namespace: 'examples',
});

await provider.tool(
  {
    sessionId: session.id,
    name: 'echo_tool',
    description: 'Echo the caller message',
    schema: {
      type: 'object',
      properties: {
        message: { type: 'string' },
      },
      required: ['message'],
    },
  },
  async (input) => ({ echo: input.message }),
);

await provider.startInBackground();

See src/examples/provider_runtime_example.ts for a maintained end-to-end provider loop with graceful drain.

Public API Snapshot

Lifecycle

connect(): Promise<void>
disconnect(): Promise<void>
isConnected(): boolean
getConnectionStatus(): ConnectionStatus
providerRuntime(options?: ProviderRuntimeOptions): ProviderRuntime

Execution

executeTool(toolName: string, params?: Record<string, unknown>): Promise<Request>
add(a: number, b: number): Promise<number>
subtract(a: number, b: number): Promise<number>
multiply(a: number, b: number): Promise<number>
divide(a: number, b: number): Promise<number>
ping(): Promise<string>

These helpers use the live request lifecycle on the Go server. They require a registered machine-backed provider to claim requests and submit results.

Lifecycle Wrappers

The client exposes public wrappers for:

  • Sessions: createSession, getSession, listSessions, updateSession
  • API keys: createApiKey, listApiKeys, revokeApiKey
  • Tools: registerTool, listTools, getToolById, getToolByName, deleteTool
  • Machines: registerMachine, listMachines, getMachine, updateMachinePing, unregisterMachine, drainMachine
  • Requests: createRequest, getRequest, listRequests, updateRequest, claimRequest, appendRequestChunks, submitRequestResult, renewRequestLease, cancelRequest, resumeStream, getRequestChunksWindow
  • Tasks: createTask, getTask, listTasks, cancelTask

Provider Runtime

The explicit ProviderRuntime exposes:

  • Session ownership: createSession(), attachSession(), managedSessionIds()
  • Tool registration: registerTool(), tool()
  • Runtime control: pollOnce(), startInBackground(), runForever(), stop(), drain(), close()

For the reference deployment, set TOOLPLANE_SERVER_PORT=9001, TOOLPLANE_USE_TLS=true, TOOLPLANE_TLS_CA_CERT_PATH=/path/to/ca.crt, and TOOLPLANE_TLS_SERVER_NAME=localhost before running the maintained examples.

ToolplaneClient

Public methods parsed from src/core/toolplane_client.ts:

| Method | Returns | | --- | --- | | async connect() | Promise<void> | | async disconnect() | Promise<void> | | isConnected() | boolean | | getConnectionStatus() | ConnectionStatus | | async executeTool(toolName: string, params: Record<string, unknown> = {}, options: { idempotencyKey?: string } = {}) | Promise<RequestModel> | | async ping() | Promise<string> | | async registerTool(name: string, description: string, schema: string, config: Record<string, string> = {}, tags: string[] = [], options: RegisterToolOptions = {}) | Promise<Tool> | | async listTools() | Promise<Tool[]> | | async getToolById(toolId: string) | Promise<Tool> | | async getToolByName(toolName: string) | Promise<Tool> | | async deleteTool(toolId: string) | Promise<boolean> | | async createSession(name: string, description: string, namespace: string = 'default', requestedSessionId: string = '') | Promise<Session> | | async getSession() | Promise<Session> | | async listSessions() | Promise<Session[]> | | async updateSession(name: string = '', description: string = '', namespace: string = '') | Promise<Session> | | async createApiKey(name: string, capabilities: string[]) | Promise<ApiKey> | | async listApiKeys() | Promise<ApiKey[]> | | async revokeApiKey(keyId: string) | Promise<boolean> | | async registerMachine(machineId: string = '', sdkVersion: string = '1.0.0', tools: RegisterToolRequest[] = []) | Promise<Machine> | | async listMachines() | Promise<Machine[]> | | async getMachine(machineId: string) | Promise<Machine> | | async updateMachinePing(machineId: string = '') | Promise<Machine> | | async unregisterMachine(machineId: string = '') | Promise<boolean> | | async drainMachine(machineId: string = '') | Promise<boolean> | | async createTask(toolName: string, input: string, idempotencyKey: string = '') | Promise<Task> | | async getTask(taskId: string) | Promise<Task> | | async listTasks() | Promise<Task[]> | | async cancelTask(taskId: string) | Promise<boolean> | | async createRequest(toolName: string, input: string, idempotencyKey: string = '') | Promise<RequestModel> | | async getRequest(requestId: string) | Promise<RequestModel> | | async getRequestChunksWindow(requestId: string) | Promise<{ chunks: unknown[]; startSeq: number; nextSeq: number; }> | | async listRequests(options: { status?: string; toolName?: string; limit?: number; /** Opaque cursor from a previous page; omit to start from the first page. */ pageToken?: string; } = {}) | Promise<RequestModel[]> | | async updateRequest(requestId: string, update: RequestUpdate) | Promise<RequestModel> | | async claimRequest(requestId: string, machineId: string = '') | Promise<RequestModel> | | async claimNextRequest(toolNames: string[] = []) | Promise<{ claimed: boolean; request: RequestModel \| null }> | | async appendRequestChunks(requestId: string, chunks: unknown[], resultType: string = 'streaming', lease?: LeaseContext) | Promise<boolean> | | async submitRequestResult(requestId: string, result: unknown, resultType: string = 'resolution', meta: Record<string, string> = {}, lease?: LeaseContext) | Promise<boolean> | | async renewRequestLease(requestId: string, machineId: string, leaseEpoch: number) | Promise<RequestModel> | | async cancelRequest(requestId: string) | Promise<boolean> | | providerRuntime(options: ProviderRuntimeOptions = {}) | ProviderRuntime | | forkSession(sessionId: string) | ToolplaneClient | | static createGRPCClient(serverHost: string, serverPort: number, sessionId: string, userId: string, apiKey?: string, tls?: GRPCTLSConfig) | ToolplaneClient | | async resumeStream(requestId: string, lastSeq: number = 0, onChunk?: (chunk: ExecuteToolChunkModel) => void) | Promise<ExecuteToolChunkModel[]> |

ProviderRuntime

Public methods parsed from src/provider_runtime.ts:

| Method | Returns | | --- | --- | | get running() | boolean | | managedSessionIds() | string[] | | async attachSession(sessionId: string, options: ProviderSessionAttachOptions = {}) | Promise<Session> | | async createSession(options: ProviderSessionCreateOptions) | Promise<Session> | | async registerTool(definition: ProviderToolRegistration) | Promise<ProviderToolHandler> | | tool(definition: Omit<ProviderToolRegistration, 'handler'>, handler: ProviderToolHandler) | Promise<ProviderToolHandler> | | tool(definition: Omit<ProviderToolRegistration, 'handler'>) | (handler: ProviderToolHandler) => Promise<ProviderToolHandler> | | tool(definition: Omit<ProviderToolRegistration, 'handler'>, handler?: ProviderToolHandler) | Promise<ProviderToolHandler> \| ((handler: ProviderToolHandler) => Promise<ProviderToolHandler>) | | async pollOnce() | Promise<void> | | async startInBackground(sessionIds?: Iterable<string>) | Promise<ProviderRuntime> | | async runForever(sessionIds?: Iterable<string>) | Promise<void> | | async stop() | Promise<void> | | async drain() | Promise<void> | | async close() | Promise<void> |

Error Handling

The client exposes a small public error hierarchy:

import {
  ToolplaneError,
  ConnectionError,
  TimeoutError,
  ProtocolError,
} from 'toolplane-typescript-client';

try {
  await client.listTools();
} catch (error) {
  if (error instanceof ConnectionError) {
    console.log(`Connection error: ${error.message}`);
  } else if (error instanceof ToolplaneError) {
    console.log(`Toolplane error: ${error.message}`);
  }
}

Scripts

npm start
npm run dev
npm run example
npm run provider
npm run advanced
npm test
npm run test:conformance
npm run test:all

Conformance

  • The shared fixture runner lives under tests/conformance/ and loads repository-wide cases from ../../conformance/cases/.
  • The public SDK remains gRPC-only.
  • The repository-internal conformance runner uses both gRPC and HTTP adapters so fixture behavior is validated across the maintained server transports.
  • The gRPC provider-runtime cases are now backed by the public ProviderRuntime surface rather than a test-only request-processing loop.

Compatibility

  • Node.js: 18+
  • TypeScript: 5.0+
  • Maintained server path: the Go server gRPC control-plane surface
  • Public protocol: gRPC with Protocol Buffers