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

@saw-protocol/runtime-local

v1.0.8

Published

Rule-based local agent runtime for the SAW Protocol (Solana Agentic Wallet Protocol)

Readme

@saw-protocol/runtime-local

A rule-based, local IAgentRuntime implementation for the SAW Protocol.

This module provides a mock reasoning engine suitable for testing, tightly coupled automation, or strict rule-based agent logic. It allows developers to register custom Javascript/TypeScript callbacks (decideFn, incomingMessageFn, negotiateFn) which execute instantly without relying on heavy external LLM APIs like OpenAI or Anthropic.

Installation

npm install @saw-protocol/runtime-local

Example Usage

1. Basic Instantiation with Fallbacks

If no callbacks are provided, LocalRuntime falls back to its default secure logic: creating acknowledgement intents and safely rejecting negotiation proposals.

import { LocalRuntime } from "@saw-protocol/runtime-local";

const myAgentId = "did:sol:mySuperAgentX";

// A runtime that automatically defaults correctly to all incoming messages.
const defaultRuntime = new LocalRuntime({
  agentId: myAgentId,
});

// Decides to fallback to a basic 'Hello World' signMessage intent
const intent = await defaultRuntime.decide(
  {
    walletState: { balance: 10 },
    memory: [],
  },
  [],
);

2. Custom Rule-Based Callback Logic

You can pass in completely custom Typescript functions to execute strict logic when deciding intents or handling agent-to-wallet messages.

import {
  LocalRuntime,
  DecisionLogic,
  IncomingMessageLogic,
} from "@saw-protocol/runtime-local";
import { PublicKey } from "@solana/web3.js";
import { v4 as uuidv4 } from "uuid";

// Strictly define how this specific runtime decides things
const customDecisionLogic: DecisionLogic = async (
  context,
  availableActions,
) => {
  console.log("Evaluating context:", context);

  if (context.walletState.balance > 0.5) {
    // Generate a strictly typed TransactionIntent
    return {
      id: uuidv4(),
      agentId: "did:sol:myAgent",
      action: {
        type: "transfer",
        params: { amount: 0.1, to: "DestinationPubKey..." },
        estimatedValue: 0.1,
      },
      walletAddress: new PublicKey("..."),
      reasoning: "Balance > 0.5, proceeding with automated transfer.",
      signature: "unsigned",
      timestamp: Date.now(),
    };
  }

  throw new Error("Conditions not met for decision");
};

// Strongly define how the runtime responds to messages from external agents
const customMessageLogic: IncomingMessageLogic = async (message, context) => {
  if (message.payload.prompt === "Swap 0.05 SOL to USDC") {
    // Acknowledge the swap intent immediately
    return {
      id: uuidv4(),
      from: "did:sol:walletRuntime",
      to: message.from,
      replyTo: message.id,
      type: "Response",
      payload: { ack: message.id, status: "swap_intent_approved" },
      signature: "unsigned",
      timestamp: Date.now(),
      ttl: 60,
    };
  }

  // Fallback to simple generic Response message for unhandled payload types
  return {
    id: uuidv4(),
    from: "did:sol:walletRuntime",
    to: message.from,
    type: "Response",
    payload: { status: "unknown" },
    signature: "unsigned",
    timestamp: Date.now(),
    ttl: 60,
  };
};

const strictRuntime = new LocalRuntime({
  agentId: "did:sol:myAgent",
  decideFn: customDecisionLogic,
  incomingMessageFn: customMessageLogic,
});

// Using the exact implementation matching the SAWP SDK
const receivedMsg = await strictRuntime.handleIncomingMessage(
  {
    id: "random-id",
    from: "did:sol:externalAgent",
    to: "did:sol:walletRuntime",
    type: "Request",
    payload: { prompt: "Swap 0.05 SOL to USDC" },
    signature: "...",
    timestamp: Date.now(),
    ttl: 60,
  },
  { walletState: {}, memory: [] },
);

console.log("Response payload:", receivedMsg.payload); // { ack: "random-id", status: "swap_intent_approved" }