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

@devicerail/tool-adapter

v0.3.8

Published

Provider-neutral AI tool adapter for DeviceRail device capabilities

Readme

@devicerail/tool-adapter

Provider-neutral DeviceRail Tool Catalogs for Node.js 22 and later.

The package converts the selected device's device.capabilities response into an immutable catalog. It adds one explicit observation tool and maps every portable tool name back to the original Driver action. It does not import an AI SDK, translate tools into a provider-specific format, or own device and Session lifecycle.

import { DeviceRailClient } from "@devicerail/client";
import {
  actionToolName,
  DeviceRailToolAdapter,
} from "@devicerail/tool-adapter";

const client = await DeviceRailClient.spawn({ command: "devicerail-daemon", hello });

// Lifecycle remains explicit and host-owned.
await client.call("device.select", { deviceId: "android-1" });
await client.call("device.connect");
await client.call("session.start");

const catalog = await new DeviceRailToolAdapter(client).discover();
const result = await catalog.invoke(
  {
    arguments: { x: 320, y: 240 },
    invocationId: "agent-call-1",
    name: actionToolName("tap"),
  },
  { actionTimeoutMs: 5_000, requestTimeoutMs: 10_000 },
);

if (result.kind === "action") {
  console.log(result.action.after, result.action.evidence);
}

beginInvoke() additionally exposes the exact RPC request ID and a typed cancel() operation. Agent/provider invocation IDs remain metadata; the adapter always generates a distinct UUID for the DeviceRail Action call. Remote RPC and Driver failures reject unchanged rather than becoming textual tool success results.

Results from injected client-compatible implementations cross the same canonical method-result Schema boundary as the stock client before the adapter applies its stricter Action, Observation, Evidence, and protected-data semantics.

Action schemas must be pure JSON with type: "object" at the root. During discovery, the adapter performs defensive shape checks for common JSON Schema keywords and then deeply freezes an isolated schema snapshot. It accepts Draft 6, Draft 7, Draft 2019-09, Draft 2020-12, and compound schema documents with nested resources.

The adapter does not fetch schemas, resolve references, select a dialect, or claim complete meta-schema validation. $id, $ref, $dynamicRef, and $recursiveRef values are preserved for the Driver/daemon validation boundary; remote and currently unresolved references do not cause network access during tool discovery.

Protected actions are excluded from catalogs by default. A host that deliberately wants to expose actions such as Android inputSecret must both negotiate action.protected.v1 during system.hello and opt the adapter in:

// The client's hello.features.optional must include "action.protected.v1".
const catalog = await new DeviceRailToolAdapter(client, {
  includeProtectedActions: true,
}).discover();

Opting in makes the protected argument visible to the Agent/provider and to the JavaScript process. DeviceRail redacts its durable Action event and omits the protected before/after screenshots, but the adapter cannot prevent an upstream model provider, host logger, operating system, or process-memory inspector from retaining the value.