autonomo-sdk 0.1.0 → 0.1.2

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Autonomo
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Autonomo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,106 +1,161 @@
1
- # Autonomo SDK for TypeScript
2
-
3
- One call for AI agents. Say what you need, and the SDK:
4
-
5
- 1. **Finds the right API** on [Autonomo](https://autonomo.fun), from your words and the kind of input you give
6
- (a token or wallet address, a transaction hash, a link).
7
- 2. **Pays for it** with x402 on Robinhood Chain, in USDG or $AUTONOMO, whichever the wallet can afford.
8
- 3. **Pays privately through [Gloam](https://gloam.trade)** when you ask, so the payment doesn't link to your wallet.
9
- 4. **Borrows from a [Borro](https://borro.markets) credit line** when the wallet is short of USDG.
10
- 5. **Keeps to your caps**: a most-per-call and a daily budget, checked before anything is signed.
11
- 6. **Returns the answer and a receipt**: which API, how it was paid, the amount and the transaction link.
12
-
13
- ```bash
14
- npm install autonomo-sdk
15
- ```
16
-
17
- Full examples for each way to pay: [autonomo.fun/docs/sdk](https://autonomo.fun/docs/sdk).
18
-
19
- ```ts
20
- import { Autonomo } from "autonomo-sdk";
21
-
22
- const autonomo = new Autonomo({ privateKey: process.env.AUTONOMO_WALLET_KEY });
23
-
24
- const { data, receipt } = await autonomo.call("is this token safe", {
25
- input: "0x86b57bcb9d249cf096cf8e21426c9dc9cafdec49",
26
- });
27
- console.log(data);
28
- console.log(receipt.route, receipt.amount, receipt.token, receipt.explorer);
29
- ```
30
-
31
- Use a **new wallet just for the agent**, holding only what it may spend. A little USDG covers many calls (most APIs
32
- cost 0.01 USDG). Paying in $AUTONOMO needs a little ETH once, for a Permit2 approval. Node 20 or later.
33
-
34
- ## Finding APIs without paying
35
-
36
- ```ts
37
- const autonomo = new Autonomo(); // no key needed to look
38
- await autonomo.find("wallet holdings"); // best matches first
39
- await autonomo.quote("explain this transaction", { input: "0x…" }); // the API, the URL and every price
40
- ```
41
-
42
- To skip the search, name the API: `autonomo.call("", { slug: "token-risk", path: "/risk/0x…" })`.
43
-
44
- ## Limits
45
-
46
- ```ts
47
- new Autonomo({
48
- privateKey,
49
- payWith: "auto", // or "usdg" / "autonomo"
50
- limits: {
51
- perCall: { usdg: "0.05", autonomo: "5000" }, // the defaults
52
- daily: { usdg: "1", autonomo: "10000" }, // per UTC day; Gloam and Borro count as USDG
53
- },
54
- });
55
- ```
56
-
57
- A call over a limit is refused before anything is signed, with the reason. Spending is kept in
58
- `~/.autonomo/spend.json` (shared with the Python SDK); pass `spendStore: memoryStore()` or your own store to change
59
- that.
60
-
61
- ## Private payments with Gloam
62
-
63
- `private: true` pays from a private Gloam balance through Gloam's own MCP server, `@gloamtrade/mcp`, running on your
64
- machine with its key and limits in `~/.gloam/agent.env`. The SDK calls its `gloam_fetch_paid` tool; Gloam cashes out
65
- exactly the price through its relay and calls the API with it. The SDK holds no Gloam keys, and no wallet key is needed.
66
- See the [SDK guide](https://autonomo.fun/docs/sdk) for the setup and a full example.
67
-
68
- ```ts
69
- const autonomo = new Autonomo({
70
- gloam: {
71
- fetchPaid: async (args) => {
72
- const out = await gloam.callTool({ name: "gloam_fetch_paid", arguments: args }); // an MCP client for @gloamtrade/mcp
73
- return JSON.parse((out.content as Array<{ text: string }>)[0].text);
74
- },
75
- },
76
- });
77
- await autonomo.call("newest launches", { private: true });
78
- ```
79
-
80
- A private call only ever pays through Gloam. If the API doesn't offer it, or Gloam isn't set up, it's refused, never
81
- sent as a public payment. The price includes Gloam's 0.5% cash-out fee.
82
-
83
- ## Borrowing with Borro
84
-
85
- ```ts
86
- const autonomo = new Autonomo({ privateKey, borro: { account: "0xYourCreditLine" } });
87
- ```
88
-
89
- When the wallet can't afford a call, the SDK asks Borro's MCP server to prepare a borrow of just what it's short,
90
- sends it from the wallet (this needs a little ETH for gas), waits for the USDG and pays. The line needs x402 bills
91
- turned on; see [Pay with a Borro credit line](https://autonomo.fun/docs/borro). Borro's own daily limit still applies.
92
-
93
- ## The receipt
94
-
95
- | Field | |
96
- | --- | --- |
97
- | `api` | The API's slug and name |
98
- | `route` | `usdg`, `autonomo`, `gloam` or `borro` |
99
- | `amount`, `token` | What was paid |
100
- | `payer`, `payTo` | The wallet (or "private (Gloam)") and the API's payment address |
101
- | `tx`, `explorer` | The payment transaction and its Blockscout link |
102
- | `borrowTxs`, `approveTx` | Borro borrows and the one-time Permit2 approval, when there were any |
103
- | `spentToday` | Today's total against the daily budget |
104
-
105
- Errors are `AutonomoError` with a `code` such as `cannot_pay`, `over_limit`, `no_private_option` or `payment_refused`.
106
- If an API fails after a payment is signed, the payment doesn't settle, so you aren't charged.
1
+ # Autonomo SDK for TypeScript
2
+
3
+ One call for AI agents. Say what you need, and the SDK:
4
+
5
+ 1. **Finds the right API** on [Autonomo](https://autonomo.fun), from your words and the kind of input you give
6
+ (a token or wallet address, a transaction hash, a link).
7
+ 2. **Pays for it** with x402 on Robinhood Chain, in USDG or $AUTONOMO, whichever the wallet can afford.
8
+ 3. **Pays privately through [Gloam](https://gloam.trade)** when you ask, so the payment doesn't link to your wallet.
9
+ 4. **Borrows from a [Borro](https://borro.markets) credit line** when the wallet is short of USDG.
10
+ 5. **Keeps to your caps**: a most-per-call and a daily budget, checked before anything is signed.
11
+ 6. **Returns the answer and a receipt**: which API, how it was paid, the amount and the transaction link.
12
+
13
+ ```bash
14
+ npm install autonomo-sdk
15
+ ```
16
+
17
+ Full examples for each way to pay: [autonomo.fun/docs/sdk](https://autonomo.fun/docs/sdk).
18
+
19
+ ```ts
20
+ import { Autonomo } from "autonomo-sdk";
21
+
22
+ const autonomo = new Autonomo({ privateKey: process.env.AUTONOMO_WALLET_KEY });
23
+
24
+ const { data, receipt } = await autonomo.call("is this token safe", {
25
+ input: "0x86b57bcb9d249cf096cf8e21426c9dc9cafdec49",
26
+ });
27
+ console.log(data);
28
+ console.log(receipt.route, receipt.amount, receipt.token, receipt.explorer);
29
+ ```
30
+
31
+ Use a **new wallet just for the agent**, holding only what it may spend. A little USDG covers many calls (most APIs
32
+ cost 0.01 USDG). Paying in $AUTONOMO needs a little ETH once, for a Permit2 approval. Node 20 or later.
33
+
34
+ ## Finding APIs without paying
35
+
36
+ ```ts
37
+ const autonomo = new Autonomo(); // no key needed to look
38
+ await autonomo.find("wallet holdings"); // best matches first
39
+ await autonomo.quote("explain this transaction", { input: "0x…" }); // the API, the URL and every price
40
+ ```
41
+
42
+ To skip the search, name the API: `autonomo.call("", { slug: "token-risk", path: "/risk/0x…" })`.
43
+
44
+ ## From the terminal
45
+
46
+ The package also installs a command, for people and for agents that run shell commands. `find`, `quote`, `spend` and
47
+ `--dry-run` need no wallet:
48
+
49
+ ```bash
50
+ npx autonomo-sdk find "wallet holdings"
51
+ npx autonomo-sdk risk 0x86b57bcb9d249cf096cf8e21426c9dc9cafdec49 --dry-run # the price, without paying
52
+ ```
53
+
54
+ To pay, put the agent wallet's key in `AUTONOMO_WALLET_KEY`. It's never taken as a flag, so it stays out of your
55
+ shell history.
56
+
57
+ ```bash
58
+ npx autonomo-sdk risk 0x86b57bcb9d249cf096cf8e21426c9dc9cafdec49
59
+ npx autonomo-sdk call "explain this transaction" 0x… --max 0.02 --daily 0.5 --json
60
+ ```
61
+
62
+ | Command | |
63
+ | --- | --- |
64
+ | `find [words] [input]` | List APIs, best matches first |
65
+ | `quote <words> [input]` | The API a call would use, and its prices |
66
+ | `call <words> [input]` | Find the right API, pay for one call, print the answer |
67
+ | `price [token]`, `launches [n]`, `risk <token>`, `tx <hash>`, `portfolio <wallet>`, `read <link>`, `offers <words>` | Shortcuts for the official APIs |
68
+ | `spend` | Today's spending against your limits |
69
+
70
+ `--max` and `--daily` set the USDG limits (`--max-autonomo` and `--daily-autonomo` for $AUTONOMO), `--pay-with`
71
+ picks the token and `--borro <credit line>` borrows when the wallet is short. At a terminal it shows the price and
72
+ asks before paying; `--yes` skips the question, and scripts are never asked. The answer goes to stdout and the
73
+ receipt to stderr, so piping into `jq` works, and `--json` prints `{ data, receipt }` as one object. Exit codes: 0
74
+ done, 1 failed, 2 bad usage, 3 over a limit, 4 can't pay, 5 payment refused, 6 no such API.
75
+
76
+ After `npm install -g autonomo-sdk` the command is `autonomo`. (`npx autonomo` is someone else's package.)
77
+
78
+ ### Paying privately from the terminal
79
+
80
+ ```bash
81
+ npx autonomo-sdk risk 0x86b57bcb9d249cf096cf8e21426c9dc9cafdec49 --private --dry-run # the private price
82
+ npx autonomo-sdk risk 0x86b57bcb9d249cf096cf8e21426c9dc9cafdec49 --private # pay from Gloam
83
+ ```
84
+
85
+ `--private` pays from your private Gloam balance, so the payment doesn't link to a wallet. The command starts Gloam's
86
+ own server (`npx -y @gloamtrade/mcp`) on your machine for that one payment and stops it afterwards.
87
+
88
+ - Set Gloam up once: its key and limits go in `~/.gloam/agent.env` and USDG goes into its private balance (see
89
+ [Pay privately with Gloam](https://autonomo.fun/docs/sdk#pay-privately-with-gloam)). The command never reads
90
+ Gloam's key, and Gloam's server is never given `AUTONOMO_WALLET_KEY`.
91
+ - No `AUTONOMO_WALLET_KEY` is needed for private calls.
92
+ - The price includes Gloam's fee and counts against `--max` and `--daily`. It can't be combined with `--pay-with`
93
+ or `--borro`.
94
+ - Paying can take a few minutes, since Gloam builds the payment's proofs on your machine.
95
+ - If Gloam paid but the API didn't answer, the error prints a payment header: run the same command again with
96
+ `--retry-header <header>` to get the answer without paying twice.
97
+
98
+ ## Limits
99
+
100
+ ```ts
101
+ new Autonomo({
102
+ privateKey,
103
+ payWith: "auto", // or "usdg" / "autonomo"
104
+ limits: {
105
+ perCall: { usdg: "0.05", autonomo: "5000" }, // the defaults
106
+ daily: { usdg: "1", autonomo: "10000" }, // per UTC day; Gloam and Borro count as USDG
107
+ },
108
+ });
109
+ ```
110
+
111
+ A call over a limit is refused before anything is signed, with the reason. Spending is kept in
112
+ `~/.autonomo/spend.json` (shared with the Python SDK); pass `spendStore: memoryStore()` or your own store to change
113
+ that.
114
+
115
+ ## Private payments with Gloam
116
+
117
+ `private: true` pays from a private Gloam balance through Gloam's own MCP server, `@gloamtrade/mcp`, running on your
118
+ machine with its key and limits in `~/.gloam/agent.env`. The SDK calls its `gloam_fetch_paid` tool; Gloam cashes out
119
+ exactly the price through its relay and calls the API with it. The SDK holds no Gloam keys, and no wallet key is needed.
120
+ See the [SDK guide](https://autonomo.fun/docs/sdk) for the setup and a full example.
121
+
122
+ ```ts
123
+ const autonomo = new Autonomo({
124
+ gloam: {
125
+ fetchPaid: async (args) => {
126
+ // gloam: an MCP client for @gloamtrade/mcp. A private payment can take a few minutes, so wait up to 5.
127
+ const out = await gloam.callTool({ name: "gloam_fetch_paid", arguments: args }, undefined, { timeout: 300_000 });
128
+ return JSON.parse((out.content as Array<{ text: string }>)[0].text);
129
+ },
130
+ },
131
+ });
132
+ await autonomo.call("newest launches", { private: true });
133
+ ```
134
+
135
+ A private call only ever pays through Gloam. If the API doesn't offer it, or Gloam isn't set up, it's refused, never
136
+ sent as a public payment. The price includes Gloam's cash-out fee (about 0.0105 USDG for a 0.01 call).
137
+
138
+ ## Borrowing with Borro
139
+
140
+ ```ts
141
+ const autonomo = new Autonomo({ privateKey, borro: { account: "0xYourCreditLine" } });
142
+ ```
143
+
144
+ When the wallet can't afford a call, the SDK asks Borro's MCP server to prepare a borrow of just what it's short,
145
+ sends it from the wallet (this needs a little ETH for gas), waits for the USDG and pays. The line needs x402 bills
146
+ turned on; see [Pay with a Borro credit line](https://autonomo.fun/docs/borro). Borro's own daily limit still applies.
147
+
148
+ ## The receipt
149
+
150
+ | Field | |
151
+ | --- | --- |
152
+ | `api` | The API's slug and name |
153
+ | `route` | `usdg`, `autonomo`, `gloam` or `borro` |
154
+ | `amount`, `token` | What was paid |
155
+ | `payer`, `payTo` | The wallet (or "private (Gloam)") and the API's payment address |
156
+ | `tx`, `explorer` | The payment transaction and its Blockscout link |
157
+ | `borrowTxs`, `approveTx` | Borro borrows and the one-time Permit2 approval, when there were any |
158
+ | `spentToday` | Today's total against the daily budget |
159
+
160
+ Errors are `AutonomoError` with a `code` such as `cannot_pay`, `over_limit`, `no_private_option` or `payment_refused`.
161
+ If an API fails after a payment is signed, the payment doesn't settle, so you aren't charged.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ import { type GloamSession } from "./gloam.js";
3
+ import { type SpendStore } from "./index.js";
4
+ /** Everything the CLI touches outside itself, so tests can swap it. */
5
+ export type Io = {
6
+ env: Record<string, string | undefined>;
7
+ out: (text: string) => void;
8
+ err: (text: string) => void;
9
+ /** True when a person is at the terminal, so a paid call asks first. */
10
+ interactive: boolean;
11
+ confirm: (question: string) => Promise<boolean>;
12
+ fetch?: typeof fetch;
13
+ spendStore?: SpendStore;
14
+ /** Starts Gloam's server for --private. The default runs `npx -y @gloamtrade/mcp`. */
15
+ startGloam?: () => Promise<GloamSession>;
16
+ };
17
+ export declare const EXIT: {
18
+ readonly ok: 0;
19
+ readonly failed: 1;
20
+ readonly usage: 2;
21
+ readonly overLimit: 3;
22
+ readonly cannotPay: 4;
23
+ readonly refused: 5;
24
+ readonly notFound: 6;
25
+ };
26
+ /** Runs one command and returns its exit code. `argv` is what follows the program name. */
27
+ export declare function run(argv: string[], io: Io): Promise<number>;
package/dist/cli.js ADDED
@@ -0,0 +1,390 @@
1
+ #!/usr/bin/env node
2
+ // Autonomo CLI: the SDK from a terminal, for people and for agents that run shell commands.
3
+ //
4
+ // npx autonomo-sdk find "wallet holdings" look, free
5
+ // npx autonomo-sdk risk 0x… --dry-run the price, without paying
6
+ // AUTONOMO_WALLET_KEY=0x… npx autonomo-sdk risk 0x… pay and print the answer
7
+ // npx autonomo-sdk risk 0x… --private pay from a private Gloam balance instead
8
+ //
9
+ // The answer goes to stdout and everything else (the receipt, questions, errors) to stderr, so `autonomo … | jq`
10
+ // works. The wallet key is only ever read from AUTONOMO_WALLET_KEY, never from a flag, so it stays out of shell
11
+ // history. The SDK's per-call cap and daily budget apply to every paid call. With --private the payment is made by
12
+ // Gloam's own server, started on this machine with its own key and limits (see gloam.ts); no wallet key is needed.
13
+ import { realpathSync } from "node:fs";
14
+ import { createInterface } from "node:readline/promises";
15
+ import { fileURLToPath } from "node:url";
16
+ import { parseArgs } from "node:util";
17
+ import { formatUnits } from "viem";
18
+ import { startGloam } from "./gloam.js";
19
+ import { Autonomo, AutonomoError, DEFAULT_LIMITS, TOKENS, VERSION, fileStore } from "./index.js";
20
+ export const EXIT = { ok: 0, failed: 1, usage: 2, overLimit: 3, cannotPay: 4, refused: 5, notFound: 6 };
21
+ const HELP = `Autonomo CLI ${VERSION}: find and pay for APIs on autonomo.fun
22
+
23
+ Usage
24
+ autonomo find [words] [input] List APIs, best matches first. Free.
25
+ autonomo quote <words> [input] The API a call would use and its prices. Free.
26
+ autonomo call <words> [input] Find the right API, pay for one call, print the answer.
27
+ autonomo spend Today's spending against your limits.
28
+
29
+ Shortcuts for the official APIs
30
+ autonomo price [token address] $AUTONOMO's price, or any launchpad token's
31
+ autonomo launches [how many] Newest token launches
32
+ autonomo risk <token address> Rug-risk check
33
+ autonomo tx <transaction hash> A transaction in plain words
34
+ autonomo portfolio <wallet> What a wallet holds
35
+ autonomo read <https link> A web page's text
36
+ autonomo offers <what you need> Matching offers on Ostrapad
37
+
38
+ Options
39
+ --max <usdg> Most to pay for one call (default ${DEFAULT_LIMITS.perCall.usdg})
40
+ --daily <usdg> Most to spend per UTC day (default ${DEFAULT_LIMITS.daily.usdg})
41
+ --max-autonomo <amount> The same two limits when paying in $AUTONOMO
42
+ --daily-autonomo <amount> (defaults ${DEFAULT_LIMITS.perCall.autonomo} and ${DEFAULT_LIMITS.daily.autonomo})
43
+ --pay-with <token> usdg, autonomo or auto (default: USDG, then $AUTONOMO)
44
+ --borro <credit line> Borrow from this Borro line when the wallet is short of USDG
45
+ --private Pay from your private Gloam balance, so the payment doesn't link to a wallet
46
+ --retry-header <header> With --private: finish a call Gloam paid for but the API didn't answer, without paying again
47
+ --slug <api> --path <p> With call or quote: use this API and path, skipping the search
48
+ --dry-run Show the price instead of paying
49
+ --yes Don't ask before paying
50
+ --json One JSON object on stdout: { data, receipt }
51
+ --help, --version
52
+
53
+ Wallet
54
+ Set AUTONOMO_WALLET_KEY to the private key of a wallet made just for the agent, holding only what it may spend.
55
+ find, quote, spend and --dry-run need no wallet.
56
+
57
+ Private payments
58
+ --private starts Gloam's own server on this machine (npx @gloamtrade/mcp) and has it pay in USDG. It needs no
59
+ AUTONOMO_WALLET_KEY: Gloam uses its own key and limits from ~/.gloam/agent.env, and that key is never read by
60
+ this command. Deposit USDG into Gloam's private balance first. The price includes Gloam's fee, counts against
61
+ --max and --daily, and paying can take a few minutes. Setup: autonomo.fun/docs/sdk#pay-privately-with-gloam
62
+
63
+ Exit codes
64
+ 0 done 1 failed 2 bad usage 3 over a limit 4 can't pay 5 payment refused 6 no such API`;
65
+ const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
66
+ const TX_HASH = /^0x[0-9a-fA-F]{64}$/;
67
+ const AMOUNT = /^\d+(\.\d+)?$/;
68
+ const GLOAM_SETUP = "Gloam needs its own key and limits in ~/.gloam/agent.env: autonomo.fun/docs/sdk#pay-privately-with-gloam";
69
+ class UsageError extends Error {
70
+ }
71
+ const usage = (message) => {
72
+ throw new UsageError(message);
73
+ };
74
+ /** Each shortcut names its API and builds the path, so nothing is searched. */
75
+ const SHORTCUTS = {
76
+ price: ([token]) => {
77
+ if (token === undefined)
78
+ return { slug: "token-price", path: "/price/autonomo" };
79
+ if (!ADDRESS.test(token))
80
+ usage("price takes a token contract address (0x and 40 hex characters), or nothing for $AUTONOMO.");
81
+ return { slug: "token-lookup", path: `/price/${token}` };
82
+ },
83
+ launches: ([count = "10"]) => {
84
+ if (!/^\d{1,3}$/.test(count) || Number(count) < 1)
85
+ usage("launches takes how many to show, e.g. autonomo launches 5.");
86
+ return { slug: "new-launches", path: `/launches?limit=${Number(count)}` };
87
+ },
88
+ risk: ([token]) => {
89
+ if (!token || !ADDRESS.test(token))
90
+ usage("risk takes a token contract address: autonomo risk 0x…");
91
+ return { slug: "token-risk", path: `/risk/${token}` };
92
+ },
93
+ tx: ([hash]) => {
94
+ if (!hash || !TX_HASH.test(hash))
95
+ usage("tx takes a transaction hash (0x and 64 hex characters).");
96
+ return { slug: "tx-explainer", path: `/tx/${hash}` };
97
+ },
98
+ portfolio: ([wallet]) => {
99
+ if (!wallet || !ADDRESS.test(wallet))
100
+ usage("portfolio takes a wallet address: autonomo portfolio 0x…");
101
+ return { slug: "wallet-portfolio", path: `/portfolio/${wallet}` };
102
+ },
103
+ read: ([link]) => {
104
+ if (!link || !/^https:\/\/\S+$/i.test(link))
105
+ usage("read takes an https:// link.");
106
+ return { slug: "page-reader", path: `/page?url=${encodeURIComponent(link)}` };
107
+ },
108
+ offers: (words) => {
109
+ const q = words.join(" ").trim();
110
+ if (!q)
111
+ usage('offers takes what you need done: autonomo offers "summarize a document"');
112
+ return { slug: "ostrapad-offer-finder", path: `/offers?q=${encodeURIComponent(q)}` };
113
+ },
114
+ };
115
+ const price = (api) => {
116
+ const parts = [api.price.usdg !== undefined && `${api.price.usdg} USDG`, api.price.autonomo !== undefined && `${api.price.autonomo} AUTONOMO`].filter(Boolean);
117
+ return parts.join(" or ") || "see quote";
118
+ };
119
+ function exitFor(e) {
120
+ if (e instanceof UsageError)
121
+ return EXIT.usage;
122
+ if (!(e instanceof AutonomoError))
123
+ return EXIT.failed;
124
+ if (e.code === "over_limit")
125
+ return EXIT.overLimit;
126
+ // cannot_pay covers both a limit and an empty wallet; the limit ones say "cap" or "budget".
127
+ if (e.code === "cannot_pay")
128
+ return /per-call cap|budget/.test(e.message) && !/the wallet holds/.test(e.message) ? EXIT.overLimit : EXIT.cannotPay;
129
+ if (e.code === "no_wallet" || e.code === "bad_key" || e.code === "no_gloam" || e.code === "no_private_option")
130
+ return EXIT.cannotPay;
131
+ if (e.code === "payment_refused" || e.code === "paid_not_served")
132
+ return EXIT.refused;
133
+ if (e.code === "not_found")
134
+ return EXIT.notFound;
135
+ return EXIT.failed;
136
+ }
137
+ /** Runs one command and returns its exit code. `argv` is what follows the program name. */
138
+ export async function run(argv, io) {
139
+ let json = argv.includes("--json");
140
+ try {
141
+ const { values, positionals } = parseArgs({
142
+ args: argv,
143
+ allowPositionals: true,
144
+ options: {
145
+ max: { type: "string" },
146
+ daily: { type: "string" },
147
+ "max-autonomo": { type: "string" },
148
+ "daily-autonomo": { type: "string" },
149
+ "pay-with": { type: "string" },
150
+ borro: { type: "string" },
151
+ private: { type: "boolean" },
152
+ "retry-header": { type: "string" },
153
+ slug: { type: "string" },
154
+ path: { type: "string" },
155
+ "dry-run": { type: "boolean" },
156
+ yes: { type: "boolean", short: "y" },
157
+ json: { type: "boolean" },
158
+ help: { type: "boolean", short: "h" },
159
+ version: { type: "boolean", short: "v" },
160
+ key: { type: "string" },
161
+ "private-key": { type: "string" },
162
+ },
163
+ });
164
+ json = Boolean(values.json);
165
+ if (values.key !== undefined || values["private-key"] !== undefined) {
166
+ usage("The wallet key isn't taken as a flag, so it stays out of your shell history. Set AUTONOMO_WALLET_KEY instead.");
167
+ }
168
+ if (values.version)
169
+ return io.out(VERSION), EXIT.ok;
170
+ const [command, ...rest] = positionals;
171
+ if (values.help || command === undefined || command === "help")
172
+ return io.out(HELP), EXIT.ok;
173
+ const amount = (flag) => {
174
+ const v = values[flag];
175
+ if (v !== undefined && !AMOUNT.test(v))
176
+ usage(`--${flag} takes an amount in whole tokens, e.g. --${flag} 0.05.`);
177
+ return v;
178
+ };
179
+ const limits = {
180
+ perCall: { usdg: amount("max") ?? DEFAULT_LIMITS.perCall.usdg, autonomo: amount("max-autonomo") ?? DEFAULT_LIMITS.perCall.autonomo },
181
+ daily: { usdg: amount("daily") ?? DEFAULT_LIMITS.daily.usdg, autonomo: amount("daily-autonomo") ?? DEFAULT_LIMITS.daily.autonomo },
182
+ };
183
+ const payWith = values["pay-with"] ?? "auto";
184
+ if (payWith !== "usdg" && payWith !== "autonomo" && payWith !== "auto")
185
+ usage("--pay-with takes usdg, autonomo or auto.");
186
+ const borro = values.borro ?? io.env.AUTONOMO_BORRO_ACCOUNT;
187
+ if (borro !== undefined && !ADDRESS.test(borro))
188
+ usage("--borro takes the credit line's address.");
189
+ const retryHeader = values["retry-header"];
190
+ if (values.private && (values["pay-with"] !== undefined || values.borro !== undefined)) {
191
+ usage("--private pays in USDG from your Gloam balance, so it can't be combined with --pay-with or --borro.");
192
+ }
193
+ if (retryHeader !== undefined && !values.private)
194
+ usage("--retry-header goes with --private: it finishes a call Gloam already paid for.");
195
+ if (retryHeader !== undefined && !retryHeader.trim())
196
+ usage("--retry-header takes the paymentHeader from the earlier result.");
197
+ const store = io.spendStore ?? fileStore();
198
+ const client = (withWallet) => new Autonomo({
199
+ privateKey: withWallet ? io.env.AUTONOMO_WALLET_KEY || undefined : undefined,
200
+ payWith: payWith,
201
+ limits,
202
+ borro: borro ? { account: borro } : undefined,
203
+ spendStore: store,
204
+ fetch: io.fetch,
205
+ });
206
+ const print = (value) => io.out(typeof value === "string" ? value : JSON.stringify(value, null, 2));
207
+ if (command === "find") {
208
+ const [words = "", input] = rest;
209
+ let apis;
210
+ if (input !== undefined) {
211
+ apis = await client(false).find(words, input);
212
+ }
213
+ else {
214
+ // Browsing: with no input to fit, show every API whose text matches, including the ones that need an input.
215
+ const terms = words.toLowerCase().split(/[^a-z0-9$]+/).filter((w) => w.length > 2);
216
+ const hits = (a) => terms.filter((w) => `${a.slug} ${a.name} ${a.description}`.toLowerCase().includes(w)).length;
217
+ apis = (await client(false).find()).filter((a) => terms.length === 0 || hits(a) > 0).sort((x, y) => hits(y) - hits(x));
218
+ }
219
+ if (json)
220
+ return print(apis), EXIT.ok;
221
+ if (apis.length === 0)
222
+ return io.err(`No API matches "${words}". Run autonomo find to see them all.`), EXIT.notFound;
223
+ for (const a of apis)
224
+ io.out(`${a.slug} ${price(a)}${a.verified ? " verified" : ""}\n ${a.name}: ${a.description}\n ${a.path}`);
225
+ return EXIT.ok;
226
+ }
227
+ if (command === "spend") {
228
+ const day = new Date().toISOString().slice(0, 10);
229
+ const spent = await store.get(day);
230
+ const row = (t) => ({ spent: formatUnits(spent[t] ?? 0n, TOKENS[t].decimals), daily: limits.daily[t], perCall: limits.perCall[t] });
231
+ const report = { day, wallet: client(true).address, usdg: row("usdg"), autonomo: row("autonomo") };
232
+ if (json)
233
+ return print(report), EXIT.ok;
234
+ io.out(`Today (${day}, UTC)`);
235
+ io.out(` USDG ${report.usdg.spent} of ${report.usdg.daily} spent, up to ${report.usdg.perCall} a call`);
236
+ io.out(` AUTONOMO ${report.autonomo.spent} of ${report.autonomo.daily} spent, up to ${report.autonomo.perCall} a call`);
237
+ io.out(` Wallet ${report.wallet ?? "none set (AUTONOMO_WALLET_KEY)"}`);
238
+ return EXIT.ok;
239
+ }
240
+ // Everything else is a call: a shortcut, or `call` / `quote` with words.
241
+ let words = "";
242
+ let opts;
243
+ const quoteOnly = command === "quote" || Boolean(values["dry-run"]);
244
+ if (command === "call" || command === "quote") {
245
+ if (values.slug) {
246
+ opts = { slug: values.slug, path: values.path, input: rest[0] };
247
+ }
248
+ else {
249
+ if (values.path)
250
+ usage("--path needs --slug, the API it belongs to.");
251
+ if (!rest[0])
252
+ usage(`${command} takes what you need in words: autonomo ${command} "is this token safe" 0x…`);
253
+ if (rest.length > 2)
254
+ usage(`Put the words in quotes: autonomo ${command} "is this token safe" 0x…`);
255
+ words = rest[0];
256
+ opts = { input: rest[1] };
257
+ }
258
+ }
259
+ else if (Object.hasOwn(SHORTCUTS, command)) {
260
+ if (values.slug || values.path)
261
+ usage(`${command} already names its API. Use call with --slug and --path instead.`);
262
+ opts = SHORTCUTS[command](rest);
263
+ }
264
+ else {
265
+ return usage(`Unknown command "${command}". Run autonomo --help.`);
266
+ }
267
+ if (quoteOnly) {
268
+ const q = await client(false).quote(words, opts);
269
+ if (json)
270
+ return print(q), EXIT.ok;
271
+ io.out(`${q.api.name} (${q.api.slug})\n ${q.url}`);
272
+ for (const o of q.offers)
273
+ io.out(` ${o.amount} ${o.token}${o.private ? " private, through Gloam" : ""}`);
274
+ return EXIT.ok;
275
+ }
276
+ if (values.private) {
277
+ // Gloam's server is only started once a payment is really going to be made, and always stopped afterwards.
278
+ let session;
279
+ const gloam = async (notice) => {
280
+ if (session)
281
+ return session;
282
+ if (!json)
283
+ io.err(notice);
284
+ try {
285
+ return (session = await (io.startGloam ?? (() => startGloam(io.env, undefined, VERSION)))());
286
+ }
287
+ catch (e) {
288
+ throw new AutonomoError(`${e instanceof Error ? e.message : String(e)} ${GLOAM_SETUP}`, "no_gloam");
289
+ }
290
+ };
291
+ try {
292
+ const autonomo = new Autonomo({
293
+ limits,
294
+ spendStore: store,
295
+ fetch: io.fetch,
296
+ gloam: { fetchPaid: async (args) => (await gloam("Paying privately through Gloam. This can take a few minutes…")).fetchPaid(args) },
297
+ });
298
+ if (retryHeader !== undefined) {
299
+ const q = await autonomo.quote(words, opts);
300
+ const r = await (await gloam("Asking Gloam to present the earlier payment…")).fetchPaid({ url: q.url, paymentHeader: retryHeader.trim(), prefer: "gloam-cashout" });
301
+ if (r.status !== "ok") {
302
+ throw new AutonomoError(`Not answered yet: ${r.message ?? r.error ?? r.code ?? r.status}. Nothing more was paid; try again with the same --retry-header.`, "paid_not_served");
303
+ }
304
+ let data = r.body ?? "";
305
+ try {
306
+ data = JSON.parse(String(data));
307
+ }
308
+ catch {
309
+ // Plain text is fine.
310
+ }
311
+ if (json)
312
+ return print({ data, receipt: null }), EXIT.ok;
313
+ print(data);
314
+ io.err(`Answered by ${q.api.name} with the earlier payment. Nothing more was paid.`);
315
+ return EXIT.ok;
316
+ }
317
+ if (io.interactive && !values.yes) {
318
+ const q = await autonomo.quote(words, opts);
319
+ const offer = q.offers.find((o) => o.private);
320
+ if (!offer)
321
+ throw new AutonomoError(`${q.api.name} doesn't offer private payment.`, "no_private_option");
322
+ const question = `${q.api.name} costs ${offer.amount} ${offer.token} privately through Gloam, its fee included. Pay from your Gloam balance? [y/N] `;
323
+ if (!(await io.confirm(question)))
324
+ return io.err("Not paid."), EXIT.ok;
325
+ }
326
+ const { data, receipt } = await autonomo.call(words, { ...opts, private: true });
327
+ if (json)
328
+ return print({ data, receipt }), EXIT.ok;
329
+ print(data);
330
+ io.err(`Paid ${receipt.amount} ${receipt.token} privately through Gloam to ${receipt.api.name}. Today: ${receipt.spentToday}.`);
331
+ if (receipt.explorer)
332
+ io.err(receipt.explorer);
333
+ return EXIT.ok;
334
+ }
335
+ finally {
336
+ await session?.close().catch(() => { });
337
+ }
338
+ }
339
+ const autonomo = client(true);
340
+ if (!autonomo.address) {
341
+ throw new AutonomoError("No wallet set. Put the agent wallet's private key in AUTONOMO_WALLET_KEY, or add --dry-run to see the price.", "no_wallet");
342
+ }
343
+ if (io.interactive && !values.yes) {
344
+ const q = await autonomo.quote(words, opts);
345
+ const prices = q.offers.filter((o) => !o.private).map((o) => `${o.amount} ${o.token}`).join(" or ");
346
+ if (!(await io.confirm(`${q.api.name} costs ${prices}. Pay from ${autonomo.address}? [y/N] `)))
347
+ return io.err("Not paid."), EXIT.ok;
348
+ }
349
+ const { data, receipt } = await autonomo.call(words, opts);
350
+ if (json)
351
+ return print({ data, receipt }), EXIT.ok;
352
+ print(data);
353
+ io.err(`Paid ${receipt.amount} ${receipt.token} to ${receipt.api.name}${receipt.route === "borro" ? " on Borro credit" : ""}. Today: ${receipt.spentToday}.`);
354
+ if (receipt.explorer)
355
+ io.err(receipt.explorer);
356
+ return EXIT.ok;
357
+ }
358
+ catch (e) {
359
+ const code = e instanceof AutonomoError ? e.code : e instanceof UsageError || e?.code?.startsWith?.("ERR_PARSE_ARGS") ? "usage" : "failed";
360
+ const message = e instanceof Error ? e.message : String(e);
361
+ io.err(json ? JSON.stringify({ error: { code, message } }) : code === "usage" ? `${message}\nRun autonomo --help for the commands.` : message);
362
+ return code === "usage" ? EXIT.usage : exitFor(e);
363
+ }
364
+ }
365
+ const isMain = (() => {
366
+ try {
367
+ return Boolean(process.argv[1]) && realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
368
+ }
369
+ catch {
370
+ return false;
371
+ }
372
+ })();
373
+ if (isMain) {
374
+ const code = await run(process.argv.slice(2), {
375
+ env: process.env,
376
+ out: (text) => console.log(text),
377
+ err: (text) => console.error(text),
378
+ interactive: Boolean(process.stdin.isTTY && process.stderr.isTTY),
379
+ confirm: async (question) => {
380
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
381
+ try {
382
+ return /^y(es)?$/i.test((await rl.question(question)).trim());
383
+ }
384
+ finally {
385
+ rl.close();
386
+ }
387
+ },
388
+ });
389
+ process.exitCode = code;
390
+ }
@@ -0,0 +1,23 @@
1
+ import type { GloamFetchPaid, GloamResult } from "./index.js";
2
+ /** A running Gloam server. */
3
+ export type GloamSession = {
4
+ /** Pays for one request from the private balance, or presents a payment made earlier (`paymentHeader`). */
5
+ fetchPaid: (args: Parameters<GloamFetchPaid>[0] | {
6
+ url: string;
7
+ paymentHeader: string;
8
+ prefer: "gloam-cashout";
9
+ }) => Promise<GloamResult>;
10
+ close: () => Promise<void>;
11
+ };
12
+ export type GloamServer = {
13
+ command: string;
14
+ args: string[];
15
+ };
16
+ /** `npx -y @gloamtrade/mcp`. On Windows npx is a script, so it's started through cmd. */
17
+ export declare const defaultGloamServer: () => GloamServer;
18
+ /** What Gloam's server is started with: everything it may need, but never Autonomo's own wallet key or settings. */
19
+ export declare function gloamEnv(env: Record<string, string | undefined>): Record<string, string>;
20
+ export declare function startGloam(env: Record<string, string | undefined>, server?: GloamServer, version?: string, timeouts?: {
21
+ start: number;
22
+ pay: number;
23
+ }): Promise<GloamSession>;
package/dist/gloam.js ADDED
@@ -0,0 +1,118 @@
1
+ // Gloam for the CLI's --private: starts Gloam's own MCP server on this machine and calls its paid-fetch tool.
2
+ //
3
+ // The Gloam key never comes near Autonomo's code. Gloam's server reads it, with its own spending limits, from
4
+ // ~/.gloam/agent.env (see autonomo.fun/docs/sdk#pay-privately-with-gloam). This file only speaks the MCP stdio
5
+ // protocol to that server: one JSON-RPC message per line. It is written out here instead of using an MCP client
6
+ // library so `npx autonomo-sdk` stays a small download.
7
+ import { spawn } from "node:child_process";
8
+ import { createInterface } from "node:readline";
9
+ /** `npx -y @gloamtrade/mcp`. On Windows npx is a script, so it's started through cmd. */
10
+ export const defaultGloamServer = () => process.platform === "win32" ? { command: "cmd", args: ["/c", "npx", "-y", "@gloamtrade/mcp"] } : { command: "npx", args: ["-y", "@gloamtrade/mcp"] };
11
+ // The first run downloads Gloam's server, and a private payment builds its proofs on this machine.
12
+ const START_MS = 120_000;
13
+ const PAY_MS = 300_000;
14
+ /** What Gloam's server is started with: everything it may need, but never Autonomo's own wallet key or settings. */
15
+ export function gloamEnv(env) {
16
+ return Object.fromEntries(Object.entries(env).filter((e) => e[1] !== undefined && !/^AUTONOMO_/i.test(e[0])));
17
+ }
18
+ export async function startGloam(env, server = defaultGloamServer(), version = "0", timeouts = { start: START_MS, pay: PAY_MS }) {
19
+ let child;
20
+ try {
21
+ child = spawn(server.command, server.args, { env: gloamEnv(env), stdio: ["pipe", "pipe", "pipe"], windowsHide: true });
22
+ }
23
+ catch (e) {
24
+ throw new Error(`Gloam's server couldn't be started: ${e instanceof Error ? e.message : String(e)}`);
25
+ }
26
+ // The tail of what the server printed, for when it stops before answering.
27
+ let tail = "";
28
+ child.stderr?.on("data", (chunk) => {
29
+ tail = (tail + chunk.toString("utf8")).slice(-400);
30
+ });
31
+ let nextId = 1;
32
+ let stopped = null;
33
+ const waiting = new Map();
34
+ const stop = (why) => {
35
+ stopped ??= why;
36
+ for (const w of waiting.values())
37
+ w.reject(new Error(stopped));
38
+ waiting.clear();
39
+ };
40
+ child.on("error", (e) => stop(`Gloam's server couldn't be started: ${e.message}`));
41
+ child.on("exit", (code) => stop(`Gloam's server stopped${code === null ? "" : ` (exit ${code})`}${tail.trim() ? `: ${tail.trim().split(/\r?\n/).at(-1)}` : "."}`));
42
+ // A write to a server that has gone must not crash the CLI: the exit handler reports it.
43
+ child.stdin?.on("error", () => { });
44
+ const send = (message) => child.stdin?.write(`${JSON.stringify(message)}\n`);
45
+ createInterface({ input: child.stdout }).on("line", (line) => {
46
+ let m;
47
+ try {
48
+ m = JSON.parse(line);
49
+ }
50
+ catch {
51
+ return; // Not protocol: a stray log line.
52
+ }
53
+ if (m.method !== undefined) {
54
+ // A request from the server: answer pings, decline anything else. Notifications need no answer.
55
+ if (m.id !== undefined)
56
+ send(m.method === "ping" ? { jsonrpc: "2.0", id: m.id, result: {} } : { jsonrpc: "2.0", id: m.id, error: { code: -32601, message: "Not supported" } });
57
+ return;
58
+ }
59
+ const w = m.id !== undefined ? waiting.get(m.id) : undefined;
60
+ if (!w)
61
+ return;
62
+ waiting.delete(m.id);
63
+ if (m.error)
64
+ w.reject(new Error(`Gloam: ${m.error.message ?? "request failed"}`));
65
+ else
66
+ w.resolve(m.result);
67
+ });
68
+ const request = (method, params, ms, what) => new Promise((resolve, reject) => {
69
+ if (stopped)
70
+ return reject(new Error(stopped));
71
+ const id = nextId++;
72
+ const timer = setTimeout(() => {
73
+ waiting.delete(id);
74
+ reject(new Error(`${what} took over ${Math.round(ms / 1000)} seconds.`));
75
+ }, ms);
76
+ waiting.set(id, {
77
+ resolve: (v) => (clearTimeout(timer), resolve(v)),
78
+ reject: (e) => (clearTimeout(timer), reject(e)),
79
+ });
80
+ send({ jsonrpc: "2.0", id, method, params });
81
+ });
82
+ const close = async () => {
83
+ if (child.exitCode !== null || child.signalCode !== null)
84
+ return;
85
+ const gone = new Promise((resolve) => child.once("exit", () => resolve()));
86
+ child.stdin?.end(); // An MCP server exits when its input closes.
87
+ const waited = await Promise.race([gone.then(() => true), new Promise((r) => setTimeout(() => r(false), 3000).unref())]);
88
+ if (waited)
89
+ return;
90
+ // Still there: stop it, and on Windows everything cmd started with it.
91
+ if (process.platform === "win32" && child.pid)
92
+ spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], { stdio: "ignore", windowsHide: true }).on("error", () => { });
93
+ else
94
+ child.kill();
95
+ };
96
+ try {
97
+ await request("initialize", { protocolVersion: "2025-06-18", capabilities: {}, clientInfo: { name: "autonomo-cli", version } }, timeouts.start, "Starting Gloam's server");
98
+ send({ jsonrpc: "2.0", method: "notifications/initialized" });
99
+ }
100
+ catch (e) {
101
+ await close();
102
+ throw e;
103
+ }
104
+ return {
105
+ close,
106
+ fetchPaid: async (args) => {
107
+ const out = await request("tools/call", { name: "gloam_fetch_paid", arguments: args }, timeouts.pay, "The private payment");
108
+ const text = out.content?.find((c) => typeof c.text === "string")?.text ?? "";
109
+ try {
110
+ return JSON.parse(text);
111
+ }
112
+ catch {
113
+ // Gloam answers errors, such as a missing key or an empty balance, in plain words.
114
+ return { status: "error", message: text.slice(0, 500) || "Gloam gave no answer." };
115
+ }
116
+ },
117
+ };
118
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type Hex } from "viem";
2
- export declare const VERSION = "0.1.0";
2
+ export declare const VERSION = "0.1.2";
3
3
  export type TokenName = "usdg" | "autonomo";
4
4
  type Token = {
5
5
  name: TokenName;
@@ -8,6 +8,16 @@ type Token = {
8
8
  decimals: number;
9
9
  };
10
10
  export declare const TOKENS: Record<TokenName, Token>;
11
+ export declare const DEFAULT_LIMITS: {
12
+ perCall: {
13
+ usdg: string;
14
+ autonomo: string;
15
+ };
16
+ daily: {
17
+ usdg: string;
18
+ autonomo: string;
19
+ };
20
+ };
11
21
  export type Limits = {
12
22
  /** Most to pay for one call, in whole tokens, e.g. { usdg: "0.05" }. */
13
23
  perCall?: Partial<Record<TokenName, string>>;
@@ -113,6 +123,7 @@ export declare class AutonomoError extends Error {
113
123
  }
114
124
  /** Ranks APIs for a query and input: word matches first, then a fitting path, then verified and the track record. */
115
125
  export declare function rankApis(apis: Api[], query: string, input?: string): Api[];
126
+ export declare function fileStore(file?: string): SpendStore;
116
127
  /** Keeps spending in memory only, for tests or short-lived agents. */
117
128
  export declare function memoryStore(): SpendStore;
118
129
  export declare class Autonomo {
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import { homedir } from "node:os";
15
15
  import { dirname, join } from "node:path";
16
16
  import { createPublicClient, createWalletClient, defineChain, erc20Abi, formatUnits, getAddress, http, maxUint256, parseUnits, toHex, } from "viem";
17
17
  import { privateKeyToAccount } from "viem/accounts";
18
- export const VERSION = "0.1.0";
18
+ export const VERSION = "0.1.2";
19
19
  const NETWORK = "eip155:4663";
20
20
  const CHAIN_ID = 4663;
21
21
  const EXPLORER = "https://robinhoodchain.blockscout.com";
@@ -26,7 +26,7 @@ export const TOKENS = {
26
26
  usdg: { name: "usdg", symbol: "USDG", address: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168", decimals: 6 },
27
27
  autonomo: { name: "autonomo", symbol: "AUTONOMO", address: "0xe83c85e1ead16fcfe85401e2b337fb4fb5b5cc96", decimals: 18 },
28
28
  };
29
- const DEFAULT_LIMITS = {
29
+ export const DEFAULT_LIMITS = {
30
30
  perCall: { usdg: "0.05", autonomo: "5000" },
31
31
  daily: { usdg: "1", autonomo: "10000" },
32
32
  };
@@ -103,7 +103,7 @@ export function rankApis(apis, query, input) {
103
103
  return scored.sort((x, y) => y.hits - x.hits || y.trust - x.trust).map((s) => s.a);
104
104
  }
105
105
  // ---------- Spending ----------
106
- function fileStore(file = join(homedir(), ".autonomo", "spend.json")) {
106
+ export function fileStore(file = join(homedir(), ".autonomo", "spend.json")) {
107
107
  const read = () => {
108
108
  try {
109
109
  return JSON.parse(readFileSync(file, "utf8"));
package/package.json CHANGED
@@ -1,47 +1,50 @@
1
- {
2
- "name": "autonomo-sdk",
3
- "version": "0.1.0",
4
- "description": "One call for AI agents: find the right paid API on Autonomo, pay in USDG or $AUTONOMO (privately through Gloam, or on Borro credit), within spending caps, and get a receipt.",
5
- "homepage": "https://autonomo.fun",
6
- "author": "Autonomo (https://autonomo.fun)",
7
- "license": "MIT",
8
- "type": "module",
9
- "main": "dist/index.js",
10
- "types": "dist/index.d.ts",
11
- "exports": {
12
- ".": {
13
- "types": "./dist/index.d.ts",
14
- "import": "./dist/index.js"
15
- }
16
- },
17
- "files": [
18
- "dist",
19
- "README.md",
20
- "LICENSE"
21
- ],
22
- "engines": {
23
- "node": ">=20"
24
- },
25
- "scripts": {
26
- "build": "tsc -p .",
27
- "test": "node --test test/*.test.mjs"
28
- },
29
- "keywords": [
30
- "x402",
31
- "autonomo",
32
- "ai-agents",
33
- "robinhood-chain",
34
- "usdg",
35
- "payments",
36
- "gloam",
37
- "borro"
38
- ],
39
- "dependencies": {
40
- "viem": "2.57.12"
41
- },
42
- "devDependencies": {
43
- "@modelcontextprotocol/sdk": "^1.32.1",
44
- "@types/node": "26.6.5",
45
- "typescript": "7.0.2"
46
- }
47
- }
1
+ {
2
+ "name": "autonomo-sdk",
3
+ "version": "0.1.2",
4
+ "description": "One call for AI agents: find the right paid API on Autonomo, pay in USDG or $AUTONOMO (privately through Gloam, or on Borro credit), within spending caps, and get a receipt.",
5
+ "homepage": "https://autonomo.fun",
6
+ "author": "Autonomo (https://autonomo.fun)",
7
+ "license": "MIT",
8
+ "type": "module",
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "engines": {
23
+ "node": ">=20"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc -p .",
27
+ "test": "node --test test/*.test.mjs"
28
+ },
29
+ "keywords": [
30
+ "x402",
31
+ "autonomo",
32
+ "ai-agents",
33
+ "robinhood-chain",
34
+ "usdg",
35
+ "payments",
36
+ "gloam",
37
+ "borro"
38
+ ],
39
+ "dependencies": {
40
+ "viem": "2.57.12"
41
+ },
42
+ "devDependencies": {
43
+ "@modelcontextprotocol/sdk": "^1.32.1",
44
+ "@types/node": "26.6.5",
45
+ "typescript": "7.0.2"
46
+ },
47
+ "bin": {
48
+ "autonomo": "dist/cli.js"
49
+ }
50
+ }