@absol-labs/agent 0.10.0 → 0.12.0-rc.1
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 +106 -30
- package/dist/capability/invocation-capability.d.ts +20 -8
- package/dist/capability/invocation-capability.d.ts.map +1 -1
- package/dist/capability/invocation-capability.js.map +1 -1
- package/dist/capability/probe-capability.d.ts +225 -0
- package/dist/capability/probe-capability.d.ts.map +1 -0
- package/dist/capability/probe-capability.js +248 -0
- package/dist/capability/probe-capability.js.map +1 -0
- package/dist/cli/args.d.ts +11 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +23 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/commands/claim.d.ts.map +1 -1
- package/dist/cli/commands/claim.js +21 -5
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.d.ts.map +1 -1
- package/dist/cli/commands/close.js +51 -7
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/invoke.d.ts +2 -0
- package/dist/cli/commands/invoke.d.ts.map +1 -1
- package/dist/cli/commands/invoke.js +3 -2
- package/dist/cli/commands/invoke.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +15 -2
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/open.d.ts.map +1 -1
- package/dist/cli/commands/open.js +121 -15
- package/dist/cli/commands/open.js.map +1 -1
- package/dist/cli/commands/pay.d.ts +19 -0
- package/dist/cli/commands/pay.d.ts.map +1 -0
- package/dist/cli/commands/pay.js +355 -0
- package/dist/cli/commands/pay.js.map +1 -0
- package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -1
- package/dist/cli/commands/reclaim-unverified.js +15 -6
- package/dist/cli/commands/reclaim-unverified.js.map +1 -1
- package/dist/cli/commands/reclaim.d.ts +23 -2
- package/dist/cli/commands/reclaim.d.ts.map +1 -1
- package/dist/cli/commands/reclaim.js +200 -21
- package/dist/cli/commands/reclaim.js.map +1 -1
- package/dist/cli/commands/refund.d.ts +13 -0
- package/dist/cli/commands/refund.d.ts.map +1 -0
- package/dist/cli/commands/refund.js +224 -0
- package/dist/cli/commands/refund.js.map +1 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +10 -1
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/streams.js +9 -13
- package/dist/cli/commands/streams.js.map +1 -1
- package/dist/cli/commands/watch.d.ts.map +1 -1
- package/dist/cli/commands/watch.js +2 -1
- package/dist/cli/commands/watch.js.map +1 -1
- package/dist/cli/config.d.ts +44 -26
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +88 -38
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/deps.d.ts +86 -7
- package/dist/cli/deps.d.ts.map +1 -1
- package/dist/cli/deps.js +102 -16
- package/dist/cli/deps.js.map +1 -1
- package/dist/cli/errors.d.ts.map +1 -1
- package/dist/cli/errors.js +21 -1
- package/dist/cli/errors.js.map +1 -1
- package/dist/cli/escape-hatch.d.ts +6 -4
- package/dist/cli/escape-hatch.d.ts.map +1 -1
- package/dist/cli/escape-hatch.js +6 -2
- package/dist/cli/escape-hatch.js.map +1 -1
- package/dist/cli/listings.d.ts +18 -0
- package/dist/cli/listings.d.ts.map +1 -1
- package/dist/cli/listings.js +22 -12
- package/dist/cli/listings.js.map +1 -1
- package/dist/cli/preflight.d.ts +20 -14
- package/dist/cli/preflight.d.ts.map +1 -1
- package/dist/cli/preflight.js +34 -20
- package/dist/cli/preflight.js.map +1 -1
- package/dist/cli/privy.d.ts +83 -0
- package/dist/cli/privy.d.ts.map +1 -0
- package/dist/cli/privy.js +232 -0
- package/dist/cli/privy.js.map +1 -0
- package/dist/cli/reclaimability.d.ts +82 -0
- package/dist/cli/reclaimability.d.ts.map +1 -0
- package/dist/cli/reclaimability.js +80 -0
- package/dist/cli/reclaimability.js.map +1 -0
- package/dist/cli/run.d.ts +2 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +40 -11
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/scan-range.d.ts +2 -2
- package/dist/cli/scan-range.js +2 -2
- package/dist/cli/spend-policy.d.ts +60 -0
- package/dist/cli/spend-policy.d.ts.map +1 -0
- package/dist/cli/spend-policy.js +65 -0
- package/dist/cli/spend-policy.js.map +1 -0
- package/dist/cli/status.d.ts +3 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +15 -3
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/wallet.d.ts +109 -40
- package/dist/cli/wallet.d.ts.map +1 -1
- package/dist/cli/wallet.js +109 -44
- package/dist/cli/wallet.js.map +1 -1
- package/dist/discovery/rate-band.d.ts +74 -0
- package/dist/discovery/rate-band.d.ts.map +1 -0
- package/dist/discovery/rate-band.js +114 -0
- package/dist/discovery/rate-band.js.map +1 -0
- package/dist/escrow-generation.d.ts +81 -0
- package/dist/escrow-generation.d.ts.map +1 -0
- package/dist/escrow-generation.js +76 -0
- package/dist/escrow-generation.js.map +1 -0
- package/dist/frameworks/agentkit.d.ts +8 -4
- package/dist/frameworks/agentkit.d.ts.map +1 -1
- package/dist/frameworks/agentkit.js +27 -10
- package/dist/frameworks/agentkit.js.map +1 -1
- package/dist/frameworks/eliza.d.ts +3 -3
- package/dist/frameworks/eliza.d.ts.map +1 -1
- package/dist/frameworks/eliza.js +15 -6
- package/dist/frameworks/eliza.js.map +1 -1
- package/dist/frameworks/langchain.d.ts.map +1 -1
- package/dist/frameworks/langchain.js +8 -0
- package/dist/frameworks/langchain.js.map +1 -1
- package/dist/gateway/caller-auth-gateway.d.ts +91 -4
- package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
- package/dist/gateway/caller-auth-gateway.js +184 -7
- package/dist/gateway/caller-auth-gateway.js.map +1 -1
- package/dist/gateway/http-server.d.ts +121 -1
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +474 -5
- package/dist/gateway/http-server.js.map +1 -1
- package/dist/gateway/probe-auth.d.ts +112 -0
- package/dist/gateway/probe-auth.d.ts.map +1 -0
- package/dist/gateway/probe-auth.js +127 -0
- package/dist/gateway/probe-auth.js.map +1 -0
- package/dist/gateway/signed-rate-bounds.d.ts +51 -0
- package/dist/gateway/signed-rate-bounds.d.ts.map +1 -0
- package/dist/gateway/signed-rate-bounds.js +94 -0
- package/dist/gateway/signed-rate-bounds.js.map +1 -0
- package/dist/gateway/x402-opener-mode.d.ts +215 -0
- package/dist/gateway/x402-opener-mode.d.ts.map +1 -0
- package/dist/gateway/x402-opener-mode.js +639 -0
- package/dist/gateway/x402-opener-mode.js.map +1 -0
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/dist/mandates/env.d.ts +3 -2
- package/dist/mandates/env.d.ts.map +1 -1
- package/dist/mandates/env.js +3 -2
- package/dist/mandates/env.js.map +1 -1
- package/dist/mcp/server.d.ts +100 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +719 -39
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/service-invoker.d.ts +97 -0
- package/dist/mcp/service-invoker.d.ts.map +1 -0
- package/dist/mcp/service-invoker.js +167 -0
- package/dist/mcp/service-invoker.js.map +1 -0
- package/dist/mcp/x402-tools.d.ts +104 -0
- package/dist/mcp/x402-tools.d.ts.map +1 -0
- package/dist/mcp/x402-tools.js +434 -0
- package/dist/mcp/x402-tools.js.map +1 -0
- package/dist/network.d.ts +119 -0
- package/dist/network.d.ts.map +1 -0
- package/dist/network.js +199 -0
- package/dist/network.js.map +1 -0
- package/dist/sdk/invoke.d.ts +23 -4
- package/dist/sdk/invoke.d.ts.map +1 -1
- package/dist/sdk/invoke.js +71 -10
- package/dist/sdk/invoke.js.map +1 -1
- package/dist/wallet/autonomous-wallet-broker.d.ts +3 -0
- package/dist/wallet/autonomous-wallet-broker.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet-broker.js +27 -23
- package/dist/wallet/autonomous-wallet-broker.js.map +1 -1
- package/dist/wallet/autonomous-wallet-protocol.d.ts +8 -2
- package/dist/wallet/autonomous-wallet-protocol.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet-protocol.js +9 -2
- package/dist/wallet/autonomous-wallet-protocol.js.map +1 -1
- package/dist/wallet/autonomous-wallet.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet.js +3 -2
- package/dist/wallet/autonomous-wallet.js.map +1 -1
- package/dist/wallet/broker-escrows.d.ts +222 -0
- package/dist/wallet/broker-escrows.d.ts.map +1 -0
- package/dist/wallet/broker-escrows.js +36 -0
- package/dist/wallet/broker-escrows.js.map +1 -0
- package/dist/wallet/lifecycle.d.ts +21 -5
- package/dist/wallet/lifecycle.d.ts.map +1 -1
- package/dist/wallet/lifecycle.js +32 -12
- package/dist/wallet/lifecycle.js.map +1 -1
- package/dist/wallet/privy-broker-server.d.ts.map +1 -1
- package/dist/wallet/privy-broker-server.js +31 -26
- package/dist/wallet/privy-broker-server.js.map +1 -1
- package/dist/wallet/privy-session-broker.d.ts +14 -5
- package/dist/wallet/privy-session-broker.d.ts.map +1 -1
- package/dist/wallet/privy-session-broker.js +29 -17
- package/dist/wallet/privy-session-broker.js.map +1 -1
- package/dist/wallet/privy-session-provider.d.ts +3 -1
- package/dist/wallet/privy-session-provider.d.ts.map +1 -1
- package/dist/wallet/privy-session-provider.js +5 -3
- package/dist/wallet/privy-session-provider.js.map +1 -1
- package/dist/wallet/provider.d.ts.map +1 -1
- package/dist/wallet/provider.js +15 -8
- package/dist/wallet/provider.js.map +1 -1
- package/dist/x402/facilitator.d.ts +42 -17
- package/dist/x402/facilitator.d.ts.map +1 -1
- package/dist/x402/facilitator.js +49 -33
- package/dist/x402/facilitator.js.map +1 -1
- package/dist/x402-buyer/guarded-fetch.d.ts +51 -0
- package/dist/x402-buyer/guarded-fetch.d.ts.map +1 -0
- package/dist/x402-buyer/guarded-fetch.js +147 -0
- package/dist/x402-buyer/guarded-fetch.js.map +1 -0
- package/dist/x402-buyer/index.d.ts +10 -0
- package/dist/x402-buyer/index.d.ts.map +1 -0
- package/dist/x402-buyer/index.js +10 -0
- package/dist/x402-buyer/index.js.map +1 -0
- package/dist/x402-buyer/pay.d.ts +135 -0
- package/dist/x402-buyer/pay.d.ts.map +1 -0
- package/dist/x402-buyer/pay.js +336 -0
- package/dist/x402-buyer/pay.js.map +1 -0
- package/dist/x402-opener/abi.d.ts +684 -0
- package/dist/x402-opener/abi.d.ts.map +1 -0
- package/dist/x402-opener/abi.js +880 -0
- package/dist/x402-opener/abi.js.map +1 -0
- package/dist/x402-opener/facilitator-entry.d.ts +3 -0
- package/dist/x402-opener/facilitator-entry.d.ts.map +1 -0
- package/dist/x402-opener/facilitator-entry.js +37 -0
- package/dist/x402-opener/facilitator-entry.js.map +1 -0
- package/dist/x402-opener/facilitator-server.d.ts +180 -0
- package/dist/x402-opener/facilitator-server.d.ts.map +1 -0
- package/dist/x402-opener/facilitator-server.js +696 -0
- package/dist/x402-opener/facilitator-server.js.map +1 -0
- package/dist/x402-opener/index.d.ts +14 -0
- package/dist/x402-opener/index.d.ts.map +1 -0
- package/dist/x402-opener/index.js +14 -0
- package/dist/x402-opener/index.js.map +1 -0
- package/dist/x402-opener/listing-resolver.d.ts +55 -0
- package/dist/x402-opener/listing-resolver.d.ts.map +1 -0
- package/dist/x402-opener/listing-resolver.js +125 -0
- package/dist/x402-opener/listing-resolver.js.map +1 -0
- package/dist/x402-opener/refund-relay.d.ts +240 -0
- package/dist/x402-opener/refund-relay.d.ts.map +1 -0
- package/dist/x402-opener/refund-relay.js +1240 -0
- package/dist/x402-opener/refund-relay.js.map +1 -0
- package/dist/x402-opener/relayer-queue.d.ts +14 -0
- package/dist/x402-opener/relayer-queue.d.ts.map +1 -0
- package/dist/x402-opener/relayer-queue.js +18 -0
- package/dist/x402-opener/relayer-queue.js.map +1 -0
- package/dist/x402-opener/scheme.d.ts +217 -0
- package/dist/x402-opener/scheme.d.ts.map +1 -0
- package/dist/x402-opener/scheme.js +749 -0
- package/dist/x402-opener/scheme.js.map +1 -0
- package/dist/x402-opener/terms.d.ts +105 -0
- package/dist/x402-opener/terms.d.ts.map +1 -0
- package/dist/x402-opener/terms.js +212 -0
- package/dist/x402-opener/terms.js.map +1 -0
- package/dist/zktls/reclaim.d.ts +2 -2
- package/docs/agent-layer.md +13 -8
- package/docs/autonomous-privy-wallet.md +188 -0
- package/docs/cli.md +342 -53
- package/docs/langchain.md +5 -0
- package/docs/mcp-hosted.md +4 -3
- package/docs/mcp-reference.md +245 -0
- package/docs/probe-capability.md +191 -0
- package/docs/quickstart.md +54 -5
- package/docs/threat-model.md +24 -3
- package/docs/x402.md +681 -0
- package/package.json +19 -6
- package/src/capability/invocation-capability.ts +17 -1
- package/src/capability/probe-capability.ts +355 -0
- package/src/cli/args.ts +29 -0
- package/src/cli/commands/claim.ts +31 -5
- package/src/cli/commands/close.ts +56 -7
- package/src/cli/commands/invoke.ts +6 -2
- package/src/cli/commands/mcp.ts +18 -2
- package/src/cli/commands/open.ts +151 -14
- package/src/cli/commands/pay.ts +442 -0
- package/src/cli/commands/reclaim-unverified.ts +24 -6
- package/src/cli/commands/reclaim.ts +274 -19
- package/src/cli/commands/refund.ts +277 -0
- package/src/cli/commands/status.ts +17 -1
- package/src/cli/commands/streams.ts +11 -15
- package/src/cli/commands/watch.ts +7 -1
- package/src/cli/config.ts +139 -52
- package/src/cli/deps.ts +189 -25
- package/src/cli/errors.ts +24 -1
- package/src/cli/escape-hatch.ts +19 -5
- package/src/cli/listings.ts +43 -10
- package/src/cli/preflight.ts +36 -21
- package/src/cli/privy.ts +398 -0
- package/src/cli/reclaimability.ts +154 -0
- package/src/cli/run.ts +54 -11
- package/src/cli/scan-range.ts +2 -2
- package/src/cli/spend-policy.ts +139 -0
- package/src/cli/status.ts +14 -1
- package/src/cli/wallet.ts +189 -58
- package/src/discovery/rate-band.ts +172 -0
- package/src/escrow-generation.ts +135 -0
- package/src/frameworks/agentkit.ts +45 -11
- package/src/frameworks/eliza.ts +27 -5
- package/src/frameworks/langchain.ts +14 -0
- package/src/gateway/caller-auth-gateway.ts +336 -13
- package/src/gateway/http-server.ts +690 -7
- package/src/gateway/probe-auth.ts +191 -0
- package/src/gateway/signed-rate-bounds.ts +164 -0
- package/src/gateway/x402-opener-mode.ts +974 -0
- package/src/index.ts +112 -14
- package/src/mandates/env.ts +3 -2
- package/src/mcp/server.ts +973 -44
- package/src/mcp/service-invoker.ts +285 -0
- package/src/mcp/x402-tools.ts +621 -0
- package/src/network.ts +302 -0
- package/src/sdk/invoke.ts +96 -17
- package/src/wallet/autonomous-wallet-broker.ts +46 -20
- package/src/wallet/autonomous-wallet-protocol.ts +11 -2
- package/src/wallet/autonomous-wallet.ts +4 -2
- package/src/wallet/broker-escrows.ts +66 -0
- package/src/wallet/lifecycle.ts +53 -18
- package/src/wallet/privy-broker-server.ts +35 -25
- package/src/wallet/privy-session-broker.ts +58 -25
- package/src/wallet/privy-session-provider.ts +7 -3
- package/src/wallet/provider.ts +20 -15
- package/src/x402/facilitator.ts +85 -46
- package/src/x402-buyer/guarded-fetch.ts +213 -0
- package/src/x402-buyer/index.ts +9 -0
- package/src/x402-buyer/pay.ts +517 -0
- package/src/x402-opener/abi.ts +881 -0
- package/src/x402-opener/facilitator-entry.ts +45 -0
- package/src/x402-opener/facilitator-server.ts +1014 -0
- package/src/x402-opener/index.ts +13 -0
- package/src/x402-opener/listing-resolver.ts +202 -0
- package/src/x402-opener/refund-relay.ts +1743 -0
- package/src/x402-opener/relayer-queue.ts +18 -0
- package/src/x402-opener/scheme.ts +1133 -0
- package/src/x402-opener/terms.ts +300 -0
package/docs/cli.md
CHANGED
|
@@ -46,7 +46,8 @@ consumer who installed the package could not run at all. `metrik mcp
|
|
|
46
46
|
## Testnet only
|
|
47
47
|
|
|
48
48
|
The CLI signs with a raw private key and moves USDC, so the chain is an **allowlist**,
|
|
49
|
-
not a default: only
|
|
49
|
+
not a default: only networks the `@absol-labs/sdk` network registry knows **and marks as
|
|
50
|
+
a testnet** are accepted (today: Base Sepolia, `84532`). There is deliberately **no
|
|
50
51
|
override flag** — an escape hatch that re-enabled real funds would defeat the guarantee,
|
|
51
52
|
and there is no mainnet deployment for it to reach anyway.
|
|
52
53
|
|
|
@@ -60,47 +61,194 @@ The rule is enforced twice:
|
|
|
60
61
|
|
|
61
62
|
## Wallet
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
Three wallet sources, resolved in a **fixed order** — first match wins:
|
|
64
65
|
|
|
65
66
|
| Order | Variables | Wallet |
|
|
66
67
|
| ----- | ------------------------------------------------------------------------------------------ | --------------------------------------- |
|
|
67
68
|
| 1 | `METRIK_AGENT_PRIVATE_KEY` | a raw Base Sepolia test key |
|
|
68
69
|
| 2 | `CDP_API_KEY_ID`, `CDP_API_KEY_SECRET`, `CDP_WALLET_SECRET`, `METRIK_AGENT_CDP_OWNER_NAME` | a Coinbase CDP Server Wallet v2 account |
|
|
70
|
+
| 3 | `METRIK_AGENT_PRIVY_*` (below) | a Privy wallet reached through a broker |
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
CLI, the MCP server and the framework adapters identically. The order is
|
|
72
|
-
rather than "whichever is configured": an environment carrying
|
|
73
|
-
which address funds the stream, and that ambiguity is a fund-moving one. When
|
|
74
|
-
present the
|
|
72
|
+
The first two are the same order `parseAgentWalletEnv()` uses, so one environment
|
|
73
|
+
configures the CLI, the MCP server and the framework adapters identically. The order is
|
|
74
|
+
**fixed** rather than "whichever is configured": an environment carrying two is ambiguous
|
|
75
|
+
about which address funds the stream, and that ambiguity is a fund-moving one. When more
|
|
76
|
+
than one is present the earlier entry wins and the CLI says so on stderr rather than
|
|
77
|
+
choosing quietly.
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
deeper:
|
|
79
|
+
Misconfigurations are refused up front, at exit `3`, instead of failing somewhere deeper:
|
|
78
80
|
|
|
79
|
-
- **A half-configured
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
- **A half-configured wallet** ("you set three of the four CDP variables", "you set the
|
|
82
|
+
Privy session token but not the address") is reported as exactly that, naming the
|
|
83
|
+
missing variables. Rendering it as "no wallet is configured" would send the reader
|
|
84
|
+
looking in the wrong place.
|
|
82
85
|
- **A CDP _smart_ account** (`METRIK_AGENT_CDP_CREATE_SMART_ACCOUNT` /
|
|
83
86
|
`METRIK_AGENT_CDP_SMART_ACCOUNT_NAME`) is refused. It is an ERC-4337 account at a
|
|
84
87
|
different address from its owner, reached through a bundler; this CLI broadcasts
|
|
85
88
|
through `--rpc-url`, so it would sign and spend from the **owner** while you funded the
|
|
86
89
|
smart account.
|
|
87
|
-
- **
|
|
88
|
-
later inside viem.
|
|
90
|
+
- **An account that cannot sign** is refused with the reason, rather than accepted and
|
|
91
|
+
failed later inside viem. The check is about capability, not locality: every wallet must
|
|
92
|
+
be able to sign EIP-712 typed data, and only the paths that broadcast through
|
|
93
|
+
`--rpc-url` additionally need a local signer.
|
|
89
94
|
|
|
90
95
|
There is no `--private-key` flag, and there will not be one — nor a flag for any other
|
|
91
96
|
credential: a secret on the command line lands in shell history, in `ps` output, and in
|
|
92
97
|
any CI log that echoes the command. Commands print the derived **address**; the
|
|
93
98
|
credential is never echoed, including by `metrik mcp --print-config`.
|
|
94
99
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
### Privy
|
|
101
|
+
|
|
102
|
+
A Privy wallet differs from the other two in one structural way: its account has no local
|
|
103
|
+
`signTransaction`. It signs and broadcasts by sending `eth_sendTransaction` /
|
|
104
|
+
`eth_signTypedData_v4` to a provider, so for a Privy wallet the **provider is the wallet
|
|
105
|
+
client's transport** instead of the plain `http(--rpc-url)` a local signer uses. That is
|
|
106
|
+
the whole of the wiring. Private-key and CDP runs are unchanged, byte for byte.
|
|
107
|
+
|
|
108
|
+
**`metrik claim` does not work on a Privy wallet.** The broker's transaction allowlist
|
|
109
|
+
carries the BUYER actions only (`openStream`, `close`, `reclaim`, `reclaimUnverified`), so
|
|
110
|
+
an operator claim is refused server-side and the client cannot raise that ceiling. Claim
|
|
111
|
+
with the operator's own `METRIK_AGENT_PRIVATE_KEY`. Every other command works. The CLI
|
|
112
|
+
warns when you try it, and `metrik --help` / `metrik claim --help` say so up front.
|
|
113
|
+
|
|
114
|
+
**`metrik mcp` does not carry a Privy wallet either.** The MCP server resolves its wallet
|
|
115
|
+
with `parseAgentWalletEnv()`, which reads `METRIK_AGENT_PRIVATE_KEY` or the CDP variables
|
|
116
|
+
and has no Privy branch — so `metrik mcp --print-config` prints a key placeholder and says
|
|
117
|
+
why on stderr rather than emitting Privy variables the server would ignore.
|
|
118
|
+
|
|
119
|
+
There are two shapes. Set one; setting both uses the agent-owned wallet and says so.
|
|
120
|
+
|
|
121
|
+
**Agent-owned (`privy-autonomous`)** — headless, no browser, no user login:
|
|
122
|
+
|
|
123
|
+
| Variable | Required | What it is |
|
|
124
|
+
| ------------------------------- | -------- | ------------------------------------------------------------------------ |
|
|
125
|
+
| `METRIK_AGENT_PRIVY_WALLET_KEY` | yes | the credential-store key of a wallet you already provisioned |
|
|
126
|
+
| `METRIK_AGENT_PRIVY_BROKER_URL` | no | overrides the broker the wallet was provisioned against |
|
|
127
|
+
| `METRIK_WALLET_ENCRYPTION_KEY` | no | selects the encrypted-file store (the durable option on a headless host) |
|
|
128
|
+
|
|
129
|
+
**The CLI never provisions a wallet for you.** A fund-moving command is the wrong place to
|
|
130
|
+
mint one, so if nothing is stored under that key the CLI says so and stops. Provision once,
|
|
131
|
+
deliberately — see [autonomous-privy-wallet.md](./autonomous-privy-wallet.md):
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
import { provisionMetrikAutonomousWallet } from "@absol-labs/agent";
|
|
135
|
+
|
|
136
|
+
const wallet = await provisionMetrikAutonomousWallet({
|
|
137
|
+
storeKey: "my-agent/base-sepolia",
|
|
138
|
+
});
|
|
139
|
+
console.log(wallet.address); // fund this with test USDC and Base Sepolia ETH
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
export METRIK_AGENT_PRIVY_WALLET_KEY=my-agent/base-sepolia
|
|
144
|
+
metrik invoke 0x… --path /health
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Read the credential-store durability section of that document before funding anything: on
|
|
148
|
+
a headless Linux host the OS store is **not** durable and provisioning is refused, which
|
|
149
|
+
is why `METRIK_WALLET_ENCRYPTION_KEY` exists. The CLI selects the same store the same way
|
|
150
|
+
— set that variable and it reads the encrypted file, unset and it reads the OS store — so
|
|
151
|
+
a mismatch between provisioning and use simply finds no wallet and says so.
|
|
152
|
+
|
|
153
|
+
**User-owned broker session (`privy-session`)** — a scoped session minted from a Privy
|
|
154
|
+
login (today that means the dApp, which holds the user's Privy access token):
|
|
155
|
+
|
|
156
|
+
| Variable | Required | What it is |
|
|
157
|
+
| ---------------------------------- | -------- | ------------------------------------------------------------------ |
|
|
158
|
+
| `METRIK_AGENT_PRIVY_BROKER_URL` | yes | the broker that minted the token; a token is valid nowhere else |
|
|
159
|
+
| `METRIK_AGENT_PRIVY_SESSION_TOKEN` | yes | the token from the broker's `POST /v1/sessions` |
|
|
160
|
+
| `METRIK_AGENT_PRIVY_ADDRESS` | yes | the embedded wallet address the session is bound to |
|
|
161
|
+
| `METRIK_AGENT_PRIVY_APP_ID` | yes | the **public** Privy app id — the broker serves it at `/v1/config` |
|
|
162
|
+
|
|
163
|
+
#### Which broker the CLI talks to
|
|
164
|
+
|
|
165
|
+
The agent-owned path defaults to the broker URL the wallet was provisioned against, which
|
|
166
|
+
for `provisionMetrikAutonomousWallet()` is the Metrik broker at
|
|
167
|
+
`https://wallet.137.23.50.249.sslip.io`. Its `GET /health` and `GET /v1/config` answer
|
|
168
|
+
publicly; `/v1/config` carries only the public app id, the public policy id and the fixed
|
|
169
|
+
policy ceilings, and nothing there is a secret. The Privy **authorization key** stays on
|
|
170
|
+
the broker and is never served.
|
|
171
|
+
|
|
172
|
+
If you would rather not trust that deployment, run your own: it is
|
|
173
|
+
`metrik-privy-broker` from this package (`src/wallet/privy-broker-server.ts`), it needs
|
|
174
|
+
your own `PRIVY_APP_ID` / `PRIVY_APP_SECRET` / authorization key / policy id, and you then
|
|
175
|
+
point `METRIK_AGENT_PRIVY_BROKER_URL` at it. A wallet provisioned against one broker
|
|
176
|
+
cannot be authorized by another — only the broker holding that wallet's Privy
|
|
177
|
+
authorization key can sign for it — so switching brokers means provisioning a new wallet.
|
|
178
|
+
|
|
179
|
+
#### The spend mandate, and why a Privy wallet does not sign one
|
|
180
|
+
|
|
181
|
+
Every fund-moving command in this package normally self-signs an EIP-712
|
|
182
|
+
`SpendMandate` first. Read why, from `src/cli/mandate.ts`: _"the person typing
|
|
183
|
+
the command IS the mandate owner: they hold the key and they just stated the
|
|
184
|
+
exact spend on the command line."_ The mandate exists because, for a key-holding
|
|
185
|
+
wallet, the client is the last line of defence — so the agent is made to state
|
|
186
|
+
its own ceiling and is held to it.
|
|
187
|
+
|
|
188
|
+
**For a Privy wallet that premise is false.** The user does not hold the key: it
|
|
189
|
+
lives at Privy and is exercised by the broker, which caps every `openStream`
|
|
190
|
+
against a policy the client cannot reach and cannot raise. A self-signed mandate
|
|
191
|
+
on top of that is an agent attesting to its own limits when a stronger limit is
|
|
192
|
+
already enforced somewhere the agent cannot touch.
|
|
193
|
+
|
|
194
|
+
So for a policy-enforced wallet the CLI **does not sign a mandate**, and
|
|
195
|
+
**substitutes the real ceiling instead of dropping the check**: it reads the
|
|
196
|
+
broker's public `GET /v1/config` and refuses an over-ceiling hire locally, in the
|
|
197
|
+
same shape as the gas and USDC preflights — fail early with an actionable
|
|
198
|
+
message rather than paying gas to learn a knowable fact. `open --dry-run`
|
|
199
|
+
reports the ceiling and whether the hire fits; a real `open` refuses.
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
mandate not signed — this wallet's ceiling is enforced by its broker, which is stronger
|
|
203
|
+
spend policy 1 USDC (1000000 atomic) total, 1000 atomic/second, 1h max — enforced by https://wallet.137.23.50.249.sslip.io
|
|
204
|
+
fits policy yes
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Two things this deliberately does NOT do:
|
|
208
|
+
|
|
209
|
+
- **It does not widen the broker.** Both brokers restrict `eth_signTypedData_v4`
|
|
210
|
+
to `primaryType: "InvocationCapability"`. Teaching them to sign a
|
|
211
|
+
`SpendMandate` would weaken the exact property that makes the wallet
|
|
212
|
+
non-custodial, to reinstate a check that is the weaker of the two.
|
|
213
|
+
- **It does not retire `METRIK_AGENT_MANDATE_*`.** Those caps are a standing
|
|
214
|
+
ceiling the operator deliberately chose, and can be TIGHTER than the broker
|
|
215
|
+
policy. They still apply, enforced locally, because no mandate is signed to
|
|
216
|
+
carry them.
|
|
217
|
+
|
|
218
|
+
Do not "restore" the mandate for consistency. It would both weaken the guarantee
|
|
219
|
+
and break every fund-moving command against the broker as deployed.
|
|
220
|
+
|
|
221
|
+
#### What works, and what does not
|
|
222
|
+
|
|
223
|
+
`open`, `close`, `reclaim`, `reclaim-unverified` and `invoke` all work with a
|
|
224
|
+
Privy wallet.
|
|
225
|
+
|
|
226
|
+
`metrik claim` does not, and that is not a Privy defect: `claim` is the
|
|
227
|
+
**operator's** side, and a broker policy allowlists the **buyer** actions only
|
|
228
|
+
(`openStream`, `close`, `reclaim`, `reclaimUnverified`, and a bounded USDC
|
|
229
|
+
approval to the escrow). An operator claims with the operator's own key. The CLI
|
|
230
|
+
says this before it runs rather than letting you discover it at the broker.
|
|
231
|
+
|
|
232
|
+
Privy support is Base Sepolia (84532) only, EOA only. No ERC-4337, no EIP-1271,
|
|
233
|
+
no gas sponsorship claim.
|
|
234
|
+
|
|
235
|
+
#### Trust model, honestly
|
|
236
|
+
|
|
237
|
+
A raw `METRIK_AGENT_PRIVATE_KEY` is the simplest thing that can possibly work and the CLI
|
|
238
|
+
holds the whole key: anything that reads your environment can move every token in that
|
|
239
|
+
wallet, forever.
|
|
240
|
+
|
|
241
|
+
Privy is not "no custody" — it is **different** custody. The signing key lives at Privy and
|
|
242
|
+
is exercised by the broker, so the parties who can move funds are Privy and whoever runs
|
|
243
|
+
the broker, together. What the CLI holds is a P-256 authorization key (agent-owned) or a
|
|
244
|
+
short-lived session token (session) — credentials that authorize a **policy-bounded**
|
|
245
|
+
request, not credentials that can drain the wallet. Leaking one is bounded by the broker's
|
|
246
|
+
policy: Base Sepolia only, the escrow and USDC contracts only, zero native value, and the
|
|
247
|
+
installed ceilings (`/v1/config`). Losing the agent-owned P-256 key is the mirror risk: the
|
|
248
|
+
wallet can never be authorized again and anything it holds is unspendable.
|
|
249
|
+
|
|
250
|
+
Pick a raw key if you are the only party and you want no third party in the path. Pick
|
|
251
|
+
Privy if you want a policy boundary between the machine running the agent and the money.
|
|
104
252
|
|
|
105
253
|
`invoke` needs the key too, even though it broadcasts nothing: it signs an **off-chain
|
|
106
254
|
EIP-712 invocation capability** as the stream's buyer. `open --dry-run` is the one path
|
|
@@ -109,19 +257,21 @@ that needs no key at all — it builds and prints the intended call and says whi
|
|
|
109
257
|
|
|
110
258
|
## Commands
|
|
111
259
|
|
|
112
|
-
| Command | Needs a wallet? | Broadcasts a tx?
|
|
113
|
-
| -------------------- | ------------------------------ |
|
|
114
|
-
| `discover` | no | no
|
|
115
|
-
| `open` | **yes** (not with `--dry-run`) | **yes**
|
|
116
|
-
| `status` | no | no
|
|
117
|
-
| `streams` | no (with `--address`) | no
|
|
118
|
-
| `watch` | no | no
|
|
119
|
-
| `invoke` | **yes** (off-chain capability) | no
|
|
120
|
-
| `
|
|
121
|
-
| `
|
|
122
|
-
| `
|
|
123
|
-
| `
|
|
124
|
-
| `
|
|
260
|
+
| Command | Needs a wallet? | Broadcasts a tx? | What it does |
|
|
261
|
+
| -------------------- | ------------------------------ | ----------------- | ------------------------------------------------ |
|
|
262
|
+
| `discover` | no | no | Lists verified registry listings |
|
|
263
|
+
| `open` | **yes** (not with `--dry-run`) | **yes** | Escrows USDC into a metered stream |
|
|
264
|
+
| `status` | no | no | One stream's on-chain state + verified accrual |
|
|
265
|
+
| `streams` | no (with `--address`) | no | Lists a wallet's streams from the escrow's logs |
|
|
266
|
+
| `watch` | no | no | Polls that until the stream closes |
|
|
267
|
+
| `invoke` | **yes** (off-chain capability) | no | Calls the paid service, authorized by the stream |
|
|
268
|
+
| `pay` | **yes** (EIP-3009 signature) | no (relayer does) | Pays an x402 endpoint into an escrow stream |
|
|
269
|
+
| `refund` | only for `--close` | no (relay does) | Gasless close/reclaim of an x402 stream |
|
|
270
|
+
| `close` | **yes** | **yes** | Stops the clock |
|
|
271
|
+
| `reclaim` | **yes** | **yes** | Takes back what was never earned |
|
|
272
|
+
| `reclaim-unverified` | **yes** | **yes** | Buyer escape hatch: reclaim with no proof |
|
|
273
|
+
| `claim` | **yes** (the operator's) | **yes** | Operator: redeem what verified |
|
|
274
|
+
| `mcp` | no | no | Prints the MCP client config for `metrik-mcp` |
|
|
125
275
|
|
|
126
276
|
### `metrik discover`
|
|
127
277
|
|
|
@@ -222,6 +372,21 @@ as `simulationPendingApproval: true`, with no `simulationError` — a script bra
|
|
|
222
372
|
that field no longer sees the expected path as a failure. An allowance-shaped revert when
|
|
223
373
|
the allowance IS already sufficient, and every other revert, are still surfaced as errors.
|
|
224
374
|
|
|
375
|
+
**The operator-signed rate band.** Before anything is signed or broadcast — `--dry-run`
|
|
376
|
+
included — `open` re-verifies the listing's operator-signed descriptor (the same check the
|
|
377
|
+
seller's gateway runs) and refuses at exit `2` when `--rate` is outside its
|
|
378
|
+
`minRatePerSecond`..`maxRatePerSecond` band, e.g. `the operator signed rates 100..10000
|
|
379
|
+
atomic/s (0.0001..0.01 USDC/s); --rate 20000 (0.02 USDC/s) would be refused by the
|
|
380
|
+
service's gateway`. The escrow accepts any non-zero rate, but the gateway answers every
|
|
381
|
+
request on an out-of-band stream with `403 stream-rate-out-of-bounds`, so the deposit
|
|
382
|
+
would sit in a stream that can never be served. Bounds are inclusive; a bound the operator
|
|
383
|
+
did not sign is not enforced, and a legacy binding signs none. A descriptor that does not
|
|
384
|
+
verify is a refusal (exit `4`), never "no band". Without `--operator`, an unreachable
|
|
385
|
+
registry already fails `open` (exit `4`). With `--operator` — the existing escape hatch for
|
|
386
|
+
a service the registry cannot vouch for — the band cannot be read, so the open proceeds
|
|
387
|
+
with a warning saying the rate was **not** checked. There is no flag to override a band
|
|
388
|
+
the CLI can read.
|
|
389
|
+
|
|
225
390
|
**Amounts.** `--budget` and `--rate` are decimal USDC by default; `--units atomic`
|
|
226
391
|
switches both to raw 6-decimal base units (what the escrow, the oracle and every
|
|
227
392
|
`METRIK_E2E_*` fixture use). The unit is explicit rather than inferred from magnitude,
|
|
@@ -384,7 +549,10 @@ Configured mandate ceilings are carried through verbatim — they are policy, no
|
|
|
384
549
|
and re-typing four caps from memory is where a wrong ceiling comes from. **Credentials are
|
|
385
550
|
always placeholders.** This command never reads a key out of your environment and prints
|
|
386
551
|
it back; the wallet block is simply shaped like the environment it ran in (the CDP
|
|
387
|
-
variables if those are what you have set, `METRIK_AGENT_PRIVATE_KEY` otherwise).
|
|
552
|
+
variables if those are what you have set, `METRIK_AGENT_PRIVATE_KEY` otherwise). A Privy
|
|
553
|
+
wallet is **not** an option here — `parseAgentWalletEnv()` has no Privy branch — so when
|
|
554
|
+
the environment carries one the command says so on stderr and prints a key placeholder
|
|
555
|
+
instead of a config the server could not start from.
|
|
388
556
|
|
|
389
557
|
### `metrik invoke`
|
|
390
558
|
|
|
@@ -414,6 +582,96 @@ listings ("consumer-attested T2 invocation is not supported for gated listings")
|
|
|
414
582
|
live listings are gated — so a `metrik prove` would be a command that fails for almost
|
|
415
583
|
everyone who ran it. It is left out until that constraint lifts.
|
|
416
584
|
|
|
585
|
+
### `metrik pay` (x402)
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
metrik pay https://x402.example/transform --json '{"text":"# hi"}' --max-amount 0.1
|
|
589
|
+
metrik pay <url> [--json <body> | --data <body>] [--method POST] [--header "K: V"] \
|
|
590
|
+
--max-amount <usdc> [--max-rate <usdc/s>] [--max-duration <s>] [--min-duration <s>] \
|
|
591
|
+
[--operator <address>] [--units atomic]
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
Pays any **x402 v2 `exact`** endpoint through `@absol-labs/sdk/x402`'s `payWithX402`,
|
|
595
|
+
with every SDK protection intact (network and USDC from the registry, EIP-3009 only,
|
|
596
|
+
registered opener factory, `payTo == factory.predict(terms)` read on-chain, bounded
|
|
597
|
+
authorization lifetime, a plain transfer to the seller refused). A Metrik seller's
|
|
598
|
+
payment opens an escrow stream with `deposit = price`; the seller earns
|
|
599
|
+
`ratePerSecond x verified seconds`, capped at the deposit.
|
|
600
|
+
|
|
601
|
+
The payer needs **USDC only, no gas** (the facilitator's relayer submits the
|
|
602
|
+
authorization). A Privy wallet cannot pay: its broker does not sign EIP-3009.
|
|
603
|
+
|
|
604
|
+
**How the spend mandate bounds an x402 payment.** No spend without a mandate: a
|
|
605
|
+
payment IS a stream open, so its opener terms are checked by `checkMandate()` exactly
|
|
606
|
+
like `metrik open`, inside the SDK's `onQuote` hook, after the SDK's own checks and
|
|
607
|
+
**before anything is signed**:
|
|
608
|
+
|
|
609
|
+
| Mandate cap | Checked against |
|
|
610
|
+
| ---------------------- | ---------------------------------------------- |
|
|
611
|
+
| `maxPerStreamUsdc` | the quote's `amount` (= the deposit) |
|
|
612
|
+
| `maxTotalUsdc` | spent so far + `amount` |
|
|
613
|
+
| `maxRatePerSecondUsdc` | `ratePerSecond` (how fast the seller can earn) |
|
|
614
|
+
| `maxDurationSeconds` | `maxDuration` (the stream window) |
|
|
615
|
+
| `allowedOperators` | `operator` (who the stream pays) |
|
|
616
|
+
|
|
617
|
+
The caps are also handed to the SDK as `maxAmount` / `maxRatePerSecond`, so the price is
|
|
618
|
+
enforced twice. A quote with no opener terms is refused. The mandate comes from
|
|
619
|
+
`METRIK_AGENT_MANDATE_*` when set, otherwise it is sized to this command:
|
|
620
|
+
`--max-amount` (required then) is the per-stream and total cap, `--max-rate` the rate cap
|
|
621
|
+
(default: no tighter than the price), `--max-duration` the window cap (default 1 day),
|
|
622
|
+
`--operator` the only allowed operator. With a standing mandate, every flag
|
|
623
|
+
**intersects** it (the most restrictive value wins; an `--operator` outside
|
|
624
|
+
`METRIK_AGENT_MANDATE_ALLOWED_OPERATORS` is refused): a flag can tighten the
|
|
625
|
+
standing ceiling, never loosen or bypass it. Like every CLI mandate it covers one
|
|
626
|
+
invocation.
|
|
627
|
+
|
|
628
|
+
If anything fails after the authorization was handed to the seller, `metrik pay`
|
|
629
|
+
establishes the outcome on-chain (USDC `authorizationState`, the opener's
|
|
630
|
+
`StreamOpenedFor` log for that nonce), exits `4`, and says whether the money left
|
|
631
|
+
the payer — with the `streamId` and the recovery command when the stream is found.
|
|
632
|
+
It never reports "nothing moved" unless the authorization was unused and expired.
|
|
633
|
+
|
|
634
|
+
A quote naming a **legacy** deployment's factory (for example a seller still on
|
|
635
|
+
StreamEscrowV2 after the default moved to V3) is refused by the SDK unless you pass
|
|
636
|
+
`--allow-legacy-factory`; that stream is then closed and reclaimed on the legacy
|
|
637
|
+
escrow, and the printed recovery command carries `--escrow <legacy escrow>`.
|
|
638
|
+
|
|
639
|
+
`--json <body>` is the request body (curl-style, sets `content-type: application/json`);
|
|
640
|
+
a bare `--json` still selects JSON output, and both can be combined. The output is the
|
|
641
|
+
response, the `streamId`, the opener, the deposit and rate, `minEarnSeconds` (after how
|
|
642
|
+
many verified seconds nothing is left to reclaim) and the **refund URL**.
|
|
643
|
+
**Refunds are not automatic** — see `metrik refund`.
|
|
644
|
+
|
|
645
|
+
Exit codes: `2` usage (including no ceiling), `3` refused by the mandate or the SDK
|
|
646
|
+
(nothing signed), `4` the settlement failed after signing (the error says whether the
|
|
647
|
+
authorization was used and how to cancel it; see [x402.md](./x402.md)).
|
|
648
|
+
|
|
649
|
+
### `metrik refund`
|
|
650
|
+
|
|
651
|
+
```bash
|
|
652
|
+
metrik refund <streamId> --refund-url <url> [--close] [--reclaim] [--attempts 5] [--max-wait 60]
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
Drives the seller's **gasless refund relay** through the SDK's `refundClient`, bound to
|
|
656
|
+
the stream and to the opener read **from chain** (`factory.isOpener`), never from the
|
|
657
|
+
relay. With no action flag it prints the status and the next step. `--close` signs the
|
|
658
|
+
opener's EIP-712 `Close` as the payer (the relay pays the gas; authorized on the mandate
|
|
659
|
+
owner's signature only, like `metrik close`). `--reclaim` sends the permissionless
|
|
660
|
+
`opener.reclaim` (no wallet needed; the refund always goes to `payerOf(streamId)`) and
|
|
661
|
+
retries a bounded number of times while the settlement window is open, honouring
|
|
662
|
+
`Retry-After`; a longer wait exits `3` with the time to retry. Every relay "success" is
|
|
663
|
+
checked against the transaction receipt on the configured chain. `--refund-url` accepts
|
|
664
|
+
the full URL `metrik pay` printed, a `{streamId}` template or the relay's origin; it can
|
|
665
|
+
also come from `METRIK_AGENT_REFUND_URL`.
|
|
666
|
+
|
|
667
|
+
Nothing is refunded automatically, and the relay is a convenience: a payer can always
|
|
668
|
+
recover on-chain without it (`metrik close` as the payer, with gas; `metrik reclaim` by
|
|
669
|
+
anyone).
|
|
670
|
+
|
|
671
|
+
`status`, `close` and `reclaim` understand opener-bought streams: they show the opener and the
|
|
672
|
+
payer, `close` routes through the opener (payer only), and `reclaim` sends the
|
|
673
|
+
permissionless opener reclaim and reports the refund to the payer.
|
|
674
|
+
|
|
417
675
|
### `metrik close` and `metrik reclaim`
|
|
418
676
|
|
|
419
677
|
```bash
|
|
@@ -427,12 +685,32 @@ returns the unspent budget, and the buyer sends it. `close` now points at
|
|
|
427
685
|
`--close-first` for next time, rather than leaving the one-shot form visible only in
|
|
428
686
|
`metrik reclaim --help`.
|
|
429
687
|
|
|
688
|
+
**`reclaim` names the condition before it spends anything.** Three different on-chain
|
|
689
|
+
states stop a reclaim, and they have three completely different answers: the stream was
|
|
690
|
+
already reclaimed (you have the money), the stream is still running (close it first), or
|
|
691
|
+
its stop time is not checkpointed yet (wait ~20 seconds). The CLI reads `getStream`,
|
|
692
|
+
`latestCheckpointCheckedAt` and the chain clock up front and says which one it is, rather
|
|
693
|
+
than sending a simulation and repeating whatever the endpoint's revert data decoded to —
|
|
694
|
+
on the public Base Sepolia RPC all three came back as `Execution reverted for an unknown
|
|
695
|
+
reason`. The pre-flight **fails open**: a read that does not answer never blocks the
|
|
696
|
+
reclaim, because refusing to return a buyer's deposit over a dropped view call is worse
|
|
697
|
+
than a wasted simulation.
|
|
698
|
+
|
|
430
699
|
**`reclaim` waits, by design.** `reclaimWithProof` reverts with `SettlementWindowOpen`
|
|
431
700
|
until a checkpoint whose `checkedAt` is at or after the stream's stop time has posted.
|
|
432
701
|
That is the normal ordering of a checkpoint rail, not a fault — in practice the first
|
|
433
|
-
attempt fails and one roughly 30 seconds later succeeds. The CLI retries
|
|
434
|
-
|
|
435
|
-
|
|
702
|
+
attempt fails and one roughly 30 seconds later succeeds. The CLI retries on a bounded
|
|
703
|
+
schedule and narrates the wait on stderr; every other failure is surfaced immediately and
|
|
704
|
+
unretried.
|
|
705
|
+
|
|
706
|
+
The wait shows up in three shapes, and all three retry: the escrow's decoded
|
|
707
|
+
`SettlementWindowOpen`; the **oracle** refusing a proof for a stream it has not
|
|
708
|
+
checkpointed yet (the SDK fetches the proof before it simulates, so the escrow's revert
|
|
709
|
+
never happens and the error is `StreamNotInCheckpointError` / `CheckpointNotReadyError`);
|
|
710
|
+
and a reclaim revert the ABI could not decode, where the chain's state is read to decide.
|
|
711
|
+
Only recognising the first of those is what made `--close-first` die on its first attempt
|
|
712
|
+
against a stream closed before its first covering checkpoint — the ordinary result of a
|
|
713
|
+
short trial run.
|
|
436
714
|
|
|
437
715
|
If it is still blocked when the budget runs out, the message does **not** just say "retry
|
|
438
716
|
later" — every attempt this command makes needs a proof from the oracle, so when the
|
|
@@ -448,8 +726,10 @@ lands on another that has not imported the block.) If the stream is **already**
|
|
|
448
726
|
the close is skipped and the command goes straight to reclaim — so re-running it is always
|
|
449
727
|
safe and never dead-ends on `StreamClosedAlready()`.
|
|
450
728
|
|
|
451
|
-
`
|
|
452
|
-
|
|
729
|
+
`--close-first` is also the one caller allowed past the still-running refusal, since
|
|
730
|
+
clearing that state is the whole point of the flag. Once the close has landed it reports
|
|
731
|
+
what the following retries are waiting for — the stop time, and how far the oracle has
|
|
732
|
+
published — so the wait reads as the advertised wait rather than as a stalled command.
|
|
453
733
|
|
|
454
734
|
Close and reclaim are buyer-recovery actions: `VerifiedStreamAgentClient` authorizes them
|
|
455
735
|
on the mandate owner's signature alone, never on caps or expiry, so a lapsed mandate can
|
|
@@ -546,17 +826,26 @@ that wait legible.
|
|
|
546
826
|
|
|
547
827
|
## Settlement configuration
|
|
548
828
|
|
|
549
|
-
Everything defaults to
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
|
554
|
-
|
|
|
555
|
-
| `--
|
|
556
|
-
| `--
|
|
557
|
-
| `--
|
|
558
|
-
| `--
|
|
559
|
-
| `--
|
|
829
|
+
Everything defaults to the selected network's entry in the `@absol-labs/sdk` network
|
|
830
|
+
registry (the default network is Base Sepolia), and every value is overridable per
|
|
831
|
+
command or through the environment. Nothing chain-specific is hardcoded in the CLI.
|
|
832
|
+
|
|
833
|
+
| Flag | Env | Default |
|
|
834
|
+
| --------------------- | -------------------------------- | ---------------------------------------------------------------------- |
|
|
835
|
+
| `--network` | `METRIK_NETWORK` | the registry default (id, chain id or CAIP-2) |
|
|
836
|
+
| `--chain-id` | `METRIK_AGENT_CHAIN_ID` | the network's chain id (must agree if both set) |
|
|
837
|
+
| `--rpc-url` | `METRIK_AGENT_RPC_URL` | the network's first registered RPC |
|
|
838
|
+
| `--escrow` | `METRIK_AGENT_ESCROW` | the network's current escrow (V3); a `legacy` one (V2) for its streams |
|
|
839
|
+
| `--escrow-generation` | `METRIK_AGENT_ESCROW_GENERATION` | the registry's; REQUIRED only for an unregistered escrow |
|
|
840
|
+
| `--usdc` | `METRIK_AGENT_USDC` | the network's registered USDC |
|
|
841
|
+
| `--oracle-url` | `METRIK_AGENT_ORACLE_URL` | the network's oracle |
|
|
842
|
+
| `--registry-url` | `METRIK_AGENT_REGISTRY_URL` | the network's public listings endpoint |
|
|
843
|
+
|
|
844
|
+
The gas preflight names the network's gas token and faucet (from its gas-token
|
|
845
|
+
metadata) instead of assuming ETH; on a network whose gas IS the settlement USDC it
|
|
846
|
+
checks the one USDC balance and requires the deposit to leave room for gas. An
|
|
847
|
+
`--escrow` the registry does not record has no log-scan anchor, so `metrik streams`
|
|
848
|
+
needs `--from-block` for it.
|
|
560
849
|
|
|
561
850
|
## Embedding it
|
|
562
851
|
|
package/docs/langchain.md
CHANGED
|
@@ -12,6 +12,11 @@ Create them with [`createLangChainVerifiedStreamTools()`](../src/frameworks/lang
|
|
|
12
12
|
## Safety model
|
|
13
13
|
|
|
14
14
|
- `hire_verified_service` checks the signed mandate before any stream open.
|
|
15
|
+
- It then refuses a `ratePerSecondUsdc` outside the listing's operator-signed rate
|
|
16
|
+
band (the seller's gateway would refuse every request on that stream), and fails
|
|
17
|
+
closed when the registry cannot be read. An unlisted `serviceRef` has no signed
|
|
18
|
+
band and is not constrained. The same check runs in the ElizaOS and AgentKit
|
|
19
|
+
adapters.
|
|
15
20
|
- `reclaim_unspent` passes the same signed-mandate context into the agent client,
|
|
16
21
|
which re-checks authorization before the SDK can write.
|
|
17
22
|
- `check_stream_status` is read-only and also returns `shouldStop` for a closed
|
package/docs/mcp-hosted.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Hosted MCP over Streamable HTTP
|
|
2
2
|
|
|
3
3
|
The agent lane ships two MCP transports over the **same** tool set
|
|
4
|
-
(`
|
|
5
|
-
and the optional
|
|
4
|
+
(`discover_services`, `hire_verified_service`, `invoke_service`,
|
|
5
|
+
`check_stream_status`, `reclaim_unspent`, `list_streams`, and the optional
|
|
6
|
+
`prove_https_response` — see [`mcp-reference.md`](./mcp-reference.md)):
|
|
6
7
|
|
|
7
8
|
- **stdio** (`src/mcp/stdio.ts`) — local dev, one process per caller. Started with
|
|
8
9
|
the published `metrik-mcp` executable (`npx --package @absol-labs/agent metrik-mcp`),
|
|
@@ -79,7 +80,7 @@ network but need distinct wallets override only the wallet vars in their `env`.
|
|
|
79
80
|
|
|
80
81
|
```bash
|
|
81
82
|
export METRIK_AGENT_RPC_URL="https://base-sepolia.example/rpc"
|
|
82
|
-
export METRIK_AGENT_ESCROW="
|
|
83
|
+
export METRIK_AGENT_ESCROW="0x0f09f36Ccc05A7c9882F438721C08De314dFd46C" # StreamEscrowV2 — NOT the retired V1 escrow
|
|
83
84
|
export METRIK_AGENT_USDC="0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
84
85
|
# ... wallet vars (private key or CDP) ...
|
|
85
86
|
export METRIK_MCP_TENANTS='[{"id":"acme","token":"REPLACE_WITH_SECRET"}]'
|