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

taurusai

v0.1.2

Published

TaurusAI - a lightweight local AI agent harness/runtime built from scratch with Node.js, TypeScript, Express and the official OpenAI SDK.

Readme

TaurusAI

A lightweight local AI agent harness/runtime built from scratch in TypeScript.

TaurusAI starts a small HTTP server on http://localhost:8790 with:

  • an AgentRegistry, SessionRegistry, ToolRegistry, and LLMProviderRegistry
  • an AgentRunner that drives the LLM ↔ tool loop
  • a REST API to list agents/tools/providers, create sessions, and send turns

The initial implementation talks directly to OpenAI via the official openai npm SDK. There is no LangChain, LangGraph, LiteLLM, TrueForge, Semantic Kernel, AutoGen, OpenRouter, or any other gateway or orchestration framework. The point is to see how a tiny agent harness actually works end-to-end.


Architecture

            npx taurusai
                 │
                 ▼
            CLI Bootstrap  (src/cli.ts)
                 │
                 ▼
          Local Express Server
          http://localhost:8790
                 │
                 ▼
   ┌────────────────────────────────────┐
   │          Agent Runtime             │
   │                                    │
   │   AgentRegistry      ToolRegistry  │
   │   SessionRegistry    ProviderReg.  │
   │   AgentRunner (loop controller)    │
   └─────────────────┬──────────────────┘
                     │
                     ▼
                LLMProvider  (interface)
                     │
                     ▼
                OpenAIProvider
                     │
                     ▼
             Official OpenAI SDK
                     │
                     ▼
                 OpenAI API

Tool-execution path:

LLM → tool_call → AgentRunner → ToolRegistry
    → tool.execute(args) → Tool Result
    → AgentRunner → LLM (next iteration)

Responsibilities

| Component | Responsibility | |-----------------------|----------------------------------------------------------| | AgentSpec | Describes an agent (model, prompt, tools, limits) | | AgentRegistry | Stores/retrieves AgentSpecs | | Session | A single conversation (messages, metadata) | | SessionRegistry | CRUD for sessions (in-memory for now) | | LLMProvider | Provider-neutral generate() interface | | OpenAIProvider | OpenAI SDK adapter → normalized responses | | LLMProviderRegistry | Lookup providers by name | | ToolDefinition | Describes a tool (name, schema, execute) | | ToolRegistry | Register / list / execute tools | | AgentRunner | The loop: LLM ↔ tools until a final answer | | CLI | Boot runtime, wire registries, start server | | API Routes | REST surface for sessions / agents / tools / providers |


Prerequisites

  • Node.js >= 18
  • An OpenAI API key

Install & local dev

npm install
cp .env.example .env     # on Windows PowerShell: copy .env.example .env
# edit .env and set OPENAI_API_KEY
npm run dev

Then in another terminal:

curl http://localhost:8790/health

To build and run from compiled output:

npm run build
npm start

REST API

| Method | Path | Description | |--------|------------------------------------|---------------------------------------------| | GET | /health | Health check | | GET | /agents | List registered agents | | GET | /tools | List registered tools | | GET | /providers | List registered LLM providers | | POST | /sessions | Create a session for an agent | | GET | /sessions | List sessions | | GET | /sessions/:sessionId | Get session + full message history | | DELETE | /sessions/:sessionId | Delete a session | | POST | /sessions/:sessionId/turns | Send a user input, run the agent loop |

End-to-end example

# 1. Create a session attached to the architecture agent
curl -s -X POST http://localhost:8790/sessions \
  -H "Content-Type: application/json" \
  -d '{"agentId":"architecture-agent"}'

# response: { "sessionId": "..." }

# 2. Send a turn that forces the model to call BOTH tools
curl -s -X POST http://localhost:8790/sessions/<sessionId>/turns \
  -H "Content-Type: application/json" \
  -d '{"input":"What is the weather in Bangalore and multiply the temperature by 2?"}'

The harness will:

  1. Call the model with the question and both tool schemas.
  2. Model asks for weather({city:"Bangalore"}) → harness returns 27.
  3. Call the model again with the tool result.
  4. Model asks for calculator({a:27, b:2, operation:"multiply"}) → harness returns 54.
  5. Call the model one more time; model produces a final natural-language answer.

Server logs will look like:

[Harness] Iteration 1
[LLM] Provider: openai
[LLM] Model: gpt-4o-mini
[LLM] Tool requested: weather
[Tool] Executing weather
[Tool] Result received
[LLM] Calling model again
[Harness] Iteration 2
[LLM] Tool requested: calculator
[Tool] Executing calculator
[Tool] Result received
[LLM] Calling model again
[Harness] Iteration 3
[Harness] Final response received

Testing the CLI locally before publishing

Option A — npm link

npm run build
npm link
taurusai

To unlink later:

npm unlink -g taurusai

Option B — npm pack

npm run build
npm pack
# produces taurusai-0.1.0.tgz
npm install -g ./taurusai-0.1.0.tgz
taurusai

Uninstall:

npm uninstall -g taurusai

Publishing to npm

  1. Create an npm account at https://www.npmjs.com.

  2. Login from the terminal:

    npm login
  3. Verify who you are:

    npm whoami
  4. Build the TypeScript output:

    npm run build
  5. Inspect what will actually be published:

    npm publish --dry-run
  6. Publish:

    npm publish

    If using a scoped package name (e.g. @santoshrbtx/taurusai), publish as public:

    npm publish --access public
  7. Verify:

    npm view taurusai
  8. Run via npx:

    npx taurusai
    # or for a scoped package:
    npx @santoshrbtx/taurusai

Versioning

npm version patch   # 0.1.0 -> 0.1.1 (bug fixes)
npm version minor   # 0.1.1 -> 0.2.0 (backwards-compatible features)
npm version major   # 0.2.0 -> 1.0.0 (breaking changes)
npm publish

Security

  • .env is in .gitignore and is not included in files in package.json, so npm publish cannot leak it.
  • dist/ is .gitignored (build output), but is listed in files in package.json so it is included in the published tarball.
  • API keys are never logged or exposed via any REST endpoint.
  • node_modules/, *.log, and *.tgz are also ignored.

Extending

  • Add a tool: implement ToolDefinition and call tools.register(myTool) in src/cli.ts. Add its name to the agent's tools list.
  • Add a provider: implement LLMProvider, register it in LLMProviderRegistry as providers.register("anthropic", new AnthropicProvider(...)), and point an agent at it via provider: "anthropic". The AgentRunner code does not change.
  • Persist sessions: swap the in-memory Map in SessionRegistry for Redis / PostgreSQL / DynamoDB. The method signatures stay the same.

License

MIT