@singularity-layer/grid 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/index.d.mts +340 -102
- package/dist/index.d.ts +340 -102
- package/dist/index.js +367 -115
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +359 -114
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
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","../src/processors.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 GridClientOptions,\n JobResponse,\n JobResult,\n ModelInfo,\n PricingInfo,\n ProviderInfo,\n ProvidersResponse,\n ReserveResponse,\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}\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","/**\n * Singularity Processors.\n *\n * A processor is a function we host: deploy one and you get a paid HTTP endpoint, an OpenAPI\n * document and an MCP server. Buyers pay the PUBLISHER directly in USDC over x402 — the platform\n * never holds it and takes no cut. The publisher pays for compute instead.\n *\n * ─── WHY THIS IS A SEPARATE CLIENT ──────────────────────────────────────────\n * Processors live on their own worker at `https://processors.x402compute.cc`, not on the grid.\n * Until 0.9.0 these methods hung off `GridClient` and pointed at `/grid/processors`, which has\n * never existed — every call 404'd. Fixing that by teaching `GridClient` a second base URL would\n * have meant a per-call host override inside the shared request path that chat, embeddings and\n * jobs all use, which is a real risk to working features for no benefit. A separate client with\n * its own base URL touches none of that.\n *\n * ─── AUTH ───────────────────────────────────────────────────────────────────\n * A compute API key (`x402c_…`) with the `processors:write` scope, sent as `X-API-Key`.\n *\n * `processors:write` is FULL CONTROL of processors owned by that key's wallet, delete and secrets\n * included — the same shape as a Cloudflare API token. If you want a credential that cannot change\n * anything, mint `processors:read`. Three things to know before relying on it: compute keys do not\n * expire, there is no audit log of what a key did, and delete is permanent — the code is wiped and\n * the slug is burned forever, so a leaked key can destroy a name you can never reclaim.\n *\n * Two routes never accept a key: `suspend` (moderation) and `auth-session`. Both need a wallet\n * signature, and neither is a publisher action.\n *\n * ─── RUNNING A PROCESSOR IS NOT DONE WITH THE API KEY ────────────────────────\n * `run()` takes the INVOKE TOKEN that `deploy()` returns, because the run route is the only one\n * with both a money path and an anonymous buyer lane and deliberately does not read an API key as\n * an ownership claim. Anonymous buyers pay with x402 instead; see `runWithPayment`.\n */\n\nimport { SGLAPIError, SGLAuthError, SGLConnectionError, SGLNotFoundError } from \"./errors.js\";\n\nexport const PROCESSORS_BASE_URL = \"https://processors.x402compute.cc\";\n\nconst DEFAULT_TIMEOUT = 60_000;\n\n/**\n * A base URL override must not become a way to post the management key somewhere else.\n *\n * The key is long-lived, does not expire, and grants full control of the caller's processors, so\n * an `http://` or attacker-supplied origin is a credential disclosure rather than a\n * misconfiguration. Plain HTTP is allowed only for loopback, which is how you point this at a\n * local worker during development.\n */\nfunction isLoopback(hostname: string): boolean {\n // URL normalises an IPv6 literal WITH its brackets, so \"::1\" never appears here.\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"[::1]\" ||\n hostname === \"::1\"\n );\n}\n\nfunction parseBaseUrl(raw: string): URL {\n let u: URL;\n try {\n u = new URL(raw);\n } catch {\n throw new Error(`ProcessorsClient baseUrl is not a valid URL: ${raw}`);\n }\n if (u.protocol !== \"https:\" && !(u.protocol === \"http:\" && isLoopback(u.hostname))) {\n throw new Error(\n `ProcessorsClient baseUrl must be https (or http on localhost); got ${u.protocol}//${u.hostname}. ` +\n \"The API key is a long-lived full-control credential and must not be sent in the clear.\",\n );\n }\n return u;\n}\n\n/**\n * May the management key be sent to this host?\n *\n * https alone is not the question. `https://attacker.example` is a perfectly valid TLS origin,\n * and if `baseUrl` is ever wired to an environment variable — which is exactly how people\n * configure a staging host — then influencing that variable is enough to harvest a long-lived\n * full-control credential. So the key travels only to the official host or to loopback unless the\n * caller says otherwise, in one explicit flag they cannot set by accident.\n */\nfunction keyAllowedOnHost(u: URL): boolean {\n return u.origin === new URL(PROCESSORS_BASE_URL).origin || isLoopback(u.hostname);\n}\n\nexport interface ProcessorsClientOptions {\n /** Compute API key (`x402c_…`) holding `processors:read` or `processors:write`. */\n apiKey?: string;\n /** Override the base URL. Defaults to https://processors.x402compute.cc */\n baseUrl?: string;\n /**\n * Send the API key to a `baseUrl` that is neither the official host nor loopback.\n *\n * Off by default on purpose: see `keyAllowedOnHost`. Set it only when you genuinely run your\n * own processors host and mean to hand it your credential.\n */\n allowKeyOnCustomHost?: boolean;\n timeoutMs?: number;\n}\n\n/** Limits are declared, not discovered: the runtime hold before each run derives from `timeout_ms`. */\nexport interface ProcessorLimits {\n timeout_ms: number;\n cpu_ms: number;\n /** Must be >= 1. */\n subrequests: number;\n}\n\nexport interface ProcessorSecretDeclaration {\n name: string;\n /** Hosts this secret may be injected at. Every one must also appear in `egress.allow`. */\n hosts?: string[];\n /** Header injection. `format` must contain the literal `{value}` placeholder. */\n inject?: { header: string; format: string };\n /** `env` makes the value readable by your own code — a deliberate downgrade, opt in per secret. */\n mode?: \"env\";\n}\n\n/** One `price_usd` is the price on EVERY chain: all three assets are 6-decimal stablecoins. */\nexport interface ProcessorPayout {\n /** base58 wallet. Defaults to the deploying wallet. */\n solana?: string;\n /** 0x… — USDC on Base. */\n base?: string;\n /** 0x… — USDG on Robinhood Chain. */\n robinhood?: string;\n}\n\nexport interface ProcessorManifest {\n manifest_version: 1;\n /** Lowercase, permanent, and NEVER reusable — `pause` exists so nobody burns one to stop traffic. */\n slug: string;\n name: string;\n description: string;\n lane?: \"managed\" | \"self_hosted\" | \"pod\";\n price_usd?: string;\n methods?: Array<\"GET\" | \"POST\">;\n input_schema: Record<string, unknown>;\n output_schema: Record<string, unknown>;\n limits: ProcessorLimits;\n egress?: { allow: string[] };\n secrets?: ProcessorSecretDeclaration[];\n payout?: ProcessorPayout;\n pricing?: Record<string, unknown>;\n inference?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface DeployProcessorInput {\n manifest: ProcessorManifest;\n /** A single ES module. Use `bundle` instead if you need imports or npm packages. */\n code?: string;\n /** esbuild output, bundled on YOUR machine. We never run `npm install` for you. */\n bundle?: string;\n files?: Record<string, string>;\n}\n\nexport interface ProcessorDeployResult {\n id: string;\n slug: string;\n /** Shown EXACTLY ONCE. Store it — there is no way to read it back, only to rotate it. */\n invoke_token: string;\n listing_state: string;\n note?: string;\n}\n\nexport interface ProcessorSummary {\n id: string;\n slug: string;\n lane: string;\n price_micro: number;\n status: string;\n listed?: boolean;\n listing_state?: string;\n run_count?: number;\n last_run_at?: string | null;\n created_at: string;\n config_rev?: number;\n code_hash?: string | null;\n manifest?: ProcessorManifest | null;\n paused_at?: string | null;\n}\n\nexport interface ProcessorListResponse {\n processors: ProcessorSummary[];\n /** Present on the owner-scoped list; the wallet the credential resolved to. */\n owner?: string;\n}\n\nexport interface ProcessorRun {\n id: string;\n status: string;\n error: string | null;\n run_ms: number | null;\n cpu_ms: number | null;\n attempt_count?: number;\n created_at: string;\n finished_at?: string | null;\n output?: unknown;\n}\n\nexport interface ProcessorRunsResponse {\n runs: ProcessorRun[];\n /** Publisher-caused failures only. Platform faults are excluded, so it measures YOUR code. */\n failure_rate_30d?: number;\n runs_30d?: number;\n}\n\nexport interface ProcessorEarnings {\n sales?: unknown;\n runtime?: unknown;\n [key: string]: unknown;\n}\n\nexport interface ProcessorWebhookRegistration {\n url: string;\n /** Returned EXACTLY ONCE on registration. There is no way to read it back. */\n secret?: string;\n active?: boolean;\n [key: string]: unknown;\n}\n\nexport class ProcessorsClient {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly timeout: number;\n\n constructor(options: ProcessorsClientOptions = {}) {\n const parsed = parseBaseUrl(options.baseUrl ?? PROCESSORS_BASE_URL);\n this.baseUrl = (options.baseUrl ?? PROCESSORS_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeoutMs ?? DEFAULT_TIMEOUT;\n this.headers = { Accept: \"application/json\", \"Content-Type\": \"application/json\" };\n if (options.apiKey) {\n if (!keyAllowedOnHost(parsed) && !options.allowKeyOnCustomHost) {\n throw new Error(\n `ProcessorsClient refuses to send an API key to ${parsed.origin}. It is neither ` +\n `${new URL(PROCESSORS_BASE_URL).origin} nor loopback. If you really do run your own ` +\n \"processors host, pass allowKeyOnCustomHost: true.\",\n );\n }\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 extraHeaders?: Record<string, string>,\n /**\n * Send the management key? Default yes. Routes that carry their OWN credential — the public\n * catalogue, and the two run paths, which authenticate with an invoke token or an x402\n * payment — pass false, so a long-lived management key is not scattered through request logs\n * and traces on calls that have no use for it.\n */\n sendApiKey = true,\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 const base = { ...this.headers };\n if (!sendApiKey) delete base[\"X-API-Key\"];\n response = await fetch(url, {\n method,\n headers: { ...base, ...extraHeaders },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n throw new SGLConnectionError(\n `Could not reach ${url}: ${err instanceof Error ? err.message : String(err)}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n // `{}` rather than undefined: several methods below promise an object, and a 204\n // would otherwise break that contract at runtime while typechecking fine.\n if (response.status === 204) return {} as T;\n\n const text = await response.text();\n let parsed: unknown;\n try {\n parsed = text ? JSON.parse(text) : undefined;\n } catch {\n parsed = text;\n }\n\n if (!response.ok) {\n const body =\n parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : undefined;\n // The worker answers `{ error, detail }`; `detail` is the human sentence when present.\n const detail =\n (typeof body?.detail === \"string\" && body.detail) ||\n (typeof body?.error === \"string\" && body.error) ||\n \"\";\n if (response.status === 401 || response.status === 403) {\n throw new SGLAuthError(response.status, detail || \"unauthorized\", body);\n }\n // 404 is \"not yours\" as well as \"no such slug\", deliberately: confirming which private slugs\n // exist to a non-owner is exactly what the rest of the surface refuses to do.\n if (response.status === 404) {\n throw new SGLNotFoundError(detail || \"not found\", body);\n }\n throw new SGLAPIError(response.status, detail || `HTTP ${response.status}`, body);\n }\n\n return parsed as T;\n }\n\n // ── Discovery ────────────────────────────────────────────────────────────\n\n /**\n * The public catalogue.\n *\n * Sends NO credential, even when the client holds one. `GET /processors` is owner-scoped when a\n * key is presented and public otherwise, so passing the key here would silently return your own\n * processors instead of the catalogue — the opposite of what the name promises. Use `list()`\n * when you want yours.\n */\n async catalogue(): Promise<ProcessorListResponse> {\n return this.request<ProcessorListResponse>(\"GET\", \"/processors\", undefined, undefined, false);\n }\n\n /** Processors owned by this key's wallet. Needs `processors:read`. */\n async list(): Promise<ProcessorListResponse> {\n return this.request<ProcessorListResponse>(\"GET\", \"/processors\");\n }\n\n /** Owner projection when the key owns it, public projection otherwise. */\n async get(slug: string): Promise<ProcessorSummary> {\n return this.request<ProcessorSummary>(\"GET\", `/processors/${encodeURIComponent(slug)}`);\n }\n\n // ── Lifecycle (needs processors:write) ───────────────────────────────────\n\n /**\n * Deploy. The wallet behind the key becomes `owner_wallet`, which is also the x402 `payTo` and\n * the runtime-billing account — so the key must be minted on a SOLANA wallet or this returns\n * `400 solana_wallet_required`.\n *\n * The `invoke_token` in the response is shown once and never again.\n */\n async deploy(input: DeployProcessorInput): Promise<ProcessorDeployResult> {\n return this.request<ProcessorDeployResult>(\"POST\", \"/processors\", input);\n }\n\n /** Push new code, a new manifest, or both. Omitting `manifest` keeps the stored one. */\n async update(\n slug: string,\n input: { manifest?: ProcessorManifest; code?: string; bundle?: string; files?: Record<string, string> },\n ): Promise<{ slug: string; config_rev: number; config_changed: boolean }> {\n return this.request(\"PATCH\", `/processors/${encodeURIComponent(slug)}`, input);\n }\n\n /**\n * Delete. **Irreversible, and the slug is burned forever** — it can never be reused, by you or\n * anyone. In-flight runs finish first; the code is wiped when they drain.\n */\n async delete(slug: string): Promise<{ slug: string; status: string; note?: string }> {\n return this.request(\"DELETE\", `/processors/${encodeURIComponent(slug)}`);\n }\n\n /** Stop or restart traffic WITHOUT losing the slug. This is the switch, not `delete`. */\n async setPaused(slug: string, paused: boolean): Promise<unknown> {\n return this.request(\"PUT\", `/processors/${encodeURIComponent(slug)}/pause`, { paused });\n }\n\n /**\n * List or unlist publicly. Instant, no review step.\n *\n * Unlisting is NOT stopping: an unlisted processor keeps answering anyone holding the URL or an\n * invoke token, earning nothing while still drawing compute from your balance. Use `setPaused`.\n */\n async setListing(slug: string, listed: boolean): Promise<unknown> {\n return this.request(\"PUT\", `/processors/${encodeURIComponent(slug)}/listing`, { listed });\n }\n\n /** Set secret VALUES. Each name must already be declared in `manifest.secrets`. */\n async setSecrets(slug: string, values: Record<string, string>): Promise<unknown> {\n return this.request(\"PUT\", `/processors/${encodeURIComponent(slug)}/secrets`, { values });\n }\n\n /** Mint a new invoke token. The old one stops working immediately. */\n async rotateToken(slug: string): Promise<{ invoke_token: string }> {\n return this.request(\"POST\", `/processors/${encodeURIComponent(slug)}/rotate-token`);\n }\n\n // ── Observability ────────────────────────────────────────────────────────\n\n async runs(slug: string): Promise<ProcessorRunsResponse> {\n return this.request<ProcessorRunsResponse>(\"GET\", `/processors/${encodeURIComponent(slug)}/runs`);\n }\n\n async run_(slug: string, runId: string): Promise<ProcessorRun> {\n return this.request<ProcessorRun>(\n \"GET\",\n `/processors/${encodeURIComponent(slug)}/runs/${encodeURIComponent(runId)}`,\n );\n }\n\n /** Sales (paid straight to your wallet, with the on-chain tx per row) and runtime spend. */\n async earnings(slug: string): Promise<ProcessorEarnings> {\n return this.request<ProcessorEarnings>(\"GET\", `/processors/${encodeURIComponent(slug)}/earnings`);\n }\n\n /** The processor's own key/value state. Read-only from out here, by design. */\n async kv(slug: string): Promise<unknown> {\n return this.request(\"GET\", `/processors/${encodeURIComponent(slug)}/kv`);\n }\n\n // ── Webhooks ─────────────────────────────────────────────────────────────\n\n async getWebhook(slug: string): Promise<ProcessorWebhookRegistration> {\n return this.request(\"GET\", `/processors/${encodeURIComponent(slug)}/webhook`);\n }\n\n /**\n * Register or replace. We immediately POST a signed verification to the URL: it must answer 2xx\n * or the webhook stays registered-but-inactive and delivers nothing. The signing secret comes\n * back EXACTLY ONCE.\n */\n async setWebhook(slug: string, url: string): Promise<ProcessorWebhookRegistration> {\n return this.request(\"PUT\", `/processors/${encodeURIComponent(slug)}/webhook`, { url });\n }\n\n async deleteWebhook(slug: string): Promise<unknown> {\n return this.request(\"DELETE\", `/processors/${encodeURIComponent(slug)}/webhook`);\n }\n\n async testWebhook(slug: string): Promise<unknown> {\n return this.request(\"POST\", `/processors/${encodeURIComponent(slug)}/webhook/test`);\n }\n\n // ── Invoking ─────────────────────────────────────────────────────────────\n\n /**\n * Run YOUR OWN processor with the invoke token from `deploy()`.\n *\n * Not the API key: the run route deliberately does not read a key as an ownership claim, because\n * it is the only route with both a money path and an anonymous buyer lane. You pay for the\n * compute; nobody pays at call time.\n */\n async run(\n slug: string,\n input: Record<string, unknown>,\n invokeToken: string,\n ): Promise<unknown> {\n return this.request(\n \"POST\",\n `/processors/${encodeURIComponent(slug)}/run`,\n { input },\n { Authorization: `Bearer ${invokeToken}` },\n false,\n );\n }\n\n /**\n * Run someone else's processor as a buyer, with an x402 payment header.\n *\n * Call once WITHOUT `paymentHeader` to get the 402 and its `accepts` array — one entry per chain\n * that publisher takes. Match on `network`, pay that entry, and retry with the header.\n *\n * Re-sending the SAME header returns the run that payment already bought and does NOT charge\n * again. That is the recovery path for every failure mode, because **there are no refunds**: the\n * money went straight to the publisher and the platform never held it.\n */\n async runWithPayment(\n slug: string,\n input: Record<string, unknown>,\n paymentHeader?: string,\n acceptNetworks?: Array<\"solana\" | \"base\" | \"robinhood\">,\n ): Promise<unknown> {\n const extra: Record<string, string> = {};\n if (paymentHeader) extra[\"X-Payment\"] = paymentHeader;\n // Robinhood is withheld from the 402 unless asked for: the reference x402 client validates the\n // WHOLE accepts array against a fixed chain list and throws on the first name it does not know,\n // so advertising it unprompted would stop a conformant buyer paying on Solana or Base either.\n if (acceptNetworks?.length) extra[\"X-Accept-Networks\"] = acceptNetworks.join(\",\");\n return this.request(\"POST\", `/processors/${encodeURIComponent(slug)}/run`, { input }, extra, false);\n }\n}\n"],"mappings":"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","names":["sha256","DEFAULT_TIMEOUT","body"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@singularity-layer/grid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.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",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "tsup",
|
|
21
21
|
"typecheck": "tsc --noEmit",
|
|
22
|
-
"prepublishOnly": "npm run build"
|
|
22
|
+
"prepublishOnly": "npm run build",
|
|
23
|
+
"test": "npm run build && node --test test/*.test.mjs"
|
|
23
24
|
},
|
|
24
25
|
"keywords": [
|
|
25
26
|
"singularity",
|