@singularity-layer/grid 0.7.0 → 0.8.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/dist/index.d.mts +81 -1
- package/dist/index.d.ts +81 -1
- package/dist/index.js +183 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +177 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -344,6 +344,86 @@ declare class GridClient {
|
|
|
344
344
|
}): Promise<ProcessorLogsResponse>;
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Agent Vault — zero-knowledge encrypted agent backup/restore.
|
|
349
|
+
*
|
|
350
|
+
* Pure-JS envelope (noble scrypt + AES-256-GCM), byte-compatible with the
|
|
351
|
+
* agentvault CLI, the pod runner, and the Python SDK:
|
|
352
|
+
* `[4-byte BE header length][JSON header][GCM body, tag appended]`, with the
|
|
353
|
+
* snapshot identity bound into the GCM AAD. Runs in Node AND browsers.
|
|
354
|
+
*
|
|
355
|
+
* Scope: this module encrypts/decrypts BYTES and drives the API. Packing a
|
|
356
|
+
* directory into a tarball is filesystem work — use the `agentvault` CLI or
|
|
357
|
+
* the Python SDK for that, or bring your own archive bytes.
|
|
358
|
+
*
|
|
359
|
+
* Auth: a Singularity compute API key (X-API-Key). Passphrases and plaintext
|
|
360
|
+
* never leave this process.
|
|
361
|
+
*/
|
|
362
|
+
declare const VAULT_URL = "https://compute.x402layer.cc";
|
|
363
|
+
interface VaultAad {
|
|
364
|
+
userId: string;
|
|
365
|
+
agentId: string;
|
|
366
|
+
backupId: string;
|
|
367
|
+
formatVersion: 1;
|
|
368
|
+
}
|
|
369
|
+
/** Envelope-encrypt arbitrary bytes under a passphrase (scrypt + AES-256-GCM). */
|
|
370
|
+
declare function encryptEnvelope(plaintext: Uint8Array, passphrase: string, aad: VaultAad): Uint8Array;
|
|
371
|
+
/** Reverse of encryptEnvelope. Throws on wrong passphrase or AAD mismatch. */
|
|
372
|
+
declare function decryptEnvelope(blob: Uint8Array, passphrase: string, aad: VaultAad): Uint8Array;
|
|
373
|
+
declare function parseAadFromKey(r2Key: string): VaultAad;
|
|
374
|
+
interface VaultAgent {
|
|
375
|
+
id: string;
|
|
376
|
+
name: string;
|
|
377
|
+
framework: string;
|
|
378
|
+
source: "local" | "pod";
|
|
379
|
+
pod_order_id: string | null;
|
|
380
|
+
}
|
|
381
|
+
interface VaultSnapshot {
|
|
382
|
+
id: string;
|
|
383
|
+
agent_id: string;
|
|
384
|
+
size_bytes: number;
|
|
385
|
+
sha256: string | null;
|
|
386
|
+
created_at: string;
|
|
387
|
+
}
|
|
388
|
+
interface VaultUsage {
|
|
389
|
+
plan: "free" | "pro";
|
|
390
|
+
planRenewsAt: string | null;
|
|
391
|
+
bytesUsed: number;
|
|
392
|
+
bytesReserved: number;
|
|
393
|
+
maxBytes: number;
|
|
394
|
+
proPriceUsd: number;
|
|
395
|
+
}
|
|
396
|
+
interface VaultClientOptions {
|
|
397
|
+
apiKey: string;
|
|
398
|
+
baseUrl?: string;
|
|
399
|
+
fetchImpl?: typeof fetch;
|
|
400
|
+
}
|
|
401
|
+
declare class VaultClient {
|
|
402
|
+
private readonly base;
|
|
403
|
+
private readonly apiKey;
|
|
404
|
+
private readonly fetchImpl;
|
|
405
|
+
constructor(options: VaultClientOptions);
|
|
406
|
+
private static id;
|
|
407
|
+
private call;
|
|
408
|
+
agents(): Promise<VaultAgent[]>;
|
|
409
|
+
createAgent(name: string, framework: string): Promise<VaultAgent>;
|
|
410
|
+
snapshots(agentId?: string): Promise<VaultSnapshot[]>;
|
|
411
|
+
usage(): Promise<VaultUsage>;
|
|
412
|
+
/** Activate Vault Pro ($3/mo from credits). */
|
|
413
|
+
subscribePro(): Promise<{
|
|
414
|
+
ok: boolean;
|
|
415
|
+
already?: boolean;
|
|
416
|
+
}>;
|
|
417
|
+
deleteSnapshot(id: string): Promise<void>;
|
|
418
|
+
/**
|
|
419
|
+
* Encrypt + upload arbitrary payload bytes (e.g. a tarball you packed) as a
|
|
420
|
+
* snapshot of `agentId`. Returns the snapshot id.
|
|
421
|
+
*/
|
|
422
|
+
backupBytes(agentId: string, payload: Uint8Array, passphrase: string): Promise<string>;
|
|
423
|
+
/** Download + decrypt a snapshot's payload bytes. */
|
|
424
|
+
restoreBytes(snapshotId: string, passphrase: string): Promise<Uint8Array>;
|
|
425
|
+
}
|
|
426
|
+
|
|
347
427
|
declare class SGLError extends Error {
|
|
348
428
|
constructor(message: string);
|
|
349
429
|
}
|
|
@@ -362,4 +442,4 @@ declare class SGLConnectionError extends SGLError {
|
|
|
362
442
|
constructor(message: string);
|
|
363
443
|
}
|
|
364
444
|
|
|
365
|
-
export { type Attestation, type AttestationProof, type CapacityResponse, type ChatChoice, type ChatCompletionRequest, type ChatCompletionResponse, type ChatContentPart, type ChatMessage, DEFAULT_BASE_URL, type DeployProcessorOptions, type EmbeddingDatum, type EmbeddingRequest, type EmbeddingResponse, GridClient, type GridClientOptions, type JobResponse, type JobResult, type JobSubmission, type ModelInfo, type ModelPricing, type PricingInfo, type ProcessorDeployResult, type ProcessorInfo, type ProcessorInvokeResult, type ProcessorListResponse, type ProcessorLogEntry, type ProcessorLogsResponse, type ReserveResponse, SGLAPIError, SGLAuthError, SGLConnectionError, SGLError, SGLNotFoundError, type TeeCapacity, type WalletAuth };
|
|
445
|
+
export { type Attestation, type AttestationProof, type CapacityResponse, type ChatChoice, type ChatCompletionRequest, type ChatCompletionResponse, type ChatContentPart, type ChatMessage, DEFAULT_BASE_URL, type DeployProcessorOptions, type EmbeddingDatum, type EmbeddingRequest, type EmbeddingResponse, GridClient, type GridClientOptions, type JobResponse, type JobResult, type JobSubmission, type ModelInfo, type ModelPricing, type PricingInfo, type ProcessorDeployResult, type ProcessorInfo, type ProcessorInvokeResult, type ProcessorListResponse, type ProcessorLogEntry, type ProcessorLogsResponse, type ReserveResponse, SGLAPIError, SGLAuthError, SGLConnectionError, SGLError, SGLNotFoundError, type TeeCapacity, VAULT_URL, type VaultAad, type VaultAgent, VaultClient, type VaultClientOptions, type VaultSnapshot, type VaultUsage, type WalletAuth, decryptEnvelope, encryptEnvelope, parseAadFromKey };
|
package/dist/index.d.ts
CHANGED
|
@@ -344,6 +344,86 @@ declare class GridClient {
|
|
|
344
344
|
}): Promise<ProcessorLogsResponse>;
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Agent Vault — zero-knowledge encrypted agent backup/restore.
|
|
349
|
+
*
|
|
350
|
+
* Pure-JS envelope (noble scrypt + AES-256-GCM), byte-compatible with the
|
|
351
|
+
* agentvault CLI, the pod runner, and the Python SDK:
|
|
352
|
+
* `[4-byte BE header length][JSON header][GCM body, tag appended]`, with the
|
|
353
|
+
* snapshot identity bound into the GCM AAD. Runs in Node AND browsers.
|
|
354
|
+
*
|
|
355
|
+
* Scope: this module encrypts/decrypts BYTES and drives the API. Packing a
|
|
356
|
+
* directory into a tarball is filesystem work — use the `agentvault` CLI or
|
|
357
|
+
* the Python SDK for that, or bring your own archive bytes.
|
|
358
|
+
*
|
|
359
|
+
* Auth: a Singularity compute API key (X-API-Key). Passphrases and plaintext
|
|
360
|
+
* never leave this process.
|
|
361
|
+
*/
|
|
362
|
+
declare const VAULT_URL = "https://compute.x402layer.cc";
|
|
363
|
+
interface VaultAad {
|
|
364
|
+
userId: string;
|
|
365
|
+
agentId: string;
|
|
366
|
+
backupId: string;
|
|
367
|
+
formatVersion: 1;
|
|
368
|
+
}
|
|
369
|
+
/** Envelope-encrypt arbitrary bytes under a passphrase (scrypt + AES-256-GCM). */
|
|
370
|
+
declare function encryptEnvelope(plaintext: Uint8Array, passphrase: string, aad: VaultAad): Uint8Array;
|
|
371
|
+
/** Reverse of encryptEnvelope. Throws on wrong passphrase or AAD mismatch. */
|
|
372
|
+
declare function decryptEnvelope(blob: Uint8Array, passphrase: string, aad: VaultAad): Uint8Array;
|
|
373
|
+
declare function parseAadFromKey(r2Key: string): VaultAad;
|
|
374
|
+
interface VaultAgent {
|
|
375
|
+
id: string;
|
|
376
|
+
name: string;
|
|
377
|
+
framework: string;
|
|
378
|
+
source: "local" | "pod";
|
|
379
|
+
pod_order_id: string | null;
|
|
380
|
+
}
|
|
381
|
+
interface VaultSnapshot {
|
|
382
|
+
id: string;
|
|
383
|
+
agent_id: string;
|
|
384
|
+
size_bytes: number;
|
|
385
|
+
sha256: string | null;
|
|
386
|
+
created_at: string;
|
|
387
|
+
}
|
|
388
|
+
interface VaultUsage {
|
|
389
|
+
plan: "free" | "pro";
|
|
390
|
+
planRenewsAt: string | null;
|
|
391
|
+
bytesUsed: number;
|
|
392
|
+
bytesReserved: number;
|
|
393
|
+
maxBytes: number;
|
|
394
|
+
proPriceUsd: number;
|
|
395
|
+
}
|
|
396
|
+
interface VaultClientOptions {
|
|
397
|
+
apiKey: string;
|
|
398
|
+
baseUrl?: string;
|
|
399
|
+
fetchImpl?: typeof fetch;
|
|
400
|
+
}
|
|
401
|
+
declare class VaultClient {
|
|
402
|
+
private readonly base;
|
|
403
|
+
private readonly apiKey;
|
|
404
|
+
private readonly fetchImpl;
|
|
405
|
+
constructor(options: VaultClientOptions);
|
|
406
|
+
private static id;
|
|
407
|
+
private call;
|
|
408
|
+
agents(): Promise<VaultAgent[]>;
|
|
409
|
+
createAgent(name: string, framework: string): Promise<VaultAgent>;
|
|
410
|
+
snapshots(agentId?: string): Promise<VaultSnapshot[]>;
|
|
411
|
+
usage(): Promise<VaultUsage>;
|
|
412
|
+
/** Activate Vault Pro ($3/mo from credits). */
|
|
413
|
+
subscribePro(): Promise<{
|
|
414
|
+
ok: boolean;
|
|
415
|
+
already?: boolean;
|
|
416
|
+
}>;
|
|
417
|
+
deleteSnapshot(id: string): Promise<void>;
|
|
418
|
+
/**
|
|
419
|
+
* Encrypt + upload arbitrary payload bytes (e.g. a tarball you packed) as a
|
|
420
|
+
* snapshot of `agentId`. Returns the snapshot id.
|
|
421
|
+
*/
|
|
422
|
+
backupBytes(agentId: string, payload: Uint8Array, passphrase: string): Promise<string>;
|
|
423
|
+
/** Download + decrypt a snapshot's payload bytes. */
|
|
424
|
+
restoreBytes(snapshotId: string, passphrase: string): Promise<Uint8Array>;
|
|
425
|
+
}
|
|
426
|
+
|
|
347
427
|
declare class SGLError extends Error {
|
|
348
428
|
constructor(message: string);
|
|
349
429
|
}
|
|
@@ -362,4 +442,4 @@ declare class SGLConnectionError extends SGLError {
|
|
|
362
442
|
constructor(message: string);
|
|
363
443
|
}
|
|
364
444
|
|
|
365
|
-
export { type Attestation, type AttestationProof, type CapacityResponse, type ChatChoice, type ChatCompletionRequest, type ChatCompletionResponse, type ChatContentPart, type ChatMessage, DEFAULT_BASE_URL, type DeployProcessorOptions, type EmbeddingDatum, type EmbeddingRequest, type EmbeddingResponse, GridClient, type GridClientOptions, type JobResponse, type JobResult, type JobSubmission, type ModelInfo, type ModelPricing, type PricingInfo, type ProcessorDeployResult, type ProcessorInfo, type ProcessorInvokeResult, type ProcessorListResponse, type ProcessorLogEntry, type ProcessorLogsResponse, type ReserveResponse, SGLAPIError, SGLAuthError, SGLConnectionError, SGLError, SGLNotFoundError, type TeeCapacity, type WalletAuth };
|
|
445
|
+
export { type Attestation, type AttestationProof, type CapacityResponse, type ChatChoice, type ChatCompletionRequest, type ChatCompletionResponse, type ChatContentPart, type ChatMessage, DEFAULT_BASE_URL, type DeployProcessorOptions, type EmbeddingDatum, type EmbeddingRequest, type EmbeddingResponse, GridClient, type GridClientOptions, type JobResponse, type JobResult, type JobSubmission, type ModelInfo, type ModelPricing, type PricingInfo, type ProcessorDeployResult, type ProcessorInfo, type ProcessorInvokeResult, type ProcessorListResponse, type ProcessorLogEntry, type ProcessorLogsResponse, type ReserveResponse, SGLAPIError, SGLAuthError, SGLConnectionError, SGLError, SGLNotFoundError, type TeeCapacity, VAULT_URL, type VaultAad, type VaultAgent, VaultClient, type VaultClientOptions, type VaultSnapshot, type VaultUsage, type WalletAuth, decryptEnvelope, encryptEnvelope, parseAadFromKey };
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,12 @@ __export(index_exports, {
|
|
|
36
36
|
SGLAuthError: () => SGLAuthError,
|
|
37
37
|
SGLConnectionError: () => SGLConnectionError,
|
|
38
38
|
SGLError: () => SGLError,
|
|
39
|
-
SGLNotFoundError: () => SGLNotFoundError
|
|
39
|
+
SGLNotFoundError: () => SGLNotFoundError,
|
|
40
|
+
VAULT_URL: () => VAULT_URL,
|
|
41
|
+
VaultClient: () => VaultClient,
|
|
42
|
+
decryptEnvelope: () => decryptEnvelope,
|
|
43
|
+
encryptEnvelope: () => encryptEnvelope,
|
|
44
|
+
parseAadFromKey: () => parseAadFromKey
|
|
40
45
|
});
|
|
41
46
|
module.exports = __toCommonJS(index_exports);
|
|
42
47
|
|
|
@@ -639,6 +644,177 @@ var GridClient = class {
|
|
|
639
644
|
);
|
|
640
645
|
}
|
|
641
646
|
};
|
|
647
|
+
|
|
648
|
+
// src/vault.ts
|
|
649
|
+
var import_aes = require("@noble/ciphers/aes");
|
|
650
|
+
var import_scrypt = require("@noble/hashes/scrypt");
|
|
651
|
+
var VAULT_URL = "https://compute.x402layer.cc";
|
|
652
|
+
var SCRYPT_PARAMS = { N: 1 << 17, r: 8, p: 1 };
|
|
653
|
+
var SCRYPT_MIN_N = 1 << 15;
|
|
654
|
+
var te = new TextEncoder();
|
|
655
|
+
var td = new TextDecoder();
|
|
656
|
+
function aadBytes(aad) {
|
|
657
|
+
const { agentId, backupId, formatVersion, userId } = aad;
|
|
658
|
+
return te.encode(JSON.stringify({ agentId, backupId, formatVersion, userId }));
|
|
659
|
+
}
|
|
660
|
+
function b64(x) {
|
|
661
|
+
let s = "";
|
|
662
|
+
for (const b of x) s += String.fromCharCode(b);
|
|
663
|
+
return btoa(s);
|
|
664
|
+
}
|
|
665
|
+
function unb64(s) {
|
|
666
|
+
const bin = atob(s);
|
|
667
|
+
const out = new Uint8Array(bin.length);
|
|
668
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
669
|
+
return out;
|
|
670
|
+
}
|
|
671
|
+
function rand(n) {
|
|
672
|
+
const out = new Uint8Array(n);
|
|
673
|
+
crypto.getRandomValues(out);
|
|
674
|
+
return out;
|
|
675
|
+
}
|
|
676
|
+
function encryptEnvelope(plaintext, passphrase, aad) {
|
|
677
|
+
const salt = rand(16);
|
|
678
|
+
const kek = (0, import_scrypt.scrypt)(te.encode(passphrase), salt, { ...SCRYPT_PARAMS, dkLen: 32 });
|
|
679
|
+
const dek = rand(32);
|
|
680
|
+
const aadBuf = aadBytes(aad);
|
|
681
|
+
const dekNonce = rand(12);
|
|
682
|
+
const wrapped = (0, import_aes.gcm)(kek, dekNonce, aadBuf).encrypt(dek);
|
|
683
|
+
const blobNonce = rand(12);
|
|
684
|
+
const body = (0, import_aes.gcm)(dek, blobNonce, aadBuf).encrypt(plaintext);
|
|
685
|
+
const header = te.encode(JSON.stringify({
|
|
686
|
+
formatVersion: 1,
|
|
687
|
+
kdf: "scrypt",
|
|
688
|
+
kdfParams: { ...SCRYPT_PARAMS, salt: b64(salt) },
|
|
689
|
+
cipher: "aes-256-gcm",
|
|
690
|
+
wrappedDek: { nonce: b64(dekNonce), ciphertext: b64(wrapped) },
|
|
691
|
+
blobNonce: b64(blobNonce),
|
|
692
|
+
aad
|
|
693
|
+
}));
|
|
694
|
+
const out = new Uint8Array(4 + header.length + body.length);
|
|
695
|
+
new DataView(out.buffer).setUint32(0, header.length, false);
|
|
696
|
+
out.set(header, 4);
|
|
697
|
+
out.set(body, 4 + header.length);
|
|
698
|
+
return out;
|
|
699
|
+
}
|
|
700
|
+
function decryptEnvelope(blob, passphrase, aad) {
|
|
701
|
+
if (blob.length < 4) throw new SGLAPIError(0, "malformed blob: too short");
|
|
702
|
+
const headerLen = new DataView(blob.buffer, blob.byteOffset).getUint32(0, false);
|
|
703
|
+
if (4 + headerLen > blob.length) throw new SGLAPIError(0, "malformed blob: header length out of bounds");
|
|
704
|
+
let header;
|
|
705
|
+
try {
|
|
706
|
+
header = JSON.parse(td.decode(blob.subarray(4, 4 + headerLen)));
|
|
707
|
+
} catch {
|
|
708
|
+
throw new SGLAPIError(0, "malformed blob: invalid header JSON");
|
|
709
|
+
}
|
|
710
|
+
if (header.kdf !== "scrypt") {
|
|
711
|
+
throw new SGLAPIError(0, `this backup uses ${String(header.kdf)} key derivation \u2014 restore it with the agentvault CLI`);
|
|
712
|
+
}
|
|
713
|
+
const p = header.kdfParams ?? {};
|
|
714
|
+
if (!Number.isInteger(p.N) || p.N < SCRYPT_MIN_N || p.N > SCRYPT_PARAMS.N || (p.N & p.N - 1) !== 0 || !Number.isInteger(p.r) || p.r < 8 || p.r > 16 || !Number.isInteger(p.p) || p.p < 1 || p.p > 4 || typeof p.salt !== "string" || !header.wrappedDek?.nonce || !header.wrappedDek?.ciphertext || !header.blobNonce) {
|
|
715
|
+
throw new SGLAPIError(0, "malformed blob: unsupported header parameters");
|
|
716
|
+
}
|
|
717
|
+
const salt = unb64(p.salt);
|
|
718
|
+
if (salt.length < 16) throw new SGLAPIError(0, "malformed blob: salt too short");
|
|
719
|
+
const kek = (0, import_scrypt.scrypt)(te.encode(passphrase), salt, { N: p.N, r: p.r, p: p.p, dkLen: 32 });
|
|
720
|
+
const aadBuf = aadBytes(aad);
|
|
721
|
+
try {
|
|
722
|
+
const dek = (0, import_aes.gcm)(kek, unb64(header.wrappedDek.nonce), aadBuf).decrypt(unb64(header.wrappedDek.ciphertext));
|
|
723
|
+
return (0, import_aes.gcm)(dek, unb64(header.blobNonce), aadBuf).decrypt(blob.subarray(4 + headerLen));
|
|
724
|
+
} catch {
|
|
725
|
+
throw new SGLAPIError(0, "incorrect passphrase or corrupted backup");
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
function parseAadFromKey(r2Key) {
|
|
729
|
+
const parts = r2Key.split("/");
|
|
730
|
+
if (parts.length !== 5 || parts[0] !== "backups" || parts[4] !== "blob.enc" || !parts[1] || !parts[2] || !parts[3]) {
|
|
731
|
+
throw new SGLAPIError(0, `malformed r2 key: ${r2Key}`);
|
|
732
|
+
}
|
|
733
|
+
return { userId: parts[1], agentId: parts[2], backupId: parts[3], formatVersion: 1 };
|
|
734
|
+
}
|
|
735
|
+
var VaultClient = class _VaultClient {
|
|
736
|
+
constructor(options) {
|
|
737
|
+
const base = (options.baseUrl ?? VAULT_URL).replace(/\/+$/, "");
|
|
738
|
+
const u = new URL(base);
|
|
739
|
+
const local = ["localhost", "127.0.0.1", "[::1]"].includes(u.hostname);
|
|
740
|
+
if (u.protocol !== "https:" && !local) {
|
|
741
|
+
throw new SGLAPIError(0, "baseUrl must be https (the API key travels in a header)");
|
|
742
|
+
}
|
|
743
|
+
if (u.username || u.password || u.search || u.hash) {
|
|
744
|
+
throw new SGLAPIError(0, "baseUrl must be a bare origin");
|
|
745
|
+
}
|
|
746
|
+
this.base = base;
|
|
747
|
+
this.apiKey = options.apiKey;
|
|
748
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
749
|
+
}
|
|
750
|
+
static id(v) {
|
|
751
|
+
if (!/^[0-9a-fA-F-]{36}$/.test(v)) throw new SGLAPIError(0, `not a snapshot id: ${v}`);
|
|
752
|
+
return v.toLowerCase();
|
|
753
|
+
}
|
|
754
|
+
async call(method, path, body) {
|
|
755
|
+
const res = await this.fetchImpl(`${this.base}${path}`, {
|
|
756
|
+
method,
|
|
757
|
+
headers: {
|
|
758
|
+
"x-api-key": this.apiKey,
|
|
759
|
+
...body !== void 0 ? { "content-type": "application/json" } : {}
|
|
760
|
+
},
|
|
761
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
762
|
+
});
|
|
763
|
+
const data = await res.json().catch(() => ({}));
|
|
764
|
+
if (!res.ok) throw new SGLAPIError(res.status, String(data.error ?? `request failed: ${res.status}`));
|
|
765
|
+
return data;
|
|
766
|
+
}
|
|
767
|
+
async agents() {
|
|
768
|
+
return (await this.call("GET", "/backups/agents")).agents;
|
|
769
|
+
}
|
|
770
|
+
async createAgent(name, framework) {
|
|
771
|
+
return (await this.call("POST", "/backups/agents", { name, framework })).agent;
|
|
772
|
+
}
|
|
773
|
+
async snapshots(agentId) {
|
|
774
|
+
const q = agentId ? `?agentId=${encodeURIComponent(agentId)}` : "";
|
|
775
|
+
return (await this.call("GET", `/backups${q}`)).backups;
|
|
776
|
+
}
|
|
777
|
+
async usage() {
|
|
778
|
+
return this.call("GET", "/backups/usage");
|
|
779
|
+
}
|
|
780
|
+
/** Activate Vault Pro ($3/mo from credits). */
|
|
781
|
+
async subscribePro() {
|
|
782
|
+
return this.call("POST", "/backups/subscribe");
|
|
783
|
+
}
|
|
784
|
+
async deleteSnapshot(id) {
|
|
785
|
+
await this.call("DELETE", `/backups/${_VaultClient.id(id)}`);
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Encrypt + upload arbitrary payload bytes (e.g. a tarball you packed) as a
|
|
789
|
+
* snapshot of `agentId`. Returns the snapshot id.
|
|
790
|
+
*/
|
|
791
|
+
async backupBytes(agentId, payload, passphrase) {
|
|
792
|
+
const res = await this.call(
|
|
793
|
+
"POST",
|
|
794
|
+
"/backups",
|
|
795
|
+
{ agentId, sizeBytes: payload.length }
|
|
796
|
+
);
|
|
797
|
+
const blob = encryptEnvelope(payload, passphrase, parseAadFromKey(res.r2Key));
|
|
798
|
+
const up = await this.fetchImpl(res.uploadUrl, {
|
|
799
|
+
method: "PUT",
|
|
800
|
+
body: blob,
|
|
801
|
+
headers: { "content-type": "application/octet-stream" }
|
|
802
|
+
});
|
|
803
|
+
if (!up.ok) throw new SGLAPIError(up.status, `upload failed: ${up.status}`);
|
|
804
|
+
const digest = await crypto.subtle.digest("SHA-256", blob);
|
|
805
|
+
const sha2562 = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
806
|
+
await this.call("POST", `/backups/${res.backupId}/complete`, { sha256: sha2562 });
|
|
807
|
+
return res.backupId;
|
|
808
|
+
}
|
|
809
|
+
/** Download + decrypt a snapshot's payload bytes. */
|
|
810
|
+
async restoreBytes(snapshotId, passphrase) {
|
|
811
|
+
const info = await this.call("GET", `/backups/${_VaultClient.id(snapshotId)}/restore`);
|
|
812
|
+
const dl = await this.fetchImpl(info.downloadUrl);
|
|
813
|
+
if (!dl.ok) throw new SGLAPIError(dl.status, `download failed: ${dl.status}`);
|
|
814
|
+
const blob = new Uint8Array(await dl.arrayBuffer());
|
|
815
|
+
return decryptEnvelope(blob, passphrase, parseAadFromKey(info.r2Key));
|
|
816
|
+
}
|
|
817
|
+
};
|
|
642
818
|
// Annotate the CommonJS export names for ESM import in node:
|
|
643
819
|
0 && (module.exports = {
|
|
644
820
|
DEFAULT_BASE_URL,
|
|
@@ -647,6 +823,11 @@ var GridClient = class {
|
|
|
647
823
|
SGLAuthError,
|
|
648
824
|
SGLConnectionError,
|
|
649
825
|
SGLError,
|
|
650
|
-
SGLNotFoundError
|
|
826
|
+
SGLNotFoundError,
|
|
827
|
+
VAULT_URL,
|
|
828
|
+
VaultClient,
|
|
829
|
+
decryptEnvelope,
|
|
830
|
+
encryptEnvelope,
|
|
831
|
+
parseAadFromKey
|
|
651
832
|
});
|
|
652
833
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/e2e.ts","../src/client.ts"],"sourcesContent":["export { GridClient, DEFAULT_BASE_URL } from \"./client.js\";\nexport {\n SGLError,\n SGLAPIError,\n SGLAuthError,\n SGLNotFoundError,\n SGLConnectionError,\n} from \"./errors.js\";\nexport type {\n Attestation,\n AttestationProof,\n CapacityResponse,\n ChatChoice,\n ChatCompletionRequest,\n ChatCompletionResponse,\n ChatContentPart,\n ChatMessage,\n EmbeddingRequest,\n EmbeddingResponse,\n EmbeddingDatum,\n ReserveResponse,\n DeployProcessorOptions,\n GridClientOptions,\n JobResponse,\n JobResult,\n JobSubmission,\n ModelInfo,\n ModelPricing,\n PricingInfo,\n ProcessorDeployResult,\n ProcessorInfo,\n ProcessorInvokeResult,\n ProcessorListResponse,\n ProcessorLogEntry,\n ProcessorLogsResponse,\n TeeCapacity,\n WalletAuth,\n} from \"./types.js\";\n","export class SGLError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SGLError\";\n }\n}\n\nexport class SGLAPIError extends SGLError {\n readonly statusCode: number;\n readonly body?: Record<string, unknown>;\n\n constructor(\n statusCode: number,\n message: string,\n body?: Record<string, unknown>,\n ) {\n super(`HTTP ${statusCode}: ${message}`);\n this.name = \"SGLAPIError\";\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n\nexport class SGLAuthError extends SGLAPIError {\n constructor(\n statusCode: number,\n message: string,\n body?: Record<string, unknown>,\n ) {\n super(statusCode, message, body);\n this.name = \"SGLAuthError\";\n }\n}\n\nexport class SGLNotFoundError extends SGLAPIError {\n constructor(message: string, body?: Record<string, unknown>) {\n super(404, message, body);\n this.name = \"SGLNotFoundError\";\n }\n}\n\nexport class SGLConnectionError extends SGLError {\n constructor(message: string) {\n super(message);\n this.name = \"SGLConnectionError\";\n }\n}\n","/**\n * End-to-end encryption for the SGL grid (client side).\n *\n * Must match sgl-node/src/encryption.rs, the orchestrator, and the browser/Python\n * clients byte-for-byte: X25519 ECDH -> HKDF-SHA256 -> XChaCha20-Poly1305 (24-byte\n * nonce), AAD-bound. Sealed blob layout: nonce(24) || ciphertext, base58.\n *\n * The orchestrator only ever relays ciphertext — it never sees the prompt or reply.\n */\n\nimport { x25519 } from \"@noble/curves/ed25519\";\nimport { xchacha20poly1305 } from \"@noble/ciphers/chacha\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { hkdf } from \"@noble/hashes/hkdf\";\nimport bs58 from \"bs58\";\n\nexport const ALGO_V2 = \"x25519-xchacha20poly1305-hkdf-v2\";\nexport const ALGO_V2_STREAM = \"x25519-xchacha20poly1305-hkdf-v2-stream\";\n\nconst HKDF_SALT = new TextEncoder().encode(\"sgl-e2e-v2-salt\");\nconst HKDF_INFO_INPUT = new TextEncoder().encode(\"sgl-e2e-v2-input\");\nconst HKDF_INFO_OUTPUT = new TextEncoder().encode(\"sgl-e2e-v2-output\");\n\nfunction v2Key(shared: Uint8Array, info: Uint8Array): Uint8Array {\n return hkdf(sha256, shared, HKDF_SALT, info, 32);\n}\nfunction aadInput(nodeB58: string, ephB58: string, respB58: string): Uint8Array {\n return new TextEncoder().encode(`sgl-aad/v2/input|node=${nodeB58}|eph=${ephB58}|resp=${respB58}`);\n}\nfunction aadOutput(respB58: string, ephB58: string): Uint8Array {\n return new TextEncoder().encode(`sgl-aad/v2/output|resp=${respB58}|eph=${ephB58}`);\n}\nfunction aadStream(respB58: string, ephB58: string, nonceB58: string, seq: number, isFinal: boolean): Uint8Array {\n return new TextEncoder().encode(\n `sgl-aad/v2/stream|resp=${respB58}|eph=${ephB58}|nonce=${nonceB58}|seq=${seq}|final=${isFinal ? 1 : 0}`,\n );\n}\n\nfunction b58enc(u: Uint8Array): string {\n return bs58.encode(u);\n}\nfunction b58dec(s: string): Uint8Array {\n return bs58.decode(s);\n}\nfunction randomBytes(n: number): Uint8Array {\n return crypto.getRandomValues(new Uint8Array(n));\n}\n\nexport interface ResponseKeypair {\n secret: Uint8Array;\n pubB58: string;\n}\n\n/** The caller's response keypair — the node seals its reply to this. */\nexport function newResponseKeypair(): ResponseKeypair {\n const secret = x25519.utils.randomPrivateKey();\n return { secret, pubB58: b58enc(x25519.getPublicKey(secret)) };\n}\n\n/** A per-request nonce bound into every stream chunk's AAD. */\nexport function randomNonceB58(): string {\n return b58enc(randomBytes(16));\n}\n\n/** Seal the prompt to the node's X25519 key. */\nexport function sealInputV2(\n nodePubB58: string,\n respPubB58: string,\n plaintext: Uint8Array,\n): { ciphertext: string; ephemeralPub: string } {\n const nodePub = b58dec(nodePubB58);\n const ephSecret = x25519.utils.randomPrivateKey();\n const ephPub = x25519.getPublicKey(ephSecret);\n const ephB58 = b58enc(ephPub);\n const shared = x25519.getSharedSecret(ephSecret, nodePub);\n const key = v2Key(shared, HKDF_INFO_INPUT);\n const aad = aadInput(nodePubB58, ephB58, respPubB58);\n const nonce = randomBytes(24);\n const ct = xchacha20poly1305(key, nonce, aad).encrypt(plaintext);\n const out = new Uint8Array(24 + ct.length);\n out.set(nonce, 0);\n out.set(ct, 24);\n return { ciphertext: b58enc(out), ephemeralPub: ephB58 };\n}\n\n/** Open the node's (non-stream) reply sealed to our response key. */\nexport function openOutputV2(\n respSecret: Uint8Array,\n respPubB58: string,\n nodeEphB58: string,\n ciphertextB58: string,\n): Uint8Array {\n const shared = x25519.getSharedSecret(respSecret, b58dec(nodeEphB58));\n const key = v2Key(shared, HKDF_INFO_OUTPUT);\n const aad = aadOutput(respPubB58, nodeEphB58);\n const blob = b58dec(ciphertextB58);\n return xchacha20poly1305(key, blob.slice(0, 24), aad).decrypt(blob.slice(24));\n}\n\n/** Derive the stream output key once from the node's stream ephemeral (chunk 0). */\nexport function streamOutKey(respSecret: Uint8Array, nodeStreamEphB58: string): Uint8Array {\n const shared = x25519.getSharedSecret(respSecret, b58dec(nodeStreamEphB58));\n return v2Key(shared, HKDF_INFO_OUTPUT);\n}\n\n/** Open one stream chunk with the precomputed key + nonce/seq/final-bound AAD. */\nexport function openStreamChunk(\n outKey: Uint8Array,\n respPubB58: string,\n streamEphB58: string,\n reqNonceB58: string,\n seq: number,\n isFinal: boolean,\n ctB58: string,\n): Uint8Array {\n const aad = aadStream(respPubB58, streamEphB58, reqNonceB58, seq, isFinal);\n const blob = b58dec(ctB58);\n return xchacha20poly1305(outKey, blob.slice(0, 24), aad).decrypt(blob.slice(24));\n}\n","import { SGLAPIError, SGLAuthError, SGLConnectionError, SGLNotFoundError } from \"./errors.js\";\nimport * as e2e from \"./e2e.js\";\nimport type {\n AttestationProof,\n CapacityResponse,\n ChatCompletionRequest,\n ChatCompletionResponse,\n EmbeddingRequest,\n EmbeddingResponse,\n DeployProcessorOptions,\n GridClientOptions,\n JobResponse,\n JobResult,\n ModelInfo,\n PricingInfo,\n ProcessorDeployResult,\n ProcessorInfo,\n ProcessorInvokeResult,\n ProcessorListResponse,\n ProcessorLogEntry,\n ProcessorLogsResponse,\n ProviderInfo,\n ProvidersResponse,\n ReserveResponse,\n WalletAuth,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://grid.x402compute.cc\";\n\nconst DEFAULT_TIMEOUT = 60_000;\n\nexport class GridClient {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly timeout: number;\n\n constructor(options: GridClientOptions = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.headers = { Accept: \"application/json\", \"Content-Type\": \"application/json\" };\n if (options.apiKey) {\n this.headers[\"Authorization\"] = `Bearer ${options.apiKey}`;\n // Grid credit billing reads X-API-Key; send both so reserve + chat resolve\n // the paying wallet (credits mode) rather than falling back to anonymous x402.\n this.headers[\"X-API-Key\"] = options.apiKey;\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n else if (err && typeof err === \"object\" && \"message\" in err)\n message = String((err as { message: unknown }).message);\n } catch {\n /* body not JSON */\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SGLAuthError(response.status, message, errorBody);\n }\n if (response.status === 404) {\n throw new SGLNotFoundError(message, errorBody);\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n if (response.status === 204) return {} as T;\n return (await response.json()) as T;\n }\n\n // -- Public endpoints (no auth) ------------------------------------------\n\n async capacity(): Promise<CapacityResponse> {\n return this.request<CapacityResponse>(\"GET\", \"/grid/capacity\");\n }\n\n async models(): Promise<ModelInfo[]> {\n const data = await this.request<{ models: ModelInfo[] }>(\"GET\", \"/grid/models\");\n return data.models ?? [];\n }\n\n async pricing(): Promise<PricingInfo[]> {\n const data = await this.request<{ pricing: PricingInfo[] }>(\"GET\", \"/grid/pricing\");\n return data.pricing ?? [];\n }\n\n /**\n * List the nodes serving a model with each node's effective per-token price\n * (operator's custom price if set, else the platform reference), cheapest\n * first. Pass a chosen `node_id` as `node` on `chatCompletions` to pin it,\n * or omit to let the grid route. Optional `cluster` filter (slug or id).\n */\n async providers(\n model: string,\n options?: { cluster?: string },\n ): Promise<ProviderInfo[]> {\n const params = new URLSearchParams({ model });\n if (options?.cluster) params.set(\"cluster\", options.cluster);\n const data = await this.request<ProvidersResponse>(\n \"GET\",\n `/v1/providers?${params.toString()}`,\n );\n return data.providers ?? [];\n }\n\n // -- Authenticated endpoints ---------------------------------------------\n\n async submitJob(\n model: string,\n input: Record<string, unknown>,\n options?: { submitterWallet?: string; submitterChain?: string },\n ): Promise<JobResponse> {\n const body: Record<string, unknown> = { model, input };\n if (options?.submitterWallet) body.submitter_wallet = options.submitterWallet;\n if (options?.submitterChain) body.submitter_chain = options.submitterChain;\n return this.request<JobResponse>(\"POST\", \"/grid/jobs\", body);\n }\n\n async getJob(jobId: string): Promise<JobResult> {\n return this.request<JobResult>(\"GET\", `/grid/jobs/${jobId}`);\n }\n\n async getAttestation(jobId: string): Promise<AttestationProof> {\n return this.request<AttestationProof>(\"GET\", `/grid/jobs/${jobId}/attestation`);\n }\n\n // -- OpenAI-compatible (end-to-end encrypted) ----------------------------\n\n /** Reserve a node + learn its X25519 key so we can seal the prompt to it.\n * Forwards an optional pinned `node` (see `providers()`), `cluster` filter,\n * and `pay_in_coin` so the orchestrator reserves + quotes accordingly. */\n private async reserve(req: {\n model: string;\n node?: string;\n cluster?: string;\n pay_in_coin?: boolean;\n max_price?: number;\n }): Promise<ReserveResponse> {\n const body: Record<string, unknown> = { model: req.model };\n if (req.node) body.node = req.node;\n if (req.cluster) body.cluster = req.cluster;\n if (req.pay_in_coin) body.pay_in_coin = req.pay_in_coin;\n if (req.max_price != null) body.max_price = req.max_price;\n const res = await this.request<ReserveResponse>(\"POST\", \"/v1/reserve\", body);\n if (!res.node_x25519_pubkey) {\n throw new SGLAPIError(503, \"Reserved node does not support E2E encryption\");\n }\n return res;\n }\n\n /**\n * End-to-end encrypted chat completion. The prompt is sealed in this client to\n * the serving node's key and only decrypts inside its TEE — the orchestrator\n * only relays ciphertext. Requires an `apiKey` (credits); without one the grid\n * replies 402 (the SDK does not sign x402 payments — use the wallet/browser flow).\n */\n async chatCompletions(\n request: ChatCompletionRequest,\n ): Promise<ChatCompletionResponse> {\n if (request.stream) {\n // Collapse the stream into a single response for the non-streaming API.\n let content = \"\";\n for await (const delta of this.chatCompletionStream(request)) content += delta;\n return {\n id: \"\", object: \"chat.completion\", created: 0, model: request.model,\n choices: [{ index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" }],\n };\n }\n\n const reservation = await this.reserve(request);\n const { secret, pubB58 } = e2e.newResponseKeypair();\n const maxTokens = request.max_tokens ?? 512;\n const sealed = e2e.sealInputV2(\n reservation.node_x25519_pubkey,\n pubB58,\n new TextEncoder().encode(JSON.stringify({\n messages: request.messages,\n temperature: request.temperature ?? 0.7,\n max_tokens: maxTokens,\n })),\n );\n const body = {\n reservation_token: reservation.reservation_token,\n max_tokens: maxTokens, // cleartext, only used to quote the x402 price\n enc: {\n ciphertext: sealed.ciphertext,\n client_ephemeral_pubkey: sealed.ephemeralPub,\n client_response_pubkey: pubB58,\n algorithm: e2e.ALGO_V2,\n },\n };\n\n let data: {\n id?: string; created?: number; sealed_result?: { ephemeral_public_key: string; ciphertext: string };\n usage?: ChatCompletionResponse[\"usage\"];\n };\n try {\n data = await this.request(\"POST\", \"/v1/chat/completions\", body);\n } catch (err) {\n if (err instanceof SGLAPIError && err.statusCode === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n throw err;\n }\n\n if (!data.sealed_result) throw new SGLAPIError(500, \"No sealed result returned\");\n const plain = e2e.openOutputV2(secret, pubB58, data.sealed_result.ephemeral_public_key, data.sealed_result.ciphertext);\n const parsed = JSON.parse(new TextDecoder().decode(plain)) as { content?: string; usage?: ChatCompletionResponse[\"usage\"] };\n\n return {\n id: data.id ?? \"\",\n object: \"chat.completion\",\n created: data.created ?? 0,\n model: request.model,\n choices: [{ index: 0, message: { role: \"assistant\", content: parsed.content ?? \"\" }, finish_reason: \"stop\" }],\n usage: data.usage ?? parsed.usage,\n attestation: {\n nodeId: reservation.node_id,\n teeType: reservation.tee_type ?? null,\n verified: !!reservation.attestation_verified,\n },\n };\n }\n\n /**\n * Create embeddings via the grid's OpenAI-compatible `/v1/embeddings` endpoint.\n *\n * `input` is a string or array of strings; `dimensions` truncates Matryoshka models\n * (e.g. nomic 768→256); `input_type` ('query' | 'document') hints asymmetric\n * retrieval models. Billed on input tokens only — there is no generation. Requires\n * an `apiKey` (credits); the TS SDK does not sign x402 payments. Unlike chat, the\n * input is not client-sealed — the orchestrator seals it to the node in-TEE. The\n * returned `data` is ordered to match `input`.\n */\n async embed(request: EmbeddingRequest): Promise<EmbeddingResponse> {\n const body: Record<string, unknown> = { model: request.model, input: request.input };\n if (request.dimensions != null) body.dimensions = request.dimensions;\n if (request.input_type != null) body.input_type = request.input_type;\n if (request.tier != null) body.tier = request.tier;\n try {\n return (await this.request(\"POST\", \"/v1/embeddings\", body)) as EmbeddingResponse;\n } catch (err) {\n if (err instanceof SGLAPIError && err.statusCode === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n throw err;\n }\n }\n\n /**\n * Streaming end-to-end encrypted chat completion. Yields decoded text as it\n * arrives; each chunk is decrypted and its ordering + termination verified (a\n * truncated stream throws). Requires `apiKey` (credits). If the server isn't\n * streaming (toggle off), the whole reply is yielded as a single chunk.\n */\n async *chatCompletionStream(\n request: ChatCompletionRequest,\n ): AsyncGenerator<string, void, unknown> {\n const reservation = await this.reserve(request);\n const { secret, pubB58 } = e2e.newResponseKeypair();\n const nonce = e2e.randomNonceB58();\n const maxTokens = request.max_tokens ?? 512;\n const sealed = e2e.sealInputV2(\n reservation.node_x25519_pubkey,\n pubB58,\n new TextEncoder().encode(JSON.stringify({\n messages: request.messages,\n temperature: request.temperature ?? 0.7,\n max_tokens: maxTokens,\n stream: true,\n nonce,\n })),\n );\n const body = {\n reservation_token: reservation.reservation_token,\n stream: true,\n max_tokens: maxTokens,\n enc: {\n ciphertext: sealed.ciphertext,\n client_ephemeral_pubkey: sealed.ephemeralPub,\n client_response_pubkey: pubB58,\n algorithm: e2e.ALGO_V2,\n },\n };\n\n const controller = new AbortController();\n const overall = setTimeout(() => controller.abort(), this.timeout);\n let resp: Response;\n try {\n resp = await fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(overall);\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n if (!resp.ok) {\n clearTimeout(overall);\n if (resp.status === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n let message = resp.statusText;\n try {\n const j = (await resp.json()) as { error?: unknown };\n if (typeof j.error === \"string\") message = j.error;\n else if (j.error && typeof j.error === \"object\" && \"message\" in j.error) message = String((j.error as { message: unknown }).message);\n } catch { /* ignore */ }\n throw new SGLAPIError(resp.status, message);\n }\n\n const ctype = resp.headers.get(\"content-type\") ?? \"\";\n if (!ctype.includes(\"text/event-stream\") || !resp.body) {\n clearTimeout(overall);\n const data = (await resp.json()) as { sealed_result?: { ephemeral_public_key: string; ciphertext: string } };\n if (!data.sealed_result) throw new SGLAPIError(500, \"No sealed result returned\");\n const plain = e2e.openOutputV2(secret, pubB58, data.sealed_result.ephemeral_public_key, data.sealed_result.ciphertext);\n const content = (JSON.parse(new TextDecoder().decode(plain)) as { content?: string }).content ?? \"\";\n if (content) yield content;\n return;\n }\n\n const reader = resp.body.getReader();\n const decoder = new TextDecoder();\n const INACTIVITY_MS = 60_000;\n const readChunk = async (): Promise<ReadableStreamReadResult<Uint8Array>> => {\n let t: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n t = setTimeout(() => reject(new SGLConnectionError(\"stream timed out (no tokens)\")), INACTIVITY_MS);\n });\n try {\n return (await Promise.race([reader.read(), timeout])) as ReadableStreamReadResult<Uint8Array>;\n } finally {\n if (t) clearTimeout(t);\n }\n };\n\n let buf = \"\";\n let expectedSeq = 0;\n let outKey: Uint8Array | null = null;\n let streamEph: string | null = null;\n let sawFinal = false;\n try {\n for (;;) {\n if (sawFinal) break;\n const { value, done } = await readChunk();\n if (done) break;\n // Normalize CRLF so \\n\\n event framing works regardless of line endings.\n buf += decoder.decode(value, { stream: true }).replace(/\\r\\n/g, \"\\n\");\n let idx: number;\n while ((idx = buf.indexOf(\"\\n\\n\")) !== -1) {\n const raw = buf.slice(0, idx);\n buf = buf.slice(idx + 2);\n if (raw.includes(\"event: error\")) throw new SGLAPIError(502, \"stream aborted by server\");\n const dataStr = raw.split(\"\\n\").filter((l) => l.startsWith(\"data:\")).map((l) => l.slice(5).trim()).join(\"\\n\");\n if (!dataStr || dataStr === \"[DONE]\") continue;\n // Fail closed: a malformed or non-chunk data event is a protocol error.\n let chunk: { seq?: number; final?: boolean; eph?: string; ct?: string };\n try {\n chunk = JSON.parse(dataStr);\n } catch {\n throw new SGLAPIError(502, \"malformed stream chunk\");\n }\n if (typeof chunk.seq !== \"number\" || !chunk.ct) {\n throw new SGLAPIError(502, \"invalid stream chunk (missing seq/ciphertext)\");\n }\n if (chunk.seq !== expectedSeq) throw new SGLAPIError(502, `stream out of order (expected ${expectedSeq}, got ${chunk.seq})`);\n if (chunk.seq === 0) {\n if (!chunk.eph) throw new SGLAPIError(502, \"stream chunk 0 missing ephemeral key\");\n streamEph = chunk.eph;\n outKey = e2e.streamOutKey(secret, streamEph);\n }\n const isFinal = chunk.final === true;\n const text = new TextDecoder().decode(\n e2e.openStreamChunk(outKey as Uint8Array, pubB58, streamEph as string, nonce, chunk.seq, isFinal, chunk.ct),\n );\n if (text) yield text;\n expectedSeq++;\n if (isFinal) { sawFinal = true; break; }\n }\n }\n } finally {\n clearTimeout(overall);\n try { await reader.cancel(); } catch { /* ignore */ }\n }\n if (!sawFinal) throw new SGLAPIError(502, \"stream ended before final chunk (truncated)\");\n }\n\n // -- Processor helpers ----------------------------------------------------\n\n private async requestWithWalletAuth<T>(\n method: string,\n path: string,\n wallet: WalletAuth,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n const reqHeaders: Record<string, string> = {\n ...this.headers,\n \"X-Auth-Address\": wallet.address,\n \"X-Auth-Chain\": wallet.chain ?? \"solana\",\n \"X-Auth-Signature\": wallet.signature,\n \"X-Auth-Timestamp\": wallet.timestamp,\n \"X-Auth-Nonce\": wallet.nonce,\n };\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n else if (err && typeof err === \"object\" && \"message\" in err)\n message = String((err as { message: unknown }).message);\n } catch {\n /* body not JSON */\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SGLAuthError(response.status, message, errorBody);\n }\n if (response.status === 404) {\n throw new SGLNotFoundError(message, errorBody);\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n if (response.status === 204) return {} as T;\n return (await response.json()) as T;\n }\n\n private async requestWithPayment<T>(\n method: string,\n path: string,\n body?: unknown,\n paymentHeader?: string,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n const reqHeaders: Record<string, string> = { ...this.headers };\n if (paymentHeader) {\n reqHeaders[\"X-Payment\"] = paymentHeader;\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (response.status === 402) {\n const requirements = (await response.json()) as Record<string, unknown>;\n throw new SGLAPIError(402, \"Payment required\", requirements);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n } catch {\n /* body not JSON */\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n return (await response.json()) as T;\n }\n\n // -- Processors -----------------------------------------------------------\n\n async deployProcessor(\n wallet: WalletAuth,\n options: DeployProcessorOptions,\n ): Promise<ProcessorDeployResult> {\n return this.requestWithWalletAuth<ProcessorDeployResult>(\n \"POST\",\n \"/grid/processors\",\n wallet,\n options,\n );\n }\n\n async invokeProcessor(\n processorName: string,\n input: Record<string, unknown>,\n options?: { paymentHeader?: string; paymentToken?: \"USDC\" | \"SGL\" },\n ): Promise<ProcessorInvokeResult> {\n const body: Record<string, unknown> = { input };\n if (options?.paymentToken) body.payment_token = options.paymentToken;\n return this.requestWithPayment<ProcessorInvokeResult>(\n \"POST\",\n `/grid/processors/${encodeURIComponent(processorName)}/invoke`,\n body,\n options?.paymentHeader,\n );\n }\n\n async listProcessors(options?: {\n owner?: string;\n page?: number;\n limit?: number;\n }): Promise<ProcessorListResponse> {\n const params = new URLSearchParams();\n if (options?.owner) params.set(\"owner\", options.owner);\n if (options?.page != null) params.set(\"page\", String(options.page));\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n const qs = params.toString();\n return this.request<ProcessorListResponse>(\n \"GET\",\n `/grid/processors${qs ? `?${qs}` : \"\"}`,\n );\n }\n\n async getProcessor(processorId: string): Promise<ProcessorInfo> {\n return this.request<ProcessorInfo>(\"GET\", `/grid/processors/${processorId}`);\n }\n\n async deleteProcessor(\n processorId: string,\n wallet: WalletAuth,\n ): Promise<{ deleted: boolean; id: string }> {\n return this.requestWithWalletAuth<{ deleted: boolean; id: string }>(\n \"DELETE\",\n `/grid/processors/${processorId}`,\n wallet,\n );\n }\n\n async getProcessorLogs(\n processorId: string,\n wallet: WalletAuth,\n options?: { page?: number; limit?: number },\n ): Promise<ProcessorLogsResponse> {\n const params = new URLSearchParams();\n if (options?.page != null) params.set(\"page\", String(options.page));\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n const qs = params.toString();\n return this.requestWithWalletAuth<ProcessorLogsResponse>(\n \"GET\",\n `/grid/processors/${processorId}/logs${qs ? `?${qs}` : \"\"}`,\n wallet,\n );\n }\n}\n"],"mappings":"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","names":["bs58"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/e2e.ts","../src/client.ts","../src/vault.ts"],"sourcesContent":["export { GridClient, DEFAULT_BASE_URL } from \"./client.js\";\nexport {\n VaultClient,\n VAULT_URL,\n encryptEnvelope,\n decryptEnvelope,\n parseAadFromKey,\n} from \"./vault.js\";\nexport type {\n VaultAad,\n VaultAgent,\n VaultSnapshot,\n VaultUsage,\n VaultClientOptions,\n} from \"./vault.js\";\nexport {\n SGLError,\n SGLAPIError,\n SGLAuthError,\n SGLNotFoundError,\n SGLConnectionError,\n} from \"./errors.js\";\nexport type {\n Attestation,\n AttestationProof,\n CapacityResponse,\n ChatChoice,\n ChatCompletionRequest,\n ChatCompletionResponse,\n ChatContentPart,\n ChatMessage,\n EmbeddingRequest,\n EmbeddingResponse,\n EmbeddingDatum,\n ReserveResponse,\n DeployProcessorOptions,\n GridClientOptions,\n JobResponse,\n JobResult,\n JobSubmission,\n ModelInfo,\n ModelPricing,\n PricingInfo,\n ProcessorDeployResult,\n ProcessorInfo,\n ProcessorInvokeResult,\n ProcessorListResponse,\n ProcessorLogEntry,\n ProcessorLogsResponse,\n TeeCapacity,\n WalletAuth,\n} from \"./types.js\";\n","export class SGLError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SGLError\";\n }\n}\n\nexport class SGLAPIError extends SGLError {\n readonly statusCode: number;\n readonly body?: Record<string, unknown>;\n\n constructor(\n statusCode: number,\n message: string,\n body?: Record<string, unknown>,\n ) {\n super(`HTTP ${statusCode}: ${message}`);\n this.name = \"SGLAPIError\";\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n\nexport class SGLAuthError extends SGLAPIError {\n constructor(\n statusCode: number,\n message: string,\n body?: Record<string, unknown>,\n ) {\n super(statusCode, message, body);\n this.name = \"SGLAuthError\";\n }\n}\n\nexport class SGLNotFoundError extends SGLAPIError {\n constructor(message: string, body?: Record<string, unknown>) {\n super(404, message, body);\n this.name = \"SGLNotFoundError\";\n }\n}\n\nexport class SGLConnectionError extends SGLError {\n constructor(message: string) {\n super(message);\n this.name = \"SGLConnectionError\";\n }\n}\n","/**\n * End-to-end encryption for the SGL grid (client side).\n *\n * Must match sgl-node/src/encryption.rs, the orchestrator, and the browser/Python\n * clients byte-for-byte: X25519 ECDH -> HKDF-SHA256 -> XChaCha20-Poly1305 (24-byte\n * nonce), AAD-bound. Sealed blob layout: nonce(24) || ciphertext, base58.\n *\n * The orchestrator only ever relays ciphertext — it never sees the prompt or reply.\n */\n\nimport { x25519 } from \"@noble/curves/ed25519\";\nimport { xchacha20poly1305 } from \"@noble/ciphers/chacha\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { hkdf } from \"@noble/hashes/hkdf\";\nimport bs58 from \"bs58\";\n\nexport const ALGO_V2 = \"x25519-xchacha20poly1305-hkdf-v2\";\nexport const ALGO_V2_STREAM = \"x25519-xchacha20poly1305-hkdf-v2-stream\";\n\nconst HKDF_SALT = new TextEncoder().encode(\"sgl-e2e-v2-salt\");\nconst HKDF_INFO_INPUT = new TextEncoder().encode(\"sgl-e2e-v2-input\");\nconst HKDF_INFO_OUTPUT = new TextEncoder().encode(\"sgl-e2e-v2-output\");\n\nfunction v2Key(shared: Uint8Array, info: Uint8Array): Uint8Array {\n return hkdf(sha256, shared, HKDF_SALT, info, 32);\n}\nfunction aadInput(nodeB58: string, ephB58: string, respB58: string): Uint8Array {\n return new TextEncoder().encode(`sgl-aad/v2/input|node=${nodeB58}|eph=${ephB58}|resp=${respB58}`);\n}\nfunction aadOutput(respB58: string, ephB58: string): Uint8Array {\n return new TextEncoder().encode(`sgl-aad/v2/output|resp=${respB58}|eph=${ephB58}`);\n}\nfunction aadStream(respB58: string, ephB58: string, nonceB58: string, seq: number, isFinal: boolean): Uint8Array {\n return new TextEncoder().encode(\n `sgl-aad/v2/stream|resp=${respB58}|eph=${ephB58}|nonce=${nonceB58}|seq=${seq}|final=${isFinal ? 1 : 0}`,\n );\n}\n\nfunction b58enc(u: Uint8Array): string {\n return bs58.encode(u);\n}\nfunction b58dec(s: string): Uint8Array {\n return bs58.decode(s);\n}\nfunction randomBytes(n: number): Uint8Array {\n return crypto.getRandomValues(new Uint8Array(n));\n}\n\nexport interface ResponseKeypair {\n secret: Uint8Array;\n pubB58: string;\n}\n\n/** The caller's response keypair — the node seals its reply to this. */\nexport function newResponseKeypair(): ResponseKeypair {\n const secret = x25519.utils.randomPrivateKey();\n return { secret, pubB58: b58enc(x25519.getPublicKey(secret)) };\n}\n\n/** A per-request nonce bound into every stream chunk's AAD. */\nexport function randomNonceB58(): string {\n return b58enc(randomBytes(16));\n}\n\n/** Seal the prompt to the node's X25519 key. */\nexport function sealInputV2(\n nodePubB58: string,\n respPubB58: string,\n plaintext: Uint8Array,\n): { ciphertext: string; ephemeralPub: string } {\n const nodePub = b58dec(nodePubB58);\n const ephSecret = x25519.utils.randomPrivateKey();\n const ephPub = x25519.getPublicKey(ephSecret);\n const ephB58 = b58enc(ephPub);\n const shared = x25519.getSharedSecret(ephSecret, nodePub);\n const key = v2Key(shared, HKDF_INFO_INPUT);\n const aad = aadInput(nodePubB58, ephB58, respPubB58);\n const nonce = randomBytes(24);\n const ct = xchacha20poly1305(key, nonce, aad).encrypt(plaintext);\n const out = new Uint8Array(24 + ct.length);\n out.set(nonce, 0);\n out.set(ct, 24);\n return { ciphertext: b58enc(out), ephemeralPub: ephB58 };\n}\n\n/** Open the node's (non-stream) reply sealed to our response key. */\nexport function openOutputV2(\n respSecret: Uint8Array,\n respPubB58: string,\n nodeEphB58: string,\n ciphertextB58: string,\n): Uint8Array {\n const shared = x25519.getSharedSecret(respSecret, b58dec(nodeEphB58));\n const key = v2Key(shared, HKDF_INFO_OUTPUT);\n const aad = aadOutput(respPubB58, nodeEphB58);\n const blob = b58dec(ciphertextB58);\n return xchacha20poly1305(key, blob.slice(0, 24), aad).decrypt(blob.slice(24));\n}\n\n/** Derive the stream output key once from the node's stream ephemeral (chunk 0). */\nexport function streamOutKey(respSecret: Uint8Array, nodeStreamEphB58: string): Uint8Array {\n const shared = x25519.getSharedSecret(respSecret, b58dec(nodeStreamEphB58));\n return v2Key(shared, HKDF_INFO_OUTPUT);\n}\n\n/** Open one stream chunk with the precomputed key + nonce/seq/final-bound AAD. */\nexport function openStreamChunk(\n outKey: Uint8Array,\n respPubB58: string,\n streamEphB58: string,\n reqNonceB58: string,\n seq: number,\n isFinal: boolean,\n ctB58: string,\n): Uint8Array {\n const aad = aadStream(respPubB58, streamEphB58, reqNonceB58, seq, isFinal);\n const blob = b58dec(ctB58);\n return xchacha20poly1305(outKey, blob.slice(0, 24), aad).decrypt(blob.slice(24));\n}\n","import { SGLAPIError, SGLAuthError, SGLConnectionError, SGLNotFoundError } from \"./errors.js\";\nimport * as e2e from \"./e2e.js\";\nimport type {\n AttestationProof,\n CapacityResponse,\n ChatCompletionRequest,\n ChatCompletionResponse,\n EmbeddingRequest,\n EmbeddingResponse,\n DeployProcessorOptions,\n GridClientOptions,\n JobResponse,\n JobResult,\n ModelInfo,\n PricingInfo,\n ProcessorDeployResult,\n ProcessorInfo,\n ProcessorInvokeResult,\n ProcessorListResponse,\n ProcessorLogEntry,\n ProcessorLogsResponse,\n ProviderInfo,\n ProvidersResponse,\n ReserveResponse,\n WalletAuth,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://grid.x402compute.cc\";\n\nconst DEFAULT_TIMEOUT = 60_000;\n\nexport class GridClient {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly timeout: number;\n\n constructor(options: GridClientOptions = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.headers = { Accept: \"application/json\", \"Content-Type\": \"application/json\" };\n if (options.apiKey) {\n this.headers[\"Authorization\"] = `Bearer ${options.apiKey}`;\n // Grid credit billing reads X-API-Key; send both so reserve + chat resolve\n // the paying wallet (credits mode) rather than falling back to anonymous x402.\n this.headers[\"X-API-Key\"] = options.apiKey;\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n else if (err && typeof err === \"object\" && \"message\" in err)\n message = String((err as { message: unknown }).message);\n } catch {\n /* body not JSON */\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SGLAuthError(response.status, message, errorBody);\n }\n if (response.status === 404) {\n throw new SGLNotFoundError(message, errorBody);\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n if (response.status === 204) return {} as T;\n return (await response.json()) as T;\n }\n\n // -- Public endpoints (no auth) ------------------------------------------\n\n async capacity(): Promise<CapacityResponse> {\n return this.request<CapacityResponse>(\"GET\", \"/grid/capacity\");\n }\n\n async models(): Promise<ModelInfo[]> {\n const data = await this.request<{ models: ModelInfo[] }>(\"GET\", \"/grid/models\");\n return data.models ?? [];\n }\n\n async pricing(): Promise<PricingInfo[]> {\n const data = await this.request<{ pricing: PricingInfo[] }>(\"GET\", \"/grid/pricing\");\n return data.pricing ?? [];\n }\n\n /**\n * List the nodes serving a model with each node's effective per-token price\n * (operator's custom price if set, else the platform reference), cheapest\n * first. Pass a chosen `node_id` as `node` on `chatCompletions` to pin it,\n * or omit to let the grid route. Optional `cluster` filter (slug or id).\n */\n async providers(\n model: string,\n options?: { cluster?: string },\n ): Promise<ProviderInfo[]> {\n const params = new URLSearchParams({ model });\n if (options?.cluster) params.set(\"cluster\", options.cluster);\n const data = await this.request<ProvidersResponse>(\n \"GET\",\n `/v1/providers?${params.toString()}`,\n );\n return data.providers ?? [];\n }\n\n // -- Authenticated endpoints ---------------------------------------------\n\n async submitJob(\n model: string,\n input: Record<string, unknown>,\n options?: { submitterWallet?: string; submitterChain?: string },\n ): Promise<JobResponse> {\n const body: Record<string, unknown> = { model, input };\n if (options?.submitterWallet) body.submitter_wallet = options.submitterWallet;\n if (options?.submitterChain) body.submitter_chain = options.submitterChain;\n return this.request<JobResponse>(\"POST\", \"/grid/jobs\", body);\n }\n\n async getJob(jobId: string): Promise<JobResult> {\n return this.request<JobResult>(\"GET\", `/grid/jobs/${jobId}`);\n }\n\n async getAttestation(jobId: string): Promise<AttestationProof> {\n return this.request<AttestationProof>(\"GET\", `/grid/jobs/${jobId}/attestation`);\n }\n\n // -- OpenAI-compatible (end-to-end encrypted) ----------------------------\n\n /** Reserve a node + learn its X25519 key so we can seal the prompt to it.\n * Forwards an optional pinned `node` (see `providers()`), `cluster` filter,\n * and `pay_in_coin` so the orchestrator reserves + quotes accordingly. */\n private async reserve(req: {\n model: string;\n node?: string;\n cluster?: string;\n pay_in_coin?: boolean;\n max_price?: number;\n }): Promise<ReserveResponse> {\n const body: Record<string, unknown> = { model: req.model };\n if (req.node) body.node = req.node;\n if (req.cluster) body.cluster = req.cluster;\n if (req.pay_in_coin) body.pay_in_coin = req.pay_in_coin;\n if (req.max_price != null) body.max_price = req.max_price;\n const res = await this.request<ReserveResponse>(\"POST\", \"/v1/reserve\", body);\n if (!res.node_x25519_pubkey) {\n throw new SGLAPIError(503, \"Reserved node does not support E2E encryption\");\n }\n return res;\n }\n\n /**\n * End-to-end encrypted chat completion. The prompt is sealed in this client to\n * the serving node's key and only decrypts inside its TEE — the orchestrator\n * only relays ciphertext. Requires an `apiKey` (credits); without one the grid\n * replies 402 (the SDK does not sign x402 payments — use the wallet/browser flow).\n */\n async chatCompletions(\n request: ChatCompletionRequest,\n ): Promise<ChatCompletionResponse> {\n if (request.stream) {\n // Collapse the stream into a single response for the non-streaming API.\n let content = \"\";\n for await (const delta of this.chatCompletionStream(request)) content += delta;\n return {\n id: \"\", object: \"chat.completion\", created: 0, model: request.model,\n choices: [{ index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" }],\n };\n }\n\n const reservation = await this.reserve(request);\n const { secret, pubB58 } = e2e.newResponseKeypair();\n const maxTokens = request.max_tokens ?? 512;\n const sealed = e2e.sealInputV2(\n reservation.node_x25519_pubkey,\n pubB58,\n new TextEncoder().encode(JSON.stringify({\n messages: request.messages,\n temperature: request.temperature ?? 0.7,\n max_tokens: maxTokens,\n })),\n );\n const body = {\n reservation_token: reservation.reservation_token,\n max_tokens: maxTokens, // cleartext, only used to quote the x402 price\n enc: {\n ciphertext: sealed.ciphertext,\n client_ephemeral_pubkey: sealed.ephemeralPub,\n client_response_pubkey: pubB58,\n algorithm: e2e.ALGO_V2,\n },\n };\n\n let data: {\n id?: string; created?: number; sealed_result?: { ephemeral_public_key: string; ciphertext: string };\n usage?: ChatCompletionResponse[\"usage\"];\n };\n try {\n data = await this.request(\"POST\", \"/v1/chat/completions\", body);\n } catch (err) {\n if (err instanceof SGLAPIError && err.statusCode === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n throw err;\n }\n\n if (!data.sealed_result) throw new SGLAPIError(500, \"No sealed result returned\");\n const plain = e2e.openOutputV2(secret, pubB58, data.sealed_result.ephemeral_public_key, data.sealed_result.ciphertext);\n const parsed = JSON.parse(new TextDecoder().decode(plain)) as { content?: string; usage?: ChatCompletionResponse[\"usage\"] };\n\n return {\n id: data.id ?? \"\",\n object: \"chat.completion\",\n created: data.created ?? 0,\n model: request.model,\n choices: [{ index: 0, message: { role: \"assistant\", content: parsed.content ?? \"\" }, finish_reason: \"stop\" }],\n usage: data.usage ?? parsed.usage,\n attestation: {\n nodeId: reservation.node_id,\n teeType: reservation.tee_type ?? null,\n verified: !!reservation.attestation_verified,\n },\n };\n }\n\n /**\n * Create embeddings via the grid's OpenAI-compatible `/v1/embeddings` endpoint.\n *\n * `input` is a string or array of strings; `dimensions` truncates Matryoshka models\n * (e.g. nomic 768→256); `input_type` ('query' | 'document') hints asymmetric\n * retrieval models. Billed on input tokens only — there is no generation. Requires\n * an `apiKey` (credits); the TS SDK does not sign x402 payments. Unlike chat, the\n * input is not client-sealed — the orchestrator seals it to the node in-TEE. The\n * returned `data` is ordered to match `input`.\n */\n async embed(request: EmbeddingRequest): Promise<EmbeddingResponse> {\n const body: Record<string, unknown> = { model: request.model, input: request.input };\n if (request.dimensions != null) body.dimensions = request.dimensions;\n if (request.input_type != null) body.input_type = request.input_type;\n if (request.tier != null) body.tier = request.tier;\n try {\n return (await this.request(\"POST\", \"/v1/embeddings\", body)) as EmbeddingResponse;\n } catch (err) {\n if (err instanceof SGLAPIError && err.statusCode === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n throw err;\n }\n }\n\n /**\n * Streaming end-to-end encrypted chat completion. Yields decoded text as it\n * arrives; each chunk is decrypted and its ordering + termination verified (a\n * truncated stream throws). Requires `apiKey` (credits). If the server isn't\n * streaming (toggle off), the whole reply is yielded as a single chunk.\n */\n async *chatCompletionStream(\n request: ChatCompletionRequest,\n ): AsyncGenerator<string, void, unknown> {\n const reservation = await this.reserve(request);\n const { secret, pubB58 } = e2e.newResponseKeypair();\n const nonce = e2e.randomNonceB58();\n const maxTokens = request.max_tokens ?? 512;\n const sealed = e2e.sealInputV2(\n reservation.node_x25519_pubkey,\n pubB58,\n new TextEncoder().encode(JSON.stringify({\n messages: request.messages,\n temperature: request.temperature ?? 0.7,\n max_tokens: maxTokens,\n stream: true,\n nonce,\n })),\n );\n const body = {\n reservation_token: reservation.reservation_token,\n stream: true,\n max_tokens: maxTokens,\n enc: {\n ciphertext: sealed.ciphertext,\n client_ephemeral_pubkey: sealed.ephemeralPub,\n client_response_pubkey: pubB58,\n algorithm: e2e.ALGO_V2,\n },\n };\n\n const controller = new AbortController();\n const overall = setTimeout(() => controller.abort(), this.timeout);\n let resp: Response;\n try {\n resp = await fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(overall);\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n if (!resp.ok) {\n clearTimeout(overall);\n if (resp.status === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n let message = resp.statusText;\n try {\n const j = (await resp.json()) as { error?: unknown };\n if (typeof j.error === \"string\") message = j.error;\n else if (j.error && typeof j.error === \"object\" && \"message\" in j.error) message = String((j.error as { message: unknown }).message);\n } catch { /* ignore */ }\n throw new SGLAPIError(resp.status, message);\n }\n\n const ctype = resp.headers.get(\"content-type\") ?? \"\";\n if (!ctype.includes(\"text/event-stream\") || !resp.body) {\n clearTimeout(overall);\n const data = (await resp.json()) as { sealed_result?: { ephemeral_public_key: string; ciphertext: string } };\n if (!data.sealed_result) throw new SGLAPIError(500, \"No sealed result returned\");\n const plain = e2e.openOutputV2(secret, pubB58, data.sealed_result.ephemeral_public_key, data.sealed_result.ciphertext);\n const content = (JSON.parse(new TextDecoder().decode(plain)) as { content?: string }).content ?? \"\";\n if (content) yield content;\n return;\n }\n\n const reader = resp.body.getReader();\n const decoder = new TextDecoder();\n const INACTIVITY_MS = 60_000;\n const readChunk = async (): Promise<ReadableStreamReadResult<Uint8Array>> => {\n let t: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n t = setTimeout(() => reject(new SGLConnectionError(\"stream timed out (no tokens)\")), INACTIVITY_MS);\n });\n try {\n return (await Promise.race([reader.read(), timeout])) as ReadableStreamReadResult<Uint8Array>;\n } finally {\n if (t) clearTimeout(t);\n }\n };\n\n let buf = \"\";\n let expectedSeq = 0;\n let outKey: Uint8Array | null = null;\n let streamEph: string | null = null;\n let sawFinal = false;\n try {\n for (;;) {\n if (sawFinal) break;\n const { value, done } = await readChunk();\n if (done) break;\n // Normalize CRLF so \\n\\n event framing works regardless of line endings.\n buf += decoder.decode(value, { stream: true }).replace(/\\r\\n/g, \"\\n\");\n let idx: number;\n while ((idx = buf.indexOf(\"\\n\\n\")) !== -1) {\n const raw = buf.slice(0, idx);\n buf = buf.slice(idx + 2);\n if (raw.includes(\"event: error\")) throw new SGLAPIError(502, \"stream aborted by server\");\n const dataStr = raw.split(\"\\n\").filter((l) => l.startsWith(\"data:\")).map((l) => l.slice(5).trim()).join(\"\\n\");\n if (!dataStr || dataStr === \"[DONE]\") continue;\n // Fail closed: a malformed or non-chunk data event is a protocol error.\n let chunk: { seq?: number; final?: boolean; eph?: string; ct?: string };\n try {\n chunk = JSON.parse(dataStr);\n } catch {\n throw new SGLAPIError(502, \"malformed stream chunk\");\n }\n if (typeof chunk.seq !== \"number\" || !chunk.ct) {\n throw new SGLAPIError(502, \"invalid stream chunk (missing seq/ciphertext)\");\n }\n if (chunk.seq !== expectedSeq) throw new SGLAPIError(502, `stream out of order (expected ${expectedSeq}, got ${chunk.seq})`);\n if (chunk.seq === 0) {\n if (!chunk.eph) throw new SGLAPIError(502, \"stream chunk 0 missing ephemeral key\");\n streamEph = chunk.eph;\n outKey = e2e.streamOutKey(secret, streamEph);\n }\n const isFinal = chunk.final === true;\n const text = new TextDecoder().decode(\n e2e.openStreamChunk(outKey as Uint8Array, pubB58, streamEph as string, nonce, chunk.seq, isFinal, chunk.ct),\n );\n if (text) yield text;\n expectedSeq++;\n if (isFinal) { sawFinal = true; break; }\n }\n }\n } finally {\n clearTimeout(overall);\n try { await reader.cancel(); } catch { /* ignore */ }\n }\n if (!sawFinal) throw new SGLAPIError(502, \"stream ended before final chunk (truncated)\");\n }\n\n // -- Processor helpers ----------------------------------------------------\n\n private async requestWithWalletAuth<T>(\n method: string,\n path: string,\n wallet: WalletAuth,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n const reqHeaders: Record<string, string> = {\n ...this.headers,\n \"X-Auth-Address\": wallet.address,\n \"X-Auth-Chain\": wallet.chain ?? \"solana\",\n \"X-Auth-Signature\": wallet.signature,\n \"X-Auth-Timestamp\": wallet.timestamp,\n \"X-Auth-Nonce\": wallet.nonce,\n };\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n else if (err && typeof err === \"object\" && \"message\" in err)\n message = String((err as { message: unknown }).message);\n } catch {\n /* body not JSON */\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SGLAuthError(response.status, message, errorBody);\n }\n if (response.status === 404) {\n throw new SGLNotFoundError(message, errorBody);\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n if (response.status === 204) return {} as T;\n return (await response.json()) as T;\n }\n\n private async requestWithPayment<T>(\n method: string,\n path: string,\n body?: unknown,\n paymentHeader?: string,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n const reqHeaders: Record<string, string> = { ...this.headers };\n if (paymentHeader) {\n reqHeaders[\"X-Payment\"] = paymentHeader;\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (response.status === 402) {\n const requirements = (await response.json()) as Record<string, unknown>;\n throw new SGLAPIError(402, \"Payment required\", requirements);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n } catch {\n /* body not JSON */\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n return (await response.json()) as T;\n }\n\n // -- Processors -----------------------------------------------------------\n\n async deployProcessor(\n wallet: WalletAuth,\n options: DeployProcessorOptions,\n ): Promise<ProcessorDeployResult> {\n return this.requestWithWalletAuth<ProcessorDeployResult>(\n \"POST\",\n \"/grid/processors\",\n wallet,\n options,\n );\n }\n\n async invokeProcessor(\n processorName: string,\n input: Record<string, unknown>,\n options?: { paymentHeader?: string; paymentToken?: \"USDC\" | \"SGL\" },\n ): Promise<ProcessorInvokeResult> {\n const body: Record<string, unknown> = { input };\n if (options?.paymentToken) body.payment_token = options.paymentToken;\n return this.requestWithPayment<ProcessorInvokeResult>(\n \"POST\",\n `/grid/processors/${encodeURIComponent(processorName)}/invoke`,\n body,\n options?.paymentHeader,\n );\n }\n\n async listProcessors(options?: {\n owner?: string;\n page?: number;\n limit?: number;\n }): Promise<ProcessorListResponse> {\n const params = new URLSearchParams();\n if (options?.owner) params.set(\"owner\", options.owner);\n if (options?.page != null) params.set(\"page\", String(options.page));\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n const qs = params.toString();\n return this.request<ProcessorListResponse>(\n \"GET\",\n `/grid/processors${qs ? `?${qs}` : \"\"}`,\n );\n }\n\n async getProcessor(processorId: string): Promise<ProcessorInfo> {\n return this.request<ProcessorInfo>(\"GET\", `/grid/processors/${processorId}`);\n }\n\n async deleteProcessor(\n processorId: string,\n wallet: WalletAuth,\n ): Promise<{ deleted: boolean; id: string }> {\n return this.requestWithWalletAuth<{ deleted: boolean; id: string }>(\n \"DELETE\",\n `/grid/processors/${processorId}`,\n wallet,\n );\n }\n\n async getProcessorLogs(\n processorId: string,\n wallet: WalletAuth,\n options?: { page?: number; limit?: number },\n ): Promise<ProcessorLogsResponse> {\n const params = new URLSearchParams();\n if (options?.page != null) params.set(\"page\", String(options.page));\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n const qs = params.toString();\n return this.requestWithWalletAuth<ProcessorLogsResponse>(\n \"GET\",\n `/grid/processors/${processorId}/logs${qs ? `?${qs}` : \"\"}`,\n wallet,\n );\n }\n}\n","/**\n * Agent Vault — zero-knowledge encrypted agent backup/restore.\n *\n * Pure-JS envelope (noble scrypt + AES-256-GCM), byte-compatible with the\n * agentvault CLI, the pod runner, and the Python SDK:\n * `[4-byte BE header length][JSON header][GCM body, tag appended]`, with the\n * snapshot identity bound into the GCM AAD. Runs in Node AND browsers.\n *\n * Scope: this module encrypts/decrypts BYTES and drives the API. Packing a\n * directory into a tarball is filesystem work — use the `agentvault` CLI or\n * the Python SDK for that, or bring your own archive bytes.\n *\n * Auth: a Singularity compute API key (X-API-Key). Passphrases and plaintext\n * never leave this process.\n */\n\nimport { gcm } from \"@noble/ciphers/aes\";\nimport { scrypt } from \"@noble/hashes/scrypt\";\nimport { SGLAPIError } from \"./errors.js\";\n\nexport const VAULT_URL = \"https://compute.x402layer.cc\";\n\nconst SCRYPT_PARAMS = { N: 1 << 17, r: 8, p: 1 } as const;\nconst SCRYPT_MIN_N = 1 << 15;\n\n// ─── Envelope (wire-identical to agentvault-core) ───────────────────────────\n\nexport interface VaultAad {\n userId: string;\n agentId: string;\n backupId: string;\n formatVersion: 1;\n}\n\nconst te = new TextEncoder();\nconst td = new TextDecoder();\n\nfunction aadBytes(aad: VaultAad): Uint8Array {\n // Canonical key order — byte-identical across CLI, pod runner, Python SDK.\n const { agentId, backupId, formatVersion, userId } = aad;\n return te.encode(JSON.stringify({ agentId, backupId, formatVersion, userId }));\n}\n\nfunction b64(x: Uint8Array): string {\n let s = \"\";\n for (const b of x) s += String.fromCharCode(b);\n return btoa(s);\n}\n\nfunction unb64(s: string): Uint8Array {\n const bin = atob(s);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nfunction rand(n: number): Uint8Array {\n const out = new Uint8Array(n);\n crypto.getRandomValues(out);\n return out;\n}\n\n/** Envelope-encrypt arbitrary bytes under a passphrase (scrypt + AES-256-GCM). */\nexport function encryptEnvelope(plaintext: Uint8Array, passphrase: string, aad: VaultAad): Uint8Array {\n const salt = rand(16);\n const kek = scrypt(te.encode(passphrase), salt, { ...SCRYPT_PARAMS, dkLen: 32 });\n const dek = rand(32);\n const aadBuf = aadBytes(aad);\n const dekNonce = rand(12);\n const wrapped = gcm(kek, dekNonce, aadBuf).encrypt(dek); // ciphertext||tag\n const blobNonce = rand(12);\n const body = gcm(dek, blobNonce, aadBuf).encrypt(plaintext);\n const header = te.encode(JSON.stringify({\n formatVersion: 1,\n kdf: \"scrypt\",\n kdfParams: { ...SCRYPT_PARAMS, salt: b64(salt) },\n cipher: \"aes-256-gcm\",\n wrappedDek: { nonce: b64(dekNonce), ciphertext: b64(wrapped) },\n blobNonce: b64(blobNonce),\n aad,\n }));\n const out = new Uint8Array(4 + header.length + body.length);\n new DataView(out.buffer).setUint32(0, header.length, false);\n out.set(header, 4);\n out.set(body, 4 + header.length);\n return out;\n}\n\n/** Reverse of encryptEnvelope. Throws on wrong passphrase or AAD mismatch. */\nexport function decryptEnvelope(blob: Uint8Array, passphrase: string, aad: VaultAad): Uint8Array {\n if (blob.length < 4) throw new SGLAPIError(0, \"malformed blob: too short\");\n const headerLen = new DataView(blob.buffer, blob.byteOffset).getUint32(0, false);\n if (4 + headerLen > blob.length) throw new SGLAPIError(0, \"malformed blob: header length out of bounds\");\n let header: {\n kdf?: string;\n kdfParams?: { N?: number; r?: number; p?: number; salt?: string };\n wrappedDek?: { nonce?: string; ciphertext?: string };\n blobNonce?: string;\n };\n try {\n header = JSON.parse(td.decode(blob.subarray(4, 4 + headerLen)));\n } catch {\n throw new SGLAPIError(0, \"malformed blob: invalid header JSON\");\n }\n if (header.kdf !== \"scrypt\") {\n throw new SGLAPIError(0, `this backup uses ${String(header.kdf)} key derivation — restore it with the agentvault CLI`);\n }\n const p = header.kdfParams ?? {};\n if (\n !Number.isInteger(p.N) || (p.N as number) < SCRYPT_MIN_N || (p.N as number) > SCRYPT_PARAMS.N ||\n ((p.N as number) & ((p.N as number) - 1)) !== 0 ||\n !Number.isInteger(p.r) || (p.r as number) < 8 || (p.r as number) > 16 ||\n !Number.isInteger(p.p) || (p.p as number) < 1 || (p.p as number) > 4 ||\n typeof p.salt !== \"string\" || !header.wrappedDek?.nonce || !header.wrappedDek?.ciphertext || !header.blobNonce\n ) {\n throw new SGLAPIError(0, \"malformed blob: unsupported header parameters\");\n }\n const salt = unb64(p.salt);\n if (salt.length < 16) throw new SGLAPIError(0, \"malformed blob: salt too short\");\n const kek = scrypt(te.encode(passphrase), salt, { N: p.N as number, r: p.r as number, p: p.p as number, dkLen: 32 });\n const aadBuf = aadBytes(aad);\n try {\n const dek = gcm(kek, unb64(header.wrappedDek.nonce), aadBuf).decrypt(unb64(header.wrappedDek.ciphertext));\n return gcm(dek, unb64(header.blobNonce), aadBuf).decrypt(blob.subarray(4 + headerLen));\n } catch {\n throw new SGLAPIError(0, \"incorrect passphrase or corrupted backup\");\n }\n}\n\nexport function parseAadFromKey(r2Key: string): VaultAad {\n const parts = r2Key.split(\"/\");\n if (parts.length !== 5 || parts[0] !== \"backups\" || parts[4] !== \"blob.enc\"\n || !parts[1] || !parts[2] || !parts[3]) {\n throw new SGLAPIError(0, `malformed r2 key: ${r2Key}`);\n }\n return { userId: parts[1], agentId: parts[2], backupId: parts[3], formatVersion: 1 };\n}\n\n// ─── API client ─────────────────────────────────────────────────────────────\n\nexport interface VaultAgent {\n id: string;\n name: string;\n framework: string;\n source: \"local\" | \"pod\";\n pod_order_id: string | null;\n}\n\nexport interface VaultSnapshot {\n id: string;\n agent_id: string;\n size_bytes: number;\n sha256: string | null;\n created_at: string;\n}\n\nexport interface VaultUsage {\n plan: \"free\" | \"pro\";\n planRenewsAt: string | null;\n bytesUsed: number;\n bytesReserved: number;\n maxBytes: number;\n proPriceUsd: number;\n}\n\nexport interface VaultClientOptions {\n apiKey: string;\n baseUrl?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport class VaultClient {\n private readonly base: string;\n private readonly apiKey: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: VaultClientOptions) {\n const base = (options.baseUrl ?? VAULT_URL).replace(/\\/+$/, \"\");\n const u = new URL(base);\n const local = [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(u.hostname);\n if (u.protocol !== \"https:\" && !local) {\n throw new SGLAPIError(0, \"baseUrl must be https (the API key travels in a header)\");\n }\n if (u.username || u.password || u.search || u.hash) {\n throw new SGLAPIError(0, \"baseUrl must be a bare origin\");\n }\n this.base = base;\n this.apiKey = options.apiKey;\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n private static id(v: string): string {\n if (!/^[0-9a-fA-F-]{36}$/.test(v)) throw new SGLAPIError(0, `not a snapshot id: ${v}`);\n return v.toLowerCase();\n }\n\n private async call<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await this.fetchImpl(`${this.base}${path}`, {\n method,\n headers: {\n \"x-api-key\": this.apiKey,\n ...(body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) throw new SGLAPIError(res.status, String(data.error ?? `request failed: ${res.status}`));\n return data as T;\n }\n\n async agents(): Promise<VaultAgent[]> {\n return (await this.call<{ agents: VaultAgent[] }>(\"GET\", \"/backups/agents\")).agents;\n }\n\n async createAgent(name: string, framework: string): Promise<VaultAgent> {\n return (await this.call<{ agent: VaultAgent }>(\"POST\", \"/backups/agents\", { name, framework })).agent;\n }\n\n async snapshots(agentId?: string): Promise<VaultSnapshot[]> {\n const q = agentId ? `?agentId=${encodeURIComponent(agentId)}` : \"\";\n return (await this.call<{ backups: VaultSnapshot[] }>(\"GET\", `/backups${q}`)).backups;\n }\n\n async usage(): Promise<VaultUsage> {\n return this.call<VaultUsage>(\"GET\", \"/backups/usage\");\n }\n\n /** Activate Vault Pro ($3/mo from credits). */\n async subscribePro(): Promise<{ ok: boolean; already?: boolean }> {\n return this.call(\"POST\", \"/backups/subscribe\");\n }\n\n async deleteSnapshot(id: string): Promise<void> {\n await this.call(\"DELETE\", `/backups/${VaultClient.id(id)}`);\n }\n\n /**\n * Encrypt + upload arbitrary payload bytes (e.g. a tarball you packed) as a\n * snapshot of `agentId`. Returns the snapshot id.\n */\n async backupBytes(agentId: string, payload: Uint8Array, passphrase: string): Promise<string> {\n const res = await this.call<{ backupId: string; r2Key: string; uploadUrl: string }>(\n \"POST\", \"/backups\", { agentId, sizeBytes: payload.length },\n );\n const blob = encryptEnvelope(payload, passphrase, parseAadFromKey(res.r2Key));\n const up = await this.fetchImpl(res.uploadUrl, {\n method: \"PUT\",\n body: blob as unknown as BodyInit,\n headers: { \"content-type\": \"application/octet-stream\" },\n });\n if (!up.ok) throw new SGLAPIError(up.status, `upload failed: ${up.status}`);\n const digest = await crypto.subtle.digest(\"SHA-256\", blob as unknown as ArrayBuffer);\n const sha256 = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n await this.call(\"POST\", `/backups/${res.backupId}/complete`, { sha256 });\n return res.backupId;\n }\n\n /** Download + decrypt a snapshot's payload bytes. */\n async restoreBytes(snapshotId: string, passphrase: string): Promise<Uint8Array> {\n const info = await this.call<{ downloadUrl: string; r2Key: string }>(\"GET\", `/backups/${VaultClient.id(snapshotId)}/restore`);\n const dl = await this.fetchImpl(info.downloadUrl);\n if (!dl.ok) throw new SGLAPIError(dl.status, `download failed: ${dl.status}`);\n const blob = new Uint8Array(await dl.arrayBuffer());\n return decryptEnvelope(blob, passphrase, parseAadFromKey(info.r2Key));\n }\n}\n"],"mappings":"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","names":["bs58","sha256"]}
|
package/dist/index.mjs
CHANGED
|
@@ -597,6 +597,177 @@ var GridClient = class {
|
|
|
597
597
|
);
|
|
598
598
|
}
|
|
599
599
|
};
|
|
600
|
+
|
|
601
|
+
// src/vault.ts
|
|
602
|
+
import { gcm } from "@noble/ciphers/aes";
|
|
603
|
+
import { scrypt } from "@noble/hashes/scrypt";
|
|
604
|
+
var VAULT_URL = "https://compute.x402layer.cc";
|
|
605
|
+
var SCRYPT_PARAMS = { N: 1 << 17, r: 8, p: 1 };
|
|
606
|
+
var SCRYPT_MIN_N = 1 << 15;
|
|
607
|
+
var te = new TextEncoder();
|
|
608
|
+
var td = new TextDecoder();
|
|
609
|
+
function aadBytes(aad) {
|
|
610
|
+
const { agentId, backupId, formatVersion, userId } = aad;
|
|
611
|
+
return te.encode(JSON.stringify({ agentId, backupId, formatVersion, userId }));
|
|
612
|
+
}
|
|
613
|
+
function b64(x) {
|
|
614
|
+
let s = "";
|
|
615
|
+
for (const b of x) s += String.fromCharCode(b);
|
|
616
|
+
return btoa(s);
|
|
617
|
+
}
|
|
618
|
+
function unb64(s) {
|
|
619
|
+
const bin = atob(s);
|
|
620
|
+
const out = new Uint8Array(bin.length);
|
|
621
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
622
|
+
return out;
|
|
623
|
+
}
|
|
624
|
+
function rand(n) {
|
|
625
|
+
const out = new Uint8Array(n);
|
|
626
|
+
crypto.getRandomValues(out);
|
|
627
|
+
return out;
|
|
628
|
+
}
|
|
629
|
+
function encryptEnvelope(plaintext, passphrase, aad) {
|
|
630
|
+
const salt = rand(16);
|
|
631
|
+
const kek = scrypt(te.encode(passphrase), salt, { ...SCRYPT_PARAMS, dkLen: 32 });
|
|
632
|
+
const dek = rand(32);
|
|
633
|
+
const aadBuf = aadBytes(aad);
|
|
634
|
+
const dekNonce = rand(12);
|
|
635
|
+
const wrapped = gcm(kek, dekNonce, aadBuf).encrypt(dek);
|
|
636
|
+
const blobNonce = rand(12);
|
|
637
|
+
const body = gcm(dek, blobNonce, aadBuf).encrypt(plaintext);
|
|
638
|
+
const header = te.encode(JSON.stringify({
|
|
639
|
+
formatVersion: 1,
|
|
640
|
+
kdf: "scrypt",
|
|
641
|
+
kdfParams: { ...SCRYPT_PARAMS, salt: b64(salt) },
|
|
642
|
+
cipher: "aes-256-gcm",
|
|
643
|
+
wrappedDek: { nonce: b64(dekNonce), ciphertext: b64(wrapped) },
|
|
644
|
+
blobNonce: b64(blobNonce),
|
|
645
|
+
aad
|
|
646
|
+
}));
|
|
647
|
+
const out = new Uint8Array(4 + header.length + body.length);
|
|
648
|
+
new DataView(out.buffer).setUint32(0, header.length, false);
|
|
649
|
+
out.set(header, 4);
|
|
650
|
+
out.set(body, 4 + header.length);
|
|
651
|
+
return out;
|
|
652
|
+
}
|
|
653
|
+
function decryptEnvelope(blob, passphrase, aad) {
|
|
654
|
+
if (blob.length < 4) throw new SGLAPIError(0, "malformed blob: too short");
|
|
655
|
+
const headerLen = new DataView(blob.buffer, blob.byteOffset).getUint32(0, false);
|
|
656
|
+
if (4 + headerLen > blob.length) throw new SGLAPIError(0, "malformed blob: header length out of bounds");
|
|
657
|
+
let header;
|
|
658
|
+
try {
|
|
659
|
+
header = JSON.parse(td.decode(blob.subarray(4, 4 + headerLen)));
|
|
660
|
+
} catch {
|
|
661
|
+
throw new SGLAPIError(0, "malformed blob: invalid header JSON");
|
|
662
|
+
}
|
|
663
|
+
if (header.kdf !== "scrypt") {
|
|
664
|
+
throw new SGLAPIError(0, `this backup uses ${String(header.kdf)} key derivation \u2014 restore it with the agentvault CLI`);
|
|
665
|
+
}
|
|
666
|
+
const p = header.kdfParams ?? {};
|
|
667
|
+
if (!Number.isInteger(p.N) || p.N < SCRYPT_MIN_N || p.N > SCRYPT_PARAMS.N || (p.N & p.N - 1) !== 0 || !Number.isInteger(p.r) || p.r < 8 || p.r > 16 || !Number.isInteger(p.p) || p.p < 1 || p.p > 4 || typeof p.salt !== "string" || !header.wrappedDek?.nonce || !header.wrappedDek?.ciphertext || !header.blobNonce) {
|
|
668
|
+
throw new SGLAPIError(0, "malformed blob: unsupported header parameters");
|
|
669
|
+
}
|
|
670
|
+
const salt = unb64(p.salt);
|
|
671
|
+
if (salt.length < 16) throw new SGLAPIError(0, "malformed blob: salt too short");
|
|
672
|
+
const kek = scrypt(te.encode(passphrase), salt, { N: p.N, r: p.r, p: p.p, dkLen: 32 });
|
|
673
|
+
const aadBuf = aadBytes(aad);
|
|
674
|
+
try {
|
|
675
|
+
const dek = gcm(kek, unb64(header.wrappedDek.nonce), aadBuf).decrypt(unb64(header.wrappedDek.ciphertext));
|
|
676
|
+
return gcm(dek, unb64(header.blobNonce), aadBuf).decrypt(blob.subarray(4 + headerLen));
|
|
677
|
+
} catch {
|
|
678
|
+
throw new SGLAPIError(0, "incorrect passphrase or corrupted backup");
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
function parseAadFromKey(r2Key) {
|
|
682
|
+
const parts = r2Key.split("/");
|
|
683
|
+
if (parts.length !== 5 || parts[0] !== "backups" || parts[4] !== "blob.enc" || !parts[1] || !parts[2] || !parts[3]) {
|
|
684
|
+
throw new SGLAPIError(0, `malformed r2 key: ${r2Key}`);
|
|
685
|
+
}
|
|
686
|
+
return { userId: parts[1], agentId: parts[2], backupId: parts[3], formatVersion: 1 };
|
|
687
|
+
}
|
|
688
|
+
var VaultClient = class _VaultClient {
|
|
689
|
+
constructor(options) {
|
|
690
|
+
const base = (options.baseUrl ?? VAULT_URL).replace(/\/+$/, "");
|
|
691
|
+
const u = new URL(base);
|
|
692
|
+
const local = ["localhost", "127.0.0.1", "[::1]"].includes(u.hostname);
|
|
693
|
+
if (u.protocol !== "https:" && !local) {
|
|
694
|
+
throw new SGLAPIError(0, "baseUrl must be https (the API key travels in a header)");
|
|
695
|
+
}
|
|
696
|
+
if (u.username || u.password || u.search || u.hash) {
|
|
697
|
+
throw new SGLAPIError(0, "baseUrl must be a bare origin");
|
|
698
|
+
}
|
|
699
|
+
this.base = base;
|
|
700
|
+
this.apiKey = options.apiKey;
|
|
701
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
702
|
+
}
|
|
703
|
+
static id(v) {
|
|
704
|
+
if (!/^[0-9a-fA-F-]{36}$/.test(v)) throw new SGLAPIError(0, `not a snapshot id: ${v}`);
|
|
705
|
+
return v.toLowerCase();
|
|
706
|
+
}
|
|
707
|
+
async call(method, path, body) {
|
|
708
|
+
const res = await this.fetchImpl(`${this.base}${path}`, {
|
|
709
|
+
method,
|
|
710
|
+
headers: {
|
|
711
|
+
"x-api-key": this.apiKey,
|
|
712
|
+
...body !== void 0 ? { "content-type": "application/json" } : {}
|
|
713
|
+
},
|
|
714
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
715
|
+
});
|
|
716
|
+
const data = await res.json().catch(() => ({}));
|
|
717
|
+
if (!res.ok) throw new SGLAPIError(res.status, String(data.error ?? `request failed: ${res.status}`));
|
|
718
|
+
return data;
|
|
719
|
+
}
|
|
720
|
+
async agents() {
|
|
721
|
+
return (await this.call("GET", "/backups/agents")).agents;
|
|
722
|
+
}
|
|
723
|
+
async createAgent(name, framework) {
|
|
724
|
+
return (await this.call("POST", "/backups/agents", { name, framework })).agent;
|
|
725
|
+
}
|
|
726
|
+
async snapshots(agentId) {
|
|
727
|
+
const q = agentId ? `?agentId=${encodeURIComponent(agentId)}` : "";
|
|
728
|
+
return (await this.call("GET", `/backups${q}`)).backups;
|
|
729
|
+
}
|
|
730
|
+
async usage() {
|
|
731
|
+
return this.call("GET", "/backups/usage");
|
|
732
|
+
}
|
|
733
|
+
/** Activate Vault Pro ($3/mo from credits). */
|
|
734
|
+
async subscribePro() {
|
|
735
|
+
return this.call("POST", "/backups/subscribe");
|
|
736
|
+
}
|
|
737
|
+
async deleteSnapshot(id) {
|
|
738
|
+
await this.call("DELETE", `/backups/${_VaultClient.id(id)}`);
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Encrypt + upload arbitrary payload bytes (e.g. a tarball you packed) as a
|
|
742
|
+
* snapshot of `agentId`. Returns the snapshot id.
|
|
743
|
+
*/
|
|
744
|
+
async backupBytes(agentId, payload, passphrase) {
|
|
745
|
+
const res = await this.call(
|
|
746
|
+
"POST",
|
|
747
|
+
"/backups",
|
|
748
|
+
{ agentId, sizeBytes: payload.length }
|
|
749
|
+
);
|
|
750
|
+
const blob = encryptEnvelope(payload, passphrase, parseAadFromKey(res.r2Key));
|
|
751
|
+
const up = await this.fetchImpl(res.uploadUrl, {
|
|
752
|
+
method: "PUT",
|
|
753
|
+
body: blob,
|
|
754
|
+
headers: { "content-type": "application/octet-stream" }
|
|
755
|
+
});
|
|
756
|
+
if (!up.ok) throw new SGLAPIError(up.status, `upload failed: ${up.status}`);
|
|
757
|
+
const digest = await crypto.subtle.digest("SHA-256", blob);
|
|
758
|
+
const sha2562 = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
759
|
+
await this.call("POST", `/backups/${res.backupId}/complete`, { sha256: sha2562 });
|
|
760
|
+
return res.backupId;
|
|
761
|
+
}
|
|
762
|
+
/** Download + decrypt a snapshot's payload bytes. */
|
|
763
|
+
async restoreBytes(snapshotId, passphrase) {
|
|
764
|
+
const info = await this.call("GET", `/backups/${_VaultClient.id(snapshotId)}/restore`);
|
|
765
|
+
const dl = await this.fetchImpl(info.downloadUrl);
|
|
766
|
+
if (!dl.ok) throw new SGLAPIError(dl.status, `download failed: ${dl.status}`);
|
|
767
|
+
const blob = new Uint8Array(await dl.arrayBuffer());
|
|
768
|
+
return decryptEnvelope(blob, passphrase, parseAadFromKey(info.r2Key));
|
|
769
|
+
}
|
|
770
|
+
};
|
|
600
771
|
export {
|
|
601
772
|
DEFAULT_BASE_URL,
|
|
602
773
|
GridClient,
|
|
@@ -604,6 +775,11 @@ export {
|
|
|
604
775
|
SGLAuthError,
|
|
605
776
|
SGLConnectionError,
|
|
606
777
|
SGLError,
|
|
607
|
-
SGLNotFoundError
|
|
778
|
+
SGLNotFoundError,
|
|
779
|
+
VAULT_URL,
|
|
780
|
+
VaultClient,
|
|
781
|
+
decryptEnvelope,
|
|
782
|
+
encryptEnvelope,
|
|
783
|
+
parseAadFromKey
|
|
608
784
|
};
|
|
609
785
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/e2e.ts","../src/client.ts"],"sourcesContent":["export class SGLError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SGLError\";\n }\n}\n\nexport class SGLAPIError extends SGLError {\n readonly statusCode: number;\n readonly body?: Record<string, unknown>;\n\n constructor(\n statusCode: number,\n message: string,\n body?: Record<string, unknown>,\n ) {\n super(`HTTP ${statusCode}: ${message}`);\n this.name = \"SGLAPIError\";\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n\nexport class SGLAuthError extends SGLAPIError {\n constructor(\n statusCode: number,\n message: string,\n body?: Record<string, unknown>,\n ) {\n super(statusCode, message, body);\n this.name = \"SGLAuthError\";\n }\n}\n\nexport class SGLNotFoundError extends SGLAPIError {\n constructor(message: string, body?: Record<string, unknown>) {\n super(404, message, body);\n this.name = \"SGLNotFoundError\";\n }\n}\n\nexport class SGLConnectionError extends SGLError {\n constructor(message: string) {\n super(message);\n this.name = \"SGLConnectionError\";\n }\n}\n","/**\n * End-to-end encryption for the SGL grid (client side).\n *\n * Must match sgl-node/src/encryption.rs, the orchestrator, and the browser/Python\n * clients byte-for-byte: X25519 ECDH -> HKDF-SHA256 -> XChaCha20-Poly1305 (24-byte\n * nonce), AAD-bound. Sealed blob layout: nonce(24) || ciphertext, base58.\n *\n * The orchestrator only ever relays ciphertext — it never sees the prompt or reply.\n */\n\nimport { x25519 } from \"@noble/curves/ed25519\";\nimport { xchacha20poly1305 } from \"@noble/ciphers/chacha\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { hkdf } from \"@noble/hashes/hkdf\";\nimport bs58 from \"bs58\";\n\nexport const ALGO_V2 = \"x25519-xchacha20poly1305-hkdf-v2\";\nexport const ALGO_V2_STREAM = \"x25519-xchacha20poly1305-hkdf-v2-stream\";\n\nconst HKDF_SALT = new TextEncoder().encode(\"sgl-e2e-v2-salt\");\nconst HKDF_INFO_INPUT = new TextEncoder().encode(\"sgl-e2e-v2-input\");\nconst HKDF_INFO_OUTPUT = new TextEncoder().encode(\"sgl-e2e-v2-output\");\n\nfunction v2Key(shared: Uint8Array, info: Uint8Array): Uint8Array {\n return hkdf(sha256, shared, HKDF_SALT, info, 32);\n}\nfunction aadInput(nodeB58: string, ephB58: string, respB58: string): Uint8Array {\n return new TextEncoder().encode(`sgl-aad/v2/input|node=${nodeB58}|eph=${ephB58}|resp=${respB58}`);\n}\nfunction aadOutput(respB58: string, ephB58: string): Uint8Array {\n return new TextEncoder().encode(`sgl-aad/v2/output|resp=${respB58}|eph=${ephB58}`);\n}\nfunction aadStream(respB58: string, ephB58: string, nonceB58: string, seq: number, isFinal: boolean): Uint8Array {\n return new TextEncoder().encode(\n `sgl-aad/v2/stream|resp=${respB58}|eph=${ephB58}|nonce=${nonceB58}|seq=${seq}|final=${isFinal ? 1 : 0}`,\n );\n}\n\nfunction b58enc(u: Uint8Array): string {\n return bs58.encode(u);\n}\nfunction b58dec(s: string): Uint8Array {\n return bs58.decode(s);\n}\nfunction randomBytes(n: number): Uint8Array {\n return crypto.getRandomValues(new Uint8Array(n));\n}\n\nexport interface ResponseKeypair {\n secret: Uint8Array;\n pubB58: string;\n}\n\n/** The caller's response keypair — the node seals its reply to this. */\nexport function newResponseKeypair(): ResponseKeypair {\n const secret = x25519.utils.randomPrivateKey();\n return { secret, pubB58: b58enc(x25519.getPublicKey(secret)) };\n}\n\n/** A per-request nonce bound into every stream chunk's AAD. */\nexport function randomNonceB58(): string {\n return b58enc(randomBytes(16));\n}\n\n/** Seal the prompt to the node's X25519 key. */\nexport function sealInputV2(\n nodePubB58: string,\n respPubB58: string,\n plaintext: Uint8Array,\n): { ciphertext: string; ephemeralPub: string } {\n const nodePub = b58dec(nodePubB58);\n const ephSecret = x25519.utils.randomPrivateKey();\n const ephPub = x25519.getPublicKey(ephSecret);\n const ephB58 = b58enc(ephPub);\n const shared = x25519.getSharedSecret(ephSecret, nodePub);\n const key = v2Key(shared, HKDF_INFO_INPUT);\n const aad = aadInput(nodePubB58, ephB58, respPubB58);\n const nonce = randomBytes(24);\n const ct = xchacha20poly1305(key, nonce, aad).encrypt(plaintext);\n const out = new Uint8Array(24 + ct.length);\n out.set(nonce, 0);\n out.set(ct, 24);\n return { ciphertext: b58enc(out), ephemeralPub: ephB58 };\n}\n\n/** Open the node's (non-stream) reply sealed to our response key. */\nexport function openOutputV2(\n respSecret: Uint8Array,\n respPubB58: string,\n nodeEphB58: string,\n ciphertextB58: string,\n): Uint8Array {\n const shared = x25519.getSharedSecret(respSecret, b58dec(nodeEphB58));\n const key = v2Key(shared, HKDF_INFO_OUTPUT);\n const aad = aadOutput(respPubB58, nodeEphB58);\n const blob = b58dec(ciphertextB58);\n return xchacha20poly1305(key, blob.slice(0, 24), aad).decrypt(blob.slice(24));\n}\n\n/** Derive the stream output key once from the node's stream ephemeral (chunk 0). */\nexport function streamOutKey(respSecret: Uint8Array, nodeStreamEphB58: string): Uint8Array {\n const shared = x25519.getSharedSecret(respSecret, b58dec(nodeStreamEphB58));\n return v2Key(shared, HKDF_INFO_OUTPUT);\n}\n\n/** Open one stream chunk with the precomputed key + nonce/seq/final-bound AAD. */\nexport function openStreamChunk(\n outKey: Uint8Array,\n respPubB58: string,\n streamEphB58: string,\n reqNonceB58: string,\n seq: number,\n isFinal: boolean,\n ctB58: string,\n): Uint8Array {\n const aad = aadStream(respPubB58, streamEphB58, reqNonceB58, seq, isFinal);\n const blob = b58dec(ctB58);\n return xchacha20poly1305(outKey, blob.slice(0, 24), aad).decrypt(blob.slice(24));\n}\n","import { SGLAPIError, SGLAuthError, SGLConnectionError, SGLNotFoundError } from \"./errors.js\";\nimport * as e2e from \"./e2e.js\";\nimport type {\n AttestationProof,\n CapacityResponse,\n ChatCompletionRequest,\n ChatCompletionResponse,\n EmbeddingRequest,\n EmbeddingResponse,\n DeployProcessorOptions,\n GridClientOptions,\n JobResponse,\n JobResult,\n ModelInfo,\n PricingInfo,\n ProcessorDeployResult,\n ProcessorInfo,\n ProcessorInvokeResult,\n ProcessorListResponse,\n ProcessorLogEntry,\n ProcessorLogsResponse,\n ProviderInfo,\n ProvidersResponse,\n ReserveResponse,\n WalletAuth,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://grid.x402compute.cc\";\n\nconst DEFAULT_TIMEOUT = 60_000;\n\nexport class GridClient {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly timeout: number;\n\n constructor(options: GridClientOptions = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.headers = { Accept: \"application/json\", \"Content-Type\": \"application/json\" };\n if (options.apiKey) {\n this.headers[\"Authorization\"] = `Bearer ${options.apiKey}`;\n // Grid credit billing reads X-API-Key; send both so reserve + chat resolve\n // the paying wallet (credits mode) rather than falling back to anonymous x402.\n this.headers[\"X-API-Key\"] = options.apiKey;\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n else if (err && typeof err === \"object\" && \"message\" in err)\n message = String((err as { message: unknown }).message);\n } catch {\n /* body not JSON */\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SGLAuthError(response.status, message, errorBody);\n }\n if (response.status === 404) {\n throw new SGLNotFoundError(message, errorBody);\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n if (response.status === 204) return {} as T;\n return (await response.json()) as T;\n }\n\n // -- Public endpoints (no auth) ------------------------------------------\n\n async capacity(): Promise<CapacityResponse> {\n return this.request<CapacityResponse>(\"GET\", \"/grid/capacity\");\n }\n\n async models(): Promise<ModelInfo[]> {\n const data = await this.request<{ models: ModelInfo[] }>(\"GET\", \"/grid/models\");\n return data.models ?? [];\n }\n\n async pricing(): Promise<PricingInfo[]> {\n const data = await this.request<{ pricing: PricingInfo[] }>(\"GET\", \"/grid/pricing\");\n return data.pricing ?? [];\n }\n\n /**\n * List the nodes serving a model with each node's effective per-token price\n * (operator's custom price if set, else the platform reference), cheapest\n * first. Pass a chosen `node_id` as `node` on `chatCompletions` to pin it,\n * or omit to let the grid route. Optional `cluster` filter (slug or id).\n */\n async providers(\n model: string,\n options?: { cluster?: string },\n ): Promise<ProviderInfo[]> {\n const params = new URLSearchParams({ model });\n if (options?.cluster) params.set(\"cluster\", options.cluster);\n const data = await this.request<ProvidersResponse>(\n \"GET\",\n `/v1/providers?${params.toString()}`,\n );\n return data.providers ?? [];\n }\n\n // -- Authenticated endpoints ---------------------------------------------\n\n async submitJob(\n model: string,\n input: Record<string, unknown>,\n options?: { submitterWallet?: string; submitterChain?: string },\n ): Promise<JobResponse> {\n const body: Record<string, unknown> = { model, input };\n if (options?.submitterWallet) body.submitter_wallet = options.submitterWallet;\n if (options?.submitterChain) body.submitter_chain = options.submitterChain;\n return this.request<JobResponse>(\"POST\", \"/grid/jobs\", body);\n }\n\n async getJob(jobId: string): Promise<JobResult> {\n return this.request<JobResult>(\"GET\", `/grid/jobs/${jobId}`);\n }\n\n async getAttestation(jobId: string): Promise<AttestationProof> {\n return this.request<AttestationProof>(\"GET\", `/grid/jobs/${jobId}/attestation`);\n }\n\n // -- OpenAI-compatible (end-to-end encrypted) ----------------------------\n\n /** Reserve a node + learn its X25519 key so we can seal the prompt to it.\n * Forwards an optional pinned `node` (see `providers()`), `cluster` filter,\n * and `pay_in_coin` so the orchestrator reserves + quotes accordingly. */\n private async reserve(req: {\n model: string;\n node?: string;\n cluster?: string;\n pay_in_coin?: boolean;\n max_price?: number;\n }): Promise<ReserveResponse> {\n const body: Record<string, unknown> = { model: req.model };\n if (req.node) body.node = req.node;\n if (req.cluster) body.cluster = req.cluster;\n if (req.pay_in_coin) body.pay_in_coin = req.pay_in_coin;\n if (req.max_price != null) body.max_price = req.max_price;\n const res = await this.request<ReserveResponse>(\"POST\", \"/v1/reserve\", body);\n if (!res.node_x25519_pubkey) {\n throw new SGLAPIError(503, \"Reserved node does not support E2E encryption\");\n }\n return res;\n }\n\n /**\n * End-to-end encrypted chat completion. The prompt is sealed in this client to\n * the serving node's key and only decrypts inside its TEE — the orchestrator\n * only relays ciphertext. Requires an `apiKey` (credits); without one the grid\n * replies 402 (the SDK does not sign x402 payments — use the wallet/browser flow).\n */\n async chatCompletions(\n request: ChatCompletionRequest,\n ): Promise<ChatCompletionResponse> {\n if (request.stream) {\n // Collapse the stream into a single response for the non-streaming API.\n let content = \"\";\n for await (const delta of this.chatCompletionStream(request)) content += delta;\n return {\n id: \"\", object: \"chat.completion\", created: 0, model: request.model,\n choices: [{ index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" }],\n };\n }\n\n const reservation = await this.reserve(request);\n const { secret, pubB58 } = e2e.newResponseKeypair();\n const maxTokens = request.max_tokens ?? 512;\n const sealed = e2e.sealInputV2(\n reservation.node_x25519_pubkey,\n pubB58,\n new TextEncoder().encode(JSON.stringify({\n messages: request.messages,\n temperature: request.temperature ?? 0.7,\n max_tokens: maxTokens,\n })),\n );\n const body = {\n reservation_token: reservation.reservation_token,\n max_tokens: maxTokens, // cleartext, only used to quote the x402 price\n enc: {\n ciphertext: sealed.ciphertext,\n client_ephemeral_pubkey: sealed.ephemeralPub,\n client_response_pubkey: pubB58,\n algorithm: e2e.ALGO_V2,\n },\n };\n\n let data: {\n id?: string; created?: number; sealed_result?: { ephemeral_public_key: string; ciphertext: string };\n usage?: ChatCompletionResponse[\"usage\"];\n };\n try {\n data = await this.request(\"POST\", \"/v1/chat/completions\", body);\n } catch (err) {\n if (err instanceof SGLAPIError && err.statusCode === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n throw err;\n }\n\n if (!data.sealed_result) throw new SGLAPIError(500, \"No sealed result returned\");\n const plain = e2e.openOutputV2(secret, pubB58, data.sealed_result.ephemeral_public_key, data.sealed_result.ciphertext);\n const parsed = JSON.parse(new TextDecoder().decode(plain)) as { content?: string; usage?: ChatCompletionResponse[\"usage\"] };\n\n return {\n id: data.id ?? \"\",\n object: \"chat.completion\",\n created: data.created ?? 0,\n model: request.model,\n choices: [{ index: 0, message: { role: \"assistant\", content: parsed.content ?? \"\" }, finish_reason: \"stop\" }],\n usage: data.usage ?? parsed.usage,\n attestation: {\n nodeId: reservation.node_id,\n teeType: reservation.tee_type ?? null,\n verified: !!reservation.attestation_verified,\n },\n };\n }\n\n /**\n * Create embeddings via the grid's OpenAI-compatible `/v1/embeddings` endpoint.\n *\n * `input` is a string or array of strings; `dimensions` truncates Matryoshka models\n * (e.g. nomic 768→256); `input_type` ('query' | 'document') hints asymmetric\n * retrieval models. Billed on input tokens only — there is no generation. Requires\n * an `apiKey` (credits); the TS SDK does not sign x402 payments. Unlike chat, the\n * input is not client-sealed — the orchestrator seals it to the node in-TEE. The\n * returned `data` is ordered to match `input`.\n */\n async embed(request: EmbeddingRequest): Promise<EmbeddingResponse> {\n const body: Record<string, unknown> = { model: request.model, input: request.input };\n if (request.dimensions != null) body.dimensions = request.dimensions;\n if (request.input_type != null) body.input_type = request.input_type;\n if (request.tier != null) body.tier = request.tier;\n try {\n return (await this.request(\"POST\", \"/v1/embeddings\", body)) as EmbeddingResponse;\n } catch (err) {\n if (err instanceof SGLAPIError && err.statusCode === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n throw err;\n }\n }\n\n /**\n * Streaming end-to-end encrypted chat completion. Yields decoded text as it\n * arrives; each chunk is decrypted and its ordering + termination verified (a\n * truncated stream throws). Requires `apiKey` (credits). If the server isn't\n * streaming (toggle off), the whole reply is yielded as a single chunk.\n */\n async *chatCompletionStream(\n request: ChatCompletionRequest,\n ): AsyncGenerator<string, void, unknown> {\n const reservation = await this.reserve(request);\n const { secret, pubB58 } = e2e.newResponseKeypair();\n const nonce = e2e.randomNonceB58();\n const maxTokens = request.max_tokens ?? 512;\n const sealed = e2e.sealInputV2(\n reservation.node_x25519_pubkey,\n pubB58,\n new TextEncoder().encode(JSON.stringify({\n messages: request.messages,\n temperature: request.temperature ?? 0.7,\n max_tokens: maxTokens,\n stream: true,\n nonce,\n })),\n );\n const body = {\n reservation_token: reservation.reservation_token,\n stream: true,\n max_tokens: maxTokens,\n enc: {\n ciphertext: sealed.ciphertext,\n client_ephemeral_pubkey: sealed.ephemeralPub,\n client_response_pubkey: pubB58,\n algorithm: e2e.ALGO_V2,\n },\n };\n\n const controller = new AbortController();\n const overall = setTimeout(() => controller.abort(), this.timeout);\n let resp: Response;\n try {\n resp = await fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(overall);\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n if (!resp.ok) {\n clearTimeout(overall);\n if (resp.status === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n let message = resp.statusText;\n try {\n const j = (await resp.json()) as { error?: unknown };\n if (typeof j.error === \"string\") message = j.error;\n else if (j.error && typeof j.error === \"object\" && \"message\" in j.error) message = String((j.error as { message: unknown }).message);\n } catch { /* ignore */ }\n throw new SGLAPIError(resp.status, message);\n }\n\n const ctype = resp.headers.get(\"content-type\") ?? \"\";\n if (!ctype.includes(\"text/event-stream\") || !resp.body) {\n clearTimeout(overall);\n const data = (await resp.json()) as { sealed_result?: { ephemeral_public_key: string; ciphertext: string } };\n if (!data.sealed_result) throw new SGLAPIError(500, \"No sealed result returned\");\n const plain = e2e.openOutputV2(secret, pubB58, data.sealed_result.ephemeral_public_key, data.sealed_result.ciphertext);\n const content = (JSON.parse(new TextDecoder().decode(plain)) as { content?: string }).content ?? \"\";\n if (content) yield content;\n return;\n }\n\n const reader = resp.body.getReader();\n const decoder = new TextDecoder();\n const INACTIVITY_MS = 60_000;\n const readChunk = async (): Promise<ReadableStreamReadResult<Uint8Array>> => {\n let t: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n t = setTimeout(() => reject(new SGLConnectionError(\"stream timed out (no tokens)\")), INACTIVITY_MS);\n });\n try {\n return (await Promise.race([reader.read(), timeout])) as ReadableStreamReadResult<Uint8Array>;\n } finally {\n if (t) clearTimeout(t);\n }\n };\n\n let buf = \"\";\n let expectedSeq = 0;\n let outKey: Uint8Array | null = null;\n let streamEph: string | null = null;\n let sawFinal = false;\n try {\n for (;;) {\n if (sawFinal) break;\n const { value, done } = await readChunk();\n if (done) break;\n // Normalize CRLF so \\n\\n event framing works regardless of line endings.\n buf += decoder.decode(value, { stream: true }).replace(/\\r\\n/g, \"\\n\");\n let idx: number;\n while ((idx = buf.indexOf(\"\\n\\n\")) !== -1) {\n const raw = buf.slice(0, idx);\n buf = buf.slice(idx + 2);\n if (raw.includes(\"event: error\")) throw new SGLAPIError(502, \"stream aborted by server\");\n const dataStr = raw.split(\"\\n\").filter((l) => l.startsWith(\"data:\")).map((l) => l.slice(5).trim()).join(\"\\n\");\n if (!dataStr || dataStr === \"[DONE]\") continue;\n // Fail closed: a malformed or non-chunk data event is a protocol error.\n let chunk: { seq?: number; final?: boolean; eph?: string; ct?: string };\n try {\n chunk = JSON.parse(dataStr);\n } catch {\n throw new SGLAPIError(502, \"malformed stream chunk\");\n }\n if (typeof chunk.seq !== \"number\" || !chunk.ct) {\n throw new SGLAPIError(502, \"invalid stream chunk (missing seq/ciphertext)\");\n }\n if (chunk.seq !== expectedSeq) throw new SGLAPIError(502, `stream out of order (expected ${expectedSeq}, got ${chunk.seq})`);\n if (chunk.seq === 0) {\n if (!chunk.eph) throw new SGLAPIError(502, \"stream chunk 0 missing ephemeral key\");\n streamEph = chunk.eph;\n outKey = e2e.streamOutKey(secret, streamEph);\n }\n const isFinal = chunk.final === true;\n const text = new TextDecoder().decode(\n e2e.openStreamChunk(outKey as Uint8Array, pubB58, streamEph as string, nonce, chunk.seq, isFinal, chunk.ct),\n );\n if (text) yield text;\n expectedSeq++;\n if (isFinal) { sawFinal = true; break; }\n }\n }\n } finally {\n clearTimeout(overall);\n try { await reader.cancel(); } catch { /* ignore */ }\n }\n if (!sawFinal) throw new SGLAPIError(502, \"stream ended before final chunk (truncated)\");\n }\n\n // -- Processor helpers ----------------------------------------------------\n\n private async requestWithWalletAuth<T>(\n method: string,\n path: string,\n wallet: WalletAuth,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n const reqHeaders: Record<string, string> = {\n ...this.headers,\n \"X-Auth-Address\": wallet.address,\n \"X-Auth-Chain\": wallet.chain ?? \"solana\",\n \"X-Auth-Signature\": wallet.signature,\n \"X-Auth-Timestamp\": wallet.timestamp,\n \"X-Auth-Nonce\": wallet.nonce,\n };\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n else if (err && typeof err === \"object\" && \"message\" in err)\n message = String((err as { message: unknown }).message);\n } catch {\n /* body not JSON */\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SGLAuthError(response.status, message, errorBody);\n }\n if (response.status === 404) {\n throw new SGLNotFoundError(message, errorBody);\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n if (response.status === 204) return {} as T;\n return (await response.json()) as T;\n }\n\n private async requestWithPayment<T>(\n method: string,\n path: string,\n body?: unknown,\n paymentHeader?: string,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n const reqHeaders: Record<string, string> = { ...this.headers };\n if (paymentHeader) {\n reqHeaders[\"X-Payment\"] = paymentHeader;\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (response.status === 402) {\n const requirements = (await response.json()) as Record<string, unknown>;\n throw new SGLAPIError(402, \"Payment required\", requirements);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n } catch {\n /* body not JSON */\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n return (await response.json()) as T;\n }\n\n // -- Processors -----------------------------------------------------------\n\n async deployProcessor(\n wallet: WalletAuth,\n options: DeployProcessorOptions,\n ): Promise<ProcessorDeployResult> {\n return this.requestWithWalletAuth<ProcessorDeployResult>(\n \"POST\",\n \"/grid/processors\",\n wallet,\n options,\n );\n }\n\n async invokeProcessor(\n processorName: string,\n input: Record<string, unknown>,\n options?: { paymentHeader?: string; paymentToken?: \"USDC\" | \"SGL\" },\n ): Promise<ProcessorInvokeResult> {\n const body: Record<string, unknown> = { input };\n if (options?.paymentToken) body.payment_token = options.paymentToken;\n return this.requestWithPayment<ProcessorInvokeResult>(\n \"POST\",\n `/grid/processors/${encodeURIComponent(processorName)}/invoke`,\n body,\n options?.paymentHeader,\n );\n }\n\n async listProcessors(options?: {\n owner?: string;\n page?: number;\n limit?: number;\n }): Promise<ProcessorListResponse> {\n const params = new URLSearchParams();\n if (options?.owner) params.set(\"owner\", options.owner);\n if (options?.page != null) params.set(\"page\", String(options.page));\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n const qs = params.toString();\n return this.request<ProcessorListResponse>(\n \"GET\",\n `/grid/processors${qs ? `?${qs}` : \"\"}`,\n );\n }\n\n async getProcessor(processorId: string): Promise<ProcessorInfo> {\n return this.request<ProcessorInfo>(\"GET\", `/grid/processors/${processorId}`);\n }\n\n async deleteProcessor(\n processorId: string,\n wallet: WalletAuth,\n ): Promise<{ deleted: boolean; id: string }> {\n return this.requestWithWalletAuth<{ deleted: boolean; id: string }>(\n \"DELETE\",\n `/grid/processors/${processorId}`,\n wallet,\n );\n }\n\n async getProcessorLogs(\n processorId: string,\n wallet: WalletAuth,\n options?: { page?: number; limit?: number },\n ): Promise<ProcessorLogsResponse> {\n const params = new URLSearchParams();\n if (options?.page != null) params.set(\"page\", String(options.page));\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n const qs = params.toString();\n return this.requestWithWalletAuth<ProcessorLogsResponse>(\n \"GET\",\n `/grid/processors/${processorId}/logs${qs ? `?${qs}` : \"\"}`,\n wallet,\n );\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/e2e.ts","../src/client.ts","../src/vault.ts"],"sourcesContent":["export class SGLError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SGLError\";\n }\n}\n\nexport class SGLAPIError extends SGLError {\n readonly statusCode: number;\n readonly body?: Record<string, unknown>;\n\n constructor(\n statusCode: number,\n message: string,\n body?: Record<string, unknown>,\n ) {\n super(`HTTP ${statusCode}: ${message}`);\n this.name = \"SGLAPIError\";\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n\nexport class SGLAuthError extends SGLAPIError {\n constructor(\n statusCode: number,\n message: string,\n body?: Record<string, unknown>,\n ) {\n super(statusCode, message, body);\n this.name = \"SGLAuthError\";\n }\n}\n\nexport class SGLNotFoundError extends SGLAPIError {\n constructor(message: string, body?: Record<string, unknown>) {\n super(404, message, body);\n this.name = \"SGLNotFoundError\";\n }\n}\n\nexport class SGLConnectionError extends SGLError {\n constructor(message: string) {\n super(message);\n this.name = \"SGLConnectionError\";\n }\n}\n","/**\n * End-to-end encryption for the SGL grid (client side).\n *\n * Must match sgl-node/src/encryption.rs, the orchestrator, and the browser/Python\n * clients byte-for-byte: X25519 ECDH -> HKDF-SHA256 -> XChaCha20-Poly1305 (24-byte\n * nonce), AAD-bound. Sealed blob layout: nonce(24) || ciphertext, base58.\n *\n * The orchestrator only ever relays ciphertext — it never sees the prompt or reply.\n */\n\nimport { x25519 } from \"@noble/curves/ed25519\";\nimport { xchacha20poly1305 } from \"@noble/ciphers/chacha\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { hkdf } from \"@noble/hashes/hkdf\";\nimport bs58 from \"bs58\";\n\nexport const ALGO_V2 = \"x25519-xchacha20poly1305-hkdf-v2\";\nexport const ALGO_V2_STREAM = \"x25519-xchacha20poly1305-hkdf-v2-stream\";\n\nconst HKDF_SALT = new TextEncoder().encode(\"sgl-e2e-v2-salt\");\nconst HKDF_INFO_INPUT = new TextEncoder().encode(\"sgl-e2e-v2-input\");\nconst HKDF_INFO_OUTPUT = new TextEncoder().encode(\"sgl-e2e-v2-output\");\n\nfunction v2Key(shared: Uint8Array, info: Uint8Array): Uint8Array {\n return hkdf(sha256, shared, HKDF_SALT, info, 32);\n}\nfunction aadInput(nodeB58: string, ephB58: string, respB58: string): Uint8Array {\n return new TextEncoder().encode(`sgl-aad/v2/input|node=${nodeB58}|eph=${ephB58}|resp=${respB58}`);\n}\nfunction aadOutput(respB58: string, ephB58: string): Uint8Array {\n return new TextEncoder().encode(`sgl-aad/v2/output|resp=${respB58}|eph=${ephB58}`);\n}\nfunction aadStream(respB58: string, ephB58: string, nonceB58: string, seq: number, isFinal: boolean): Uint8Array {\n return new TextEncoder().encode(\n `sgl-aad/v2/stream|resp=${respB58}|eph=${ephB58}|nonce=${nonceB58}|seq=${seq}|final=${isFinal ? 1 : 0}`,\n );\n}\n\nfunction b58enc(u: Uint8Array): string {\n return bs58.encode(u);\n}\nfunction b58dec(s: string): Uint8Array {\n return bs58.decode(s);\n}\nfunction randomBytes(n: number): Uint8Array {\n return crypto.getRandomValues(new Uint8Array(n));\n}\n\nexport interface ResponseKeypair {\n secret: Uint8Array;\n pubB58: string;\n}\n\n/** The caller's response keypair — the node seals its reply to this. */\nexport function newResponseKeypair(): ResponseKeypair {\n const secret = x25519.utils.randomPrivateKey();\n return { secret, pubB58: b58enc(x25519.getPublicKey(secret)) };\n}\n\n/** A per-request nonce bound into every stream chunk's AAD. */\nexport function randomNonceB58(): string {\n return b58enc(randomBytes(16));\n}\n\n/** Seal the prompt to the node's X25519 key. */\nexport function sealInputV2(\n nodePubB58: string,\n respPubB58: string,\n plaintext: Uint8Array,\n): { ciphertext: string; ephemeralPub: string } {\n const nodePub = b58dec(nodePubB58);\n const ephSecret = x25519.utils.randomPrivateKey();\n const ephPub = x25519.getPublicKey(ephSecret);\n const ephB58 = b58enc(ephPub);\n const shared = x25519.getSharedSecret(ephSecret, nodePub);\n const key = v2Key(shared, HKDF_INFO_INPUT);\n const aad = aadInput(nodePubB58, ephB58, respPubB58);\n const nonce = randomBytes(24);\n const ct = xchacha20poly1305(key, nonce, aad).encrypt(plaintext);\n const out = new Uint8Array(24 + ct.length);\n out.set(nonce, 0);\n out.set(ct, 24);\n return { ciphertext: b58enc(out), ephemeralPub: ephB58 };\n}\n\n/** Open the node's (non-stream) reply sealed to our response key. */\nexport function openOutputV2(\n respSecret: Uint8Array,\n respPubB58: string,\n nodeEphB58: string,\n ciphertextB58: string,\n): Uint8Array {\n const shared = x25519.getSharedSecret(respSecret, b58dec(nodeEphB58));\n const key = v2Key(shared, HKDF_INFO_OUTPUT);\n const aad = aadOutput(respPubB58, nodeEphB58);\n const blob = b58dec(ciphertextB58);\n return xchacha20poly1305(key, blob.slice(0, 24), aad).decrypt(blob.slice(24));\n}\n\n/** Derive the stream output key once from the node's stream ephemeral (chunk 0). */\nexport function streamOutKey(respSecret: Uint8Array, nodeStreamEphB58: string): Uint8Array {\n const shared = x25519.getSharedSecret(respSecret, b58dec(nodeStreamEphB58));\n return v2Key(shared, HKDF_INFO_OUTPUT);\n}\n\n/** Open one stream chunk with the precomputed key + nonce/seq/final-bound AAD. */\nexport function openStreamChunk(\n outKey: Uint8Array,\n respPubB58: string,\n streamEphB58: string,\n reqNonceB58: string,\n seq: number,\n isFinal: boolean,\n ctB58: string,\n): Uint8Array {\n const aad = aadStream(respPubB58, streamEphB58, reqNonceB58, seq, isFinal);\n const blob = b58dec(ctB58);\n return xchacha20poly1305(outKey, blob.slice(0, 24), aad).decrypt(blob.slice(24));\n}\n","import { SGLAPIError, SGLAuthError, SGLConnectionError, SGLNotFoundError } from \"./errors.js\";\nimport * as e2e from \"./e2e.js\";\nimport type {\n AttestationProof,\n CapacityResponse,\n ChatCompletionRequest,\n ChatCompletionResponse,\n EmbeddingRequest,\n EmbeddingResponse,\n DeployProcessorOptions,\n GridClientOptions,\n JobResponse,\n JobResult,\n ModelInfo,\n PricingInfo,\n ProcessorDeployResult,\n ProcessorInfo,\n ProcessorInvokeResult,\n ProcessorListResponse,\n ProcessorLogEntry,\n ProcessorLogsResponse,\n ProviderInfo,\n ProvidersResponse,\n ReserveResponse,\n WalletAuth,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://grid.x402compute.cc\";\n\nconst DEFAULT_TIMEOUT = 60_000;\n\nexport class GridClient {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly timeout: number;\n\n constructor(options: GridClientOptions = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.headers = { Accept: \"application/json\", \"Content-Type\": \"application/json\" };\n if (options.apiKey) {\n this.headers[\"Authorization\"] = `Bearer ${options.apiKey}`;\n // Grid credit billing reads X-API-Key; send both so reserve + chat resolve\n // the paying wallet (credits mode) rather than falling back to anonymous x402.\n this.headers[\"X-API-Key\"] = options.apiKey;\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n else if (err && typeof err === \"object\" && \"message\" in err)\n message = String((err as { message: unknown }).message);\n } catch {\n /* body not JSON */\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SGLAuthError(response.status, message, errorBody);\n }\n if (response.status === 404) {\n throw new SGLNotFoundError(message, errorBody);\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n if (response.status === 204) return {} as T;\n return (await response.json()) as T;\n }\n\n // -- Public endpoints (no auth) ------------------------------------------\n\n async capacity(): Promise<CapacityResponse> {\n return this.request<CapacityResponse>(\"GET\", \"/grid/capacity\");\n }\n\n async models(): Promise<ModelInfo[]> {\n const data = await this.request<{ models: ModelInfo[] }>(\"GET\", \"/grid/models\");\n return data.models ?? [];\n }\n\n async pricing(): Promise<PricingInfo[]> {\n const data = await this.request<{ pricing: PricingInfo[] }>(\"GET\", \"/grid/pricing\");\n return data.pricing ?? [];\n }\n\n /**\n * List the nodes serving a model with each node's effective per-token price\n * (operator's custom price if set, else the platform reference), cheapest\n * first. Pass a chosen `node_id` as `node` on `chatCompletions` to pin it,\n * or omit to let the grid route. Optional `cluster` filter (slug or id).\n */\n async providers(\n model: string,\n options?: { cluster?: string },\n ): Promise<ProviderInfo[]> {\n const params = new URLSearchParams({ model });\n if (options?.cluster) params.set(\"cluster\", options.cluster);\n const data = await this.request<ProvidersResponse>(\n \"GET\",\n `/v1/providers?${params.toString()}`,\n );\n return data.providers ?? [];\n }\n\n // -- Authenticated endpoints ---------------------------------------------\n\n async submitJob(\n model: string,\n input: Record<string, unknown>,\n options?: { submitterWallet?: string; submitterChain?: string },\n ): Promise<JobResponse> {\n const body: Record<string, unknown> = { model, input };\n if (options?.submitterWallet) body.submitter_wallet = options.submitterWallet;\n if (options?.submitterChain) body.submitter_chain = options.submitterChain;\n return this.request<JobResponse>(\"POST\", \"/grid/jobs\", body);\n }\n\n async getJob(jobId: string): Promise<JobResult> {\n return this.request<JobResult>(\"GET\", `/grid/jobs/${jobId}`);\n }\n\n async getAttestation(jobId: string): Promise<AttestationProof> {\n return this.request<AttestationProof>(\"GET\", `/grid/jobs/${jobId}/attestation`);\n }\n\n // -- OpenAI-compatible (end-to-end encrypted) ----------------------------\n\n /** Reserve a node + learn its X25519 key so we can seal the prompt to it.\n * Forwards an optional pinned `node` (see `providers()`), `cluster` filter,\n * and `pay_in_coin` so the orchestrator reserves + quotes accordingly. */\n private async reserve(req: {\n model: string;\n node?: string;\n cluster?: string;\n pay_in_coin?: boolean;\n max_price?: number;\n }): Promise<ReserveResponse> {\n const body: Record<string, unknown> = { model: req.model };\n if (req.node) body.node = req.node;\n if (req.cluster) body.cluster = req.cluster;\n if (req.pay_in_coin) body.pay_in_coin = req.pay_in_coin;\n if (req.max_price != null) body.max_price = req.max_price;\n const res = await this.request<ReserveResponse>(\"POST\", \"/v1/reserve\", body);\n if (!res.node_x25519_pubkey) {\n throw new SGLAPIError(503, \"Reserved node does not support E2E encryption\");\n }\n return res;\n }\n\n /**\n * End-to-end encrypted chat completion. The prompt is sealed in this client to\n * the serving node's key and only decrypts inside its TEE — the orchestrator\n * only relays ciphertext. Requires an `apiKey` (credits); without one the grid\n * replies 402 (the SDK does not sign x402 payments — use the wallet/browser flow).\n */\n async chatCompletions(\n request: ChatCompletionRequest,\n ): Promise<ChatCompletionResponse> {\n if (request.stream) {\n // Collapse the stream into a single response for the non-streaming API.\n let content = \"\";\n for await (const delta of this.chatCompletionStream(request)) content += delta;\n return {\n id: \"\", object: \"chat.completion\", created: 0, model: request.model,\n choices: [{ index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" }],\n };\n }\n\n const reservation = await this.reserve(request);\n const { secret, pubB58 } = e2e.newResponseKeypair();\n const maxTokens = request.max_tokens ?? 512;\n const sealed = e2e.sealInputV2(\n reservation.node_x25519_pubkey,\n pubB58,\n new TextEncoder().encode(JSON.stringify({\n messages: request.messages,\n temperature: request.temperature ?? 0.7,\n max_tokens: maxTokens,\n })),\n );\n const body = {\n reservation_token: reservation.reservation_token,\n max_tokens: maxTokens, // cleartext, only used to quote the x402 price\n enc: {\n ciphertext: sealed.ciphertext,\n client_ephemeral_pubkey: sealed.ephemeralPub,\n client_response_pubkey: pubB58,\n algorithm: e2e.ALGO_V2,\n },\n };\n\n let data: {\n id?: string; created?: number; sealed_result?: { ephemeral_public_key: string; ciphertext: string };\n usage?: ChatCompletionResponse[\"usage\"];\n };\n try {\n data = await this.request(\"POST\", \"/v1/chat/completions\", body);\n } catch (err) {\n if (err instanceof SGLAPIError && err.statusCode === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n throw err;\n }\n\n if (!data.sealed_result) throw new SGLAPIError(500, \"No sealed result returned\");\n const plain = e2e.openOutputV2(secret, pubB58, data.sealed_result.ephemeral_public_key, data.sealed_result.ciphertext);\n const parsed = JSON.parse(new TextDecoder().decode(plain)) as { content?: string; usage?: ChatCompletionResponse[\"usage\"] };\n\n return {\n id: data.id ?? \"\",\n object: \"chat.completion\",\n created: data.created ?? 0,\n model: request.model,\n choices: [{ index: 0, message: { role: \"assistant\", content: parsed.content ?? \"\" }, finish_reason: \"stop\" }],\n usage: data.usage ?? parsed.usage,\n attestation: {\n nodeId: reservation.node_id,\n teeType: reservation.tee_type ?? null,\n verified: !!reservation.attestation_verified,\n },\n };\n }\n\n /**\n * Create embeddings via the grid's OpenAI-compatible `/v1/embeddings` endpoint.\n *\n * `input` is a string or array of strings; `dimensions` truncates Matryoshka models\n * (e.g. nomic 768→256); `input_type` ('query' | 'document') hints asymmetric\n * retrieval models. Billed on input tokens only — there is no generation. Requires\n * an `apiKey` (credits); the TS SDK does not sign x402 payments. Unlike chat, the\n * input is not client-sealed — the orchestrator seals it to the node in-TEE. The\n * returned `data` is ordered to match `input`.\n */\n async embed(request: EmbeddingRequest): Promise<EmbeddingResponse> {\n const body: Record<string, unknown> = { model: request.model, input: request.input };\n if (request.dimensions != null) body.dimensions = request.dimensions;\n if (request.input_type != null) body.input_type = request.input_type;\n if (request.tier != null) body.tier = request.tier;\n try {\n return (await this.request(\"POST\", \"/v1/embeddings\", body)) as EmbeddingResponse;\n } catch (err) {\n if (err instanceof SGLAPIError && err.statusCode === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n throw err;\n }\n }\n\n /**\n * Streaming end-to-end encrypted chat completion. Yields decoded text as it\n * arrives; each chunk is decrypted and its ordering + termination verified (a\n * truncated stream throws). Requires `apiKey` (credits). If the server isn't\n * streaming (toggle off), the whole reply is yielded as a single chunk.\n */\n async *chatCompletionStream(\n request: ChatCompletionRequest,\n ): AsyncGenerator<string, void, unknown> {\n const reservation = await this.reserve(request);\n const { secret, pubB58 } = e2e.newResponseKeypair();\n const nonce = e2e.randomNonceB58();\n const maxTokens = request.max_tokens ?? 512;\n const sealed = e2e.sealInputV2(\n reservation.node_x25519_pubkey,\n pubB58,\n new TextEncoder().encode(JSON.stringify({\n messages: request.messages,\n temperature: request.temperature ?? 0.7,\n max_tokens: maxTokens,\n stream: true,\n nonce,\n })),\n );\n const body = {\n reservation_token: reservation.reservation_token,\n stream: true,\n max_tokens: maxTokens,\n enc: {\n ciphertext: sealed.ciphertext,\n client_ephemeral_pubkey: sealed.ephemeralPub,\n client_response_pubkey: pubB58,\n algorithm: e2e.ALGO_V2,\n },\n };\n\n const controller = new AbortController();\n const overall = setTimeout(() => controller.abort(), this.timeout);\n let resp: Response;\n try {\n resp = await fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(overall);\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n if (!resp.ok) {\n clearTimeout(overall);\n if (resp.status === 402) {\n throw new SGLAPIError(402, \"Payment required — pass an apiKey (credits). The TS SDK does not sign x402 payments; use the wallet/browser flow for pay-per-call.\");\n }\n let message = resp.statusText;\n try {\n const j = (await resp.json()) as { error?: unknown };\n if (typeof j.error === \"string\") message = j.error;\n else if (j.error && typeof j.error === \"object\" && \"message\" in j.error) message = String((j.error as { message: unknown }).message);\n } catch { /* ignore */ }\n throw new SGLAPIError(resp.status, message);\n }\n\n const ctype = resp.headers.get(\"content-type\") ?? \"\";\n if (!ctype.includes(\"text/event-stream\") || !resp.body) {\n clearTimeout(overall);\n const data = (await resp.json()) as { sealed_result?: { ephemeral_public_key: string; ciphertext: string } };\n if (!data.sealed_result) throw new SGLAPIError(500, \"No sealed result returned\");\n const plain = e2e.openOutputV2(secret, pubB58, data.sealed_result.ephemeral_public_key, data.sealed_result.ciphertext);\n const content = (JSON.parse(new TextDecoder().decode(plain)) as { content?: string }).content ?? \"\";\n if (content) yield content;\n return;\n }\n\n const reader = resp.body.getReader();\n const decoder = new TextDecoder();\n const INACTIVITY_MS = 60_000;\n const readChunk = async (): Promise<ReadableStreamReadResult<Uint8Array>> => {\n let t: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n t = setTimeout(() => reject(new SGLConnectionError(\"stream timed out (no tokens)\")), INACTIVITY_MS);\n });\n try {\n return (await Promise.race([reader.read(), timeout])) as ReadableStreamReadResult<Uint8Array>;\n } finally {\n if (t) clearTimeout(t);\n }\n };\n\n let buf = \"\";\n let expectedSeq = 0;\n let outKey: Uint8Array | null = null;\n let streamEph: string | null = null;\n let sawFinal = false;\n try {\n for (;;) {\n if (sawFinal) break;\n const { value, done } = await readChunk();\n if (done) break;\n // Normalize CRLF so \\n\\n event framing works regardless of line endings.\n buf += decoder.decode(value, { stream: true }).replace(/\\r\\n/g, \"\\n\");\n let idx: number;\n while ((idx = buf.indexOf(\"\\n\\n\")) !== -1) {\n const raw = buf.slice(0, idx);\n buf = buf.slice(idx + 2);\n if (raw.includes(\"event: error\")) throw new SGLAPIError(502, \"stream aborted by server\");\n const dataStr = raw.split(\"\\n\").filter((l) => l.startsWith(\"data:\")).map((l) => l.slice(5).trim()).join(\"\\n\");\n if (!dataStr || dataStr === \"[DONE]\") continue;\n // Fail closed: a malformed or non-chunk data event is a protocol error.\n let chunk: { seq?: number; final?: boolean; eph?: string; ct?: string };\n try {\n chunk = JSON.parse(dataStr);\n } catch {\n throw new SGLAPIError(502, \"malformed stream chunk\");\n }\n if (typeof chunk.seq !== \"number\" || !chunk.ct) {\n throw new SGLAPIError(502, \"invalid stream chunk (missing seq/ciphertext)\");\n }\n if (chunk.seq !== expectedSeq) throw new SGLAPIError(502, `stream out of order (expected ${expectedSeq}, got ${chunk.seq})`);\n if (chunk.seq === 0) {\n if (!chunk.eph) throw new SGLAPIError(502, \"stream chunk 0 missing ephemeral key\");\n streamEph = chunk.eph;\n outKey = e2e.streamOutKey(secret, streamEph);\n }\n const isFinal = chunk.final === true;\n const text = new TextDecoder().decode(\n e2e.openStreamChunk(outKey as Uint8Array, pubB58, streamEph as string, nonce, chunk.seq, isFinal, chunk.ct),\n );\n if (text) yield text;\n expectedSeq++;\n if (isFinal) { sawFinal = true; break; }\n }\n }\n } finally {\n clearTimeout(overall);\n try { await reader.cancel(); } catch { /* ignore */ }\n }\n if (!sawFinal) throw new SGLAPIError(502, \"stream ended before final chunk (truncated)\");\n }\n\n // -- Processor helpers ----------------------------------------------------\n\n private async requestWithWalletAuth<T>(\n method: string,\n path: string,\n wallet: WalletAuth,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n const reqHeaders: Record<string, string> = {\n ...this.headers,\n \"X-Auth-Address\": wallet.address,\n \"X-Auth-Chain\": wallet.chain ?? \"solana\",\n \"X-Auth-Signature\": wallet.signature,\n \"X-Auth-Timestamp\": wallet.timestamp,\n \"X-Auth-Nonce\": wallet.nonce,\n };\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n else if (err && typeof err === \"object\" && \"message\" in err)\n message = String((err as { message: unknown }).message);\n } catch {\n /* body not JSON */\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SGLAuthError(response.status, message, errorBody);\n }\n if (response.status === 404) {\n throw new SGLNotFoundError(message, errorBody);\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n if (response.status === 204) return {} as T;\n return (await response.json()) as T;\n }\n\n private async requestWithPayment<T>(\n method: string,\n path: string,\n body?: unknown,\n paymentHeader?: string,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n const reqHeaders: Record<string, string> = { ...this.headers };\n if (paymentHeader) {\n reqHeaders[\"X-Payment\"] = paymentHeader;\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new SGLConnectionError(`Request to ${url} timed out`);\n }\n throw new SGLConnectionError(\n `Could not connect to ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (response.status === 402) {\n const requirements = (await response.json()) as Record<string, unknown>;\n throw new SGLAPIError(402, \"Payment required\", requirements);\n }\n\n if (!response.ok) {\n let errorBody: Record<string, unknown> | undefined;\n let message = response.statusText;\n try {\n errorBody = (await response.json()) as Record<string, unknown>;\n const err = errorBody?.error;\n if (typeof err === \"string\") message = err;\n } catch {\n /* body not JSON */\n }\n throw new SGLAPIError(response.status, message, errorBody);\n }\n\n return (await response.json()) as T;\n }\n\n // -- Processors -----------------------------------------------------------\n\n async deployProcessor(\n wallet: WalletAuth,\n options: DeployProcessorOptions,\n ): Promise<ProcessorDeployResult> {\n return this.requestWithWalletAuth<ProcessorDeployResult>(\n \"POST\",\n \"/grid/processors\",\n wallet,\n options,\n );\n }\n\n async invokeProcessor(\n processorName: string,\n input: Record<string, unknown>,\n options?: { paymentHeader?: string; paymentToken?: \"USDC\" | \"SGL\" },\n ): Promise<ProcessorInvokeResult> {\n const body: Record<string, unknown> = { input };\n if (options?.paymentToken) body.payment_token = options.paymentToken;\n return this.requestWithPayment<ProcessorInvokeResult>(\n \"POST\",\n `/grid/processors/${encodeURIComponent(processorName)}/invoke`,\n body,\n options?.paymentHeader,\n );\n }\n\n async listProcessors(options?: {\n owner?: string;\n page?: number;\n limit?: number;\n }): Promise<ProcessorListResponse> {\n const params = new URLSearchParams();\n if (options?.owner) params.set(\"owner\", options.owner);\n if (options?.page != null) params.set(\"page\", String(options.page));\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n const qs = params.toString();\n return this.request<ProcessorListResponse>(\n \"GET\",\n `/grid/processors${qs ? `?${qs}` : \"\"}`,\n );\n }\n\n async getProcessor(processorId: string): Promise<ProcessorInfo> {\n return this.request<ProcessorInfo>(\"GET\", `/grid/processors/${processorId}`);\n }\n\n async deleteProcessor(\n processorId: string,\n wallet: WalletAuth,\n ): Promise<{ deleted: boolean; id: string }> {\n return this.requestWithWalletAuth<{ deleted: boolean; id: string }>(\n \"DELETE\",\n `/grid/processors/${processorId}`,\n wallet,\n );\n }\n\n async getProcessorLogs(\n processorId: string,\n wallet: WalletAuth,\n options?: { page?: number; limit?: number },\n ): Promise<ProcessorLogsResponse> {\n const params = new URLSearchParams();\n if (options?.page != null) params.set(\"page\", String(options.page));\n if (options?.limit != null) params.set(\"limit\", String(options.limit));\n const qs = params.toString();\n return this.requestWithWalletAuth<ProcessorLogsResponse>(\n \"GET\",\n `/grid/processors/${processorId}/logs${qs ? `?${qs}` : \"\"}`,\n wallet,\n );\n }\n}\n","/**\n * Agent Vault — zero-knowledge encrypted agent backup/restore.\n *\n * Pure-JS envelope (noble scrypt + AES-256-GCM), byte-compatible with the\n * agentvault CLI, the pod runner, and the Python SDK:\n * `[4-byte BE header length][JSON header][GCM body, tag appended]`, with the\n * snapshot identity bound into the GCM AAD. Runs in Node AND browsers.\n *\n * Scope: this module encrypts/decrypts BYTES and drives the API. Packing a\n * directory into a tarball is filesystem work — use the `agentvault` CLI or\n * the Python SDK for that, or bring your own archive bytes.\n *\n * Auth: a Singularity compute API key (X-API-Key). Passphrases and plaintext\n * never leave this process.\n */\n\nimport { gcm } from \"@noble/ciphers/aes\";\nimport { scrypt } from \"@noble/hashes/scrypt\";\nimport { SGLAPIError } from \"./errors.js\";\n\nexport const VAULT_URL = \"https://compute.x402layer.cc\";\n\nconst SCRYPT_PARAMS = { N: 1 << 17, r: 8, p: 1 } as const;\nconst SCRYPT_MIN_N = 1 << 15;\n\n// ─── Envelope (wire-identical to agentvault-core) ───────────────────────────\n\nexport interface VaultAad {\n userId: string;\n agentId: string;\n backupId: string;\n formatVersion: 1;\n}\n\nconst te = new TextEncoder();\nconst td = new TextDecoder();\n\nfunction aadBytes(aad: VaultAad): Uint8Array {\n // Canonical key order — byte-identical across CLI, pod runner, Python SDK.\n const { agentId, backupId, formatVersion, userId } = aad;\n return te.encode(JSON.stringify({ agentId, backupId, formatVersion, userId }));\n}\n\nfunction b64(x: Uint8Array): string {\n let s = \"\";\n for (const b of x) s += String.fromCharCode(b);\n return btoa(s);\n}\n\nfunction unb64(s: string): Uint8Array {\n const bin = atob(s);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nfunction rand(n: number): Uint8Array {\n const out = new Uint8Array(n);\n crypto.getRandomValues(out);\n return out;\n}\n\n/** Envelope-encrypt arbitrary bytes under a passphrase (scrypt + AES-256-GCM). */\nexport function encryptEnvelope(plaintext: Uint8Array, passphrase: string, aad: VaultAad): Uint8Array {\n const salt = rand(16);\n const kek = scrypt(te.encode(passphrase), salt, { ...SCRYPT_PARAMS, dkLen: 32 });\n const dek = rand(32);\n const aadBuf = aadBytes(aad);\n const dekNonce = rand(12);\n const wrapped = gcm(kek, dekNonce, aadBuf).encrypt(dek); // ciphertext||tag\n const blobNonce = rand(12);\n const body = gcm(dek, blobNonce, aadBuf).encrypt(plaintext);\n const header = te.encode(JSON.stringify({\n formatVersion: 1,\n kdf: \"scrypt\",\n kdfParams: { ...SCRYPT_PARAMS, salt: b64(salt) },\n cipher: \"aes-256-gcm\",\n wrappedDek: { nonce: b64(dekNonce), ciphertext: b64(wrapped) },\n blobNonce: b64(blobNonce),\n aad,\n }));\n const out = new Uint8Array(4 + header.length + body.length);\n new DataView(out.buffer).setUint32(0, header.length, false);\n out.set(header, 4);\n out.set(body, 4 + header.length);\n return out;\n}\n\n/** Reverse of encryptEnvelope. Throws on wrong passphrase or AAD mismatch. */\nexport function decryptEnvelope(blob: Uint8Array, passphrase: string, aad: VaultAad): Uint8Array {\n if (blob.length < 4) throw new SGLAPIError(0, \"malformed blob: too short\");\n const headerLen = new DataView(blob.buffer, blob.byteOffset).getUint32(0, false);\n if (4 + headerLen > blob.length) throw new SGLAPIError(0, \"malformed blob: header length out of bounds\");\n let header: {\n kdf?: string;\n kdfParams?: { N?: number; r?: number; p?: number; salt?: string };\n wrappedDek?: { nonce?: string; ciphertext?: string };\n blobNonce?: string;\n };\n try {\n header = JSON.parse(td.decode(blob.subarray(4, 4 + headerLen)));\n } catch {\n throw new SGLAPIError(0, \"malformed blob: invalid header JSON\");\n }\n if (header.kdf !== \"scrypt\") {\n throw new SGLAPIError(0, `this backup uses ${String(header.kdf)} key derivation — restore it with the agentvault CLI`);\n }\n const p = header.kdfParams ?? {};\n if (\n !Number.isInteger(p.N) || (p.N as number) < SCRYPT_MIN_N || (p.N as number) > SCRYPT_PARAMS.N ||\n ((p.N as number) & ((p.N as number) - 1)) !== 0 ||\n !Number.isInteger(p.r) || (p.r as number) < 8 || (p.r as number) > 16 ||\n !Number.isInteger(p.p) || (p.p as number) < 1 || (p.p as number) > 4 ||\n typeof p.salt !== \"string\" || !header.wrappedDek?.nonce || !header.wrappedDek?.ciphertext || !header.blobNonce\n ) {\n throw new SGLAPIError(0, \"malformed blob: unsupported header parameters\");\n }\n const salt = unb64(p.salt);\n if (salt.length < 16) throw new SGLAPIError(0, \"malformed blob: salt too short\");\n const kek = scrypt(te.encode(passphrase), salt, { N: p.N as number, r: p.r as number, p: p.p as number, dkLen: 32 });\n const aadBuf = aadBytes(aad);\n try {\n const dek = gcm(kek, unb64(header.wrappedDek.nonce), aadBuf).decrypt(unb64(header.wrappedDek.ciphertext));\n return gcm(dek, unb64(header.blobNonce), aadBuf).decrypt(blob.subarray(4 + headerLen));\n } catch {\n throw new SGLAPIError(0, \"incorrect passphrase or corrupted backup\");\n }\n}\n\nexport function parseAadFromKey(r2Key: string): VaultAad {\n const parts = r2Key.split(\"/\");\n if (parts.length !== 5 || parts[0] !== \"backups\" || parts[4] !== \"blob.enc\"\n || !parts[1] || !parts[2] || !parts[3]) {\n throw new SGLAPIError(0, `malformed r2 key: ${r2Key}`);\n }\n return { userId: parts[1], agentId: parts[2], backupId: parts[3], formatVersion: 1 };\n}\n\n// ─── API client ─────────────────────────────────────────────────────────────\n\nexport interface VaultAgent {\n id: string;\n name: string;\n framework: string;\n source: \"local\" | \"pod\";\n pod_order_id: string | null;\n}\n\nexport interface VaultSnapshot {\n id: string;\n agent_id: string;\n size_bytes: number;\n sha256: string | null;\n created_at: string;\n}\n\nexport interface VaultUsage {\n plan: \"free\" | \"pro\";\n planRenewsAt: string | null;\n bytesUsed: number;\n bytesReserved: number;\n maxBytes: number;\n proPriceUsd: number;\n}\n\nexport interface VaultClientOptions {\n apiKey: string;\n baseUrl?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport class VaultClient {\n private readonly base: string;\n private readonly apiKey: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: VaultClientOptions) {\n const base = (options.baseUrl ?? VAULT_URL).replace(/\\/+$/, \"\");\n const u = new URL(base);\n const local = [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(u.hostname);\n if (u.protocol !== \"https:\" && !local) {\n throw new SGLAPIError(0, \"baseUrl must be https (the API key travels in a header)\");\n }\n if (u.username || u.password || u.search || u.hash) {\n throw new SGLAPIError(0, \"baseUrl must be a bare origin\");\n }\n this.base = base;\n this.apiKey = options.apiKey;\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n private static id(v: string): string {\n if (!/^[0-9a-fA-F-]{36}$/.test(v)) throw new SGLAPIError(0, `not a snapshot id: ${v}`);\n return v.toLowerCase();\n }\n\n private async call<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await this.fetchImpl(`${this.base}${path}`, {\n method,\n headers: {\n \"x-api-key\": this.apiKey,\n ...(body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) throw new SGLAPIError(res.status, String(data.error ?? `request failed: ${res.status}`));\n return data as T;\n }\n\n async agents(): Promise<VaultAgent[]> {\n return (await this.call<{ agents: VaultAgent[] }>(\"GET\", \"/backups/agents\")).agents;\n }\n\n async createAgent(name: string, framework: string): Promise<VaultAgent> {\n return (await this.call<{ agent: VaultAgent }>(\"POST\", \"/backups/agents\", { name, framework })).agent;\n }\n\n async snapshots(agentId?: string): Promise<VaultSnapshot[]> {\n const q = agentId ? `?agentId=${encodeURIComponent(agentId)}` : \"\";\n return (await this.call<{ backups: VaultSnapshot[] }>(\"GET\", `/backups${q}`)).backups;\n }\n\n async usage(): Promise<VaultUsage> {\n return this.call<VaultUsage>(\"GET\", \"/backups/usage\");\n }\n\n /** Activate Vault Pro ($3/mo from credits). */\n async subscribePro(): Promise<{ ok: boolean; already?: boolean }> {\n return this.call(\"POST\", \"/backups/subscribe\");\n }\n\n async deleteSnapshot(id: string): Promise<void> {\n await this.call(\"DELETE\", `/backups/${VaultClient.id(id)}`);\n }\n\n /**\n * Encrypt + upload arbitrary payload bytes (e.g. a tarball you packed) as a\n * snapshot of `agentId`. Returns the snapshot id.\n */\n async backupBytes(agentId: string, payload: Uint8Array, passphrase: string): Promise<string> {\n const res = await this.call<{ backupId: string; r2Key: string; uploadUrl: string }>(\n \"POST\", \"/backups\", { agentId, sizeBytes: payload.length },\n );\n const blob = encryptEnvelope(payload, passphrase, parseAadFromKey(res.r2Key));\n const up = await this.fetchImpl(res.uploadUrl, {\n method: \"PUT\",\n body: blob as unknown as BodyInit,\n headers: { \"content-type\": \"application/octet-stream\" },\n });\n if (!up.ok) throw new SGLAPIError(up.status, `upload failed: ${up.status}`);\n const digest = await crypto.subtle.digest(\"SHA-256\", blob as unknown as ArrayBuffer);\n const sha256 = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n await this.call(\"POST\", `/backups/${res.backupId}/complete`, { sha256 });\n return res.backupId;\n }\n\n /** Download + decrypt a snapshot's payload bytes. */\n async restoreBytes(snapshotId: string, passphrase: string): Promise<Uint8Array> {\n const info = await this.call<{ downloadUrl: string; r2Key: string }>(\"GET\", `/backups/${VaultClient.id(snapshotId)}/restore`);\n const dl = await this.fetchImpl(info.downloadUrl);\n if (!dl.ok) throw new SGLAPIError(dl.status, `download failed: ${dl.status}`);\n const blob = new Uint8Array(await dl.arrayBuffer());\n return decryptEnvelope(blob, passphrase, parseAadFromKey(info.r2Key));\n }\n}\n"],"mappings":";AAAO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAClC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,cAAN,cAA0B,SAAS;AAAA,EAIxC,YACE,YACA,SACA,MACA;AACA,UAAM,QAAQ,UAAU,KAAK,OAAO,EAAE;AACtC,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,eAAN,cAA2B,YAAY;AAAA,EAC5C,YACE,YACA,SACA,MACA;AACA,UAAM,YAAY,SAAS,IAAI;AAC/B,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,mBAAN,cAA+B,YAAY;AAAA,EAChD,YAAY,SAAiB,MAAgC;AAC3D,UAAM,KAAK,SAAS,IAAI;AACxB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,qBAAN,cAAiC,SAAS;AAAA,EAC/C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACpCA,SAAS,cAAc;AACvB,SAAS,yBAAyB;AAClC,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,OAAO,UAAU;AAEV,IAAM,UAAU;AAGvB,IAAM,YAAY,IAAI,YAAY,EAAE,OAAO,iBAAiB;AAC5D,IAAM,kBAAkB,IAAI,YAAY,EAAE,OAAO,kBAAkB;AACnE,IAAM,mBAAmB,IAAI,YAAY,EAAE,OAAO,mBAAmB;AAErE,SAAS,MAAM,QAAoB,MAA8B;AAC/D,SAAO,KAAK,QAAQ,QAAQ,WAAW,MAAM,EAAE;AACjD;AACA,SAAS,SAAS,SAAiB,QAAgB,SAA6B;AAC9E,SAAO,IAAI,YAAY,EAAE,OAAO,yBAAyB,OAAO,QAAQ,MAAM,SAAS,OAAO,EAAE;AAClG;AACA,SAAS,UAAU,SAAiB,QAA4B;AAC9D,SAAO,IAAI,YAAY,EAAE,OAAO,0BAA0B,OAAO,QAAQ,MAAM,EAAE;AACnF;AACA,SAAS,UAAU,SAAiB,QAAgB,UAAkB,KAAa,SAA8B;AAC/G,SAAO,IAAI,YAAY,EAAE;AAAA,IACvB,0BAA0B,OAAO,QAAQ,MAAM,UAAU,QAAQ,QAAQ,GAAG,UAAU,UAAU,IAAI,CAAC;AAAA,EACvG;AACF;AAEA,SAAS,OAAO,GAAuB;AACrC,SAAO,KAAK,OAAO,CAAC;AACtB;AACA,SAAS,OAAO,GAAuB;AACrC,SAAO,KAAK,OAAO,CAAC;AACtB;AACA,SAAS,YAAY,GAAuB;AAC1C,SAAO,OAAO,gBAAgB,IAAI,WAAW,CAAC,CAAC;AACjD;AAQO,SAAS,qBAAsC;AACpD,QAAM,SAAS,OAAO,MAAM,iBAAiB;AAC7C,SAAO,EAAE,QAAQ,QAAQ,OAAO,OAAO,aAAa,MAAM,CAAC,EAAE;AAC/D;AAGO,SAAS,iBAAyB;AACvC,SAAO,OAAO,YAAY,EAAE,CAAC;AAC/B;AAGO,SAAS,YACd,YACA,YACA,WAC8C;AAC9C,QAAM,UAAU,OAAO,UAAU;AACjC,QAAM,YAAY,OAAO,MAAM,iBAAiB;AAChD,QAAM,SAAS,OAAO,aAAa,SAAS;AAC5C,QAAM,SAAS,OAAO,MAAM;AAC5B,QAAM,SAAS,OAAO,gBAAgB,WAAW,OAAO;AACxD,QAAM,MAAM,MAAM,QAAQ,eAAe;AACzC,QAAM,MAAM,SAAS,YAAY,QAAQ,UAAU;AACnD,QAAM,QAAQ,YAAY,EAAE;AAC5B,QAAM,KAAK,kBAAkB,KAAK,OAAO,GAAG,EAAE,QAAQ,SAAS;AAC/D,QAAM,MAAM,IAAI,WAAW,KAAK,GAAG,MAAM;AACzC,MAAI,IAAI,OAAO,CAAC;AAChB,MAAI,IAAI,IAAI,EAAE;AACd,SAAO,EAAE,YAAY,OAAO,GAAG,GAAG,cAAc,OAAO;AACzD;AAGO,SAAS,aACd,YACA,YACA,YACA,eACY;AACZ,QAAM,SAAS,OAAO,gBAAgB,YAAY,OAAO,UAAU,CAAC;AACpE,QAAM,MAAM,MAAM,QAAQ,gBAAgB;AAC1C,QAAM,MAAM,UAAU,YAAY,UAAU;AAC5C,QAAM,OAAO,OAAO,aAAa;AACjC,SAAO,kBAAkB,KAAK,KAAK,MAAM,GAAG,EAAE,GAAG,GAAG,EAAE,QAAQ,KAAK,MAAM,EAAE,CAAC;AAC9E;AAGO,SAAS,aAAa,YAAwB,kBAAsC;AACzF,QAAM,SAAS,OAAO,gBAAgB,YAAY,OAAO,gBAAgB,CAAC;AAC1E,SAAO,MAAM,QAAQ,gBAAgB;AACvC;AAGO,SAAS,gBACd,QACA,YACA,cACA,aACA,KACA,SACA,OACY;AACZ,QAAM,MAAM,UAAU,YAAY,cAAc,aAAa,KAAK,OAAO;AACzE,QAAM,OAAO,OAAO,KAAK;AACzB,SAAO,kBAAkB,QAAQ,KAAK,MAAM,GAAG,EAAE,GAAG,GAAG,EAAE,QAAQ,KAAK,MAAM,EAAE,CAAC;AACjF;;;AC3FO,IAAM,mBAAmB;AAEhC,IAAM,kBAAkB;AAEjB,IAAM,aAAN,MAAiB;AAAA,EAKtB,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AACvE,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,UAAU,EAAE,QAAQ,oBAAoB,gBAAgB,mBAAmB;AAChF,QAAI,QAAQ,QAAQ;AAClB,WAAK,QAAQ,eAAe,IAAI,UAAU,QAAQ,MAAM;AAGxD,WAAK,QAAQ,WAAW,IAAI,QAAQ;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAc,QACZ,QACA,MACA,MACY;AACZ,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI;AAClC,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AAE/D,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,KAAK;AAAA,QAC1B;AAAA,QACA,SAAS,KAAK;AAAA,QACd,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,QACpC,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,eAAe,SAAS,IAAI,SAAS,cAAc;AACrD,cAAM,IAAI,mBAAmB,cAAc,GAAG,YAAY;AAAA,MAC5D;AACA,YAAM,IAAI;AAAA,QACR,wBAAwB,KAAK,OAAO,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3F;AAAA,IACF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,UAAI;AACJ,UAAI,UAAU,SAAS;AACvB,UAAI;AACF,oBAAa,MAAM,SAAS,KAAK;AACjC,cAAM,MAAM,WAAW;AACvB,YAAI,OAAO,QAAQ,SAAU,WAAU;AAAA,iBAC9B,OAAO,OAAO,QAAQ,YAAY,aAAa;AACtD,oBAAU,OAAQ,IAA6B,OAAO;AAAA,MAC1D,QAAQ;AAAA,MAER;AAEA,UAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,cAAM,IAAI,aAAa,SAAS,QAAQ,SAAS,SAAS;AAAA,MAC5D;AACA,UAAI,SAAS,WAAW,KAAK;AAC3B,cAAM,IAAI,iBAAiB,SAAS,SAAS;AAAA,MAC/C;AACA,YAAM,IAAI,YAAY,SAAS,QAAQ,SAAS,SAAS;AAAA,IAC3D;AAEA,QAAI,SAAS,WAAW,IAAK,QAAO,CAAC;AACrC,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B;AAAA;AAAA,EAIA,MAAM,WAAsC;AAC1C,WAAO,KAAK,QAA0B,OAAO,gBAAgB;AAAA,EAC/D;AAAA,EAEA,MAAM,SAA+B;AACnC,UAAM,OAAO,MAAM,KAAK,QAAiC,OAAO,cAAc;AAC9E,WAAO,KAAK,UAAU,CAAC;AAAA,EACzB;AAAA,EAEA,MAAM,UAAkC;AACtC,UAAM,OAAO,MAAM,KAAK,QAAoC,OAAO,eAAe;AAClF,WAAO,KAAK,WAAW,CAAC;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UACJ,OACA,SACyB;AACzB,UAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,CAAC;AAC5C,QAAI,SAAS,QAAS,QAAO,IAAI,WAAW,QAAQ,OAAO;AAC3D,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,iBAAiB,OAAO,SAAS,CAAC;AAAA,IACpC;AACA,WAAO,KAAK,aAAa,CAAC;AAAA,EAC5B;AAAA;AAAA,EAIA,MAAM,UACJ,OACA,OACA,SACsB;AACtB,UAAM,OAAgC,EAAE,OAAO,MAAM;AACrD,QAAI,SAAS,gBAAiB,MAAK,mBAAmB,QAAQ;AAC9D,QAAI,SAAS,eAAgB,MAAK,kBAAkB,QAAQ;AAC5D,WAAO,KAAK,QAAqB,QAAQ,cAAc,IAAI;AAAA,EAC7D;AAAA,EAEA,MAAM,OAAO,OAAmC;AAC9C,WAAO,KAAK,QAAmB,OAAO,cAAc,KAAK,EAAE;AAAA,EAC7D;AAAA,EAEA,MAAM,eAAe,OAA0C;AAC7D,WAAO,KAAK,QAA0B,OAAO,cAAc,KAAK,cAAc;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,QAAQ,KAMO;AAC3B,UAAM,OAAgC,EAAE,OAAO,IAAI,MAAM;AACzD,QAAI,IAAI,KAAM,MAAK,OAAO,IAAI;AAC9B,QAAI,IAAI,QAAS,MAAK,UAAU,IAAI;AACpC,QAAI,IAAI,YAAa,MAAK,cAAc,IAAI;AAC5C,QAAI,IAAI,aAAa,KAAM,MAAK,YAAY,IAAI;AAChD,UAAM,MAAM,MAAM,KAAK,QAAyB,QAAQ,eAAe,IAAI;AAC3E,QAAI,CAAC,IAAI,oBAAoB;AAC3B,YAAM,IAAI,YAAY,KAAK,+CAA+C;AAAA,IAC5E;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBACJ,SACiC;AACjC,QAAI,QAAQ,QAAQ;AAElB,UAAI,UAAU;AACd,uBAAiB,SAAS,KAAK,qBAAqB,OAAO,EAAG,YAAW;AACzE,aAAO;AAAA,QACL,IAAI;AAAA,QAAI,QAAQ;AAAA,QAAmB,SAAS;AAAA,QAAG,OAAO,QAAQ;AAAA,QAC9D,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,MAAM,aAAa,QAAQ,GAAG,eAAe,OAAO,CAAC;AAAA,MACxF;AAAA,IACF;AAEA,UAAM,cAAc,MAAM,KAAK,QAAQ,OAAO;AAC9C,UAAM,EAAE,QAAQ,OAAO,IAAQ,mBAAmB;AAClD,UAAM,YAAY,QAAQ,cAAc;AACxC,UAAM,SAAa;AAAA,MACjB,YAAY;AAAA,MACZ;AAAA,MACA,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU;AAAA,QACtC,UAAU,QAAQ;AAAA,QAClB,aAAa,QAAQ,eAAe;AAAA,QACpC,YAAY;AAAA,MACd,CAAC,CAAC;AAAA,IACJ;AACA,UAAM,OAAO;AAAA,MACX,mBAAmB,YAAY;AAAA,MAC/B,YAAY;AAAA;AAAA,MACZ,KAAK;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,yBAAyB,OAAO;AAAA,QAChC,wBAAwB;AAAA,QACxB,WAAe;AAAA,MACjB;AAAA,IACF;AAEA,QAAI;AAIJ,QAAI;AACF,aAAO,MAAM,KAAK,QAAQ,QAAQ,wBAAwB,IAAI;AAAA,IAChE,SAAS,KAAK;AACZ,UAAI,eAAe,eAAe,IAAI,eAAe,KAAK;AACxD,cAAM,IAAI,YAAY,KAAK,yIAAoI;AAAA,MACjK;AACA,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,KAAK,cAAe,OAAM,IAAI,YAAY,KAAK,2BAA2B;AAC/E,UAAM,QAAY,aAAa,QAAQ,QAAQ,KAAK,cAAc,sBAAsB,KAAK,cAAc,UAAU;AACrH,UAAM,SAAS,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,KAAK,CAAC;AAEzD,WAAO;AAAA,MACL,IAAI,KAAK,MAAM;AAAA,MACf,QAAQ;AAAA,MACR,SAAS,KAAK,WAAW;AAAA,MACzB,OAAO,QAAQ;AAAA,MACf,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,MAAM,aAAa,SAAS,OAAO,WAAW,GAAG,GAAG,eAAe,OAAO,CAAC;AAAA,MAC5G,OAAO,KAAK,SAAS,OAAO;AAAA,MAC5B,aAAa;AAAA,QACX,QAAQ,YAAY;AAAA,QACpB,SAAS,YAAY,YAAY;AAAA,QACjC,UAAU,CAAC,CAAC,YAAY;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,MAAM,SAAuD;AACjE,UAAM,OAAgC,EAAE,OAAO,QAAQ,OAAO,OAAO,QAAQ,MAAM;AACnF,QAAI,QAAQ,cAAc,KAAM,MAAK,aAAa,QAAQ;AAC1D,QAAI,QAAQ,cAAc,KAAM,MAAK,aAAa,QAAQ;AAC1D,QAAI,QAAQ,QAAQ,KAAM,MAAK,OAAO,QAAQ;AAC9C,QAAI;AACF,aAAQ,MAAM,KAAK,QAAQ,QAAQ,kBAAkB,IAAI;AAAA,IAC3D,SAAS,KAAK;AACZ,UAAI,eAAe,eAAe,IAAI,eAAe,KAAK;AACxD,cAAM,IAAI,YAAY,KAAK,yIAAoI;AAAA,MACjK;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,qBACL,SACuC;AACvC,UAAM,cAAc,MAAM,KAAK,QAAQ,OAAO;AAC9C,UAAM,EAAE,QAAQ,OAAO,IAAQ,mBAAmB;AAClD,UAAM,QAAY,eAAe;AACjC,UAAM,YAAY,QAAQ,cAAc;AACxC,UAAM,SAAa;AAAA,MACjB,YAAY;AAAA,MACZ;AAAA,MACA,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU;AAAA,QACtC,UAAU,QAAQ;AAAA,QAClB,aAAa,QAAQ,eAAe;AAAA,QACpC,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR;AAAA,MACF,CAAC,CAAC;AAAA,IACJ;AACA,UAAM,OAAO;AAAA,MACX,mBAAmB,YAAY;AAAA,MAC/B,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,KAAK;AAAA,QACH,YAAY,OAAO;AAAA,QACnB,yBAAyB,OAAO;AAAA,QAChC,wBAAwB;AAAA,QACxB,WAAe;AAAA,MACjB;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AACjE,QAAI;AACJ,QAAI;AACF,aAAO,MAAM,MAAM,GAAG,KAAK,OAAO,wBAAwB;AAAA,QACxD,QAAQ;AAAA,QACR,SAAS,KAAK;AAAA,QACd,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,mBAAa,OAAO;AACpB,YAAM,IAAI;AAAA,QACR,wBAAwB,KAAK,OAAO,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3F;AAAA,IACF;AACA,QAAI,CAAC,KAAK,IAAI;AACZ,mBAAa,OAAO;AACpB,UAAI,KAAK,WAAW,KAAK;AACvB,cAAM,IAAI,YAAY,KAAK,yIAAoI;AAAA,MACjK;AACA,UAAI,UAAU,KAAK;AACnB,UAAI;AACF,cAAM,IAAK,MAAM,KAAK,KAAK;AAC3B,YAAI,OAAO,EAAE,UAAU,SAAU,WAAU,EAAE;AAAA,iBACpC,EAAE,SAAS,OAAO,EAAE,UAAU,YAAY,aAAa,EAAE,MAAO,WAAU,OAAQ,EAAE,MAA+B,OAAO;AAAA,MACrI,QAAQ;AAAA,MAAe;AACvB,YAAM,IAAI,YAAY,KAAK,QAAQ,OAAO;AAAA,IAC5C;AAEA,UAAM,QAAQ,KAAK,QAAQ,IAAI,cAAc,KAAK;AAClD,QAAI,CAAC,MAAM,SAAS,mBAAmB,KAAK,CAAC,KAAK,MAAM;AACtD,mBAAa,OAAO;AACpB,YAAM,OAAQ,MAAM,KAAK,KAAK;AAC9B,UAAI,CAAC,KAAK,cAAe,OAAM,IAAI,YAAY,KAAK,2BAA2B;AAC/E,YAAM,QAAY,aAAa,QAAQ,QAAQ,KAAK,cAAc,sBAAsB,KAAK,cAAc,UAAU;AACrH,YAAM,UAAW,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,KAAK,CAAC,EAA2B,WAAW;AACjG,UAAI,QAAS,OAAM;AACnB;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,KAAK,UAAU;AACnC,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,gBAAgB;AACtB,UAAM,YAAY,YAA2D;AAC3E,UAAI;AACJ,YAAM,UAAU,IAAI,QAAe,CAAC,GAAG,WAAW;AAChD,YAAI,WAAW,MAAM,OAAO,IAAI,mBAAmB,8BAA8B,CAAC,GAAG,aAAa;AAAA,MACpG,CAAC;AACD,UAAI;AACF,eAAQ,MAAM,QAAQ,KAAK,CAAC,OAAO,KAAK,GAAG,OAAO,CAAC;AAAA,MACrD,UAAE;AACA,YAAI,EAAG,cAAa,CAAC;AAAA,MACvB;AAAA,IACF;AAEA,QAAI,MAAM;AACV,QAAI,cAAc;AAClB,QAAI,SAA4B;AAChC,QAAI,YAA2B;AAC/B,QAAI,WAAW;AACf,QAAI;AACF,iBAAS;AACP,YAAI,SAAU;AACd,cAAM,EAAE,OAAO,KAAK,IAAI,MAAM,UAAU;AACxC,YAAI,KAAM;AAEV,eAAO,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,EAAE,QAAQ,SAAS,IAAI;AACpE,YAAI;AACJ,gBAAQ,MAAM,IAAI,QAAQ,MAAM,OAAO,IAAI;AACzC,gBAAM,MAAM,IAAI,MAAM,GAAG,GAAG;AAC5B,gBAAM,IAAI,MAAM,MAAM,CAAC;AACvB,cAAI,IAAI,SAAS,cAAc,EAAG,OAAM,IAAI,YAAY,KAAK,0BAA0B;AACvF,gBAAM,UAAU,IAAI,MAAM,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,KAAK,IAAI;AAC5G,cAAI,CAAC,WAAW,YAAY,SAAU;AAEtC,cAAI;AACJ,cAAI;AACF,oBAAQ,KAAK,MAAM,OAAO;AAAA,UAC5B,QAAQ;AACN,kBAAM,IAAI,YAAY,KAAK,wBAAwB;AAAA,UACrD;AACA,cAAI,OAAO,MAAM,QAAQ,YAAY,CAAC,MAAM,IAAI;AAC9C,kBAAM,IAAI,YAAY,KAAK,+CAA+C;AAAA,UAC5E;AACA,cAAI,MAAM,QAAQ,YAAa,OAAM,IAAI,YAAY,KAAK,iCAAiC,WAAW,SAAS,MAAM,GAAG,GAAG;AAC3H,cAAI,MAAM,QAAQ,GAAG;AACnB,gBAAI,CAAC,MAAM,IAAK,OAAM,IAAI,YAAY,KAAK,sCAAsC;AACjF,wBAAY,MAAM;AAClB,qBAAa,aAAa,QAAQ,SAAS;AAAA,UAC7C;AACA,gBAAM,UAAU,MAAM,UAAU;AAChC,gBAAM,OAAO,IAAI,YAAY,EAAE;AAAA,YACzB,gBAAgB,QAAsB,QAAQ,WAAqB,OAAO,MAAM,KAAK,SAAS,MAAM,EAAE;AAAA,UAC5G;AACA,cAAI,KAAM,OAAM;AAChB;AACA,cAAI,SAAS;AAAE,uBAAW;AAAM;AAAA,UAAO;AAAA,QACzC;AAAA,MACF;AAAA,IACF,UAAE;AACA,mBAAa,OAAO;AACpB,UAAI;AAAE,cAAM,OAAO,OAAO;AAAA,MAAG,QAAQ;AAAA,MAAe;AAAA,IACtD;AACA,QAAI,CAAC,SAAU,OAAM,IAAI,YAAY,KAAK,6CAA6C;AAAA,EACzF;AAAA;AAAA,EAIA,MAAc,sBACZ,QACA,MACA,QACA,MACY;AACZ,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI;AAClC,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AAE/D,UAAM,aAAqC;AAAA,MACzC,GAAG,KAAK;AAAA,MACR,kBAAkB,OAAO;AAAA,MACzB,gBAAgB,OAAO,SAAS;AAAA,MAChC,oBAAoB,OAAO;AAAA,MAC3B,oBAAoB,OAAO;AAAA,MAC3B,gBAAgB,OAAO;AAAA,IACzB;AAEA,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,KAAK;AAAA,QAC1B;AAAA,QACA,SAAS;AAAA,QACT,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,QACpC,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,eAAe,SAAS,IAAI,SAAS,cAAc;AACrD,cAAM,IAAI,mBAAmB,cAAc,GAAG,YAAY;AAAA,MAC5D;AACA,YAAM,IAAI;AAAA,QACR,wBAAwB,KAAK,OAAO,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3F;AAAA,IACF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,UAAI;AACJ,UAAI,UAAU,SAAS;AACvB,UAAI;AACF,oBAAa,MAAM,SAAS,KAAK;AACjC,cAAM,MAAM,WAAW;AACvB,YAAI,OAAO,QAAQ,SAAU,WAAU;AAAA,iBAC9B,OAAO,OAAO,QAAQ,YAAY,aAAa;AACtD,oBAAU,OAAQ,IAA6B,OAAO;AAAA,MAC1D,QAAQ;AAAA,MAER;AAEA,UAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,cAAM,IAAI,aAAa,SAAS,QAAQ,SAAS,SAAS;AAAA,MAC5D;AACA,UAAI,SAAS,WAAW,KAAK;AAC3B,cAAM,IAAI,iBAAiB,SAAS,SAAS;AAAA,MAC/C;AACA,YAAM,IAAI,YAAY,SAAS,QAAQ,SAAS,SAAS;AAAA,IAC3D;AAEA,QAAI,SAAS,WAAW,IAAK,QAAO,CAAC;AACrC,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B;AAAA,EAEA,MAAc,mBACZ,QACA,MACA,MACA,eACY;AACZ,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI;AAClC,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AAE/D,UAAM,aAAqC,EAAE,GAAG,KAAK,QAAQ;AAC7D,QAAI,eAAe;AACjB,iBAAW,WAAW,IAAI;AAAA,IAC5B;AAEA,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,KAAK;AAAA,QAC1B;AAAA,QACA,SAAS;AAAA,QACT,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,QACpC,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,eAAe,SAAS,IAAI,SAAS,cAAc;AACrD,cAAM,IAAI,mBAAmB,cAAc,GAAG,YAAY;AAAA,MAC5D;AACA,YAAM,IAAI;AAAA,QACR,wBAAwB,KAAK,OAAO,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3F;AAAA,IACF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAEA,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,eAAgB,MAAM,SAAS,KAAK;AAC1C,YAAM,IAAI,YAAY,KAAK,oBAAoB,YAAY;AAAA,IAC7D;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,UAAI;AACJ,UAAI,UAAU,SAAS;AACvB,UAAI;AACF,oBAAa,MAAM,SAAS,KAAK;AACjC,cAAM,MAAM,WAAW;AACvB,YAAI,OAAO,QAAQ,SAAU,WAAU;AAAA,MACzC,QAAQ;AAAA,MAER;AACA,YAAM,IAAI,YAAY,SAAS,QAAQ,SAAS,SAAS;AAAA,IAC3D;AAEA,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B;AAAA;AAAA,EAIA,MAAM,gBACJ,QACA,SACgC;AAChC,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,eACA,OACA,SACgC;AAChC,UAAM,OAAgC,EAAE,MAAM;AAC9C,QAAI,SAAS,aAAc,MAAK,gBAAgB,QAAQ;AACxD,WAAO,KAAK;AAAA,MACV;AAAA,MACA,oBAAoB,mBAAmB,aAAa,CAAC;AAAA,MACrD;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,SAIc;AACjC,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,SAAS,MAAO,QAAO,IAAI,SAAS,QAAQ,KAAK;AACrD,QAAI,SAAS,QAAQ,KAAM,QAAO,IAAI,QAAQ,OAAO,QAAQ,IAAI,CAAC;AAClE,QAAI,SAAS,SAAS,KAAM,QAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AACrE,UAAM,KAAK,OAAO,SAAS;AAC3B,WAAO,KAAK;AAAA,MACV;AAAA,MACA,mBAAmB,KAAK,IAAI,EAAE,KAAK,EAAE;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,aAA6C;AAC9D,WAAO,KAAK,QAAuB,OAAO,oBAAoB,WAAW,EAAE;AAAA,EAC7E;AAAA,EAEA,MAAM,gBACJ,aACA,QAC2C;AAC3C,WAAO,KAAK;AAAA,MACV;AAAA,MACA,oBAAoB,WAAW;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,iBACJ,aACA,QACA,SACgC;AAChC,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,SAAS,QAAQ,KAAM,QAAO,IAAI,QAAQ,OAAO,QAAQ,IAAI,CAAC;AAClE,QAAI,SAAS,SAAS,KAAM,QAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AACrE,UAAM,KAAK,OAAO,SAAS;AAC3B,WAAO,KAAK;AAAA,MACV;AAAA,MACA,oBAAoB,WAAW,QAAQ,KAAK,IAAI,EAAE,KAAK,EAAE;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACF;;;AC5lBA,SAAS,WAAW;AACpB,SAAS,cAAc;AAGhB,IAAM,YAAY;AAEzB,IAAM,gBAAgB,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG,GAAG,EAAE;AAC/C,IAAM,eAAe,KAAK;AAW1B,IAAM,KAAK,IAAI,YAAY;AAC3B,IAAM,KAAK,IAAI,YAAY;AAE3B,SAAS,SAAS,KAA2B;AAE3C,QAAM,EAAE,SAAS,UAAU,eAAe,OAAO,IAAI;AACrD,SAAO,GAAG,OAAO,KAAK,UAAU,EAAE,SAAS,UAAU,eAAe,OAAO,CAAC,CAAC;AAC/E;AAEA,SAAS,IAAI,GAAuB;AAClC,MAAI,IAAI;AACR,aAAW,KAAK,EAAG,MAAK,OAAO,aAAa,CAAC;AAC7C,SAAO,KAAK,CAAC;AACf;AAEA,SAAS,MAAM,GAAuB;AACpC,QAAM,MAAM,KAAK,CAAC;AAClB,QAAM,MAAM,IAAI,WAAW,IAAI,MAAM;AACrC,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,CAAC,IAAI,IAAI,WAAW,CAAC;AAC9D,SAAO;AACT;AAEA,SAAS,KAAK,GAAuB;AACnC,QAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,SAAO,gBAAgB,GAAG;AAC1B,SAAO;AACT;AAGO,SAAS,gBAAgB,WAAuB,YAAoB,KAA2B;AACpG,QAAM,OAAO,KAAK,EAAE;AACpB,QAAM,MAAM,OAAO,GAAG,OAAO,UAAU,GAAG,MAAM,EAAE,GAAG,eAAe,OAAO,GAAG,CAAC;AAC/E,QAAM,MAAM,KAAK,EAAE;AACnB,QAAM,SAAS,SAAS,GAAG;AAC3B,QAAM,WAAW,KAAK,EAAE;AACxB,QAAM,UAAU,IAAI,KAAK,UAAU,MAAM,EAAE,QAAQ,GAAG;AACtD,QAAM,YAAY,KAAK,EAAE;AACzB,QAAM,OAAO,IAAI,KAAK,WAAW,MAAM,EAAE,QAAQ,SAAS;AAC1D,QAAM,SAAS,GAAG,OAAO,KAAK,UAAU;AAAA,IACtC,eAAe;AAAA,IACf,KAAK;AAAA,IACL,WAAW,EAAE,GAAG,eAAe,MAAM,IAAI,IAAI,EAAE;AAAA,IAC/C,QAAQ;AAAA,IACR,YAAY,EAAE,OAAO,IAAI,QAAQ,GAAG,YAAY,IAAI,OAAO,EAAE;AAAA,IAC7D,WAAW,IAAI,SAAS;AAAA,IACxB;AAAA,EACF,CAAC,CAAC;AACF,QAAM,MAAM,IAAI,WAAW,IAAI,OAAO,SAAS,KAAK,MAAM;AAC1D,MAAI,SAAS,IAAI,MAAM,EAAE,UAAU,GAAG,OAAO,QAAQ,KAAK;AAC1D,MAAI,IAAI,QAAQ,CAAC;AACjB,MAAI,IAAI,MAAM,IAAI,OAAO,MAAM;AAC/B,SAAO;AACT;AAGO,SAAS,gBAAgB,MAAkB,YAAoB,KAA2B;AAC/F,MAAI,KAAK,SAAS,EAAG,OAAM,IAAI,YAAY,GAAG,2BAA2B;AACzE,QAAM,YAAY,IAAI,SAAS,KAAK,QAAQ,KAAK,UAAU,EAAE,UAAU,GAAG,KAAK;AAC/E,MAAI,IAAI,YAAY,KAAK,OAAQ,OAAM,IAAI,YAAY,GAAG,6CAA6C;AACvG,MAAI;AAMJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG,OAAO,KAAK,SAAS,GAAG,IAAI,SAAS,CAAC,CAAC;AAAA,EAChE,QAAQ;AACN,UAAM,IAAI,YAAY,GAAG,qCAAqC;AAAA,EAChE;AACA,MAAI,OAAO,QAAQ,UAAU;AAC3B,UAAM,IAAI,YAAY,GAAG,oBAAoB,OAAO,OAAO,GAAG,CAAC,2DAAsD;AAAA,EACvH;AACA,QAAM,IAAI,OAAO,aAAa,CAAC;AAC/B,MACE,CAAC,OAAO,UAAU,EAAE,CAAC,KAAM,EAAE,IAAe,gBAAiB,EAAE,IAAe,cAAc,MAC1F,EAAE,IAAiB,EAAE,IAAe,OAAQ,KAC9C,CAAC,OAAO,UAAU,EAAE,CAAC,KAAM,EAAE,IAAe,KAAM,EAAE,IAAe,MACnE,CAAC,OAAO,UAAU,EAAE,CAAC,KAAM,EAAE,IAAe,KAAM,EAAE,IAAe,KACnE,OAAO,EAAE,SAAS,YAAY,CAAC,OAAO,YAAY,SAAS,CAAC,OAAO,YAAY,cAAc,CAAC,OAAO,WACrG;AACA,UAAM,IAAI,YAAY,GAAG,+CAA+C;AAAA,EAC1E;AACA,QAAM,OAAO,MAAM,EAAE,IAAI;AACzB,MAAI,KAAK,SAAS,GAAI,OAAM,IAAI,YAAY,GAAG,gCAAgC;AAC/E,QAAM,MAAM,OAAO,GAAG,OAAO,UAAU,GAAG,MAAM,EAAE,GAAG,EAAE,GAAa,GAAG,EAAE,GAAa,GAAG,EAAE,GAAa,OAAO,GAAG,CAAC;AACnH,QAAM,SAAS,SAAS,GAAG;AAC3B,MAAI;AACF,UAAM,MAAM,IAAI,KAAK,MAAM,OAAO,WAAW,KAAK,GAAG,MAAM,EAAE,QAAQ,MAAM,OAAO,WAAW,UAAU,CAAC;AACxG,WAAO,IAAI,KAAK,MAAM,OAAO,SAAS,GAAG,MAAM,EAAE,QAAQ,KAAK,SAAS,IAAI,SAAS,CAAC;AAAA,EACvF,QAAQ;AACN,UAAM,IAAI,YAAY,GAAG,0CAA0C;AAAA,EACrE;AACF;AAEO,SAAS,gBAAgB,OAAyB;AACvD,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,MAAI,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM,aAAa,MAAM,CAAC,MAAM,cAC1D,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG;AAC1C,UAAM,IAAI,YAAY,GAAG,qBAAqB,KAAK,EAAE;AAAA,EACvD;AACA,SAAO,EAAE,QAAQ,MAAM,CAAC,GAAG,SAAS,MAAM,CAAC,GAAG,UAAU,MAAM,CAAC,GAAG,eAAe,EAAE;AACrF;AAmCO,IAAM,cAAN,MAAM,aAAY;AAAA,EAKvB,YAAY,SAA6B;AACvC,UAAM,QAAQ,QAAQ,WAAW,WAAW,QAAQ,QAAQ,EAAE;AAC9D,UAAM,IAAI,IAAI,IAAI,IAAI;AACtB,UAAM,QAAQ,CAAC,aAAa,aAAa,OAAO,EAAE,SAAS,EAAE,QAAQ;AACrE,QAAI,EAAE,aAAa,YAAY,CAAC,OAAO;AACrC,YAAM,IAAI,YAAY,GAAG,yDAAyD;AAAA,IACpF;AACA,QAAI,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM;AAClD,YAAM,IAAI,YAAY,GAAG,+BAA+B;AAAA,IAC1D;AACA,SAAK,OAAO;AACZ,SAAK,SAAS,QAAQ;AACtB,SAAK,YAAY,QAAQ,aAAa;AAAA,EACxC;AAAA,EAEA,OAAe,GAAG,GAAmB;AACnC,QAAI,CAAC,qBAAqB,KAAK,CAAC,EAAG,OAAM,IAAI,YAAY,GAAG,sBAAsB,CAAC,EAAE;AACrF,WAAO,EAAE,YAAY;AAAA,EACvB;AAAA,EAEA,MAAc,KAAQ,QAAgB,MAAc,MAA4B;AAC9E,UAAM,MAAM,MAAM,KAAK,UAAU,GAAG,KAAK,IAAI,GAAG,IAAI,IAAI;AAAA,MACtD;AAAA,MACA,SAAS;AAAA,QACP,aAAa,KAAK;AAAA,QAClB,GAAI,SAAS,SAAY,EAAE,gBAAgB,mBAAmB,IAAI,CAAC;AAAA,MACrE;AAAA,MACA,MAAM,SAAS,SAAY,KAAK,UAAU,IAAI,IAAI;AAAA,IACpD,CAAC;AACD,UAAM,OAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC/C,QAAI,CAAC,IAAI,GAAI,OAAM,IAAI,YAAY,IAAI,QAAQ,OAAO,KAAK,SAAS,mBAAmB,IAAI,MAAM,EAAE,CAAC;AACpG,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAgC;AACpC,YAAQ,MAAM,KAAK,KAA+B,OAAO,iBAAiB,GAAG;AAAA,EAC/E;AAAA,EAEA,MAAM,YAAY,MAAc,WAAwC;AACtE,YAAQ,MAAM,KAAK,KAA4B,QAAQ,mBAAmB,EAAE,MAAM,UAAU,CAAC,GAAG;AAAA,EAClG;AAAA,EAEA,MAAM,UAAU,SAA4C;AAC1D,UAAM,IAAI,UAAU,YAAY,mBAAmB,OAAO,CAAC,KAAK;AAChE,YAAQ,MAAM,KAAK,KAAmC,OAAO,WAAW,CAAC,EAAE,GAAG;AAAA,EAChF;AAAA,EAEA,MAAM,QAA6B;AACjC,WAAO,KAAK,KAAiB,OAAO,gBAAgB;AAAA,EACtD;AAAA;AAAA,EAGA,MAAM,eAA4D;AAChE,WAAO,KAAK,KAAK,QAAQ,oBAAoB;AAAA,EAC/C;AAAA,EAEA,MAAM,eAAe,IAA2B;AAC9C,UAAM,KAAK,KAAK,UAAU,YAAY,aAAY,GAAG,EAAE,CAAC,EAAE;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAY,SAAiB,SAAqB,YAAqC;AAC3F,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MAAQ;AAAA,MAAY,EAAE,SAAS,WAAW,QAAQ,OAAO;AAAA,IAC3D;AACA,UAAM,OAAO,gBAAgB,SAAS,YAAY,gBAAgB,IAAI,KAAK,CAAC;AAC5E,UAAM,KAAK,MAAM,KAAK,UAAU,IAAI,WAAW;AAAA,MAC7C,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS,EAAE,gBAAgB,2BAA2B;AAAA,IACxD,CAAC;AACD,QAAI,CAAC,GAAG,GAAI,OAAM,IAAI,YAAY,GAAG,QAAQ,kBAAkB,GAAG,MAAM,EAAE;AAC1E,UAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW,IAA8B;AACnF,UAAMA,UAAS,CAAC,GAAG,IAAI,WAAW,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAC9F,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,QAAQ,aAAa,EAAE,QAAAA,QAAO,CAAC;AACvE,WAAO,IAAI;AAAA,EACb;AAAA;AAAA,EAGA,MAAM,aAAa,YAAoB,YAAyC;AAC9E,UAAM,OAAO,MAAM,KAAK,KAA6C,OAAO,YAAY,aAAY,GAAG,UAAU,CAAC,UAAU;AAC5H,UAAM,KAAK,MAAM,KAAK,UAAU,KAAK,WAAW;AAChD,QAAI,CAAC,GAAG,GAAI,OAAM,IAAI,YAAY,GAAG,QAAQ,oBAAoB,GAAG,MAAM,EAAE;AAC5E,UAAM,OAAO,IAAI,WAAW,MAAM,GAAG,YAAY,CAAC;AAClD,WAAO,gBAAgB,MAAM,YAAY,gBAAgB,KAAK,KAAK,CAAC;AAAA,EACtE;AACF;","names":["sha256"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@singularity-layer/grid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "TypeScript SDK for the SGL Network confidential compute grid (end-to-end encrypted + streaming)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -55,4 +55,4 @@
|
|
|
55
55
|
"tsup": "^8.0.0",
|
|
56
56
|
"typescript": "^5.4.0"
|
|
57
57
|
}
|
|
58
|
-
}
|
|
58
|
+
}
|