openmausbot 0.1.68 → 0.1.70
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/assets/index-B2F__IRS.css +1 -0
- package/dist/assets/index-CLj3t5Ba.js +280 -0
- package/dist/assets/{index-HqooKFTS.js → index-D1RGhLUK.js} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/container-mcp.js +40 -2
- package/dist-server/drivers/agents-proxy.js +188 -5
- package/dist-server/index.js +2431 -984
- package/dist-server/local-computer-proxy.js +2 -0
- package/dist-server/openmausbot.js +923 -334
- package/dist-server/pair-cli.js +923 -334
- package/dist-server/prepare-cloudflared.js +20 -3
- package/dist-server/server/avatar-image.js +86 -34
- package/dist-server/server/bot-package.js +60 -14
- package/dist-server/server/config.js +23 -2
- package/dist-server/server/delegations.js +132 -74
- package/dist-server/server/drivers/acp/qwen.js +142 -5
- package/dist-server/server/drivers/agents-proxy.js +224 -4
- package/dist-server/server/drivers/claude-login-auth.js +102 -9
- package/dist-server/server/drivers/claude.js +11 -5
- package/dist-server/server/drivers/codex-device-auth.js +102 -3
- package/dist-server/server/drivers/codex-identity.js +115 -0
- package/dist-server/server/drivers/codex.js +6 -0
- package/dist-server/server/engine-install.js +137 -0
- package/dist-server/server/env-path.js +12 -0
- package/dist-server/server/harness/registry.js +33 -6
- package/dist-server/server/index.js +365 -26
- package/dist-server/server/package-export.js +7 -0
- package/dist-server/server/peer-provenance.js +6 -2
- package/dist-server/server/provider-auth-sessions.js +24 -0
- package/dist-server/server/routine-requests.js +270 -25
- package/dist-server/server/routines.js +297 -69
- package/dist-server/server/steer-queue.js +48 -1
- package/dist-server/server/store.js +22 -4
- package/dist-server/server/system-prompt.js +1 -0
- package/dist-server/server/team-backup.js +18 -4
- package/dist-server/shared/image-generation.js +28 -0
- package/dist-server/shared/team-backup.js +1 -0
- package/dist-server/vps-container-mcp.js +40 -2
- package/package.json +1 -1
- package/dist/assets/index-CbaejjQA.js +0 -278
- package/dist/assets/index-aJ5EWZOQ.css +0 -1
|
@@ -2298,7 +2298,7 @@ function displayText(value, multiline = false) {
|
|
|
2298
2298
|
}
|
|
2299
2299
|
function plainText(question, hidden, context) {
|
|
2300
2300
|
const { input, output, signal } = context;
|
|
2301
|
-
return new Promise((
|
|
2301
|
+
return new Promise((resolve13, reject) => {
|
|
2302
2302
|
input.setRawMode?.(hidden);
|
|
2303
2303
|
const rl = createInterface({ input, terminal: hidden });
|
|
2304
2304
|
let finished = false;
|
|
@@ -2309,7 +2309,7 @@ function plainText(question, hidden, context) {
|
|
|
2309
2309
|
rl.close();
|
|
2310
2310
|
output.write("\n");
|
|
2311
2311
|
if (error51) reject(error51);
|
|
2312
|
-
else
|
|
2312
|
+
else resolve13(answer ?? "");
|
|
2313
2313
|
};
|
|
2314
2314
|
const cancel = () => finish(void 0, signal.reason ?? new SetupCancelled());
|
|
2315
2315
|
signal.addEventListener("abort", cancel, { once: true });
|
|
@@ -17526,6 +17526,30 @@ var init_zod = __esm({
|
|
|
17526
17526
|
}
|
|
17527
17527
|
});
|
|
17528
17528
|
|
|
17529
|
+
// shared/image-generation.ts
|
|
17530
|
+
function normalizeImageGenerationUrl(value) {
|
|
17531
|
+
const message2 = "Use an HTTPS API base URL, or HTTP for a local router, without passwords, query parameters or fragments";
|
|
17532
|
+
let url2;
|
|
17533
|
+
try {
|
|
17534
|
+
url2 = new URL(value.trim());
|
|
17535
|
+
} catch {
|
|
17536
|
+
throw new Error(message2);
|
|
17537
|
+
}
|
|
17538
|
+
if (value.length > 2048 || url2.username || url2.password || url2.search || url2.hash) throw new Error(message2);
|
|
17539
|
+
const host = url2.hostname.toLowerCase();
|
|
17540
|
+
const ipv43 = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(host);
|
|
17541
|
+
const local = host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local") || host === "host.docker.internal" || host === "host.containers.internal" || host === "[::1]" || /^\[f[cd][0-9a-f]{2}:/.test(host) || ipv43 && (Number(ipv43[1]) === 127 || Number(ipv43[1]) === 10 || Number(ipv43[1]) === 192 && Number(ipv43[2]) === 168 || Number(ipv43[1]) === 172 && Number(ipv43[2]) >= 16 && Number(ipv43[2]) <= 31);
|
|
17542
|
+
if (url2.protocol !== "https:" && !(url2.protocol === "http:" && local)) throw new Error(message2);
|
|
17543
|
+
if (ipv43 && (Number(ipv43[1]) === 0 || Number(ipv43[1]) === 169 && Number(ipv43[2]) === 254)) throw new Error(message2);
|
|
17544
|
+
url2.pathname = url2.pathname.replace(/\/+$/, "").replace(/\/images\/generations$/, "");
|
|
17545
|
+
return url2.toString().replace(/\/+$/, "");
|
|
17546
|
+
}
|
|
17547
|
+
var init_image_generation = __esm({
|
|
17548
|
+
"shared/image-generation.ts"() {
|
|
17549
|
+
"use strict";
|
|
17550
|
+
}
|
|
17551
|
+
});
|
|
17552
|
+
|
|
17529
17553
|
// server/contracts.ts
|
|
17530
17554
|
var EFFORT_LEVELS, eventCounter, newEventId, newId;
|
|
17531
17555
|
var init_contracts = __esm({
|
|
@@ -17732,6 +17756,7 @@ function loadConfig() {
|
|
|
17732
17756
|
if (process.env.OMB_TTS_KEY !== void 0) cfg.tts.key = process.env.OMB_TTS_KEY;
|
|
17733
17757
|
cfg.imageGen = { ...cfg.imageGen };
|
|
17734
17758
|
if (process.env.OMB_OPENAI_IMAGE_KEY !== void 0) cfg.imageGen.key = process.env.OMB_OPENAI_IMAGE_KEY;
|
|
17759
|
+
if (process.env.OMB_CUSTOM_IMAGE_KEY !== void 0) cfg.imageGen.customApiKey = process.env.OMB_CUSTOM_IMAGE_KEY;
|
|
17735
17760
|
const splitEmails = (value) => value.split(/[,\s]+/).map((entry) => entry.trim().toLowerCase()).filter(Boolean);
|
|
17736
17761
|
if (process.env.OMB_SIGNIN_EMAILS !== void 0 || process.env.OMB_SIGNIN_MEMBER_EMAILS !== void 0) {
|
|
17737
17762
|
cfg.signIn = { ...cfg.signIn };
|
|
@@ -17880,6 +17905,7 @@ var init_config = __esm({
|
|
|
17880
17905
|
"server/config.ts"() {
|
|
17881
17906
|
"use strict";
|
|
17882
17907
|
init_zod();
|
|
17908
|
+
init_image_generation();
|
|
17883
17909
|
init_atomic();
|
|
17884
17910
|
init_contracts();
|
|
17885
17911
|
init_mcp_registry();
|
|
@@ -17988,8 +18014,25 @@ var init_config = __esm({
|
|
|
17988
18014
|
* engine: "elevenlabs" (default; needs a key) or "system" (the Mac's
|
|
17989
18015
|
* built-in voices, no key). */
|
|
17990
18016
|
tts: external_exports.object({ key: optionalText, voice: optionalText, provider: external_exports.enum(["elevenlabs", "system"]).optional() }).optional(),
|
|
17991
|
-
/**
|
|
17992
|
-
imageGen: external_exports.object({
|
|
18017
|
+
/** Avatar provider credentials stay separate; choosing a router never reuses a cloud key. */
|
|
18018
|
+
imageGen: external_exports.object({
|
|
18019
|
+
provider: external_exports.enum(["openai", "xai", "custom"]).optional(),
|
|
18020
|
+
key: optionalText,
|
|
18021
|
+
customApiKey: optionalText,
|
|
18022
|
+
customUrl: external_exports.string().trim().max(2048).transform((value, ctx) => {
|
|
18023
|
+
if (!value) return "";
|
|
18024
|
+
try {
|
|
18025
|
+
return normalizeImageGenerationUrl(value);
|
|
18026
|
+
} catch (error51) {
|
|
18027
|
+
ctx.addIssue({ code: "custom", message: error51.message });
|
|
18028
|
+
return external_exports.NEVER;
|
|
18029
|
+
}
|
|
18030
|
+
}).optional(),
|
|
18031
|
+
customModel: external_exports.string().trim().max(200).refine(
|
|
18032
|
+
(value) => !["\r", "\n", "\0"].some((character) => value.includes(character)),
|
|
18033
|
+
"Use a model ID without control characters"
|
|
18034
|
+
).optional()
|
|
18035
|
+
}).optional(),
|
|
17993
18036
|
/** Non-secret profile details shown in the sidebar. */
|
|
17994
18037
|
profile: external_exports.object({ name: optionalText, email: optionalText }).optional(),
|
|
17995
18038
|
/** UI language override (BCP-47, lowercase). Empty/absent = follow the
|
|
@@ -18024,6 +18067,7 @@ var init_config = __esm({
|
|
|
18024
18067
|
"OPENCODE_API_KEY",
|
|
18025
18068
|
"OMB_TTS_KEY",
|
|
18026
18069
|
"OMB_OPENAI_IMAGE_KEY",
|
|
18070
|
+
"OMB_CUSTOM_IMAGE_KEY",
|
|
18027
18071
|
"COMPOSIO_API_KEY",
|
|
18028
18072
|
"OMB_COMPOSIO_BROKER_TOKEN",
|
|
18029
18073
|
// Harness-private filesystem hints are not credentials themselves, but
|
|
@@ -18431,6 +18475,11 @@ function windowsKnownDirs() {
|
|
|
18431
18475
|
join7(home, "go", "bin")
|
|
18432
18476
|
];
|
|
18433
18477
|
}
|
|
18478
|
+
function registerPathDir(dir) {
|
|
18479
|
+
if (registeredDirs.includes(dir)) return;
|
|
18480
|
+
registeredDirs.unshift(dir);
|
|
18481
|
+
resetPathCache();
|
|
18482
|
+
}
|
|
18434
18483
|
function resetPathCache() {
|
|
18435
18484
|
cached2 = null;
|
|
18436
18485
|
probed = false;
|
|
@@ -18438,6 +18487,7 @@ function resetPathCache() {
|
|
|
18438
18487
|
function augmentedPath() {
|
|
18439
18488
|
if (cached2 === null) {
|
|
18440
18489
|
cached2 = mergePaths([
|
|
18490
|
+
...registeredDirs.filter((d) => existsSync5(d)),
|
|
18441
18491
|
...process.env.OMB_EXTRA_PATH ? process.env.OMB_EXTRA_PATH.split(delimiter3) : [],
|
|
18442
18492
|
...process.env.PATH ? process.env.PATH.split(delimiter3) : [],
|
|
18443
18493
|
// Keep the last successful login-shell result while a rescan starts a
|
|
@@ -18602,13 +18652,14 @@ function resolveCliSpawn(cli, args) {
|
|
|
18602
18652
|
}
|
|
18603
18653
|
return resolveWord(cli, args);
|
|
18604
18654
|
}
|
|
18605
|
-
var cached2, probed, loginShellPath;
|
|
18655
|
+
var cached2, probed, loginShellPath, registeredDirs;
|
|
18606
18656
|
var init_env_path = __esm({
|
|
18607
18657
|
"server/env-path.ts"() {
|
|
18608
18658
|
"use strict";
|
|
18609
18659
|
cached2 = null;
|
|
18610
18660
|
probed = false;
|
|
18611
18661
|
loginShellPath = null;
|
|
18662
|
+
registeredDirs = [];
|
|
18612
18663
|
}
|
|
18613
18664
|
});
|
|
18614
18665
|
|
|
@@ -18679,12 +18730,12 @@ function describeSpawnFailure(err, cli) {
|
|
|
18679
18730
|
function killCliTree(child, timeoutMs = 5e3) {
|
|
18680
18731
|
const pid = child.pid;
|
|
18681
18732
|
if (!pid || child.exitCode !== null || child.signalCode !== null) return Promise.resolve(true);
|
|
18682
|
-
return new Promise((
|
|
18733
|
+
return new Promise((resolve13) => {
|
|
18683
18734
|
let timer;
|
|
18684
18735
|
const done = (stopped) => {
|
|
18685
18736
|
clearTimeout(timer);
|
|
18686
18737
|
child.off("close", closed);
|
|
18687
|
-
|
|
18738
|
+
resolve13(stopped);
|
|
18688
18739
|
};
|
|
18689
18740
|
const closed = () => done(true);
|
|
18690
18741
|
child.once("close", closed);
|
|
@@ -18722,7 +18773,124 @@ var init_procs = __esm({
|
|
|
18722
18773
|
}
|
|
18723
18774
|
});
|
|
18724
18775
|
|
|
18776
|
+
// server/engine-install.ts
|
|
18777
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync6 } from "node:fs";
|
|
18778
|
+
import { join as join9 } from "node:path";
|
|
18779
|
+
import { stripVTControlCharacters as stripVTControlCharacters3 } from "node:util";
|
|
18780
|
+
function enginesPrefix(baseDir = DATA_DIR) {
|
|
18781
|
+
return join9(baseDir, "tools", "npm");
|
|
18782
|
+
}
|
|
18783
|
+
function enginesBinDir(baseDir = DATA_DIR, platform = process.platform) {
|
|
18784
|
+
return platform === "win32" ? enginesPrefix(baseDir) : join9(enginesPrefix(baseDir), "bin");
|
|
18785
|
+
}
|
|
18786
|
+
function npmPackageOf(install) {
|
|
18787
|
+
const line = install?.command?.linux ?? install?.command?.darwin ?? install?.command?.win32;
|
|
18788
|
+
const match = line ? /^npm install -g ((?:@[\w.-]+\/)?[\w.-]+)$/.exec(line.trim()) : null;
|
|
18789
|
+
return match ? match[1] : null;
|
|
18790
|
+
}
|
|
18791
|
+
function npmAvailable() {
|
|
18792
|
+
return findCliCandidates("npm").length > 0;
|
|
18793
|
+
}
|
|
18794
|
+
function serverInstallFor(install, npmPresent = npmAvailable()) {
|
|
18795
|
+
if (!install || install.managed) return null;
|
|
18796
|
+
const pkg = npmPackageOf(install);
|
|
18797
|
+
return pkg && npmPresent ? { package: pkg } : null;
|
|
18798
|
+
}
|
|
18799
|
+
function installNpmEngine(pkg, options = {}) {
|
|
18800
|
+
const key = `${options.baseDir ?? DATA_DIR} ${pkg}`;
|
|
18801
|
+
const existing = running.get(key);
|
|
18802
|
+
if (existing) return existing;
|
|
18803
|
+
const run3 = installOnce(pkg, options).finally(() => running.delete(key));
|
|
18804
|
+
running.set(key, run3);
|
|
18805
|
+
return run3;
|
|
18806
|
+
}
|
|
18807
|
+
async function installOnce(pkg, options) {
|
|
18808
|
+
const prefix = enginesPrefix(options.baseDir);
|
|
18809
|
+
mkdirSync6(prefix, { recursive: true });
|
|
18810
|
+
const env = {
|
|
18811
|
+
...options.env ?? process.env,
|
|
18812
|
+
PATH: options.path ?? augmentedPath(),
|
|
18813
|
+
NO_COLOR: "1",
|
|
18814
|
+
npm_config_update_notifier: "false",
|
|
18815
|
+
npm_config_fund: "false",
|
|
18816
|
+
npm_config_audit: "false"
|
|
18817
|
+
};
|
|
18818
|
+
stripWorkspaceCredentialEnv(env);
|
|
18819
|
+
const args = ["install", "-g", "--prefix", prefix, "--loglevel=error", `--allow-scripts=${pkg}`, `${pkg}@latest`];
|
|
18820
|
+
const result = await runNpm(args, env, prefix, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
18821
|
+
if (result.code !== 0) {
|
|
18822
|
+
throw new Error(`npm could not install ${pkg} on this server.${tail(result.output)}`);
|
|
18823
|
+
}
|
|
18824
|
+
registerPathDir(enginesBinDir(options.baseDir));
|
|
18825
|
+
resetPathCache();
|
|
18826
|
+
if (options.cli) {
|
|
18827
|
+
const binDir = enginesBinDir(options.baseDir);
|
|
18828
|
+
if (!findCliCandidates(options.cli).some((path3) => path3.startsWith(binDir))) {
|
|
18829
|
+
throw new Error(`${pkg} installed, but it did not provide a \`${options.cli}\` command. Check the package name in this engine's install descriptor.`);
|
|
18830
|
+
}
|
|
18831
|
+
}
|
|
18832
|
+
}
|
|
18833
|
+
function tail(output) {
|
|
18834
|
+
const clean = stripVTControlCharacters3(output).trim();
|
|
18835
|
+
if (!clean) return "";
|
|
18836
|
+
const lines = clean.split(/\r?\n/).filter((line) => line.trim()).slice(-6);
|
|
18837
|
+
return `
|
|
18838
|
+
${lines.join("\n").slice(-600)}`;
|
|
18839
|
+
}
|
|
18840
|
+
function runNpm(args, env, cwd, timeoutMs) {
|
|
18841
|
+
return new Promise((resolveRun, rejectRun) => {
|
|
18842
|
+
let child;
|
|
18843
|
+
try {
|
|
18844
|
+
child = spawnCli("npm", args, { env, cwd, stdio: ["pipe", "pipe", "pipe"] });
|
|
18845
|
+
} catch {
|
|
18846
|
+
rejectRun(new Error("npm could not start on this server. Install Node.js with npm for the user running OpenMausBot, then try again."));
|
|
18847
|
+
return;
|
|
18848
|
+
}
|
|
18849
|
+
child.stdin.end();
|
|
18850
|
+
let output = "";
|
|
18851
|
+
const receive = (chunk) => {
|
|
18852
|
+
if (output.length < MAX_OUTPUT) output += chunk.toString("utf8").slice(0, MAX_OUTPUT - output.length);
|
|
18853
|
+
};
|
|
18854
|
+
child.stdout.on("data", receive);
|
|
18855
|
+
child.stderr.on("data", receive);
|
|
18856
|
+
let timedOut = false;
|
|
18857
|
+
const timer = setTimeout(() => {
|
|
18858
|
+
timedOut = true;
|
|
18859
|
+
void killCliTree(child);
|
|
18860
|
+
}, timeoutMs);
|
|
18861
|
+
timer.unref();
|
|
18862
|
+
child.once("error", (error51) => {
|
|
18863
|
+
clearTimeout(timer);
|
|
18864
|
+
rejectRun(new Error(error51.code === "ENOENT" ? "npm is not installed on this server. Install Node.js with npm for the user running OpenMausBot, then try again." : "npm could not start on this server. Check that Node.js is installed for the user running OpenMausBot."));
|
|
18865
|
+
});
|
|
18866
|
+
child.once("close", (code) => {
|
|
18867
|
+
clearTimeout(timer);
|
|
18868
|
+
if (timedOut) {
|
|
18869
|
+
rejectRun(new Error("The install took too long and was stopped. Check the server's network connection and try again."));
|
|
18870
|
+
return;
|
|
18871
|
+
}
|
|
18872
|
+
resolveRun({ code, output });
|
|
18873
|
+
});
|
|
18874
|
+
});
|
|
18875
|
+
}
|
|
18876
|
+
var MAX_OUTPUT, DEFAULT_TIMEOUT_MS, running;
|
|
18877
|
+
var init_engine_install = __esm({
|
|
18878
|
+
"server/engine-install.ts"() {
|
|
18879
|
+
"use strict";
|
|
18880
|
+
init_config();
|
|
18881
|
+
init_env_path();
|
|
18882
|
+
init_procs();
|
|
18883
|
+
MAX_OUTPUT = 64 * 1024;
|
|
18884
|
+
DEFAULT_TIMEOUT_MS = 10 * 6e4;
|
|
18885
|
+
running = /* @__PURE__ */ new Map();
|
|
18886
|
+
}
|
|
18887
|
+
});
|
|
18888
|
+
|
|
18725
18889
|
// server/harness/registry.ts
|
|
18890
|
+
function withServerInstall(install, npmPresent) {
|
|
18891
|
+
const server = install ? serverInstallFor(install, npmPresent) : null;
|
|
18892
|
+
return server ? { ...install, server } : install;
|
|
18893
|
+
}
|
|
18726
18894
|
function cliDefaultOf(driver) {
|
|
18727
18895
|
if (!driver) return void 0;
|
|
18728
18896
|
try {
|
|
@@ -18741,13 +18909,21 @@ var init_registry = __esm({
|
|
|
18741
18909
|
"server/harness/registry.ts"() {
|
|
18742
18910
|
"use strict";
|
|
18743
18911
|
init_env_path();
|
|
18912
|
+
init_engine_install();
|
|
18744
18913
|
ProviderRegistry = class {
|
|
18745
18914
|
byId = /* @__PURE__ */ new Map();
|
|
18746
18915
|
/** decoded per-instance `cli` overrides, for describe() — drivers spawn
|
|
18747
18916
|
* from their own config; this map only reports what was configured */
|
|
18748
18917
|
cliByInstance = /* @__PURE__ */ new Map();
|
|
18749
18918
|
driversByKind;
|
|
18750
|
-
|
|
18919
|
+
/** Where Settings-driven npm installs go; the data directory by default. */
|
|
18920
|
+
enginesBaseDir;
|
|
18921
|
+
/** Whether npm is on this machine; injectable because the PATH scan also
|
|
18922
|
+
* looks in standard install locations, which tests cannot empty. */
|
|
18923
|
+
npmPresent;
|
|
18924
|
+
constructor(drivers, options = {}) {
|
|
18925
|
+
this.enginesBaseDir = options.enginesBaseDir;
|
|
18926
|
+
this.npmPresent = options.npmAvailable ?? npmAvailable;
|
|
18751
18927
|
this.driversByKind = new Map(drivers.map((d) => [d.driverKind, d]));
|
|
18752
18928
|
}
|
|
18753
18929
|
async load(configs) {
|
|
@@ -18822,10 +18998,20 @@ var init_registry = __esm({
|
|
|
18822
18998
|
await instance.refreshModels?.();
|
|
18823
18999
|
return true;
|
|
18824
19000
|
}
|
|
19001
|
+
/** A driver's own installer (a managed download) first; otherwise the
|
|
19002
|
+
* app's npm prefix, when the driver's install one-liner is an npm package
|
|
19003
|
+
* and npm is on PATH. False means Settings has nothing to offer here. */
|
|
18825
19004
|
async installRuntime(instanceId) {
|
|
18826
|
-
const
|
|
18827
|
-
if (!
|
|
18828
|
-
|
|
19005
|
+
const entry = this.byId.get(instanceId);
|
|
19006
|
+
if (!entry) return false;
|
|
19007
|
+
if (entry.live?.installRuntime) {
|
|
19008
|
+
await entry.live.installRuntime();
|
|
19009
|
+
return true;
|
|
19010
|
+
}
|
|
19011
|
+
const driver = this.driversByKind.get(entry.shadow?.driverKind ?? entry.live.driverKind);
|
|
19012
|
+
const server = serverInstallFor(driver?.install, this.npmPresent());
|
|
19013
|
+
if (!server) return false;
|
|
19014
|
+
await installNpmEngine(server.package, { baseDir: this.enginesBaseDir, cli: cliDefaultOf(driver) });
|
|
18829
19015
|
return true;
|
|
18830
19016
|
}
|
|
18831
19017
|
async startAuthentication(instanceId) {
|
|
@@ -18860,6 +19046,7 @@ var init_registry = __esm({
|
|
|
18860
19046
|
candidatesByName.set(name, found);
|
|
18861
19047
|
return found;
|
|
18862
19048
|
};
|
|
19049
|
+
const npmPresent = this.npmPresent();
|
|
18863
19050
|
return Promise.all(
|
|
18864
19051
|
this.entries().map(async (entry) => {
|
|
18865
19052
|
const driver = this.driversByKind.get(entry.shadow?.driverKind ?? entry.live.driverKind);
|
|
@@ -18873,7 +19060,7 @@ var init_registry = __esm({
|
|
|
18873
19060
|
capabilities: { computerMcp: false, agentsMcp: false, localComputerMcp: false },
|
|
18874
19061
|
// an unknown driver has no driver record, hence no install path
|
|
18875
19062
|
access: driver?.metadata.access ?? "subscription",
|
|
18876
|
-
install: driver?.install,
|
|
19063
|
+
install: withServerInstall(driver?.install, npmPresent),
|
|
18877
19064
|
cli: entry.shadow.cli,
|
|
18878
19065
|
cliDefault: cliDefaultOf(driver),
|
|
18879
19066
|
// a shadow is exactly the "your CLI is broken, pick another"
|
|
@@ -18907,10 +19094,12 @@ var init_registry = __esm({
|
|
|
18907
19094
|
approvalReview: inst.reviewPermission !== void 0
|
|
18908
19095
|
},
|
|
18909
19096
|
access: driver?.metadata.access ?? "subscription",
|
|
18910
|
-
install: driver?.install,
|
|
19097
|
+
install: withServerInstall(driver?.install, npmPresent),
|
|
18911
19098
|
authentication: inst.startAuthentication ? {
|
|
18912
|
-
method: inst.getAuthentication && inst.completeAuthentication ? "paste-code" : inst.getAuthentication ? "device-code" : "browser"
|
|
19099
|
+
method: inst.getAuthentication && inst.completeAuthentication ? "paste-code" : inst.getAuthentication ? "device-code" : "browser",
|
|
18913
19100
|
// a link and a callback URL (managed engines)
|
|
19101
|
+
// the browser may remove the stored sign-in to switch accounts
|
|
19102
|
+
signOut: inst.signOut !== void 0
|
|
18914
19103
|
} : void 0,
|
|
18915
19104
|
cli: this.cliByInstance.get(inst.instanceId),
|
|
18916
19105
|
cliDefault: cliDefaultOf(driver),
|
|
@@ -18940,7 +19129,7 @@ var init_registry = __esm({
|
|
|
18940
19129
|
// server/drivers/local-inject.ts
|
|
18941
19130
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
18942
19131
|
import { homedir as homedir6 } from "node:os";
|
|
18943
|
-
import { join as
|
|
19132
|
+
import { join as join10 } from "node:path";
|
|
18944
19133
|
function contextWindowsFromPs(extra) {
|
|
18945
19134
|
const out = /* @__PURE__ */ new Map();
|
|
18946
19135
|
const rec = extra && typeof extra === "object" ? extra : null;
|
|
@@ -19025,7 +19214,7 @@ function firstUnslothToken(row) {
|
|
|
19025
19214
|
function readUnslothKey(env) {
|
|
19026
19215
|
const home = env.HOME || env.USERPROFILE || homedir6();
|
|
19027
19216
|
try {
|
|
19028
|
-
const raw = JSON.parse(readFileSync5(
|
|
19217
|
+
const raw = JSON.parse(readFileSync5(join10(home, ".unsloth", "studio", "auth", "agent_api_key.json"), "utf8"));
|
|
19029
19218
|
if (raw.servers && typeof raw.servers === "object") {
|
|
19030
19219
|
const servers = raw.servers;
|
|
19031
19220
|
for (const url2 of ["http://127.0.0.1:8888", "http://localhost:8888"]) {
|
|
@@ -19084,12 +19273,12 @@ function loadedIdsFromPayloads(_host, catalog, extra) {
|
|
|
19084
19273
|
};
|
|
19085
19274
|
if (extra && typeof extra === "object") {
|
|
19086
19275
|
const rec = extra;
|
|
19087
|
-
const
|
|
19088
|
-
const hasLoadedFlags =
|
|
19276
|
+
const running2 = Array.isArray(rec.models) ? rec.models : Array.isArray(rec.data) ? rec.data : [];
|
|
19277
|
+
const hasLoadedFlags = running2.some(
|
|
19089
19278
|
(row) => row && typeof row === "object" && ("loaded" in row || "state" in row)
|
|
19090
19279
|
);
|
|
19091
19280
|
if (!hasLoadedFlags && typeof rec.default_model === "string") add(rec.default_model);
|
|
19092
|
-
for (const row of
|
|
19281
|
+
for (const row of running2) {
|
|
19093
19282
|
if (typeof row === "string") {
|
|
19094
19283
|
if (!hasLoadedFlags) add(row);
|
|
19095
19284
|
continue;
|
|
@@ -19226,12 +19415,12 @@ var init_local_inject = __esm({
|
|
|
19226
19415
|
});
|
|
19227
19416
|
|
|
19228
19417
|
// server/proxy-paths.ts
|
|
19229
|
-
import { existsSync as
|
|
19230
|
-
import { dirname as dirname4, join as
|
|
19418
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
19419
|
+
import { dirname as dirname4, join as join11 } from "node:path";
|
|
19231
19420
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19232
19421
|
function resolveProxy(relative2) {
|
|
19233
|
-
const source =
|
|
19234
|
-
return
|
|
19422
|
+
const source = join11(SERVER_ROOT, `${relative2}.ts`);
|
|
19423
|
+
return existsSync7(source) ? source : join11(SERVER_ROOT, `${relative2}.js`);
|
|
19235
19424
|
}
|
|
19236
19425
|
var SERVER_ROOT, SPAWNED_PROXIES;
|
|
19237
19426
|
var init_proxy_paths = __esm({
|
|
@@ -19259,7 +19448,7 @@ var init_proxy_paths = __esm({
|
|
|
19259
19448
|
|
|
19260
19449
|
// server/container-computer.ts
|
|
19261
19450
|
import { execFile as execFile4 } from "node:child_process";
|
|
19262
|
-
import { join as
|
|
19451
|
+
import { join as join12, resolve as resolve3 } from "node:path";
|
|
19263
19452
|
import { promisify } from "node:util";
|
|
19264
19453
|
function computerProxyEnv(computer) {
|
|
19265
19454
|
return {
|
|
@@ -19283,7 +19472,7 @@ var init_container_computer = __esm({
|
|
|
19283
19472
|
IMAGE_REPOSITORY = "localhost/openmausbot/cua-local-vm";
|
|
19284
19473
|
IMAGE_LAYER_VERSION = "5";
|
|
19285
19474
|
IMAGE = `${IMAGE_REPOSITORY}:driver-${CUA_DRIVER_VERSION}-v${IMAGE_LAYER_VERSION}`;
|
|
19286
|
-
VM_WORKSPACE_DIR =
|
|
19475
|
+
VM_WORKSPACE_DIR = join12(DATA_DIR, "vm-home");
|
|
19287
19476
|
MEMORY_BYTES = 4 * 1024 * 1024 * 1024;
|
|
19288
19477
|
SHM_BYTES = 512 * 1024 * 1024;
|
|
19289
19478
|
containerMcpPath = SPAWNED_PROXIES.containerMcp;
|
|
@@ -19374,11 +19563,11 @@ var init_redact = __esm({
|
|
|
19374
19563
|
|
|
19375
19564
|
// server/drivers/native.ts
|
|
19376
19565
|
import { appendFileSync } from "node:fs";
|
|
19377
|
-
import { join as
|
|
19566
|
+
import { join as join13 } from "node:path";
|
|
19378
19567
|
function appendNative(threadId, entry) {
|
|
19379
19568
|
try {
|
|
19380
19569
|
appendFileSync(
|
|
19381
|
-
|
|
19570
|
+
join13(NATIVE_DIR, `${threadId}.ndjson`),
|
|
19382
19571
|
JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), ...entry, msg: redactSecrets(entry.msg) }) + "\n",
|
|
19383
19572
|
{ mode: 384 }
|
|
19384
19573
|
);
|
|
@@ -19625,7 +19814,7 @@ function createAcpDriver(support11) {
|
|
|
19625
19814
|
}
|
|
19626
19815
|
appendNative(threadId, { dir: "out", source: SOURCE, msg: nativeLogMessage(obj) });
|
|
19627
19816
|
};
|
|
19628
|
-
const request = (method, params, timeoutMs) => new Promise((
|
|
19817
|
+
const request = (method, params, timeoutMs) => new Promise((resolve13, reject) => {
|
|
19629
19818
|
const id = nextId++;
|
|
19630
19819
|
let timer = null;
|
|
19631
19820
|
if (timeoutMs) {
|
|
@@ -19635,7 +19824,7 @@ function createAcpDriver(support11) {
|
|
|
19635
19824
|
}, timeoutMs);
|
|
19636
19825
|
timer.unref?.();
|
|
19637
19826
|
}
|
|
19638
|
-
rpcPending.set(id, { resolve:
|
|
19827
|
+
rpcPending.set(id, { resolve: resolve13, reject, timer });
|
|
19639
19828
|
send({ jsonrpc: "2.0", id, method, params });
|
|
19640
19829
|
});
|
|
19641
19830
|
const stop = () => killCliTree(child);
|
|
@@ -20071,12 +20260,12 @@ ${turn.text}` : turn.text;
|
|
|
20071
20260
|
const snapshot = async () => {
|
|
20072
20261
|
const env = childEnv();
|
|
20073
20262
|
if (support11.snapshot) return support11.snapshot(env, config2, instanceId);
|
|
20074
|
-
const version2 = await new Promise((
|
|
20263
|
+
const version2 = await new Promise((resolve13) => {
|
|
20075
20264
|
execCli(
|
|
20076
20265
|
config2.cli,
|
|
20077
20266
|
["--version"],
|
|
20078
20267
|
{ timeout: 8e3, env },
|
|
20079
|
-
(err, stdout2) =>
|
|
20268
|
+
(err, stdout2) => resolve13(err ? null : stdout2.trim())
|
|
20080
20269
|
);
|
|
20081
20270
|
});
|
|
20082
20271
|
if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
|
|
@@ -20164,7 +20353,7 @@ import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypt
|
|
|
20164
20353
|
import { mkdir as mkdir2, mkdtemp, readFile as readFile2, rm, stat as stat2 } from "node:fs/promises";
|
|
20165
20354
|
import { request as httpRequest } from "node:http";
|
|
20166
20355
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
20167
|
-
import { delimiter as delimiter4, join as
|
|
20356
|
+
import { delimiter as delimiter4, join as join14, resolve as resolve5 } from "node:path";
|
|
20168
20357
|
function quoteBrowserArgument(value) {
|
|
20169
20358
|
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
20170
20359
|
}
|
|
@@ -20199,11 +20388,11 @@ function authorizationUrlFromLine(line) {
|
|
|
20199
20388
|
}
|
|
20200
20389
|
}
|
|
20201
20390
|
function antigravityProfileDirectory(instanceId, baseDir = DATA_DIR) {
|
|
20202
|
-
return
|
|
20391
|
+
return join14(baseDir, "providers", "antigravity", createHash3("sha256").update(instanceId).digest("hex"));
|
|
20203
20392
|
}
|
|
20204
20393
|
async function prepareAntigravityProfile(input) {
|
|
20205
20394
|
const directory = resolve5(input.profileDirectory ?? antigravityProfileDirectory(input.instanceId, input.baseDir));
|
|
20206
|
-
const acpDirectory =
|
|
20395
|
+
const acpDirectory = join14(directory, "antigravity-acp");
|
|
20207
20396
|
await mkdir2(acpDirectory, { recursive: true, mode: 448 });
|
|
20208
20397
|
if (process.platform !== "win32") {
|
|
20209
20398
|
const { chmod: chmod2 } = await import("node:fs/promises");
|
|
@@ -20211,7 +20400,7 @@ async function prepareAntigravityProfile(input) {
|
|
|
20211
20400
|
await chmod2(acpDirectory, 448);
|
|
20212
20401
|
}
|
|
20213
20402
|
writeFileAtomic(
|
|
20214
|
-
|
|
20403
|
+
join14(acpDirectory, "settings.json"),
|
|
20215
20404
|
`${JSON.stringify({ auth: { type: "oauth-personal" } })}
|
|
20216
20405
|
`,
|
|
20217
20406
|
{ mode: 384 }
|
|
@@ -20234,7 +20423,7 @@ async function prepareAntigravityProfile(input) {
|
|
|
20234
20423
|
PYTHONUNBUFFERED: "1",
|
|
20235
20424
|
ELECTRON_RUN_AS_NODE: "1"
|
|
20236
20425
|
});
|
|
20237
|
-
return { directory, tokenPath:
|
|
20426
|
+
return { directory, tokenPath: join14(acpDirectory, "acp_token.json"), environment };
|
|
20238
20427
|
}
|
|
20239
20428
|
async function antigravityProfileAuthenticated(profile) {
|
|
20240
20429
|
try {
|
|
@@ -20363,7 +20552,7 @@ function isValidAntigravityInitializeResult(initialized, expectedVersion) {
|
|
|
20363
20552
|
return true;
|
|
20364
20553
|
}
|
|
20365
20554
|
async function validateAntigravityRuntime(runtime, expectedVersion) {
|
|
20366
|
-
const profileDirectory = await mkdtemp(
|
|
20555
|
+
const profileDirectory = await mkdtemp(join14(tmpdir2(), "openmaus-antigravity-verify-"));
|
|
20367
20556
|
let client;
|
|
20368
20557
|
let failed = false;
|
|
20369
20558
|
let failure;
|
|
@@ -20466,14 +20655,14 @@ var init_antigravity_acp = __esm({
|
|
|
20466
20655
|
this.child.stderr.setEncoding("utf8");
|
|
20467
20656
|
this.child.stderr.on("data", (chunk) => this.consumeDiagnostics(chunk));
|
|
20468
20657
|
this.child.once("error", (error51) => this.failAll(error51));
|
|
20469
|
-
this.exited = new Promise((
|
|
20658
|
+
this.exited = new Promise((resolve13) => {
|
|
20470
20659
|
this.child.once("close", (code, signal) => {
|
|
20471
20660
|
this.noteStartupDiagnostic(this.diagnosticBuffer);
|
|
20472
20661
|
this.diagnosticBuffer = "";
|
|
20473
20662
|
if (!this.closed) this.failAll(new Error(
|
|
20474
20663
|
`Antigravity ACP exited ${code ?? signal ?? "unexpectedly"}.${this.nativeStartupHint ? ` ${this.nativeStartupHint}` : ""}`
|
|
20475
20664
|
));
|
|
20476
|
-
|
|
20665
|
+
resolve13();
|
|
20477
20666
|
});
|
|
20478
20667
|
});
|
|
20479
20668
|
}
|
|
@@ -20579,8 +20768,8 @@ var init_antigravity_acp = __esm({
|
|
|
20579
20768
|
async closeAndWait(timeoutMs = 5e3) {
|
|
20580
20769
|
this.close();
|
|
20581
20770
|
let timer;
|
|
20582
|
-
const timedOut = new Promise((
|
|
20583
|
-
timer = setTimeout(() =>
|
|
20771
|
+
const timedOut = new Promise((resolve13) => {
|
|
20772
|
+
timer = setTimeout(() => resolve13(false), timeoutMs);
|
|
20584
20773
|
timer.unref?.();
|
|
20585
20774
|
});
|
|
20586
20775
|
try {
|
|
@@ -20752,7 +20941,7 @@ import {
|
|
|
20752
20941
|
writeFile as writeFile2
|
|
20753
20942
|
} from "node:fs/promises";
|
|
20754
20943
|
import { constants } from "node:fs";
|
|
20755
|
-
import { delimiter as delimiter5, dirname as dirname6, isAbsolute as isAbsolute2, join as
|
|
20944
|
+
import { delimiter as delimiter5, dirname as dirname6, isAbsolute as isAbsolute2, join as join15, resolve as resolve6 } from "node:path";
|
|
20756
20945
|
import { Transform } from "node:stream";
|
|
20757
20946
|
import { pipeline } from "node:stream/promises";
|
|
20758
20947
|
import { createInflateRaw } from "node:zlib";
|
|
@@ -20773,7 +20962,7 @@ async function retryOnWindowsFileLock(step, options = {}) {
|
|
|
20773
20962
|
}
|
|
20774
20963
|
}
|
|
20775
20964
|
function runtimeRoot(baseDir = DATA_DIR) {
|
|
20776
|
-
return
|
|
20965
|
+
return join15(baseDir, "tools", "antigravity-acp", `${process.platform}-${process.arch}`);
|
|
20777
20966
|
}
|
|
20778
20967
|
function executableNames(platform = process.platform) {
|
|
20779
20968
|
return platform === "win32" ? { executable: "agy_acp_server.exe", harness: "localharness_external.exe" } : { executable: "agy_acp_server.par", harness: "localharness_external" };
|
|
@@ -20790,10 +20979,10 @@ async function executableFile(path3, bytes) {
|
|
|
20790
20979
|
}
|
|
20791
20980
|
async function completedRelease(directory, asset) {
|
|
20792
20981
|
try {
|
|
20793
|
-
const record3 = JSON.parse(await readFile3(
|
|
20982
|
+
const record3 = JSON.parse(await readFile3(join15(directory, INSTALL_RECORD), "utf8"));
|
|
20794
20983
|
if (record3.sha256 !== asset.sha256 || record3.version !== asset.version || record3.executable.name !== asset.executable.name || record3.executable.bytes !== asset.executable.bytes || record3.harness.name !== asset.harness.name || record3.harness.bytes !== asset.harness.bytes) return null;
|
|
20795
|
-
const executablePath =
|
|
20796
|
-
const harnessPath =
|
|
20984
|
+
const executablePath = join15(directory, asset.executable.name);
|
|
20985
|
+
const harnessPath = join15(directory, asset.harness.name);
|
|
20797
20986
|
if (!await executableFile(executablePath, asset.executable.bytes)) return null;
|
|
20798
20987
|
if (!await executableFile(harnessPath, asset.harness.bytes)) return null;
|
|
20799
20988
|
return { executablePath, harnessPath, source: "managed", version: asset.version };
|
|
@@ -20809,7 +20998,7 @@ function pathCandidates(binary2, env) {
|
|
|
20809
20998
|
async function externalRuntime(candidate, source) {
|
|
20810
20999
|
const names = executableNames();
|
|
20811
21000
|
const executablePath = resolve6(candidate);
|
|
20812
|
-
const harnessPath =
|
|
21001
|
+
const harnessPath = join15(dirname6(executablePath), names.harness);
|
|
20813
21002
|
if (!await executableFile(executablePath) || !await executableFile(harnessPath)) return null;
|
|
20814
21003
|
return { executablePath, harnessPath, source, version: null };
|
|
20815
21004
|
}
|
|
@@ -20829,7 +21018,7 @@ async function resolveAntigravityRuntime(binaryPath, env = process.env, baseDir
|
|
|
20829
21018
|
}
|
|
20830
21019
|
const asset = resolveAntigravityReleaseAsset();
|
|
20831
21020
|
if (asset) {
|
|
20832
|
-
const managed = await completedRelease(
|
|
21021
|
+
const managed = await completedRelease(join15(runtimeRoot(baseDir), "versions", asset.sha256), asset);
|
|
20833
21022
|
if (managed) return managed;
|
|
20834
21023
|
}
|
|
20835
21024
|
const names = executableNames();
|
|
@@ -20849,25 +21038,25 @@ async function pinnedZipEntries(path3) {
|
|
|
20849
21038
|
try {
|
|
20850
21039
|
const info = await handle.stat();
|
|
20851
21040
|
const tailBytes = Math.min(info.size, MAX_EOCD_BYTES);
|
|
20852
|
-
const
|
|
21041
|
+
const tail2 = Buffer.alloc(tailBytes);
|
|
20853
21042
|
const tailOffset = info.size - tailBytes;
|
|
20854
|
-
if ((await handle.read(
|
|
21043
|
+
if ((await handle.read(tail2, 0, tailBytes, tailOffset)).bytesRead !== tailBytes) {
|
|
20855
21044
|
throw new Error("The verified archive was truncated.");
|
|
20856
21045
|
}
|
|
20857
21046
|
let eocd = -1;
|
|
20858
|
-
for (let cursor4 =
|
|
20859
|
-
if (
|
|
21047
|
+
for (let cursor4 = tail2.length - 22; cursor4 >= 0; cursor4 -= 1) {
|
|
21048
|
+
if (tail2.readUInt32LE(cursor4) === EOCD_SIGNATURE && cursor4 + 22 + tail2.readUInt16LE(cursor4 + 20) === tail2.length) {
|
|
20860
21049
|
eocd = cursor4;
|
|
20861
21050
|
break;
|
|
20862
21051
|
}
|
|
20863
21052
|
}
|
|
20864
21053
|
if (eocd < 0) throw new Error("The verified archive has no valid ZIP directory.");
|
|
20865
|
-
const disk =
|
|
20866
|
-
const directoryDisk =
|
|
20867
|
-
const diskEntries =
|
|
20868
|
-
const entryCount =
|
|
20869
|
-
const directoryBytes =
|
|
20870
|
-
const directoryOffset =
|
|
21054
|
+
const disk = tail2.readUInt16LE(eocd + 4);
|
|
21055
|
+
const directoryDisk = tail2.readUInt16LE(eocd + 6);
|
|
21056
|
+
const diskEntries = tail2.readUInt16LE(eocd + 8);
|
|
21057
|
+
const entryCount = tail2.readUInt16LE(eocd + 10);
|
|
21058
|
+
const directoryBytes = tail2.readUInt32LE(eocd + 12);
|
|
21059
|
+
const directoryOffset = tail2.readUInt32LE(eocd + 16);
|
|
20871
21060
|
const eocdOffset = tailOffset + eocd;
|
|
20872
21061
|
if (disk !== 0 || directoryDisk !== 0 || diskEntries !== entryCount || entryCount !== 2 || directoryBytes === 4294967295 || directoryOffset === 4294967295 || directoryOffset + directoryBytes > eocdOffset) throw new Error("The verified archive uses an unsupported ZIP layout.");
|
|
20873
21062
|
const directory = Buffer.alloc(directoryBytes);
|
|
@@ -20951,19 +21140,19 @@ async function extractPinnedArchive(archivePath, outputDirectory, asset) {
|
|
|
20951
21140
|
start: dataOffset,
|
|
20952
21141
|
end: dataOffset + entry.compressedBytes - 1
|
|
20953
21142
|
});
|
|
20954
|
-
const destination = createWriteStream(
|
|
21143
|
+
const destination = createWriteStream(join15(outputDirectory, entry.name), { flags: "wx", mode: 448 });
|
|
20955
21144
|
if (entry.compression === 8) await pipeline(source, createInflateRaw(), counter, destination);
|
|
20956
21145
|
else await pipeline(source, counter, destination);
|
|
20957
21146
|
if (bytes !== expectedBytes) throw new Error("An extracted file was truncated.");
|
|
20958
21147
|
}
|
|
20959
21148
|
if (seen.size !== 2) throw new Error("The archive is missing an expected file.");
|
|
20960
21149
|
}
|
|
20961
|
-
async function
|
|
21150
|
+
async function installOnce2(options) {
|
|
20962
21151
|
const asset = options.asset === void 0 ? resolveAntigravityReleaseAsset() : options.asset;
|
|
20963
21152
|
if (!asset) throw new Error(`Google does not publish an Antigravity runtime for ${process.platform}-${process.arch}.`);
|
|
20964
21153
|
const root = runtimeRoot(options.baseDir);
|
|
20965
|
-
const versions =
|
|
20966
|
-
const destination =
|
|
21154
|
+
const versions = join15(root, "versions");
|
|
21155
|
+
const destination = join15(versions, asset.sha256);
|
|
20967
21156
|
await mkdir3(versions, { recursive: true, mode: 448 });
|
|
20968
21157
|
const existing = await completedRelease(destination, asset);
|
|
20969
21158
|
if (existing) {
|
|
@@ -20979,11 +21168,11 @@ async function installOnce(options) {
|
|
|
20979
21168
|
} catch (error51) {
|
|
20980
21169
|
if (error51 instanceof Error && error51.message.includes("Antigravity needs")) throw error51;
|
|
20981
21170
|
}
|
|
20982
|
-
const staging = await mkdtemp2(
|
|
21171
|
+
const staging = await mkdtemp2(join15(versions, `${STAGING_PREFIX}${randomUUID7()}-`));
|
|
20983
21172
|
let failed = false;
|
|
20984
21173
|
try {
|
|
20985
|
-
const archivePath =
|
|
20986
|
-
const runtimeDirectory =
|
|
21174
|
+
const archivePath = join15(staging, "download.zip");
|
|
21175
|
+
const runtimeDirectory = join15(staging, "runtime");
|
|
20987
21176
|
await mkdir3(runtimeDirectory, { mode: 448 });
|
|
20988
21177
|
const controller = new AbortController();
|
|
20989
21178
|
const timeout = setTimeout(() => controller.abort(), DOWNLOAD_TIMEOUT_MS2);
|
|
@@ -21029,12 +21218,12 @@ async function installOnce(options) {
|
|
|
21029
21218
|
}
|
|
21030
21219
|
await extractPinnedArchive(archivePath, runtimeDirectory, asset);
|
|
21031
21220
|
if (process.platform !== "win32") {
|
|
21032
|
-
await chmod(
|
|
21033
|
-
await chmod(
|
|
21221
|
+
await chmod(join15(runtimeDirectory, asset.executable.name), 493);
|
|
21222
|
+
await chmod(join15(runtimeDirectory, asset.harness.name), 493);
|
|
21034
21223
|
}
|
|
21035
21224
|
const candidate = {
|
|
21036
|
-
executablePath:
|
|
21037
|
-
harnessPath:
|
|
21225
|
+
executablePath: join15(runtimeDirectory, asset.executable.name),
|
|
21226
|
+
harnessPath: join15(runtimeDirectory, asset.harness.name),
|
|
21038
21227
|
source: "managed",
|
|
21039
21228
|
version: asset.version
|
|
21040
21229
|
};
|
|
@@ -21045,7 +21234,7 @@ async function installOnce(options) {
|
|
|
21045
21234
|
executable: asset.executable,
|
|
21046
21235
|
harness: asset.harness
|
|
21047
21236
|
};
|
|
21048
|
-
await writeFile2(
|
|
21237
|
+
await writeFile2(join15(runtimeDirectory, INSTALL_RECORD), `${JSON.stringify(record3)}
|
|
21049
21238
|
`, { flag: "wx", mode: 384 });
|
|
21050
21239
|
try {
|
|
21051
21240
|
await retryOnWindowsFileLock(() => rename(runtimeDirectory, destination));
|
|
@@ -21072,9 +21261,9 @@ function installAntigravityRuntime(options = {}) {
|
|
|
21072
21261
|
const key = runtimeRoot(options.baseDir);
|
|
21073
21262
|
const existing = installs.get(key);
|
|
21074
21263
|
if (existing) return existing;
|
|
21075
|
-
const
|
|
21076
|
-
installs.set(key,
|
|
21077
|
-
return
|
|
21264
|
+
const running2 = installOnce2(options).finally(() => installs.delete(key));
|
|
21265
|
+
installs.set(key, running2);
|
|
21266
|
+
return running2;
|
|
21078
21267
|
}
|
|
21079
21268
|
function antigravityManagedInstallAvailable() {
|
|
21080
21269
|
return resolveAntigravityReleaseAsset() !== null;
|
|
@@ -21089,7 +21278,7 @@ var init_antigravity_runtime = __esm({
|
|
|
21089
21278
|
FREE_SPACE_MARGIN = 256 * 1024 * 1024;
|
|
21090
21279
|
DOWNLOAD_TIMEOUT_MS2 = 45 * 6e4;
|
|
21091
21280
|
STAGING_PREFIX = ".install-";
|
|
21092
|
-
wait = (ms) => new Promise((
|
|
21281
|
+
wait = (ms) => new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
21093
21282
|
INSTALL_RECORD = ".install-complete.json";
|
|
21094
21283
|
AntigravitySetupError = class extends Error {
|
|
21095
21284
|
status = 409;
|
|
@@ -21485,14 +21674,14 @@ var init_boxagent = __esm({
|
|
|
21485
21674
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
21486
21675
|
import { realpathSync } from "node:fs";
|
|
21487
21676
|
import { homedir as homedir8 } from "node:os";
|
|
21488
|
-
import { basename as basename4, dirname as dirname7, isAbsolute as isAbsolute3, join as
|
|
21489
|
-
import { stripVTControlCharacters as
|
|
21677
|
+
import { basename as basename4, dirname as dirname7, isAbsolute as isAbsolute3, join as join16, resolve as resolve7 } from "node:path";
|
|
21678
|
+
import { stripVTControlCharacters as stripVTControlCharacters4 } from "node:util";
|
|
21490
21679
|
function canonicalPath(path3) {
|
|
21491
21680
|
try {
|
|
21492
21681
|
return realpathSync(path3);
|
|
21493
21682
|
} catch {
|
|
21494
21683
|
const parent = dirname7(path3);
|
|
21495
|
-
return parent === path3 ? path3 :
|
|
21684
|
+
return parent === path3 ? path3 : join16(canonicalPath(parent), basename4(path3));
|
|
21496
21685
|
}
|
|
21497
21686
|
}
|
|
21498
21687
|
function claudeSignInLink(value) {
|
|
@@ -21507,7 +21696,7 @@ function claudeSignInLink(value) {
|
|
|
21507
21696
|
}
|
|
21508
21697
|
}
|
|
21509
21698
|
function claudeLoginPrompt(output) {
|
|
21510
|
-
const lines =
|
|
21699
|
+
const lines = stripVTControlCharacters4(output).split(/\r?\n/).slice(0, -1);
|
|
21511
21700
|
for (const line of lines) {
|
|
21512
21701
|
const match = /(https:\/\/\S+)/.exec(line.trim());
|
|
21513
21702
|
const link = match ? claudeSignInLink(match[1].replace(/[),.;]+$/, "")) : null;
|
|
@@ -21519,17 +21708,18 @@ function claudeLoginCode(value) {
|
|
|
21519
21708
|
const code = value.trim();
|
|
21520
21709
|
return /^[A-Za-z0-9_\-#.:]{8,1024}$/.test(code) ? code : null;
|
|
21521
21710
|
}
|
|
21522
|
-
var
|
|
21711
|
+
var MAX_OUTPUT2, SIGN_IN_HOSTS, authenticatingHomes, NOT_AVAILABLE, ClaudeLoginController;
|
|
21523
21712
|
var init_claude_login_auth = __esm({
|
|
21524
21713
|
"server/drivers/claude-login-auth.ts"() {
|
|
21525
21714
|
"use strict";
|
|
21526
21715
|
init_procs();
|
|
21527
|
-
|
|
21716
|
+
MAX_OUTPUT2 = 32768;
|
|
21528
21717
|
SIGN_IN_HOSTS = ["claude.com", "claude.ai", "console.anthropic.com", "platform.claude.com"];
|
|
21529
21718
|
authenticatingHomes = /* @__PURE__ */ new Set();
|
|
21530
21719
|
NOT_AVAILABLE = "This sign-in is no longer available. Start sign-in again.";
|
|
21531
21720
|
ClaudeLoginController = class {
|
|
21532
21721
|
flow = null;
|
|
21722
|
+
logoutChild = null;
|
|
21533
21723
|
disposed = false;
|
|
21534
21724
|
options;
|
|
21535
21725
|
constructor(options) {
|
|
@@ -21548,7 +21738,7 @@ var init_claude_login_auth = __esm({
|
|
|
21548
21738
|
if (!isAbsolute3(home) || env.CLAUDE_CONFIG_DIR && !isAbsolute3(env.CLAUDE_CONFIG_DIR)) {
|
|
21549
21739
|
throw new Error("Use an absolute HOME and CLAUDE_CONFIG_DIR path for this server's Claude provider before signing in.");
|
|
21550
21740
|
}
|
|
21551
|
-
const homeKey = canonicalPath(resolve7(env.CLAUDE_CONFIG_DIR ||
|
|
21741
|
+
const homeKey = canonicalPath(resolve7(env.CLAUDE_CONFIG_DIR || join16(home, ".claude")));
|
|
21552
21742
|
if (authenticatingHomes.has(homeKey)) {
|
|
21553
21743
|
throw new Error("A Claude sign-in is already running for this server account. Finish or cancel it before starting another.");
|
|
21554
21744
|
}
|
|
@@ -21621,43 +21811,121 @@ var init_claude_login_auth = __esm({
|
|
|
21621
21811
|
if (this.flow?.status.phase === "waiting") this.finish(this.flow, "cancelled", "Claude sign-in cancelled.");
|
|
21622
21812
|
await this.flow?.stopping;
|
|
21623
21813
|
if (this.flow?.terminationFailed) throw new Error(this.flow.status.message);
|
|
21814
|
+
if (this.logoutChild && !await this.stopChild(this.logoutChild)) {
|
|
21815
|
+
throw new Error("Claude Code could not be stopped on this server. Ask the server administrator to stop the account command before trying again.");
|
|
21816
|
+
}
|
|
21624
21817
|
}
|
|
21625
21818
|
async dispose() {
|
|
21626
21819
|
this.disposed = true;
|
|
21627
21820
|
await this.cancel();
|
|
21628
21821
|
this.flow = null;
|
|
21629
21822
|
}
|
|
21823
|
+
/** Remove the sign-in Claude Code stores for this server account (its
|
|
21824
|
+
* configuration directory) so a different subscription can sign in. A
|
|
21825
|
+
* sign-in in progress is never pulled away underneath the browser
|
|
21826
|
+
* completing it, and the CLI's own status is the verdict, as for sign-in. */
|
|
21827
|
+
async signOut() {
|
|
21828
|
+
if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
|
|
21829
|
+
if (this.flow?.status.phase === "waiting") throw new Error("Finish or cancel the Claude sign-in in progress before signing out.");
|
|
21830
|
+
await this.flow?.stopping;
|
|
21831
|
+
if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
|
|
21832
|
+
const env = this.options.environment();
|
|
21833
|
+
const home = env.HOME || env.USERPROFILE || homedir8();
|
|
21834
|
+
if (!isAbsolute3(home) || env.CLAUDE_CONFIG_DIR && !isAbsolute3(env.CLAUDE_CONFIG_DIR)) {
|
|
21835
|
+
throw new Error("Use an absolute HOME and CLAUDE_CONFIG_DIR path for this server's Claude provider before signing out.");
|
|
21836
|
+
}
|
|
21837
|
+
const homeKey = canonicalPath(resolve7(env.CLAUDE_CONFIG_DIR || join16(home, ".claude")));
|
|
21838
|
+
if (authenticatingHomes.has(homeKey)) {
|
|
21839
|
+
throw new Error("A Claude sign-in is running for this server account. Finish or cancel it before signing out.");
|
|
21840
|
+
}
|
|
21841
|
+
authenticatingHomes.add(homeKey);
|
|
21842
|
+
try {
|
|
21843
|
+
await this.logout(env);
|
|
21844
|
+
if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
|
|
21845
|
+
const status = await this.authStatus(env);
|
|
21846
|
+
if (status === "in") throw new Error("Claude Code still reports a sign-in on this server. Update Claude Code and check its auth status before trying again.");
|
|
21847
|
+
if (status === "unknown") throw new Error("Claude Code could not confirm the sign-out on this server. Update Claude Code and check its auth status before trying again.");
|
|
21848
|
+
} finally {
|
|
21849
|
+
const child = this.logoutChild;
|
|
21850
|
+
if (child && child.exitCode === null && child.signalCode === null) {
|
|
21851
|
+
child.once("close", () => authenticatingHomes.delete(homeKey));
|
|
21852
|
+
} else authenticatingHomes.delete(homeKey);
|
|
21853
|
+
}
|
|
21854
|
+
}
|
|
21855
|
+
/** `claude auth logout`, bounded and non-interactive. Its output stays
|
|
21856
|
+
* here; the status command afterwards decides whether it worked. */
|
|
21857
|
+
logout(env) {
|
|
21858
|
+
return new Promise((resolveDone, rejectDone) => {
|
|
21859
|
+
if (this.disposed) {
|
|
21860
|
+
rejectDone(new Error("This provider was removed. Refresh Settings before signing out."));
|
|
21861
|
+
return;
|
|
21862
|
+
}
|
|
21863
|
+
let child;
|
|
21864
|
+
try {
|
|
21865
|
+
child = spawnCli(this.options.cli, ["auth", "logout"], { env: { ...env, NO_COLOR: "1" }, stdio: ["pipe", "pipe", "pipe"] });
|
|
21866
|
+
} catch {
|
|
21867
|
+
rejectDone(new Error("Claude Code could not start on this server. Install or update the configured Claude CLI, then try again."));
|
|
21868
|
+
return;
|
|
21869
|
+
}
|
|
21870
|
+
this.logoutChild = child;
|
|
21871
|
+
child.stdin.end();
|
|
21872
|
+
child.stdout.on("data", () => {
|
|
21873
|
+
});
|
|
21874
|
+
child.stderr.on("data", () => {
|
|
21875
|
+
});
|
|
21876
|
+
const timer = setTimeout(() => {
|
|
21877
|
+
void this.stopChild(child).catch(() => false).then((stopped) => {
|
|
21878
|
+
if (!stopped) rejectDone(new Error("Claude Code could not be stopped on this server. Ask the server administrator to stop the account command before trying again."));
|
|
21879
|
+
});
|
|
21880
|
+
}, this.options.startupTimeoutMs ?? 3e4);
|
|
21881
|
+
timer.unref();
|
|
21882
|
+
child.once("error", (error51) => {
|
|
21883
|
+
clearTimeout(timer);
|
|
21884
|
+
rejectDone(new Error(error51.code === "ENOENT" ? "Claude Code is not installed on this server. Install it on the server, then try again." : "Claude Code could not start on this server. Check the configured CLI path and its executable permissions."));
|
|
21885
|
+
});
|
|
21886
|
+
child.once("close", () => {
|
|
21887
|
+
clearTimeout(timer);
|
|
21888
|
+
if (this.logoutChild === child) this.logoutChild = null;
|
|
21889
|
+
resolveDone();
|
|
21890
|
+
});
|
|
21891
|
+
});
|
|
21892
|
+
}
|
|
21630
21893
|
signedIn(env) {
|
|
21894
|
+
return this.authStatus(env).then((status) => status === "in");
|
|
21895
|
+
}
|
|
21896
|
+
/** `claude auth status --json`: signed in, signed out, or not answered. */
|
|
21897
|
+
authStatus(env) {
|
|
21631
21898
|
return new Promise((resolveStatus) => {
|
|
21632
21899
|
let child;
|
|
21633
21900
|
try {
|
|
21634
21901
|
child = spawnCli(this.options.cli, ["auth", "status", "--json"], { env: { ...env, NO_COLOR: "1" }, stdio: ["ignore", "pipe", "pipe"] });
|
|
21635
21902
|
} catch {
|
|
21636
|
-
resolveStatus(
|
|
21903
|
+
resolveStatus("unknown");
|
|
21637
21904
|
return;
|
|
21638
21905
|
}
|
|
21639
21906
|
let stdout2 = "";
|
|
21640
21907
|
child.stdout.on("data", (chunk) => {
|
|
21641
|
-
if (stdout2.length <
|
|
21908
|
+
if (stdout2.length < MAX_OUTPUT2) stdout2 += chunk.toString("utf8");
|
|
21642
21909
|
});
|
|
21643
21910
|
child.stderr.on("data", () => {
|
|
21644
21911
|
});
|
|
21645
21912
|
const timer = setTimeout(() => {
|
|
21646
21913
|
child.kill("SIGKILL");
|
|
21647
|
-
resolveStatus(
|
|
21914
|
+
resolveStatus("unknown");
|
|
21648
21915
|
}, 8e3);
|
|
21649
21916
|
timer.unref();
|
|
21650
21917
|
child.once("error", () => {
|
|
21651
21918
|
clearTimeout(timer);
|
|
21652
|
-
resolveStatus(
|
|
21919
|
+
resolveStatus("unknown");
|
|
21653
21920
|
});
|
|
21654
|
-
child.once("close", () => {
|
|
21921
|
+
child.once("close", (code) => {
|
|
21655
21922
|
clearTimeout(timer);
|
|
21656
21923
|
try {
|
|
21657
21924
|
const status = JSON.parse(stdout2);
|
|
21658
|
-
|
|
21925
|
+
const loggedIn = typeof status === "object" && status !== null ? Reflect.get(status, "loggedIn") : void 0;
|
|
21926
|
+
resolveStatus(code === 0 && loggedIn === true ? "in" : code === 1 && loggedIn === false ? "out" : "unknown");
|
|
21659
21927
|
} catch {
|
|
21660
|
-
resolveStatus(
|
|
21928
|
+
resolveStatus("unknown");
|
|
21661
21929
|
}
|
|
21662
21930
|
});
|
|
21663
21931
|
});
|
|
@@ -21678,7 +21946,7 @@ var init_claude_login_auth = __esm({
|
|
|
21678
21946
|
flow.child = child;
|
|
21679
21947
|
const receive = (chunk) => {
|
|
21680
21948
|
if (flow.status.phase !== "waiting") return;
|
|
21681
|
-
if (flow.output.length + chunk.length >
|
|
21949
|
+
if (flow.output.length + chunk.length > MAX_OUTPUT2) {
|
|
21682
21950
|
this.finish(flow, "failed", "Claude Code returned an unexpected sign-in response. Update the server's Claude CLI and try again.");
|
|
21683
21951
|
return;
|
|
21684
21952
|
}
|
|
@@ -21700,7 +21968,7 @@ var init_claude_login_auth = __esm({
|
|
|
21700
21968
|
child.once("close", (code) => {
|
|
21701
21969
|
if (flow.child === child) flow.child = null;
|
|
21702
21970
|
if (flow.status.phase !== "waiting") return;
|
|
21703
|
-
const output =
|
|
21971
|
+
const output = stripVTControlCharacters4(flow.output);
|
|
21704
21972
|
flow.output = "";
|
|
21705
21973
|
void this.signedIn(flow.env).then((signedIn) => {
|
|
21706
21974
|
if (flow.status.phase !== "waiting") return;
|
|
@@ -21733,7 +22001,7 @@ var init_claude_login_auth = __esm({
|
|
|
21733
22001
|
else flow.completion.reject(new Error(message2 ?? "Claude sign-in did not finish."));
|
|
21734
22002
|
flow.completion = void 0;
|
|
21735
22003
|
}
|
|
21736
|
-
flow.stopping = this.stopChild(flow).catch(() => false).then((stopped) => {
|
|
22004
|
+
flow.stopping = this.stopChild(flow.child).catch(() => false).then((stopped) => {
|
|
21737
22005
|
const release = () => authenticatingHomes.delete(flow.homeKey);
|
|
21738
22006
|
if (stopped) {
|
|
21739
22007
|
release();
|
|
@@ -21748,8 +22016,7 @@ var init_claude_login_auth = __esm({
|
|
|
21748
22016
|
if (phase === "succeeded") void this.options.onAuthenticated?.().catch(() => {
|
|
21749
22017
|
});
|
|
21750
22018
|
}
|
|
21751
|
-
async stopChild(
|
|
21752
|
-
const child = flow.child;
|
|
22019
|
+
async stopChild(child) {
|
|
21753
22020
|
if (!child || await killCliTree(child, this.options.terminateTimeoutMs ?? 1500)) return true;
|
|
21754
22021
|
if (process.platform !== "win32" && child.pid) {
|
|
21755
22022
|
try {
|
|
@@ -21803,13 +22070,13 @@ function computeBackoff(attempt, random = Math.random) {
|
|
|
21803
22070
|
function interruptibleDelay(ms, signal) {
|
|
21804
22071
|
let timer = null;
|
|
21805
22072
|
let onCancel = null;
|
|
21806
|
-
const promise2 = new Promise((
|
|
21807
|
-
timer = setTimeout(() =>
|
|
22073
|
+
const promise2 = new Promise((resolve13) => {
|
|
22074
|
+
timer = setTimeout(() => resolve13("elapsed"), Math.max(1, ms));
|
|
21808
22075
|
timer.unref?.();
|
|
21809
|
-
if (signal?.aborted) return
|
|
22076
|
+
if (signal?.aborted) return resolve13("cancelled");
|
|
21810
22077
|
onCancel = () => {
|
|
21811
22078
|
clearTimeout(timer);
|
|
21812
|
-
|
|
22079
|
+
resolve13("cancelled");
|
|
21813
22080
|
};
|
|
21814
22081
|
signal?.addEventListener("abort", onCancel, { once: true });
|
|
21815
22082
|
});
|
|
@@ -21861,34 +22128,34 @@ import { createHash as createHash5, randomBytes as randomBytes2 } from "node:cry
|
|
|
21861
22128
|
import { chmodSync as chmodSync3, mkdtempSync as mkdtempSync2, readFileSync as readFileSync6, rmSync as rmSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
21862
22129
|
import { createServer as createNetServer } from "node:net";
|
|
21863
22130
|
import { homedir as homedir9, tmpdir as tmpdir3 } from "node:os";
|
|
21864
|
-
import { join as
|
|
22131
|
+
import { join as join17, dirname as dirname8, isAbsolute as isAbsolute4, normalize } from "node:path";
|
|
21865
22132
|
function claudeAuthStatus(cli, env, run3 = execCli) {
|
|
21866
|
-
return new Promise((
|
|
22133
|
+
return new Promise((resolve13) => {
|
|
21867
22134
|
run3(cli, ["auth", "status", "--json"], { timeout: 8e3, maxBuffer: 65536, env }, (_error, stdout2) => {
|
|
21868
22135
|
try {
|
|
21869
22136
|
const status = JSON.parse(stdout2);
|
|
21870
22137
|
if (!status || typeof status !== "object" || !("loggedIn" in status) || status.loggedIn !== true) {
|
|
21871
|
-
return
|
|
22138
|
+
return resolve13({ authenticated: false });
|
|
21872
22139
|
}
|
|
21873
22140
|
const identity = status;
|
|
21874
22141
|
const boundedText = (value, max) => typeof value === "string" && value.trim().length > 0 && value.length <= max && !/[\p{Cc}\p{Cf}]/u.test(value) ? value.trim() : void 0;
|
|
21875
22142
|
const candidateEmail = boundedText(identity.email, 254);
|
|
21876
22143
|
const email3 = candidateEmail && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(candidateEmail) ? candidateEmail : void 0;
|
|
21877
22144
|
const organization = boundedText(identity.orgName, 160);
|
|
21878
|
-
|
|
22145
|
+
resolve13({
|
|
21879
22146
|
authenticated: true,
|
|
21880
22147
|
...email3 || organization ? { account: { ...email3 ? { email: email3 } : {}, ...organization ? { organization } : {} } } : {}
|
|
21881
22148
|
});
|
|
21882
22149
|
} catch {
|
|
21883
|
-
|
|
22150
|
+
resolve13({ authenticated: false });
|
|
21884
22151
|
}
|
|
21885
22152
|
});
|
|
21886
22153
|
});
|
|
21887
22154
|
}
|
|
21888
22155
|
function resolveClaudeConfigDir(configDir, env = process.env) {
|
|
21889
22156
|
const home = env.HOME || env.USERPROFILE || homedir9();
|
|
21890
|
-
const configured = configDir?.trim() || env.CLAUDE_CONFIG_DIR?.trim() ||
|
|
21891
|
-
const expanded = configured === "~" ? home : configured.startsWith("~/") ?
|
|
22157
|
+
const configured = configDir?.trim() || env.CLAUDE_CONFIG_DIR?.trim() || join17(home, ".claude");
|
|
22158
|
+
const expanded = configured === "~" ? home : configured.startsWith("~/") ? join17(home, configured.slice(2)) : configured;
|
|
21892
22159
|
if (!isAbsolute4(expanded) || /[\p{Cc}\p{Cf}]/u.test(expanded)) {
|
|
21893
22160
|
throw new Error("claude: configDir must be an absolute path or start with ~/");
|
|
21894
22161
|
}
|
|
@@ -21940,7 +22207,7 @@ function extrasFromUnknown(value) {
|
|
|
21940
22207
|
function readClaudeModelCatalog(env = process.env) {
|
|
21941
22208
|
let settings2 = {};
|
|
21942
22209
|
try {
|
|
21943
|
-
settings2 = JSON.parse(readFileSync6(
|
|
22210
|
+
settings2 = JSON.parse(readFileSync6(join17(resolveClaudeConfigDir(void 0, env), "settings.json"), "utf8"));
|
|
21944
22211
|
} catch {
|
|
21945
22212
|
return STATIC_CLAUDE_MODELS;
|
|
21946
22213
|
}
|
|
@@ -21990,7 +22257,7 @@ function brokerSocketCandidates(threadId) {
|
|
|
21990
22257
|
const base2 = permissionSocketPath(threadId);
|
|
21991
22258
|
if (process.platform !== "win32") {
|
|
21992
22259
|
const scope = createHash5("sha256").update(`${DATA_DIR}\0${process.pid}\0${threadId}`).digest("hex").slice(0, 16);
|
|
21993
|
-
return [base2,
|
|
22260
|
+
return [base2, join17(tmpdir3(), `omb-perm-${scope}.sock`)];
|
|
21994
22261
|
}
|
|
21995
22262
|
return [
|
|
21996
22263
|
base2,
|
|
@@ -22071,9 +22338,9 @@ async function createPermissionBroker(opts) {
|
|
|
22071
22338
|
unlinkSync3(candidate);
|
|
22072
22339
|
} catch {
|
|
22073
22340
|
}
|
|
22074
|
-
let outcome = await new Promise((
|
|
22075
|
-
attempt.once("listening", () =>
|
|
22076
|
-
attempt.once("error", (error51) =>
|
|
22341
|
+
let outcome = await new Promise((resolve13) => {
|
|
22342
|
+
attempt.once("listening", () => resolve13("listening"));
|
|
22343
|
+
attempt.once("error", (error51) => resolve13(error51));
|
|
22077
22344
|
attempt.listen(candidate);
|
|
22078
22345
|
});
|
|
22079
22346
|
if (outcome === "listening" && process.platform !== "win32") {
|
|
@@ -22330,19 +22597,19 @@ var init_claude = __esm({
|
|
|
22330
22597
|
};
|
|
22331
22598
|
const writeUser = (s, threadId, promptMsg) => {
|
|
22332
22599
|
if (!s.child.stdin.writable || s.child.stdin.destroyed) return Promise.resolve(false);
|
|
22333
|
-
return new Promise((
|
|
22600
|
+
return new Promise((resolve13) => {
|
|
22334
22601
|
try {
|
|
22335
22602
|
s.child.stdin.write(JSON.stringify(promptMsg) + "\n", (error51) => {
|
|
22336
|
-
if (error51) return
|
|
22603
|
+
if (error51) return resolve13(false);
|
|
22337
22604
|
appendNative(threadId, {
|
|
22338
22605
|
dir: "out",
|
|
22339
22606
|
source: "claude.sdk.message",
|
|
22340
22607
|
msg: diagnosticClaudeUserMessage(promptMsg)
|
|
22341
22608
|
});
|
|
22342
|
-
|
|
22609
|
+
resolve13(true);
|
|
22343
22610
|
});
|
|
22344
22611
|
} catch {
|
|
22345
|
-
|
|
22612
|
+
resolve13(false);
|
|
22346
22613
|
}
|
|
22347
22614
|
});
|
|
22348
22615
|
};
|
|
@@ -22456,7 +22723,7 @@ var init_claude = __esm({
|
|
|
22456
22723
|
allowed.push("mcp__ogb");
|
|
22457
22724
|
let mcpConfigPath = null;
|
|
22458
22725
|
if (Object.keys(mcpServers).length) {
|
|
22459
|
-
mcpConfigPath =
|
|
22726
|
+
mcpConfigPath = join17(mkdtempSync2(join17(tmpdir3(), "omb-mcp-")), "mcp.json");
|
|
22460
22727
|
args.push("--mcp-config", mcpConfigPath);
|
|
22461
22728
|
args.push("--allowedTools", allowed.join(","));
|
|
22462
22729
|
}
|
|
@@ -22524,7 +22791,7 @@ var init_claude = __esm({
|
|
|
22524
22791
|
};
|
|
22525
22792
|
try {
|
|
22526
22793
|
if (turn.system) {
|
|
22527
|
-
systemPromptPath =
|
|
22794
|
+
systemPromptPath = join17(mkdtempSync2(join17(tmpdir3(), "omb-system-")), "prompt.txt");
|
|
22528
22795
|
writeFileSync5(systemPromptPath, turn.system, { mode: 384 });
|
|
22529
22796
|
args.push("--append-system-prompt-file", systemPromptPath);
|
|
22530
22797
|
}
|
|
@@ -22832,19 +23099,19 @@ var init_claude = __esm({
|
|
|
22832
23099
|
} });
|
|
22833
23100
|
const snapshot = async () => {
|
|
22834
23101
|
const env = environment();
|
|
22835
|
-
const version2 = await new Promise((
|
|
23102
|
+
const version2 = await new Promise((resolve13) => {
|
|
22836
23103
|
execCli(
|
|
22837
23104
|
config2.cli,
|
|
22838
23105
|
["--version"],
|
|
22839
23106
|
{ timeout: 8e3, env },
|
|
22840
|
-
(err, stdout2) =>
|
|
23107
|
+
(err, stdout2) => resolve13(err ? null : stdout2.trim())
|
|
22841
23108
|
);
|
|
22842
23109
|
});
|
|
22843
23110
|
if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
|
|
22844
23111
|
const auth = await claudeAuthStatus(config2.cli, env);
|
|
22845
23112
|
return { state: "available", version: version2, ...auth, billing: "subscription" };
|
|
22846
23113
|
};
|
|
22847
|
-
const generateReview = (prompt, signal) => new Promise((
|
|
23114
|
+
const generateReview = (prompt, signal) => new Promise((resolve13, reject) => {
|
|
22848
23115
|
const child = spawnCli(
|
|
22849
23116
|
config2.cli,
|
|
22850
23117
|
["-p", "--model", "claude-haiku-4-5", "--output-format", "text"],
|
|
@@ -22862,7 +23129,7 @@ var init_claude = __esm({
|
|
|
22862
23129
|
clearTimeout(timer);
|
|
22863
23130
|
signal?.removeEventListener("abort", onAbort);
|
|
22864
23131
|
if (error51) reject(error51);
|
|
22865
|
-
else
|
|
23132
|
+
else resolve13(stdout2.trim());
|
|
22866
23133
|
};
|
|
22867
23134
|
const onAbort = () => {
|
|
22868
23135
|
killCliTree(child);
|
|
@@ -22910,6 +23177,7 @@ var init_claude = __esm({
|
|
|
22910
23177
|
getAuthentication: (flowId) => login.get(flowId),
|
|
22911
23178
|
completeAuthentication: (flowId, code) => login.complete(flowId, code),
|
|
22912
23179
|
cancelAuthentication: () => login.cancel(),
|
|
23180
|
+
signOut: () => login.signOut(),
|
|
22913
23181
|
adapter: {
|
|
22914
23182
|
provider: DRIVER_KIND2,
|
|
22915
23183
|
capabilities: {
|
|
@@ -22951,9 +23219,13 @@ var init_claude = __esm({
|
|
|
22951
23219
|
generateText: (prompt) => generateReview(prompt),
|
|
22952
23220
|
reviewPermission: generateReview,
|
|
22953
23221
|
dispose: async () => {
|
|
22954
|
-
|
|
22955
|
-
|
|
22956
|
-
|
|
23222
|
+
try {
|
|
23223
|
+
await login.dispose();
|
|
23224
|
+
} finally {
|
|
23225
|
+
for (const { stop } of active.values()) stop();
|
|
23226
|
+
for (const threadId of [...sessions.keys()]) closeSession(threadId, "dispose");
|
|
23227
|
+
listeners.clear();
|
|
23228
|
+
}
|
|
22957
23229
|
}
|
|
22958
23230
|
};
|
|
22959
23231
|
}
|
|
@@ -22964,7 +23236,7 @@ var init_claude = __esm({
|
|
|
22964
23236
|
// server/drivers/codex-catalog.ts
|
|
22965
23237
|
import { readdirSync as readdirSync2, readFileSync as readFileSync7 } from "node:fs";
|
|
22966
23238
|
import { homedir as homedir10 } from "node:os";
|
|
22967
|
-
import { basename as basename5, join as
|
|
23239
|
+
import { basename as basename5, join as join18 } from "node:path";
|
|
22968
23240
|
function encodeCodexSelection(provider, model) {
|
|
22969
23241
|
return `${provider}${SEP}${model}`;
|
|
22970
23242
|
}
|
|
@@ -22977,7 +23249,7 @@ function decodeCodexSelection(id) {
|
|
|
22977
23249
|
return { model: id, modelProvider: MODEL_ID2.test(id) ? OFFICIAL_CODEX_PROVIDER : null };
|
|
22978
23250
|
}
|
|
22979
23251
|
function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
|
|
22980
|
-
return new Promise((
|
|
23252
|
+
return new Promise((resolve13) => {
|
|
22981
23253
|
const child = spawnCli(cli, ["app-server"], {
|
|
22982
23254
|
cwd: homedir10(),
|
|
22983
23255
|
env,
|
|
@@ -22994,7 +23266,7 @@ function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
|
|
|
22994
23266
|
settled = true;
|
|
22995
23267
|
clearTimeout(timer);
|
|
22996
23268
|
killCliTree(child);
|
|
22997
|
-
|
|
23269
|
+
resolve13(catalog);
|
|
22998
23270
|
};
|
|
22999
23271
|
const request = (method, params, kind) => {
|
|
23000
23272
|
const id = nextId++;
|
|
@@ -23080,7 +23352,7 @@ function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
|
|
|
23080
23352
|
}
|
|
23081
23353
|
function codexHome(env) {
|
|
23082
23354
|
if (env.CODEX_HOME) return env.CODEX_HOME;
|
|
23083
|
-
return
|
|
23355
|
+
return join18(env.HOME || env.USERPROFILE || homedir10(), ".codex");
|
|
23084
23356
|
}
|
|
23085
23357
|
function unquote(raw) {
|
|
23086
23358
|
let value = raw.trim();
|
|
@@ -23166,11 +23438,11 @@ function niceLabel(model, provider, known, named) {
|
|
|
23166
23438
|
}
|
|
23167
23439
|
function collectCatalogNames(home) {
|
|
23168
23440
|
const named = /* @__PURE__ */ new Map();
|
|
23169
|
-
for (const file2 of listDir(
|
|
23441
|
+
for (const file2 of listDir(join18(home, "model-catalogs"))) {
|
|
23170
23442
|
if (!file2.endsWith(".json")) continue;
|
|
23171
23443
|
const provider = basename5(file2, ".json").replace(/-models$/, "");
|
|
23172
23444
|
if (!PROVIDER_ID.test(provider)) continue;
|
|
23173
|
-
const raw = readText(
|
|
23445
|
+
const raw = readText(join18(home, "model-catalogs", file2));
|
|
23174
23446
|
if (!raw) continue;
|
|
23175
23447
|
let parsed;
|
|
23176
23448
|
try {
|
|
@@ -23222,7 +23494,7 @@ async function probeProviderModels(provider, env, fetchImpl) {
|
|
|
23222
23494
|
async function readCodexModelCatalog(env = process.env, fetchImpl = fetch, cli) {
|
|
23223
23495
|
const official = (cli ? await readCodexAppServerModelCatalog(cli, env) : null) ?? STATIC_CODEX_MODELS;
|
|
23224
23496
|
const home = codexHome(env);
|
|
23225
|
-
const mainText = readText(
|
|
23497
|
+
const mainText = readText(join18(home, "config.toml"));
|
|
23226
23498
|
if (!mainText) return mergeLocalInject(official, env, fetchImpl);
|
|
23227
23499
|
const main2 = parseCodexToml(mainText);
|
|
23228
23500
|
const known = new Map(main2.providers.map((provider) => [provider.id, provider]));
|
|
@@ -23237,7 +23509,7 @@ async function readCodexModelCatalog(env = process.env, fetchImpl = fetch, cli)
|
|
|
23237
23509
|
remember(main2.modelProvider, main2.model);
|
|
23238
23510
|
for (const file2 of listDir(home)) {
|
|
23239
23511
|
if (!file2.endsWith(".config.toml")) continue;
|
|
23240
|
-
const profile = parseCodexToml(readText(
|
|
23512
|
+
const profile = parseCodexToml(readText(join18(home, file2)) ?? "");
|
|
23241
23513
|
for (const provider of profile.providers) {
|
|
23242
23514
|
if (!known.has(provider.id)) known.set(provider.id, provider);
|
|
23243
23515
|
}
|
|
@@ -23303,8 +23575,8 @@ var init_codex_catalog = __esm({
|
|
|
23303
23575
|
|
|
23304
23576
|
// server/drivers/codex-instructions.ts
|
|
23305
23577
|
import { createHash as createHash6 } from "node:crypto";
|
|
23306
|
-
import { mkdirSync as
|
|
23307
|
-
import { join as
|
|
23578
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync8 } from "node:fs";
|
|
23579
|
+
import { join as join19 } from "node:path";
|
|
23308
23580
|
function codexDeveloperInstructions(config2, botInstructions) {
|
|
23309
23581
|
if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) {
|
|
23310
23582
|
throw new Error("Codex returned no effective configuration; cannot safely update bot instructions.");
|
|
@@ -23318,8 +23590,8 @@ function codexDeveloperInstructions(config2, botInstructions) {
|
|
|
23318
23590
|
${configured}` : botInstructions;
|
|
23319
23591
|
}
|
|
23320
23592
|
async function syncCodexInstructions(key, nativeThreadId, instructions, resumed, request) {
|
|
23321
|
-
const directory =
|
|
23322
|
-
const path3 =
|
|
23593
|
+
const directory = join19(DATA_DIR, "codex-instructions");
|
|
23594
|
+
const path3 = join19(directory, `${digest(JSON.stringify([key, nativeThreadId]))}.sha256`);
|
|
23323
23595
|
const fingerprint = digest(instructions);
|
|
23324
23596
|
let previous;
|
|
23325
23597
|
try {
|
|
@@ -23348,7 +23620,7 @@ async function syncCodexInstructions(key, nativeThreadId, instructions, resumed,
|
|
|
23348
23620
|
}
|
|
23349
23621
|
}
|
|
23350
23622
|
if (!resumed || previous !== fingerprint) {
|
|
23351
|
-
|
|
23623
|
+
mkdirSync7(directory, { recursive: true });
|
|
23352
23624
|
writeFileAtomic(path3, fingerprint, { mode: 384 });
|
|
23353
23625
|
}
|
|
23354
23626
|
}
|
|
@@ -23366,18 +23638,18 @@ var init_codex_instructions = __esm({
|
|
|
23366
23638
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
23367
23639
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
23368
23640
|
import { homedir as homedir11 } from "node:os";
|
|
23369
|
-
import { basename as basename6, dirname as dirname9, isAbsolute as isAbsolute5, join as
|
|
23370
|
-
import { stripVTControlCharacters as
|
|
23641
|
+
import { basename as basename6, dirname as dirname9, isAbsolute as isAbsolute5, join as join20, resolve as resolve8 } from "node:path";
|
|
23642
|
+
import { stripVTControlCharacters as stripVTControlCharacters5 } from "node:util";
|
|
23371
23643
|
function canonicalPath2(path3) {
|
|
23372
23644
|
try {
|
|
23373
23645
|
return realpathSync2(path3);
|
|
23374
23646
|
} catch {
|
|
23375
23647
|
const parent = dirname9(path3);
|
|
23376
|
-
return parent === path3 ? path3 :
|
|
23648
|
+
return parent === path3 ? path3 : join20(canonicalPath2(parent), basename6(path3));
|
|
23377
23649
|
}
|
|
23378
23650
|
}
|
|
23379
23651
|
function codexDevicePrompt(output) {
|
|
23380
|
-
const clean =
|
|
23652
|
+
const clean = stripVTControlCharacters5(output);
|
|
23381
23653
|
const lines = clean.split(/\r?\n/).slice(0, -1).map((line) => line.trim());
|
|
23382
23654
|
if (!lines.some((line) => /^https:\/\/auth\.openai\.com\/codex\/device\/?$/.test(line))) return null;
|
|
23383
23655
|
const userCode = lines.find((line) => /^[A-Z0-9]{4,8}-[A-Z0-9]{4,8}$/.test(line));
|
|
@@ -23395,16 +23667,17 @@ function loginFailure(output) {
|
|
|
23395
23667
|
}
|
|
23396
23668
|
return "ChatGPT sign-in did not finish. Check the server's connection and that device-code login is enabled in ChatGPT, then try again.";
|
|
23397
23669
|
}
|
|
23398
|
-
var DEVICE_URL,
|
|
23670
|
+
var DEVICE_URL, MAX_OUTPUT3, authenticatingHomes2, CodexDeviceAuthController;
|
|
23399
23671
|
var init_codex_device_auth = __esm({
|
|
23400
23672
|
"server/drivers/codex-device-auth.ts"() {
|
|
23401
23673
|
"use strict";
|
|
23402
23674
|
init_procs();
|
|
23403
23675
|
DEVICE_URL = "https://auth.openai.com/codex/device";
|
|
23404
|
-
|
|
23676
|
+
MAX_OUTPUT3 = 16384;
|
|
23405
23677
|
authenticatingHomes2 = /* @__PURE__ */ new Set();
|
|
23406
23678
|
CodexDeviceAuthController = class {
|
|
23407
23679
|
flow = null;
|
|
23680
|
+
command = null;
|
|
23408
23681
|
disposed = false;
|
|
23409
23682
|
options;
|
|
23410
23683
|
constructor(options) {
|
|
@@ -23423,7 +23696,7 @@ var init_codex_device_auth = __esm({
|
|
|
23423
23696
|
if (!isAbsolute5(home) || env.CODEX_HOME && !isAbsolute5(env.CODEX_HOME)) {
|
|
23424
23697
|
throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing in.");
|
|
23425
23698
|
}
|
|
23426
|
-
const homeKey = canonicalPath2(resolve8(env.CODEX_HOME ||
|
|
23699
|
+
const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join20(home, ".codex")));
|
|
23427
23700
|
if (authenticatingHomes2.has(homeKey)) {
|
|
23428
23701
|
throw new Error("A ChatGPT sign-in is already running for this server account. Finish or cancel it before starting another.");
|
|
23429
23702
|
}
|
|
@@ -23480,12 +23753,92 @@ var init_codex_device_auth = __esm({
|
|
|
23480
23753
|
if (this.flow?.status.phase === "waiting") this.finish(this.flow, "cancelled", "ChatGPT sign-in cancelled.");
|
|
23481
23754
|
await this.flow?.stopping;
|
|
23482
23755
|
if (this.flow?.terminationFailed) throw new Error(this.flow.status.message);
|
|
23756
|
+
if (this.command && !await this.stopChild(this.command)) {
|
|
23757
|
+
throw new Error("Codex could not be stopped on this server. Ask the server administrator to stop the account command before trying again.");
|
|
23758
|
+
}
|
|
23483
23759
|
}
|
|
23484
23760
|
async dispose() {
|
|
23485
23761
|
this.disposed = true;
|
|
23486
23762
|
await this.cancel();
|
|
23487
23763
|
this.flow = null;
|
|
23488
23764
|
}
|
|
23765
|
+
/** Remove the ChatGPT sign-in Codex stores for this server account so a
|
|
23766
|
+
* different account can connect. A sign-in in progress is never pulled
|
|
23767
|
+
* away underneath the browser completing it. */
|
|
23768
|
+
async signOut() {
|
|
23769
|
+
if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
|
|
23770
|
+
if (this.flow?.status.phase === "waiting") throw new Error("Finish or cancel the ChatGPT sign-in in progress before signing out.");
|
|
23771
|
+
await this.flow?.stopping;
|
|
23772
|
+
if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
|
|
23773
|
+
const env = this.options.environment();
|
|
23774
|
+
const home = env.HOME || env.USERPROFILE || homedir11();
|
|
23775
|
+
if (!isAbsolute5(home) || env.CODEX_HOME && !isAbsolute5(env.CODEX_HOME)) {
|
|
23776
|
+
throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing out.");
|
|
23777
|
+
}
|
|
23778
|
+
const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join20(home, ".codex")));
|
|
23779
|
+
if (authenticatingHomes2.has(homeKey)) {
|
|
23780
|
+
throw new Error("A ChatGPT sign-in is running for this server account. Finish or cancel it before signing out.");
|
|
23781
|
+
}
|
|
23782
|
+
authenticatingHomes2.add(homeKey);
|
|
23783
|
+
try {
|
|
23784
|
+
const before = await this.exec(["login", "status"], env, home);
|
|
23785
|
+
if (before.code === 1 && /^not logged in\b/im.test(before.output)) return;
|
|
23786
|
+
if (before.code !== 0 || !/^logged in.*chatgpt\b/im.test(before.output)) {
|
|
23787
|
+
throw new Error("Codex did not confirm a ChatGPT sign-in. Other authentication methods will not be removed; ask the server administrator to check the account.");
|
|
23788
|
+
}
|
|
23789
|
+
const logout = await this.exec(["logout"], env, home);
|
|
23790
|
+
if (logout.code !== 0) throw new Error("Codex could not remove the sign-in on this server. Check the server's Codex installation and try again.");
|
|
23791
|
+
const status = await this.exec(["login", "status"], env, home);
|
|
23792
|
+
if (status.code !== 1 || !/^not logged in\b/im.test(status.output)) {
|
|
23793
|
+
throw new Error("Codex still reports a sign-in on this server. Update Codex and check its login status before trying again.");
|
|
23794
|
+
}
|
|
23795
|
+
} finally {
|
|
23796
|
+
const child = this.command;
|
|
23797
|
+
if (child && child.exitCode === null && child.signalCode === null) {
|
|
23798
|
+
child.once("close", () => authenticatingHomes2.delete(homeKey));
|
|
23799
|
+
} else authenticatingHomes2.delete(homeKey);
|
|
23800
|
+
}
|
|
23801
|
+
}
|
|
23802
|
+
/** One bounded, non-interactive Codex command. Its output stays here;
|
|
23803
|
+
* callers see an exit code and a status-line match, never the text. */
|
|
23804
|
+
exec(args, env, cwd) {
|
|
23805
|
+
return new Promise((resolveExec, rejectExec) => {
|
|
23806
|
+
if (this.disposed) {
|
|
23807
|
+
rejectExec(new Error("This provider was removed. Refresh Settings before signing out."));
|
|
23808
|
+
return;
|
|
23809
|
+
}
|
|
23810
|
+
let child;
|
|
23811
|
+
try {
|
|
23812
|
+
child = spawnCli(this.options.cli, args, { env: { ...env, NO_COLOR: "1" }, cwd, stdio: ["pipe", "pipe", "pipe"] });
|
|
23813
|
+
} catch {
|
|
23814
|
+
rejectExec(new Error("Codex could not start on this server. Install or update the configured Codex CLI, then try again."));
|
|
23815
|
+
return;
|
|
23816
|
+
}
|
|
23817
|
+
this.command = child;
|
|
23818
|
+
child.stdin.end();
|
|
23819
|
+
let output = "";
|
|
23820
|
+
const receive = (chunk) => {
|
|
23821
|
+
if (output.length < MAX_OUTPUT3) output += chunk.toString("utf8").slice(0, MAX_OUTPUT3 - output.length);
|
|
23822
|
+
};
|
|
23823
|
+
child.stdout.on("data", receive);
|
|
23824
|
+
child.stderr.on("data", receive);
|
|
23825
|
+
const timer = setTimeout(() => {
|
|
23826
|
+
void this.stopChild(child).catch(() => false).then((stopped) => {
|
|
23827
|
+
if (!stopped) rejectExec(new Error("Codex could not be stopped on this server. Ask the server administrator to stop the account command before trying again."));
|
|
23828
|
+
});
|
|
23829
|
+
}, this.options.startupTimeoutMs ?? 3e4);
|
|
23830
|
+
timer.unref();
|
|
23831
|
+
child.once("error", (error51) => {
|
|
23832
|
+
clearTimeout(timer);
|
|
23833
|
+
rejectExec(new Error(error51.code === "ENOENT" ? "Codex is not installed on this server. Run npm install -g @openai/codex@latest on the server, then try again." : "Codex could not start on this server. Check the configured CLI path and its executable permissions."));
|
|
23834
|
+
});
|
|
23835
|
+
child.once("close", (code) => {
|
|
23836
|
+
clearTimeout(timer);
|
|
23837
|
+
if (this.command === child) this.command = null;
|
|
23838
|
+
resolveExec({ code, output: stripVTControlCharacters5(output) });
|
|
23839
|
+
});
|
|
23840
|
+
});
|
|
23841
|
+
}
|
|
23489
23842
|
run(flow, args, env, cwd, done, parsePrompt = false) {
|
|
23490
23843
|
if (flow.status.phase !== "waiting") return;
|
|
23491
23844
|
let child;
|
|
@@ -23500,7 +23853,7 @@ var init_codex_device_auth = __esm({
|
|
|
23500
23853
|
let output = "";
|
|
23501
23854
|
const receive = (chunk) => {
|
|
23502
23855
|
if (flow.status.phase !== "waiting") return;
|
|
23503
|
-
if (output.length + chunk.length >
|
|
23856
|
+
if (output.length + chunk.length > MAX_OUTPUT3) {
|
|
23504
23857
|
this.finish(flow, "failed", "Codex returned an unexpected sign-in response. Update the server's Codex CLI and try again.");
|
|
23505
23858
|
return;
|
|
23506
23859
|
}
|
|
@@ -23521,7 +23874,7 @@ var init_codex_device_auth = __esm({
|
|
|
23521
23874
|
});
|
|
23522
23875
|
child.once("close", (code) => {
|
|
23523
23876
|
if (flow.child === child) flow.child = null;
|
|
23524
|
-
if (flow.status.phase === "waiting") done(code,
|
|
23877
|
+
if (flow.status.phase === "waiting") done(code, stripVTControlCharacters5(output));
|
|
23525
23878
|
output = "";
|
|
23526
23879
|
});
|
|
23527
23880
|
}
|
|
@@ -23540,7 +23893,7 @@ var init_codex_device_auth = __esm({
|
|
|
23540
23893
|
if (phase === "succeeded") flow.resolve({ ...flow.status, phase });
|
|
23541
23894
|
else flow.reject(new Error(message2 ?? "ChatGPT sign-in did not finish."));
|
|
23542
23895
|
}
|
|
23543
|
-
flow.stopping = this.stopChild(flow).catch(() => false).then((stopped) => {
|
|
23896
|
+
flow.stopping = this.stopChild(flow.child).catch(() => false).then((stopped) => {
|
|
23544
23897
|
const release = () => authenticatingHomes2.delete(flow.homeKey);
|
|
23545
23898
|
if (stopped) {
|
|
23546
23899
|
release();
|
|
@@ -23555,8 +23908,7 @@ var init_codex_device_auth = __esm({
|
|
|
23555
23908
|
if (phase === "succeeded") void this.options.onAuthenticated?.().catch(() => {
|
|
23556
23909
|
});
|
|
23557
23910
|
}
|
|
23558
|
-
async stopChild(
|
|
23559
|
-
const child = flow.child;
|
|
23911
|
+
async stopChild(child) {
|
|
23560
23912
|
if (!child || await killCliTree(child, this.options.terminateTimeoutMs ?? 1500)) return true;
|
|
23561
23913
|
if (process.platform !== "win32" && child.pid) {
|
|
23562
23914
|
try {
|
|
@@ -23580,9 +23932,122 @@ var init_codex_device_auth = __esm({
|
|
|
23580
23932
|
}
|
|
23581
23933
|
});
|
|
23582
23934
|
|
|
23583
|
-
// server/drivers/codex.ts
|
|
23584
|
-
import { existsSync as existsSync7 } from "node:fs";
|
|
23935
|
+
// server/drivers/codex-identity.ts
|
|
23585
23936
|
import { homedir as homedir12 } from "node:os";
|
|
23937
|
+
import { isAbsolute as isAbsolute6, join as join21, resolve as resolve9 } from "node:path";
|
|
23938
|
+
function codexHome2(env) {
|
|
23939
|
+
if (env.CODEX_HOME) return isAbsolute6(env.CODEX_HOME) ? resolve9(env.CODEX_HOME) : null;
|
|
23940
|
+
const home = env.HOME || env.USERPROFILE || homedir12();
|
|
23941
|
+
return isAbsolute6(home) ? join21(home, ".codex") : null;
|
|
23942
|
+
}
|
|
23943
|
+
async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
|
|
23944
|
+
const cwd = env.HOME || env.USERPROFILE || homedir12();
|
|
23945
|
+
if (!isAbsolute6(cwd) || !codexHome2(env)) return null;
|
|
23946
|
+
return new Promise((resolveEmail) => {
|
|
23947
|
+
let child;
|
|
23948
|
+
try {
|
|
23949
|
+
child = spawnCli(cli, ["app-server"], { cwd, env, stdio: ["pipe", "pipe", "pipe"] });
|
|
23950
|
+
} catch {
|
|
23951
|
+
resolveEmail(null);
|
|
23952
|
+
return;
|
|
23953
|
+
}
|
|
23954
|
+
let finishing = false;
|
|
23955
|
+
let buffer = "";
|
|
23956
|
+
let outputBytes = 0;
|
|
23957
|
+
let initialized = false;
|
|
23958
|
+
const finish = async (email3) => {
|
|
23959
|
+
if (finishing) return;
|
|
23960
|
+
finishing = true;
|
|
23961
|
+
clearTimeout(timer);
|
|
23962
|
+
let stopped = await killCliTree(child, 1e3);
|
|
23963
|
+
if (!stopped && child.pid) {
|
|
23964
|
+
try {
|
|
23965
|
+
if (process.platform === "win32") child.kill("SIGKILL");
|
|
23966
|
+
else process.kill(-child.pid, "SIGKILL");
|
|
23967
|
+
} catch {
|
|
23968
|
+
try {
|
|
23969
|
+
child.kill("SIGKILL");
|
|
23970
|
+
} catch {
|
|
23971
|
+
}
|
|
23972
|
+
}
|
|
23973
|
+
stopped = await killCliTree(child, 1e3);
|
|
23974
|
+
}
|
|
23975
|
+
resolveEmail(stopped ? email3 : null);
|
|
23976
|
+
};
|
|
23977
|
+
const timer = setTimeout(() => {
|
|
23978
|
+
void finish(null);
|
|
23979
|
+
}, timeoutMs);
|
|
23980
|
+
timer.unref();
|
|
23981
|
+
const send = (message2) => {
|
|
23982
|
+
try {
|
|
23983
|
+
child.stdin.write(`${JSON.stringify(message2)}
|
|
23984
|
+
`);
|
|
23985
|
+
} catch {
|
|
23986
|
+
void finish(null);
|
|
23987
|
+
}
|
|
23988
|
+
};
|
|
23989
|
+
child.stdin.on("error", () => {
|
|
23990
|
+
void finish(null);
|
|
23991
|
+
});
|
|
23992
|
+
child.stderr.resume();
|
|
23993
|
+
child.on("error", () => {
|
|
23994
|
+
void finish(null);
|
|
23995
|
+
});
|
|
23996
|
+
child.on("close", () => {
|
|
23997
|
+
void finish(null);
|
|
23998
|
+
});
|
|
23999
|
+
child.stdout.setEncoding("utf8");
|
|
24000
|
+
child.stdout.on("data", (chunk) => {
|
|
24001
|
+
if (finishing) return;
|
|
24002
|
+
outputBytes += Buffer.byteLength(chunk);
|
|
24003
|
+
if (outputBytes > MAX_OUTPUT4) {
|
|
24004
|
+
void finish(null);
|
|
24005
|
+
return;
|
|
24006
|
+
}
|
|
24007
|
+
buffer += chunk;
|
|
24008
|
+
let newline;
|
|
24009
|
+
while (!finishing && (newline = buffer.indexOf("\n")) !== -1) {
|
|
24010
|
+
const line = buffer.slice(0, newline);
|
|
24011
|
+
buffer = buffer.slice(newline + 1);
|
|
24012
|
+
if (!line.trim()) continue;
|
|
24013
|
+
let message2;
|
|
24014
|
+
try {
|
|
24015
|
+
message2 = JSON.parse(line);
|
|
24016
|
+
} catch {
|
|
24017
|
+
void finish(null);
|
|
24018
|
+
return;
|
|
24019
|
+
}
|
|
24020
|
+
if (!initialized && message2?.id === 1) {
|
|
24021
|
+
if (message2.error || !message2.result) {
|
|
24022
|
+
void finish(null);
|
|
24023
|
+
return;
|
|
24024
|
+
}
|
|
24025
|
+
initialized = true;
|
|
24026
|
+
send({ method: "initialized", params: {} });
|
|
24027
|
+
send({ id: 2, method: "account/read", params: { refreshToken: false } });
|
|
24028
|
+
} else if (initialized && message2?.id === 2) {
|
|
24029
|
+
const account = message2.error ? null : message2.result?.account;
|
|
24030
|
+
const email3 = account?.type === "chatgpt" ? account.email : null;
|
|
24031
|
+
void finish(typeof email3 === "string" && email3.length <= 254 && EMAIL.test(email3) && !/[\p{Cc}\p{Cf}]/u.test(email3) ? email3 : null);
|
|
24032
|
+
}
|
|
24033
|
+
}
|
|
24034
|
+
});
|
|
24035
|
+
send({ id: 1, method: "initialize", params: { clientInfo: { name: "openmausbot", version: "1" } } });
|
|
24036
|
+
});
|
|
24037
|
+
}
|
|
24038
|
+
var MAX_OUTPUT4, EMAIL;
|
|
24039
|
+
var init_codex_identity = __esm({
|
|
24040
|
+
"server/drivers/codex-identity.ts"() {
|
|
24041
|
+
"use strict";
|
|
24042
|
+
init_procs();
|
|
24043
|
+
MAX_OUTPUT4 = 16384;
|
|
24044
|
+
EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
24045
|
+
}
|
|
24046
|
+
});
|
|
24047
|
+
|
|
24048
|
+
// server/drivers/codex.ts
|
|
24049
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
24050
|
+
import { homedir as homedir13 } from "node:os";
|
|
23586
24051
|
function codexPredatesAstra(version2) {
|
|
23587
24052
|
const value = version2.trim();
|
|
23588
24053
|
const match = /\bcodex-cli\s+v?(\d+)\.(\d+)\.(\d+)(?:[-+][0-9a-z.-]+)?(?![\d.])\b/i.exec(value) ?? /^v?(\d+)\.(\d+)\.(\d+)(?:[-+][0-9a-z.-]+)?$/i.exec(value);
|
|
@@ -23598,7 +24063,7 @@ function codexPredatesAstra(version2) {
|
|
|
23598
24063
|
function codexUpdateCommand(cli, platform = process.platform) {
|
|
23599
24064
|
if (cli === "codex") return "codex update";
|
|
23600
24065
|
const trimmed = cli.trim();
|
|
23601
|
-
const tokens = trimmed.includes(" ") &&
|
|
24066
|
+
const tokens = trimmed.includes(" ") && existsSync8(trimmed) ? [trimmed] : splitCliString(trimmed);
|
|
23602
24067
|
const quote = platform === "win32" ? (token) => `'${token.replaceAll("'", "''")}'` : (token) => `'${token.replaceAll("'", `'\\''`)}'`;
|
|
23603
24068
|
const command = (tokens.length > 0 ? tokens : [trimmed]).map(quote).join(" ");
|
|
23604
24069
|
return platform === "win32" ? `& ${command} update` : `${command} update`;
|
|
@@ -23852,6 +24317,7 @@ var init_codex = __esm({
|
|
|
23852
24317
|
init_native();
|
|
23853
24318
|
init_codex_instructions();
|
|
23854
24319
|
init_codex_device_auth();
|
|
24320
|
+
init_codex_identity();
|
|
23855
24321
|
init_codex_catalog();
|
|
23856
24322
|
DRIVER_KIND3 = "codex";
|
|
23857
24323
|
ASTRA_MODEL_ID = "gpt-6-astra";
|
|
@@ -23985,7 +24451,7 @@ var init_codex = __esm({
|
|
|
23985
24451
|
);
|
|
23986
24452
|
}
|
|
23987
24453
|
const child = spawnCli(config2.cli, appServerArgs, {
|
|
23988
|
-
cwd: turn.cwd ??
|
|
24454
|
+
cwd: turn.cwd ?? homedir13(),
|
|
23989
24455
|
env,
|
|
23990
24456
|
stdio: ["pipe", "pipe", "pipe"]
|
|
23991
24457
|
});
|
|
@@ -24013,7 +24479,7 @@ var init_codex = __esm({
|
|
|
24013
24479
|
msg: codexNativeLogMessage(obj)
|
|
24014
24480
|
});
|
|
24015
24481
|
};
|
|
24016
|
-
const request = (method, params, timeoutMs = 6e4) => new Promise((
|
|
24482
|
+
const request = (method, params, timeoutMs = 6e4) => new Promise((resolve13, reject) => {
|
|
24017
24483
|
const id = nextId++;
|
|
24018
24484
|
if (method === "config/read") sensitiveResponseIds.add(id);
|
|
24019
24485
|
const timer = setTimeout(() => {
|
|
@@ -24023,7 +24489,7 @@ var init_codex = __esm({
|
|
|
24023
24489
|
rpcPending.set(id, {
|
|
24024
24490
|
resolve: (v) => {
|
|
24025
24491
|
clearTimeout(timer);
|
|
24026
|
-
|
|
24492
|
+
resolve13(v);
|
|
24027
24493
|
},
|
|
24028
24494
|
reject: (e) => {
|
|
24029
24495
|
clearTimeout(timer);
|
|
@@ -24291,7 +24757,7 @@ var init_codex = __esm({
|
|
|
24291
24757
|
let effectiveConfig;
|
|
24292
24758
|
try {
|
|
24293
24759
|
const configured = await request("config/read", {
|
|
24294
|
-
cwd: turn.cwd ??
|
|
24760
|
+
cwd: turn.cwd ?? homedir13(),
|
|
24295
24761
|
includeLayers: false
|
|
24296
24762
|
});
|
|
24297
24763
|
effectiveConfig = configured?.config;
|
|
@@ -24335,7 +24801,7 @@ var init_codex = __esm({
|
|
|
24335
24801
|
const selection = decodeCodexSelection(turn.model);
|
|
24336
24802
|
const startThread = () => request("thread/start", {
|
|
24337
24803
|
developerInstructions,
|
|
24338
|
-
cwd: turn.cwd ??
|
|
24804
|
+
cwd: turn.cwd ?? homedir13(),
|
|
24339
24805
|
model: selection.model,
|
|
24340
24806
|
...selection.modelProvider ? { modelProvider: selection.modelProvider } : {},
|
|
24341
24807
|
...approvalParams.thread,
|
|
@@ -24402,8 +24868,8 @@ var init_codex = __esm({
|
|
|
24402
24868
|
void settle(false, "shutdown_timeout");
|
|
24403
24869
|
return;
|
|
24404
24870
|
}
|
|
24405
|
-
await new Promise((
|
|
24406
|
-
const timer = setTimeout(
|
|
24871
|
+
await new Promise((resolve13) => {
|
|
24872
|
+
const timer = setTimeout(resolve13, Math.max(1, Math.round(delayMs * retryScale)));
|
|
24407
24873
|
timer.unref?.();
|
|
24408
24874
|
});
|
|
24409
24875
|
if (!stopRequested) {
|
|
@@ -24431,28 +24897,30 @@ var init_codex = __esm({
|
|
|
24431
24897
|
};
|
|
24432
24898
|
const snapshot = async () => {
|
|
24433
24899
|
const env = childEnv();
|
|
24434
|
-
const version2 = await new Promise((
|
|
24900
|
+
const version2 = await new Promise((resolve13) => {
|
|
24435
24901
|
execCli(
|
|
24436
24902
|
config2.cli,
|
|
24437
24903
|
["--version"],
|
|
24438
24904
|
{ timeout: 8e3, env },
|
|
24439
|
-
(err, stdout2) =>
|
|
24905
|
+
(err, stdout2) => resolve13(err ? null : stdout2.trim())
|
|
24440
24906
|
);
|
|
24441
24907
|
});
|
|
24442
24908
|
if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
|
|
24443
|
-
const authenticated = await new Promise((
|
|
24909
|
+
const authenticated = await new Promise((resolve13) => {
|
|
24444
24910
|
execCli(
|
|
24445
24911
|
config2.cli,
|
|
24446
24912
|
["login", "status"],
|
|
24447
24913
|
{ timeout: 8e3, env },
|
|
24448
|
-
(err, stdout2, stderr) =>
|
|
24914
|
+
(err, stdout2, stderr) => resolve13(!err && /^logged in\b/im.test(`${stdout2}
|
|
24449
24915
|
${stderr ?? ""}`))
|
|
24450
24916
|
);
|
|
24451
24917
|
});
|
|
24918
|
+
const email3 = authenticated ? await codexAccountEmail(config2.cli, env) : null;
|
|
24452
24919
|
return {
|
|
24453
24920
|
state: "available",
|
|
24454
24921
|
version: version2,
|
|
24455
24922
|
authenticated,
|
|
24923
|
+
...email3 ? { account: { email: email3 } } : {},
|
|
24456
24924
|
update: codexAstraUpdate(version2, models, config2.cli),
|
|
24457
24925
|
billing: "subscription"
|
|
24458
24926
|
};
|
|
@@ -24469,6 +24937,7 @@ ${stderr ?? ""}`))
|
|
|
24469
24937
|
startAuthentication: () => authentication.start(),
|
|
24470
24938
|
getAuthentication: (flowId) => authentication.get(flowId),
|
|
24471
24939
|
cancelAuthentication: () => authentication.cancel(),
|
|
24940
|
+
signOut: () => authentication.signOut(),
|
|
24472
24941
|
snapshot,
|
|
24473
24942
|
adapter: {
|
|
24474
24943
|
provider: DRIVER_KIND3,
|
|
@@ -24792,12 +25261,12 @@ var init_grok = __esm({
|
|
|
24792
25261
|
});
|
|
24793
25262
|
|
|
24794
25263
|
// server/drivers/acp/grok.ts
|
|
24795
|
-
import { existsSync as
|
|
24796
|
-
import { homedir as
|
|
24797
|
-
import { join as
|
|
25264
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
25265
|
+
import { homedir as homedir14 } from "node:os";
|
|
25266
|
+
import { join as join22 } from "node:path";
|
|
24798
25267
|
function grokHome(env) {
|
|
24799
25268
|
if (env.GROK_HOME) return env.GROK_HOME;
|
|
24800
|
-
return
|
|
25269
|
+
return join22(env.HOME || env.USERPROFILE || homedir14(), ".grok");
|
|
24801
25270
|
}
|
|
24802
25271
|
function unquote2(raw) {
|
|
24803
25272
|
const value = raw.trim();
|
|
@@ -24807,7 +25276,7 @@ function unquote2(raw) {
|
|
|
24807
25276
|
return value;
|
|
24808
25277
|
}
|
|
24809
25278
|
function readGrokModelCatalog(env = process.env) {
|
|
24810
|
-
const path3 =
|
|
25279
|
+
const path3 = join22(grokHome(env), "config.toml");
|
|
24811
25280
|
let text2 = "";
|
|
24812
25281
|
try {
|
|
24813
25282
|
text2 = readFileSync9(path3, "utf8");
|
|
@@ -24880,7 +25349,7 @@ function ensureGrokInjectSlug(modelId, env = process.env) {
|
|
|
24880
25349
|
if (!inject) return modelId;
|
|
24881
25350
|
const host = localHost(inject.host);
|
|
24882
25351
|
if (!host) return modelId;
|
|
24883
|
-
const path3 =
|
|
25352
|
+
const path3 = join22(grokHome(env), "config.toml");
|
|
24884
25353
|
let text2 = "";
|
|
24885
25354
|
try {
|
|
24886
25355
|
text2 = readFileSync9(path3, "utf8");
|
|
@@ -25015,7 +25484,7 @@ var init_grok2 = __esm({
|
|
|
25015
25484
|
// an unauthenticated CLI is a user action, not something to paper over.
|
|
25016
25485
|
pickAuthMethod: (methods) => methods.some((m) => m.id === "cached_token") ? "cached_token" : null,
|
|
25017
25486
|
authFailure: "fail",
|
|
25018
|
-
isAuthenticated: () =>
|
|
25487
|
+
isAuthenticated: () => existsSync9(join22(homedir14(), ".grok", "auth.json")),
|
|
25019
25488
|
// `--append-system-prompt`/`--rules` are accepted by the CLI but do NOT
|
|
25020
25489
|
// reach the agent-stdio system prompt (verified against 1.0.0), so the
|
|
25021
25490
|
// persona is prepended codex-style.
|
|
@@ -25028,12 +25497,12 @@ ${turn.text}` : turn.text
|
|
|
25028
25497
|
});
|
|
25029
25498
|
|
|
25030
25499
|
// server/drivers/acp/gemini.ts
|
|
25031
|
-
import { existsSync as
|
|
25032
|
-
import { homedir as
|
|
25033
|
-
import { join as
|
|
25500
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
|
|
25501
|
+
import { homedir as homedir15 } from "node:os";
|
|
25502
|
+
import { join as join23 } from "node:path";
|
|
25034
25503
|
function liveOauthCredential() {
|
|
25035
25504
|
try {
|
|
25036
|
-
const creds = JSON.parse(readFileSync10(
|
|
25505
|
+
const creds = JSON.parse(readFileSync10(join23(homedir15(), ".gemini", "oauth_creds.json"), "utf8"));
|
|
25037
25506
|
if (typeof creds.access_token !== "string" || creds.access_token.trim().length === 0) return false;
|
|
25038
25507
|
const hasRefresh = typeof creds.refresh_token === "string" && creds.refresh_token.trim().length > 0;
|
|
25039
25508
|
if (creds.expiry_date !== void 0) {
|
|
@@ -25046,7 +25515,7 @@ function liveOauthCredential() {
|
|
|
25046
25515
|
}
|
|
25047
25516
|
}
|
|
25048
25517
|
function geminiIsAuthenticated(env) {
|
|
25049
|
-
return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) ||
|
|
25518
|
+
return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync10(join23(homedir15(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
|
|
25050
25519
|
}
|
|
25051
25520
|
var AUTH_PREFERENCE, nonBlank, support3, GeminiAgentDriver;
|
|
25052
25521
|
var init_gemini = __esm({
|
|
@@ -25088,17 +25557,17 @@ ${turn.text}` : turn.text
|
|
|
25088
25557
|
});
|
|
25089
25558
|
|
|
25090
25559
|
// server/drivers/acp/kimi.ts
|
|
25091
|
-
import { existsSync as
|
|
25092
|
-
import { homedir as
|
|
25093
|
-
import { join as
|
|
25560
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
|
|
25561
|
+
import { homedir as homedir16 } from "node:os";
|
|
25562
|
+
import { join as join24 } from "node:path";
|
|
25094
25563
|
function isLocalInjectAlias(slug) {
|
|
25095
25564
|
return LOCAL_PROVIDER_PREFIXES.some((prefix) => slug.startsWith(prefix));
|
|
25096
25565
|
}
|
|
25097
25566
|
function kimiDataRoot(env) {
|
|
25098
|
-
return env.KIMI_CODE_HOME ||
|
|
25567
|
+
return env.KIMI_CODE_HOME || join24(env.HOME || env.USERPROFILE || homedir16(), ".kimi-code");
|
|
25099
25568
|
}
|
|
25100
25569
|
function credentialsPath(env) {
|
|
25101
|
-
return
|
|
25570
|
+
return join24(kimiDataRoot(env), "credentials", "kimi-code.json");
|
|
25102
25571
|
}
|
|
25103
25572
|
function quoteToml2(value) {
|
|
25104
25573
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
@@ -25385,8 +25854,8 @@ function ensureKimiInjectAlias(modelId, env = process.env) {
|
|
|
25385
25854
|
if (!host) return modelId;
|
|
25386
25855
|
const alias = `${inject.host}/${inject.model.replace(/\//g, "-")}`;
|
|
25387
25856
|
const dataRoot = kimiDataRoot(env);
|
|
25388
|
-
|
|
25389
|
-
const path3 =
|
|
25857
|
+
mkdirSync8(dataRoot, { recursive: true });
|
|
25858
|
+
const path3 = join24(dataRoot, "config.toml");
|
|
25390
25859
|
let text2 = "";
|
|
25391
25860
|
try {
|
|
25392
25861
|
text2 = readFileSync11(path3, "utf8");
|
|
@@ -25451,7 +25920,7 @@ function readKimiModelCatalog(env) {
|
|
|
25451
25920
|
const dataRoot = kimiDataRoot(env);
|
|
25452
25921
|
let text2 = "";
|
|
25453
25922
|
try {
|
|
25454
|
-
text2 = readFileSync11(
|
|
25923
|
+
text2 = readFileSync11(join24(dataRoot, "config.toml"), "utf8");
|
|
25455
25924
|
} catch {
|
|
25456
25925
|
return STATIC_KIMI_MODELS;
|
|
25457
25926
|
}
|
|
@@ -25560,7 +26029,7 @@ var init_kimi = __esm({
|
|
|
25560
26029
|
authFailure: "continue",
|
|
25561
26030
|
// Match the child CLI's own data-root precedence. A custom instance HOME or
|
|
25562
26031
|
// KIMI_CODE_HOME must not be checked against the server user's home instead.
|
|
25563
|
-
isAuthenticated: (env) =>
|
|
26032
|
+
isAuthenticated: (env) => existsSync11(credentialsPath(env)),
|
|
25564
26033
|
buildPromptText: (turn) => turn.system ? `${turn.system}
|
|
25565
26034
|
|
|
25566
26035
|
${turn.text}` : turn.text
|
|
@@ -25570,19 +26039,19 @@ ${turn.text}` : turn.text
|
|
|
25570
26039
|
});
|
|
25571
26040
|
|
|
25572
26041
|
// server/drivers/acp/droid.ts
|
|
25573
|
-
import { existsSync as
|
|
25574
|
-
import { homedir as
|
|
25575
|
-
import { join as
|
|
26042
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
26043
|
+
import { homedir as homedir17 } from "node:os";
|
|
26044
|
+
import { join as join25 } from "node:path";
|
|
25576
26045
|
function authFilePaths(env) {
|
|
25577
|
-
const home = env.FACTORY_HOME_OVERRIDE || env.HOME ||
|
|
25578
|
-
return AUTH_FILES.map((name) =>
|
|
26046
|
+
const home = env.FACTORY_HOME_OVERRIDE || env.HOME || homedir17();
|
|
26047
|
+
return AUTH_FILES.map((name) => join25(home, ".factory", name));
|
|
25579
26048
|
}
|
|
25580
26049
|
function droidInjectId(host, model) {
|
|
25581
26050
|
const safe = `${host}-${model}`.replace(/[^a-zA-Z0-9._+-]+/g, "-").replace(/-+/g, "-");
|
|
25582
26051
|
return `${INJECT_ID_PREFIX}${safe}`;
|
|
25583
26052
|
}
|
|
25584
26053
|
function factoryHome(env) {
|
|
25585
|
-
return env.FACTORY_HOME_OVERRIDE || env.HOME || env.USERPROFILE ||
|
|
26054
|
+
return env.FACTORY_HOME_OVERRIDE || env.HOME || env.USERPROFILE || homedir17();
|
|
25586
26055
|
}
|
|
25587
26056
|
function ensureDroidInjectModel(modelId, env = process.env) {
|
|
25588
26057
|
const inject = decodeInjectId(modelId);
|
|
@@ -25590,14 +26059,14 @@ function ensureDroidInjectModel(modelId, env = process.env) {
|
|
|
25590
26059
|
const host = localHost(inject.host);
|
|
25591
26060
|
if (!host) return modelId;
|
|
25592
26061
|
const id = droidInjectId(inject.host, inject.model);
|
|
25593
|
-
const dir =
|
|
25594
|
-
|
|
25595
|
-
const path3 =
|
|
26062
|
+
const dir = join25(factoryHome(env), ".factory");
|
|
26063
|
+
mkdirSync9(dir, { recursive: true });
|
|
26064
|
+
const path3 = join25(dir, "settings.json");
|
|
25596
26065
|
let settings2 = {};
|
|
25597
26066
|
try {
|
|
25598
26067
|
settings2 = JSON.parse(readFileSync12(path3, "utf8"));
|
|
25599
26068
|
} catch (error51) {
|
|
25600
|
-
if (
|
|
26069
|
+
if (existsSync12(path3)) throw error51;
|
|
25601
26070
|
}
|
|
25602
26071
|
const custom2 = Array.isArray(settings2.customModels) ? [...settings2.customModels] : [];
|
|
25603
26072
|
const match = custom2.find(
|
|
@@ -25628,11 +26097,11 @@ function ensureDroidInjectModel(modelId, env = process.env) {
|
|
|
25628
26097
|
function applyDroidLocalAuthEnv(env, modelId) {
|
|
25629
26098
|
if (!decodeInjectId(modelId)) return;
|
|
25630
26099
|
if (env.FACTORY_API_KEY?.trim()) return;
|
|
25631
|
-
if (authFilePaths(env).some(
|
|
26100
|
+
if (authFilePaths(env).some(existsSync12)) return;
|
|
25632
26101
|
env.FACTORY_API_KEY = "openmausbot-local";
|
|
25633
26102
|
}
|
|
25634
26103
|
function readSettings(env) {
|
|
25635
|
-
return JSON.parse(readFileSync12(
|
|
26104
|
+
return JSON.parse(readFileSync12(join25(factoryHome(env), ".factory", "settings.json"), "utf8"));
|
|
25636
26105
|
}
|
|
25637
26106
|
async function resolveModels(env) {
|
|
25638
26107
|
let catalog = MODELS3;
|
|
@@ -25719,7 +26188,7 @@ var init_droid = __esm({
|
|
|
25719
26188
|
// The signed-in CLI is the primary source; FACTORY_API_KEY is the fallback
|
|
25720
26189
|
// droid itself advertises, and it is checked last so an ambient key can
|
|
25721
26190
|
// never be what makes an otherwise logged-out instance look ready.
|
|
25722
|
-
isAuthenticated: (env) => authFilePaths(env).some(
|
|
26191
|
+
isAuthenticated: (env) => authFilePaths(env).some(existsSync12) || Boolean(env.FACTORY_API_KEY),
|
|
25723
26192
|
resolveModels,
|
|
25724
26193
|
resolveTurnModel: (model, env) => model ? ensureDroidInjectModel(model, env) : model,
|
|
25725
26194
|
applyTurnEnv: (env, { requestedModel }) => {
|
|
@@ -25901,10 +26370,10 @@ function decodeCursorAuthText(text2) {
|
|
|
25901
26370
|
return null;
|
|
25902
26371
|
}
|
|
25903
26372
|
function execText(run3, cli, args, env) {
|
|
25904
|
-
return new Promise((
|
|
26373
|
+
return new Promise((resolve13) => {
|
|
25905
26374
|
run3(cli, args, { timeout: EXEC_TIMEOUT_MS, env }, (err, stdout2) => {
|
|
25906
|
-
if (err) return
|
|
25907
|
-
|
|
26375
|
+
if (err) return resolve13(null);
|
|
26376
|
+
resolve13(String(stdout2 ?? ""));
|
|
25908
26377
|
});
|
|
25909
26378
|
});
|
|
25910
26379
|
}
|
|
@@ -26022,9 +26491,9 @@ ${turn.text}` : turn.text
|
|
|
26022
26491
|
});
|
|
26023
26492
|
|
|
26024
26493
|
// server/drivers/acp/opencode-go.ts
|
|
26025
|
-
import { existsSync as
|
|
26026
|
-
import { homedir as
|
|
26027
|
-
import { join as
|
|
26494
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
|
|
26495
|
+
import { homedir as homedir18 } from "node:os";
|
|
26496
|
+
import { join as join26 } from "node:path";
|
|
26028
26497
|
function labelForModel(id) {
|
|
26029
26498
|
return id.split(/[-_.]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
26030
26499
|
}
|
|
@@ -26098,7 +26567,7 @@ function parseOpenCodeModelsOutput(stdout2) {
|
|
|
26098
26567
|
return { default: (preferred ?? options[0]).id, options };
|
|
26099
26568
|
}
|
|
26100
26569
|
function runOpenCodeModels(cli, environment, verbose) {
|
|
26101
|
-
return new Promise((
|
|
26570
|
+
return new Promise((resolve13, reject) => {
|
|
26102
26571
|
execCli(
|
|
26103
26572
|
cli,
|
|
26104
26573
|
["models", ...verbose ? ["--verbose"] : []],
|
|
@@ -26108,7 +26577,7 @@ function runOpenCodeModels(cli, environment, verbose) {
|
|
|
26108
26577
|
reject(new Error(stderr?.trim() || error51.message, { cause: error51 }));
|
|
26109
26578
|
return;
|
|
26110
26579
|
}
|
|
26111
|
-
|
|
26580
|
+
resolve13(stdout2);
|
|
26112
26581
|
}
|
|
26113
26582
|
);
|
|
26114
26583
|
});
|
|
@@ -26124,8 +26593,8 @@ async function discoverOpenCodeModels(environment, cli = "opencode") {
|
|
|
26124
26593
|
}
|
|
26125
26594
|
}
|
|
26126
26595
|
function opencodeConfigDir(env) {
|
|
26127
|
-
const home = env.HOME || env.USERPROFILE ||
|
|
26128
|
-
return
|
|
26596
|
+
const home = env.HOME || env.USERPROFILE || homedir18();
|
|
26597
|
+
return join26(env.XDG_CONFIG_HOME || join26(home, ".config"), "opencode");
|
|
26129
26598
|
}
|
|
26130
26599
|
function ensureOpenCodeInjectModel(modelId, env = process.env) {
|
|
26131
26600
|
const inject = decodeInjectId(modelId);
|
|
@@ -26134,10 +26603,10 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
|
|
|
26134
26603
|
if (!host) return modelId;
|
|
26135
26604
|
const native = `${inject.host}/${inject.model}`;
|
|
26136
26605
|
const dir = opencodeConfigDir(env);
|
|
26137
|
-
|
|
26138
|
-
const path3 =
|
|
26606
|
+
mkdirSync10(dir, { recursive: true });
|
|
26607
|
+
const path3 = join26(dir, "opencode.json");
|
|
26139
26608
|
let config2 = { $schema: "https://opencode.ai/config.json" };
|
|
26140
|
-
if (
|
|
26609
|
+
if (existsSync13(path3)) {
|
|
26141
26610
|
try {
|
|
26142
26611
|
config2 = JSON.parse(readFileSync13(path3, "utf8"));
|
|
26143
26612
|
} catch {
|
|
@@ -26171,12 +26640,12 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
|
|
|
26171
26640
|
return native;
|
|
26172
26641
|
}
|
|
26173
26642
|
function storedAuthPaths(env) {
|
|
26174
|
-
const home = env.HOME || env.USERPROFILE ||
|
|
26643
|
+
const home = env.HOME || env.USERPROFILE || homedir18();
|
|
26175
26644
|
const roots = [
|
|
26176
|
-
env.XDG_DATA_HOME ||
|
|
26177
|
-
process.platform === "darwin" ?
|
|
26645
|
+
env.XDG_DATA_HOME || join26(home, ".local", "share"),
|
|
26646
|
+
process.platform === "darwin" ? join26(home, "Library", "Application Support") : process.platform === "win32" ? env.LOCALAPPDATA || join26(home, "AppData", "Local") : ""
|
|
26178
26647
|
].filter(Boolean);
|
|
26179
|
-
return [...new Set(roots)].map((root) =>
|
|
26648
|
+
return [...new Set(roots)].map((root) => join26(root, "opencode", "auth.json"));
|
|
26180
26649
|
}
|
|
26181
26650
|
function usableAuthEntry(parsed) {
|
|
26182
26651
|
return Object.values(parsed).some((auth) => {
|
|
@@ -26306,11 +26775,97 @@ ${turn.text}` : turn.text
|
|
|
26306
26775
|
});
|
|
26307
26776
|
|
|
26308
26777
|
// server/drivers/acp/qwen.ts
|
|
26309
|
-
import { chmodSync as chmodSync4, existsSync as
|
|
26310
|
-
import {
|
|
26311
|
-
import {
|
|
26778
|
+
import { chmodSync as chmodSync4, existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
|
|
26779
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
26780
|
+
import { homedir as homedir19 } from "node:os";
|
|
26781
|
+
import { join as join27 } from "node:path";
|
|
26312
26782
|
function qwenHome(env) {
|
|
26313
|
-
|
|
26783
|
+
const home = process.platform === "win32" ? env.USERPROFILE || env.HOME || homedir19() : env.HOME || env.USERPROFILE || homedir19();
|
|
26784
|
+
return join27(home, ".qwen");
|
|
26785
|
+
}
|
|
26786
|
+
function isRecord(value) {
|
|
26787
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
26788
|
+
}
|
|
26789
|
+
function qwenModelLabel(id, name) {
|
|
26790
|
+
if (!name || name.toLocaleLowerCase().endsWith(id.toLocaleLowerCase())) return id;
|
|
26791
|
+
return `${id} \u2014 ${name}`;
|
|
26792
|
+
}
|
|
26793
|
+
function readQwenRoutes(env) {
|
|
26794
|
+
let settings2;
|
|
26795
|
+
try {
|
|
26796
|
+
settings2 = JSON.parse(readFileSync14(join27(qwenHome(env), "settings.json"), "utf8"));
|
|
26797
|
+
} catch {
|
|
26798
|
+
return [];
|
|
26799
|
+
}
|
|
26800
|
+
if (!isRecord(settings2) || !isRecord(settings2.modelProviders)) return [];
|
|
26801
|
+
const routes = [];
|
|
26802
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26803
|
+
const mappings = isRecord(settings2.providerProtocol) ? settings2.providerProtocol : {};
|
|
26804
|
+
for (const [provider, rows] of Object.entries(settings2.modelProviders)) {
|
|
26805
|
+
const protocol = Object.hasOwn(mappings, provider) ? mappings[provider] : provider;
|
|
26806
|
+
if (typeof protocol !== "string" || !PROTOCOLS.has(protocol) || !Array.isArray(rows)) continue;
|
|
26807
|
+
for (const row of rows) {
|
|
26808
|
+
if (!isRecord(row) || typeof row.id !== "string") continue;
|
|
26809
|
+
const model = row.id;
|
|
26810
|
+
if (!model.trim()) continue;
|
|
26811
|
+
if (row.baseUrl !== void 0 && typeof row.baseUrl !== "string") continue;
|
|
26812
|
+
const baseUrl = typeof row.baseUrl === "string" && row.baseUrl ? row.baseUrl : void 0;
|
|
26813
|
+
if (baseUrl) {
|
|
26814
|
+
try {
|
|
26815
|
+
new URL(baseUrl);
|
|
26816
|
+
} catch {
|
|
26817
|
+
throw new Error("A Qwen model has an invalid endpoint. Fix its baseUrl in Qwen settings and refresh models.");
|
|
26818
|
+
}
|
|
26819
|
+
}
|
|
26820
|
+
const identity = JSON.stringify([protocol, model, baseUrl ?? null]);
|
|
26821
|
+
if (seen.has(identity)) continue;
|
|
26822
|
+
seen.add(identity);
|
|
26823
|
+
if (row.imageOnly === true || row.voiceOnly === true || row.fastOnly === true) continue;
|
|
26824
|
+
routes.push({
|
|
26825
|
+
id: `${model}(${protocol})`,
|
|
26826
|
+
model,
|
|
26827
|
+
provider,
|
|
26828
|
+
protocol,
|
|
26829
|
+
baseUrl,
|
|
26830
|
+
label: typeof row.name === "string" && row.name ? row.name : model,
|
|
26831
|
+
envKey: typeof row.envKey === "string" ? row.envKey : void 0
|
|
26832
|
+
});
|
|
26833
|
+
}
|
|
26834
|
+
}
|
|
26835
|
+
const counts = /* @__PURE__ */ new Map();
|
|
26836
|
+
for (const route of routes) counts.set(route.id, (counts.get(route.id) ?? 0) + 1);
|
|
26837
|
+
for (const route of routes) {
|
|
26838
|
+
if (counts.get(route.id) === 1) continue;
|
|
26839
|
+
const endpoint = route.baseUrl ?? (route.protocol === "openai" ? "https://api.openai.com/v1" : "");
|
|
26840
|
+
let publicEndpoint = null;
|
|
26841
|
+
if (endpoint) {
|
|
26842
|
+
try {
|
|
26843
|
+
const url2 = new URL(endpoint);
|
|
26844
|
+
url2.username = "";
|
|
26845
|
+
url2.password = "";
|
|
26846
|
+
url2.search = "";
|
|
26847
|
+
url2.hash = "";
|
|
26848
|
+
publicEndpoint = url2.href;
|
|
26849
|
+
} catch {
|
|
26850
|
+
throw new Error("A Qwen model has an invalid endpoint. Fix its baseUrl in Qwen settings and refresh models.");
|
|
26851
|
+
}
|
|
26852
|
+
}
|
|
26853
|
+
const identity = [route.id, route.label, route.envKey ?? null, route.baseUrl === void 0, publicEndpoint];
|
|
26854
|
+
route.id = `qwen-route:v1:${createHash7("sha256").update(JSON.stringify(identity)).digest("base64url").slice(0, 16)}`;
|
|
26855
|
+
}
|
|
26856
|
+
if (new Set(routes.map((route) => route.id)).size !== routes.length) {
|
|
26857
|
+
throw new Error("Qwen has indistinguishable model routes. Give them distinct names, envKey values, or public endpoints in Qwen settings.");
|
|
26858
|
+
}
|
|
26859
|
+
return routes;
|
|
26860
|
+
}
|
|
26861
|
+
function readQwenModelCatalog(env = process.env) {
|
|
26862
|
+
const options = readQwenRoutes(env).map(({ id, model, label, provider }) => ({
|
|
26863
|
+
id,
|
|
26864
|
+
label: qwenModelLabel(model, label),
|
|
26865
|
+
custom: true,
|
|
26866
|
+
provider
|
|
26867
|
+
}));
|
|
26868
|
+
return { default: options[0]?.id ?? "", options };
|
|
26314
26869
|
}
|
|
26315
26870
|
function envKeyFor(hostId) {
|
|
26316
26871
|
return `OPENMAUSBOT_QWEN_${hostId.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`;
|
|
@@ -26321,10 +26876,10 @@ function ensureQwenInjectModel(modelId, env = process.env) {
|
|
|
26321
26876
|
const host = localHost(inject.host);
|
|
26322
26877
|
if (!host) return modelId;
|
|
26323
26878
|
const dir = qwenHome(env);
|
|
26324
|
-
|
|
26325
|
-
const path3 =
|
|
26879
|
+
mkdirSync11(dir, { recursive: true });
|
|
26880
|
+
const path3 = join27(dir, "settings.json");
|
|
26326
26881
|
let settings2 = {};
|
|
26327
|
-
if (
|
|
26882
|
+
if (existsSync14(path3)) {
|
|
26328
26883
|
try {
|
|
26329
26884
|
settings2 = JSON.parse(readFileSync14(path3, "utf8"));
|
|
26330
26885
|
} catch {
|
|
@@ -26359,23 +26914,54 @@ function ensureQwenInjectModel(modelId, env = process.env) {
|
|
|
26359
26914
|
return inject.model;
|
|
26360
26915
|
}
|
|
26361
26916
|
async function resolveModels2(env) {
|
|
26362
|
-
const catalog = await mergeLocalInject(
|
|
26363
|
-
|
|
26364
|
-
|
|
26365
|
-
|
|
26917
|
+
const catalog = await mergeLocalInject(readQwenModelCatalog(env), env);
|
|
26918
|
+
const routes = readQwenRoutes(env);
|
|
26919
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
26920
|
+
for (const option of catalog.options) {
|
|
26921
|
+
const injected = decodeInjectId(option.id);
|
|
26922
|
+
if (!injected) continue;
|
|
26923
|
+
const endpoint = localHost(injected.host)?.baseUrl;
|
|
26924
|
+
for (const route of routes) {
|
|
26925
|
+
if (route.protocol === "openai" && route.model === injected.model && route.baseUrl === endpoint) {
|
|
26926
|
+
replacements.set(route.id, option.id);
|
|
26927
|
+
}
|
|
26928
|
+
}
|
|
26929
|
+
}
|
|
26930
|
+
const options = catalog.options.filter((option) => !replacements.has(option.id));
|
|
26931
|
+
const preferred = replacements.get(catalog.default) ?? catalog.default;
|
|
26932
|
+
return { default: options.some((option) => option.id === preferred) ? preferred : options[0]?.id ?? "", options };
|
|
26933
|
+
}
|
|
26934
|
+
function resolveQwenTurnModel(model, env) {
|
|
26935
|
+
if (!model) return model;
|
|
26936
|
+
const injected = decodeInjectId(model);
|
|
26937
|
+
if (injected) ensureQwenInjectModel(model, env);
|
|
26938
|
+
const routes = readQwenRoutes(env);
|
|
26939
|
+
if (injected) {
|
|
26940
|
+
const route = routes.find((row) => row.protocol === "openai" && row.model === injected.model && row.baseUrl === localHost(injected.host)?.baseUrl);
|
|
26941
|
+
if (!route) throw new Error("Qwen could not configure this local model. Refresh models and select it again.");
|
|
26942
|
+
return route.id;
|
|
26943
|
+
}
|
|
26944
|
+
if (routes.some((route) => route.id === model)) return model;
|
|
26945
|
+
const matches = routes.filter((route) => route.model === model);
|
|
26946
|
+
if (matches.length > 1) throw new Error("This Qwen model has multiple providers. Refresh models and select the intended provider again.");
|
|
26947
|
+
if (!matches.length) throw new Error("This Qwen model is no longer configured. Refresh models and select it again.");
|
|
26948
|
+
return matches[0].id;
|
|
26949
|
+
}
|
|
26950
|
+
var EMPTY, PROTOCOLS, support8, QwenAgentDriver;
|
|
26366
26951
|
var init_qwen = __esm({
|
|
26367
26952
|
"server/drivers/acp/qwen.ts"() {
|
|
26368
26953
|
"use strict";
|
|
26369
26954
|
init_local_inject();
|
|
26370
26955
|
init_core3();
|
|
26371
26956
|
EMPTY = { default: "", options: [] };
|
|
26957
|
+
PROTOCOLS = /* @__PURE__ */ new Set(["openai", "anthropic", "gemini", "vertex-ai"]);
|
|
26372
26958
|
support8 = {
|
|
26373
26959
|
driverKind: "qwenAgent",
|
|
26374
26960
|
displayName: "Qwen",
|
|
26375
26961
|
access: "custom",
|
|
26376
26962
|
models: EMPTY,
|
|
26377
26963
|
resolveModels: resolveModels2,
|
|
26378
|
-
resolveTurnModel:
|
|
26964
|
+
resolveTurnModel: resolveQwenTurnModel,
|
|
26379
26965
|
defaultCli: "qwen",
|
|
26380
26966
|
nativeSource: "qwen.acp",
|
|
26381
26967
|
loginNote: "Qwen Code CLI is not installed",
|
|
@@ -26387,7 +26973,10 @@ var init_qwen = __esm({
|
|
|
26387
26973
|
},
|
|
26388
26974
|
docsUrl: "https://qwenlm.github.io/qwen-code-docs/en/users/overview/"
|
|
26389
26975
|
},
|
|
26390
|
-
|
|
26976
|
+
// A raw -m only changes the model within the saved provider. ACP switches
|
|
26977
|
+
// the complete route and confirms it before any prompt leaves OMB.
|
|
26978
|
+
spawnArgs: () => ["--acp"],
|
|
26979
|
+
selectModel: { configId: "model" },
|
|
26391
26980
|
pickAuthMethod: () => null,
|
|
26392
26981
|
authFailure: "continue",
|
|
26393
26982
|
isAuthenticated: () => true,
|
|
@@ -33287,9 +33876,9 @@ var init_browser = __esm({
|
|
|
33287
33876
|
|
|
33288
33877
|
// server/drivers/acp/hermes.ts
|
|
33289
33878
|
import { spawn as spawn5 } from "node:child_process";
|
|
33290
|
-
import { mkdirSync as
|
|
33291
|
-
import { homedir as
|
|
33292
|
-
import { join as
|
|
33879
|
+
import { mkdirSync as mkdirSync12, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "node:fs";
|
|
33880
|
+
import { homedir as homedir20 } from "node:os";
|
|
33881
|
+
import { join as join28 } from "node:path";
|
|
33293
33882
|
function bindHermesScreenshotCompat(env, modelId) {
|
|
33294
33883
|
delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT];
|
|
33295
33884
|
delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL];
|
|
@@ -33299,7 +33888,7 @@ function bindHermesScreenshotCompat(env, modelId) {
|
|
|
33299
33888
|
env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL] = inject.model;
|
|
33300
33889
|
}
|
|
33301
33890
|
function hermesHome(env) {
|
|
33302
|
-
return env.HERMES_HOME ||
|
|
33891
|
+
return env.HERMES_HOME || join28(env.HOME || env.USERPROFILE || homedir20(), ".hermes");
|
|
33303
33892
|
}
|
|
33304
33893
|
function quoteYaml(value) {
|
|
33305
33894
|
if (/^[\w./:+-]+$/.test(value)) return value;
|
|
@@ -33340,8 +33929,8 @@ function ensureHermesInjectProvider(modelId, env = process.env) {
|
|
|
33340
33929
|
const host = localHost(inject.host);
|
|
33341
33930
|
if (!host) return modelId;
|
|
33342
33931
|
const dir = hermesHome(env);
|
|
33343
|
-
|
|
33344
|
-
const path3 =
|
|
33932
|
+
mkdirSync12(dir, { recursive: true });
|
|
33933
|
+
const path3 = join28(dir, "config.yaml");
|
|
33345
33934
|
let text2 = "";
|
|
33346
33935
|
try {
|
|
33347
33936
|
text2 = readFileSync15(path3, "utf8");
|
|
@@ -33412,13 +34001,13 @@ function hermesConfiguredModel(env = process.env) {
|
|
|
33412
34001
|
const dir = hermesHome(env);
|
|
33413
34002
|
let secrets = "";
|
|
33414
34003
|
try {
|
|
33415
|
-
secrets = readFileSync15(
|
|
34004
|
+
secrets = readFileSync15(join28(dir, ".env"), "utf8");
|
|
33416
34005
|
} catch {
|
|
33417
34006
|
}
|
|
33418
34007
|
const hasHostedProviderKey = HERMES_HOSTED_PROVIDER_KEYS.some((name) => nonEmptyDotenvValue(secrets, name));
|
|
33419
34008
|
let configuredDefault = null;
|
|
33420
34009
|
try {
|
|
33421
|
-
configuredDefault = hermesConfigDefault(readFileSync15(
|
|
34010
|
+
configuredDefault = hermesConfigDefault(readFileSync15(join28(dir, "config.yaml"), "utf8"));
|
|
33422
34011
|
} catch {
|
|
33423
34012
|
}
|
|
33424
34013
|
const configuredProvider = configuredDefault?.provider.toLowerCase() ?? "";
|
|
@@ -33434,12 +34023,12 @@ function hermesConfiguredModel(env = process.env) {
|
|
|
33434
34023
|
};
|
|
33435
34024
|
}
|
|
33436
34025
|
async function fetchHermesAcpModels(cli, env) {
|
|
33437
|
-
return await new Promise((
|
|
34026
|
+
return await new Promise((resolve13) => {
|
|
33438
34027
|
let child;
|
|
33439
34028
|
try {
|
|
33440
34029
|
child = spawn5(cli, ["acp"], { stdio: ["pipe", "pipe", "ignore"], env });
|
|
33441
34030
|
} catch {
|
|
33442
|
-
return
|
|
34031
|
+
return resolve13([]);
|
|
33443
34032
|
}
|
|
33444
34033
|
let settled = false;
|
|
33445
34034
|
let timer;
|
|
@@ -33460,7 +34049,7 @@ async function fetchHermesAcpModels(cli, env) {
|
|
|
33460
34049
|
}
|
|
33461
34050
|
} catch {
|
|
33462
34051
|
}
|
|
33463
|
-
|
|
34052
|
+
resolve13(out);
|
|
33464
34053
|
};
|
|
33465
34054
|
timer = setTimeout(() => done([]), 5e3);
|
|
33466
34055
|
child.once("error", () => done([]));
|
|
@@ -33503,7 +34092,7 @@ async function fetchHermesAcpModels(cli, env) {
|
|
|
33503
34092
|
}
|
|
33504
34093
|
if (msg?.id === initId) {
|
|
33505
34094
|
if (!msg.result) return done([]);
|
|
33506
|
-
sessionId = send("session/new", { cwd: env.HOME || env.USERPROFILE ||
|
|
34095
|
+
sessionId = send("session/new", { cwd: env.HOME || env.USERPROFILE || homedir20(), mcpServers: [] });
|
|
33507
34096
|
} else if (sessionId && msg?.id === sessionId) {
|
|
33508
34097
|
const list = Array.isArray(msg.result?.models?.availableModels) ? msg.result.models.availableModels : [];
|
|
33509
34098
|
done(
|
|
@@ -33738,9 +34327,9 @@ var init_openai_compat = __esm({
|
|
|
33738
34327
|
});
|
|
33739
34328
|
|
|
33740
34329
|
// server/drivers/pi.ts
|
|
33741
|
-
import { chmodSync as chmodSync5, existsSync as
|
|
33742
|
-
import { homedir as
|
|
33743
|
-
import { join as
|
|
34330
|
+
import { chmodSync as chmodSync5, existsSync as existsSync15, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync12 } from "node:fs";
|
|
34331
|
+
import { homedir as homedir21, tmpdir as tmpdir4 } from "node:os";
|
|
34332
|
+
import { join as join29 } from "node:path";
|
|
33744
34333
|
function readPiPromptImages(turn) {
|
|
33745
34334
|
return (turn.images ?? []).map((image) => ({
|
|
33746
34335
|
type: "image",
|
|
@@ -33847,7 +34436,7 @@ async function applyPiLocalCatalog(catalog, env = process.env, fetchImpl = fetch
|
|
|
33847
34436
|
return preferPiInjectRows(await mergeLocalInject(catalog, env, fetchImpl));
|
|
33848
34437
|
}
|
|
33849
34438
|
function piAgentDir(env) {
|
|
33850
|
-
return
|
|
34439
|
+
return join29(env.HOME || env.USERPROFILE || homedir21(), ".pi", "agent");
|
|
33851
34440
|
}
|
|
33852
34441
|
function ensurePiInjectModel(modelId, env = process.env) {
|
|
33853
34442
|
const split = splitPiModel(modelId);
|
|
@@ -33857,10 +34446,10 @@ function ensurePiInjectModel(modelId, env = process.env) {
|
|
|
33857
34446
|
const host = localHost(inject.host);
|
|
33858
34447
|
if (!host) return split;
|
|
33859
34448
|
const dir = piAgentDir(env);
|
|
33860
|
-
|
|
33861
|
-
const path3 =
|
|
34449
|
+
mkdirSync13(dir, { recursive: true });
|
|
34450
|
+
const path3 = join29(dir, "models.json");
|
|
33862
34451
|
let root = { providers: {} };
|
|
33863
|
-
if (
|
|
34452
|
+
if (existsSync15(path3)) {
|
|
33864
34453
|
try {
|
|
33865
34454
|
const parsed = JSON.parse(readFileSync16(path3, "utf8"));
|
|
33866
34455
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
@@ -33912,7 +34501,7 @@ function ensurePiInjectModel(modelId, env = process.env) {
|
|
|
33912
34501
|
return split;
|
|
33913
34502
|
}
|
|
33914
34503
|
function readPiDefaultModel(env) {
|
|
33915
|
-
const home = env.HOME || env.USERPROFILE ||
|
|
34504
|
+
const home = env.HOME || env.USERPROFILE || homedir21();
|
|
33916
34505
|
try {
|
|
33917
34506
|
const s = JSON.parse(readFileSync16(`${home}/.pi/agent/settings.json`, "utf8"));
|
|
33918
34507
|
return s.defaultProvider && s.defaultModel ? `${s.defaultProvider}/${s.defaultModel}` : "";
|
|
@@ -33922,7 +34511,7 @@ function readPiDefaultModel(env) {
|
|
|
33922
34511
|
}
|
|
33923
34512
|
async function fetchPiModels(cli, env) {
|
|
33924
34513
|
const child = spawnCli(cli, PI_ARGS, { stdio: ["pipe", "pipe", "pipe"], env });
|
|
33925
|
-
return new Promise((
|
|
34514
|
+
return new Promise((resolve13) => {
|
|
33926
34515
|
let buf = "";
|
|
33927
34516
|
let done = false;
|
|
33928
34517
|
const fallbackDefault = readPiDefaultModel(env);
|
|
@@ -33933,7 +34522,7 @@ async function fetchPiModels(cli, env) {
|
|
|
33933
34522
|
killCliTree(child);
|
|
33934
34523
|
} catch {
|
|
33935
34524
|
}
|
|
33936
|
-
|
|
34525
|
+
resolve13(catalog);
|
|
33937
34526
|
};
|
|
33938
34527
|
const timer = setTimeout(() => finish({ default: "", options: [] }), 15e3);
|
|
33939
34528
|
timer.unref?.();
|
|
@@ -34060,9 +34649,9 @@ var init_pi = __esm({
|
|
|
34060
34649
|
const mcpServers = buildMcpServers(turn);
|
|
34061
34650
|
let mcpTempDir = null;
|
|
34062
34651
|
if (mcpServers) {
|
|
34063
|
-
mcpTempDir = mkdtempSync3(
|
|
34652
|
+
mcpTempDir = mkdtempSync3(join29(tmpdir4(), "omb-pi-mcp-"));
|
|
34064
34653
|
try {
|
|
34065
|
-
writeFileSync12(
|
|
34654
|
+
writeFileSync12(join29(mcpTempDir, "mcp.json"), JSON.stringify({ mcpServers }), { mode: 384 });
|
|
34066
34655
|
} catch (err) {
|
|
34067
34656
|
try {
|
|
34068
34657
|
rmSync3(mcpTempDir, { recursive: true, force: true });
|
|
@@ -34080,7 +34669,7 @@ var init_pi = __esm({
|
|
|
34080
34669
|
env: piEnvironment({
|
|
34081
34670
|
...process.env,
|
|
34082
34671
|
...input.environment,
|
|
34083
|
-
...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG:
|
|
34672
|
+
...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG: join29(mcpTempDir, "mcp.json") } : {}
|
|
34084
34673
|
})
|
|
34085
34674
|
});
|
|
34086
34675
|
} catch (err) {
|
|
@@ -34103,13 +34692,13 @@ var init_pi = __esm({
|
|
|
34103
34692
|
}
|
|
34104
34693
|
responseWaiters.clear();
|
|
34105
34694
|
};
|
|
34106
|
-
const awaitResponse = (command, timeoutMs = 2e4) => new Promise((
|
|
34695
|
+
const awaitResponse = (command, timeoutMs = 2e4) => new Promise((resolve13, reject) => {
|
|
34107
34696
|
const timer = setTimeout(() => {
|
|
34108
34697
|
responseWaiters.delete(command);
|
|
34109
34698
|
reject(new Error(`pi ${command} timed out`));
|
|
34110
34699
|
}, timeoutMs);
|
|
34111
34700
|
timer.unref?.();
|
|
34112
|
-
responseWaiters.set(command, { resolve:
|
|
34701
|
+
responseWaiters.set(command, { resolve: resolve13, reject, timer });
|
|
34113
34702
|
});
|
|
34114
34703
|
child.stdin.on("error", () => rejectWaiters(new Error("pi stdin closed")));
|
|
34115
34704
|
const send = (obj) => {
|
|
@@ -34317,7 +34906,7 @@ ${turn.text}` : turn.text;
|
|
|
34317
34906
|
return { turnId };
|
|
34318
34907
|
};
|
|
34319
34908
|
const snapshot = async () => {
|
|
34320
|
-
const version2 = await new Promise((
|
|
34909
|
+
const version2 = await new Promise((resolve13) => {
|
|
34321
34910
|
const child = spawnCli(config2.cli, ["--version"], {
|
|
34322
34911
|
stdio: ["ignore", "pipe", "pipe"],
|
|
34323
34912
|
env: piEnvironment({ ...process.env, ...input.environment })
|
|
@@ -34330,16 +34919,16 @@ ${turn.text}` : turn.text;
|
|
|
34330
34919
|
killCliTree(child);
|
|
34331
34920
|
} catch {
|
|
34332
34921
|
}
|
|
34333
|
-
|
|
34922
|
+
resolve13(null);
|
|
34334
34923
|
}, 8e3);
|
|
34335
34924
|
timer.unref?.();
|
|
34336
34925
|
child.on("error", () => {
|
|
34337
34926
|
clearTimeout(timer);
|
|
34338
|
-
|
|
34927
|
+
resolve13(null);
|
|
34339
34928
|
});
|
|
34340
34929
|
child.on("close", () => {
|
|
34341
34930
|
clearTimeout(timer);
|
|
34342
|
-
|
|
34931
|
+
resolve13(out.trim() || null);
|
|
34343
34932
|
});
|
|
34344
34933
|
});
|
|
34345
34934
|
if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
|
|
@@ -34418,15 +35007,15 @@ ${turn.text}` : turn.text;
|
|
|
34418
35007
|
|
|
34419
35008
|
// server/drivers/minimax.ts
|
|
34420
35009
|
import { readFileSync as readFileSync17 } from "node:fs";
|
|
34421
|
-
import { homedir as
|
|
34422
|
-
import { join as
|
|
35010
|
+
import { homedir as homedir22 } from "node:os";
|
|
35011
|
+
import { join as join30 } from "node:path";
|
|
34423
35012
|
function normalizedApiUrl(value) {
|
|
34424
35013
|
const root = value.trim().replace(/\/+$/, "");
|
|
34425
35014
|
return root.endsWith("/v1") ? root : `${root}/v1`;
|
|
34426
35015
|
}
|
|
34427
|
-
function loadLocalMiniMaxConfig(home =
|
|
35016
|
+
function loadLocalMiniMaxConfig(home = homedir22()) {
|
|
34428
35017
|
try {
|
|
34429
|
-
const raw = localConfigSchema.parse(JSON.parse(readFileSync17(
|
|
35018
|
+
const raw = localConfigSchema.parse(JSON.parse(readFileSync17(join30(home, ".mmx", "config.json"), "utf8")));
|
|
34430
35019
|
const configuredUrl = raw.base_url?.trim() ? raw.base_url : raw.region === "cn" ? CN_URL : DEFAULT_URL2;
|
|
34431
35020
|
return {
|
|
34432
35021
|
apiKey: raw.api_key?.trim() ?? "",
|
|
@@ -34694,7 +35283,7 @@ __export(cli_setup_exports, {
|
|
|
34694
35283
|
});
|
|
34695
35284
|
import { spawn as spawn6 } from "node:child_process";
|
|
34696
35285
|
import { readFileSync as readFileSync18 } from "node:fs";
|
|
34697
|
-
import { join as
|
|
35286
|
+
import { join as join31, resolve as resolve10 } from "node:path";
|
|
34698
35287
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
34699
35288
|
async function inspect(id, entry) {
|
|
34700
35289
|
const registry2 = new ProviderRegistry(BUILT_IN_DRIVERS);
|
|
@@ -34727,11 +35316,11 @@ async function runSetupCli(cli, args, environment = {}) {
|
|
|
34727
35316
|
resetPathCache();
|
|
34728
35317
|
}
|
|
34729
35318
|
function assertDataDir(dataDir) {
|
|
34730
|
-
if (
|
|
35319
|
+
if (resolve10(dataDir) !== resolve10(DATA_DIR)) throw new Error("Setup data directory mismatch. Restart the CLI with --data-dir.");
|
|
34731
35320
|
}
|
|
34732
35321
|
function checkStoredConfig(dataDir) {
|
|
34733
35322
|
try {
|
|
34734
|
-
parseStoredConfig(JSON.parse(readFileSync18(
|
|
35323
|
+
parseStoredConfig(JSON.parse(readFileSync18(join31(dataDir, "config.json"), "utf8")));
|
|
34735
35324
|
} catch (error51) {
|
|
34736
35325
|
if (error51.code === "ENOENT") return;
|
|
34737
35326
|
throw new Error("Existing config.json could not be read or validated. Setup has not changed it; repair it before continuing.");
|
|
@@ -35009,7 +35598,7 @@ var init_browser_engine_release = __esm({
|
|
|
35009
35598
|
});
|
|
35010
35599
|
|
|
35011
35600
|
// server/browser-bundle-release.ts
|
|
35012
|
-
import { join as
|
|
35601
|
+
import { join as join32 } from "node:path";
|
|
35013
35602
|
function browserBundleSpec(target) {
|
|
35014
35603
|
if (!Object.hasOwn(CHROME_ASSETS, target)) throw new Error(`Unsupported desktop browser target: ${target}`);
|
|
35015
35604
|
const pinned = CHROME_ASSETS[target];
|
|
@@ -35045,10 +35634,10 @@ function browserBundlePaths(bundleDirectory, target) {
|
|
|
35045
35634
|
const spec = browserBundleSpec(target);
|
|
35046
35635
|
return {
|
|
35047
35636
|
directory: bundleDirectory,
|
|
35048
|
-
manifest:
|
|
35049
|
-
engine:
|
|
35050
|
-
chrome:
|
|
35051
|
-
licenses:
|
|
35637
|
+
manifest: join32(bundleDirectory, "manifest.json"),
|
|
35638
|
+
engine: join32(bundleDirectory, spec.engine.executable),
|
|
35639
|
+
chrome: join32(bundleDirectory, spec.chrome.executable),
|
|
35640
|
+
licenses: join32(bundleDirectory, "licenses")
|
|
35052
35641
|
};
|
|
35053
35642
|
}
|
|
35054
35643
|
var CHROME_VERSION, CHROME_ASSETS;
|
|
@@ -35102,27 +35691,27 @@ __export(browser_engine_exports, {
|
|
|
35102
35691
|
resolveAgentBrowserBinary: () => resolveAgentBrowserBinary
|
|
35103
35692
|
});
|
|
35104
35693
|
import { spawn as spawn7 } from "node:child_process";
|
|
35105
|
-
import { createHash as
|
|
35106
|
-
import { chmodSync as chmodSync6, constants as constants2, copyFileSync, existsSync as
|
|
35107
|
-
import { homedir as
|
|
35108
|
-
import { delimiter as delimiter6, dirname as dirname10, join as
|
|
35694
|
+
import { createHash as createHash8, randomBytes as randomBytes3, randomUUID as randomUUID11 } from "node:crypto";
|
|
35695
|
+
import { chmodSync as chmodSync6, constants as constants2, copyFileSync, existsSync as existsSync16, mkdirSync as mkdirSync14, readFileSync as readFileSync19, readdirSync as readdirSync3, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "node:fs";
|
|
35696
|
+
import { homedir as homedir23, tmpdir as tmpdir5 } from "node:os";
|
|
35697
|
+
import { delimiter as delimiter6, dirname as dirname10, join as join33, resolve as resolve11 } from "node:path";
|
|
35109
35698
|
function browserRestoreKey(session) {
|
|
35110
35699
|
if (!/^[A-Za-z0-9_-]{1,96}$/.test(session)) throw new Error("Invalid browser session.");
|
|
35111
|
-
return `omb-${
|
|
35700
|
+
return `omb-${createHash8("sha256").update(session).digest("hex")}`;
|
|
35112
35701
|
}
|
|
35113
35702
|
function browserSessionsDirectory(env) {
|
|
35114
35703
|
const namespace = env.AGENT_BROWSER_NAMESPACE;
|
|
35115
35704
|
if (namespace && !/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/.test(namespace)) throw new Error("Invalid browser namespace.");
|
|
35116
|
-
const home = (process.platform === "win32" ? env.USERPROFILE : env.HOME) ||
|
|
35117
|
-
const stateRoot = namespace ?
|
|
35118
|
-
return
|
|
35705
|
+
const home = (process.platform === "win32" ? env.USERPROFILE : env.HOME) || homedir23();
|
|
35706
|
+
const stateRoot = namespace ? join33(home, ".agent-browser", "namespaces", namespace, "state") : join33(home, ".agent-browser");
|
|
35707
|
+
return join33(stateRoot, "sessions");
|
|
35119
35708
|
}
|
|
35120
35709
|
function managedBrowserConfigPath(env) {
|
|
35121
|
-
return
|
|
35710
|
+
return join33(browserSessionsDirectory(env), "..", "omb-managed-config.json");
|
|
35122
35711
|
}
|
|
35123
35712
|
function ensureManagedBrowserConfig(env) {
|
|
35124
35713
|
const path3 = managedBrowserConfigPath(env);
|
|
35125
|
-
|
|
35714
|
+
mkdirSync14(dirname10(path3), { recursive: true, mode: 448 });
|
|
35126
35715
|
try {
|
|
35127
35716
|
writeFileSync13(path3, "{}\n", { flag: "wx", mode: 384 });
|
|
35128
35717
|
} catch (error51) {
|
|
@@ -35191,7 +35780,7 @@ async function closeBrowserSession(binaryPath, env, timeoutMs = 15e3) {
|
|
|
35191
35780
|
} catch {
|
|
35192
35781
|
return false;
|
|
35193
35782
|
}
|
|
35194
|
-
await new Promise((
|
|
35783
|
+
await new Promise((resolve13) => setTimeout(resolve13, Math.min(25, Math.max(1, deadline - Date.now()))));
|
|
35195
35784
|
}
|
|
35196
35785
|
return false;
|
|
35197
35786
|
}
|
|
@@ -35205,12 +35794,12 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
|
|
|
35205
35794
|
ensureManagedBrowserConfig(env);
|
|
35206
35795
|
if (options.persistent === false) return;
|
|
35207
35796
|
const directory = browserSessionsDirectory(env);
|
|
35208
|
-
const key =
|
|
35797
|
+
const key = join33(directory, session);
|
|
35209
35798
|
let pending = preparedBrowserSessions.get(key);
|
|
35210
35799
|
if (!pending) {
|
|
35211
35800
|
pending = (async () => {
|
|
35212
|
-
const targetBase =
|
|
35213
|
-
const hasTarget = () =>
|
|
35801
|
+
const targetBase = join33(directory, `${restoreKey}-${session}`);
|
|
35802
|
+
const hasTarget = () => existsSync16(`${targetBase}.json.enc`) || existsSync16(`${targetBase}.json`);
|
|
35214
35803
|
if (hasTarget()) return;
|
|
35215
35804
|
check2();
|
|
35216
35805
|
if (!await closeBrowserSession(binaryPath, { ...env, AGENT_BROWSER_RESTORE: session }, options.timeoutMs)) {
|
|
@@ -35219,7 +35808,7 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
|
|
|
35219
35808
|
check2();
|
|
35220
35809
|
if (hasTarget()) return;
|
|
35221
35810
|
const candidates = [".json.enc", ".json"].flatMap((suffix) => {
|
|
35222
|
-
const path3 =
|
|
35811
|
+
const path3 = join33(directory, `${session}-${session}${suffix}`);
|
|
35223
35812
|
try {
|
|
35224
35813
|
const stat4 = statSync3(path3);
|
|
35225
35814
|
if (!stat4.isFile()) throw new Error("Saved browser state is not a file.");
|
|
@@ -35249,19 +35838,19 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
|
|
|
35249
35838
|
function executableName(platform = process.platform) {
|
|
35250
35839
|
return platform === "win32" ? "agent-browser.exe" : "agent-browser";
|
|
35251
35840
|
}
|
|
35252
|
-
function isMusl(platform = process.platform, exists =
|
|
35841
|
+
function isMusl(platform = process.platform, exists = existsSync16) {
|
|
35253
35842
|
return platform === "linux" && (exists("/lib/ld-musl-x86_64.so.1") || exists("/lib/ld-musl-aarch64.so.1"));
|
|
35254
35843
|
}
|
|
35255
35844
|
function pinnedBinaryPath(dataDir = DATA_DIR, platform = process.platform, arch = process.arch) {
|
|
35256
35845
|
const version2 = agentBrowserReleaseVersion(resolveAgentBrowserReleaseAsset(platform, arch));
|
|
35257
|
-
return
|
|
35846
|
+
return join33(dataDir, ENGINE_DIR, version2, executableName(platform));
|
|
35258
35847
|
}
|
|
35259
35848
|
function onPath(env, platform, exists) {
|
|
35260
35849
|
const pathValue = platform === "win32" ? Object.entries(env).findLast(([key]) => key.toUpperCase() === "PATH")?.[1] : env.PATH;
|
|
35261
35850
|
for (const part of (pathValue ?? "").split(delimiter6)) {
|
|
35262
35851
|
const dir = part.trim().replace(/^"|"$/gu, "");
|
|
35263
35852
|
if (!dir) continue;
|
|
35264
|
-
const candidate =
|
|
35853
|
+
const candidate = resolve11(dir, executableName(platform));
|
|
35265
35854
|
if (exists(candidate)) return candidate;
|
|
35266
35855
|
}
|
|
35267
35856
|
return null;
|
|
@@ -35270,7 +35859,7 @@ function packagedBrowser(options) {
|
|
|
35270
35859
|
const resources = (options.env ?? process.env).OMB_RESOURCES_PATH;
|
|
35271
35860
|
if (!resources) return null;
|
|
35272
35861
|
try {
|
|
35273
|
-
return browserBundlePaths(
|
|
35862
|
+
return browserBundlePaths(join33(resolve11(resources), "browser-engine"), `${options.platform ?? process.platform}-${options.arch ?? process.arch}`);
|
|
35274
35863
|
} catch {
|
|
35275
35864
|
return null;
|
|
35276
35865
|
}
|
|
@@ -35281,9 +35870,9 @@ function completePackage(bundle, exists) {
|
|
|
35281
35870
|
function resolveAgentBrowserBinary(options = {}) {
|
|
35282
35871
|
const env = options.env ?? process.env;
|
|
35283
35872
|
const platform = options.platform ?? process.platform;
|
|
35284
|
-
const exists = options.exists ??
|
|
35873
|
+
const exists = options.exists ?? existsSync16;
|
|
35285
35874
|
const override = env.OMB_AGENT_BROWSER_PATH?.trim();
|
|
35286
|
-
if (override) return
|
|
35875
|
+
if (override) return resolve11(override) && exists(resolve11(override)) ? resolve11(override) : null;
|
|
35287
35876
|
const bundle = packagedBrowser(options);
|
|
35288
35877
|
if (bundle && exists(bundle.directory)) return completePackage(bundle, exists) ? bundle.engine : null;
|
|
35289
35878
|
const pinned = pinnedBinaryPath(options.dataDir, platform, options.arch);
|
|
@@ -35295,8 +35884,8 @@ async function installAgentBrowserBinary(options = {}) {
|
|
|
35295
35884
|
const asset = options.asset ?? resolveAgentBrowserReleaseAsset(platform, options.arch ?? process.arch, options.musl ?? isMusl(platform));
|
|
35296
35885
|
if (!asset) throw new Error(`agent-browser publishes no build for ${platform}-${options.arch ?? process.arch}.`);
|
|
35297
35886
|
const destination = pinnedBinaryPath(options.dataDir, platform, options.arch);
|
|
35298
|
-
const directory =
|
|
35299
|
-
|
|
35887
|
+
const directory = join33(destination, "..");
|
|
35888
|
+
mkdirSync14(directory, { recursive: true, mode: 448 });
|
|
35300
35889
|
const url2 = agentBrowserReleaseUrl(asset);
|
|
35301
35890
|
options.log?.(`downloading agent-browser ${agentBrowserReleaseVersion(asset)} (${Math.round(asset.bytes / 1024 / 1024)} MB, digest pinned)`);
|
|
35302
35891
|
const controller = new AbortController();
|
|
@@ -35311,7 +35900,7 @@ async function installAgentBrowserBinary(options = {}) {
|
|
|
35311
35900
|
clearTimeout(timer);
|
|
35312
35901
|
}
|
|
35313
35902
|
if (body.length !== asset.bytes) throw new Error("the agent-browser download did not match its pinned size; nothing was installed");
|
|
35314
|
-
const digest2 =
|
|
35903
|
+
const digest2 = createHash8("sha256").update(body).digest("hex");
|
|
35315
35904
|
if (digest2 !== asset.sha256) throw new Error("the agent-browser download failed its SHA-256 check; nothing was installed");
|
|
35316
35905
|
const staging = `${destination}.${randomBytes3(6).toString("hex")}.part`;
|
|
35317
35906
|
writeFileSync13(staging, body, { mode: 493 });
|
|
@@ -35321,7 +35910,7 @@ async function installAgentBrowserBinary(options = {}) {
|
|
|
35321
35910
|
}
|
|
35322
35911
|
function ensureChrome(binaryPath, options = {}) {
|
|
35323
35912
|
const bundle = packagedBrowser(options);
|
|
35324
|
-
if (!options.withDeps && bundle &&
|
|
35913
|
+
if (!options.withDeps && bundle && resolve11(binaryPath) === bundle.engine && completePackage(bundle, existsSync16)) {
|
|
35325
35914
|
options.log?.("agent-browser: the bundled browser is ready; no download needed");
|
|
35326
35915
|
return Promise.resolve();
|
|
35327
35916
|
}
|
|
@@ -35347,14 +35936,14 @@ function ensureChrome(binaryPath, options = {}) {
|
|
|
35347
35936
|
});
|
|
35348
35937
|
}
|
|
35349
35938
|
function browserEngineEncryptionKey(dataDir = DATA_DIR) {
|
|
35350
|
-
const file2 =
|
|
35939
|
+
const file2 = join33(dataDir, KEY_FILE);
|
|
35351
35940
|
try {
|
|
35352
35941
|
const existing = readFileSync19(file2, "utf8").trim();
|
|
35353
35942
|
if (/^[0-9a-f]{64}$/u.test(existing)) return existing;
|
|
35354
35943
|
} catch {
|
|
35355
35944
|
}
|
|
35356
35945
|
const key = randomBytes3(32).toString("hex");
|
|
35357
|
-
|
|
35946
|
+
mkdirSync14(dataDir, { recursive: true });
|
|
35358
35947
|
writeFileAtomic(file2, `${key}
|
|
35359
35948
|
`, { mode: 384 });
|
|
35360
35949
|
return key;
|
|
@@ -35368,7 +35957,7 @@ function browserEngineStatus(options = {}) {
|
|
|
35368
35957
|
const version2 = managed ? agentBrowserReleaseVersion(resolveAgentBrowserReleaseAsset(platform2, options.arch)) : AGENT_BROWSER_VERSION;
|
|
35369
35958
|
return { kind: "ready", binaryPath, version: version2 };
|
|
35370
35959
|
}
|
|
35371
|
-
if (bundle && (options.exists ??
|
|
35960
|
+
if (bundle && (options.exists ?? existsSync16)(bundle.directory)) {
|
|
35372
35961
|
return { kind: "unavailable", reason: "The desktop browser bundle is incomplete. Reinstall or update OpenMausBot to repair it.", installable: false };
|
|
35373
35962
|
}
|
|
35374
35963
|
const platform = options.platform ?? process.platform;
|
|
@@ -35401,13 +35990,13 @@ function agentBrowserIntegration(input) {
|
|
|
35401
35990
|
if (sourceEnv[name]) env[name] = sourceEnv[name];
|
|
35402
35991
|
}
|
|
35403
35992
|
const bundle = packagedBrowser({ env: sourceEnv });
|
|
35404
|
-
if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle &&
|
|
35993
|
+
if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve11(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync16)) {
|
|
35405
35994
|
env.AGENT_BROWSER_EXECUTABLE_PATH = bundle.chrome;
|
|
35406
35995
|
}
|
|
35407
35996
|
return { command: input.binaryPath, args: ["mcp", "--tools", "core", "--no-webmcp"], env };
|
|
35408
35997
|
}
|
|
35409
35998
|
function agentBrowserFrame(input) {
|
|
35410
|
-
const file2 =
|
|
35999
|
+
const file2 = join33(tmpdir5(), `openmausbot-browser-${randomUUID11()}.png`);
|
|
35411
36000
|
return new Promise((settle, fail) => {
|
|
35412
36001
|
const child = spawn7(input.binaryPath, ["screenshot", file2], {
|
|
35413
36002
|
env: browserRuntimeEnv(input.env),
|
|
@@ -35477,8 +36066,8 @@ async function clearBrowserSessionState(binaryPath, session, options = {}) {
|
|
|
35477
36066
|
}
|
|
35478
36067
|
};
|
|
35479
36068
|
try {
|
|
35480
|
-
for (const base2 of bases) for (const suffix of [".json", ".json.enc", ".json.previous", ".json.enc.previous"]) remove(
|
|
35481
|
-
const pendingDirectory =
|
|
36069
|
+
for (const base2 of bases) for (const suffix of [".json", ".json.enc", ".json.previous", ".json.enc.previous"]) remove(join33(directory, base2 + suffix));
|
|
36070
|
+
const pendingDirectory = join33(directory, ".tmp");
|
|
35482
36071
|
let pendingFiles = [];
|
|
35483
36072
|
try {
|
|
35484
36073
|
pendingFiles = readdirSync3(pendingDirectory);
|
|
@@ -35486,8 +36075,8 @@ async function clearBrowserSessionState(binaryPath, session, options = {}) {
|
|
|
35486
36075
|
if (error51.code !== "ENOENT") throw error51;
|
|
35487
36076
|
}
|
|
35488
36077
|
const candidates = bases.map((base2) => new RegExp(`^${base2}-candidate-[0-9]+\\.json(?:\\.enc)?$`));
|
|
35489
|
-
for (const name of pendingFiles) if (candidates.some((candidate) => candidate.test(name))) remove(
|
|
35490
|
-
preparedBrowserSessions.delete(
|
|
36078
|
+
for (const name of pendingFiles) if (candidates.some((candidate) => candidate.test(name))) remove(join33(pendingDirectory, name));
|
|
36079
|
+
preparedBrowserSessions.delete(join33(directory, session));
|
|
35491
36080
|
return true;
|
|
35492
36081
|
} catch {
|
|
35493
36082
|
return false;
|
|
@@ -35514,9 +36103,9 @@ var init_browser_engine = __esm({
|
|
|
35514
36103
|
// server/cli.ts
|
|
35515
36104
|
var import_qrcode_terminal = __toESM(require_main(), 1);
|
|
35516
36105
|
import { spawn as spawn8 } from "node:child_process";
|
|
35517
|
-
import { closeSync as closeSync3, existsSync as
|
|
35518
|
-
import { homedir as
|
|
35519
|
-
import { dirname as dirname11, join as
|
|
36106
|
+
import { closeSync as closeSync3, existsSync as existsSync17, mkdirSync as mkdirSync15, openSync as openSync3, readFileSync as readFileSync20 } from "node:fs";
|
|
36107
|
+
import { homedir as homedir24 } from "node:os";
|
|
36108
|
+
import { dirname as dirname11, join as join34, resolve as resolve12 } from "node:path";
|
|
35520
36109
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
35521
36110
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
35522
36111
|
|
|
@@ -36114,13 +36703,13 @@ function writePrivateToken(runtimeRoot2, token, { fileSystem, processId, identif
|
|
|
36114
36703
|
}
|
|
36115
36704
|
async function waitForExit(child, milliseconds) {
|
|
36116
36705
|
if (child.exitCode !== null || child.signalCode !== null) return;
|
|
36117
|
-
await new Promise((
|
|
36706
|
+
await new Promise((resolve13) => {
|
|
36118
36707
|
let settled = false;
|
|
36119
36708
|
const finish = () => {
|
|
36120
36709
|
if (settled) return;
|
|
36121
36710
|
settled = true;
|
|
36122
36711
|
clearTimeout(timer);
|
|
36123
|
-
|
|
36712
|
+
resolve13();
|
|
36124
36713
|
};
|
|
36125
36714
|
child.once("exit", finish);
|
|
36126
36715
|
const timer = setTimeout(finish, milliseconds);
|
|
@@ -36284,8 +36873,8 @@ function createManagedCompanionTunnel({
|
|
|
36284
36873
|
child = spawned;
|
|
36285
36874
|
const cancellationController = new AbortController();
|
|
36286
36875
|
let resolveCancellation;
|
|
36287
|
-
const cancellation = new Promise((
|
|
36288
|
-
resolveCancellation =
|
|
36876
|
+
const cancellation = new Promise((resolve13) => {
|
|
36877
|
+
resolveCancellation = resolve13;
|
|
36289
36878
|
});
|
|
36290
36879
|
let cancelled = false;
|
|
36291
36880
|
attemptHandle = {
|
|
@@ -36301,8 +36890,8 @@ function createManagedCompanionTunnel({
|
|
|
36301
36890
|
let terminated = false;
|
|
36302
36891
|
let expectedStop = false;
|
|
36303
36892
|
let resolveExit;
|
|
36304
|
-
const exit = new Promise((
|
|
36305
|
-
resolveExit =
|
|
36893
|
+
const exit = new Promise((resolve13) => {
|
|
36894
|
+
resolveExit = resolve13;
|
|
36306
36895
|
});
|
|
36307
36896
|
const onTerminated = () => {
|
|
36308
36897
|
if (terminated) return;
|
|
@@ -36336,8 +36925,8 @@ function createManagedCompanionTunnel({
|
|
|
36336
36925
|
}
|
|
36337
36926
|
if (Date.now() >= deadline) break;
|
|
36338
36927
|
await Promise.race([
|
|
36339
|
-
new Promise((
|
|
36340
|
-
const timer = setTimeout(
|
|
36928
|
+
new Promise((resolve13) => {
|
|
36929
|
+
const timer = setTimeout(resolve13, verifyIntervalMs);
|
|
36341
36930
|
timer.unref?.();
|
|
36342
36931
|
}),
|
|
36343
36932
|
exit,
|
|
@@ -37337,14 +37926,14 @@ function explainTailscaleFailure(reason) {
|
|
|
37337
37926
|
}
|
|
37338
37927
|
}
|
|
37339
37928
|
function run(cli, args, timeoutMs) {
|
|
37340
|
-
return new Promise((
|
|
37929
|
+
return new Promise((resolve13) => {
|
|
37341
37930
|
execFile(
|
|
37342
37931
|
cli,
|
|
37343
37932
|
args,
|
|
37344
37933
|
{ timeout: timeoutMs, killSignal: "SIGKILL", maxBuffer: 16 * 1024 * 1024, env: { ...process.env, PATH: searchPath() } },
|
|
37345
37934
|
(error51, stdout2, stderr) => {
|
|
37346
37935
|
const code = error51 && "code" in error51 && typeof error51.code === "number" ? error51.code : error51 ? null : 0;
|
|
37347
|
-
|
|
37936
|
+
resolve13({ ok: !error51, stdout: String(stdout2 ?? ""), stderr: String(stderr ?? ""), code });
|
|
37348
37937
|
}
|
|
37349
37938
|
);
|
|
37350
37939
|
});
|
|
@@ -37761,7 +38350,7 @@ function parseArgs(argv, env = process.env) {
|
|
|
37761
38350
|
const options = {
|
|
37762
38351
|
command: command === "--help" || command === "-h" ? "help" : command,
|
|
37763
38352
|
port: Number(env.OMB_PORT || 8799),
|
|
37764
|
-
dataDir: env.OMB_DATA_DIR ||
|
|
38353
|
+
dataDir: env.OMB_DATA_DIR || join34(homedir24(), ".openmausbot"),
|
|
37765
38354
|
tailscale: false,
|
|
37766
38355
|
tunnel: false,
|
|
37767
38356
|
client: false,
|
|
@@ -37780,7 +38369,7 @@ function parseArgs(argv, env = process.env) {
|
|
|
37780
38369
|
};
|
|
37781
38370
|
try {
|
|
37782
38371
|
if (arg === "--port") options.port = Number(value());
|
|
37783
|
-
else if (arg === "--data-dir") options.dataDir =
|
|
38372
|
+
else if (arg === "--data-dir") options.dataDir = resolve12(value());
|
|
37784
38373
|
else if (arg === "--label") options.label = value();
|
|
37785
38374
|
else if (arg === "--public-url") options.publicUrl = value().replace(/\/+$/, "");
|
|
37786
38375
|
else if (arg === "--tailscale") options.tailscale = true;
|
|
@@ -37891,7 +38480,7 @@ function defaultIo() {
|
|
|
37891
38480
|
}
|
|
37892
38481
|
function serverVersion(here = HERE2) {
|
|
37893
38482
|
try {
|
|
37894
|
-
const parsed = JSON.parse(readFileSync20(
|
|
38483
|
+
const parsed = JSON.parse(readFileSync20(resolve12(here, "..", "package.json"), "utf8"));
|
|
37895
38484
|
const version2 = typeof parsed === "object" && parsed !== null ? Reflect.get(parsed, "version") : void 0;
|
|
37896
38485
|
return typeof version2 === "string" && version2 ? version2 : "0.0.0";
|
|
37897
38486
|
} catch {
|
|
@@ -37916,7 +38505,7 @@ async function isWorkspaceRunning(options) {
|
|
|
37916
38505
|
try {
|
|
37917
38506
|
const { status, body } = await api(options.port, "/api/health");
|
|
37918
38507
|
if (status !== 200 || body?.app !== "openmausbot") return false;
|
|
37919
|
-
const expected = readFileSync20(
|
|
38508
|
+
const expected = readFileSync20(join34(options.dataDir, "environment-id"), "utf8").trim();
|
|
37920
38509
|
const descriptor = await api(options.port, "/.well-known/openmausbot/environment");
|
|
37921
38510
|
return /^[0-9a-f-]{36}$/i.test(expected) && descriptor.status === 200 && descriptor.body?.environmentId === expected;
|
|
37922
38511
|
} catch {
|
|
@@ -38116,9 +38705,9 @@ async function runStatus(options, io = defaultIo()) {
|
|
|
38116
38705
|
return code;
|
|
38117
38706
|
}
|
|
38118
38707
|
async function runAccess(options, io = defaultIo()) {
|
|
38119
|
-
const file2 =
|
|
38708
|
+
const file2 = join34(options.dataDir, "config.json");
|
|
38120
38709
|
let raw = {};
|
|
38121
|
-
if (
|
|
38710
|
+
if (existsSync17(file2)) {
|
|
38122
38711
|
try {
|
|
38123
38712
|
const parsed = JSON.parse(readFileSync20(file2, "utf8"));
|
|
38124
38713
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error("not an object");
|
|
@@ -38134,7 +38723,7 @@ async function runAccess(options, io = defaultIo()) {
|
|
|
38134
38723
|
const members = list(Reflect.get(current, "members"));
|
|
38135
38724
|
const overridden = process.env.OMB_SIGNIN_EMAILS !== void 0 || process.env.OMB_SIGNIN_MEMBER_EMAILS !== void 0;
|
|
38136
38725
|
const write = (next) => {
|
|
38137
|
-
|
|
38726
|
+
mkdirSync15(options.dataDir, { recursive: true, mode: 448 });
|
|
38138
38727
|
writeFileAtomic(file2, `${JSON.stringify({ ...raw, signIn: next }, null, 2)}
|
|
38139
38728
|
`, { mode: 384 });
|
|
38140
38729
|
};
|
|
@@ -38268,16 +38857,16 @@ async function runBrowser(options, io = defaultIo()) {
|
|
|
38268
38857
|
return 0;
|
|
38269
38858
|
}
|
|
38270
38859
|
function serverEntry(here = HERE2) {
|
|
38271
|
-
const bundled =
|
|
38272
|
-
const root =
|
|
38273
|
-
if (
|
|
38274
|
-
const staticDir2 = [
|
|
38275
|
-
const skillsDir =
|
|
38860
|
+
const bundled = join34(here, "index.js");
|
|
38861
|
+
const root = resolve12(here, "..");
|
|
38862
|
+
if (existsSync17(bundled)) {
|
|
38863
|
+
const staticDir2 = [join34(root, "dist"), join34(here, "..", "ui")].find((d) => existsSync17(join34(d, "index.html"))) ?? null;
|
|
38864
|
+
const skillsDir = existsSync17(join34(root, "skills")) ? join34(root, "skills") : null;
|
|
38276
38865
|
return { command: process.execPath, args: [bundled], staticDir: staticDir2, skillsDir };
|
|
38277
38866
|
}
|
|
38278
|
-
const source =
|
|
38279
|
-
const staticDir =
|
|
38280
|
-
return { command: process.execPath, args: ["--experimental-strip-types", source], staticDir, skillsDir:
|
|
38867
|
+
const source = join34(here, "index.ts");
|
|
38868
|
+
const staticDir = existsSync17(join34(root, "dist", "index.html")) ? join34(root, "dist") : null;
|
|
38869
|
+
return { command: process.execPath, args: ["--experimental-strip-types", source], staticDir, skillsDir: existsSync17(join34(root, "skills")) ? join34(root, "skills") : null };
|
|
38281
38870
|
}
|
|
38282
38871
|
async function planTunnel(options, log) {
|
|
38283
38872
|
let access2 = null;
|
|
@@ -38377,9 +38966,9 @@ async function runServe(options, log = console.log) {
|
|
|
38377
38966
|
let child;
|
|
38378
38967
|
try {
|
|
38379
38968
|
if (options.guided) {
|
|
38380
|
-
const logsDir =
|
|
38381
|
-
|
|
38382
|
-
logPath =
|
|
38969
|
+
const logsDir = join34(options.dataDir, "logs");
|
|
38970
|
+
mkdirSync15(logsDir, { recursive: true, mode: 448 });
|
|
38971
|
+
logPath = join34(logsDir, `server-${Date.now()}-${process.pid}.log`);
|
|
38383
38972
|
logFd = openSync3(logPath, "wx", 384);
|
|
38384
38973
|
log("\nStarting your workspace\u2026");
|
|
38385
38974
|
}
|
|
@@ -38571,7 +39160,7 @@ async function runOnboardingCommand(options, io = defaultIo(), startServer = run
|
|
|
38571
39160
|
}
|
|
38572
39161
|
if (options.command === "setup") {
|
|
38573
39162
|
io.log("\nAll set. Start with: openmausbot (or npx openmausbot without a global install).");
|
|
38574
|
-
if (options.dataDir !==
|
|
39163
|
+
if (options.dataDir !== join34(homedir24(), ".openmausbot") || options.port !== 8799) {
|
|
38575
39164
|
io.log(`Use the same --data-dir (${options.dataDir}) and --port (${options.port}) options when starting.`);
|
|
38576
39165
|
}
|
|
38577
39166
|
return 0;
|