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

@olane/o-tool

v0.8.0

Published

oLane base tool class

Downloads

1,124

Readme

@olane/o-tool

Tool augmentation system for Olane OS - build specialized tool nodes (applications) that AI agents use

The tool system layer of Olane OS. Transform generalist LLMs into specialists through tool augmentation and context injection - create discoverable, validated capabilities without fine-tuning models.

npm version License: ISC

Features

  • 🔧 Convention-Based Tool Registration - Automatic discovery via _tool_ prefix
  • Built-in Parameter Validation - Type-safe parameter checking with clear error messages
  • 🔍 Automatic Discovery - Tools indexed in vector store for semantic search by agents
  • 🏗️ Mixin Architecture - Compose tool capabilities with any oCore class
  • 🌲 Hierarchical Organization - Inherit context and capabilities from parent tools
  • 📡 Streaming Support - Handle long-running operations with progress updates
  • 🎯 Built-in Tools - Handshake, routing, indexing, and lifecycle management included

Installation

npm install @olane/o-tool

Quick Start

Creating a Simple Tool

import { oToolBase, oRequest, ToolResult } from '@olane/o-tool';
import { oAddress } from '@olane/o-core';

class CalculatorTool extends oToolBase {
  constructor() {
    super({
      address: new oAddress('o://calculator'),
      description: 'Performs mathematical calculations',
      methods: {
        add: {
          description: 'Add two numbers',
          parameters: {
            a: { type: 'number', required: true },
            b: { type: 'number', required: true }
          }
        }
      }
    });
  }

  // Tool methods use _tool_ prefix for automatic registration
  async _tool_add(request: oRequest): Promise<ToolResult> {
    const { a, b } = request.params;
    return { result: a + b };
  }
}

// Start the tool
const calculator = new CalculatorTool();
await calculator.start();

// Use the tool
const response = await calculator.use({
  method: 'add',
  params: { a: 5, b: 3 }
});

console.log(response.result); // { result: 8 }

Using the Mixin Pattern

Extend any oCore class with tool capabilities:

import { oTool } from '@olane/o-tool';
import { oNode } from '@olane/o-node';

class MyNetworkTool extends oTool(oNode) {
  constructor(config) {
    super(config);
  }

  async _tool_process(request: oRequest): Promise<ToolResult> {
    // Your custom logic here
    return { status: 'processed' };
  }
}

Core Concepts

Tool Convention Pattern

Tools are automatically discovered using naming conventions:

  • _tool_methodName - Defines an executable tool method

Method metadata is defined using oMethod definition files that provide structured schemas for AI agents to understand how to use your tool methods.

// weather.methods.ts - Define method schemas for AI discovery
import { oMethod } from '@olane/o-protocol';

export const WEATHER_METHODS: { [key: string]: oMethod } = {
  get_forecast: {
    name: 'get_forecast',
    description: 'Get weather forecast for a city',
    dependencies: [],
    parameters: [
      {
        name: 'city',
        type: 'string',
        value: 'string',
        description: 'City name to get forecast for',
        required: true,
      },
    ],
  },
};

// weather.tool.ts - Implement the tool
class WeatherTool extends oToolBase {
  constructor() {
    super({
      address: new oAddress('o://weather'),
      description: 'Weather forecast service',
      methods: WEATHER_METHODS,
    });
  }

  // Executable tool method
  async _tool_get_forecast(request: oRequest): Promise<ToolResult> {
    const { city } = request.params;
    return { forecast: '☀️ Sunny, 72°F' };
  }
}

Built-in Tools

Every tool automatically includes these methods:

| Method | Description | |--------|-------------| | handshake | Capability negotiation between agents | | route | Route requests through the hierarchy | | index_network | Index tool in vector store for discovery | | hello_world | Connectivity test | | stop | Graceful shutdown | | child_register | Register child tools in hierarchy |

Automatic Validation

Parameter validation happens automatically before tool execution:

// Missing required parameters trigger clear errors
try {
  await tool.use({ method: 'add', params: { a: 5 } });
} catch (error) {
  // Error: Missing required parameters: ["b"]
  console.log(error.message);
}

Examples

Search Tool with Vector Store Integration

import { oLaneTool } from '@olane/o-lane';
import { oAddress, oRequest } from '@olane/o-core';

class SearchTool extends oLaneTool {
  constructor(config) {
    super({
      ...config,
      address: new oAddress('o://search'),
      description: 'Search for information in the network'
    });
  }

  async _tool_vector(request: oRequest): Promise<ToolResult> {
    const { query } = request.params;
    
    const response = await this.use(new oAddress('o://vector-store'), {
      method: 'search_similar',
      params: { query, limit: 10 }
    });
    
    return response.result.data;
  }
}

Tool with Streaming Support

class DataProcessorTool extends oToolBase {
  async _tool_process_large_file(request: oRequest & { stream?: Stream }): Promise<ToolResult> {
    const { filePath } = request.params;
    const { stream } = request;
    
    // Send progress updates
    for (let i = 0; i < 100; i += 10) {
      if (stream) {
        await CoreUtils.sendResponse(
          { progress: i, status: 'processing' },
          stream
        );
      }
    }
    
    return { status: 'complete', processed: true };
  }
}

Hierarchical Tool Organization

// Parent tool
const parentTool = new CalculatorTool();
await parentTool.start();

// Child tool inherits context from parent
class AdvancedCalculatorTool extends oToolBase {
  async initialize() {
    await super.initialize();
    
    // Register with parent
    await this.use(new oAddress('o://calculator'), {
      method: 'child_register',
      params: { address: this.address.toString() }
    });
  }

  async _tool_complex_calculation(request: oRequest): Promise<ToolResult> {
    // Can leverage parent tool capabilities
    const result = await this.use(new oAddress('o://calculator'), {
      method: 'add',
      params: { a: 10, b: 20 }
    });
    
    return { result: result.result * 2 };
  }
}

API Reference

oToolBase

Base class for creating tools.

Key Methods:

  • execute(request: oRequest, stream?: Stream): Promise<RunResult> - Execute tool with request
  • run(request: oRequest, stream?: Stream): Promise<RunResult> - Run with validation
  • myTools(): Promise<string[]> - Get list of available tool methods
  • callMyTool(request: oRequest, stream?: Stream): Promise<ToolResult> - Call specific tool method
  • index(): Promise<{summary: string}> - Index tool in vector store
  • whoami(): Promise<object> - Get tool metadata

oTool(Base)

Mixin function that adds tool capabilities to any oCore class.

function oTool<T extends new (...args: any[]) => oToolBase>(Base: T): T

Usage:

class CustomTool extends oTool(MyBaseClass) {
  // Tool methods...
}

Interfaces

oToolConfig

interface oToolConfig extends Omit<oCoreConfig, 'address'> {
  description?: string;
  methods?: Record<string, MethodMetadata>;
}

ToolResult

interface ToolResult {
  [key: string]: unknown;
}

RunResult

interface RunResult extends ToolResult {
  error?: oError;
}

Utilities

MethodUtils.findMissingParams(tool, method, params)

Validates parameters against tool method requirements.

const missing = MethodUtils.findMissingParams(tool, 'add', { a: 5 });
// Returns: ['b']

Tool Discovery & Indexing

Tools automatically integrate with Olane's vector store for semantic discovery:

// Index your tool for agent discovery
await tool.use({ method: 'index_network' });

// Agents can now discover your tool semantically
const results = await this.use(new oAddress('o://vector-store'), {
  method: 'search_similar',
  params: { query: 'calculate numbers' }
});
// Returns: o://calculator with tool descriptions

Error Handling

Tools use structured error handling with oError:

import { oError, oErrorCodes } from '@olane/o-core';

async _tool_divide(request: oRequest): Promise<ToolResult> {
  const { a, b } = request.params;
  
  if (b === 0) {
    throw new oError(
      oErrorCodes.INVALID_PARAMETERS,
      'Cannot divide by zero',
      { a, b }
    );
  }
  
  return { result: a / b };
}

Testing

import { oRequest } from '@olane/o-core';

describe('CalculatorTool', () => {
  let tool: CalculatorTool;
  
  beforeEach(async () => {
    tool = new CalculatorTool();
    await tool.start();
  });
  
  it('should add two numbers', async () => {
    const request = new oRequest({
      method: 'add',
      params: { a: 5, b: 3 },
      id: '123'
    });
    
    const result = await tool.callMyTool(request);
    expect(result.result).toBe(8);
  });
  
  afterEach(async () => {
    await tool.stop();
  });
});

Related Packages

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and development process.

License

ISC © oLane Inc.

Resources