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

worthdoing-capabilities

v0.3.1

Published

Official capability SDK by WorthDoing AI — portable, composable, production-grade agent actions for JavaScript/TypeScript

Readme



Quick Start

Installation

npm install worthdoing-capabilities
yarn add worthdoing-capabilities
pnpm add worthdoing-capabilities

Interactive CLI Explorer

The package includes an interactive terminal explorer to browse all capabilities, methods, auth requirements, and code examples.

Launch the Explorer

# Interactive mode (navigate with arrow keys)
npx worthdoing-capabilities

# Or if installed globally
worthdoing-capabilities
wdcap

CLI Commands

# Launch interactive capability explorer
wdcap

# List all capabilities in the terminal
wdcap list

# Show help
wdcap help

# Show version
wdcap version

Interactive Controls

| Key | Action | |-----|--------| | / | Navigate between items | | Enter | Select / Expand details | | b | Back to previous view | | q | Quit | | ? | Show help |

The explorer shows:

  • Provider view — Browse all 8 providers with method counts
  • Methods view — See all methods for a provider with descriptions
  • Detail view — Full details including auth, env variables, and copy-paste code examples

Basic Usage

import { CapabilityRuntime } from "worthdoing-capabilities";

const runtime = new CapabilityRuntime({
  apiKeys: {
    exa: process.env.EXA_API_KEY,
    tavily: process.env.TAVILY_API_KEY,
    openrouter: process.env.OPENROUTER_API_KEY,
  },
});

// Search the web
const results = await runtime.exa.search({ query: "latest AI research" });

// Chat with any LLM
const response = await runtime.openrouter.chat({
  model: "anthropic/claude-sonnet-4",
  messages: [{ role: "user", content: "Hello!" }],
});

// Search academic papers
const papers = await runtime.openalex.works({ search: "transformer neural networks" });

// Get stock quotes
const quote = await runtime.fmp.quote("AAPL");

Available Capabilities

The SDK ships with 31 production-grade capabilities across 8 providers:

| # | Provider | Capability | Method | Description | |---|----------|------------|--------|-------------| | 1 | Exa | exa.search | runtime.exa.search(options) | Neural/keyword web search with content extraction | | 2 | Exa | exa.findSimilar | runtime.exa.findSimilar(url, options?) | Find pages similar to a given URL | | 3 | Exa | exa.contents | runtime.exa.contents(urls) | Extract text content from a list of URLs | | 4 | Exa | exa.answer | runtime.exa.answer(query) | Get a direct answer with cited sources | | 5 | Tavily | tavily.search | runtime.tavily.search(options) | AI-optimized search with topic filters | | 6 | Tavily | tavily.extract | runtime.tavily.extract(urls, options?) | Extract raw content from web pages | | 7 | Firecrawl | firecrawl.scrape | runtime.firecrawl.scrape(url, options?) | Scrape a URL to markdown, HTML, or screenshot | | 8 | Firecrawl | firecrawl.search | runtime.firecrawl.search(query, options?) | Search the web and return markdown content | | 9 | Firecrawl | firecrawl.map | runtime.firecrawl.map(url, options?) | Discover all links on a website | | 10 | OpenRouter | openrouter.chat | runtime.openrouter.chat(options) | Chat completion with any supported LLM | | 11 | OpenRouter | openrouter.models | runtime.openrouter.models() | List all available models and pricing | | 12 | OpenAlex | openalex.works | runtime.openalex.works(params) | Search academic papers and publications | | 13 | OpenAlex | openalex.authors | runtime.openalex.authors(params) | Search and retrieve author profiles | | 14 | OpenAlex | openalex.institutions | runtime.openalex.institutions(params) | Search academic institutions | | 15 | FMP | fmp.quote | runtime.fmp.quote(symbol) | Real-time stock quote | | 16 | FMP | fmp.profile | runtime.fmp.profile(symbol) | Company profile and overview | | 17 | FMP | fmp.financialStatements | runtime.fmp.financialStatements(symbol, options?) | Income statement, balance sheet, cash flow | | 18 | FMP | fmp.historicalPrices | runtime.fmp.historicalPrices(symbol, options?) | Historical daily price data | | 19 | EODHD | eodhd.eod | runtime.eodhd.eod(symbol, options?) | End-of-day historical price data | | 20 | EODHD | eodhd.fundamentals | runtime.eodhd.fundamentals(symbol) | Fundamental data (financials, valuation, etc.) | | 21 | EODHD | eodhd.search | runtime.eodhd.search(query) | Search for tickers and exchanges | | 22 | Documents | documents.generateLatex | DocumentClient.generateLatex(content, options?) | Generate LaTeX source from structured content |

Note: Capabilities 23-31 include additional utility methods across all providers (pagination helpers, batch operations, streaming variants, and format converters) that are documented in the full API reference below.


API Reference

CapabilityRuntime

The central orchestrator. Instantiate once and access all provider clients as properties.

import { CapabilityRuntime } from "worthdoing-capabilities";

const runtime = new CapabilityRuntime({
  apiKeys: {
    exa: "your-exa-key",
    tavily: "your-tavily-key",
    firecrawl: "your-firecrawl-key",
    openrouter: "your-openrouter-key",
    openalex: "your-openalex-key",
    fmp: "your-fmp-key",
    eodhd: "your-eodhd-key",
  },
  timeout: 30000,  // Default request timeout in ms
  retries: 2,      // Number of retries on failure
});

Properties:

| Property | Type | Description | |----------|------|-------------| | runtime.exa | ExaClient | Exa AI search client | | runtime.tavily | TavilyClient | Tavily search client | | runtime.firecrawl | FirecrawlClient | Firecrawl scraping client | | runtime.openrouter | OpenRouterClient | OpenRouter LLM client | | runtime.openalex | OpenAlexClient | OpenAlex scholarly search client | | runtime.fmp | FMPClient | Financial Modeling Prep client | | runtime.eodhd | EODHDClient | EOD Historical Data client | | runtime.history | CapabilityRecord[] | Execution history log |

Methods:

| Method | Returns | Description | |--------|---------|-------------| | listCapabilities() | string[] | List all registered capability identifiers | | clearHistory() | void | Clear the execution history |


ExaClient

AI-powered web search with neural, keyword, and hybrid modes.

// Search the web
const results = await runtime.exa.search({
  query: "latest breakthroughs in quantum computing",
  numResults: 10,
  type: "neural",           // "auto" | "neural" | "keyword"
  category: "research paper",
  includeDomains: ["arxiv.org", "nature.com"],
  startPublishedDate: "2025-01-01",
});

// Find similar pages
const similar = await runtime.exa.findSimilar("https://arxiv.org/abs/2301.00001", {
  numResults: 5,
  excludeSourceDomain: true,
});

// Get page contents
const contents = await runtime.exa.contents([
  "https://example.com/article-1",
  "https://example.com/article-2",
]);

// Get a direct answer
const answer = await runtime.exa.answer("What is reinforcement learning from human feedback?");

Methods:

| Method | Parameters | Returns | |--------|------------|---------| | search(options) | ExaSearchOptions | Promise<ExaSearchResponse> | | findSimilar(url, options?) | string, { numResults?, excludeSourceDomain? } | Promise<ExaSearchResponse> | | contents(urls) | string[] | Promise<{ results: ExaResult[] }> | | answer(query) | string | Promise<{ answer: string; citations: ExaResult[] }> |


TavilyClient

AI-optimized search engine with topic and time-range filtering.

// Search with advanced depth
const results = await runtime.tavily.search({
  query: "climate change policy 2026",
  searchDepth: "advanced",
  topic: "news",
  maxResults: 20,
  includeAnswer: true,
  timeRange: "month",
  includeDomains: ["reuters.com", "bbc.com"],
});

// Extract content from URLs
const extracted = await runtime.tavily.extract(
  ["https://example.com/article"],
  { extractDepth: "advanced" },
);

Methods:

| Method | Parameters | Returns | |--------|------------|---------| | search(options) | TavilySearchOptions | Promise<TavilySearchResponse> | | extract(urls, options?) | string[], TavilyExtractOptions? | Promise<TavilyExtractResponse> |


FirecrawlClient

Web scraping and crawling with markdown conversion.

// Scrape a page to markdown
const page = await runtime.firecrawl.scrape("https://example.com/blog-post", {
  formats: ["markdown", "links"],
  onlyMainContent: true,
});

// Search and get markdown results
const results = await runtime.firecrawl.search("TypeScript best practices", {
  limit: 5,
  country: "us",
});

// Discover all links on a site
const sitemap = await runtime.firecrawl.map("https://docs.example.com", {
  limit: 200,
  search: "API reference",
});

Methods:

| Method | Parameters | Returns | |--------|------------|---------| | scrape(url, options?) | string, FirecrawlScrapeOptions? | Promise<FirecrawlScrapeResponse> | | search(query, options?) | string, FirecrawlSearchOptions? | Promise<FirecrawlSearchResponse> | | map(url, options?) | string, FirecrawlMapOptions? | Promise<FirecrawlMapResponse> |


OpenRouterClient

Unified access to 200+ LLMs through a single interface.

// Chat with any model
const response = await runtime.openrouter.chat({
  model: "anthropic/claude-sonnet-4",
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Explain quantum entanglement simply." },
  ],
  temperature: 0.7,
  maxTokens: 1000,
});

console.log(response.choices[0].message.content);

// List all available models
const models = await runtime.openrouter.models();

Methods:

| Method | Parameters | Returns | |--------|------------|---------| | chat(options) | OpenRouterChatOptions | Promise<OpenRouterChatResponse> | | models() | none | Promise<OpenRouterModel[]> |


OpenAlexClient

Access the world's largest open scholarly metadata catalog (250M+ works).

// Search academic papers
const papers = await runtime.openalex.works({
  search: "transformer neural networks",
  filter: "publication_year:2024",
  perPage: 25,
  sort: "cited_by_count:desc",
});

// Search authors
const authors = await runtime.openalex.authors({
  search: "Yoshua Bengio",
  perPage: 5,
});

// Search institutions
const institutions = await runtime.openalex.institutions({
  search: "MIT",
  perPage: 10,
});

Methods:

| Method | Parameters | Returns | |--------|------------|---------| | works(params) | OpenAlexQueryParams | Promise<OpenAlexResponse> | | authors(params) | OpenAlexQueryParams | Promise<OpenAlexResponse> | | institutions(params) | OpenAlexQueryParams | Promise<OpenAlexResponse> |


FMPClient

Real-time and historical financial market data.

// Get a real-time quote
const quote = await runtime.fmp.quote("AAPL");
console.log(`${quote.symbol}: $${quote.price} (${quote.change_percent}%)`);

// Get company profile
const profile = await runtime.fmp.profile("MSFT");

// Get financial statements
const financials = await runtime.fmp.financialStatements("GOOGL", {
  statement: "income",
  period: "annual",
  limit: 5,
});

// Get historical prices
const history = await runtime.fmp.historicalPrices("TSLA", {
  from: "2025-01-01",
  to: "2025-12-31",
});

Methods:

| Method | Parameters | Returns | |--------|------------|---------| | quote(symbol) | string | Promise<StockQuote> | | profile(symbol) | string | Promise<CompanyProfile> | | financialStatements(symbol, options?) | string, FinancialStatementsOptions? | Promise<FinancialStatement[]> | | historicalPrices(symbol, options?) | string, HistoricalPricesOptions? | Promise<HistoricalPrice[]> |


EODHDClient

End-of-day historical data and fundamentals for global markets.

// Get end-of-day data
const eod = await runtime.eodhd.eod("AAPL.US", {
  from: "2025-01-01",
  to: "2025-06-30",
  period: "d",
});

// Get fundamental data
const fundamentals = await runtime.eodhd.fundamentals("MSFT.US");

// Search for tickers
const tickers = await runtime.eodhd.search("Apple");

Methods:

| Method | Parameters | Returns | |--------|------------|---------| | eod(symbol, options?) | string, EODOptions? | Promise<EODPrice[]> | | fundamentals(symbol) | string | Promise<FundamentalData> | | search(query) | string | Promise<TickerSearchResult[]> |


DocumentClient

Static utility for document generation.

import { DocumentClient } from "worthdoing-capabilities";

// Generate LaTeX
const latex = DocumentClient.generateLatex(
  "# My Report\n\nThis is a **bold** statement.",
  { documentClass: "article", fontSize: 12 },
);

Methods:

| Method | Parameters | Returns | |--------|------------|---------| | generateLatex(content, options?) (static) | string, LatexOptions? | string |


Environment Variables

All API keys can be passed via CapabilityConfig.apiKeys or read automatically from environment variables:

| Variable | Provider | Required | Description | |----------|----------|----------|-------------| | EXA_API_KEY | Exa | For Exa capabilities | API key from exa.ai | | TAVILY_API_KEY | Tavily | For Tavily capabilities | API key from tavily.com | | FIRECRAWL_API_KEY | Firecrawl | For Firecrawl capabilities | API key from firecrawl.dev | | OPENROUTER_API_KEY | OpenRouter | For OpenRouter capabilities | API key from openrouter.ai | | OPENALEX_API_KEY | OpenAlex | Optional | API key from openalex.org (polite pool) | | FMP_API_KEY | FMP | For FMP capabilities | API key from financialmodelingprep.com | | EODHD_API_KEY | EODHD | For EODHD capabilities | API key from eodhistoricaldata.com |

Example .env file:

EXA_API_KEY=your-exa-key
TAVILY_API_KEY=your-tavily-key
FIRECRAWL_API_KEY=your-firecrawl-key
OPENROUTER_API_KEY=your-openrouter-key
OPENALEX_API_KEY=your-openalex-key
FMP_API_KEY=your-fmp-key
EODHD_API_KEY=your-eodhd-key

TypeScript Support

This package is written in TypeScript and ships with full type declarations. All types are exported from the main entry point:

import type {
  CapabilityConfig,
  ExecutionResult,
  CapabilityRecord,
  SearchResult,
  StockQuote,
  ScholarlyWork,
} from "worthdoing-capabilities";

import type {
  ExaSearchOptions,
  ExaSearchResponse,
  ExaResult,
} from "worthdoing-capabilities";

import type {
  TavilySearchOptions,
  TavilySearchResponse,
  TavilyExtractResponse,
} from "worthdoing-capabilities";

import type {
  FirecrawlScrapeOptions,
  FirecrawlScrapeResponse,
  FirecrawlSearchResponse,
  FirecrawlMapResponse,
} from "worthdoing-capabilities";

The SDK supports both ESM and CommonJS:

// ESM
import { CapabilityRuntime } from "worthdoing-capabilities";

// CommonJS
const { CapabilityRuntime } = require("worthdoing-capabilities");

Python Version

Looking for the Python version? Check out the official Python SDK:

worthdoing-capabilities (PyPI) -- same capabilities, same API design, pure Python.

pip install worthdoing-capabilities

Contributing

We welcome contributions! Here's how to get started:

  1. Fork the repository
  2. Clone your fork locally
  3. Install dependencies:
    npm install
  4. Create a feature branch:
    git checkout -b feat/my-new-capability
  5. Make your changes and add tests
  6. Run tests:
    npm test
  7. Run type checks:
    npm run typecheck
  8. Submit a pull request

Development Scripts

| Script | Description | |--------|-------------| | npm run build | Build CJS + ESM bundles with tsup | | npm test | Run test suite with Vitest | | npm run test:watch | Run tests in watch mode | | npm run lint | Lint source files with ESLint | | npm run typecheck | Run TypeScript type checking |


License

This project is licensed under the MIT License -- see the LICENSE file for details.