@avow-finance/sdk 0.0.0-stage → 0.2.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 (267) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +122 -2
  3. package/dist/agent-entry.d.ts +15 -0
  4. package/dist/agent-entry.d.ts.map +1 -0
  5. package/dist/agent-entry.js +11 -0
  6. package/dist/agent-entry.js.map +1 -0
  7. package/dist/agent-key.d.ts +34 -0
  8. package/dist/agent-key.d.ts.map +1 -0
  9. package/dist/agent-key.js +33 -0
  10. package/dist/agent-key.js.map +1 -0
  11. package/dist/agent.d.ts +261 -0
  12. package/dist/agent.d.ts.map +1 -0
  13. package/dist/agent.js +493 -0
  14. package/dist/agent.js.map +1 -0
  15. package/dist/avow-api.d.ts +78 -0
  16. package/dist/avow-api.d.ts.map +1 -0
  17. package/dist/avow-api.js +2 -0
  18. package/dist/avow-api.js.map +1 -0
  19. package/dist/contest.d.ts +135 -0
  20. package/dist/contest.d.ts.map +1 -0
  21. package/dist/contest.js +186 -0
  22. package/dist/contest.js.map +1 -0
  23. package/dist/http.d.ts +161 -0
  24. package/dist/http.d.ts.map +1 -0
  25. package/dist/http.js +311 -0
  26. package/dist/http.js.map +1 -0
  27. package/dist/index.d.ts +38 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +38 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/job/accept.d.ts +84 -0
  32. package/dist/job/accept.d.ts.map +1 -0
  33. package/dist/job/accept.js +136 -0
  34. package/dist/job/accept.js.map +1 -0
  35. package/dist/job/customer.d.ts +43 -0
  36. package/dist/job/customer.d.ts.map +1 -0
  37. package/dist/job/customer.js +83 -0
  38. package/dist/job/customer.js.map +1 -0
  39. package/dist/job/quote.d.ts +34 -0
  40. package/dist/job/quote.d.ts.map +1 -0
  41. package/dist/job/quote.js +37 -0
  42. package/dist/job/quote.js.map +1 -0
  43. package/dist/lock.d.ts +269 -0
  44. package/dist/lock.d.ts.map +1 -0
  45. package/dist/lock.js +283 -0
  46. package/dist/lock.js.map +1 -0
  47. package/dist/moderato.d.ts +27 -0
  48. package/dist/moderato.d.ts.map +1 -0
  49. package/dist/moderato.js +34 -0
  50. package/dist/moderato.js.map +1 -0
  51. package/dist/node/cli.d.ts +3 -0
  52. package/dist/node/cli.d.ts.map +1 -0
  53. package/dist/node/cli.js +346 -0
  54. package/dist/node/cli.js.map +1 -0
  55. package/dist/node/connect.d.ts +15 -0
  56. package/dist/node/connect.d.ts.map +1 -0
  57. package/dist/node/connect.js +91 -0
  58. package/dist/node/connect.js.map +1 -0
  59. package/dist/node/eval.d.ts +3 -0
  60. package/dist/node/eval.d.ts.map +1 -0
  61. package/dist/node/eval.js +67 -0
  62. package/dist/node/eval.js.map +1 -0
  63. package/dist/node/first-run.d.ts +50 -0
  64. package/dist/node/first-run.d.ts.map +1 -0
  65. package/dist/node/first-run.js +149 -0
  66. package/dist/node/first-run.js.map +1 -0
  67. package/dist/node/job.d.ts +50 -0
  68. package/dist/node/job.d.ts.map +1 -0
  69. package/dist/node/job.js +176 -0
  70. package/dist/node/job.js.map +1 -0
  71. package/dist/node/mailbox.d.ts +19 -0
  72. package/dist/node/mailbox.d.ts.map +1 -0
  73. package/dist/node/mailbox.js +81 -0
  74. package/dist/node/mailbox.js.map +1 -0
  75. package/dist/node/mcp.d.ts +74 -0
  76. package/dist/node/mcp.d.ts.map +1 -0
  77. package/dist/node/mcp.js +367 -0
  78. package/dist/node/mcp.js.map +1 -0
  79. package/dist/node/platform.d.ts +35 -0
  80. package/dist/node/platform.d.ts.map +1 -0
  81. package/dist/node/platform.js +102 -0
  82. package/dist/node/platform.js.map +1 -0
  83. package/dist/node/runner-session.d.ts +41 -0
  84. package/dist/node/runner-session.d.ts.map +1 -0
  85. package/dist/node/runner-session.js +100 -0
  86. package/dist/node/runner-session.js.map +1 -0
  87. package/dist/node/runner.d.ts +63 -0
  88. package/dist/node/runner.d.ts.map +1 -0
  89. package/dist/node/runner.js +341 -0
  90. package/dist/node/runner.js.map +1 -0
  91. package/dist/node/service-child.d.ts +2 -0
  92. package/dist/node/service-child.d.ts.map +1 -0
  93. package/dist/node/service-child.js +40 -0
  94. package/dist/node/service-child.js.map +1 -0
  95. package/dist/node/service-excerpt.d.ts +21 -0
  96. package/dist/node/service-excerpt.d.ts.map +1 -0
  97. package/dist/node/service-excerpt.js +32 -0
  98. package/dist/node/service-excerpt.js.map +1 -0
  99. package/dist/node/service-process.d.ts +12 -0
  100. package/dist/node/service-process.d.ts.map +1 -0
  101. package/dist/node/service-process.js +132 -0
  102. package/dist/node/service-process.js.map +1 -0
  103. package/dist/node/session-input.d.ts +12 -0
  104. package/dist/node/session-input.d.ts.map +1 -0
  105. package/dist/node/session-input.js +42 -0
  106. package/dist/node/session-input.js.map +1 -0
  107. package/dist/node/session-view.d.ts +20 -0
  108. package/dist/node/session-view.d.ts.map +1 -0
  109. package/dist/node/session-view.js +198 -0
  110. package/dist/node/session-view.js.map +1 -0
  111. package/dist/node-agent.d.ts +2 -0
  112. package/dist/node-agent.d.ts.map +1 -0
  113. package/dist/node-agent.js +6 -0
  114. package/dist/node-agent.js.map +1 -0
  115. package/dist/node.d.ts +2 -0
  116. package/dist/node.d.ts.map +1 -0
  117. package/dist/node.js +9 -0
  118. package/dist/node.js.map +1 -0
  119. package/dist/sandbox/agent.d.ts +187 -0
  120. package/dist/sandbox/agent.d.ts.map +1 -0
  121. package/dist/sandbox/agent.js +468 -0
  122. package/dist/sandbox/agent.js.map +1 -0
  123. package/dist/sandbox/business-store.d.ts +19 -0
  124. package/dist/sandbox/business-store.d.ts.map +1 -0
  125. package/dist/sandbox/business-store.js +19 -0
  126. package/dist/sandbox/business-store.js.map +1 -0
  127. package/dist/sandbox/business.d.ts +70 -0
  128. package/dist/sandbox/business.d.ts.map +1 -0
  129. package/dist/sandbox/business.js +115 -0
  130. package/dist/sandbox/business.js.map +1 -0
  131. package/dist/sandbox/connect.d.ts +64 -0
  132. package/dist/sandbox/connect.d.ts.map +1 -0
  133. package/dist/sandbox/connect.js +182 -0
  134. package/dist/sandbox/connect.js.map +1 -0
  135. package/dist/sandbox/deployment.d.ts +14 -0
  136. package/dist/sandbox/deployment.d.ts.map +1 -0
  137. package/dist/sandbox/deployment.js +38 -0
  138. package/dist/sandbox/deployment.js.map +1 -0
  139. package/dist/sandbox/keys.d.ts +45 -0
  140. package/dist/sandbox/keys.d.ts.map +1 -0
  141. package/dist/sandbox/keys.js +132 -0
  142. package/dist/sandbox/keys.js.map +1 -0
  143. package/dist/sandbox/mailbox.d.ts +90 -0
  144. package/dist/sandbox/mailbox.d.ts.map +1 -0
  145. package/dist/sandbox/mailbox.js +400 -0
  146. package/dist/sandbox/mailbox.js.map +1 -0
  147. package/dist/sandbox/mandate.d.ts +84 -0
  148. package/dist/sandbox/mandate.d.ts.map +1 -0
  149. package/dist/sandbox/mandate.js +107 -0
  150. package/dist/sandbox/mandate.js.map +1 -0
  151. package/dist/sandbox/namespace.d.ts +16 -0
  152. package/dist/sandbox/namespace.d.ts.map +1 -0
  153. package/dist/sandbox/namespace.js +16 -0
  154. package/dist/sandbox/namespace.js.map +1 -0
  155. package/dist/sandbox/session.d.ts +60 -0
  156. package/dist/sandbox/session.d.ts.map +1 -0
  157. package/dist/sandbox/session.js +94 -0
  158. package/dist/sandbox/session.js.map +1 -0
  159. package/dist/sandbox/setup.d.ts +136 -0
  160. package/dist/sandbox/setup.d.ts.map +1 -0
  161. package/dist/sandbox/setup.js +490 -0
  162. package/dist/sandbox/setup.js.map +1 -0
  163. package/dist/sandbox/store.d.ts +69 -0
  164. package/dist/sandbox/store.d.ts.map +1 -0
  165. package/dist/sandbox/store.js +115 -0
  166. package/dist/sandbox/store.js.map +1 -0
  167. package/dist/sandbox/supplier-key.d.ts +73 -0
  168. package/dist/sandbox/supplier-key.d.ts.map +1 -0
  169. package/dist/sandbox/supplier-key.js +180 -0
  170. package/dist/sandbox/supplier-key.js.map +1 -0
  171. package/dist/sandbox/suppliers.d.ts +7 -0
  172. package/dist/sandbox/suppliers.d.ts.map +1 -0
  173. package/dist/sandbox/suppliers.js +29 -0
  174. package/dist/sandbox/suppliers.js.map +1 -0
  175. package/dist/sandbox/terms.d.ts +32 -0
  176. package/dist/sandbox/terms.d.ts.map +1 -0
  177. package/dist/sandbox/terms.js +58 -0
  178. package/dist/sandbox/terms.js.map +1 -0
  179. package/dist/sandbox/vault.d.ts +24 -0
  180. package/dist/sandbox/vault.d.ts.map +1 -0
  181. package/dist/sandbox/vault.js +54 -0
  182. package/dist/sandbox/vault.js.map +1 -0
  183. package/dist/send.d.ts +122 -0
  184. package/dist/send.d.ts.map +1 -0
  185. package/dist/send.js +328 -0
  186. package/dist/send.js.map +1 -0
  187. package/dist/service-entry.d.ts +6 -0
  188. package/dist/service-entry.d.ts.map +1 -0
  189. package/dist/service-entry.js +6 -0
  190. package/dist/service-entry.js.map +1 -0
  191. package/dist/session/anthropic.d.ts +17 -0
  192. package/dist/session/anthropic.d.ts.map +1 -0
  193. package/dist/session/anthropic.js +215 -0
  194. package/dist/session/anthropic.js.map +1 -0
  195. package/dist/session/charge.d.ts +13 -0
  196. package/dist/session/charge.d.ts.map +1 -0
  197. package/dist/session/charge.js +33 -0
  198. package/dist/session/charge.js.map +1 -0
  199. package/dist/session/data.d.ts +8 -0
  200. package/dist/session/data.d.ts.map +1 -0
  201. package/dist/session/data.js +20 -0
  202. package/dist/session/data.js.map +1 -0
  203. package/dist/session/eval.d.ts +41 -0
  204. package/dist/session/eval.d.ts.map +1 -0
  205. package/dist/session/eval.js +281 -0
  206. package/dist/session/eval.js.map +1 -0
  207. package/dist/session/executor.d.ts +80 -0
  208. package/dist/session/executor.d.ts.map +1 -0
  209. package/dist/session/executor.js +381 -0
  210. package/dist/session/executor.js.map +1 -0
  211. package/dist/session/fixture-world.d.ts +29 -0
  212. package/dist/session/fixture-world.d.ts.map +1 -0
  213. package/dist/session/fixture-world.js +708 -0
  214. package/dist/session/fixture-world.js.map +1 -0
  215. package/dist/session/live-world.d.ts +22 -0
  216. package/dist/session/live-world.d.ts.map +1 -0
  217. package/dist/session/live-world.js +329 -0
  218. package/dist/session/live-world.js.map +1 -0
  219. package/dist/session/ollama.d.ts +29 -0
  220. package/dist/session/ollama.d.ts.map +1 -0
  221. package/dist/session/ollama.js +177 -0
  222. package/dist/session/ollama.js.map +1 -0
  223. package/dist/session/provider.d.ts +79 -0
  224. package/dist/session/provider.d.ts.map +1 -0
  225. package/dist/session/provider.js +19 -0
  226. package/dist/session/provider.js.map +1 -0
  227. package/dist/session/scripted.d.ts +45 -0
  228. package/dist/session/scripted.d.ts.map +1 -0
  229. package/dist/session/scripted.js +236 -0
  230. package/dist/session/scripted.js.map +1 -0
  231. package/dist/session/selection.d.ts +37 -0
  232. package/dist/session/selection.d.ts.map +1 -0
  233. package/dist/session/selection.js +104 -0
  234. package/dist/session/selection.js.map +1 -0
  235. package/dist/session/service-check.d.ts +48 -0
  236. package/dist/session/service-check.d.ts.map +1 -0
  237. package/dist/session/service-check.js +86 -0
  238. package/dist/session/service-check.js.map +1 -0
  239. package/dist/session/service.d.ts +128 -0
  240. package/dist/session/service.d.ts.map +1 -0
  241. package/dist/session/service.js +150 -0
  242. package/dist/session/service.js.map +1 -0
  243. package/dist/session/session.d.ts +95 -0
  244. package/dist/session/session.d.ts.map +1 -0
  245. package/dist/session/session.js +312 -0
  246. package/dist/session/session.js.map +1 -0
  247. package/dist/session/toolbox.d.ts +69 -0
  248. package/dist/session/toolbox.d.ts.map +1 -0
  249. package/dist/session/toolbox.js +391 -0
  250. package/dist/session/toolbox.js.map +1 -0
  251. package/dist/session/tools.d.ts +45 -0
  252. package/dist/session/tools.d.ts.map +1 -0
  253. package/dist/session/tools.js +137 -0
  254. package/dist/session/tools.js.map +1 -0
  255. package/dist/session/world.d.ts +188 -0
  256. package/dist/session/world.d.ts.map +1 -0
  257. package/dist/session/world.js +2 -0
  258. package/dist/session/world.js.map +1 -0
  259. package/dist/sign.d.ts +19 -0
  260. package/dist/sign.d.ts.map +1 -0
  261. package/dist/sign.js +33 -0
  262. package/dist/sign.js.map +1 -0
  263. package/dist/supplier.d.ts +41 -0
  264. package/dist/supplier.d.ts.map +1 -0
  265. package/dist/supplier.js +57 -0
  266. package/dist/supplier.js.map +1 -0
  267. package/package.json +56 -3
@@ -0,0 +1,187 @@
1
+ import { type AvowDomain, type CommitmentReference, type GpuReservationTerms, type Mandate, type RailState, type ReasonCode, type RefusalAmounts, type RefusalLayer, type RequestKey, type SandboxDeployment, type SandboxTool, type SessionEvent, type Signed } from '@avow-finance/spec';
2
+ import { type Address, type Hex } from 'viem';
3
+ import { type Commitment } from '../agent.js';
4
+ import type { SandboxClient } from './business.js';
5
+ import { type SandboxStore, type SandboxSupplier } from './store.js';
6
+ import { type SandboxResource } from './terms.js';
7
+ /**
8
+ * A booking refused before any money moved, by the SDK, Avow, Avow's relay, the lock or the
9
+ * account's keychain, or a reserve that never landed for no reason anyone gave. Its message is the sentence `refusalSentence` writes from the reason code,
10
+ * the layer and the amounts.
11
+ */
12
+ export declare class Refusal extends Error {
13
+ readonly code: ReasonCode;
14
+ readonly layer: RefusalLayer;
15
+ /** What the booking needed, the authority left and the key's daily limit, in micros. */
16
+ readonly amounts: RefusalAmounts;
17
+ /** Avow's decision id, when Avow decided. */
18
+ readonly decisionId: string | null;
19
+ constructor(r: {
20
+ code: ReasonCode;
21
+ layer: RefusalLayer;
22
+ amounts: RefusalAmounts;
23
+ decisionId?: string | null;
24
+ }, options?: {
25
+ cause?: unknown;
26
+ });
27
+ }
28
+ /** A session a runner opened, and which run of the agent this is. */
29
+ export interface SandboxSession {
30
+ id: string;
31
+ run: number;
32
+ }
33
+ /**
34
+ * What the platform gives the sandbox by default. Importing the SDK in Node sets a store in the
35
+ * `.avow` folder, and the session its runner passes to the agent's process.
36
+ */
37
+ export interface SandboxPlatform {
38
+ store?: () => SandboxStore;
39
+ session?: () => SandboxSession | null;
40
+ }
41
+ /** Sets what the sandbox uses when it isn't told otherwise. */
42
+ export declare function setSandboxPlatform(next: SandboxPlatform): void;
43
+ /** The platform's store, when it has one. */
44
+ export declare const platformStore: () => SandboxStore | undefined;
45
+ /** The session the platform passes, when there is one. */
46
+ export declare const platformSession: () => SandboxSession | null;
47
+ export interface SandboxAgentOptions {
48
+ /** Where the business keeps the agent's key and mandate. The `.avow` folder in Node, by default. */
49
+ store?: SandboxStore;
50
+ /** The sandbox's screen, which publishes the deployment's facts and checks shared links. */
51
+ screenUrl?: string;
52
+ /** The deployment's facts, read from the screen when left out. */
53
+ deployment?: SandboxDeployment;
54
+ /** The session to report to, or null for none. In Node, the one the runner opened. */
55
+ session?: SandboxSession | null;
56
+ /** Who drives the agent, the developer's file by default, or a model through the MCP server. */
57
+ source?: 'script' | 'mcp';
58
+ /** The MCP tool this run answers, when a model called one. */
59
+ tool?: SandboxTool | null;
60
+ /** Where warnings go, a line at a time. `console.log` by default. */
61
+ log?: (line: string) => void;
62
+ fetch?: typeof fetch;
63
+ }
64
+ /** One booking: the supplier's id, what it's for, and the reserve backing it, in dollars. */
65
+ export interface SandboxBooking {
66
+ supplier: string;
67
+ resource: SandboxResource;
68
+ reserve: number;
69
+ }
70
+ /** One check the agent's machine made, and why it failed if it did. */
71
+ export interface SandboxCheck {
72
+ name: string;
73
+ passed: boolean;
74
+ reason: ReasonCode | null;
75
+ }
76
+ /** A commitment the agent made, with its reserve funded in the business's lock. */
77
+ export interface SandboxCommitment {
78
+ /** Where the backing sits and the terms hash, which anyone can check against the lock. */
79
+ readonly reference: CommitmentReference;
80
+ /** A link anyone can open to check the commitment, which carries the reference. */
81
+ readonly link: string;
82
+ /** The reserve, in dollars. */
83
+ readonly amount: number;
84
+ /** The authority the agent has left after this booking, in dollars. */
85
+ readonly left: number;
86
+ /** Everything the SDK knows about the commitment, its salt included. Keep the salt private. */
87
+ readonly commitment: Commitment;
88
+ /**
89
+ * Checks the commitment on this machine with the open verifier, every check the buyer's side can
90
+ * make. Avow's approval has to name this commitment, the supplier, the lock's token, the terms
91
+ * and the mandate's caps and hash. The lock has to be one the trusted factory made, holding the
92
+ * commitment under the terms hash, enforcing what the terms map to, under the approval checked.
93
+ * The agent's key has to be on the account, bound to the mandate's hash.
94
+ */
95
+ verify(): Promise<SandboxCheck[]>;
96
+ /**
97
+ * Waits for the supplier to accept on the lock. It resolves true once the acceptance lands, and
98
+ * false once the acceptance deadline passes without one, after which the reserve goes back.
99
+ */
100
+ accepted(): Promise<boolean>;
101
+ }
102
+ /** A commitment the business's agent made, as the lock holds it now. */
103
+ export interface SandboxCommitmentRecord {
104
+ reference: CommitmentReference;
105
+ link: string;
106
+ /** The reserve, in dollars. */
107
+ amount: number;
108
+ supplier: string;
109
+ /** Unix seconds. */
110
+ madeAt: bigint;
111
+ /** The lock's state for it now, or `unread` when the chain didn't answer. */
112
+ state: RailState | 'unread';
113
+ /** Whether it was made under the agent's current mandate, or under an earlier authority. */
114
+ current: boolean;
115
+ /** When the lock gives back what it still holds, in unix seconds, once it's read. */
116
+ releaseDate: bigint | null;
117
+ }
118
+ /** An agent with authority to commit a sandbox business, within the mandate it holds. */
119
+ export interface SandboxAgent {
120
+ /** The most the agent can hold in bookings at once, in dollars. */
121
+ readonly authority: number;
122
+ /** The most the agent's key can move in a day, in dollars, or null when it has no daily limit. */
123
+ readonly dailyLimit: number | null;
124
+ readonly suppliers: readonly SandboxSupplier[];
125
+ readonly business: {
126
+ account: Address;
127
+ lock: Address;
128
+ businessId: string;
129
+ };
130
+ /** The mandate the business's root key signed for the agent. */
131
+ readonly mandate: Signed<Mandate>;
132
+ readonly mandateHash: Hex;
133
+ /** The authority the agent has left, in dollars, as the lock counts it. */
134
+ left(): Promise<number>;
135
+ /** What the agent's key can still move today, in dollars, as the account's keychain counts it. */
136
+ dailyLeft(): Promise<number | null>;
137
+ /** Every commitment the business's agents made, each with its state on the lock now. */
138
+ commitments(): Promise<SandboxCommitmentRecord[]>;
139
+ /**
140
+ * Books with one of the agent's suppliers. It resolves with the commitment once the reserve is
141
+ * funded, and throws a `Refusal` when the booking is refused before any money moves.
142
+ */
143
+ book(booking: SandboxBooking): Promise<SandboxCommitment>;
144
+ /**
145
+ * Books with one of the agent's suppliers on terms already written, such as an offer's, with the
146
+ * reserve those terms set. It checks, refuses and funds as `book` does.
147
+ */
148
+ bookTerms(booking: {
149
+ supplier: string;
150
+ terms: GpuReservationTerms;
151
+ }): Promise<SandboxCommitment>;
152
+ }
153
+ /** Posts a business's events to its session in order, never holding up the caller. */
154
+ export declare function sessionReporter(m: {
155
+ session: SandboxSession;
156
+ key: RequestKey;
157
+ domain: AvowDomain;
158
+ apiUrl: string;
159
+ fetch: typeof fetch;
160
+ log: (line: string) => void;
161
+ }): (event: SessionEvent) => void;
162
+ /** Checks a session a caller passed. */
163
+ export declare function checkSession(session: SandboxSession | null): SandboxSession | null;
164
+ /** The daily limit the root key set on the agent's key for the lock's token, in micros. */
165
+ export declare const dailyLimitOf: (mandate: Mandate, token: Address) => bigint | null;
166
+ /** What the agent's key can still move today, in micros, as the account's keychain counts it. */
167
+ export declare function keyLeftToday(client: SandboxClient, account: Address, key: Address, token: Address): Promise<bigint>;
168
+ /**
169
+ * The agent of a sandbox business, acting with only its own key under the mandate its business
170
+ * signed. It reads the agent's item from the store and never the business's key, and it has no
171
+ * call that signs a mandate, enrolls a key or changes the authority. Run `npm start` first, which
172
+ * sets the business up and asks before it signs the agent's mandate.
173
+ */
174
+ export declare function sandboxAgent(options?: SandboxAgentOptions): Promise<SandboxAgent>;
175
+ /**
176
+ * Who refused a reserve Avow had approved. The account's keychain refuses a key past its daily
177
+ * limit when the transaction is prepared, and Avow's relay refuses with its own reason, or with
178
+ * none when it can't be reached or hands back other bytes, which is the relay being unavailable. A
179
+ * transaction that landed and reverted, or that reverted while the node prepared it, is the lock's
180
+ * refusal. Anything else, such as one that expired in no block or that the node never took, is
181
+ * unknown.
182
+ */
183
+ export declare function fundingRefusal(error: unknown): {
184
+ code: ReasonCode;
185
+ layer: RefusalLayer;
186
+ };
187
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/sandbox/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,468 @@
1
+ import { approvalCaps, approvalDigest, approvalMandateProblem, approvalPartiesProblem, approvalTermsProblem, approvalTokenProblem, checkEnvelope, isSessionId, lockTerms, refusalSentence, TESTNET_DEMO_PROFILE, } from '@avow-finance/spec';
2
+ import { readAgentKey, readBacking, tempoChainReader, verifyCommitmentReference, verifyCommitmentTerms, } from '@avow-finance/verifier';
3
+ import { isAddressEqual } from 'viem';
4
+ import { Abis, Account, Addresses } from 'viem/tempo';
5
+ import { BookingError, createAgent } from '../agent.js';
6
+ import { agentRequestKey, httpAvowApi, relayReason } from '../http.js';
7
+ import { readOpenReserves } from '../lock.js';
8
+ import { moderatoClient, moderatoUsdToken } from '../moderato.js';
9
+ import { landedReverted, sendErrorIn, sendSponsored } from '../send.js';
10
+ import { SupplierDeclined } from '../supplier.js';
11
+ import { loadSandboxDeployment, madeOn, trustedFactory } from './deployment.js';
12
+ import { SANDBOX_SCREEN_URL, sessionRelay, verifyUrl } from './session.js';
13
+ import { addCommitment, loadAgentItem, loadCommitments, } from './store.js';
14
+ import { connectSupplier } from './suppliers.js';
15
+ import { micros, sandboxTerms, toDollars } from './terms.js';
16
+ /**
17
+ * A booking refused before any money moved, by the SDK, Avow, Avow's relay, the lock or the
18
+ * account's keychain, or a reserve that never landed for no reason anyone gave. Its message is the sentence `refusalSentence` writes from the reason code,
19
+ * the layer and the amounts.
20
+ */
21
+ export class Refusal extends Error {
22
+ code;
23
+ layer;
24
+ /** What the booking needed, the authority left and the key's daily limit, in micros. */
25
+ amounts;
26
+ /** Avow's decision id, when Avow decided. */
27
+ decisionId;
28
+ constructor(r, options) {
29
+ super(refusalSentence(r), options);
30
+ this.name = 'Refusal';
31
+ this.code = r.code;
32
+ this.layer = r.layer;
33
+ this.amounts = r.amounts;
34
+ this.decisionId = r.decisionId ?? null;
35
+ }
36
+ }
37
+ let platform = {};
38
+ /** Sets what the sandbox uses when it isn't told otherwise. */
39
+ export function setSandboxPlatform(next) {
40
+ platform = next;
41
+ }
42
+ /** The platform's store, when it has one. */
43
+ export const platformStore = () => platform.store?.();
44
+ /** The session the platform passes, when there is one. */
45
+ export const platformSession = () => platform.session?.() ?? null;
46
+ const DAY = 86400n;
47
+ const systemClock = () => BigInt(Math.floor(Date.now() / 1000));
48
+ const pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
49
+ const describe = (e) => (e instanceof Error ? e.message : String(e)).slice(0, 300);
50
+ /** Posts a business's events to its session in order, never holding up the caller. */
51
+ export function sessionReporter(m) {
52
+ const relay = sessionRelay({
53
+ baseUrl: m.apiUrl,
54
+ sessionId: m.session.id,
55
+ key: m.key,
56
+ domain: m.domain,
57
+ fetch: m.fetch,
58
+ retryFor: 15n,
59
+ attemptTimeout: 10_000,
60
+ });
61
+ let queue = Promise.resolve();
62
+ let warned = false;
63
+ return (event) => {
64
+ queue = queue.then(() => relay.post(event).then(() => { }, (error) => {
65
+ if (warned)
66
+ return;
67
+ warned = true;
68
+ m.log(`The screen didn't get this run's events: ${describe(error)}`);
69
+ }), () => { });
70
+ };
71
+ }
72
+ /** Checks a session a caller passed. */
73
+ export function checkSession(session) {
74
+ if (session && (!isSessionId(session.id) || !Number.isInteger(session.run) || session.run < 1)) {
75
+ throw new RangeError('The session needs a session id and a run number from 1 up');
76
+ }
77
+ return session;
78
+ }
79
+ /** The daily limit the root key set on the agent's key for the lock's token, in micros. */
80
+ export const dailyLimitOf = (mandate, token) => mandate.paymentLimits.find((l) => isAddressEqual(l.token, token) && l.period === DAY)?.amount ??
81
+ null;
82
+ /** What the agent's key can still move today, in micros, as the account's keychain counts it. */
83
+ export async function keyLeftToday(client, account, key, token) {
84
+ const [remaining] = await client.readContract({
85
+ address: Addresses.accountKeychain,
86
+ abi: Abis.accountKeychain,
87
+ functionName: 'getRemainingLimitWithPeriod',
88
+ args: [account, key, token],
89
+ });
90
+ return remaining;
91
+ }
92
+ /**
93
+ * The agent of a sandbox business, acting with only its own key under the mandate its business
94
+ * signed. It reads the agent's item from the store and never the business's key, and it has no
95
+ * call that signs a mandate, enrolls a key or changes the authority. Run `npm start` first, which
96
+ * sets the business up and asks before it signs the agent's mandate.
97
+ */
98
+ export async function sandboxAgent(options = {}) {
99
+ const log = options.log ?? ((line) => console.log(line));
100
+ const send = options.fetch ?? ((input, init) => fetch(input, init));
101
+ const store = options.store ?? platform.store?.();
102
+ if (!store) {
103
+ throw new Error('The agent needs the folder its business set up. In Node that is the .avow folder, and anywhere else pass a store.');
104
+ }
105
+ const item = await loadAgentItem(store);
106
+ if (!item) {
107
+ throw new Error("This folder has no agent yet. Run npm start, which sets up your business and asks you before it signs your agent's mandate.");
108
+ }
109
+ const screenUrl = options.screenUrl ?? SANDBOX_SCREEN_URL;
110
+ const deployment = options.deployment ?? (await loadSandboxDeployment(screenUrl, send));
111
+ if (!madeOn(item.business, deployment)) {
112
+ throw new Error('The sandbox runs a new deployment now. Run npm start to set your business up on it.');
113
+ }
114
+ const client = moderatoClient(deployment.rpcUrl);
115
+ const agentKey = Account.fromSecp256k1(item.agentKey, {
116
+ access: item.business.account,
117
+ });
118
+ if (!isAddressEqual(agentKey.accessKeyAddress, item.mandate.message.agentKey)) {
119
+ throw new Error("The agent's key isn't the one its mandate names");
120
+ }
121
+ const domain = { chainId: deployment.chainId, verifyingContract: item.business.lock };
122
+ const session = checkSession(options.session !== undefined ? options.session : (platform.session?.() ?? null));
123
+ const report = session
124
+ ? sessionReporter({
125
+ session,
126
+ key: agentRequestKey(agentKey),
127
+ domain,
128
+ apiUrl: deployment.apiUrl,
129
+ fetch: send,
130
+ log,
131
+ })
132
+ : () => { };
133
+ const run = session?.run ?? 0;
134
+ const source = options.source ?? 'script';
135
+ report({ type: 'run_started', run, source, tool: options.tool ?? null });
136
+ return booker({
137
+ deployment,
138
+ client,
139
+ store,
140
+ agentKey,
141
+ mandate: item.mandate,
142
+ mandateHash: item.mandateHash,
143
+ keyAuthorizedIn: item.keyAuthorizedIn,
144
+ business: {
145
+ account: item.business.account,
146
+ lock: item.business.lock,
147
+ businessId: item.business.businessId,
148
+ },
149
+ suppliers: item.suppliers,
150
+ screenUrl,
151
+ run,
152
+ source,
153
+ report,
154
+ send,
155
+ });
156
+ }
157
+ /** The agent's side of booking, under the mandate it holds. */
158
+ function booker(m) {
159
+ const { deployment, client, mandate, run, source, report, send } = m;
160
+ const { lock, account } = m.business;
161
+ const domain = { chainId: deployment.chainId, verifyingContract: lock };
162
+ const cap = mandate.message.capOpenReserves;
163
+ const dailyLimit = dailyLimitOf(mandate.message, deployment.token);
164
+ const token = moderatoUsdToken(deployment.token);
165
+ /** The authority left, read from the lock, which Avow's reserve check reads too. */
166
+ async function leftNow() {
167
+ for (let i = 1;; i++) {
168
+ try {
169
+ const open = await readOpenReserves(client, lock, m.mandateHash);
170
+ return open >= cap ? 0n : cap - open;
171
+ }
172
+ catch (error) {
173
+ if (i >= 3)
174
+ throw error;
175
+ await pause(1000);
176
+ }
177
+ }
178
+ }
179
+ const dailyLeftNow = () => dailyLimit === null
180
+ ? Promise.resolve(null)
181
+ : keyLeftToday(client, account, m.agentKey.accessKeyAddress, deployment.token);
182
+ async function refusal(r, extra) {
183
+ const left = await leftNow().catch(() => r.leftBefore);
184
+ const dailyLeft = await dailyLeftNow().catch(() => null);
185
+ const amounts = {
186
+ needed: r.needed,
187
+ left,
188
+ authority: cap,
189
+ capPerCommitment: mandate.message.capPerCommitment,
190
+ dailyLimit,
191
+ dailyLeft,
192
+ };
193
+ report({ type: 'refused', run, source, code: r.code, layer: r.layer, amounts });
194
+ return new Refusal({ code: r.code, layer: r.layer, amounts, decisionId: extra.decisionId ?? null }, extra.cause === undefined ? undefined : { cause: extra.cause });
195
+ }
196
+ return {
197
+ authority: toDollars(cap),
198
+ dailyLimit: dailyLimit === null ? null : toDollars(dailyLimit),
199
+ suppliers: m.suppliers,
200
+ business: m.business,
201
+ mandate,
202
+ mandateHash: m.mandateHash,
203
+ left: async () => toDollars(await leftNow()),
204
+ dailyLeft: async () => {
205
+ const left = await dailyLeftNow();
206
+ return left === null ? null : toDollars(left);
207
+ },
208
+ async commitments() {
209
+ const stored = await loadCommitments(m.store);
210
+ return Promise.all(stored.map(async (c) => {
211
+ const held = await readBacking(client, c.reference.lock, c.reference.commitmentId, c.reference.side).catch(() => undefined);
212
+ return {
213
+ reference: c.reference,
214
+ link: verifyUrl(c.reference, m.screenUrl),
215
+ amount: toDollars(c.amount),
216
+ supplier: c.supplier,
217
+ madeAt: c.madeAt,
218
+ state: held === undefined ? 'unread' : (held?.state ?? 'none'),
219
+ current: c.mandateHash.toLowerCase() === m.mandateHash.toLowerCase(),
220
+ releaseDate: held ? held.releaseDate : null,
221
+ };
222
+ }));
223
+ },
224
+ book(b) {
225
+ const reserve = micros(b.reserve, 'reserve');
226
+ const terms = sandboxTerms({ deployment, resource: b.resource, reserve, now: systemClock() });
227
+ return bookOn(b.supplier, terms, reserve);
228
+ },
229
+ bookTerms(b) {
230
+ return bookOn(b.supplier, b.terms, b.terms.backing.amount);
231
+ },
232
+ };
233
+ async function bookOn(supplierId, terms, reserve) {
234
+ {
235
+ const b = { supplier: supplierId };
236
+ const leftBefore = await leftNow();
237
+ const supplier = m.suppliers.find((s) => s.id === b.supplier);
238
+ // The mandate names its suppliers, so the SDK refuses any other before anyone signs.
239
+ if (!supplier || !mandate.message.suppliers.includes(b.supplier)) {
240
+ throw await refusal({ code: 'mandate.supplier_not_allowed', layer: 'sdk', needed: reserve, leftBefore }, {});
241
+ }
242
+ const connection = await connectSupplier(supplier, send);
243
+ const avow = httpAvowApi({
244
+ baseUrl: deployment.apiUrl,
245
+ key: agentRequestKey(m.agentKey),
246
+ domain,
247
+ retryFor: 120n,
248
+ fetch: send,
249
+ });
250
+ // Avow's own refusal, kept so the refusal says which layer made it.
251
+ let avowRefused = null;
252
+ const watched = {
253
+ ...avow,
254
+ approveReserve: async (request) => {
255
+ const answer = await avow.approveReserve(request);
256
+ if (!answer.ok)
257
+ avowRefused = answer.reason;
258
+ return answer;
259
+ },
260
+ };
261
+ const agent = createAgent({
262
+ client,
263
+ key: m.agentKey,
264
+ mandate,
265
+ token,
266
+ profile: TESTNET_DEMO_PROFILE,
267
+ avow: watched,
268
+ send: async (calls) => {
269
+ const receipt = await sendSponsored({
270
+ client,
271
+ account: m.agentKey,
272
+ calls,
273
+ sponsor: (transaction) => avow.sponsor(transaction),
274
+ });
275
+ return { transactionHash: receipt.transactionHash, blockNumber: receipt.blockNumber };
276
+ },
277
+ });
278
+ let booked;
279
+ try {
280
+ booked = await agent.book({ supplier: connection, terms, category: 'compute' });
281
+ }
282
+ catch (error) {
283
+ if (error instanceof SupplierDeclined) {
284
+ throw await refusal({ code: 'supplier.declined', layer: 'supplier', needed: reserve, leftBefore }, { cause: error });
285
+ }
286
+ if (error instanceof BookingError && error.outcome === 'failed') {
287
+ throw await refusal({ ...fundingRefusal(error), needed: reserve, leftBefore }, { cause: error });
288
+ }
289
+ throw error;
290
+ }
291
+ if (!booked.ok) {
292
+ const layer = avowRefused === booked.reason ? 'avow' : 'sdk';
293
+ throw await refusal({ code: booked.reason, layer, needed: reserve, leftBefore }, { decisionId: booked.decisionId ?? null });
294
+ }
295
+ const commitment = booked.commitment;
296
+ const reference = {
297
+ kind: 'commitment',
298
+ chainId: deployment.chainId,
299
+ lock,
300
+ commitmentId: commitment.commitmentId,
301
+ side: 'buyer',
302
+ termsHash: commitment.termsHash,
303
+ };
304
+ await addCommitment(m.store, {
305
+ reference,
306
+ amount: reserve,
307
+ supplier: supplier.id,
308
+ mandateHash: m.mandateHash,
309
+ madeAt: systemClock(),
310
+ });
311
+ const left = await leftNow().catch(() => (leftBefore > reserve ? leftBefore - reserve : 0n));
312
+ report({ type: 'committed', run, source, reference, amount: reserve });
313
+ let acceptance = null;
314
+ return {
315
+ reference,
316
+ link: verifyUrl(reference, m.screenUrl),
317
+ amount: toDollars(reserve),
318
+ left: toDollars(left),
319
+ commitment,
320
+ verify: () => verifyCommitment({
321
+ client,
322
+ deployment,
323
+ domain,
324
+ commitment,
325
+ reference,
326
+ mandate: mandate.message,
327
+ mandateHash: m.mandateHash,
328
+ account,
329
+ agentKey: m.agentKey.accessKeyAddress,
330
+ keyAuthorizedIn: m.keyAuthorizedIn,
331
+ }),
332
+ accepted() {
333
+ acceptance ??= waitForAcceptance(client, lock, commitment).then((accepted) => {
334
+ if (accepted)
335
+ report({ type: 'accepted', run, source, reference });
336
+ return accepted;
337
+ });
338
+ return acceptance;
339
+ },
340
+ };
341
+ }
342
+ }
343
+ }
344
+ /** Whether the account's keychain refused somewhere in an error's causes, over the daily limit. */
345
+ function keychainRefused(error) {
346
+ let e = error;
347
+ for (let i = 0; i < 6 && e instanceof Error; i++) {
348
+ if (/SpendingLimitExceeded/.test(e.message))
349
+ return true;
350
+ e = e.cause;
351
+ }
352
+ return false;
353
+ }
354
+ /**
355
+ * Who refused a reserve Avow had approved. The account's keychain refuses a key past its daily
356
+ * limit when the transaction is prepared, and Avow's relay refuses with its own reason, or with
357
+ * none when it can't be reached or hands back other bytes, which is the relay being unavailable. A
358
+ * transaction that landed and reverted, or that reverted while the node prepared it, is the lock's
359
+ * refusal. Anything else, such as one that expired in no block or that the node never took, is
360
+ * unknown.
361
+ */
362
+ export function fundingRefusal(error) {
363
+ if (keychainRefused(error))
364
+ return { code: 'keychain.over_daily_limit', layer: 'keychain' };
365
+ const reason = relayReason(error);
366
+ if (reason)
367
+ return { code: reason, layer: 'relay' };
368
+ const stopped = sendErrorIn(error);
369
+ if (stopped?.stage === 'relay')
370
+ return { code: 'service.unavailable', layer: 'relay' };
371
+ if (stopped?.stage === 'altered')
372
+ return { code: 'sponsorship.altered', layer: 'relay' };
373
+ if (landedReverted(error) || (stopped?.stage === 'prepare' && /revert/i.test(stopped.message))) {
374
+ return { code: 'chain.reserve_missing', layer: 'lock' };
375
+ }
376
+ return { code: 'chain.reserve_missing', layer: 'unknown' };
377
+ }
378
+ /** Every check the buyer's side can make of a commitment it funded, in order. */
379
+ async function verifyCommitment(m) {
380
+ const { client, deployment, domain, commitment } = m;
381
+ const a = commitment.approval.message;
382
+ const factory = trustedFactory(deployment.chainId);
383
+ const check = (name, reason) => ({
384
+ name,
385
+ passed: reason === null,
386
+ reason,
387
+ });
388
+ const approvalReason = checkEnvelope(commitment.approval, {
389
+ type: 'Approval',
390
+ chainId: domain.chainId,
391
+ lock: domain.verifyingContract,
392
+ }) ??
393
+ (a.commitmentId.toLowerCase() === commitment.commitmentId.toLowerCase()
394
+ ? null
395
+ : 'approval.commitment_mismatch') ??
396
+ approvalPartiesProblem(a, commitment.supplier) ??
397
+ approvalTokenProblem(a, deployment.token) ??
398
+ approvalTermsProblem(a, {
399
+ lock: lockTerms(commitment.terms, 6),
400
+ termsHash: commitment.termsHash,
401
+ }) ??
402
+ approvalMandateProblem(a, {
403
+ mandateHash: m.mandateHash,
404
+ caps: approvalCaps(m.mandate, 6),
405
+ fundingKeys: [m.agentKey],
406
+ });
407
+ const checks = [
408
+ check("Avow's approval names this commitment, the supplier, the token, your terms and your mandate", approvalReason),
409
+ ];
410
+ if (!factory) {
411
+ return [...checks, check('The SDK trusts a factory on this chain', 'chain.lock_unknown')];
412
+ }
413
+ const reader = tempoChainReader(client, { factory, chainId: deployment.chainId });
414
+ // A node a block behind the one the reserve landed in doesn't show it yet, so each read waits.
415
+ const settled = async (read) => {
416
+ let result = await read();
417
+ for (let i = 1; i < 4 && !result.ok; i++) {
418
+ await pause(1500);
419
+ result = await read();
420
+ }
421
+ return result;
422
+ };
423
+ const unavailable = { ok: false, reason: 'service.unavailable' };
424
+ const onLock = await settled(() => verifyCommitmentReference(m.reference, reader).catch(() => unavailable));
425
+ checks.push(check("A lock Avow's factory made holds the commitment under your terms hash", onLock.ok ? null : onLock.reason));
426
+ const enforced = await settled(() => verifyCommitmentTerms({
427
+ reference: m.reference,
428
+ terms: commitment.terms,
429
+ salt: commitment.salt,
430
+ acceptedTokens: [moderatoUsdToken(deployment.token)],
431
+ }, reader).catch(() => unavailable));
432
+ checks.push(check('The lock enforces exactly what your terms map to', enforced.ok ? null : enforced.reason));
433
+ const held = await readBacking(client, domain.verifyingContract, commitment.commitmentId, 'buyer')
434
+ .then((b) => b ?? null)
435
+ .catch(() => undefined);
436
+ checks.push(check('The lock holds the reserve under the approval you checked', held === undefined
437
+ ? 'service.unavailable'
438
+ : held && held.approvalHash.toLowerCase() === approvalDigest(a, domain).toLowerCase()
439
+ ? null
440
+ : 'chain.approval_mismatch'));
441
+ const key = await readAgentKey(client, m.account, m.agentKey, m.keyAuthorizedIn).catch(() => undefined);
442
+ checks.push(check("Your agent's key is on the account, bound to your mandate", key === undefined
443
+ ? 'service.unavailable'
444
+ : key?.active && key.witness?.toLowerCase() === m.mandateHash.toLowerCase()
445
+ ? null
446
+ : 'chain.agent_key_inactive'));
447
+ return checks;
448
+ }
449
+ /**
450
+ * Follows the lock until the supplier accepts the reserve, or until the acceptance deadline has
451
+ * passed on the chain's clock with a minute to spare. A read that fails is read again.
452
+ */
453
+ async function waitForAcceptance(client, lock, commitment) {
454
+ const acceptBy = commitment.approval.message.acceptBy;
455
+ for (;;) {
456
+ const held = await readBacking(client, lock, commitment.commitmentId, 'buyer').catch(() => undefined);
457
+ if (held && held.state !== 'reserved')
458
+ return held.state === 'accepted';
459
+ const now = await client
460
+ .getBlock({ blockTag: 'latest' })
461
+ .then((block) => block.timestamp)
462
+ .catch(() => null);
463
+ if (now !== null && now > acceptBy + 60n)
464
+ return false;
465
+ await pause(3000);
466
+ }
467
+ }
468
+ //# sourceMappingURL=agent.js.map