unbrowse 9.6.0 → 9.6.1

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": "9.6.0",
3
+ "version": "9.6.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/unbrowse-ai/unbrowse.git"
package/runtime/cli.js CHANGED
@@ -1730,6 +1730,69 @@ var init_cached_resolution = __esm(() => {
1730
1730
  init_principal_scope();
1731
1731
  });
1732
1732
 
1733
+ // .tmp-runtime-src/values/cardinality.ts
1734
+ function isListLikeIntent(intent) {
1735
+ return LIST_INTENT_RE.test(intent ?? "");
1736
+ }
1737
+ function valueLooksLikeSingleItem(value) {
1738
+ if (value == null || Array.isArray(value) || typeof value !== "object")
1739
+ return false;
1740
+ const obj = value;
1741
+ for (const key of COLLECTION_KEYS) {
1742
+ if (Array.isArray(obj[key]))
1743
+ return false;
1744
+ }
1745
+ for (const v of Object.values(obj)) {
1746
+ if (Array.isArray(v) && v.some((x) => x !== null && typeof x === "object"))
1747
+ return false;
1748
+ }
1749
+ const atType = typeof obj["@type"] === "string" ? obj["@type"].toLowerCase() : "";
1750
+ const isItemType = ITEM_SCHEMA_TYPES.has(atType);
1751
+ const hasName = "name" in obj || "title" in obj || "headline" in obj;
1752
+ const hasPriceish = "offers" in obj || "price" in obj || "sku" in obj;
1753
+ return isItemType || hasName && hasPriceish;
1754
+ }
1755
+ function resolutionCardinalityMatches(intent, data) {
1756
+ if (!isListLikeIntent(intent))
1757
+ return true;
1758
+ return !valueLooksLikeSingleItem(data);
1759
+ }
1760
+ var LIST_INTENT_RE, ITEM_SCHEMA_TYPES, COLLECTION_KEYS;
1761
+ var init_cardinality = __esm(() => {
1762
+ LIST_INTENT_RE = /\b(search|find|lookup|browse|discover|list(?:ings?)?|feed|catalog(?:ue)?)\b/i;
1763
+ ITEM_SCHEMA_TYPES = new Set([
1764
+ "product",
1765
+ "offer",
1766
+ "article",
1767
+ "newsarticle",
1768
+ "blogposting",
1769
+ "recipe",
1770
+ "event",
1771
+ "place",
1772
+ "localbusiness",
1773
+ "jobposting",
1774
+ "book",
1775
+ "movie",
1776
+ "creativework",
1777
+ "person",
1778
+ "organization"
1779
+ ]);
1780
+ COLLECTION_KEYS = [
1781
+ "itemListElement",
1782
+ "items",
1783
+ "results",
1784
+ "products",
1785
+ "listings",
1786
+ "data",
1787
+ "edges",
1788
+ "hits",
1789
+ "records",
1790
+ "entries",
1791
+ "rows",
1792
+ "nodes"
1793
+ ];
1794
+ });
1795
+
1733
1796
  // .tmp-runtime-src/values/cache-key.ts
1734
1797
  function requestCacheKey(parts) {
1735
1798
  const method = (parts.method ?? "GET").toUpperCase();
@@ -2223,7 +2286,7 @@ var init_telemetry = __esm(() => {
2223
2286
  });
2224
2287
 
2225
2288
  // .tmp-runtime-src/build-info.generated.ts
2226
- var BUILD_RELEASE_VERSION = "9.6.0", BUILD_GIT_SHA = "5b6b9dc9e8e1", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiOS42LjAiLCJnaXRfc2hhIjoiNWI2YjlkYzllOGUxIiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUA1YjZiOWRjOWU4ZTEiLCJpc3N1ZWRfYXQiOiIyMDI2LTA2LTE3VDIyOjAyOjQ0LjA3MVoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "MqIyb1B_GA8W5Nv_Jictwt1jVCCTgxxdIjUFJqLoeAU", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
2289
+ var BUILD_RELEASE_VERSION = "9.6.1", BUILD_GIT_SHA = "7c8049ccfb77", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiOS42LjEiLCJnaXRfc2hhIjoiN2M4MDQ5Y2NmYjc3IiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUA3YzgwNDljY2ZiNzciLCJpc3N1ZWRfYXQiOiIyMDI2LTA2LTE4VDAzOjA1OjI0LjExOVoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "EvwEtBNSpI-heDzj2LEUfGnS7PdM_EEZif1VhvQBaz8", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
2227
2290
 
2228
2291
  // .tmp-runtime-src/version.ts
2229
2292
  import { createHash as createHash7 } from "crypto";
@@ -130488,6 +130551,69 @@ function bindingGraphFromOperationGraph(og) {
130488
130551
  return { endpoints, edges };
130489
130552
  }
130490
130553
 
130554
+ // .tmp-runtime-src/values/cardinality.ts
130555
+ function isListLikeIntent2(intent) {
130556
+ return LIST_INTENT_RE2.test(intent ?? "");
130557
+ }
130558
+ function schemaLooksLikeSingleItem(rs) {
130559
+ if (!rs || typeof rs !== "object")
130560
+ return false;
130561
+ const schema = rs;
130562
+ if (schema.type === "array")
130563
+ return false;
130564
+ const props = schema.properties ?? {};
130565
+ for (const key2 of COLLECTION_KEYS2) {
130566
+ if (key2 in props)
130567
+ return false;
130568
+ }
130569
+ for (const value of Object.values(props)) {
130570
+ if (value && typeof value === "object" && value.type === "array" && value.items?.type === "object") {
130571
+ return false;
130572
+ }
130573
+ }
130574
+ if (schema.type !== "object")
130575
+ return false;
130576
+ const hasType = "@type" in props;
130577
+ const hasName = "name" in props || "title" in props;
130578
+ const hasPriceish = "offers" in props || "price" in props || "sku" in props;
130579
+ return hasType || hasName && hasPriceish;
130580
+ }
130581
+ var LIST_INTENT_RE2, ITEM_SCHEMA_TYPES2, COLLECTION_KEYS2;
130582
+ var init_cardinality2 = __esm(() => {
130583
+ LIST_INTENT_RE2 = /\b(search|find|lookup|browse|discover|list(?:ings?)?|feed|catalog(?:ue)?)\b/i;
130584
+ ITEM_SCHEMA_TYPES2 = new Set([
130585
+ "product",
130586
+ "offer",
130587
+ "article",
130588
+ "newsarticle",
130589
+ "blogposting",
130590
+ "recipe",
130591
+ "event",
130592
+ "place",
130593
+ "localbusiness",
130594
+ "jobposting",
130595
+ "book",
130596
+ "movie",
130597
+ "creativework",
130598
+ "person",
130599
+ "organization"
130600
+ ]);
130601
+ COLLECTION_KEYS2 = [
130602
+ "itemListElement",
130603
+ "items",
130604
+ "results",
130605
+ "products",
130606
+ "listings",
130607
+ "data",
130608
+ "edges",
130609
+ "hits",
130610
+ "records",
130611
+ "entries",
130612
+ "rows",
130613
+ "nodes"
130614
+ ];
130615
+ });
130616
+
130491
130617
  // .tmp-runtime-src/values/yield-safety.ts
130492
130618
  function tokenizeKey(key2) {
130493
130619
  return key2.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[_\-.\s]+/).map((s) => s.toLowerCase()).filter(Boolean);
@@ -132155,7 +132281,10 @@ function pickWalkTarget(requestedUrl, ranked, minScore = 0.8) {
132155
132281
  return false;
132156
132282
  }
132157
132283
  };
132158
- return eligible.find((c) => hasPath(c.url)) ?? eligible[0];
132284
+ const reqReg = registrableHost(requestedUrl);
132285
+ const sameDomain = reqReg ? eligible.filter((c) => registrableHost(c.url) === reqReg) : [];
132286
+ const pool2 = sameDomain.length > 0 ? sameDomain : eligible;
132287
+ return pool2.find((c) => hasPath(c.url)) ?? pool2[0];
132159
132288
  }
132160
132289
  function artifactResultWithShortlist(artifact, skillId, triggerUrl) {
132161
132290
  const ep = artifact.endpoint;
@@ -132616,6 +132745,26 @@ function endpointTargetsMismatchedLocalReplayHost(endpoint, contextUrl) {
132616
132745
  function endpointHasNegativeTag(endpoint, tag) {
132617
132746
  return (endpoint.semantic?.negative_tags ?? []).some((candidate) => candidate.trim().toLowerCase() === tag.trim().toLowerCase());
132618
132747
  }
132748
+ function looksLikeSingleItemRoute(endpoint) {
132749
+ const tmpl = endpoint.url_template ?? "";
132750
+ let pathAndQuery = tmpl;
132751
+ try {
132752
+ const u = new URL(tmpl);
132753
+ pathAndQuery = `${u.pathname}${u.search}`;
132754
+ } catch {}
132755
+ const lower = pathAndQuery.toLowerCase();
132756
+ if (/\/(?:search|q|categories?|browse|results?|listings|explore|discover|feed|catalog(?:ue)?|collections?|shop|all)\b/.test(lower) || /[?&](?:q|query|keyword|keywords|search|term|category|cat|page)=/.test(lower)) {
132757
+ return false;
132758
+ }
132759
+ if (/\/(?:p|product|products|item|items|listing|detail|details|dp|pd|sku)\/[^/]+/.test(lower))
132760
+ return true;
132761
+ const lastSeg = lower.split("?")[0].replace(/\/+$/, "").split("/").pop() ?? "";
132762
+ if (/-\d{3,}$/.test(lastSeg) || /^\d{3,}$/.test(lastSeg))
132763
+ return true;
132764
+ if (/\{[^}]+\}/.test(lower))
132765
+ return false;
132766
+ return schemaLooksLikeSingleItem(endpoint.response_schema);
132767
+ }
132619
132768
  function isResolveUsableEndpointForIntent(endpoint, intent, contextUrl) {
132620
132769
  if (endpointTargetsMismatchedLocalReplayHost(endpoint, contextUrl))
132621
132770
  return false;
@@ -132625,6 +132774,9 @@ function isResolveUsableEndpointForIntent(endpoint, intent, contextUrl) {
132625
132774
  if (isFeedTimelineIntent(intent, contextUrl) && endpointHasNegativeTag(endpoint, "helper")) {
132626
132775
  return false;
132627
132776
  }
132777
+ if (isSearchLikeIntent(intent, contextUrl) && looksLikeSingleItemRoute(endpoint)) {
132778
+ return false;
132779
+ }
132628
132780
  return true;
132629
132781
  }
132630
132782
  function normalizeRouteContext(url) {
@@ -132767,7 +132919,7 @@ function withContextReplayEndpoint(skill, _intent, _contextUrl) {
132767
132919
  return skill;
132768
132920
  }
132769
132921
  function isSearchLikeIntent(intent, contextUrl) {
132770
- if (/\b(search|find|lookup|browse|discover)\b/i.test(intent ?? ""))
132922
+ if (isListLikeIntent2(intent))
132771
132923
  return true;
132772
132924
  try {
132773
132925
  const pathname = contextUrl ? new URL(contextUrl).pathname.toLowerCase() : "";
@@ -137481,6 +137633,8 @@ var init_orchestrator = __esm(async () => {
137481
137633
  init_search_forms();
137482
137634
  init_ddg_search();
137483
137635
  init_cached_resolution2();
137636
+ init_cardinality2();
137637
+ init_cardinality2();
137484
137638
  init_principal_scope();
137485
137639
  init_yield_safety();
137486
137640
  init_trace_store();
@@ -239361,7 +239515,7 @@ async function cmdResolve(flags) {
239361
239515
  }
239362
239516
  if (resolveCacheSafe(flags)) {
239363
239517
  const cachedHit = peekResolution(resolveCacheKeyFor(flags, intent), resolveCacheTtlMs());
239364
- if (cachedHit) {
239518
+ if (cachedHit && resolutionCardinalityMatches(intent, cachedHit.result ?? cachedHit.data)) {
239365
239519
  const replay = markResolveCacheReplay(cachedHit);
239366
239520
  const hostType2 = detectTelemetryHostType2();
239367
239521
  if (process.env.UNBROWSE_LANDING_TOKEN || process.env.UNBROWSE_ATTRIBUTION_B64) {
@@ -239581,7 +239735,7 @@ async function cmdResolve(flags) {
239581
239735
  if (skill?.skill_id && trace) {
239582
239736
  result._feedback = `unbrowse feedback --skill ${skill.skill_id} --endpoint ${trace.endpoint_id || "?"} --rating <1-5>`;
239583
239737
  }
239584
- if (resolveCacheSafe(flags) && isResolveSuccessResult(result)) {
239738
+ if (resolveCacheSafe(flags) && isResolveSuccessResult(result) && resolutionCardinalityMatches(intent, result.result ?? result.data)) {
239585
239739
  storeResolution(resolveCacheKeyFor(flags, intent), result, resolveCacheTtlMs());
239586
239740
  }
239587
239741
  output(result, !!flags.pretty);
@@ -241712,6 +241866,7 @@ var init_cli = __esm(async () => {
241712
241866
  init_extract_auth_header();
241713
241867
  init_kuri_proxy_bridge();
241714
241868
  init_cached_resolution();
241869
+ init_cardinality();
241715
241870
  init_issue();
241716
241871
  init_client2();
241717
241872
  init_impact_log();
package/runtime/mcp.js CHANGED
@@ -36310,7 +36310,7 @@ var init_cached_resolution = __esm(() => {
36310
36310
  });
36311
36311
 
36312
36312
  // .tmp-runtime-src/build-info.generated.ts
36313
- var BUILD_RELEASE_VERSION = "9.6.0", BUILD_GIT_SHA = "5b6b9dc9e8e1", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiOS42LjAiLCJnaXRfc2hhIjoiNWI2YjlkYzllOGUxIiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUA1YjZiOWRjOWU4ZTEiLCJpc3N1ZWRfYXQiOiIyMDI2LTA2LTE3VDIyOjAyOjQ0LjA3MVoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "MqIyb1B_GA8W5Nv_Jictwt1jVCCTgxxdIjUFJqLoeAU", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
36313
+ var BUILD_RELEASE_VERSION = "9.6.1", BUILD_GIT_SHA = "7c8049ccfb77", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiOS42LjEiLCJnaXRfc2hhIjoiN2M4MDQ5Y2NmYjc3IiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUA3YzgwNDljY2ZiNzciLCJpc3N1ZWRfYXQiOiIyMDI2LTA2LTE4VDAzOjA1OjI0LjExOVoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "EvwEtBNSpI-heDzj2LEUfGnS7PdM_EEZif1VhvQBaz8", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
36314
36314
 
36315
36315
  // .tmp-runtime-src/version.ts
36316
36316
  import { createHash as createHash4 } from "crypto";
@@ -128876,6 +128876,92 @@ function bindingGraphFromOperationGraph(og) {
128876
128876
  return { endpoints, edges };
128877
128877
  }
128878
128878
 
128879
+ // .tmp-runtime-src/values/cardinality.ts
128880
+ function isListLikeIntent(intent) {
128881
+ return LIST_INTENT_RE.test(intent ?? "");
128882
+ }
128883
+ function valueLooksLikeSingleItem(value) {
128884
+ if (value == null || Array.isArray(value) || typeof value !== "object")
128885
+ return false;
128886
+ const obj = value;
128887
+ for (const key2 of COLLECTION_KEYS) {
128888
+ if (Array.isArray(obj[key2]))
128889
+ return false;
128890
+ }
128891
+ for (const v of Object.values(obj)) {
128892
+ if (Array.isArray(v) && v.some((x) => x !== null && typeof x === "object"))
128893
+ return false;
128894
+ }
128895
+ const atType = typeof obj["@type"] === "string" ? obj["@type"].toLowerCase() : "";
128896
+ const isItemType = ITEM_SCHEMA_TYPES.has(atType);
128897
+ const hasName = "name" in obj || "title" in obj || "headline" in obj;
128898
+ const hasPriceish = "offers" in obj || "price" in obj || "sku" in obj;
128899
+ return isItemType || hasName && hasPriceish;
128900
+ }
128901
+ function schemaLooksLikeSingleItem(rs) {
128902
+ if (!rs || typeof rs !== "object")
128903
+ return false;
128904
+ const schema = rs;
128905
+ if (schema.type === "array")
128906
+ return false;
128907
+ const props = schema.properties ?? {};
128908
+ for (const key2 of COLLECTION_KEYS) {
128909
+ if (key2 in props)
128910
+ return false;
128911
+ }
128912
+ for (const value of Object.values(props)) {
128913
+ if (value && typeof value === "object" && value.type === "array" && value.items?.type === "object") {
128914
+ return false;
128915
+ }
128916
+ }
128917
+ if (schema.type !== "object")
128918
+ return false;
128919
+ const hasType = "@type" in props;
128920
+ const hasName = "name" in props || "title" in props;
128921
+ const hasPriceish = "offers" in props || "price" in props || "sku" in props;
128922
+ return hasType || hasName && hasPriceish;
128923
+ }
128924
+ function resolutionCardinalityMatches(intent, data2) {
128925
+ if (!isListLikeIntent(intent))
128926
+ return true;
128927
+ return !valueLooksLikeSingleItem(data2);
128928
+ }
128929
+ var LIST_INTENT_RE, ITEM_SCHEMA_TYPES, COLLECTION_KEYS;
128930
+ var init_cardinality = __esm(() => {
128931
+ LIST_INTENT_RE = /\b(search|find|lookup|browse|discover|list(?:ings?)?|feed|catalog(?:ue)?)\b/i;
128932
+ ITEM_SCHEMA_TYPES = new Set([
128933
+ "product",
128934
+ "offer",
128935
+ "article",
128936
+ "newsarticle",
128937
+ "blogposting",
128938
+ "recipe",
128939
+ "event",
128940
+ "place",
128941
+ "localbusiness",
128942
+ "jobposting",
128943
+ "book",
128944
+ "movie",
128945
+ "creativework",
128946
+ "person",
128947
+ "organization"
128948
+ ]);
128949
+ COLLECTION_KEYS = [
128950
+ "itemListElement",
128951
+ "items",
128952
+ "results",
128953
+ "products",
128954
+ "listings",
128955
+ "data",
128956
+ "edges",
128957
+ "hits",
128958
+ "records",
128959
+ "entries",
128960
+ "rows",
128961
+ "nodes"
128962
+ ];
128963
+ });
128964
+
128879
128965
  // .tmp-runtime-src/values/yield-safety.ts
128880
128966
  function tokenizeKey(key2) {
128881
128967
  return key2.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[_\-.\s]+/).map((s) => s.toLowerCase()).filter(Boolean);
@@ -130567,7 +130653,10 @@ function pickWalkTarget(requestedUrl, ranked, minScore = 0.8) {
130567
130653
  return false;
130568
130654
  }
130569
130655
  };
130570
- return eligible.find((c) => hasPath(c.url)) ?? eligible[0];
130656
+ const reqReg = registrableHost(requestedUrl);
130657
+ const sameDomain = reqReg ? eligible.filter((c) => registrableHost(c.url) === reqReg) : [];
130658
+ const pool2 = sameDomain.length > 0 ? sameDomain : eligible;
130659
+ return pool2.find((c) => hasPath(c.url)) ?? pool2[0];
130571
130660
  }
130572
130661
  function artifactResultWithShortlist(artifact, skillId, triggerUrl) {
130573
130662
  const ep = artifact.endpoint;
@@ -131028,6 +131117,26 @@ function endpointTargetsMismatchedLocalReplayHost(endpoint, contextUrl) {
131028
131117
  function endpointHasNegativeTag(endpoint, tag) {
131029
131118
  return (endpoint.semantic?.negative_tags ?? []).some((candidate) => candidate.trim().toLowerCase() === tag.trim().toLowerCase());
131030
131119
  }
131120
+ function looksLikeSingleItemRoute(endpoint) {
131121
+ const tmpl = endpoint.url_template ?? "";
131122
+ let pathAndQuery = tmpl;
131123
+ try {
131124
+ const u = new URL(tmpl);
131125
+ pathAndQuery = `${u.pathname}${u.search}`;
131126
+ } catch {}
131127
+ const lower = pathAndQuery.toLowerCase();
131128
+ if (/\/(?:search|q|categories?|browse|results?|listings|explore|discover|feed|catalog(?:ue)?|collections?|shop|all)\b/.test(lower) || /[?&](?:q|query|keyword|keywords|search|term|category|cat|page)=/.test(lower)) {
131129
+ return false;
131130
+ }
131131
+ if (/\/(?:p|product|products|item|items|listing|detail|details|dp|pd|sku)\/[^/]+/.test(lower))
131132
+ return true;
131133
+ const lastSeg = lower.split("?")[0].replace(/\/+$/, "").split("/").pop() ?? "";
131134
+ if (/-\d{3,}$/.test(lastSeg) || /^\d{3,}$/.test(lastSeg))
131135
+ return true;
131136
+ if (/\{[^}]+\}/.test(lower))
131137
+ return false;
131138
+ return schemaLooksLikeSingleItem(endpoint.response_schema);
131139
+ }
131031
131140
  function isResolveUsableEndpointForIntent(endpoint, intent, contextUrl) {
131032
131141
  if (endpointTargetsMismatchedLocalReplayHost(endpoint, contextUrl))
131033
131142
  return false;
@@ -131037,6 +131146,9 @@ function isResolveUsableEndpointForIntent(endpoint, intent, contextUrl) {
131037
131146
  if (isFeedTimelineIntent(intent, contextUrl) && endpointHasNegativeTag(endpoint, "helper")) {
131038
131147
  return false;
131039
131148
  }
131149
+ if (isSearchLikeIntent(intent, contextUrl) && looksLikeSingleItemRoute(endpoint)) {
131150
+ return false;
131151
+ }
131040
131152
  return true;
131041
131153
  }
131042
131154
  function normalizeRouteContext(url) {
@@ -131179,7 +131291,7 @@ function withContextReplayEndpoint(skill, _intent, _contextUrl) {
131179
131291
  return skill;
131180
131292
  }
131181
131293
  function isSearchLikeIntent(intent, contextUrl) {
131182
- if (/\b(search|find|lookup|browse|discover)\b/i.test(intent ?? ""))
131294
+ if (isListLikeIntent(intent))
131183
131295
  return true;
131184
131296
  try {
131185
131297
  const pathname = contextUrl ? new URL(contextUrl).pathname.toLowerCase() : "";
@@ -135893,6 +136005,8 @@ var init_orchestrator = __esm(async () => {
135893
136005
  init_search_forms();
135894
136006
  init_ddg_search();
135895
136007
  init_cached_resolution();
136008
+ init_cardinality();
136009
+ init_cardinality();
135896
136010
  init_principal_scope();
135897
136011
  init_yield_safety();
135898
136012
  init_trace_store();
@@ -232579,7 +232693,7 @@ async function cmdResolve(flags) {
232579
232693
  }
232580
232694
  if (resolveCacheSafe(flags)) {
232581
232695
  const cachedHit = peekResolution(resolveCacheKeyFor(flags, intent), resolveCacheTtlMs());
232582
- if (cachedHit) {
232696
+ if (cachedHit && resolutionCardinalityMatches(intent, cachedHit.result ?? cachedHit.data)) {
232583
232697
  const replay = markResolveCacheReplay(cachedHit);
232584
232698
  const hostType2 = detectTelemetryHostType();
232585
232699
  if (process.env.UNBROWSE_LANDING_TOKEN || process.env.UNBROWSE_ATTRIBUTION_B64) {
@@ -232799,7 +232913,7 @@ async function cmdResolve(flags) {
232799
232913
  if (skill?.skill_id && trace) {
232800
232914
  result._feedback = `unbrowse feedback --skill ${skill.skill_id} --endpoint ${trace.endpoint_id || "?"} --rating <1-5>`;
232801
232915
  }
232802
- if (resolveCacheSafe(flags) && isResolveSuccessResult(result)) {
232916
+ if (resolveCacheSafe(flags) && isResolveSuccessResult(result) && resolutionCardinalityMatches(intent, result.result ?? result.data)) {
232803
232917
  storeResolution(resolveCacheKeyFor(flags, intent), result, resolveCacheTtlMs());
232804
232918
  }
232805
232919
  output(result, !!flags.pretty);
@@ -234916,6 +235030,7 @@ var init_cli = __esm(async () => {
234916
235030
  init_extract_auth_header();
234917
235031
  init_kuri_proxy_bridge();
234918
235032
  init_cached_resolution();
235033
+ init_cardinality();
234919
235034
  init_issue();
234920
235035
  init_client2();
234921
235036
  init_impact_log();
@@ -236206,6 +236321,7 @@ __export(exports_orchestrator, {
236206
236321
  selectSkillIdsToHydrate: () => selectSkillIdsToHydrate2,
236207
236322
  selectSearchTermsForExecution: () => selectSearchTermsForExecution2,
236208
236323
  scopedCacheKey: () => scopedCacheKey2,
236324
+ schemaLooksLikeSingleItem: () => schemaLooksLikeSingleItem,
236209
236325
  resolveEndpointTemplateBindings: () => resolveEndpointTemplateBindings2,
236210
236326
  resolveAndExecute: () => resolveAndExecute2,
236211
236327
  registrableHost: () => registrableHost2,
@@ -236220,7 +236336,9 @@ __export(exports_orchestrator, {
236220
236336
  pickPreferredSkillSnapshot: () => pickPreferredSkillSnapshot2,
236221
236337
  persistDomainCache: () => persistDomainCache2,
236222
236338
  marketplaceSkillMatchesContext: () => marketplaceSkillMatchesContext2,
236339
+ looksLikeSingleItemRoute: () => looksLikeSingleItemRoute2,
236223
236340
  isRouteCacheEntryStale: () => isRouteCacheEntryStale2,
236341
+ isResolveUsableEndpointForIntent: () => isResolveUsableEndpointForIntent2,
236224
236342
  isCachedSkillRelevantForIntent: () => isCachedSkillRelevantForIntent2,
236225
236343
  invalidateRouteCacheForDomain: () => invalidateRouteCacheForDomain3,
236226
236344
  inferSearchParamOverrides: () => inferSearchParamOverrides2,
@@ -236275,7 +236393,10 @@ function pickWalkTarget2(requestedUrl, ranked, minScore = 0.8) {
236275
236393
  return false;
236276
236394
  }
236277
236395
  };
236278
- return eligible.find((c) => hasPath(c.url)) ?? eligible[0];
236396
+ const reqReg = registrableHost2(requestedUrl);
236397
+ const sameDomain = reqReg ? eligible.filter((c) => registrableHost2(c.url) === reqReg) : [];
236398
+ const pool2 = sameDomain.length > 0 ? sameDomain : eligible;
236399
+ return pool2.find((c) => hasPath(c.url)) ?? pool2[0];
236279
236400
  }
236280
236401
  function artifactResultWithShortlist2(artifact, skillId, triggerUrl) {
236281
236402
  const ep = artifact.endpoint;
@@ -236736,6 +236857,26 @@ function endpointTargetsMismatchedLocalReplayHost2(endpoint, contextUrl) {
236736
236857
  function endpointHasNegativeTag2(endpoint, tag) {
236737
236858
  return (endpoint.semantic?.negative_tags ?? []).some((candidate) => candidate.trim().toLowerCase() === tag.trim().toLowerCase());
236738
236859
  }
236860
+ function looksLikeSingleItemRoute2(endpoint) {
236861
+ const tmpl = endpoint.url_template ?? "";
236862
+ let pathAndQuery = tmpl;
236863
+ try {
236864
+ const u = new URL(tmpl);
236865
+ pathAndQuery = `${u.pathname}${u.search}`;
236866
+ } catch {}
236867
+ const lower = pathAndQuery.toLowerCase();
236868
+ if (/\/(?:search|q|categories?|browse|results?|listings|explore|discover|feed|catalog(?:ue)?|collections?|shop|all)\b/.test(lower) || /[?&](?:q|query|keyword|keywords|search|term|category|cat|page)=/.test(lower)) {
236869
+ return false;
236870
+ }
236871
+ if (/\/(?:p|product|products|item|items|listing|detail|details|dp|pd|sku)\/[^/]+/.test(lower))
236872
+ return true;
236873
+ const lastSeg = lower.split("?")[0].replace(/\/+$/, "").split("/").pop() ?? "";
236874
+ if (/-\d{3,}$/.test(lastSeg) || /^\d{3,}$/.test(lastSeg))
236875
+ return true;
236876
+ if (/\{[^}]+\}/.test(lower))
236877
+ return false;
236878
+ return schemaLooksLikeSingleItem(endpoint.response_schema);
236879
+ }
236739
236880
  function isResolveUsableEndpointForIntent2(endpoint, intent, contextUrl) {
236740
236881
  if (endpointTargetsMismatchedLocalReplayHost2(endpoint, contextUrl))
236741
236882
  return false;
@@ -236745,6 +236886,9 @@ function isResolveUsableEndpointForIntent2(endpoint, intent, contextUrl) {
236745
236886
  if (isFeedTimelineIntent2(intent, contextUrl) && endpointHasNegativeTag2(endpoint, "helper")) {
236746
236887
  return false;
236747
236888
  }
236889
+ if (isSearchLikeIntent2(intent, contextUrl) && looksLikeSingleItemRoute2(endpoint)) {
236890
+ return false;
236891
+ }
236748
236892
  return true;
236749
236893
  }
236750
236894
  function normalizeRouteContext2(url) {
@@ -236887,7 +237031,7 @@ function withContextReplayEndpoint2(skill, _intent, _contextUrl) {
236887
237031
  return skill;
236888
237032
  }
236889
237033
  function isSearchLikeIntent2(intent, contextUrl) {
236890
- if (/\b(search|find|lookup|browse|discover)\b/i.test(intent ?? ""))
237034
+ if (isListLikeIntent(intent))
236891
237035
  return true;
236892
237036
  try {
236893
237037
  const pathname = contextUrl ? new URL(contextUrl).pathname.toLowerCase() : "";
@@ -241606,6 +241750,8 @@ var init_orchestrator2 = __esm(async () => {
241606
241750
  init_search_forms();
241607
241751
  init_ddg_search();
241608
241752
  init_cached_resolution();
241753
+ init_cardinality();
241754
+ init_cardinality();
241609
241755
  init_principal_scope();
241610
241756
  init_yield_safety();
241611
241757
  init_trace_store();
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": "149881254046a20778f642b69f20f0c6468f6fb4",
5
- "built_at": "2026-06-17T21:47:52.749Z",
5
+ "built_at": "2026-06-18T02:47:19.984Z",
6
6
  "binaries": {
7
7
  "darwin-arm64": {
8
8
  "zig_target": "aarch64-macos",
@@ -21,11 +21,11 @@
21
21
  },
22
22
  "linux-x64": {
23
23
  "zig_target": "x86_64-linux",
24
- "sha256": "250b2dfafc912dfda669416984036cf745749a0f5322c85acf0f95d7902e2dff"
24
+ "sha256": "ae7633e7140f4d98633aa28f3bcff33e1398f3caf709a530c6cd2b36c251d113"
25
25
  },
26
26
  "win-x64": {
27
27
  "zig_target": "x86_64-windows-gnu",
28
- "sha256": "f920a3a3f95e38c3245c52af11989a046a0c8c87b4091d8b3c0a1638b44b6179",
28
+ "sha256": "54a2d73ab37bd056e5e469c9c8aeb5c992645962aee10465f1452a33fab447db",
29
29
  "source": "pre-staged"
30
30
  }
31
31
  },
@@ -33,22 +33,22 @@
33
33
  "darwin-arm64": {
34
34
  "zig_target": "aarch64-macos",
35
35
  "lib": "libkuri_ffi.dylib",
36
- "sha256": "898a9290964371d9814d98de79bc62678833a0b914c47f765d46d6080ee391d5"
36
+ "sha256": "774ff424fb6a4abb2634b7a891b10fa9760474851e2e7d25ebd6701917d959db"
37
37
  },
38
38
  "darwin-x64": {
39
39
  "zig_target": "x86_64-macos",
40
40
  "lib": "libkuri_ffi.dylib",
41
- "sha256": "730a09622d95ee3a5c9f5c41a7971d8ab93e7ca401be717c54c13bbbe498f604"
41
+ "sha256": "116afae77447b5036978d883541d264edbe3a2413788e904cf77b9123c0b79c3"
42
42
  },
43
43
  "linux-arm64": {
44
44
  "zig_target": "aarch64-linux",
45
45
  "lib": "libkuri_ffi.so",
46
- "sha256": "ef27e02d48f90d159b0bbcbc35b07970354af2924653ba0b00a863d9153c0313"
46
+ "sha256": "4558df5a2057910dd646491a9de9d1e8b81e958e0d830f1b33a1d30d0d91e95f"
47
47
  },
48
48
  "linux-x64": {
49
49
  "zig_target": "x86_64-linux",
50
50
  "lib": "libkuri_ffi.so",
51
- "sha256": "de4075e2444204d2f860d1293577d4389247c6fe55049c7505196d9e8eb5f4fb"
51
+ "sha256": "b9bbb67c58aadfacbdf5304cdc7c1cea9014c6c3bb83dda7eb8661277f6c8b36"
52
52
  }
53
53
  }
54
54
  }
Binary file