x402-agent-gateway 0.1.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 +119 -0
- package/bin/cli.js +116 -0
- package/package.json +51 -0
- package/src/index.js +128 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# x402 Agent Gateway
|
|
2
|
+
|
|
3
|
+
Pay-per-call APIs for autonomous agents, settled in USDC over [x402](https://x402.org).
|
|
4
|
+
No account, no API key, no subscription. An agent discovers the endpoint, gets a `402`
|
|
5
|
+
with the exact amount, pays, and gets the result.
|
|
6
|
+
|
|
7
|
+
Live API: `https://api.x-402.online`
|
|
8
|
+
|
|
9
|
+
## Start here: the free quote
|
|
10
|
+
|
|
11
|
+
Nothing below costs anything until you choose to pay. Two endpoints are free and require
|
|
12
|
+
no wallet at all.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx x402-agent-gateway capabilities # what can be solved
|
|
16
|
+
npx x402-agent-gateway preview "summarise ethereum etf news" # the plan and the price
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The quote tells you which capability was chosen, why, what it costs, **and when a direct
|
|
20
|
+
route would be cheaper than the gateway**. The gateway has a single price, so it overcharges
|
|
21
|
+
for cheap capabilities. You should know that before you pay, not after.
|
|
22
|
+
|
|
23
|
+
## The flagship product
|
|
24
|
+
|
|
25
|
+
**`POST /v1/us/brief` — $0.040004**
|
|
26
|
+
|
|
27
|
+
A decision-grade briefing on a US public company, from SEC EDGAR, in one call:
|
|
28
|
+
|
|
29
|
+
- a summary where **every claim cites its origin**: `[identity]`, `[financials]`, `[filings]`
|
|
30
|
+
- key points and the open questions the data does not settle
|
|
31
|
+
- **the underlying facts alongside**: identity, three years of annual figures, recent filings
|
|
32
|
+
|
|
33
|
+
Buying the three underlying routes separately costs **$0.090024**. This replaces them with a
|
|
34
|
+
synthesised answer for **56% less**, and you can still verify every claim because the raw
|
|
35
|
+
facts come back with it.
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import { Gateway } from "x402-agent-gateway";
|
|
39
|
+
|
|
40
|
+
const g = new Gateway({ fetch: myX402Fetch }); // any x402-capable fetch
|
|
41
|
+
const r = await g.usBrief("AAPL");
|
|
42
|
+
|
|
43
|
+
r.brief.summary // "Apple Inc. (CIK 0000320193) is a Nasdaq-listed … [identity]"
|
|
44
|
+
r.brief.key_points // each one cites its source
|
|
45
|
+
r.financials.revenue // the raw figures, to check the summary against
|
|
46
|
+
r.filings // the recent SEC filings
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from x402_gateway import Gateway
|
|
51
|
+
g = Gateway()
|
|
52
|
+
r = g.us_brief("AAPL")
|
|
53
|
+
print(r["brief"]["summary"], r["financials"]["revenue"])
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Without a payment-capable fetch, `usBrief` raises `PaymentRequired` **carrying the x402
|
|
57
|
+
challenge** — amount, network and address. Pay it with whatever tooling you already use.
|
|
58
|
+
This SDK does not impose its own.
|
|
59
|
+
|
|
60
|
+
## Capabilities behind one endpoint
|
|
61
|
+
|
|
62
|
+
`POST /v1/solve` — $0.012002. Send a task in plain words, or name a capability and its
|
|
63
|
+
input. The gateway resolves which capability is needed, ranks providers by expected net
|
|
64
|
+
margin and observed success rate, executes, falls back to the next provider on failure, and
|
|
65
|
+
returns the result with the routing it used.
|
|
66
|
+
|
|
67
|
+
| capability | what it does |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `company_brief_us` | the SEC briefing above |
|
|
70
|
+
| `web_search` | ranked web results |
|
|
71
|
+
| `news_search` | fresh headlines |
|
|
72
|
+
| `news_brief` | headlines plus a sourced summary |
|
|
73
|
+
| `llm_generate` | text generation, two providers, one engine |
|
|
74
|
+
| `web_extract` | a page as clean markdown, French residential IP, real browser |
|
|
75
|
+
| `web_render` | full HTML after JavaScript execution |
|
|
76
|
+
|
|
77
|
+
`GET /v1/capabilities` returns the input and output schemas, and lists only what is actually
|
|
78
|
+
servable right now.
|
|
79
|
+
|
|
80
|
+
## Discovery, for machines
|
|
81
|
+
|
|
82
|
+
| surface | what it carries |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `/openapi.json` | the full OpenAPI description |
|
|
85
|
+
| `/llms.txt` | a plain-text summary for language models |
|
|
86
|
+
| `/.well-known/x402` | the x402 payment metadata |
|
|
87
|
+
| `/.well-known/agent-card.json` | the A2A Agent Card, protocol 0.3.0 |
|
|
88
|
+
| `/mcp` | an MCP server, 63 tools, `tools/list` over JSON-RPC |
|
|
89
|
+
| `/v1/capabilities` | the gateway's capability registry |
|
|
90
|
+
|
|
91
|
+
## Payment
|
|
92
|
+
|
|
93
|
+
x402, `exact` scheme, USDC on Base (`eip155:8453`) and Solana. Each route has a **unique**
|
|
94
|
+
amount, so every settlement is attributable on-chain by the amount alone. `/v1/us/brief`
|
|
95
|
+
is `40004` micro-USDC, `/v1/solve` is `12002`.
|
|
96
|
+
|
|
97
|
+
## Install
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm install x402-agent-gateway # Node 20+
|
|
101
|
+
pip install x402-agent-gateway # Python 3.10+, no dependencies
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Both are in this repository under `node/` and `python/`. If the published packages are not
|
|
105
|
+
up yet, point the client at the API directly — the SDK is a thin, optional convenience:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
curl -s -X POST https://api.x-402.online/v1/us/brief \
|
|
109
|
+
-H 'content-type: application/json' -d '{"ticker":"AAPL"}'
|
|
110
|
+
# → 402 with the exact amount to pay
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## What this is not
|
|
114
|
+
|
|
115
|
+
Not investment advice. `/v1/us/brief` reports what SEC EDGAR contains and cites it; it never
|
|
116
|
+
recommends buying or selling anything, and it says in `open_questions` what the filings do
|
|
117
|
+
not answer rather than filling the gap with a guess.
|
|
118
|
+
|
|
119
|
+
MIT licensed.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// CLI du gateway. Trois verbes, et le devis est celui qu'on tape en premier parce qu'il
|
|
3
|
+
// est gratuit : on voit le plan et le prix avant de sortir un portefeuille.
|
|
4
|
+
|
|
5
|
+
import { Gateway, PaymentRequired, GatewayError } from "../src/index.js";
|
|
6
|
+
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
const verbe = args[0];
|
|
9
|
+
const reste = args.slice(1);
|
|
10
|
+
|
|
11
|
+
function opt(nom, defaut) {
|
|
12
|
+
const i = reste.indexOf(`--${nom}`);
|
|
13
|
+
if (i === -1) return defaut;
|
|
14
|
+
const v = reste[i + 1];
|
|
15
|
+
reste.splice(i, 2);
|
|
16
|
+
return v;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const base = opt("url", process.env.GATEWAY_URL);
|
|
20
|
+
const cle = opt("key", process.env.GATEWAY_API_KEY);
|
|
21
|
+
const json = reste.includes("--json") && reste.splice(reste.indexOf("--json"), 1);
|
|
22
|
+
const g = new Gateway({ baseUrl: base, apiKey: cle });
|
|
23
|
+
|
|
24
|
+
const AIDE = `agent-gateway — une intégration pour toutes les capacités
|
|
25
|
+
|
|
26
|
+
agent-gateway capabilities ce que le gateway sait faire (gratuit)
|
|
27
|
+
agent-gateway preview "<tâche>" le plan et le prix, sans exécuter (gratuit)
|
|
28
|
+
agent-gateway solve "<tâche>" exécute et livre (x402)
|
|
29
|
+
|
|
30
|
+
Options
|
|
31
|
+
--capability <nom> impose la capacité au lieu de la deviner
|
|
32
|
+
--input '<json>' l'entrée, quand on impose la capacité
|
|
33
|
+
--url <base> défaut https://api.x-402.online (ou GATEWAY_URL)
|
|
34
|
+
--key <clé> clé interne, pour un accès sans x402 (ou GATEWAY_API_KEY)
|
|
35
|
+
--json sortie brute, pour un script`;
|
|
36
|
+
|
|
37
|
+
function demande() {
|
|
38
|
+
const cap = opt("capability", null);
|
|
39
|
+
if (cap) {
|
|
40
|
+
const brut = opt("input", "{}");
|
|
41
|
+
let input;
|
|
42
|
+
try { input = JSON.parse(brut); }
|
|
43
|
+
catch { sortir(`--input n'est pas du JSON valide : ${brut}`); }
|
|
44
|
+
return { capability: cap, input };
|
|
45
|
+
}
|
|
46
|
+
const tache = reste.filter((a) => !a.startsWith("--")).join(" ").trim();
|
|
47
|
+
if (!tache) sortir("il faut une tâche, ou --capability avec --input");
|
|
48
|
+
return { task: tache };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function sortir(msg, code = 1) {
|
|
52
|
+
console.error(`erreur : ${msg}`);
|
|
53
|
+
process.exit(code);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
if (!verbe || verbe === "help" || verbe === "--help" || verbe === "-h") {
|
|
58
|
+
console.log(AIDE);
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (verbe === "capabilities") {
|
|
63
|
+
const r = await g.capabilities();
|
|
64
|
+
if (json) { console.log(JSON.stringify(r, null, 2)); process.exit(0); }
|
|
65
|
+
console.log(`prix par solve : ${r.price_per_solve_usd} $ · paiement ${r.payment.protocol} ${r.payment.asset}\n`);
|
|
66
|
+
for (const c of r.capabilities) {
|
|
67
|
+
console.log(` ${c.capability.padEnd(20)} ${String(c.providers).padStart(2)} provider(s) · ~${c.latency_ms_estimee} ms`);
|
|
68
|
+
console.log(` ${" ".repeat(20)} ${c.description}`);
|
|
69
|
+
}
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (verbe === "preview") {
|
|
74
|
+
const r = await g.preview(demande());
|
|
75
|
+
if (json) { console.log(JSON.stringify(r, null, 2)); process.exit(0); }
|
|
76
|
+
const q = r.quote;
|
|
77
|
+
console.log(`capacité ${q.capability}`);
|
|
78
|
+
console.log(`pourquoi ${q.why_this_capability}`);
|
|
79
|
+
console.log(`entrée ${JSON.stringify(q.normalized_input)}`);
|
|
80
|
+
console.log(`prix ${q.price_usd} $ (${q.payment.amount_micro} micro-USDC)`);
|
|
81
|
+
console.log(`providers ${q.providers_in_order.join(" puis ")}`);
|
|
82
|
+
console.log(`exécutera ${q.will_execute}${q.refused_because ? ` — ${q.refused_because}` : ""}`);
|
|
83
|
+
if (q.cheaper_direct) {
|
|
84
|
+
console.log(`\nmoins cher en direct : ${q.cheaper_direct.route} à ${q.cheaper_direct.price_usd} $ (${q.cheaper_direct.you_save_usd} $ économisés)`);
|
|
85
|
+
console.log(` ${q.cheaper_direct.note}`);
|
|
86
|
+
}
|
|
87
|
+
process.exit(0);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (verbe === "solve") {
|
|
91
|
+
const r = await g.solve(demande());
|
|
92
|
+
if (json) { console.log(JSON.stringify(r, null, 2)); process.exit(0); }
|
|
93
|
+
console.log(`capacité ${r.capability} · ${r.routing.provider} · ${r.routing.latency_ms} ms`);
|
|
94
|
+
if (r.routing.attempts.length > 1) {
|
|
95
|
+
console.log(`tentatives : ${r.routing.attempts.map((a) => `${a.provider}${a.ok ? " ok" : " échec"}`).join(" | ")}`);
|
|
96
|
+
}
|
|
97
|
+
console.log("");
|
|
98
|
+
console.log(JSON.stringify(r.result, null, 2));
|
|
99
|
+
process.exit(0);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
sortir(`verbe inconnu « ${verbe} »\n\n${AIDE}`);
|
|
103
|
+
} catch (e) {
|
|
104
|
+
if (e instanceof PaymentRequired) {
|
|
105
|
+
console.error("paiement requis. Le défi x402 :");
|
|
106
|
+
for (const a of e.accepts) console.error(` ${a.network} · ${a.amount} (micro-USDC) · vers ${a.payTo}`);
|
|
107
|
+
console.error("\nUtilise « preview » pour voir le plan sans payer, ou passe un fetch payeur au SDK.");
|
|
108
|
+
process.exit(2);
|
|
109
|
+
}
|
|
110
|
+
if (e instanceof GatewayError) {
|
|
111
|
+
console.error(`erreur : ${e.message}`);
|
|
112
|
+
if (e.body) console.error(JSON.stringify(e.body, null, 2));
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
throw e;
|
|
116
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "x402-agent-gateway",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "One endpoint for any agent capability: resolve a task, route it to the best provider, pay per call in USDC over x402.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"agent-gateway": "bin/cli.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src",
|
|
15
|
+
"bin",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"test": "node --test test/"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"x402",
|
|
23
|
+
"agent",
|
|
24
|
+
"gateway",
|
|
25
|
+
"mcp",
|
|
26
|
+
"a2a",
|
|
27
|
+
"usdc",
|
|
28
|
+
"ai",
|
|
29
|
+
"ai-agents",
|
|
30
|
+
"pay-per-call",
|
|
31
|
+
"sec-edgar",
|
|
32
|
+
"agentic-commerce"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=20"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/laurenthalbrun/x402-agent-gateway.git",
|
|
41
|
+
"directory": "node"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/laurenthalbrun/x402-agent-gateway#readme",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/laurenthalbrun/x402-agent-gateway/issues"
|
|
46
|
+
},
|
|
47
|
+
"author": "laurenthalbrun",
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// SDK Node du Universal Agent Gateway.
|
|
2
|
+
//
|
|
3
|
+
// Objectif : première intégration en moins de cinq minutes. Donc trois fonctions, aucune
|
|
4
|
+
// dépendance obligatoire, et le paiement optionnel.
|
|
5
|
+
//
|
|
6
|
+
// Choix qui compte : `preview` et `capabilities` sont GRATUITS et ne demandent aucun
|
|
7
|
+
// portefeuille. Un développeur doit pouvoir installer, appeler, voir le plan et le prix,
|
|
8
|
+
// et décider ensuite. Un SDK qui exige une clé ou un portefeuille avant de montrer quoi
|
|
9
|
+
// que ce soit se fait désinstaller.
|
|
10
|
+
|
|
11
|
+
const DEFAUT = "https://api.x-402.online";
|
|
12
|
+
|
|
13
|
+
export class GatewayError extends Error {
|
|
14
|
+
constructor(message, { status, body } = {}) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "GatewayError";
|
|
17
|
+
this.status = status;
|
|
18
|
+
this.body = body;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Levée quand la route répond 402 et qu'aucun moyen de paiement n'a été fourni.
|
|
23
|
+
* Elle porte le défi tel quel : le montant, le réseau et l'adresse sont dedans, donc un
|
|
24
|
+
* agent peut payer avec son propre outillage sans que ce SDK impose le sien. */
|
|
25
|
+
export class PaymentRequired extends GatewayError {
|
|
26
|
+
constructor(challenge) {
|
|
27
|
+
super("payment required", { status: 402, body: challenge });
|
|
28
|
+
this.name = "PaymentRequired";
|
|
29
|
+
this.challenge = challenge;
|
|
30
|
+
this.accepts = challenge && challenge.accepts ? challenge.accepts : [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class Gateway {
|
|
35
|
+
/**
|
|
36
|
+
* @param {object} [opts]
|
|
37
|
+
* @param {string} [opts.baseUrl] par défaut https://api.x-402.online
|
|
38
|
+
* @param {Function} [opts.fetch] un fetch qui sait payer x402 (par ex. @x402/fetch).
|
|
39
|
+
* Sans lui, `solve` lève PaymentRequired avec le défi.
|
|
40
|
+
* @param {string} [opts.apiKey] clé interne, pour les appels qui ne passent pas par x402
|
|
41
|
+
* @param {number} [opts.timeoutMs] 60 s par défaut ; certaines capacités prennent 12 s
|
|
42
|
+
*/
|
|
43
|
+
constructor(opts = {}) {
|
|
44
|
+
this.baseUrl = (opts.baseUrl || DEFAUT).replace(/\/+$/, "");
|
|
45
|
+
this.fetch = opts.fetch || globalThis.fetch;
|
|
46
|
+
this.apiKey = opts.apiKey || null;
|
|
47
|
+
this.timeoutMs = opts.timeoutMs || 60000;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async #appel(chemin, { method = "POST", body } = {}) {
|
|
51
|
+
const headers = { "content-type": "application/json" };
|
|
52
|
+
if (this.apiKey) headers["x-api-key"] = this.apiKey;
|
|
53
|
+
const r = await this.fetch(`${this.baseUrl}${chemin}`, {
|
|
54
|
+
method,
|
|
55
|
+
headers,
|
|
56
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
57
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
58
|
+
});
|
|
59
|
+
const txt = await r.text();
|
|
60
|
+
let j = null;
|
|
61
|
+
try { j = JSON.parse(txt); } catch { /* laisse j a null */ }
|
|
62
|
+
if (r.status === 402) throw new PaymentRequired(j);
|
|
63
|
+
if (!r.ok) {
|
|
64
|
+
throw new GatewayError(
|
|
65
|
+
(j && (j.error || j.erreur)) || `HTTP ${r.status}`,
|
|
66
|
+
{ status: r.status, body: j ?? txt.slice(0, 400) },
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return j;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Les trois méthodes sont `async` pour une raison précise, trouvée par un test : sans
|
|
73
|
+
// ça, une demande malformée levait de façon SYNCHRONE pendant que tout le reste
|
|
74
|
+
// rejetait une promesse. Un appelant qui fait `.catch()` n'attrape pas un throw
|
|
75
|
+
// synchrone, et son programme s'arrête là où il croyait avoir géré l'erreur. Une API
|
|
76
|
+
// qui échoue de deux façons différentes selon l'erreur est un piège.
|
|
77
|
+
|
|
78
|
+
/** Le registre : ce que le gateway sait faire, avec les schémas et le prix. Gratuit. */
|
|
79
|
+
async capabilities() {
|
|
80
|
+
return this.#appel("/v1/capabilities", { method: "GET" });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Le devis : quelle capacité, quelle entrée normalisée, quel prix, et si une route
|
|
84
|
+
* directe est moins chère. Gratuit, n'exécute rien, ne consomme aucun amont. */
|
|
85
|
+
async preview(demande) {
|
|
86
|
+
return this.#appel("/v1/solve/preview", { body: normaliser(demande) });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** L'exécution. Sans fetch payeur, lève PaymentRequired en portant le défi x402. */
|
|
90
|
+
async solve(demande) {
|
|
91
|
+
return this.#appel("/v1/solve", { body: normaliser(demande) });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ===== Appels directs, pour qui sait déjà ce qu'il veut =====================
|
|
95
|
+
//
|
|
96
|
+
// Le gateway devine la capacité à partir d'une tâche en mots simples, ce qui est
|
|
97
|
+
// pratique quand on ne sait pas. Quand on sait, deviner est du travail inutile et,
|
|
98
|
+
// à prix unique, le gateway coûte plus cher que la route directe. Ces méthodes
|
|
99
|
+
// appellent donc la route, et le SDK le dit plutôt que de pousser vers le gateway.
|
|
100
|
+
|
|
101
|
+
/** Identité d'une société cotée américaine, depuis SEC EDGAR. 0,02001 $. */
|
|
102
|
+
async usCompany(tickerOuCik) {
|
|
103
|
+
if (!tickerOuCik) throw new GatewayError("usCompany attend un ticker ou un CIK");
|
|
104
|
+
return this.#appel("/v1/us/company", { body: { ticker: String(tickerOuCik) } });
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Briefing sourcé sur une société cotée américaine : synthèse dont chaque affirmation
|
|
108
|
+
* cite son origine, plus l'identité, les comptes annuels et les dépôts récents en clair
|
|
109
|
+
* pour vérification. 0,040004 $, contre 0,090024 $ si on achète les trois séparément. */
|
|
110
|
+
async usBrief(tickerOuCik) {
|
|
111
|
+
if (!tickerOuCik) throw new GatewayError("usBrief attend un ticker ou un CIK");
|
|
112
|
+
return this.#appel("/v1/us/brief", { body: { ticker: String(tickerOuCik) } });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Accepte `solve("une tâche")` aussi bien que `solve({ capability, input })`. */
|
|
117
|
+
function normaliser(d) {
|
|
118
|
+
if (typeof d === "string") return { task: d };
|
|
119
|
+
if (d && typeof d === "object") return d;
|
|
120
|
+
throw new GatewayError("demande invalide : une chaîne ou { task } ou { capability, input }");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Raccourci sans instanciation, pour le cas le plus courant. */
|
|
124
|
+
export function gateway(opts) {
|
|
125
|
+
return new Gateway(opts);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export default Gateway;
|