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

@adhd/agent-plugin-budget

v0.1.0

Published

Budget enforcement plugin for @adhd/agent-mcp — caps token spend, cost, wall-clock time, and model calls per task/session/agent

Readme

@adhd/agent-plugin-budget

Enforcement plugin for @adhd/agent-mcp. Caps token spend, model calls, wall-clock time, and tool usage per task, session, agent, provider, or globally — with configurable time windows and warning/block modes.

Config

Place at .adhd/agent-mcp/config.json (auto-discovered by the plugin loader):

{
  "plugins": [
    {
      "module": "@adhd/agent-plugin-budget",
      "config": {
        "defaults": {
          "caps": [
            { "field": "tokens", "maximum": 50000 },
            { "field": "calls", "maximum": 8 },
            { "field": "wallClock", "maximum": 120000 }
          ]
        }
      }
    }
  ]
}

Caps

Each cap defines one limit. Fields:

| Field | Unit | Scope | Description | | -------------- | ----- | --------- | ----------------------------------------------------------------------------------------------------------------------- | | tokens | count | all | Sum of input + output + cache tokens | | inputTokens | count | all | Input tokens only | | outputTokens | count | all | Output tokens only | | calls | count | all | Number of LLM model calls | | wallClock | ms | task only | Wall-clock time from task start | | modelMs | ms | task only | Cumulative model response time | | cost | USD | all | Estimated cost (requires costPerInputToken / costPerOutputToken) | | toolCalls | count | tool only | Per-tool call count | | responseSize | chars | tool only | Raw response character length. Enforced at transform:tool_result — truncates (warning) or replaces with error (block) |

Custom message

Each cap supports an optional message that overrides the auto-generated enforcement message. Use it to give the agent actionable guidance:

{ "field": "toolCalls", "maximum": 5, "mode": "block", "message": "Search is expensive. Use the index: query__search first" }

Scopes

| Scope | Coverage | DB query | | --------- | ----------------------------------------------------- | -------------------------------------------- | | task | Current task in-memory only | None | | session | Current task + all historical tasks in session | task_usage JOIN tasks WHERE session_id | | agent | Current task + all historical tasks for this agent | task_usage WHERE agent_name | | global | Current task + ALL historical tasks across all agents | task_usage all rows |

Scope is inherited from the dimension's scope field if not set on the individual cap:

{
  "defaults": {
    "scope": "agent",
    "caps": [
      { "field": "tokens", "maximum": 50000 },
      { "field": "calls", "maximum": 8 }
    ]
  }
}

Time windows

Use ISO8601 durations for rolling window caps:

{ "field": "tokens", "maximum": 200000, "window": "PT24H", "scope": "agent" }

Supported formats: PT24H, PT1H30M, P1DT6H, PT30M, etc.

When a cap has both scope and window, the window query provides the historical total (scope-filtered, within the window) — no double-counting.

Tool-level caps

Tool caps enforce at pre:tool_call (toolCalls) or transform:tool_result (responseSize):

{
  "tool": {
    "default": { "caps": [{ "field": "toolCalls", "maximum": 100 }], "mode": "warning" },
    "overrides": {
      "web_search": {
        "caps": [{ "field": "toolCalls", "maximum": 20 }],
        "mode": "block"
      },
      "filesystem__read_text_file": {
        "caps": [
          { "field": "responseSize", "maximum": 500, "mode": "warning", "message": "File too large. Use read_text_file with head:100 to preview, search_files for pattern matching, or read_multiple_files to batch-read small files" },
          { "field": "toolCalls", "maximum": 100, "mode": "warning", "message": "Too many file reads. Use search_files or get_file_info first" }
        ]
      }
    }
  }
}
  • toolCalls field — enforced at pre:tool_call
    • warning — tool call is blocked, agent receives a diagnostic, task continues
    • block — tool call is blocked, task fails with BUDGET_EXCEEDED
  • responseSize field — enforced at transform:tool_result (after the tool runs)
    • warning — tool result is truncated to maximum chars, task continues
    • block — tool result is replaced with an error message (task continues, agent sees the error)

Dimensions

Caps are merged from three dimensions in this order: defaults ← agent ← provider

{
  "defaults": {
    "caps": [{ "field": "calls", "maximum": 8 }]
  },
  "agent": {
    "default": { "caps": [{ "field": "calls", "maximum": 5 }] },
    "overrides": {
      "cheap-agent": {
        "caps": [{ "field": "calls", "maximum": 1, "message": "Cheap agents get 1 call max" }]
      }
    }
  },
  "provider": {
    "default": { "caps": [{ "field": "cost", "maximum": 0.1 }] },
    "overrides": {
      "anthropic": { "caps": [{ "field": "cost", "maximum": 0.5 }] }
    }
  },
  "tool": {
    "default": { "caps": [{ "field": "toolCalls", "maximum": 100 }], "mode": "warning" },
    "overrides": {
      "web_search": {
        "caps": [{ "field": "toolCalls", "maximum": 20, "message": "Consider caching search results" }],
        "mode": "block"
      },
      "filesystem__read_file": {
        "caps": [{ "field": "responseSize", "maximum": 500, "mode": "warning", "message": "Raw file content is too large. Use shell tools instead: head -n 100, wc -l, grep for patterns" }]
      }
    }
  }
}

Caps are additive across dimensions — multiple caps targeting the same field all apply. For example, defaults and agent.overrides can both cap calls; the stricter bound wins by throwing first.

Cost estimation

For the cost field, set token prices on the defaults dimension:

{
  "defaults": {
    "costPerInputToken": 0.000003,
    "costPerOutputToken": 0.000015,
    "caps": [{ "field": "cost", "maximum": 0.1 }]
  }
}

Cost = inputTokens × costPerInputToken + outputTokens × costPerOutputToken.

Backward compat (flat format)

The old flat field format is supported via automatic conversion:

{
  "config": {
    "maxTotalTokens": 50000,
    "maxModelCalls": 8,
    "maxWallClockMs": 120000,
    "scope": "agent"
  }
}

Converts internally to:

{
  "caps": [
    { "field": "tokens", "maximum": 50000 },
    { "field": "calls", "maximum": 8 },
    { "field": "wallClock", "maximum": 120000 }
  ],
  "scope": "agent"
}

Custom messages in flat format

The message key is also passed through in flat format — it applies to all caps in the dimension:

{
  "config": {
    "maxTotalTokens": 50000,
    "maxModelCalls": 8,
    "mode": "warning",
    "message": "Budget limit hit"
  }
}

Performance

Enforcement makes exactly U + W DB queries per event where:

  • U = number of unique non-task scopes across all caps (0..3)
  • W = number of unique (scope, window) pairs across all caps

Zero DB queries when no caps are configured. No per-cap scaling.

Testing

nx test agent-plugin-budget