unbrowse 3.2.2 → 3.2.3
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 +2 -2
- package/dist/server.js +461 -258
- 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.2", BUILD_GIT_SHA = "150cce0d751e", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "
|
|
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";
|
|
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
|
@@ -228,8 +228,8 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
228
228
|
var BUILD_RELEASE_VERSION = "3.2.2";
|
|
229
229
|
var BUILD_GIT_SHA = "150cce0d751e";
|
|
230
230
|
var BUILD_CODE_HASH = "1488fc1d92b7";
|
|
231
|
-
var BUILD_RELEASE_MANIFEST_BASE64 = "
|
|
232
|
-
var BUILD_RELEASE_MANIFEST_SIGNATURE = "
|
|
231
|
+
var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiMy4yLjIiLCJnaXRfc2hhIjoiMTUwY2NlMGQ3NTFlIiwiY29kZV9oYXNoIjoiMTQ4OGZjMWQ5MmI3IiwidHJhY2VfdmVyc2lvbiI6IjE0ODhmYzFkOTJiN0AxNTBjY2UwZDc1MWUiLCJpc3N1ZWRfYXQiOiIyMDI2LTA0LTA2VDExOjU4OjM1LjkxNFoifQ";
|
|
232
|
+
var BUILD_RELEASE_MANIFEST_SIGNATURE = "Lfph_KbGZrv74O5Pnop_b_0GcSTspB27fOgkCMZK6tk";
|
|
233
233
|
var BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
|
|
234
234
|
|
|
235
235
|
// ../../src/version.ts
|
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,85 @@ 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
6230
|
try {
|
|
5937
|
-
const
|
|
5938
|
-
|
|
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 ?? [];
|
|
5939
6235
|
} catch {}
|
|
6236
|
+
if (cdpPendingBodies.size > 0) {
|
|
6237
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
6238
|
+
}
|
|
6239
|
+
if (cdpWs) {
|
|
6240
|
+
try {
|
|
6241
|
+
cdpWs.close();
|
|
6242
|
+
} catch {}
|
|
6243
|
+
}
|
|
6244
|
+
const harUrls = new Set(harEntries.map((e) => e.request?.url).filter(Boolean));
|
|
6245
|
+
let cdpAdded = 0;
|
|
6246
|
+
for (const [requestId, req] of cdpRequestMap) {
|
|
6247
|
+
if (harUrls.has(req.url))
|
|
6248
|
+
continue;
|
|
6249
|
+
const resp = cdpResponseMeta.get(requestId);
|
|
6250
|
+
if (!resp)
|
|
6251
|
+
continue;
|
|
6252
|
+
const body = cdpResolvedBodies.get(req.url);
|
|
6253
|
+
harEntries.push({
|
|
6254
|
+
startedDateTime: new Date().toISOString(),
|
|
6255
|
+
request: { method: req.method, url: req.url, headers: req.headers, postData: req.postData ? { text: req.postData } : undefined },
|
|
6256
|
+
response: { status: resp.status, headers: resp.headers, content: body ? { text: body, mimeType: resp.mimeType } : {} }
|
|
6257
|
+
});
|
|
6258
|
+
if (body && body.length > 0 && !responseBodies.has(req.url)) {
|
|
6259
|
+
responseBodies.set(req.url, body);
|
|
6260
|
+
}
|
|
6261
|
+
cdpAdded++;
|
|
6262
|
+
}
|
|
6263
|
+
if (cdpAdded > 0) {
|
|
6264
|
+
log("capture", `CDP direct capture added ${cdpAdded} entries (${cdpResolvedBodies.size} with bodies, ${harEntries.length} total HAR)`);
|
|
6265
|
+
}
|
|
5940
6266
|
const HAR_REPLAY_CT2 = /application\/json|text\/plain|\+json/i;
|
|
5941
6267
|
let harReplayCount = 0;
|
|
5942
6268
|
for (const entry of harEntries) {
|
|
@@ -5960,7 +6286,7 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
5960
6286
|
const postData = method !== "GET" ? entry.request?.postData?.text : undefined;
|
|
5961
6287
|
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
6288
|
const body = await phase("har-replay", () => evaluate(tabId, replayScript));
|
|
5963
|
-
if (typeof body === "string" && body.length > 0 && body.length <
|
|
6289
|
+
if (typeof body === "string" && body.length > 0 && body.length < 524288) {
|
|
5964
6290
|
responseBodies.set(harUrl, body);
|
|
5965
6291
|
harReplayCount++;
|
|
5966
6292
|
log("capture", `har-replay-fetched ${harUrl.substring(0, 80)} (${body.length}B)`);
|
|
@@ -5988,7 +6314,7 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
5988
6314
|
html = await phase("getPageHtml", () => getPageHtml(tabId));
|
|
5989
6315
|
} catch {}
|
|
5990
6316
|
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}})()` },
|
|
6317
|
+
{ 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
6318
|
{ name: "youtube", script: `(function(){try{return typeof ytInitialData!=='undefined'?JSON.stringify(ytInitialData):null}catch(e){return null}})()` },
|
|
5993
6319
|
{ name: "nextjs", script: `(function(){try{return window.__NEXT_DATA__?JSON.stringify(window.__NEXT_DATA__):null}catch(e){return null}})()` },
|
|
5994
6320
|
{ name: "nuxt", script: `(function(){try{return window.__NUXT__?JSON.stringify(window.__NUXT__):null}catch(e){return null}})()` }
|
|
@@ -6000,8 +6326,12 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
6000
6326
|
if (typeof raw !== "string" || !raw || raw === "null")
|
|
6001
6327
|
continue;
|
|
6002
6328
|
if (extractor.name === "ytmusic") {
|
|
6003
|
-
const
|
|
6004
|
-
|
|
6329
|
+
const parsed = JSON.parse(raw);
|
|
6330
|
+
const apiKey = parsed.__apiKey || "";
|
|
6331
|
+
const innertubeContext = parsed.__context;
|
|
6332
|
+
delete parsed.__apiKey;
|
|
6333
|
+
delete parsed.__context;
|
|
6334
|
+
for (const [path4, data] of Object.entries(parsed)) {
|
|
6005
6335
|
if (!data || typeof data !== "object")
|
|
6006
6336
|
continue;
|
|
6007
6337
|
const cleaned = { ...data };
|
|
@@ -6022,12 +6352,15 @@ async function captureSession(url, authHeaders, cookies, intent, options) {
|
|
|
6022
6352
|
continue;
|
|
6023
6353
|
const origin = new URL(url).origin;
|
|
6024
6354
|
const contextParams = new URL(url).searchParams;
|
|
6025
|
-
const
|
|
6355
|
+
const keyParam = apiKey ? `key=${apiKey}&` : "";
|
|
6356
|
+
const queryStr = path4.includes("search") && contextParams.toString() ? `?${keyParam}${contextParams.toString()}&prettyPrint=false` : `?${keyParam}prettyPrint=false`;
|
|
6026
6357
|
const syntheticUrl = `${origin}/youtubei/v1${path4}${queryStr}`;
|
|
6027
6358
|
responseBodies.set(syntheticUrl, bodyStr);
|
|
6359
|
+
const queryValue = contextParams.get("q") ?? "";
|
|
6360
|
+
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
6361
|
harEntries.push({
|
|
6029
6362
|
startedDateTime: new Date().toISOString(),
|
|
6030
|
-
request: { method: "POST", url: syntheticUrl, headers: [{ name: "content-type", value: "application/json" }], postData: { text:
|
|
6363
|
+
request: { method: "POST", url: syntheticUrl, headers: [{ name: "content-type", value: "application/json" }], postData: { text: postBody } },
|
|
6031
6364
|
response: { status: 200, headers: [{ name: "content-type", value: "application/json" }], content: { text: bodyStr, mimeType: "application/json" } }
|
|
6032
6365
|
});
|
|
6033
6366
|
embeddedDataCount++;
|
|
@@ -6523,11 +6856,13 @@ var MAX_CONCURRENT_TABS = 3, activeTabs = 0, waitQueue, activeTabRegistry, inter
|
|
|
6523
6856
|
return origSend.apply(this, arguments);
|
|
6524
6857
|
};
|
|
6525
6858
|
})()`, REPLAY_SKIP, HAR_REPLAY_CT;
|
|
6526
|
-
var init_capture = __esm(() => {
|
|
6859
|
+
var init_capture = __esm(async () => {
|
|
6527
6860
|
init_client();
|
|
6528
6861
|
init_domain();
|
|
6529
6862
|
init_logger();
|
|
6863
|
+
init_reverse_engineer();
|
|
6530
6864
|
init_browser_access();
|
|
6865
|
+
await init_vault();
|
|
6531
6866
|
waitQueue = [];
|
|
6532
6867
|
activeTabRegistry = new Set;
|
|
6533
6868
|
interceptorInjectedTabs = new Set;
|
|
@@ -6544,17 +6879,17 @@ var init_capture = __esm(() => {
|
|
|
6544
6879
|
});
|
|
6545
6880
|
|
|
6546
6881
|
// ../../src/build-info.generated.ts
|
|
6547
|
-
var BUILD_RELEASE_VERSION = "3.2.2", BUILD_GIT_SHA = "150cce0d751e", BUILD_CODE_HASH = "1488fc1d92b7", BUILD_RELEASE_MANIFEST_BASE64 = "
|
|
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";
|
|
6548
6883
|
|
|
6549
6884
|
// ../../src/version.ts
|
|
6550
6885
|
import { createHash } from "crypto";
|
|
6551
|
-
import { existsSync as
|
|
6552
|
-
import { dirname, join as
|
|
6886
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, readdirSync } from "fs";
|
|
6887
|
+
import { dirname, join as join3, parse } from "path";
|
|
6553
6888
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6554
6889
|
function collectTsFiles(dir) {
|
|
6555
6890
|
const results = [];
|
|
6556
6891
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
6557
|
-
const full =
|
|
6892
|
+
const full = join3(dir, entry.name);
|
|
6558
6893
|
if (entry.isDirectory() && entry.name !== "node_modules") {
|
|
6559
6894
|
results.push(...collectTsFiles(full));
|
|
6560
6895
|
} else if (entry.name.endsWith(".ts")) {
|
|
@@ -6567,21 +6902,21 @@ function hashFiles(srcDir, files) {
|
|
|
6567
6902
|
const hash = createHash("sha256");
|
|
6568
6903
|
for (const file of files) {
|
|
6569
6904
|
hash.update(file.slice(srcDir.length));
|
|
6570
|
-
hash.update(
|
|
6905
|
+
hash.update(readFileSync2(file, "utf-8"));
|
|
6571
6906
|
}
|
|
6572
6907
|
return hash.digest("hex").slice(0, 12);
|
|
6573
6908
|
}
|
|
6574
6909
|
function resolveCodeHashSourceDir(moduleDir) {
|
|
6575
6910
|
const candidates = [
|
|
6576
6911
|
moduleDir,
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6912
|
+
join3(moduleDir, "runtime-src"),
|
|
6913
|
+
join3(moduleDir, "..", "runtime-src"),
|
|
6914
|
+
join3(moduleDir, "src"),
|
|
6915
|
+
join3(moduleDir, "..", "src")
|
|
6581
6916
|
];
|
|
6582
6917
|
for (const candidate of candidates) {
|
|
6583
6918
|
try {
|
|
6584
|
-
if (!
|
|
6919
|
+
if (!existsSync4(candidate))
|
|
6585
6920
|
continue;
|
|
6586
6921
|
const files = collectTsFiles(candidate);
|
|
6587
6922
|
if (files.length > 0)
|
|
@@ -6631,7 +6966,7 @@ function getPackageVersionForModuleDir(moduleDir) {
|
|
|
6631
6966
|
const root = parse(dir).root;
|
|
6632
6967
|
while (true) {
|
|
6633
6968
|
try {
|
|
6634
|
-
const pkg = JSON.parse(
|
|
6969
|
+
const pkg = JSON.parse(readFileSync2(join3(dir, "package.json"), "utf-8"));
|
|
6635
6970
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
6636
6971
|
} catch {}
|
|
6637
6972
|
if (dir === root)
|
|
@@ -6735,18 +7070,18 @@ async function ensureCascadeSplitForSkill(skill, deps = {}) {
|
|
|
6735
7070
|
var init_cascade = () => {};
|
|
6736
7071
|
|
|
6737
7072
|
// ../../src/payments/wallet.ts
|
|
6738
|
-
import { existsSync as
|
|
6739
|
-
import { homedir } from "node:os";
|
|
6740
|
-
import { join as
|
|
7073
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
7074
|
+
import { homedir as homedir2 } from "node:os";
|
|
7075
|
+
import { join as join4 } from "node:path";
|
|
6741
7076
|
function asNonEmptyString(value) {
|
|
6742
7077
|
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
6743
7078
|
}
|
|
6744
7079
|
function getLobsterWalletFromLocalConfig() {
|
|
6745
|
-
const agentsPath =
|
|
6746
|
-
if (!
|
|
7080
|
+
const agentsPath = join4(process.env.HOME || homedir2(), ".lobster", "agents.json");
|
|
7081
|
+
if (!existsSync5(agentsPath))
|
|
6747
7082
|
return;
|
|
6748
7083
|
try {
|
|
6749
|
-
const raw = JSON.parse(
|
|
7084
|
+
const raw = JSON.parse(readFileSync3(agentsPath, "utf8"));
|
|
6750
7085
|
const activeAgentId = asNonEmptyString(raw.activeAgentId);
|
|
6751
7086
|
const activeAgent = Array.isArray(raw.agents) ? raw.agents.find((agent) => asNonEmptyString(agent.id) === activeAgentId) : activeAgentId ? raw.agents?.[activeAgentId] : undefined;
|
|
6752
7087
|
return asNonEmptyString(activeAgent?.authorizedWallets?.solana) ?? asNonEmptyString(activeAgent?.walletAddress) ?? asNonEmptyString(activeAgent?.wallet_address);
|
|
@@ -6897,9 +7232,9 @@ __export(exports_lobster_pay, {
|
|
|
6897
7232
|
isLobsterAvailable: () => isLobsterAvailable
|
|
6898
7233
|
});
|
|
6899
7234
|
import { execFile, execFileSync as execFileSync2 } from "node:child_process";
|
|
6900
|
-
import { existsSync as
|
|
6901
|
-
import { homedir as
|
|
6902
|
-
import { join as
|
|
7235
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
7236
|
+
import { homedir as homedir3 } from "node:os";
|
|
7237
|
+
import { join as join5 } from "node:path";
|
|
6903
7238
|
function getLobsterCommand() {
|
|
6904
7239
|
try {
|
|
6905
7240
|
execFileSync2("lobstercash", ["--version"], { stdio: "ignore", timeout: 3000 });
|
|
@@ -6907,8 +7242,8 @@ function getLobsterCommand() {
|
|
|
6907
7242
|
} catch (_e) {}
|
|
6908
7243
|
try {
|
|
6909
7244
|
const npmPrefix = execFileSync2("npm", ["config", "get", "prefix"], { encoding: "utf8", timeout: 5000 }).trim();
|
|
6910
|
-
const lobsterPath =
|
|
6911
|
-
if (
|
|
7245
|
+
const lobsterPath = join5(npmPrefix, "bin", "lobstercash");
|
|
7246
|
+
if (existsSync6(lobsterPath)) {
|
|
6912
7247
|
execFileSync2(lobsterPath, ["--version"], { stdio: "ignore", timeout: 3000 });
|
|
6913
7248
|
return { cmd: lobsterPath, prefix: [] };
|
|
6914
7249
|
}
|
|
@@ -6921,8 +7256,8 @@ function lobsterCmd() {
|
|
|
6921
7256
|
return cachedCommand;
|
|
6922
7257
|
}
|
|
6923
7258
|
function isLobsterAvailable() {
|
|
6924
|
-
const agentsPath =
|
|
6925
|
-
return
|
|
7259
|
+
const agentsPath = join5(process.env.HOME || homedir3(), ".lobster", "agents.json");
|
|
7260
|
+
return existsSync6(agentsPath);
|
|
6926
7261
|
}
|
|
6927
7262
|
function lobsterX402Fetch(url, options) {
|
|
6928
7263
|
return new Promise((resolve) => {
|
|
@@ -7054,10 +7389,10 @@ __export(exports_client2, {
|
|
|
7054
7389
|
buildDefaultAgentName: () => buildDefaultAgentName,
|
|
7055
7390
|
autoFileIssue: () => autoFileIssue
|
|
7056
7391
|
});
|
|
7057
|
-
import { readFileSync as
|
|
7058
|
-
import { join as
|
|
7059
|
-
import { homedir as
|
|
7060
|
-
import { randomBytes, createHash as createHash3 } from "crypto";
|
|
7392
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
|
|
7393
|
+
import { join as join6 } from "path";
|
|
7394
|
+
import { homedir as homedir4, hostname, release as osRelease } from "os";
|
|
7395
|
+
import { randomBytes as randomBytes2, createHash as createHash3 } from "crypto";
|
|
7061
7396
|
import { createInterface } from "readline";
|
|
7062
7397
|
function buildReleaseAttestationHeaders(manifestBase64, signature) {
|
|
7063
7398
|
const manifest = manifestBase64.trim();
|
|
@@ -7091,18 +7426,18 @@ function scopedSkillKey(skillId, scopeId) {
|
|
|
7091
7426
|
return scopeId ? `${scopeId}:${skillId}` : skillId;
|
|
7092
7427
|
}
|
|
7093
7428
|
function getSkillCacheDir() {
|
|
7094
|
-
return process.env.UNBROWSE_SKILL_CACHE_DIR ||
|
|
7429
|
+
return process.env.UNBROWSE_SKILL_CACHE_DIR || join6(getConfigDir(), "skill-cache");
|
|
7095
7430
|
}
|
|
7096
7431
|
function getConfigDir() {
|
|
7097
7432
|
if (process.env.UNBROWSE_CONFIG_DIR)
|
|
7098
7433
|
return process.env.UNBROWSE_CONFIG_DIR;
|
|
7099
|
-
return PROFILE_NAME ?
|
|
7434
|
+
return PROFILE_NAME ? join6(homedir4(), ".unbrowse", "profiles", PROFILE_NAME) : join6(homedir4(), ".unbrowse");
|
|
7100
7435
|
}
|
|
7101
7436
|
function getConfigPath() {
|
|
7102
|
-
return
|
|
7437
|
+
return join6(getConfigDir(), "config.json");
|
|
7103
7438
|
}
|
|
7104
7439
|
function getInstallTelemetryPath() {
|
|
7105
|
-
return
|
|
7440
|
+
return join6(getConfigDir(), "install-state.json");
|
|
7106
7441
|
}
|
|
7107
7442
|
function getLandingToken() {
|
|
7108
7443
|
const token = process.env.UNBROWSE_LANDING_TOKEN?.trim();
|
|
@@ -7120,8 +7455,8 @@ function isLocalOnlyMode() {
|
|
|
7120
7455
|
function loadConfig() {
|
|
7121
7456
|
try {
|
|
7122
7457
|
const configPath = getConfigPath();
|
|
7123
|
-
if (
|
|
7124
|
-
return JSON.parse(
|
|
7458
|
+
if (existsSync7(configPath)) {
|
|
7459
|
+
return JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
7125
7460
|
}
|
|
7126
7461
|
} catch {}
|
|
7127
7462
|
return null;
|
|
@@ -7129,15 +7464,15 @@ function loadConfig() {
|
|
|
7129
7464
|
function saveConfig(config) {
|
|
7130
7465
|
const configDir = getConfigDir();
|
|
7131
7466
|
const configPath = getConfigPath();
|
|
7132
|
-
if (!
|
|
7133
|
-
|
|
7134
|
-
|
|
7467
|
+
if (!existsSync7(configDir))
|
|
7468
|
+
mkdirSync4(configDir, { recursive: true });
|
|
7469
|
+
writeFileSync3(configPath, JSON.stringify(config, null, 2), { mode: 384 });
|
|
7135
7470
|
}
|
|
7136
7471
|
function loadInstallTelemetryState() {
|
|
7137
7472
|
try {
|
|
7138
7473
|
const statePath = getInstallTelemetryPath();
|
|
7139
|
-
if (
|
|
7140
|
-
return JSON.parse(
|
|
7474
|
+
if (existsSync7(statePath)) {
|
|
7475
|
+
return JSON.parse(readFileSync4(statePath, "utf-8"));
|
|
7141
7476
|
}
|
|
7142
7477
|
} catch {}
|
|
7143
7478
|
return null;
|
|
@@ -7145,13 +7480,13 @@ function loadInstallTelemetryState() {
|
|
|
7145
7480
|
function saveInstallTelemetryState(state) {
|
|
7146
7481
|
const configDir = getConfigDir();
|
|
7147
7482
|
const statePath = getInstallTelemetryPath();
|
|
7148
|
-
if (!
|
|
7149
|
-
|
|
7150
|
-
|
|
7483
|
+
if (!existsSync7(configDir))
|
|
7484
|
+
mkdirSync4(configDir, { recursive: true });
|
|
7485
|
+
writeFileSync3(statePath, JSON.stringify(state, null, 2), { mode: 384 });
|
|
7151
7486
|
}
|
|
7152
7487
|
function createInstallTelemetryState() {
|
|
7153
7488
|
return {
|
|
7154
|
-
install_id: `install_${
|
|
7489
|
+
install_id: `install_${randomBytes2(8).toString("hex")}`,
|
|
7155
7490
|
first_seen_at: new Date().toISOString()
|
|
7156
7491
|
};
|
|
7157
7492
|
}
|
|
@@ -7291,7 +7626,7 @@ function isValidAgentEmail(value) {
|
|
|
7291
7626
|
return EMAIL_RE.test(normalizeAgentEmail(value));
|
|
7292
7627
|
}
|
|
7293
7628
|
function buildDefaultAgentName() {
|
|
7294
|
-
return `${hostname()}-${
|
|
7629
|
+
return `${hostname()}-${randomBytes2(3).toString("hex")}`;
|
|
7295
7630
|
}
|
|
7296
7631
|
function resolveAgentName(preferredEmail, fallbackName) {
|
|
7297
7632
|
const normalized = normalizeAgentEmail(preferredEmail ?? "");
|
|
@@ -7646,11 +7981,11 @@ async function waitForBackgroundRegistration(timeoutMs = 0) {
|
|
|
7646
7981
|
]);
|
|
7647
7982
|
}
|
|
7648
7983
|
function skillCachePath(skillId) {
|
|
7649
|
-
return
|
|
7984
|
+
return join6(getSkillCacheDir(), `${skillId}.json`);
|
|
7650
7985
|
}
|
|
7651
7986
|
function readSkillCache(skillId) {
|
|
7652
7987
|
try {
|
|
7653
|
-
const raw =
|
|
7988
|
+
const raw = readFileSync4(skillCachePath(skillId), "utf-8");
|
|
7654
7989
|
return JSON.parse(raw);
|
|
7655
7990
|
} catch {
|
|
7656
7991
|
return null;
|
|
@@ -7660,8 +7995,8 @@ function writeSkillCache(skill, scopeId) {
|
|
|
7660
7995
|
try {
|
|
7661
7996
|
recentLocalSkills.set(scopedSkillKey(skill.skill_id, scopeId), skill);
|
|
7662
7997
|
const skillCacheDir = getSkillCacheDir();
|
|
7663
|
-
if (!
|
|
7664
|
-
|
|
7998
|
+
if (!existsSync7(skillCacheDir))
|
|
7999
|
+
mkdirSync4(skillCacheDir, { recursive: true });
|
|
7665
8000
|
const existing = readSkillCache(skill.skill_id);
|
|
7666
8001
|
if (existing) {
|
|
7667
8002
|
for (const ep of skill.endpoints) {
|
|
@@ -7677,7 +8012,7 @@ function writeSkillCache(skill, scopeId) {
|
|
|
7677
8012
|
const hasStrategy = skill.endpoints.some((e) => e.exec_strategy);
|
|
7678
8013
|
if (hasStrategy)
|
|
7679
8014
|
console.log(`[cache] writing skill ${skill.skill_id} with exec_strategy`);
|
|
7680
|
-
|
|
8015
|
+
writeFileSync3(skillCachePath(skill.skill_id), JSON.stringify(skill), "utf-8");
|
|
7681
8016
|
} catch {}
|
|
7682
8017
|
}
|
|
7683
8018
|
function cachePublishedSkill(skill, scopeId) {
|
|
@@ -7712,7 +8047,7 @@ function isIntentCompatible(lhs, rhs) {
|
|
|
7712
8047
|
function findExistingSkillForDomain(domain, intent) {
|
|
7713
8048
|
try {
|
|
7714
8049
|
const skillCacheDir = getSkillCacheDir();
|
|
7715
|
-
if (!
|
|
8050
|
+
if (!existsSync7(skillCacheDir))
|
|
7716
8051
|
return null;
|
|
7717
8052
|
const files = readdirSync2(skillCacheDir);
|
|
7718
8053
|
let compatible = null;
|
|
@@ -7721,7 +8056,7 @@ function findExistingSkillForDomain(domain, intent) {
|
|
|
7721
8056
|
if (!f.endsWith(".json") || f === "browser-capture.json")
|
|
7722
8057
|
continue;
|
|
7723
8058
|
try {
|
|
7724
|
-
const raw =
|
|
8059
|
+
const raw = readFileSync4(join6(skillCacheDir, f), "utf-8");
|
|
7725
8060
|
const skill = JSON.parse(raw);
|
|
7726
8061
|
if (skill.domain === domain && skill.execution_type === "http") {
|
|
7727
8062
|
if (!fallback)
|
|
@@ -7771,11 +8106,11 @@ async function getSkillChunk2(skillId, opts) {
|
|
|
7771
8106
|
async function listSkills() {
|
|
7772
8107
|
if (LOCAL_ONLY) {
|
|
7773
8108
|
try {
|
|
7774
|
-
if (!
|
|
8109
|
+
if (!existsSync7(SKILL_CACHE_DIR))
|
|
7775
8110
|
return [];
|
|
7776
8111
|
return readdirSync2(SKILL_CACHE_DIR).filter((file) => file.endsWith(".json")).map((file) => {
|
|
7777
8112
|
try {
|
|
7778
|
-
return JSON.parse(
|
|
8113
|
+
return JSON.parse(readFileSync4(join6(SKILL_CACHE_DIR, file), "utf-8"));
|
|
7779
8114
|
} catch {
|
|
7780
8115
|
return null;
|
|
7781
8116
|
}
|
|
@@ -8467,10 +8802,10 @@ var init_publish_admission = __esm(() => {
|
|
|
8467
8802
|
|
|
8468
8803
|
// ../../src/telemetry.ts
|
|
8469
8804
|
import { createHash as createHash4 } from "node:crypto";
|
|
8470
|
-
import { existsSync as
|
|
8471
|
-
import { join as
|
|
8805
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
8806
|
+
import { join as join7 } from "node:path";
|
|
8472
8807
|
function getTraceDir() {
|
|
8473
|
-
return process.env.UNBROWSE_TRACES_DIR ??
|
|
8808
|
+
return process.env.UNBROWSE_TRACES_DIR ?? join7(process.env.HOME ?? "/tmp", ".unbrowse", "traces");
|
|
8474
8809
|
}
|
|
8475
8810
|
function isTracingEnabled() {
|
|
8476
8811
|
return process.env.UNBROWSE_DISABLE_TRACES !== "1";
|
|
@@ -8544,11 +8879,11 @@ function emitRouteTrace(params) {
|
|
|
8544
8879
|
};
|
|
8545
8880
|
try {
|
|
8546
8881
|
const traceDir = getTraceDir();
|
|
8547
|
-
if (!
|
|
8548
|
-
|
|
8882
|
+
if (!existsSync8(traceDir))
|
|
8883
|
+
mkdirSync5(traceDir, { recursive: true });
|
|
8549
8884
|
const stamp = params.started_at.replace(/[:.]/g, "-");
|
|
8550
|
-
const file =
|
|
8551
|
-
|
|
8885
|
+
const file = join7(traceDir, `${stamp}-${params.outcome}-${params.trace_id}.json`);
|
|
8886
|
+
writeFileSync4(file, JSON.stringify(artifact, null, 2), "utf-8");
|
|
8552
8887
|
return file;
|
|
8553
8888
|
} catch {
|
|
8554
8889
|
return null;
|
|
@@ -9184,161 +9519,6 @@ var init_token_resolver = __esm(() => {
|
|
|
9184
9519
|
init_token_sources();
|
|
9185
9520
|
});
|
|
9186
9521
|
|
|
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
9522
|
// ../../src/runtime/supervisor.ts
|
|
9343
9523
|
function getDefaultLoginConfig(headless) {
|
|
9344
9524
|
return {
|
|
@@ -14010,6 +14190,10 @@ function validateWorkflowReplayParams(recipe, params) {
|
|
|
14010
14190
|
continue;
|
|
14011
14191
|
const value = valueForSpec(spec, params);
|
|
14012
14192
|
if (spec.required && (value == null || value === "")) {
|
|
14193
|
+
if (spec.default_value != null && spec.default_value !== "")
|
|
14194
|
+
continue;
|
|
14195
|
+
if (spec.example_value != null && spec.example_value !== "")
|
|
14196
|
+
continue;
|
|
14013
14197
|
errors.push({ name: spec.name, reason: "required" });
|
|
14014
14198
|
continue;
|
|
14015
14199
|
}
|
|
@@ -14304,18 +14488,27 @@ async function reloadExecutionAuthState(skill, epDomain, authHeaders, cookies) {
|
|
|
14304
14488
|
cookies.push(...resolved);
|
|
14305
14489
|
} catch {}
|
|
14306
14490
|
}
|
|
14307
|
-
|
|
14308
|
-
|
|
14309
|
-
|
|
14310
|
-
|
|
14311
|
-
|
|
14312
|
-
|
|
14313
|
-
|
|
14314
|
-
|
|
14315
|
-
|
|
14316
|
-
|
|
14317
|
-
|
|
14318
|
-
|
|
14491
|
+
{
|
|
14492
|
+
for (const sessionKey of [`${epDomain}-session`, `${getRegistrableDomain(epDomain)}-session`]) {
|
|
14493
|
+
try {
|
|
14494
|
+
const sessionData = await getCredential(sessionKey);
|
|
14495
|
+
if (sessionData) {
|
|
14496
|
+
const parsed = JSON.parse(sessionData);
|
|
14497
|
+
if (parsed.headers)
|
|
14498
|
+
Object.assign(authHeaders, parsed.headers);
|
|
14499
|
+
if (parsed.cookies && cookies.length === 0)
|
|
14500
|
+
cookies.push(...parsed.cookies);
|
|
14501
|
+
if (Object.keys(authHeaders).length > 0)
|
|
14502
|
+
break;
|
|
14503
|
+
}
|
|
14504
|
+
} catch {}
|
|
14505
|
+
}
|
|
14506
|
+
}
|
|
14507
|
+
if (cookies.length > 0 && authHeaders["csrf-token"]) {
|
|
14508
|
+
const jsessionId = cookies.find((c) => c.name === "JSESSIONID");
|
|
14509
|
+
if (jsessionId) {
|
|
14510
|
+
authHeaders["csrf-token"] = jsessionId.value.replace(/"/g, "");
|
|
14511
|
+
}
|
|
14319
14512
|
}
|
|
14320
14513
|
}
|
|
14321
14514
|
function persistWorkflowArtifactForCapture(artifactSkill, captured, capturedAuthHeaders) {
|
|
@@ -15336,10 +15529,13 @@ async function executeBrowserCapture(skill, params, options) {
|
|
|
15336
15529
|
}));
|
|
15337
15530
|
}
|
|
15338
15531
|
if (!auth_profile_ref) {
|
|
15339
|
-
const vaultKey
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15532
|
+
for (const vaultKey of [`auth:${targetDomain}`, `${domain}-session`, `${targetDomain}-session`]) {
|
|
15533
|
+
const hasStoredAuth = await getCredential(vaultKey) != null;
|
|
15534
|
+
if (hasStoredAuth) {
|
|
15535
|
+
auth_profile_ref = vaultKey;
|
|
15536
|
+
break;
|
|
15537
|
+
}
|
|
15538
|
+
}
|
|
15343
15539
|
}
|
|
15344
15540
|
const authBackedCapture = usedStoredAuth || !!auth_profile_ref;
|
|
15345
15541
|
if (authBackedCapture) {
|
|
@@ -15920,7 +16116,7 @@ async function executeEndpoint(skill, endpoint, params = {}, projection, options
|
|
|
15920
16116
|
u.searchParams.set(k, String(v));
|
|
15921
16117
|
}
|
|
15922
16118
|
}
|
|
15923
|
-
urlTemplate = restoreTemplatePlaceholderEncoding(u.toString());
|
|
16119
|
+
urlTemplate = restoreTemplatePlaceholderEncoding(u.toString()).replace(/%28/gi, "(").replace(/%29/gi, ")").replace(/%2C/gi, ",").replace(/%3A/gi, ":");
|
|
15924
16120
|
} catch {}
|
|
15925
16121
|
}
|
|
15926
16122
|
let url = interpolate(urlTemplate, mergedParams);
|
|
@@ -16056,7 +16252,7 @@ async function executeEndpoint(skill, endpoint, params = {}, projection, options
|
|
|
16056
16252
|
let last = { data: null, status: 0 };
|
|
16057
16253
|
for (const replayUrl of replayUrls) {
|
|
16058
16254
|
const replayHeaders = buildStructuredReplayHeaders(url, replayUrl, headers);
|
|
16059
|
-
log("exec", `server-fetch: ${endpoint.method} ${replayUrl.substring(0,
|
|
16255
|
+
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
16256
|
const res = await fetch(replayUrl, {
|
|
16061
16257
|
method: endpoint.method,
|
|
16062
16258
|
headers: replayHeaders,
|
|
@@ -16460,7 +16656,12 @@ function interpolate(template, params) {
|
|
|
16460
16656
|
const base = template.substring(0, qIdx);
|
|
16461
16657
|
const query = template.substring(qIdx + 1);
|
|
16462
16658
|
const interpolatedBase = base.replace(/\{(\w+)\}/g, (_, k) => params[k] != null ? String(params[k]) : `{${k}}`);
|
|
16463
|
-
const interpolatedQuery = query.replace(/\{(\w+)\}/g, (_, k) =>
|
|
16659
|
+
const interpolatedQuery = query.replace(/\{(\w+)\}/g, (_, k) => {
|
|
16660
|
+
if (params[k] == null)
|
|
16661
|
+
return `{${k}}`;
|
|
16662
|
+
const val = String(params[k]);
|
|
16663
|
+
return val.replace(/[#&=\s]/g, (ch) => encodeURIComponent(ch));
|
|
16664
|
+
});
|
|
16464
16665
|
return `${interpolatedBase}?${interpolatedQuery}`;
|
|
16465
16666
|
}
|
|
16466
16667
|
function interpolateObj(obj, params) {
|
|
@@ -17020,8 +17221,6 @@ function isSpaShell(html) {
|
|
|
17020
17221
|
}
|
|
17021
17222
|
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
17223
|
var init_execution = __esm(async () => {
|
|
17023
|
-
init_capture();
|
|
17024
|
-
init_capture();
|
|
17025
17224
|
init_reverse_engineer();
|
|
17026
17225
|
init_bundle_scanner();
|
|
17027
17226
|
init_token_resolver();
|
|
@@ -17045,6 +17244,8 @@ var init_execution = __esm(async () => {
|
|
|
17045
17244
|
init_compile();
|
|
17046
17245
|
init_publish();
|
|
17047
17246
|
await __promiseAll([
|
|
17247
|
+
init_capture(),
|
|
17248
|
+
init_capture(),
|
|
17048
17249
|
init_vault(),
|
|
17049
17250
|
init_auth(),
|
|
17050
17251
|
init_indexer(),
|
|
@@ -19694,7 +19895,7 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
|
|
|
19694
19895
|
for (const cookie of cookies)
|
|
19695
19896
|
await setCookie(handoffTabId, cookie).catch(() => {});
|
|
19696
19897
|
} catch {}
|
|
19697
|
-
await evaluate(handoffTabId, (await
|
|
19898
|
+
await evaluate(handoffTabId, (await init_capture().then(() => exports_capture)).INTERCEPTOR_SCRIPT).catch(() => {});
|
|
19698
19899
|
await harStart(handoffTabId).catch(() => {});
|
|
19699
19900
|
try {
|
|
19700
19901
|
const routesModule = await init_routes().then(() => exports_routes);
|
|
@@ -24195,13 +24396,13 @@ function schedulePeriodicVerification() {
|
|
|
24195
24396
|
}, VERIFICATION_INTERVAL_MS);
|
|
24196
24397
|
}
|
|
24197
24398
|
var VERIFICATION_INTERVAL_MS, VERIFY_ENDPOINT_BATCH_SIZE;
|
|
24198
|
-
var init_verification = __esm(() => {
|
|
24199
|
-
init_capture();
|
|
24399
|
+
var init_verification = __esm(async () => {
|
|
24200
24400
|
init_marketplace();
|
|
24201
24401
|
init_marketplace();
|
|
24202
24402
|
init_drift();
|
|
24203
24403
|
init_matrix();
|
|
24204
24404
|
init_candidates();
|
|
24405
|
+
await init_capture();
|
|
24205
24406
|
VERIFICATION_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
24206
24407
|
VERIFY_ENDPOINT_BATCH_SIZE = Math.max(1, Number(process.env.UNBROWSE_VERIFY_ENDPOINT_BATCH_SIZE ?? 3));
|
|
24207
24408
|
});
|
|
@@ -24308,9 +24509,11 @@ function schedulePeriodicStaleCleanup() {
|
|
|
24308
24509
|
var VERIFY_TIMEOUT_MS, CLEANUP_INTERVAL_MS, CLEANUP_BATCH_SIZE, CLEANUP_VERIFY_ENDPOINT_LIMIT;
|
|
24309
24510
|
var init_stale_cleanup_runner = __esm(async () => {
|
|
24310
24511
|
init_marketplace();
|
|
24311
|
-
init_verification();
|
|
24312
24512
|
init_candidates();
|
|
24313
|
-
await
|
|
24513
|
+
await __promiseAll([
|
|
24514
|
+
init_verification(),
|
|
24515
|
+
init_orchestrator()
|
|
24516
|
+
]);
|
|
24314
24517
|
VERIFY_TIMEOUT_MS = Math.max(5000, Number(process.env.UNBROWSE_STALE_VERIFY_TIMEOUT_MS ?? 15000));
|
|
24315
24518
|
CLEANUP_INTERVAL_MS = Math.max(30 * 60 * 1000, Number(process.env.UNBROWSE_STALE_CLEANUP_INTERVAL_MS ?? 6 * 60 * 60 * 1000));
|
|
24316
24519
|
CLEANUP_BATCH_SIZE = Math.max(1, Number(process.env.UNBROWSE_STALE_CLEANUP_BATCH_SIZE ?? 25));
|
|
@@ -25352,7 +25555,7 @@ async function registerRoutes(app) {
|
|
|
25352
25555
|
if (!skill)
|
|
25353
25556
|
return reply.code(404).send({ error: "Skill not found" });
|
|
25354
25557
|
try {
|
|
25355
|
-
const { verifySkill: verifySkill2 } = await
|
|
25558
|
+
const { verifySkill: verifySkill2 } = await init_verification().then(() => exports_verification);
|
|
25356
25559
|
const results = await verifySkill2(skill);
|
|
25357
25560
|
return reply.send({ skill_id, verification: results });
|
|
25358
25561
|
} catch (err) {
|
|
@@ -25945,7 +26148,6 @@ var BETA_API_URL, TRACES_DIR, BROWSE_BROKER_MAX, BROWSE_BROKER_BASE_PORT, browse
|
|
|
25945
26148
|
var init_routes = __esm(async () => {
|
|
25946
26149
|
init_client();
|
|
25947
26150
|
init_reverse_engineer();
|
|
25948
|
-
init_capture();
|
|
25949
26151
|
init_marketplace();
|
|
25950
26152
|
init_graph();
|
|
25951
26153
|
init_client2();
|
|
@@ -25964,6 +26166,7 @@ var init_routes = __esm(async () => {
|
|
|
25964
26166
|
init_schema_review();
|
|
25965
26167
|
init_artifact();
|
|
25966
26168
|
await __promiseAll([
|
|
26169
|
+
init_capture(),
|
|
25967
26170
|
init_indexer(),
|
|
25968
26171
|
init_vault(),
|
|
25969
26172
|
init_orchestrator(),
|
|
@@ -25986,12 +26189,12 @@ import { config as loadEnv } from "dotenv";
|
|
|
25986
26189
|
|
|
25987
26190
|
// ../../src/server.ts
|
|
25988
26191
|
init_ratelimit();
|
|
25989
|
-
init_verification();
|
|
25990
26192
|
init_client2();
|
|
25991
|
-
init_capture();
|
|
25992
26193
|
init_version();
|
|
25993
26194
|
await __promiseAll([
|
|
25994
26195
|
init_routes(),
|
|
26196
|
+
init_verification(),
|
|
26197
|
+
init_capture(),
|
|
25995
26198
|
init_stale_cleanup_runner()
|
|
25996
26199
|
]);
|
|
25997
26200
|
import { execSync as execSync2 } from "node:child_process";
|