unbrowse 3.2.2 → 3.2.3-experiments.01e3d8e
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 +37 -35
- package/dist/mcp.js +5 -5
- package/dist/server.js +468 -260
- package/package.json +1 -1
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.
|
|
34
|
+
var BUILD_RELEASE_VERSION = "3.2.3-experiments.01e3d8e", BUILD_GIT_SHA = "01e3d8e6e795", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4yLjMtZXhwZXJpbWVudHMuMDFlM2Q4ZSIsImdpdF9zaGEiOiIwMWUzZDhlNmU3OTUiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QDAxZTNkOGU2ZTc5NSIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMTU6MjE6NDEuMzgxWiJ9", BUILD_RELEASE_MANIFEST_SIGNATURE = "jOgZcgINViNe1-ALsQWqd8pidR2gQYKph_7sGhujkT8", BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
|
|
35
35
|
|
|
36
36
|
// ../../src/version.ts
|
|
37
37
|
import { createHash } from "crypto";
|
|
@@ -679,23 +679,6 @@ var init_telemetry = __esm(() => {
|
|
|
679
679
|
autoFiledKeys = new Set;
|
|
680
680
|
});
|
|
681
681
|
|
|
682
|
-
// ../../src/runtime/browser-access.ts
|
|
683
|
-
var init_browser_access = () => {};
|
|
684
|
-
|
|
685
|
-
// ../../src/capture/index.ts
|
|
686
|
-
import { nanoid as nanoid2 } from "nanoid";
|
|
687
|
-
var activeTabRegistry, interceptorInjectedTabs, cdpDocStartTabs, cdpCapturedHeaders;
|
|
688
|
-
var init_capture = __esm(() => {
|
|
689
|
-
init_client2();
|
|
690
|
-
init_domain();
|
|
691
|
-
init_logger();
|
|
692
|
-
init_browser_access();
|
|
693
|
-
activeTabRegistry = new Set;
|
|
694
|
-
interceptorInjectedTabs = new Set;
|
|
695
|
-
cdpDocStartTabs = new Set;
|
|
696
|
-
cdpCapturedHeaders = new Map;
|
|
697
|
-
});
|
|
698
|
-
|
|
699
682
|
// ../../src/transform/index.ts
|
|
700
683
|
var EPHEMERAL_KEYS;
|
|
701
684
|
var init_transform = __esm(() => {
|
|
@@ -704,7 +687,7 @@ var init_transform = __esm(() => {
|
|
|
704
687
|
|
|
705
688
|
// ../../src/debug-trace.ts
|
|
706
689
|
import { join as join6 } from "node:path";
|
|
707
|
-
import { nanoid as
|
|
690
|
+
import { nanoid as nanoid2 } from "nanoid";
|
|
708
691
|
var TRACE_DIR;
|
|
709
692
|
var init_debug_trace = __esm(() => {
|
|
710
693
|
TRACE_DIR = process.env.TRACES_DIR ?? join6(process.cwd(), "traces");
|
|
@@ -719,7 +702,7 @@ var init_description_prompt = __esm(() => {
|
|
|
719
702
|
init_sanitize();
|
|
720
703
|
});
|
|
721
704
|
// ../../src/reverse-engineer/index.ts
|
|
722
|
-
import { nanoid as
|
|
705
|
+
import { nanoid as nanoid3 } from "nanoid";
|
|
723
706
|
var ALLOWED_METHODS, STRIP_HEADERS, REPLAY_HEADER_EXACT, SAFE_HEADERS, AD_SCHEMA_KEYS;
|
|
724
707
|
var init_reverse_engineer = __esm(() => {
|
|
725
708
|
init_transform();
|
|
@@ -791,19 +774,6 @@ var init_reverse_engineer = __esm(() => {
|
|
|
791
774
|
]);
|
|
792
775
|
});
|
|
793
776
|
|
|
794
|
-
// ../../src/reverse-engineer/bundle-scanner.ts
|
|
795
|
-
var init_bundle_scanner = __esm(() => {
|
|
796
|
-
init_logger();
|
|
797
|
-
});
|
|
798
|
-
|
|
799
|
-
// ../../src/reverse-engineer/token-sources.ts
|
|
800
|
-
var init_token_sources = () => {};
|
|
801
|
-
|
|
802
|
-
// ../../src/execution/token-resolver.ts
|
|
803
|
-
var init_token_resolver = __esm(() => {
|
|
804
|
-
init_token_sources();
|
|
805
|
-
});
|
|
806
|
-
|
|
807
777
|
// ../../src/vault/index.ts
|
|
808
778
|
import { join as join7 } from "path";
|
|
809
779
|
import { homedir as homedir5 } from "os";
|
|
@@ -834,6 +804,38 @@ var init_vault = __esm(async () => {
|
|
|
834
804
|
vaultLock = Promise.resolve();
|
|
835
805
|
});
|
|
836
806
|
|
|
807
|
+
// ../../src/runtime/browser-access.ts
|
|
808
|
+
var init_browser_access = () => {};
|
|
809
|
+
|
|
810
|
+
// ../../src/capture/index.ts
|
|
811
|
+
import { nanoid as nanoid4 } from "nanoid";
|
|
812
|
+
var activeTabRegistry, interceptorInjectedTabs, cdpDocStartTabs, cdpCapturedHeaders;
|
|
813
|
+
var init_capture = __esm(async () => {
|
|
814
|
+
init_client2();
|
|
815
|
+
init_domain();
|
|
816
|
+
init_logger();
|
|
817
|
+
init_reverse_engineer();
|
|
818
|
+
init_browser_access();
|
|
819
|
+
await init_vault();
|
|
820
|
+
activeTabRegistry = new Set;
|
|
821
|
+
interceptorInjectedTabs = new Set;
|
|
822
|
+
cdpDocStartTabs = new Set;
|
|
823
|
+
cdpCapturedHeaders = new Map;
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
// ../../src/reverse-engineer/bundle-scanner.ts
|
|
827
|
+
var init_bundle_scanner = __esm(() => {
|
|
828
|
+
init_logger();
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
// ../../src/reverse-engineer/token-sources.ts
|
|
832
|
+
var init_token_sources = () => {};
|
|
833
|
+
|
|
834
|
+
// ../../src/execution/token-resolver.ts
|
|
835
|
+
var init_token_resolver = __esm(() => {
|
|
836
|
+
init_token_sources();
|
|
837
|
+
});
|
|
838
|
+
|
|
837
839
|
// ../../src/auth/index.ts
|
|
838
840
|
var init_auth = __esm(async () => {
|
|
839
841
|
init_client2();
|
|
@@ -1018,8 +1020,6 @@ var init_compile = () => {};
|
|
|
1018
1020
|
import { nanoid as nanoid6 } from "nanoid";
|
|
1019
1021
|
var VALID_VERIFICATION_STATUSES, STOPWORDS;
|
|
1020
1022
|
var init_execution = __esm(async () => {
|
|
1021
|
-
init_capture();
|
|
1022
|
-
init_capture();
|
|
1023
1023
|
init_reverse_engineer();
|
|
1024
1024
|
init_bundle_scanner();
|
|
1025
1025
|
init_token_resolver();
|
|
@@ -1043,6 +1043,8 @@ var init_execution = __esm(async () => {
|
|
|
1043
1043
|
init_compile();
|
|
1044
1044
|
init_publish();
|
|
1045
1045
|
await __promiseAll([
|
|
1046
|
+
init_capture(),
|
|
1047
|
+
init_capture(),
|
|
1046
1048
|
init_vault(),
|
|
1047
1049
|
init_auth(),
|
|
1048
1050
|
init_indexer(),
|
package/dist/mcp.js
CHANGED
|
@@ -225,12 +225,12 @@ 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.
|
|
229
|
-
var BUILD_GIT_SHA = "
|
|
228
|
+
var BUILD_RELEASE_VERSION = "3.2.3-experiments.01e3d8e";
|
|
229
|
+
var BUILD_GIT_SHA = "01e3d8e6e795";
|
|
230
230
|
var BUILD_CODE_HASH = "1488fc1d92b7";
|
|
231
|
-
var BUILD_RELEASE_MANIFEST_BASE64 = "
|
|
232
|
-
var BUILD_RELEASE_MANIFEST_SIGNATURE = "
|
|
233
|
-
var BUILD_DEFAULT_BACKEND_URL = "https://
|
|
231
|
+
var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4yLjMtZXhwZXJpbWVudHMuMDFlM2Q4ZSIsImdpdF9zaGEiOiIwMWUzZDhlNmU3OTUiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QDAxZTNkOGU2ZTc5NSIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMTU6MjE6NDEuMzgxWiJ9";
|
|
232
|
+
var BUILD_RELEASE_MANIFEST_SIGNATURE = "jOgZcgINViNe1-ALsQWqd8pidR2gQYKph_7sGhujkT8";
|
|
233
|
+
var BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
|
|
234
234
|
|
|
235
235
|
// ../../src/version.ts
|
|
236
236
|
var MODULE_DIR = dirname(fileURLToPath2(import.meta.url));
|
package/dist/server.js
CHANGED
|
@@ -4299,7 +4299,12 @@ function extractEndpoints(requests, wsMessages, context) {
|
|
|
4299
4299
|
const sanitizedQParams = isGet ? sanitizeQueryParams(extractQueryParams(req.url)) : undefined;
|
|
4300
4300
|
let pathTemplate = sanitizeUrlTemplate(normalized);
|
|
4301
4301
|
const qBindings = sanitizedQParams ? buildQueryBindingMap(Object.keys(sanitizedQParams)) : {};
|
|
4302
|
-
const
|
|
4302
|
+
const existingQKeys = new Set;
|
|
4303
|
+
try {
|
|
4304
|
+
for (const k of new URL(pathTemplate).searchParams.keys())
|
|
4305
|
+
existingQKeys.add(k.toLowerCase());
|
|
4306
|
+
} catch {}
|
|
4307
|
+
const qTemplateStr = sanitizedQParams && Object.keys(sanitizedQParams).length > 0 ? Object.keys(sanitizedQParams).filter((k) => !existingQKeys.has(k.toLowerCase())).map((k) => `${encodeURIComponent(k)}={${qBindings[k] ?? k}}`).join("&") || null : null;
|
|
4303
4308
|
const { url: templatizedPath, pathParams, pathBindingCandidates } = templatizePathSegments(pathTemplate, req.url, context);
|
|
4304
4309
|
pathTemplate = templatizedPath;
|
|
4305
4310
|
const parsedRequestBody = !isGet && req.request_body ? tryParseBody(req.request_body) : undefined;
|
|
@@ -4315,7 +4320,7 @@ function extractEndpoints(requests, wsMessages, context) {
|
|
|
4315
4320
|
let endpoint = {
|
|
4316
4321
|
endpoint_id: nanoid2(),
|
|
4317
4322
|
method: req.method,
|
|
4318
|
-
url_template: qTemplateStr ? `${pathTemplate}
|
|
4323
|
+
url_template: qTemplateStr ? `${pathTemplate}${pathTemplate.includes("?") ? "&" : "?"}${qTemplateStr}` : pathTemplate,
|
|
4319
4324
|
description: buildEndpointDescription(req, sampleRequest, sampleResponse),
|
|
4320
4325
|
headers_template: sanitizeHeaders(req.request_headers),
|
|
4321
4326
|
query: sanitizedQParams,
|
|
@@ -5027,6 +5032,179 @@ var init_reverse_engineer = __esm(() => {
|
|
|
5027
5032
|
ON_DOMAIN_NOISE = /\/(recaptcha|captcha|update-recaptcha|csrf|consent|data-protection|badge|drawer|header-action|geolocation|onboarding|wana\/bids|prebid|bids\/request|ads\/|pixel|beacon|collect|impression|click-tracking|heartbeat|webConfig|config\.json|manifest\.json|service-worker|sw\.js|favicon|robots\.txt|sitemap|opensearch|partial\/[a-zA-Z]+\/mod-|logging|csp-report|gen_204|generate_204|sodar|__webpack|__next|devvit-|user-drawer|action-item)/i;
|
|
5028
5033
|
});
|
|
5029
5034
|
|
|
5035
|
+
// ../../src/vault/index.ts
|
|
5036
|
+
var exports_vault = {};
|
|
5037
|
+
__export(exports_vault, {
|
|
5038
|
+
storeCredential: () => storeCredential,
|
|
5039
|
+
setKeytarClientForTests: () => setKeytarClientForTests,
|
|
5040
|
+
resetKeytarClientForTests: () => resetKeytarClientForTests,
|
|
5041
|
+
normalizeKeytarModule: () => normalizeKeytarModule,
|
|
5042
|
+
getCredential: () => getCredential,
|
|
5043
|
+
deleteCredential: () => deleteCredential
|
|
5044
|
+
});
|
|
5045
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
5046
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
5047
|
+
import { join as join2 } from "path";
|
|
5048
|
+
import { homedir } from "os";
|
|
5049
|
+
function normalizeKeytarModule(mod) {
|
|
5050
|
+
let candidate = mod;
|
|
5051
|
+
for (let depth = 0;depth < 3; depth++) {
|
|
5052
|
+
if (!candidate || typeof candidate !== "object" || !("default" in candidate))
|
|
5053
|
+
break;
|
|
5054
|
+
candidate = candidate.default;
|
|
5055
|
+
}
|
|
5056
|
+
if (!candidate)
|
|
5057
|
+
return null;
|
|
5058
|
+
if (typeof candidate.setPassword === "function" && typeof candidate.getPassword === "function" && typeof candidate.deletePassword === "function") {
|
|
5059
|
+
return candidate;
|
|
5060
|
+
}
|
|
5061
|
+
return null;
|
|
5062
|
+
}
|
|
5063
|
+
function isKeytarBindingError(error) {
|
|
5064
|
+
const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
5065
|
+
return KEYTAR_BINDING_ERROR_RE.test(message);
|
|
5066
|
+
}
|
|
5067
|
+
function disableKeytar(error) {
|
|
5068
|
+
keytar = null;
|
|
5069
|
+
if (keytarFallbackLogged)
|
|
5070
|
+
return;
|
|
5071
|
+
const summary = error instanceof Error ? error.message : String(error);
|
|
5072
|
+
log("vault", `keytar runtime unavailable (${summary}); using encrypted file fallback`);
|
|
5073
|
+
keytarFallbackLogged = true;
|
|
5074
|
+
}
|
|
5075
|
+
async function callKeytar(op) {
|
|
5076
|
+
if (!keytar)
|
|
5077
|
+
return KEYTAR_UNAVAILABLE;
|
|
5078
|
+
try {
|
|
5079
|
+
return await op(keytar);
|
|
5080
|
+
} catch (error) {
|
|
5081
|
+
if (!isKeytarBindingError(error))
|
|
5082
|
+
throw error;
|
|
5083
|
+
disableKeytar(error);
|
|
5084
|
+
return KEYTAR_UNAVAILABLE;
|
|
5085
|
+
}
|
|
5086
|
+
}
|
|
5087
|
+
function setKeytarClientForTests(client) {
|
|
5088
|
+
keytar = client;
|
|
5089
|
+
keytarFallbackLogged = false;
|
|
5090
|
+
}
|
|
5091
|
+
function resetKeytarClientForTests() {
|
|
5092
|
+
keytar = importedKeytar;
|
|
5093
|
+
keytarFallbackLogged = false;
|
|
5094
|
+
}
|
|
5095
|
+
function getOrCreateKey() {
|
|
5096
|
+
if (!existsSync3(VAULT_DIR))
|
|
5097
|
+
mkdirSync3(VAULT_DIR, { recursive: true, mode: 448 });
|
|
5098
|
+
if (existsSync3(KEY_FILE))
|
|
5099
|
+
return readFileSync(KEY_FILE);
|
|
5100
|
+
const key = randomBytes(32);
|
|
5101
|
+
writeFileSync2(KEY_FILE, key, { mode: 384 });
|
|
5102
|
+
return key;
|
|
5103
|
+
}
|
|
5104
|
+
function withVaultLock(fn) {
|
|
5105
|
+
const prev = vaultLock;
|
|
5106
|
+
let release;
|
|
5107
|
+
vaultLock = new Promise((r) => {
|
|
5108
|
+
release = r;
|
|
5109
|
+
});
|
|
5110
|
+
return prev.then(fn).finally(() => release());
|
|
5111
|
+
}
|
|
5112
|
+
function readVaultFile() {
|
|
5113
|
+
if (!existsSync3(VAULT_FILE))
|
|
5114
|
+
return {};
|
|
5115
|
+
try {
|
|
5116
|
+
const key = getOrCreateKey();
|
|
5117
|
+
const raw = readFileSync(VAULT_FILE);
|
|
5118
|
+
const iv = raw.subarray(0, 16);
|
|
5119
|
+
const enc = raw.subarray(16);
|
|
5120
|
+
const decipher = createDecipheriv("aes-256-cbc", key, iv);
|
|
5121
|
+
const dec = Buffer.concat([decipher.update(enc), decipher.final()]);
|
|
5122
|
+
return JSON.parse(dec.toString("utf8"));
|
|
5123
|
+
} catch {
|
|
5124
|
+
return {};
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
function writeVaultFile(data) {
|
|
5128
|
+
const key = getOrCreateKey();
|
|
5129
|
+
const iv = randomBytes(16);
|
|
5130
|
+
const cipher = createCipheriv("aes-256-cbc", key, iv);
|
|
5131
|
+
const enc = Buffer.concat([cipher.update(JSON.stringify(data), "utf8"), cipher.final()]);
|
|
5132
|
+
writeFileSync2(VAULT_FILE, Buffer.concat([iv, enc]), { mode: 384 });
|
|
5133
|
+
}
|
|
5134
|
+
async function storeCredential(account, value, opts) {
|
|
5135
|
+
const wrapped = {
|
|
5136
|
+
value,
|
|
5137
|
+
stored_at: new Date().toISOString(),
|
|
5138
|
+
expires_at: opts?.expires_at,
|
|
5139
|
+
max_age_ms: opts?.max_age_ms
|
|
5140
|
+
};
|
|
5141
|
+
const serialized = JSON.stringify(wrapped);
|
|
5142
|
+
const keytarResult = await callKeytar((client) => client.setPassword(SERVICE, account, serialized));
|
|
5143
|
+
if (keytarResult !== KEYTAR_UNAVAILABLE)
|
|
5144
|
+
return;
|
|
5145
|
+
await withVaultLock(() => {
|
|
5146
|
+
const data = readVaultFile();
|
|
5147
|
+
data[account] = serialized;
|
|
5148
|
+
writeVaultFile(data);
|
|
5149
|
+
});
|
|
5150
|
+
}
|
|
5151
|
+
function isExpired(cred) {
|
|
5152
|
+
if (cred.expires_at) {
|
|
5153
|
+
return new Date(cred.expires_at).getTime() <= Date.now();
|
|
5154
|
+
}
|
|
5155
|
+
if (cred.max_age_ms) {
|
|
5156
|
+
return new Date(cred.stored_at).getTime() + cred.max_age_ms <= Date.now();
|
|
5157
|
+
}
|
|
5158
|
+
return false;
|
|
5159
|
+
}
|
|
5160
|
+
async function getCredential(account) {
|
|
5161
|
+
let raw;
|
|
5162
|
+
const keytarResult = await callKeytar((client) => client.getPassword(SERVICE, account));
|
|
5163
|
+
if (keytarResult !== KEYTAR_UNAVAILABLE) {
|
|
5164
|
+
raw = keytarResult;
|
|
5165
|
+
} else {
|
|
5166
|
+
const data = readVaultFile();
|
|
5167
|
+
raw = data[account] ?? null;
|
|
5168
|
+
}
|
|
5169
|
+
if (!raw)
|
|
5170
|
+
return null;
|
|
5171
|
+
try {
|
|
5172
|
+
const parsed = JSON.parse(raw);
|
|
5173
|
+
if (parsed.value && parsed.stored_at) {
|
|
5174
|
+
if (isExpired(parsed)) {
|
|
5175
|
+
await deleteCredential(account);
|
|
5176
|
+
return null;
|
|
5177
|
+
}
|
|
5178
|
+
return parsed.value;
|
|
5179
|
+
}
|
|
5180
|
+
} catch {}
|
|
5181
|
+
return raw;
|
|
5182
|
+
}
|
|
5183
|
+
async function deleteCredential(account) {
|
|
5184
|
+
const keytarResult = await callKeytar((client) => client.deletePassword(SERVICE, account));
|
|
5185
|
+
if (keytarResult !== KEYTAR_UNAVAILABLE)
|
|
5186
|
+
return;
|
|
5187
|
+
await withVaultLock(() => {
|
|
5188
|
+
const data = readVaultFile();
|
|
5189
|
+
delete data[account];
|
|
5190
|
+
writeVaultFile(data);
|
|
5191
|
+
});
|
|
5192
|
+
}
|
|
5193
|
+
var KEYTAR_UNAVAILABLE, KEYTAR_BINDING_ERROR_RE, keytar = null, importedKeytar, keytarFallbackLogged = false, SERVICE = "unbrowse", VAULT_DIR, VAULT_FILE, KEY_FILE, vaultLock;
|
|
5194
|
+
var init_vault = __esm(async () => {
|
|
5195
|
+
init_logger();
|
|
5196
|
+
KEYTAR_UNAVAILABLE = Symbol("KEYTAR_UNAVAILABLE");
|
|
5197
|
+
KEYTAR_BINDING_ERROR_RE = /(keytar(?:\.node)?|native bindings?|bindings file|no native build was found|could not locate the bindings file|module did not self-register|err_dlopen_failed|dlopen\(|compiled against a different node\.js version|cannot find module .*keytar|wasm is not supported on this platform|(set|get|delete)password is not a function)/i;
|
|
5198
|
+
try {
|
|
5199
|
+
keytar = normalizeKeytarModule(await import("keytar"));
|
|
5200
|
+
} catch {}
|
|
5201
|
+
importedKeytar = keytar;
|
|
5202
|
+
VAULT_DIR = join2(homedir(), ".unbrowse", "vault");
|
|
5203
|
+
VAULT_FILE = join2(VAULT_DIR, "credentials.enc");
|
|
5204
|
+
KEY_FILE = join2(VAULT_DIR, ".key");
|
|
5205
|
+
vaultLock = Promise.resolve();
|
|
5206
|
+
});
|
|
5207
|
+
|
|
5030
5208
|
// ../../src/runtime/browser-access.ts
|
|
5031
5209
|
var DEFAULT_BROWSER_ACCESS;
|
|
5032
5210
|
var init_browser_access = __esm(() => {
|
|
@@ -5477,7 +5655,12 @@ function normalizeCapturedUrl(url, baseUrl) {
|
|
|
5477
5655
|
if (!url)
|
|
5478
5656
|
return url;
|
|
5479
5657
|
try {
|
|
5480
|
-
|
|
5658
|
+
const parsed = new URL(url);
|
|
5659
|
+
if (baseUrl && (parsed.hostname === "127.0.0.1" || parsed.hostname === "localhost")) {
|
|
5660
|
+
const pageOrigin = new URL(baseUrl).origin;
|
|
5661
|
+
return `${pageOrigin}${parsed.pathname}${parsed.search}`;
|
|
5662
|
+
}
|
|
5663
|
+
return parsed.toString();
|
|
5481
5664
|
} catch {
|
|
5482
5665
|
if (!baseUrl)
|
|
5483
5666
|
return url;
|
|
@@ -5878,7 +6061,76 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
5878
6061
|
log("capture", "scriptInject unavailable — falling back to evaluate injection");
|
|
5879
6062
|
}
|
|
5880
6063
|
}
|
|
5881
|
-
|
|
6064
|
+
try {
|
|
6065
|
+
await phase("harStart", () => harStart(tabId));
|
|
6066
|
+
} catch {}
|
|
6067
|
+
const cdpNetworkEntries = [];
|
|
6068
|
+
const cdpRequestMap = new Map;
|
|
6069
|
+
const cdpResponseMeta = new Map;
|
|
6070
|
+
const cdpFinishedRequests = new Set;
|
|
6071
|
+
let cdpWs = null;
|
|
6072
|
+
let cdpMsgId = 10;
|
|
6073
|
+
const cdpPendingBodies = new Map;
|
|
6074
|
+
const cdpResolvedBodies = new Map;
|
|
6075
|
+
const API_URL_PATTERN = /\/api\/|\/graphql|voyager|youtubei|\/v\d+\//i;
|
|
6076
|
+
try {
|
|
6077
|
+
const cdpPort = getCdpPort();
|
|
6078
|
+
if (cdpPort) {
|
|
6079
|
+
const tabsResp = await fetch(`http://127.0.0.1:${cdpPort}/json`);
|
|
6080
|
+
const tabs = await tabsResp.json();
|
|
6081
|
+
const cdpTab = tabs.find((t) => t.id === tabId) ?? tabs.find((t) => t.type === "page");
|
|
6082
|
+
if (cdpTab?.webSocketDebuggerUrl) {
|
|
6083
|
+
cdpWs = new WebSocket(cdpTab.webSocketDebuggerUrl);
|
|
6084
|
+
await new Promise((resolve, reject) => {
|
|
6085
|
+
cdpWs.onopen = () => resolve();
|
|
6086
|
+
cdpWs.onerror = () => reject(new Error("CDP WS failed"));
|
|
6087
|
+
setTimeout(() => reject(new Error("CDP WS timeout")), 3000);
|
|
6088
|
+
});
|
|
6089
|
+
cdpWs.onmessage = (ev) => {
|
|
6090
|
+
try {
|
|
6091
|
+
const msg = JSON.parse(String(ev.data));
|
|
6092
|
+
if (msg.method === "Network.requestWillBeSent") {
|
|
6093
|
+
const p = msg.params;
|
|
6094
|
+
const reqHeaders = Object.entries(p.request?.headers ?? {}).map(([name, value]) => ({ name, value: String(value) }));
|
|
6095
|
+
cdpRequestMap.set(p.requestId, {
|
|
6096
|
+
method: p.request?.method ?? "GET",
|
|
6097
|
+
url: p.request?.url ?? "",
|
|
6098
|
+
headers: reqHeaders,
|
|
6099
|
+
postData: p.request?.postData
|
|
6100
|
+
});
|
|
6101
|
+
} else if (msg.method === "Network.responseReceived") {
|
|
6102
|
+
const p = msg.params;
|
|
6103
|
+
const respHeaders = Object.entries(p.response?.headers ?? {}).map(([name, value]) => ({ name, value: String(value) }));
|
|
6104
|
+
cdpResponseMeta.set(p.requestId, {
|
|
6105
|
+
status: p.response?.status ?? 0,
|
|
6106
|
+
headers: respHeaders,
|
|
6107
|
+
mimeType: p.response?.mimeType ?? ""
|
|
6108
|
+
});
|
|
6109
|
+
} else if (msg.method === "Network.loadingFinished") {
|
|
6110
|
+
const requestId = msg.params?.requestId;
|
|
6111
|
+
cdpFinishedRequests.add(requestId);
|
|
6112
|
+
const req = cdpRequestMap.get(requestId);
|
|
6113
|
+
const resp = cdpResponseMeta.get(requestId);
|
|
6114
|
+
if (req && resp && API_URL_PATTERN.test(req.url) && (resp.mimeType.includes("json") || resp.mimeType.includes("text"))) {
|
|
6115
|
+
const id = ++cdpMsgId;
|
|
6116
|
+
cdpPendingBodies.set(id, req.url);
|
|
6117
|
+
cdpWs.send(JSON.stringify({ id, method: "Network.getResponseBody", params: { requestId } }));
|
|
6118
|
+
}
|
|
6119
|
+
} else if (msg.id && cdpPendingBodies.has(msg.id)) {
|
|
6120
|
+
const reqUrl = cdpPendingBodies.get(msg.id);
|
|
6121
|
+
cdpPendingBodies.delete(msg.id);
|
|
6122
|
+
if (msg.result?.body) {
|
|
6123
|
+
cdpResolvedBodies.set(reqUrl, msg.result.body);
|
|
6124
|
+
}
|
|
6125
|
+
}
|
|
6126
|
+
} catch {}
|
|
6127
|
+
};
|
|
6128
|
+
cdpWs.send(JSON.stringify({ id: 1, method: "Network.enable", params: {} }));
|
|
6129
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
6130
|
+
log("capture", "CDP network capture enabled (direct websocket)");
|
|
6131
|
+
}
|
|
6132
|
+
}
|
|
6133
|
+
} catch {}
|
|
5882
6134
|
let pageDomain;
|
|
5883
6135
|
try {
|
|
5884
6136
|
pageDomain = getRegistrableDomain(new URL(url).hostname);
|
|
@@ -5932,11 +6184,90 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
5932
6184
|
const perfEntries = await phase("evaluate:perf", () => collectPerformanceResourceEntries(tabId));
|
|
5933
6185
|
performanceUrls = await phase("replay-fetch", () => replayPerformanceApiResponses(tabId, perfEntries, responseBodies, url, intent));
|
|
5934
6186
|
} catch {}
|
|
6187
|
+
if (cdpRequestMap.size > 0) {
|
|
6188
|
+
try {
|
|
6189
|
+
const cdpRawReqs = [...cdpRequestMap.values()].map((r) => ({
|
|
6190
|
+
url: r.url,
|
|
6191
|
+
method: r.method,
|
|
6192
|
+
request_headers: Object.fromEntries(r.headers.map((h) => [h.name.toLowerCase(), h.value])),
|
|
6193
|
+
response_status: 200,
|
|
6194
|
+
response_headers: {},
|
|
6195
|
+
response_body: undefined,
|
|
6196
|
+
timestamp: ""
|
|
6197
|
+
}));
|
|
6198
|
+
const authHeaders2 = extractAuthHeaders(cdpRawReqs);
|
|
6199
|
+
if (Object.keys(authHeaders2).length > 0) {
|
|
6200
|
+
const rawKey = `${domain}-session`;
|
|
6201
|
+
const { getCredential: getCredential2 } = await init_vault().then(() => exports_vault);
|
|
6202
|
+
let existing = {};
|
|
6203
|
+
try {
|
|
6204
|
+
const stored = await getCredential2(rawKey);
|
|
6205
|
+
if (stored)
|
|
6206
|
+
existing = JSON.parse(stored);
|
|
6207
|
+
} catch {}
|
|
6208
|
+
if (!existing.cookies || existing.cookies.length === 0) {
|
|
6209
|
+
try {
|
|
6210
|
+
const loginKey = `auth:${getRegistrableDomain(domain)}`;
|
|
6211
|
+
const loginStored = await getCredential2(loginKey);
|
|
6212
|
+
if (loginStored) {
|
|
6213
|
+
const loginData = JSON.parse(loginStored);
|
|
6214
|
+
if (loginData.cookies?.length)
|
|
6215
|
+
existing.cookies = loginData.cookies;
|
|
6216
|
+
}
|
|
6217
|
+
} catch {}
|
|
6218
|
+
}
|
|
6219
|
+
await storeCredential(rawKey, JSON.stringify({
|
|
6220
|
+
...existing,
|
|
6221
|
+
headers: { ...existing.headers ?? {}, ...authHeaders2 }
|
|
6222
|
+
}));
|
|
6223
|
+
log("capture", `early auth store: ${Object.keys(authHeaders2).join(", ")} for ${domain}`);
|
|
6224
|
+
}
|
|
6225
|
+
} catch (e) {
|
|
6226
|
+
log("capture", `early auth store failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
6227
|
+
}
|
|
6228
|
+
}
|
|
5935
6229
|
let harEntries = [];
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
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
|
+
}
|
|
6241
|
+
if (cdpPendingBodies.size > 0) {
|
|
6242
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
6243
|
+
}
|
|
6244
|
+
if (cdpWs) {
|
|
6245
|
+
try {
|
|
6246
|
+
cdpWs.close();
|
|
6247
|
+
} catch {}
|
|
6248
|
+
}
|
|
6249
|
+
const harUrls = new Set(harEntries.map((e) => e.request?.url).filter(Boolean));
|
|
6250
|
+
let cdpAdded = 0;
|
|
6251
|
+
for (const [requestId, req] of cdpRequestMap) {
|
|
6252
|
+
if (harUrls.has(req.url))
|
|
6253
|
+
continue;
|
|
6254
|
+
const resp = cdpResponseMeta.get(requestId);
|
|
6255
|
+
if (!resp)
|
|
6256
|
+
continue;
|
|
6257
|
+
const body = cdpResolvedBodies.get(req.url);
|
|
6258
|
+
harEntries.push({
|
|
6259
|
+
startedDateTime: new Date().toISOString(),
|
|
6260
|
+
request: { method: req.method, url: req.url, headers: req.headers, postData: req.postData ? { text: req.postData } : undefined },
|
|
6261
|
+
response: { status: resp.status, headers: resp.headers, content: body ? { text: body, mimeType: resp.mimeType } : {} }
|
|
6262
|
+
});
|
|
6263
|
+
if (body && body.length > 0 && !responseBodies.has(req.url)) {
|
|
6264
|
+
responseBodies.set(req.url, body);
|
|
6265
|
+
}
|
|
6266
|
+
cdpAdded++;
|
|
6267
|
+
}
|
|
6268
|
+
if (cdpAdded > 0) {
|
|
6269
|
+
log("capture", `CDP direct capture added ${cdpAdded} entries (${cdpResolvedBodies.size} with bodies, ${harEntries.length} total HAR)`);
|
|
6270
|
+
}
|
|
5940
6271
|
const HAR_REPLAY_CT2 = /application\/json|text\/plain|\+json/i;
|
|
5941
6272
|
let harReplayCount = 0;
|
|
5942
6273
|
for (const entry of harEntries) {
|
|
@@ -5960,7 +6291,7 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
5960
6291
|
const postData = method !== "GET" ? entry.request?.postData?.text : undefined;
|
|
5961
6292
|
const replayScript = method === "GET" || !postData ? `(function(){var x=new XMLHttpRequest();x.open('GET','${harUrl.replace(/'/g, "\\'")}',false);x.send();return x.status>=200&&x.status<400?x.responseText:''})()` : `(function(){var x=new XMLHttpRequest();x.open('${method}','${harUrl.replace(/'/g, "\\'")}',false);x.setRequestHeader('Content-Type','application/json');x.send(${JSON.stringify(postData)});return x.status>=200&&x.status<400?x.responseText:''})()`;
|
|
5962
6293
|
const body = await phase("har-replay", () => evaluate(tabId, replayScript));
|
|
5963
|
-
if (typeof body === "string" && body.length > 0 && body.length <
|
|
6294
|
+
if (typeof body === "string" && body.length > 0 && body.length < 524288) {
|
|
5964
6295
|
responseBodies.set(harUrl, body);
|
|
5965
6296
|
harReplayCount++;
|
|
5966
6297
|
log("capture", `har-replay-fetched ${harUrl.substring(0, 80)} (${body.length}B)`);
|
|
@@ -5988,7 +6319,7 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
5988
6319
|
html = await phase("getPageHtml", () => getPageHtml(tabId));
|
|
5989
6320
|
} catch {}
|
|
5990
6321
|
const SSR_DATA_EXTRACTORS = [
|
|
5991
|
-
{ name: "ytmusic", script: `(function(){try{var d=ytcfg.get('YTMUSIC_INITIAL_DATA');if(!d||!d.length)return null;var out={};d.forEach(function(x){if(x.path&&x.data)out[x.path]=x.data});return JSON.stringify(out)}catch(e){return null}})()` },
|
|
6322
|
+
{ name: "ytmusic", script: `(function(){try{var d=ytcfg.get('YTMUSIC_INITIAL_DATA');if(!d||!d.length)return null;var out={};d.forEach(function(x){if(x.path&&x.data)out[x.path]=x.data});out.__apiKey=ytcfg.get('INNERTUBE_API_KEY')||'';out.__context=ytcfg.get('INNERTUBE_CONTEXT')||null;return JSON.stringify(out)}catch(e){return null}})()` },
|
|
5992
6323
|
{ name: "youtube", script: `(function(){try{return typeof ytInitialData!=='undefined'?JSON.stringify(ytInitialData):null}catch(e){return null}})()` },
|
|
5993
6324
|
{ name: "nextjs", script: `(function(){try{return window.__NEXT_DATA__?JSON.stringify(window.__NEXT_DATA__):null}catch(e){return null}})()` },
|
|
5994
6325
|
{ name: "nuxt", script: `(function(){try{return window.__NUXT__?JSON.stringify(window.__NUXT__):null}catch(e){return null}})()` }
|
|
@@ -6000,8 +6331,12 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
6000
6331
|
if (typeof raw !== "string" || !raw || raw === "null")
|
|
6001
6332
|
continue;
|
|
6002
6333
|
if (extractor.name === "ytmusic") {
|
|
6003
|
-
const
|
|
6004
|
-
|
|
6334
|
+
const parsed = JSON.parse(raw);
|
|
6335
|
+
const apiKey = parsed.__apiKey || "";
|
|
6336
|
+
const innertubeContext = parsed.__context;
|
|
6337
|
+
delete parsed.__apiKey;
|
|
6338
|
+
delete parsed.__context;
|
|
6339
|
+
for (const [path4, data] of Object.entries(parsed)) {
|
|
6005
6340
|
if (!data || typeof data !== "object")
|
|
6006
6341
|
continue;
|
|
6007
6342
|
const cleaned = { ...data };
|
|
@@ -6022,12 +6357,15 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
6022
6357
|
continue;
|
|
6023
6358
|
const origin = new URL(url).origin;
|
|
6024
6359
|
const contextParams = new URL(url).searchParams;
|
|
6025
|
-
const
|
|
6360
|
+
const keyParam = apiKey ? `key=${apiKey}&` : "";
|
|
6361
|
+
const queryStr = path4.includes("search") && contextParams.toString() ? `?${keyParam}${contextParams.toString()}&prettyPrint=false` : `?${keyParam}prettyPrint=false`;
|
|
6026
6362
|
const syntheticUrl = `${origin}/youtubei/v1${path4}${queryStr}`;
|
|
6027
6363
|
responseBodies.set(syntheticUrl, bodyStr);
|
|
6364
|
+
const queryValue = contextParams.get("q") ?? "";
|
|
6365
|
+
const postBody = path4.includes("search") && innertubeContext ? JSON.stringify({ context: innertubeContext, query: queryValue }) : path4.includes("browse") && innertubeContext ? JSON.stringify({ context: innertubeContext, browseId: "FEmusic_liked_videos" }) : JSON.stringify({ context: innertubeContext ?? {} });
|
|
6028
6366
|
harEntries.push({
|
|
6029
6367
|
startedDateTime: new Date().toISOString(),
|
|
6030
|
-
request: { method: "POST", url: syntheticUrl, headers: [{ name: "content-type", value: "application/json" }], postData: { text:
|
|
6368
|
+
request: { method: "POST", url: syntheticUrl, headers: [{ name: "content-type", value: "application/json" }], postData: { text: postBody } },
|
|
6031
6369
|
response: { status: 200, headers: [{ name: "content-type", value: "application/json" }], content: { text: bodyStr, mimeType: "application/json" } }
|
|
6032
6370
|
});
|
|
6033
6371
|
embeddedDataCount++;
|
|
@@ -6523,11 +6861,13 @@ var MAX_CONCURRENT_TABS = 3, activeTabs = 0, waitQueue, activeTabRegistry, inter
|
|
|
6523
6861
|
return origSend.apply(this, arguments);
|
|
6524
6862
|
};
|
|
6525
6863
|
})()`, REPLAY_SKIP, HAR_REPLAY_CT;
|
|
6526
|
-
var init_capture = __esm(() => {
|
|
6864
|
+
var init_capture = __esm(async () => {
|
|
6527
6865
|
init_client();
|
|
6528
6866
|
init_domain();
|
|
6529
6867
|
init_logger();
|
|
6868
|
+
init_reverse_engineer();
|
|
6530
6869
|
init_browser_access();
|
|
6870
|
+
await init_vault();
|
|
6531
6871
|
waitQueue = [];
|
|
6532
6872
|
activeTabRegistry = new Set;
|
|
6533
6873
|
interceptorInjectedTabs = new Set;
|
|
@@ -6544,17 +6884,17 @@ var init_capture = __esm(() => {
|
|
|
6544
6884
|
});
|
|
6545
6885
|
|
|
6546
6886
|
// ../../src/build-info.generated.ts
|
|
6547
|
-
var BUILD_RELEASE_VERSION = "3.2.
|
|
6887
|
+
var BUILD_RELEASE_VERSION = "3.2.3-experiments.01e3d8e", BUILD_GIT_SHA = "01e3d8e6e795", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4yLjMtZXhwZXJpbWVudHMuMDFlM2Q4ZSIsImdpdF9zaGEiOiIwMWUzZDhlNmU3OTUiLCJjb2RlX2hhc2giOiIxNDg4ZmMxZDkyYjciLCJ0cmFjZV92ZXJzaW9uIjoiMTQ4OGZjMWQ5MmI3QDAxZTNkOGU2ZTc5NSIsImlzc3VlZF9hdCI6IjIwMjYtMDQtMDZUMTU6MjE6NDEuMzgxWiJ9", BUILD_RELEASE_MANIFEST_SIGNATURE = "jOgZcgINViNe1-ALsQWqd8pidR2gQYKph_7sGhujkT8", BUILD_DEFAULT_BACKEND_URL = "https://unbrowse-backend-experiments.lewis-6d8.workers.dev";
|
|
6548
6888
|
|
|
6549
6889
|
// ../../src/version.ts
|
|
6550
6890
|
import { createHash } from "crypto";
|
|
6551
|
-
import { existsSync as
|
|
6552
|
-
import { dirname, join as
|
|
6891
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, readdirSync } from "fs";
|
|
6892
|
+
import { dirname, join as join3, parse } from "path";
|
|
6553
6893
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6554
6894
|
function collectTsFiles(dir) {
|
|
6555
6895
|
const results = [];
|
|
6556
6896
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
6557
|
-
const full =
|
|
6897
|
+
const full = join3(dir, entry.name);
|
|
6558
6898
|
if (entry.isDirectory() && entry.name !== "node_modules") {
|
|
6559
6899
|
results.push(...collectTsFiles(full));
|
|
6560
6900
|
} else if (entry.name.endsWith(".ts")) {
|
|
@@ -6567,21 +6907,21 @@ function hashFiles(srcDir, files) {
|
|
|
6567
6907
|
const hash = createHash("sha256");
|
|
6568
6908
|
for (const file of files) {
|
|
6569
6909
|
hash.update(file.slice(srcDir.length));
|
|
6570
|
-
hash.update(
|
|
6910
|
+
hash.update(readFileSync2(file, "utf-8"));
|
|
6571
6911
|
}
|
|
6572
6912
|
return hash.digest("hex").slice(0, 12);
|
|
6573
6913
|
}
|
|
6574
6914
|
function resolveCodeHashSourceDir(moduleDir) {
|
|
6575
6915
|
const candidates = [
|
|
6576
6916
|
moduleDir,
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6917
|
+
join3(moduleDir, "runtime-src"),
|
|
6918
|
+
join3(moduleDir, "..", "runtime-src"),
|
|
6919
|
+
join3(moduleDir, "src"),
|
|
6920
|
+
join3(moduleDir, "..", "src")
|
|
6581
6921
|
];
|
|
6582
6922
|
for (const candidate of candidates) {
|
|
6583
6923
|
try {
|
|
6584
|
-
if (!
|
|
6924
|
+
if (!existsSync4(candidate))
|
|
6585
6925
|
continue;
|
|
6586
6926
|
const files = collectTsFiles(candidate);
|
|
6587
6927
|
if (files.length > 0)
|
|
@@ -6631,7 +6971,7 @@ function getPackageVersionForModuleDir(moduleDir) {
|
|
|
6631
6971
|
const root = parse(dir).root;
|
|
6632
6972
|
while (true) {
|
|
6633
6973
|
try {
|
|
6634
|
-
const pkg = JSON.parse(
|
|
6974
|
+
const pkg = JSON.parse(readFileSync2(join3(dir, "package.json"), "utf-8"));
|
|
6635
6975
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
6636
6976
|
} catch {}
|
|
6637
6977
|
if (dir === root)
|
|
@@ -6735,18 +7075,18 @@ async function ensureCascadeSplitForSkill(skill, deps = {}) {
|
|
|
6735
7075
|
var init_cascade = () => {};
|
|
6736
7076
|
|
|
6737
7077
|
// ../../src/payments/wallet.ts
|
|
6738
|
-
import { existsSync as
|
|
6739
|
-
import { homedir } from "node:os";
|
|
6740
|
-
import { join as
|
|
7078
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
7079
|
+
import { homedir as homedir2 } from "node:os";
|
|
7080
|
+
import { join as join4 } from "node:path";
|
|
6741
7081
|
function asNonEmptyString(value) {
|
|
6742
7082
|
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
6743
7083
|
}
|
|
6744
7084
|
function getLobsterWalletFromLocalConfig() {
|
|
6745
|
-
const agentsPath =
|
|
6746
|
-
if (!
|
|
7085
|
+
const agentsPath = join4(process.env.HOME || homedir2(), ".lobster", "agents.json");
|
|
7086
|
+
if (!existsSync5(agentsPath))
|
|
6747
7087
|
return;
|
|
6748
7088
|
try {
|
|
6749
|
-
const raw = JSON.parse(
|
|
7089
|
+
const raw = JSON.parse(readFileSync3(agentsPath, "utf8"));
|
|
6750
7090
|
const activeAgentId = asNonEmptyString(raw.activeAgentId);
|
|
6751
7091
|
const activeAgent = Array.isArray(raw.agents) ? raw.agents.find((agent) => asNonEmptyString(agent.id) === activeAgentId) : activeAgentId ? raw.agents?.[activeAgentId] : undefined;
|
|
6752
7092
|
return asNonEmptyString(activeAgent?.authorizedWallets?.solana) ?? asNonEmptyString(activeAgent?.walletAddress) ?? asNonEmptyString(activeAgent?.wallet_address);
|
|
@@ -6897,9 +7237,9 @@ __export(exports_lobster_pay, {
|
|
|
6897
7237
|
isLobsterAvailable: () => isLobsterAvailable
|
|
6898
7238
|
});
|
|
6899
7239
|
import { execFile, execFileSync as execFileSync2 } from "node:child_process";
|
|
6900
|
-
import { existsSync as
|
|
6901
|
-
import { homedir as
|
|
6902
|
-
import { join as
|
|
7240
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
7241
|
+
import { homedir as homedir3 } from "node:os";
|
|
7242
|
+
import { join as join5 } from "node:path";
|
|
6903
7243
|
function getLobsterCommand() {
|
|
6904
7244
|
try {
|
|
6905
7245
|
execFileSync2("lobstercash", ["--version"], { stdio: "ignore", timeout: 3000 });
|
|
@@ -6907,8 +7247,8 @@ function getLobsterCommand() {
|
|
|
6907
7247
|
} catch (_e) {}
|
|
6908
7248
|
try {
|
|
6909
7249
|
const npmPrefix = execFileSync2("npm", ["config", "get", "prefix"], { encoding: "utf8", timeout: 5000 }).trim();
|
|
6910
|
-
const lobsterPath =
|
|
6911
|
-
if (
|
|
7250
|
+
const lobsterPath = join5(npmPrefix, "bin", "lobstercash");
|
|
7251
|
+
if (existsSync6(lobsterPath)) {
|
|
6912
7252
|
execFileSync2(lobsterPath, ["--version"], { stdio: "ignore", timeout: 3000 });
|
|
6913
7253
|
return { cmd: lobsterPath, prefix: [] };
|
|
6914
7254
|
}
|
|
@@ -6921,8 +7261,8 @@ function lobsterCmd() {
|
|
|
6921
7261
|
return cachedCommand;
|
|
6922
7262
|
}
|
|
6923
7263
|
function isLobsterAvailable() {
|
|
6924
|
-
const agentsPath =
|
|
6925
|
-
return
|
|
7264
|
+
const agentsPath = join5(process.env.HOME || homedir3(), ".lobster", "agents.json");
|
|
7265
|
+
return existsSync6(agentsPath);
|
|
6926
7266
|
}
|
|
6927
7267
|
function lobsterX402Fetch(url, options) {
|
|
6928
7268
|
return new Promise((resolve) => {
|
|
@@ -7054,10 +7394,10 @@ __export(exports_client2, {
|
|
|
7054
7394
|
buildDefaultAgentName: () => buildDefaultAgentName,
|
|
7055
7395
|
autoFileIssue: () => autoFileIssue
|
|
7056
7396
|
});
|
|
7057
|
-
import { readFileSync as
|
|
7058
|
-
import { join as
|
|
7059
|
-
import { homedir as
|
|
7060
|
-
import { randomBytes, createHash as createHash3 } from "crypto";
|
|
7397
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
|
|
7398
|
+
import { join as join6 } from "path";
|
|
7399
|
+
import { homedir as homedir4, hostname, release as osRelease } from "os";
|
|
7400
|
+
import { randomBytes as randomBytes2, createHash as createHash3 } from "crypto";
|
|
7061
7401
|
import { createInterface } from "readline";
|
|
7062
7402
|
function buildReleaseAttestationHeaders(manifestBase64, signature) {
|
|
7063
7403
|
const manifest = manifestBase64.trim();
|
|
@@ -7091,18 +7431,18 @@ function scopedSkillKey(skillId, scopeId) {
|
|
|
7091
7431
|
return scopeId ? `${scopeId}:${skillId}` : skillId;
|
|
7092
7432
|
}
|
|
7093
7433
|
function getSkillCacheDir() {
|
|
7094
|
-
return process.env.UNBROWSE_SKILL_CACHE_DIR ||
|
|
7434
|
+
return process.env.UNBROWSE_SKILL_CACHE_DIR || join6(getConfigDir(), "skill-cache");
|
|
7095
7435
|
}
|
|
7096
7436
|
function getConfigDir() {
|
|
7097
7437
|
if (process.env.UNBROWSE_CONFIG_DIR)
|
|
7098
7438
|
return process.env.UNBROWSE_CONFIG_DIR;
|
|
7099
|
-
return PROFILE_NAME ?
|
|
7439
|
+
return PROFILE_NAME ? join6(homedir4(), ".unbrowse", "profiles", PROFILE_NAME) : join6(homedir4(), ".unbrowse");
|
|
7100
7440
|
}
|
|
7101
7441
|
function getConfigPath() {
|
|
7102
|
-
return
|
|
7442
|
+
return join6(getConfigDir(), "config.json");
|
|
7103
7443
|
}
|
|
7104
7444
|
function getInstallTelemetryPath() {
|
|
7105
|
-
return
|
|
7445
|
+
return join6(getConfigDir(), "install-state.json");
|
|
7106
7446
|
}
|
|
7107
7447
|
function getLandingToken() {
|
|
7108
7448
|
const token = process.env.UNBROWSE_LANDING_TOKEN?.trim();
|
|
@@ -7120,8 +7460,8 @@ function isLocalOnlyMode() {
|
|
|
7120
7460
|
function loadConfig() {
|
|
7121
7461
|
try {
|
|
7122
7462
|
const configPath = getConfigPath();
|
|
7123
|
-
if (
|
|
7124
|
-
return JSON.parse(
|
|
7463
|
+
if (existsSync7(configPath)) {
|
|
7464
|
+
return JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
7125
7465
|
}
|
|
7126
7466
|
} catch {}
|
|
7127
7467
|
return null;
|
|
@@ -7129,15 +7469,15 @@ function loadConfig() {
|
|
|
7129
7469
|
function saveConfig(config) {
|
|
7130
7470
|
const configDir = getConfigDir();
|
|
7131
7471
|
const configPath = getConfigPath();
|
|
7132
|
-
if (!
|
|
7133
|
-
|
|
7134
|
-
|
|
7472
|
+
if (!existsSync7(configDir))
|
|
7473
|
+
mkdirSync4(configDir, { recursive: true });
|
|
7474
|
+
writeFileSync3(configPath, JSON.stringify(config, null, 2), { mode: 384 });
|
|
7135
7475
|
}
|
|
7136
7476
|
function loadInstallTelemetryState() {
|
|
7137
7477
|
try {
|
|
7138
7478
|
const statePath = getInstallTelemetryPath();
|
|
7139
|
-
if (
|
|
7140
|
-
return JSON.parse(
|
|
7479
|
+
if (existsSync7(statePath)) {
|
|
7480
|
+
return JSON.parse(readFileSync4(statePath, "utf-8"));
|
|
7141
7481
|
}
|
|
7142
7482
|
} catch {}
|
|
7143
7483
|
return null;
|
|
@@ -7145,13 +7485,13 @@ function loadInstallTelemetryState() {
|
|
|
7145
7485
|
function saveInstallTelemetryState(state) {
|
|
7146
7486
|
const configDir = getConfigDir();
|
|
7147
7487
|
const statePath = getInstallTelemetryPath();
|
|
7148
|
-
if (!
|
|
7149
|
-
|
|
7150
|
-
|
|
7488
|
+
if (!existsSync7(configDir))
|
|
7489
|
+
mkdirSync4(configDir, { recursive: true });
|
|
7490
|
+
writeFileSync3(statePath, JSON.stringify(state, null, 2), { mode: 384 });
|
|
7151
7491
|
}
|
|
7152
7492
|
function createInstallTelemetryState() {
|
|
7153
7493
|
return {
|
|
7154
|
-
install_id: `install_${
|
|
7494
|
+
install_id: `install_${randomBytes2(8).toString("hex")}`,
|
|
7155
7495
|
first_seen_at: new Date().toISOString()
|
|
7156
7496
|
};
|
|
7157
7497
|
}
|
|
@@ -7291,7 +7631,7 @@ function isValidAgentEmail(value) {
|
|
|
7291
7631
|
return EMAIL_RE.test(normalizeAgentEmail(value));
|
|
7292
7632
|
}
|
|
7293
7633
|
function buildDefaultAgentName() {
|
|
7294
|
-
return `${hostname()}-${
|
|
7634
|
+
return `${hostname()}-${randomBytes2(3).toString("hex")}`;
|
|
7295
7635
|
}
|
|
7296
7636
|
function resolveAgentName(preferredEmail, fallbackName) {
|
|
7297
7637
|
const normalized = normalizeAgentEmail(preferredEmail ?? "");
|
|
@@ -7646,11 +7986,11 @@ async function waitForBackgroundRegistration(timeoutMs = 0) {
|
|
|
7646
7986
|
]);
|
|
7647
7987
|
}
|
|
7648
7988
|
function skillCachePath(skillId) {
|
|
7649
|
-
return
|
|
7989
|
+
return join6(getSkillCacheDir(), `${skillId}.json`);
|
|
7650
7990
|
}
|
|
7651
7991
|
function readSkillCache(skillId) {
|
|
7652
7992
|
try {
|
|
7653
|
-
const raw =
|
|
7993
|
+
const raw = readFileSync4(skillCachePath(skillId), "utf-8");
|
|
7654
7994
|
return JSON.parse(raw);
|
|
7655
7995
|
} catch {
|
|
7656
7996
|
return null;
|
|
@@ -7660,8 +8000,8 @@ function writeSkillCache(skill, scopeId) {
|
|
|
7660
8000
|
try {
|
|
7661
8001
|
recentLocalSkills.set(scopedSkillKey(skill.skill_id, scopeId), skill);
|
|
7662
8002
|
const skillCacheDir = getSkillCacheDir();
|
|
7663
|
-
if (!
|
|
7664
|
-
|
|
8003
|
+
if (!existsSync7(skillCacheDir))
|
|
8004
|
+
mkdirSync4(skillCacheDir, { recursive: true });
|
|
7665
8005
|
const existing = readSkillCache(skill.skill_id);
|
|
7666
8006
|
if (existing) {
|
|
7667
8007
|
for (const ep of skill.endpoints) {
|
|
@@ -7677,7 +8017,7 @@ function writeSkillCache(skill, scopeId) {
|
|
|
7677
8017
|
const hasStrategy = skill.endpoints.some((e) => e.exec_strategy);
|
|
7678
8018
|
if (hasStrategy)
|
|
7679
8019
|
console.log(`[cache] writing skill ${skill.skill_id} with exec_strategy`);
|
|
7680
|
-
|
|
8020
|
+
writeFileSync3(skillCachePath(skill.skill_id), JSON.stringify(skill), "utf-8");
|
|
7681
8021
|
} catch {}
|
|
7682
8022
|
}
|
|
7683
8023
|
function cachePublishedSkill(skill, scopeId) {
|
|
@@ -7712,7 +8052,7 @@ function isIntentCompatible(lhs, rhs) {
|
|
|
7712
8052
|
function findExistingSkillForDomain(domain, intent) {
|
|
7713
8053
|
try {
|
|
7714
8054
|
const skillCacheDir = getSkillCacheDir();
|
|
7715
|
-
if (!
|
|
8055
|
+
if (!existsSync7(skillCacheDir))
|
|
7716
8056
|
return null;
|
|
7717
8057
|
const files = readdirSync2(skillCacheDir);
|
|
7718
8058
|
let compatible = null;
|
|
@@ -7721,7 +8061,7 @@ function findExistingSkillForDomain(domain, intent) {
|
|
|
7721
8061
|
if (!f.endsWith(".json") || f === "browser-capture.json")
|
|
7722
8062
|
continue;
|
|
7723
8063
|
try {
|
|
7724
|
-
const raw =
|
|
8064
|
+
const raw = readFileSync4(join6(skillCacheDir, f), "utf-8");
|
|
7725
8065
|
const skill = JSON.parse(raw);
|
|
7726
8066
|
if (skill.domain === domain && skill.execution_type === "http") {
|
|
7727
8067
|
if (!fallback)
|
|
@@ -7771,11 +8111,11 @@ async function getSkillChunk2(skillId, opts) {
|
|
|
7771
8111
|
async function listSkills() {
|
|
7772
8112
|
if (LOCAL_ONLY) {
|
|
7773
8113
|
try {
|
|
7774
|
-
if (!
|
|
8114
|
+
if (!existsSync7(SKILL_CACHE_DIR))
|
|
7775
8115
|
return [];
|
|
7776
8116
|
return readdirSync2(SKILL_CACHE_DIR).filter((file) => file.endsWith(".json")).map((file) => {
|
|
7777
8117
|
try {
|
|
7778
|
-
return JSON.parse(
|
|
8118
|
+
return JSON.parse(readFileSync4(join6(SKILL_CACHE_DIR, file), "utf-8"));
|
|
7779
8119
|
} catch {
|
|
7780
8120
|
return null;
|
|
7781
8121
|
}
|
|
@@ -8467,10 +8807,10 @@ var init_publish_admission = __esm(() => {
|
|
|
8467
8807
|
|
|
8468
8808
|
// ../../src/telemetry.ts
|
|
8469
8809
|
import { createHash as createHash4 } from "node:crypto";
|
|
8470
|
-
import { existsSync as
|
|
8471
|
-
import { join as
|
|
8810
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
8811
|
+
import { join as join7 } from "node:path";
|
|
8472
8812
|
function getTraceDir() {
|
|
8473
|
-
return process.env.UNBROWSE_TRACES_DIR ??
|
|
8813
|
+
return process.env.UNBROWSE_TRACES_DIR ?? join7(process.env.HOME ?? "/tmp", ".unbrowse", "traces");
|
|
8474
8814
|
}
|
|
8475
8815
|
function isTracingEnabled() {
|
|
8476
8816
|
return process.env.UNBROWSE_DISABLE_TRACES !== "1";
|
|
@@ -8544,11 +8884,11 @@ function emitRouteTrace(params) {
|
|
|
8544
8884
|
};
|
|
8545
8885
|
try {
|
|
8546
8886
|
const traceDir = getTraceDir();
|
|
8547
|
-
if (!
|
|
8548
|
-
|
|
8887
|
+
if (!existsSync8(traceDir))
|
|
8888
|
+
mkdirSync5(traceDir, { recursive: true });
|
|
8549
8889
|
const stamp = params.started_at.replace(/[:.]/g, "-");
|
|
8550
|
-
const file =
|
|
8551
|
-
|
|
8890
|
+
const file = join7(traceDir, `${stamp}-${params.outcome}-${params.trace_id}.json`);
|
|
8891
|
+
writeFileSync4(file, JSON.stringify(artifact, null, 2), "utf-8");
|
|
8552
8892
|
return file;
|
|
8553
8893
|
} catch {
|
|
8554
8894
|
return null;
|
|
@@ -9184,161 +9524,6 @@ var init_token_resolver = __esm(() => {
|
|
|
9184
9524
|
init_token_sources();
|
|
9185
9525
|
});
|
|
9186
9526
|
|
|
9187
|
-
// ../../src/vault/index.ts
|
|
9188
|
-
import { createCipheriv, createDecipheriv, randomBytes as randomBytes2 } from "crypto";
|
|
9189
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
9190
|
-
import { join as join7 } from "path";
|
|
9191
|
-
import { homedir as homedir4 } from "os";
|
|
9192
|
-
function normalizeKeytarModule(mod) {
|
|
9193
|
-
let candidate = mod;
|
|
9194
|
-
for (let depth = 0;depth < 3; depth++) {
|
|
9195
|
-
if (!candidate || typeof candidate !== "object" || !("default" in candidate))
|
|
9196
|
-
break;
|
|
9197
|
-
candidate = candidate.default;
|
|
9198
|
-
}
|
|
9199
|
-
if (!candidate)
|
|
9200
|
-
return null;
|
|
9201
|
-
if (typeof candidate.setPassword === "function" && typeof candidate.getPassword === "function" && typeof candidate.deletePassword === "function") {
|
|
9202
|
-
return candidate;
|
|
9203
|
-
}
|
|
9204
|
-
return null;
|
|
9205
|
-
}
|
|
9206
|
-
function isKeytarBindingError(error) {
|
|
9207
|
-
const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
9208
|
-
return KEYTAR_BINDING_ERROR_RE.test(message);
|
|
9209
|
-
}
|
|
9210
|
-
function disableKeytar(error) {
|
|
9211
|
-
keytar = null;
|
|
9212
|
-
if (keytarFallbackLogged)
|
|
9213
|
-
return;
|
|
9214
|
-
const summary = error instanceof Error ? error.message : String(error);
|
|
9215
|
-
log("vault", `keytar runtime unavailable (${summary}); using encrypted file fallback`);
|
|
9216
|
-
keytarFallbackLogged = true;
|
|
9217
|
-
}
|
|
9218
|
-
async function callKeytar(op) {
|
|
9219
|
-
if (!keytar)
|
|
9220
|
-
return KEYTAR_UNAVAILABLE;
|
|
9221
|
-
try {
|
|
9222
|
-
return await op(keytar);
|
|
9223
|
-
} catch (error) {
|
|
9224
|
-
if (!isKeytarBindingError(error))
|
|
9225
|
-
throw error;
|
|
9226
|
-
disableKeytar(error);
|
|
9227
|
-
return KEYTAR_UNAVAILABLE;
|
|
9228
|
-
}
|
|
9229
|
-
}
|
|
9230
|
-
function getOrCreateKey() {
|
|
9231
|
-
if (!existsSync8(VAULT_DIR))
|
|
9232
|
-
mkdirSync5(VAULT_DIR, { recursive: true, mode: 448 });
|
|
9233
|
-
if (existsSync8(KEY_FILE))
|
|
9234
|
-
return readFileSync4(KEY_FILE);
|
|
9235
|
-
const key = randomBytes2(32);
|
|
9236
|
-
writeFileSync4(KEY_FILE, key, { mode: 384 });
|
|
9237
|
-
return key;
|
|
9238
|
-
}
|
|
9239
|
-
function withVaultLock(fn) {
|
|
9240
|
-
const prev = vaultLock;
|
|
9241
|
-
let release;
|
|
9242
|
-
vaultLock = new Promise((r) => {
|
|
9243
|
-
release = r;
|
|
9244
|
-
});
|
|
9245
|
-
return prev.then(fn).finally(() => release());
|
|
9246
|
-
}
|
|
9247
|
-
function readVaultFile() {
|
|
9248
|
-
if (!existsSync8(VAULT_FILE))
|
|
9249
|
-
return {};
|
|
9250
|
-
try {
|
|
9251
|
-
const key = getOrCreateKey();
|
|
9252
|
-
const raw = readFileSync4(VAULT_FILE);
|
|
9253
|
-
const iv = raw.subarray(0, 16);
|
|
9254
|
-
const enc = raw.subarray(16);
|
|
9255
|
-
const decipher = createDecipheriv("aes-256-cbc", key, iv);
|
|
9256
|
-
const dec = Buffer.concat([decipher.update(enc), decipher.final()]);
|
|
9257
|
-
return JSON.parse(dec.toString("utf8"));
|
|
9258
|
-
} catch {
|
|
9259
|
-
return {};
|
|
9260
|
-
}
|
|
9261
|
-
}
|
|
9262
|
-
function writeVaultFile(data) {
|
|
9263
|
-
const key = getOrCreateKey();
|
|
9264
|
-
const iv = randomBytes2(16);
|
|
9265
|
-
const cipher = createCipheriv("aes-256-cbc", key, iv);
|
|
9266
|
-
const enc = Buffer.concat([cipher.update(JSON.stringify(data), "utf8"), cipher.final()]);
|
|
9267
|
-
writeFileSync4(VAULT_FILE, Buffer.concat([iv, enc]), { mode: 384 });
|
|
9268
|
-
}
|
|
9269
|
-
async function storeCredential(account, value, opts) {
|
|
9270
|
-
const wrapped = {
|
|
9271
|
-
value,
|
|
9272
|
-
stored_at: new Date().toISOString(),
|
|
9273
|
-
expires_at: opts?.expires_at,
|
|
9274
|
-
max_age_ms: opts?.max_age_ms
|
|
9275
|
-
};
|
|
9276
|
-
const serialized = JSON.stringify(wrapped);
|
|
9277
|
-
const keytarResult = await callKeytar((client) => client.setPassword(SERVICE, account, serialized));
|
|
9278
|
-
if (keytarResult !== KEYTAR_UNAVAILABLE)
|
|
9279
|
-
return;
|
|
9280
|
-
await withVaultLock(() => {
|
|
9281
|
-
const data = readVaultFile();
|
|
9282
|
-
data[account] = serialized;
|
|
9283
|
-
writeVaultFile(data);
|
|
9284
|
-
});
|
|
9285
|
-
}
|
|
9286
|
-
function isExpired(cred) {
|
|
9287
|
-
if (cred.expires_at) {
|
|
9288
|
-
return new Date(cred.expires_at).getTime() <= Date.now();
|
|
9289
|
-
}
|
|
9290
|
-
if (cred.max_age_ms) {
|
|
9291
|
-
return new Date(cred.stored_at).getTime() + cred.max_age_ms <= Date.now();
|
|
9292
|
-
}
|
|
9293
|
-
return false;
|
|
9294
|
-
}
|
|
9295
|
-
async function getCredential(account) {
|
|
9296
|
-
let raw;
|
|
9297
|
-
const keytarResult = await callKeytar((client) => client.getPassword(SERVICE, account));
|
|
9298
|
-
if (keytarResult !== KEYTAR_UNAVAILABLE) {
|
|
9299
|
-
raw = keytarResult;
|
|
9300
|
-
} else {
|
|
9301
|
-
const data = readVaultFile();
|
|
9302
|
-
raw = data[account] ?? null;
|
|
9303
|
-
}
|
|
9304
|
-
if (!raw)
|
|
9305
|
-
return null;
|
|
9306
|
-
try {
|
|
9307
|
-
const parsed = JSON.parse(raw);
|
|
9308
|
-
if (parsed.value && parsed.stored_at) {
|
|
9309
|
-
if (isExpired(parsed)) {
|
|
9310
|
-
await deleteCredential(account);
|
|
9311
|
-
return null;
|
|
9312
|
-
}
|
|
9313
|
-
return parsed.value;
|
|
9314
|
-
}
|
|
9315
|
-
} catch {}
|
|
9316
|
-
return raw;
|
|
9317
|
-
}
|
|
9318
|
-
async function deleteCredential(account) {
|
|
9319
|
-
const keytarResult = await callKeytar((client) => client.deletePassword(SERVICE, account));
|
|
9320
|
-
if (keytarResult !== KEYTAR_UNAVAILABLE)
|
|
9321
|
-
return;
|
|
9322
|
-
await withVaultLock(() => {
|
|
9323
|
-
const data = readVaultFile();
|
|
9324
|
-
delete data[account];
|
|
9325
|
-
writeVaultFile(data);
|
|
9326
|
-
});
|
|
9327
|
-
}
|
|
9328
|
-
var KEYTAR_UNAVAILABLE, KEYTAR_BINDING_ERROR_RE, keytar = null, keytarFallbackLogged = false, SERVICE = "unbrowse", VAULT_DIR, VAULT_FILE, KEY_FILE, vaultLock;
|
|
9329
|
-
var init_vault = __esm(async () => {
|
|
9330
|
-
init_logger();
|
|
9331
|
-
KEYTAR_UNAVAILABLE = Symbol("KEYTAR_UNAVAILABLE");
|
|
9332
|
-
KEYTAR_BINDING_ERROR_RE = /(keytar(?:\.node)?|native bindings?|bindings file|no native build was found|could not locate the bindings file|module did not self-register|err_dlopen_failed|dlopen\(|compiled against a different node\.js version|cannot find module .*keytar|wasm is not supported on this platform|(set|get|delete)password is not a function)/i;
|
|
9333
|
-
try {
|
|
9334
|
-
keytar = normalizeKeytarModule(await import("keytar"));
|
|
9335
|
-
} catch {}
|
|
9336
|
-
VAULT_DIR = join7(homedir4(), ".unbrowse", "vault");
|
|
9337
|
-
VAULT_FILE = join7(VAULT_DIR, "credentials.enc");
|
|
9338
|
-
KEY_FILE = join7(VAULT_DIR, ".key");
|
|
9339
|
-
vaultLock = Promise.resolve();
|
|
9340
|
-
});
|
|
9341
|
-
|
|
9342
9527
|
// ../../src/runtime/supervisor.ts
|
|
9343
9528
|
function getDefaultLoginConfig(headless) {
|
|
9344
9529
|
return {
|
|
@@ -14010,6 +14195,10 @@ function validateWorkflowReplayParams(recipe, params) {
|
|
|
14010
14195
|
continue;
|
|
14011
14196
|
const value = valueForSpec(spec, params);
|
|
14012
14197
|
if (spec.required && (value == null || value === "")) {
|
|
14198
|
+
if (spec.default_value != null && spec.default_value !== "")
|
|
14199
|
+
continue;
|
|
14200
|
+
if (spec.example_value != null && spec.example_value !== "")
|
|
14201
|
+
continue;
|
|
14013
14202
|
errors.push({ name: spec.name, reason: "required" });
|
|
14014
14203
|
continue;
|
|
14015
14204
|
}
|
|
@@ -14304,18 +14493,27 @@ async function reloadExecutionAuthState(skill, epDomain, authHeaders, cookies) {
|
|
|
14304
14493
|
cookies.push(...resolved);
|
|
14305
14494
|
} catch {}
|
|
14306
14495
|
}
|
|
14307
|
-
|
|
14308
|
-
|
|
14309
|
-
|
|
14310
|
-
|
|
14311
|
-
|
|
14312
|
-
|
|
14313
|
-
|
|
14314
|
-
|
|
14315
|
-
|
|
14316
|
-
|
|
14317
|
-
|
|
14318
|
-
|
|
14496
|
+
{
|
|
14497
|
+
for (const sessionKey of [`${epDomain}-session`, `${getRegistrableDomain(epDomain)}-session`]) {
|
|
14498
|
+
try {
|
|
14499
|
+
const sessionData = await getCredential(sessionKey);
|
|
14500
|
+
if (sessionData) {
|
|
14501
|
+
const parsed = JSON.parse(sessionData);
|
|
14502
|
+
if (parsed.headers)
|
|
14503
|
+
Object.assign(authHeaders, parsed.headers);
|
|
14504
|
+
if (parsed.cookies && cookies.length === 0)
|
|
14505
|
+
cookies.push(...parsed.cookies);
|
|
14506
|
+
if (Object.keys(authHeaders).length > 0)
|
|
14507
|
+
break;
|
|
14508
|
+
}
|
|
14509
|
+
} catch {}
|
|
14510
|
+
}
|
|
14511
|
+
}
|
|
14512
|
+
if (cookies.length > 0 && authHeaders["csrf-token"]) {
|
|
14513
|
+
const jsessionId = cookies.find((c) => c.name === "JSESSIONID");
|
|
14514
|
+
if (jsessionId) {
|
|
14515
|
+
authHeaders["csrf-token"] = jsessionId.value.replace(/"/g, "");
|
|
14516
|
+
}
|
|
14319
14517
|
}
|
|
14320
14518
|
}
|
|
14321
14519
|
function persistWorkflowArtifactForCapture(artifactSkill, captured, capturedAuthHeaders) {
|
|
@@ -15336,10 +15534,13 @@ async function executeBrowserCapture(skill, params, options) {
|
|
|
15336
15534
|
}));
|
|
15337
15535
|
}
|
|
15338
15536
|
if (!auth_profile_ref) {
|
|
15339
|
-
const vaultKey
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15537
|
+
for (const vaultKey of [`auth:${targetDomain}`, `${domain}-session`, `${targetDomain}-session`]) {
|
|
15538
|
+
const hasStoredAuth = await getCredential(vaultKey) != null;
|
|
15539
|
+
if (hasStoredAuth) {
|
|
15540
|
+
auth_profile_ref = vaultKey;
|
|
15541
|
+
break;
|
|
15542
|
+
}
|
|
15543
|
+
}
|
|
15343
15544
|
}
|
|
15344
15545
|
const authBackedCapture = usedStoredAuth || !!auth_profile_ref;
|
|
15345
15546
|
if (authBackedCapture) {
|
|
@@ -15920,7 +16121,7 @@ async function executeEndpoint(skill, endpoint, params = {}, projection, options
|
|
|
15920
16121
|
u.searchParams.set(k, String(v));
|
|
15921
16122
|
}
|
|
15922
16123
|
}
|
|
15923
|
-
urlTemplate = restoreTemplatePlaceholderEncoding(u.toString());
|
|
16124
|
+
urlTemplate = restoreTemplatePlaceholderEncoding(u.toString()).replace(/%28/gi, "(").replace(/%29/gi, ")").replace(/%2C/gi, ",").replace(/%3A/gi, ":");
|
|
15924
16125
|
} catch {}
|
|
15925
16126
|
}
|
|
15926
16127
|
let url = interpolate(urlTemplate, mergedParams);
|
|
@@ -16056,7 +16257,7 @@ async function executeEndpoint(skill, endpoint, params = {}, projection, options
|
|
|
16056
16257
|
let last = { data: null, status: 0 };
|
|
16057
16258
|
for (const replayUrl of replayUrls) {
|
|
16058
16259
|
const replayHeaders = buildStructuredReplayHeaders(url, replayUrl, headers);
|
|
16059
|
-
log("exec", `server-fetch: ${endpoint.method} ${replayUrl.substring(0,
|
|
16260
|
+
log("exec", `server-fetch: ${endpoint.method} ${replayUrl.substring(0, 200)} csrf-token=${(replayHeaders["csrf-token"] || "none").substring(0, 20)}... hdrs=${Object.keys(replayHeaders).length} cookies=${replayHeaders["cookie"]?.length ?? 0}chars`);
|
|
16060
16261
|
const res = await fetch(replayUrl, {
|
|
16061
16262
|
method: endpoint.method,
|
|
16062
16263
|
headers: replayHeaders,
|
|
@@ -16460,7 +16661,12 @@ function interpolate(template, params) {
|
|
|
16460
16661
|
const base = template.substring(0, qIdx);
|
|
16461
16662
|
const query = template.substring(qIdx + 1);
|
|
16462
16663
|
const interpolatedBase = base.replace(/\{(\w+)\}/g, (_, k) => params[k] != null ? String(params[k]) : `{${k}}`);
|
|
16463
|
-
const interpolatedQuery = query.replace(/\{(\w+)\}/g, (_, k) =>
|
|
16664
|
+
const interpolatedQuery = query.replace(/\{(\w+)\}/g, (_, k) => {
|
|
16665
|
+
if (params[k] == null)
|
|
16666
|
+
return `{${k}}`;
|
|
16667
|
+
const val = String(params[k]);
|
|
16668
|
+
return val.replace(/[#&=\s]/g, (ch) => encodeURIComponent(ch));
|
|
16669
|
+
});
|
|
16464
16670
|
return `${interpolatedBase}?${interpolatedQuery}`;
|
|
16465
16671
|
}
|
|
16466
16672
|
function interpolateObj(obj, params) {
|
|
@@ -17020,8 +17226,6 @@ function isSpaShell(html) {
|
|
|
17020
17226
|
}
|
|
17021
17227
|
var DEFAULT_BROWSER_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", VALID_VERIFICATION_STATUSES, BM25_K1 = 1.2, BM25_B = 0.75, STOPWORDS, SYNONYMS;
|
|
17022
17228
|
var init_execution = __esm(async () => {
|
|
17023
|
-
init_capture();
|
|
17024
|
-
init_capture();
|
|
17025
17229
|
init_reverse_engineer();
|
|
17026
17230
|
init_bundle_scanner();
|
|
17027
17231
|
init_token_resolver();
|
|
@@ -17045,6 +17249,8 @@ var init_execution = __esm(async () => {
|
|
|
17045
17249
|
init_compile();
|
|
17046
17250
|
init_publish();
|
|
17047
17251
|
await __promiseAll([
|
|
17252
|
+
init_capture(),
|
|
17253
|
+
init_capture(),
|
|
17048
17254
|
init_vault(),
|
|
17049
17255
|
init_auth(),
|
|
17050
17256
|
init_indexer(),
|
|
@@ -19694,7 +19900,7 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
|
|
|
19694
19900
|
for (const cookie of cookies)
|
|
19695
19901
|
await setCookie(handoffTabId, cookie).catch(() => {});
|
|
19696
19902
|
} catch {}
|
|
19697
|
-
await evaluate(handoffTabId, (await
|
|
19903
|
+
await evaluate(handoffTabId, (await init_capture().then(() => exports_capture)).INTERCEPTOR_SCRIPT).catch(() => {});
|
|
19698
19904
|
await harStart(handoffTabId).catch(() => {});
|
|
19699
19905
|
try {
|
|
19700
19906
|
const routesModule = await init_routes().then(() => exports_routes);
|
|
@@ -24195,13 +24401,13 @@ function schedulePeriodicVerification() {
|
|
|
24195
24401
|
}, VERIFICATION_INTERVAL_MS);
|
|
24196
24402
|
}
|
|
24197
24403
|
var VERIFICATION_INTERVAL_MS, VERIFY_ENDPOINT_BATCH_SIZE;
|
|
24198
|
-
var init_verification = __esm(() => {
|
|
24199
|
-
init_capture();
|
|
24404
|
+
var init_verification = __esm(async () => {
|
|
24200
24405
|
init_marketplace();
|
|
24201
24406
|
init_marketplace();
|
|
24202
24407
|
init_drift();
|
|
24203
24408
|
init_matrix();
|
|
24204
24409
|
init_candidates();
|
|
24410
|
+
await init_capture();
|
|
24205
24411
|
VERIFICATION_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
24206
24412
|
VERIFY_ENDPOINT_BATCH_SIZE = Math.max(1, Number(process.env.UNBROWSE_VERIFY_ENDPOINT_BATCH_SIZE ?? 3));
|
|
24207
24413
|
});
|
|
@@ -24308,9 +24514,11 @@ function schedulePeriodicStaleCleanup() {
|
|
|
24308
24514
|
var VERIFY_TIMEOUT_MS, CLEANUP_INTERVAL_MS, CLEANUP_BATCH_SIZE, CLEANUP_VERIFY_ENDPOINT_LIMIT;
|
|
24309
24515
|
var init_stale_cleanup_runner = __esm(async () => {
|
|
24310
24516
|
init_marketplace();
|
|
24311
|
-
init_verification();
|
|
24312
24517
|
init_candidates();
|
|
24313
|
-
await
|
|
24518
|
+
await __promiseAll([
|
|
24519
|
+
init_verification(),
|
|
24520
|
+
init_orchestrator()
|
|
24521
|
+
]);
|
|
24314
24522
|
VERIFY_TIMEOUT_MS = Math.max(5000, Number(process.env.UNBROWSE_STALE_VERIFY_TIMEOUT_MS ?? 15000));
|
|
24315
24523
|
CLEANUP_INTERVAL_MS = Math.max(30 * 60 * 1000, Number(process.env.UNBROWSE_STALE_CLEANUP_INTERVAL_MS ?? 6 * 60 * 60 * 1000));
|
|
24316
24524
|
CLEANUP_BATCH_SIZE = Math.max(1, Number(process.env.UNBROWSE_STALE_CLEANUP_BATCH_SIZE ?? 25));
|
|
@@ -25352,7 +25560,7 @@ async function registerRoutes(app) {
|
|
|
25352
25560
|
if (!skill)
|
|
25353
25561
|
return reply.code(404).send({ error: "Skill not found" });
|
|
25354
25562
|
try {
|
|
25355
|
-
const { verifySkill: verifySkill2 } = await
|
|
25563
|
+
const { verifySkill: verifySkill2 } = await init_verification().then(() => exports_verification);
|
|
25356
25564
|
const results = await verifySkill2(skill);
|
|
25357
25565
|
return reply.send({ skill_id, verification: results });
|
|
25358
25566
|
} catch (err) {
|
|
@@ -25945,7 +26153,6 @@ var BETA_API_URL, TRACES_DIR, BROWSE_BROKER_MAX, BROWSE_BROKER_BASE_PORT, browse
|
|
|
25945
26153
|
var init_routes = __esm(async () => {
|
|
25946
26154
|
init_client();
|
|
25947
26155
|
init_reverse_engineer();
|
|
25948
|
-
init_capture();
|
|
25949
26156
|
init_marketplace();
|
|
25950
26157
|
init_graph();
|
|
25951
26158
|
init_client2();
|
|
@@ -25964,6 +26171,7 @@ var init_routes = __esm(async () => {
|
|
|
25964
26171
|
init_schema_review();
|
|
25965
26172
|
init_artifact();
|
|
25966
26173
|
await __promiseAll([
|
|
26174
|
+
init_capture(),
|
|
25967
26175
|
init_indexer(),
|
|
25968
26176
|
init_vault(),
|
|
25969
26177
|
init_orchestrator(),
|
|
@@ -25986,12 +26194,12 @@ import { config as loadEnv } from "dotenv";
|
|
|
25986
26194
|
|
|
25987
26195
|
// ../../src/server.ts
|
|
25988
26196
|
init_ratelimit();
|
|
25989
|
-
init_verification();
|
|
25990
26197
|
init_client2();
|
|
25991
|
-
init_capture();
|
|
25992
26198
|
init_version();
|
|
25993
26199
|
await __promiseAll([
|
|
25994
26200
|
init_routes(),
|
|
26201
|
+
init_verification(),
|
|
26202
|
+
init_capture(),
|
|
25995
26203
|
init_stale_cleanup_runner()
|
|
25996
26204
|
]);
|
|
25997
26205
|
import { execSync as execSync2 } from "node:child_process";
|
package/package.json
CHANGED