unbrowse 3.1.0-experiments.e503b7d → 3.1.0-experiments.ef43417

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.e503b7d", BUILD_GIT_SHA = "e503b7d2167b", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuZTUwM2I3ZCIsImdpdF9zaGEiOiJlNTAzYjdkMjE2N2IiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGU1MDNiN2QyMTY3YiIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMDA6MzQ6MjIuMTg3WiJ9", BUILD_RELEASE_MANIFEST_SIGNATURE = "36eJ8u5UlMxjTqUP6YRiW3XcKkrqc77k0lsCcdLzCZw", BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
34
+ var BUILD_RELEASE_VERSION = "3.1.0-experiments.ef43417", BUILD_GIT_SHA = "ef434171bbc8", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuZWY0MzQxNyIsImdpdF9zaGEiOiJlZjQzNDE3MWJiYzgiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGVmNDM0MTcxYmJjOCIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMDI6NTQ6MTAuMjU3WiJ9", BUILD_RELEASE_MANIFEST_SIGNATURE = "TWn8YbnQaAVxkiuNsLHcxl8-9saAN2wWFxDFtz9Xc0c", 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";
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.e503b7d";
229
- var BUILD_GIT_SHA = "e503b7d2167b";
228
+ var BUILD_RELEASE_VERSION = "3.1.0-experiments.ef43417";
229
+ var BUILD_GIT_SHA = "ef434171bbc8";
230
230
  var BUILD_CODE_HASH = "1488fc1d92b7";
231
- var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuZTUwM2I3ZCIsImdpdF9zaGEiOiJlNTAzYjdkMjE2N2IiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGU1MDNiN2QyMTY3YiIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMDA6MzQ6MjIuMTg3WiJ9";
232
- var BUILD_RELEASE_MANIFEST_SIGNATURE = "36eJ8u5UlMxjTqUP6YRiW3XcKkrqc77k0lsCcdLzCZw";
231
+ var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuZWY0MzQxNyIsImdpdF9zaGEiOiJlZjQzNDE3MWJiYzgiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGVmNDM0MTcxYmJjOCIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMDI6NTQ6MTAuMjU3WiJ9";
232
+ var BUILD_RELEASE_MANIFEST_SIGNATURE = "TWn8YbnQaAVxkiuNsLHcxl8-9saAN2wWFxDFtz9Xc0c";
233
233
  var BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
234
234
 
235
235
  // ../../src/version.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unbrowse",
3
- "version": "3.1.0-experiments.e503b7d",
3
+ "version": "3.1.0-experiments.ef43417",
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(() => {});
@@ -1178,9 +1178,17 @@ export async function registerRoutes(app: FastifyInstance) {
1178
1178
 
1179
1179
  async function restartBrowseCapture(session: BrowseSession): Promise<void> {
1180
1180
  const broker = brokerForSession(session);
1181
- // Start HAR + interceptor regardless of page load state — the page will load
1182
- // and HAR records all traffic from the moment it starts.
1183
- await broker.waitForLoad(session.tabId, 2_000).catch(() => null);
1181
+ // Ensure Kuri is actually responding before starting HAR.
1182
+ // Cold starts on packaged CLI can have ConnectionRefused retries
1183
+ // if we start HAR during instability, it gets lost on restart.
1184
+ for (let attempt = 0; attempt < 5; attempt++) {
1185
+ try {
1186
+ await broker.waitForLoad(session.tabId, 2_000);
1187
+ break;
1188
+ } catch {
1189
+ if (attempt < 4) await new Promise((r) => setTimeout(r, 1_000));
1190
+ }
1191
+ }
1184
1192
  await broker.networkEnable(session.tabId).catch(() => {});
1185
1193
  await broker.harStart(session.tabId).catch(() => {});
1186
1194
  await broker.scriptInject(session.tabId, INTERCEPTOR_SCRIPT).catch(() => {});
@@ -1,6 +1,6 @@
1
- export const BUILD_RELEASE_VERSION = "3.1.0-experiments.e503b7d";
2
- export const BUILD_GIT_SHA = "e503b7d2167b";
1
+ export const BUILD_RELEASE_VERSION = "3.1.0-experiments.ef43417";
2
+ export const BUILD_GIT_SHA = "ef434171bbc8";
3
3
  export const BUILD_CODE_HASH = "1488fc1d92b7";
4
- export const BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuZTUwM2I3ZCIsImdpdF9zaGEiOiJlNTAzYjdkMjE2N2IiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGU1MDNiN2QyMTY3YiIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMDA6MzQ6MjIuMTg3WiJ9";
5
- export const BUILD_RELEASE_MANIFEST_SIGNATURE = "36eJ8u5UlMxjTqUP6YRiW3XcKkrqc77k0lsCcdLzCZw";
4
+ export const BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4xLjAtZXhwZXJpbWVudHMuZWY0MzQxNyIsImdpdF9zaGEiOiJlZjQzNDE3MWJiYzgiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QGVmNDM0MTcxYmJjOCIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMDI6NTQ6MTAuMjU3WiJ9";
5
+ export const BUILD_RELEASE_MANIFEST_SIGNATURE = "TWn8YbnQaAVxkiuNsLHcxl8-9saAN2wWFxDFtz9Xc0c";
6
6
  export const BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
@@ -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
+ }
Binary file
Binary file
Binary file
Binary file
@@ -2,24 +2,24 @@
2
2
  "repo_url": "https://github.com/justrach/kuri.git",
3
3
  "branch": "adding-extensions",
4
4
  "source_sha": "eadfaa5f921f7152e1762aed5ed64b3a4fbefbf3",
5
- "built_at": "2026-04-06T00:34:22.236Z",
5
+ "built_at": "2026-04-06T02:54:10.305Z",
6
6
  "binaries": {
7
7
  "darwin-arm64": {
8
8
  "zig_target": "aarch64-macos",
9
- "sha256": "e230b49c36db62c3a5c9cf62e316b637ffff7452335211f63c390aab1a13e250",
9
+ "sha256": "1796501e393403016723c6b69266b834e2db04ba2559f51c84c957bd85c3927b",
10
10
  "source": "prebuilt"
11
11
  },
12
12
  "darwin-x64": {
13
13
  "zig_target": "x86_64-macos",
14
- "sha256": "5ce0dced30e64cb4c580495974f11a136d106d70004683b72300f27bd9d3c0b1"
14
+ "sha256": "82db8a0f3596d1f9335785eca8009e257bf379197e725f29aaedd6f9c2456267"
15
15
  },
16
16
  "linux-arm64": {
17
17
  "zig_target": "aarch64-linux",
18
- "sha256": "adc3bdfb7642f0e7e21c249dc570da9d30403703837aa072bc1c2bf5bb88f950"
18
+ "sha256": "8b53f4944274cb8930488ef822b0052f121e824424501863c399f251d827386b"
19
19
  },
20
20
  "linux-x64": {
21
21
  "zig_target": "x86_64-linux",
22
- "sha256": "8e033bdf050019e700801a5a6bf5298c2ad54914d7620385bfa8fd14fe77c4da"
22
+ "sha256": "ac00c41f2a8c706de9f0dcce1087fcdccb53484303c05f101bb461f7b9dceb48"
23
23
  }
24
24
  }
25
25
  }