unbrowse 3.6.0-preview.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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.6.0-preview.0", BUILD_GIT_SHA = "53592d89047b", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy42LjAtcHJldmlldy4wIiwiZ2l0X3NoYSI6IjUzNTkyZDg5MDQ3YiIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFANTM1OTJkODkwNDdiIiwiaXNzdWVkX2F0IjoiMjAyNi0wNC0wOVQyMDo0MTozMC4wODJaIn0", BUILD_RELEASE_MANIFEST_SIGNATURE = "HlE5m4HLbj0SjURsLry2pCTQTH-KmnP05XG5sH6-CSk", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
34
+ var BUILD_RELEASE_VERSION = "3.7.0", BUILD_GIT_SHA = "051ddb5b3add", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy43LjAiLCJnaXRfc2hhIjoiMDUxZGRiNWIzYWRkIiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUAwNTFkZGI1YjNhZGQiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTEwVDAzOjA3OjU1Ljg4MloifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "TKsUZaH-T1iT7XTgsV8ykdoZDHQj05PQkkmGr0Yf3dQ", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
35
35
 
36
36
  // ../../src/version.ts
37
37
  import { createHash } from "crypto";
@@ -2630,18 +2630,12 @@ async function autonomousLogin(loginUrl, domain) {
2630
2630
  return { success: false, method: "failed", domain: targetDomain, cookies_stored: 0, error: "No email provider configured (set AGENTMAIL_API_KEY or configure Gmail via gcloud)", duration_ms: elapsed() };
2631
2631
  }
2632
2632
  log("autonomous-login", `starting for ${targetDomain} — url: ${loginUrl}`);
2633
- const prevHeadless = process.env.HEADLESS;
2634
- process.env.HEADLESS = "false";
2635
2633
  let tabId;
2636
2634
  try {
2637
2635
  await start();
2638
2636
  tabId = await getDefaultTab();
2639
2637
  await networkEnable(tabId);
2640
2638
  } catch (err) {
2641
- if (prevHeadless !== undefined)
2642
- process.env.HEADLESS = prevHeadless;
2643
- else
2644
- delete process.env.HEADLESS;
2645
2639
  return { success: false, method: "failed", domain: targetDomain, cookies_stored: 0, error: `Kuri start failed: ${err}`, duration_ms: elapsed() };
2646
2640
  }
2647
2641
  try {
@@ -2730,12 +2724,7 @@ async function autonomousLogin(loginUrl, domain) {
2730
2724
  };
2731
2725
  }
2732
2726
  return { success: false, method: "failed", domain: targetDomain, email: agentEmail, cookies_stored: 0, error: "login flow completed but no auth cookies detected", duration_ms: elapsed() };
2733
- } finally {
2734
- if (prevHeadless !== undefined)
2735
- process.env.HEADLESS = prevHeadless;
2736
- else
2737
- delete process.env.HEADLESS;
2738
- }
2727
+ } finally {}
2739
2728
  }
2740
2729
  var OTP_FILL_TIMEOUT_MS = 120000, POST_SUBMIT_SETTLE_MS = 3000;
2741
2730
  var init_autonomous_login = __esm(async () => {
@@ -3374,8 +3363,6 @@ import fs2 from "node:fs";
3374
3363
  import path9 from "node:path";
3375
3364
  async function bootstrapAgentMailKey() {
3376
3365
  log("bootstrap-agentmail", "starting — opening console.agentmail.to");
3377
- const prevHeadless = process.env.HEADLESS;
3378
- process.env.HEADLESS = "false";
3379
3366
  try {
3380
3367
  await start();
3381
3368
  const tabId = await getDefaultTab();
@@ -3496,12 +3483,7 @@ async function bootstrapAgentMailKey() {
3496
3483
  success: false,
3497
3484
  error: "Reached dashboard but could not extract API key. Create one manually at https://console.agentmail.to/dashboard/api-keys"
3498
3485
  };
3499
- } finally {
3500
- if (prevHeadless !== undefined)
3501
- process.env.HEADLESS = prevHeadless;
3502
- else
3503
- delete process.env.HEADLESS;
3504
- }
3486
+ } finally {}
3505
3487
  }
3506
3488
  function persistApiKeyToShell(apiKey) {
3507
3489
  const shell = process.env.SHELL ?? "/bin/zsh";
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.6.0-preview.0";
229
- var BUILD_GIT_SHA = "53592d89047b";
228
+ var BUILD_RELEASE_VERSION = "3.7.0";
229
+ var BUILD_GIT_SHA = "051ddb5b3add";
230
230
  var BUILD_CODE_HASH = "5d9ebf619c61";
231
- var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy42LjAtcHJldmlldy4wIiwiZ2l0X3NoYSI6IjUzNTkyZDg5MDQ3YiIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFANTM1OTJkODkwNDdiIiwiaXNzdWVkX2F0IjoiMjAyNi0wNC0wOVQyMDo0MTozMC4wODJaIn0";
232
- var BUILD_RELEASE_MANIFEST_SIGNATURE = "HlE5m4HLbj0SjURsLry2pCTQTH-KmnP05XG5sH6-CSk";
231
+ var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy43LjAiLCJnaXRfc2hhIjoiMDUxZGRiNWIzYWRkIiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUAwNTFkZGI1YjNhZGQiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTEwVDAzOjA3OjU1Ljg4MloifQ";
232
+ var BUILD_RELEASE_MANIFEST_SIGNATURE = "TKsUZaH-T1iT7XTgsV8ykdoZDHQj05PQkkmGr0Yf3dQ";
233
233
  var BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
234
234
 
235
235
  // ../../src/version.ts
package/dist/server.js CHANGED
@@ -7096,7 +7096,7 @@ var init_capture = __esm(async () => {
7096
7096
  });
7097
7097
 
7098
7098
  // ../../src/build-info.generated.ts
7099
- var BUILD_RELEASE_VERSION = "3.6.0-preview.0", BUILD_GIT_SHA = "53592d89047b", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy42LjAtcHJldmlldy4wIiwiZ2l0X3NoYSI6IjUzNTkyZDg5MDQ3YiIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFANTM1OTJkODkwNDdiIiwiaXNzdWVkX2F0IjoiMjAyNi0wNC0wOVQyMDo0MTozMC4wODJaIn0", BUILD_RELEASE_MANIFEST_SIGNATURE = "HlE5m4HLbj0SjURsLry2pCTQTH-KmnP05XG5sH6-CSk", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
7099
+ var BUILD_RELEASE_VERSION = "3.7.0", BUILD_GIT_SHA = "051ddb5b3add", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy43LjAiLCJnaXRfc2hhIjoiMDUxZGRiNWIzYWRkIiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUAwNTFkZGI1YjNhZGQiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTEwVDAzOjA3OjU1Ljg4MloifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "TKsUZaH-T1iT7XTgsV8ykdoZDHQj05PQkkmGr0Yf3dQ", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
7100
7100
 
7101
7101
  // ../../src/version.ts
7102
7102
  import { createHash } from "crypto";
@@ -10893,18 +10893,12 @@ async function autonomousLogin(loginUrl, domain) {
10893
10893
  return { success: false, method: "failed", domain: targetDomain, cookies_stored: 0, error: "No email provider configured (set AGENTMAIL_API_KEY or configure Gmail via gcloud)", duration_ms: elapsed() };
10894
10894
  }
10895
10895
  log("autonomous-login", `starting for ${targetDomain} — url: ${loginUrl}`);
10896
- const prevHeadless = process.env.HEADLESS;
10897
- process.env.HEADLESS = "false";
10898
10896
  let tabId;
10899
10897
  try {
10900
10898
  await start();
10901
10899
  tabId = await getDefaultTab();
10902
10900
  await networkEnable(tabId);
10903
10901
  } catch (err) {
10904
- if (prevHeadless !== undefined)
10905
- process.env.HEADLESS = prevHeadless;
10906
- else
10907
- delete process.env.HEADLESS;
10908
10902
  return { success: false, method: "failed", domain: targetDomain, cookies_stored: 0, error: `Kuri start failed: ${err}`, duration_ms: elapsed() };
10909
10903
  }
10910
10904
  try {
@@ -10993,12 +10987,7 @@ async function autonomousLogin(loginUrl, domain) {
10993
10987
  };
10994
10988
  }
10995
10989
  return { success: false, method: "failed", domain: targetDomain, email: agentEmail, cookies_stored: 0, error: "login flow completed but no auth cookies detected", duration_ms: elapsed() };
10996
- } finally {
10997
- if (prevHeadless !== undefined)
10998
- process.env.HEADLESS = prevHeadless;
10999
- else
11000
- delete process.env.HEADLESS;
11001
- }
10990
+ } finally {}
11002
10991
  }
11003
10992
  var OTP_FILL_TIMEOUT_MS = 120000, POST_SUBMIT_SETTLE_MS = 3000;
11004
10993
  var init_autonomous_login = __esm(async () => {
@@ -15506,6 +15495,7 @@ __export(exports_execution, {
15506
15495
  buildCanonicalDocumentEndpoint: () => buildCanonicalDocumentEndpoint
15507
15496
  });
15508
15497
  import { nanoid as nanoid6 } from "nanoid";
15498
+ import { createHash as createHash5 } from "node:crypto";
15509
15499
  function stampTrace(trace) {
15510
15500
  trace.trace_version = TRACE_VERSION;
15511
15501
  return trace;
@@ -16100,8 +16090,9 @@ function buildCanonicalDocumentEndpoint(url, intent, authRequired = false) {
16100
16090
  const replayTemplate = deriveStructuredDataReplayTemplate(url);
16101
16091
  if (replayUrl === url && replayTemplate === url)
16102
16092
  return;
16093
+ const canonicalId = createHash5("sha1").update(replayTemplate !== url ? replayTemplate : replayUrl).digest("base64url").slice(0, 21);
16103
16094
  const endpoint = {
16104
- endpoint_id: nanoid6(),
16095
+ endpoint_id: canonicalId,
16105
16096
  method: "GET",
16106
16097
  url_template: replayTemplate !== url ? replayTemplate : replayUrl,
16107
16098
  idempotency: "safe",
@@ -19126,10 +19117,10 @@ var init_timing_economics = __esm(() => {
19126
19117
  });
19127
19118
 
19128
19119
  // ../../src/routing-telemetry.ts
19129
- import { createHash as createHash5 } from "node:crypto";
19120
+ import { createHash as createHash6 } from "node:crypto";
19130
19121
  import { nanoid as nanoid8 } from "nanoid";
19131
19122
  function stableHash(value) {
19132
- return createHash5("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 24);
19123
+ return createHash6("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 24);
19133
19124
  }
19134
19125
  function sanitizeScalar(value) {
19135
19126
  if (value == null)
@@ -19483,7 +19474,7 @@ function applyVerificationResults(skill, verification) {
19483
19474
  import { nanoid as nanoid9 } from "nanoid";
19484
19475
  import { existsSync as existsSync13, writeFileSync as writeFileSync8, readFileSync as readFileSync8, mkdirSync as mkdirSync9, readdirSync as readdirSync6 } from "node:fs";
19485
19476
  import { dirname as dirname2, join as join12 } from "node:path";
19486
- import { createHash as createHash6 } from "node:crypto";
19477
+ import { createHash as createHash7 } from "node:crypto";
19487
19478
  function summarizeSchema(schema, maxDepth = 3) {
19488
19479
  function walk(s, depth) {
19489
19480
  if (depth <= 0)
@@ -19611,7 +19602,7 @@ function scopedResolveCacheKeys(scope, key) {
19611
19602
  return scope === "global" ? [scopedCacheKey("global", key)] : [scopedCacheKey(scope, key), scopedCacheKey("global", key)];
19612
19603
  }
19613
19604
  function snapshotPathForCacheKey(cacheKey) {
19614
- const digest = createHash6("sha1").update(cacheKey).digest("hex");
19605
+ const digest = createHash7("sha1").update(cacheKey).digest("hex");
19615
19606
  return join12(SKILL_SNAPSHOT_DIR, `${digest}.json`);
19616
19607
  }
19617
19608
  function writeSkillSnapshot(cacheKey, skill) {
@@ -19933,10 +19924,17 @@ function withContextReplayEndpoint(skill, intent, contextUrl) {
19933
19924
  if (skill.endpoints.some((endpoint) => endpoint.method === canonical.method && endpoint.url_template === canonical.url_template)) {
19934
19925
  return skill;
19935
19926
  }
19936
- return {
19927
+ const augmented = {
19937
19928
  ...skill,
19938
19929
  endpoints: [canonical, ...skill.endpoints]
19939
19930
  };
19931
+ try {
19932
+ const existing = findExistingSkillForDomain(skill.domain);
19933
+ if (!existing || !existing.endpoints.some((ep) => ep.endpoint_id === canonical.endpoint_id)) {
19934
+ cachePublishedSkill(augmented);
19935
+ }
19936
+ } catch {}
19937
+ return augmented;
19940
19938
  }
19941
19939
  function isSearchLikeIntent(intent, contextUrl) {
19942
19940
  if (/\b(search|find|lookup|browse|discover)\b/i.test(intent ?? ""))
@@ -19955,7 +19953,7 @@ function buildLocalCanonicalReplaySkill(intent, contextUrl) {
19955
19953
  const domain = new URL(contextUrl).hostname.replace(/^www\./, "");
19956
19954
  const now = new Date().toISOString();
19957
19955
  const skill = {
19958
- skill_id: `canonical-${createHash6("sha1").update(contextUrl).digest("hex").slice(0, 12)}`,
19956
+ skill_id: `canonical-${createHash7("sha1").update(contextUrl).digest("hex").slice(0, 12)}`,
19959
19957
  version: "1.0.0",
19960
19958
  schema_version: "1",
19961
19959
  name: `Canonical replay for ${domain}`,
@@ -22157,7 +22155,18 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
22157
22155
  continue;
22158
22156
  if (targetRegDomain && getRegistrableDomain(skill.domain) !== targetRegDomain)
22159
22157
  continue;
22160
- const endpointId = extractEndpointId(c.metadata) ?? undefined;
22158
+ let endpointId = extractEndpointId(c.metadata) ?? undefined;
22159
+ if (endpointId && !skill.endpoints.some((ep) => ep.endpoint_id === endpointId)) {
22160
+ const vecUrl = c.metadata?.url_template;
22161
+ const urlMatch = vecUrl ? skill.endpoints.find((ep) => ep.url_template === vecUrl) : undefined;
22162
+ if (urlMatch) {
22163
+ console.log(`[marketplace] vecdb endpoint ${endpointId} stale → recovered via URL match: ${urlMatch.endpoint_id}`);
22164
+ endpointId = urlMatch.endpoint_id;
22165
+ } else {
22166
+ console.log(`[marketplace] vecdb endpoint ${endpointId} not found on skill ${skillId} — dropping to skill-level match`);
22167
+ endpointId = undefined;
22168
+ }
22169
+ }
22161
22170
  ranked.push({
22162
22171
  candidate: c,
22163
22172
  skill,
@@ -27588,7 +27597,7 @@ var init_routes = __esm(async () => {
27588
27597
  ]);
27589
27598
  BETA_API_URL = process.env.UNBROWSE_BACKEND_URL || DEFAULT_BACKEND_URL;
27590
27599
  TRACES_DIR = process.env.TRACES_DIR ?? join17(process.cwd(), "traces");
27591
- BROWSE_BROKER_MAX = Math.max(1, Number(process.env.KURI_MULTI_BROKER_MAX ?? "2"));
27600
+ BROWSE_BROKER_MAX = Math.max(1, Number(process.env.KURI_MULTI_BROKER_MAX ?? "1"));
27592
27601
  BROWSE_BROKER_BASE_PORT = Number(process.env.KURI_PORT ?? "7700");
27593
27602
  browseSessions = new Map;
27594
27603
  STATS_CACHE_TTL = 5 * 60 * 1000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unbrowse",
3
- "version": "3.6.0-preview.0",
3
+ "version": "3.7.0",
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": {
@@ -29,6 +29,8 @@
29
29
  "@fastify/rate-limit": "^10.3.0",
30
30
  "@cascade-fyi/splits-sdk": "^0.11.1",
31
31
  "@solana/kit": "^6.6.0",
32
+ "@x402/fetch": "^2.9.0",
33
+ "agentmail": "^0.4.18",
32
34
  "bs58": "^6.0.0",
33
35
  "cheerio": "^1.2.0",
34
36
  "dotenv": "^17.3.1",