fix(hub): delete a team's listing rows with the team; record the new surface

- cascade_delete_org now deletes HubListing: a team with a listing request could not be deleted
  (the foreign key failed with a 500). Found by test_org_delete_clears_EVERY_org_scoped_table.
- tests/snapshots: the two admin listing routes and their schema (scripts/dump_surface.py).
- The five plugin copies of the skill, regenerated after the pricing, listing and capability text
  (scripts/build_plugin.py).
This commit is contained in:
UncleCode
2026-09-24 15:39:51 +08:00
parent 7e21b4a2ab
commit 744200d44f
8 changed files with 285 additions and 75 deletions
+19 -15
View File
@@ -305,8 +305,12 @@ Only tools this org has registered resolve. Discover them with `treg tool ls` ·
that runs in a sandbox. Every step runs through the team's own tools and keys; a caller pays the
metered steps plus the price you set, and the price lands on your balance as credit. The tool is
callable at once by id, `<team-slug>.<name>`, from any agent with a treg token. A new tool is NOT in
search: you share the id or the page `https://treg.to/hub/<id>`. List it with `treg hub list <id>` and it
appears in `catalog_search` too, marked `kind: "hub"`, ranked by relevance like any endpoint.
search: you share the id or the page `https://treg.to/hub/<id>`. Ask for a place in search with `treg hub list <id>`:
once treg approves the request it appears in `catalog_search` too, marked `kind: "hub"`, ranked by
relevance like any endpoint (`treg hub ls` shows where the request stands, and a rejection's reason).
Name the job in recipe.json, `"capability": "people.email.find"` (a capability id from
`treg catalog search`): once approved, `catalog_get` on any provider of that job lists your tool
beside them, with a success rate that starts at an estimate and follows real runs.
**First, check this registry HAS the hub.** It is a per-deployment switch, and it is off by default.
When it is off every `/hub/...` route answers `404` and every `treg hub` command refuses. That is
@@ -332,9 +336,9 @@ treg tool add supabase --base-url https://<ref>.supabase.co \
```
**What a script gets — the whole surface:** `ctx.inputs` (checked against the manifest),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, label)` (bill the caller for an own-key step whose cost treg cannot see: your vendor; needs `pricing.max_charge_usd`, the most all charges may total in one run, shown to the caller),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, note)` (your price, one line at a time; see Pricing below),
`ctx.csv(text)` → rows keyed by the header, `ctx.data` → the rows of the `data.csv` uploaded with
the tool (a fifth file, ≤ 50 MB, read-only; replace it and publish again), and `ctx.log(text)`.
the tool (a fifth file, ≤ 5 MB, read-only; replace it and publish again), and `ctx.log(text)`.
No network, no files, no `require`; `ctx.call` is the only road out, and `target` must be in the
manifest's `uses`: a catalog id, one of the team's own tools as `<tool>/<path>`, or a full URL
under such a tool's base URL. **Your own server is a tool:** `treg tool add my-api --base-url
@@ -344,16 +348,16 @@ Caps: 120 s, 20 calls, 64 MB, four runs at a time per team. A steps recipe inste
`steps` and reads earlier answers with references (`$input.x`, `$step.path`, `$step[]`,
`$step.length`); steps that do not depend on each other run four at a time.
**Pricing — one mode per tool, your price only.** The provider fees (the catalog steps) are billed
to the caller on top; your price is what you earn per successful run. In `recipe.json`, either a
`price_usd`, or a `pricing` block:
- `{"mode": "per_call", "price_usd": 0.02}` — a fixed price per successful run.
- `{"mode": "per_result", "per_result_usd": 0.002, "results_from": "limit"}` — per result returned:
your code returns an integer `results` (declare it as an output field); `results_from` names the
`int` input whose `max` bounds one run.
- `{"mode": "percent", "percent": 5}` — that percent of the run's provider fees (the tool must call
at least one catalog tool).
Callers never see the mode: they see what recent runs cost, low to high, fees and your price together.
**Pricing — your price only.** The provider fees (the catalog steps) are billed to the caller on
top; your price is what you earn per successful run. A failed run charges nothing.
- A steps recipe: `"pricing": {"price_usd": 0.02}`, a fixed price per successful run (0 = free).
- A script: `"pricing": {"max_price_usd": 0.05}`, and the price itself in run.js with
`ctx.charge(usd, note)`, as many lines as you need: a fee (`ctx.charge(0.01, "fee")`), per result
(`ctx.charge(rows.length * 0.002, "per row")`), a margin on a catalog call
(`ctx.charge(r.cost_usd * 0.2, "20% margin")`), your vendor's cost (`ctx.charge(0.03, "vendor hit")`).
The caller sees `max_price_usd` before the run; the run settles at the sum of the lines, and a
line that would pass the cap stops the run. No `pricing` block: free, and ctx.charge is refused.
Callers see what recent runs cost, low to high, fees and your price together.
The caller's `X-Treg-Run-Max-Cost` caps the whole run, your price included; when the caller sends none your
`limits.cost_usd` does (else $1.00). A run that passes the cap is stopped and returns nothing, so a script
that makes several paid calls should add up `cost_usd` and stop early.
@@ -364,7 +368,7 @@ that makes several paid calls should add up `cost_usd` and stop early.
treg hub run . --input domain=figma.com # a real run on your own token; nothing stored; read the trace
treg hub publish . # validate, run check.json once on your balance, live on pass
treg hub ls · treg hub earnings <id> # your tools; what one earned, per day
treg hub list <id> · treg hub unlist <id> # show it in catalog search, or take it out (no version bump)
treg hub list <id> · treg hub unlist <id> # ask for catalog search (treg approves), or take it out
treg hub log <id> --public off # hide the run log on your share page (default: shown)
```
+19 -15
View File
@@ -308,8 +308,12 @@ Only tools this org has registered resolve. Discover them with `treg tool ls` ·
that runs in a sandbox. Every step runs through the team's own tools and keys; a caller pays the
metered steps plus the price you set, and the price lands on your balance as credit. The tool is
callable at once by id, `<team-slug>.<name>`, from any agent with a treg token. A new tool is NOT in
search: you share the id or the page `https://treg.to/hub/<id>`. List it with `treg hub list <id>` and it
appears in `catalog_search` too, marked `kind: "hub"`, ranked by relevance like any endpoint.
search: you share the id or the page `https://treg.to/hub/<id>`. Ask for a place in search with `treg hub list <id>`:
once treg approves the request it appears in `catalog_search` too, marked `kind: "hub"`, ranked by
relevance like any endpoint (`treg hub ls` shows where the request stands, and a rejection's reason).
Name the job in recipe.json, `"capability": "people.email.find"` (a capability id from
`treg catalog search`): once approved, `catalog_get` on any provider of that job lists your tool
beside them, with a success rate that starts at an estimate and follows real runs.
**First, check this registry HAS the hub.** It is a per-deployment switch, and it is off by default.
When it is off every `/hub/...` route answers `404` and every `treg hub` command refuses. That is
@@ -335,9 +339,9 @@ treg tool add supabase --base-url https://<ref>.supabase.co \
```
**What a script gets — the whole surface:** `ctx.inputs` (checked against the manifest),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, label)` (bill the caller for an own-key step whose cost treg cannot see: your vendor; needs `pricing.max_charge_usd`, the most all charges may total in one run, shown to the caller),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, note)` (your price, one line at a time; see Pricing below),
`ctx.csv(text)` → rows keyed by the header, `ctx.data` → the rows of the `data.csv` uploaded with
the tool (a fifth file, ≤ 50 MB, read-only; replace it and publish again), and `ctx.log(text)`.
the tool (a fifth file, ≤ 5 MB, read-only; replace it and publish again), and `ctx.log(text)`.
No network, no files, no `require`; `ctx.call` is the only road out, and `target` must be in the
manifest's `uses`: a catalog id, one of the team's own tools as `<tool>/<path>`, or a full URL
under such a tool's base URL. **Your own server is a tool:** `treg tool add my-api --base-url
@@ -347,16 +351,16 @@ Caps: 120 s, 20 calls, 64 MB, four runs at a time per team. A steps recipe inste
`steps` and reads earlier answers with references (`$input.x`, `$step.path`, `$step[]`,
`$step.length`); steps that do not depend on each other run four at a time.
**Pricing — one mode per tool, your price only.** The provider fees (the catalog steps) are billed
to the caller on top; your price is what you earn per successful run. In `recipe.json`, either a
`price_usd`, or a `pricing` block:
- `{"mode": "per_call", "price_usd": 0.02}` — a fixed price per successful run.
- `{"mode": "per_result", "per_result_usd": 0.002, "results_from": "limit"}` — per result returned:
your code returns an integer `results` (declare it as an output field); `results_from` names the
`int` input whose `max` bounds one run.
- `{"mode": "percent", "percent": 5}` — that percent of the run's provider fees (the tool must call
at least one catalog tool).
Callers never see the mode: they see what recent runs cost, low to high, fees and your price together.
**Pricing — your price only.** The provider fees (the catalog steps) are billed to the caller on
top; your price is what you earn per successful run. A failed run charges nothing.
- A steps recipe: `"pricing": {"price_usd": 0.02}`, a fixed price per successful run (0 = free).
- A script: `"pricing": {"max_price_usd": 0.05}`, and the price itself in run.js with
`ctx.charge(usd, note)`, as many lines as you need: a fee (`ctx.charge(0.01, "fee")`), per result
(`ctx.charge(rows.length * 0.002, "per row")`), a margin on a catalog call
(`ctx.charge(r.cost_usd * 0.2, "20% margin")`), your vendor's cost (`ctx.charge(0.03, "vendor hit")`).
The caller sees `max_price_usd` before the run; the run settles at the sum of the lines, and a
line that would pass the cap stops the run. No `pricing` block: free, and ctx.charge is refused.
Callers see what recent runs cost, low to high, fees and your price together.
The caller's `X-Treg-Run-Max-Cost` caps the whole run, your price included; when the caller sends none your
`limits.cost_usd` does (else $1.00). A run that passes the cap is stopped and returns nothing, so a script
that makes several paid calls should add up `cost_usd` and stop early.
@@ -367,7 +371,7 @@ that makes several paid calls should add up `cost_usd` and stop early.
treg hub run . --input domain=figma.com # a real run on your own token; nothing stored; read the trace
treg hub publish . # validate, run check.json once on your balance, live on pass
treg hub ls · treg hub earnings <id> # your tools; what one earned, per day
treg hub list <id> · treg hub unlist <id> # show it in catalog search, or take it out (no version bump)
treg hub list <id> · treg hub unlist <id> # ask for catalog search (treg approves), or take it out
treg hub log <id> --public off # hide the run log on your share page (default: shown)
```
+19 -15
View File
@@ -289,8 +289,12 @@ Only tools this org has registered resolve. Discover them with `treg tool ls` ·
that runs in a sandbox. Every step runs through the team's own tools and keys; a caller pays the
metered steps plus the price you set, and the price lands on your balance as credit. The tool is
callable at once by id, `<team-slug>.<name>`, from any agent with a treg token. A new tool is NOT in
search: you share the id or the page `https://treg.to/hub/<id>`. List it with `treg hub list <id>` and it
appears in `catalog_search` too, marked `kind: "hub"`, ranked by relevance like any endpoint.
search: you share the id or the page `https://treg.to/hub/<id>`. Ask for a place in search with `treg hub list <id>`:
once treg approves the request it appears in `catalog_search` too, marked `kind: "hub"`, ranked by
relevance like any endpoint (`treg hub ls` shows where the request stands, and a rejection's reason).
Name the job in recipe.json, `"capability": "people.email.find"` (a capability id from
`treg catalog search`): once approved, `catalog_get` on any provider of that job lists your tool
beside them, with a success rate that starts at an estimate and follows real runs.
**First, check this registry HAS the hub.** It is a per-deployment switch, and it is off by default.
When it is off every `/hub/...` route answers `404` and every `treg hub` command refuses. That is
@@ -316,9 +320,9 @@ treg tool add supabase --base-url https://<ref>.supabase.co \
```
**What a script gets — the whole surface:** `ctx.inputs` (checked against the manifest),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, label)` (bill the caller for an own-key step whose cost treg cannot see: your vendor; needs `pricing.max_charge_usd`, the most all charges may total in one run, shown to the caller),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, note)` (your price, one line at a time; see Pricing below),
`ctx.csv(text)` → rows keyed by the header, `ctx.data` → the rows of the `data.csv` uploaded with
the tool (a fifth file, ≤ 50 MB, read-only; replace it and publish again), and `ctx.log(text)`.
the tool (a fifth file, ≤ 5 MB, read-only; replace it and publish again), and `ctx.log(text)`.
No network, no files, no `require`; `ctx.call` is the only road out, and `target` must be in the
manifest's `uses`: a catalog id, one of the team's own tools as `<tool>/<path>`, or a full URL
under such a tool's base URL. **Your own server is a tool:** `treg tool add my-api --base-url
@@ -328,16 +332,16 @@ Caps: 120 s, 20 calls, 64 MB, four runs at a time per team. A steps recipe inste
`steps` and reads earlier answers with references (`$input.x`, `$step.path`, `$step[]`,
`$step.length`); steps that do not depend on each other run four at a time.
**Pricing — one mode per tool, your price only.** The provider fees (the catalog steps) are billed
to the caller on top; your price is what you earn per successful run. In `recipe.json`, either a
`price_usd`, or a `pricing` block:
- `{"mode": "per_call", "price_usd": 0.02}` — a fixed price per successful run.
- `{"mode": "per_result", "per_result_usd": 0.002, "results_from": "limit"}` — per result returned:
your code returns an integer `results` (declare it as an output field); `results_from` names the
`int` input whose `max` bounds one run.
- `{"mode": "percent", "percent": 5}` — that percent of the run's provider fees (the tool must call
at least one catalog tool).
Callers never see the mode: they see what recent runs cost, low to high, fees and your price together.
**Pricing — your price only.** The provider fees (the catalog steps) are billed to the caller on
top; your price is what you earn per successful run. A failed run charges nothing.
- A steps recipe: `"pricing": {"price_usd": 0.02}`, a fixed price per successful run (0 = free).
- A script: `"pricing": {"max_price_usd": 0.05}`, and the price itself in run.js with
`ctx.charge(usd, note)`, as many lines as you need: a fee (`ctx.charge(0.01, "fee")`), per result
(`ctx.charge(rows.length * 0.002, "per row")`), a margin on a catalog call
(`ctx.charge(r.cost_usd * 0.2, "20% margin")`), your vendor's cost (`ctx.charge(0.03, "vendor hit")`).
The caller sees `max_price_usd` before the run; the run settles at the sum of the lines, and a
line that would pass the cap stops the run. No `pricing` block: free, and ctx.charge is refused.
Callers see what recent runs cost, low to high, fees and your price together.
The caller's `X-Treg-Run-Max-Cost` caps the whole run, your price included; when the caller sends none your
`limits.cost_usd` does (else $1.00). A run that passes the cap is stopped and returns nothing, so a script
that makes several paid calls should add up `cost_usd` and stop early.
@@ -348,7 +352,7 @@ that makes several paid calls should add up `cost_usd` and stop early.
treg hub run . --input domain=figma.com # a real run on your own token; nothing stored; read the trace
treg hub publish . # validate, run check.json once on your balance, live on pass
treg hub ls · treg hub earnings <id> # your tools; what one earned, per day
treg hub list <id> · treg hub unlist <id> # show it in catalog search, or take it out (no version bump)
treg hub list <id> · treg hub unlist <id> # ask for catalog search (treg approves), or take it out
treg hub log <id> --public off # hide the run log on your share page (default: shown)
```
+19 -15
View File
@@ -303,8 +303,12 @@ Only tools this org has registered resolve. Discover them with `treg tool ls` ·
that runs in a sandbox. Every step runs through the team's own tools and keys; a caller pays the
metered steps plus the price you set, and the price lands on your balance as credit. The tool is
callable at once by id, `<team-slug>.<name>`, from any agent with a treg token. A new tool is NOT in
search: you share the id or the page `https://treg.to/hub/<id>`. List it with `treg hub list <id>` and it
appears in `catalog_search` too, marked `kind: "hub"`, ranked by relevance like any endpoint.
search: you share the id or the page `https://treg.to/hub/<id>`. Ask for a place in search with `treg hub list <id>`:
once treg approves the request it appears in `catalog_search` too, marked `kind: "hub"`, ranked by
relevance like any endpoint (`treg hub ls` shows where the request stands, and a rejection's reason).
Name the job in recipe.json, `"capability": "people.email.find"` (a capability id from
`treg catalog search`): once approved, `catalog_get` on any provider of that job lists your tool
beside them, with a success rate that starts at an estimate and follows real runs.
**First, check this registry HAS the hub.** It is a per-deployment switch, and it is off by default.
When it is off every `/hub/...` route answers `404` and every `treg hub` command refuses. That is
@@ -330,9 +334,9 @@ treg tool add supabase --base-url https://<ref>.supabase.co \
```
**What a script gets — the whole surface:** `ctx.inputs` (checked against the manifest),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, label)` (bill the caller for an own-key step whose cost treg cannot see: your vendor; needs `pricing.max_charge_usd`, the most all charges may total in one run, shown to the caller),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, note)` (your price, one line at a time; see Pricing below),
`ctx.csv(text)` → rows keyed by the header, `ctx.data` → the rows of the `data.csv` uploaded with
the tool (a fifth file, ≤ 50 MB, read-only; replace it and publish again), and `ctx.log(text)`.
the tool (a fifth file, ≤ 5 MB, read-only; replace it and publish again), and `ctx.log(text)`.
No network, no files, no `require`; `ctx.call` is the only road out, and `target` must be in the
manifest's `uses`: a catalog id, one of the team's own tools as `<tool>/<path>`, or a full URL
under such a tool's base URL. **Your own server is a tool:** `treg tool add my-api --base-url
@@ -342,16 +346,16 @@ Caps: 120 s, 20 calls, 64 MB, four runs at a time per team. A steps recipe inste
`steps` and reads earlier answers with references (`$input.x`, `$step.path`, `$step[]`,
`$step.length`); steps that do not depend on each other run four at a time.
**Pricing — one mode per tool, your price only.** The provider fees (the catalog steps) are billed
to the caller on top; your price is what you earn per successful run. In `recipe.json`, either a
`price_usd`, or a `pricing` block:
- `{"mode": "per_call", "price_usd": 0.02}` — a fixed price per successful run.
- `{"mode": "per_result", "per_result_usd": 0.002, "results_from": "limit"}` — per result returned:
your code returns an integer `results` (declare it as an output field); `results_from` names the
`int` input whose `max` bounds one run.
- `{"mode": "percent", "percent": 5}` — that percent of the run's provider fees (the tool must call
at least one catalog tool).
Callers never see the mode: they see what recent runs cost, low to high, fees and your price together.
**Pricing — your price only.** The provider fees (the catalog steps) are billed to the caller on
top; your price is what you earn per successful run. A failed run charges nothing.
- A steps recipe: `"pricing": {"price_usd": 0.02}`, a fixed price per successful run (0 = free).
- A script: `"pricing": {"max_price_usd": 0.05}`, and the price itself in run.js with
`ctx.charge(usd, note)`, as many lines as you need: a fee (`ctx.charge(0.01, "fee")`), per result
(`ctx.charge(rows.length * 0.002, "per row")`), a margin on a catalog call
(`ctx.charge(r.cost_usd * 0.2, "20% margin")`), your vendor's cost (`ctx.charge(0.03, "vendor hit")`).
The caller sees `max_price_usd` before the run; the run settles at the sum of the lines, and a
line that would pass the cap stops the run. No `pricing` block: free, and ctx.charge is refused.
Callers see what recent runs cost, low to high, fees and your price together.
The caller's `X-Treg-Run-Max-Cost` caps the whole run, your price included; when the caller sends none your
`limits.cost_usd` does (else $1.00). A run that passes the cap is stopped and returns nothing, so a script
that makes several paid calls should add up `cost_usd` and stop early.
@@ -362,7 +366,7 @@ that makes several paid calls should add up `cost_usd` and stop early.
treg hub run . --input domain=figma.com # a real run on your own token; nothing stored; read the trace
treg hub publish . # validate, run check.json once on your balance, live on pass
treg hub ls · treg hub earnings <id> # your tools; what one earned, per day
treg hub list <id> · treg hub unlist <id> # show it in catalog search, or take it out (no version bump)
treg hub list <id> · treg hub unlist <id> # ask for catalog search (treg approves), or take it out
treg hub log <id> --public off # hide the run log on your share page (default: shown)
```
+19 -15
View File
@@ -287,8 +287,12 @@ Only tools this org has registered resolve. Discover them with `treg tool ls` ·
that runs in a sandbox. Every step runs through the team's own tools and keys; a caller pays the
metered steps plus the price you set, and the price lands on your balance as credit. The tool is
callable at once by id, `<team-slug>.<name>`, from any agent with a treg token. A new tool is NOT in
search: you share the id or the page `https://treg.to/hub/<id>`. List it with `treg hub list <id>` and it
appears in `catalog_search` too, marked `kind: "hub"`, ranked by relevance like any endpoint.
search: you share the id or the page `https://treg.to/hub/<id>`. Ask for a place in search with `treg hub list <id>`:
once treg approves the request it appears in `catalog_search` too, marked `kind: "hub"`, ranked by
relevance like any endpoint (`treg hub ls` shows where the request stands, and a rejection's reason).
Name the job in recipe.json, `"capability": "people.email.find"` (a capability id from
`treg catalog search`): once approved, `catalog_get` on any provider of that job lists your tool
beside them, with a success rate that starts at an estimate and follows real runs.
**First, check this registry HAS the hub.** It is a per-deployment switch, and it is off by default.
When it is off every `/hub/...` route answers `404` and every `treg hub` command refuses. That is
@@ -314,9 +318,9 @@ treg tool add supabase --base-url https://<ref>.supabase.co \
```
**What a script gets — the whole surface:** `ctx.inputs` (checked against the manifest),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, label)` (bill the caller for an own-key step whose cost treg cannot see: your vendor; needs `pricing.max_charge_usd`, the most all charges may total in one run, shown to the caller),
`ctx.call(target, {method, query, body, headers, timeout_s})` → `{status, headers, json, text, timed_out, cost_usd}` (calls in one `Promise.all` run four at once), `ctx.charge(usd, note)` (your price, one line at a time; see Pricing below),
`ctx.csv(text)` → rows keyed by the header, `ctx.data` → the rows of the `data.csv` uploaded with
the tool (a fifth file, ≤ 50 MB, read-only; replace it and publish again), and `ctx.log(text)`.
the tool (a fifth file, ≤ 5 MB, read-only; replace it and publish again), and `ctx.log(text)`.
No network, no files, no `require`; `ctx.call` is the only road out, and `target` must be in the
manifest's `uses`: a catalog id, one of the team's own tools as `<tool>/<path>`, or a full URL
under such a tool's base URL. **Your own server is a tool:** `treg tool add my-api --base-url
@@ -326,16 +330,16 @@ Caps: 120 s, 20 calls, 64 MB, four runs at a time per team. A steps recipe inste
`steps` and reads earlier answers with references (`$input.x`, `$step.path`, `$step[]`,
`$step.length`); steps that do not depend on each other run four at a time.
**Pricing — one mode per tool, your price only.** The provider fees (the catalog steps) are billed
to the caller on top; your price is what you earn per successful run. In `recipe.json`, either a
`price_usd`, or a `pricing` block:
- `{"mode": "per_call", "price_usd": 0.02}` — a fixed price per successful run.
- `{"mode": "per_result", "per_result_usd": 0.002, "results_from": "limit"}` — per result returned:
your code returns an integer `results` (declare it as an output field); `results_from` names the
`int` input whose `max` bounds one run.
- `{"mode": "percent", "percent": 5}` — that percent of the run's provider fees (the tool must call
at least one catalog tool).
Callers never see the mode: they see what recent runs cost, low to high, fees and your price together.
**Pricing — your price only.** The provider fees (the catalog steps) are billed to the caller on
top; your price is what you earn per successful run. A failed run charges nothing.
- A steps recipe: `"pricing": {"price_usd": 0.02}`, a fixed price per successful run (0 = free).
- A script: `"pricing": {"max_price_usd": 0.05}`, and the price itself in run.js with
`ctx.charge(usd, note)`, as many lines as you need: a fee (`ctx.charge(0.01, "fee")`), per result
(`ctx.charge(rows.length * 0.002, "per row")`), a margin on a catalog call
(`ctx.charge(r.cost_usd * 0.2, "20% margin")`), your vendor's cost (`ctx.charge(0.03, "vendor hit")`).
The caller sees `max_price_usd` before the run; the run settles at the sum of the lines, and a
line that would pass the cap stops the run. No `pricing` block: free, and ctx.charge is refused.
Callers see what recent runs cost, low to high, fees and your price together.
The caller's `X-Treg-Run-Max-Cost` caps the whole run, your price included; when the caller sends none your
`limits.cost_usd` does (else $1.00). A run that passes the cap is stopped and returns nothing, so a script
that makes several paid calls should add up `cost_usd` and stop early.
@@ -346,7 +350,7 @@ that makes several paid calls should add up `cost_usd` and stop early.
treg hub run . --input domain=figma.com # a real run on your own token; nothing stored; read the trace
treg hub publish . # validate, run check.json once on your balance, live on pass
treg hub ls · treg hub earnings <id> # your tools; what one earned, per day
treg hub list <id> · treg hub unlist <id> # show it in catalog search, or take it out (no version bump)
treg hub list <id> · treg hub unlist <id> # ask for catalog search (treg approves), or take it out
treg hub log <id> --public off # hide the run log on your share page (default: shown)
```
+2
View File
@@ -23,6 +23,7 @@ from ...models import (
CallReview,
Media,
Hold,
HubListing,
HubRun,
HubTool,
IdempotentCall,
@@ -208,6 +209,7 @@ ORG_SCOPED_MODELS = (
IdempotentCall, # a remembered answer belongs to the team that paid for it
ToolRequest, # attribution rows go with the team; anonymous filings carry no org_id and stay
Feedback,
HubListing, # a tool's search listing goes with the team that asked for it
HubTool, # a maker's published tools go with the team that owned them
CallReview,
Media, # hosted reference files expire on their own; a deleted team's go now
+171
View File
@@ -594,6 +594,39 @@
"title": "KeyNameIn",
"type": "object"
},
"ListingDecisionIn": {
"additionalProperties": false,
"properties": {
"capability": {
"anyOf": [
{
"maxLength": 200,
"type": "string"
},
{
"type": "null"
}
],
"title": "Capability"
},
"decision": {
"pattern": "^(approve|reject)$",
"title": "Decision",
"type": "string"
},
"reason": {
"default": "",
"maxLength": 500,
"title": "Reason",
"type": "string"
}
},
"required": [
"decision"
],
"title": "ListingDecisionIn",
"type": "object"
},
"OAuthStartIn": {
"description": "Two modes. BYO: supply client_id/client_secret/auth_uri/token_uri/scopes yourself.\nREGISTRY: supply `provider` (+ optional `capability`) and treg fills all of it from its own\napproved app — see oauth_providers.py.",
"properties": {
@@ -2186,6 +2219,144 @@
"summary": "Admin Health"
}
},
"/admin/hub/listings": {
"get": {
"description": "The review queue: listing requests in `state` (requested | approved | rejected), oldest first.",
"operationId": "admin_hub_listings_admin_hub_listings_get",
"parameters": [
{
"in": "query",
"name": "state",
"required": false,
"schema": {
"default": "requested",
"title": "State",
"type": "string"
}
},
{
"in": "header",
"name": "x-treg-token",
"required": false,
"schema": {
"default": "",
"title": "X-Treg-Token",
"type": "string"
}
},
{
"in": "cookie",
"name": "treg_session",
"required": false,
"schema": {
"default": "",
"title": "Treg Session",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"additionalProperties": true,
"type": "object"
},
"title": "Response Admin Hub Listings Admin Hub Listings Get",
"type": "array"
}
}
},
"description": "Successful Response"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
"description": "Validation Error"
}
},
"summary": "Admin Hub Listings"
}
},
"/admin/hub/listings/{tool_id}": {
"post": {
"description": "Approve (the tool enters search, beside the providers of its capability) or reject (it leaves\nsearch; the maker reads the reason). A rejection needs a reason: the maker has to know what to fix.",
"operationId": "admin_hub_listing_decide_admin_hub_listings__tool_id__post",
"parameters": [
{
"in": "path",
"name": "tool_id",
"required": true,
"schema": {
"title": "Tool Id",
"type": "string"
}
},
{
"in": "header",
"name": "x-treg-token",
"required": false,
"schema": {
"default": "",
"title": "X-Treg-Token",
"type": "string"
}
},
{
"in": "cookie",
"name": "treg_session",
"required": false,
"schema": {
"default": "",
"title": "Treg Session",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ListingDecisionIn"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": true,
"title": "Response Admin Hub Listing Decide Admin Hub Listings Tool Id Post",
"type": "object"
}
}
},
"description": "Successful Response"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
"description": "Validation Error"
}
},
"summary": "Admin Hub Listing Decide"
}
},
"/admin/orgs": {
"get": {
"operationId": "admin_orgs_admin_orgs_get",
+17
View File
@@ -405,6 +405,23 @@
"name": "hub_tool_health",
"path": "/hub/tools/{tool_id}/health"
},
{
"kind": "APIRoute",
"methods": [
"GET",
"HEAD"
],
"name": "admin_hub_listings",
"path": "/admin/hub/listings"
},
{
"kind": "APIRoute",
"methods": [
"POST"
],
"name": "admin_hub_listing_decide",
"path": "/admin/hub/listings/{tool_id}"
},
{
"kind": "APIRoute",
"methods": [