unbrowse 6.2.6 → 6.4.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 +321 -76
- package/dist/mcp.js +4 -4
- package/dist/server.js +921 -902
- 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.
|
|
34
|
+
var BUILD_RELEASE_VERSION = "6.4.0", BUILD_GIT_SHA = "5445eb4fd89e", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi40LjAiLCJnaXRfc2hhIjoiNTQ0NWViNGZkODllIiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUA1NDQ1ZWI0ZmQ4OWUiLCJpc3N1ZWRfYXQiOiIyMDI2LTA1LTAxVDA5OjQ5OjE0LjcyMFoifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "3l8L_1jJ1G9weeuFgVBrYwcglXLwH_AnfmsnXqdPigg", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
|
|
35
35
|
|
|
36
36
|
// ../../src/version.ts
|
|
37
37
|
import { createHash } from "crypto";
|
|
@@ -515,8 +515,11 @@ var init_client = __esm(() => {
|
|
|
515
515
|
|
|
516
516
|
// ../../src/marketplace/index.ts
|
|
517
517
|
import { nanoid } from "nanoid";
|
|
518
|
+
var TTL_MS, marketplaceCache;
|
|
518
519
|
var init_marketplace = __esm(() => {
|
|
519
520
|
init_client();
|
|
521
|
+
TTL_MS = 5 * 60 * 1000;
|
|
522
|
+
marketplaceCache = new Map;
|
|
520
523
|
});
|
|
521
524
|
|
|
522
525
|
// ../../src/domain.ts
|
|
@@ -1559,6 +1562,11 @@ var RETRYABLE_STATUSES;
|
|
|
1559
1562
|
var init_retry = __esm(() => {
|
|
1560
1563
|
RETRYABLE_STATUSES = new Set([500, 502, 503, 504, 429]);
|
|
1561
1564
|
});
|
|
1565
|
+
|
|
1566
|
+
// ../../src/execution/probe.ts
|
|
1567
|
+
var init_probe = __esm(() => {
|
|
1568
|
+
init_logger();
|
|
1569
|
+
});
|
|
1562
1570
|
// ../../src/extraction/index.ts
|
|
1563
1571
|
import * as cheerio from "cheerio";
|
|
1564
1572
|
var STRIP_TAGS, CHROME_TAGS;
|
|
@@ -1628,6 +1636,102 @@ var init_schema_review = __esm(() => {
|
|
|
1628
1636
|
init_sanitize();
|
|
1629
1637
|
});
|
|
1630
1638
|
|
|
1639
|
+
// ../../src/config/contribution.ts
|
|
1640
|
+
import fs2 from "node:fs";
|
|
1641
|
+
import path6 from "node:path";
|
|
1642
|
+
import os3 from "node:os";
|
|
1643
|
+
function configPath() {
|
|
1644
|
+
return process.env.UNBROWSE_CONFIG_PATH || path6.join(os3.homedir(), ".unbrowse", "config.json");
|
|
1645
|
+
}
|
|
1646
|
+
function freshDefault() {
|
|
1647
|
+
return {
|
|
1648
|
+
contribution: { ...DEFAULT.contribution },
|
|
1649
|
+
rev_share: { ...DEFAULT.rev_share },
|
|
1650
|
+
notice_shown_count: 0
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
function getContributionConfig() {
|
|
1654
|
+
if (cached)
|
|
1655
|
+
return cached;
|
|
1656
|
+
const p = configPath();
|
|
1657
|
+
let fileExisted = false;
|
|
1658
|
+
let raw = null;
|
|
1659
|
+
try {
|
|
1660
|
+
const content = fs2.readFileSync(p, "utf-8");
|
|
1661
|
+
fileExisted = true;
|
|
1662
|
+
if (content.trim().length > 0) {
|
|
1663
|
+
raw = JSON.parse(content);
|
|
1664
|
+
}
|
|
1665
|
+
} catch {}
|
|
1666
|
+
if (!raw) {
|
|
1667
|
+
cached = freshDefault();
|
|
1668
|
+
return cached;
|
|
1669
|
+
}
|
|
1670
|
+
const contributionRaw = raw.contribution ?? null;
|
|
1671
|
+
const revShareRaw = raw.rev_share ?? null;
|
|
1672
|
+
const isExistingUserMigration = fileExisted && !contributionRaw;
|
|
1673
|
+
cached = {
|
|
1674
|
+
contribution: {
|
|
1675
|
+
share_pointers: !!(contributionRaw?.share_pointers ?? DEFAULT.contribution.share_pointers),
|
|
1676
|
+
set_via: contributionRaw?.set_via ?? DEFAULT.contribution.set_via,
|
|
1677
|
+
...contributionRaw?.set_at ? { set_at: String(contributionRaw.set_at) } : {}
|
|
1678
|
+
},
|
|
1679
|
+
rev_share: {
|
|
1680
|
+
opted_in: !!(revShareRaw?.opted_in ?? DEFAULT.rev_share.opted_in),
|
|
1681
|
+
...revShareRaw?.wallet_address ? { wallet_address: String(revShareRaw.wallet_address) } : {}
|
|
1682
|
+
},
|
|
1683
|
+
notice_shown_count: typeof raw.notice_shown_count === "number" ? raw.notice_shown_count : isExistingUserMigration ? 5 : 0
|
|
1684
|
+
};
|
|
1685
|
+
if (isExistingUserMigration) {
|
|
1686
|
+
try {
|
|
1687
|
+
const merged = { ...raw, ...cached };
|
|
1688
|
+
fs2.mkdirSync(path6.dirname(p), { recursive: true });
|
|
1689
|
+
fs2.writeFileSync(p, JSON.stringify(merged, null, 2));
|
|
1690
|
+
} catch {}
|
|
1691
|
+
}
|
|
1692
|
+
return cached;
|
|
1693
|
+
}
|
|
1694
|
+
function setContributionConfig(updates) {
|
|
1695
|
+
const current = getContributionConfig();
|
|
1696
|
+
const next = {
|
|
1697
|
+
contribution: {
|
|
1698
|
+
...current.contribution,
|
|
1699
|
+
...updates.contribution ?? {},
|
|
1700
|
+
set_at: new Date().toISOString()
|
|
1701
|
+
},
|
|
1702
|
+
rev_share: {
|
|
1703
|
+
...current.rev_share,
|
|
1704
|
+
...updates.rev_share ?? {}
|
|
1705
|
+
},
|
|
1706
|
+
notice_shown_count: updates.notice_shown_count ?? current.notice_shown_count ?? 0
|
|
1707
|
+
};
|
|
1708
|
+
const p = configPath();
|
|
1709
|
+
let existing = {};
|
|
1710
|
+
try {
|
|
1711
|
+
const content = fs2.readFileSync(p, "utf-8");
|
|
1712
|
+
if (content.trim())
|
|
1713
|
+
existing = JSON.parse(content);
|
|
1714
|
+
} catch {}
|
|
1715
|
+
const merged = { ...existing, ...next };
|
|
1716
|
+
fs2.mkdirSync(path6.dirname(p), { recursive: true });
|
|
1717
|
+
fs2.writeFileSync(p, JSON.stringify(merged, null, 2));
|
|
1718
|
+
cached = next;
|
|
1719
|
+
}
|
|
1720
|
+
function decrementNoticeCounter() {
|
|
1721
|
+
const cfg = getContributionConfig();
|
|
1722
|
+
const next = Math.max(0, (cfg.notice_shown_count ?? 0) - 1);
|
|
1723
|
+
setContributionConfig({ notice_shown_count: next });
|
|
1724
|
+
return next;
|
|
1725
|
+
}
|
|
1726
|
+
var DEFAULT, cached = null;
|
|
1727
|
+
var init_contribution = __esm(() => {
|
|
1728
|
+
DEFAULT = {
|
|
1729
|
+
contribution: { share_pointers: false, set_via: "default" },
|
|
1730
|
+
rev_share: { opted_in: false },
|
|
1731
|
+
notice_shown_count: 0
|
|
1732
|
+
};
|
|
1733
|
+
});
|
|
1734
|
+
|
|
1631
1735
|
// ../../src/indexer/index.ts
|
|
1632
1736
|
import { join as join9 } from "node:path";
|
|
1633
1737
|
var SKILL_SNAPSHOT_DIR, indexInFlight, pendingIndexJobs;
|
|
@@ -1643,6 +1747,7 @@ var init_indexer = __esm(async () => {
|
|
|
1643
1747
|
init_settings();
|
|
1644
1748
|
init_graph();
|
|
1645
1749
|
init_schema_review();
|
|
1750
|
+
init_contribution();
|
|
1646
1751
|
await init_orchestrator();
|
|
1647
1752
|
SKILL_SNAPSHOT_DIR = process.env.UNBROWSE_SKILL_SNAPSHOT_DIR ?? join9(process.env.HOME ?? "/tmp", ".unbrowse", "skill-snapshots");
|
|
1648
1753
|
indexInFlight = new Map;
|
|
@@ -1659,9 +1764,9 @@ var init_payments = __esm(() => {
|
|
|
1659
1764
|
});
|
|
1660
1765
|
|
|
1661
1766
|
// ../../src/execution/robots.ts
|
|
1662
|
-
var
|
|
1767
|
+
var TTL_MS2, cache;
|
|
1663
1768
|
var init_robots = __esm(() => {
|
|
1664
|
-
|
|
1769
|
+
TTL_MS2 = 24 * 60 * 60 * 1000;
|
|
1665
1770
|
cache = new Map;
|
|
1666
1771
|
});
|
|
1667
1772
|
|
|
@@ -1733,6 +1838,7 @@ var init_execution = __esm(async () => {
|
|
|
1733
1838
|
init_client();
|
|
1734
1839
|
init_client();
|
|
1735
1840
|
init_retry();
|
|
1841
|
+
init_probe();
|
|
1736
1842
|
init_domain();
|
|
1737
1843
|
init_extraction();
|
|
1738
1844
|
init_graph();
|
|
@@ -1865,6 +1971,13 @@ import { nanoid as nanoid8 } from "nanoid";
|
|
|
1865
1971
|
var init_routing_telemetry = __esm(() => {
|
|
1866
1972
|
init_telemetry();
|
|
1867
1973
|
});
|
|
1974
|
+
|
|
1975
|
+
// ../../src/orchestrator/resolve-race.ts
|
|
1976
|
+
var init_resolve_race = __esm(async () => {
|
|
1977
|
+
init_probe();
|
|
1978
|
+
init_marketplace();
|
|
1979
|
+
await init_execution();
|
|
1980
|
+
});
|
|
1868
1981
|
// ../../src/orchestrator/index.ts
|
|
1869
1982
|
import { nanoid as nanoid9 } from "nanoid";
|
|
1870
1983
|
import { existsSync as existsSync12, writeFileSync as writeFileSync4, readFileSync as readFileSync7, mkdirSync as mkdirSync6, readdirSync as readdirSync4 } from "node:fs";
|
|
@@ -1901,7 +2014,8 @@ var init_orchestrator = __esm(async () => {
|
|
|
1901
2014
|
init_execution(),
|
|
1902
2015
|
init_dag_advisor(),
|
|
1903
2016
|
init_prefetch(),
|
|
1904
|
-
init_runtime()
|
|
2017
|
+
init_runtime(),
|
|
2018
|
+
init_resolve_race()
|
|
1905
2019
|
]);
|
|
1906
2020
|
LIVE_CAPTURE_TIMEOUT_MS = Number(process.env.UNBROWSE_LIVE_CAPTURE_TIMEOUT_MS ?? "120000");
|
|
1907
2021
|
capturedDomainCache = new Map;
|
|
@@ -2285,9 +2399,9 @@ function getChromiumKeychainServiceName2(opts) {
|
|
|
2285
2399
|
}
|
|
2286
2400
|
function getChromiumDecryptionKey2(opts) {
|
|
2287
2401
|
const service = getChromiumKeychainServiceName2(opts);
|
|
2288
|
-
const
|
|
2289
|
-
if (
|
|
2290
|
-
return
|
|
2402
|
+
const cached2 = _chromiumKeyCache2.get(service);
|
|
2403
|
+
if (cached2)
|
|
2404
|
+
return cached2;
|
|
2291
2405
|
if (platform2() !== "darwin")
|
|
2292
2406
|
return null;
|
|
2293
2407
|
try {
|
|
@@ -3831,6 +3945,7 @@ init_publish();
|
|
|
3831
3945
|
init_settings();
|
|
3832
3946
|
init_graph();
|
|
3833
3947
|
init_schema_review();
|
|
3948
|
+
init_contribution();
|
|
3834
3949
|
import { join as join11 } from "node:path";
|
|
3835
3950
|
var SKILL_SNAPSHOT_DIR3 = process.env.UNBROWSE_SKILL_SNAPSHOT_DIR ?? join11(process.env.HOME ?? "/tmp", ".unbrowse", "skill-snapshots");
|
|
3836
3951
|
var indexInFlight2 = new Map;
|
|
@@ -3871,23 +3986,23 @@ init_logger();
|
|
|
3871
3986
|
init_wallet();
|
|
3872
3987
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
3873
3988
|
import { existsSync as existsSync14, mkdirSync as mkdirSync8, writeFileSync as writeFileSync6 } from "node:fs";
|
|
3874
|
-
import
|
|
3875
|
-
import
|
|
3989
|
+
import os5 from "node:os";
|
|
3990
|
+
import path8 from "node:path";
|
|
3876
3991
|
|
|
3877
3992
|
// ../../src/runtime/update-hints.ts
|
|
3878
3993
|
init_paths();
|
|
3879
3994
|
import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
|
|
3880
|
-
import
|
|
3881
|
-
import
|
|
3995
|
+
import os4 from "node:os";
|
|
3996
|
+
import path7 from "node:path";
|
|
3882
3997
|
var DEFAULT_INTERVAL_MS = 12 * 60 * 60 * 1000;
|
|
3883
3998
|
var CODEX_MARKER = "# Unbrowse update hints — managed by unbrowse setup";
|
|
3884
3999
|
function getHomeDir() {
|
|
3885
|
-
return process.env.HOME ||
|
|
4000
|
+
return process.env.HOME || os4.homedir();
|
|
3886
4001
|
}
|
|
3887
4002
|
function getConfigDir2() {
|
|
3888
4003
|
if (process.env.UNBROWSE_CONFIG_DIR)
|
|
3889
4004
|
return process.env.UNBROWSE_CONFIG_DIR;
|
|
3890
|
-
return
|
|
4005
|
+
return path7.join(getHomeDir(), ".unbrowse");
|
|
3891
4006
|
}
|
|
3892
4007
|
function ensureDir3(dir) {
|
|
3893
4008
|
if (!existsSync13(dir))
|
|
@@ -3902,20 +4017,20 @@ function readJsonFile(file) {
|
|
|
3902
4017
|
}
|
|
3903
4018
|
}
|
|
3904
4019
|
function writeJsonFile(file, value) {
|
|
3905
|
-
ensureDir3(
|
|
4020
|
+
ensureDir3(path7.dirname(file));
|
|
3906
4021
|
writeFileSync5(file, `${JSON.stringify(value, null, 2)}
|
|
3907
4022
|
`);
|
|
3908
4023
|
}
|
|
3909
4024
|
function getInstallSourcePath() {
|
|
3910
|
-
return
|
|
4025
|
+
return path7.join(getConfigDir2(), "install-source.json");
|
|
3911
4026
|
}
|
|
3912
4027
|
function detectRepoRoot(start2) {
|
|
3913
|
-
let dir =
|
|
3914
|
-
const root =
|
|
4028
|
+
let dir = path7.resolve(start2);
|
|
4029
|
+
const root = path7.parse(dir).root;
|
|
3915
4030
|
while (dir !== root) {
|
|
3916
|
-
if (existsSync13(
|
|
4031
|
+
if (existsSync13(path7.join(dir, ".git")))
|
|
3917
4032
|
return dir;
|
|
3918
|
-
dir =
|
|
4033
|
+
dir = path7.dirname(dir);
|
|
3919
4034
|
}
|
|
3920
4035
|
return;
|
|
3921
4036
|
}
|
|
@@ -3924,7 +4039,7 @@ function detectInstallMethod(packageRoot) {
|
|
|
3924
4039
|
return "repo-clone";
|
|
3925
4040
|
if (process.env.UNBROWSE_SETUP_METHOD === "npm-global")
|
|
3926
4041
|
return "npm-global";
|
|
3927
|
-
if (packageRoot.includes(`${
|
|
4042
|
+
if (packageRoot.includes(`${path7.sep}node_modules${path7.sep}`))
|
|
3928
4043
|
return "npm-global";
|
|
3929
4044
|
return detectRepoRoot(packageRoot) ? "repo-clone" : "unknown";
|
|
3930
4045
|
}
|
|
@@ -3934,12 +4049,12 @@ function detectInstallHost(repoRoot) {
|
|
|
3934
4049
|
return explicit;
|
|
3935
4050
|
if (!repoRoot)
|
|
3936
4051
|
return "unknown";
|
|
3937
|
-
const codexHome = process.env.CODEX_HOME ||
|
|
3938
|
-
if (repoRoot ===
|
|
4052
|
+
const codexHome = process.env.CODEX_HOME || path7.join(getHomeDir(), ".codex");
|
|
4053
|
+
if (repoRoot === path7.join(codexHome, "skills", "unbrowse"))
|
|
3939
4054
|
return "codex";
|
|
3940
|
-
if (repoRoot ===
|
|
4055
|
+
if (repoRoot === path7.join(getHomeDir(), ".claude", "skills", "unbrowse"))
|
|
3941
4056
|
return "claude";
|
|
3942
|
-
if (repoRoot ===
|
|
4057
|
+
if (repoRoot === path7.join(getHomeDir(), "unbrowse"))
|
|
3943
4058
|
return "off";
|
|
3944
4059
|
return "unknown";
|
|
3945
4060
|
}
|
|
@@ -3967,14 +4082,14 @@ function commandIncludesHook(command, marker) {
|
|
|
3967
4082
|
return typeof command === "string" && command.includes(marker);
|
|
3968
4083
|
}
|
|
3969
4084
|
function getCodexConfigPath() {
|
|
3970
|
-
const codexHome = process.env.CODEX_HOME ||
|
|
3971
|
-
return
|
|
4085
|
+
const codexHome = process.env.CODEX_HOME || path7.join(getHomeDir(), ".codex");
|
|
4086
|
+
return path7.join(codexHome, "config.toml");
|
|
3972
4087
|
}
|
|
3973
4088
|
function getClaudeSettingsPath() {
|
|
3974
|
-
return
|
|
4089
|
+
return path7.join(getHomeDir(), ".claude", "settings.json");
|
|
3975
4090
|
}
|
|
3976
4091
|
function getHookScriptPath(metaUrl) {
|
|
3977
|
-
return
|
|
4092
|
+
return path7.join(getPackageRoot(metaUrl), "bin", "unbrowse-update-hint.mjs");
|
|
3978
4093
|
}
|
|
3979
4094
|
function ensureCodexHooksFeature(content) {
|
|
3980
4095
|
if (/\bcodex_hooks\s*=\s*true\b/.test(content))
|
|
@@ -3991,14 +4106,14 @@ codex_hooks = true
|
|
|
3991
4106
|
`;
|
|
3992
4107
|
}
|
|
3993
4108
|
function writeCodexHook(metaUrl) {
|
|
3994
|
-
const
|
|
3995
|
-
if (!existsSync13(
|
|
3996
|
-
return { host: "codex", action: "not-detected", config_file:
|
|
4109
|
+
const configPath2 = getCodexConfigPath();
|
|
4110
|
+
if (!existsSync13(path7.dirname(configPath2))) {
|
|
4111
|
+
return { host: "codex", action: "not-detected", config_file: configPath2 };
|
|
3997
4112
|
}
|
|
3998
4113
|
try {
|
|
3999
4114
|
const hookScript = getHookScriptPath(metaUrl).replace(/\\/g, "/");
|
|
4000
|
-
const fileExistsBefore = existsSync13(
|
|
4001
|
-
let content = fileExistsBefore ? readFileSync8(
|
|
4115
|
+
const fileExistsBefore = existsSync13(configPath2);
|
|
4116
|
+
let content = fileExistsBefore ? readFileSync8(configPath2, "utf8") : "";
|
|
4002
4117
|
const previous = content;
|
|
4003
4118
|
content = ensureCodexHooksFeature(content);
|
|
4004
4119
|
if (!content.includes("unbrowse-update-hint.mjs")) {
|
|
@@ -4013,26 +4128,26 @@ command = ${JSON.stringify(command)}
|
|
|
4013
4128
|
`;
|
|
4014
4129
|
}
|
|
4015
4130
|
if (content !== previous) {
|
|
4016
|
-
writeFileSync5(
|
|
4131
|
+
writeFileSync5(configPath2, content, "utf8");
|
|
4017
4132
|
return {
|
|
4018
4133
|
host: "codex",
|
|
4019
4134
|
action: fileExistsBefore ? "updated" : "installed",
|
|
4020
|
-
config_file:
|
|
4135
|
+
config_file: configPath2
|
|
4021
4136
|
};
|
|
4022
4137
|
}
|
|
4023
|
-
return { host: "codex", action: "already-installed", config_file:
|
|
4138
|
+
return { host: "codex", action: "already-installed", config_file: configPath2 };
|
|
4024
4139
|
} catch (error) {
|
|
4025
4140
|
return {
|
|
4026
4141
|
host: "codex",
|
|
4027
4142
|
action: "failed",
|
|
4028
|
-
config_file:
|
|
4143
|
+
config_file: configPath2,
|
|
4029
4144
|
message: error instanceof Error ? error.message : String(error)
|
|
4030
4145
|
};
|
|
4031
4146
|
}
|
|
4032
4147
|
}
|
|
4033
4148
|
function writeClaudeHook(metaUrl) {
|
|
4034
4149
|
const settingsPath = getClaudeSettingsPath();
|
|
4035
|
-
if (!existsSync13(
|
|
4150
|
+
if (!existsSync13(path7.dirname(settingsPath))) {
|
|
4036
4151
|
return { host: "claude", action: "not-detected", config_file: settingsPath };
|
|
4037
4152
|
}
|
|
4038
4153
|
try {
|
|
@@ -4092,18 +4207,18 @@ function detectPackageManagers() {
|
|
|
4092
4207
|
}
|
|
4093
4208
|
function resolveConfigHome() {
|
|
4094
4209
|
if (process.platform === "win32") {
|
|
4095
|
-
return process.env.APPDATA ||
|
|
4210
|
+
return process.env.APPDATA || path8.join(os5.homedir(), "AppData", "Roaming");
|
|
4096
4211
|
}
|
|
4097
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
4212
|
+
return process.env.XDG_CONFIG_HOME || path8.join(os5.homedir(), ".config");
|
|
4098
4213
|
}
|
|
4099
4214
|
function getOpenCodeGlobalCommandsDir() {
|
|
4100
|
-
return
|
|
4215
|
+
return path8.join(resolveConfigHome(), "opencode", "commands");
|
|
4101
4216
|
}
|
|
4102
4217
|
function getOpenCodeProjectCommandsDir(cwd) {
|
|
4103
|
-
return
|
|
4218
|
+
return path8.join(cwd, ".opencode", "commands");
|
|
4104
4219
|
}
|
|
4105
4220
|
function detectOpenCode(cwd) {
|
|
4106
|
-
return hasBinary("opencode") || existsSync14(
|
|
4221
|
+
return hasBinary("opencode") || existsSync14(path8.join(resolveConfigHome(), "opencode")) || existsSync14(path8.join(cwd, ".opencode"));
|
|
4107
4222
|
}
|
|
4108
4223
|
function renderOpenCodeCommand() {
|
|
4109
4224
|
return `---
|
|
@@ -4131,12 +4246,12 @@ function writeOpenCodeCommand(scope, cwd) {
|
|
|
4131
4246
|
if (scope === "auto" && !detected) {
|
|
4132
4247
|
return { detected: false, action: "not-detected", scope: "off" };
|
|
4133
4248
|
}
|
|
4134
|
-
const resolvedScope = scope === "project" ? "project" : scope === "global" ? "global" : existsSync14(
|
|
4249
|
+
const resolvedScope = scope === "project" ? "project" : scope === "global" ? "global" : existsSync14(path8.join(cwd, ".opencode")) ? "project" : "global";
|
|
4135
4250
|
const commandsDir = resolvedScope === "project" ? getOpenCodeProjectCommandsDir(cwd) : getOpenCodeGlobalCommandsDir();
|
|
4136
|
-
const commandFile =
|
|
4251
|
+
const commandFile = path8.join(ensureDir2(commandsDir), "unbrowse.md");
|
|
4137
4252
|
const content = renderOpenCodeCommand();
|
|
4138
4253
|
const action2 = existsSync14(commandFile) ? "updated" : "installed";
|
|
4139
|
-
mkdirSync8(
|
|
4254
|
+
mkdirSync8(path8.dirname(commandFile), { recursive: true });
|
|
4140
4255
|
writeFileSync6(commandFile, content);
|
|
4141
4256
|
return {
|
|
4142
4257
|
detected: detected || scope !== "auto",
|
|
@@ -4150,7 +4265,7 @@ async function ensureBrowserEngineInstalled() {
|
|
|
4150
4265
|
if (existsSync14(binary)) {
|
|
4151
4266
|
return { installed: true, action: "already-installed" };
|
|
4152
4267
|
}
|
|
4153
|
-
const sourceDir = getKuriSourceCandidates().find((candidate) => existsSync14(
|
|
4268
|
+
const sourceDir = getKuriSourceCandidates().find((candidate) => existsSync14(path8.join(candidate, "build.zig")));
|
|
4154
4269
|
if (!sourceDir) {
|
|
4155
4270
|
return {
|
|
4156
4271
|
installed: false,
|
|
@@ -4197,7 +4312,7 @@ async function runSetup(options) {
|
|
|
4197
4312
|
const browser = options?.installBrowser === false ? { installed: false, action: "skipped" } : await ensureBrowserEngineInstalled();
|
|
4198
4313
|
const walletCheck = checkWalletConfigured();
|
|
4199
4314
|
const skipWalletSetup = process.env.UNBROWSE_SKIP_WALLET_SETUP === "1";
|
|
4200
|
-
let lobsterInstalled = hasBinary("lobstercash") || existsSync14(
|
|
4315
|
+
let lobsterInstalled = hasBinary("lobstercash") || existsSync14(path8.join(os5.homedir(), ".agents", "skills", "lobstercash", "SKILL.md"));
|
|
4201
4316
|
if (!skipWalletSetup && !walletCheck.configured) {
|
|
4202
4317
|
if (!lobsterInstalled) {
|
|
4203
4318
|
console.log("[unbrowse] Setting up Crossmint wallet (required for earning + payments)...");
|
|
@@ -4237,7 +4352,7 @@ async function runSetup(options) {
|
|
|
4237
4352
|
return {
|
|
4238
4353
|
os: {
|
|
4239
4354
|
platform: process.platform,
|
|
4240
|
-
release:
|
|
4355
|
+
release: os5.release(),
|
|
4241
4356
|
arch: process.arch
|
|
4242
4357
|
},
|
|
4243
4358
|
host_environment: hostEnv,
|
|
@@ -4252,17 +4367,17 @@ async function runSetup(options) {
|
|
|
4252
4367
|
// ../../src/runtime/update-hints.ts
|
|
4253
4368
|
init_paths();
|
|
4254
4369
|
import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "node:fs";
|
|
4255
|
-
import
|
|
4256
|
-
import
|
|
4370
|
+
import os6 from "node:os";
|
|
4371
|
+
import path9 from "node:path";
|
|
4257
4372
|
var INSTALL_SCRIPT_URL = "https://unbrowse.ai/install.sh";
|
|
4258
4373
|
var DEFAULT_INTERVAL_MS2 = 12 * 60 * 60 * 1000;
|
|
4259
4374
|
function getHomeDir2() {
|
|
4260
|
-
return process.env.HOME ||
|
|
4375
|
+
return process.env.HOME || os6.homedir();
|
|
4261
4376
|
}
|
|
4262
4377
|
function getConfigDir3() {
|
|
4263
4378
|
if (process.env.UNBROWSE_CONFIG_DIR)
|
|
4264
4379
|
return process.env.UNBROWSE_CONFIG_DIR;
|
|
4265
|
-
return
|
|
4380
|
+
return path9.join(getHomeDir2(), ".unbrowse");
|
|
4266
4381
|
}
|
|
4267
4382
|
function ensureDir4(dir) {
|
|
4268
4383
|
if (!existsSync15(dir))
|
|
@@ -4277,23 +4392,23 @@ function readJsonFile2(file) {
|
|
|
4277
4392
|
}
|
|
4278
4393
|
}
|
|
4279
4394
|
function writeJsonFile2(file, value) {
|
|
4280
|
-
ensureDir4(
|
|
4395
|
+
ensureDir4(path9.dirname(file));
|
|
4281
4396
|
writeFileSync7(file, `${JSON.stringify(value, null, 2)}
|
|
4282
4397
|
`);
|
|
4283
4398
|
}
|
|
4284
4399
|
function getInstallSourcePath2() {
|
|
4285
|
-
return
|
|
4400
|
+
return path9.join(getConfigDir3(), "install-source.json");
|
|
4286
4401
|
}
|
|
4287
4402
|
function getUpdateCheckStatePath() {
|
|
4288
|
-
return
|
|
4403
|
+
return path9.join(getConfigDir3(), "update-check.json");
|
|
4289
4404
|
}
|
|
4290
4405
|
function detectRepoRoot2(start2) {
|
|
4291
|
-
let dir =
|
|
4292
|
-
const root =
|
|
4406
|
+
let dir = path9.resolve(start2);
|
|
4407
|
+
const root = path9.parse(dir).root;
|
|
4293
4408
|
while (dir !== root) {
|
|
4294
|
-
if (existsSync15(
|
|
4409
|
+
if (existsSync15(path9.join(dir, ".git")))
|
|
4295
4410
|
return dir;
|
|
4296
|
-
dir =
|
|
4411
|
+
dir = path9.dirname(dir);
|
|
4297
4412
|
}
|
|
4298
4413
|
return;
|
|
4299
4414
|
}
|
|
@@ -4302,7 +4417,7 @@ function detectInstallMethod2(packageRoot) {
|
|
|
4302
4417
|
return "repo-clone";
|
|
4303
4418
|
if (process.env.UNBROWSE_SETUP_METHOD === "npm-global")
|
|
4304
4419
|
return "npm-global";
|
|
4305
|
-
if (packageRoot.includes(`${
|
|
4420
|
+
if (packageRoot.includes(`${path9.sep}node_modules${path9.sep}`))
|
|
4306
4421
|
return "npm-global";
|
|
4307
4422
|
return detectRepoRoot2(packageRoot) ? "repo-clone" : "unknown";
|
|
4308
4423
|
}
|
|
@@ -4312,19 +4427,19 @@ function detectInstallHost2(repoRoot) {
|
|
|
4312
4427
|
return explicit;
|
|
4313
4428
|
if (!repoRoot)
|
|
4314
4429
|
return "unknown";
|
|
4315
|
-
const codexHome = process.env.CODEX_HOME ||
|
|
4316
|
-
if (repoRoot ===
|
|
4430
|
+
const codexHome = process.env.CODEX_HOME || path9.join(getHomeDir2(), ".codex");
|
|
4431
|
+
if (repoRoot === path9.join(codexHome, "skills", "unbrowse"))
|
|
4317
4432
|
return "codex";
|
|
4318
|
-
if (repoRoot ===
|
|
4433
|
+
if (repoRoot === path9.join(getHomeDir2(), ".claude", "skills", "unbrowse"))
|
|
4319
4434
|
return "claude";
|
|
4320
|
-
if (repoRoot ===
|
|
4435
|
+
if (repoRoot === path9.join(getHomeDir2(), "unbrowse"))
|
|
4321
4436
|
return "off";
|
|
4322
4437
|
return "unknown";
|
|
4323
4438
|
}
|
|
4324
4439
|
function getInstalledVersion(metaUrl) {
|
|
4325
4440
|
const packageRoot = getPackageRoot(metaUrl);
|
|
4326
4441
|
try {
|
|
4327
|
-
const pkg = JSON.parse(readFileSync9(
|
|
4442
|
+
const pkg = JSON.parse(readFileSync9(path9.join(packageRoot, "package.json"), "utf8"));
|
|
4328
4443
|
return pkg.version ?? "unknown";
|
|
4329
4444
|
} catch {
|
|
4330
4445
|
return "unknown";
|
|
@@ -4420,6 +4535,81 @@ function recordUpdateHint(latestVersion) {
|
|
|
4420
4535
|
});
|
|
4421
4536
|
}
|
|
4422
4537
|
|
|
4538
|
+
// ../../src/cli-setup.ts
|
|
4539
|
+
init_contribution();
|
|
4540
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
4541
|
+
async function defaultReadChoice(allowed, dflt) {
|
|
4542
|
+
const isInteractive = !!process.stdin.isTTY && !!process.stdout.isTTY && process.env.UNBROWSE_NON_INTERACTIVE !== "1";
|
|
4543
|
+
if (!isInteractive)
|
|
4544
|
+
return dflt;
|
|
4545
|
+
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
4546
|
+
try {
|
|
4547
|
+
for (;; ) {
|
|
4548
|
+
const answer = await new Promise((resolve) => {
|
|
4549
|
+
rl.question(`Choice [${dflt}]: `, resolve);
|
|
4550
|
+
});
|
|
4551
|
+
const trimmed = answer.trim();
|
|
4552
|
+
if (!trimmed)
|
|
4553
|
+
return dflt;
|
|
4554
|
+
const n = parseInt(trimmed, 10);
|
|
4555
|
+
if (allowed.includes(n))
|
|
4556
|
+
return n;
|
|
4557
|
+
console.log(`Please enter ${allowed.join(", ")} (or press Enter for ${dflt}).`);
|
|
4558
|
+
}
|
|
4559
|
+
} finally {
|
|
4560
|
+
rl.close();
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
async function promptContributionMode(opts = {}) {
|
|
4564
|
+
const log2 = opts.log ?? ((msg) => console.log(msg));
|
|
4565
|
+
const cfg = getContributionConfig();
|
|
4566
|
+
if (!opts.force && cfg.contribution.set_via && cfg.contribution.set_via !== "default") {
|
|
4567
|
+
return null;
|
|
4568
|
+
}
|
|
4569
|
+
log2("");
|
|
4570
|
+
log2("How do you want unbrowse to handle the routes you discover?");
|
|
4571
|
+
log2("");
|
|
4572
|
+
log2(" [1] Private (default) — cache locally, never publish");
|
|
4573
|
+
log2(" [2] Share — contribute pointers to the marketplace");
|
|
4574
|
+
log2(" [3] Share + earn — contribute and add a wallet for x402 rev-share");
|
|
4575
|
+
log2("");
|
|
4576
|
+
const reader = opts.readChoice ?? defaultReadChoice;
|
|
4577
|
+
const choice = await reader([1, 2, 3], 1);
|
|
4578
|
+
const set_via = opts.force ? "mode-command" : "setup-prompt";
|
|
4579
|
+
if (choice === 1) {
|
|
4580
|
+
setContributionConfig({
|
|
4581
|
+
contribution: { share_pointers: false, set_via },
|
|
4582
|
+
rev_share: { opted_in: false }
|
|
4583
|
+
});
|
|
4584
|
+
log2("Private mode set. Run `unbrowse mode` anytime to change.");
|
|
4585
|
+
} else if (choice === 2) {
|
|
4586
|
+
setContributionConfig({
|
|
4587
|
+
contribution: { share_pointers: true, set_via },
|
|
4588
|
+
rev_share: { opted_in: false }
|
|
4589
|
+
});
|
|
4590
|
+
log2("Sharing pointers enabled. Add a wallet via `unbrowse mode` to opt into rev-share.");
|
|
4591
|
+
} else {
|
|
4592
|
+
setContributionConfig({
|
|
4593
|
+
contribution: { share_pointers: true, set_via },
|
|
4594
|
+
rev_share: { opted_in: true }
|
|
4595
|
+
});
|
|
4596
|
+
log2("Sharing + rev-share enabled. Run `unbrowse wallet` to add your wallet for payouts.");
|
|
4597
|
+
}
|
|
4598
|
+
return choice;
|
|
4599
|
+
}
|
|
4600
|
+
function maybeShowContributionNotice() {
|
|
4601
|
+
const cfg = getContributionConfig();
|
|
4602
|
+
if (cfg.contribution.set_via !== "default")
|
|
4603
|
+
return false;
|
|
4604
|
+
const remaining = cfg.notice_shown_count ?? 0;
|
|
4605
|
+
if (remaining <= 0)
|
|
4606
|
+
return false;
|
|
4607
|
+
process.stderr.write("[unbrowse] contribution mode is now `private` by default — captures stay on your machine.\n" + `[unbrowse] run \`unbrowse mode\` to opt into sharing + rev-share. (notice will repeat ${remaining - 1} more time${remaining - 1 === 1 ? "" : "s"})
|
|
4608
|
+
`);
|
|
4609
|
+
decrementNoticeCounter();
|
|
4610
|
+
return true;
|
|
4611
|
+
}
|
|
4612
|
+
|
|
4423
4613
|
// ../../src/cli.ts
|
|
4424
4614
|
loadEnv({ quiet: true });
|
|
4425
4615
|
loadEnv({ path: ".env.runtime", quiet: true });
|
|
@@ -4465,8 +4655,8 @@ function parseArgs(argv) {
|
|
|
4465
4655
|
}
|
|
4466
4656
|
return { command, args: positional, flags, params };
|
|
4467
4657
|
}
|
|
4468
|
-
async function api2(method,
|
|
4469
|
-
let target = `${BASE_URL}${
|
|
4658
|
+
async function api2(method, path10, body) {
|
|
4659
|
+
let target = `${BASE_URL}${path10}`;
|
|
4470
4660
|
let requestBody = body;
|
|
4471
4661
|
if (method === "GET" && body && typeof body === "object") {
|
|
4472
4662
|
const params = new URLSearchParams;
|
|
@@ -4566,6 +4756,8 @@ function slimTrace(obj) {
|
|
|
4566
4756
|
out.provider = obj.provider;
|
|
4567
4757
|
if ("result" in obj)
|
|
4568
4758
|
out.result = obj.result;
|
|
4759
|
+
if (Array.isArray(obj.decision_trace))
|
|
4760
|
+
out.decision_trace = obj.decision_trace;
|
|
4569
4761
|
if (obj.available_endpoints)
|
|
4570
4762
|
out.available_endpoints = obj.available_endpoints;
|
|
4571
4763
|
if (obj.impact)
|
|
@@ -4706,6 +4898,7 @@ async function cmdResolve(flags) {
|
|
|
4706
4898
|
const intent = flags.intent;
|
|
4707
4899
|
if (!intent)
|
|
4708
4900
|
die("--intent is required");
|
|
4901
|
+
maybeShowContributionNotice();
|
|
4709
4902
|
const hostType = detectTelemetryHostType();
|
|
4710
4903
|
await ensureCliInstallTracked(hostType);
|
|
4711
4904
|
await recordFunnelTelemetryEvent("cli_invoked", {
|
|
@@ -4767,6 +4960,14 @@ async function cmdResolve(flags) {
|
|
|
4767
4960
|
body.force_capture = true;
|
|
4768
4961
|
if (flags["skip-robots"])
|
|
4769
4962
|
body.skip_robots_check = true;
|
|
4963
|
+
const budgetFlag = flags.budget;
|
|
4964
|
+
if (typeof budgetFlag === "string") {
|
|
4965
|
+
const parsed = parseInt(budgetFlag, 10);
|
|
4966
|
+
if (Number.isFinite(parsed) && parsed > 0)
|
|
4967
|
+
body.budget_ms = parsed;
|
|
4968
|
+
} else if (typeof budgetFlag === "number" && Number.isFinite(budgetFlag) && budgetFlag > 0) {
|
|
4969
|
+
body.budget_ms = budgetFlag;
|
|
4970
|
+
}
|
|
4770
4971
|
body.projection = { raw: true };
|
|
4771
4972
|
const startedAt = Date.now();
|
|
4772
4973
|
async function resolveOnce(message = "Still working. Searching cached routes...") {
|
|
@@ -4853,8 +5054,8 @@ async function cmdResolve(flags) {
|
|
|
4853
5054
|
throw error;
|
|
4854
5055
|
}
|
|
4855
5056
|
}
|
|
4856
|
-
function drillPath(data,
|
|
4857
|
-
const segments =
|
|
5057
|
+
function drillPath(data, path10) {
|
|
5058
|
+
const segments = path10.split(/\./).flatMap((s) => {
|
|
4858
5059
|
const m = s.match(/^(.+)\[\]$/);
|
|
4859
5060
|
return m ? [m[1], "[]"] : [s];
|
|
4860
5061
|
});
|
|
@@ -4881,9 +5082,9 @@ function drillPath(data, path9) {
|
|
|
4881
5082
|
}
|
|
4882
5083
|
return values;
|
|
4883
5084
|
}
|
|
4884
|
-
function resolveDotPath(obj,
|
|
5085
|
+
function resolveDotPath(obj, path10) {
|
|
4885
5086
|
let cur = obj;
|
|
4886
|
-
for (const key of
|
|
5087
|
+
for (const key of path10.split(".")) {
|
|
4887
5088
|
if (cur == null || typeof cur !== "object")
|
|
4888
5089
|
return;
|
|
4889
5090
|
cur = cur[key];
|
|
@@ -4900,8 +5101,8 @@ function applyExtract(items, extractSpec) {
|
|
|
4900
5101
|
return items.map((item) => {
|
|
4901
5102
|
const row = {};
|
|
4902
5103
|
let hasValue = false;
|
|
4903
|
-
for (const { alias, path:
|
|
4904
|
-
const val = resolveDotPath(item,
|
|
5104
|
+
for (const { alias, path: path10 } of fields) {
|
|
5105
|
+
const val = resolveDotPath(item, path10);
|
|
4905
5106
|
row[alias] = val ?? null;
|
|
4906
5107
|
if (val != null)
|
|
4907
5108
|
hasValue = true;
|
|
@@ -4932,6 +5133,7 @@ async function cmdExecute(flags) {
|
|
|
4932
5133
|
const skillId = flags.skill;
|
|
4933
5134
|
if (!skillId)
|
|
4934
5135
|
die("--skill is required");
|
|
5136
|
+
maybeShowContributionNotice();
|
|
4935
5137
|
const hostType = detectTelemetryHostType();
|
|
4936
5138
|
await ensureCliInstallTracked(hostType);
|
|
4937
5139
|
await recordFunnelTelemetryEvent("cli_invoked", {
|
|
@@ -5373,6 +5575,35 @@ async function cmdSetup(flags) {
|
|
|
5373
5575
|
info(' unbrowse resolve --intent "list posts" --url "https://jsonplaceholder.typicode.com"');
|
|
5374
5576
|
}
|
|
5375
5577
|
}
|
|
5578
|
+
async function cmdMode(_flags) {
|
|
5579
|
+
await promptContributionMode({ force: true });
|
|
5580
|
+
}
|
|
5581
|
+
async function runPostSetupContributionPrompt() {
|
|
5582
|
+
try {
|
|
5583
|
+
await promptContributionMode({ force: false });
|
|
5584
|
+
} catch {}
|
|
5585
|
+
}
|
|
5586
|
+
async function cmdCapture(flags) {
|
|
5587
|
+
const url = flags.url;
|
|
5588
|
+
const intent = flags.intent || "capture";
|
|
5589
|
+
if (!url)
|
|
5590
|
+
die("--url is required");
|
|
5591
|
+
maybeShowContributionNotice();
|
|
5592
|
+
const t0 = Date.now();
|
|
5593
|
+
const result = await api2("POST", "/v1/capture", { url, intent });
|
|
5594
|
+
const endpoints = Array.isArray(result.endpoints) ? result.endpoints : Array.isArray(result.available_endpoints) ? result.available_endpoints : [];
|
|
5595
|
+
const skill = result.skill ?? null;
|
|
5596
|
+
const skillId = result.skill_id ?? skill?.skill_id ?? (typeof result.learned_skill_id === "string" ? result.learned_skill_id : undefined);
|
|
5597
|
+
const envelope = {
|
|
5598
|
+
skill_id: skillId,
|
|
5599
|
+
endpoints_discovered: typeof result.endpoints_discovered === "number" ? result.endpoints_discovered : endpoints.length,
|
|
5600
|
+
marketplace_published: !!result.marketplace_published,
|
|
5601
|
+
ms: typeof result.ms === "number" ? result.ms : Date.now() - t0,
|
|
5602
|
+
next_step: endpoints.length > 0 ? `unbrowse resolve --intent "${intent.replace(/"/g, "\\\"")}" --url "${url.replace(/"/g, "\\\"")}"` : "no endpoints discovered; site may need authentication or different intent",
|
|
5603
|
+
...result.error ? { error: result.error } : {}
|
|
5604
|
+
};
|
|
5605
|
+
output(envelope, !!flags.pretty);
|
|
5606
|
+
}
|
|
5376
5607
|
var CLI_REFERENCE = {
|
|
5377
5608
|
commands: [
|
|
5378
5609
|
{ name: "health", usage: "", desc: "Server health check" },
|
|
@@ -5417,7 +5648,9 @@ var CLI_REFERENCE = {
|
|
|
5417
5648
|
{ name: "earnings", usage: "[--json]", desc: "Show your credit balance, earnings from indexing, and spending" },
|
|
5418
5649
|
{ name: "corpus-test", usage: "--url <url> [--id <id>] [--retries N]", desc: "Capture a single URL with retry logic; keeps best result across N attempts" },
|
|
5419
5650
|
{ 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" },
|
|
5420
|
-
{ name: "register", usage: "[--no-prompt]", desc: "Optional: register an API key to publish skills, check earnings, and access backend analytics" }
|
|
5651
|
+
{ name: "register", usage: "[--no-prompt]", desc: "Optional: register an API key to publish skills, check earnings, and access backend analytics" },
|
|
5652
|
+
{ name: "mode", usage: "", desc: "Re-prompt for contribution mode (private / share / share + earn)" },
|
|
5653
|
+
{ 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`." }
|
|
5421
5654
|
],
|
|
5422
5655
|
globalFlags: [
|
|
5423
5656
|
{ flag: "--pretty", desc: "Indented JSON output" },
|
|
@@ -5874,6 +6107,7 @@ async function cmdGo(args, flags) {
|
|
|
5874
6107
|
const url = args[0] ?? flags.url;
|
|
5875
6108
|
if (!url)
|
|
5876
6109
|
die("Usage: unbrowse go <url>");
|
|
6110
|
+
maybeShowContributionNotice();
|
|
5877
6111
|
output(await api2("POST", "/v1/browse/go", {
|
|
5878
6112
|
url,
|
|
5879
6113
|
...typeof flags.session === "string" ? { session_id: flags.session } : {}
|
|
@@ -6300,6 +6534,11 @@ async function main() {
|
|
|
6300
6534
|
}
|
|
6301
6535
|
if (command === "setup") {
|
|
6302
6536
|
await cmdSetup(flags);
|
|
6537
|
+
await runPostSetupContributionPrompt();
|
|
6538
|
+
return;
|
|
6539
|
+
}
|
|
6540
|
+
if (command === "mode") {
|
|
6541
|
+
await cmdMode(flags);
|
|
6303
6542
|
return;
|
|
6304
6543
|
}
|
|
6305
6544
|
if (command === "mcp")
|
|
@@ -6378,7 +6617,9 @@ async function main() {
|
|
|
6378
6617
|
"corpus-run",
|
|
6379
6618
|
"sessions-scan",
|
|
6380
6619
|
"cache-clear",
|
|
6381
|
-
"register"
|
|
6620
|
+
"register",
|
|
6621
|
+
"mode",
|
|
6622
|
+
"capture"
|
|
6382
6623
|
]);
|
|
6383
6624
|
if (!KNOWN_COMMANDS.has(command)) {
|
|
6384
6625
|
const pack = findSitePack(command);
|
|
@@ -6492,6 +6733,10 @@ async function main() {
|
|
|
6492
6733
|
return cmdSessionsScan(flags);
|
|
6493
6734
|
case "register":
|
|
6494
6735
|
return cmdRegister(flags);
|
|
6736
|
+
case "mode":
|
|
6737
|
+
return cmdMode(flags);
|
|
6738
|
+
case "capture":
|
|
6739
|
+
return cmdCapture(flags);
|
|
6495
6740
|
default:
|
|
6496
6741
|
info(`Unknown command: ${command}`);
|
|
6497
6742
|
printHelp();
|