@opencode/browse 0.0.6-dev.27 → 0.0.6
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-n0qhph13.mjs → cli-jp1jev7t.mjs} +10 -67
- package/dist/cli.mjs +9 -9
- package/dist/{helpers-zeewknn2.mjs → helpers-ynamkf6t.mjs} +1 -1
- package/dist/{main-3g2t8jtq.mjs → main-0g9jqyts.mjs} +2 -2
- package/dist/{main-a6mpfd6z.mjs → main-3cza6vx1.mjs} +2 -2
- package/dist/{main-xzc7qp1c.mjs → main-605j7tjk.mjs} +4 -34
- package/dist/{main-cxrsjs2z.mjs → main-hanwxg2c.mjs} +33 -468
- package/dist/{main-a4yj9bpn.mjs → main-njp635rz.mjs} +3 -3
- package/dist/{main-x96gxahz.mjs → main-q5j1am67.mjs} +2 -2
- package/dist/main-ry14nc9q.mjs +4 -0
- package/dist/{main-bq8az9yr.mjs → main-yv64m9we.mjs} +1 -1
- package/dist/{mcp-za7ymfdd.mjs → mcp-4w28g9h2.mjs} +11 -78
- package/dist/{relay-xqg264d4.mjs → relay-21t4e4tv.mjs} +35 -1104
- package/dist/{runtime-update-gteb0gp8.mjs → runtime-update-zjx0kaj7.mjs} +4 -4
- package/dist/{setup-zka6z53q.mjs → setup-0z9803a3.mjs} +5 -5
- package/dist/{skill-text-kyjcembk.mjs → skill-text-rc6te209.mjs} +0 -75
- package/dist/{supervisor-w6hs0gbw.mjs → supervisor-9qwn7rb1.mjs} +3 -3
- package/dist/{update-pj25xbh4.mjs → update-sxawv22k.mjs} +3 -3
- package/dist/{version-1hb8s8jj.mjs → version-8gwa4g0s.mjs} +1 -1
- package/package.json +1 -1
- package/skills/browse/SKILL.md +0 -75
- package/dist/main-vp3devjb.mjs +0 -4
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
parseTargetSelection2,
|
|
3
3
|
getObject2,
|
|
4
4
|
getString2
|
|
5
|
-
} from "./main-
|
|
5
|
+
} from "./main-605j7tjk.mjs";
|
|
6
6
|
import {
|
|
7
7
|
isNodeError,
|
|
8
8
|
writeJsonFileAtomically
|
|
9
|
-
} from "./main-
|
|
9
|
+
} from "./main-yv64m9we.mjs";
|
|
10
10
|
import {
|
|
11
11
|
dataRoot,
|
|
12
12
|
cliCommand
|
|
13
|
-
} from "./main-
|
|
13
|
+
} from "./main-3cza6vx1.mjs";
|
|
14
14
|
|
|
15
15
|
// src/relay/user-settings.ts
|
|
16
16
|
var settingKeys = ["window", "grouping", "idleMinutes", "cursor", "humanInput", "handoffNotifications", "autoUpdate"];
|
|
@@ -306,452 +306,17 @@ function toolResult(options) {
|
|
|
306
306
|
});
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
// src/auth/deadbolt.ts
|
|
310
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
311
|
-
import crypto from "node:crypto";
|
|
312
|
-
import fs from "node:fs";
|
|
313
|
-
import net from "node:net";
|
|
314
|
-
import os from "node:os";
|
|
315
|
-
import path from "node:path";
|
|
316
|
-
class DeadboltError extends Error {
|
|
317
|
-
name = "DeadboltError";
|
|
318
|
-
code;
|
|
319
|
-
detail;
|
|
320
|
-
constructor(code, message, detail = {}) {
|
|
321
|
-
super(message);
|
|
322
|
-
this.code = code;
|
|
323
|
-
this.detail = detail;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
var clientFileName = "deadbolt-client.json";
|
|
327
|
-
function clientFilePath(root = dataRoot()) {
|
|
328
|
-
return path.join(root, clientFileName);
|
|
329
|
-
}
|
|
330
|
-
function readClientFile(root = dataRoot()) {
|
|
331
|
-
let text;
|
|
332
|
-
try {
|
|
333
|
-
const file = clientFilePath(root);
|
|
334
|
-
const stat = fs.statSync(file);
|
|
335
|
-
if (process.platform !== "win32" && (stat.mode & 63) !== 0)
|
|
336
|
-
fs.chmodSync(file, 384);
|
|
337
|
-
text = fs.readFileSync(file, "utf8");
|
|
338
|
-
} catch {
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
try {
|
|
342
|
-
const value = JSON.parse(text);
|
|
343
|
-
if (typeof value.id !== "string" || !value.id || typeof value.token !== "string" || !value.token)
|
|
344
|
-
return;
|
|
345
|
-
return {
|
|
346
|
-
version: 1,
|
|
347
|
-
id: value.id,
|
|
348
|
-
token: value.token,
|
|
349
|
-
connectedAt: typeof value.connectedAt === "string" ? value.connectedAt : ""
|
|
350
|
-
};
|
|
351
|
-
} catch {
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
function readClient(root = dataRoot()) {
|
|
356
|
-
const file = readClientFile(root);
|
|
357
|
-
return file ? { id: file.id, token: file.token } : undefined;
|
|
358
|
-
}
|
|
359
|
-
async function saveClient(client, root = dataRoot()) {
|
|
360
|
-
const value = { version: 1, id: client.id, token: client.token, connectedAt: new Date().toISOString() };
|
|
361
|
-
await writeJsonFileAtomically(clientFilePath(root), value, { dirMode: 448 });
|
|
362
|
-
}
|
|
363
|
-
function removeClient(root = dataRoot()) {
|
|
364
|
-
const file = clientFilePath(root);
|
|
365
|
-
if (!fs.existsSync(file))
|
|
366
|
-
return false;
|
|
367
|
-
fs.rmSync(file, { force: true });
|
|
368
|
-
return true;
|
|
369
|
-
}
|
|
370
|
-
function computedSocketPath(env = process.env) {
|
|
371
|
-
const nonEmpty = (name) => env[name] ? env[name] : undefined;
|
|
372
|
-
const deadboltHome = nonEmpty("DEADBOLT_HOME");
|
|
373
|
-
const suffix = deadboltHome ? `-${blake3Hex(Buffer.from(deadboltHome, "utf8")).slice(0, 8)}` : "";
|
|
374
|
-
const uid = typeof process.getuid === "function" ? process.getuid() : 0;
|
|
375
|
-
const runtime = nonEmpty("XDG_RUNTIME_DIR") ?? userRuntimeDir(uid);
|
|
376
|
-
const directory = runtime ? path.join(runtime, `deadbolt${suffix}`) : path.join(nonEmpty("TMPDIR") ?? os.tmpdir(), `deadbolt${suffix}-${uid}`);
|
|
377
|
-
return path.join(directory, "agent.sock");
|
|
378
|
-
}
|
|
379
|
-
function userRuntimeDir(uid) {
|
|
380
|
-
const directory = `/run/user/${uid}`;
|
|
381
|
-
try {
|
|
382
|
-
const stat = fs.statSync(directory);
|
|
383
|
-
return stat.isDirectory() && stat.uid === uid ? directory : undefined;
|
|
384
|
-
} catch {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
function socketPath(options = {}) {
|
|
389
|
-
const env = options.env ?? process.env;
|
|
390
|
-
return env.OPENCODE_BROWSER_DEADBOLT_SOCKET || computedSocketPath(env);
|
|
391
|
-
}
|
|
392
|
-
var requestTimeoutMs = 15000;
|
|
393
|
-
var maxReplyBytes = 4 * 1024 * 1024;
|
|
394
|
-
function errorCode(code) {
|
|
395
|
-
const normalized = typeof code === "string" ? code.replace(/-/g, "_") : "";
|
|
396
|
-
switch (normalized) {
|
|
397
|
-
case "locked":
|
|
398
|
-
case "not_granted":
|
|
399
|
-
case "forbidden":
|
|
400
|
-
case "rate_limited":
|
|
401
|
-
case "domain_mismatch":
|
|
402
|
-
case "not_found":
|
|
403
|
-
case "choose_passkey":
|
|
404
|
-
return normalized;
|
|
405
|
-
case "not_initialized":
|
|
406
|
-
return "locked";
|
|
407
|
-
default:
|
|
408
|
-
return "failed";
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
var errorHints = {
|
|
412
|
-
locked: "Deadbolt is locked, so agent sign-ins are paused until the user unlocks it.",
|
|
413
|
-
forbidden: "Deadbolt doesn't know this browse install (its client was removed or revoked). Ask the user to run `opencode-browser deadbolt connect`.",
|
|
414
|
-
rate_limited: "Deadbolt is rate-limiting this client; wait before trying again."
|
|
415
|
-
};
|
|
416
|
-
function rawRequest(socket, request, timeoutMs = requestTimeoutMs) {
|
|
417
|
-
return new Promise((resolve, reject) => {
|
|
418
|
-
const connection = net.createConnection(socket);
|
|
419
|
-
let buffer = "";
|
|
420
|
-
let settled = false;
|
|
421
|
-
const finish = (error, value) => {
|
|
422
|
-
if (settled)
|
|
423
|
-
return;
|
|
424
|
-
settled = true;
|
|
425
|
-
clearTimeout(timer);
|
|
426
|
-
connection.destroy();
|
|
427
|
-
if (error)
|
|
428
|
-
reject(error);
|
|
429
|
-
else
|
|
430
|
-
resolve(value);
|
|
431
|
-
};
|
|
432
|
-
const timer = setTimeout(() => finish(new DeadboltError("unavailable", `Deadbolt did not answer ${String(request.cmd)} within ${timeoutMs} ms`)), timeoutMs);
|
|
433
|
-
connection.setEncoding("utf8");
|
|
434
|
-
connection.on("connect", () => connection.write(`${JSON.stringify(request)}
|
|
435
|
-
`));
|
|
436
|
-
connection.on("error", (cause) => {
|
|
437
|
-
const missing = cause.code === "ENOENT" || cause.code === "ECONNREFUSED";
|
|
438
|
-
finish(new DeadboltError("unavailable", missing ? "Deadbolt isn't running (no agent socket). Ask the user to start or unlock Deadbolt." : `Could not reach Deadbolt: ${cause.message}`));
|
|
439
|
-
});
|
|
440
|
-
connection.on("data", (chunk) => {
|
|
441
|
-
buffer += chunk;
|
|
442
|
-
if (buffer.length > maxReplyBytes)
|
|
443
|
-
return finish(new DeadboltError("failed", "Deadbolt's reply was too large"));
|
|
444
|
-
let newline;
|
|
445
|
-
while ((newline = buffer.indexOf(`
|
|
446
|
-
`)) !== -1) {
|
|
447
|
-
const line = buffer.slice(0, newline).trim();
|
|
448
|
-
buffer = buffer.slice(newline + 1);
|
|
449
|
-
if (!line)
|
|
450
|
-
continue;
|
|
451
|
-
let message;
|
|
452
|
-
try {
|
|
453
|
-
message = JSON.parse(line);
|
|
454
|
-
} catch {
|
|
455
|
-
return finish(new DeadboltError("failed", "Deadbolt sent a reply that isn't JSON"));
|
|
456
|
-
}
|
|
457
|
-
if (message.type === "ok")
|
|
458
|
-
return finish(undefined, message.reply ?? {});
|
|
459
|
-
if (message.type === "error") {
|
|
460
|
-
const code = errorCode(message.code);
|
|
461
|
-
const text = typeof message.message === "string" ? message.message : String(message.code);
|
|
462
|
-
const detail = message.grant ?? {};
|
|
463
|
-
const choices = passkeyList(message.choices ?? message.passkeys);
|
|
464
|
-
return finish(new DeadboltError(code, errorHints[code] ? `${text.replace(/[\s.]*$/, ".")} ${errorHints[code]}` : text, {
|
|
465
|
-
...typeof detail.site === "string" ? { site: detail.site } : {},
|
|
466
|
-
...typeof detail.login === "string" ? { login: detail.login } : {},
|
|
467
|
-
...choices.length > 0 ? { choices } : {}
|
|
468
|
-
}));
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
});
|
|
472
|
-
connection.on("end", () => finish(new DeadboltError("failed", "Deadbolt closed the connection without a reply")));
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
var str = (value) => typeof value === "string" ? value : undefined;
|
|
476
|
-
function passkeyList(value) {
|
|
477
|
-
if (!Array.isArray(value))
|
|
478
|
-
return [];
|
|
479
|
-
return value.filter((entry) => entry !== null && typeof entry === "object").map((entry) => {
|
|
480
|
-
const username = str(entry.username);
|
|
481
|
-
const displayName = str(entry.display_name) ?? str(entry.displayName);
|
|
482
|
-
return { ref: entry.ref ?? entry.login, ...username ? { username } : {}, ...displayName ? { displayName } : {}, granted: entry.granted !== false };
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
function toLogin(raw) {
|
|
486
|
-
const signIn = raw.sign_in;
|
|
487
|
-
const fields = Array.isArray(raw.fields) ? raw.fields.filter((field) => typeof field === "string") : undefined;
|
|
488
|
-
const username = str(raw.username);
|
|
489
|
-
return {
|
|
490
|
-
ref: raw.ref ?? raw.login,
|
|
491
|
-
title: str(raw.title) ?? "",
|
|
492
|
-
...username ? { username } : {},
|
|
493
|
-
hasPassword: raw.has_password === true,
|
|
494
|
-
hasTotp: raw.has_totp === true || raw.has_otp === true,
|
|
495
|
-
hasPasskey: raw.has_passkey === true,
|
|
496
|
-
granted: fields !== undefined && fields.length > 0 || raw.passkeys === true,
|
|
497
|
-
passkeys: raw.passkeys === true,
|
|
498
|
-
...fields ? { fields } : {},
|
|
499
|
-
...signIn && typeof signIn.provider === "string" ? { signIn: { provider: signIn.provider, ...str(signIn.account) ? { account: str(signIn.account) } : {} } } : {}
|
|
500
|
-
};
|
|
501
|
-
}
|
|
502
|
-
function connect(options = {}) {
|
|
503
|
-
const client = options.client ?? readClient(options.root);
|
|
504
|
-
if (!client) {
|
|
505
|
-
throw new DeadboltError("not_connected", "browse isn't connected to Deadbolt. Ask the user to run `opencode-browser deadbolt connect` and to allow the logins agents may use with `deadbolt agents allow <site>`.");
|
|
506
|
-
}
|
|
507
|
-
const socket = options.socket ?? socketPath();
|
|
508
|
-
let protocol;
|
|
509
|
-
const version = async () => {
|
|
510
|
-
if (protocol === undefined) {
|
|
511
|
-
const status = await rawRequest(socket, { v: 0, cmd: "status" });
|
|
512
|
-
protocol = typeof status.protocol === "number" ? status.protocol : 0;
|
|
513
|
-
}
|
|
514
|
-
return protocol;
|
|
515
|
-
};
|
|
516
|
-
const send = async (cmd, fields) => rawRequest(socket, { v: await version(), cmd, client: { id: client.id, token: client.token }, ...fields });
|
|
517
|
-
const site = async (origin) => {
|
|
518
|
-
const reply = await send("agent-logins", { origin });
|
|
519
|
-
const raw = (Array.isArray(reply.logins) ? reply.logins : []).filter((login) => login !== null && typeof login === "object");
|
|
520
|
-
const logins = raw.map(toLogin);
|
|
521
|
-
let passkeys = passkeyList(reply.passkeys);
|
|
522
|
-
if (!Array.isArray(reply.passkeys)) {
|
|
523
|
-
passkeys = logins.filter((login) => login.hasPasskey).map((login) => ({ ref: login.ref, ...login.username ? { username: login.username } : {}, granted: login.passkeys }));
|
|
524
|
-
}
|
|
525
|
-
return { logins, passkeys };
|
|
526
|
-
};
|
|
527
|
-
return {
|
|
528
|
-
socket,
|
|
529
|
-
client,
|
|
530
|
-
status: async () => {
|
|
531
|
-
const status = await rawRequest(socket, { v: 0, cmd: "status" });
|
|
532
|
-
protocol = typeof status.protocol === "number" ? status.protocol : 0;
|
|
533
|
-
return { protocol, unlocked: status.unlocked === true, ...str(status.version) ? { version: str(status.version) } : {} };
|
|
534
|
-
},
|
|
535
|
-
logins: async (origin) => (await site(origin)).logins,
|
|
536
|
-
site: (origin) => site(origin),
|
|
537
|
-
fill: async (origin, login, want) => {
|
|
538
|
-
const reply = await send("agent-fill", { origin, login: login.ref, want: [...want] });
|
|
539
|
-
const values = reply.values ?? reply;
|
|
540
|
-
return {
|
|
541
|
-
...str(values.username) !== undefined ? { username: str(values.username) } : {},
|
|
542
|
-
...str(values.password) !== undefined ? { password: str(values.password) } : {},
|
|
543
|
-
...str(values.totp) !== undefined ? { totp: str(values.totp) } : {}
|
|
544
|
-
};
|
|
545
|
-
},
|
|
546
|
-
passkeyGet: async (request) => {
|
|
547
|
-
const reply = await send("agent-passkey-get", {
|
|
548
|
-
origin: request.origin,
|
|
549
|
-
...request.rpId ? { rp_id: request.rpId } : {},
|
|
550
|
-
challenge: request.challenge,
|
|
551
|
-
allow_credentials: [...request.allowCredentials],
|
|
552
|
-
user_verification: request.userVerification,
|
|
553
|
-
...request.login !== undefined ? { login: request.login } : {}
|
|
554
|
-
});
|
|
555
|
-
if (reply.reply === "choose-passkey") {
|
|
556
|
-
throw new DeadboltError("choose_passkey", "Several passkeys could sign in here; name one by its username.", { choices: passkeyList(reply.choices ?? reply.passkeys) });
|
|
557
|
-
}
|
|
558
|
-
const credentialId = str(reply.credential_id);
|
|
559
|
-
const clientDataJson = str(reply.client_data_json);
|
|
560
|
-
const authenticatorData = str(reply.authenticator_data);
|
|
561
|
-
const signature = str(reply.signature);
|
|
562
|
-
if (!credentialId || !clientDataJson || !authenticatorData || !signature)
|
|
563
|
-
throw new DeadboltError("failed", "Deadbolt's passkey assertion is incomplete");
|
|
564
|
-
return { credentialId, clientDataJson, authenticatorData, signature, ...str(reply.user_handle) ? { userHandle: str(reply.user_handle) } : {} };
|
|
565
|
-
}
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
var deadboltNamePrefix = "deadbolt:";
|
|
569
|
-
function parseDeadboltName(name) {
|
|
570
|
-
if (!name.startsWith(deadboltNamePrefix))
|
|
571
|
-
return;
|
|
572
|
-
const rest = name.slice(deadboltNamePrefix.length).trim();
|
|
573
|
-
const origin = /^https?:\/\/[^/]+/i.exec(rest);
|
|
574
|
-
const site = origin ? origin[0] : rest.split("/")[0];
|
|
575
|
-
const username = rest.slice(site.length + 1);
|
|
576
|
-
if (!site)
|
|
577
|
-
return;
|
|
578
|
-
return { site: site.toLowerCase(), ...username ? { username } : {} };
|
|
579
|
-
}
|
|
580
|
-
function originOnSite(origin, site) {
|
|
581
|
-
let url;
|
|
582
|
-
try {
|
|
583
|
-
url = new URL(origin);
|
|
584
|
-
} catch {
|
|
585
|
-
return false;
|
|
586
|
-
}
|
|
587
|
-
if (/^https?:\/\//i.test(site)) {
|
|
588
|
-
try {
|
|
589
|
-
return new URL(site).origin === url.origin;
|
|
590
|
-
} catch {
|
|
591
|
-
return false;
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
const host = url.hostname.toLowerCase();
|
|
595
|
-
const bare = site.replace(/^\*\./, "").replace(/:\d+$/, "").toLowerCase();
|
|
596
|
-
const local = host === "localhost" || host === "127.0.0.1" || host === "[::1]" || host.endsWith(".localhost");
|
|
597
|
-
if (url.protocol !== "https:" && !(url.protocol === "http:" && local))
|
|
598
|
-
return false;
|
|
599
|
-
return host === bare || host.endsWith(`.${bare}`);
|
|
600
|
-
}
|
|
601
|
-
function pickLogin(logins, site, username, field) {
|
|
602
|
-
const granted = logins.filter((login) => login.granted && (field === undefined || login.fields === undefined || login.fields.includes(field)));
|
|
603
|
-
const candidates = username === undefined ? granted : granted.filter((login) => login.username?.toLowerCase() === username.toLowerCase());
|
|
604
|
-
if (candidates.length === 1)
|
|
605
|
-
return candidates[0];
|
|
606
|
-
if (candidates.length === 0) {
|
|
607
|
-
throw new DeadboltError("not_granted", username === undefined ? `No Deadbolt login is granted to browse for ${site}${field ? ` (${field})` : ""}. Ask the user to allow one with \`deadbolt agents allow ${site}\`.` : `No Deadbolt login for ${username} is granted to browse for ${site}${field ? ` (${field})` : ""}. Ask the user to allow it with \`deadbolt agents allow ${site} --login ${username}\`.`, { site, ...username ? { login: username } : {} });
|
|
608
|
-
}
|
|
609
|
-
throw new DeadboltError("failed", `Several Deadbolt logins are granted for ${site}; name one: deadbolt:${site}/<username> (${candidates.map((login) => login.username ?? login.title).join(", ")})`);
|
|
610
|
-
}
|
|
611
|
-
function originsFromPatterns(patterns) {
|
|
612
|
-
const origins = new Set;
|
|
613
|
-
for (const pattern of patterns) {
|
|
614
|
-
const scheme = /^(https?):\/\//i.exec(pattern)?.[1]?.toLowerCase() ?? "https";
|
|
615
|
-
const host = pattern.replace(/^https?:\/\//i, "").replace(/^\*\./, "").replace(/\/$/, "");
|
|
616
|
-
try {
|
|
617
|
-
origins.add(new URL(`${scheme}://${host}`).origin);
|
|
618
|
-
} catch {}
|
|
619
|
-
}
|
|
620
|
-
return [...origins];
|
|
621
|
-
}
|
|
622
|
-
async function listLogins(origins, connection) {
|
|
623
|
-
let deadbolt;
|
|
624
|
-
try {
|
|
625
|
-
deadbolt = connection ?? connect();
|
|
626
|
-
} catch (error) {
|
|
627
|
-
return { connected: false, logins: [], passkeys: [], error: { code: error instanceof DeadboltError ? error.code : "failed", message: error instanceof Error ? error.message : String(error) } };
|
|
628
|
-
}
|
|
629
|
-
const logins = [];
|
|
630
|
-
const passkeys = [];
|
|
631
|
-
for (const origin of origins.slice(0, 20)) {
|
|
632
|
-
try {
|
|
633
|
-
const found = await deadbolt.site(origin);
|
|
634
|
-
for (const { ref: _ref, ...login } of found.logins)
|
|
635
|
-
logins.push({ ...login, origin });
|
|
636
|
-
for (const { ref: _ref, ...passkey } of found.passkeys)
|
|
637
|
-
passkeys.push({ ...passkey, origin });
|
|
638
|
-
} catch (error) {
|
|
639
|
-
if (error instanceof DeadboltError && (error.code === "domain_mismatch" || error.code === "not_found" || error.code === "not_granted"))
|
|
640
|
-
continue;
|
|
641
|
-
return { connected: true, logins, passkeys, error: { code: error instanceof DeadboltError ? error.code : "failed", message: error instanceof Error ? error.message : String(error) } };
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
return { connected: true, logins, passkeys };
|
|
645
|
-
}
|
|
646
|
-
function pickPasskey(passkeys, username) {
|
|
647
|
-
const wanted = username.toLowerCase();
|
|
648
|
-
const granted = passkeys.filter((passkey) => passkey.granted);
|
|
649
|
-
return granted.find((passkey) => passkey.username?.toLowerCase() === wanted) ?? granted.find((passkey) => passkey.displayName?.toLowerCase() === wanted);
|
|
650
|
-
}
|
|
651
|
-
async function pair(options = {}) {
|
|
652
|
-
const command = options.command ?? (process.env.OPENCODE_BROWSER_DEADBOLT_CLI || "deadbolt");
|
|
653
|
-
const stdout = await new Promise((resolve, reject) => {
|
|
654
|
-
const child = spawn(command, ["agents", "add-client", options.name ?? "browse", "--json"], { stdio: ["inherit", "pipe", "inherit"] });
|
|
655
|
-
let output = "";
|
|
656
|
-
child.stdout.setEncoding("utf8");
|
|
657
|
-
child.stdout.on("data", (chunk) => {
|
|
658
|
-
output += chunk;
|
|
659
|
-
});
|
|
660
|
-
child.on("error", (cause) => reject(new DeadboltError("unavailable", cause.code === "ENOENT" ? `${command} isn't installed or on PATH. Install Deadbolt first.` : `Could not run ${command}: ${cause.message}`)));
|
|
661
|
-
child.on("close", (code) => code === 0 ? resolve(output) : reject(new DeadboltError("failed", `deadbolt agents add-client exited with status ${code}`)));
|
|
662
|
-
});
|
|
663
|
-
let parsed;
|
|
664
|
-
try {
|
|
665
|
-
const line = stdout.trim().split(`
|
|
666
|
-
`).filter(Boolean).at(-1) ?? "";
|
|
667
|
-
parsed = JSON.parse(line);
|
|
668
|
-
} catch {
|
|
669
|
-
throw new DeadboltError("failed", "deadbolt agents add-client --json didn't print a client");
|
|
670
|
-
}
|
|
671
|
-
const client = parsed.client ?? parsed;
|
|
672
|
-
const id = str(client.id);
|
|
673
|
-
const token = str(client.token) ?? str(parsed.token);
|
|
674
|
-
if (!id || !token)
|
|
675
|
-
throw new DeadboltError("failed", "deadbolt agents add-client --json printed no id and token");
|
|
676
|
-
await saveClient({ id, token }, options.root);
|
|
677
|
-
return { id };
|
|
678
|
-
}
|
|
679
|
-
function unpair(options = {}) {
|
|
680
|
-
const client = readClient(options.root);
|
|
681
|
-
if (!client)
|
|
682
|
-
return { removed: false, revoked: false };
|
|
683
|
-
const command = options.command ?? (process.env.OPENCODE_BROWSER_DEADBOLT_CLI || "deadbolt");
|
|
684
|
-
const result = spawnSync(command, ["agents", "remove-client", client.id], { stdio: ["inherit", "ignore", "inherit"], timeout: 120000 });
|
|
685
|
-
return { removed: removeClient(options.root), revoked: result.status === 0 };
|
|
686
|
-
}
|
|
687
|
-
function isBase64Url(value, maxLength = 8192) {
|
|
688
|
-
return typeof value === "string" && value.length <= maxLength && /^[A-Za-z0-9_-]*$/.test(value);
|
|
689
|
-
}
|
|
690
|
-
function randomName(prefix) {
|
|
691
|
-
return `${prefix}${crypto.randomBytes(12).toString("hex")}`;
|
|
692
|
-
}
|
|
693
|
-
var blake3Iv = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225];
|
|
694
|
-
var blake3Permutation = [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8];
|
|
695
|
-
function blake3Compress(cv, block, blockLength, flags) {
|
|
696
|
-
const s = new Uint32Array([...cv, blake3Iv[0], blake3Iv[1], blake3Iv[2], blake3Iv[3], 0, 0, blockLength, flags]);
|
|
697
|
-
let m = Uint32Array.from(block);
|
|
698
|
-
const rotr = (x, n) => x >>> n | x << 32 - n;
|
|
699
|
-
const g = (a, b, c, d, x, y) => {
|
|
700
|
-
s[a] = s[a] + s[b] + x;
|
|
701
|
-
s[d] = rotr(s[d] ^ s[a], 16);
|
|
702
|
-
s[c] = s[c] + s[d];
|
|
703
|
-
s[b] = rotr(s[b] ^ s[c], 12);
|
|
704
|
-
s[a] = s[a] + s[b] + y;
|
|
705
|
-
s[d] = rotr(s[d] ^ s[a], 8);
|
|
706
|
-
s[c] = s[c] + s[d];
|
|
707
|
-
s[b] = rotr(s[b] ^ s[c], 7);
|
|
708
|
-
};
|
|
709
|
-
for (let round = 0;round < 7; round++) {
|
|
710
|
-
g(0, 4, 8, 12, m[0], m[1]);
|
|
711
|
-
g(1, 5, 9, 13, m[2], m[3]);
|
|
712
|
-
g(2, 6, 10, 14, m[4], m[5]);
|
|
713
|
-
g(3, 7, 11, 15, m[6], m[7]);
|
|
714
|
-
g(0, 5, 10, 15, m[8], m[9]);
|
|
715
|
-
g(1, 6, 11, 12, m[10], m[11]);
|
|
716
|
-
g(2, 7, 8, 13, m[12], m[13]);
|
|
717
|
-
g(3, 4, 9, 14, m[14], m[15]);
|
|
718
|
-
if (round < 6)
|
|
719
|
-
m = Uint32Array.from(blake3Permutation, (index) => m[index]);
|
|
720
|
-
}
|
|
721
|
-
return Array.from({ length: 8 }, (_, index) => (s[index] ^ s[index + 8]) >>> 0);
|
|
722
|
-
}
|
|
723
|
-
function blake3Hex(input) {
|
|
724
|
-
if (input.length > 1024)
|
|
725
|
-
throw new Error("blake3Hex handles inputs up to 1024 bytes (DEADBOLT_HOME is longer: set OPENCODE_BROWSER_DEADBOLT_SOCKET)");
|
|
726
|
-
const blocks = Math.max(1, Math.ceil(input.length / 64));
|
|
727
|
-
let cv = [...blake3Iv];
|
|
728
|
-
for (let index = 0;index < blocks; index++) {
|
|
729
|
-
const bytes = new Uint8Array(64);
|
|
730
|
-
const chunk = input.subarray(index * 64, index * 64 + 64);
|
|
731
|
-
bytes.set(chunk);
|
|
732
|
-
const words = new Uint32Array(16);
|
|
733
|
-
const view = new DataView(bytes.buffer);
|
|
734
|
-
for (let word = 0;word < 16; word++)
|
|
735
|
-
words[word] = view.getUint32(word * 4, true);
|
|
736
|
-
const flags = (index === 0 ? 1 : 0) | (index === blocks - 1 ? 2 | 8 : 0);
|
|
737
|
-
cv = blake3Compress(cv, words, chunk.length, flags);
|
|
738
|
-
}
|
|
739
|
-
const out = Buffer.alloc(32);
|
|
740
|
-
cv.forEach((word, index) => out.writeUInt32LE(word, index * 4));
|
|
741
|
-
return out.toString("hex");
|
|
742
|
-
}
|
|
743
|
-
|
|
744
309
|
// src/auth/site-secrets.ts
|
|
745
|
-
import
|
|
746
|
-
import
|
|
747
|
-
import
|
|
310
|
+
import crypto from "node:crypto";
|
|
311
|
+
import fs2 from "node:fs/promises";
|
|
312
|
+
import path2 from "node:path";
|
|
748
313
|
import { Effect as Effect3, Schema as Schema2 } from "effect";
|
|
749
314
|
|
|
750
315
|
// src/auth/profile.ts
|
|
751
316
|
import { Effect as Effect2, Schema, Semaphore } from "effect";
|
|
752
|
-
import { spawn
|
|
753
|
-
import
|
|
754
|
-
import
|
|
317
|
+
import { spawn } from "node:child_process";
|
|
318
|
+
import fs from "node:fs/promises";
|
|
319
|
+
import path from "node:path";
|
|
755
320
|
|
|
756
321
|
// src/update/child-process.ts
|
|
757
322
|
async function terminateChildProcess(options) {
|
|
@@ -1253,7 +818,7 @@ class AuthProfileError extends Schema.TaggedError()("AuthProfile.Error", {
|
|
|
1253
818
|
cause: Schema.optionalKey(Schema.Defect())
|
|
1254
819
|
}) {
|
|
1255
820
|
}
|
|
1256
|
-
var defaultBaseDir = () =>
|
|
821
|
+
var defaultBaseDir = () => path.join(dataRoot(), "secrets");
|
|
1257
822
|
var writeLock = Semaphore.makeUnsafe(1);
|
|
1258
823
|
var profileLockTimeoutMs = 30000;
|
|
1259
824
|
var staleProfileLockMs = 60000;
|
|
@@ -1262,7 +827,7 @@ var maximumTimeoutMs = 2147483647;
|
|
|
1262
827
|
var read = Effect2.fn("AuthProfile.read")(function* (name, options = {}) {
|
|
1263
828
|
const filePath = yield* profilePath(options.baseDir ?? defaultBaseDir(), name);
|
|
1264
829
|
const text = yield* Effect2.tryPromise({
|
|
1265
|
-
try: () =>
|
|
830
|
+
try: () => fs.readFile(filePath, "utf8"),
|
|
1266
831
|
catch: (cause) => isNodeError(cause) && cause.code === "ENOENT" ? new AuthProfileError({ message: `Auth profile not found: ${name}`, operation: "read", reason: "not-found", cause }) : new AuthProfileError({ message: `Could not read auth profile: ${name}`, operation: "read", reason: "read-failed", cause })
|
|
1267
832
|
});
|
|
1268
833
|
return yield* Schema.decodeUnknownEffect(StoredAuthProfile)(yield* Effect2.try({
|
|
@@ -1280,12 +845,12 @@ function withLock(name, options, effect) {
|
|
|
1280
845
|
const lockPath = `${filePath}.lock`;
|
|
1281
846
|
yield* Effect2.tryPromise({
|
|
1282
847
|
try: async () => {
|
|
1283
|
-
await
|
|
1284
|
-
await
|
|
848
|
+
await fs.mkdir(baseDir, { recursive: true, mode: 448 });
|
|
849
|
+
await fs.chmod(baseDir, 448);
|
|
1285
850
|
const deadline = Date.now() + profileLockTimeoutMs;
|
|
1286
851
|
while (true) {
|
|
1287
852
|
try {
|
|
1288
|
-
const handle = await
|
|
853
|
+
const handle = await fs.open(lockPath, "wx", 384);
|
|
1289
854
|
let written = false;
|
|
1290
855
|
try {
|
|
1291
856
|
await handle.writeFile(`${process.pid}
|
|
@@ -1294,17 +859,17 @@ function withLock(name, options, effect) {
|
|
|
1294
859
|
} finally {
|
|
1295
860
|
await handle.close();
|
|
1296
861
|
if (!written)
|
|
1297
|
-
await
|
|
862
|
+
await fs.unlink(lockPath).catch(() => {});
|
|
1298
863
|
}
|
|
1299
864
|
return;
|
|
1300
865
|
} catch (cause) {
|
|
1301
866
|
if (!isNodeError(cause) || cause.code !== "EEXIST")
|
|
1302
867
|
throw cause;
|
|
1303
|
-
const stat = await
|
|
868
|
+
const stat = await fs.stat(lockPath).catch(() => {
|
|
1304
869
|
return;
|
|
1305
870
|
});
|
|
1306
871
|
if (stat && Date.now() - stat.mtimeMs > staleProfileLockMs) {
|
|
1307
|
-
await
|
|
872
|
+
await fs.unlink(lockPath).catch(() => {});
|
|
1308
873
|
continue;
|
|
1309
874
|
}
|
|
1310
875
|
if (Date.now() >= deadline)
|
|
@@ -1318,7 +883,7 @@ function withLock(name, options, effect) {
|
|
|
1318
883
|
return lockPath;
|
|
1319
884
|
});
|
|
1320
885
|
return Effect2.acquireUseRelease(acquire, () => effect, (lockPath) => Effect2.tryPromise({
|
|
1321
|
-
try: () =>
|
|
886
|
+
try: () => fs.unlink(lockPath).catch(() => {}).then(() => {}),
|
|
1322
887
|
catch: (cause) => new AuthProfileError({ message: `Could not release auth profile lock: ${name}`, operation: "lock", reason: "write-failed", cause })
|
|
1323
888
|
}));
|
|
1324
889
|
}
|
|
@@ -1405,7 +970,7 @@ function summary(profile) {
|
|
|
1405
970
|
}
|
|
1406
971
|
var profileNamePattern = /^[a-z0-9][a-z0-9._-]{0,63}$/i;
|
|
1407
972
|
function profilePath(baseDir, name) {
|
|
1408
|
-
return profileNamePattern.test(name) ? Effect2.succeed(
|
|
973
|
+
return profileNamePattern.test(name) ? Effect2.succeed(path.join(baseDir, `${name}.json`)) : Effect2.fail(new AuthProfileError({ message: `Invalid auth profile name: ${name}`, operation: "path", reason: "invalid-name" }));
|
|
1409
974
|
}
|
|
1410
975
|
function sameSlots(left, right) {
|
|
1411
976
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
@@ -1438,7 +1003,7 @@ function redactOutput(text, slots, maxBytes) {
|
|
|
1438
1003
|
}
|
|
1439
1004
|
function runChild(options) {
|
|
1440
1005
|
return Effect2.callback((resume) => {
|
|
1441
|
-
const child =
|
|
1006
|
+
const child = spawn(options.command, [...options.args], {
|
|
1442
1007
|
...options.cwd ? { cwd: options.cwd } : {},
|
|
1443
1008
|
env: childEnvironment(options.env),
|
|
1444
1009
|
detached: process.platform !== "win32",
|
|
@@ -1511,7 +1076,7 @@ function childEnvironment(profile) {
|
|
|
1511
1076
|
|
|
1512
1077
|
// src/auth/domain-policy.ts
|
|
1513
1078
|
import dns from "node:dns/promises";
|
|
1514
|
-
import
|
|
1079
|
+
import net from "node:net";
|
|
1515
1080
|
|
|
1516
1081
|
class OriginPatternError extends Error {
|
|
1517
1082
|
name = "OriginPatternError";
|
|
@@ -1547,7 +1112,7 @@ function parseOriginPattern(raw) {
|
|
|
1547
1112
|
throw new OriginPatternError(`Origin pattern ${JSON.stringify(raw)} must be a host or origin`);
|
|
1548
1113
|
}
|
|
1549
1114
|
const host = unbracket(parsed.hostname.toLowerCase());
|
|
1550
|
-
if (wildcard &&
|
|
1115
|
+
if (wildcard && net.isIP(host))
|
|
1551
1116
|
throw new OriginPatternError(`Origin pattern ${JSON.stringify(raw)}: wildcards don't apply to IP addresses`);
|
|
1552
1117
|
if (wildcard && !host.includes("."))
|
|
1553
1118
|
throw new OriginPatternError(`Origin pattern ${JSON.stringify(raw)}: "*." needs a domain with a dot, like *.example.com`);
|
|
@@ -1592,14 +1157,14 @@ var privateIpv4Ranges = [
|
|
|
1592
1157
|
];
|
|
1593
1158
|
function isPrivateAddress(address) {
|
|
1594
1159
|
const ip = unbracket(address.toLowerCase()).replace(/%.*$/, "");
|
|
1595
|
-
if (
|
|
1160
|
+
if (net.isIPv4(ip)) {
|
|
1596
1161
|
const value = ipv4ToNumber(ip);
|
|
1597
1162
|
return privateIpv4Ranges.some(([base, bits]) => {
|
|
1598
1163
|
const mask = bits === 0 ? 0 : 4294967295 << 32 - bits >>> 0;
|
|
1599
1164
|
return (value & mask) >>> 0 === (ipv4ToNumber(base) & mask) >>> 0;
|
|
1600
1165
|
});
|
|
1601
1166
|
}
|
|
1602
|
-
if (
|
|
1167
|
+
if (net.isIPv6(ip)) {
|
|
1603
1168
|
if (ip === "::" || ip === "::1")
|
|
1604
1169
|
return true;
|
|
1605
1170
|
const mapped = /^(?:0*:)*:?ffff:(\d+\.\d+\.\d+\.\d+)$/.exec(ip) ?? /^::(\d+\.\d+\.\d+\.\d+)$/.exec(ip);
|
|
@@ -1625,7 +1190,7 @@ function isLocalhostName(host) {
|
|
|
1625
1190
|
}
|
|
1626
1191
|
function isPrivateHost(host) {
|
|
1627
1192
|
const bare = unbracket(host.toLowerCase());
|
|
1628
|
-
return isLocalhostName(bare) ||
|
|
1193
|
+
return isLocalhostName(bare) || net.isIP(bare) !== 0 && isPrivateAddress(bare);
|
|
1629
1194
|
}
|
|
1630
1195
|
function defaultPort(protocol) {
|
|
1631
1196
|
return protocol === "https:" ? "443" : "80";
|
|
@@ -1676,7 +1241,7 @@ function checkUrl(rawUrl, rules, options = {}) {
|
|
|
1676
1241
|
}
|
|
1677
1242
|
async function resolvesToPrivateAddress(host, timeoutMs = 2000) {
|
|
1678
1243
|
const bare = unbracket(host);
|
|
1679
|
-
if (
|
|
1244
|
+
if (net.isIP(bare) || isLocalhostName(bare))
|
|
1680
1245
|
return isPrivateHost(bare) ? bare : undefined;
|
|
1681
1246
|
let timer;
|
|
1682
1247
|
try {
|
|
@@ -1722,9 +1287,9 @@ class SiteSecretError extends Schema2.TaggedError()("SiteSecret.Error", {
|
|
|
1722
1287
|
cause: Schema2.optionalKey(Schema2.Defect())
|
|
1723
1288
|
}) {
|
|
1724
1289
|
}
|
|
1725
|
-
var defaultSiteSecretsDir = () =>
|
|
1290
|
+
var defaultSiteSecretsDir = () => path2.join(dataRoot(), "site-secrets");
|
|
1726
1291
|
function secretPath(baseDir, name) {
|
|
1727
|
-
return profileNamePattern.test(name) ? Effect3.succeed(
|
|
1292
|
+
return profileNamePattern.test(name) ? Effect3.succeed(path2.join(baseDir, `${name}.json`)) : Effect3.fail(new SiteSecretError({ message: `Invalid secret name: ${name} (letters, digits, ".", "_" and "-", up to 64)`, reason: "invalid-name" }));
|
|
1728
1293
|
}
|
|
1729
1294
|
function summary2(secret) {
|
|
1730
1295
|
return { name: secret.name, kind: secret.kind, allowedOrigins: [...secret.allowedOrigins], createdAt: secret.createdAt, updatedAt: secret.updatedAt };
|
|
@@ -1732,7 +1297,7 @@ function summary2(secret) {
|
|
|
1732
1297
|
var readSecret = Effect3.fn("SiteSecrets.read")(function* (name, options = {}) {
|
|
1733
1298
|
const filePath = yield* secretPath(options.baseDir ?? defaultSiteSecretsDir(), name);
|
|
1734
1299
|
const text = yield* Effect3.tryPromise({
|
|
1735
|
-
try: () =>
|
|
1300
|
+
try: () => fs2.readFile(filePath, "utf8"),
|
|
1736
1301
|
catch: (cause) => isNodeError(cause) && cause.code === "ENOENT" ? new SiteSecretError({ message: `Secret not found: ${name}. Ask the user to add it with \`opencode-browser secrets add ${name} --origin <origin>\`.`, reason: "not-found" }) : new SiteSecretError({ message: `Could not read secret ${name}`, reason: "read-failed", cause })
|
|
1737
1302
|
});
|
|
1738
1303
|
return yield* Effect3.try({
|
|
@@ -1774,7 +1339,7 @@ var addSecret = Effect3.fn("SiteSecrets.add")(function* (options) {
|
|
|
1774
1339
|
var listSecrets = Effect3.fn("SiteSecrets.list")(function* (options = {}) {
|
|
1775
1340
|
const baseDir = options.baseDir ?? defaultSiteSecretsDir();
|
|
1776
1341
|
const names = yield* Effect3.tryPromise({
|
|
1777
|
-
try: () =>
|
|
1342
|
+
try: () => fs2.readdir(baseDir).catch((cause) => isNodeError(cause) && cause.code === "ENOENT" ? [] : Promise.reject(cause)),
|
|
1778
1343
|
catch: (cause) => new SiteSecretError({ message: "Could not list secrets", reason: "read-failed", cause })
|
|
1779
1344
|
});
|
|
1780
1345
|
const secrets = [];
|
|
@@ -1789,7 +1354,7 @@ var removeSecret = Effect3.fn("SiteSecrets.remove")(function* (name, options = {
|
|
|
1789
1354
|
const baseDir = options.baseDir ?? defaultSiteSecretsDir();
|
|
1790
1355
|
const filePath = yield* secretPath(baseDir, name);
|
|
1791
1356
|
return yield* withLock(name, { baseDir }, Effect3.tryPromise({
|
|
1792
|
-
try: () =>
|
|
1357
|
+
try: () => fs2.rm(filePath).then(() => true, (cause) => isNodeError(cause) && cause.code === "ENOENT" ? false : Promise.reject(cause)),
|
|
1793
1358
|
catch: (cause) => new SiteSecretError({ message: `Could not remove secret ${name}`, reason: "write-failed", cause })
|
|
1794
1359
|
})).pipe(Effect3.mapError((error) => error instanceof SiteSecretError ? error : new SiteSecretError({ message: error.message, reason: "write-failed", cause: error })));
|
|
1795
1360
|
});
|
|
@@ -1831,7 +1396,7 @@ function totpCode(seed, now = Date.now()) {
|
|
|
1831
1396
|
const { key, digits, period, algorithm } = totpParameters(seed);
|
|
1832
1397
|
const counter = Buffer.alloc(8);
|
|
1833
1398
|
counter.writeBigUInt64BE(BigInt(Math.floor(now / 1000 / period)));
|
|
1834
|
-
const hmac =
|
|
1399
|
+
const hmac = crypto.createHmac(algorithm, key).update(counter).digest();
|
|
1835
1400
|
const offset = hmac[hmac.length - 1] & 15;
|
|
1836
1401
|
const binary = (hmac.readUInt32BE(offset) & 2147483647) % 10 ** digits;
|
|
1837
1402
|
return String(binary).padStart(digits, "0");
|
|
@@ -1840,4 +1405,4 @@ function secretText(secret) {
|
|
|
1840
1405
|
return secret.kind === "totp" ? totpCode(secret.value) : secret.value;
|
|
1841
1406
|
}
|
|
1842
1407
|
|
|
1843
|
-
export { settingKeys, settingSpecs, securityVariables, SettingsInputError, parseSettingChanges, settingsFromExtension, settingsToExtension, describeSettings, describeChanges, formatSettings, browsersNote2, mcpUpdateNote2, objectSchema, emptyInputSchema, sessionSchemaProperty, sessionAliasSchemaProperty, sessionOnlyInputSchema, ensureSessionExists, parseExecuteArguments, parseAdoptArguments, requiredStringField, optionalStringField, optionalBooleanField, optionalPositiveIntegerField, optionalStringArrayField, requireObject, toolResultForValue2, mcpErrorMessage2, toolResult,
|
|
1408
|
+
export { settingKeys, settingSpecs, securityVariables, SettingsInputError, parseSettingChanges, settingsFromExtension, settingsToExtension, describeSettings, describeChanges, formatSettings, browsersNote2, mcpUpdateNote2, objectSchema, emptyInputSchema, sessionSchemaProperty, sessionAliasSchemaProperty, sessionOnlyInputSchema, ensureSessionExists, parseExecuteArguments, parseAdoptArguments, requiredStringField, optionalStringField, optionalBooleanField, optionalPositiveIntegerField, optionalStringArrayField, requireObject, toolResultForValue2, mcpErrorMessage2, toolResult, terminateChildProcess, SecretCollector, looksLikeTokenSegment, AuthProfileError, read, readOptional, withLock, write, status, run, OriginPatternError, parseOriginPatterns, normalizeOriginPatterns, isPrivateAddress, explicitlyAllowsHost, checkUrl, checkNavigationUrl, readSecret, addSecret, listSecrets, removeSecret, secretText };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isNodeError
|
|
3
|
-
} from "./main-
|
|
3
|
+
} from "./main-yv64m9we.mjs";
|
|
4
4
|
import {
|
|
5
5
|
isValidSessionId2
|
|
6
|
-
} from "./main-
|
|
6
|
+
} from "./main-605j7tjk.mjs";
|
|
7
7
|
import {
|
|
8
8
|
dataRoot
|
|
9
|
-
} from "./main-
|
|
9
|
+
} from "./main-3cza6vx1.mjs";
|
|
10
10
|
|
|
11
11
|
// src/session-manager/journal.ts
|
|
12
12
|
import fs from "node:fs";
|