unbrowse 3.2.3 → 3.3.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.2.2", BUILD_GIT_SHA = "150cce0d751e", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4yLjIiLCJnaXRfc2hhIjoiMTUwY2NlMGQ3NTFlIiwiY29kZV9oYXNoIjoiMTQ4OGZjMWQ5MmI3IiwidHJhY2VfdmVyc2lvbiI6IjE0ODhmYzFkOTJiN0AxNTBjY2UwZDc1MWUiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTA2VDExOjU4OjM1LjkxNFoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "Lfph_KbGZrv74O5Pnop_b_0GcSTspB27fOgkCMZK6tk", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
34
+ var BUILD_RELEASE_VERSION = "3.3.0", BUILD_GIT_SHA = "d503455236d3", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4zLjAiLCJnaXRfc2hhIjoiZDUwMzQ1NTIzNmQzIiwiY29kZV9oYXNoIjoiMTQ4OGZjMWQ5MmI3IiwidHJhY2VfdmVyc2lvbiI6IjE0ODhmYzFkOTJiN0BkNTAzNDU1MjM2ZDMiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTA2VDE2OjQyOjAxLjcyOFoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "QZKL6cxuZOauUsIdM3tms9r0wyOad9mfa9StUKd4v44", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
35
35
 
36
36
  // ../../src/version.ts
37
37
  import { createHash } from "crypto";
@@ -3387,7 +3387,8 @@ async function cmdResolve(flags) {
3387
3387
  params: { endpoint_id: endpointId, ...extraParams },
3388
3388
  intent,
3389
3389
  projection: { raw: true },
3390
- ...flags["confirm-third-party-terms"] ? { confirm_third_party_terms: true } : {}
3390
+ ...flags["confirm-third-party-terms"] ? { confirm_third_party_terms: true } : {},
3391
+ ...flags["skip-robots"] ? { skip_robots_check: true } : {}
3391
3392
  };
3392
3393
  }, endpointNeedsThirdPartyTermsConfirmation = function(endpoint) {
3393
3394
  return endpoint.requires_third_party_terms_confirmation === true;
@@ -3419,6 +3420,8 @@ async function cmdResolve(flags) {
3419
3420
  body.confirm_third_party_terms = true;
3420
3421
  if (flags["force-capture"])
3421
3422
  body.force_capture = true;
3423
+ if (flags["skip-robots"])
3424
+ body.skip_robots_check = true;
3422
3425
  body.projection = { raw: true };
3423
3426
  const startedAt = Date.now();
3424
3427
  async function resolveOnce(message = "Still working. Searching cached routes...") {
@@ -3628,6 +3631,8 @@ async function cmdExecute(flags) {
3628
3631
  body.confirm_unsafe = true;
3629
3632
  if (flags["confirm-third-party-terms"])
3630
3633
  body.confirm_third_party_terms = true;
3634
+ if (flags["skip-robots"])
3635
+ body.skip_robots_check = true;
3631
3636
  body.projection = { raw: true };
3632
3637
  let result = await withPendingNotice(api2("POST", `/v1/skills/${skillId}/execute`, body), "Still working. This endpoint may require browser replay or first-time auth/capture setup.");
3633
3638
  if (isResolveSuccessResult(result)) {
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.2.2";
229
- var BUILD_GIT_SHA = "150cce0d751e";
228
+ var BUILD_RELEASE_VERSION = "3.3.0";
229
+ var BUILD_GIT_SHA = "d503455236d3";
230
230
  var BUILD_CODE_HASH = "1488fc1d92b7";
231
- var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4yLjIiLCJnaXRfc2hhIjoiMTUwY2NlMGQ3NTFlIiwiY29kZV9oYXNoIjoiMTQ4OGZjMWQ5MmI3IiwidHJhY2VfdmVyc2lvbiI6IjE0ODhmYzFkOTJiN0AxNTBjY2UwZDc1MWUiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTA2VDExOjU4OjM1LjkxNFoifQ";
232
- var BUILD_RELEASE_MANIFEST_SIGNATURE = "Lfph_KbGZrv74O5Pnop_b_0GcSTspB27fOgkCMZK6tk";
231
+ var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4zLjAiLCJnaXRfc2hhIjoiZDUwMzQ1NTIzNmQzIiwiY29kZV9oYXNoIjoiMTQ4OGZjMWQ5MmI3IiwidHJhY2VfdmVyc2lvbiI6IjE0ODhmYzFkOTJiN0BkNTAzNDU1MjM2ZDMiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTA2VDE2OjQyOjAxLjcyOFoifQ";
232
+ var BUILD_RELEASE_MANIFEST_SIGNATURE = "QZKL6cxuZOauUsIdM3tms9r0wyOad9mfa9StUKd4v44";
233
233
  var BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
234
234
 
235
235
  // ../../src/version.ts
@@ -1658,6 +1658,7 @@ var tools = [
1658
1658
  dry_run: { type: "boolean", description: "Preview unsafe calls without applying them." },
1659
1659
  confirm_third_party_terms: { type: "boolean", description: "Explicitly confirm policy-sensitive third-party terms risk for flagged domains/actions." },
1660
1660
  force_capture: { type: "boolean", description: "Bypass cache and re-capture the exact URL." },
1661
+ skip_robots: { type: "boolean", description: "Bypass robots.txt compliance check." },
1661
1662
  raw: { type: "boolean", description: "Keep raw projection enabled. Default true." },
1662
1663
  schema: { type: "boolean", description: "Return a schema tree instead of data." },
1663
1664
  path: { type: "string", description: "Drill into the result before returning it, e.g. data.items[] ." },
@@ -1692,6 +1693,8 @@ var tools = [
1692
1693
  body.confirm_third_party_terms = true;
1693
1694
  if (args.force_capture === true)
1694
1695
  body.force_capture = true;
1696
+ if (args.skip_robots === true)
1697
+ body.skip_robots_check = true;
1695
1698
  let result = await api2("POST", "/v1/intent/resolve", body);
1696
1699
  const authError = resolveNestedError(result);
1697
1700
  if (authError === "auth_required") {
@@ -1725,6 +1728,7 @@ var tools = [
1725
1728
  dry_run: { type: "boolean", description: "Preview unsafe calls without applying them." },
1726
1729
  confirm_unsafe: { type: "boolean", description: "Confirm mutation if the endpoint is unsafe." },
1727
1730
  confirm_third_party_terms: { type: "boolean", description: "Explicitly confirm policy-sensitive third-party terms risk for flagged domains/actions." },
1731
+ skip_robots: { type: "boolean", description: "Bypass robots.txt compliance check." },
1728
1732
  raw: { type: "boolean", description: "Keep raw projection enabled. Default true." },
1729
1733
  schema: { type: "boolean", description: "Return a schema tree instead of data." },
1730
1734
  path: { type: "string", description: "Drill into the result before returning it, e.g. data.items[] ." },
@@ -1754,6 +1758,8 @@ var tools = [
1754
1758
  body.confirm_unsafe = true;
1755
1759
  if (args.confirm_third_party_terms === true)
1756
1760
  body.confirm_third_party_terms = true;
1761
+ if (args.skip_robots === true)
1762
+ body.skip_robots_check = true;
1757
1763
  const result = await api2("POST", `/v1/skills/${args.skill}/execute`, body);
1758
1764
  const nestedError = resolveNestedError(result);
1759
1765
  recordImpactForTool("execute", result, args);
package/dist/server.js CHANGED
@@ -6227,12 +6227,17 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
6227
6227
  }
6228
6228
  }
6229
6229
  let harEntries = [];
6230
- try {
6231
- const harPromise = harStop(tabId);
6232
- const timeoutPromise = new Promise((resolve) => setTimeout(() => resolve({ entries: [] }), 5000));
6233
- const harResult = await Promise.race([harPromise, timeoutPromise]);
6234
- harEntries = harResult.entries ?? [];
6235
- } catch {}
6230
+ if (cdpRequestMap.size === 0) {
6231
+ try {
6232
+ const harResult = await Promise.race([
6233
+ harStop(tabId),
6234
+ new Promise((r) => setTimeout(() => r({ entries: [] }), 5000))
6235
+ ]);
6236
+ harEntries = harResult.entries ?? [];
6237
+ } catch {}
6238
+ } else {
6239
+ harStop(tabId).catch(() => {});
6240
+ }
6236
6241
  if (cdpPendingBodies.size > 0) {
6237
6242
  await new Promise((r) => setTimeout(r, 1500));
6238
6243
  }
@@ -6879,7 +6884,7 @@ var init_capture = __esm(async () => {
6879
6884
  });
6880
6885
 
6881
6886
  // ../../src/build-info.generated.ts
6882
- var BUILD_RELEASE_VERSION = "3.2.2", BUILD_GIT_SHA = "150cce0d751e", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4yLjIiLCJnaXRfc2hhIjoiMTUwY2NlMGQ3NTFlIiwiY29kZV9oYXNoIjoiMTQ4OGZjMWQ5MmI3IiwidHJhY2VfdmVyc2lvbiI6IjE0ODhmYzFkOTJiN0AxNTBjY2UwZDc1MWUiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTA2VDExOjU4OjM1LjkxNFoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "Lfph_KbGZrv74O5Pnop_b_0GcSTspB27fOgkCMZK6tk", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
6887
+ var BUILD_RELEASE_VERSION = "3.3.0", BUILD_GIT_SHA = "d503455236d3", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4zLjAiLCJnaXRfc2hhIjoiZDUwMzQ1NTIzNmQzIiwiY29kZV9oYXNoIjoiMTQ4OGZjMWQ5MmI3IiwidHJhY2VfdmVyc2lvbiI6IjE0ODhmYzFkOTJiN0BkNTAzNDU1MjM2ZDMiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTA2VDE2OjQyOjAxLjcyOFoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "QZKL6cxuZOauUsIdM3tms9r0wyOad9mfa9StUKd4v44", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
6883
6888
 
6884
6889
  // ../../src/version.ts
6885
6890
  import { createHash } from "crypto";
@@ -13237,6 +13242,8 @@ function getEndpointPolicy(endpoint) {
13237
13242
  return;
13238
13243
  if (matched.require_for_mutations && !MUTATION_METHODS.has(endpoint.method))
13239
13244
  return;
13245
+ if (endpoint.idempotency === "safe" || endpoint.idempotency === "read")
13246
+ return;
13240
13247
  return {
13241
13248
  requires_third_party_terms_confirmation: true,
13242
13249
  policy_domain: matched.domain,
@@ -25197,11 +25204,11 @@ async function registerRoutes(app) {
25197
25204
  });
25198
25205
  app.post("/v1/intent/resolve", { config: { rateLimit: ROUTE_LIMITS["/v1/intent/resolve"] } }, async (req, reply) => {
25199
25206
  const clientScope = clientScopeFor(req);
25200
- const { intent, params, context, projection, confirm_unsafe, confirm_third_party_terms, dry_run, force_capture } = req.body;
25207
+ const { intent, params, context, projection, confirm_unsafe, confirm_third_party_terms, dry_run, force_capture, skip_robots_check } = req.body;
25201
25208
  if (!intent)
25202
25209
  return reply.code(400).send({ error: "intent required" });
25203
25210
  try {
25204
- const result = await resolveAndExecute(intent, params ?? {}, context, projection, { confirm_unsafe, confirm_third_party_terms, dry_run, force_capture, client_scope: clientScope });
25211
+ const result = await resolveAndExecute(intent, params ?? {}, context, projection, { confirm_unsafe, confirm_third_party_terms, dry_run, force_capture, skip_robots_check, client_scope: clientScope });
25205
25212
  const res = attachAgentOutcomeHints({ ...result }, {
25206
25213
  skill: result.skill,
25207
25214
  endpointId: result.trace.endpoint_id,
@@ -25398,7 +25405,7 @@ async function registerRoutes(app) {
25398
25405
  app.post("/v1/skills/:skill_id/execute", { config: { rateLimit: ROUTE_LIMITS["/v1/skills/:skill_id/execute"] } }, async (req, reply) => {
25399
25406
  const clientScope = clientScopeFor(req);
25400
25407
  const { skill_id } = req.params;
25401
- const { params, projection, confirm_unsafe, confirm_third_party_terms, dry_run, intent, context_url } = req.body;
25408
+ const { params, projection, confirm_unsafe, confirm_third_party_terms, dry_run, intent, context_url, skip_robots_check } = req.body;
25402
25409
  let skill = getRecentLocalSkill(skill_id, clientScope);
25403
25410
  if (!skill) {
25404
25411
  const { findExistingSkillForDomain: findLocal } = await Promise.resolve().then(() => (init_client2(), exports_client2));
@@ -25420,7 +25427,7 @@ async function registerRoutes(app) {
25420
25427
  ...context_url && typeof params?.url !== "string" ? { url: context_url } : {}
25421
25428
  };
25422
25429
  try {
25423
- const execResult = await executeSkill(skill, execParams, projection, { confirm_unsafe, confirm_third_party_terms, dry_run, intent, contextUrl: context_url, client_scope: clientScope });
25430
+ const execResult = await executeSkill(skill, execParams, projection, { confirm_unsafe, confirm_third_party_terms, dry_run, skip_robots_check, intent, contextUrl: context_url, client_scope: clientScope });
25424
25431
  saveTrace(execResult.trace);
25425
25432
  if (execResult.trace.endpoint_id) {
25426
25433
  recordExecution(skill.skill_id, execResult.trace.endpoint_id, execResult.trace, skill).catch(() => {});
@@ -25431,7 +25438,7 @@ async function registerRoutes(app) {
25431
25438
  if (execResult.trace.status_code === 404 && skill.domain && skill.intent_signature && skill.execution_type !== "browser-capture") {
25432
25439
  try {
25433
25440
  const recoveryUrl = context_url || typeof execParams.url === "string" && execParams.url || skill.endpoints.find((endpoint) => typeof endpoint.trigger_url === "string" && endpoint.trigger_url)?.trigger_url || `https://${skill.domain}`;
25434
- const freshResult = await resolveAndExecute(intent || skill.intent_signature, { ...execParams, url: recoveryUrl }, { url: recoveryUrl }, projection, { confirm_unsafe, confirm_third_party_terms, dry_run, intent: intent || skill.intent_signature, client_scope: clientScope });
25441
+ const freshResult = await resolveAndExecute(intent || skill.intent_signature, { ...execParams, url: recoveryUrl }, { url: recoveryUrl }, projection, { confirm_unsafe, confirm_third_party_terms, dry_run, skip_robots_check, intent: intent || skill.intent_signature, client_scope: clientScope });
25435
25442
  saveTrace(freshResult.trace);
25436
25443
  if (freshResult.trace?.skill_id && freshResult.trace?.endpoint_id) {
25437
25444
  recordExecution(freshResult.trace.skill_id, freshResult.trace.endpoint_id, freshResult.trace, skill).catch(() => {});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unbrowse",
3
- "version": "3.2.3",
3
+ "version": "3.3.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": {