foldrun 2.10.11 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/bin/foldrun.mjs +1 -2
- package/docs/api.md +3 -3
- package/docs/budgets-and-billing.md +4 -2
- package/docs/cli.md +1 -2
- package/package.json +1 -1
- package/src/commands.mjs +5 -19
package/README.md
CHANGED
|
@@ -147,7 +147,6 @@ declared the same way.
|
|
|
147
147
|
| `foldrun storage put <file>` | upload a file into a workspace's storage (`--as <path>` names it) — also `rm <path>` |
|
|
148
148
|
| `foldrun storage share <path>` | a public link to one produced file (`--ttl <days>`, default 7; `--forever`) — also `shares` (`--all`) and `unshare <token>` |
|
|
149
149
|
| `foldrun billing` | the account's balance and its recent ledger entries, with what each was for — on foldrun's hosted platform (a self-hosted install has no billing) |
|
|
150
|
-
| `foldrun billing credit <usd>` | credit added by hand — on foldrun's hosted platform without Stripe (dev) |
|
|
151
150
|
| `foldrun billing plans` | the plans and this cycle's credits — also `plan <id>`, `plan cancel`, `plan resume`, `top-up <usd>`, `card` (Stripe's own pages for anything with a card) |
|
|
152
151
|
| `foldrun account` | the account's defaults: timezone, notify, budget, concurrency — also `set <key> <value>` and `clear <key>` |
|
|
153
152
|
| `foldrun account providers` | which model providers the account's files use and whether each key still answers (`--check` asks now) |
|
package/bin/foldrun.mjs
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
// foldrun team who is in the account, their roles and workspaces (read-only)
|
|
29
29
|
// foldrun restore <ws> a workspace's source back to a point in its history (shows the change, asks)
|
|
30
30
|
// foldrun onboarding the account's getting-started steps, the next one first
|
|
31
|
-
// foldrun billing the balance, and what the money went on
|
|
31
|
+
// foldrun billing the balance, and what the money went on
|
|
32
32
|
// foldrun gallery the tools the platform ships to every account — list, pull, upgrade <tool>
|
|
33
33
|
// foldrun storage <verb> ls / cat / get / put / rm / share / shares / unshare — what the agents produced, and public links to it
|
|
34
34
|
// foldrun runtimes the environments a workspace's agents need, and whether each is built
|
|
@@ -195,7 +195,6 @@ const HELP = `foldrun — agents are just folders
|
|
|
195
195
|
foldrun billing plans the plans, which one the account is on and this cycle's credits — also plan <id>, plan cancel, plan resume (asks first)
|
|
196
196
|
foldrun billing top-up <usd> Stripe's checkout page for adding credit (owner only; --no-browser prints it)
|
|
197
197
|
foldrun billing card Stripe's page for saving a card for auto top-up (owner only)
|
|
198
|
-
foldrun billing credit <usd> put credit on the balance by hand (--note "…") — only on an install without Stripe (self-hosted, dev); refused once billing is live
|
|
199
198
|
foldrun gallery the platform's built-in tools (web) and whether you keep your own copy — also pull (a copy for offline runs), upgrade <tool>
|
|
200
199
|
foldrun identity what your cloud must trust for keyless identities: the issuer and each agent's subject (--to <workspace>, --json)
|
|
201
200
|
foldrun jobs the four jobs — governance, guardrail, observability, evaluation — and what each has set (--to <workspace>, --json)
|
package/docs/api.md
CHANGED
|
@@ -353,7 +353,7 @@ Reads return which secrets exist, never their values.
|
|
|
353
353
|
| `/api/account/telemetry/test` | POST | send one made-up run as an OpenTelemetry trace to the collector `telemetry:` names — the account's, or `{ workspace }`'s — with its header secrets filled from the vault; `{ ok, status?, error?, spans?, endpoint }`. `409` when no `telemetry:` is set. Needs `workspace:manage` |
|
|
354
354
|
| `/api/account/jobs?workspace=` | GET | the four jobs (governance, guardrail, observability, evaluation) and each `AGENTS.md` field of each: `{ jobs: [{ name, title, what, fields: [{ key, account, workspace?, combine, writable }] }] }` — the account's value and the workspace's when `workspace` is given (null: unset), as written with blocks folded; `combine` is how the two meet at run time (`workspace replaces`, `either turns it on`, `both apply`, `per key`, `per field`, `level nearest, sites from both`, `account only`); `writable` is whether that scope's settings PATCH (`/api/account`, or the workspace's) writes it — the rest are written in `AGENTS.md`. See [The four jobs](four-jobs) |
|
|
355
355
|
| `/api/account/pause` | GET, POST, DELETE | the account's kill switch: the same as a workspace's `/pause`, for every workspace at once. GET `{ paused, account, workspaces }` (`workspaces`: those paused on their own). POST `{ reason?, stop?: true }`, DELETE resumes the account — a workspace paused on its own stays paused. Needs `workspace:manage` and access to every workspace |
|
|
356
|
-
| `/api/account/close` | POST | the owner asks to close the account — in person, never a key, with `confirm` set to the account's name and an optional `reason`. Not a delete: the account is suspended at once (runs in flight finish, sign-in and the export still work), `closeRequested` is set on its admin state, and the super admin is mailed to settle the last invoice and any refund. Returns `{ ok, suspended, notified }`; 409 when already asked. Hosted installs only |
|
|
356
|
+
| `/api/account/close` | POST | the owner asks to close the account — in person, never a key, with `confirm` set to the account's name and an optional `reason`. Not a delete: the account is suspended at once (runs in flight finish, sign-in and the export still work), `closeRequested` is set on its admin state, and the super admin is mailed to settle the last invoice and any refund. A plan's subscription is set to stop at the end of the period already paid for — nothing renews, no refund — and `billing` says what was done (the close stands even if Stripe could not be reached; `billing` then says so). Returns `{ ok, suspended, notified, billing }`; 409 when already asked. Hosted installs only |
|
|
357
357
|
| `/api/account/backups` | GET | what is backed up for this account: `policy` (`schedule`, `keepLocal`, `keepOffsiteDays`, `encrypted`, `covers`, `excludes`), `last`, `backups` (each nightly archive that holds this account, newest first: `id`, `at`, `bytes` (the encrypted object), `sha256` (the archive inside the encryption — what a decrypt must reproduce), `kinds` — files, database, keys — `verified`, `offsite`, `keepDays`, `encrypted` (sealed with age before it left the server; false for archives taken before October 2026), `recipient` (the key's fingerprint, `sha256:<16 hex>`, or null)), `requests` (earlier restore requests) and `workspaces` (`name`, `head`, `history`, `lastChange`) — what a restore can reach. See [Backups and restore](backups-and-restore.md) |
|
|
358
358
|
| `/api/account/backups/requests` | GET, POST | ask the platform team to restore what an account cannot restore itself. POST `{ what, target, workspace?, backupId?, note? }` (`what` is runs, state, storage or everything) records the request, mails the operator and audits it as `backup.restore_requested`; answers 201 `{ ok, request }` with `notified` saying whether the mail went. Restores nothing. `workspace:manage`, and a member scoped to some workspaces must name one. GET lists this account's requests |
|
|
359
359
|
| `/api/account/api` | GET, PATCH | how this account meets the API — GET `{ version: { current, pinned, effective, supported, supportMonths }, limits: { plan, windowSeconds, perCredential: { read, write }, perAccount: { read, write } }, usage }`. `usage` is the last 30 days — `{ days, versions: [{ version, requests, lastSeen }], deprecated: [{ route, requests, lastSeen, deprecatedAt, sunsetAt, link, callers: [{ credential, requests, lastSeen }] }] }`, `credential` naming a key by its label and prefix — or `null` when it could not be read; PATCH `{ version: "YYYY-MM-DD" \| null }` pins the version API-key requests without a `Foldrun-Version` header get (null: always current); the dashboard always gets current. `keys:manage`. See [api-usage](api-usage.md) |
|
|
@@ -394,7 +394,7 @@ person: a key names an account, never a who.
|
|
|
394
394
|
|
|
395
395
|
| Route | Methods | |
|
|
396
396
|
|---|---|---|
|
|
397
|
-
| `/api/billing` | GET, POST | balance and recent ledger entries; POST
|
|
397
|
+
| `/api/billing` | GET, POST | balance and recent ledger entries; POST answers `404` to every caller — credit comes through checkout (`/api/billing/checkout`) or the platform's console adjustment |
|
|
398
398
|
| `/api/billing/checkout` | POST | a Stripe session (`usd`) |
|
|
399
399
|
| `/api/billing/confirm?session_id=` | GET | settle one |
|
|
400
400
|
| `/api/billing/card` | POST | save a card |
|
|
@@ -403,7 +403,7 @@ person: a key names an account, never a who.
|
|
|
403
403
|
| `/api/billing/statement?month=&format=` | GET | one month of the ledger as a statement. JSON by default; `format=csv` downloads it with the month, the account and the spent and added totals in its header. `month` is `YYYY-MM`, default the current month. What the customer sees is the charge; the platform's provider cost is not on it. The whole account's money, so refused (403) to a member or key scoped to some workspaces, as the audit log is |
|
|
404
404
|
| `/api/billing/wallet` | GET, PUT | the balance summary (burn, runway, daily spend, month to date, the suggested top-up), the refill rule and the low-balance email — GET `{ enabled, stripe, summary, cardSaved, autoTopUp, email, dunning }`, PUT `autoTopUp`, `email`. `dunning.status` is `none`, `grace` (a plan invoice failed; runs go on until `graceUntil`) or `suspended` (new runs paused until it is paid), with `payUrl`, `amountDue` (minor units) and `currency` |
|
|
405
405
|
| `/api/billing/plans` | GET | the catalogue (four plans: fee, credits, per-credit price, runs at once, workspaces, lane), where this account stands (plan, status, this cycle's credits and what is left, when it resets), the balance in dollars and credits, and any overdraft the platform has allowed |
|
|
406
|
-
| `/api/billing/subscribe` | POST, DELETE | POST `plan` — starter, creator, pro or scale. With no subscription yet, answers `url`: a Stripe Checkout in subscription mode; the return trip starts the first cycle. With a live one, changes it at Stripe at once, prorated (an upgrade is invoiced today and the bigger bundle lands with it; a downgrade comes back as credit on the next invoice), and answers `changed: true
|
|
406
|
+
| `/api/billing/subscribe` | POST, DELETE | POST `plan` — starter, creator, pro or scale. With no subscription yet, answers `url`: a Stripe Checkout in subscription mode; the return trip starts the first cycle. With a live one, changes it at Stripe at once, prorated (an upgrade is invoiced today and the bigger bundle lands with it; a downgrade comes back as credit on the next invoice), and answers `changed: true` — only once its prorated invoice is paid: when the payment needs the customer (a declined card, 3-D Secure) the change waits at Stripe as a pending update, nothing about the plan moves, and the answer is 402 `{ pending: true, payUrl }` — paying that invoice applies it; unpaid, Stripe drops it and voids the invoice after 23 hours. A plan set to stop and changed this way stays set to stop once paid — resuming it is the customer's own choice (`resume: true`); nothing resumes on its own. A plan set to stop at the period's end is still that live subscription: choosing a plan takes the stop off (and changes it if it is another plan) — never a second Checkout. With no subscription known here but one still billing at Stripe for the account's customer, 409: a second is not started. POST `resume: true` takes a pending cancellation off — nothing is charged and no cycle moves. DELETE ends the plan with the current cycle: the credits stand until then, and credits bought on top are kept |
|
|
407
407
|
| `/api/billing/stripe` | POST | Stripe's webhook — signature-verified, not for you. Every delivery is logged (see `/api/admin/stripe-events`). Beside top-ups it turns plan cycles: one grant per (subscription, plan, period), whichever of the checkout, `invoice.paid` (either invoice shape) or `customer.subscription.updated` arrives first; `invoice.payment_failed` marks the plan past due and starts dunning (an email, a grace period, then new runs paused — see budgets-and-billing.md), `invoice.paid` and `invoice.voided` end it, `customer.subscription.deleted` ends the plan that subscription paid for — what is left of the bundle expires, the levers come off, money the customer added stays. `charge.refunded` debits a refunded top-up (never a plan fee), `charge.dispute.created` debits a chargeback and `charge.dispute.closed` returns it when won. Answers 500 — so Stripe redelivers — only when a lookup the event needs failed. The full event list is in budgets-and-billing.md |
|
|
408
408
|
|
|
409
409
|
## Versions
|
|
@@ -176,7 +176,9 @@ asked. Without a plan, credit costs 1¢ each, one run at a time, up to 3
|
|
|
176
176
|
workspaces, standard lane — a plan is cheaper from the first month you would have spent its fee
|
|
177
177
|
anyway. Changing plan is charged at once, prorated by Stripe; the new plan
|
|
178
178
|
and its bundle land when that invoice is paid — a change whose payment
|
|
179
|
-
fails leaves you on the plan you had
|
|
179
|
+
fails leaves you on the plan you had, with Stripe's page to pay it; paid
|
|
180
|
+
within 23 hours it goes through, otherwise Stripe drops it and voids the
|
|
181
|
+
invoice. Ending one ends it with the cycle.
|
|
180
182
|
|
|
181
183
|
**Seats are unlimited** on every plan: agents work, people supervise, and a
|
|
182
184
|
per-seat fee would tax the approver the safety story depends on.
|
|
@@ -326,7 +328,7 @@ avatar, with eight tabs:
|
|
|
326
328
|
|
|
327
329
|
| tab | what it is |
|
|
328
330
|
|---|---|
|
|
329
|
-
| **Balance** | the number, large, with how long it lasts in words, thirty days of spend as a sparkline, what is held against runs in flight, and Add credit with the amount that covers a month already chosen
|
|
331
|
+
| **Balance** | the number, large, with how long it lasts in words, thirty days of spend as a sparkline, what is held against runs in flight, and Add credit with the amount that covers a month already chosen |
|
|
330
332
|
| **Plan** | the plan you are on, this cycle's credits and when they reset, and the plans you could move to |
|
|
331
333
|
| **Usage** | what was consumed, from the run records, and what each flow and agent cost by week from the ledger |
|
|
332
334
|
| **Statement** | the ledger as a statement: grouped by day, human labels, month-to-date, filters, and a CSV for the month |
|
package/docs/cli.md
CHANGED
|
@@ -151,7 +151,6 @@ claude.ai or Claude Code there, nor any MCP configuration on disk.
|
|
|
151
151
|
| `foldrun billing` | the account's balance, whether billing is on at all, what the platform is currently waiving, and the recent ledger entries with what each was for — a run names its workspace, flow and run id; an adjustment carries its own note. `--limit <n>` shows more. `statement [YYYY-MM]` is a month of the ledger (this month by default) — `--csv` for the file an accountant wants, to stdout or `--file <path>`. `wallet` is the burn, the runway and auto top-up; `wallet set auto-top-up --threshold <usd> --amount <usd>` turns it on (a refill of 5–500), `set auto-top-up off` turns it off, `set email <address>` is where receipts go. `details` is who invoices are made out to; `details set --name "…" --abn … --address "line1, city, state, postcode, AU" --email …` changes it, merged with what is there. `portal` prints a link to Stripe's billing portal. Changing the wallet, the details, and the portal are the account owner's; anyone else is told so |
|
|
152
152
|
| `foldrun billing plans` | the Plans page: every plan with its monthly fee, credits, runs at once and workspaces, which one the account is on and this cycle's credits left (`GET /api/billing/plans`). `billing plan <id>` chooses one — a first plan answers with Stripe's checkout page, a change on a live plan is prorated at Stripe at once (asks first; `--yes`); `plan cancel` stops it at the end of the cycle, `plan resume` undoes that until then (`POST`/`DELETE /api/billing/subscribe`) |
|
|
153
153
|
| `foldrun billing top-up <usd>` | the Payment page's top-up: Stripe's checkout page for that amount, opened in the browser (`--no-browser`, or no terminal, prints it). The credit lands when Stripe confirms the payment. `billing card` is the same for saving a card for auto top-up. Both need `billing:manage` |
|
|
154
|
-
| `foldrun billing credit <usd>` | put credit on the balance by hand (`POST /api/billing { usd, note }`, `--note "…"` on the ledger line) — on foldrun's hosted platform where Stripe is not connected (a dev install); once billing is live the platform refuses it and top-ups go through `billing top-up`. The dashboard's Billing → Add credit does the same while billing is off. Needs `billing:manage`. A self-hosted install has no billing |
|
|
155
154
|
| `foldrun gallery` | the tools the platform ships to every account (`web`), and for each whether this account keeps its own copy and whether that copy still matches. `pull` lays the shelf down under `~/.foldrun/gallery/<host>/` for offline runs (`foldrun run` and `foldrun eval` refresh it themselves before each run); `upgrade <tool>` replaces the account's copy with the current gallery version, the old one a revision back |
|
|
156
155
|
| `foldrun identity` | keyless cloud identity: the issuer your cloud must trust and the subject each agent's tokens carry (`GET /api/identity`); `--to <workspace>` fills the workspace in, `--json` |
|
|
157
156
|
| `foldrun jobs` | the four jobs — governance, guardrail, observability, evaluation — and every `AGENTS.md` field of each, with what is set (`GET /api/account/jobs`). `--to <workspace>` shows the workspace's value beside the account's and how the two combine; `--json` the document. `account set <job>.<field>` and `workspace set <job>.<field>` refuse a field that scope cannot set and name the `AGENTS.md` to write it in. See [The four jobs](four-jobs) |
|
|
@@ -220,7 +219,7 @@ claude.ai or Claude Code there, nor any MCP configuration on disk.
|
|
|
220
219
|
| `--limit <n>` | `runs`, `billing`, `history`: how many rows, newest first (`runs` default 20, `billing` 15). Each workspace is asked for its own newest `n` before the merge, so one busy desk cannot crowd out a quiet one |
|
|
221
220
|
| `--step <n>` | `approve`, `reject`: decide one gate, numbered as `report` prints it. Without it, every step of that run which is waiting |
|
|
222
221
|
| `--payload <json\|text\|@file>` | `approve`: release a step waiting on `wait: event` with this body (`POST …/approve` `{ payload }`). JSON is sent as JSON, anything else as text; `@file` reads a file |
|
|
223
|
-
| `--note "<text>"` | `approve`: guidance the approved step reads in its prompt — "approve, but skip the Sydney batch". `reject`: the reason, recorded on the trace
|
|
222
|
+
| `--note "<text>"` | `approve`: guidance the approved step reads in its prompt — "approve, but skip the Sydney batch". `reject`: the reason, recorded on the trace |
|
|
224
223
|
| `--yes` | skip the confirmation, deliberately: `approve`, `stop`, `deploy` (when it would delete files), and a bulk `stop` or `rerun`, `flow rotate-hook`, `flow draft`, `assistant`, `history restore`, `restore`, `billing plan`, `repo deploy`/`merge`, `workspace set name`, and every delete — `runs rm`, `storage rm`, `storage unshare`, `source rm`, `secrets rm`, `keys revoke`, `workspaces rm`. Required when there is no terminal to ask; without it nothing is deleted |
|
|
225
224
|
| `--json` | `report`: the raw run record instead of the report. `observe`, `usage`, `workspaces`, `workspaces show`, `agent ls`, `flow ls`, `agent import --list`, `assistant`, `backups requests`, `status --platform --history`, `team`: the raw document |
|
|
226
225
|
| `--events <a,b>` | `account set notify`: which events are notified on — `failed`, `awaiting-approval`, `completed` |
|
package/package.json
CHANGED
package/src/commands.mjs
CHANGED
|
@@ -9838,26 +9838,12 @@ async function billingVerbCmd(positional, flags) {
|
|
|
9838
9838
|
}
|
|
9839
9839
|
|
|
9840
9840
|
if (verb === "credit") {
|
|
9841
|
-
//
|
|
9842
|
-
//
|
|
9843
|
-
// the platform
|
|
9844
|
-
|
|
9845
|
-
if (!(amount > 0) || !Number.isFinite(amount)) throw new Error("`foldrun billing credit <usd> [--note \"…\"]` — a positive amount in USD");
|
|
9846
|
-
let r;
|
|
9847
|
-
try {
|
|
9848
|
-
r = await remoteCall(url, flags, "/api/billing", { method: "POST", body: JSON.stringify({ usd: amount, ...(typeof flags.note === "string" ? { note: flags.note } : {}) }) });
|
|
9849
|
-
} catch (err) {
|
|
9850
|
-
if (err instanceof HttpError && err.status === 403 && /checkout/.test(err.message)) {
|
|
9851
|
-
throw new Error(`billing is live on this platform, so credit is not added by hand — \`foldrun billing top-up ${amount}\` (${err.message})`);
|
|
9852
|
-
}
|
|
9853
|
-
if (err instanceof HttpError && err.status === 403) throw new Error(`billing credit is the account owner's alone (billing:manage) — ${err.message}`);
|
|
9854
|
-
throw err;
|
|
9855
|
-
}
|
|
9856
|
-
const bal = r.balanceUsd;
|
|
9857
|
-
console.log(`\n ${c.green("✓")} credited ${usd(amount)}${bal !== undefined ? c.dim(` · balance ${usd(bal)}`) : ""}${typeof flags.note === "string" ? c.dim(` · "${flags.note}"`) : ""}\n`);
|
|
9858
|
-
return 0;
|
|
9841
|
+
// Credit by hand is gone (FOL-94): the platform's POST /api/billing
|
|
9842
|
+
// answers 404 to every caller. A customer adds credit through checkout;
|
|
9843
|
+
// the platform team credits an account from its console. Nothing is sent.
|
|
9844
|
+
throw new Error("credit is not added by hand — `foldrun billing top-up <usd>` opens Stripe's checkout; for a credit from the platform, ask the platform team");
|
|
9859
9845
|
}
|
|
9860
|
-
throw new Error(`unknown billing verb "${verb}" — statement, wallet, details
|
|
9846
|
+
throw new Error(`unknown billing verb "${verb}" — statement, wallet, details or portal (bare \`foldrun billing\` is the balance)`);
|
|
9861
9847
|
}
|
|
9862
9848
|
|
|
9863
9849
|
/** The defaults a workspace's AGENTS.md sets, read from its source. */
|