@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.
- package/LICENSE +201 -0
- package/README.md +122 -2
- package/dist/agent-entry.d.ts +15 -0
- package/dist/agent-entry.d.ts.map +1 -0
- package/dist/agent-entry.js +11 -0
- package/dist/agent-entry.js.map +1 -0
- package/dist/agent-key.d.ts +34 -0
- package/dist/agent-key.d.ts.map +1 -0
- package/dist/agent-key.js +33 -0
- package/dist/agent-key.js.map +1 -0
- package/dist/agent.d.ts +261 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +493 -0
- package/dist/agent.js.map +1 -0
- package/dist/avow-api.d.ts +78 -0
- package/dist/avow-api.d.ts.map +1 -0
- package/dist/avow-api.js +2 -0
- package/dist/avow-api.js.map +1 -0
- package/dist/contest.d.ts +135 -0
- package/dist/contest.d.ts.map +1 -0
- package/dist/contest.js +186 -0
- package/dist/contest.js.map +1 -0
- package/dist/http.d.ts +161 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +311 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/job/accept.d.ts +84 -0
- package/dist/job/accept.d.ts.map +1 -0
- package/dist/job/accept.js +136 -0
- package/dist/job/accept.js.map +1 -0
- package/dist/job/customer.d.ts +43 -0
- package/dist/job/customer.d.ts.map +1 -0
- package/dist/job/customer.js +83 -0
- package/dist/job/customer.js.map +1 -0
- package/dist/job/quote.d.ts +34 -0
- package/dist/job/quote.d.ts.map +1 -0
- package/dist/job/quote.js +37 -0
- package/dist/job/quote.js.map +1 -0
- package/dist/lock.d.ts +269 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lock.js +283 -0
- package/dist/lock.js.map +1 -0
- package/dist/moderato.d.ts +27 -0
- package/dist/moderato.d.ts.map +1 -0
- package/dist/moderato.js +34 -0
- package/dist/moderato.js.map +1 -0
- package/dist/node/cli.d.ts +3 -0
- package/dist/node/cli.d.ts.map +1 -0
- package/dist/node/cli.js +346 -0
- package/dist/node/cli.js.map +1 -0
- package/dist/node/connect.d.ts +15 -0
- package/dist/node/connect.d.ts.map +1 -0
- package/dist/node/connect.js +91 -0
- package/dist/node/connect.js.map +1 -0
- package/dist/node/eval.d.ts +3 -0
- package/dist/node/eval.d.ts.map +1 -0
- package/dist/node/eval.js +67 -0
- package/dist/node/eval.js.map +1 -0
- package/dist/node/first-run.d.ts +50 -0
- package/dist/node/first-run.d.ts.map +1 -0
- package/dist/node/first-run.js +149 -0
- package/dist/node/first-run.js.map +1 -0
- package/dist/node/job.d.ts +50 -0
- package/dist/node/job.d.ts.map +1 -0
- package/dist/node/job.js +176 -0
- package/dist/node/job.js.map +1 -0
- package/dist/node/mailbox.d.ts +19 -0
- package/dist/node/mailbox.d.ts.map +1 -0
- package/dist/node/mailbox.js +81 -0
- package/dist/node/mailbox.js.map +1 -0
- package/dist/node/mcp.d.ts +74 -0
- package/dist/node/mcp.d.ts.map +1 -0
- package/dist/node/mcp.js +367 -0
- package/dist/node/mcp.js.map +1 -0
- package/dist/node/platform.d.ts +35 -0
- package/dist/node/platform.d.ts.map +1 -0
- package/dist/node/platform.js +102 -0
- package/dist/node/platform.js.map +1 -0
- package/dist/node/runner-session.d.ts +41 -0
- package/dist/node/runner-session.d.ts.map +1 -0
- package/dist/node/runner-session.js +100 -0
- package/dist/node/runner-session.js.map +1 -0
- package/dist/node/runner.d.ts +63 -0
- package/dist/node/runner.d.ts.map +1 -0
- package/dist/node/runner.js +341 -0
- package/dist/node/runner.js.map +1 -0
- package/dist/node/service-child.d.ts +2 -0
- package/dist/node/service-child.d.ts.map +1 -0
- package/dist/node/service-child.js +40 -0
- package/dist/node/service-child.js.map +1 -0
- package/dist/node/service-excerpt.d.ts +21 -0
- package/dist/node/service-excerpt.d.ts.map +1 -0
- package/dist/node/service-excerpt.js +32 -0
- package/dist/node/service-excerpt.js.map +1 -0
- package/dist/node/service-process.d.ts +12 -0
- package/dist/node/service-process.d.ts.map +1 -0
- package/dist/node/service-process.js +132 -0
- package/dist/node/service-process.js.map +1 -0
- package/dist/node/session-input.d.ts +12 -0
- package/dist/node/session-input.d.ts.map +1 -0
- package/dist/node/session-input.js +42 -0
- package/dist/node/session-input.js.map +1 -0
- package/dist/node/session-view.d.ts +20 -0
- package/dist/node/session-view.d.ts.map +1 -0
- package/dist/node/session-view.js +198 -0
- package/dist/node/session-view.js.map +1 -0
- package/dist/node-agent.d.ts +2 -0
- package/dist/node-agent.d.ts.map +1 -0
- package/dist/node-agent.js +6 -0
- package/dist/node-agent.js.map +1 -0
- package/dist/node.d.ts +2 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +9 -0
- package/dist/node.js.map +1 -0
- package/dist/sandbox/agent.d.ts +187 -0
- package/dist/sandbox/agent.d.ts.map +1 -0
- package/dist/sandbox/agent.js +468 -0
- package/dist/sandbox/agent.js.map +1 -0
- package/dist/sandbox/business-store.d.ts +19 -0
- package/dist/sandbox/business-store.d.ts.map +1 -0
- package/dist/sandbox/business-store.js +19 -0
- package/dist/sandbox/business-store.js.map +1 -0
- package/dist/sandbox/business.d.ts +70 -0
- package/dist/sandbox/business.d.ts.map +1 -0
- package/dist/sandbox/business.js +115 -0
- package/dist/sandbox/business.js.map +1 -0
- package/dist/sandbox/connect.d.ts +64 -0
- package/dist/sandbox/connect.d.ts.map +1 -0
- package/dist/sandbox/connect.js +182 -0
- package/dist/sandbox/connect.js.map +1 -0
- package/dist/sandbox/deployment.d.ts +14 -0
- package/dist/sandbox/deployment.d.ts.map +1 -0
- package/dist/sandbox/deployment.js +38 -0
- package/dist/sandbox/deployment.js.map +1 -0
- package/dist/sandbox/keys.d.ts +45 -0
- package/dist/sandbox/keys.d.ts.map +1 -0
- package/dist/sandbox/keys.js +132 -0
- package/dist/sandbox/keys.js.map +1 -0
- package/dist/sandbox/mailbox.d.ts +90 -0
- package/dist/sandbox/mailbox.d.ts.map +1 -0
- package/dist/sandbox/mailbox.js +400 -0
- package/dist/sandbox/mailbox.js.map +1 -0
- package/dist/sandbox/mandate.d.ts +84 -0
- package/dist/sandbox/mandate.d.ts.map +1 -0
- package/dist/sandbox/mandate.js +107 -0
- package/dist/sandbox/mandate.js.map +1 -0
- package/dist/sandbox/namespace.d.ts +16 -0
- package/dist/sandbox/namespace.d.ts.map +1 -0
- package/dist/sandbox/namespace.js +16 -0
- package/dist/sandbox/namespace.js.map +1 -0
- package/dist/sandbox/session.d.ts +60 -0
- package/dist/sandbox/session.d.ts.map +1 -0
- package/dist/sandbox/session.js +94 -0
- package/dist/sandbox/session.js.map +1 -0
- package/dist/sandbox/setup.d.ts +136 -0
- package/dist/sandbox/setup.d.ts.map +1 -0
- package/dist/sandbox/setup.js +490 -0
- package/dist/sandbox/setup.js.map +1 -0
- package/dist/sandbox/store.d.ts +69 -0
- package/dist/sandbox/store.d.ts.map +1 -0
- package/dist/sandbox/store.js +115 -0
- package/dist/sandbox/store.js.map +1 -0
- package/dist/sandbox/supplier-key.d.ts +73 -0
- package/dist/sandbox/supplier-key.d.ts.map +1 -0
- package/dist/sandbox/supplier-key.js +180 -0
- package/dist/sandbox/supplier-key.js.map +1 -0
- package/dist/sandbox/suppliers.d.ts +7 -0
- package/dist/sandbox/suppliers.d.ts.map +1 -0
- package/dist/sandbox/suppliers.js +29 -0
- package/dist/sandbox/suppliers.js.map +1 -0
- package/dist/sandbox/terms.d.ts +32 -0
- package/dist/sandbox/terms.d.ts.map +1 -0
- package/dist/sandbox/terms.js +58 -0
- package/dist/sandbox/terms.js.map +1 -0
- package/dist/sandbox/vault.d.ts +24 -0
- package/dist/sandbox/vault.d.ts.map +1 -0
- package/dist/sandbox/vault.js +54 -0
- package/dist/sandbox/vault.js.map +1 -0
- package/dist/send.d.ts +122 -0
- package/dist/send.d.ts.map +1 -0
- package/dist/send.js +328 -0
- package/dist/send.js.map +1 -0
- package/dist/service-entry.d.ts +6 -0
- package/dist/service-entry.d.ts.map +1 -0
- package/dist/service-entry.js +6 -0
- package/dist/service-entry.js.map +1 -0
- package/dist/session/anthropic.d.ts +17 -0
- package/dist/session/anthropic.d.ts.map +1 -0
- package/dist/session/anthropic.js +215 -0
- package/dist/session/anthropic.js.map +1 -0
- package/dist/session/charge.d.ts +13 -0
- package/dist/session/charge.d.ts.map +1 -0
- package/dist/session/charge.js +33 -0
- package/dist/session/charge.js.map +1 -0
- package/dist/session/data.d.ts +8 -0
- package/dist/session/data.d.ts.map +1 -0
- package/dist/session/data.js +20 -0
- package/dist/session/data.js.map +1 -0
- package/dist/session/eval.d.ts +41 -0
- package/dist/session/eval.d.ts.map +1 -0
- package/dist/session/eval.js +281 -0
- package/dist/session/eval.js.map +1 -0
- package/dist/session/executor.d.ts +80 -0
- package/dist/session/executor.d.ts.map +1 -0
- package/dist/session/executor.js +381 -0
- package/dist/session/executor.js.map +1 -0
- package/dist/session/fixture-world.d.ts +29 -0
- package/dist/session/fixture-world.d.ts.map +1 -0
- package/dist/session/fixture-world.js +708 -0
- package/dist/session/fixture-world.js.map +1 -0
- package/dist/session/live-world.d.ts +22 -0
- package/dist/session/live-world.d.ts.map +1 -0
- package/dist/session/live-world.js +329 -0
- package/dist/session/live-world.js.map +1 -0
- package/dist/session/ollama.d.ts +29 -0
- package/dist/session/ollama.d.ts.map +1 -0
- package/dist/session/ollama.js +177 -0
- package/dist/session/ollama.js.map +1 -0
- package/dist/session/provider.d.ts +79 -0
- package/dist/session/provider.d.ts.map +1 -0
- package/dist/session/provider.js +19 -0
- package/dist/session/provider.js.map +1 -0
- package/dist/session/scripted.d.ts +45 -0
- package/dist/session/scripted.d.ts.map +1 -0
- package/dist/session/scripted.js +236 -0
- package/dist/session/scripted.js.map +1 -0
- package/dist/session/selection.d.ts +37 -0
- package/dist/session/selection.d.ts.map +1 -0
- package/dist/session/selection.js +104 -0
- package/dist/session/selection.js.map +1 -0
- package/dist/session/service-check.d.ts +48 -0
- package/dist/session/service-check.d.ts.map +1 -0
- package/dist/session/service-check.js +86 -0
- package/dist/session/service-check.js.map +1 -0
- package/dist/session/service.d.ts +128 -0
- package/dist/session/service.d.ts.map +1 -0
- package/dist/session/service.js +150 -0
- package/dist/session/service.js.map +1 -0
- package/dist/session/session.d.ts +95 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +312 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/toolbox.d.ts +69 -0
- package/dist/session/toolbox.d.ts.map +1 -0
- package/dist/session/toolbox.js +391 -0
- package/dist/session/toolbox.js.map +1 -0
- package/dist/session/tools.d.ts +45 -0
- package/dist/session/tools.d.ts.map +1 -0
- package/dist/session/tools.js +137 -0
- package/dist/session/tools.js.map +1 -0
- package/dist/session/world.d.ts +188 -0
- package/dist/session/world.d.ts.map +1 -0
- package/dist/session/world.js +2 -0
- package/dist/session/world.js.map +1 -0
- package/dist/sign.d.ts +19 -0
- package/dist/sign.d.ts.map +1 -0
- package/dist/sign.js +33 -0
- package/dist/sign.js.map +1 -0
- package/dist/supplier.d.ts +41 -0
- package/dist/supplier.d.ts.map +1 -0
- package/dist/supplier.js +57 -0
- package/dist/supplier.js.map +1 -0
- package/package.json +56 -3
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import { formatUsd, mandateHash, REFUSED_BY, } from '@avow-finance/spec';
|
|
2
|
+
import { readAgentKey, readBacking } from '@avow-finance/verifier';
|
|
3
|
+
import { isAddressEqual } from 'viem';
|
|
4
|
+
import { generatePrivateKey } from 'viem/accounts';
|
|
5
|
+
import { Account } from 'viem/tempo';
|
|
6
|
+
import { rootRequestKey } from '../http.js';
|
|
7
|
+
import { cancelFreeCall, FACTORY_ABI, removeSupplierCall } from '../lock.js';
|
|
8
|
+
import { moderatoClient } from '../moderato.js';
|
|
9
|
+
import { sendOwn } from '../send.js';
|
|
10
|
+
import { checkSession, dailyLimitOf, platformSession, platformStore, Refusal, sandboxAgent, } from './agent.js';
|
|
11
|
+
import { createSandboxBusiness } from './business.js';
|
|
12
|
+
import { loadBusinessItem, saveBusinessItem } from './business-store.js';
|
|
13
|
+
import { loadSandboxDeployment, madeOn } from './deployment.js';
|
|
14
|
+
import { approvedSuppliers, lockCreatedIn, revokeOtherKeys } from './keys.js';
|
|
15
|
+
import { enrollSandboxAgent, SANDBOX_DAILY_LIMIT, sandboxMandate } from './mandate.js';
|
|
16
|
+
import { SANDBOX_SCREEN_URL, sessionRelay } from './session.js';
|
|
17
|
+
import { loadAgentItem, loadCommitments, saveAgentItem, saveCommitments, } from './store.js';
|
|
18
|
+
import { ensureSandboxSupplier } from './supplier-key.js';
|
|
19
|
+
import { checkSuppliers, connectSupplier } from './suppliers.js';
|
|
20
|
+
import { micros, toDollars } from './terms.js';
|
|
21
|
+
import { openKey, sealKey } from './vault.js';
|
|
22
|
+
const DAY = 86400n;
|
|
23
|
+
/** A mandate expiring sooner than this is replaced, once the person agrees. */
|
|
24
|
+
const MANDATE_MARGIN = 3600n;
|
|
25
|
+
const systemClock = () => BigInt(Math.floor(Date.now() / 1000));
|
|
26
|
+
/** What setting up a business does after each step, which shows as under way until it's done. */
|
|
27
|
+
const NEXT_STEP = {
|
|
28
|
+
fees: "Creating the business's lock",
|
|
29
|
+
lock: "Registering the business with Avow's sandbox",
|
|
30
|
+
registered: 'Waiting for the test dollars',
|
|
31
|
+
funded: null,
|
|
32
|
+
};
|
|
33
|
+
const stepLine = (s) => {
|
|
34
|
+
switch (s.step) {
|
|
35
|
+
case 'fees':
|
|
36
|
+
return s.hashes.length > 0 ? "Fees funded from Moderato's faucet" : 'Fees already covered';
|
|
37
|
+
case 'lock':
|
|
38
|
+
return s.createdIn ? 'Lock created on chain' : 'Lock found on chain';
|
|
39
|
+
case 'registered':
|
|
40
|
+
return "Registered with Avow's sandbox";
|
|
41
|
+
case 'funded':
|
|
42
|
+
return `${formatUsd(s.balance)} of test dollars in your account`;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/** What a step on chain leaves that the developer can look up, shown when they ask for details. */
|
|
46
|
+
const stepDetail = (s) => s.step === 'lock'
|
|
47
|
+
? `Your business's lock is ${s.lock}.`
|
|
48
|
+
: s.step === 'registered'
|
|
49
|
+
? `Avow's sandbox knows your business as ${s.businessId}.`
|
|
50
|
+
: null;
|
|
51
|
+
const authorityText = (cap, daily, suppliers) => `${formatUsd(cap)} held at once, ${daily === null ? 'no daily limit' : `${formatUsd(daily)} a day moved by the key`}, ${suppliers.join(', ')} only`;
|
|
52
|
+
/**
|
|
53
|
+
* Whether the chain shows the agent's key live on the account and authorized for the mandate in
|
|
54
|
+
* the agent's file, with that mandate's hash as its witness. Only the root key authorizes a key,
|
|
55
|
+
* so a file the agent rewrote, or an older mandate put back, fails this.
|
|
56
|
+
*/
|
|
57
|
+
async function keyHoldsMandate(client, account, agent, domain) {
|
|
58
|
+
const m = agent.mandate.message;
|
|
59
|
+
if (!isAddressEqual(m.account, account))
|
|
60
|
+
return false;
|
|
61
|
+
const key = await readAgentKey(client, account, m.agentKey, agent.keyAuthorizedIn).catch(() => null);
|
|
62
|
+
return (key !== null &&
|
|
63
|
+
key.active &&
|
|
64
|
+
(key.expiry === null || key.expiry > systemClock()) &&
|
|
65
|
+
key.witness?.toLowerCase() === mandateHash(m, domain).toLowerCase());
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The business's side of the sandbox, which only the runner calls. The first time, it asks for a
|
|
69
|
+
* passphrase and seals a new root key under it, registers the business with Avow's sandbox, waits
|
|
70
|
+
* for its test dollars and creates its lock. It takes whether the business is set up, and which
|
|
71
|
+
* mandate the agent holds, from the chain, since anything running as the developer can write the
|
|
72
|
+
* .avow folder, and it sets a business up again only after a yes to a question that says what that
|
|
73
|
+
* replaces. Whenever the authority or the suppliers in the config differ from the mandate the chain
|
|
74
|
+
* holds, or the mandate is about to expire, it asks before signing a new mandate, then asks for the
|
|
75
|
+
* passphrase. A transaction of its own revokes every other key the account's keychain still
|
|
76
|
+
* authorizes, access or admin, read from the chain from the lock's creation, so nothing the agent
|
|
77
|
+
* can write keeps a key live. Then a new agent key goes on the account, and each supplier the lock
|
|
78
|
+
* approves that the new mandate doesn't name comes off, each in its own transaction. The root key
|
|
79
|
+
* is opened only for those signatures, and never stored or passed on in the clear.
|
|
80
|
+
*/
|
|
81
|
+
export async function prepareSandboxBusiness(options) {
|
|
82
|
+
const { config, prompts } = options;
|
|
83
|
+
const log = options.log ?? ((line) => console.log(line));
|
|
84
|
+
const send = options.fetch ?? ((input, init) => fetch(input, init));
|
|
85
|
+
if (typeof config.name !== 'string' || config.name.trim() === '' || config.name.length > 200) {
|
|
86
|
+
throw new RangeError("The business's name has to be 1 to 200 characters");
|
|
87
|
+
}
|
|
88
|
+
const country = config.country ?? 'US';
|
|
89
|
+
if (!/^[A-Z]{2}$/.test(country))
|
|
90
|
+
throw new RangeError('The country has to be two capital letters');
|
|
91
|
+
const authority = micros(config.authority, 'authority');
|
|
92
|
+
const dailyLimit = config.dailyLimit === undefined ? SANDBOX_DAILY_LIMIT : micros(config.dailyLimit, 'daily limit');
|
|
93
|
+
const suppliers = checkSuppliers(config.suppliers);
|
|
94
|
+
const ids = suppliers.map((s) => s.id);
|
|
95
|
+
const store = options.store ?? platformStore();
|
|
96
|
+
if (!store)
|
|
97
|
+
throw new Error('The business needs a store. In Node it uses the .avow folder.');
|
|
98
|
+
const screenUrl = options.screenUrl ?? SANDBOX_SCREEN_URL;
|
|
99
|
+
const deployment = options.deployment ?? (await loadSandboxDeployment(screenUrl, send));
|
|
100
|
+
const client = options.client ?? moderatoClient(deployment.rpcUrl);
|
|
101
|
+
// The root key is open only inside this call, once the person typed the passphrase.
|
|
102
|
+
let opened = null;
|
|
103
|
+
let item = await loadBusinessItem(store);
|
|
104
|
+
const fresh = !item;
|
|
105
|
+
if (!item) {
|
|
106
|
+
if ((await store.read('agent')) !== null) {
|
|
107
|
+
throw new Error("The business's file is gone from .avow but its agent's file is there, so the business's key is missing. Restore .avow/business.json, or start over with npm run fresh.");
|
|
108
|
+
}
|
|
109
|
+
log('Your business\nYour business holds the money, in a lock of its own on chain. Its key is made on this machine, sealed under a passphrase you choose, and never leaves it.', 'step');
|
|
110
|
+
const passphrase = await prompts.newPassphrase();
|
|
111
|
+
const privateKey = generatePrivateKey();
|
|
112
|
+
const account = Account.fromSecp256k1(privateKey).address;
|
|
113
|
+
const key = await sealKey(privateKey, passphrase, account);
|
|
114
|
+
item = { account, key, business: null };
|
|
115
|
+
await saveBusinessItem(store, item);
|
|
116
|
+
opened = privateKey;
|
|
117
|
+
}
|
|
118
|
+
const sealed = item;
|
|
119
|
+
const openRoot = async () => {
|
|
120
|
+
opened ??= await openKey(sealed.key, await prompts.passphrase(), sealed.account);
|
|
121
|
+
const root = Account.fromSecp256k1(opened);
|
|
122
|
+
if (!isAddressEqual(root.address, sealed.account)) {
|
|
123
|
+
throw new Error("The business's key doesn't match its account");
|
|
124
|
+
}
|
|
125
|
+
return root;
|
|
126
|
+
};
|
|
127
|
+
// Whether the business is set up comes from the chain, never from the file alone, since anything
|
|
128
|
+
// running as the developer can write the file. The lock is the factory's for the sealed key's
|
|
129
|
+
// account, and the file's record counts only when it names that lock and the lock is on chain.
|
|
130
|
+
const lock = await client.readContract({
|
|
131
|
+
address: deployment.factory,
|
|
132
|
+
abi: FACTORY_ABI,
|
|
133
|
+
functionName: 'lockAddress',
|
|
134
|
+
args: [sealed.account],
|
|
135
|
+
});
|
|
136
|
+
const lockMade = (await client.getCode({ address: lock })) !== undefined;
|
|
137
|
+
const recorded = item.business;
|
|
138
|
+
let business = recorded &&
|
|
139
|
+
madeOn(recorded, deployment) &&
|
|
140
|
+
isAddressEqual(recorded.account, sealed.account) &&
|
|
141
|
+
isAddressEqual(recorded.lock, lock) &&
|
|
142
|
+
lockMade
|
|
143
|
+
? recorded
|
|
144
|
+
: null;
|
|
145
|
+
let setUpAgain = false;
|
|
146
|
+
let fundedNow = null;
|
|
147
|
+
if (!business) {
|
|
148
|
+
if (!fresh) {
|
|
149
|
+
const [question, ...details] = lockMade
|
|
150
|
+
? [
|
|
151
|
+
'Set the business up again on the same key and lock?',
|
|
152
|
+
`Your business's lock is on chain at ${lock}, but .avow/business.json doesn't record it, so its setup stopped part way or something changed the file.`,
|
|
153
|
+
"A yes registers the business with Avow's sandbox again, replaces the record in .avow/business.json, and then signs your agent a new mandate, which revokes every other key on the account.",
|
|
154
|
+
]
|
|
155
|
+
: [
|
|
156
|
+
'Set your business up under this deployment?',
|
|
157
|
+
"Your business's key is in .avow, but no lock for it is on chain under this deployment, so its setup stopped part way or it was set up on another one.",
|
|
158
|
+
"A yes creates the lock, registers the business with Avow's sandbox and replaces the record in .avow/business.json.",
|
|
159
|
+
];
|
|
160
|
+
if (!(await prompts.confirm(question, details))) {
|
|
161
|
+
throw new Error('Nothing changed, and your business stays as it was. Run npm start again to set it up.');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (!fresh)
|
|
165
|
+
log('Your business on Tempo testnet', 'stage');
|
|
166
|
+
const root = await openRoot();
|
|
167
|
+
log("Funding the account's fees", 'wait');
|
|
168
|
+
let funded = null;
|
|
169
|
+
const made = await createSandboxBusiness({
|
|
170
|
+
deployment,
|
|
171
|
+
client,
|
|
172
|
+
root,
|
|
173
|
+
legalName: config.name,
|
|
174
|
+
country,
|
|
175
|
+
onStep: (s) => {
|
|
176
|
+
log(stepLine(s), 'done');
|
|
177
|
+
const detail = stepDetail(s);
|
|
178
|
+
if (detail)
|
|
179
|
+
log(detail, 'detail');
|
|
180
|
+
const next = NEXT_STEP[s.step];
|
|
181
|
+
if (next)
|
|
182
|
+
log(next, 'wait');
|
|
183
|
+
if (s.step === 'funded')
|
|
184
|
+
funded = s.balance;
|
|
185
|
+
},
|
|
186
|
+
fetch: send,
|
|
187
|
+
});
|
|
188
|
+
business = {
|
|
189
|
+
chainId: deployment.chainId,
|
|
190
|
+
apiUrl: deployment.apiUrl,
|
|
191
|
+
factory: deployment.factory,
|
|
192
|
+
token: deployment.token,
|
|
193
|
+
account: made.account,
|
|
194
|
+
lock: made.lock,
|
|
195
|
+
businessId: made.businessId,
|
|
196
|
+
};
|
|
197
|
+
item = { ...item, business };
|
|
198
|
+
await saveBusinessItem(store, item);
|
|
199
|
+
fundedNow = funded;
|
|
200
|
+
// Commitments from another deployment belong to another lock.
|
|
201
|
+
if (recorded && !madeOn(recorded, deployment))
|
|
202
|
+
await saveCommitments(store, []);
|
|
203
|
+
setUpAgain = !fresh;
|
|
204
|
+
}
|
|
205
|
+
const domain = { chainId: deployment.chainId, verifyingContract: lock };
|
|
206
|
+
// The job chapter quotes and accepts jobs as a supplier, with a signing key of its own. A failure
|
|
207
|
+
// here leaves the business set up, and the result says why it can't take jobs.
|
|
208
|
+
let supplier = null;
|
|
209
|
+
if (options.supplier) {
|
|
210
|
+
try {
|
|
211
|
+
const registered = await ensureSandboxSupplier({
|
|
212
|
+
store,
|
|
213
|
+
business,
|
|
214
|
+
deployment,
|
|
215
|
+
client,
|
|
216
|
+
openRoot,
|
|
217
|
+
log,
|
|
218
|
+
fetch: send,
|
|
219
|
+
});
|
|
220
|
+
supplier = { ok: true, signingKey: registered.profile.signingKey };
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
supplier = { ok: false, why: error instanceof Error ? error.message : String(error) };
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (fresh) {
|
|
227
|
+
log(fundedNow === null
|
|
228
|
+
? 'Your business is set up, with its own lock on chain'
|
|
229
|
+
: `Your business has ${formatUsd(fundedNow)} in test dollars, held in its own lock`, 'step_done');
|
|
230
|
+
}
|
|
231
|
+
let agent = await loadAgentItem(store);
|
|
232
|
+
if (agent && !isAddressEqual(agent.business.lock, lock))
|
|
233
|
+
agent = null;
|
|
234
|
+
// The agent's file names the mandate it holds, and the agent can write that file. So the mandate
|
|
235
|
+
// counts only while the chain shows its key live on the account and authorized for that mandate,
|
|
236
|
+
// which only the root key can do. Anything else, or a business set up again, gets a new mandate.
|
|
237
|
+
if (agent && (setUpAgain || !(await keyHoldsMandate(client, business.account, agent, domain)))) {
|
|
238
|
+
log("Your agent's file doesn't name a key the chain shows live under its mandate, so your agent needs a new mandate.", 'note');
|
|
239
|
+
agent = null;
|
|
240
|
+
}
|
|
241
|
+
const current = agent?.mandate.message;
|
|
242
|
+
const changed = !current ||
|
|
243
|
+
current.capOpenReserves !== authority ||
|
|
244
|
+
current.capPerCommitment !== authority ||
|
|
245
|
+
dailyLimitOf(current, deployment.token) !== dailyLimit ||
|
|
246
|
+
[...current.suppliers].sort().join() !== [...ids].sort().join();
|
|
247
|
+
const expiring = current !== undefined && current.expiry <= systemClock() + MANDATE_MARGIN;
|
|
248
|
+
const prepared = (a, signed, announced) => ({
|
|
249
|
+
businessId: a.business.businessId,
|
|
250
|
+
account: a.business.account,
|
|
251
|
+
lock,
|
|
252
|
+
authority: toDollars(a.mandate.message.capOpenReserves),
|
|
253
|
+
suppliers: [...a.mandate.message.suppliers],
|
|
254
|
+
mandateHash: mandateHash(a.mandate.message, domain),
|
|
255
|
+
signed,
|
|
256
|
+
announced,
|
|
257
|
+
supplier,
|
|
258
|
+
});
|
|
259
|
+
// An authority change goes to the session signed by the root key, and the runner waits for it,
|
|
260
|
+
// so it can tell whether the screen has the agent's authority.
|
|
261
|
+
const session = checkSession(options.session !== undefined ? options.session : platformSession());
|
|
262
|
+
const postAuthority = async (root, a, previous) => {
|
|
263
|
+
if (!session)
|
|
264
|
+
return false;
|
|
265
|
+
log("Giving your screen your agent's authority", 'wait');
|
|
266
|
+
try {
|
|
267
|
+
await sessionRelay({
|
|
268
|
+
baseUrl: deployment.apiUrl,
|
|
269
|
+
sessionId: session.id,
|
|
270
|
+
key: rootRequestKey(root),
|
|
271
|
+
domain,
|
|
272
|
+
fetch: send,
|
|
273
|
+
retryFor: 15n,
|
|
274
|
+
attemptTimeout: 10_000,
|
|
275
|
+
}).post({
|
|
276
|
+
type: 'authority_changed',
|
|
277
|
+
run: session.run,
|
|
278
|
+
source: 'business',
|
|
279
|
+
authority: a.mandate.message.capOpenReserves,
|
|
280
|
+
previous,
|
|
281
|
+
suppliers: [...a.mandate.message.suppliers],
|
|
282
|
+
// The hash comes from the mandate the chain bound the agent's key to, and never from the
|
|
283
|
+
// agent's file, which the agent can write.
|
|
284
|
+
mandateHash: mandateHash(a.mandate.message, domain),
|
|
285
|
+
});
|
|
286
|
+
log("Your screen has your agent's authority.", 'done');
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
log(`The screen didn't get your agent's authority: ${error instanceof Error ? error.message : String(error)}`, 'note');
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
// A session new to the authority gets the mandate the agent holds now, which takes the key.
|
|
295
|
+
const announceCurrent = async (a) => {
|
|
296
|
+
if (!options.announce || !session)
|
|
297
|
+
return false;
|
|
298
|
+
log('Your screen', 'stage');
|
|
299
|
+
log("Your screen has a new session, so your business's key signs your agent's current authority for it. The passphrase opens the key for that one signature.", 'note');
|
|
300
|
+
const done = await postAuthority(await openRoot(), a, null);
|
|
301
|
+
opened = null;
|
|
302
|
+
return done;
|
|
303
|
+
};
|
|
304
|
+
if (agent && !changed && !expiring) {
|
|
305
|
+
// Supplier URLs aren't in the mandate, so a changed URL needs no new signature.
|
|
306
|
+
if (JSON.stringify(agent.suppliers) !== JSON.stringify(suppliers)) {
|
|
307
|
+
agent = { ...agent, suppliers };
|
|
308
|
+
await saveAgentItem(store, agent);
|
|
309
|
+
}
|
|
310
|
+
return prepared(agent, false, await announceCurrent(agent));
|
|
311
|
+
}
|
|
312
|
+
// A first setup shows the limits as the step that teaches them, one to a line with who holds it.
|
|
313
|
+
if (fresh) {
|
|
314
|
+
log("Your agent's limits\nYour agent gets a key of its own, and Avow and the chain refuse anything it tries past these limits.", 'step');
|
|
315
|
+
}
|
|
316
|
+
const question = fresh
|
|
317
|
+
? 'Sign these limits for your agent?'
|
|
318
|
+
: changed
|
|
319
|
+
? `Sign a new mandate as ${config.name}?`
|
|
320
|
+
: `Your agent's mandate expires within the hour. Sign a new one as ${config.name}?`;
|
|
321
|
+
const details = fresh
|
|
322
|
+
? [
|
|
323
|
+
`${formatUsd(authority)} held at once, which Avow holds it to`,
|
|
324
|
+
`${formatUsd(dailyLimit)} a day moved by its key, which the chain holds it to`,
|
|
325
|
+
`Books only with ${ids.join(', ')}`,
|
|
326
|
+
]
|
|
327
|
+
: [
|
|
328
|
+
`${authorityText(authority, dailyLimit, ids)}.`,
|
|
329
|
+
'It revokes every other key on the account.',
|
|
330
|
+
];
|
|
331
|
+
if (!(await prompts.confirm(question, details))) {
|
|
332
|
+
if (agent && current) {
|
|
333
|
+
log(`Kept the current mandate: ${authorityText(current.capOpenReserves, dailyLimitOf(current, deployment.token), current.suppliers)}.`, 'note');
|
|
334
|
+
return prepared(agent, false, await announceCurrent(agent));
|
|
335
|
+
}
|
|
336
|
+
throw new Error("No mandate was signed, so your agent can't book yet. Run npm start again to sign one.");
|
|
337
|
+
}
|
|
338
|
+
const root = await openRoot();
|
|
339
|
+
log("Signing and enrolling your agent's mandate", 'wait');
|
|
340
|
+
// The scan starts where the factory created the lock, read from the chain, so nothing on this
|
|
341
|
+
// machine can move it past a key.
|
|
342
|
+
const since = await lockCreatedIn({
|
|
343
|
+
client,
|
|
344
|
+
factory: deployment.factory,
|
|
345
|
+
account: root.address,
|
|
346
|
+
lock,
|
|
347
|
+
});
|
|
348
|
+
// The revocation goes first, in a transaction of its own, so nothing after it can stop it.
|
|
349
|
+
const revoked = await revokeOtherKeys({ client, root, since });
|
|
350
|
+
if (revoked.length > 0) {
|
|
351
|
+
log(`Revoked ${revoked.length} key${revoked.length === 1 ? '' : 's'} the account's keychain still authorized.`, 'done');
|
|
352
|
+
log("Signing and enrolling your agent's mandate", 'wait');
|
|
353
|
+
}
|
|
354
|
+
const profiles = await Promise.all(suppliers.map(async (s) => (await connectSupplier(s, send)).profile));
|
|
355
|
+
const agentPrivateKey = generatePrivateKey();
|
|
356
|
+
const agentKey = Account.fromSecp256k1(agentPrivateKey, { access: root.address });
|
|
357
|
+
const now = systemClock();
|
|
358
|
+
const mandate = sandboxMandate({
|
|
359
|
+
businessId: business.businessId,
|
|
360
|
+
agentId: `agt_${agentKey.accessKeyAddress.slice(2, 12).toLowerCase()}`,
|
|
361
|
+
account: root.address,
|
|
362
|
+
agentKey: agentKey.accessKeyAddress,
|
|
363
|
+
suppliers: ids,
|
|
364
|
+
token: deployment.token,
|
|
365
|
+
capPerCommitment: authority,
|
|
366
|
+
capOpenReserves: authority,
|
|
367
|
+
dailyLimit,
|
|
368
|
+
expiry: now + 7n * DAY,
|
|
369
|
+
});
|
|
370
|
+
const enrolled = await enrollSandboxAgent({
|
|
371
|
+
deployment,
|
|
372
|
+
client,
|
|
373
|
+
root,
|
|
374
|
+
agent: agentKey,
|
|
375
|
+
lock,
|
|
376
|
+
mandate,
|
|
377
|
+
suppliers: profiles,
|
|
378
|
+
fetch: send,
|
|
379
|
+
});
|
|
380
|
+
const next = {
|
|
381
|
+
agentKey: agentPrivateKey,
|
|
382
|
+
business,
|
|
383
|
+
mandate: enrolled.mandate,
|
|
384
|
+
mandateHash: enrolled.mandateHash,
|
|
385
|
+
keyAuthorizedIn: enrolled.keyAuthorizedIn,
|
|
386
|
+
suppliers,
|
|
387
|
+
};
|
|
388
|
+
await saveAgentItem(store, next);
|
|
389
|
+
log("Mandate signed, and your agent's key enrolled on your account", 'done');
|
|
390
|
+
// Each supplier the lock approves that the new mandate doesn't name comes off on its own, so one
|
|
391
|
+
// that fails leaves the others done, and the person hears which.
|
|
392
|
+
const keep = profiles.map((p) => p.account);
|
|
393
|
+
const dropped = (await approvedSuppliers(client, lock, since)).filter((a) => !keep.some((k) => isAddressEqual(k, a)));
|
|
394
|
+
for (const supplier of dropped) {
|
|
395
|
+
try {
|
|
396
|
+
await sendOwn({ client, account: root, calls: [removeSupplierCall(lock, supplier)] });
|
|
397
|
+
log(`Took supplier ${supplier} off the lock, since the new mandate doesn't name it.`, 'done');
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
log(`Supplier ${supplier} is still approved on the lock: ${error instanceof Error ? error.message : String(error)}. The new mandate doesn't name it, so Avow won't approve a reserve for it.`, 'note');
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
await showHeldBookings({ store, client, current: enrolled.mandateHash, log });
|
|
404
|
+
const announced = await postAuthority(root, next, current?.capOpenReserves ?? null);
|
|
405
|
+
opened = null;
|
|
406
|
+
if (fresh) {
|
|
407
|
+
// The new key's first act is a booking a dollar past its limit, so the step ends on proof.
|
|
408
|
+
log('Trying a booking past the limit', 'wait');
|
|
409
|
+
const tried = await limitTry(authority, async (reserve) => {
|
|
410
|
+
const agent = await sandboxAgent({
|
|
411
|
+
store,
|
|
412
|
+
deployment,
|
|
413
|
+
session: null,
|
|
414
|
+
log: () => { },
|
|
415
|
+
fetch: send,
|
|
416
|
+
});
|
|
417
|
+
await agent.book({
|
|
418
|
+
supplier: ids[0],
|
|
419
|
+
resource: { gpu: 'H100', count: 1, hours: 1 },
|
|
420
|
+
reserve,
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
log(`Your agent can hold ${formatUsd(authority)} at once and move ${formatUsd(dailyLimit)} a day.${tried ? ` ${tried}` : ''}`, 'step_done');
|
|
424
|
+
}
|
|
425
|
+
return prepared(next, true, announced);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Has the agent try to hold a dollar more than its business just allowed, and says who refused
|
|
429
|
+
* it. A first setup doesn't stop for a try that couldn't run, such as one whose supplier didn't
|
|
430
|
+
* answer, so that gives null and the step ends without it.
|
|
431
|
+
*/
|
|
432
|
+
export async function limitTry(authority, book) {
|
|
433
|
+
const over = authority + 1000000n;
|
|
434
|
+
try {
|
|
435
|
+
await book(toDollars(over));
|
|
436
|
+
}
|
|
437
|
+
catch (error) {
|
|
438
|
+
if (!(error instanceof Refusal))
|
|
439
|
+
return null;
|
|
440
|
+
return `It asked to hold ${formatUsd(over)}, and ${REFUSED_BY[error.layer]} refused, so no money moved.`;
|
|
441
|
+
}
|
|
442
|
+
return `It asked to hold ${formatUsd(over)} and nothing refused it, which should never happen, so tell Avow.`;
|
|
443
|
+
}
|
|
444
|
+
/** Lists what the lock still holds under an earlier authority, which stays until its release. */
|
|
445
|
+
async function showHeldBookings(m) {
|
|
446
|
+
const earlier = (await loadCommitments(m.store)).filter((c) => c.mandateHash.toLowerCase() !== m.current.toLowerCase());
|
|
447
|
+
const held = (await Promise.all(earlier.map(async (c) => ({
|
|
448
|
+
c,
|
|
449
|
+
backing: await readBacking(m.client, c.reference.lock, c.reference.commitmentId, 'buyer').catch(() => null),
|
|
450
|
+
})))).filter(({ backing }) => backing && ['reserved', 'accepted', 'charge_pending', 'paused'].includes(backing.state));
|
|
451
|
+
if (held.length === 0)
|
|
452
|
+
return;
|
|
453
|
+
m.log('Bookings made under an earlier authority stay held in the lock until their release:');
|
|
454
|
+
for (const { c, backing } of held) {
|
|
455
|
+
const release = backing ? new Date(Number(backing.releaseDate) * 1000).toISOString() : 'unknown';
|
|
456
|
+
m.log(` ${formatUsd(c.amount)} with ${c.supplier}, ${backing?.state}, released at ${release}`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Cancels one of the agent's commitments on the lock before free cancellation ends, which gives
|
|
461
|
+
* the whole reserve back. It's the business's call, signed by its root key once the person types
|
|
462
|
+
* the passphrase, since the agent's key can't cancel on the lock.
|
|
463
|
+
*/
|
|
464
|
+
export async function cancelSandboxCommitment(options) {
|
|
465
|
+
const send = options.fetch ?? ((input, init) => fetch(input, init));
|
|
466
|
+
const store = options.store ?? platformStore();
|
|
467
|
+
if (!store)
|
|
468
|
+
throw new Error('The business needs a store. In Node it uses the .avow folder.');
|
|
469
|
+
const item = await loadBusinessItem(store);
|
|
470
|
+
if (!item?.business)
|
|
471
|
+
throw new Error('This folder has no business yet. Run npm start first.');
|
|
472
|
+
const deployment = options.deployment ??
|
|
473
|
+
(await loadSandboxDeployment(options.screenUrl ?? SANDBOX_SCREEN_URL, send));
|
|
474
|
+
const client = options.client ?? moderatoClient(deployment.rpcUrl);
|
|
475
|
+
// The lock is the factory's for the account, read from the chain, whatever the file names.
|
|
476
|
+
const lock = await client.readContract({
|
|
477
|
+
address: deployment.factory,
|
|
478
|
+
abi: FACTORY_ABI,
|
|
479
|
+
functionName: 'lockAddress',
|
|
480
|
+
args: [item.account],
|
|
481
|
+
});
|
|
482
|
+
const root = Account.fromSecp256k1(await openKey(item.key, await options.prompts.passphrase(), item.account));
|
|
483
|
+
const receipt = await sendOwn({
|
|
484
|
+
client,
|
|
485
|
+
account: root,
|
|
486
|
+
calls: [cancelFreeCall(lock, options.commitmentId)],
|
|
487
|
+
});
|
|
488
|
+
return receipt.transactionHash;
|
|
489
|
+
}
|
|
490
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/sandbox/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EACT,WAAW,EACX,UAAU,GAEX,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAA0B,cAAc,EAAE,MAAM,MAAM,CAAA;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,aAAa,EACb,OAAO,EAEP,YAAY,GACb,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,qBAAqB,EAAgD,MAAM,eAAe,CAAA;AACnG,OAAO,EAAqB,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC7E,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACtF,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EAEL,aAAa,EACb,eAAe,EAGf,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAgG7C,MAAM,GAAG,GAAG,MAAO,CAAA;AACnB,+EAA+E;AAC/E,MAAM,cAAc,GAAG,KAAK,CAAA;AAC5B,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAA;AAE/D,iGAAiG;AACjG,MAAM,SAAS,GAAuD;IACpE,IAAI,EAAE,8BAA8B;IACpC,IAAI,EAAE,8CAA8C;IACpD,UAAU,EAAE,8BAA8B;IAC1C,MAAM,EAAE,IAAI;CACb,CAAA;AAED,MAAM,QAAQ,GAAG,CAAC,CAAsB,EAAU,EAAE;IAClD,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,sBAAsB,CAAA;QAC5F,KAAK,MAAM;YACT,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,qBAAqB,CAAA;QACtE,KAAK,YAAY;YACf,OAAO,gCAAgC,CAAA;QACzC,KAAK,QAAQ;YACX,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,kCAAkC,CAAA;IACpE,CAAC;AACH,CAAC,CAAA;AAED,mGAAmG;AACnG,MAAM,UAAU,GAAG,CAAC,CAAsB,EAAiB,EAAE,CAC3D,CAAC,CAAC,IAAI,KAAK,MAAM;IACf,CAAC,CAAC,2BAA2B,CAAC,CAAC,IAAI,GAAG;IACtC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY;QACvB,CAAC,CAAC,yCAAyC,CAAC,CAAC,UAAU,GAAG;QAC1D,CAAC,CAAC,IAAI,CAAA;AAEZ,MAAM,aAAa,GAAG,CAAC,GAAW,EAAE,KAAoB,EAAE,SAA4B,EAAE,EAAE,CACxF,GAAG,SAAS,CAAC,GAAG,CAAC,kBAAkB,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,yBAAyB,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAA;AAErJ;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAC5B,MAAqB,EACrB,OAAgB,EAChB,KAAgB,EAChB,MAAkB;IAElB,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAA;IAC/B,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACrD,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC,KAAK,CACtF,GAAG,EAAE,CAAC,IAAI,CACX,CAAA;IACD,OAAO,CACL,GAAG,KAAK,IAAI;QACZ,GAAG,CAAC,MAAM;QACV,CAAC,GAAG,CAAC,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;QACnD,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,WAAW,EAAE,CACpE,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAAsC;IAEtC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;IAChE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;IACnE,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC7F,MAAM,IAAI,UAAU,CAAC,mDAAmD,CAAC,CAAA;IAC3E,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAA;IACtC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,2CAA2C,CAAC,CAAA;IAClG,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IACvD,MAAM,UAAU,GACd,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,CAAA;IAClG,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAClD,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,EAAE,CAAA;IAC9C,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAA;IAC5F,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAA;IACzD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,MAAM,qBAAqB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAA;IACvF,MAAM,MAAM,GAAkB,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IAEjF,oFAAoF;IACpF,IAAI,MAAM,GAAe,IAAI,CAAA;IAC7B,IAAI,IAAI,GAAwB,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAA;IAC7D,MAAM,KAAK,GAAG,CAAC,IAAI,CAAA;IACnB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,wKAAwK,CACzK,CAAA;QACH,CAAC;QACD,GAAG,CACD,0KAA0K,EAC1K,MAAM,CACP,CAAA;QACD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAA;QAChD,MAAM,UAAU,GAAG,kBAAkB,EAAE,CAAA;QACvC,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,OAAO,CAAA;QACzD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;QAC1D,IAAI,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;QACvC,MAAM,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACnC,MAAM,GAAG,UAAU,CAAA;IACrB,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,MAAM,KAAK,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,OAAO,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QAChF,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QAC1C,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;QACjE,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,iGAAiG;IACjG,8FAA8F;IAC9F,+FAA+F;IAC/F,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;QACrC,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,GAAG,EAAE,WAAW;QAChB,YAAY,EAAE,aAAa;QAC3B,IAAI,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;KACvB,CAAC,CAAA;IACF,MAAM,QAAQ,GAAG,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,SAAS,CAAA;IACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;IAC9B,IAAI,QAAQ,GACV,QAAQ;QACR,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC;QAC5B,cAAc,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC;QAChD,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;QACnC,QAAQ;QACN,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,IAAI,CAAA;IACV,IAAI,UAAU,GAAG,KAAK,CAAA;IACtB,IAAI,SAAS,GAAkB,IAAI,CAAA;IACnC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,QAAQ,EAAE,GAAG,OAAO,CAAC,GAAG,QAAQ;gBACrC,CAAC,CAAC;oBACE,qDAAqD;oBACrD,uCAAuC,IAAI,2GAA2G;oBACtJ,4LAA4L;iBAC7L;gBACH,CAAC,CAAC;oBACE,6CAA6C;oBAC7C,uJAAuJ;oBACvJ,oHAAoH;iBACrH,CAAA;YACL,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,QAAkB,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;gBAC1D,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAA;YACH,CAAC;QACH,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,GAAG,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAA;QAC1D,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAA;QAC7B,GAAG,CAAC,4BAA4B,EAAE,MAAM,CAAC,CAAA;QACzC,IAAI,MAAM,GAAkB,IAAI,CAAA;QAChC,MAAM,IAAI,GAAG,MAAM,qBAAqB,CAAC;YACvC,UAAU;YACV,MAAM;YACN,IAAI;YACJ,SAAS,EAAE,MAAM,CAAC,IAAI;YACtB,OAAO;YACP,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;gBACZ,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;gBACxB,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;gBAC5B,IAAI,MAAM;oBAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;gBACjC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;gBAC9B,IAAI,IAAI;oBAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;gBAC3B,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;oBAAE,MAAM,GAAG,CAAC,CAAC,OAAO,CAAA;YAC7C,CAAC;YACD,KAAK,EAAE,IAAI;SACZ,CAAC,CAAA;QACF,QAAQ,GAAG;YACT,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAA;QACD,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAA;QAC5B,MAAM,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACnC,SAAS,GAAG,MAAM,CAAA;QAClB,8DAA8D;QAC9D,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC;YAAE,MAAM,eAAe,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QAC/E,UAAU,GAAG,CAAC,KAAK,CAAA;IACrB,CAAC;IACD,MAAM,MAAM,GAAe,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAA;IACnF,kGAAkG;IAClG,+EAA+E;IAC/E,IAAI,QAAQ,GAAwC,IAAI,CAAA;IACxD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,qBAAqB,CAAC;gBAC7C,KAAK;gBACL,QAAQ;gBACR,UAAU;gBACV,MAAM;gBACN,QAAQ;gBACR,GAAG;gBACH,KAAK,EAAE,IAAI;aACZ,CAAC,CAAA;YACF,QAAQ,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,CAAA;QACpE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAA;QACvF,CAAC;IACH,CAAC;IACD,IAAI,KAAK,EAAE,CAAC;QACV,GAAG,CACD,SAAS,KAAK,IAAI;YAChB,CAAC,CAAC,qDAAqD;YACvD,CAAC,CAAC,qBAAqB,SAAS,CAAC,SAAS,CAAC,wCAAwC,EACrF,WAAW,CACZ,CAAA;IACH,CAAC;IACD,IAAI,KAAK,GAAqB,MAAM,aAAa,CAAC,KAAK,CAAC,CAAA;IACxD,IAAI,KAAK,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;QAAE,KAAK,GAAG,IAAI,CAAA;IACrE,iGAAiG;IACjG,iGAAiG;IACjG,iGAAiG;IACjG,IAAI,KAAK,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/F,GAAG,CACD,iHAAiH,EACjH,MAAM,CACP,CAAA;QACD,KAAK,GAAG,IAAI,CAAA;IACd,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,CAAC,OAAO,CAAA;IACtC,MAAM,OAAO,GACX,CAAC,OAAO;QACR,OAAO,CAAC,eAAe,KAAK,SAAS;QACrC,OAAO,CAAC,gBAAgB,KAAK,SAAS;QACtC,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,UAAU;QACtD,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAA;IACjE,MAAM,QAAQ,GAAG,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,IAAI,WAAW,EAAE,GAAG,cAAc,CAAA;IAC1F,MAAM,QAAQ,GAAG,CACf,CAAY,EACZ,MAAe,EACf,SAAkB,EACO,EAAE,CAAC,CAAC;QAC7B,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;QACjC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO;QAC3B,IAAI;QACJ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC;QACvD,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QAC3C,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC;QACnD,MAAM;QACN,SAAS;QACT,QAAQ;KACT,CAAC,CAAA;IAEF,+FAA+F;IAC/F,+DAA+D;IAC/D,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAA;IACjG,MAAM,aAAa,GAAG,KAAK,EACzB,IAA0C,EAC1C,CAAY,EACZ,QAAuB,EACL,EAAE;QACpB,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAA;QAC1B,GAAG,CAAC,2CAA2C,EAAE,MAAM,CAAC,CAAA;QACxD,IAAI,CAAC;YACH,MAAM,YAAY,CAAC;gBACjB,OAAO,EAAE,UAAU,CAAC,MAAM;gBAC1B,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC;gBACzB,MAAM;gBACN,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,GAAG;gBACb,cAAc,EAAE,MAAM;aACvB,CAAC,CAAC,IAAI,CAAC;gBACN,IAAI,EAAE,mBAAmB;gBACzB,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,MAAM,EAAE,UAAU;gBAClB,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe;gBAC5C,QAAQ;gBACR,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;gBAC3C,yFAAyF;gBACzF,2CAA2C;gBAC3C,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC;aACpD,CAAC,CAAA;YACF,GAAG,CAAC,yCAAyC,EAAE,MAAM,CAAC,CAAA;YACtD,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CACD,iDAAiD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EACzG,MAAM,CACP,CAAA;YACD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC,CAAA;IACD,4FAA4F;IAC5F,MAAM,eAAe,GAAG,KAAK,EAAE,CAAY,EAAoB,EAAE;QAC/D,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAA;QAC/C,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAA;QAC3B,GAAG,CACD,yJAAyJ,EACzJ,MAAM,CACP,CAAA;QACD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,QAAQ,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;QAC3D,MAAM,GAAG,IAAI,CAAA;QACb,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,IAAI,KAAK,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnC,gFAAgF;QAChF,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;YAClE,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,CAAA;YAC/B,MAAM,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;QACD,OAAO,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC,KAAK,CAAC,CAAC,CAAA;IAC7D,CAAC;IAED,iGAAiG;IACjG,IAAI,KAAK,EAAE,CAAC;QACV,GAAG,CACD,2HAA2H,EAC3H,MAAM,CACP,CAAA;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK;QACpB,CAAC,CAAC,mCAAmC;QACrC,CAAC,CAAC,OAAO;YACP,CAAC,CAAC,yBAAyB,MAAM,CAAC,IAAI,GAAG;YACzC,CAAC,CAAC,mEAAmE,MAAM,CAAC,IAAI,GAAG,CAAA;IACvF,MAAM,OAAO,GAAG,KAAK;QACnB,CAAC,CAAC;YACE,GAAG,SAAS,CAAC,SAAS,CAAC,uCAAuC;YAC9D,GAAG,SAAS,CAAC,UAAU,CAAC,sDAAsD;YAC9E,mBAAmB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SACpC;QACH,CAAC,CAAC;YACE,GAAG,aAAa,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,CAAC,GAAG;YAC/C,4CAA4C;SAC7C,CAAA;IACL,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;QAChD,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;YACrB,GAAG,CACD,6BAA6B,aAAa,CAAC,OAAO,CAAC,eAAe,EAAE,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,EAClI,MAAM,CACP,CAAA;YACD,OAAO,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC,KAAK,CAAC,CAAC,CAAA;QAC7D,CAAC;QACD,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAA;IACH,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAA;IAC7B,GAAG,CAAC,4CAA4C,EAAE,MAAM,CAAC,CAAA;IACzD,8FAA8F;IAC9F,kCAAkC;IAClC,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC;QAChC,MAAM;QACN,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI;KACL,CAAC,CAAA;IAEF,2FAA2F;IAC3F,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC9D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,GAAG,CACD,WAAW,OAAO,CAAC,MAAM,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,2CAA2C,EAC1G,MAAM,CACP,CAAA;QACD,GAAG,CAAC,4CAA4C,EAAE,MAAM,CAAC,CAAA;IAC3D,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CACrE,CAAA;IACD,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAA;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,eAAe,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;IACjF,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;IACzB,MAAM,OAAO,GAAG,cAAc,CAAC;QAC7B,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,OAAO,EAAE,OAAO,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE;QACtE,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,QAAQ,CAAC,gBAAgB;QACnC,SAAS,EAAE,GAAG;QACd,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,gBAAgB,EAAE,SAAS;QAC3B,eAAe,EAAE,SAAS;QAC1B,UAAU;QACV,MAAM,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG;KACvB,CAAC,CAAA;IACF,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC;QACxC,UAAU;QACV,MAAM;QACN,IAAI;QACJ,KAAK,EAAE,QAAQ;QACf,IAAI;QACJ,OAAO;QACP,SAAS,EAAE,QAAQ;QACnB,KAAK,EAAE,IAAI;KACZ,CAAC,CAAA;IACF,MAAM,IAAI,GAAc;QACtB,QAAQ,EAAE,eAAe;QACzB,QAAQ;QACR,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,eAAe,EAAE,QAAQ,CAAC,eAAe;QACzC,SAAS;KACV,CAAA;IACD,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAChC,GAAG,CAAC,+DAA+D,EAAE,MAAM,CAAC,CAAA;IAE5E,iGAAiG;IACjG,iEAAiE;IACjE,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,OAAO,GAAG,CAAC,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CACnE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAC/C,CAAA;IACD,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAA;YACrF,GAAG,CAAC,iBAAiB,QAAQ,uDAAuD,EAAE,MAAM,CAAC,CAAA;QAC/F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CACD,YAAY,QAAQ,mCAAmC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,4EAA4E,EACzL,MAAM,CACP,CAAA;QACH,CAAC;IACH,CAAC;IACD,MAAM,gBAAgB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,CAAA;IAC7E,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,IAAI,IAAI,CAAC,CAAA;IACnF,MAAM,GAAG,IAAI,CAAA;IACb,IAAI,KAAK,EAAE,CAAC;QACV,2FAA2F;QAC3F,GAAG,CAAC,iCAAiC,EAAE,MAAM,CAAC,CAAA;QAC9C,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACxD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC;gBAC/B,KAAK;gBACL,UAAU;gBACV,OAAO,EAAE,IAAI;gBACb,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;gBACb,KAAK,EAAE,IAAI;aACZ,CAAC,CAAA;YACF,MAAM,KAAK,CAAC,IAAI,CAAC;gBACf,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAW;gBAC1B,QAAQ,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;gBAC7C,OAAO;aACR,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QACF,GAAG,CACD,uBAAuB,SAAS,CAAC,SAAS,CAAC,qBAAqB,SAAS,CAAC,UAAU,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EACzH,WAAW,CACZ,CAAA;IACH,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;AACxC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,SAAiB,EACjB,IAA2C;IAE3C,MAAM,IAAI,GAAG,SAAS,GAAG,QAAU,CAAA;IACnC,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,OAAO,CAAC;YAAE,OAAO,IAAI,CAAA;QAC5C,OAAO,oBAAoB,SAAS,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,8BAA8B,CAAA;IAC1G,CAAC;IACD,OAAO,oBAAoB,SAAS,CAAC,IAAI,CAAC,mEAAmE,CAAA;AAC/G,CAAC;AAED,iGAAiG;AACjG,KAAK,UAAU,gBAAgB,CAAC,CAK/B;IACC,MAAM,OAAO,GAAG,CAAC,MAAM,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CACrD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAC/D,CAAA;IACD,MAAM,IAAI,GAAG,CACX,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,EAAE,MAAM,WAAW,CACxB,CAAC,CAAC,MAAM,EACR,CAAC,CAAC,SAAS,CAAC,IAAI,EAChB,CAAC,CAAC,SAAS,CAAC,YAAY,EACxB,OAAO,CACR,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;KACpB,CAAC,CAAC,CACJ,CACF,CAAC,MAAM,CACN,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CACd,OAAO,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAC1F,CAAA;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAC7B,CAAC,CAAC,GAAG,CAAC,qFAAqF,CAAC,CAAA;IAC5F,KAAK,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;QAChG,CAAC,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,KAAK,OAAO,EAAE,KAAK,iBAAiB,OAAO,EAAE,CAAC,CAAA;IACjG,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,OAQ7C;IACC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,EAAE,CAAA;IAC9C,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAA;IAC5F,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAA;IAC1C,IAAI,CAAC,IAAI,EAAE,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;IAC7F,MAAM,UAAU,GACd,OAAO,CAAC,UAAU;QAClB,CAAC,MAAM,qBAAqB,CAAC,OAAO,CAAC,SAAS,IAAI,kBAAkB,EAAE,IAAI,CAAC,CAAC,CAAA;IAC9E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IAClE,2FAA2F;IAC3F,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;QACrC,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,GAAG,EAAE,WAAW;QAChB,YAAY,EAAE,aAAa;QAC3B,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;KACrB,CAAC,CAAA;IACF,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAChC,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAC1E,CAAA;IACD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC;QAC5B,MAAM;QACN,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;KACpD,CAAC,CAAA;IACF,OAAO,OAAO,CAAC,eAAe,CAAA;AAChC,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type CommitmentReference, type Mandate, type Signed } from '@avow-finance/spec';
|
|
2
|
+
import { type Address, type Hex } from 'viem';
|
|
3
|
+
/**
|
|
4
|
+
* What a sandbox keeps, each item apart. `business` holds the business's root key sealed under its
|
|
5
|
+
* passphrase, which only the runner opens. `agent` holds the agent's own key and the mandate it acts
|
|
6
|
+
* under. `supplier` holds the signing key the business quotes and accepts jobs with, and its
|
|
7
|
+
* registration as a sandbox supplier. Those two are all a job process reads. `state` holds the
|
|
8
|
+
* commitments the agent made. `request` holds the key of an agent that asked a business for
|
|
9
|
+
* authority and is waiting for the answer, so asking again after a restart keeps the same key.
|
|
10
|
+
*/
|
|
11
|
+
export type SandboxStoreItem = 'business' | 'agent' | 'supplier' | 'state' | 'request' | 'mailbox';
|
|
12
|
+
/**
|
|
13
|
+
* Where a sandbox keeps its items, as text. In Node it's the `.avow` folder of the working
|
|
14
|
+
* directory unless you pass a store, and that folder ignores itself in git.
|
|
15
|
+
*/
|
|
16
|
+
export interface SandboxStore {
|
|
17
|
+
read(item: SandboxStoreItem): Promise<string | null>;
|
|
18
|
+
write(item: SandboxStoreItem, text: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/** A store held in memory, for a test or a page that shouldn't keep anything. */
|
|
21
|
+
export declare function memoryStore(): SandboxStore;
|
|
22
|
+
/** A supplier the agent may book: its business id, and the URL of its adapter. */
|
|
23
|
+
export interface SandboxSupplier {
|
|
24
|
+
id: string;
|
|
25
|
+
url: string;
|
|
26
|
+
}
|
|
27
|
+
/** A sandbox business as Avow registered it, on the deployment it was made on. */
|
|
28
|
+
export interface StoredBusiness {
|
|
29
|
+
chainId: number;
|
|
30
|
+
apiUrl: string;
|
|
31
|
+
factory: Address;
|
|
32
|
+
token: Address;
|
|
33
|
+
account: Address;
|
|
34
|
+
lock: Address;
|
|
35
|
+
businessId: string;
|
|
36
|
+
}
|
|
37
|
+
/** The agent's item: its own key, and the mandate the business signed for it. */
|
|
38
|
+
export interface AgentItem {
|
|
39
|
+
agentKey: Hex;
|
|
40
|
+
business: StoredBusiness;
|
|
41
|
+
mandate: Signed<Mandate>;
|
|
42
|
+
mandateHash: Hex;
|
|
43
|
+
keyAuthorizedIn: Hex;
|
|
44
|
+
suppliers: SandboxSupplier[];
|
|
45
|
+
}
|
|
46
|
+
/** A commitment the agent made, with the mandate it was made under. */
|
|
47
|
+
export interface StoredCommitment {
|
|
48
|
+
reference: CommitmentReference;
|
|
49
|
+
/** The reserve, in micros. */
|
|
50
|
+
amount: bigint;
|
|
51
|
+
supplier: string;
|
|
52
|
+
mandateHash: Hex;
|
|
53
|
+
/** Unix seconds. */
|
|
54
|
+
madeAt: bigint;
|
|
55
|
+
}
|
|
56
|
+
export declare const isAddressText: (v: unknown) => v is Address;
|
|
57
|
+
export declare const isRecord: (v: unknown) => v is Record<string, unknown>;
|
|
58
|
+
export declare function readJson(text: string, item: SandboxStoreItem): Record<string, unknown>;
|
|
59
|
+
export declare const write: (store: SandboxStore, item: SandboxStoreItem, value: object) => Promise<void>;
|
|
60
|
+
export declare function readBusiness(json: unknown): StoredBusiness | null;
|
|
61
|
+
/** The agent's item, or null when the business hasn't enrolled an agent. */
|
|
62
|
+
export declare function loadAgentItem(store: SandboxStore): Promise<AgentItem | null>;
|
|
63
|
+
export declare const saveAgentItem: (store: SandboxStore, item: AgentItem) => Promise<void>;
|
|
64
|
+
/** The commitments the agent made, as far as each still parses. */
|
|
65
|
+
export declare function loadCommitments(store: SandboxStore): Promise<StoredCommitment[]>;
|
|
66
|
+
export declare const saveCommitments: (store: SandboxStore, commitments: readonly StoredCommitment[]) => Promise<void>;
|
|
67
|
+
/** Adds one commitment, reading the list again first so another process's addition isn't lost. */
|
|
68
|
+
export declare function addCommitment(store: SandboxStore, c: StoredCommitment): Promise<void>;
|
|
69
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/sandbox/store.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,OAAO,EAIZ,KAAK,MAAM,EAEZ,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,GAAG,EAAa,MAAM,MAAM,CAAA;AAExD;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAA;AAElG;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACpD,KAAK,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3D;AAED,iFAAiF;AACjF,wBAAgB,WAAW,IAAI,YAAY,CAQ1C;AAED,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,OAAO,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,GAAG,CAAA;IACb,QAAQ,EAAE,cAAc,CAAA;IACxB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IACxB,WAAW,EAAE,GAAG,CAAA;IAChB,eAAe,EAAE,GAAG,CAAA;IACpB,SAAS,EAAE,eAAe,EAAE,CAAA;CAC7B;AAED,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,mBAAmB,CAAA;IAC9B,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,GAAG,CAAA;IAChB,oBAAoB;IACpB,MAAM,EAAE,MAAM,CAAA;CACf;AAGD,eAAO,MAAM,aAAa,MAAO,OAAO,KAAG,CAAC,IAAI,OAAgD,CAAA;AAChG,eAAO,MAAM,QAAQ,MAAO,OAAO,KAAG,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACP,CAAA;AAE1D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUtF;AAED,eAAO,MAAM,KAAK,UAAW,YAAY,QAAQ,gBAAgB,SAAS,MAAM,kBACK,CAAA;AAErF,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAWjE;AAWD,4EAA4E;AAC5E,wBAAsB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA4BlF;AAED,eAAO,MAAM,aAAa,UAAW,YAAY,QAAQ,SAAS,kBAAgC,CAAA;AAElG,mEAAmE;AACnE,wBAAsB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA8BtF;AAED,eAAO,MAAM,eAAe,UAAW,YAAY,eAAe,SAAS,gBAAgB,EAAE,kBACrD,CAAA;AAExC,kGAAkG;AAClG,wBAAsB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3F"}
|