@absol-labs/agent 0.5.0 → 0.6.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/README.md CHANGED
@@ -271,6 +271,7 @@ await server.listen(8787);
271
271
 
272
272
  Or run the ready-made standalone server from env (`METRIK_GATEWAY_ESCROW_ADDRESS`,
273
273
  `METRIK_GATEWAY_RPC_URL`, `METRIK_GATEWAY_SERVICE_REF`, `METRIK_GATEWAY_UPSTREAM_URL`,
274
+ optional comma-separated `METRIK_GATEWAY_SERVICE_REFS` migration aliases,
274
275
  optional `METRIK_GATEWAY_CHAIN_ID` / `METRIK_GATEWAY_PORT` / `METRIK_GATEWAY_HOST`):
275
276
 
276
277
  ```bash
@@ -289,7 +290,11 @@ directly:
289
290
 
290
291
  ```ts
291
292
  import { privateKeyToAccount } from "viem/accounts";
292
- import { createSdkInvokeStreamReader, invoke } from "@absol-labs/agent";
293
+ import {
294
+ createSdkInvokeStreamReader,
295
+ discoverServices,
296
+ invoke,
297
+ } from "@absol-labs/agent";
293
298
 
294
299
  const buyer = privateKeyToAccount(
295
300
  process.env.METRIK_AGENT_PRIVATE_KEY as `0x${string}`,
@@ -298,6 +303,11 @@ const streamReader = createSdkInvokeStreamReader({
298
303
  escrowAddress: "0x...",
299
304
  rpcUrl: process.env.METRIK_AGENT_RPC_URL!,
300
305
  });
306
+ const { serviceRef } = await streamReader.getStreamV2(streamId);
307
+ const listing = (await discoverServices()).find(
308
+ (service) => service.serviceRef.toLowerCase() === serviceRef.toLowerCase(),
309
+ );
310
+ if (!listing) throw new Error("verified signed listing unavailable");
301
311
 
302
312
  const { response } = await invoke(
303
313
  streamId, // from hireVerifiedService()
@@ -310,7 +320,7 @@ const { response } = await invoke(
310
320
  streamReader,
311
321
  buyer,
312
322
  domain: { chainId: 84532, verifyingContract: "0x..." }, // same escrow as above
313
- serviceBaseUrl: "https://gateway.example.com", // the seller's gateway, not the real upstream
323
+ listing, // verified signature + signed callerAuth.accessUrl; no manual credential/URL
314
324
  },
315
325
  );
316
326
 
@@ -323,30 +333,43 @@ capability scoped to exactly that one `method`+`path` (short expiry, single-use
323
333
  and attaches it as the `x-metrik-capability` header. Use `capabilityFor()` directly if
324
334
  you only need the signed capability without the SDK also performing the `fetch`.
325
335
 
326
- For a T2 (consumer-zkTLS) service, `invokeWithT2DeliveryProof()` attaches the SAME
336
+ For a public T2 (consumer-zkTLS) service, `invokeWithT2DeliveryProof()` attaches the SAME
327
337
  capability to the exact request the buyer's Reclaim attestor proves, so the
328
338
  capability-authorized call IS the delivery evidence - usage and proof become one action:
329
339
 
330
340
  ```ts
331
- import { invokeWithT2DeliveryProof } from "@absol-labs/agent";
341
+ import { discoverServices, invokeWithT2DeliveryProof } from "@absol-labs/agent";
342
+
343
+ const { serviceRef: t2ServiceRef } = await streamReader.getStreamV2(streamId);
344
+ const publicT2Listing = (await discoverServices()).find(
345
+ (service) => service.serviceRef.toLowerCase() === t2ServiceRef.toLowerCase(),
346
+ );
347
+ if (!publicT2Listing || publicT2Listing.access !== "public") {
348
+ throw new Error("verified public T2 listing unavailable");
349
+ }
332
350
 
333
351
  const { t2 } = await invokeWithT2DeliveryProof(streamId, {
334
352
  streamReader,
335
353
  buyer,
336
354
  domain: { chainId: 84532, verifyingContract: "0x..." },
337
355
  request: {
338
- url: "https://gateway.example.com/v1/infer",
356
+ url: "https://public-t2-service.example.com/v1/infer",
339
357
  method: "POST",
340
358
  responseMatches: [{ type: "regex", value: '"result":"(?<result>.*)"' }],
341
359
  nonceInjection: { in: "query", name: "nonce" },
342
360
  },
343
361
  intervalIndex: 0n,
344
362
  nonce: deliveryNonce, // from GET /delivery/nonce
363
+ listing: publicT2Listing,
345
364
  });
346
365
 
347
366
  // t2.body is the exact POST /delivery/proof request payload.
348
367
  ```
349
368
 
369
+ Gated consumer-attested invocation fails closed for now: proof-target pinning does
370
+ not yet distinguish the public oracle origin from a signed access gateway. Gated
371
+ services use output-probe verification until that protocol support exists.
372
+
350
373
  ## Consumer zkTLS (delivery proofs)
351
374
 
352
375
  `ReclaimConsumerProofService` (and `createReclaimConsumerProofServiceFromEnv`) generate a
@@ -1,3 +1,4 @@
1
+ import { type SignedServiceBinding, type SignedServiceDescriptor } from "@absol-labs/shared";
1
2
  /**
2
3
  * Service discovery for the Metrik verified-service marketplace.
3
4
  *
@@ -26,9 +27,14 @@ export interface ServiceListing {
26
27
  readonly serviceRef: `0x${string}`;
27
28
  readonly operator: `0x${string}`;
28
29
  readonly publicUrl: string;
30
+ readonly access: "public" | "gated";
31
+ /** Signed invocation origin; gated listings fail closed if this is absent. */
32
+ readonly accessUrl: string;
33
+ /** The schema-validated and cryptographically verified signed record. */
34
+ readonly signed: SignedServiceBinding | SignedServiceDescriptor;
29
35
  /** Unsigned informational category from the listings row (may be absent). */
30
36
  readonly category: string | null;
31
- /** Optional signed operator-supplied target metadata (e.g. resolver hints). */
37
+ /** Optional unsigned operator-supplied resolver hints; never used for invocation. */
32
38
  readonly targetMetadata?: Record<string, string>;
33
39
  }
34
40
  export interface DiscoverServicesOptions {
@@ -63,12 +69,14 @@ export interface DiscoverServicesOptions {
63
69
  */
64
70
  export declare const DEFAULT_METRIK_REGISTRY_URL = "https://pzvnacjolaipeobmptsb.supabase.co/rest/v1/listings?select=service_ref,operator,public_url,category,signed_binding&order=created_at.desc";
65
71
  /**
66
- * `serviceRef` of the built-in verified demo listing. Kept as a named constant so
72
+ * `serviceRef` of the built-in verified live-data listing. Kept as a named constant so
67
73
  * callers can recognise (and dedupe against) the seeded row.
68
74
  */
69
- export declare const DEMO_SEED_SERVICE_REF: "0x84ef78c5ac9fc084422dc2d3e1ef19623bb05d0d81c097d4da49f9c47ec3ed12";
75
+ export declare const LIVE_DATA_SEED_SERVICE_REF: "0x79e57358e98a35273c1cd9d5f1bf9ae1e0af8705db432eb706459dc4f88b6fe0";
76
+ /** @deprecated Use {@link LIVE_DATA_SEED_SERVICE_REF}. */
77
+ export declare const DEMO_SEED_SERVICE_REF: "0x79e57358e98a35273c1cd9d5f1bf9ae1e0af8705db432eb706459dc4f88b6fe0";
70
78
  /**
71
- * A REAL, operator-signed demo listing row embedded so `discoverServices()` returns
79
+ * A real, operator-signed live-data listing row embedded so `discoverServices()` returns
72
80
  * something hireable with ZERO configuration (no Supabase anon key, no registry URL).
73
81
  *
74
82
  * This is PUBLIC data — a signed {@link https://github.com/Absol-Labs | Metrik}
@@ -79,20 +87,257 @@ export declare const DEMO_SEED_SERVICE_REF: "0x84ef78c5ac9fc084422dc2d3e1ef19623
79
87
  * with any field here and the seed silently drops itself, identically to a bad
80
88
  * registry row. The `category` column is unsigned informational metadata only.
81
89
  */
90
+ export declare const LIVE_DATA_SEED_LISTING: {
91
+ readonly service_ref: "0x79e57358e98a35273c1cd9d5f1bf9ae1e0af8705db432eb706459dc4f88b6fe0";
92
+ readonly operator: "0xB3e162711920dFD8933609019Dc35C73cC1a09F0";
93
+ readonly public_url: "https://livedata.137.23.50.249.sslip.io";
94
+ readonly category: "live-data";
95
+ readonly signed_binding: {
96
+ readonly serviceRef: "0x79e57358e98a35273c1cd9d5f1bf9ae1e0af8705db432eb706459dc4f88b6fe0";
97
+ readonly descriptor: {
98
+ readonly version: 3;
99
+ readonly operator: "0xB3e162711920dFD8933609019Dc35C73cC1a09F0";
100
+ readonly publicUrl: "https://livedata.137.23.50.249.sslip.io";
101
+ readonly issuedAt: 1787772057;
102
+ readonly interface: {
103
+ readonly baseUrl: "https://livedata.137.23.50.249.sslip.io";
104
+ readonly healthPath: "/health";
105
+ readonly endpoints: readonly [{
106
+ readonly name: "health";
107
+ readonly path: "/health";
108
+ readonly method: "GET";
109
+ readonly description: "Liveness probe.";
110
+ }, {
111
+ readonly name: "readiness";
112
+ readonly path: "/readiness";
113
+ readonly method: "GET";
114
+ readonly description: "Non-value dependency readiness backed by the same real BTC cache policy.";
115
+ }, {
116
+ readonly name: "price";
117
+ readonly path: "/price";
118
+ readonly method: "GET";
119
+ readonly description: "Real live crypto spot price (?symbol=BTC|ETH|SOL) from CoinGecko's public API.";
120
+ }];
121
+ readonly authModel: "caller-auth";
122
+ readonly example: {
123
+ readonly endpoint: "price";
124
+ readonly request: {
125
+ readonly symbol: "BTC";
126
+ };
127
+ readonly response: {
128
+ readonly symbol: "BTC";
129
+ readonly source: "coingecko-public-api";
130
+ };
131
+ readonly description: "Real, nondeterministic live price — no re-execution guarantee.";
132
+ };
133
+ readonly expectedStatuses: readonly [200];
134
+ };
135
+ readonly verification: {
136
+ readonly canaries: readonly [{
137
+ readonly path: "/readiness";
138
+ readonly method: "GET";
139
+ readonly matcher: {
140
+ readonly type: "json-field-equals";
141
+ readonly field: "source";
142
+ readonly expected: "coingecko-public-api";
143
+ };
144
+ readonly nonce: {
145
+ readonly inject: {
146
+ readonly in: "query";
147
+ readonly name: "nonce";
148
+ };
149
+ readonly echo: {
150
+ readonly from: "json-path";
151
+ readonly path: "nonce";
152
+ };
153
+ };
154
+ }, {
155
+ readonly path: "/canary";
156
+ readonly method: "GET";
157
+ readonly matcher: {
158
+ readonly type: "includes";
159
+ readonly expected: "metrik-canary:live-data:";
160
+ };
161
+ readonly nonce: {
162
+ readonly inject: {
163
+ readonly in: "query";
164
+ readonly name: "nonce";
165
+ };
166
+ readonly echo: {
167
+ readonly from: "json-path";
168
+ readonly path: "nonce";
169
+ };
170
+ };
171
+ }];
172
+ readonly schema: {
173
+ readonly path: "/readiness?nonce=metrik-schema";
174
+ readonly required: readonly [{
175
+ readonly pointer: "ready";
176
+ readonly type: "boolean";
177
+ }, {
178
+ readonly pointer: "source";
179
+ readonly type: "string";
180
+ readonly nonEmpty: true;
181
+ }, {
182
+ readonly pointer: "fetchedAt";
183
+ readonly type: "string";
184
+ readonly nonEmpty: true;
185
+ }, {
186
+ readonly pointer: "priceAgeMs";
187
+ readonly type: "number";
188
+ }, {
189
+ readonly pointer: "freshness";
190
+ readonly type: "string";
191
+ readonly nonEmpty: true;
192
+ }];
193
+ };
194
+ readonly sla: {
195
+ readonly maxLatencyMs: 5000;
196
+ readonly freshnessSeconds: 60;
197
+ };
198
+ };
199
+ readonly commercial: {
200
+ readonly minRatePerSecond: "100";
201
+ readonly maxRatePerSecond: "10000";
202
+ readonly currency: "USDC";
203
+ readonly slaDescription: "Failed or unproven intervals do not advance verified cumulative entitlement; the stream remains active until buyer close or expiry.";
204
+ readonly refundPolicy: "The buyer reclaims unspent escrow using the latest checkpoint after close/expiry, or the unverified escape path after its grace window.";
205
+ };
206
+ readonly access: "gated";
207
+ readonly callerAuth: {
208
+ readonly mechanism: "on-chain";
209
+ readonly role: "buyer";
210
+ readonly accessUrl: "https://gateway.137.23.50.249.sslip.io";
211
+ };
212
+ };
213
+ readonly signature: "0x2f4d2784eb40b1542517bc19f12534fb2e97da4ade5a3ff56193fcfb97fbef921309f77af3445e336cb07a4379011b080bba700033a098f672b0b2f096197f161b";
214
+ };
215
+ };
216
+ /** @deprecated Use {@link LIVE_DATA_SEED_LISTING}. */
82
217
  export declare const DEMO_SEED_LISTING: {
83
- readonly service_ref: "0x84ef78c5ac9fc084422dc2d3e1ef19623bb05d0d81c097d4da49f9c47ec3ed12";
84
- readonly operator: "0x28ea4eF61ac4cca3ed6a64dBb5b2D4be1aDC9814";
85
- readonly public_url: "https://metrik-demo-service.vercel.app";
86
- readonly category: "demo";
218
+ readonly service_ref: "0x79e57358e98a35273c1cd9d5f1bf9ae1e0af8705db432eb706459dc4f88b6fe0";
219
+ readonly operator: "0xB3e162711920dFD8933609019Dc35C73cC1a09F0";
220
+ readonly public_url: "https://livedata.137.23.50.249.sslip.io";
221
+ readonly category: "live-data";
87
222
  readonly signed_binding: {
88
- readonly serviceRef: "0x84ef78c5ac9fc084422dc2d3e1ef19623bb05d0d81c097d4da49f9c47ec3ed12";
89
- readonly binding: {
90
- readonly version: 2;
91
- readonly operator: "0x28ea4eF61ac4cca3ed6a64dBb5b2D4be1aDC9814";
92
- readonly publicUrl: "https://metrik-demo-service.vercel.app";
93
- readonly issuedAt: 1787500000;
223
+ readonly serviceRef: "0x79e57358e98a35273c1cd9d5f1bf9ae1e0af8705db432eb706459dc4f88b6fe0";
224
+ readonly descriptor: {
225
+ readonly version: 3;
226
+ readonly operator: "0xB3e162711920dFD8933609019Dc35C73cC1a09F0";
227
+ readonly publicUrl: "https://livedata.137.23.50.249.sslip.io";
228
+ readonly issuedAt: 1787772057;
229
+ readonly interface: {
230
+ readonly baseUrl: "https://livedata.137.23.50.249.sslip.io";
231
+ readonly healthPath: "/health";
232
+ readonly endpoints: readonly [{
233
+ readonly name: "health";
234
+ readonly path: "/health";
235
+ readonly method: "GET";
236
+ readonly description: "Liveness probe.";
237
+ }, {
238
+ readonly name: "readiness";
239
+ readonly path: "/readiness";
240
+ readonly method: "GET";
241
+ readonly description: "Non-value dependency readiness backed by the same real BTC cache policy.";
242
+ }, {
243
+ readonly name: "price";
244
+ readonly path: "/price";
245
+ readonly method: "GET";
246
+ readonly description: "Real live crypto spot price (?symbol=BTC|ETH|SOL) from CoinGecko's public API.";
247
+ }];
248
+ readonly authModel: "caller-auth";
249
+ readonly example: {
250
+ readonly endpoint: "price";
251
+ readonly request: {
252
+ readonly symbol: "BTC";
253
+ };
254
+ readonly response: {
255
+ readonly symbol: "BTC";
256
+ readonly source: "coingecko-public-api";
257
+ };
258
+ readonly description: "Real, nondeterministic live price — no re-execution guarantee.";
259
+ };
260
+ readonly expectedStatuses: readonly [200];
261
+ };
262
+ readonly verification: {
263
+ readonly canaries: readonly [{
264
+ readonly path: "/readiness";
265
+ readonly method: "GET";
266
+ readonly matcher: {
267
+ readonly type: "json-field-equals";
268
+ readonly field: "source";
269
+ readonly expected: "coingecko-public-api";
270
+ };
271
+ readonly nonce: {
272
+ readonly inject: {
273
+ readonly in: "query";
274
+ readonly name: "nonce";
275
+ };
276
+ readonly echo: {
277
+ readonly from: "json-path";
278
+ readonly path: "nonce";
279
+ };
280
+ };
281
+ }, {
282
+ readonly path: "/canary";
283
+ readonly method: "GET";
284
+ readonly matcher: {
285
+ readonly type: "includes";
286
+ readonly expected: "metrik-canary:live-data:";
287
+ };
288
+ readonly nonce: {
289
+ readonly inject: {
290
+ readonly in: "query";
291
+ readonly name: "nonce";
292
+ };
293
+ readonly echo: {
294
+ readonly from: "json-path";
295
+ readonly path: "nonce";
296
+ };
297
+ };
298
+ }];
299
+ readonly schema: {
300
+ readonly path: "/readiness?nonce=metrik-schema";
301
+ readonly required: readonly [{
302
+ readonly pointer: "ready";
303
+ readonly type: "boolean";
304
+ }, {
305
+ readonly pointer: "source";
306
+ readonly type: "string";
307
+ readonly nonEmpty: true;
308
+ }, {
309
+ readonly pointer: "fetchedAt";
310
+ readonly type: "string";
311
+ readonly nonEmpty: true;
312
+ }, {
313
+ readonly pointer: "priceAgeMs";
314
+ readonly type: "number";
315
+ }, {
316
+ readonly pointer: "freshness";
317
+ readonly type: "string";
318
+ readonly nonEmpty: true;
319
+ }];
320
+ };
321
+ readonly sla: {
322
+ readonly maxLatencyMs: 5000;
323
+ readonly freshnessSeconds: 60;
324
+ };
325
+ };
326
+ readonly commercial: {
327
+ readonly minRatePerSecond: "100";
328
+ readonly maxRatePerSecond: "10000";
329
+ readonly currency: "USDC";
330
+ readonly slaDescription: "Failed or unproven intervals do not advance verified cumulative entitlement; the stream remains active until buyer close or expiry.";
331
+ readonly refundPolicy: "The buyer reclaims unspent escrow using the latest checkpoint after close/expiry, or the unverified escape path after its grace window.";
332
+ };
333
+ readonly access: "gated";
334
+ readonly callerAuth: {
335
+ readonly mechanism: "on-chain";
336
+ readonly role: "buyer";
337
+ readonly accessUrl: "https://gateway.137.23.50.249.sslip.io";
338
+ };
94
339
  };
95
- readonly signature: "0x17917e96836a63238d0abe70c8c55081c4d694ad43311cdb3ea91dad349827fa6480657be2362e0b7f0524a0ee4ba0c48068255c3423a965392724874d244cd21b";
340
+ readonly signature: "0x2f4d2784eb40b1542517bc19f12534fb2e97da4ade5a3ff56193fcfb97fbef921309f77af3445e336cb07a4379011b080bba700033a098f672b0b2f096197f161b";
96
341
  };
97
342
  };
98
343
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/discovery/registry.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;qEACqE;AACrE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,KAAK,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,uBAAuB;IACtC;4FACwF;IACxF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;wFAIoF;IACpF,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;uEACmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC1D;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,mJAC0G,CAAC;AAInJ;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAChC,oEAA6E,CAAC;AAEhF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;CAgBpB,CAAC;AAkCX;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,cAAc,EAAE,CAAC,CA6E3B"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/discovery/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC7B,MAAM,oBAAoB,CAAC;AAI5B;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;qEACqE;AACrE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,KAAK,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpC,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,GAAG,uBAAuB,CAAC;IAChE,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,qFAAqF;IACrF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,uBAAuB;IACtC;4FACwF;IACxF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;wFAIoF;IACpF,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;uEACmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC1D;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,mJAC0G,CAAC;AAInJ;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EACrC,oEAA6E,CAAC;AAChF,0DAA0D;AAC1D,eAAO,MAAM,qBAAqB,sEAA6B,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0GzB,CAAC;AACX,sDAAsD;AACtD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAyB,CAAC;AA+CxD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,cAAc,EAAE,CAAC,CA6E3B"}