unbrowse 6.5.0-preview.9 → 6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +76 -10
- package/dist/mcp.js +9 -5
- package/dist/server.js +118 -12
- 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 = "6.5.0
|
|
34
|
+
var BUILD_RELEASE_VERSION = "6.5.0", BUILD_GIT_SHA = "a0a05eb03b07", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi41LjAiLCJnaXRfc2hhIjoiYTBhMDVlYjAzYjA3IiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUBhMGEwNWViMDNiMDciLCJpc3N1ZWRfYXQiOiIyMDI2LTA1LTAzVDE3OjA4OjI2Ljg3OVoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "QG8diudmY_8OEQowkwHoR3Wac09OBJjDifA_xd9kmr0", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
|
|
35
35
|
|
|
36
36
|
// ../../src/version.ts
|
|
37
37
|
import { createHash } from "crypto";
|
|
@@ -2949,6 +2949,17 @@ function loadConfig() {
|
|
|
2949
2949
|
} catch {}
|
|
2950
2950
|
return null;
|
|
2951
2951
|
}
|
|
2952
|
+
function resetLocalRegistration() {
|
|
2953
|
+
const configPath = getConfigPath();
|
|
2954
|
+
try {
|
|
2955
|
+
if (!existsSync4(configPath))
|
|
2956
|
+
return { removed: false, config_path: configPath };
|
|
2957
|
+
unlinkSync(configPath);
|
|
2958
|
+
return { removed: true, config_path: configPath };
|
|
2959
|
+
} catch {
|
|
2960
|
+
return { removed: false, config_path: configPath };
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2952
2963
|
function saveConfig(config) {
|
|
2953
2964
|
const configDir = getConfigDir();
|
|
2954
2965
|
const configPath = getConfigPath();
|
|
@@ -3144,9 +3155,13 @@ function getLocalWalletContext() {
|
|
|
3144
3155
|
function getApiKey() {
|
|
3145
3156
|
if (LOCAL_ONLY)
|
|
3146
3157
|
return "local-only";
|
|
3158
|
+
const config = loadConfig();
|
|
3159
|
+
if (config?.ignore_env_api_key && config.api_key) {
|
|
3160
|
+
process.env.UNBROWSE_API_KEY = config.api_key;
|
|
3161
|
+
return config.api_key;
|
|
3162
|
+
}
|
|
3147
3163
|
if (process.env.UNBROWSE_API_KEY)
|
|
3148
3164
|
return process.env.UNBROWSE_API_KEY;
|
|
3149
|
-
const config = loadConfig();
|
|
3150
3165
|
if (config?.api_key) {
|
|
3151
3166
|
process.env.UNBROWSE_API_KEY = config.api_key;
|
|
3152
3167
|
return config.api_key;
|
|
@@ -3459,7 +3474,19 @@ async function ensureRegistered(options) {
|
|
|
3459
3474
|
try {
|
|
3460
3475
|
const wallet = getLocalWalletContext();
|
|
3461
3476
|
const attribution = parseInstallAttribution();
|
|
3462
|
-
|
|
3477
|
+
let registeredWallet = wallet;
|
|
3478
|
+
let registration;
|
|
3479
|
+
try {
|
|
3480
|
+
registration = await api("POST", "/v1/agents/register", { name, tos_version: tosInfo.version, ...wallet, ...attribution });
|
|
3481
|
+
} catch (err) {
|
|
3482
|
+
const msg = err.message ?? "";
|
|
3483
|
+
if (!wallet.wallet_address || !msg.includes("wallet_already_claimed"))
|
|
3484
|
+
throw err;
|
|
3485
|
+
console.warn("[unbrowse] Wallet is already claimed by another agent. Registering this CLI without a payout wallet; sign in by email or run `unbrowse register --email ... --reset` to recover that account.");
|
|
3486
|
+
registeredWallet = {};
|
|
3487
|
+
registration = await api("POST", "/v1/agents/register", { name, tos_version: tosInfo.version, ...attribution });
|
|
3488
|
+
}
|
|
3489
|
+
const { agent_id, api_key } = registration;
|
|
3463
3490
|
process.env.UNBROWSE_API_KEY = api_key;
|
|
3464
3491
|
saveConfig({
|
|
3465
3492
|
api_key,
|
|
@@ -3468,7 +3495,8 @@ async function ensureRegistered(options) {
|
|
|
3468
3495
|
registered_at: new Date().toISOString(),
|
|
3469
3496
|
tos_accepted_version: tosInfo.version,
|
|
3470
3497
|
tos_accepted_at: new Date().toISOString(),
|
|
3471
|
-
...
|
|
3498
|
+
...process.env.UNBROWSE_IGNORE_ENV_API_KEY === "1" ? { ignore_env_api_key: true } : {},
|
|
3499
|
+
...registeredWallet
|
|
3472
3500
|
});
|
|
3473
3501
|
await recordFunnelTelemetryEvent("registration_succeeded", {
|
|
3474
3502
|
source: "cli",
|
|
@@ -5641,6 +5669,7 @@ async function cmdExecute(flags) {
|
|
|
5641
5669
|
const limitFlag = flags.limit ? Number(flags.limit) : undefined;
|
|
5642
5670
|
const schemaFlag = !!flags.schema;
|
|
5643
5671
|
const rawFlag = !!flags.raw;
|
|
5672
|
+
const resultError = resolveResultError(result);
|
|
5644
5673
|
if (schemaFlag && !rawFlag) {
|
|
5645
5674
|
const data = result.result;
|
|
5646
5675
|
output({
|
|
@@ -5651,7 +5680,7 @@ async function cmdExecute(flags) {
|
|
|
5651
5680
|
}, !!flags.pretty);
|
|
5652
5681
|
return;
|
|
5653
5682
|
}
|
|
5654
|
-
if (!rawFlag && (pathFlag || extractFlag || limitFlag)) {
|
|
5683
|
+
if (!rawFlag && !resultError && (pathFlag || extractFlag || limitFlag)) {
|
|
5655
5684
|
const data = pathFlag ? drillPath(result.result, pathFlag) : result.result;
|
|
5656
5685
|
const items = Array.isArray(data) ? data : data != null ? [data] : [];
|
|
5657
5686
|
const extracted = extractFlag ? applyExtract(items, extractFlag) : items;
|
|
@@ -6115,6 +6144,14 @@ async function refreshContributionPreferenceFromServer(verbose = false) {
|
|
|
6115
6144
|
}
|
|
6116
6145
|
}
|
|
6117
6146
|
async function cmdAccount(flags) {
|
|
6147
|
+
if (flags["reset-key"]) {
|
|
6148
|
+
await cmdRegister({
|
|
6149
|
+
reset: true,
|
|
6150
|
+
email: typeof flags.email === "string" ? flags.email : undefined,
|
|
6151
|
+
"no-prompt": flags["no-prompt"]
|
|
6152
|
+
});
|
|
6153
|
+
return;
|
|
6154
|
+
}
|
|
6118
6155
|
await refreshContributionPreferenceFromServer(false);
|
|
6119
6156
|
const cfg = loadConfig();
|
|
6120
6157
|
const contribution = getContributionConfig2();
|
|
@@ -6290,8 +6327,8 @@ var CLI_REFERENCE = {
|
|
|
6290
6327
|
{ name: "earnings", usage: "[--json]", desc: "Show your credit balance, earnings from indexing, and spending" },
|
|
6291
6328
|
{ name: "corpus-test", usage: "--url <url> [--id <id>] [--retries N]", desc: "Capture a single URL with retry logic; keeps best result across N attempts" },
|
|
6292
6329
|
{ name: "corpus-run", usage: "--corpus <file> --out <file> [--retries N]", desc: "Run corpus-test over all cases in a corpus JSON file and write a comparable snapshot" },
|
|
6293
|
-
{ name: "register", usage: "[--email lewis@example.com] [--no-prompt]", desc: "Register an API key. With --
|
|
6294
|
-
{ name: "account", usage: "[--json] [--pretty]", desc: "Show local account, dashboard link, wallet, and contribution mode" },
|
|
6330
|
+
{ name: "register", usage: "[--email lewis@example.com] [--reset] [--no-prompt]", desc: "Register an API key. With --reset, discard the local cached key first; with --email, mint an account-bound key." },
|
|
6331
|
+
{ name: "account", usage: "[--json] [--pretty] [--reset-key] [--email lewis@example.com]", desc: "Show local account, dashboard link, wallet, and contribution mode; --reset-key forces local key reset." },
|
|
6295
6332
|
{ name: "dashboard", usage: "[--no-open] [--pretty]", desc: "Open the website dashboard and pair it to this CLI install through localhost" },
|
|
6296
6333
|
{ name: "mode", usage: "", desc: "Re-prompt for contribution mode (private / share / share + earn)" },
|
|
6297
6334
|
{ name: "capture", usage: "--url <url> --intent <intent>", desc: "Live-browser capture for a single URL \u2014 discovers + indexes API endpoints. Marketplace publish gated by `unbrowse mode`." },
|
|
@@ -6890,9 +6927,35 @@ async function cmdClose(flags) {
|
|
|
6890
6927
|
output(await api2("POST", "/v1/browse/close", typeof flags.session === "string" ? { session_id: flags.session } : undefined), false);
|
|
6891
6928
|
}
|
|
6892
6929
|
async function cmdRegister(flags) {
|
|
6930
|
+
const reset = flags.reset === true || flags.force === true || flags["reset-key"] === true;
|
|
6931
|
+
const previousConfig = reset ? loadConfig() : null;
|
|
6932
|
+
let ignoredEnvApiKey = false;
|
|
6933
|
+
const stopServerAfterReset = () => {
|
|
6934
|
+
if (!reset)
|
|
6935
|
+
return;
|
|
6936
|
+
if (stopServer(BASE_URL)) {
|
|
6937
|
+
info("Stopped local server so the next command starts with the fresh key.");
|
|
6938
|
+
}
|
|
6939
|
+
};
|
|
6940
|
+
if (reset) {
|
|
6941
|
+
const envKey = process.env.UNBROWSE_API_KEY?.trim();
|
|
6942
|
+
const result = resetLocalRegistration();
|
|
6943
|
+
delete process.env.UNBROWSE_API_KEY;
|
|
6944
|
+
if (envKey) {
|
|
6945
|
+
ignoredEnvApiKey = true;
|
|
6946
|
+
process.env.UNBROWSE_IGNORE_ENV_API_KEY = "1";
|
|
6947
|
+
}
|
|
6948
|
+
info(`${result.removed ? "Removed" : "No"} local API key cache at ${result.config_path}.`);
|
|
6949
|
+
if (envKey) {
|
|
6950
|
+
info("Ignoring UNBROWSE_API_KEY for this reset run. Future Unbrowse commands will prefer the fresh saved key; still remove or update that env var in your shell.");
|
|
6951
|
+
}
|
|
6952
|
+
if (typeof flags.email !== "string" && previousConfig?.email) {
|
|
6953
|
+
flags.email = previousConfig.email;
|
|
6954
|
+
}
|
|
6955
|
+
}
|
|
6893
6956
|
if (typeof flags.email === "string" && flags.email.length > 0) {
|
|
6894
6957
|
const email = flags.email;
|
|
6895
|
-
if (getApiKey()) {
|
|
6958
|
+
if (!reset && getApiKey()) {
|
|
6896
6959
|
info("Already registered. Re-running with --email will mint a new key and overwrite ~/.unbrowse/config.json.");
|
|
6897
6960
|
}
|
|
6898
6961
|
info(`Sending magic link to ${email}\u2026`);
|
|
@@ -6914,7 +6977,8 @@ async function cmdRegister(flags) {
|
|
|
6914
6977
|
tos_accepted_version: null,
|
|
6915
6978
|
tos_accepted_at: null,
|
|
6916
6979
|
email: result.email,
|
|
6917
|
-
user_id: result.user_id
|
|
6980
|
+
user_id: result.user_id,
|
|
6981
|
+
...ignoredEnvApiKey ? { ignore_env_api_key: true } : {}
|
|
6918
6982
|
});
|
|
6919
6983
|
process.env.UNBROWSE_API_KEY = result.api_key;
|
|
6920
6984
|
info(`Signed in as ${result.email}. API key saved to ~/.unbrowse/config.json.`);
|
|
@@ -6929,15 +6993,17 @@ async function cmdRegister(flags) {
|
|
|
6929
6993
|
info(`Auto-publish to marketplace: ${serverPrefs.share_pointers ? "ON" : "off"} (synced from your account).`);
|
|
6930
6994
|
}
|
|
6931
6995
|
} catch {}
|
|
6996
|
+
stopServerAfterReset();
|
|
6932
6997
|
return;
|
|
6933
6998
|
}
|
|
6934
|
-
if (getApiKey()) {
|
|
6999
|
+
if (!reset && getApiKey()) {
|
|
6935
7000
|
info("Already registered. API key loaded from env or ~/.unbrowse/config.json");
|
|
6936
7001
|
return;
|
|
6937
7002
|
}
|
|
6938
7003
|
await ensureRegistered({ promptForEmail: !flags["no-prompt"], exitOnFailure: false });
|
|
6939
7004
|
if (getApiKey()) {
|
|
6940
7005
|
info("Registration complete. You can now publish skills and check earnings.");
|
|
7006
|
+
stopServerAfterReset();
|
|
6941
7007
|
} else {
|
|
6942
7008
|
info("Registration skipped or failed. Unbrowse still works locally \u2014 publish/earnings are disabled.");
|
|
6943
7009
|
}
|
package/dist/mcp.js
CHANGED
|
@@ -226,11 +226,11 @@ import { dirname, join, parse } from "path";
|
|
|
226
226
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
227
227
|
|
|
228
228
|
// ../../src/build-info.generated.ts
|
|
229
|
-
var BUILD_RELEASE_VERSION = "6.5.0
|
|
230
|
-
var BUILD_GIT_SHA = "
|
|
229
|
+
var BUILD_RELEASE_VERSION = "6.5.0";
|
|
230
|
+
var BUILD_GIT_SHA = "a0a05eb03b07";
|
|
231
231
|
var BUILD_CODE_HASH = "5d9ebf619c61";
|
|
232
|
-
var BUILD_RELEASE_MANIFEST_BASE64 = "
|
|
233
|
-
var BUILD_RELEASE_MANIFEST_SIGNATURE = "
|
|
232
|
+
var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi41LjAiLCJnaXRfc2hhIjoiYTBhMDVlYjAzYjA3IiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUBhMGEwNWViMDNiMDciLCJpc3N1ZWRfYXQiOiIyMDI2LTA1LTAzVDE3OjA4OjI2Ljg3OVoifQ";
|
|
233
|
+
var BUILD_RELEASE_MANIFEST_SIGNATURE = "QG8diudmY_8OEQowkwHoR3Wac09OBJjDifA_xd9kmr0";
|
|
234
234
|
var BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
|
|
235
235
|
var BUILD_DEFAULT_PROFILE = "";
|
|
236
236
|
|
|
@@ -809,9 +809,13 @@ function loadConfig() {
|
|
|
809
809
|
function getApiKey() {
|
|
810
810
|
if (LOCAL_ONLY)
|
|
811
811
|
return "local-only";
|
|
812
|
+
const config = loadConfig();
|
|
813
|
+
if (config?.ignore_env_api_key && config.api_key) {
|
|
814
|
+
process.env.UNBROWSE_API_KEY = config.api_key;
|
|
815
|
+
return config.api_key;
|
|
816
|
+
}
|
|
812
817
|
if (process.env.UNBROWSE_API_KEY)
|
|
813
818
|
return process.env.UNBROWSE_API_KEY;
|
|
814
|
-
const config = loadConfig();
|
|
815
819
|
if (config?.api_key) {
|
|
816
820
|
process.env.UNBROWSE_API_KEY = config.api_key;
|
|
817
821
|
return config.api_key;
|
package/dist/server.js
CHANGED
|
@@ -7344,7 +7344,7 @@ var init_capture = __esm(async () => {
|
|
|
7344
7344
|
});
|
|
7345
7345
|
|
|
7346
7346
|
// ../../src/build-info.generated.ts
|
|
7347
|
-
var BUILD_RELEASE_VERSION = "6.5.0
|
|
7347
|
+
var BUILD_RELEASE_VERSION = "6.5.0", BUILD_GIT_SHA = "a0a05eb03b07", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi41LjAiLCJnaXRfc2hhIjoiYTBhMDVlYjAzYjA3IiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUBhMGEwNWViMDNiMDciLCJpc3N1ZWRfYXQiOiIyMDI2LTA1LTAzVDE3OjA4OjI2Ljg3OVoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "QG8diudmY_8OEQowkwHoR3Wac09OBJjDifA_xd9kmr0", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
|
|
7348
7348
|
|
|
7349
7349
|
// ../../src/version.ts
|
|
7350
7350
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -7815,6 +7815,7 @@ __export(exports_client2, {
|
|
|
7815
7815
|
searchIntent: () => searchIntent,
|
|
7816
7816
|
saveConfig: () => saveConfig,
|
|
7817
7817
|
resolveAgentName: () => resolveAgentName,
|
|
7818
|
+
resetLocalRegistration: () => resetLocalRegistration,
|
|
7818
7819
|
registerAgent: () => registerAgent,
|
|
7819
7820
|
recordTransaction: () => recordTransaction,
|
|
7820
7821
|
recordRoutingTelemetry: () => recordRoutingTelemetry,
|
|
@@ -7956,6 +7957,17 @@ function loadConfig() {
|
|
|
7956
7957
|
} catch {}
|
|
7957
7958
|
return null;
|
|
7958
7959
|
}
|
|
7960
|
+
function resetLocalRegistration() {
|
|
7961
|
+
const configPath = getConfigPath();
|
|
7962
|
+
try {
|
|
7963
|
+
if (!existsSync7(configPath))
|
|
7964
|
+
return { removed: false, config_path: configPath };
|
|
7965
|
+
unlinkSync(configPath);
|
|
7966
|
+
return { removed: true, config_path: configPath };
|
|
7967
|
+
} catch {
|
|
7968
|
+
return { removed: false, config_path: configPath };
|
|
7969
|
+
}
|
|
7970
|
+
}
|
|
7959
7971
|
function saveConfig(config) {
|
|
7960
7972
|
const configDir = getConfigDir();
|
|
7961
7973
|
const configPath = getConfigPath();
|
|
@@ -8178,9 +8190,13 @@ function getLocalWalletContext() {
|
|
|
8178
8190
|
function getApiKey() {
|
|
8179
8191
|
if (LOCAL_ONLY)
|
|
8180
8192
|
return "local-only";
|
|
8193
|
+
const config = loadConfig();
|
|
8194
|
+
if (config?.ignore_env_api_key && config.api_key) {
|
|
8195
|
+
process.env.UNBROWSE_API_KEY = config.api_key;
|
|
8196
|
+
return config.api_key;
|
|
8197
|
+
}
|
|
8181
8198
|
if (process.env.UNBROWSE_API_KEY)
|
|
8182
8199
|
return process.env.UNBROWSE_API_KEY;
|
|
8183
|
-
const config = loadConfig();
|
|
8184
8200
|
if (config?.api_key) {
|
|
8185
8201
|
process.env.UNBROWSE_API_KEY = config.api_key;
|
|
8186
8202
|
return config.api_key;
|
|
@@ -8496,7 +8512,19 @@ async function ensureRegistered(options) {
|
|
|
8496
8512
|
try {
|
|
8497
8513
|
const wallet = getLocalWalletContext();
|
|
8498
8514
|
const attribution = parseInstallAttribution();
|
|
8499
|
-
|
|
8515
|
+
let registeredWallet = wallet;
|
|
8516
|
+
let registration;
|
|
8517
|
+
try {
|
|
8518
|
+
registration = await api("POST", "/v1/agents/register", { name, tos_version: tosInfo.version, ...wallet, ...attribution });
|
|
8519
|
+
} catch (err) {
|
|
8520
|
+
const msg = err.message ?? "";
|
|
8521
|
+
if (!wallet.wallet_address || !msg.includes("wallet_already_claimed"))
|
|
8522
|
+
throw err;
|
|
8523
|
+
console.warn("[unbrowse] Wallet is already claimed by another agent. Registering this CLI without a payout wallet; sign in by email or run `unbrowse register --email ... --reset` to recover that account.");
|
|
8524
|
+
registeredWallet = {};
|
|
8525
|
+
registration = await api("POST", "/v1/agents/register", { name, tos_version: tosInfo.version, ...attribution });
|
|
8526
|
+
}
|
|
8527
|
+
const { agent_id, api_key } = registration;
|
|
8500
8528
|
process.env.UNBROWSE_API_KEY = api_key;
|
|
8501
8529
|
saveConfig({
|
|
8502
8530
|
api_key,
|
|
@@ -8505,7 +8533,8 @@ async function ensureRegistered(options) {
|
|
|
8505
8533
|
registered_at: new Date().toISOString(),
|
|
8506
8534
|
tos_accepted_version: tosInfo.version,
|
|
8507
8535
|
tos_accepted_at: new Date().toISOString(),
|
|
8508
|
-
...
|
|
8536
|
+
...process.env.UNBROWSE_IGNORE_ENV_API_KEY === "1" ? { ignore_env_api_key: true } : {},
|
|
8537
|
+
...registeredWallet
|
|
8509
8538
|
});
|
|
8510
8539
|
await recordFunnelTelemetryEvent("registration_succeeded", {
|
|
8511
8540
|
source: "cli",
|
|
@@ -16086,6 +16115,27 @@ function stampTrace(trace) {
|
|
|
16086
16115
|
trace.trace_version = TRACE_VERSION;
|
|
16087
16116
|
return trace;
|
|
16088
16117
|
}
|
|
16118
|
+
function buildBrowserFallbackCommands(contextUrl, skill) {
|
|
16119
|
+
const target = contextUrl || `https://${skill.domain}`;
|
|
16120
|
+
return [
|
|
16121
|
+
`unbrowse go "${target}"`,
|
|
16122
|
+
"unbrowse snap --filter interactive",
|
|
16123
|
+
"unbrowse text",
|
|
16124
|
+
"unbrowse close"
|
|
16125
|
+
];
|
|
16126
|
+
}
|
|
16127
|
+
function staleEndpointResult(status, skill, endpoint, contextUrl, message) {
|
|
16128
|
+
const target = contextUrl || endpoint.trigger_url || `https://${skill.domain}`;
|
|
16129
|
+
return {
|
|
16130
|
+
error: "stale_endpoint",
|
|
16131
|
+
status_code: status,
|
|
16132
|
+
skill_id: skill.skill_id,
|
|
16133
|
+
endpoint_id: endpoint.endpoint_id,
|
|
16134
|
+
message: message ?? `Endpoint ${endpoint.endpoint_id} returned HTTP ${status} after replay recovery. Treat this marketplace route as stale and use browser capture for this task.`,
|
|
16135
|
+
next_step: `Use browser fallback: unbrowse go "${target}", inspect with snap/text, then close to checkpoint and publish a fresh route.`,
|
|
16136
|
+
commands: buildBrowserFallbackCommands(target, skill)
|
|
16137
|
+
};
|
|
16138
|
+
}
|
|
16089
16139
|
function serializeReplayBody(body, headers) {
|
|
16090
16140
|
if (body == null)
|
|
16091
16141
|
return;
|
|
@@ -17896,9 +17946,9 @@ async function executeEndpoint(skill, endpoint, params = {}, projection, options
|
|
|
17896
17946
|
}
|
|
17897
17947
|
}
|
|
17898
17948
|
}
|
|
17899
|
-
|
|
17949
|
+
let { status, trace_id } = result;
|
|
17900
17950
|
let data = result.data;
|
|
17901
|
-
|
|
17951
|
+
let trace = stampTrace({
|
|
17902
17952
|
trace_id,
|
|
17903
17953
|
skill_id: skill.skill_id,
|
|
17904
17954
|
endpoint_id: endpoint.endpoint_id,
|
|
@@ -17926,7 +17976,7 @@ async function executeEndpoint(skill, endpoint, params = {}, projection, options
|
|
|
17926
17976
|
try {
|
|
17927
17977
|
const sessionRefreshed = await authRuntime.refreshSession(epDomain);
|
|
17928
17978
|
if (sessionRefreshed) {
|
|
17929
|
-
log("auth", `session refreshed via authRuntime for ${epDomain} —
|
|
17979
|
+
log("auth", `session refreshed via authRuntime for ${epDomain} — retrying replay once`);
|
|
17930
17980
|
authRecovered = true;
|
|
17931
17981
|
}
|
|
17932
17982
|
if (!authRecovered) {
|
|
@@ -17944,20 +17994,51 @@ async function executeEndpoint(skill, endpoint, params = {}, projection, options
|
|
|
17944
17994
|
}
|
|
17945
17995
|
}
|
|
17946
17996
|
if (authRecovered) {
|
|
17947
|
-
|
|
17997
|
+
await reloadExecutionAuthState(skill, epDomain, authHeaders, cookies);
|
|
17998
|
+
const retry = await serverFetch(workflowBindings?.extraHeaders, workflowBindings?.bodyOverride);
|
|
17999
|
+
decisionTrace.push({ step: "auth_recovery_retry", status: retry.status });
|
|
18000
|
+
result = retry;
|
|
18001
|
+
status = retry.status;
|
|
18002
|
+
trace_id = retry.trace_id;
|
|
18003
|
+
data = retry.data;
|
|
18004
|
+
trace = stampTrace({
|
|
18005
|
+
trace_id,
|
|
18006
|
+
skill_id: skill.skill_id,
|
|
18007
|
+
endpoint_id: endpoint.endpoint_id,
|
|
18008
|
+
started_at: startedAt,
|
|
18009
|
+
completed_at: new Date().toISOString(),
|
|
18010
|
+
success: status >= 200 && status < 300,
|
|
18011
|
+
status_code: status
|
|
18012
|
+
});
|
|
18013
|
+
trace.decision_trace = decisionTrace;
|
|
18014
|
+
if (trace.success) {
|
|
18015
|
+
trace.result = data;
|
|
18016
|
+
} else {
|
|
18017
|
+
trace.error = `HTTP ${status}`;
|
|
18018
|
+
data = staleEndpointResult(status, skill, endpoint, options?.contextUrl, `Credentials were refreshed, but endpoint ${endpoint.endpoint_id} still returned HTTP ${status}. Treat this marketplace route as stale and use browser capture for this task.`);
|
|
18019
|
+
trace.result = data;
|
|
18020
|
+
}
|
|
17948
18021
|
} else {
|
|
17949
18022
|
if (skill.auth_profile_ref) {
|
|
17950
18023
|
await deleteCredential(skill.auth_profile_ref);
|
|
17951
18024
|
}
|
|
17952
18025
|
trace.error = `${trace.error} (stale credentials — re-authenticate via /v1/auth/login)`;
|
|
18026
|
+
data = staleEndpointResult(status, skill, endpoint, options?.contextUrl, `Endpoint ${endpoint.endpoint_id} returned HTTP ${status}, and credential recovery did not produce a usable session.`);
|
|
18027
|
+
trace.result = data;
|
|
17953
18028
|
}
|
|
17954
18029
|
} catch {
|
|
17955
18030
|
if (skill.auth_profile_ref) {
|
|
17956
18031
|
await deleteCredential(skill.auth_profile_ref);
|
|
17957
18032
|
}
|
|
17958
18033
|
trace.error = `${trace.error} (stale credential deleted)`;
|
|
18034
|
+
data = staleEndpointResult(status, skill, endpoint, options?.contextUrl, `Endpoint ${endpoint.endpoint_id} returned HTTP ${status}; credential recovery failed and stale credentials were cleared.`);
|
|
18035
|
+
trace.result = data;
|
|
17959
18036
|
}
|
|
17960
18037
|
}
|
|
18038
|
+
if (!trace.success && (status === 404 || status === 429 || status >= 500)) {
|
|
18039
|
+
data = staleEndpointResult(status, skill, endpoint, options?.contextUrl);
|
|
18040
|
+
trace.result = data;
|
|
18041
|
+
}
|
|
17961
18042
|
if (trace.success && endpoint.response_schema && data != null) {
|
|
17962
18043
|
const drift = detectSchemaDrift(endpoint.response_schema, data);
|
|
17963
18044
|
if (drift.drifted) {
|
|
@@ -25545,14 +25626,29 @@ async function createBrowseSession(sessions, client, injectInterceptor2, session
|
|
|
25545
25626
|
});
|
|
25546
25627
|
}
|
|
25547
25628
|
async function isBrowseSessionLive(session, client) {
|
|
25548
|
-
|
|
25629
|
+
const dbg = (reason, extra = {}) => {
|
|
25630
|
+
if (!process.env.UNBROWSE_BROWSE_LIVENESS_DEBUG)
|
|
25631
|
+
return;
|
|
25632
|
+
console.warn("[browse-liveness] not live", JSON.stringify({
|
|
25633
|
+
session_id: session.sessionId,
|
|
25634
|
+
tab_id: session.tabId,
|
|
25635
|
+
url: session.url,
|
|
25636
|
+
reason,
|
|
25637
|
+
...extra
|
|
25638
|
+
}));
|
|
25639
|
+
};
|
|
25640
|
+
if (!session.tabId) {
|
|
25641
|
+
dbg("no_tab_id");
|
|
25549
25642
|
return false;
|
|
25643
|
+
}
|
|
25550
25644
|
const sessionClient = resolveSessionClient(session, client);
|
|
25551
25645
|
try {
|
|
25552
25646
|
await sessionClient.start();
|
|
25553
25647
|
} catch (error) {
|
|
25554
|
-
if (isRecoverableBrowseFailure(error))
|
|
25648
|
+
if (isRecoverableBrowseFailure(error)) {
|
|
25649
|
+
dbg("session_client_start_recoverable", { error: String(error?.message ?? error) });
|
|
25555
25650
|
return false;
|
|
25651
|
+
}
|
|
25556
25652
|
throw error;
|
|
25557
25653
|
}
|
|
25558
25654
|
for (let attempt = 0;attempt < LIVE_CHECK_RETRIES; attempt += 1) {
|
|
@@ -25564,6 +25660,11 @@ async function isBrowseSessionLive(session, client) {
|
|
|
25564
25660
|
await sleep(LIVE_CHECK_RETRY_DELAY_MS);
|
|
25565
25661
|
continue;
|
|
25566
25662
|
}
|
|
25663
|
+
dbg("tab_not_in_discover", {
|
|
25664
|
+
attempt,
|
|
25665
|
+
discovered_tab_ids: tabs.map((t) => t.id),
|
|
25666
|
+
discovered_tab_count: tabs.length
|
|
25667
|
+
});
|
|
25567
25668
|
return false;
|
|
25568
25669
|
}
|
|
25569
25670
|
session.brokerPort = sessionClient.getPort?.() ?? session.brokerPort;
|
|
@@ -25589,8 +25690,10 @@ async function isBrowseSessionLive(session, client) {
|
|
|
25589
25690
|
return true;
|
|
25590
25691
|
}
|
|
25591
25692
|
} catch (error) {
|
|
25592
|
-
if (!isRecoverableBrowseFailure(error))
|
|
25693
|
+
if (!isRecoverableBrowseFailure(error)) {
|
|
25694
|
+
dbg("get_current_url_unrecoverable", { error: String(error?.message ?? error) });
|
|
25593
25695
|
return false;
|
|
25696
|
+
}
|
|
25594
25697
|
}
|
|
25595
25698
|
if (hasMeaningfulBrowseUrl(session.url) || hasMeaningfulBrowseUrl(exactTab.url)) {
|
|
25596
25699
|
if (hasMeaningfulBrowseUrl(exactTab.url)) {
|
|
@@ -25600,12 +25703,15 @@ async function isBrowseSessionLive(session, client) {
|
|
|
25600
25703
|
return true;
|
|
25601
25704
|
}
|
|
25602
25705
|
} catch (error) {
|
|
25603
|
-
if (!isRecoverableBrowseFailure(error))
|
|
25706
|
+
if (!isRecoverableBrowseFailure(error)) {
|
|
25707
|
+
dbg("loop_unrecoverable", { error: String(error?.message ?? error) });
|
|
25604
25708
|
return false;
|
|
25709
|
+
}
|
|
25605
25710
|
}
|
|
25606
25711
|
if (attempt < LIVE_CHECK_RETRIES - 1)
|
|
25607
25712
|
await sleep(LIVE_CHECK_RETRY_DELAY_MS);
|
|
25608
25713
|
}
|
|
25714
|
+
dbg("retries_exhausted_url_check_failed");
|
|
25609
25715
|
return false;
|
|
25610
25716
|
}
|
|
25611
25717
|
async function listLiveBrowseSessions(sessions, client) {
|