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

@zerodot/node-sdk

v1.5.0

Published

Contract for zerodot node packages: node types, helpers and the SDK version.

Readme

@zerodot/node-sdk

The contract for zerodot node packages: defineNode, the node and credential types, helpers for items, binary data and icons, and SDK_VERSION.

See nodes for real packages.

Install

npm install --save-peer @zerodot/node-sdk zod

Declare the contract versions that your package works with in its package.json. zerodot checks the range before it runs any package code.

{ "zerodot": { "sdk": "^1.4" } }

A node

import { defineNode } from "@zerodot/node-sdk";
import { z } from "zod";

export default defineNode({
  type: "acme.greet",
  label: "Greet",
  description: "Says hello to a person",
  category: "integration",
  icon: "UserIcon",
  config: z.object({ name: z.string().min(1) }),
  defaultConfig: { name: "" },
  ports: { in: ["in"], out: ["out"] },
  run: ({ config, input }) => ({ port: "out", data: { message: `Hello ${config.name}`, input } }),
});

The config can hold expressions, for example {{ $input.name }}. zerodot resolves them before run gets the config.

Nodes as agent tools

An AI Agent can use a node as a tool. Set usableAsTool to control this. If you do not set it, an integration node is a tool and other nodes are not. Trigger nodes, supply nodes and join nodes are never tools.

defineNode({ type: "acme.greet", usableAsTool: true /* ... */ });

In a tool node, $fromAI(key, description?, type?, defaultValue?) marks a value that the model gives. zerodot makes the input schema of the tool from these calls.

  • The type is string (default), number, boolean, or json (a non-empty object or list). The case does not matter.
  • A key has 1 to 64 letters, numbers, underscores, or hyphens. All calls with the same key must have the same description and type.
  • With a default value, the key is optional: the default is used when the model leaves it out. The default is read as the type ("true" is true for a boolean).
  • The arguments are text in ", ', or backtick quotes. They are not expressions.
{{ $fromAI("name", "The name of the person") }}
{{ $fromAI("count", "How many times", "number", 1) }}

The model gets the output of run. Binary data is sent as its type, file name and size only.

Community packages (not @zerodot/*) are tools only when the server sets ZERODOT_COMMUNITY_NODES_AS_TOOLS=true.

Supply nodes

A supply node gives a value (for example a chat model or a memory) to a supply port of another node. It has no ports and no step. Supply nodes and supply ports work only in official @zerodot/* packages.

import { defineSupplyNode } from "@zerodot/node-sdk";

export default defineSupplyNode({
  type: "acme.model",
  label: "Acme Chat Model",
  category: "integration",
  icon: "AiBrain01Icon",
  config: z.object({ model: z.string() }),
  defaultConfig: { model: "" },
  supplies: "ai.model",
  supply: ({ config, credential }) => createModel(config.model, credential),
});

A node that takes supplies declares supplyPorts, and run gets the values in supplies:

supplyPorts: [
  { name: "model", kind: "ai.model", label: "Chat Model", required: true },
  { name: "tools", kind: "ai.tool", label: "Tool", multiple: true },
],

TOOL_KIND ("ai.tool") is the kind of a tool port. A tool port also takes normal nodes that can be tools.

From 1.5:

  • A node that runs as a tool gets its supplies too, for each call.
  • A supply node can declare supplyPorts. supply then gets the values in supplies (for example, a vector store tool with an embedding supply).
  • The engine builds a supply value one time for the run when its config and credential use no $input, $node, or $fromAI, and the supply nodes under it do not either. Otherwise it builds the value for each run of the parent.
  • A supply port can have showWhen and hideWhen, as a config field has. A hidden port gives no value and is not required. The rules read the saved config, before expressions resolve.
  • When a supply value has a close() function, the engine calls it when the value is not used again: at the end of the run for a value it keeps, or when the parent is done. The last value built closes first. A close that fails or takes more than 5 seconds shows on the supply node and does not stop the run. Use this to keep one connection for the run.
  • A value from the run cache writes its logs to the node that uses it now. When a node attempt that used cached values fails, the engine closes them and builds them again for the next use, so a retry gets a new connection.

Supply modes

One node can be a step with some configs and a supply with others. For example, a vector store that inserts documents as a step and retrieves them as a supply. Use defineNode with run, supply and supplyModes:

defineNode({
  type: "acme.vectorStore",
  // ...
  ports: { in: ["in"], out: ["out"] },
  supplyModes: [
    { kind: "ai.vectorStore", showWhen: { mode: ["retrieve"] } },
    { kind: TOOL_KIND, showWhen: { mode: ["retrieveAsTool"] } },
  ],
  run: ({ config }) => insertOrGet(config),
  supply: ({ config, node }) =>
    config.mode === "retrieveAsTool" ? retrieveTool(toolName(node.name, new Set())) : vectorStore(),
});
  • The first mode whose rules match the saved config gives the kind. The rules read the config before expressions resolve, so the mode field must be a plain value. suppliesOf(definition, config) gives the kind, or undefined for a step.
  • In a supply mode, the node has no in or out ports, and it is not a tool node. In a mode that gives TOOL_KIND, supply returns the tool itself (a NodeTool: spec and call). $fromAI does not work in a supply mode.
  • When the user adds the node on a supply port, the editor sets the values of the first showWhen condition of the mode for that kind. When the user changes the mode, the editor removes the connections that are not valid now.
  • Do not set supplies together with supplyModes.

Option icons

An option of a select can show an icon. Both fields are optional. iconUrl (a data URL, see fileIcon) wins over icon (a Hugeicons name, for example Globe02Icon).

// A nested field (FieldSpec)
options: [{ value: "get", label: "Get", hint: "Read a row", icon: "Download01Icon" }];

// A select in the config schema, by value, like `hints`
z.enum(["get", "put"]).meta({ icons: { get: { icon: "Download01Icon" }, put: { iconUrl } } });

The type is ItemIcon: { icon?: string; iconUrl?: string }.

Versions

SDK_VERSION is the version of the contract. A minor version only adds. A major version can break a package. satisfiesSdk(range) tells if the contract fits a range.

| Contract | Adds | | -------- | ------------------------------------------------------------------------------- | | 1.4 | Supply ports and supply nodes, nodes as agent tools (usableAsTool, $fromAI) | | 1.5 | Supplies for tool runs and supply nodes, run cache, close(), port showWhen |

MIT license.