unbrowse 10.1.3 → 10.1.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unbrowse",
3
- "version": "10.1.3",
3
+ "version": "10.1.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/unbrowse-ai/unbrowse.git"
package/runtime/cli.js CHANGED
@@ -64314,6 +64314,83 @@ function resolutionHostMatches(url, data) {
64314
64314
  return true;
64315
64315
  return hosts.some((h) => h === reqHost);
64316
64316
  }
64317
+ function isConcreteResourceLeaf(leaf) {
64318
+ return !!leaf && !/^(search|explore|trending|tabs|home|for-you|foryou|latest|live|people|posts|videos)$/.test(leaf);
64319
+ }
64320
+ function urlHasConcreteResourcePath(url) {
64321
+ if (!url)
64322
+ return false;
64323
+ try {
64324
+ const segments = new URL(url).pathname.split("/").filter(Boolean);
64325
+ if (segments.length === 0)
64326
+ return false;
64327
+ const leaf = decodeURIComponent(segments[segments.length - 1] ?? "").toLowerCase();
64328
+ return isConcreteResourceLeaf(leaf);
64329
+ } catch {
64330
+ return false;
64331
+ }
64332
+ }
64333
+ function pathCoherent(candidate, contextPath) {
64334
+ const toPath = (s) => {
64335
+ try {
64336
+ return new URL(s).pathname;
64337
+ } catch {
64338
+ return s;
64339
+ }
64340
+ };
64341
+ const decodeSeg = (s) => {
64342
+ try {
64343
+ return decodeURIComponent(s);
64344
+ } catch {
64345
+ return s;
64346
+ }
64347
+ };
64348
+ const candSegments = toPath(candidate).split("/").filter(Boolean).map(decodeSeg);
64349
+ const ctxSegments = toPath(contextPath).split("/").filter(Boolean).map(decodeSeg);
64350
+ if (candSegments.length !== ctxSegments.length)
64351
+ return false;
64352
+ for (let i = 0;i < candSegments.length; i++) {
64353
+ const cand = candSegments[i] ?? "";
64354
+ const ctx = ctxSegments[i] ?? "";
64355
+ const isHole = /^\{[^}]*\}$/.test(cand);
64356
+ if (!isHole && cand !== ctx)
64357
+ return false;
64358
+ }
64359
+ return true;
64360
+ }
64361
+ function collectRecordUrls(data) {
64362
+ const out = [];
64363
+ const push = (rec) => {
64364
+ if (!rec || typeof rec !== "object")
64365
+ return;
64366
+ const r = rec;
64367
+ for (const k of ["url", "link", "href", "source_url", "url_template"]) {
64368
+ const v = r[k];
64369
+ if (typeof v === "string" && v)
64370
+ out.push(v);
64371
+ }
64372
+ };
64373
+ if (Array.isArray(data))
64374
+ for (const rec of data.slice(0, 20))
64375
+ push(rec);
64376
+ else
64377
+ push(data);
64378
+ return out;
64379
+ }
64380
+ function resolutionPathMatches(url, data) {
64381
+ if (!urlHasConcreteResourcePath(url))
64382
+ return true;
64383
+ let contextPath = "";
64384
+ try {
64385
+ contextPath = new URL(url).pathname;
64386
+ } catch {
64387
+ return true;
64388
+ }
64389
+ const urls = collectRecordUrls(data);
64390
+ if (urls.length === 0)
64391
+ return true;
64392
+ return urls.some((u) => pathCoherent(u, contextPath));
64393
+ }
64317
64394
  var LIST_INTENT_RE, ITEM_SCHEMA_TYPES, COLLECTION_KEYS;
64318
64395
  var init_cardinality = __esm(() => {
64319
64396
  LIST_INTENT_RE = /\b(search|find|lookup|browse|discover|list(?:ings?)?|feed|catalog(?:ue)?)\b/i;
@@ -64846,7 +64923,7 @@ var init_telemetry = __esm(() => {
64846
64923
  });
64847
64924
 
64848
64925
  // .tmp-runtime-src/build-info.generated.ts
64849
- var BUILD_RELEASE_VERSION = "10.1.3", BUILD_GIT_SHA = "de11df6cf838", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMTAuMS4zIiwiZ2l0X3NoYSI6ImRlMTFkZjZjZjgzOCIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFAZGUxMWRmNmNmODM4IiwiaXNzdWVkX2F0IjoiMjAyNi0wNi0yM1QwOTowMzoyNC4wODlaIn0", BUILD_RELEASE_MANIFEST_SIGNATURE = "tQDAYXIj-Q4C-i2E4CTsKtHaEiTFy7uzrDQDxDjqO6o", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
64926
+ var BUILD_RELEASE_VERSION = "10.1.4", BUILD_GIT_SHA = "089d49f75f26", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMTAuMS40IiwiZ2l0X3NoYSI6IjA4OWQ0OWY3NWYyNiIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFAMDg5ZDQ5Zjc1ZjI2IiwiaXNzdWVkX2F0IjoiMjAyNi0wNi0yM1QxMDowNjoyMy45MjNaIn0", BUILD_RELEASE_MANIFEST_SIGNATURE = "cDbcbJgh0OyGCynwPC9q8d8xvPCtfzsY9H0lAtidjN4", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
64850
64927
 
64851
64928
  // .tmp-runtime-src/version.ts
64852
64929
  import { createHash as createHash8 } from "crypto";
@@ -113921,6 +113998,50 @@ function cardinalityMatches2(intent, subject, opts) {
113921
113998
  return !routeLooksLikeSingleItem2(subject.route);
113922
113999
  }
113923
114000
  }
114001
+ function isConcreteResourceLeaf2(leaf) {
114002
+ return !!leaf && !/^(search|explore|trending|tabs|home|for-you|foryou|latest|live|people|posts|videos)$/.test(leaf);
114003
+ }
114004
+ function urlHasConcreteResourcePath2(url) {
114005
+ if (!url)
114006
+ return false;
114007
+ try {
114008
+ const segments = new URL(url).pathname.split("/").filter(Boolean);
114009
+ if (segments.length === 0)
114010
+ return false;
114011
+ const leaf = decodeURIComponent(segments[segments.length - 1] ?? "").toLowerCase();
114012
+ return isConcreteResourceLeaf2(leaf);
114013
+ } catch {
114014
+ return false;
114015
+ }
114016
+ }
114017
+ function pathCoherent2(candidate, contextPath) {
114018
+ const toPath = (s) => {
114019
+ try {
114020
+ return new URL(s).pathname;
114021
+ } catch {
114022
+ return s;
114023
+ }
114024
+ };
114025
+ const decodeSeg = (s) => {
114026
+ try {
114027
+ return decodeURIComponent(s);
114028
+ } catch {
114029
+ return s;
114030
+ }
114031
+ };
114032
+ const candSegments = toPath(candidate).split("/").filter(Boolean).map(decodeSeg);
114033
+ const ctxSegments = toPath(contextPath).split("/").filter(Boolean).map(decodeSeg);
114034
+ if (candSegments.length !== ctxSegments.length)
114035
+ return false;
114036
+ for (let i = 0;i < candSegments.length; i++) {
114037
+ const cand = candSegments[i] ?? "";
114038
+ const ctx = ctxSegments[i] ?? "";
114039
+ const isHole = /^\{[^}]*\}$/.test(cand);
114040
+ if (!isHole && cand !== ctx)
114041
+ return false;
114042
+ }
114043
+ return true;
114044
+ }
113924
114045
  var LIST_INTENT_RE2, ITEM_SCHEMA_TYPES2, COLLECTION_KEYS2;
113925
114046
  var init_cardinality2 = __esm(() => {
113926
114047
  LIST_INTENT_RE2 = /\b(search|find|lookup|browse|discover|list(?:ings?)?|feed|catalog(?:ue)?)\b/i;
@@ -197284,7 +197405,7 @@ function isConcreteEntityDetailIntent(intent, contextUrl) {
197284
197405
  return false;
197285
197406
  try {
197286
197407
  const leaf = decodeURIComponent(new URL(contextUrl).pathname.split("/").filter(Boolean).pop() ?? "").toLowerCase();
197287
- return !!leaf && !/^(search|explore|trending|tabs|home|for-you|foryou|latest|live|people|posts|videos)$/.test(leaf);
197408
+ return isConcreteResourceLeaf2(leaf);
197288
197409
  } catch {
197289
197410
  return false;
197290
197411
  }
@@ -197296,7 +197417,8 @@ function marketplaceSkillMatchesContext(skill, intent, contextUrl) {
197296
197417
  if (isFeedTimelineIntent(intent, contextUrl)) {
197297
197418
  return skill.endpoints.some((endpoint) => endpointMatchesFeedTimelineContext(endpoint, contextUrl));
197298
197419
  }
197299
- if (!contextUrl || !isConcreteEntityDetailIntent(intent, contextUrl))
197420
+ const concretePath = contextUrl && urlHasConcreteResourcePath2(contextUrl);
197421
+ if (!contextUrl || !isConcreteEntityDetailIntent(intent, contextUrl) && !concretePath)
197300
197422
  return true;
197301
197423
  let contextPath = "";
197302
197424
  try {
@@ -197306,6 +197428,17 @@ function marketplaceSkillMatchesContext(skill, intent, contextUrl) {
197306
197428
  }
197307
197429
  if (!contextPath)
197308
197430
  return true;
197431
+ if (concretePath) {
197432
+ for (const endpoint of skill.endpoints ?? []) {
197433
+ let triggerPath = "";
197434
+ try {
197435
+ triggerPath = endpoint.trigger_url ? new URL(endpoint.trigger_url).pathname : "";
197436
+ } catch {}
197437
+ if (pathCoherent2(endpoint.url_template, contextPath) || triggerPath === contextPath)
197438
+ return true;
197439
+ }
197440
+ return false;
197441
+ }
197309
197442
  let hasApiLikeEndpoint = false;
197310
197443
  for (const endpoint of skill.endpoints ?? []) {
197311
197444
  let path10 = "";
@@ -197324,6 +197457,55 @@ function marketplaceSkillMatchesContext(skill, intent, contextUrl) {
197324
197457
  }
197325
197458
  return hasApiLikeEndpoint;
197326
197459
  }
197460
+ function skillPathCoherentForConcreteUrl(skill, contextUrl) {
197461
+ if (!urlHasConcreteResourcePath2(contextUrl))
197462
+ return true;
197463
+ let contextPath = "";
197464
+ try {
197465
+ contextPath = new URL(contextUrl).pathname;
197466
+ } catch {
197467
+ return true;
197468
+ }
197469
+ return (skill.endpoints ?? []).some((ep) => {
197470
+ if (pathCoherent2(ep.url_template, contextPath))
197471
+ return true;
197472
+ try {
197473
+ return ep.trigger_url ? new URL(ep.trigger_url).pathname === contextPath : false;
197474
+ } catch {
197475
+ return false;
197476
+ }
197477
+ });
197478
+ }
197479
+ async function fetchLiteralConcreteBody(url) {
197480
+ try {
197481
+ const res = await fetch(url, {
197482
+ headers: { Accept: "*/*", "User-Agent": "unbrowse/1.0" },
197483
+ signal: AbortSignal.timeout(15000),
197484
+ redirect: "follow"
197485
+ });
197486
+ if (!res.ok)
197487
+ return null;
197488
+ const ct = res.headers.get("content-type") ?? "";
197489
+ const body = await res.text();
197490
+ if (!(body.length > 0 && body.length < 2000000))
197491
+ return null;
197492
+ const trimmed = body.trimStart();
197493
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
197494
+ try {
197495
+ const parsed = JSON.parse(body);
197496
+ if (parsed !== null && typeof parsed === "object")
197497
+ return { result: parsed, content_type: ct };
197498
+ } catch {}
197499
+ }
197500
+ return {
197501
+ result: { url, content_type: ct, text: body, source_url: url, extraction: { source: "direct-fetch", rejected: false } },
197502
+ content_type: ct
197503
+ };
197504
+ } catch (e) {
197505
+ console.log(`[direct-fetch] ${url} literal concrete fetch failed: ${e instanceof Error ? e.message : String(e)} — falling through to skill`);
197506
+ return null;
197507
+ }
197508
+ }
197327
197509
  function prioritizeIntentMatchedApis(ranked, intent, contextUrl) {
197328
197510
  const preferred = inferPreferredEntityTokens(intent);
197329
197511
  if (preferred.length === 0)
@@ -198886,6 +199068,27 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
198886
199068
  timing: finalize("marketplace", w.data, w.skill.skill_id, w.skill, recipeTrace)
198887
199069
  };
198888
199070
  }
199071
+ if ((w.kind === "marketplace" || w.kind === "local-skill") && urlHasConcreteResourcePath2(raceContextUrl) && !skillPathCoherentForConcreteUrl(w.skill, raceContextUrl)) {
199072
+ const literal = await fetchLiteralConcreteBody(raceContextUrl);
199073
+ if (literal) {
199074
+ const trace2 = {
199075
+ trace_id: nanoid(),
199076
+ skill_id: "direct-fetch",
199077
+ endpoint_id: "direct-fetch",
199078
+ started_at: new Date(t0).toISOString(),
199079
+ completed_at: new Date().toISOString(),
199080
+ success: true
199081
+ };
199082
+ console.log(`[direct-fetch] ${raceContextUrl} concrete-resource literal URL preferred over non-path-coherent skill ${w.skill.skill_id} (ct=${literal.content_type})`);
199083
+ return {
199084
+ result: literal.result,
199085
+ trace: trace2,
199086
+ source: "direct-fetch",
199087
+ skill: undefined,
199088
+ timing: finalize("direct-fetch", literal.result, "direct-fetch", undefined, trace2)
199089
+ };
199090
+ }
199091
+ }
198889
199092
  if (w.kind === "marketplace") {
198890
199093
  return buildDeferral(w.skill, "marketplace", { decision_trace: decisionTrace });
198891
199094
  }
@@ -198914,6 +199117,46 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
198914
199117
  }
198915
199118
  console.log(`[direct-fetch] ${raceContextUrl} probe said JSON but direct fetch yielded no usable JSON — falling through to exa`);
198916
199119
  }
199120
+ if (w.kind === "probe" && w.status >= 200 && w.status < 400 && !probeLooksLikeDirectJsonApi(w) && !probeLooksLikeFetchableHtmlDocument(w) && urlHasConcreteResourcePath2(raceContextUrl)) {
199121
+ try {
199122
+ const litRes = await fetch(raceContextUrl, {
199123
+ headers: { Accept: "*/*", "User-Agent": "unbrowse/1.0" },
199124
+ signal: AbortSignal.timeout(15000),
199125
+ redirect: "follow"
199126
+ });
199127
+ if (litRes.ok) {
199128
+ const ct = litRes.headers.get("content-type") ?? "";
199129
+ const body = await litRes.text();
199130
+ if (body.length > 0 && body.length < 2000000) {
199131
+ const trace2 = {
199132
+ trace_id: nanoid(),
199133
+ skill_id: "direct-fetch",
199134
+ endpoint_id: "direct-fetch",
199135
+ started_at: new Date(t0).toISOString(),
199136
+ completed_at: new Date().toISOString(),
199137
+ success: true
199138
+ };
199139
+ const result2 = {
199140
+ url: raceContextUrl,
199141
+ content_type: ct,
199142
+ text: body,
199143
+ source_url: raceContextUrl,
199144
+ extraction: { source: "direct-fetch", rejected: false }
199145
+ };
199146
+ console.log(`[direct-fetch] ${raceContextUrl} concrete-resource literal URL — direct fetch over exa (ct=${ct}, ${body.length}B)`);
199147
+ return {
199148
+ result: result2,
199149
+ trace: trace2,
199150
+ source: "direct-fetch",
199151
+ skill: undefined,
199152
+ timing: finalize("direct-fetch", result2, "direct-fetch", undefined, trace2)
199153
+ };
199154
+ }
199155
+ }
199156
+ } catch (e) {
199157
+ console.log(`[direct-fetch] ${raceContextUrl} concrete-resource literal fetch failed: ${e instanceof Error ? e.message : String(e)} — falling through to exa`);
199158
+ }
199159
+ }
198917
199160
  if (w.kind === "probe" && probeLooksLikeFetchableHtmlDocument(w)) {
198918
199161
  const directDoc = await fetchDirectDocument(raceContextUrl);
198919
199162
  if (directDoc && !directDoc.rejected) {
@@ -304031,7 +304274,7 @@ async function cmdResolve(flags) {
304031
304274
  if (resolveCacheSafe(flags)) {
304032
304275
  const cachedHit = peekResolution(resolveCacheKeyFor(flags, intent), resolveCacheTtlMs());
304033
304276
  const cachedData = cachedHit ? cachedHit.result ?? cachedHit.data : undefined;
304034
- if (cachedHit && resolutionCardinalityMatches(intent, cachedData) && resolutionHostMatches(typeof flags.url === "string" ? flags.url : undefined, cachedData)) {
304277
+ if (cachedHit && resolutionCardinalityMatches(intent, cachedData) && resolutionHostMatches(typeof flags.url === "string" ? flags.url : undefined, cachedData) && resolutionPathMatches(typeof flags.url === "string" ? flags.url : undefined, cachedData)) {
304035
304278
  const replay = markResolveCacheReplay(cachedHit);
304036
304279
  const hostType2 = detectTelemetryHostType2();
304037
304280
  if (process.env.UNBROWSE_LANDING_TOKEN || process.env.UNBROWSE_ATTRIBUTION_B64) {
package/runtime/mcp.js CHANGED
@@ -101443,7 +101443,7 @@ async function mergedAuthHeaders(key, signer) {
101443
101443
  var AUTH_DOMAIN = "unbrowse-auth:v1";
101444
101444
 
101445
101445
  // .tmp-runtime-src/build-info.generated.ts
101446
- var BUILD_RELEASE_VERSION = "10.1.3", BUILD_GIT_SHA = "de11df6cf838", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMTAuMS4zIiwiZ2l0X3NoYSI6ImRlMTFkZjZjZjgzOCIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFAZGUxMWRmNmNmODM4IiwiaXNzdWVkX2F0IjoiMjAyNi0wNi0yM1QwOTowMzoyNC4wODlaIn0", BUILD_RELEASE_MANIFEST_SIGNATURE = "tQDAYXIj-Q4C-i2E4CTsKtHaEiTFy7uzrDQDxDjqO6o", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
101446
+ var BUILD_RELEASE_VERSION = "10.1.4", BUILD_GIT_SHA = "089d49f75f26", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMTAuMS40IiwiZ2l0X3NoYSI6IjA4OWQ0OWY3NWYyNiIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFAMDg5ZDQ5Zjc1ZjI2IiwiaXNzdWVkX2F0IjoiMjAyNi0wNi0yM1QxMDowNjoyMy45MjNaIn0", BUILD_RELEASE_MANIFEST_SIGNATURE = "cDbcbJgh0OyGCynwPC9q8d8xvPCtfzsY9H0lAtidjN4", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
101447
101447
 
101448
101448
  // .tmp-runtime-src/version.ts
101449
101449
  import { createHash as createHash6 } from "crypto";
@@ -104975,6 +104975,83 @@ function resolutionHostMatches(url, data) {
104975
104975
  return true;
104976
104976
  return hosts.some((h) => h === reqHost);
104977
104977
  }
104978
+ function isConcreteResourceLeaf(leaf) {
104979
+ return !!leaf && !/^(search|explore|trending|tabs|home|for-you|foryou|latest|live|people|posts|videos)$/.test(leaf);
104980
+ }
104981
+ function urlHasConcreteResourcePath(url) {
104982
+ if (!url)
104983
+ return false;
104984
+ try {
104985
+ const segments = new URL(url).pathname.split("/").filter(Boolean);
104986
+ if (segments.length === 0)
104987
+ return false;
104988
+ const leaf = decodeURIComponent(segments[segments.length - 1] ?? "").toLowerCase();
104989
+ return isConcreteResourceLeaf(leaf);
104990
+ } catch {
104991
+ return false;
104992
+ }
104993
+ }
104994
+ function pathCoherent(candidate, contextPath) {
104995
+ const toPath = (s) => {
104996
+ try {
104997
+ return new URL(s).pathname;
104998
+ } catch {
104999
+ return s;
105000
+ }
105001
+ };
105002
+ const decodeSeg = (s) => {
105003
+ try {
105004
+ return decodeURIComponent(s);
105005
+ } catch {
105006
+ return s;
105007
+ }
105008
+ };
105009
+ const candSegments = toPath(candidate).split("/").filter(Boolean).map(decodeSeg);
105010
+ const ctxSegments = toPath(contextPath).split("/").filter(Boolean).map(decodeSeg);
105011
+ if (candSegments.length !== ctxSegments.length)
105012
+ return false;
105013
+ for (let i = 0;i < candSegments.length; i++) {
105014
+ const cand = candSegments[i] ?? "";
105015
+ const ctx = ctxSegments[i] ?? "";
105016
+ const isHole = /^\{[^}]*\}$/.test(cand);
105017
+ if (!isHole && cand !== ctx)
105018
+ return false;
105019
+ }
105020
+ return true;
105021
+ }
105022
+ function collectRecordUrls(data) {
105023
+ const out = [];
105024
+ const push = (rec) => {
105025
+ if (!rec || typeof rec !== "object")
105026
+ return;
105027
+ const r = rec;
105028
+ for (const k of ["url", "link", "href", "source_url", "url_template"]) {
105029
+ const v = r[k];
105030
+ if (typeof v === "string" && v)
105031
+ out.push(v);
105032
+ }
105033
+ };
105034
+ if (Array.isArray(data))
105035
+ for (const rec of data.slice(0, 20))
105036
+ push(rec);
105037
+ else
105038
+ push(data);
105039
+ return out;
105040
+ }
105041
+ function resolutionPathMatches(url, data) {
105042
+ if (!urlHasConcreteResourcePath(url))
105043
+ return true;
105044
+ let contextPath = "";
105045
+ try {
105046
+ contextPath = new URL(url).pathname;
105047
+ } catch {
105048
+ return true;
105049
+ }
105050
+ const urls = collectRecordUrls(data);
105051
+ if (urls.length === 0)
105052
+ return true;
105053
+ return urls.some((u) => pathCoherent(u, contextPath));
105054
+ }
104978
105055
  var LIST_INTENT_RE, ITEM_SCHEMA_TYPES, COLLECTION_KEYS;
104979
105056
  var init_cardinality = __esm(() => {
104980
105057
  LIST_INTENT_RE = /\b(search|find|lookup|browse|discover|list(?:ings?)?|feed|catalog(?:ue)?)\b/i;
@@ -194465,7 +194542,7 @@ function isConcreteEntityDetailIntent(intent, contextUrl) {
194465
194542
  return false;
194466
194543
  try {
194467
194544
  const leaf = decodeURIComponent(new URL(contextUrl).pathname.split("/").filter(Boolean).pop() ?? "").toLowerCase();
194468
- return !!leaf && !/^(search|explore|trending|tabs|home|for-you|foryou|latest|live|people|posts|videos)$/.test(leaf);
194545
+ return isConcreteResourceLeaf(leaf);
194469
194546
  } catch {
194470
194547
  return false;
194471
194548
  }
@@ -194477,7 +194554,8 @@ function marketplaceSkillMatchesContext(skill, intent, contextUrl) {
194477
194554
  if (isFeedTimelineIntent(intent, contextUrl)) {
194478
194555
  return skill.endpoints.some((endpoint) => endpointMatchesFeedTimelineContext(endpoint, contextUrl));
194479
194556
  }
194480
- if (!contextUrl || !isConcreteEntityDetailIntent(intent, contextUrl))
194557
+ const concretePath = contextUrl && urlHasConcreteResourcePath(contextUrl);
194558
+ if (!contextUrl || !isConcreteEntityDetailIntent(intent, contextUrl) && !concretePath)
194481
194559
  return true;
194482
194560
  let contextPath = "";
194483
194561
  try {
@@ -194487,6 +194565,17 @@ function marketplaceSkillMatchesContext(skill, intent, contextUrl) {
194487
194565
  }
194488
194566
  if (!contextPath)
194489
194567
  return true;
194568
+ if (concretePath) {
194569
+ for (const endpoint of skill.endpoints ?? []) {
194570
+ let triggerPath = "";
194571
+ try {
194572
+ triggerPath = endpoint.trigger_url ? new URL(endpoint.trigger_url).pathname : "";
194573
+ } catch {}
194574
+ if (pathCoherent(endpoint.url_template, contextPath) || triggerPath === contextPath)
194575
+ return true;
194576
+ }
194577
+ return false;
194578
+ }
194490
194579
  let hasApiLikeEndpoint = false;
194491
194580
  for (const endpoint of skill.endpoints ?? []) {
194492
194581
  let path8 = "";
@@ -194505,6 +194594,55 @@ function marketplaceSkillMatchesContext(skill, intent, contextUrl) {
194505
194594
  }
194506
194595
  return hasApiLikeEndpoint;
194507
194596
  }
194597
+ function skillPathCoherentForConcreteUrl(skill, contextUrl) {
194598
+ if (!urlHasConcreteResourcePath(contextUrl))
194599
+ return true;
194600
+ let contextPath = "";
194601
+ try {
194602
+ contextPath = new URL(contextUrl).pathname;
194603
+ } catch {
194604
+ return true;
194605
+ }
194606
+ return (skill.endpoints ?? []).some((ep) => {
194607
+ if (pathCoherent(ep.url_template, contextPath))
194608
+ return true;
194609
+ try {
194610
+ return ep.trigger_url ? new URL(ep.trigger_url).pathname === contextPath : false;
194611
+ } catch {
194612
+ return false;
194613
+ }
194614
+ });
194615
+ }
194616
+ async function fetchLiteralConcreteBody(url) {
194617
+ try {
194618
+ const res = await fetch(url, {
194619
+ headers: { Accept: "*/*", "User-Agent": "unbrowse/1.0" },
194620
+ signal: AbortSignal.timeout(15000),
194621
+ redirect: "follow"
194622
+ });
194623
+ if (!res.ok)
194624
+ return null;
194625
+ const ct = res.headers.get("content-type") ?? "";
194626
+ const body = await res.text();
194627
+ if (!(body.length > 0 && body.length < 2000000))
194628
+ return null;
194629
+ const trimmed = body.trimStart();
194630
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
194631
+ try {
194632
+ const parsed = JSON.parse(body);
194633
+ if (parsed !== null && typeof parsed === "object")
194634
+ return { result: parsed, content_type: ct };
194635
+ } catch {}
194636
+ }
194637
+ return {
194638
+ result: { url, content_type: ct, text: body, source_url: url, extraction: { source: "direct-fetch", rejected: false } },
194639
+ content_type: ct
194640
+ };
194641
+ } catch (e) {
194642
+ console.log(`[direct-fetch] ${url} literal concrete fetch failed: ${e instanceof Error ? e.message : String(e)} — falling through to skill`);
194643
+ return null;
194644
+ }
194645
+ }
194508
194646
  function prioritizeIntentMatchedApis(ranked, intent, contextUrl) {
194509
194647
  const preferred = inferPreferredEntityTokens(intent);
194510
194648
  if (preferred.length === 0)
@@ -196067,6 +196205,27 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
196067
196205
  timing: finalize("marketplace", w.data, w.skill.skill_id, w.skill, recipeTrace)
196068
196206
  };
196069
196207
  }
196208
+ if ((w.kind === "marketplace" || w.kind === "local-skill") && urlHasConcreteResourcePath(raceContextUrl) && !skillPathCoherentForConcreteUrl(w.skill, raceContextUrl)) {
196209
+ const literal = await fetchLiteralConcreteBody(raceContextUrl);
196210
+ if (literal) {
196211
+ const trace2 = {
196212
+ trace_id: nanoid(),
196213
+ skill_id: "direct-fetch",
196214
+ endpoint_id: "direct-fetch",
196215
+ started_at: new Date(t0).toISOString(),
196216
+ completed_at: new Date().toISOString(),
196217
+ success: true
196218
+ };
196219
+ console.log(`[direct-fetch] ${raceContextUrl} concrete-resource literal URL preferred over non-path-coherent skill ${w.skill.skill_id} (ct=${literal.content_type})`);
196220
+ return {
196221
+ result: literal.result,
196222
+ trace: trace2,
196223
+ source: "direct-fetch",
196224
+ skill: undefined,
196225
+ timing: finalize("direct-fetch", literal.result, "direct-fetch", undefined, trace2)
196226
+ };
196227
+ }
196228
+ }
196070
196229
  if (w.kind === "marketplace") {
196071
196230
  return buildDeferral(w.skill, "marketplace", { decision_trace: decisionTrace });
196072
196231
  }
@@ -196095,6 +196254,46 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
196095
196254
  }
196096
196255
  console.log(`[direct-fetch] ${raceContextUrl} probe said JSON but direct fetch yielded no usable JSON — falling through to exa`);
196097
196256
  }
196257
+ if (w.kind === "probe" && w.status >= 200 && w.status < 400 && !probeLooksLikeDirectJsonApi(w) && !probeLooksLikeFetchableHtmlDocument(w) && urlHasConcreteResourcePath(raceContextUrl)) {
196258
+ try {
196259
+ const litRes = await fetch(raceContextUrl, {
196260
+ headers: { Accept: "*/*", "User-Agent": "unbrowse/1.0" },
196261
+ signal: AbortSignal.timeout(15000),
196262
+ redirect: "follow"
196263
+ });
196264
+ if (litRes.ok) {
196265
+ const ct = litRes.headers.get("content-type") ?? "";
196266
+ const body = await litRes.text();
196267
+ if (body.length > 0 && body.length < 2000000) {
196268
+ const trace2 = {
196269
+ trace_id: nanoid(),
196270
+ skill_id: "direct-fetch",
196271
+ endpoint_id: "direct-fetch",
196272
+ started_at: new Date(t0).toISOString(),
196273
+ completed_at: new Date().toISOString(),
196274
+ success: true
196275
+ };
196276
+ const result2 = {
196277
+ url: raceContextUrl,
196278
+ content_type: ct,
196279
+ text: body,
196280
+ source_url: raceContextUrl,
196281
+ extraction: { source: "direct-fetch", rejected: false }
196282
+ };
196283
+ console.log(`[direct-fetch] ${raceContextUrl} concrete-resource literal URL — direct fetch over exa (ct=${ct}, ${body.length}B)`);
196284
+ return {
196285
+ result: result2,
196286
+ trace: trace2,
196287
+ source: "direct-fetch",
196288
+ skill: undefined,
196289
+ timing: finalize("direct-fetch", result2, "direct-fetch", undefined, trace2)
196290
+ };
196291
+ }
196292
+ }
196293
+ } catch (e) {
196294
+ console.log(`[direct-fetch] ${raceContextUrl} concrete-resource literal fetch failed: ${e instanceof Error ? e.message : String(e)} — falling through to exa`);
196295
+ }
196296
+ }
196098
196297
  if (w.kind === "probe" && probeLooksLikeFetchableHtmlDocument(w)) {
196099
196298
  const directDoc = await fetchDirectDocument(raceContextUrl);
196100
196299
  if (directDoc && !directDoc.rejected) {
@@ -296280,7 +296479,7 @@ async function cmdResolve(flags) {
296280
296479
  if (resolveCacheSafe(flags)) {
296281
296480
  const cachedHit = peekResolution(resolveCacheKeyFor(flags, intent), resolveCacheTtlMs());
296282
296481
  const cachedData = cachedHit ? cachedHit.result ?? cachedHit.data : undefined;
296283
- if (cachedHit && resolutionCardinalityMatches(intent, cachedData) && resolutionHostMatches(typeof flags.url === "string" ? flags.url : undefined, cachedData)) {
296482
+ if (cachedHit && resolutionCardinalityMatches(intent, cachedData) && resolutionHostMatches(typeof flags.url === "string" ? flags.url : undefined, cachedData) && resolutionPathMatches(typeof flags.url === "string" ? flags.url : undefined, cachedData)) {
296284
296483
  const replay = markResolveCacheReplay(cachedHit);
296285
296484
  const hostType2 = detectTelemetryHostType();
296286
296485
  if (process.env.UNBROWSE_LANDING_TOKEN || process.env.UNBROWSE_ATTRIBUTION_B64) {
@@ -301630,7 +301829,7 @@ function isConcreteEntityDetailIntent2(intent, contextUrl) {
301630
301829
  return false;
301631
301830
  try {
301632
301831
  const leaf = decodeURIComponent(new URL(contextUrl).pathname.split("/").filter(Boolean).pop() ?? "").toLowerCase();
301633
- return !!leaf && !/^(search|explore|trending|tabs|home|for-you|foryou|latest|live|people|posts|videos)$/.test(leaf);
301832
+ return isConcreteResourceLeaf(leaf);
301634
301833
  } catch {
301635
301834
  return false;
301636
301835
  }
@@ -301642,7 +301841,8 @@ function marketplaceSkillMatchesContext2(skill, intent, contextUrl) {
301642
301841
  if (isFeedTimelineIntent2(intent, contextUrl)) {
301643
301842
  return skill.endpoints.some((endpoint) => endpointMatchesFeedTimelineContext2(endpoint, contextUrl));
301644
301843
  }
301645
- if (!contextUrl || !isConcreteEntityDetailIntent2(intent, contextUrl))
301844
+ const concretePath = contextUrl && urlHasConcreteResourcePath(contextUrl);
301845
+ if (!contextUrl || !isConcreteEntityDetailIntent2(intent, contextUrl) && !concretePath)
301646
301846
  return true;
301647
301847
  let contextPath = "";
301648
301848
  try {
@@ -301652,6 +301852,17 @@ function marketplaceSkillMatchesContext2(skill, intent, contextUrl) {
301652
301852
  }
301653
301853
  if (!contextPath)
301654
301854
  return true;
301855
+ if (concretePath) {
301856
+ for (const endpoint of skill.endpoints ?? []) {
301857
+ let triggerPath = "";
301858
+ try {
301859
+ triggerPath = endpoint.trigger_url ? new URL(endpoint.trigger_url).pathname : "";
301860
+ } catch {}
301861
+ if (pathCoherent(endpoint.url_template, contextPath) || triggerPath === contextPath)
301862
+ return true;
301863
+ }
301864
+ return false;
301865
+ }
301655
301866
  let hasApiLikeEndpoint = false;
301656
301867
  for (const endpoint of skill.endpoints ?? []) {
301657
301868
  let path27 = "";
@@ -301670,6 +301881,55 @@ function marketplaceSkillMatchesContext2(skill, intent, contextUrl) {
301670
301881
  }
301671
301882
  return hasApiLikeEndpoint;
301672
301883
  }
301884
+ function skillPathCoherentForConcreteUrl2(skill, contextUrl) {
301885
+ if (!urlHasConcreteResourcePath(contextUrl))
301886
+ return true;
301887
+ let contextPath = "";
301888
+ try {
301889
+ contextPath = new URL(contextUrl).pathname;
301890
+ } catch {
301891
+ return true;
301892
+ }
301893
+ return (skill.endpoints ?? []).some((ep) => {
301894
+ if (pathCoherent(ep.url_template, contextPath))
301895
+ return true;
301896
+ try {
301897
+ return ep.trigger_url ? new URL(ep.trigger_url).pathname === contextPath : false;
301898
+ } catch {
301899
+ return false;
301900
+ }
301901
+ });
301902
+ }
301903
+ async function fetchLiteralConcreteBody2(url) {
301904
+ try {
301905
+ const res = await fetch(url, {
301906
+ headers: { Accept: "*/*", "User-Agent": "unbrowse/1.0" },
301907
+ signal: AbortSignal.timeout(15000),
301908
+ redirect: "follow"
301909
+ });
301910
+ if (!res.ok)
301911
+ return null;
301912
+ const ct = res.headers.get("content-type") ?? "";
301913
+ const body = await res.text();
301914
+ if (!(body.length > 0 && body.length < 2000000))
301915
+ return null;
301916
+ const trimmed = body.trimStart();
301917
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
301918
+ try {
301919
+ const parsed = JSON.parse(body);
301920
+ if (parsed !== null && typeof parsed === "object")
301921
+ return { result: parsed, content_type: ct };
301922
+ } catch {}
301923
+ }
301924
+ return {
301925
+ result: { url, content_type: ct, text: body, source_url: url, extraction: { source: "direct-fetch", rejected: false } },
301926
+ content_type: ct
301927
+ };
301928
+ } catch (e) {
301929
+ console.log(`[direct-fetch] ${url} literal concrete fetch failed: ${e instanceof Error ? e.message : String(e)} — falling through to skill`);
301930
+ return null;
301931
+ }
301932
+ }
301673
301933
  function prioritizeIntentMatchedApis2(ranked, intent, contextUrl) {
301674
301934
  const preferred = inferPreferredEntityTokens2(intent);
301675
301935
  if (preferred.length === 0)
@@ -303232,6 +303492,27 @@ async function resolveAndExecute2(intent, params = {}, context, projection, opti
303232
303492
  timing: finalize("marketplace", w.data, w.skill.skill_id, w.skill, recipeTrace)
303233
303493
  };
303234
303494
  }
303495
+ if ((w.kind === "marketplace" || w.kind === "local-skill") && urlHasConcreteResourcePath(raceContextUrl) && !skillPathCoherentForConcreteUrl2(w.skill, raceContextUrl)) {
303496
+ const literal = await fetchLiteralConcreteBody2(raceContextUrl);
303497
+ if (literal) {
303498
+ const trace2 = {
303499
+ trace_id: nanoid(),
303500
+ skill_id: "direct-fetch",
303501
+ endpoint_id: "direct-fetch",
303502
+ started_at: new Date(t0).toISOString(),
303503
+ completed_at: new Date().toISOString(),
303504
+ success: true
303505
+ };
303506
+ console.log(`[direct-fetch] ${raceContextUrl} concrete-resource literal URL preferred over non-path-coherent skill ${w.skill.skill_id} (ct=${literal.content_type})`);
303507
+ return {
303508
+ result: literal.result,
303509
+ trace: trace2,
303510
+ source: "direct-fetch",
303511
+ skill: undefined,
303512
+ timing: finalize("direct-fetch", literal.result, "direct-fetch", undefined, trace2)
303513
+ };
303514
+ }
303515
+ }
303235
303516
  if (w.kind === "marketplace") {
303236
303517
  return buildDeferral(w.skill, "marketplace", { decision_trace: decisionTrace });
303237
303518
  }
@@ -303260,6 +303541,46 @@ async function resolveAndExecute2(intent, params = {}, context, projection, opti
303260
303541
  }
303261
303542
  console.log(`[direct-fetch] ${raceContextUrl} probe said JSON but direct fetch yielded no usable JSON — falling through to exa`);
303262
303543
  }
303544
+ if (w.kind === "probe" && w.status >= 200 && w.status < 400 && !probeLooksLikeDirectJsonApi2(w) && !probeLooksLikeFetchableHtmlDocument2(w) && urlHasConcreteResourcePath(raceContextUrl)) {
303545
+ try {
303546
+ const litRes = await fetch(raceContextUrl, {
303547
+ headers: { Accept: "*/*", "User-Agent": "unbrowse/1.0" },
303548
+ signal: AbortSignal.timeout(15000),
303549
+ redirect: "follow"
303550
+ });
303551
+ if (litRes.ok) {
303552
+ const ct = litRes.headers.get("content-type") ?? "";
303553
+ const body = await litRes.text();
303554
+ if (body.length > 0 && body.length < 2000000) {
303555
+ const trace2 = {
303556
+ trace_id: nanoid(),
303557
+ skill_id: "direct-fetch",
303558
+ endpoint_id: "direct-fetch",
303559
+ started_at: new Date(t0).toISOString(),
303560
+ completed_at: new Date().toISOString(),
303561
+ success: true
303562
+ };
303563
+ const result2 = {
303564
+ url: raceContextUrl,
303565
+ content_type: ct,
303566
+ text: body,
303567
+ source_url: raceContextUrl,
303568
+ extraction: { source: "direct-fetch", rejected: false }
303569
+ };
303570
+ console.log(`[direct-fetch] ${raceContextUrl} concrete-resource literal URL — direct fetch over exa (ct=${ct}, ${body.length}B)`);
303571
+ return {
303572
+ result: result2,
303573
+ trace: trace2,
303574
+ source: "direct-fetch",
303575
+ skill: undefined,
303576
+ timing: finalize("direct-fetch", result2, "direct-fetch", undefined, trace2)
303577
+ };
303578
+ }
303579
+ }
303580
+ } catch (e) {
303581
+ console.log(`[direct-fetch] ${raceContextUrl} concrete-resource literal fetch failed: ${e instanceof Error ? e.message : String(e)} — falling through to exa`);
303582
+ }
303583
+ }
303263
303584
  if (w.kind === "probe" && probeLooksLikeFetchableHtmlDocument2(w)) {
303264
303585
  const directDoc = await fetchDirectDocument(raceContextUrl);
303265
303586
  if (directDoc && !directDoc.rejected) {