unbrowse 7.2.0-preview.0 → 8.0.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.
@@ -24,7 +24,6 @@ const REQUIRED_FALLBACK_PACKAGES = [
24
24
  "tsx",
25
25
  "bs58",
26
26
  "@solana/kit",
27
- "@cascade-fyi/splits-sdk",
28
27
  ];
29
28
 
30
29
  const KNOWN_BAD_FALLBACK_VERSIONS = new Set([
@@ -0,0 +1,43 @@
1
+ import type { AccountMe, AccountCredits, ApiKeyCreateInput, ApiKeyCreateResponse, ApiKeyListResponse, ApiKeyRevokeResponse, ExecuteInput, ExecuteResponse, HealthResponse, RequestOptions, ResolveInput, ResolveResponse, SearchInput, SearchResponse, SponsorStatus, UnbrowseClientOptions } from "./types.js";
2
+ import type { WorkerProxyCapabilities, WorkerProxyRequest, WorkerProxyResponse } from "./proxy-types.js";
3
+ export declare class Unbrowse {
4
+ readonly apiKey: string | undefined;
5
+ readonly baseURL: string;
6
+ readonly timeout: number;
7
+ readonly maxRetries: number;
8
+ readonly logLevel: NonNullable<UnbrowseClientOptions["logLevel"]>;
9
+ private readonly _fetch;
10
+ private readonly defaultHeaders;
11
+ readonly account: AccountResource;
12
+ readonly keys: KeysResource;
13
+ readonly proxy: ProxyResource;
14
+ constructor(opts?: UnbrowseClientOptions);
15
+ resolve(input: ResolveInput, opts?: RequestOptions): Promise<ResolveResponse>;
16
+ execute(input: ExecuteInput, opts?: RequestOptions): Promise<ExecuteResponse>;
17
+ search(input: SearchInput, opts?: RequestOptions): Promise<SearchResponse>;
18
+ health(opts?: RequestOptions): Promise<HealthResponse>;
19
+ request<T>(method: string, path: string, body: unknown, opts: RequestOptions): Promise<T>;
20
+ private debug;
21
+ }
22
+ declare class AccountResource {
23
+ private readonly client;
24
+ constructor(client: Unbrowse);
25
+ me(opts?: RequestOptions): Promise<AccountMe>;
26
+ credits(opts?: RequestOptions): Promise<AccountCredits>;
27
+ sponsorStatus(opts?: RequestOptions): Promise<SponsorStatus>;
28
+ }
29
+ declare class KeysResource {
30
+ private readonly client;
31
+ constructor(client: Unbrowse);
32
+ list(opts?: RequestOptions): Promise<ApiKeyListResponse>;
33
+ create(input?: ApiKeyCreateInput, opts?: RequestOptions): Promise<ApiKeyCreateResponse>;
34
+ revoke(keyId: string, opts?: RequestOptions): Promise<ApiKeyRevokeResponse>;
35
+ rotate(keyId: string, opts?: RequestOptions): Promise<ApiKeyCreateResponse>;
36
+ }
37
+ declare class ProxyResource {
38
+ private readonly client;
39
+ constructor(client: Unbrowse);
40
+ fetch(req: WorkerProxyRequest, opts?: RequestOptions): Promise<WorkerProxyResponse>;
41
+ capabilities(opts?: RequestOptions): Promise<WorkerProxyCapabilities>;
42
+ }
43
+ export {};
@@ -0,0 +1,256 @@
1
+ import { errorFromStatus, UnbrowseConnectionError, UnbrowseError, UnbrowseTimeoutError, } from "./errors.js";
2
+ const DEFAULT_BASE_URL = "https://beta-api.unbrowse.ai";
3
+ const DEFAULT_TIMEOUT_MS = 60_000;
4
+ const DEFAULT_MAX_RETRIES = 2;
5
+ const SDK_VERSION = "7.0.0-preview.1";
6
+ export class Unbrowse {
7
+ apiKey;
8
+ baseURL;
9
+ timeout;
10
+ maxRetries;
11
+ logLevel;
12
+ _fetch;
13
+ defaultHeaders;
14
+ account;
15
+ keys;
16
+ proxy;
17
+ constructor(opts = {}) {
18
+ const env = readEnv();
19
+ this.apiKey = opts.apiKey ?? env.UNBROWSE_API_KEY;
20
+ this.baseURL = stripTrailingSlash(opts.baseURL ?? env.UNBROWSE_BASE_URL ?? DEFAULT_BASE_URL);
21
+ this.timeout = opts.timeout ?? DEFAULT_TIMEOUT_MS;
22
+ this.maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES;
23
+ this.logLevel = opts.logLevel ?? env.UNBROWSE_LOG ?? "off";
24
+ this.defaultHeaders = opts.defaultHeaders ?? {};
25
+ const f = opts.fetch ?? globalThis.fetch;
26
+ if (typeof f !== "function") {
27
+ throw new UnbrowseError("No fetch implementation available. Pass `fetch` in client options or run on Node 18+ / a modern browser.");
28
+ }
29
+ this._fetch = f.bind(globalThis);
30
+ this.account = new AccountResource(this);
31
+ this.keys = new KeysResource(this);
32
+ this.proxy = new ProxyResource(this);
33
+ }
34
+ resolve(input, opts = {}) {
35
+ return this.request("POST", "/v1/resolve", input, opts);
36
+ }
37
+ execute(input, opts = {}) {
38
+ // Auto-idempotency on execute so a network-retry never double-charges the agent.
39
+ const idempotencyKey = input.idempotency_key ?? opts.idempotencyKey ?? randomIdempotencyKey();
40
+ return this.request("POST", "/v1/execute", input, { ...opts, idempotencyKey });
41
+ }
42
+ search(input, opts = {}) {
43
+ return this.request("POST", "/v1/search", input, opts);
44
+ }
45
+ health(opts = {}) {
46
+ return this.request("GET", "/v1/health", undefined, opts);
47
+ }
48
+ // Internal request driver. Public so the resource classes can call it; not part
49
+ // of the documented surface.
50
+ async request(method, path, body, opts) {
51
+ const url = `${this.baseURL}${path}`;
52
+ const headers = {
53
+ "Accept": "application/json",
54
+ "User-Agent": `@unbrowse/sdk/${SDK_VERSION}`,
55
+ ...this.defaultHeaders,
56
+ ...(opts.headers ?? {}),
57
+ };
58
+ if (this.apiKey)
59
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
60
+ if (body !== undefined && method !== "GET")
61
+ headers["Content-Type"] = "application/json";
62
+ if (opts.idempotencyKey)
63
+ headers["Idempotency-Key"] = opts.idempotencyKey;
64
+ const maxRetries = opts.maxRetries ?? this.maxRetries;
65
+ const timeoutMs = opts.timeout ?? this.timeout;
66
+ let lastErr;
67
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
68
+ const ctrl = new AbortController();
69
+ const t = setTimeout(() => ctrl.abort(), timeoutMs);
70
+ const signal = combineSignals(ctrl.signal, opts.signal);
71
+ try {
72
+ const response = await this._fetch(url, {
73
+ method,
74
+ headers,
75
+ body: body !== undefined && method !== "GET" ? JSON.stringify(body) : undefined,
76
+ signal,
77
+ });
78
+ clearTimeout(t);
79
+ const request_id = response.headers.get("x-request-id") ?? undefined;
80
+ const responseBody = await parseBody(response);
81
+ if (response.ok) {
82
+ this.debug(`${method} ${path} ${response.status} req=${request_id ?? "-"} attempt=${attempt}`);
83
+ if (responseBody && typeof responseBody === "object" && !Array.isArray(responseBody)) {
84
+ responseBody._request_id = request_id;
85
+ }
86
+ return responseBody;
87
+ }
88
+ const retryAfter = parseRetryAfter(response.headers.get("retry-after"));
89
+ const err = errorFromStatus({
90
+ status: response.status,
91
+ body: responseBody,
92
+ request_id,
93
+ url,
94
+ method,
95
+ retry_after_ms: retryAfter,
96
+ });
97
+ if (shouldRetry(response.status, attempt, maxRetries)) {
98
+ lastErr = err;
99
+ const delay = retryAfter ?? backoffDelay(attempt);
100
+ this.debug(`${method} ${path} ${response.status} retry-in=${delay}ms attempt=${attempt}`);
101
+ await sleep(delay);
102
+ continue;
103
+ }
104
+ throw err;
105
+ }
106
+ catch (e) {
107
+ clearTimeout(t);
108
+ if (e instanceof UnbrowseError)
109
+ throw e;
110
+ const isAbort = e?.name === "AbortError";
111
+ const wrapped = isAbort
112
+ ? new UnbrowseTimeoutError(`Request timed out after ${timeoutMs}ms`, e)
113
+ : new UnbrowseConnectionError(`Network error: ${e?.message ?? String(e)}`, e);
114
+ if (attempt < maxRetries) {
115
+ lastErr = wrapped;
116
+ const delay = backoffDelay(attempt);
117
+ this.debug(`${method} ${path} network-error retry-in=${delay}ms attempt=${attempt}`);
118
+ await sleep(delay);
119
+ continue;
120
+ }
121
+ throw wrapped;
122
+ }
123
+ }
124
+ throw lastErr ?? new UnbrowseError("Retries exhausted");
125
+ }
126
+ debug(line) {
127
+ if (this.logLevel === "debug" || this.logLevel === "info") {
128
+ // eslint-disable-next-line no-console
129
+ console.log(`[unbrowse] ${line}`);
130
+ }
131
+ }
132
+ }
133
+ class AccountResource {
134
+ client;
135
+ constructor(client) {
136
+ this.client = client;
137
+ }
138
+ me(opts = {}) {
139
+ return this.client.request("GET", "/v1/account/me", undefined, opts);
140
+ }
141
+ credits(opts = {}) {
142
+ return this.client.request("GET", "/v1/account/credits", undefined, opts);
143
+ }
144
+ sponsorStatus(opts = {}) {
145
+ return this.client.request("GET", "/v1/account/sponsor-status", undefined, opts);
146
+ }
147
+ }
148
+ class KeysResource {
149
+ client;
150
+ constructor(client) {
151
+ this.client = client;
152
+ }
153
+ list(opts = {}) {
154
+ return this.client.request("GET", "/v1/account/keys", undefined, opts);
155
+ }
156
+ create(input = {}, opts = {}) {
157
+ return this.client.request("POST", "/v1/account/keys", input, opts);
158
+ }
159
+ revoke(keyId, opts = {}) {
160
+ return this.client.request("DELETE", `/v1/account/keys/${encodeURIComponent(keyId)}`, undefined, opts);
161
+ }
162
+ rotate(keyId, opts = {}) {
163
+ return this.client.request("POST", `/v1/account/keys/${encodeURIComponent(keyId)}/rotate`, undefined, opts);
164
+ }
165
+ }
166
+ class ProxyResource {
167
+ client;
168
+ constructor(client) {
169
+ this.client = client;
170
+ }
171
+ // POST /v1/proxy — worker fetches the target URL on behalf of the agent.
172
+ // Use this when the SDK runs in a browser/edge where direct outbound fetches
173
+ // would expose the user IP, get geo-fenced, or hit anti-bot. Pass
174
+ // proxy:"residential" to tunnel the worker's outbound fetch through a residential proxy.
175
+ fetch(req, opts = {}) {
176
+ return this.client.request("POST", "/v1/proxy", req, opts);
177
+ }
178
+ // GET /v1/proxy — capability check. Use to decide whether to request
179
+ // proxy:"residential" before committing to the call. Reports whether
180
+ // the worker's residential proxy credentials are configured.
181
+ capabilities(opts = {}) {
182
+ return this.client.request("GET", "/v1/proxy", undefined, opts);
183
+ }
184
+ }
185
+ // ---------- helpers ----------
186
+ function readEnv() {
187
+ if (typeof process !== "undefined" && process.env)
188
+ return process.env;
189
+ return {};
190
+ }
191
+ function stripTrailingSlash(s) {
192
+ return s.endsWith("/") ? s.slice(0, -1) : s;
193
+ }
194
+ async function parseBody(response) {
195
+ const ct = response.headers.get("content-type") ?? "";
196
+ if (ct.includes("application/json")) {
197
+ try {
198
+ return await response.json();
199
+ }
200
+ catch {
201
+ return null;
202
+ }
203
+ }
204
+ const text = await response.text().catch(() => "");
205
+ return text || null;
206
+ }
207
+ function parseRetryAfter(h) {
208
+ if (!h)
209
+ return undefined;
210
+ const n = Number(h);
211
+ if (Number.isFinite(n))
212
+ return n * 1000;
213
+ const t = Date.parse(h);
214
+ if (Number.isFinite(t))
215
+ return Math.max(0, t - Date.now());
216
+ return undefined;
217
+ }
218
+ function shouldRetry(status, attempt, max) {
219
+ if (attempt >= max)
220
+ return false;
221
+ return status === 429 || status === 408 || status === 409 || status >= 500;
222
+ }
223
+ function backoffDelay(attempt) {
224
+ // exponential backoff with full jitter; 250ms, 500ms, 1s, 2s, ... capped at 8s
225
+ const base = Math.min(8_000, 250 * Math.pow(2, attempt));
226
+ return Math.floor(Math.random() * base);
227
+ }
228
+ function sleep(ms) {
229
+ return new Promise((r) => setTimeout(r, ms));
230
+ }
231
+ function randomIdempotencyKey() {
232
+ // RFC 4122 v4-ish. Good enough for idempotency; not used for security.
233
+ if (typeof crypto !== "undefined" && "randomUUID" in crypto)
234
+ return crypto.randomUUID();
235
+ const hex = "0123456789abcdef";
236
+ let out = "";
237
+ for (let i = 0; i < 32; i++) {
238
+ out += hex[Math.floor(Math.random() * 16)];
239
+ if (i === 7 || i === 11 || i === 15 || i === 19)
240
+ out += "-";
241
+ }
242
+ return out;
243
+ }
244
+ function combineSignals(a, b) {
245
+ if (!b)
246
+ return a;
247
+ if (a.aborted)
248
+ return a;
249
+ if (b.aborted)
250
+ return b;
251
+ const ctrl = new AbortController();
252
+ const onAbort = () => ctrl.abort();
253
+ a.addEventListener("abort", onAbort, { once: true });
254
+ b.addEventListener("abort", onAbort, { once: true });
255
+ return ctrl.signal;
256
+ }
@@ -0,0 +1,52 @@
1
+ export declare class UnbrowseError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export interface UnbrowseAPIErrorOptions {
5
+ status: number;
6
+ body: unknown;
7
+ request_id?: string;
8
+ url: string;
9
+ method: string;
10
+ }
11
+ export declare class UnbrowseAPIError extends UnbrowseError {
12
+ readonly status: number;
13
+ readonly body: unknown;
14
+ readonly request_id: string | undefined;
15
+ readonly url: string;
16
+ readonly method: string;
17
+ constructor(message: string, opts: UnbrowseAPIErrorOptions);
18
+ }
19
+ export declare class UnbrowseAuthenticationError extends UnbrowseAPIError {
20
+ constructor(message: string, opts: UnbrowseAPIErrorOptions);
21
+ }
22
+ export declare class UnbrowsePaymentRequiredError extends UnbrowseAPIError {
23
+ constructor(message: string, opts: UnbrowseAPIErrorOptions);
24
+ }
25
+ export declare class UnbrowsePermissionError extends UnbrowseAPIError {
26
+ constructor(message: string, opts: UnbrowseAPIErrorOptions);
27
+ }
28
+ export declare class UnbrowseNotFoundError extends UnbrowseAPIError {
29
+ constructor(message: string, opts: UnbrowseAPIErrorOptions);
30
+ }
31
+ export declare class UnbrowseBadRequestError extends UnbrowseAPIError {
32
+ constructor(message: string, opts: UnbrowseAPIErrorOptions);
33
+ }
34
+ export declare class UnbrowseRateLimitError extends UnbrowseAPIError {
35
+ readonly retry_after_ms: number | undefined;
36
+ constructor(message: string, opts: UnbrowseAPIErrorOptions & {
37
+ retry_after_ms?: number;
38
+ });
39
+ }
40
+ export declare class UnbrowseServerError extends UnbrowseAPIError {
41
+ constructor(message: string, opts: UnbrowseAPIErrorOptions);
42
+ }
43
+ export declare class UnbrowseConnectionError extends UnbrowseError {
44
+ readonly cause: unknown;
45
+ constructor(message: string, cause: unknown);
46
+ }
47
+ export declare class UnbrowseTimeoutError extends UnbrowseConnectionError {
48
+ constructor(message: string, cause: unknown);
49
+ }
50
+ export declare function errorFromStatus(opts: UnbrowseAPIErrorOptions & {
51
+ retry_after_ms?: number;
52
+ }): UnbrowseAPIError;
@@ -0,0 +1,116 @@
1
+ // Typed error hierarchy. Mirrors OpenAI / Stripe conventions so `instanceof`
2
+ // checks read naturally for calling agents. Every error carries the request_id
3
+ // when the server returned one, so users can paste it into support.
4
+ export class UnbrowseError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "UnbrowseError";
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
11
+ export class UnbrowseAPIError extends UnbrowseError {
12
+ status;
13
+ body;
14
+ request_id;
15
+ url;
16
+ method;
17
+ constructor(message, opts) {
18
+ super(message);
19
+ this.name = "UnbrowseAPIError";
20
+ this.status = opts.status;
21
+ this.body = opts.body;
22
+ this.request_id = opts.request_id;
23
+ this.url = opts.url;
24
+ this.method = opts.method;
25
+ }
26
+ }
27
+ export class UnbrowseAuthenticationError extends UnbrowseAPIError {
28
+ constructor(message, opts) {
29
+ super(message, opts);
30
+ this.name = "UnbrowseAuthenticationError";
31
+ }
32
+ }
33
+ export class UnbrowsePaymentRequiredError extends UnbrowseAPIError {
34
+ // 402 — surfaces x402 sponsor exhaustion / wallet top-up requirement.
35
+ // body is the x402 payment requirements object the server returned.
36
+ constructor(message, opts) {
37
+ super(message, opts);
38
+ this.name = "UnbrowsePaymentRequiredError";
39
+ }
40
+ }
41
+ export class UnbrowsePermissionError extends UnbrowseAPIError {
42
+ constructor(message, opts) {
43
+ super(message, opts);
44
+ this.name = "UnbrowsePermissionError";
45
+ }
46
+ }
47
+ export class UnbrowseNotFoundError extends UnbrowseAPIError {
48
+ constructor(message, opts) {
49
+ super(message, opts);
50
+ this.name = "UnbrowseNotFoundError";
51
+ }
52
+ }
53
+ export class UnbrowseBadRequestError extends UnbrowseAPIError {
54
+ constructor(message, opts) {
55
+ super(message, opts);
56
+ this.name = "UnbrowseBadRequestError";
57
+ }
58
+ }
59
+ export class UnbrowseRateLimitError extends UnbrowseAPIError {
60
+ retry_after_ms;
61
+ constructor(message, opts) {
62
+ super(message, opts);
63
+ this.name = "UnbrowseRateLimitError";
64
+ this.retry_after_ms = opts.retry_after_ms;
65
+ }
66
+ }
67
+ export class UnbrowseServerError extends UnbrowseAPIError {
68
+ constructor(message, opts) {
69
+ super(message, opts);
70
+ this.name = "UnbrowseServerError";
71
+ }
72
+ }
73
+ export class UnbrowseConnectionError extends UnbrowseError {
74
+ cause;
75
+ constructor(message, cause) {
76
+ super(message);
77
+ this.name = "UnbrowseConnectionError";
78
+ this.cause = cause;
79
+ }
80
+ }
81
+ export class UnbrowseTimeoutError extends UnbrowseConnectionError {
82
+ constructor(message, cause) {
83
+ super(message, cause);
84
+ this.name = "UnbrowseTimeoutError";
85
+ }
86
+ }
87
+ export function errorFromStatus(opts) {
88
+ const msg = extractMessage(opts.body) ?? `HTTP ${opts.status} from ${opts.method} ${opts.url}`;
89
+ switch (opts.status) {
90
+ case 400: return new UnbrowseBadRequestError(msg, opts);
91
+ case 401: return new UnbrowseAuthenticationError(msg, opts);
92
+ case 402: return new UnbrowsePaymentRequiredError(msg, opts);
93
+ case 403: return new UnbrowsePermissionError(msg, opts);
94
+ case 404: return new UnbrowseNotFoundError(msg, opts);
95
+ case 429: return new UnbrowseRateLimitError(msg, opts);
96
+ }
97
+ if (opts.status >= 500)
98
+ return new UnbrowseServerError(msg, opts);
99
+ return new UnbrowseAPIError(msg, opts);
100
+ }
101
+ function extractMessage(body) {
102
+ if (!body || typeof body !== "object")
103
+ return undefined;
104
+ const b = body;
105
+ if (typeof b.error === "string")
106
+ return b.error;
107
+ if (typeof b.message === "string")
108
+ return b.message;
109
+ const inner = b.error;
110
+ if (inner && typeof inner === "object" && "message" in inner) {
111
+ const m = inner.message;
112
+ if (typeof m === "string")
113
+ return m;
114
+ }
115
+ return undefined;
116
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * A drop-in replacement for the global `fetch`, with optional, opt-in payment.
3
+ *
4
+ * Default behaviour is identical to native fetch — zero config, zero
5
+ * dependencies, no API key:
6
+ *
7
+ * import { unfetch } from "@unbrowse/client";
8
+ * const res = await unfetch("https://example.com"); // just works
9
+ *
10
+ * Opt-in payment: pass a `pay` handler to transparently satisfy an HTTP 402
11
+ * response. The handler is where any payment mechanism lives — a subscription /
12
+ * credit balance, an embedded-wallet signer, or an on-chain micropayment — and
13
+ * it is *injected*, never imported, so this module stays dependency-free. When
14
+ * no handler is configured a 402 is returned to the caller unchanged, exactly
15
+ * like native fetch.
16
+ *
17
+ * In other words: paying is a capability this client can use, not a path it
18
+ * forces. The 402 mechanism is an implementation detail behind the handler, not
19
+ * the front door.
20
+ */
21
+ /** The standard fetch signature, re-exported as a type for handler authors. */
22
+ export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
23
+ /**
24
+ * Context handed to a {@link PayHandler} when a request comes back `402 Payment
25
+ * Required`. The handler inspects it and decides whether (and how) to pay.
26
+ */
27
+ export interface PaymentRequired {
28
+ /** The 402 response, unconsumed — read `.clone()` if you need the body. */
29
+ readonly response: Response;
30
+ /** The original request that triggered the 402, for re-issue after payment. */
31
+ readonly request: {
32
+ input: string | URL | Request;
33
+ init?: RequestInit;
34
+ };
35
+ /**
36
+ * Parsed payment terms when the server advertises them. We surface the common
37
+ * shapes (an `accepts` array, or `x402`/`flex` envelopes) without prescribing
38
+ * one — the handler owns the protocol. `null` when the body is not JSON.
39
+ */
40
+ readonly terms: Record<string, unknown> | null;
41
+ }
42
+ /**
43
+ * Resolves a 402. Return the headers to merge into a single retry of the
44
+ * original request (e.g. `{ "X-PAYMENT": "..." }` or an `Authorization` token),
45
+ * or `null` to decline — in which case the original 402 is returned unchanged.
46
+ */
47
+ export type PayHandler = (ctx: PaymentRequired) => Promise<HeadersInit | null>;
48
+ export interface CreateFetchOptions {
49
+ /** The transport to wrap. Defaults to the platform `fetch`. */
50
+ fetch?: FetchLike;
51
+ /**
52
+ * Optional payment handler. When omitted, the returned fetch is a pure
53
+ * pass-through and a 402 is never intercepted.
54
+ */
55
+ pay?: PayHandler;
56
+ }
57
+ /**
58
+ * Build a `fetch`-shaped function. With no options it is the platform fetch.
59
+ * With a `pay` handler it transparently retries a single 402 once the handler
60
+ * supplies payment headers.
61
+ */
62
+ export declare function createFetch(options?: CreateFetchOptions): FetchLike;
63
+ /**
64
+ * The keyless, dependency-free default: a `fetch` drop-in with no payment
65
+ * handler. Identical to the platform fetch; exported so callers can swap
66
+ * `fetch` → `unfetch` with no behavioural change and wire payment later.
67
+ */
68
+ export declare const unfetch: FetchLike;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * A drop-in replacement for the global `fetch`, with optional, opt-in payment.
3
+ *
4
+ * Default behaviour is identical to native fetch — zero config, zero
5
+ * dependencies, no API key:
6
+ *
7
+ * import { unfetch } from "@unbrowse/client";
8
+ * const res = await unfetch("https://example.com"); // just works
9
+ *
10
+ * Opt-in payment: pass a `pay` handler to transparently satisfy an HTTP 402
11
+ * response. The handler is where any payment mechanism lives — a subscription /
12
+ * credit balance, an embedded-wallet signer, or an on-chain micropayment — and
13
+ * it is *injected*, never imported, so this module stays dependency-free. When
14
+ * no handler is configured a 402 is returned to the caller unchanged, exactly
15
+ * like native fetch.
16
+ *
17
+ * In other words: paying is a capability this client can use, not a path it
18
+ * forces. The 402 mechanism is an implementation detail behind the handler, not
19
+ * the front door.
20
+ */
21
+ /**
22
+ * Build a `fetch`-shaped function. With no options it is the platform fetch.
23
+ * With a `pay` handler it transparently retries a single 402 once the handler
24
+ * supplies payment headers.
25
+ */
26
+ export function createFetch(options = {}) {
27
+ const base = options.fetch ?? globalThis.fetch;
28
+ if (typeof base !== "function") {
29
+ throw new Error("No fetch implementation available. Pass `fetch` in options or run on Node 18+ / a modern browser.");
30
+ }
31
+ const transport = base.bind(globalThis);
32
+ const pay = options.pay;
33
+ // No payment handler → an exact pass-through. This is the zero-config default.
34
+ if (!pay)
35
+ return transport;
36
+ return async function unbrowseFetch(input, init) {
37
+ const res = await transport(input, init);
38
+ if (res.status !== 402)
39
+ return res;
40
+ const terms = await readJsonSafe(res.clone());
41
+ const extra = await pay({ response: res, request: { input, init }, terms });
42
+ if (!extra)
43
+ return res; // handler declined — behave like native fetch.
44
+ // Single retry with the handler's payment headers merged in. One retry only:
45
+ // a payment that does not satisfy the route must surface, not loop.
46
+ const headers = new Headers(init?.headers);
47
+ new Headers(extra).forEach((value, key) => headers.set(key, value));
48
+ return transport(input, { ...init, headers });
49
+ };
50
+ }
51
+ /**
52
+ * The keyless, dependency-free default: a `fetch` drop-in with no payment
53
+ * handler. Identical to the platform fetch; exported so callers can swap
54
+ * `fetch` → `unfetch` with no behavioural change and wire payment later.
55
+ */
56
+ export const unfetch = createFetch();
57
+ async function readJsonSafe(res) {
58
+ const ct = res.headers.get("content-type") ?? "";
59
+ if (!ct.includes("json"))
60
+ return null;
61
+ try {
62
+ const body = await res.json();
63
+ return body && typeof body === "object" && !Array.isArray(body)
64
+ ? body
65
+ : null;
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
@@ -0,0 +1,6 @@
1
+ export { Unbrowse } from "./client.js";
2
+ export { createFetch, unfetch } from "./fetch.js";
3
+ export type { CreateFetchOptions, FetchLike, PayHandler, PaymentRequired, } from "./fetch.js";
4
+ export { UnbrowseError, UnbrowseAPIError, UnbrowseAuthenticationError, UnbrowsePaymentRequiredError, UnbrowsePermissionError, UnbrowseNotFoundError, UnbrowseBadRequestError, UnbrowseRateLimitError, UnbrowseServerError, UnbrowseConnectionError, UnbrowseTimeoutError, } from "./errors.js";
5
+ export type { AccountMe, AccountCredits, ApiKey, ApiKeyCreateInput, ApiKeyCreateResponse, ApiKeyFunding, ApiKeyListResponse, ApiKeyRevokeResponse, AvailableEndpoint, ExecuteInput, ExecuteResponse, HealthResponse, RequestOptions, ResolveInput, ResolveResponse, SearchHit, SearchInput, SearchResponse, SponsorStatus, UnbrowseClientOptions, } from "./types.js";
6
+ export type { WorkerProxyCapabilities, WorkerProxyRequest, WorkerProxyResponse, } from "./proxy-types.js";
@@ -0,0 +1,3 @@
1
+ export { Unbrowse } from "./client.js";
2
+ export { createFetch, unfetch } from "./fetch.js";
3
+ export { UnbrowseError, UnbrowseAPIError, UnbrowseAuthenticationError, UnbrowsePaymentRequiredError, UnbrowsePermissionError, UnbrowseNotFoundError, UnbrowseBadRequestError, UnbrowseRateLimitError, UnbrowseServerError, UnbrowseConnectionError, UnbrowseTimeoutError, } from "./errors.js";
@@ -0,0 +1,24 @@
1
+ export interface WorkerProxyResponse {
2
+ status: number;
3
+ headers: Record<string, string>;
4
+ body: string;
5
+ proxy_used: "direct" | "residential";
6
+ duration_ms: number;
7
+ egress_ip?: string;
8
+ _request_id?: string;
9
+ }
10
+ export interface WorkerProxyRequest {
11
+ url: string;
12
+ method?: string;
13
+ headers?: Record<string, string>;
14
+ body?: string | null;
15
+ proxy?: "direct" | "residential";
16
+ timeout_ms?: number;
17
+ }
18
+ export interface WorkerProxyCapabilities {
19
+ modes: Array<"direct" | "residential">;
20
+ residential_configured: boolean;
21
+ max_body_bytes: number;
22
+ default_timeout_ms: number;
23
+ _request_id?: string;
24
+ }
@@ -0,0 +1,2 @@
1
+ // Shape of POST /v1/proxy responses on the worker.
2
+ export {};
@@ -0,0 +1,146 @@
1
+ export interface ResolveInput {
2
+ intent: string;
3
+ contextUrl?: string;
4
+ domain?: string;
5
+ limit?: number;
6
+ }
7
+ export interface AvailableEndpoint {
8
+ endpoint_id: string;
9
+ skill_id: string;
10
+ url: string;
11
+ method: string;
12
+ description?: string;
13
+ score?: number;
14
+ schema?: unknown;
15
+ requires?: string[];
16
+ yields?: string[];
17
+ action_kind?: string;
18
+ sample_values?: Record<string, unknown>;
19
+ }
20
+ export interface ResolveResponse {
21
+ status: "ok" | "empty" | "browse_session_open" | "auth_required" | "no_cached_match";
22
+ available_operations?: AvailableEndpoint[];
23
+ available_endpoints?: AvailableEndpoint[];
24
+ next_step?: string;
25
+ suggested_commands?: string[];
26
+ request_id?: string;
27
+ _request_id?: string;
28
+ }
29
+ export interface ExecuteInput {
30
+ endpoint_id?: string;
31
+ url?: string;
32
+ method?: string;
33
+ params?: Record<string, unknown>;
34
+ body?: unknown;
35
+ raw?: boolean;
36
+ extract?: string;
37
+ limit?: number;
38
+ idempotency_key?: string;
39
+ transport?: "worker-proxy" | "direct";
40
+ proxy?: "direct" | "residential";
41
+ }
42
+ export interface ExecuteResponse {
43
+ success: boolean;
44
+ status_code?: number;
45
+ data?: unknown;
46
+ raw?: unknown;
47
+ endpoint_id?: string;
48
+ trace?: unknown;
49
+ request_id?: string;
50
+ _request_id?: string;
51
+ }
52
+ export interface SearchInput {
53
+ intent: string;
54
+ domain?: string;
55
+ limit?: number;
56
+ }
57
+ export interface SearchHit {
58
+ endpoint_id: string;
59
+ skill_id: string;
60
+ url: string;
61
+ score: number;
62
+ snippet?: string;
63
+ }
64
+ export interface SearchResponse {
65
+ hits: SearchHit[];
66
+ _request_id?: string;
67
+ }
68
+ export interface HealthResponse {
69
+ status: "ok" | "degraded";
70
+ version?: string;
71
+ uptime_s?: number;
72
+ _request_id?: string;
73
+ }
74
+ export interface AccountMe {
75
+ user_id: string;
76
+ email: string;
77
+ email_verified: boolean;
78
+ created_at: string;
79
+ _request_id?: string;
80
+ }
81
+ export interface AccountCredits {
82
+ user_id: string;
83
+ balance_usd: number;
84
+ used_usd: number;
85
+ granted_usd: number;
86
+ _request_id?: string;
87
+ }
88
+ export interface SponsorStatus {
89
+ agent_id: string;
90
+ date: string;
91
+ agent_remaining_usd: number;
92
+ agent_cap_usd: number;
93
+ global_remaining_usd: number;
94
+ global_cap_usd: number;
95
+ _request_id?: string;
96
+ }
97
+ export interface ApiKey {
98
+ keyId: string;
99
+ name: string;
100
+ created_at: string | null;
101
+ revoked_at: string | null;
102
+ funding: ApiKeyFunding | null;
103
+ }
104
+ export interface ApiKeyFunding {
105
+ wallet_address?: string;
106
+ credit_budget_usd?: number;
107
+ bound_at?: string;
108
+ }
109
+ export interface ApiKeyCreateInput {
110
+ name?: string;
111
+ }
112
+ export interface ApiKeyCreateResponse {
113
+ keyId: string;
114
+ key: string;
115
+ name: string;
116
+ created_at: string;
117
+ message: string;
118
+ rotated_from?: string;
119
+ _request_id?: string;
120
+ }
121
+ export interface ApiKeyListResponse {
122
+ keys: ApiKey[];
123
+ _request_id?: string;
124
+ }
125
+ export interface ApiKeyRevokeResponse {
126
+ ok: true;
127
+ keyId: string;
128
+ revoked: true;
129
+ _request_id?: string;
130
+ }
131
+ export interface UnbrowseClientOptions {
132
+ apiKey?: string;
133
+ baseURL?: string;
134
+ timeout?: number;
135
+ maxRetries?: number;
136
+ fetch?: typeof globalThis.fetch;
137
+ defaultHeaders?: Record<string, string>;
138
+ logLevel?: "off" | "error" | "warn" | "info" | "debug";
139
+ }
140
+ export interface RequestOptions {
141
+ timeout?: number;
142
+ maxRetries?: number;
143
+ idempotencyKey?: string;
144
+ signal?: AbortSignal;
145
+ headers?: Record<string, string>;
146
+ }
@@ -0,0 +1,5 @@
1
+ // Minimal local types for sdk v7. Mirrors backend response shapes from
2
+ // backend/src/routes/{resolve,execute,search,health,account}.ts. Kept local
3
+ // (not re-exported from packages/sdk) so v7 can ship without depending on the
4
+ // legacy package; the legacy package will be deprecated in favor of this one.
5
+ export {};
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Wallet Standard (open-wallet-standard / `@wallet-standard`) bridge for the
3
+ * Unbrowse SDK — turns ANY Wallet Standard wallet (Phantom, Solflare, Backpack,
4
+ * a Privy embedded Solana wallet, lobster.cash, …) into a {@link PayHandler}
5
+ * that transparently satisfies an HTTP 402 over x402.
6
+ *
7
+ * Dependency-free by design: this module describes the *minimal* Wallet Standard
8
+ * shapes it consumes structurally — it does NOT import `@wallet-standard/*`, so
9
+ * the shipped SDK stays zero-dep and browser-safe. Pass any object that
10
+ * conforms (the real `@wallet-standard` `Wallet` does) and it just works.
11
+ *
12
+ * Delegation boundary: this bridge prepares the payment *intent* (the bytes to
13
+ * sign) and hands signing to the wallet. The wallet owns provisioning, approval,
14
+ * signing, and broadcast — we never touch keys. Web2 users who "just want to pay
15
+ * via API" can opt into {@link makeUnbrowseWallet}, an optional default wallet
16
+ * that delegates signing to the Unbrowse server via an API key.
17
+ */
18
+ import type { PayHandler, PaymentRequired } from "./fetch.js";
19
+ export type Bytes = Uint8Array;
20
+ export interface WsAccount {
21
+ readonly address: string;
22
+ readonly publicKey: Bytes;
23
+ readonly chains: readonly string[];
24
+ readonly features: readonly string[];
25
+ readonly label?: string;
26
+ }
27
+ export interface WsConnectFeature {
28
+ connect(input?: {
29
+ silent?: boolean;
30
+ }): Promise<{
31
+ accounts: readonly WsAccount[];
32
+ }>;
33
+ }
34
+ export interface WsSignMessageFeature {
35
+ signMessage(input: {
36
+ account: WsAccount;
37
+ message: Bytes;
38
+ }): Promise<ReadonlyArray<{
39
+ signedMessage: Bytes;
40
+ signature: Bytes;
41
+ }>>;
42
+ }
43
+ /** The subset of a Wallet Standard `Wallet` this bridge uses. */
44
+ export interface WsWallet {
45
+ readonly version: string;
46
+ readonly name: string;
47
+ readonly icon?: string;
48
+ readonly chains: readonly string[];
49
+ readonly accounts: readonly WsAccount[];
50
+ readonly features: Record<string, unknown> & {
51
+ "standard:connect"?: WsConnectFeature;
52
+ "solana:signMessage"?: WsSignMessageFeature;
53
+ };
54
+ }
55
+ /** Wallets that can connect + sign a Solana message (what x402 over Solana needs). */
56
+ export declare function pickSolanaWallets(wallets: readonly WsWallet[]): WsWallet[];
57
+ /**
58
+ * The bytes a wallet signs for an x402 payment. The server advertises the
59
+ * challenge in the 402 `terms` (an `accepts`/`flex`/`x402` envelope); we surface
60
+ * the common shapes and sign the canonical challenge string. The exact on-wire
61
+ * payload assembly is owned by the x402 facilitator the server names — this
62
+ * produces the message to authorize.
63
+ */
64
+ export declare function paymentMessage(terms: PaymentRequired["terms"]): Bytes;
65
+ export interface WalletStandardPayOptions {
66
+ /** Which account to pay from (defaults to the wallet's first account). */
67
+ account?: WsAccount;
68
+ /** Header name the server expects (default `X-PAYMENT`, the x402 standard). */
69
+ header?: string;
70
+ }
71
+ /**
72
+ * Build a {@link PayHandler} from any Wallet Standard wallet. On a 402 it asks
73
+ * the wallet to sign the payment challenge and returns the `X-PAYMENT` header
74
+ * for a single retry. Returns `null` (declines) if the wallet cannot sign — the
75
+ * caller then sees the original 402, never a thrown error.
76
+ *
77
+ * import { Unbrowse } from "unbrowse/sdk";
78
+ * import { walletStandardPay } from "unbrowse/sdk/wallet-standard";
79
+ * const pay = walletStandardPay(myWallet);
80
+ * const unbrowse = new Unbrowse({ apiKey, pay });
81
+ */
82
+ export declare function walletStandardPay(wallet: WsWallet, opts?: WalletStandardPayOptions): PayHandler;
83
+ export interface UnbrowseWalletOptions {
84
+ /** Required to opt in — signing is delegated to the Unbrowse server. */
85
+ apiKey: string;
86
+ /** The agent's Solana address (base58) the server signs for. */
87
+ address: string;
88
+ /** The agent's public key bytes. */
89
+ publicKey: Bytes;
90
+ /** Server base URL (defaults to the hosted Unbrowse API). */
91
+ baseUrl?: string;
92
+ /** Injected fetch (defaults to platform fetch); keeps this testable + zero-dep. */
93
+ fetch?: typeof fetch;
94
+ }
95
+ /**
96
+ * An OPTIONAL default wallet for users who don't want to run their own wallet —
97
+ * a Wallet Standard `Wallet` whose signing is delegated to the Unbrowse server
98
+ * (authorized by an API key). It is opt-in: you must pass an `apiKey`. Register
99
+ * it with `@wallet-standard/wallet`'s `registerWallet()` to expose it to any
100
+ * Wallet Standard consumer (including the Unbrowse frontend).
101
+ *
102
+ * Web2-native: the user "just wants to pay via API" — no seed phrase, no
103
+ * extension. The server (or lobster.cash, or any other wallet) remains the
104
+ * transaction-state authority; this is a thin convenience default, never forced.
105
+ */
106
+ export declare function makeUnbrowseWallet(opts: UnbrowseWalletOptions): WsWallet;
@@ -0,0 +1,128 @@
1
+ const SOLANA = "solana:";
2
+ const F_CONNECT = "standard:connect";
3
+ const F_SIGN_MESSAGE = "solana:signMessage";
4
+ /** Wallets that can connect + sign a Solana message (what x402 over Solana needs). */
5
+ export function pickSolanaWallets(wallets) {
6
+ return wallets.filter((w) => w.chains.some((c) => c.startsWith(SOLANA)) &&
7
+ F_SIGN_MESSAGE in w.features);
8
+ }
9
+ function toBase64(bytes) {
10
+ // browser + node, no deps
11
+ if (typeof btoa === "function") {
12
+ let s = "";
13
+ for (const b of bytes)
14
+ s += String.fromCharCode(b);
15
+ return btoa(s);
16
+ }
17
+ // @ts-ignore Buffer exists in node
18
+ return Buffer.from(bytes).toString("base64");
19
+ }
20
+ /**
21
+ * The bytes a wallet signs for an x402 payment. The server advertises the
22
+ * challenge in the 402 `terms` (an `accepts`/`flex`/`x402` envelope); we surface
23
+ * the common shapes and sign the canonical challenge string. The exact on-wire
24
+ * payload assembly is owned by the x402 facilitator the server names — this
25
+ * produces the message to authorize.
26
+ */
27
+ export function paymentMessage(terms) {
28
+ let challenge = "";
29
+ if (terms && typeof terms === "object") {
30
+ const t = terms;
31
+ const accepts = Array.isArray(t.accepts) ? t.accepts[0] : undefined;
32
+ challenge =
33
+ (typeof t.challenge === "string" && t.challenge) ||
34
+ (typeof t.message === "string" && t.message) ||
35
+ (accepts && typeof accepts.challenge === "string" && accepts.challenge) ||
36
+ JSON.stringify(accepts ?? t);
37
+ }
38
+ return new TextEncoder().encode(challenge);
39
+ }
40
+ /**
41
+ * Build a {@link PayHandler} from any Wallet Standard wallet. On a 402 it asks
42
+ * the wallet to sign the payment challenge and returns the `X-PAYMENT` header
43
+ * for a single retry. Returns `null` (declines) if the wallet cannot sign — the
44
+ * caller then sees the original 402, never a thrown error.
45
+ *
46
+ * import { Unbrowse } from "unbrowse/sdk";
47
+ * import { walletStandardPay } from "unbrowse/sdk/wallet-standard";
48
+ * const pay = walletStandardPay(myWallet);
49
+ * const unbrowse = new Unbrowse({ apiKey, pay });
50
+ */
51
+ export function walletStandardPay(wallet, opts = {}) {
52
+ const header = opts.header ?? "X-PAYMENT";
53
+ return async (ctx) => {
54
+ const sign = wallet.features[F_SIGN_MESSAGE];
55
+ if (!sign)
56
+ return null; // wallet can't sign Solana messages → decline cleanly
57
+ let account = opts.account ?? wallet.accounts[0];
58
+ if (!account) {
59
+ const connect = wallet.features[F_CONNECT];
60
+ if (!connect)
61
+ return null;
62
+ const { accounts } = await connect.connect();
63
+ account = accounts[0];
64
+ if (!account)
65
+ return null;
66
+ }
67
+ const message = paymentMessage(ctx.terms);
68
+ const [result] = await sign.signMessage({ account, message });
69
+ if (!result)
70
+ return null;
71
+ return { [header]: toBase64(result.signature) };
72
+ };
73
+ }
74
+ const DEFAULT_BASE = "https://beta-api.unbrowse.ai";
75
+ /**
76
+ * An OPTIONAL default wallet for users who don't want to run their own wallet —
77
+ * a Wallet Standard `Wallet` whose signing is delegated to the Unbrowse server
78
+ * (authorized by an API key). It is opt-in: you must pass an `apiKey`. Register
79
+ * it with `@wallet-standard/wallet`'s `registerWallet()` to expose it to any
80
+ * Wallet Standard consumer (including the Unbrowse frontend).
81
+ *
82
+ * Web2-native: the user "just wants to pay via API" — no seed phrase, no
83
+ * extension. The server (or lobster.cash, or any other wallet) remains the
84
+ * transaction-state authority; this is a thin convenience default, never forced.
85
+ */
86
+ export function makeUnbrowseWallet(opts) {
87
+ if (!opts.apiKey) {
88
+ throw new Error("makeUnbrowseWallet is opt-in: pass { apiKey } to delegate signing to the Unbrowse server.");
89
+ }
90
+ const base = (opts.baseUrl ?? DEFAULT_BASE).replace(/\/$/, "");
91
+ const doFetch = opts.fetch ?? globalThis.fetch;
92
+ const account = {
93
+ address: opts.address,
94
+ publicKey: opts.publicKey,
95
+ chains: ["solana:mainnet"],
96
+ features: [F_SIGN_MESSAGE],
97
+ };
98
+ const signMessage = async ({ message }) => {
99
+ const res = await doFetch(`${base}/v1/wallet/sign`, {
100
+ method: "POST",
101
+ headers: { "content-type": "application/json", authorization: `Bearer ${opts.apiKey}` },
102
+ body: JSON.stringify({ address: opts.address, message: toBase64(message) }),
103
+ });
104
+ if (!res.ok)
105
+ throw new Error(`unbrowse wallet sign failed: ${res.status}`);
106
+ const data = (await res.json());
107
+ const sig = Uint8Array.from(atobBytes(data.signature));
108
+ return [{ signedMessage: message, signature: sig }];
109
+ };
110
+ return {
111
+ version: "1.0.0",
112
+ name: "Unbrowse",
113
+ chains: ["solana:mainnet"],
114
+ accounts: [account],
115
+ features: {
116
+ [F_CONNECT]: { connect: async () => ({ accounts: [account] }) },
117
+ [F_SIGN_MESSAGE]: { signMessage },
118
+ },
119
+ };
120
+ }
121
+ function atobBytes(b64) {
122
+ const bin = typeof atob === "function" ? atob(b64) : // @ts-ignore
123
+ Buffer.from(b64, "base64").toString("binary");
124
+ const out = [];
125
+ for (let i = 0; i < bin.length; i++)
126
+ out.push(bin.charCodeAt(i));
127
+ return out;
128
+ }
package/package.json CHANGED
@@ -1,13 +1,25 @@
1
1
  {
2
2
  "name": "unbrowse",
3
- "version": "7.2.0-preview.0",
3
+ "version": "8.0.0",
4
4
  "description": "Reverse-engineer any website into reusable API skills. Zero-dep single binary with embedded browser engine.",
5
+ "mcpName": "io.github.unbrowse-ai/unbrowse",
5
6
  "type": "module",
6
7
  "bin": {
7
8
  "unbrowse": "bin/unbrowse-wrapper.mjs"
8
9
  },
10
+ "exports": {
11
+ "./sdk": {
12
+ "types": "./dist-sdk/index.d.ts",
13
+ "import": "./dist-sdk/index.js"
14
+ },
15
+ "./sdk/wallet-standard": {
16
+ "types": "./dist-sdk/wallet-standard.d.ts",
17
+ "import": "./dist-sdk/wallet-standard.js"
18
+ }
19
+ },
9
20
  "files": [
10
21
  "bin",
22
+ "dist-sdk",
11
23
  "vendor/kuri",
12
24
  "vendor/utls-proxy",
13
25
  "scripts/release-assets.mjs",
@@ -20,7 +32,8 @@
20
32
  ],
21
33
  "scripts": {
22
34
  "postinstall": "node scripts/postinstall.mjs",
23
- "prepack": "node scripts/prepare-pack.mjs && node scripts/assert-kuri-vendor.mjs && node scripts/assert-utls-vendor.mjs",
35
+ "build:sdk": "tsc -p tsconfig.sdk.json",
36
+ "prepack": "npm run build:sdk && node scripts/prepare-pack.mjs && node scripts/assert-kuri-vendor.mjs && node scripts/assert-utls-vendor.mjs",
24
37
  "prepublishOnly": "node scripts/assert-release-flow.mjs && node scripts/verify-release-assets.mjs",
25
38
  "start": "bun src/index.ts",
26
39
  "dev": "bun --watch src/index.ts"
@@ -28,7 +41,6 @@
28
41
  "dependencies": {
29
42
  "@fastify/cors": "^11.2.0",
30
43
  "@fastify/rate-limit": "^10.3.0",
31
- "@cascade-fyi/splits-sdk": "^0.11.1",
32
44
  "@solana/kit": "^6.6.0",
33
45
  "@x402/fetch": "^2.9.0",
34
46
  "bs58": "^6.0.0",
Binary file
@@ -2,7 +2,7 @@
2
2
  "repo_url": "https://github.com/justrach/kuri.git",
3
3
  "branch": "adding-extensions",
4
4
  "source_sha": "8938f89f3d0c032bd19c59db0de4eadca18a1800",
5
- "built_at": "2026-05-31T07:22:18.500Z",
5
+ "built_at": "2026-06-03T23:17:01.192Z",
6
6
  "binaries": {
7
7
  "darwin-arm64": {
8
8
  "zig_target": "aarch64-macos",
@@ -21,33 +21,33 @@
21
21
  },
22
22
  "linux-x64": {
23
23
  "zig_target": "x86_64-linux",
24
- "sha256": "fa91a78820effff9db8465fa66567ac7fe22f42ea89522ef7b6f482e6678ad0d"
24
+ "sha256": "0c51e54e535d7992a39eb5e2c71caee07ade770a257b4a0467f54c2c3477e190"
25
25
  },
26
26
  "win-x64": {
27
27
  "zig_target": "x86_64-windows-gnu",
28
- "sha256": "0919906d9b1512166dd6af207782949cd1ace6babec1817f94e4efdf3beb26db"
28
+ "sha256": "a9e9e048b9c37f462a5e8ed33c66e9d07631f4d1390008074d3bc7bb234a7103"
29
29
  }
30
30
  },
31
31
  "ffi": {
32
32
  "darwin-arm64": {
33
33
  "zig_target": "aarch64-macos",
34
34
  "lib": "libkuri_ffi.dylib",
35
- "sha256": "ec87c92ed59368e674266ce47aa42c9c6496313953e2747d01b28e116f5a21f4"
35
+ "sha256": "7e1c9505a1b10dcec1f22d9ca24c72a9a99ddf024e8a216779a5bbb03f6d65f4"
36
36
  },
37
37
  "darwin-x64": {
38
38
  "zig_target": "x86_64-macos",
39
39
  "lib": "libkuri_ffi.dylib",
40
- "sha256": "905e7e6bb67fb9791e4a3585e1802042a65d7fcb2d5d064651f2cfc48e97cb0d"
40
+ "sha256": "919513fc1f35ae2be0d457d827f7440c2f1fed165bce3ef5abcb42a20cc37d53"
41
41
  },
42
42
  "linux-arm64": {
43
43
  "zig_target": "aarch64-linux",
44
44
  "lib": "libkuri_ffi.so",
45
- "sha256": "9dbdf3b4e4588ee30295715a74afb3c1e01059cf5a3c451f6ab21d63036caa44"
45
+ "sha256": "926376c2f27394c3141edfa75df52640583d0efec4ea378e8e1f516098dc1ad7"
46
46
  },
47
47
  "linux-x64": {
48
48
  "zig_target": "x86_64-linux",
49
49
  "lib": "libkuri_ffi.so",
50
- "sha256": "7685b4b81338f5ade4d72839b85f341ca32f4711964d3becfc9970785240cdb2"
50
+ "sha256": "89f303f8d20bcaa30ed3b10280e9d018d51e29cc65728a56763e05be0bfc03a6"
51
51
  }
52
52
  }
53
53
  }
Binary file