@absol-labs/agent 0.9.1 → 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 (293) hide show
  1. package/README.md +184 -26
  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/amounts.d.ts +26 -0
  6. package/dist/cli/amounts.d.ts.map +1 -0
  7. package/dist/cli/amounts.js +71 -0
  8. package/dist/cli/amounts.js.map +1 -0
  9. package/dist/cli/args.d.ts +32 -0
  10. package/dist/cli/args.d.ts.map +1 -0
  11. package/dist/cli/args.js +119 -0
  12. package/dist/cli/args.js.map +1 -0
  13. package/dist/cli/attesters.d.ts +51 -0
  14. package/dist/cli/attesters.d.ts.map +1 -0
  15. package/dist/cli/attesters.js +58 -0
  16. package/dist/cli/attesters.js.map +1 -0
  17. package/dist/cli/bin.d.ts +3 -0
  18. package/dist/cli/bin.d.ts.map +1 -0
  19. package/dist/cli/bin.js +5 -0
  20. package/dist/cli/bin.js.map +1 -0
  21. package/dist/cli/commands/claim.d.ts +13 -0
  22. package/dist/cli/commands/claim.d.ts.map +1 -0
  23. package/dist/cli/commands/claim.js +102 -0
  24. package/dist/cli/commands/claim.js.map +1 -0
  25. package/dist/cli/commands/close.d.ts +3 -0
  26. package/dist/cli/commands/close.d.ts.map +1 -0
  27. package/dist/cli/commands/close.js +55 -0
  28. package/dist/cli/commands/close.js.map +1 -0
  29. package/dist/cli/commands/discover.d.ts +3 -0
  30. package/dist/cli/commands/discover.d.ts.map +1 -0
  31. package/dist/cli/commands/discover.js +183 -0
  32. package/dist/cli/commands/discover.js.map +1 -0
  33. package/dist/cli/commands/invoke.d.ts +3 -0
  34. package/dist/cli/commands/invoke.d.ts.map +1 -0
  35. package/dist/cli/commands/invoke.js +142 -0
  36. package/dist/cli/commands/invoke.js.map +1 -0
  37. package/dist/cli/commands/mcp.d.ts +3 -0
  38. package/dist/cli/commands/mcp.d.ts.map +1 -0
  39. package/dist/cli/commands/mcp.js +113 -0
  40. package/dist/cli/commands/mcp.js.map +1 -0
  41. package/dist/cli/commands/open.d.ts +3 -0
  42. package/dist/cli/commands/open.d.ts.map +1 -0
  43. package/dist/cli/commands/open.js +331 -0
  44. package/dist/cli/commands/open.js.map +1 -0
  45. package/dist/cli/commands/reclaim-unverified.d.ts +3 -0
  46. package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -0
  47. package/dist/cli/commands/reclaim-unverified.js +172 -0
  48. package/dist/cli/commands/reclaim-unverified.js.map +1 -0
  49. package/dist/cli/commands/reclaim.d.ts +33 -0
  50. package/dist/cli/commands/reclaim.d.ts.map +1 -0
  51. package/dist/cli/commands/reclaim.js +308 -0
  52. package/dist/cli/commands/reclaim.js.map +1 -0
  53. package/dist/cli/commands/status.d.ts +3 -0
  54. package/dist/cli/commands/status.d.ts.map +1 -0
  55. package/dist/cli/commands/status.js +43 -0
  56. package/dist/cli/commands/status.js.map +1 -0
  57. package/dist/cli/commands/streams.d.ts +3 -0
  58. package/dist/cli/commands/streams.d.ts.map +1 -0
  59. package/dist/cli/commands/streams.js +257 -0
  60. package/dist/cli/commands/streams.js.map +1 -0
  61. package/dist/cli/commands/watch.d.ts +3 -0
  62. package/dist/cli/commands/watch.d.ts.map +1 -0
  63. package/dist/cli/commands/watch.js +55 -0
  64. package/dist/cli/commands/watch.js.map +1 -0
  65. package/dist/cli/config.d.ts +61 -0
  66. package/dist/cli/config.d.ts.map +1 -0
  67. package/dist/cli/config.js +140 -0
  68. package/dist/cli/config.js.map +1 -0
  69. package/dist/cli/context.d.ts +29 -0
  70. package/dist/cli/context.d.ts.map +1 -0
  71. package/dist/cli/context.js +2 -0
  72. package/dist/cli/context.js.map +1 -0
  73. package/dist/cli/deps.d.ts +191 -0
  74. package/dist/cli/deps.d.ts.map +1 -0
  75. package/dist/cli/deps.js +277 -0
  76. package/dist/cli/deps.js.map +1 -0
  77. package/dist/cli/descriptor.d.ts +61 -0
  78. package/dist/cli/descriptor.d.ts.map +1 -0
  79. package/dist/cli/descriptor.js +78 -0
  80. package/dist/cli/descriptor.js.map +1 -0
  81. package/dist/cli/errors.d.ts +48 -0
  82. package/dist/cli/errors.d.ts.map +1 -0
  83. package/dist/cli/errors.js +129 -0
  84. package/dist/cli/errors.js.map +1 -0
  85. package/dist/cli/escape-hatch.d.ts +50 -0
  86. package/dist/cli/escape-hatch.d.ts.map +1 -0
  87. package/dist/cli/escape-hatch.js +45 -0
  88. package/dist/cli/escape-hatch.js.map +1 -0
  89. package/dist/cli/index.d.ts +8 -0
  90. package/dist/cli/index.d.ts.map +1 -0
  91. package/dist/cli/index.js +7 -0
  92. package/dist/cli/index.js.map +1 -0
  93. package/dist/cli/listings.d.ts +15 -0
  94. package/dist/cli/listings.d.ts.map +1 -0
  95. package/dist/cli/listings.js +56 -0
  96. package/dist/cli/listings.js.map +1 -0
  97. package/dist/cli/mandate.d.ts +66 -0
  98. package/dist/cli/mandate.d.ts.map +1 -0
  99. package/dist/cli/mandate.js +61 -0
  100. package/dist/cli/mandate.js.map +1 -0
  101. package/dist/cli/output.d.ts +33 -0
  102. package/dist/cli/output.d.ts.map +1 -0
  103. package/dist/cli/output.js +34 -0
  104. package/dist/cli/output.js.map +1 -0
  105. package/dist/cli/preflight.d.ts +38 -0
  106. package/dist/cli/preflight.d.ts.map +1 -0
  107. package/dist/cli/preflight.js +72 -0
  108. package/dist/cli/preflight.js.map +1 -0
  109. package/dist/cli/privy.d.ts +83 -0
  110. package/dist/cli/privy.d.ts.map +1 -0
  111. package/dist/cli/privy.js +230 -0
  112. package/dist/cli/privy.js.map +1 -0
  113. package/dist/cli/progress.d.ts +36 -0
  114. package/dist/cli/progress.d.ts.map +1 -0
  115. package/dist/cli/progress.js +40 -0
  116. package/dist/cli/progress.js.map +1 -0
  117. package/dist/cli/run.d.ts +25 -0
  118. package/dist/cli/run.d.ts.map +1 -0
  119. package/dist/cli/run.js +173 -0
  120. package/dist/cli/run.js.map +1 -0
  121. package/dist/cli/scan-range.d.ts +55 -0
  122. package/dist/cli/scan-range.d.ts.map +1 -0
  123. package/dist/cli/scan-range.js +57 -0
  124. package/dist/cli/scan-range.js.map +1 -0
  125. package/dist/cli/spend-policy.d.ts +60 -0
  126. package/dist/cli/spend-policy.d.ts.map +1 -0
  127. package/dist/cli/spend-policy.js +65 -0
  128. package/dist/cli/spend-policy.js.map +1 -0
  129. package/dist/cli/status.d.ts +90 -0
  130. package/dist/cli/status.d.ts.map +1 -0
  131. package/dist/cli/status.js +252 -0
  132. package/dist/cli/status.js.map +1 -0
  133. package/dist/cli/timeout.d.ts +30 -0
  134. package/dist/cli/timeout.d.ts.map +1 -0
  135. package/dist/cli/timeout.js +55 -0
  136. package/dist/cli/timeout.js.map +1 -0
  137. package/dist/cli/version.d.ts +12 -0
  138. package/dist/cli/version.d.ts.map +1 -0
  139. package/dist/cli/version.js +22 -0
  140. package/dist/cli/version.js.map +1 -0
  141. package/dist/cli/wallet.d.ts +164 -0
  142. package/dist/cli/wallet.d.ts.map +1 -0
  143. package/dist/cli/wallet.js +234 -0
  144. package/dist/cli/wallet.js.map +1 -0
  145. package/dist/frameworks/crewai.d.ts +10 -0
  146. package/dist/frameworks/crewai.d.ts.map +1 -1
  147. package/dist/frameworks/crewai.js +12 -2
  148. package/dist/frameworks/crewai.js.map +1 -1
  149. package/dist/gateway/caller-auth-gateway.d.ts +38 -3
  150. package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
  151. package/dist/gateway/caller-auth-gateway.js +25 -1
  152. package/dist/gateway/caller-auth-gateway.js.map +1 -1
  153. package/dist/gateway/http-server.d.ts +53 -0
  154. package/dist/gateway/http-server.d.ts.map +1 -1
  155. package/dist/gateway/http-server.js +189 -4
  156. package/dist/gateway/http-server.js.map +1 -1
  157. package/dist/gateway/server-entry.d.ts +1 -0
  158. package/dist/gateway/server-entry.js +1 -0
  159. package/dist/gateway/server-entry.js.map +1 -1
  160. package/dist/gateway/x402-mode.d.ts +123 -0
  161. package/dist/gateway/x402-mode.d.ts.map +1 -0
  162. package/dist/gateway/x402-mode.js +212 -0
  163. package/dist/gateway/x402-mode.js.map +1 -0
  164. package/dist/index.d.ts +6 -4
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +8 -3
  167. package/dist/index.js.map +1 -1
  168. package/dist/mandates/env.d.ts +3 -2
  169. package/dist/mandates/env.d.ts.map +1 -1
  170. package/dist/mandates/env.js +3 -2
  171. package/dist/mandates/env.js.map +1 -1
  172. package/dist/mcp/http-server.d.ts +1 -0
  173. package/dist/mcp/http-server.js +1 -0
  174. package/dist/mcp/http-server.js.map +1 -1
  175. package/dist/mcp/server.d.ts +49 -0
  176. package/dist/mcp/server.d.ts.map +1 -1
  177. package/dist/mcp/server.js +533 -25
  178. package/dist/mcp/server.js.map +1 -1
  179. package/dist/mcp/service-invoker.d.ts +97 -0
  180. package/dist/mcp/service-invoker.d.ts.map +1 -0
  181. package/dist/mcp/service-invoker.js +167 -0
  182. package/dist/mcp/service-invoker.js.map +1 -0
  183. package/dist/mcp/stdio.d.ts +1 -0
  184. package/dist/mcp/stdio.js +1 -0
  185. package/dist/mcp/stdio.js.map +1 -1
  186. package/dist/sdk/client.d.ts +25 -1
  187. package/dist/sdk/client.d.ts.map +1 -1
  188. package/dist/sdk/client.js +20 -1
  189. package/dist/sdk/client.js.map +1 -1
  190. package/dist/sdk/invoke.d.ts +19 -4
  191. package/dist/sdk/invoke.d.ts.map +1 -1
  192. package/dist/sdk/invoke.js +69 -5
  193. package/dist/sdk/invoke.js.map +1 -1
  194. package/dist/x402/delivery-oracle.d.ts +108 -0
  195. package/dist/x402/delivery-oracle.d.ts.map +1 -0
  196. package/dist/x402/delivery-oracle.js +174 -0
  197. package/dist/x402/delivery-oracle.js.map +1 -0
  198. package/dist/x402/facilitator-server-entry.d.ts +3 -0
  199. package/dist/x402/facilitator-server-entry.d.ts.map +1 -0
  200. package/dist/x402/facilitator-server-entry.js +27 -0
  201. package/dist/x402/facilitator-server-entry.js.map +1 -0
  202. package/dist/x402/facilitator-server.d.ts +73 -0
  203. package/dist/x402/facilitator-server.d.ts.map +1 -0
  204. package/dist/x402/facilitator-server.js +305 -0
  205. package/dist/x402/facilitator-server.js.map +1 -0
  206. package/dist/x402/facilitator.d.ts +69 -17
  207. package/dist/x402/facilitator.d.ts.map +1 -1
  208. package/dist/x402/facilitator.js +76 -33
  209. package/dist/x402/facilitator.js.map +1 -1
  210. package/dist/x402/payment-requirements.d.ts +106 -0
  211. package/dist/x402/payment-requirements.d.ts.map +1 -0
  212. package/dist/x402/payment-requirements.js +138 -0
  213. package/dist/x402/payment-requirements.js.map +1 -0
  214. package/dist/x402/relayer.d.ts +41 -0
  215. package/dist/x402/relayer.d.ts.map +1 -0
  216. package/dist/x402/relayer.js +64 -0
  217. package/dist/x402/relayer.js.map +1 -0
  218. package/dist/x402/resource-index.d.ts +75 -0
  219. package/dist/x402/resource-index.d.ts.map +1 -0
  220. package/dist/x402/resource-index.js +126 -0
  221. package/dist/x402/resource-index.js.map +1 -0
  222. package/dist/x402/verified-delivery-facilitator.d.ts +285 -0
  223. package/dist/x402/verified-delivery-facilitator.d.ts.map +1 -0
  224. package/dist/x402/verified-delivery-facilitator.js +423 -0
  225. package/dist/x402/verified-delivery-facilitator.js.map +1 -0
  226. package/dist/zktls/t2-delivery-proof.d.ts +6 -6
  227. package/docs/agent-layer.md +14 -9
  228. package/docs/cli.md +705 -0
  229. package/docs/crewai.md +6 -2
  230. package/docs/eliza.md +6 -1
  231. package/docs/mcp-hosted.md +7 -5
  232. package/docs/mcp-reference.md +175 -0
  233. package/docs/quickstart.md +36 -9
  234. package/docs/threat-model.md +4 -3
  235. package/docs/x402.md +648 -0
  236. package/package.json +33 -10
  237. package/src/capability/invocation-capability.ts +17 -1
  238. package/src/cli/amounts.ts +102 -0
  239. package/src/cli/args.ts +150 -0
  240. package/src/cli/attesters.ts +86 -0
  241. package/src/cli/bin.ts +5 -0
  242. package/src/cli/commands/claim.ts +126 -0
  243. package/src/cli/commands/close.ts +69 -0
  244. package/src/cli/commands/discover.ts +228 -0
  245. package/src/cli/commands/invoke.ts +178 -0
  246. package/src/cli/commands/mcp.ts +135 -0
  247. package/src/cli/commands/open.ts +397 -0
  248. package/src/cli/commands/reclaim-unverified.ts +218 -0
  249. package/src/cli/commands/reclaim.ts +377 -0
  250. package/src/cli/commands/status.ts +56 -0
  251. package/src/cli/commands/streams.ts +344 -0
  252. package/src/cli/commands/watch.ts +70 -0
  253. package/src/cli/config.ts +208 -0
  254. package/src/cli/context.ts +30 -0
  255. package/src/cli/deps.ts +528 -0
  256. package/src/cli/descriptor.ts +133 -0
  257. package/src/cli/errors.ts +162 -0
  258. package/src/cli/escape-hatch.ts +92 -0
  259. package/src/cli/index.ts +27 -0
  260. package/src/cli/listings.ts +77 -0
  261. package/src/cli/mandate.ts +126 -0
  262. package/src/cli/output.ts +63 -0
  263. package/src/cli/preflight.ts +88 -0
  264. package/src/cli/privy.ts +396 -0
  265. package/src/cli/progress.ts +75 -0
  266. package/src/cli/run.ts +209 -0
  267. package/src/cli/scan-range.ts +76 -0
  268. package/src/cli/spend-policy.ts +139 -0
  269. package/src/cli/status.ts +381 -0
  270. package/src/cli/timeout.ts +64 -0
  271. package/src/cli/version.ts +21 -0
  272. package/src/cli/wallet.ts +372 -0
  273. package/src/frameworks/crewai.ts +13 -2
  274. package/src/gateway/caller-auth-gateway.ts +77 -6
  275. package/src/gateway/http-server.ts +280 -6
  276. package/src/gateway/server-entry.ts +1 -0
  277. package/src/gateway/x402-mode.ts +350 -0
  278. package/src/index.ts +40 -5
  279. package/src/mandates/env.ts +3 -2
  280. package/src/mcp/http-server.ts +1 -0
  281. package/src/mcp/server.ts +706 -30
  282. package/src/mcp/service-invoker.ts +285 -0
  283. package/src/mcp/stdio.ts +1 -0
  284. package/src/sdk/client.ts +33 -1
  285. package/src/sdk/invoke.ts +90 -12
  286. package/src/x402/delivery-oracle.ts +285 -0
  287. package/src/x402/facilitator-server-entry.ts +35 -0
  288. package/src/x402/facilitator-server.ts +445 -0
  289. package/src/x402/facilitator.ts +125 -46
  290. package/src/x402/payment-requirements.ts +231 -0
  291. package/src/x402/relayer.ts +122 -0
  292. package/src/x402/resource-index.ts +228 -0
  293. package/src/x402/verified-delivery-facilitator.ts +744 -0
@@ -0,0 +1,331 @@
1
+ import { MandateDeniedError } from "../../sdk/client.js";
2
+ import { booleanFlag, requiredStringFlag, stringFlag } from "../args.js";
3
+ import { formatDuration, formatUsdc, parseAmountUnits, parseDurationSeconds, parseUsdcAmount, } from "../amounts.js";
4
+ import { assertTestnetRpc, parseBytes32 } from "../config.js";
5
+ import { writeClientOptions } from "../deps.js";
6
+ import { CliError, configError } from "../errors.js";
7
+ import { assertWithinOperatorCaps, assertWithinSpendPolicy, } from "../spend-policy.js";
8
+ import { cliMandateCaps, signCliMandate } from "../mandate.js";
9
+ import { assertCanFundStream, assertCanPayGas } from "../preflight.js";
10
+ import { isPolicyEnforced, optionalCliWallet, resolveCliWallet, PRIVATE_KEY_ENV, } from "../wallet.js";
11
+ import { resolveListing } from "../listings.js";
12
+ export const openCommand = {
13
+ name: "open",
14
+ summary: "Hire a verified service: escrow USDC into a metered stream",
15
+ usage: "metrik open --service <serviceRef> --rate <usdc/s> --budget <usdc> --duration <seconds> [--units atomic] [--dry-run]",
16
+ flags: [
17
+ "service",
18
+ "rate",
19
+ "budget",
20
+ "duration",
21
+ "units",
22
+ "operator",
23
+ "dry-run",
24
+ ],
25
+ signs: true,
26
+ async run(context) {
27
+ const { args, config, env, out, deps } = context;
28
+ const units = parseAmountUnits(stringFlag(args, "units"));
29
+ const serviceRef = parseBytes32(requiredStringFlag(args, "service"), "--service");
30
+ const budgetUsdc = parseUsdcAmount(requiredStringFlag(args, "budget"), units, "budget");
31
+ const ratePerSecondUsdc = parseUsdcAmount(requiredStringFlag(args, "rate"), units, "rate");
32
+ const durationSeconds = parseDurationSeconds(requiredStringFlag(args, "duration"));
33
+ const dryRun = booleanFlag(args, "dry-run");
34
+ if (budgetUsdc <= 0n || ratePerSecondUsdc <= 0n) {
35
+ throw new CliError("--budget and --rate must both be greater than zero", {
36
+ exitCode: 2,
37
+ });
38
+ }
39
+ const maxSpend = ratePerSecondUsdc * BigInt(durationSeconds);
40
+ if (maxSpend > budgetUsdc) {
41
+ out.note(`note: --rate x --duration (${formatUsdc(maxSpend)}) exceeds --budget; accrual is capped at the deposit and the stream simply runs out of budget before it expires.`);
42
+ }
43
+ // `--dry-run` broadcasts nothing, so it does NOT require a key: it is the
44
+ // look-before-you-leap path, and the person most in need of it is exactly
45
+ // the one who has not funded a wallet yet. Without a key the preview prints
46
+ // the intended call and says which parts (allowance, simulation, mandate
47
+ // signature) could not be produced, rather than inventing them.
48
+ const wallet = dryRun
49
+ ? await optionalCliWallet(env, { note: out.note, rpcUrl: config.rpcUrl })
50
+ : await resolveCliWallet(env, { note: out.note, rpcUrl: config.rpcUrl });
51
+ const account = wallet?.account ?? null;
52
+ const read = deps.createReadClient(config);
53
+ await assertTestnetRpc(config, () => read.getChainId());
54
+ if (account !== null && !dryRun) {
55
+ // Both balances, before anything is signed. Gas first: a wallet with no
56
+ // ETH cannot send the approval that the USDC check exists to protect.
57
+ await assertCanPayGas(read, account.address);
58
+ await assertCanFundStream(read, account.address, budgetUsdc);
59
+ }
60
+ const operatorOverride = stringFlag(args, "operator");
61
+ const listing = await resolveListing(context, serviceRef, {
62
+ required: operatorOverride === undefined,
63
+ });
64
+ const operator = (operatorOverride ?? listing?.operator);
65
+ if (operator === undefined) {
66
+ throw configError(`serviceRef ${serviceRef} is not in the registry and no --operator was given`, "run `metrik discover` to find a listed service, or pass --operator explicitly.");
67
+ }
68
+ const spend = { operator, budgetUsdc, ratePerSecondUsdc, durationSeconds };
69
+ const mandateCaps = cliMandateCaps(spend, env);
70
+ // A policy-enforced wallet (Privy) is capped by its broker, not by a
71
+ // mandate this process signs for itself. Read the REAL ceiling and hold it
72
+ // to that instead — see `../spend-policy.ts` for why that substitution is
73
+ // the stronger of the two, and why re-adding the self-signed mandate here
74
+ // would both weaken it and break the wallet outright.
75
+ const policy = wallet !== null && isPolicyEnforced(wallet)
76
+ ? await wallet.readSpendPolicy()
77
+ : null;
78
+ if (policy !== null && !dryRun) {
79
+ assertWithinSpendPolicy(policy, spend);
80
+ // The operator's own standing ceiling still applies, and may be TIGHTER
81
+ // than the broker's. Enforced here because no mandate is signed to carry
82
+ // it — "policy-enforced" retires the self-signed mandate, not the caps
83
+ // the operator deliberately configured.
84
+ if (mandateCaps.source === "env") {
85
+ assertWithinOperatorCaps(mandateCaps.caps, spend);
86
+ }
87
+ }
88
+ const mandate = account === null || policy !== null
89
+ ? null
90
+ : await signCliMandate(account, spend, {
91
+ chainId: config.chainId,
92
+ env,
93
+ });
94
+ const write = deps.createWriteClient(config, account, writeClientOptions(wallet));
95
+ const hire = {
96
+ operator,
97
+ serviceRef,
98
+ budgetUsdc,
99
+ ratePerSecond: ratePerSecondUsdc,
100
+ maxDurationSeconds: durationSeconds,
101
+ };
102
+ if (dryRun) {
103
+ const preview = await write.buildHireTx(hire);
104
+ // A dry run simulates `openStream` from the CURRENT chain state, which
105
+ // does not include the USDC approval the real command sends first. So the
106
+ // simulation reverts on the allowance every time the allowance is not
107
+ // already in place — which, on a first hire, is always. Reporting that as
108
+ // `simulationError` made the one command meant to build confidence
109
+ // predict failure on first use. It is a known ordering step, not a fault.
110
+ const approvalBlocksSimulation = isApprovalOrdering(preview);
111
+ // Reported, never enforced: a dry run broadcasts nothing, so an
112
+ // underfunded wallet is information here, not a refusal. The same read
113
+ // IS a gate on the real path (`assertCanFundStream` above).
114
+ const usdcBalance = account === null
115
+ ? null
116
+ : await read.usdcBalance(account.address).catch(() => null);
117
+ out.result({
118
+ dryRun: true,
119
+ buyer: account?.address ?? null,
120
+ operator,
121
+ serviceRef,
122
+ budgetUsdc,
123
+ ratePerSecondUsdc,
124
+ durationSeconds,
125
+ mandateSource: mandateCaps.source,
126
+ mandateSigned: mandate !== null,
127
+ spendPolicy: policy === null
128
+ ? null
129
+ : {
130
+ brokerUrl: policy.brokerUrl,
131
+ maxTotalUsdc: policy.maxTotalUsdc,
132
+ maxRatePerSecondUsdc: policy.maxRatePerSecondUsdc,
133
+ maxDurationSeconds: policy.maxDurationSeconds,
134
+ fits: budgetUsdc <= policy.maxTotalUsdc &&
135
+ ratePerSecondUsdc <= policy.maxRatePerSecondUsdc &&
136
+ durationSeconds <= policy.maxDurationSeconds,
137
+ },
138
+ to: preview.to,
139
+ data: preview.data,
140
+ chainId: preview.chainId,
141
+ approval: {
142
+ required: preview.approval.required,
143
+ amount: preview.approval.amount,
144
+ spender: preview.approval.spender,
145
+ token: preview.approval.token,
146
+ },
147
+ usdcBalance,
148
+ usdcSufficient: usdcBalance === null ? null : usdcBalance >= budgetUsdc,
149
+ simulatedStreamId: preview.simulatedStreamId,
150
+ // Mutually exclusive by construction: an allowance-ordering revert is
151
+ // reported as `simulationPendingApproval`, never as an error, so a
152
+ // script branching on `simulationError` does not treat the expected
153
+ // first-hire path as a failure.
154
+ simulationPendingApproval: approvalBlocksSimulation,
155
+ ...(preview.simulationError === undefined || approvalBlocksSimulation
156
+ ? {}
157
+ : { simulationError: preview.simulationError }),
158
+ });
159
+ out.print("Dry run — nothing was broadcast.");
160
+ out.table([
161
+ [
162
+ "buyer",
163
+ account?.address ??
164
+ `unknown (no wallet configured — set ${PRIVATE_KEY_ENV} or the CDP variables to preview from a real address)`,
165
+ ],
166
+ ["operator", operator],
167
+ ["serviceRef", serviceRef],
168
+ ["budget", formatUsdc(budgetUsdc)],
169
+ ["rate", `${formatUsdc(ratePerSecondUsdc)} / second`],
170
+ ["duration", formatDuration(durationSeconds)],
171
+ [
172
+ "mandate",
173
+ mandate !== null
174
+ ? `self-signed, caps from ${mandateCaps.source}`
175
+ : policy !== null
176
+ ? "not signed — this wallet's ceiling is enforced by its broker, which is stronger"
177
+ : `not signed (no wallet); caps would come from ${mandateCaps.source}`,
178
+ ],
179
+ ...(policy === null
180
+ ? []
181
+ : [
182
+ [
183
+ "spend policy",
184
+ `${formatUsdc(policy.maxTotalUsdc)} total, ${policy.maxRatePerSecondUsdc} atomic/second, ${formatDuration(policy.maxDurationSeconds)} max — enforced by ${policy.brokerUrl}`,
185
+ ],
186
+ [
187
+ "fits policy",
188
+ budgetUsdc <= policy.maxTotalUsdc &&
189
+ ratePerSecondUsdc <= policy.maxRatePerSecondUsdc &&
190
+ durationSeconds <= policy.maxDurationSeconds
191
+ ? "yes"
192
+ : "NO — a real open would be refused before broadcasting",
193
+ ],
194
+ ]),
195
+ ["escrow", preview.to],
196
+ [
197
+ "usdc balance",
198
+ usdcBalance === null
199
+ ? "unread (no wallet configured)"
200
+ : usdcBalance >= budgetUsdc
201
+ ? `${formatUsdc(usdcBalance)} (covers the budget)`
202
+ : `${formatUsdc(usdcBalance)} — SHORT of the ${formatUsdc(budgetUsdc)} budget; a real open would be refused`,
203
+ ],
204
+ [
205
+ "usdc approval",
206
+ preview.approval.required === null
207
+ ? `${formatUsdc(preview.approval.amount)} (allowance unread)`
208
+ : preview.approval.required
209
+ ? `${formatUsdc(preview.approval.amount)} (required)`
210
+ : "already sufficient",
211
+ ],
212
+ [
213
+ "simulated streamId",
214
+ preview.simulatedStreamId ??
215
+ (approvalBlocksSimulation
216
+ ? "not simulated yet — the bounded USDC approval above is sent FIRST by a real open, and the escrow cannot pull the deposit until it lands. Expected on a first hire, not a failure."
217
+ : `unavailable (${preview.simulationError ?? "simulation did not run"})`),
218
+ ],
219
+ ]);
220
+ out.print("");
221
+ out.print(METERING_NOTE);
222
+ return;
223
+ }
224
+ out.note(`opening a stream on chain ${config.chainId} for ${formatUsdc(budgetUsdc)} …`);
225
+ // Unreachable without a wallet: `resolveCliWallet` above throws when the
226
+ // command is not a dry run. The narrowing keeps that a type-level fact.
227
+ if (account === null) {
228
+ throw configError("this command signs a transaction and needs a wallet, and none was resolved");
229
+ }
230
+ let result;
231
+ try {
232
+ result = await write.openVerifiedStream({
233
+ operator,
234
+ serviceRef,
235
+ budgetUsdc,
236
+ ratePerSecondUsdc,
237
+ maxDurationSeconds: durationSeconds,
238
+ // `null` for a policy-enforced wallet: the ceiling was checked against
239
+ // the broker's own policy above, and the broker checks it again on the
240
+ // transaction it signs.
241
+ signedMandate: mandate === null ? null : mandate.signed,
242
+ spentSoFarUsdc: 0n,
243
+ nowSeconds: deps.nowSeconds(),
244
+ });
245
+ }
246
+ catch (error) {
247
+ if (error instanceof MandateDeniedError) {
248
+ throw new CliError(`spend mandate denied this hire: ${error.reason}`, {
249
+ exitCode: 3,
250
+ hint: mandateCaps.source === "env"
251
+ ? "the requested hire exceeds your METRIK_AGENT_MANDATE_* ceiling."
252
+ : "the hire does not satisfy the mandate signed for it.",
253
+ cause: error,
254
+ });
255
+ }
256
+ throw error;
257
+ }
258
+ out.result({
259
+ streamId: result.streamId,
260
+ txHash: result.txHash,
261
+ approveTxHash: result.approveTxHash,
262
+ buyer: account.address,
263
+ operator,
264
+ serviceRef,
265
+ budgetUsdc,
266
+ ratePerSecondUsdc,
267
+ durationSeconds,
268
+ escrow: result.handle.escrow,
269
+ chainId: result.handle.chainId,
270
+ });
271
+ out.print("Stream opened.");
272
+ out.table([
273
+ ["streamId", result.streamId],
274
+ ["tx", result.txHash],
275
+ ["approve tx", result.approveTxHash ?? "not needed"],
276
+ ["buyer", account.address],
277
+ ["operator", operator],
278
+ ["budget", formatUsdc(budgetUsdc)],
279
+ ["rate", `${formatUsdc(ratePerSecondUsdc)} / second`],
280
+ ["duration", formatDuration(durationSeconds)],
281
+ ]);
282
+ out.print("");
283
+ out.print(METERING_NOTE);
284
+ out.print("");
285
+ out.print(`Next: metrik status ${result.streamId}`);
286
+ },
287
+ };
288
+ /**
289
+ * What the buyer is actually paying for.
290
+ *
291
+ * A live acceptance run made ONE `invoke` call and paid for 302 seconds, which
292
+ * is exactly the design — and exactly what nothing in the CLI said. "Pay for
293
+ * verified delivery" reads as "pay for delivery TO ME", so a buyer expects
294
+ * per-call billing and gets a rental meter. The meter runs on the oracle's
295
+ * probes of the endpoint, not on the buyer's own requests; one call and a
296
+ * thousand calls cost the same second.
297
+ */
298
+ const METERING_NOTE = "How you are billed: this is TIME-metered rental of an endpoint the oracle keeps probing — not per-call billing. The meter runs on verified availability, so it charges the same whether you send one request or a thousand, and it keeps charging while you send none. `metrik close <streamId>` stops the clock; nothing else does.";
299
+ /**
300
+ * Shapes that mean "the spender's allowance is too small", across the OpenZeppelin
301
+ * string revert and the ERC-6093 custom error. Matched as phrases, never on the
302
+ * bare word `allowance`: the no-wallet preview reports `no account configured —
303
+ * allowance and simulation skipped`, which contains the word and is a COMPLETELY
304
+ * different fact. Excusing that as "an approval will be sent first" would state
305
+ * a reason the CLI does not have.
306
+ */
307
+ const ALLOWANCE_SHORTFALL = [
308
+ /transfer amount exceeds allowance/i,
309
+ /insufficient allowance/i,
310
+ /ERC20InsufficientAllowance/,
311
+ ];
312
+ /**
313
+ * True when the dry run's simulation failed ONLY because the USDC approval a
314
+ * real open sends first has not been sent.
315
+ *
316
+ * Deliberately narrow: it requires an actual REVERT, whose reason is an
317
+ * allowance shortfall, on a preview that says an approval is (or may be)
318
+ * needed. Anything else keeps being reported as a simulation error, because
319
+ * every other failure is a real one the buyer should see before spending.
320
+ */
321
+ function isApprovalOrdering(preview) {
322
+ const error = preview.simulationError;
323
+ if (error === undefined || preview.simulatedStreamId != null)
324
+ return false;
325
+ if (preview.approval.required === false)
326
+ return false;
327
+ if (!/\brevert(ed)?\b/i.test(error))
328
+ return false;
329
+ return ALLOWANCE_SHORTFALL.some((pattern) => pattern.test(error));
330
+ }
331
+ //# sourceMappingURL=open.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.js","sourceRoot":"","sources":["../../../src/cli/commands/open.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CommandSpec } from "../context.js";
2
+ export declare const reclaimUnverifiedCommand: CommandSpec;
3
+ //# sourceMappingURL=reclaim-unverified.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reclaim-unverified.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/reclaim-unverified.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,eAAe,CAAC;AA2CjE,eAAO,MAAM,wBAAwB,EAAE,WAwGtC,CAAC"}
@@ -0,0 +1,172 @@
1
+ import { booleanFlag } from "../args.js";
2
+ import { formatDuration, formatUsdc } from "../amounts.js";
3
+ import { assertTestnetRpc, parseBytes32 } from "../config.js";
4
+ import { CliError, usageError } from "../errors.js";
5
+ import { escapeHatchWindow, formatTimestamp, readChainNow, } from "../escape-hatch.js";
6
+ import { signRecoveryMandate } from "../mandate.js";
7
+ import { assertCanPayGas } from "../preflight.js";
8
+ import { writeClientOptions } from "../deps.js";
9
+ import { isPolicyEnforced, resolveCliWallet } from "../wallet.js";
10
+ /**
11
+ * The acknowledgement this command will not run without.
12
+ *
13
+ * `reclaim-unverified` is deliberately BOTH a command of its own and a command
14
+ * that refuses to run on its arguments alone:
15
+ *
16
+ * - it is not `metrik reclaim --unverified`, because that is one token away
17
+ * from the safe path, sits in the same command's flag list (so a script that
18
+ * templates flags can pick it up), and shell completion offers it beside
19
+ * `--close-first`;
20
+ * - and the flag below has no default and no `--no-` form, so the only way to
21
+ * reach the transaction is to type a phrase that says what it costs.
22
+ *
23
+ * Nothing about this command is reachable by fat-fingering the ordinary one.
24
+ */
25
+ const ACKNOWLEDGEMENT_FLAG = "forfeit-unclaimed";
26
+ /**
27
+ * Exactly what the escrow does, so the warning does not have to be trusted.
28
+ *
29
+ * `StreamEscrowV2.reclaimUnverified` sets `entitlement = stream.claimedCumulative`
30
+ * and then `settledCumulative = entitlement; deposit = entitlement`. The
31
+ * operator's own redemption path caps at that value once the stream is
32
+ * reclaimed (`if (stream.reclaimed && payableCumulative > stream.settledCumulative)
33
+ * payableCumulative = stream.settledCumulative;`) and then requires
34
+ * `payableCumulative > stream.claimedCumulative` — which can never hold again.
35
+ * Every voucher earned but not yet redeemed on-chain is therefore forfeit
36
+ * PERMANENTLY, and its value is paid to the buyer.
37
+ */
38
+ const FORFEIT_WARNING = [
39
+ "This pays you deposit - claimedCumulative with NO proof and NO oracle.",
40
+ "What it costs the operator: everything they verifiably earned but have not yet",
41
+ "claimed on-chain is forfeited to you, permanently. The escrow caps their",
42
+ "entitlement at what they had already claimed, so every later claim reverts",
43
+ "NothingToClaim(). There is no way to pay it back afterwards.",
44
+ "",
45
+ "Use it when the oracle cannot give you a proof. Where `metrik reclaim` works,",
46
+ "use that instead — it settles the operator honestly and pays you the rest.",
47
+ ];
48
+ export const reclaimUnverifiedCommand = {
49
+ name: "reclaim-unverified",
50
+ summary: "Escape hatch: reclaim with no proof when the oracle cannot give you one",
51
+ usage: `metrik reclaim-unverified <streamId> --${ACKNOWLEDGEMENT_FLAG}`,
52
+ flags: [ACKNOWLEDGEMENT_FLAG],
53
+ signs: true,
54
+ async run(context) {
55
+ const { args, config, env, out, deps } = context;
56
+ const [streamIdArg] = args.positionals;
57
+ if (streamIdArg === undefined) {
58
+ throw usageError("metrik reclaim-unverified requires a <streamId>");
59
+ }
60
+ const streamId = parseBytes32(streamIdArg, "<streamId>");
61
+ if (!booleanFlag(args, ACKNOWLEDGEMENT_FLAG)) {
62
+ throw usageError(`metrik reclaim-unverified forfeits the operator's unclaimed earnings, so it requires --${ACKNOWLEDGEMENT_FLAG}`, [
63
+ ...FORFEIT_WARNING,
64
+ "",
65
+ `Re-run with --${ACKNOWLEDGEMENT_FLAG} once that is what you intend.`,
66
+ ].join("\n "));
67
+ }
68
+ const wallet = await resolveCliWallet(env, {
69
+ note: out.note,
70
+ rpcUrl: config.rpcUrl,
71
+ });
72
+ const { account } = wallet;
73
+ const read = deps.createReadClient(config);
74
+ await assertTestnetRpc(config, () => read.getChainId());
75
+ await assertCanPayGas(read, account.address);
76
+ const stream = await read.getStreamV2(streamId);
77
+ if (stream.reclaimed) {
78
+ throw new CliError("this stream has already been reclaimed — there is nothing left to take back", {
79
+ exitCode: 4,
80
+ hint: `check where it went: metrik status ${streamId}`,
81
+ });
82
+ }
83
+ // Readiness is computed against the chain's clock, because the escrow
84
+ // compares against `block.timestamp`. Spending gas on a guaranteed
85
+ // `EscapeHatchNotReady()` revert is exactly the failure this gate exists to
86
+ // prevent.
87
+ const grace = await readEscapeGrace(read);
88
+ const now = await readChainNow(read, deps.nowSeconds());
89
+ const window = escapeHatchWindow(stream, grace, now.seconds);
90
+ if (!window.ready) {
91
+ throw notReady(streamId, window, now.source);
92
+ }
93
+ // The amount at stake, when it is knowable. It usually is not: the reason to
94
+ // be on this path at all is that the oracle is not answering, and the
95
+ // operator's redeemable balance is derived from the oracle's proof.
96
+ const forfeit = await readForfeitEstimate(read, streamId);
97
+ out.note("");
98
+ for (const line of FORFEIT_WARNING)
99
+ out.note(line);
100
+ out.note(forfeit === null
101
+ ? "Operator balance at stake: unknown — the oracle did not answer, which is the situation this command is for."
102
+ : `Operator balance at stake right now: ${formatUsdc(forfeit)} (net of protocol fee). This transaction forfeits it.`);
103
+ out.note("");
104
+ const write = deps.createWriteClient(config, account, writeClientOptions(wallet));
105
+ const result = await write.reclaimUnverifiedStream({
106
+ streamId,
107
+ // `null` for a policy-enforced wallet — see `../spend-policy.ts`.
108
+ signedMandate: isPolicyEnforced(wallet)
109
+ ? null
110
+ : await signRecoveryMandate(account, config.chainId),
111
+ spentSoFarUsdc: 0n,
112
+ nowSeconds: deps.nowSeconds(),
113
+ });
114
+ out.result({
115
+ streamId,
116
+ txHash: result.txHash,
117
+ unverified: true,
118
+ escapeHatchReadyAt: window.readyAt,
119
+ escapeGraceSeconds: window.graceSeconds,
120
+ forfeitedOperatorClaimable: forfeit,
121
+ });
122
+ out.print("Reclaimed without a proof.");
123
+ out.table([
124
+ ["streamId", streamId],
125
+ ["tx", result.txHash],
126
+ ["escape hatch opened", formatTimestamp(window.readyAt)],
127
+ [
128
+ "operator earnings forfeited",
129
+ forfeit === null ? "unknown (oracle unreachable)" : formatUsdc(forfeit),
130
+ ],
131
+ ]);
132
+ },
133
+ };
134
+ function notReady(streamId, window, clock) {
135
+ return new CliError(`the no-proof escape hatch is not open yet: it unlocks at ${formatTimestamp(window.readyAt)}, in ${formatDuration(window.secondsRemaining)}`, {
136
+ exitCode: 4,
137
+ hint: [
138
+ `The escrow gates this on expiresAt + escapeGraceSeconds (${window.graceSeconds}s), never on when you closed${clock === "chain"
139
+ ? ""
140
+ : " — and the chain's own clock could not be read, so this is your machine's"}.`,
141
+ `Until then the honest path is the proof-based one: metrik reclaim ${streamId}`,
142
+ ].join(" "),
143
+ });
144
+ }
145
+ /** `escapeGraceSeconds` is a public immutable; failing to read it is fatal here. */
146
+ async function readEscapeGrace(read) {
147
+ try {
148
+ return await read.escapeGraceSeconds();
149
+ }
150
+ catch (error) {
151
+ throw new CliError("could not read escapeGraceSeconds from the escrow, so whether the escape hatch is open is unknown", {
152
+ exitCode: 4,
153
+ hint: "this command refuses to broadcast on a guess: retry when the RPC endpoint answers.",
154
+ cause: error,
155
+ });
156
+ }
157
+ }
158
+ /**
159
+ * What the operator could redeem right now, i.e. what this transaction takes
160
+ * from them. `null` when the oracle cannot be reached — which is the normal case
161
+ * on this path and is reported as unknown rather than as zero.
162
+ */
163
+ async function readForfeitEstimate(read, streamId) {
164
+ try {
165
+ const proof = await read.checkpointProof(streamId);
166
+ return await read.claimableForV2(streamId, proof.cumulativeAmount);
167
+ }
168
+ catch {
169
+ return null;
170
+ }
171
+ }
172
+ //# sourceMappingURL=reclaim-unverified.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reclaim-unverified.js","sourceRoot":"","sources":["../../../src/cli/commands/reclaim-unverified.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { CommandSpec } from "../context.js";
2
+ import type { CliReadClient, CliWriteClient } from "../deps.js";
3
+ import type { ReclaimVerifiedStreamResult, StreamProofTransactionResult } from "../../sdk/client.js";
4
+ export declare const reclaimCommand: CommandSpec;
5
+ /**
6
+ * Send the close that `--close-first` asks for, tolerating the one race that
7
+ * matters: a stale read said "active" but the stream was in fact already closed.
8
+ * That is the state the caller wanted, so it is reported as `null` (no close
9
+ * sent) rather than as a failure — re-running the command must never dead-end on
10
+ * `StreamClosedAlready()` while the buyer's money is still reclaimable.
11
+ *
12
+ * Every OTHER close failure is rethrown untouched.
13
+ */
14
+ export declare function closeBeforeReclaim(write: CliWriteClient, input: Parameters<CliWriteClient["closeStream"]>[0]): Promise<StreamProofTransactionResult | null>;
15
+ export declare function awaitClosed(read: Pick<CliReadClient, "getStreamV2">, streamId: `0x${string}`, sleep: (ms: number) => Promise<void>, closeTxHash: string): Promise<void>;
16
+ /**
17
+ * `reclaimWithProof` reverts with `SettlementWindowOpen` until the oracle has
18
+ * published a checkpoint whose `checkedAt` is at or after the stream's stop
19
+ * time. That is not an error condition — it is the normal ordering of a
20
+ * checkpoint rail, and it happens on the FIRST attempt essentially every time.
21
+ * A CLI that surfaced the raw revert would teach every user that reclaim is
22
+ * broken, so the wait is built in and narrated. Any other failure is rethrown
23
+ * immediately: only an open settlement window is retried.
24
+ */
25
+ export declare function reclaimWithBoundedRetry(write: CliWriteClient, buildInput: () => Promise<Parameters<CliWriteClient["reclaimStream"]>[0]>, options: {
26
+ readonly attempts: number;
27
+ readonly intervalMs: number;
28
+ readonly sleep: (ms: number) => Promise<void>;
29
+ readonly onRetry: (attempt: number, reason: string) => void;
30
+ /** What to tell the buyer once the budget is spent. See `describeLastResort`. */
31
+ readonly exhaustedHint?: () => Promise<string>;
32
+ }): Promise<ReclaimVerifiedStreamResult>;
33
+ //# sourceMappingURL=reclaim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reclaim.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/reclaim.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EACV,2BAA2B,EAC3B,4BAA4B,EAC7B,MAAM,qBAAqB,CAAC;AAW7B,eAAO,MAAM,cAAc,EAAE,WA4I5B,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC,CAO9C;AA0BD,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,EACxC,QAAQ,EAAE,KAAK,MAAM,EAAE,EACvB,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EACpC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,cAAc,EACrB,UAAU,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACzE,OAAO,EAAE;IACP,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,iFAAiF;IACjF,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAChD,GACA,OAAO,CAAC,2BAA2B,CAAC,CAuBtC"}