openmausbot 0.1.68 → 0.1.69
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-HqooKFTS.js → index-BmHupgVJ.js} +1 -1
- package/dist/assets/index-COp5lMnv.js +279 -0
- package/dist/assets/index-Jk7TIeyW.css +1 -0
- package/dist/index.html +2 -2
- package/dist-server/container-mcp.js +38 -2
- package/dist-server/drivers/agents-proxy.js +85 -5
- package/dist-server/index.js +1465 -611
- package/dist-server/openmausbot.js +554 -191
- package/dist-server/pair-cli.js +554 -191
- 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/drivers/acp/qwen.js +142 -5
- package/dist-server/server/drivers/agents-proxy.js +95 -4
- 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/harness/registry.js +2 -0
- package/dist-server/server/index.js +26 -5
- package/dist-server/server/package-export.js +7 -0
- 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 +185 -18
- package/dist-server/server/steer-queue.js +28 -0
- package/dist-server/shared/image-generation.js +28 -0
- package/dist-server/vps-container-mcp.js +38 -2
- package/package.json +1 -1
- package/dist/assets/index-CbaejjQA.js +0 -278
- package/dist/assets/index-aJ5EWZOQ.css +0 -1
package/dist-server/pair-cli.js
CHANGED
|
@@ -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
|
|
@@ -18679,12 +18723,12 @@ function describeSpawnFailure(err, cli) {
|
|
|
18679
18723
|
function killCliTree(child, timeoutMs = 5e3) {
|
|
18680
18724
|
const pid = child.pid;
|
|
18681
18725
|
if (!pid || child.exitCode !== null || child.signalCode !== null) return Promise.resolve(true);
|
|
18682
|
-
return new Promise((
|
|
18726
|
+
return new Promise((resolve13) => {
|
|
18683
18727
|
let timer;
|
|
18684
18728
|
const done = (stopped) => {
|
|
18685
18729
|
clearTimeout(timer);
|
|
18686
18730
|
child.off("close", closed);
|
|
18687
|
-
|
|
18731
|
+
resolve13(stopped);
|
|
18688
18732
|
};
|
|
18689
18733
|
const closed = () => done(true);
|
|
18690
18734
|
child.once("close", closed);
|
|
@@ -18909,8 +18953,10 @@ var init_registry = __esm({
|
|
|
18909
18953
|
access: driver?.metadata.access ?? "subscription",
|
|
18910
18954
|
install: driver?.install,
|
|
18911
18955
|
authentication: inst.startAuthentication ? {
|
|
18912
|
-
method: inst.getAuthentication && inst.completeAuthentication ? "paste-code" : inst.getAuthentication ? "device-code" : "browser"
|
|
18956
|
+
method: inst.getAuthentication && inst.completeAuthentication ? "paste-code" : inst.getAuthentication ? "device-code" : "browser",
|
|
18913
18957
|
// a link and a callback URL (managed engines)
|
|
18958
|
+
// the browser may remove the stored sign-in to switch accounts
|
|
18959
|
+
signOut: inst.signOut !== void 0
|
|
18914
18960
|
} : void 0,
|
|
18915
18961
|
cli: this.cliByInstance.get(inst.instanceId),
|
|
18916
18962
|
cliDefault: cliDefaultOf(driver),
|
|
@@ -19625,7 +19671,7 @@ function createAcpDriver(support11) {
|
|
|
19625
19671
|
}
|
|
19626
19672
|
appendNative(threadId, { dir: "out", source: SOURCE, msg: nativeLogMessage(obj) });
|
|
19627
19673
|
};
|
|
19628
|
-
const request = (method, params, timeoutMs) => new Promise((
|
|
19674
|
+
const request = (method, params, timeoutMs) => new Promise((resolve13, reject) => {
|
|
19629
19675
|
const id = nextId++;
|
|
19630
19676
|
let timer = null;
|
|
19631
19677
|
if (timeoutMs) {
|
|
@@ -19635,7 +19681,7 @@ function createAcpDriver(support11) {
|
|
|
19635
19681
|
}, timeoutMs);
|
|
19636
19682
|
timer.unref?.();
|
|
19637
19683
|
}
|
|
19638
|
-
rpcPending.set(id, { resolve:
|
|
19684
|
+
rpcPending.set(id, { resolve: resolve13, reject, timer });
|
|
19639
19685
|
send({ jsonrpc: "2.0", id, method, params });
|
|
19640
19686
|
});
|
|
19641
19687
|
const stop = () => killCliTree(child);
|
|
@@ -20071,12 +20117,12 @@ ${turn.text}` : turn.text;
|
|
|
20071
20117
|
const snapshot = async () => {
|
|
20072
20118
|
const env = childEnv();
|
|
20073
20119
|
if (support11.snapshot) return support11.snapshot(env, config2, instanceId);
|
|
20074
|
-
const version2 = await new Promise((
|
|
20120
|
+
const version2 = await new Promise((resolve13) => {
|
|
20075
20121
|
execCli(
|
|
20076
20122
|
config2.cli,
|
|
20077
20123
|
["--version"],
|
|
20078
20124
|
{ timeout: 8e3, env },
|
|
20079
|
-
(err, stdout2) =>
|
|
20125
|
+
(err, stdout2) => resolve13(err ? null : stdout2.trim())
|
|
20080
20126
|
);
|
|
20081
20127
|
});
|
|
20082
20128
|
if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
|
|
@@ -20466,14 +20512,14 @@ var init_antigravity_acp = __esm({
|
|
|
20466
20512
|
this.child.stderr.setEncoding("utf8");
|
|
20467
20513
|
this.child.stderr.on("data", (chunk) => this.consumeDiagnostics(chunk));
|
|
20468
20514
|
this.child.once("error", (error51) => this.failAll(error51));
|
|
20469
|
-
this.exited = new Promise((
|
|
20515
|
+
this.exited = new Promise((resolve13) => {
|
|
20470
20516
|
this.child.once("close", (code, signal) => {
|
|
20471
20517
|
this.noteStartupDiagnostic(this.diagnosticBuffer);
|
|
20472
20518
|
this.diagnosticBuffer = "";
|
|
20473
20519
|
if (!this.closed) this.failAll(new Error(
|
|
20474
20520
|
`Antigravity ACP exited ${code ?? signal ?? "unexpectedly"}.${this.nativeStartupHint ? ` ${this.nativeStartupHint}` : ""}`
|
|
20475
20521
|
));
|
|
20476
|
-
|
|
20522
|
+
resolve13();
|
|
20477
20523
|
});
|
|
20478
20524
|
});
|
|
20479
20525
|
}
|
|
@@ -20579,8 +20625,8 @@ var init_antigravity_acp = __esm({
|
|
|
20579
20625
|
async closeAndWait(timeoutMs = 5e3) {
|
|
20580
20626
|
this.close();
|
|
20581
20627
|
let timer;
|
|
20582
|
-
const timedOut = new Promise((
|
|
20583
|
-
timer = setTimeout(() =>
|
|
20628
|
+
const timedOut = new Promise((resolve13) => {
|
|
20629
|
+
timer = setTimeout(() => resolve13(false), timeoutMs);
|
|
20584
20630
|
timer.unref?.();
|
|
20585
20631
|
});
|
|
20586
20632
|
try {
|
|
@@ -21089,7 +21135,7 @@ var init_antigravity_runtime = __esm({
|
|
|
21089
21135
|
FREE_SPACE_MARGIN = 256 * 1024 * 1024;
|
|
21090
21136
|
DOWNLOAD_TIMEOUT_MS2 = 45 * 6e4;
|
|
21091
21137
|
STAGING_PREFIX = ".install-";
|
|
21092
|
-
wait = (ms) => new Promise((
|
|
21138
|
+
wait = (ms) => new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
21093
21139
|
INSTALL_RECORD = ".install-complete.json";
|
|
21094
21140
|
AntigravitySetupError = class extends Error {
|
|
21095
21141
|
status = 409;
|
|
@@ -21803,13 +21849,13 @@ function computeBackoff(attempt, random = Math.random) {
|
|
|
21803
21849
|
function interruptibleDelay(ms, signal) {
|
|
21804
21850
|
let timer = null;
|
|
21805
21851
|
let onCancel = null;
|
|
21806
|
-
const promise2 = new Promise((
|
|
21807
|
-
timer = setTimeout(() =>
|
|
21852
|
+
const promise2 = new Promise((resolve13) => {
|
|
21853
|
+
timer = setTimeout(() => resolve13("elapsed"), Math.max(1, ms));
|
|
21808
21854
|
timer.unref?.();
|
|
21809
|
-
if (signal?.aborted) return
|
|
21855
|
+
if (signal?.aborted) return resolve13("cancelled");
|
|
21810
21856
|
onCancel = () => {
|
|
21811
21857
|
clearTimeout(timer);
|
|
21812
|
-
|
|
21858
|
+
resolve13("cancelled");
|
|
21813
21859
|
};
|
|
21814
21860
|
signal?.addEventListener("abort", onCancel, { once: true });
|
|
21815
21861
|
});
|
|
@@ -21863,24 +21909,24 @@ import { createServer as createNetServer } from "node:net";
|
|
|
21863
21909
|
import { homedir as homedir9, tmpdir as tmpdir3 } from "node:os";
|
|
21864
21910
|
import { join as join16, dirname as dirname8, isAbsolute as isAbsolute4, normalize } from "node:path";
|
|
21865
21911
|
function claudeAuthStatus(cli, env, run3 = execCli) {
|
|
21866
|
-
return new Promise((
|
|
21912
|
+
return new Promise((resolve13) => {
|
|
21867
21913
|
run3(cli, ["auth", "status", "--json"], { timeout: 8e3, maxBuffer: 65536, env }, (_error, stdout2) => {
|
|
21868
21914
|
try {
|
|
21869
21915
|
const status = JSON.parse(stdout2);
|
|
21870
21916
|
if (!status || typeof status !== "object" || !("loggedIn" in status) || status.loggedIn !== true) {
|
|
21871
|
-
return
|
|
21917
|
+
return resolve13({ authenticated: false });
|
|
21872
21918
|
}
|
|
21873
21919
|
const identity = status;
|
|
21874
21920
|
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
21921
|
const candidateEmail = boundedText(identity.email, 254);
|
|
21876
21922
|
const email3 = candidateEmail && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(candidateEmail) ? candidateEmail : void 0;
|
|
21877
21923
|
const organization = boundedText(identity.orgName, 160);
|
|
21878
|
-
|
|
21924
|
+
resolve13({
|
|
21879
21925
|
authenticated: true,
|
|
21880
21926
|
...email3 || organization ? { account: { ...email3 ? { email: email3 } : {}, ...organization ? { organization } : {} } } : {}
|
|
21881
21927
|
});
|
|
21882
21928
|
} catch {
|
|
21883
|
-
|
|
21929
|
+
resolve13({ authenticated: false });
|
|
21884
21930
|
}
|
|
21885
21931
|
});
|
|
21886
21932
|
});
|
|
@@ -22071,9 +22117,9 @@ async function createPermissionBroker(opts) {
|
|
|
22071
22117
|
unlinkSync3(candidate);
|
|
22072
22118
|
} catch {
|
|
22073
22119
|
}
|
|
22074
|
-
let outcome = await new Promise((
|
|
22075
|
-
attempt.once("listening", () =>
|
|
22076
|
-
attempt.once("error", (error51) =>
|
|
22120
|
+
let outcome = await new Promise((resolve13) => {
|
|
22121
|
+
attempt.once("listening", () => resolve13("listening"));
|
|
22122
|
+
attempt.once("error", (error51) => resolve13(error51));
|
|
22077
22123
|
attempt.listen(candidate);
|
|
22078
22124
|
});
|
|
22079
22125
|
if (outcome === "listening" && process.platform !== "win32") {
|
|
@@ -22330,19 +22376,19 @@ var init_claude = __esm({
|
|
|
22330
22376
|
};
|
|
22331
22377
|
const writeUser = (s, threadId, promptMsg) => {
|
|
22332
22378
|
if (!s.child.stdin.writable || s.child.stdin.destroyed) return Promise.resolve(false);
|
|
22333
|
-
return new Promise((
|
|
22379
|
+
return new Promise((resolve13) => {
|
|
22334
22380
|
try {
|
|
22335
22381
|
s.child.stdin.write(JSON.stringify(promptMsg) + "\n", (error51) => {
|
|
22336
|
-
if (error51) return
|
|
22382
|
+
if (error51) return resolve13(false);
|
|
22337
22383
|
appendNative(threadId, {
|
|
22338
22384
|
dir: "out",
|
|
22339
22385
|
source: "claude.sdk.message",
|
|
22340
22386
|
msg: diagnosticClaudeUserMessage(promptMsg)
|
|
22341
22387
|
});
|
|
22342
|
-
|
|
22388
|
+
resolve13(true);
|
|
22343
22389
|
});
|
|
22344
22390
|
} catch {
|
|
22345
|
-
|
|
22391
|
+
resolve13(false);
|
|
22346
22392
|
}
|
|
22347
22393
|
});
|
|
22348
22394
|
};
|
|
@@ -22832,19 +22878,19 @@ var init_claude = __esm({
|
|
|
22832
22878
|
} });
|
|
22833
22879
|
const snapshot = async () => {
|
|
22834
22880
|
const env = environment();
|
|
22835
|
-
const version2 = await new Promise((
|
|
22881
|
+
const version2 = await new Promise((resolve13) => {
|
|
22836
22882
|
execCli(
|
|
22837
22883
|
config2.cli,
|
|
22838
22884
|
["--version"],
|
|
22839
22885
|
{ timeout: 8e3, env },
|
|
22840
|
-
(err, stdout2) =>
|
|
22886
|
+
(err, stdout2) => resolve13(err ? null : stdout2.trim())
|
|
22841
22887
|
);
|
|
22842
22888
|
});
|
|
22843
22889
|
if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
|
|
22844
22890
|
const auth = await claudeAuthStatus(config2.cli, env);
|
|
22845
22891
|
return { state: "available", version: version2, ...auth, billing: "subscription" };
|
|
22846
22892
|
};
|
|
22847
|
-
const generateReview = (prompt, signal) => new Promise((
|
|
22893
|
+
const generateReview = (prompt, signal) => new Promise((resolve13, reject) => {
|
|
22848
22894
|
const child = spawnCli(
|
|
22849
22895
|
config2.cli,
|
|
22850
22896
|
["-p", "--model", "claude-haiku-4-5", "--output-format", "text"],
|
|
@@ -22862,7 +22908,7 @@ var init_claude = __esm({
|
|
|
22862
22908
|
clearTimeout(timer);
|
|
22863
22909
|
signal?.removeEventListener("abort", onAbort);
|
|
22864
22910
|
if (error51) reject(error51);
|
|
22865
|
-
else
|
|
22911
|
+
else resolve13(stdout2.trim());
|
|
22866
22912
|
};
|
|
22867
22913
|
const onAbort = () => {
|
|
22868
22914
|
killCliTree(child);
|
|
@@ -22977,7 +23023,7 @@ function decodeCodexSelection(id) {
|
|
|
22977
23023
|
return { model: id, modelProvider: MODEL_ID2.test(id) ? OFFICIAL_CODEX_PROVIDER : null };
|
|
22978
23024
|
}
|
|
22979
23025
|
function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
|
|
22980
|
-
return new Promise((
|
|
23026
|
+
return new Promise((resolve13) => {
|
|
22981
23027
|
const child = spawnCli(cli, ["app-server"], {
|
|
22982
23028
|
cwd: homedir10(),
|
|
22983
23029
|
env,
|
|
@@ -22994,7 +23040,7 @@ function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
|
|
|
22994
23040
|
settled = true;
|
|
22995
23041
|
clearTimeout(timer);
|
|
22996
23042
|
killCliTree(child);
|
|
22997
|
-
|
|
23043
|
+
resolve13(catalog);
|
|
22998
23044
|
};
|
|
22999
23045
|
const request = (method, params, kind) => {
|
|
23000
23046
|
const id = nextId++;
|
|
@@ -23405,6 +23451,7 @@ var init_codex_device_auth = __esm({
|
|
|
23405
23451
|
authenticatingHomes2 = /* @__PURE__ */ new Set();
|
|
23406
23452
|
CodexDeviceAuthController = class {
|
|
23407
23453
|
flow = null;
|
|
23454
|
+
command = null;
|
|
23408
23455
|
disposed = false;
|
|
23409
23456
|
options;
|
|
23410
23457
|
constructor(options) {
|
|
@@ -23480,12 +23527,92 @@ var init_codex_device_auth = __esm({
|
|
|
23480
23527
|
if (this.flow?.status.phase === "waiting") this.finish(this.flow, "cancelled", "ChatGPT sign-in cancelled.");
|
|
23481
23528
|
await this.flow?.stopping;
|
|
23482
23529
|
if (this.flow?.terminationFailed) throw new Error(this.flow.status.message);
|
|
23530
|
+
if (this.command && !await this.stopChild(this.command)) {
|
|
23531
|
+
throw new Error("Codex could not be stopped on this server. Ask the server administrator to stop the account command before trying again.");
|
|
23532
|
+
}
|
|
23483
23533
|
}
|
|
23484
23534
|
async dispose() {
|
|
23485
23535
|
this.disposed = true;
|
|
23486
23536
|
await this.cancel();
|
|
23487
23537
|
this.flow = null;
|
|
23488
23538
|
}
|
|
23539
|
+
/** Remove the ChatGPT sign-in Codex stores for this server account so a
|
|
23540
|
+
* different account can connect. A sign-in in progress is never pulled
|
|
23541
|
+
* away underneath the browser completing it. */
|
|
23542
|
+
async signOut() {
|
|
23543
|
+
if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
|
|
23544
|
+
if (this.flow?.status.phase === "waiting") throw new Error("Finish or cancel the ChatGPT sign-in in progress before signing out.");
|
|
23545
|
+
await this.flow?.stopping;
|
|
23546
|
+
if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
|
|
23547
|
+
const env = this.options.environment();
|
|
23548
|
+
const home = env.HOME || env.USERPROFILE || homedir11();
|
|
23549
|
+
if (!isAbsolute5(home) || env.CODEX_HOME && !isAbsolute5(env.CODEX_HOME)) {
|
|
23550
|
+
throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing out.");
|
|
23551
|
+
}
|
|
23552
|
+
const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join19(home, ".codex")));
|
|
23553
|
+
if (authenticatingHomes2.has(homeKey)) {
|
|
23554
|
+
throw new Error("A ChatGPT sign-in is running for this server account. Finish or cancel it before signing out.");
|
|
23555
|
+
}
|
|
23556
|
+
authenticatingHomes2.add(homeKey);
|
|
23557
|
+
try {
|
|
23558
|
+
const before = await this.exec(["login", "status"], env, home);
|
|
23559
|
+
if (before.code === 1 && /^not logged in\b/im.test(before.output)) return;
|
|
23560
|
+
if (before.code !== 0 || !/^logged in.*chatgpt\b/im.test(before.output)) {
|
|
23561
|
+
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.");
|
|
23562
|
+
}
|
|
23563
|
+
const logout = await this.exec(["logout"], env, home);
|
|
23564
|
+
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.");
|
|
23565
|
+
const status = await this.exec(["login", "status"], env, home);
|
|
23566
|
+
if (status.code !== 1 || !/^not logged in\b/im.test(status.output)) {
|
|
23567
|
+
throw new Error("Codex still reports a sign-in on this server. Update Codex and check its login status before trying again.");
|
|
23568
|
+
}
|
|
23569
|
+
} finally {
|
|
23570
|
+
const child = this.command;
|
|
23571
|
+
if (child && child.exitCode === null && child.signalCode === null) {
|
|
23572
|
+
child.once("close", () => authenticatingHomes2.delete(homeKey));
|
|
23573
|
+
} else authenticatingHomes2.delete(homeKey);
|
|
23574
|
+
}
|
|
23575
|
+
}
|
|
23576
|
+
/** One bounded, non-interactive Codex command. Its output stays here;
|
|
23577
|
+
* callers see an exit code and a status-line match, never the text. */
|
|
23578
|
+
exec(args, env, cwd) {
|
|
23579
|
+
return new Promise((resolveExec, rejectExec) => {
|
|
23580
|
+
if (this.disposed) {
|
|
23581
|
+
rejectExec(new Error("This provider was removed. Refresh Settings before signing out."));
|
|
23582
|
+
return;
|
|
23583
|
+
}
|
|
23584
|
+
let child;
|
|
23585
|
+
try {
|
|
23586
|
+
child = spawnCli(this.options.cli, args, { env: { ...env, NO_COLOR: "1" }, cwd, stdio: ["pipe", "pipe", "pipe"] });
|
|
23587
|
+
} catch {
|
|
23588
|
+
rejectExec(new Error("Codex could not start on this server. Install or update the configured Codex CLI, then try again."));
|
|
23589
|
+
return;
|
|
23590
|
+
}
|
|
23591
|
+
this.command = child;
|
|
23592
|
+
child.stdin.end();
|
|
23593
|
+
let output = "";
|
|
23594
|
+
const receive = (chunk) => {
|
|
23595
|
+
if (output.length < MAX_OUTPUT2) output += chunk.toString("utf8").slice(0, MAX_OUTPUT2 - output.length);
|
|
23596
|
+
};
|
|
23597
|
+
child.stdout.on("data", receive);
|
|
23598
|
+
child.stderr.on("data", receive);
|
|
23599
|
+
const timer = setTimeout(() => {
|
|
23600
|
+
void this.stopChild(child).catch(() => false).then((stopped) => {
|
|
23601
|
+
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."));
|
|
23602
|
+
});
|
|
23603
|
+
}, this.options.startupTimeoutMs ?? 3e4);
|
|
23604
|
+
timer.unref();
|
|
23605
|
+
child.once("error", (error51) => {
|
|
23606
|
+
clearTimeout(timer);
|
|
23607
|
+
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."));
|
|
23608
|
+
});
|
|
23609
|
+
child.once("close", (code) => {
|
|
23610
|
+
clearTimeout(timer);
|
|
23611
|
+
if (this.command === child) this.command = null;
|
|
23612
|
+
resolveExec({ code, output: stripVTControlCharacters4(output) });
|
|
23613
|
+
});
|
|
23614
|
+
});
|
|
23615
|
+
}
|
|
23489
23616
|
run(flow, args, env, cwd, done, parsePrompt = false) {
|
|
23490
23617
|
if (flow.status.phase !== "waiting") return;
|
|
23491
23618
|
let child;
|
|
@@ -23540,7 +23667,7 @@ var init_codex_device_auth = __esm({
|
|
|
23540
23667
|
if (phase === "succeeded") flow.resolve({ ...flow.status, phase });
|
|
23541
23668
|
else flow.reject(new Error(message2 ?? "ChatGPT sign-in did not finish."));
|
|
23542
23669
|
}
|
|
23543
|
-
flow.stopping = this.stopChild(flow).catch(() => false).then((stopped) => {
|
|
23670
|
+
flow.stopping = this.stopChild(flow.child).catch(() => false).then((stopped) => {
|
|
23544
23671
|
const release = () => authenticatingHomes2.delete(flow.homeKey);
|
|
23545
23672
|
if (stopped) {
|
|
23546
23673
|
release();
|
|
@@ -23555,8 +23682,7 @@ var init_codex_device_auth = __esm({
|
|
|
23555
23682
|
if (phase === "succeeded") void this.options.onAuthenticated?.().catch(() => {
|
|
23556
23683
|
});
|
|
23557
23684
|
}
|
|
23558
|
-
async stopChild(
|
|
23559
|
-
const child = flow.child;
|
|
23685
|
+
async stopChild(child) {
|
|
23560
23686
|
if (!child || await killCliTree(child, this.options.terminateTimeoutMs ?? 1500)) return true;
|
|
23561
23687
|
if (process.platform !== "win32" && child.pid) {
|
|
23562
23688
|
try {
|
|
@@ -23580,9 +23706,122 @@ var init_codex_device_auth = __esm({
|
|
|
23580
23706
|
}
|
|
23581
23707
|
});
|
|
23582
23708
|
|
|
23709
|
+
// server/drivers/codex-identity.ts
|
|
23710
|
+
import { homedir as homedir12 } from "node:os";
|
|
23711
|
+
import { isAbsolute as isAbsolute6, join as join20, resolve as resolve9 } from "node:path";
|
|
23712
|
+
function codexHome2(env) {
|
|
23713
|
+
if (env.CODEX_HOME) return isAbsolute6(env.CODEX_HOME) ? resolve9(env.CODEX_HOME) : null;
|
|
23714
|
+
const home = env.HOME || env.USERPROFILE || homedir12();
|
|
23715
|
+
return isAbsolute6(home) ? join20(home, ".codex") : null;
|
|
23716
|
+
}
|
|
23717
|
+
async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
|
|
23718
|
+
const cwd = env.HOME || env.USERPROFILE || homedir12();
|
|
23719
|
+
if (!isAbsolute6(cwd) || !codexHome2(env)) return null;
|
|
23720
|
+
return new Promise((resolveEmail) => {
|
|
23721
|
+
let child;
|
|
23722
|
+
try {
|
|
23723
|
+
child = spawnCli(cli, ["app-server"], { cwd, env, stdio: ["pipe", "pipe", "pipe"] });
|
|
23724
|
+
} catch {
|
|
23725
|
+
resolveEmail(null);
|
|
23726
|
+
return;
|
|
23727
|
+
}
|
|
23728
|
+
let finishing = false;
|
|
23729
|
+
let buffer = "";
|
|
23730
|
+
let outputBytes = 0;
|
|
23731
|
+
let initialized = false;
|
|
23732
|
+
const finish = async (email3) => {
|
|
23733
|
+
if (finishing) return;
|
|
23734
|
+
finishing = true;
|
|
23735
|
+
clearTimeout(timer);
|
|
23736
|
+
let stopped = await killCliTree(child, 1e3);
|
|
23737
|
+
if (!stopped && child.pid) {
|
|
23738
|
+
try {
|
|
23739
|
+
if (process.platform === "win32") child.kill("SIGKILL");
|
|
23740
|
+
else process.kill(-child.pid, "SIGKILL");
|
|
23741
|
+
} catch {
|
|
23742
|
+
try {
|
|
23743
|
+
child.kill("SIGKILL");
|
|
23744
|
+
} catch {
|
|
23745
|
+
}
|
|
23746
|
+
}
|
|
23747
|
+
stopped = await killCliTree(child, 1e3);
|
|
23748
|
+
}
|
|
23749
|
+
resolveEmail(stopped ? email3 : null);
|
|
23750
|
+
};
|
|
23751
|
+
const timer = setTimeout(() => {
|
|
23752
|
+
void finish(null);
|
|
23753
|
+
}, timeoutMs);
|
|
23754
|
+
timer.unref();
|
|
23755
|
+
const send = (message2) => {
|
|
23756
|
+
try {
|
|
23757
|
+
child.stdin.write(`${JSON.stringify(message2)}
|
|
23758
|
+
`);
|
|
23759
|
+
} catch {
|
|
23760
|
+
void finish(null);
|
|
23761
|
+
}
|
|
23762
|
+
};
|
|
23763
|
+
child.stdin.on("error", () => {
|
|
23764
|
+
void finish(null);
|
|
23765
|
+
});
|
|
23766
|
+
child.stderr.resume();
|
|
23767
|
+
child.on("error", () => {
|
|
23768
|
+
void finish(null);
|
|
23769
|
+
});
|
|
23770
|
+
child.on("close", () => {
|
|
23771
|
+
void finish(null);
|
|
23772
|
+
});
|
|
23773
|
+
child.stdout.setEncoding("utf8");
|
|
23774
|
+
child.stdout.on("data", (chunk) => {
|
|
23775
|
+
if (finishing) return;
|
|
23776
|
+
outputBytes += Buffer.byteLength(chunk);
|
|
23777
|
+
if (outputBytes > MAX_OUTPUT3) {
|
|
23778
|
+
void finish(null);
|
|
23779
|
+
return;
|
|
23780
|
+
}
|
|
23781
|
+
buffer += chunk;
|
|
23782
|
+
let newline;
|
|
23783
|
+
while (!finishing && (newline = buffer.indexOf("\n")) !== -1) {
|
|
23784
|
+
const line = buffer.slice(0, newline);
|
|
23785
|
+
buffer = buffer.slice(newline + 1);
|
|
23786
|
+
if (!line.trim()) continue;
|
|
23787
|
+
let message2;
|
|
23788
|
+
try {
|
|
23789
|
+
message2 = JSON.parse(line);
|
|
23790
|
+
} catch {
|
|
23791
|
+
void finish(null);
|
|
23792
|
+
return;
|
|
23793
|
+
}
|
|
23794
|
+
if (!initialized && message2?.id === 1) {
|
|
23795
|
+
if (message2.error || !message2.result) {
|
|
23796
|
+
void finish(null);
|
|
23797
|
+
return;
|
|
23798
|
+
}
|
|
23799
|
+
initialized = true;
|
|
23800
|
+
send({ method: "initialized", params: {} });
|
|
23801
|
+
send({ id: 2, method: "account/read", params: { refreshToken: false } });
|
|
23802
|
+
} else if (initialized && message2?.id === 2) {
|
|
23803
|
+
const account = message2.error ? null : message2.result?.account;
|
|
23804
|
+
const email3 = account?.type === "chatgpt" ? account.email : null;
|
|
23805
|
+
void finish(typeof email3 === "string" && email3.length <= 254 && EMAIL.test(email3) && !/[\p{Cc}\p{Cf}]/u.test(email3) ? email3 : null);
|
|
23806
|
+
}
|
|
23807
|
+
}
|
|
23808
|
+
});
|
|
23809
|
+
send({ id: 1, method: "initialize", params: { clientInfo: { name: "openmausbot", version: "1" } } });
|
|
23810
|
+
});
|
|
23811
|
+
}
|
|
23812
|
+
var MAX_OUTPUT3, EMAIL;
|
|
23813
|
+
var init_codex_identity = __esm({
|
|
23814
|
+
"server/drivers/codex-identity.ts"() {
|
|
23815
|
+
"use strict";
|
|
23816
|
+
init_procs();
|
|
23817
|
+
MAX_OUTPUT3 = 16384;
|
|
23818
|
+
EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
23819
|
+
}
|
|
23820
|
+
});
|
|
23821
|
+
|
|
23583
23822
|
// server/drivers/codex.ts
|
|
23584
23823
|
import { existsSync as existsSync7 } from "node:fs";
|
|
23585
|
-
import { homedir as
|
|
23824
|
+
import { homedir as homedir13 } from "node:os";
|
|
23586
23825
|
function codexPredatesAstra(version2) {
|
|
23587
23826
|
const value = version2.trim();
|
|
23588
23827
|
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);
|
|
@@ -23852,6 +24091,7 @@ var init_codex = __esm({
|
|
|
23852
24091
|
init_native();
|
|
23853
24092
|
init_codex_instructions();
|
|
23854
24093
|
init_codex_device_auth();
|
|
24094
|
+
init_codex_identity();
|
|
23855
24095
|
init_codex_catalog();
|
|
23856
24096
|
DRIVER_KIND3 = "codex";
|
|
23857
24097
|
ASTRA_MODEL_ID = "gpt-6-astra";
|
|
@@ -23985,7 +24225,7 @@ var init_codex = __esm({
|
|
|
23985
24225
|
);
|
|
23986
24226
|
}
|
|
23987
24227
|
const child = spawnCli(config2.cli, appServerArgs, {
|
|
23988
|
-
cwd: turn.cwd ??
|
|
24228
|
+
cwd: turn.cwd ?? homedir13(),
|
|
23989
24229
|
env,
|
|
23990
24230
|
stdio: ["pipe", "pipe", "pipe"]
|
|
23991
24231
|
});
|
|
@@ -24013,7 +24253,7 @@ var init_codex = __esm({
|
|
|
24013
24253
|
msg: codexNativeLogMessage(obj)
|
|
24014
24254
|
});
|
|
24015
24255
|
};
|
|
24016
|
-
const request = (method, params, timeoutMs = 6e4) => new Promise((
|
|
24256
|
+
const request = (method, params, timeoutMs = 6e4) => new Promise((resolve13, reject) => {
|
|
24017
24257
|
const id = nextId++;
|
|
24018
24258
|
if (method === "config/read") sensitiveResponseIds.add(id);
|
|
24019
24259
|
const timer = setTimeout(() => {
|
|
@@ -24023,7 +24263,7 @@ var init_codex = __esm({
|
|
|
24023
24263
|
rpcPending.set(id, {
|
|
24024
24264
|
resolve: (v) => {
|
|
24025
24265
|
clearTimeout(timer);
|
|
24026
|
-
|
|
24266
|
+
resolve13(v);
|
|
24027
24267
|
},
|
|
24028
24268
|
reject: (e) => {
|
|
24029
24269
|
clearTimeout(timer);
|
|
@@ -24291,7 +24531,7 @@ var init_codex = __esm({
|
|
|
24291
24531
|
let effectiveConfig;
|
|
24292
24532
|
try {
|
|
24293
24533
|
const configured = await request("config/read", {
|
|
24294
|
-
cwd: turn.cwd ??
|
|
24534
|
+
cwd: turn.cwd ?? homedir13(),
|
|
24295
24535
|
includeLayers: false
|
|
24296
24536
|
});
|
|
24297
24537
|
effectiveConfig = configured?.config;
|
|
@@ -24335,7 +24575,7 @@ var init_codex = __esm({
|
|
|
24335
24575
|
const selection = decodeCodexSelection(turn.model);
|
|
24336
24576
|
const startThread = () => request("thread/start", {
|
|
24337
24577
|
developerInstructions,
|
|
24338
|
-
cwd: turn.cwd ??
|
|
24578
|
+
cwd: turn.cwd ?? homedir13(),
|
|
24339
24579
|
model: selection.model,
|
|
24340
24580
|
...selection.modelProvider ? { modelProvider: selection.modelProvider } : {},
|
|
24341
24581
|
...approvalParams.thread,
|
|
@@ -24402,8 +24642,8 @@ var init_codex = __esm({
|
|
|
24402
24642
|
void settle(false, "shutdown_timeout");
|
|
24403
24643
|
return;
|
|
24404
24644
|
}
|
|
24405
|
-
await new Promise((
|
|
24406
|
-
const timer = setTimeout(
|
|
24645
|
+
await new Promise((resolve13) => {
|
|
24646
|
+
const timer = setTimeout(resolve13, Math.max(1, Math.round(delayMs * retryScale)));
|
|
24407
24647
|
timer.unref?.();
|
|
24408
24648
|
});
|
|
24409
24649
|
if (!stopRequested) {
|
|
@@ -24431,28 +24671,30 @@ var init_codex = __esm({
|
|
|
24431
24671
|
};
|
|
24432
24672
|
const snapshot = async () => {
|
|
24433
24673
|
const env = childEnv();
|
|
24434
|
-
const version2 = await new Promise((
|
|
24674
|
+
const version2 = await new Promise((resolve13) => {
|
|
24435
24675
|
execCli(
|
|
24436
24676
|
config2.cli,
|
|
24437
24677
|
["--version"],
|
|
24438
24678
|
{ timeout: 8e3, env },
|
|
24439
|
-
(err, stdout2) =>
|
|
24679
|
+
(err, stdout2) => resolve13(err ? null : stdout2.trim())
|
|
24440
24680
|
);
|
|
24441
24681
|
});
|
|
24442
24682
|
if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
|
|
24443
|
-
const authenticated = await new Promise((
|
|
24683
|
+
const authenticated = await new Promise((resolve13) => {
|
|
24444
24684
|
execCli(
|
|
24445
24685
|
config2.cli,
|
|
24446
24686
|
["login", "status"],
|
|
24447
24687
|
{ timeout: 8e3, env },
|
|
24448
|
-
(err, stdout2, stderr) =>
|
|
24688
|
+
(err, stdout2, stderr) => resolve13(!err && /^logged in\b/im.test(`${stdout2}
|
|
24449
24689
|
${stderr ?? ""}`))
|
|
24450
24690
|
);
|
|
24451
24691
|
});
|
|
24692
|
+
const email3 = authenticated ? await codexAccountEmail(config2.cli, env) : null;
|
|
24452
24693
|
return {
|
|
24453
24694
|
state: "available",
|
|
24454
24695
|
version: version2,
|
|
24455
24696
|
authenticated,
|
|
24697
|
+
...email3 ? { account: { email: email3 } } : {},
|
|
24456
24698
|
update: codexAstraUpdate(version2, models, config2.cli),
|
|
24457
24699
|
billing: "subscription"
|
|
24458
24700
|
};
|
|
@@ -24469,6 +24711,7 @@ ${stderr ?? ""}`))
|
|
|
24469
24711
|
startAuthentication: () => authentication.start(),
|
|
24470
24712
|
getAuthentication: (flowId) => authentication.get(flowId),
|
|
24471
24713
|
cancelAuthentication: () => authentication.cancel(),
|
|
24714
|
+
signOut: () => authentication.signOut(),
|
|
24472
24715
|
snapshot,
|
|
24473
24716
|
adapter: {
|
|
24474
24717
|
provider: DRIVER_KIND3,
|
|
@@ -24793,11 +25036,11 @@ var init_grok = __esm({
|
|
|
24793
25036
|
|
|
24794
25037
|
// server/drivers/acp/grok.ts
|
|
24795
25038
|
import { existsSync as existsSync8, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
24796
|
-
import { homedir as
|
|
24797
|
-
import { join as
|
|
25039
|
+
import { homedir as homedir14 } from "node:os";
|
|
25040
|
+
import { join as join21 } from "node:path";
|
|
24798
25041
|
function grokHome(env) {
|
|
24799
25042
|
if (env.GROK_HOME) return env.GROK_HOME;
|
|
24800
|
-
return
|
|
25043
|
+
return join21(env.HOME || env.USERPROFILE || homedir14(), ".grok");
|
|
24801
25044
|
}
|
|
24802
25045
|
function unquote2(raw) {
|
|
24803
25046
|
const value = raw.trim();
|
|
@@ -24807,7 +25050,7 @@ function unquote2(raw) {
|
|
|
24807
25050
|
return value;
|
|
24808
25051
|
}
|
|
24809
25052
|
function readGrokModelCatalog(env = process.env) {
|
|
24810
|
-
const path3 =
|
|
25053
|
+
const path3 = join21(grokHome(env), "config.toml");
|
|
24811
25054
|
let text2 = "";
|
|
24812
25055
|
try {
|
|
24813
25056
|
text2 = readFileSync9(path3, "utf8");
|
|
@@ -24880,7 +25123,7 @@ function ensureGrokInjectSlug(modelId, env = process.env) {
|
|
|
24880
25123
|
if (!inject) return modelId;
|
|
24881
25124
|
const host = localHost(inject.host);
|
|
24882
25125
|
if (!host) return modelId;
|
|
24883
|
-
const path3 =
|
|
25126
|
+
const path3 = join21(grokHome(env), "config.toml");
|
|
24884
25127
|
let text2 = "";
|
|
24885
25128
|
try {
|
|
24886
25129
|
text2 = readFileSync9(path3, "utf8");
|
|
@@ -25015,7 +25258,7 @@ var init_grok2 = __esm({
|
|
|
25015
25258
|
// an unauthenticated CLI is a user action, not something to paper over.
|
|
25016
25259
|
pickAuthMethod: (methods) => methods.some((m) => m.id === "cached_token") ? "cached_token" : null,
|
|
25017
25260
|
authFailure: "fail",
|
|
25018
|
-
isAuthenticated: () => existsSync8(
|
|
25261
|
+
isAuthenticated: () => existsSync8(join21(homedir14(), ".grok", "auth.json")),
|
|
25019
25262
|
// `--append-system-prompt`/`--rules` are accepted by the CLI but do NOT
|
|
25020
25263
|
// reach the agent-stdio system prompt (verified against 1.0.0), so the
|
|
25021
25264
|
// persona is prepended codex-style.
|
|
@@ -25029,11 +25272,11 @@ ${turn.text}` : turn.text
|
|
|
25029
25272
|
|
|
25030
25273
|
// server/drivers/acp/gemini.ts
|
|
25031
25274
|
import { existsSync as existsSync9, readFileSync as readFileSync10 } from "node:fs";
|
|
25032
|
-
import { homedir as
|
|
25033
|
-
import { join as
|
|
25275
|
+
import { homedir as homedir15 } from "node:os";
|
|
25276
|
+
import { join as join22 } from "node:path";
|
|
25034
25277
|
function liveOauthCredential() {
|
|
25035
25278
|
try {
|
|
25036
|
-
const creds = JSON.parse(readFileSync10(
|
|
25279
|
+
const creds = JSON.parse(readFileSync10(join22(homedir15(), ".gemini", "oauth_creds.json"), "utf8"));
|
|
25037
25280
|
if (typeof creds.access_token !== "string" || creds.access_token.trim().length === 0) return false;
|
|
25038
25281
|
const hasRefresh = typeof creds.refresh_token === "string" && creds.refresh_token.trim().length > 0;
|
|
25039
25282
|
if (creds.expiry_date !== void 0) {
|
|
@@ -25046,7 +25289,7 @@ function liveOauthCredential() {
|
|
|
25046
25289
|
}
|
|
25047
25290
|
}
|
|
25048
25291
|
function geminiIsAuthenticated(env) {
|
|
25049
|
-
return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync9(
|
|
25292
|
+
return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync9(join22(homedir15(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
|
|
25050
25293
|
}
|
|
25051
25294
|
var AUTH_PREFERENCE, nonBlank, support3, GeminiAgentDriver;
|
|
25052
25295
|
var init_gemini = __esm({
|
|
@@ -25089,16 +25332,16 @@ ${turn.text}` : turn.text
|
|
|
25089
25332
|
|
|
25090
25333
|
// server/drivers/acp/kimi.ts
|
|
25091
25334
|
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
|
|
25092
|
-
import { homedir as
|
|
25093
|
-
import { join as
|
|
25335
|
+
import { homedir as homedir16 } from "node:os";
|
|
25336
|
+
import { join as join23 } from "node:path";
|
|
25094
25337
|
function isLocalInjectAlias(slug) {
|
|
25095
25338
|
return LOCAL_PROVIDER_PREFIXES.some((prefix) => slug.startsWith(prefix));
|
|
25096
25339
|
}
|
|
25097
25340
|
function kimiDataRoot(env) {
|
|
25098
|
-
return env.KIMI_CODE_HOME ||
|
|
25341
|
+
return env.KIMI_CODE_HOME || join23(env.HOME || env.USERPROFILE || homedir16(), ".kimi-code");
|
|
25099
25342
|
}
|
|
25100
25343
|
function credentialsPath(env) {
|
|
25101
|
-
return
|
|
25344
|
+
return join23(kimiDataRoot(env), "credentials", "kimi-code.json");
|
|
25102
25345
|
}
|
|
25103
25346
|
function quoteToml2(value) {
|
|
25104
25347
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
@@ -25386,7 +25629,7 @@ function ensureKimiInjectAlias(modelId, env = process.env) {
|
|
|
25386
25629
|
const alias = `${inject.host}/${inject.model.replace(/\//g, "-")}`;
|
|
25387
25630
|
const dataRoot = kimiDataRoot(env);
|
|
25388
25631
|
mkdirSync7(dataRoot, { recursive: true });
|
|
25389
|
-
const path3 =
|
|
25632
|
+
const path3 = join23(dataRoot, "config.toml");
|
|
25390
25633
|
let text2 = "";
|
|
25391
25634
|
try {
|
|
25392
25635
|
text2 = readFileSync11(path3, "utf8");
|
|
@@ -25451,7 +25694,7 @@ function readKimiModelCatalog(env) {
|
|
|
25451
25694
|
const dataRoot = kimiDataRoot(env);
|
|
25452
25695
|
let text2 = "";
|
|
25453
25696
|
try {
|
|
25454
|
-
text2 = readFileSync11(
|
|
25697
|
+
text2 = readFileSync11(join23(dataRoot, "config.toml"), "utf8");
|
|
25455
25698
|
} catch {
|
|
25456
25699
|
return STATIC_KIMI_MODELS;
|
|
25457
25700
|
}
|
|
@@ -25571,18 +25814,18 @@ ${turn.text}` : turn.text
|
|
|
25571
25814
|
|
|
25572
25815
|
// server/drivers/acp/droid.ts
|
|
25573
25816
|
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
25574
|
-
import { homedir as
|
|
25575
|
-
import { join as
|
|
25817
|
+
import { homedir as homedir17 } from "node:os";
|
|
25818
|
+
import { join as join24 } from "node:path";
|
|
25576
25819
|
function authFilePaths(env) {
|
|
25577
|
-
const home = env.FACTORY_HOME_OVERRIDE || env.HOME ||
|
|
25578
|
-
return AUTH_FILES.map((name) =>
|
|
25820
|
+
const home = env.FACTORY_HOME_OVERRIDE || env.HOME || homedir17();
|
|
25821
|
+
return AUTH_FILES.map((name) => join24(home, ".factory", name));
|
|
25579
25822
|
}
|
|
25580
25823
|
function droidInjectId(host, model) {
|
|
25581
25824
|
const safe = `${host}-${model}`.replace(/[^a-zA-Z0-9._+-]+/g, "-").replace(/-+/g, "-");
|
|
25582
25825
|
return `${INJECT_ID_PREFIX}${safe}`;
|
|
25583
25826
|
}
|
|
25584
25827
|
function factoryHome(env) {
|
|
25585
|
-
return env.FACTORY_HOME_OVERRIDE || env.HOME || env.USERPROFILE ||
|
|
25828
|
+
return env.FACTORY_HOME_OVERRIDE || env.HOME || env.USERPROFILE || homedir17();
|
|
25586
25829
|
}
|
|
25587
25830
|
function ensureDroidInjectModel(modelId, env = process.env) {
|
|
25588
25831
|
const inject = decodeInjectId(modelId);
|
|
@@ -25590,9 +25833,9 @@ function ensureDroidInjectModel(modelId, env = process.env) {
|
|
|
25590
25833
|
const host = localHost(inject.host);
|
|
25591
25834
|
if (!host) return modelId;
|
|
25592
25835
|
const id = droidInjectId(inject.host, inject.model);
|
|
25593
|
-
const dir =
|
|
25836
|
+
const dir = join24(factoryHome(env), ".factory");
|
|
25594
25837
|
mkdirSync8(dir, { recursive: true });
|
|
25595
|
-
const path3 =
|
|
25838
|
+
const path3 = join24(dir, "settings.json");
|
|
25596
25839
|
let settings2 = {};
|
|
25597
25840
|
try {
|
|
25598
25841
|
settings2 = JSON.parse(readFileSync12(path3, "utf8"));
|
|
@@ -25632,7 +25875,7 @@ function applyDroidLocalAuthEnv(env, modelId) {
|
|
|
25632
25875
|
env.FACTORY_API_KEY = "openmausbot-local";
|
|
25633
25876
|
}
|
|
25634
25877
|
function readSettings(env) {
|
|
25635
|
-
return JSON.parse(readFileSync12(
|
|
25878
|
+
return JSON.parse(readFileSync12(join24(factoryHome(env), ".factory", "settings.json"), "utf8"));
|
|
25636
25879
|
}
|
|
25637
25880
|
async function resolveModels(env) {
|
|
25638
25881
|
let catalog = MODELS3;
|
|
@@ -25901,10 +26144,10 @@ function decodeCursorAuthText(text2) {
|
|
|
25901
26144
|
return null;
|
|
25902
26145
|
}
|
|
25903
26146
|
function execText(run3, cli, args, env) {
|
|
25904
|
-
return new Promise((
|
|
26147
|
+
return new Promise((resolve13) => {
|
|
25905
26148
|
run3(cli, args, { timeout: EXEC_TIMEOUT_MS, env }, (err, stdout2) => {
|
|
25906
|
-
if (err) return
|
|
25907
|
-
|
|
26149
|
+
if (err) return resolve13(null);
|
|
26150
|
+
resolve13(String(stdout2 ?? ""));
|
|
25908
26151
|
});
|
|
25909
26152
|
});
|
|
25910
26153
|
}
|
|
@@ -26023,8 +26266,8 @@ ${turn.text}` : turn.text
|
|
|
26023
26266
|
|
|
26024
26267
|
// server/drivers/acp/opencode-go.ts
|
|
26025
26268
|
import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
|
|
26026
|
-
import { homedir as
|
|
26027
|
-
import { join as
|
|
26269
|
+
import { homedir as homedir18 } from "node:os";
|
|
26270
|
+
import { join as join25 } from "node:path";
|
|
26028
26271
|
function labelForModel(id) {
|
|
26029
26272
|
return id.split(/[-_.]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
26030
26273
|
}
|
|
@@ -26098,7 +26341,7 @@ function parseOpenCodeModelsOutput(stdout2) {
|
|
|
26098
26341
|
return { default: (preferred ?? options[0]).id, options };
|
|
26099
26342
|
}
|
|
26100
26343
|
function runOpenCodeModels(cli, environment, verbose) {
|
|
26101
|
-
return new Promise((
|
|
26344
|
+
return new Promise((resolve13, reject) => {
|
|
26102
26345
|
execCli(
|
|
26103
26346
|
cli,
|
|
26104
26347
|
["models", ...verbose ? ["--verbose"] : []],
|
|
@@ -26108,7 +26351,7 @@ function runOpenCodeModels(cli, environment, verbose) {
|
|
|
26108
26351
|
reject(new Error(stderr?.trim() || error51.message, { cause: error51 }));
|
|
26109
26352
|
return;
|
|
26110
26353
|
}
|
|
26111
|
-
|
|
26354
|
+
resolve13(stdout2);
|
|
26112
26355
|
}
|
|
26113
26356
|
);
|
|
26114
26357
|
});
|
|
@@ -26124,8 +26367,8 @@ async function discoverOpenCodeModels(environment, cli = "opencode") {
|
|
|
26124
26367
|
}
|
|
26125
26368
|
}
|
|
26126
26369
|
function opencodeConfigDir(env) {
|
|
26127
|
-
const home = env.HOME || env.USERPROFILE ||
|
|
26128
|
-
return
|
|
26370
|
+
const home = env.HOME || env.USERPROFILE || homedir18();
|
|
26371
|
+
return join25(env.XDG_CONFIG_HOME || join25(home, ".config"), "opencode");
|
|
26129
26372
|
}
|
|
26130
26373
|
function ensureOpenCodeInjectModel(modelId, env = process.env) {
|
|
26131
26374
|
const inject = decodeInjectId(modelId);
|
|
@@ -26135,7 +26378,7 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
|
|
|
26135
26378
|
const native = `${inject.host}/${inject.model}`;
|
|
26136
26379
|
const dir = opencodeConfigDir(env);
|
|
26137
26380
|
mkdirSync9(dir, { recursive: true });
|
|
26138
|
-
const path3 =
|
|
26381
|
+
const path3 = join25(dir, "opencode.json");
|
|
26139
26382
|
let config2 = { $schema: "https://opencode.ai/config.json" };
|
|
26140
26383
|
if (existsSync12(path3)) {
|
|
26141
26384
|
try {
|
|
@@ -26171,12 +26414,12 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
|
|
|
26171
26414
|
return native;
|
|
26172
26415
|
}
|
|
26173
26416
|
function storedAuthPaths(env) {
|
|
26174
|
-
const home = env.HOME || env.USERPROFILE ||
|
|
26417
|
+
const home = env.HOME || env.USERPROFILE || homedir18();
|
|
26175
26418
|
const roots = [
|
|
26176
|
-
env.XDG_DATA_HOME ||
|
|
26177
|
-
process.platform === "darwin" ?
|
|
26419
|
+
env.XDG_DATA_HOME || join25(home, ".local", "share"),
|
|
26420
|
+
process.platform === "darwin" ? join25(home, "Library", "Application Support") : process.platform === "win32" ? env.LOCALAPPDATA || join25(home, "AppData", "Local") : ""
|
|
26178
26421
|
].filter(Boolean);
|
|
26179
|
-
return [...new Set(roots)].map((root) =>
|
|
26422
|
+
return [...new Set(roots)].map((root) => join25(root, "opencode", "auth.json"));
|
|
26180
26423
|
}
|
|
26181
26424
|
function usableAuthEntry(parsed) {
|
|
26182
26425
|
return Object.values(parsed).some((auth) => {
|
|
@@ -26307,10 +26550,96 @@ ${turn.text}` : turn.text
|
|
|
26307
26550
|
|
|
26308
26551
|
// server/drivers/acp/qwen.ts
|
|
26309
26552
|
import { chmodSync as chmodSync4, existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
|
|
26310
|
-
import {
|
|
26311
|
-
import {
|
|
26553
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
26554
|
+
import { homedir as homedir19 } from "node:os";
|
|
26555
|
+
import { join as join26 } from "node:path";
|
|
26312
26556
|
function qwenHome(env) {
|
|
26313
|
-
|
|
26557
|
+
const home = process.platform === "win32" ? env.USERPROFILE || env.HOME || homedir19() : env.HOME || env.USERPROFILE || homedir19();
|
|
26558
|
+
return join26(home, ".qwen");
|
|
26559
|
+
}
|
|
26560
|
+
function isRecord(value) {
|
|
26561
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
26562
|
+
}
|
|
26563
|
+
function qwenModelLabel(id, name) {
|
|
26564
|
+
if (!name || name.toLocaleLowerCase().endsWith(id.toLocaleLowerCase())) return id;
|
|
26565
|
+
return `${id} \u2014 ${name}`;
|
|
26566
|
+
}
|
|
26567
|
+
function readQwenRoutes(env) {
|
|
26568
|
+
let settings2;
|
|
26569
|
+
try {
|
|
26570
|
+
settings2 = JSON.parse(readFileSync14(join26(qwenHome(env), "settings.json"), "utf8"));
|
|
26571
|
+
} catch {
|
|
26572
|
+
return [];
|
|
26573
|
+
}
|
|
26574
|
+
if (!isRecord(settings2) || !isRecord(settings2.modelProviders)) return [];
|
|
26575
|
+
const routes = [];
|
|
26576
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26577
|
+
const mappings = isRecord(settings2.providerProtocol) ? settings2.providerProtocol : {};
|
|
26578
|
+
for (const [provider, rows] of Object.entries(settings2.modelProviders)) {
|
|
26579
|
+
const protocol = Object.hasOwn(mappings, provider) ? mappings[provider] : provider;
|
|
26580
|
+
if (typeof protocol !== "string" || !PROTOCOLS.has(protocol) || !Array.isArray(rows)) continue;
|
|
26581
|
+
for (const row of rows) {
|
|
26582
|
+
if (!isRecord(row) || typeof row.id !== "string") continue;
|
|
26583
|
+
const model = row.id;
|
|
26584
|
+
if (!model.trim()) continue;
|
|
26585
|
+
if (row.baseUrl !== void 0 && typeof row.baseUrl !== "string") continue;
|
|
26586
|
+
const baseUrl = typeof row.baseUrl === "string" && row.baseUrl ? row.baseUrl : void 0;
|
|
26587
|
+
if (baseUrl) {
|
|
26588
|
+
try {
|
|
26589
|
+
new URL(baseUrl);
|
|
26590
|
+
} catch {
|
|
26591
|
+
throw new Error("A Qwen model has an invalid endpoint. Fix its baseUrl in Qwen settings and refresh models.");
|
|
26592
|
+
}
|
|
26593
|
+
}
|
|
26594
|
+
const identity = JSON.stringify([protocol, model, baseUrl ?? null]);
|
|
26595
|
+
if (seen.has(identity)) continue;
|
|
26596
|
+
seen.add(identity);
|
|
26597
|
+
if (row.imageOnly === true || row.voiceOnly === true || row.fastOnly === true) continue;
|
|
26598
|
+
routes.push({
|
|
26599
|
+
id: `${model}(${protocol})`,
|
|
26600
|
+
model,
|
|
26601
|
+
provider,
|
|
26602
|
+
protocol,
|
|
26603
|
+
baseUrl,
|
|
26604
|
+
label: typeof row.name === "string" && row.name ? row.name : model,
|
|
26605
|
+
envKey: typeof row.envKey === "string" ? row.envKey : void 0
|
|
26606
|
+
});
|
|
26607
|
+
}
|
|
26608
|
+
}
|
|
26609
|
+
const counts = /* @__PURE__ */ new Map();
|
|
26610
|
+
for (const route of routes) counts.set(route.id, (counts.get(route.id) ?? 0) + 1);
|
|
26611
|
+
for (const route of routes) {
|
|
26612
|
+
if (counts.get(route.id) === 1) continue;
|
|
26613
|
+
const endpoint = route.baseUrl ?? (route.protocol === "openai" ? "https://api.openai.com/v1" : "");
|
|
26614
|
+
let publicEndpoint = null;
|
|
26615
|
+
if (endpoint) {
|
|
26616
|
+
try {
|
|
26617
|
+
const url2 = new URL(endpoint);
|
|
26618
|
+
url2.username = "";
|
|
26619
|
+
url2.password = "";
|
|
26620
|
+
url2.search = "";
|
|
26621
|
+
url2.hash = "";
|
|
26622
|
+
publicEndpoint = url2.href;
|
|
26623
|
+
} catch {
|
|
26624
|
+
throw new Error("A Qwen model has an invalid endpoint. Fix its baseUrl in Qwen settings and refresh models.");
|
|
26625
|
+
}
|
|
26626
|
+
}
|
|
26627
|
+
const identity = [route.id, route.label, route.envKey ?? null, route.baseUrl === void 0, publicEndpoint];
|
|
26628
|
+
route.id = `qwen-route:v1:${createHash7("sha256").update(JSON.stringify(identity)).digest("base64url").slice(0, 16)}`;
|
|
26629
|
+
}
|
|
26630
|
+
if (new Set(routes.map((route) => route.id)).size !== routes.length) {
|
|
26631
|
+
throw new Error("Qwen has indistinguishable model routes. Give them distinct names, envKey values, or public endpoints in Qwen settings.");
|
|
26632
|
+
}
|
|
26633
|
+
return routes;
|
|
26634
|
+
}
|
|
26635
|
+
function readQwenModelCatalog(env = process.env) {
|
|
26636
|
+
const options = readQwenRoutes(env).map(({ id, model, label, provider }) => ({
|
|
26637
|
+
id,
|
|
26638
|
+
label: qwenModelLabel(model, label),
|
|
26639
|
+
custom: true,
|
|
26640
|
+
provider
|
|
26641
|
+
}));
|
|
26642
|
+
return { default: options[0]?.id ?? "", options };
|
|
26314
26643
|
}
|
|
26315
26644
|
function envKeyFor(hostId) {
|
|
26316
26645
|
return `OPENMAUSBOT_QWEN_${hostId.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`;
|
|
@@ -26322,7 +26651,7 @@ function ensureQwenInjectModel(modelId, env = process.env) {
|
|
|
26322
26651
|
if (!host) return modelId;
|
|
26323
26652
|
const dir = qwenHome(env);
|
|
26324
26653
|
mkdirSync10(dir, { recursive: true });
|
|
26325
|
-
const path3 =
|
|
26654
|
+
const path3 = join26(dir, "settings.json");
|
|
26326
26655
|
let settings2 = {};
|
|
26327
26656
|
if (existsSync13(path3)) {
|
|
26328
26657
|
try {
|
|
@@ -26359,23 +26688,54 @@ function ensureQwenInjectModel(modelId, env = process.env) {
|
|
|
26359
26688
|
return inject.model;
|
|
26360
26689
|
}
|
|
26361
26690
|
async function resolveModels2(env) {
|
|
26362
|
-
const catalog = await mergeLocalInject(
|
|
26363
|
-
|
|
26364
|
-
|
|
26365
|
-
|
|
26691
|
+
const catalog = await mergeLocalInject(readQwenModelCatalog(env), env);
|
|
26692
|
+
const routes = readQwenRoutes(env);
|
|
26693
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
26694
|
+
for (const option of catalog.options) {
|
|
26695
|
+
const injected = decodeInjectId(option.id);
|
|
26696
|
+
if (!injected) continue;
|
|
26697
|
+
const endpoint = localHost(injected.host)?.baseUrl;
|
|
26698
|
+
for (const route of routes) {
|
|
26699
|
+
if (route.protocol === "openai" && route.model === injected.model && route.baseUrl === endpoint) {
|
|
26700
|
+
replacements.set(route.id, option.id);
|
|
26701
|
+
}
|
|
26702
|
+
}
|
|
26703
|
+
}
|
|
26704
|
+
const options = catalog.options.filter((option) => !replacements.has(option.id));
|
|
26705
|
+
const preferred = replacements.get(catalog.default) ?? catalog.default;
|
|
26706
|
+
return { default: options.some((option) => option.id === preferred) ? preferred : options[0]?.id ?? "", options };
|
|
26707
|
+
}
|
|
26708
|
+
function resolveQwenTurnModel(model, env) {
|
|
26709
|
+
if (!model) return model;
|
|
26710
|
+
const injected = decodeInjectId(model);
|
|
26711
|
+
if (injected) ensureQwenInjectModel(model, env);
|
|
26712
|
+
const routes = readQwenRoutes(env);
|
|
26713
|
+
if (injected) {
|
|
26714
|
+
const route = routes.find((row) => row.protocol === "openai" && row.model === injected.model && row.baseUrl === localHost(injected.host)?.baseUrl);
|
|
26715
|
+
if (!route) throw new Error("Qwen could not configure this local model. Refresh models and select it again.");
|
|
26716
|
+
return route.id;
|
|
26717
|
+
}
|
|
26718
|
+
if (routes.some((route) => route.id === model)) return model;
|
|
26719
|
+
const matches = routes.filter((route) => route.model === model);
|
|
26720
|
+
if (matches.length > 1) throw new Error("This Qwen model has multiple providers. Refresh models and select the intended provider again.");
|
|
26721
|
+
if (!matches.length) throw new Error("This Qwen model is no longer configured. Refresh models and select it again.");
|
|
26722
|
+
return matches[0].id;
|
|
26723
|
+
}
|
|
26724
|
+
var EMPTY, PROTOCOLS, support8, QwenAgentDriver;
|
|
26366
26725
|
var init_qwen = __esm({
|
|
26367
26726
|
"server/drivers/acp/qwen.ts"() {
|
|
26368
26727
|
"use strict";
|
|
26369
26728
|
init_local_inject();
|
|
26370
26729
|
init_core3();
|
|
26371
26730
|
EMPTY = { default: "", options: [] };
|
|
26731
|
+
PROTOCOLS = /* @__PURE__ */ new Set(["openai", "anthropic", "gemini", "vertex-ai"]);
|
|
26372
26732
|
support8 = {
|
|
26373
26733
|
driverKind: "qwenAgent",
|
|
26374
26734
|
displayName: "Qwen",
|
|
26375
26735
|
access: "custom",
|
|
26376
26736
|
models: EMPTY,
|
|
26377
26737
|
resolveModels: resolveModels2,
|
|
26378
|
-
resolveTurnModel:
|
|
26738
|
+
resolveTurnModel: resolveQwenTurnModel,
|
|
26379
26739
|
defaultCli: "qwen",
|
|
26380
26740
|
nativeSource: "qwen.acp",
|
|
26381
26741
|
loginNote: "Qwen Code CLI is not installed",
|
|
@@ -26387,7 +26747,10 @@ var init_qwen = __esm({
|
|
|
26387
26747
|
},
|
|
26388
26748
|
docsUrl: "https://qwenlm.github.io/qwen-code-docs/en/users/overview/"
|
|
26389
26749
|
},
|
|
26390
|
-
|
|
26750
|
+
// A raw -m only changes the model within the saved provider. ACP switches
|
|
26751
|
+
// the complete route and confirms it before any prompt leaves OMB.
|
|
26752
|
+
spawnArgs: () => ["--acp"],
|
|
26753
|
+
selectModel: { configId: "model" },
|
|
26391
26754
|
pickAuthMethod: () => null,
|
|
26392
26755
|
authFailure: "continue",
|
|
26393
26756
|
isAuthenticated: () => true,
|
|
@@ -33288,8 +33651,8 @@ var init_browser = __esm({
|
|
|
33288
33651
|
// server/drivers/acp/hermes.ts
|
|
33289
33652
|
import { spawn as spawn5 } from "node:child_process";
|
|
33290
33653
|
import { mkdirSync as mkdirSync11, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "node:fs";
|
|
33291
|
-
import { homedir as
|
|
33292
|
-
import { join as
|
|
33654
|
+
import { homedir as homedir20 } from "node:os";
|
|
33655
|
+
import { join as join27 } from "node:path";
|
|
33293
33656
|
function bindHermesScreenshotCompat(env, modelId) {
|
|
33294
33657
|
delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT];
|
|
33295
33658
|
delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL];
|
|
@@ -33299,7 +33662,7 @@ function bindHermesScreenshotCompat(env, modelId) {
|
|
|
33299
33662
|
env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL] = inject.model;
|
|
33300
33663
|
}
|
|
33301
33664
|
function hermesHome(env) {
|
|
33302
|
-
return env.HERMES_HOME ||
|
|
33665
|
+
return env.HERMES_HOME || join27(env.HOME || env.USERPROFILE || homedir20(), ".hermes");
|
|
33303
33666
|
}
|
|
33304
33667
|
function quoteYaml(value) {
|
|
33305
33668
|
if (/^[\w./:+-]+$/.test(value)) return value;
|
|
@@ -33341,7 +33704,7 @@ function ensureHermesInjectProvider(modelId, env = process.env) {
|
|
|
33341
33704
|
if (!host) return modelId;
|
|
33342
33705
|
const dir = hermesHome(env);
|
|
33343
33706
|
mkdirSync11(dir, { recursive: true });
|
|
33344
|
-
const path3 =
|
|
33707
|
+
const path3 = join27(dir, "config.yaml");
|
|
33345
33708
|
let text2 = "";
|
|
33346
33709
|
try {
|
|
33347
33710
|
text2 = readFileSync15(path3, "utf8");
|
|
@@ -33412,13 +33775,13 @@ function hermesConfiguredModel(env = process.env) {
|
|
|
33412
33775
|
const dir = hermesHome(env);
|
|
33413
33776
|
let secrets = "";
|
|
33414
33777
|
try {
|
|
33415
|
-
secrets = readFileSync15(
|
|
33778
|
+
secrets = readFileSync15(join27(dir, ".env"), "utf8");
|
|
33416
33779
|
} catch {
|
|
33417
33780
|
}
|
|
33418
33781
|
const hasHostedProviderKey = HERMES_HOSTED_PROVIDER_KEYS.some((name) => nonEmptyDotenvValue(secrets, name));
|
|
33419
33782
|
let configuredDefault = null;
|
|
33420
33783
|
try {
|
|
33421
|
-
configuredDefault = hermesConfigDefault(readFileSync15(
|
|
33784
|
+
configuredDefault = hermesConfigDefault(readFileSync15(join27(dir, "config.yaml"), "utf8"));
|
|
33422
33785
|
} catch {
|
|
33423
33786
|
}
|
|
33424
33787
|
const configuredProvider = configuredDefault?.provider.toLowerCase() ?? "";
|
|
@@ -33434,12 +33797,12 @@ function hermesConfiguredModel(env = process.env) {
|
|
|
33434
33797
|
};
|
|
33435
33798
|
}
|
|
33436
33799
|
async function fetchHermesAcpModels(cli, env) {
|
|
33437
|
-
return await new Promise((
|
|
33800
|
+
return await new Promise((resolve13) => {
|
|
33438
33801
|
let child;
|
|
33439
33802
|
try {
|
|
33440
33803
|
child = spawn5(cli, ["acp"], { stdio: ["pipe", "pipe", "ignore"], env });
|
|
33441
33804
|
} catch {
|
|
33442
|
-
return
|
|
33805
|
+
return resolve13([]);
|
|
33443
33806
|
}
|
|
33444
33807
|
let settled = false;
|
|
33445
33808
|
let timer;
|
|
@@ -33460,7 +33823,7 @@ async function fetchHermesAcpModels(cli, env) {
|
|
|
33460
33823
|
}
|
|
33461
33824
|
} catch {
|
|
33462
33825
|
}
|
|
33463
|
-
|
|
33826
|
+
resolve13(out);
|
|
33464
33827
|
};
|
|
33465
33828
|
timer = setTimeout(() => done([]), 5e3);
|
|
33466
33829
|
child.once("error", () => done([]));
|
|
@@ -33503,7 +33866,7 @@ async function fetchHermesAcpModels(cli, env) {
|
|
|
33503
33866
|
}
|
|
33504
33867
|
if (msg?.id === initId) {
|
|
33505
33868
|
if (!msg.result) return done([]);
|
|
33506
|
-
sessionId = send("session/new", { cwd: env.HOME || env.USERPROFILE ||
|
|
33869
|
+
sessionId = send("session/new", { cwd: env.HOME || env.USERPROFILE || homedir20(), mcpServers: [] });
|
|
33507
33870
|
} else if (sessionId && msg?.id === sessionId) {
|
|
33508
33871
|
const list = Array.isArray(msg.result?.models?.availableModels) ? msg.result.models.availableModels : [];
|
|
33509
33872
|
done(
|
|
@@ -33739,8 +34102,8 @@ var init_openai_compat = __esm({
|
|
|
33739
34102
|
|
|
33740
34103
|
// server/drivers/pi.ts
|
|
33741
34104
|
import { chmodSync as chmodSync5, existsSync as existsSync14, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync12 } from "node:fs";
|
|
33742
|
-
import { homedir as
|
|
33743
|
-
import { join as
|
|
34105
|
+
import { homedir as homedir21, tmpdir as tmpdir4 } from "node:os";
|
|
34106
|
+
import { join as join28 } from "node:path";
|
|
33744
34107
|
function readPiPromptImages(turn) {
|
|
33745
34108
|
return (turn.images ?? []).map((image) => ({
|
|
33746
34109
|
type: "image",
|
|
@@ -33847,7 +34210,7 @@ async function applyPiLocalCatalog(catalog, env = process.env, fetchImpl = fetch
|
|
|
33847
34210
|
return preferPiInjectRows(await mergeLocalInject(catalog, env, fetchImpl));
|
|
33848
34211
|
}
|
|
33849
34212
|
function piAgentDir(env) {
|
|
33850
|
-
return
|
|
34213
|
+
return join28(env.HOME || env.USERPROFILE || homedir21(), ".pi", "agent");
|
|
33851
34214
|
}
|
|
33852
34215
|
function ensurePiInjectModel(modelId, env = process.env) {
|
|
33853
34216
|
const split = splitPiModel(modelId);
|
|
@@ -33858,7 +34221,7 @@ function ensurePiInjectModel(modelId, env = process.env) {
|
|
|
33858
34221
|
if (!host) return split;
|
|
33859
34222
|
const dir = piAgentDir(env);
|
|
33860
34223
|
mkdirSync12(dir, { recursive: true });
|
|
33861
|
-
const path3 =
|
|
34224
|
+
const path3 = join28(dir, "models.json");
|
|
33862
34225
|
let root = { providers: {} };
|
|
33863
34226
|
if (existsSync14(path3)) {
|
|
33864
34227
|
try {
|
|
@@ -33912,7 +34275,7 @@ function ensurePiInjectModel(modelId, env = process.env) {
|
|
|
33912
34275
|
return split;
|
|
33913
34276
|
}
|
|
33914
34277
|
function readPiDefaultModel(env) {
|
|
33915
|
-
const home = env.HOME || env.USERPROFILE ||
|
|
34278
|
+
const home = env.HOME || env.USERPROFILE || homedir21();
|
|
33916
34279
|
try {
|
|
33917
34280
|
const s = JSON.parse(readFileSync16(`${home}/.pi/agent/settings.json`, "utf8"));
|
|
33918
34281
|
return s.defaultProvider && s.defaultModel ? `${s.defaultProvider}/${s.defaultModel}` : "";
|
|
@@ -33922,7 +34285,7 @@ function readPiDefaultModel(env) {
|
|
|
33922
34285
|
}
|
|
33923
34286
|
async function fetchPiModels(cli, env) {
|
|
33924
34287
|
const child = spawnCli(cli, PI_ARGS, { stdio: ["pipe", "pipe", "pipe"], env });
|
|
33925
|
-
return new Promise((
|
|
34288
|
+
return new Promise((resolve13) => {
|
|
33926
34289
|
let buf = "";
|
|
33927
34290
|
let done = false;
|
|
33928
34291
|
const fallbackDefault = readPiDefaultModel(env);
|
|
@@ -33933,7 +34296,7 @@ async function fetchPiModels(cli, env) {
|
|
|
33933
34296
|
killCliTree(child);
|
|
33934
34297
|
} catch {
|
|
33935
34298
|
}
|
|
33936
|
-
|
|
34299
|
+
resolve13(catalog);
|
|
33937
34300
|
};
|
|
33938
34301
|
const timer = setTimeout(() => finish({ default: "", options: [] }), 15e3);
|
|
33939
34302
|
timer.unref?.();
|
|
@@ -34060,9 +34423,9 @@ var init_pi = __esm({
|
|
|
34060
34423
|
const mcpServers = buildMcpServers(turn);
|
|
34061
34424
|
let mcpTempDir = null;
|
|
34062
34425
|
if (mcpServers) {
|
|
34063
|
-
mcpTempDir = mkdtempSync3(
|
|
34426
|
+
mcpTempDir = mkdtempSync3(join28(tmpdir4(), "omb-pi-mcp-"));
|
|
34064
34427
|
try {
|
|
34065
|
-
writeFileSync12(
|
|
34428
|
+
writeFileSync12(join28(mcpTempDir, "mcp.json"), JSON.stringify({ mcpServers }), { mode: 384 });
|
|
34066
34429
|
} catch (err) {
|
|
34067
34430
|
try {
|
|
34068
34431
|
rmSync3(mcpTempDir, { recursive: true, force: true });
|
|
@@ -34080,7 +34443,7 @@ var init_pi = __esm({
|
|
|
34080
34443
|
env: piEnvironment({
|
|
34081
34444
|
...process.env,
|
|
34082
34445
|
...input.environment,
|
|
34083
|
-
...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG:
|
|
34446
|
+
...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG: join28(mcpTempDir, "mcp.json") } : {}
|
|
34084
34447
|
})
|
|
34085
34448
|
});
|
|
34086
34449
|
} catch (err) {
|
|
@@ -34103,13 +34466,13 @@ var init_pi = __esm({
|
|
|
34103
34466
|
}
|
|
34104
34467
|
responseWaiters.clear();
|
|
34105
34468
|
};
|
|
34106
|
-
const awaitResponse = (command, timeoutMs = 2e4) => new Promise((
|
|
34469
|
+
const awaitResponse = (command, timeoutMs = 2e4) => new Promise((resolve13, reject) => {
|
|
34107
34470
|
const timer = setTimeout(() => {
|
|
34108
34471
|
responseWaiters.delete(command);
|
|
34109
34472
|
reject(new Error(`pi ${command} timed out`));
|
|
34110
34473
|
}, timeoutMs);
|
|
34111
34474
|
timer.unref?.();
|
|
34112
|
-
responseWaiters.set(command, { resolve:
|
|
34475
|
+
responseWaiters.set(command, { resolve: resolve13, reject, timer });
|
|
34113
34476
|
});
|
|
34114
34477
|
child.stdin.on("error", () => rejectWaiters(new Error("pi stdin closed")));
|
|
34115
34478
|
const send = (obj) => {
|
|
@@ -34317,7 +34680,7 @@ ${turn.text}` : turn.text;
|
|
|
34317
34680
|
return { turnId };
|
|
34318
34681
|
};
|
|
34319
34682
|
const snapshot = async () => {
|
|
34320
|
-
const version2 = await new Promise((
|
|
34683
|
+
const version2 = await new Promise((resolve13) => {
|
|
34321
34684
|
const child = spawnCli(config2.cli, ["--version"], {
|
|
34322
34685
|
stdio: ["ignore", "pipe", "pipe"],
|
|
34323
34686
|
env: piEnvironment({ ...process.env, ...input.environment })
|
|
@@ -34330,16 +34693,16 @@ ${turn.text}` : turn.text;
|
|
|
34330
34693
|
killCliTree(child);
|
|
34331
34694
|
} catch {
|
|
34332
34695
|
}
|
|
34333
|
-
|
|
34696
|
+
resolve13(null);
|
|
34334
34697
|
}, 8e3);
|
|
34335
34698
|
timer.unref?.();
|
|
34336
34699
|
child.on("error", () => {
|
|
34337
34700
|
clearTimeout(timer);
|
|
34338
|
-
|
|
34701
|
+
resolve13(null);
|
|
34339
34702
|
});
|
|
34340
34703
|
child.on("close", () => {
|
|
34341
34704
|
clearTimeout(timer);
|
|
34342
|
-
|
|
34705
|
+
resolve13(out.trim() || null);
|
|
34343
34706
|
});
|
|
34344
34707
|
});
|
|
34345
34708
|
if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
|
|
@@ -34418,15 +34781,15 @@ ${turn.text}` : turn.text;
|
|
|
34418
34781
|
|
|
34419
34782
|
// server/drivers/minimax.ts
|
|
34420
34783
|
import { readFileSync as readFileSync17 } from "node:fs";
|
|
34421
|
-
import { homedir as
|
|
34422
|
-
import { join as
|
|
34784
|
+
import { homedir as homedir22 } from "node:os";
|
|
34785
|
+
import { join as join29 } from "node:path";
|
|
34423
34786
|
function normalizedApiUrl(value) {
|
|
34424
34787
|
const root = value.trim().replace(/\/+$/, "");
|
|
34425
34788
|
return root.endsWith("/v1") ? root : `${root}/v1`;
|
|
34426
34789
|
}
|
|
34427
|
-
function loadLocalMiniMaxConfig(home =
|
|
34790
|
+
function loadLocalMiniMaxConfig(home = homedir22()) {
|
|
34428
34791
|
try {
|
|
34429
|
-
const raw = localConfigSchema.parse(JSON.parse(readFileSync17(
|
|
34792
|
+
const raw = localConfigSchema.parse(JSON.parse(readFileSync17(join29(home, ".mmx", "config.json"), "utf8")));
|
|
34430
34793
|
const configuredUrl = raw.base_url?.trim() ? raw.base_url : raw.region === "cn" ? CN_URL : DEFAULT_URL2;
|
|
34431
34794
|
return {
|
|
34432
34795
|
apiKey: raw.api_key?.trim() ?? "",
|
|
@@ -34694,7 +35057,7 @@ __export(cli_setup_exports, {
|
|
|
34694
35057
|
});
|
|
34695
35058
|
import { spawn as spawn6 } from "node:child_process";
|
|
34696
35059
|
import { readFileSync as readFileSync18 } from "node:fs";
|
|
34697
|
-
import { join as
|
|
35060
|
+
import { join as join30, resolve as resolve10 } from "node:path";
|
|
34698
35061
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
34699
35062
|
async function inspect(id, entry) {
|
|
34700
35063
|
const registry2 = new ProviderRegistry(BUILT_IN_DRIVERS);
|
|
@@ -34727,11 +35090,11 @@ async function runSetupCli(cli, args, environment = {}) {
|
|
|
34727
35090
|
resetPathCache();
|
|
34728
35091
|
}
|
|
34729
35092
|
function assertDataDir(dataDir) {
|
|
34730
|
-
if (
|
|
35093
|
+
if (resolve10(dataDir) !== resolve10(DATA_DIR)) throw new Error("Setup data directory mismatch. Restart the CLI with --data-dir.");
|
|
34731
35094
|
}
|
|
34732
35095
|
function checkStoredConfig(dataDir) {
|
|
34733
35096
|
try {
|
|
34734
|
-
parseStoredConfig(JSON.parse(readFileSync18(
|
|
35097
|
+
parseStoredConfig(JSON.parse(readFileSync18(join30(dataDir, "config.json"), "utf8")));
|
|
34735
35098
|
} catch (error51) {
|
|
34736
35099
|
if (error51.code === "ENOENT") return;
|
|
34737
35100
|
throw new Error("Existing config.json could not be read or validated. Setup has not changed it; repair it before continuing.");
|
|
@@ -35009,7 +35372,7 @@ var init_browser_engine_release = __esm({
|
|
|
35009
35372
|
});
|
|
35010
35373
|
|
|
35011
35374
|
// server/browser-bundle-release.ts
|
|
35012
|
-
import { join as
|
|
35375
|
+
import { join as join31 } from "node:path";
|
|
35013
35376
|
function browserBundleSpec(target) {
|
|
35014
35377
|
if (!Object.hasOwn(CHROME_ASSETS, target)) throw new Error(`Unsupported desktop browser target: ${target}`);
|
|
35015
35378
|
const pinned = CHROME_ASSETS[target];
|
|
@@ -35045,10 +35408,10 @@ function browserBundlePaths(bundleDirectory, target) {
|
|
|
35045
35408
|
const spec = browserBundleSpec(target);
|
|
35046
35409
|
return {
|
|
35047
35410
|
directory: bundleDirectory,
|
|
35048
|
-
manifest:
|
|
35049
|
-
engine:
|
|
35050
|
-
chrome:
|
|
35051
|
-
licenses:
|
|
35411
|
+
manifest: join31(bundleDirectory, "manifest.json"),
|
|
35412
|
+
engine: join31(bundleDirectory, spec.engine.executable),
|
|
35413
|
+
chrome: join31(bundleDirectory, spec.chrome.executable),
|
|
35414
|
+
licenses: join31(bundleDirectory, "licenses")
|
|
35052
35415
|
};
|
|
35053
35416
|
}
|
|
35054
35417
|
var CHROME_VERSION, CHROME_ASSETS;
|
|
@@ -35102,23 +35465,23 @@ __export(browser_engine_exports, {
|
|
|
35102
35465
|
resolveAgentBrowserBinary: () => resolveAgentBrowserBinary
|
|
35103
35466
|
});
|
|
35104
35467
|
import { spawn as spawn7 } from "node:child_process";
|
|
35105
|
-
import { createHash as
|
|
35468
|
+
import { createHash as createHash8, randomBytes as randomBytes3, randomUUID as randomUUID11 } from "node:crypto";
|
|
35106
35469
|
import { chmodSync as chmodSync6, constants as constants2, copyFileSync, existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as readFileSync19, readdirSync as readdirSync3, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "node:fs";
|
|
35107
|
-
import { homedir as
|
|
35108
|
-
import { delimiter as delimiter6, dirname as dirname10, join as
|
|
35470
|
+
import { homedir as homedir23, tmpdir as tmpdir5 } from "node:os";
|
|
35471
|
+
import { delimiter as delimiter6, dirname as dirname10, join as join32, resolve as resolve11 } from "node:path";
|
|
35109
35472
|
function browserRestoreKey(session) {
|
|
35110
35473
|
if (!/^[A-Za-z0-9_-]{1,96}$/.test(session)) throw new Error("Invalid browser session.");
|
|
35111
|
-
return `omb-${
|
|
35474
|
+
return `omb-${createHash8("sha256").update(session).digest("hex")}`;
|
|
35112
35475
|
}
|
|
35113
35476
|
function browserSessionsDirectory(env) {
|
|
35114
35477
|
const namespace = env.AGENT_BROWSER_NAMESPACE;
|
|
35115
35478
|
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
|
|
35479
|
+
const home = (process.platform === "win32" ? env.USERPROFILE : env.HOME) || homedir23();
|
|
35480
|
+
const stateRoot = namespace ? join32(home, ".agent-browser", "namespaces", namespace, "state") : join32(home, ".agent-browser");
|
|
35481
|
+
return join32(stateRoot, "sessions");
|
|
35119
35482
|
}
|
|
35120
35483
|
function managedBrowserConfigPath(env) {
|
|
35121
|
-
return
|
|
35484
|
+
return join32(browserSessionsDirectory(env), "..", "omb-managed-config.json");
|
|
35122
35485
|
}
|
|
35123
35486
|
function ensureManagedBrowserConfig(env) {
|
|
35124
35487
|
const path3 = managedBrowserConfigPath(env);
|
|
@@ -35191,7 +35554,7 @@ async function closeBrowserSession(binaryPath, env, timeoutMs = 15e3) {
|
|
|
35191
35554
|
} catch {
|
|
35192
35555
|
return false;
|
|
35193
35556
|
}
|
|
35194
|
-
await new Promise((
|
|
35557
|
+
await new Promise((resolve13) => setTimeout(resolve13, Math.min(25, Math.max(1, deadline - Date.now()))));
|
|
35195
35558
|
}
|
|
35196
35559
|
return false;
|
|
35197
35560
|
}
|
|
@@ -35205,11 +35568,11 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
|
|
|
35205
35568
|
ensureManagedBrowserConfig(env);
|
|
35206
35569
|
if (options.persistent === false) return;
|
|
35207
35570
|
const directory = browserSessionsDirectory(env);
|
|
35208
|
-
const key =
|
|
35571
|
+
const key = join32(directory, session);
|
|
35209
35572
|
let pending = preparedBrowserSessions.get(key);
|
|
35210
35573
|
if (!pending) {
|
|
35211
35574
|
pending = (async () => {
|
|
35212
|
-
const targetBase =
|
|
35575
|
+
const targetBase = join32(directory, `${restoreKey}-${session}`);
|
|
35213
35576
|
const hasTarget = () => existsSync15(`${targetBase}.json.enc`) || existsSync15(`${targetBase}.json`);
|
|
35214
35577
|
if (hasTarget()) return;
|
|
35215
35578
|
check2();
|
|
@@ -35219,7 +35582,7 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
|
|
|
35219
35582
|
check2();
|
|
35220
35583
|
if (hasTarget()) return;
|
|
35221
35584
|
const candidates = [".json.enc", ".json"].flatMap((suffix) => {
|
|
35222
|
-
const path3 =
|
|
35585
|
+
const path3 = join32(directory, `${session}-${session}${suffix}`);
|
|
35223
35586
|
try {
|
|
35224
35587
|
const stat4 = statSync3(path3);
|
|
35225
35588
|
if (!stat4.isFile()) throw new Error("Saved browser state is not a file.");
|
|
@@ -35254,14 +35617,14 @@ function isMusl(platform = process.platform, exists = existsSync15) {
|
|
|
35254
35617
|
}
|
|
35255
35618
|
function pinnedBinaryPath(dataDir = DATA_DIR, platform = process.platform, arch = process.arch) {
|
|
35256
35619
|
const version2 = agentBrowserReleaseVersion(resolveAgentBrowserReleaseAsset(platform, arch));
|
|
35257
|
-
return
|
|
35620
|
+
return join32(dataDir, ENGINE_DIR, version2, executableName(platform));
|
|
35258
35621
|
}
|
|
35259
35622
|
function onPath(env, platform, exists) {
|
|
35260
35623
|
const pathValue = platform === "win32" ? Object.entries(env).findLast(([key]) => key.toUpperCase() === "PATH")?.[1] : env.PATH;
|
|
35261
35624
|
for (const part of (pathValue ?? "").split(delimiter6)) {
|
|
35262
35625
|
const dir = part.trim().replace(/^"|"$/gu, "");
|
|
35263
35626
|
if (!dir) continue;
|
|
35264
|
-
const candidate =
|
|
35627
|
+
const candidate = resolve11(dir, executableName(platform));
|
|
35265
35628
|
if (exists(candidate)) return candidate;
|
|
35266
35629
|
}
|
|
35267
35630
|
return null;
|
|
@@ -35270,7 +35633,7 @@ function packagedBrowser(options) {
|
|
|
35270
35633
|
const resources = (options.env ?? process.env).OMB_RESOURCES_PATH;
|
|
35271
35634
|
if (!resources) return null;
|
|
35272
35635
|
try {
|
|
35273
|
-
return browserBundlePaths(
|
|
35636
|
+
return browserBundlePaths(join32(resolve11(resources), "browser-engine"), `${options.platform ?? process.platform}-${options.arch ?? process.arch}`);
|
|
35274
35637
|
} catch {
|
|
35275
35638
|
return null;
|
|
35276
35639
|
}
|
|
@@ -35283,7 +35646,7 @@ function resolveAgentBrowserBinary(options = {}) {
|
|
|
35283
35646
|
const platform = options.platform ?? process.platform;
|
|
35284
35647
|
const exists = options.exists ?? existsSync15;
|
|
35285
35648
|
const override = env.OMB_AGENT_BROWSER_PATH?.trim();
|
|
35286
|
-
if (override) return
|
|
35649
|
+
if (override) return resolve11(override) && exists(resolve11(override)) ? resolve11(override) : null;
|
|
35287
35650
|
const bundle = packagedBrowser(options);
|
|
35288
35651
|
if (bundle && exists(bundle.directory)) return completePackage(bundle, exists) ? bundle.engine : null;
|
|
35289
35652
|
const pinned = pinnedBinaryPath(options.dataDir, platform, options.arch);
|
|
@@ -35295,7 +35658,7 @@ async function installAgentBrowserBinary(options = {}) {
|
|
|
35295
35658
|
const asset = options.asset ?? resolveAgentBrowserReleaseAsset(platform, options.arch ?? process.arch, options.musl ?? isMusl(platform));
|
|
35296
35659
|
if (!asset) throw new Error(`agent-browser publishes no build for ${platform}-${options.arch ?? process.arch}.`);
|
|
35297
35660
|
const destination = pinnedBinaryPath(options.dataDir, platform, options.arch);
|
|
35298
|
-
const directory =
|
|
35661
|
+
const directory = join32(destination, "..");
|
|
35299
35662
|
mkdirSync13(directory, { recursive: true, mode: 448 });
|
|
35300
35663
|
const url2 = agentBrowserReleaseUrl(asset);
|
|
35301
35664
|
options.log?.(`downloading agent-browser ${agentBrowserReleaseVersion(asset)} (${Math.round(asset.bytes / 1024 / 1024)} MB, digest pinned)`);
|
|
@@ -35311,7 +35674,7 @@ async function installAgentBrowserBinary(options = {}) {
|
|
|
35311
35674
|
clearTimeout(timer);
|
|
35312
35675
|
}
|
|
35313
35676
|
if (body.length !== asset.bytes) throw new Error("the agent-browser download did not match its pinned size; nothing was installed");
|
|
35314
|
-
const digest2 =
|
|
35677
|
+
const digest2 = createHash8("sha256").update(body).digest("hex");
|
|
35315
35678
|
if (digest2 !== asset.sha256) throw new Error("the agent-browser download failed its SHA-256 check; nothing was installed");
|
|
35316
35679
|
const staging = `${destination}.${randomBytes3(6).toString("hex")}.part`;
|
|
35317
35680
|
writeFileSync13(staging, body, { mode: 493 });
|
|
@@ -35321,7 +35684,7 @@ async function installAgentBrowserBinary(options = {}) {
|
|
|
35321
35684
|
}
|
|
35322
35685
|
function ensureChrome(binaryPath, options = {}) {
|
|
35323
35686
|
const bundle = packagedBrowser(options);
|
|
35324
|
-
if (!options.withDeps && bundle &&
|
|
35687
|
+
if (!options.withDeps && bundle && resolve11(binaryPath) === bundle.engine && completePackage(bundle, existsSync15)) {
|
|
35325
35688
|
options.log?.("agent-browser: the bundled browser is ready; no download needed");
|
|
35326
35689
|
return Promise.resolve();
|
|
35327
35690
|
}
|
|
@@ -35347,7 +35710,7 @@ function ensureChrome(binaryPath, options = {}) {
|
|
|
35347
35710
|
});
|
|
35348
35711
|
}
|
|
35349
35712
|
function browserEngineEncryptionKey(dataDir = DATA_DIR) {
|
|
35350
|
-
const file2 =
|
|
35713
|
+
const file2 = join32(dataDir, KEY_FILE);
|
|
35351
35714
|
try {
|
|
35352
35715
|
const existing = readFileSync19(file2, "utf8").trim();
|
|
35353
35716
|
if (/^[0-9a-f]{64}$/u.test(existing)) return existing;
|
|
@@ -35401,13 +35764,13 @@ function agentBrowserIntegration(input) {
|
|
|
35401
35764
|
if (sourceEnv[name]) env[name] = sourceEnv[name];
|
|
35402
35765
|
}
|
|
35403
35766
|
const bundle = packagedBrowser({ env: sourceEnv });
|
|
35404
|
-
if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle &&
|
|
35767
|
+
if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve11(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync15)) {
|
|
35405
35768
|
env.AGENT_BROWSER_EXECUTABLE_PATH = bundle.chrome;
|
|
35406
35769
|
}
|
|
35407
35770
|
return { command: input.binaryPath, args: ["mcp", "--tools", "core", "--no-webmcp"], env };
|
|
35408
35771
|
}
|
|
35409
35772
|
function agentBrowserFrame(input) {
|
|
35410
|
-
const file2 =
|
|
35773
|
+
const file2 = join32(tmpdir5(), `openmausbot-browser-${randomUUID11()}.png`);
|
|
35411
35774
|
return new Promise((settle, fail) => {
|
|
35412
35775
|
const child = spawn7(input.binaryPath, ["screenshot", file2], {
|
|
35413
35776
|
env: browserRuntimeEnv(input.env),
|
|
@@ -35477,8 +35840,8 @@ async function clearBrowserSessionState(binaryPath, session, options = {}) {
|
|
|
35477
35840
|
}
|
|
35478
35841
|
};
|
|
35479
35842
|
try {
|
|
35480
|
-
for (const base2 of bases) for (const suffix of [".json", ".json.enc", ".json.previous", ".json.enc.previous"]) remove(
|
|
35481
|
-
const pendingDirectory =
|
|
35843
|
+
for (const base2 of bases) for (const suffix of [".json", ".json.enc", ".json.previous", ".json.enc.previous"]) remove(join32(directory, base2 + suffix));
|
|
35844
|
+
const pendingDirectory = join32(directory, ".tmp");
|
|
35482
35845
|
let pendingFiles = [];
|
|
35483
35846
|
try {
|
|
35484
35847
|
pendingFiles = readdirSync3(pendingDirectory);
|
|
@@ -35486,8 +35849,8 @@ async function clearBrowserSessionState(binaryPath, session, options = {}) {
|
|
|
35486
35849
|
if (error51.code !== "ENOENT") throw error51;
|
|
35487
35850
|
}
|
|
35488
35851
|
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(
|
|
35852
|
+
for (const name of pendingFiles) if (candidates.some((candidate) => candidate.test(name))) remove(join32(pendingDirectory, name));
|
|
35853
|
+
preparedBrowserSessions.delete(join32(directory, session));
|
|
35491
35854
|
return true;
|
|
35492
35855
|
} catch {
|
|
35493
35856
|
return false;
|
|
@@ -35515,8 +35878,8 @@ var init_browser_engine = __esm({
|
|
|
35515
35878
|
var import_qrcode_terminal = __toESM(require_main(), 1);
|
|
35516
35879
|
import { spawn as spawn8 } from "node:child_process";
|
|
35517
35880
|
import { closeSync as closeSync3, existsSync as existsSync16, mkdirSync as mkdirSync14, openSync as openSync3, readFileSync as readFileSync20 } from "node:fs";
|
|
35518
|
-
import { homedir as
|
|
35519
|
-
import { dirname as dirname11, join as
|
|
35881
|
+
import { homedir as homedir24 } from "node:os";
|
|
35882
|
+
import { dirname as dirname11, join as join33, resolve as resolve12 } from "node:path";
|
|
35520
35883
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
35521
35884
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
35522
35885
|
|
|
@@ -36114,13 +36477,13 @@ function writePrivateToken(runtimeRoot2, token, { fileSystem, processId, identif
|
|
|
36114
36477
|
}
|
|
36115
36478
|
async function waitForExit(child, milliseconds) {
|
|
36116
36479
|
if (child.exitCode !== null || child.signalCode !== null) return;
|
|
36117
|
-
await new Promise((
|
|
36480
|
+
await new Promise((resolve13) => {
|
|
36118
36481
|
let settled = false;
|
|
36119
36482
|
const finish = () => {
|
|
36120
36483
|
if (settled) return;
|
|
36121
36484
|
settled = true;
|
|
36122
36485
|
clearTimeout(timer);
|
|
36123
|
-
|
|
36486
|
+
resolve13();
|
|
36124
36487
|
};
|
|
36125
36488
|
child.once("exit", finish);
|
|
36126
36489
|
const timer = setTimeout(finish, milliseconds);
|
|
@@ -36284,8 +36647,8 @@ function createManagedCompanionTunnel({
|
|
|
36284
36647
|
child = spawned;
|
|
36285
36648
|
const cancellationController = new AbortController();
|
|
36286
36649
|
let resolveCancellation;
|
|
36287
|
-
const cancellation = new Promise((
|
|
36288
|
-
resolveCancellation =
|
|
36650
|
+
const cancellation = new Promise((resolve13) => {
|
|
36651
|
+
resolveCancellation = resolve13;
|
|
36289
36652
|
});
|
|
36290
36653
|
let cancelled = false;
|
|
36291
36654
|
attemptHandle = {
|
|
@@ -36301,8 +36664,8 @@ function createManagedCompanionTunnel({
|
|
|
36301
36664
|
let terminated = false;
|
|
36302
36665
|
let expectedStop = false;
|
|
36303
36666
|
let resolveExit;
|
|
36304
|
-
const exit = new Promise((
|
|
36305
|
-
resolveExit =
|
|
36667
|
+
const exit = new Promise((resolve13) => {
|
|
36668
|
+
resolveExit = resolve13;
|
|
36306
36669
|
});
|
|
36307
36670
|
const onTerminated = () => {
|
|
36308
36671
|
if (terminated) return;
|
|
@@ -36336,8 +36699,8 @@ function createManagedCompanionTunnel({
|
|
|
36336
36699
|
}
|
|
36337
36700
|
if (Date.now() >= deadline) break;
|
|
36338
36701
|
await Promise.race([
|
|
36339
|
-
new Promise((
|
|
36340
|
-
const timer = setTimeout(
|
|
36702
|
+
new Promise((resolve13) => {
|
|
36703
|
+
const timer = setTimeout(resolve13, verifyIntervalMs);
|
|
36341
36704
|
timer.unref?.();
|
|
36342
36705
|
}),
|
|
36343
36706
|
exit,
|
|
@@ -37337,14 +37700,14 @@ function explainTailscaleFailure(reason) {
|
|
|
37337
37700
|
}
|
|
37338
37701
|
}
|
|
37339
37702
|
function run(cli, args, timeoutMs) {
|
|
37340
|
-
return new Promise((
|
|
37703
|
+
return new Promise((resolve13) => {
|
|
37341
37704
|
execFile(
|
|
37342
37705
|
cli,
|
|
37343
37706
|
args,
|
|
37344
37707
|
{ timeout: timeoutMs, killSignal: "SIGKILL", maxBuffer: 16 * 1024 * 1024, env: { ...process.env, PATH: searchPath() } },
|
|
37345
37708
|
(error51, stdout2, stderr) => {
|
|
37346
37709
|
const code = error51 && "code" in error51 && typeof error51.code === "number" ? error51.code : error51 ? null : 0;
|
|
37347
|
-
|
|
37710
|
+
resolve13({ ok: !error51, stdout: String(stdout2 ?? ""), stderr: String(stderr ?? ""), code });
|
|
37348
37711
|
}
|
|
37349
37712
|
);
|
|
37350
37713
|
});
|
|
@@ -37761,7 +38124,7 @@ function parseArgs(argv, env = process.env) {
|
|
|
37761
38124
|
const options = {
|
|
37762
38125
|
command: command === "--help" || command === "-h" ? "help" : command,
|
|
37763
38126
|
port: Number(env.OMB_PORT || 8799),
|
|
37764
|
-
dataDir: env.OMB_DATA_DIR ||
|
|
38127
|
+
dataDir: env.OMB_DATA_DIR || join33(homedir24(), ".openmausbot"),
|
|
37765
38128
|
tailscale: false,
|
|
37766
38129
|
tunnel: false,
|
|
37767
38130
|
client: false,
|
|
@@ -37780,7 +38143,7 @@ function parseArgs(argv, env = process.env) {
|
|
|
37780
38143
|
};
|
|
37781
38144
|
try {
|
|
37782
38145
|
if (arg === "--port") options.port = Number(value());
|
|
37783
|
-
else if (arg === "--data-dir") options.dataDir =
|
|
38146
|
+
else if (arg === "--data-dir") options.dataDir = resolve12(value());
|
|
37784
38147
|
else if (arg === "--label") options.label = value();
|
|
37785
38148
|
else if (arg === "--public-url") options.publicUrl = value().replace(/\/+$/, "");
|
|
37786
38149
|
else if (arg === "--tailscale") options.tailscale = true;
|
|
@@ -37891,7 +38254,7 @@ function defaultIo() {
|
|
|
37891
38254
|
}
|
|
37892
38255
|
function serverVersion(here = HERE2) {
|
|
37893
38256
|
try {
|
|
37894
|
-
const parsed = JSON.parse(readFileSync20(
|
|
38257
|
+
const parsed = JSON.parse(readFileSync20(resolve12(here, "..", "package.json"), "utf8"));
|
|
37895
38258
|
const version2 = typeof parsed === "object" && parsed !== null ? Reflect.get(parsed, "version") : void 0;
|
|
37896
38259
|
return typeof version2 === "string" && version2 ? version2 : "0.0.0";
|
|
37897
38260
|
} catch {
|
|
@@ -37916,7 +38279,7 @@ async function isWorkspaceRunning(options) {
|
|
|
37916
38279
|
try {
|
|
37917
38280
|
const { status, body } = await api(options.port, "/api/health");
|
|
37918
38281
|
if (status !== 200 || body?.app !== "openmausbot") return false;
|
|
37919
|
-
const expected = readFileSync20(
|
|
38282
|
+
const expected = readFileSync20(join33(options.dataDir, "environment-id"), "utf8").trim();
|
|
37920
38283
|
const descriptor = await api(options.port, "/.well-known/openmausbot/environment");
|
|
37921
38284
|
return /^[0-9a-f-]{36}$/i.test(expected) && descriptor.status === 200 && descriptor.body?.environmentId === expected;
|
|
37922
38285
|
} catch {
|
|
@@ -38116,7 +38479,7 @@ async function runStatus(options, io = defaultIo()) {
|
|
|
38116
38479
|
return code;
|
|
38117
38480
|
}
|
|
38118
38481
|
async function runAccess(options, io = defaultIo()) {
|
|
38119
|
-
const file2 =
|
|
38482
|
+
const file2 = join33(options.dataDir, "config.json");
|
|
38120
38483
|
let raw = {};
|
|
38121
38484
|
if (existsSync16(file2)) {
|
|
38122
38485
|
try {
|
|
@@ -38268,16 +38631,16 @@ async function runBrowser(options, io = defaultIo()) {
|
|
|
38268
38631
|
return 0;
|
|
38269
38632
|
}
|
|
38270
38633
|
function serverEntry(here = HERE2) {
|
|
38271
|
-
const bundled =
|
|
38272
|
-
const root =
|
|
38634
|
+
const bundled = join33(here, "index.js");
|
|
38635
|
+
const root = resolve12(here, "..");
|
|
38273
38636
|
if (existsSync16(bundled)) {
|
|
38274
|
-
const staticDir2 = [
|
|
38275
|
-
const skillsDir = existsSync16(
|
|
38637
|
+
const staticDir2 = [join33(root, "dist"), join33(here, "..", "ui")].find((d) => existsSync16(join33(d, "index.html"))) ?? null;
|
|
38638
|
+
const skillsDir = existsSync16(join33(root, "skills")) ? join33(root, "skills") : null;
|
|
38276
38639
|
return { command: process.execPath, args: [bundled], staticDir: staticDir2, skillsDir };
|
|
38277
38640
|
}
|
|
38278
|
-
const source =
|
|
38279
|
-
const staticDir = existsSync16(
|
|
38280
|
-
return { command: process.execPath, args: ["--experimental-strip-types", source], staticDir, skillsDir: existsSync16(
|
|
38641
|
+
const source = join33(here, "index.ts");
|
|
38642
|
+
const staticDir = existsSync16(join33(root, "dist", "index.html")) ? join33(root, "dist") : null;
|
|
38643
|
+
return { command: process.execPath, args: ["--experimental-strip-types", source], staticDir, skillsDir: existsSync16(join33(root, "skills")) ? join33(root, "skills") : null };
|
|
38281
38644
|
}
|
|
38282
38645
|
async function planTunnel(options, log) {
|
|
38283
38646
|
let access2 = null;
|
|
@@ -38377,9 +38740,9 @@ async function runServe(options, log = console.log) {
|
|
|
38377
38740
|
let child;
|
|
38378
38741
|
try {
|
|
38379
38742
|
if (options.guided) {
|
|
38380
|
-
const logsDir =
|
|
38743
|
+
const logsDir = join33(options.dataDir, "logs");
|
|
38381
38744
|
mkdirSync14(logsDir, { recursive: true, mode: 448 });
|
|
38382
|
-
logPath =
|
|
38745
|
+
logPath = join33(logsDir, `server-${Date.now()}-${process.pid}.log`);
|
|
38383
38746
|
logFd = openSync3(logPath, "wx", 384);
|
|
38384
38747
|
log("\nStarting your workspace\u2026");
|
|
38385
38748
|
}
|
|
@@ -38571,7 +38934,7 @@ async function runOnboardingCommand(options, io = defaultIo(), startServer = run
|
|
|
38571
38934
|
}
|
|
38572
38935
|
if (options.command === "setup") {
|
|
38573
38936
|
io.log("\nAll set. Start with: openmausbot (or npx openmausbot without a global install).");
|
|
38574
|
-
if (options.dataDir !==
|
|
38937
|
+
if (options.dataDir !== join33(homedir24(), ".openmausbot") || options.port !== 8799) {
|
|
38575
38938
|
io.log(`Use the same --data-dir (${options.dataDir}) and --port (${options.port}) options when starting.`);
|
|
38576
38939
|
}
|
|
38577
38940
|
return 0;
|