@absol-labs/agent 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/README.md +107 -23
  2. package/dist/capability/invocation-capability.d.ts +18 -6
  3. package/dist/capability/invocation-capability.d.ts.map +1 -1
  4. package/dist/capability/invocation-capability.js.map +1 -1
  5. package/dist/cli/commands/claim.d.ts.map +1 -1
  6. package/dist/cli/commands/claim.js +20 -4
  7. package/dist/cli/commands/claim.js.map +1 -1
  8. package/dist/cli/commands/close.d.ts.map +1 -1
  9. package/dist/cli/commands/close.js +16 -4
  10. package/dist/cli/commands/close.js.map +1 -1
  11. package/dist/cli/commands/invoke.d.ts.map +1 -1
  12. package/dist/cli/commands/invoke.js +1 -0
  13. package/dist/cli/commands/invoke.js.map +1 -1
  14. package/dist/cli/commands/open.d.ts.map +1 -1
  15. package/dist/cli/commands/open.js +63 -11
  16. package/dist/cli/commands/open.js.map +1 -1
  17. package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -1
  18. package/dist/cli/commands/reclaim-unverified.js +12 -4
  19. package/dist/cli/commands/reclaim-unverified.js.map +1 -1
  20. package/dist/cli/commands/reclaim.d.ts.map +1 -1
  21. package/dist/cli/commands/reclaim.js +16 -5
  22. package/dist/cli/commands/reclaim.js.map +1 -1
  23. package/dist/cli/commands/streams.js +1 -1
  24. package/dist/cli/commands/streams.js.map +1 -1
  25. package/dist/cli/deps.d.ts +53 -7
  26. package/dist/cli/deps.d.ts.map +1 -1
  27. package/dist/cli/deps.js +65 -15
  28. package/dist/cli/deps.js.map +1 -1
  29. package/dist/cli/privy.d.ts +83 -0
  30. package/dist/cli/privy.d.ts.map +1 -0
  31. package/dist/cli/privy.js +230 -0
  32. package/dist/cli/privy.js.map +1 -0
  33. package/dist/cli/spend-policy.d.ts +60 -0
  34. package/dist/cli/spend-policy.d.ts.map +1 -0
  35. package/dist/cli/spend-policy.js +65 -0
  36. package/dist/cli/spend-policy.js.map +1 -0
  37. package/dist/cli/wallet.d.ts +108 -39
  38. package/dist/cli/wallet.d.ts.map +1 -1
  39. package/dist/cli/wallet.js +108 -43
  40. package/dist/cli/wallet.js.map +1 -1
  41. package/dist/gateway/caller-auth-gateway.d.ts +38 -3
  42. package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
  43. package/dist/gateway/caller-auth-gateway.js +25 -1
  44. package/dist/gateway/caller-auth-gateway.js.map +1 -1
  45. package/dist/gateway/http-server.d.ts +53 -0
  46. package/dist/gateway/http-server.d.ts.map +1 -1
  47. package/dist/gateway/http-server.js +189 -4
  48. package/dist/gateway/http-server.js.map +1 -1
  49. package/dist/gateway/x402-mode.d.ts +123 -0
  50. package/dist/gateway/x402-mode.d.ts.map +1 -0
  51. package/dist/gateway/x402-mode.js +212 -0
  52. package/dist/gateway/x402-mode.js.map +1 -0
  53. package/dist/index.d.ts +6 -4
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +8 -3
  56. package/dist/index.js.map +1 -1
  57. package/dist/mandates/env.d.ts +3 -2
  58. package/dist/mandates/env.d.ts.map +1 -1
  59. package/dist/mandates/env.js +3 -2
  60. package/dist/mandates/env.js.map +1 -1
  61. package/dist/mcp/server.d.ts +49 -0
  62. package/dist/mcp/server.d.ts.map +1 -1
  63. package/dist/mcp/server.js +513 -24
  64. package/dist/mcp/server.js.map +1 -1
  65. package/dist/mcp/service-invoker.d.ts +97 -0
  66. package/dist/mcp/service-invoker.d.ts.map +1 -0
  67. package/dist/mcp/service-invoker.js +167 -0
  68. package/dist/mcp/service-invoker.js.map +1 -0
  69. package/dist/sdk/invoke.d.ts +19 -4
  70. package/dist/sdk/invoke.d.ts.map +1 -1
  71. package/dist/sdk/invoke.js +69 -5
  72. package/dist/sdk/invoke.js.map +1 -1
  73. package/dist/x402/delivery-oracle.d.ts +108 -0
  74. package/dist/x402/delivery-oracle.d.ts.map +1 -0
  75. package/dist/x402/delivery-oracle.js +174 -0
  76. package/dist/x402/delivery-oracle.js.map +1 -0
  77. package/dist/x402/facilitator-server-entry.d.ts +3 -0
  78. package/dist/x402/facilitator-server-entry.d.ts.map +1 -0
  79. package/dist/x402/facilitator-server-entry.js +27 -0
  80. package/dist/x402/facilitator-server-entry.js.map +1 -0
  81. package/dist/x402/facilitator-server.d.ts +73 -0
  82. package/dist/x402/facilitator-server.d.ts.map +1 -0
  83. package/dist/x402/facilitator-server.js +305 -0
  84. package/dist/x402/facilitator-server.js.map +1 -0
  85. package/dist/x402/facilitator.d.ts +69 -17
  86. package/dist/x402/facilitator.d.ts.map +1 -1
  87. package/dist/x402/facilitator.js +76 -33
  88. package/dist/x402/facilitator.js.map +1 -1
  89. package/dist/x402/payment-requirements.d.ts +106 -0
  90. package/dist/x402/payment-requirements.d.ts.map +1 -0
  91. package/dist/x402/payment-requirements.js +138 -0
  92. package/dist/x402/payment-requirements.js.map +1 -0
  93. package/dist/x402/relayer.d.ts +41 -0
  94. package/dist/x402/relayer.d.ts.map +1 -0
  95. package/dist/x402/relayer.js +64 -0
  96. package/dist/x402/relayer.js.map +1 -0
  97. package/dist/x402/resource-index.d.ts +75 -0
  98. package/dist/x402/resource-index.d.ts.map +1 -0
  99. package/dist/x402/resource-index.js +126 -0
  100. package/dist/x402/resource-index.js.map +1 -0
  101. package/dist/x402/verified-delivery-facilitator.d.ts +285 -0
  102. package/dist/x402/verified-delivery-facilitator.d.ts.map +1 -0
  103. package/dist/x402/verified-delivery-facilitator.js +423 -0
  104. package/dist/x402/verified-delivery-facilitator.js.map +1 -0
  105. package/dist/zktls/t2-delivery-proof.d.ts +6 -6
  106. package/docs/agent-layer.md +12 -8
  107. package/docs/cli.md +158 -22
  108. package/docs/mcp-hosted.md +4 -3
  109. package/docs/mcp-reference.md +175 -0
  110. package/docs/quickstart.md +18 -4
  111. package/docs/threat-model.md +4 -3
  112. package/docs/x402.md +648 -0
  113. package/package.json +18 -7
  114. package/src/capability/invocation-capability.ts +17 -1
  115. package/src/cli/commands/claim.ts +30 -4
  116. package/src/cli/commands/close.ts +20 -4
  117. package/src/cli/commands/invoke.ts +1 -0
  118. package/src/cli/commands/open.ts +76 -10
  119. package/src/cli/commands/reclaim-unverified.ts +16 -4
  120. package/src/cli/commands/reclaim.ts +22 -5
  121. package/src/cli/commands/streams.ts +1 -1
  122. package/src/cli/deps.ts +115 -24
  123. package/src/cli/privy.ts +396 -0
  124. package/src/cli/spend-policy.ts +139 -0
  125. package/src/cli/wallet.ts +188 -57
  126. package/src/gateway/caller-auth-gateway.ts +77 -6
  127. package/src/gateway/http-server.ts +280 -6
  128. package/src/gateway/x402-mode.ts +350 -0
  129. package/src/index.ts +40 -5
  130. package/src/mandates/env.ts +3 -2
  131. package/src/mcp/server.ts +681 -29
  132. package/src/mcp/service-invoker.ts +285 -0
  133. package/src/sdk/invoke.ts +90 -12
  134. package/src/x402/delivery-oracle.ts +285 -0
  135. package/src/x402/facilitator-server-entry.ts +35 -0
  136. package/src/x402/facilitator-server.ts +445 -0
  137. package/src/x402/facilitator.ts +125 -46
  138. package/src/x402/payment-requirements.ts +231 -0
  139. package/src/x402/relayer.ts +122 -0
  140. package/src/x402/resource-index.ts +228 -0
  141. package/src/x402/verified-delivery-facilitator.ts +744 -0
@@ -0,0 +1,83 @@
1
+ import { type Account, type Transport } from "viem";
2
+ import { type AutonomousWalletCredentialStore } from "../wallet/autonomous-wallet.js";
3
+ /**
4
+ * The CLI's two Privy wallet shapes.
5
+ *
6
+ * Privy differs from the private-key and CDP paths in ONE structural way: the
7
+ * account it yields has no local `signTransaction`. It signs and broadcasts by
8
+ * sending `eth_sendTransaction` / `eth_signTypedData_v4` to a provider, so the
9
+ * viem wallet client's TRANSPORT must be that provider rather than a plain HTTP
10
+ * RPC. That is the whole difference, and it is what `transport` below carries.
11
+ *
12
+ * Neither shape puts a wallet key on this machine. The signing key lives at
13
+ * Privy; the broker holds the Privy authorization key. What the CLI holds is
14
+ * either a short-lived session token (`session`) or a P-256 authorization key
15
+ * in the host credential store (`autonomous`) — a key that authorizes a
16
+ * policy-bounded request, not a key that can move funds by itself.
17
+ */
18
+ export type PrivyCliWalletSource = "privy-autonomous" | "privy-session";
19
+ /** The store key naming the agent-owned wallet in the host credential store. */
20
+ export declare const PRIVY_WALLET_KEY_ENV = "METRIK_AGENT_PRIVY_WALLET_KEY";
21
+ /** Broker base URL. Optional for `autonomous`, REQUIRED for `session`. */
22
+ export declare const PRIVY_BROKER_URL_ENV = "METRIK_AGENT_PRIVY_BROKER_URL";
23
+ /** A scoped session token minted by the broker's `POST /v1/sessions`. */
24
+ export declare const PRIVY_SESSION_TOKEN_ENV = "METRIK_AGENT_PRIVY_SESSION_TOKEN";
25
+ /** The embedded wallet address the session is bound to. */
26
+ export declare const PRIVY_ADDRESS_ENV = "METRIK_AGENT_PRIVY_ADDRESS";
27
+ /** The PUBLIC Privy app id. Not a secret — the broker serves it at `/v1/config`. */
28
+ export declare const PRIVY_APP_ID_ENV = "METRIK_AGENT_PRIVY_APP_ID";
29
+ /** Every variable either Privy shape reads. Named in errors, never printed. */
30
+ export declare const PRIVY_ENV_VARS: readonly ["METRIK_AGENT_PRIVY_WALLET_KEY", "METRIK_AGENT_PRIVY_BROKER_URL", "METRIK_AGENT_PRIVY_SESSION_TOKEN", "METRIK_AGENT_PRIVY_ADDRESS", "METRIK_AGENT_PRIVY_APP_ID"];
31
+ /** The variables the user-owned session shape needs, all of them. */
32
+ export declare const PRIVY_SESSION_ENV_VARS: readonly ["METRIK_AGENT_PRIVY_BROKER_URL", "METRIK_AGENT_PRIVY_SESSION_TOKEN", "METRIK_AGENT_PRIVY_ADDRESS", "METRIK_AGENT_PRIVY_APP_ID"];
33
+ /**
34
+ * The spend ceiling a broker enforces server-side, read from `GET /v1/config`.
35
+ *
36
+ * These are the SAME numbers the broker checks `openStream` against
37
+ * (`deposit <= maxTotalUsdc`, `ratePerSecond <= maxRatePerSecondUsdc`,
38
+ * `duration <= maxDurationSeconds`), which is why the CLI can use them to
39
+ * refuse an over-ceiling hire locally instead of paying gas to learn a knowable
40
+ * fact. It reads them rather than hardcoding them: the ceiling belongs to the
41
+ * broker, and a copy in this file would be a second source of truth that goes
42
+ * stale silently.
43
+ */
44
+ export interface PrivySpendPolicy {
45
+ readonly brokerUrl: string;
46
+ readonly chainId: number;
47
+ readonly maxTotalUsdc: bigint;
48
+ readonly maxRatePerSecondUsdc: bigint;
49
+ readonly maxDurationSeconds: number;
50
+ }
51
+ /** Reads a broker's public policy. No credential is sent; nothing secret is served. */
52
+ export declare function fetchPrivySpendPolicy(brokerUrl: string, fetchImpl?: typeof fetch): Promise<PrivySpendPolicy>;
53
+ export interface ResolvedPrivyCliWallet {
54
+ readonly source: PrivyCliWalletSource;
55
+ /** A JSON-RPC account: `signTypedData` works, `signTransaction` does not exist. */
56
+ readonly account: Account;
57
+ /** The provider-as-transport. Without this every write goes to a plain RPC and fails. */
58
+ readonly transport: Transport;
59
+ /** One line naming the wallet's origin. Safe to print: no credential in it. */
60
+ readonly description: string;
61
+ /** Reads the broker ceiling this wallet is capped at. Bound to its broker URL. */
62
+ readonly readSpendPolicy: () => Promise<PrivySpendPolicy>;
63
+ }
64
+ export interface ResolvePrivyCliWalletOptions {
65
+ /** `--rpc-url`, so a Privy wallet's READS use the same endpoint as everything else. */
66
+ readonly rpcUrl?: string;
67
+ readonly note?: (line: string) => void;
68
+ /** Test seam. Defaults to the real credential store selected from `env`. */
69
+ readonly store?: AutonomousWalletCredentialStore;
70
+ /** Test seam for the broker HTTP contract. */
71
+ readonly fetchImpl?: typeof fetch;
72
+ }
73
+ /**
74
+ * Resolves a Privy wallet from the environment, or `null` when no Privy
75
+ * variable is set at all.
76
+ *
77
+ * A PARTIALLY configured Privy setup is an error, not a `null` — "you set the
78
+ * session token but not the address" and "you configured no Privy wallet" are
79
+ * different facts, and rendering the first as the second sends the reader
80
+ * looking in the wrong place. This mirrors the CDP path exactly.
81
+ */
82
+ export declare function resolvePrivyCliWallet(env: NodeJS.ProcessEnv, options?: ResolvePrivyCliWalletOptions): Promise<ResolvedPrivyCliWallet | null>;
83
+ //# sourceMappingURL=privy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privy.d.ts","sourceRoot":"","sources":["../../src/cli/privy.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,SAAS,EACf,MAAM,MAAM,CAAC;AAEd,OAAO,EAQL,KAAK,+BAA+B,EAErC,MAAM,gCAAgC,CAAC;AAQxC;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAExE,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,kCAAkC,CAAC;AACpE,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB,kCAAkC,CAAC;AACpE,yEAAyE;AACzE,eAAO,MAAM,uBAAuB,qCAAqC,CAAC;AAC1E,2DAA2D;AAC3D,eAAO,MAAM,iBAAiB,+BAA+B,CAAC;AAC9D,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAE5D,+EAA+E;AAC/E,eAAO,MAAM,cAAc,4KAMjB,CAAC;AAEX,qEAAqE;AACrE,eAAO,MAAM,sBAAsB,2IAKzB,CAAC;AAEX;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED,uFAAuF;AACvF,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAyC3B;AAUD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,eAAe,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,4BAA4B;IAC3C,uFAAuF;IACvF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,+BAA+B,CAAC;IACjD,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CA8CxC"}
@@ -0,0 +1,230 @@
1
+ import { custom, isAddress, getAddress, } from "viem";
2
+ import { AutonomousWalletError, EncryptedFileCredentialStore, HttpAutonomousWalletBroker, METRIK_AUTONOMOUS_WALLET_BROKER_URL, METRIK_WALLET_ENCRYPTION_KEY_ENV, createAutonomousWalletProvider, createDefaultAutonomousWalletStore, } from "../wallet/autonomous-wallet.js";
3
+ import { createPrivySessionProvider } from "../wallet/privy-session-provider.js";
4
+ import { createPrivyEmbeddedAccount, } from "../wallet/provider.js";
5
+ import { configError } from "./errors.js";
6
+ /** The store key naming the agent-owned wallet in the host credential store. */
7
+ export const PRIVY_WALLET_KEY_ENV = "METRIK_AGENT_PRIVY_WALLET_KEY";
8
+ /** Broker base URL. Optional for `autonomous`, REQUIRED for `session`. */
9
+ export const PRIVY_BROKER_URL_ENV = "METRIK_AGENT_PRIVY_BROKER_URL";
10
+ /** A scoped session token minted by the broker's `POST /v1/sessions`. */
11
+ export const PRIVY_SESSION_TOKEN_ENV = "METRIK_AGENT_PRIVY_SESSION_TOKEN";
12
+ /** The embedded wallet address the session is bound to. */
13
+ export const PRIVY_ADDRESS_ENV = "METRIK_AGENT_PRIVY_ADDRESS";
14
+ /** The PUBLIC Privy app id. Not a secret — the broker serves it at `/v1/config`. */
15
+ export const PRIVY_APP_ID_ENV = "METRIK_AGENT_PRIVY_APP_ID";
16
+ /** Every variable either Privy shape reads. Named in errors, never printed. */
17
+ export const PRIVY_ENV_VARS = [
18
+ PRIVY_WALLET_KEY_ENV,
19
+ PRIVY_BROKER_URL_ENV,
20
+ PRIVY_SESSION_TOKEN_ENV,
21
+ PRIVY_ADDRESS_ENV,
22
+ PRIVY_APP_ID_ENV,
23
+ ];
24
+ /** The variables the user-owned session shape needs, all of them. */
25
+ export const PRIVY_SESSION_ENV_VARS = [
26
+ PRIVY_BROKER_URL_ENV,
27
+ PRIVY_SESSION_TOKEN_ENV,
28
+ PRIVY_ADDRESS_ENV,
29
+ PRIVY_APP_ID_ENV,
30
+ ];
31
+ /** Reads a broker's public policy. No credential is sent; nothing secret is served. */
32
+ export async function fetchPrivySpendPolicy(brokerUrl, fetchImpl = fetch) {
33
+ const base = brokerUrl.replace(/\/$/, "");
34
+ const response = await fetchImpl(`${base}/v1/config`, {
35
+ headers: { accept: "application/json" },
36
+ }).catch((error) => {
37
+ throw configError(`the Privy broker at ${base} did not answer its public policy`, `${describe(error)} The CLI reads GET /v1/config to know the ceiling your wallet is capped at; without it, it cannot tell you before broadcasting whether a hire fits.`);
38
+ });
39
+ const body = (await response.json().catch(() => null));
40
+ if (!response.ok || body === null) {
41
+ throw configError(`the Privy broker at ${base} rejected the public policy read (${response.status})`);
42
+ }
43
+ const chainId = Number(body.chainId);
44
+ const maxTotalUsdc = asBigint(body.maxTotalUsdcAtomic);
45
+ const maxRatePerSecondUsdc = asBigint(body.maxRatePerSecondAtomic);
46
+ const maxDurationSeconds = Number(body.maxDurationSeconds);
47
+ if (!Number.isSafeInteger(chainId) ||
48
+ maxTotalUsdc === null ||
49
+ maxRatePerSecondUsdc === null ||
50
+ !Number.isSafeInteger(maxDurationSeconds)) {
51
+ throw configError(`the Privy broker at ${base} returned a policy this CLI cannot read`, "expected chainId, maxTotalUsdcAtomic, maxRatePerSecondAtomic and maxDurationSeconds.");
52
+ }
53
+ return {
54
+ brokerUrl: base,
55
+ chainId,
56
+ maxTotalUsdc,
57
+ maxRatePerSecondUsdc,
58
+ maxDurationSeconds,
59
+ };
60
+ }
61
+ function asBigint(value) {
62
+ if (typeof value === "bigint")
63
+ return value;
64
+ if (typeof value === "number" && Number.isSafeInteger(value))
65
+ return BigInt(value);
66
+ if (typeof value === "string" && /^[0-9]+$/.test(value))
67
+ return BigInt(value);
68
+ return null;
69
+ }
70
+ /**
71
+ * Resolves a Privy wallet from the environment, or `null` when no Privy
72
+ * variable is set at all.
73
+ *
74
+ * A PARTIALLY configured Privy setup is an error, not a `null` — "you set the
75
+ * session token but not the address" and "you configured no Privy wallet" are
76
+ * different facts, and rendering the first as the second sends the reader
77
+ * looking in the wrong place. This mirrors the CDP path exactly.
78
+ */
79
+ export async function resolvePrivyCliWallet(env, options = {}) {
80
+ const walletKey = read(env, PRIVY_WALLET_KEY_ENV);
81
+ const brokerUrl = read(env, PRIVY_BROKER_URL_ENV);
82
+ const sessionToken = read(env, PRIVY_SESSION_TOKEN_ENV);
83
+ const address = read(env, PRIVY_ADDRESS_ENV);
84
+ const appId = read(env, PRIVY_APP_ID_ENV);
85
+ if (walletKey === null &&
86
+ brokerUrl === null &&
87
+ sessionToken === null &&
88
+ address === null &&
89
+ appId === null) {
90
+ return null;
91
+ }
92
+ if (walletKey !== null) {
93
+ if (sessionToken !== null) {
94
+ options.note?.(`warning: both ${PRIVY_WALLET_KEY_ENV} and ${PRIVY_SESSION_TOKEN_ENV} are set; using the agent-owned wallet named by ${PRIVY_WALLET_KEY_ENV}. Unset it to sign with the session token.`);
95
+ }
96
+ return await resolveAutonomous(walletKey, brokerUrl, env, options);
97
+ }
98
+ const missing = PRIVY_SESSION_ENV_VARS.filter((name) => read(env, name) === null);
99
+ if (missing.length > 0) {
100
+ throw configError(`the Privy wallet is partially configured: ${missing.join(", ")} ${missing.length === 1 ? "is" : "are"} not set`, `a Privy wallet is configured one of two ways: set ${PRIVY_WALLET_KEY_ENV} to the store key of an agent-owned wallet you provisioned with provisionMetrikAutonomousWallet(), or set all of ${PRIVY_SESSION_ENV_VARS.join(", ")} for a broker session. Set the missing one${missing.length === 1 ? "" : "s"}, or unset the others to use a different wallet.`);
101
+ }
102
+ return resolveSession({
103
+ brokerUrl: brokerUrl,
104
+ sessionToken: sessionToken,
105
+ address: address,
106
+ appId: appId,
107
+ ...(options.rpcUrl === undefined ? {} : { rpcUrl: options.rpcUrl }),
108
+ ...(options.fetchImpl === undefined
109
+ ? {}
110
+ : { fetchImpl: options.fetchImpl }),
111
+ });
112
+ }
113
+ async function resolveAutonomous(walletKey, brokerUrlOverride, env, options) {
114
+ const store = options.store ?? selectCredentialStore(env);
115
+ let record;
116
+ try {
117
+ record = await store.load(walletKey);
118
+ }
119
+ catch (error) {
120
+ throw configError(`could not read the agent-owned Privy wallet "${walletKey}" from the credential store`, `${describe(error)} On a headless host the OS credential store is often unavailable; set ${METRIK_WALLET_ENCRYPTION_KEY_ENV} to use the encrypted-file store instead.`);
121
+ }
122
+ if (record === null) {
123
+ throw configError(`no agent-owned Privy wallet is stored under the key "${walletKey}"`, `the CLI never provisions a wallet on your behalf — a fund-moving command is the wrong place to mint one. Provision it once with provisionMetrikAutonomousWallet({ storeKey: "${walletKey}" }) (see docs/autonomous-privy-wallet.md), then re-run this command.`);
124
+ }
125
+ if (record.walletId === undefined || record.address === undefined) {
126
+ throw configError(`the agent-owned Privy wallet "${walletKey}" was never finished provisioning`, "the local key exists but the broker never returned a wallet id and address. Re-run provisionMetrikAutonomousWallet() with the same store key — it retries with the same key and idempotency nonce.");
127
+ }
128
+ const brokerUrl = brokerUrlOverride ?? record.brokerUrl;
129
+ if (brokerUrlOverride !== null && brokerUrlOverride !== record.brokerUrl) {
130
+ options.note?.(`note: ${PRIVY_BROKER_URL_ENV} (${brokerUrlOverride}) overrides the broker this wallet was provisioned against (${record.brokerUrl}); only a broker holding this wallet's Privy authorization key can authorize it.`);
131
+ }
132
+ let broker;
133
+ try {
134
+ broker = new HttpAutonomousWalletBroker(brokerUrl, {
135
+ ...(options.fetchImpl === undefined
136
+ ? {}
137
+ : { fetchImpl: options.fetchImpl }),
138
+ });
139
+ }
140
+ catch (error) {
141
+ throw configError(`the autonomous wallet broker URL is not usable: ${describe(error)}`, `set ${PRIVY_BROKER_URL_ENV} to an HTTPS broker you control (the default is ${METRIK_AUTONOMOUS_WALLET_BROKER_URL}).`);
142
+ }
143
+ const provider = createAutonomousWalletProvider({
144
+ wallet: record,
145
+ broker,
146
+ ...(options.rpcUrl === undefined ? {} : { rpcUrl: options.rpcUrl }),
147
+ ...(options.fetchImpl === undefined
148
+ ? {}
149
+ : { fetchImpl: options.fetchImpl }),
150
+ });
151
+ const account = await embeddedAccount(provider, record.appId, record.address);
152
+ return {
153
+ source: "privy-autonomous",
154
+ account,
155
+ transport: custom(provider),
156
+ description: `${record.address} (agent-owned Privy wallet "${walletKey}" via ${brokerUrl})`,
157
+ readSpendPolicy: async () => await fetchPrivySpendPolicy(brokerUrl, options.fetchImpl ?? globalThis.fetch.bind(globalThis)),
158
+ };
159
+ }
160
+ function resolveSession(input) {
161
+ if (!isAddress(input.address)) {
162
+ throw configError(`${PRIVY_ADDRESS_ENV} must be a 0x-prefixed 20-byte address`);
163
+ }
164
+ const address = getAddress(input.address);
165
+ let provider;
166
+ try {
167
+ provider = createPrivySessionProvider({
168
+ brokerUrl: input.brokerUrl,
169
+ sessionToken: input.sessionToken,
170
+ address,
171
+ ...(input.rpcUrl === undefined ? {} : { rpcUrl: input.rpcUrl }),
172
+ ...(input.fetchImpl === undefined ? {} : { fetchImpl: input.fetchImpl }),
173
+ });
174
+ }
175
+ catch (error) {
176
+ throw configError(`the Privy session broker URL is not usable: ${describe(error)}`, `set ${PRIVY_BROKER_URL_ENV} to the HTTPS broker that minted ${PRIVY_SESSION_TOKEN_ENV}. A session token is only valid against the broker that issued it.`);
177
+ }
178
+ return embeddedAccount(provider, input.appId, address).then((account) => ({
179
+ source: "privy-session",
180
+ account,
181
+ transport: custom(provider),
182
+ description: `${address} (Privy broker session via ${input.brokerUrl})`,
183
+ readSpendPolicy: async () => await fetchPrivySpendPolicy(input.brokerUrl, input.fetchImpl ?? globalThis.fetch.bind(globalThis)),
184
+ }));
185
+ }
186
+ /**
187
+ * Wraps a provider in the package's existing Privy EOA adapter.
188
+ *
189
+ * Both CLI providers answer `eth_chainId` and `eth_accounts` locally, so the
190
+ * adapter's session assertion is a pure local consistency check here — no
191
+ * network call happens while the wallet is being resolved.
192
+ */
193
+ async function embeddedAccount(provider, appId, address) {
194
+ try {
195
+ return await createPrivyEmbeddedAccount({
196
+ appId,
197
+ address,
198
+ provider,
199
+ chainId: 84532,
200
+ });
201
+ }
202
+ catch (error) {
203
+ throw configError(`the Privy wallet could not be prepared: ${describe(error)}`, `check ${PRIVY_ENV_VARS.join(", ")}. Metrik Privy wallets are Base Sepolia (84532) only.`);
204
+ }
205
+ }
206
+ /**
207
+ * The credential store the autonomous wallet was provisioned into.
208
+ *
209
+ * Selection mirrors `provisionMetrikAutonomousWallet`'s documented options:
210
+ * setting `METRIK_WALLET_ENCRYPTION_KEY` means the encrypted-file store (the
211
+ * durable option for a headless host), otherwise the host OS store. Picking a
212
+ * different store than provisioning used simply finds no record, and the
213
+ * "no wallet is stored under this key" error above says so.
214
+ */
215
+ function selectCredentialStore(env) {
216
+ if (read(env, METRIK_WALLET_ENCRYPTION_KEY_ENV) !== null) {
217
+ return new EncryptedFileCredentialStore({ env });
218
+ }
219
+ return createDefaultAutonomousWalletStore();
220
+ }
221
+ function read(env, name) {
222
+ const value = env[name];
223
+ return value === undefined || value.length === 0 ? null : value;
224
+ }
225
+ function describe(error) {
226
+ if (error instanceof AutonomousWalletError)
227
+ return error.message;
228
+ return error instanceof Error ? error.message : String(error);
229
+ }
230
+ //# sourceMappingURL=privy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privy.js","sourceRoot":"","sources":["../../src/cli/privy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import type { PrivySpendPolicy } from "./privy.js";
2
+ import type { RequestedSpend } from "./mandate.js";
3
+ import type { ServerMandateCaps } from "../mandates/env.js";
4
+ /**
5
+ * Where a hire's spend ceiling comes from, and who enforces it.
6
+ *
7
+ * The CLI has two kinds of wallet, and they differ in WHO holds the key — which
8
+ * is the whole reason the self-signed spend mandate exists at all:
9
+ *
10
+ * - **Key-holding wallet** (a raw private key, a CDP account). The person
11
+ * typing the command holds the key, so nothing outside this process bounds
12
+ * what that key can spend. `signCliMandate()` makes the agent state its own
13
+ * ceiling, and `checkMandate()` enforces it here. That is the best available
14
+ * guarantee when the client is the last line of defence.
15
+ *
16
+ * - **Policy-enforced wallet** (Privy, either shape). The key lives at Privy
17
+ * and is exercised by the broker, which caps every `openStream` against a
18
+ * policy the client CANNOT reach or raise. Re-signing a local mandate on top
19
+ * of that adds nothing: it is an agent attesting to its own limits when a
20
+ * stronger limit is already enforced somewhere the agent cannot touch. Worse,
21
+ * it cannot even be produced — the broker's typed-data policy allows an
22
+ * `InvocationCapability` and nothing else — so insisting on it would block
23
+ * the wallet whose ceiling is the stronger of the two.
24
+ *
25
+ * So for a policy-enforced wallet the CLI does not self-sign a mandate. It
26
+ * SUBSTITUTES the real ceiling rather than dropping the check: it reads the
27
+ * broker's public `/v1/config` and refuses an over-ceiling hire locally, in the
28
+ * same shape as the gas and USDC preflights — fail early with an actionable
29
+ * message instead of paying gas to learn a knowable fact.
30
+ *
31
+ * **Do not "restore" the mandate here for consistency.** Its premise is
32
+ * key-holding, and that premise is false for these wallets. Reinstating it
33
+ * would weaken the property that makes them non-custodial (the broker would
34
+ * have to be widened to sign `SpendMandate`) while making every fund-moving
35
+ * command fail against the broker as deployed.
36
+ */
37
+ export interface SpendCeiling {
38
+ readonly policy: PrivySpendPolicy;
39
+ }
40
+ /**
41
+ * Refuse a hire the broker will refuse anyway, before any gas is spent.
42
+ *
43
+ * Mirrors the broker's own `openStream` check exactly — `deposit`,
44
+ * `ratePerSecond` and `duration` each against their ceiling — because a
45
+ * divergent copy would either block hires the broker would allow or promise
46
+ * hires it will not.
47
+ */
48
+ export declare function assertWithinSpendPolicy(policy: PrivySpendPolicy, spend: RequestedSpend): void;
49
+ /**
50
+ * Refuse a hire that exceeds an OPERATOR-SET standing ceiling.
51
+ *
52
+ * `METRIK_AGENT_MANDATE_*` is not the self-signed mandate: it is a ceiling the
53
+ * operator deliberately configured, and it can be TIGHTER than the broker
54
+ * policy. A policy-enforced wallet skips the self-signed mandate, so without
55
+ * this the env caps would silently stop applying to exactly the wallets an
56
+ * unattended run is most likely to use. Enforced locally here instead, with the
57
+ * same comparisons `checkMandate()` makes.
58
+ */
59
+ export declare function assertWithinOperatorCaps(caps: ServerMandateCaps, spend: RequestedSpend): void;
60
+ //# sourceMappingURL=spend-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spend-policy.d.ts","sourceRoot":"","sources":["../../src/cli/spend-policy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,cAAc,GACpB,IAAI,CA4BN;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,cAAc,GACpB,IAAI,CAyCN"}
@@ -0,0 +1,65 @@
1
+ import { formatUsdc } from "./amounts.js";
2
+ import { CliError } from "./errors.js";
3
+ /**
4
+ * Refuse a hire the broker will refuse anyway, before any gas is spent.
5
+ *
6
+ * Mirrors the broker's own `openStream` check exactly — `deposit`,
7
+ * `ratePerSecond` and `duration` each against their ceiling — because a
8
+ * divergent copy would either block hires the broker would allow or promise
9
+ * hires it will not.
10
+ */
11
+ export function assertWithinSpendPolicy(policy, spend) {
12
+ const over = [];
13
+ if (spend.budgetUsdc > policy.maxTotalUsdc) {
14
+ over.push(`--budget ${formatUsdc(spend.budgetUsdc)} exceeds the policy ceiling of ${formatUsdc(policy.maxTotalUsdc)}`);
15
+ }
16
+ if (spend.ratePerSecondUsdc > policy.maxRatePerSecondUsdc) {
17
+ over.push(`--rate ${spend.ratePerSecondUsdc} atomic/second exceeds the policy ceiling of ${policy.maxRatePerSecondUsdc} atomic/second`);
18
+ }
19
+ if (spend.durationSeconds > policy.maxDurationSeconds) {
20
+ over.push(`--duration ${spend.durationSeconds}s exceeds the policy ceiling of ${policy.maxDurationSeconds}s`);
21
+ }
22
+ if (over.length === 0)
23
+ return;
24
+ throw new CliError(`this hire is outside the spend policy your wallet is capped at: ${over.join("; ")}`, {
25
+ exitCode: 3,
26
+ hint: `the ceiling is enforced by the broker at ${policy.brokerUrl} (GET /v1/config), not by this CLI — you cannot raise it from this side, ` +
27
+ "which is exactly what makes the wallet non-custodial. Size the stream to fit, or use a key-holding wallet.",
28
+ });
29
+ }
30
+ /**
31
+ * Refuse a hire that exceeds an OPERATOR-SET standing ceiling.
32
+ *
33
+ * `METRIK_AGENT_MANDATE_*` is not the self-signed mandate: it is a ceiling the
34
+ * operator deliberately configured, and it can be TIGHTER than the broker
35
+ * policy. A policy-enforced wallet skips the self-signed mandate, so without
36
+ * this the env caps would silently stop applying to exactly the wallets an
37
+ * unattended run is most likely to use. Enforced locally here instead, with the
38
+ * same comparisons `checkMandate()` makes.
39
+ */
40
+ export function assertWithinOperatorCaps(caps, spend) {
41
+ const over = [];
42
+ if (spend.budgetUsdc > caps.maxPerStreamUsdc) {
43
+ over.push(`--budget ${formatUsdc(spend.budgetUsdc)} exceeds METRIK_AGENT_MANDATE max-per-stream ${formatUsdc(caps.maxPerStreamUsdc)}`);
44
+ }
45
+ if (spend.budgetUsdc > caps.maxTotalUsdc) {
46
+ over.push(`--budget ${formatUsdc(spend.budgetUsdc)} exceeds METRIK_AGENT_MANDATE max-total ${formatUsdc(caps.maxTotalUsdc)}`);
47
+ }
48
+ if (spend.ratePerSecondUsdc > caps.maxRatePerSecondUsdc) {
49
+ over.push(`--rate ${spend.ratePerSecondUsdc} atomic/second exceeds METRIK_AGENT_MANDATE max rate ${caps.maxRatePerSecondUsdc} atomic/second`);
50
+ }
51
+ if (spend.durationSeconds > caps.maxDurationSeconds) {
52
+ over.push(`--duration ${spend.durationSeconds}s exceeds METRIK_AGENT_MANDATE max duration ${caps.maxDurationSeconds}s`);
53
+ }
54
+ if (caps.allowedOperators.length > 0 &&
55
+ !caps.allowedOperators.some((operator) => operator.toLowerCase() === spend.operator.toLowerCase())) {
56
+ over.push(`operator ${spend.operator} is not in METRIK_AGENT_MANDATE_ALLOWED_OPERATORS`);
57
+ }
58
+ if (over.length === 0)
59
+ return;
60
+ throw new CliError(`this hire is outside the standing mandate caps in your environment: ${over.join("; ")}`, {
61
+ exitCode: 3,
62
+ hint: "these caps come from METRIK_AGENT_MANDATE_* and are yours to change. They are enforced locally for a policy-enforced wallet, which signs no mandate of its own.",
63
+ });
64
+ }
65
+ //# sourceMappingURL=spend-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spend-policy.js","sourceRoot":"","sources":["../../src/cli/spend-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA0CvC;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAwB,EACxB,KAAqB;IAErB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;QAC3C,IAAI,CAAC,IAAI,CACP,YAAY,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,kCAAkC,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAC5G,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,iBAAiB,GAAG,MAAM,CAAC,oBAAoB,EAAE,CAAC;QAC1D,IAAI,CAAC,IAAI,CACP,UAAU,KAAK,CAAC,iBAAiB,gDAAgD,MAAM,CAAC,oBAAoB,gBAAgB,CAC7H,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACtD,IAAI,CAAC,IAAI,CACP,cAAc,KAAK,CAAC,eAAe,mCAAmC,MAAM,CAAC,kBAAkB,GAAG,CACnG,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAE9B,MAAM,IAAI,QAAQ,CAChB,mEAAmE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACpF;QACE,QAAQ,EAAE,CAAC;QACX,IAAI,EACF,4CAA4C,MAAM,CAAC,SAAS,2EAA2E;YACvI,4GAA4G;KAC/G,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CACtC,IAAuB,EACvB,KAAqB;IAErB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC7C,IAAI,CAAC,IAAI,CACP,YAAY,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,gDAAgD,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAC5H,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACzC,IAAI,CAAC,IAAI,CACP,YAAY,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,2CAA2C,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CACnH,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACxD,IAAI,CAAC,IAAI,CACP,UAAU,KAAK,CAAC,iBAAiB,wDAAwD,IAAI,CAAC,oBAAoB,gBAAgB,CACnI,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACpD,IAAI,CAAC,IAAI,CACP,cAAc,KAAK,CAAC,eAAe,+CAA+C,IAAI,CAAC,kBAAkB,GAAG,CAC7G,CAAC;IACJ,CAAC;IACD,IACE,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC;QAChC,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CACzB,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CACtE,EACD,CAAC;QACD,IAAI,CAAC,IAAI,CACP,YAAY,KAAK,CAAC,QAAQ,mDAAmD,CAC9E,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAE9B,MAAM,IAAI,QAAQ,CAChB,uEAAuE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACxF;QACE,QAAQ,EAAE,CAAC;QACX,IAAI,EAAE,iKAAiK;KACxK,CACF,CAAC;AACJ,CAAC"}