unbrowse 3.1.0-experiments.a2cf008 → 3.1.0-experiments.acc0c3e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -31,7 +31,7 @@ var __promiseAll = (args) => Promise.all(args);
31
31
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
32
32
 
33
33
  // ../../src/build-info.generated.ts
34
- var BUILD_RELEASE_VERSION = "3.1.0-experiments.a2cf008", BUILD_GIT_SHA = "a2cf008142ff", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuYTJjZjAwOCIsImdpdF9zaGEiOiJhMmNmMDA4MTQyZmYiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGEyY2YwMDgxNDJmZiIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDVUMjM6MzQ6NDEuMzk1WiJ9", BUILD_RELEASE_MANIFEST_SIGNATURE = "1vxiaCYILmk4RglXTLEsIOnEpX1T_x2iDsMRsp_SSis", BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
34
+ var BUILD_RELEASE_VERSION = "3.1.0-experiments.acc0c3e", BUILD_GIT_SHA = "acc0c3e1f8c5", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuYWNjMGMzZSIsImdpdF9zaGEiOiJhY2MwYzNlMWY4YzUiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGFjYzBjM2UxZjhjNSIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMDI6MzI6NTMuOTQxWiJ9", BUILD_RELEASE_MANIFEST_SIGNATURE = "ZqdsNG9DQl3Sx4n94HXYdmjYsiExN3BXql7Z-yRx7wE", BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
35
35
 
36
36
  // ../../src/version.ts
37
37
  import { createHash } from "crypto";
@@ -1369,7 +1369,7 @@ init_wallet();
1369
1369
  init_telemetry_attribution();
1370
1370
  import { readFileSync as readFileSync3, writeFileSync, existsSync as existsSync4, mkdirSync, readdirSync as readdirSync2 } from "fs";
1371
1371
  import { join as join4 } from "path";
1372
- import { homedir as homedir3, hostname } from "os";
1372
+ import { homedir as homedir3, hostname, release as osRelease } from "os";
1373
1373
  import { randomBytes, createHash as createHash2 } from "crypto";
1374
1374
  import { createInterface } from "readline";
1375
1375
  var API_URL = process.env.UNBROWSE_BACKEND_URL || DEFAULT_BACKEND_URL;
@@ -1562,9 +1562,19 @@ async function recordInstallTelemetryEvent(source, options) {
1562
1562
  skill_version: options?.skillVersion,
1563
1563
  status: options?.status ?? "installed",
1564
1564
  created_at: createdAt,
1565
- properties: mergeTelemetryProperties(options?.properties, getTelemetryAttribution())
1565
+ properties: mergeTelemetryProperties({ ...getRuntimeContext(), ...options?.properties }, getTelemetryAttribution())
1566
1566
  });
1567
1567
  }
1568
+ function getRuntimeContext() {
1569
+ return {
1570
+ cli_version: PACKAGE_VERSION,
1571
+ code_hash: CODE_HASH,
1572
+ node_version: process.version,
1573
+ platform: process.platform,
1574
+ arch: process.arch,
1575
+ os_release: osRelease()
1576
+ };
1577
+ }
1568
1578
  async function recordFunnelTelemetryEvent(name, options) {
1569
1579
  const createdAt = options?.createdAt ?? new Date().toISOString();
1570
1580
  const landingToken = getLandingToken();
@@ -1576,7 +1586,7 @@ async function recordFunnelTelemetryEvent(name, options) {
1576
1586
  source: options?.source ?? "cli",
1577
1587
  host_type: options?.hostType ?? detectTelemetryHostType(),
1578
1588
  created_at: createdAt,
1579
- properties: mergeTelemetryProperties(options?.properties, getTelemetryAttribution())
1589
+ properties: mergeTelemetryProperties({ ...getRuntimeContext(), ...options?.properties }, getTelemetryAttribution())
1580
1590
  });
1581
1591
  }
1582
1592
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/i;
package/dist/mcp.js CHANGED
@@ -225,11 +225,11 @@ import { dirname, join, parse } from "path";
225
225
  import { fileURLToPath as fileURLToPath2 } from "url";
226
226
 
227
227
  // ../../src/build-info.generated.ts
228
- var BUILD_RELEASE_VERSION = "3.1.0-experiments.a2cf008";
229
- var BUILD_GIT_SHA = "a2cf008142ff";
228
+ var BUILD_RELEASE_VERSION = "3.1.0-experiments.acc0c3e";
229
+ var BUILD_GIT_SHA = "acc0c3e1f8c5";
230
230
  var BUILD_CODE_HASH = "1488fc1d92b7";
231
- var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuYTJjZjAwOCIsImdpdF9zaGEiOiJhMmNmMDA4MTQyZmYiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGEyY2YwMDgxNDJmZiIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDVUMjM6MzQ6NDEuMzk1WiJ9";
232
- var BUILD_RELEASE_MANIFEST_SIGNATURE = "1vxiaCYILmk4RglXTLEsIOnEpX1T_x2iDsMRsp_SSis";
231
+ var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuYWNjMGMzZSIsImdpdF9zaGEiOiJhY2MwYzNlMWY4YzUiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGFjYzBjM2UxZjhjNSIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMDI6MzI6NTMuOTQxWiJ9";
232
+ var BUILD_RELEASE_MANIFEST_SIGNATURE = "ZqdsNG9DQl3Sx4n94HXYdmjYsiExN3BXql7Z-yRx7wE";
233
233
  var BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
234
234
 
235
235
  // ../../src/version.ts
@@ -743,7 +743,7 @@ function readImpactSummary() {
743
743
  // ../../src/client/index.ts
744
744
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync6, mkdirSync as mkdirSync4, readdirSync as readdirSync3 } from "fs";
745
745
  import { join as join5 } from "path";
746
- import { homedir as homedir4, hostname } from "os";
746
+ import { homedir as homedir4, hostname, release as osRelease } from "os";
747
747
 
748
748
  // ../../src/payments/cascade.ts
749
749
  import bs58 from "bs58";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unbrowse",
3
- "version": "3.1.0-experiments.a2cf008",
3
+ "version": "3.1.0-experiments.acc0c3e",
4
4
  "description": "Reverse-engineer any website into reusable API skills. Zero-dep single binary with embedded browser engine.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -169,6 +169,10 @@ export async function cacheBrowseRequests(params: {
169
169
  // so serverFetch can replay them. Use registrable domain for vault key
170
170
  // so ads.x.com and ads-api.x.com share the same session.
171
171
  const capturedAuthHeaders = extractAuthHeaders(requests);
172
+ // Filter out [REDACTED] placeholders from cookie-inferred auth headers
173
+ for (const [k, v] of Object.entries(capturedAuthHeaders)) {
174
+ if (v === "[REDACTED]") delete capturedAuthHeaders[k];
175
+ }
172
176
  if (Object.keys(capturedAuthHeaders).length > 0) {
173
177
  const sessionKey = `${getRegistrableDomain(domain)}-session`;
174
178
  await storeCredential(sessionKey, JSON.stringify({ headers: capturedAuthHeaders })).catch(() => {});
@@ -1,6 +1,6 @@
1
- export const BUILD_RELEASE_VERSION = "3.1.0-experiments.a2cf008";
2
- export const BUILD_GIT_SHA = "a2cf008142ff";
1
+ export const BUILD_RELEASE_VERSION = "3.1.0-experiments.acc0c3e";
2
+ export const BUILD_GIT_SHA = "acc0c3e1f8c5";
3
3
  export const BUILD_CODE_HASH = "1488fc1d92b7";
4
- export const BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuYTJjZjAwOCIsImdpdF9zaGEiOiJhMmNmMDA4MTQyZmYiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGEyY2YwMDgxNDJmZiIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDVUMjM6MzQ6NDEuMzk1WiJ9";
5
- export const BUILD_RELEASE_MANIFEST_SIGNATURE = "1vxiaCYILmk4RglXTLEsIOnEpX1T_x2iDsMRsp_SSis";
4
+ export const BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuYWNjMGMzZSIsImdpdF9zaGEiOiJhY2MwYzNlMWY4YzUiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGFjYzBjM2UxZjhjNSIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMDI6MzI6NTMuOTQxWiJ9";
5
+ export const BUILD_RELEASE_MANIFEST_SIGNATURE = "ZqdsNG9DQl3Sx4n94HXYdmjYsiExN3BXql7Z-yRx7wE";
6
6
  export const BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
@@ -1,6 +1,6 @@
1
1
  import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "fs";
2
2
  import { join } from "path";
3
- import { homedir, hostname } from "os";
3
+ import { homedir, hostname, release as osRelease } from "os";
4
4
  import { randomBytes, createHash } from "crypto";
5
5
  import { createInterface } from "readline";
6
6
  import type {
@@ -16,6 +16,7 @@ import {
16
16
  CODE_HASH,
17
17
  DEFAULT_BACKEND_URL,
18
18
  GIT_SHA,
19
+ PACKAGE_VERSION,
19
20
  RELEASE_MANIFEST_BASE64,
20
21
  RELEASE_MANIFEST_SIGNATURE,
21
22
  TRACE_VERSION,
@@ -302,10 +303,21 @@ export async function recordInstallTelemetryEvent(
302
303
  skill_version: options?.skillVersion,
303
304
  status: options?.status ?? "installed",
304
305
  created_at: createdAt,
305
- properties: mergeTelemetryProperties(options?.properties, getTelemetryAttribution()),
306
+ properties: mergeTelemetryProperties({ ...getRuntimeContext(), ...options?.properties }, getTelemetryAttribution()),
306
307
  });
307
308
  }
308
309
 
310
+ function getRuntimeContext(): Record<string, unknown> {
311
+ return {
312
+ cli_version: PACKAGE_VERSION,
313
+ code_hash: CODE_HASH,
314
+ node_version: process.version,
315
+ platform: process.platform,
316
+ arch: process.arch,
317
+ os_release: osRelease(),
318
+ };
319
+ }
320
+
309
321
  export async function recordFunnelTelemetryEvent(
310
322
  name: string,
311
323
  options?: {
@@ -326,7 +338,7 @@ export async function recordFunnelTelemetryEvent(
326
338
  source: options?.source ?? "cli",
327
339
  host_type: options?.hostType ?? detectTelemetryHostType(),
328
340
  created_at: createdAt,
329
- properties: mergeTelemetryProperties(options?.properties, getTelemetryAttribution()),
341
+ properties: mergeTelemetryProperties({ ...getRuntimeContext(), ...options?.properties }, getTelemetryAttribution()),
330
342
  });
331
343
  }
332
344
 
@@ -2022,7 +2022,7 @@ export async function executeEndpoint(
2022
2022
  try {
2023
2023
  const { resolveAuthTokens } = await import("./token-resolver.js");
2024
2024
  const resolved = await resolveAuthTokens(endpoint, cookies, authHeaders);
2025
- log("exec", `token resolver returned ${Object.keys(resolved).length} headers: ${Object.keys(resolved).join(",") || "none"}`);
2025
+ log("exec", `token resolver returned ${Object.keys(resolved).length} headers: ${Object.keys(resolved).join(",") || "none"} auth=${(resolved.authorization || "").substring(0, 40)}`);
2026
2026
  Object.assign(authHeaders, resolved);
2027
2027
  } catch (e) { log("exec", `token resolver failed: ${e}`); }
2028
2028
  }
@@ -2241,7 +2241,7 @@ export async function executeEndpoint(
2241
2241
 
2242
2242
  for (const replayUrl of replayUrls) {
2243
2243
  const replayHeaders = buildStructuredReplayHeaders(url, replayUrl, headers);
2244
- log("exec", `server-fetch: ${endpoint.method} ${replayUrl.substring(0, 80)} csrf=${replayHeaders["x-csrf-token"]?.substring(0, 10)}... cookies=${(replayHeaders["cookie"]?.length ?? 0)}chars`);
2244
+ log("exec", `server-fetch: ${endpoint.method} ${replayUrl.substring(0, 80)} auth=${(replayHeaders["authorization"] || "none").substring(0, 50)} csrf=${replayHeaders["x-csrf-token"]?.substring(0, 10)}... cookies=${(replayHeaders["cookie"]?.length ?? 0)}chars`);
2245
2245
  const res = await fetch(replayUrl, {
2246
2246
  method: endpoint.method,
2247
2247
  headers: replayHeaders,
@@ -3165,6 +3165,7 @@ export function rankEndpoints(endpoints: EndpointDescriptor[], intent?: string,
3165
3165
  }
3166
3166
  }
3167
3167
  score += ep.reliability_score * 5;
3168
+ if (ep.verification_status === "verified") score += 15;
3168
3169
  if (ep.method === "WS" && ep.response_schema) score += 3;
3169
3170
 
3170
3171
  // === Domain affinity ===
@@ -54,7 +54,14 @@ export async function resolveAuthTokens(
54
54
  }
55
55
 
56
56
  for (const binding of headerBindings) {
57
- const value = await resolveBinding(binding, html, cookies);
57
+ let value = await resolveBinding(binding, html, cookies);
58
+
59
+ // If stored sources didn't resolve (e.g. bearer in a different bundle),
60
+ // scan all loaded script resources via Performance API
61
+ if (!value && binding.sources.some((s) => s.kind === "js-bundle")) {
62
+ value = await scanAllScriptResources(tabId, binding);
63
+ }
64
+
58
65
  if (value) {
59
66
  resolved[binding.param_name] = binding.param_name.toLowerCase() === "authorization"
60
67
  ? (value.startsWith("Bearer ") ? value : `Bearer ${value}`)
@@ -133,3 +140,35 @@ async function waitForLoad(tabId: string): Promise<void> {
133
140
  await new Promise((r) => setTimeout(r, 500));
134
141
  }
135
142
  }
143
+
144
+ /**
145
+ * Scan all script resources loaded by the page via Performance API.
146
+ * Fetches each bundle and searches for a token matching the binding pattern.
147
+ * This handles cases where the enrichment captured the wrong bundle URLs.
148
+ */
149
+ async function scanAllScriptResources(tabId: string, binding: AuthTokenBinding): Promise<string | undefined> {
150
+ try {
151
+ const raw = await kuri.evaluate(tabId, `
152
+ JSON.stringify(
153
+ performance.getEntriesByType('resource')
154
+ .filter(function(e) { return e.initiatorType === 'script'; })
155
+ .map(function(e) { return e.name; })
156
+ )
157
+ `);
158
+ if (typeof raw !== "string" || !raw.startsWith("[")) return undefined;
159
+ const urls: string[] = JSON.parse(raw);
160
+
161
+ const tokenPattern = /AAAAAAAAAAAAAAAAAAA[A-Za-z0-9+/=_%-]{20,}/;
162
+
163
+ for (const url of urls) {
164
+ try {
165
+ const resp = await fetch(url);
166
+ if (!resp.ok) continue;
167
+ const body = await resp.text();
168
+ const m = body.match(tokenPattern);
169
+ if (m && m[0].length >= 20) return m[0];
170
+ } catch { /* fetch failed, try next */ }
171
+ }
172
+ } catch { /* evaluate failed */ }
173
+ return undefined;
174
+ }
@@ -309,7 +309,7 @@ export function enrichEndpointsWithTokenSources(
309
309
  sources.push({ kind: "cookie", cookie_names: ["ct0", "csrf_token", "_csrf", "csrftoken", "XSRF-TOKEN"] });
310
310
  } else if (lowerName === "authorization") {
311
311
  if (html) {
312
- const scriptSrcRe = /<script[^>]+src=["']([^"']+\.js[^"']*?)["']/gi;
312
+ const scriptSrcRe = /<script[^>]+src=["']([^"']+)["']/gi;
313
313
  let m: RegExpExecArray | null;
314
314
  while ((m = scriptSrcRe.exec(html)) !== null) {
315
315
  if (/main|app|client|bundle|vendor/i.test(m[1])) {
Binary file
Binary file
Binary file
Binary file
@@ -1,28 +1,25 @@
1
1
  {
2
2
  "repo_url": "https://github.com/justrach/kuri.git",
3
3
  "branch": "adding-extensions",
4
- "source_sha": "08eecbe3740f046a46f656eed7ebfc66c1bad9bb",
5
- "built_at": "2026-04-05T06:43:57.212Z",
4
+ "source_sha": "eadfaa5f921f7152e1762aed5ed64b3a4fbefbf3",
5
+ "built_at": "2026-04-06T02:32:53.993Z",
6
6
  "binaries": {
7
7
  "darwin-arm64": {
8
8
  "zig_target": "aarch64-macos",
9
- "sha256": "1553633e722d18059dedffa8a52d55ed6c052e4961fd2753ee0b62be60b241bf"
9
+ "sha256": "e230b49c36db62c3a5c9cf62e316b637ffff7452335211f63c390aab1a13e250",
10
+ "source": "prebuilt"
10
11
  },
11
12
  "darwin-x64": {
12
13
  "zig_target": "x86_64-macos",
13
- "sha256": "b5eb07e631c6ddad64019c8d0c86c32cb76a74ff0791ac5611a3aa3550767ec8"
14
+ "sha256": "f43bae178982b7d5d7da9d041a2984204afecf60c81f6c037451b372adbd2968"
14
15
  },
15
16
  "linux-arm64": {
16
17
  "zig_target": "aarch64-linux",
17
- "sha256": "ea88a26f7b335d5842b0c1d83bfa4066bed0a119284560f6bd3833f1d240cce2"
18
+ "sha256": "8416277825f6d55a2936de06f5dedce8ce1fe9445bb94843edd62103e22f8e0d"
18
19
  },
19
20
  "linux-x64": {
20
21
  "zig_target": "x86_64-linux",
21
- "sha256": "175a7c59e458e952a26974f0fb5c2ce374e56f2c4c352903b481b5aa5a16978f"
22
- },
23
- "win-x64": {
24
- "zig_target": "x86_64-windows",
25
- "sha256": "176291ad9827a183ba7322ddb56cc1fa5edc7c214a264ecdf8a1d5d18366d686"
22
+ "sha256": "459df714ac61fc906d9234f223791d51359c002a8ecbada9995211df9e0283cd"
26
23
  }
27
24
  }
28
25
  }
Binary file