# dimebot

**Pocket money for AI agents.** Give dimebot a task in plain words and a budget. It works out which paid calls the
agent will make, prices each one, keeps every single payment at or under a dime, fits the whole plan inside the
budget and walks each payment through the HTTP 402 "Payment Required" handshake — offline. You get a receipt, a CSV
and the policy that produced it.

dimebot does **not** hold keys, sign transactions or pay anyone. It is the planning and checking step that runs
before your agent's wallet does.

```
npm test        # 15 tests, no dependencies
node bin/dimebot.js "Search 6 queries, read 24 pages and write one careful brief" --budget 0.5
```

```
 1. read     turn the task into paid calls
 2. price    price each call from the sheet
 3. dime     check every single payment against the cap
 4. route    use a cheaper tier where the task allows it
 5. fit      fit the plan inside the budget
 6. rehearse walk each payment through HTTP 402, offline
 7. ledger   count and bucket the payments
 8. receipt  write the receipt, the CSV and the policy

   search ×6 = 3¢
   fetch ×24 = 4.8¢
   large ×1 = 4¢

31 payments, 11.8¢ in total, 100% at or under a dime.
```

## Use it from JavaScript

Node 18+ (`require`) or a browser (`<script src="dimebot.js">` makes `window.dimebot`).

```js
const dimebot = require("./src/dimebot.js");

const r = dimebot.run({
  task: "Scan 5 repos for leaked keys, review the results and audit 2 token contracts",
  budget: 0.5,      // US dollars for the whole job
  cap: 0.10         // the most any single payment may be
}, step => console.log(step.i + 1, step.tool, step.ms + " ms"));

r.receipt.summary  // "6 payments, 44¢ in total, 100% at or under a dime; 2 calls held for a human."
r.held             // [{ service: "audit", usd: 0.25, count: 2, status: "waits for a human: 25¢ is over the 10¢ cap" }]
r.receipt.csv      // one row per payment: n,service,usd,id,status
```

## API

| Call | Returns |
| --- | --- |
| `run(input, onStep?)` | `{ steps, needs, skipped, changes, trims, fits, payments, held, ledger, receipt }` |
| `plan(input)` | the eight steps `run()` will take: `[{ tool, args, why }]` |
| `tools.read({ text })` | `{ needs: [{ service, count, clause, quality }], skipped }` |
| `tools.price({ needs, prices })` | `{ lines, total }` |
| `tools.dime({ lines, cap })` | `{ cap, lines (with overCap), over }` |
| `tools.route({ lines, budget, prices })` | `{ lines, changes, total }` |
| `tools.fit({ lines, budget })` | `{ lines, held, trims, spend, fits, budget }` |
| `tools.rehearse({ lines, held, cap, seed })` | `{ payments, held, sample }` |
| `tools.ledger({ payments })` | `{ count, total, buckets, shareUnderDime, byService }` |
| `tools.receipt({ ledger, payments, held, cap, budget, prices })` | `{ summary, lines, csv, policy }` |
| `prices` | a fresh copy of the example price sheet |
| `cents(usd)` | `0.002 → "0.2¢"`, `0.118 → "11.8¢"`, `1.5 → "$1.50"` |

`input` is `{ task, budget = 1, cap = 0.10, prices = example sheet, seed = task }`.

## The example price sheet

These are example prices, not live quotes. Pass your own sheet with `prices` (or `--prices sheet.json`).

| Service | Words that select it | USD per call |
| --- | --- | --- |
| feed | price, tick, quote, rate, weather | 0.001 |
| fetch | read, page, article, site, link, post | 0.002 |
| small | summarise, classify, translate, alert, draft, write | 0.003 |
| search | search, query, look up | 0.005 |
| large | review, report, brief, analyse, plan, careful | 0.04 |
| image | image, picture, thumbnail, banner | 0.06 |
| scan | scan, repo, codebase, leaked keys | 0.08 |
| audit | audit … contract / token | 0.25 |

## Rules dimebot follows

1. **Nothing is guessed.** A clause it cannot map to a service is returned in `skipped`.
2. **The dime rule.** A payment above `cap` is never auto-paid; it is held for a human, with the reason.
3. **Cheaper first, quality respected.** "quick", "rough", "draft" allow the cheaper tier; "careful", "best",
   "deep", "thorough" keep the better one even under budget pressure.
4. **Budgets are hard.** Bulk counts are trimmed in proportion until the plan fits; single calls are never cut.
5. **Offline.** The 402 rehearsal sends nothing; each payment gets a stable FNV-1a id so two runs can be compared.

## Files

```
src/dimebot.js         the library (one file, UMD, zero dependencies)
bin/dimebot.js         the CLI
test/dimebot.test.js   15 tests
examples/              research.js, custom-prices.js
```

MIT License.
