@opencode/browse 0.0.6-dev.19 → 0.0.6-dev.21
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-22fe7etn.mjs → cli-qcdv8aqh.mjs} +85 -84
- package/dist/cli.mjs +14 -9
- package/dist/{helpers-rta4d2as.mjs → helpers-d74qp3s1.mjs} +10 -9
- package/dist/{main-yd50d95g.mjs → main-0m569gdn.mjs} +165 -127
- package/dist/{main-2wrztakb.mjs → main-33kf3cfr.mjs} +12 -4
- package/dist/main-3gthmkzw.mjs +112 -0
- package/dist/{main-xatp12cr.mjs → main-6bjnpchg.mjs} +4 -4
- package/dist/{main-75rdz6bc.mjs → main-7qs0mwvc.mjs} +1 -1
- package/dist/main-ek76h9k1.mjs +4 -0
- package/dist/{main-8a245rm1.mjs → main-qm2keaeb.mjs} +199 -186
- package/dist/{main-knahxbey.mjs → main-ybvatjk0.mjs} +5 -5
- package/dist/{main-90enpn5q.mjs → main-yq58hnwq.mjs} +10 -10
- package/dist/{mcp-p0mcjvq9.mjs → mcp-qmq1yerr.mjs} +38 -39
- package/dist/{relay-tfvn856e.mjs → relay-446cn6cs.mjs} +4073 -3894
- package/dist/{runtime-update-pxbj49tf.mjs → runtime-update-fj4s270v.mjs} +6 -5
- package/dist/{setup-y8pd11b8.mjs → setup-atsf76r6.mjs} +3844 -3132
- package/dist/skill-text-v35020jn.mjs +1007 -0
- package/dist/supervisor-bvnx7xgg.mjs +154 -0
- package/dist/{update-5fx8t344.mjs → update-38wp6pt4.mjs} +4 -2
- package/dist/{version-cjhq7cm9.mjs → version-x7djen82.mjs} +1 -1
- package/package.json +3 -2
- package/skills/browse/SKILL.md +29 -29
- package/dist/main-ts9jjqs8.mjs +0 -4
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
opencodeBrowserVersion2
|
|
3
|
+
} from "./main-ek76h9k1.mjs";
|
|
4
|
+
|
|
1
5
|
// src/update/auto-update.ts
|
|
2
6
|
import { spawn } from "node:child_process";
|
|
3
|
-
import {
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import { chmodSync, closeSync, copyFileSync, cpSync, existsSync, linkSync, mkdirSync, openSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
9
|
import { createRequire } from "node:module";
|
|
5
10
|
import path2 from "node:path";
|
|
6
11
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
12
|
+
import { gunzipSync } from "node:zlib";
|
|
7
13
|
|
|
8
14
|
// src/paths.ts
|
|
9
15
|
import fs from "node:fs";
|
|
@@ -22,13 +28,33 @@ function dataRoot(home = os.homedir()) {
|
|
|
22
28
|
var packageRoot = () => path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
23
29
|
var oldStoreMarker = () => path.join(dataRoot(), "old-store-extension");
|
|
24
30
|
function fromCheckout() {
|
|
25
|
-
return fs.existsSync(path.join(packageRoot(), "src", "main.ts"));
|
|
31
|
+
return !compiledBinary() && fs.existsSync(path.join(packageRoot(), "src", "main.ts"));
|
|
32
|
+
}
|
|
33
|
+
var compiledBinary = () => globalThis.__OPENCODE_BROWSER_COMPILED__ === true;
|
|
34
|
+
var binaryPackage = () => globalThis.__OPENCODE_BROWSER_TARGET__ ? `@opencode/browse-${globalThis.__OPENCODE_BROWSER_TARGET__}` : undefined;
|
|
35
|
+
var binaryName = (platform = process.platform) => platform === "win32" ? "browse.exe" : "browse";
|
|
36
|
+
var scriptEntry = (entry) => /\.[cm]?[jt]s$/.test(entry);
|
|
37
|
+
var entryCommand = (entry, node = process.execPath) => scriptEntry(entry) ? [node, entry] : [entry];
|
|
38
|
+
function installedBinary() {
|
|
39
|
+
try {
|
|
40
|
+
const binary = JSON.parse(fs.readFileSync(path.join(dataRoot(), "runtime", "current.json"), "utf8")).binary;
|
|
41
|
+
return typeof binary === "string" ? binary : undefined;
|
|
42
|
+
} catch {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
26
45
|
}
|
|
46
|
+
var runningEntry = () => compiledBinary() ? process.execPath : process.argv[1];
|
|
27
47
|
function checkoutRoot() {
|
|
28
48
|
return fromCheckout() ? path.dirname(packageRoot()) : undefined;
|
|
29
49
|
}
|
|
30
50
|
var quoted = (value) => /^[\w@%+=:,./-]+$/.test(value) ? value : JSON.stringify(value);
|
|
31
51
|
function cliCommand(args) {
|
|
52
|
+
if (compiledBinary()) {
|
|
53
|
+
const binary = installedBinary() ?? process.execPath;
|
|
54
|
+
const dir = path.dirname(binary);
|
|
55
|
+
const onPath = (process.env.PATH ?? "").split(path.delimiter).some((entry) => entry && path.resolve(entry) === dir);
|
|
56
|
+
return `${onPath ? "browse" : quoted(binary)} ${args}`;
|
|
57
|
+
}
|
|
32
58
|
if (fromCheckout())
|
|
33
59
|
return `node ${quoted(path.join(packageRoot(), "dist", "cli.mjs"))} ${args}`;
|
|
34
60
|
const shim = path.join(dataRoot(), "bin", "opencode-browser.mjs");
|
|
@@ -43,13 +69,15 @@ function storeConfig(env = process.env, baked = { id: "mfnicocicmmlkpjnaffgihfjh
|
|
|
43
69
|
return id ? { id } : {};
|
|
44
70
|
}
|
|
45
71
|
var RELEASE_SERVICE = "https://anoma.ly/release";
|
|
46
|
-
function devExtension(baked = { file: "browse-extension-0.0.6-dev.
|
|
72
|
+
function devExtension(baked = { file: "browse-extension-0.0.6-dev.21.zip", sha256: "a2451776eced3e411999d7e1ae2858b4d4631550cac30baac18acbaeb626030a", size: 172633 }) {
|
|
47
73
|
return baked && /^[0-9a-f]{64}$/.test(baked.sha256) && /^[\w.-]+\.zip$/.test(baked.file) ? baked : undefined;
|
|
48
74
|
}
|
|
49
75
|
var devExtensionUrl = (extension, env = process.env) => `${(env.OPENCODE_BROWSER_RELEASE_SERVICE || RELEASE_SERVICE).replace(/\/+$/, "")}/browse/files/${extension.sha256}/${extension.file}`;
|
|
50
76
|
var devExtensionFolder = (root = dataRoot()) => path.join(root, "extension");
|
|
51
77
|
var storeUrl = (id) => `https://chromewebstore.google.com/detail/${id}`;
|
|
52
78
|
function installCommand() {
|
|
79
|
+
if (compiledBinary())
|
|
80
|
+
return cliCommand("install");
|
|
53
81
|
return fromCheckout() ? `cd ${quoted(path.dirname(packageRoot()))} && bun run setup` : "npx @opencode/browse install";
|
|
54
82
|
}
|
|
55
83
|
|
|
@@ -70,7 +98,8 @@ function runtimeLayout(root = dataRoot()) {
|
|
|
70
98
|
};
|
|
71
99
|
}
|
|
72
100
|
var versionDirectory = (layout, version) => path2.join(layout.versions, version);
|
|
73
|
-
var versionEntry = (layout, version) => path2.join(versionDirectory(layout, version), "node_modules", "@opencode", "browse", "dist", "cli.mjs");
|
|
101
|
+
var versionEntry = (layout, version, binary = compiledBinary()) => binary ? path2.join(versionDirectory(layout, version), binaryName()) : path2.join(versionDirectory(layout, version), "node_modules", "@opencode", "browse", "dist", "cli.mjs");
|
|
102
|
+
var updatePackage = () => (compiledBinary() ? binaryPackage() : undefined) ?? PACKAGE_NAME;
|
|
74
103
|
var channelOf = (version) => version.includes("-dev.") ? "dev" : "latest";
|
|
75
104
|
var UPDATE_VERSION = /^(\d+)\.(\d+)\.(\d+)(?:-dev\.(\d+)(?:\.(\d+))?)?$/;
|
|
76
105
|
function compareVersions(left, right) {
|
|
@@ -130,6 +159,8 @@ function npmRuntime(options = {}) {
|
|
|
130
159
|
if (options.checkout ?? fromCheckout())
|
|
131
160
|
return;
|
|
132
161
|
const layout = options.layout ?? runtimeLayout();
|
|
162
|
+
if (compiledBinary())
|
|
163
|
+
return binaryRuntime(layout);
|
|
133
164
|
const defaultEntry = () => fileURLToPath2(import.meta.url.endsWith(".ts") ? import.meta.url : new URL("./cli.mjs", import.meta.url));
|
|
134
165
|
const entry = realpath(options.entry ?? defaultEntry());
|
|
135
166
|
const relative = path2.relative(realpath(layout.versions), entry).split(path2.sep);
|
|
@@ -140,6 +171,16 @@ function npmRuntime(options = {}) {
|
|
|
140
171
|
return;
|
|
141
172
|
return { layout, version: relative[0], current };
|
|
142
173
|
}
|
|
174
|
+
function binaryRuntime(layout) {
|
|
175
|
+
const current = readCurrent(layout);
|
|
176
|
+
if (!current?.binary)
|
|
177
|
+
return;
|
|
178
|
+
const self = realpath(process.execPath);
|
|
179
|
+
const inVersions = !path2.relative(realpath(layout.versions), self).startsWith("..");
|
|
180
|
+
if (self !== realpath(current.binary) && !inVersions)
|
|
181
|
+
return;
|
|
182
|
+
return { layout, version: opencodeBrowserVersion2, current };
|
|
183
|
+
}
|
|
143
184
|
function autoUpdateOverride(env = process.env) {
|
|
144
185
|
const value = env.OPENCODE_BROWSER_AUTO_UPDATE?.trim().toLowerCase();
|
|
145
186
|
if (value === "on" || value === "1" || value === "true")
|
|
@@ -224,24 +265,25 @@ var runCommand = (command, args, options = {}) => new Promise((resolve) => {
|
|
|
224
265
|
});
|
|
225
266
|
async function registryUrl(run = runCommand, env = process.env) {
|
|
226
267
|
const override = env.OPENCODE_BROWSER_NPM_REGISTRY?.trim();
|
|
227
|
-
const configured = override || (await run("npm", ["config", "get", "registry"], { timeoutMs: 15000 })).stdout.trim();
|
|
268
|
+
const configured = override || (compiledBinary() ? "" : (await run("npm", ["config", "get", "registry"], { timeoutMs: 15000 })).stdout.trim());
|
|
228
269
|
return /^https?:\/\//.test(configured) ? configured.replace(/\/+$/, "") : DEFAULT_REGISTRY;
|
|
229
270
|
}
|
|
230
271
|
async function fetchPublished(options) {
|
|
231
272
|
const request = options.fetch ?? fetch;
|
|
232
|
-
const
|
|
273
|
+
const name = options.packageName ?? updatePackage();
|
|
274
|
+
const response = await request(`${options.registry}/${name.replace("/", "%2f")}`, {
|
|
233
275
|
headers: { accept: "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8" },
|
|
234
276
|
signal: AbortSignal.timeout(20000)
|
|
235
277
|
});
|
|
236
278
|
if (!response.ok)
|
|
237
|
-
throw new Error(`the registry answered ${response.status} for ${
|
|
279
|
+
throw new Error(`the registry answered ${response.status} for ${name}`);
|
|
238
280
|
const body = await response.json();
|
|
239
281
|
const version = body["dist-tags"]?.[options.channel];
|
|
240
282
|
if (!version)
|
|
241
|
-
throw new Error(`${
|
|
283
|
+
throw new Error(`${name} has no ${options.channel} dist-tag`);
|
|
242
284
|
const integrity = body.versions?.[version]?.dist?.integrity;
|
|
243
285
|
if (!integrity || !/^sha512-/.test(integrity))
|
|
244
|
-
throw new Error(`${
|
|
286
|
+
throw new Error(`${name}@${version} has no sha512 integrity in the registry`);
|
|
245
287
|
return { version, integrity };
|
|
246
288
|
}
|
|
247
289
|
function copyRunningPackage(source, prefix) {
|
|
@@ -267,6 +309,8 @@ function copyRunningPackage(source, prefix) {
|
|
|
267
309
|
copy(source);
|
|
268
310
|
}
|
|
269
311
|
async function installVersion(options) {
|
|
312
|
+
if (compiledBinary() || options.runningBinary)
|
|
313
|
+
return installBinaryVersion(options);
|
|
270
314
|
const run = options.run ?? runCommand;
|
|
271
315
|
const { layout } = options;
|
|
272
316
|
const spec = options.spec ?? `${PACKAGE_NAME}@${options.version}`;
|
|
@@ -310,6 +354,106 @@ async function installVersion(options) {
|
|
|
310
354
|
rmSync(temporary, { recursive: true, force: true });
|
|
311
355
|
}
|
|
312
356
|
}
|
|
357
|
+
async function installBinaryVersion(options) {
|
|
358
|
+
const run = options.run ?? runCommand;
|
|
359
|
+
const { layout } = options;
|
|
360
|
+
mkdirSync(layout.versions, { recursive: true });
|
|
361
|
+
const temporary = path2.join(layout.versions, `.install-${process.pid}-${Date.now()}`);
|
|
362
|
+
rmSync(temporary, { recursive: true, force: true });
|
|
363
|
+
mkdirSync(temporary, { recursive: true });
|
|
364
|
+
try {
|
|
365
|
+
const file = path2.join(temporary, binaryName());
|
|
366
|
+
const expected = options.runningBinary ? opencodeBrowserVersion2 : options.version;
|
|
367
|
+
if (options.runningBinary)
|
|
368
|
+
copyFileSync(options.runningBinary, file);
|
|
369
|
+
else {
|
|
370
|
+
const name = updatePackage();
|
|
371
|
+
if (name === PACKAGE_NAME)
|
|
372
|
+
throw new Error("this executable doesn't know its platform package");
|
|
373
|
+
const registry = options.registry ?? await registryUrl(run);
|
|
374
|
+
const integrity = options.integrity ?? await publishedIntegrity(registry, name, options.version);
|
|
375
|
+
const response = await fetch(`${registry}/${name}/-/${name.split("/")[1]}-${options.version}.tgz`, { signal: AbortSignal.timeout(10 * 60000) });
|
|
376
|
+
if (!response.ok)
|
|
377
|
+
throw new Error(`downloading ${name}@${options.version} failed: the registry answered ${response.status}`);
|
|
378
|
+
const tgz = new Uint8Array(await response.arrayBuffer());
|
|
379
|
+
const actual = `sha512-${createHash("sha512").update(tgz).digest("base64")}`;
|
|
380
|
+
if (actual !== integrity)
|
|
381
|
+
throw new Error(`${name}@${options.version} downloaded with integrity ${actual}, not the registry's ${integrity}`);
|
|
382
|
+
const executable = tarFile(tgz, `package/bin/${binaryName()}`);
|
|
383
|
+
if (!executable)
|
|
384
|
+
throw new Error(`${name}@${options.version} has no bin/${binaryName()}`);
|
|
385
|
+
writeFileSync(file, executable);
|
|
386
|
+
}
|
|
387
|
+
chmodSync(file, 493);
|
|
388
|
+
const reported = await run(file, ["--version"], { timeoutMs: 30000, env: { ...process.env, OPENCODE_BROWSER_AUTOSTART: "0" } });
|
|
389
|
+
if (reported.status !== 0 || reported.stdout.trim() !== expected)
|
|
390
|
+
throw new Error(`browse ${expected} didn't run: \`--version\` printed ${JSON.stringify(reported.stdout.trim() || reported.stderr.trim()).slice(0, 200)}`);
|
|
391
|
+
const target = versionDirectory(layout, expected);
|
|
392
|
+
rmSync(target, { recursive: true, force: true });
|
|
393
|
+
renameSync(temporary, target);
|
|
394
|
+
return versionEntry(layout, expected, true);
|
|
395
|
+
} finally {
|
|
396
|
+
rmSync(temporary, { recursive: true, force: true });
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async function publishedIntegrity(registry, name, version) {
|
|
400
|
+
const response = await fetch(`${registry}/${name.replace("/", "%2f")}/${version}`, { signal: AbortSignal.timeout(20000) });
|
|
401
|
+
if (!response.ok)
|
|
402
|
+
throw new Error(`the registry answered ${response.status} for ${name}@${version}`);
|
|
403
|
+
const integrity = (await response.json()).dist?.integrity;
|
|
404
|
+
if (!integrity || !/^sha512-/.test(integrity))
|
|
405
|
+
throw new Error(`${name}@${version} has no sha512 integrity in the registry`);
|
|
406
|
+
return integrity;
|
|
407
|
+
}
|
|
408
|
+
function tarFile(tgz, wanted) {
|
|
409
|
+
const tar = gunzipSync(tgz);
|
|
410
|
+
let offset = 0;
|
|
411
|
+
let longName;
|
|
412
|
+
while (offset + 512 <= tar.length) {
|
|
413
|
+
const header = tar.subarray(offset, offset + 512);
|
|
414
|
+
if (header.every((byte) => byte === 0))
|
|
415
|
+
return;
|
|
416
|
+
const field = (start, length) => header.subarray(start, start + length).toString("utf8").replace(/\0[\s\S]*$/, "");
|
|
417
|
+
const size = parseInt(field(124, 12).trim() || "0", 8);
|
|
418
|
+
const type = field(156, 1) || "0";
|
|
419
|
+
const prefix = field(345, 155);
|
|
420
|
+
const name = longName ?? (prefix ? `${prefix}/${field(0, 100)}` : field(0, 100));
|
|
421
|
+
longName = undefined;
|
|
422
|
+
const body = tar.subarray(offset + 512, offset + 512 + size);
|
|
423
|
+
offset += 512 + Math.ceil(size / 512) * 512;
|
|
424
|
+
if (type === "x")
|
|
425
|
+
longName = /(?:^|\n)\d+ path=([^\n]*)\n/.exec(body.toString("utf8"))?.[1];
|
|
426
|
+
else if (type === "L")
|
|
427
|
+
longName = body.toString("utf8").replace(/\0[\s\S]*$/, "");
|
|
428
|
+
else if (type === "0" && name === wanted)
|
|
429
|
+
return Buffer.from(body);
|
|
430
|
+
}
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
function placeBinary(source, target) {
|
|
434
|
+
const staged = `${target}.${process.pid}.new`;
|
|
435
|
+
rmSync(staged, { force: true });
|
|
436
|
+
try {
|
|
437
|
+
linkSync(source, staged);
|
|
438
|
+
} catch {
|
|
439
|
+
copyFileSync(source, staged);
|
|
440
|
+
}
|
|
441
|
+
chmodSync(staged, 493);
|
|
442
|
+
if (process.platform === "win32") {
|
|
443
|
+
const dir = path2.dirname(target);
|
|
444
|
+
const stale = `${path2.basename(target)}.old-`;
|
|
445
|
+
for (const name of readdirSync(dir)) {
|
|
446
|
+
if (!name.startsWith(stale))
|
|
447
|
+
continue;
|
|
448
|
+
try {
|
|
449
|
+
rmSync(path2.join(dir, name), { force: true });
|
|
450
|
+
} catch {}
|
|
451
|
+
}
|
|
452
|
+
if (existsSync(target))
|
|
453
|
+
renameSync(target, `${target}.old-${Date.now()}`);
|
|
454
|
+
}
|
|
455
|
+
renameSync(staged, target);
|
|
456
|
+
}
|
|
313
457
|
function processAlive(pid) {
|
|
314
458
|
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
315
459
|
return false;
|
|
@@ -344,15 +488,19 @@ function validatePending(layout) {
|
|
|
344
488
|
return state;
|
|
345
489
|
return updateState(layout, ({ pending: _pending, ...rest }) => rest);
|
|
346
490
|
}
|
|
347
|
-
function switchVersion(layout, version, previous) {
|
|
348
|
-
|
|
491
|
+
function switchVersion(layout, version, previous, binary = compiledBinary() ? readCurrent(layout)?.binary : undefined) {
|
|
492
|
+
const entry = versionEntry(layout, version, binary !== undefined);
|
|
493
|
+
if (!existsSync(entry))
|
|
349
494
|
throw new Error(`${version} isn't installed in ${layout.versions}`);
|
|
350
|
-
|
|
351
|
-
|
|
495
|
+
if (binary && !(version === opencodeBrowserVersion2 && realpath(binary) === realpath(process.execPath)))
|
|
496
|
+
placeBinary(entry, binary);
|
|
497
|
+
writeCurrent(layout, { version, ...previous && previous !== version ? { previous } : {}, channel: channelOf(version), ...binary ? { binary } : {} });
|
|
498
|
+
if (!binary)
|
|
499
|
+
writeShim(layout);
|
|
352
500
|
}
|
|
353
501
|
function shimSource() {
|
|
354
502
|
return `#!/usr/bin/env node
|
|
355
|
-
//
|
|
503
|
+
// browse's stable entry, written by install (cli/src/auto-update.ts). opencode's browse MCP server runs this
|
|
356
504
|
// file, so its configuration never changes when the runtime updates. Don't edit; install rewrites it.
|
|
357
505
|
import { spawn } from "node:child_process"
|
|
358
506
|
import { readFileSync } from "node:fs"
|
|
@@ -606,7 +754,8 @@ function spawnRuntimeChild(layout, entry, args, onExit, env = process.env) {
|
|
|
606
754
|
mkdirSync(path2.join(layout.root, "logs"), { recursive: true });
|
|
607
755
|
const log = openSync(path2.join(layout.root, "logs", "auto-update.log"), "a", 384);
|
|
608
756
|
try {
|
|
609
|
-
const
|
|
757
|
+
const [file, ...prefix] = entryCommand(entry);
|
|
758
|
+
const child = spawn(file, [...prefix, ...args], { detached: true, stdio: ["ignore", log, log], env: { ...rest, OPENCODE_BROWSER_HOME: layout.root } });
|
|
610
759
|
child.on("error", () => onExit(null));
|
|
611
760
|
child.on("exit", (code) => onExit(code));
|
|
612
761
|
child.unref();
|
|
@@ -619,115 +768,4 @@ function spawnRuntimeChild(layout, entry, args, onExit, env = process.env) {
|
|
|
619
768
|
}
|
|
620
769
|
}
|
|
621
770
|
|
|
622
|
-
|
|
623
|
-
var extensionProtocolVersion = 3;
|
|
624
|
-
var minExtensionProtocolVersion = 3;
|
|
625
|
-
var unpackedExtensionId = "afeafocngkodbmaipcngoamamfmekgfo";
|
|
626
|
-
var unpackedReloadAdvice = "Reload Browse on your browser's extensions page (↻).";
|
|
627
|
-
var checkoutReloadPrefix = "Extension protocol incompatible: extension-older; reload ";
|
|
628
|
-
var extensionReconnectAlarmPeriodMs = 30000;
|
|
629
|
-
var legacyExtensionProtocolVersion = 1;
|
|
630
|
-
function extensionProtocolCompatibility(value) {
|
|
631
|
-
const legacy = value === undefined;
|
|
632
|
-
const valid = typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
633
|
-
const version = valid ? value : legacy ? legacyExtensionProtocolVersion : null;
|
|
634
|
-
return { version, compatible: version !== null && version >= minExtensionProtocolVersion && version <= extensionProtocolVersion, legacy };
|
|
635
|
-
}
|
|
636
|
-
function extensionProtocolSkew(version) {
|
|
637
|
-
if (typeof version !== "number")
|
|
638
|
-
return;
|
|
639
|
-
if (version > extensionProtocolVersion)
|
|
640
|
-
return "extension-newer";
|
|
641
|
-
if (version < minExtensionProtocolVersion)
|
|
642
|
-
return "extension-older";
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
function extensionProtocolAdvice(version, commands, distribution) {
|
|
646
|
-
const skew = extensionProtocolSkew(version);
|
|
647
|
-
const versions = `extension protocol ${version ?? "unknown"}, this relay speaks ${minExtensionProtocolVersion === extensionProtocolVersion ? extensionProtocolVersion : `${minExtensionProtocolVersion} to ${extensionProtocolVersion}`}`;
|
|
648
|
-
if (skew === "extension-newer")
|
|
649
|
-
return `The Browse extension is newer than this browse CLI (${versions}). Update the CLI: run \`${commands.install}\` (an npm install with automatic updates also catches up by itself within a day), then restart opencode.`;
|
|
650
|
-
if (skew === "extension-older") {
|
|
651
|
-
const store = "The Chrome Web Store updates it within a few hours (to update now, open chrome://extensions, turn on Developer mode and click Update).";
|
|
652
|
-
const next = distribution === "unpacked" ? unpackedReloadAdvice : distribution === "store" ? store : `For an unpacked extension: ${unpackedReloadAdvice} For a store extension: ${store}`;
|
|
653
|
-
return `The Browse extension is older than this browse CLI (${versions}). ${next}`;
|
|
654
|
-
}
|
|
655
|
-
return `The Browse extension and this browse CLI don't speak the same protocol (${versions}). Run \`${commands.install}\` again and update the extension.`;
|
|
656
|
-
}
|
|
657
|
-
function makePageStatus(options) {
|
|
658
|
-
return {
|
|
659
|
-
state: options.state,
|
|
660
|
-
owner: options.targetOwner === "user" ? "user" : "session",
|
|
661
|
-
...options.sessionId ? { sessionId: options.sessionId } : {},
|
|
662
|
-
...options.sessionId && options.readOnly ? { readOnly: true } : {},
|
|
663
|
-
...options.message ? { message: options.message } : {},
|
|
664
|
-
...options.handoffId ? { handoffId: options.handoffId } : {},
|
|
665
|
-
...options.recording ? { recording: true } : {}
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
var extensionCommandMethodValues = [
|
|
669
|
-
"ping",
|
|
670
|
-
"debugger.attach",
|
|
671
|
-
"debugger.detach",
|
|
672
|
-
"debugger.sendCommand",
|
|
673
|
-
"tabs.create",
|
|
674
|
-
"tabs.remove",
|
|
675
|
-
"tabs.group",
|
|
676
|
-
"tabs.ungroup",
|
|
677
|
-
"action.setAttached",
|
|
678
|
-
"action.setBadge",
|
|
679
|
-
"pageStatus.set",
|
|
680
|
-
"pageStatus.clear",
|
|
681
|
-
"runtime.reload",
|
|
682
|
-
"recording.start",
|
|
683
|
-
"recording.stop",
|
|
684
|
-
"recording.status",
|
|
685
|
-
"recording.cancel",
|
|
686
|
-
"tabs.cleanup",
|
|
687
|
-
"update.notice",
|
|
688
|
-
"relay.settings",
|
|
689
|
-
"settings.get",
|
|
690
|
-
"settings.set"
|
|
691
|
-
];
|
|
692
|
-
var extensionEventMethodValues = [
|
|
693
|
-
"protocol",
|
|
694
|
-
"hello",
|
|
695
|
-
"auth.code",
|
|
696
|
-
"auth.response",
|
|
697
|
-
"ready",
|
|
698
|
-
"toolbar.clicked",
|
|
699
|
-
"handoff.completed",
|
|
700
|
-
"debugger.event",
|
|
701
|
-
"debugger.attached",
|
|
702
|
-
"debugger.detached",
|
|
703
|
-
"tabs.removed",
|
|
704
|
-
"tabs.opened",
|
|
705
|
-
"pong",
|
|
706
|
-
"log",
|
|
707
|
-
"recording.cancelled",
|
|
708
|
-
"pageStatus.requested",
|
|
709
|
-
"settings"
|
|
710
|
-
];
|
|
711
|
-
function parseJsonObject(input) {
|
|
712
|
-
const parsed = JSON.parse(input);
|
|
713
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
714
|
-
throw new Error("Expected JSON object");
|
|
715
|
-
}
|
|
716
|
-
return parsed;
|
|
717
|
-
}
|
|
718
|
-
var extensionCommandMethods = new Set(extensionCommandMethodValues);
|
|
719
|
-
var extensionEventMethods = new Set(extensionEventMethodValues);
|
|
720
|
-
function isCdpRequest(input) {
|
|
721
|
-
return typeof input.id === "number" && typeof input.method === "string" && (input.params === undefined || isJsonObject(input.params)) && (input.sessionId === undefined || typeof input.sessionId === "string");
|
|
722
|
-
}
|
|
723
|
-
function isExtensionResponse(input) {
|
|
724
|
-
return typeof input.id === "number" && (input.result === undefined || isJsonObject(input.result)) && (input.error === undefined || typeof input.error === "string") && !(input.result !== undefined && input.error !== undefined);
|
|
725
|
-
}
|
|
726
|
-
function isExtensionEvent(input) {
|
|
727
|
-
return typeof input.method === "string" && extensionEventMethods.has(input.method) && (input.params === undefined || isJsonObject(input.params));
|
|
728
|
-
}
|
|
729
|
-
function isJsonObject(value) {
|
|
730
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
export { dataRoot, oldStoreMarker, fromCheckout, checkoutRoot, cliCommand, storeConfig, devExtension, devExtensionUrl, devExtensionFolder, storeUrl, installCommand, autoUpdateModes, runtimeLayout, versionEntry, channelOf, UPDATE_VERSION, compareVersions, readCurrent, writeCurrent, updateState, npmRuntime, autoUpdateOverride, storedMode, effectiveMode, setStoredMode, autoUpdateStatus, describeAutoUpdate, registryUrl, fetchPublished, installVersion, pruneVersions, switchVersion, createAutoUpdater, extensionProtocolVersion, minExtensionProtocolVersion, unpackedExtensionId, unpackedReloadAdvice, checkoutReloadPrefix, extensionReconnectAlarmPeriodMs, extensionProtocolCompatibility, extensionProtocolSkew, extensionProtocolAdvice, makePageStatus, parseJsonObject, isCdpRequest, isExtensionResponse, isExtensionEvent, isJsonObject };
|
|
771
|
+
export { dataRoot, oldStoreMarker, fromCheckout, compiledBinary, binaryPackage, scriptEntry, entryCommand, runningEntry, checkoutRoot, cliCommand, storeConfig, devExtension, devExtensionUrl, devExtensionFolder, storeUrl, installCommand, autoUpdateModes, runtimeLayout, versionEntry, channelOf, UPDATE_VERSION, compareVersions, readCurrent, writeCurrent, updateState, npmRuntime, autoUpdateOverride, storedMode, effectiveMode, setStoredMode, autoUpdateStatus, describeAutoUpdate, registryUrl, fetchPublished, installVersion, pruneVersions, switchVersion, createAutoUpdater };
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
dataRoot,
|
|
3
|
+
compiledBinary,
|
|
3
4
|
checkoutRoot,
|
|
4
5
|
cliCommand,
|
|
5
6
|
compareVersions,
|
|
6
7
|
npmRuntime,
|
|
7
|
-
autoUpdateStatus
|
|
8
|
+
autoUpdateStatus
|
|
9
|
+
} from "./main-0m569gdn.mjs";
|
|
10
|
+
import {
|
|
8
11
|
unpackedReloadAdvice
|
|
9
|
-
} from "./main-
|
|
12
|
+
} from "./main-3gthmkzw.mjs";
|
|
10
13
|
|
|
11
14
|
// src/update.ts
|
|
12
15
|
import { execFile, spawnSync } from "node:child_process";
|
|
@@ -227,7 +230,7 @@ function runUpdate(args, deps) {
|
|
|
227
230
|
};
|
|
228
231
|
const repo = deps.repo;
|
|
229
232
|
if (!repo) {
|
|
230
|
-
log("
|
|
233
|
+
log("browse was installed from npm. Update it with:");
|
|
231
234
|
log(" npx @opencode/browse@latest install");
|
|
232
235
|
log("then restart opencode.");
|
|
233
236
|
return 0;
|
|
@@ -312,9 +315,14 @@ function runUpdate(args, deps) {
|
|
|
312
315
|
async function runUpdateCommand2(args) {
|
|
313
316
|
const log = (line) => process.stdout.write(line + `
|
|
314
317
|
`);
|
|
315
|
-
const { runNpmUpdate } = await import("./runtime-update-
|
|
318
|
+
const { runNpmUpdate } = await import("./runtime-update-fj4s270v.mjs");
|
|
316
319
|
if (await runNpmUpdate(args))
|
|
317
320
|
return;
|
|
321
|
+
if (compiledBinary()) {
|
|
322
|
+
log(`This browse isn't installed. Run \`${cliCommand("install")}\` to set it up; it updates itself from then on.`);
|
|
323
|
+
process.exitCode = 1;
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
318
326
|
if (args.includes("--check")) {
|
|
319
327
|
const repo = checkoutRoot();
|
|
320
328
|
if (!repo)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// src/protocol.ts
|
|
2
|
+
var extensionProtocolVersion = 3;
|
|
3
|
+
var minExtensionProtocolVersion = 3;
|
|
4
|
+
var unpackedExtensionId = "afeafocngkodbmaipcngoamamfmekgfo";
|
|
5
|
+
var unpackedReloadAdvice = "Reload browse on your browser's extensions page (↻).";
|
|
6
|
+
var checkoutReloadPrefix = "Extension protocol incompatible: extension-older; reload ";
|
|
7
|
+
var extensionReconnectAlarmPeriodMs = 30000;
|
|
8
|
+
var legacyExtensionProtocolVersion = 1;
|
|
9
|
+
function extensionProtocolCompatibility(value) {
|
|
10
|
+
const legacy = value === undefined;
|
|
11
|
+
const valid = typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
12
|
+
const version = valid ? value : legacy ? legacyExtensionProtocolVersion : null;
|
|
13
|
+
return { version, compatible: version !== null && version >= minExtensionProtocolVersion && version <= extensionProtocolVersion, legacy };
|
|
14
|
+
}
|
|
15
|
+
function extensionProtocolSkew(version) {
|
|
16
|
+
if (typeof version !== "number")
|
|
17
|
+
return;
|
|
18
|
+
if (version > extensionProtocolVersion)
|
|
19
|
+
return "extension-newer";
|
|
20
|
+
if (version < minExtensionProtocolVersion)
|
|
21
|
+
return "extension-older";
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
function extensionProtocolAdvice(version, commands, distribution) {
|
|
25
|
+
const skew = extensionProtocolSkew(version);
|
|
26
|
+
const versions = `extension protocol ${version ?? "unknown"}, this relay speaks ${minExtensionProtocolVersion === extensionProtocolVersion ? extensionProtocolVersion : `${minExtensionProtocolVersion} to ${extensionProtocolVersion}`}`;
|
|
27
|
+
if (skew === "extension-newer")
|
|
28
|
+
return `The browse extension is newer than this browse CLI (${versions}). Update the CLI: run \`${commands.install}\` (an npm install with automatic updates also catches up by itself within a day), then restart opencode.`;
|
|
29
|
+
if (skew === "extension-older") {
|
|
30
|
+
const store = "The Chrome Web Store updates it within a few hours (to update now, open chrome://extensions, turn on Developer mode and click Update).";
|
|
31
|
+
const next = distribution === "unpacked" ? unpackedReloadAdvice : distribution === "store" ? store : `For an unpacked extension: ${unpackedReloadAdvice} For a store extension: ${store}`;
|
|
32
|
+
return `The browse extension is older than this browse CLI (${versions}). ${next}`;
|
|
33
|
+
}
|
|
34
|
+
return `The browse extension and this browse CLI don't speak the same protocol (${versions}). Run \`${commands.install}\` again and update the extension.`;
|
|
35
|
+
}
|
|
36
|
+
function makePageStatus(options) {
|
|
37
|
+
return {
|
|
38
|
+
state: options.state,
|
|
39
|
+
owner: options.targetOwner === "user" ? "user" : "session",
|
|
40
|
+
...options.sessionId ? { sessionId: options.sessionId } : {},
|
|
41
|
+
...options.sessionId && options.readOnly ? { readOnly: true } : {},
|
|
42
|
+
...options.message ? { message: options.message } : {},
|
|
43
|
+
...options.handoffId ? { handoffId: options.handoffId } : {},
|
|
44
|
+
...options.recording ? { recording: true } : {}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
var extensionCommandMethodValues = [
|
|
48
|
+
"ping",
|
|
49
|
+
"debugger.attach",
|
|
50
|
+
"debugger.detach",
|
|
51
|
+
"debugger.sendCommand",
|
|
52
|
+
"tabs.create",
|
|
53
|
+
"tabs.remove",
|
|
54
|
+
"tabs.group",
|
|
55
|
+
"tabs.ungroup",
|
|
56
|
+
"action.setAttached",
|
|
57
|
+
"action.setBadge",
|
|
58
|
+
"pageStatus.set",
|
|
59
|
+
"pageStatus.clear",
|
|
60
|
+
"runtime.reload",
|
|
61
|
+
"recording.start",
|
|
62
|
+
"recording.stop",
|
|
63
|
+
"recording.status",
|
|
64
|
+
"recording.cancel",
|
|
65
|
+
"tabs.cleanup",
|
|
66
|
+
"update.notice",
|
|
67
|
+
"relay.settings",
|
|
68
|
+
"settings.get",
|
|
69
|
+
"settings.set"
|
|
70
|
+
];
|
|
71
|
+
var extensionEventMethodValues = [
|
|
72
|
+
"protocol",
|
|
73
|
+
"hello",
|
|
74
|
+
"auth.code",
|
|
75
|
+
"auth.response",
|
|
76
|
+
"ready",
|
|
77
|
+
"toolbar.clicked",
|
|
78
|
+
"handoff.completed",
|
|
79
|
+
"debugger.event",
|
|
80
|
+
"debugger.attached",
|
|
81
|
+
"debugger.detached",
|
|
82
|
+
"tabs.removed",
|
|
83
|
+
"tabs.opened",
|
|
84
|
+
"pong",
|
|
85
|
+
"log",
|
|
86
|
+
"recording.cancelled",
|
|
87
|
+
"pageStatus.requested",
|
|
88
|
+
"settings"
|
|
89
|
+
];
|
|
90
|
+
function parseJsonObject(input) {
|
|
91
|
+
const parsed = JSON.parse(input);
|
|
92
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
93
|
+
throw new Error("Expected JSON object");
|
|
94
|
+
}
|
|
95
|
+
return parsed;
|
|
96
|
+
}
|
|
97
|
+
var extensionCommandMethods = new Set(extensionCommandMethodValues);
|
|
98
|
+
var extensionEventMethods = new Set(extensionEventMethodValues);
|
|
99
|
+
function isCdpRequest(input) {
|
|
100
|
+
return typeof input.id === "number" && typeof input.method === "string" && (input.params === undefined || isJsonObject(input.params)) && (input.sessionId === undefined || typeof input.sessionId === "string");
|
|
101
|
+
}
|
|
102
|
+
function isExtensionResponse(input) {
|
|
103
|
+
return typeof input.id === "number" && (input.result === undefined || isJsonObject(input.result)) && (input.error === undefined || typeof input.error === "string") && !(input.result !== undefined && input.error !== undefined);
|
|
104
|
+
}
|
|
105
|
+
function isExtensionEvent(input) {
|
|
106
|
+
return typeof input.method === "string" && extensionEventMethods.has(input.method) && (input.params === undefined || isJsonObject(input.params));
|
|
107
|
+
}
|
|
108
|
+
function isJsonObject(value) {
|
|
109
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { extensionProtocolVersion, minExtensionProtocolVersion, unpackedExtensionId, unpackedReloadAdvice, checkoutReloadPrefix, extensionReconnectAlarmPeriodMs, extensionProtocolCompatibility, extensionProtocolSkew, extensionProtocolAdvice, makePageStatus, parseJsonObject, isCdpRequest, isExtensionResponse, isExtensionEvent, isJsonObject };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
writePrivateJsonFileSync
|
|
3
|
-
} from "./main-
|
|
3
|
+
} from "./main-7qs0mwvc.mjs";
|
|
4
4
|
import {
|
|
5
5
|
dataRoot,
|
|
6
6
|
devExtensionUrl,
|
|
7
7
|
devExtensionFolder
|
|
8
|
-
} from "./main-
|
|
8
|
+
} from "./main-0m569gdn.mjs";
|
|
9
9
|
|
|
10
10
|
// src/relay/browser-pairing.ts
|
|
11
11
|
import crypto from "node:crypto";
|
|
@@ -195,7 +195,7 @@ async function syncDevExtension(extension, options = {}) {
|
|
|
195
195
|
}
|
|
196
196
|
const manifest = JSON.parse(readFileSync(path2.join(staging, "manifest.json"), "utf8"));
|
|
197
197
|
if (!manifest.key)
|
|
198
|
-
throw new Error("the dev extension has no manifest key, so it wouldn't have
|
|
198
|
+
throw new Error("the dev extension has no manifest key, so it wouldn't have browse's unpacked ID");
|
|
199
199
|
writeExtensionPairing(staging, mintPairingCode(root, { ttlMs: bundledPairingCodeTtlMs }));
|
|
200
200
|
const build = (() => {
|
|
201
201
|
try {
|
|
@@ -300,4 +300,4 @@ function isLocalPeer(socket) {
|
|
|
300
300
|
return remote !== undefined && (remote === "::1" || remote.startsWith("127."));
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
-
export { context, pairingCodeTtlMs, bundledPairingCodeTtlMs, formatPairingCode, pairingCodeKey, mintPairingCode, pendingPairingCodeKeys, consumePairingCode, recordPairingFailure, writeExtensionPairing, readBrowserPairings, browserToken, newBrowserToken, issueBrowserToken, touchBrowserPairing, revokeBrowserToken, legacyPairingCode, removeLegacyPairingCode, legacyPairingProof, pairingProof, ecdhExchange, pairingSessionKey, sessionProof, wrapToken, installedDevExtension, syncDevExtension
|
|
303
|
+
export { parseHostname, readRelayConfig, writeRelayConfig, relayHostname, isLocalPeer, context, pairingCodeTtlMs, bundledPairingCodeTtlMs, formatPairingCode, pairingCodeKey, mintPairingCode, pendingPairingCodeKeys, consumePairingCode, recordPairingFailure, writeExtensionPairing, readBrowserPairings, browserToken, newBrowserToken, issueBrowserToken, touchBrowserPairing, revokeBrowserToken, legacyPairingCode, removeLegacyPairingCode, legacyPairingProof, pairingProof, ecdhExchange, pairingSessionKey, sessionProof, wrapToken, installedDevExtension, syncDevExtension };
|