@fangyb/ahchat-bridge 0.1.21 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +535 -234
- package/dist/index.js +248 -117
- package/package.json +2 -2
- package/dist/cli.js +0 -51540
package/dist/cli.cjs
CHANGED
|
@@ -3679,9 +3679,8 @@ var require_websocket_server = __commonJS({
|
|
|
3679
3679
|
|
|
3680
3680
|
// src/cli.ts
|
|
3681
3681
|
init_cjs_shims();
|
|
3682
|
-
var
|
|
3683
|
-
var
|
|
3684
|
-
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
3682
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
3683
|
+
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
3685
3684
|
|
|
3686
3685
|
// ../../node_modules/.pnpm/cac@6.7.14/node_modules/cac/dist/index.mjs
|
|
3687
3686
|
init_cjs_shims();
|
|
@@ -5097,11 +5096,11 @@ var RotatingFileStream = class extends import_stream.Writable {
|
|
|
5097
5096
|
timeout;
|
|
5098
5097
|
timeoutPromise;
|
|
5099
5098
|
constructor(generator, options) {
|
|
5100
|
-
const { encoding, history, maxFiles, maxSize, path:
|
|
5099
|
+
const { encoding, history, maxFiles, maxSize, path: path24 } = options;
|
|
5101
5100
|
super({ decodeStrings: true, defaultEncoding: encoding });
|
|
5102
5101
|
this.createGzip = import_zlib.createGzip;
|
|
5103
5102
|
this.exec = import_child_process.exec;
|
|
5104
|
-
this.filename =
|
|
5103
|
+
this.filename = path24 + generator(null);
|
|
5105
5104
|
this.fsCreateReadStream = import_fs.createReadStream;
|
|
5106
5105
|
this.fsCreateWriteStream = import_fs.createWriteStream;
|
|
5107
5106
|
this.fsOpen = import_promises.open;
|
|
@@ -5113,7 +5112,7 @@ var RotatingFileStream = class extends import_stream.Writable {
|
|
|
5113
5112
|
this.options = options;
|
|
5114
5113
|
this.stdout = process.stdout;
|
|
5115
5114
|
if (maxFiles || maxSize)
|
|
5116
|
-
options.history =
|
|
5115
|
+
options.history = path24 + (history ? history : this.generator(null) + ".txt");
|
|
5117
5116
|
this.on("close", () => this.finished ? null : this.emit("finish"));
|
|
5118
5117
|
this.on("finish", () => this.finished = this.clear());
|
|
5119
5118
|
(async () => {
|
|
@@ -5241,9 +5240,9 @@ var RotatingFileStream = class extends import_stream.Writable {
|
|
|
5241
5240
|
return this.move();
|
|
5242
5241
|
}
|
|
5243
5242
|
async findName() {
|
|
5244
|
-
const { interval, path:
|
|
5243
|
+
const { interval, path: path24, intervalBoundary } = this.options;
|
|
5245
5244
|
for (let index = 1; index < 1e3; ++index) {
|
|
5246
|
-
const filename =
|
|
5245
|
+
const filename = path24 + this.generator(interval && intervalBoundary ? new Date(this.prev) : this.rotation, index);
|
|
5247
5246
|
if (!await exists(filename))
|
|
5248
5247
|
return filename;
|
|
5249
5248
|
}
|
|
@@ -5273,11 +5272,11 @@ var RotatingFileStream = class extends import_stream.Writable {
|
|
|
5273
5272
|
return this.unlink(filename);
|
|
5274
5273
|
}
|
|
5275
5274
|
async classical() {
|
|
5276
|
-
const { compress, path:
|
|
5275
|
+
const { compress, path: path24, rotate } = this.options;
|
|
5277
5276
|
let rotatedName = "";
|
|
5278
5277
|
for (let count = rotate; count > 0; --count) {
|
|
5279
|
-
const currName =
|
|
5280
|
-
const prevName = count === 1 ? this.filename :
|
|
5278
|
+
const currName = path24 + this.generator(count);
|
|
5279
|
+
const prevName = count === 1 ? this.filename : path24 + this.generator(count - 1);
|
|
5281
5280
|
if (!await exists(prevName))
|
|
5282
5281
|
continue;
|
|
5283
5282
|
if (!rotatedName)
|
|
@@ -5715,7 +5714,7 @@ function createModuleLogger(module2) {
|
|
|
5715
5714
|
|
|
5716
5715
|
// src/start.ts
|
|
5717
5716
|
init_cjs_shims();
|
|
5718
|
-
var
|
|
5717
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
5719
5718
|
|
|
5720
5719
|
// ../shared/src/index.ts
|
|
5721
5720
|
init_cjs_shims();
|
|
@@ -29753,10 +29752,10 @@ function mergeDefs(...defs) {
|
|
|
29753
29752
|
function cloneDef(schema) {
|
|
29754
29753
|
return mergeDefs(schema._zod.def);
|
|
29755
29754
|
}
|
|
29756
|
-
function getElementAtPath(obj,
|
|
29757
|
-
if (!
|
|
29755
|
+
function getElementAtPath(obj, path24) {
|
|
29756
|
+
if (!path24)
|
|
29758
29757
|
return obj;
|
|
29759
|
-
return
|
|
29758
|
+
return path24.reduce((acc, key) => acc?.[key], obj);
|
|
29760
29759
|
}
|
|
29761
29760
|
function promiseAllObject(promisesObj) {
|
|
29762
29761
|
const keys = Object.keys(promisesObj);
|
|
@@ -30165,11 +30164,11 @@ function explicitlyAborted(x2, startIndex = 0) {
|
|
|
30165
30164
|
}
|
|
30166
30165
|
return false;
|
|
30167
30166
|
}
|
|
30168
|
-
function prefixIssues(
|
|
30167
|
+
function prefixIssues(path24, issues) {
|
|
30169
30168
|
return issues.map((iss) => {
|
|
30170
30169
|
var _a3;
|
|
30171
30170
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
30172
|
-
iss.path.unshift(
|
|
30171
|
+
iss.path.unshift(path24);
|
|
30173
30172
|
return iss;
|
|
30174
30173
|
});
|
|
30175
30174
|
}
|
|
@@ -30316,16 +30315,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
30316
30315
|
}
|
|
30317
30316
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
30318
30317
|
const fieldErrors = { _errors: [] };
|
|
30319
|
-
const processError = (error52,
|
|
30318
|
+
const processError = (error52, path24 = []) => {
|
|
30320
30319
|
for (const issue2 of error52.issues) {
|
|
30321
30320
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
30322
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
30321
|
+
issue2.errors.map((issues) => processError({ issues }, [...path24, ...issue2.path]));
|
|
30323
30322
|
} else if (issue2.code === "invalid_key") {
|
|
30324
|
-
processError({ issues: issue2.issues }, [...
|
|
30323
|
+
processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
|
|
30325
30324
|
} else if (issue2.code === "invalid_element") {
|
|
30326
|
-
processError({ issues: issue2.issues }, [...
|
|
30325
|
+
processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
|
|
30327
30326
|
} else {
|
|
30328
|
-
const fullpath = [...
|
|
30327
|
+
const fullpath = [...path24, ...issue2.path];
|
|
30329
30328
|
if (fullpath.length === 0) {
|
|
30330
30329
|
fieldErrors._errors.push(mapper(issue2));
|
|
30331
30330
|
} else {
|
|
@@ -30352,17 +30351,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
30352
30351
|
}
|
|
30353
30352
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
30354
30353
|
const result = { errors: [] };
|
|
30355
|
-
const processError = (error52,
|
|
30354
|
+
const processError = (error52, path24 = []) => {
|
|
30356
30355
|
var _a3, _b2;
|
|
30357
30356
|
for (const issue2 of error52.issues) {
|
|
30358
30357
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
30359
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
30358
|
+
issue2.errors.map((issues) => processError({ issues }, [...path24, ...issue2.path]));
|
|
30360
30359
|
} else if (issue2.code === "invalid_key") {
|
|
30361
|
-
processError({ issues: issue2.issues }, [...
|
|
30360
|
+
processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
|
|
30362
30361
|
} else if (issue2.code === "invalid_element") {
|
|
30363
|
-
processError({ issues: issue2.issues }, [...
|
|
30362
|
+
processError({ issues: issue2.issues }, [...path24, ...issue2.path]);
|
|
30364
30363
|
} else {
|
|
30365
|
-
const fullpath = [...
|
|
30364
|
+
const fullpath = [...path24, ...issue2.path];
|
|
30366
30365
|
if (fullpath.length === 0) {
|
|
30367
30366
|
result.errors.push(mapper(issue2));
|
|
30368
30367
|
continue;
|
|
@@ -30394,8 +30393,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
30394
30393
|
}
|
|
30395
30394
|
function toDotPath(_path) {
|
|
30396
30395
|
const segs = [];
|
|
30397
|
-
const
|
|
30398
|
-
for (const seg of
|
|
30396
|
+
const path24 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
30397
|
+
for (const seg of path24) {
|
|
30399
30398
|
if (typeof seg === "number")
|
|
30400
30399
|
segs.push(`[${seg}]`);
|
|
30401
30400
|
else if (typeof seg === "symbol")
|
|
@@ -43168,13 +43167,13 @@ function resolveRef(ref, ctx) {
|
|
|
43168
43167
|
if (!ref.startsWith("#")) {
|
|
43169
43168
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
43170
43169
|
}
|
|
43171
|
-
const
|
|
43172
|
-
if (
|
|
43170
|
+
const path24 = ref.slice(1).split("/").filter(Boolean);
|
|
43171
|
+
if (path24.length === 0) {
|
|
43173
43172
|
return ctx.rootSchema;
|
|
43174
43173
|
}
|
|
43175
43174
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
43176
|
-
if (
|
|
43177
|
-
const key =
|
|
43175
|
+
if (path24[0] === defsKey) {
|
|
43176
|
+
const key = path24[1];
|
|
43178
43177
|
if (!key || !ctx.defs[key]) {
|
|
43179
43178
|
throw new Error(`Reference not found: ${ref}`);
|
|
43180
43179
|
}
|
|
@@ -49771,8 +49770,8 @@ var HttpAgentRegistry = class {
|
|
|
49771
49770
|
agents = /* @__PURE__ */ new Map();
|
|
49772
49771
|
apiUrl(suffix) {
|
|
49773
49772
|
const base = this.serverApiUrl.replace(/\/$/, "");
|
|
49774
|
-
const
|
|
49775
|
-
return `${base}${
|
|
49773
|
+
const path24 = suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
49774
|
+
return `${base}${path24}`;
|
|
49776
49775
|
}
|
|
49777
49776
|
async refresh() {
|
|
49778
49777
|
const attempt = async () => {
|
|
@@ -49864,8 +49863,8 @@ var HttpSubscriptionRegistry = class {
|
|
|
49864
49863
|
subscriptions = /* @__PURE__ */ new Map();
|
|
49865
49864
|
apiUrl(suffix) {
|
|
49866
49865
|
const base = this.serverApiUrl.replace(/\/$/, "");
|
|
49867
|
-
const
|
|
49868
|
-
return `${base}${
|
|
49866
|
+
const path24 = suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
49867
|
+
return `${base}${path24}`;
|
|
49869
49868
|
}
|
|
49870
49869
|
async refresh() {
|
|
49871
49870
|
const attempt = async () => {
|
|
@@ -50753,19 +50752,220 @@ async function dumpAgentContext(agentId, deps) {
|
|
|
50753
50752
|
// src/listDir.ts
|
|
50754
50753
|
init_cjs_shims();
|
|
50755
50754
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
50755
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
50756
|
+
|
|
50757
|
+
// src/runtimeEnv.ts
|
|
50758
|
+
init_cjs_shims();
|
|
50759
|
+
var import_node_child_process2 = require("child_process");
|
|
50760
|
+
var import_node_fs4 = require("fs");
|
|
50761
|
+
var import_node_os8 = __toESM(require("os"), 1);
|
|
50756
50762
|
var import_node_path11 = __toESM(require("path"), 1);
|
|
50763
|
+
var MIN_NODE_MAJOR = 20;
|
|
50764
|
+
function getHomeDir() {
|
|
50765
|
+
return process.env.USERPROFILE || import_node_os8.default.homedir();
|
|
50766
|
+
}
|
|
50767
|
+
function splitPath(value) {
|
|
50768
|
+
if (!value) return [];
|
|
50769
|
+
return value.split(import_node_path11.default.delimiter).filter((entry) => entry.length > 0);
|
|
50770
|
+
}
|
|
50771
|
+
function uniq(values) {
|
|
50772
|
+
return [...new Set(values.filter(Boolean))];
|
|
50773
|
+
}
|
|
50774
|
+
function parseNodeVersionMajor(version2) {
|
|
50775
|
+
const raw = version2.trim().replace(/^v/, "");
|
|
50776
|
+
const [majorRaw] = raw.split(".");
|
|
50777
|
+
if (!majorRaw) return null;
|
|
50778
|
+
const major = Number.parseInt(majorRaw, 10);
|
|
50779
|
+
return Number.isFinite(major) ? major : null;
|
|
50780
|
+
}
|
|
50781
|
+
function joinHomePath(home, suffix) {
|
|
50782
|
+
const parts = suffix.split(/[\\/]+/).filter((part) => part.length > 0);
|
|
50783
|
+
return import_node_path11.default.join(home, ...parts);
|
|
50784
|
+
}
|
|
50785
|
+
function sortNodeVersionDirsDesc(names) {
|
|
50786
|
+
return [...names].sort((a, b2) => {
|
|
50787
|
+
const aParts = a.replace(/^v/, "").split(".").map((p) => Number.parseInt(p, 10) || 0);
|
|
50788
|
+
const bParts = b2.replace(/^v/, "").split(".").map((p) => Number.parseInt(p, 10) || 0);
|
|
50789
|
+
for (let i = 0; i < Math.max(aParts.length, bParts.length); i += 1) {
|
|
50790
|
+
const delta = (bParts[i] ?? 0) - (aParts[i] ?? 0);
|
|
50791
|
+
if (delta !== 0) return delta;
|
|
50792
|
+
}
|
|
50793
|
+
return b2.localeCompare(a);
|
|
50794
|
+
});
|
|
50795
|
+
}
|
|
50796
|
+
function listNodeVersionBins(root, binSuffix) {
|
|
50797
|
+
if (!(0, import_node_fs4.existsSync)(root)) return [];
|
|
50798
|
+
try {
|
|
50799
|
+
return sortNodeVersionDirsDesc((0, import_node_fs4.readdirSync)(root)).map((version2) => import_node_path11.default.join(root, version2, ...binSuffix)).filter((candidate) => (0, import_node_fs4.existsSync)(candidate));
|
|
50800
|
+
} catch {
|
|
50801
|
+
return [];
|
|
50802
|
+
}
|
|
50803
|
+
}
|
|
50804
|
+
function getNodeRuntimeStatus(version2 = process.versions.node) {
|
|
50805
|
+
const major = parseNodeVersionMajor(version2);
|
|
50806
|
+
return {
|
|
50807
|
+
version: version2,
|
|
50808
|
+
major,
|
|
50809
|
+
supported: major !== null && major >= MIN_NODE_MAJOR
|
|
50810
|
+
};
|
|
50811
|
+
}
|
|
50812
|
+
function getNodeToolExtraPathEntries(env2 = process.env) {
|
|
50813
|
+
const home = getHomeDir();
|
|
50814
|
+
const entries = [];
|
|
50815
|
+
if (process.platform === "win32") {
|
|
50816
|
+
for (const envName of ["NVM_SYMLINK", "NVM_HOME"]) {
|
|
50817
|
+
const value = env2[envName];
|
|
50818
|
+
if (value && (0, import_node_fs4.existsSync)(value)) entries.push(value);
|
|
50819
|
+
}
|
|
50820
|
+
for (const candidate of [
|
|
50821
|
+
import_node_path11.default.join(home, "AppData", "Roaming", "npm"),
|
|
50822
|
+
import_node_path11.default.join(home, ".volta", "bin"),
|
|
50823
|
+
import_node_path11.default.join(home, ".asdf", "shims"),
|
|
50824
|
+
import_node_path11.default.join(env2.ProgramFiles ?? "C:\\Program Files", "nodejs"),
|
|
50825
|
+
import_node_path11.default.join(env2.LOCALAPPDATA ?? import_node_path11.default.join(home, "AppData", "Local"), "Programs", "nodejs")
|
|
50826
|
+
]) {
|
|
50827
|
+
if ((0, import_node_fs4.existsSync)(candidate)) entries.push(candidate);
|
|
50828
|
+
}
|
|
50829
|
+
return uniq(entries);
|
|
50830
|
+
}
|
|
50831
|
+
const nvmRoot = env2.NVM_DIR ?? import_node_path11.default.join(home, ".nvm");
|
|
50832
|
+
entries.push(...listNodeVersionBins(import_node_path11.default.join(nvmRoot, "versions", "node"), ["bin"]));
|
|
50833
|
+
const fnmRoots = [
|
|
50834
|
+
import_node_path11.default.join(home, ".fnm", "node-versions"),
|
|
50835
|
+
import_node_path11.default.join(home, ".local", "share", "fnm", "node-versions")
|
|
50836
|
+
];
|
|
50837
|
+
for (const fnmRoot of fnmRoots) {
|
|
50838
|
+
entries.push(...listNodeVersionBins(fnmRoot, ["installation", "bin"]));
|
|
50839
|
+
}
|
|
50840
|
+
for (const candidate of [
|
|
50841
|
+
import_node_path11.default.join(home, ".volta", "bin"),
|
|
50842
|
+
import_node_path11.default.join(home, ".asdf", "shims"),
|
|
50843
|
+
import_node_path11.default.join(home, ".local", "bin"),
|
|
50844
|
+
"/opt/homebrew/bin",
|
|
50845
|
+
"/usr/local/bin"
|
|
50846
|
+
]) {
|
|
50847
|
+
if ((0, import_node_fs4.existsSync)(candidate)) entries.push(candidate);
|
|
50848
|
+
}
|
|
50849
|
+
return uniq(entries);
|
|
50850
|
+
}
|
|
50851
|
+
function buildAugmentedPath(env2 = process.env) {
|
|
50852
|
+
return uniq([...getNodeToolExtraPathEntries(env2), ...splitPath(env2.PATH)]).join(import_node_path11.default.delimiter);
|
|
50853
|
+
}
|
|
50854
|
+
function withAugmentedPathEnv(env2 = process.env) {
|
|
50855
|
+
return { ...env2, PATH: buildAugmentedPath(env2) };
|
|
50856
|
+
}
|
|
50857
|
+
function executableNames(name) {
|
|
50858
|
+
if (process.platform !== "win32") return [name];
|
|
50859
|
+
if (/\.(cmd|exe|bat)$/i.test(name)) return [name];
|
|
50860
|
+
return [`${name}.cmd`, `${name}.exe`, `${name}.bat`, name];
|
|
50861
|
+
}
|
|
50862
|
+
function canExecute(candidate) {
|
|
50863
|
+
try {
|
|
50864
|
+
if (process.platform === "win32") return (0, import_node_fs4.existsSync)(candidate);
|
|
50865
|
+
(0, import_node_fs4.accessSync)(candidate, import_node_fs4.constants.X_OK);
|
|
50866
|
+
return true;
|
|
50867
|
+
} catch {
|
|
50868
|
+
return false;
|
|
50869
|
+
}
|
|
50870
|
+
}
|
|
50871
|
+
function resolveCommand(names, env2 = process.env) {
|
|
50872
|
+
const pathEntries = splitPath(buildAugmentedPath(env2));
|
|
50873
|
+
for (const entry of pathEntries) {
|
|
50874
|
+
for (const name of names) {
|
|
50875
|
+
for (const executableName of executableNames(name)) {
|
|
50876
|
+
const candidate = import_node_path11.default.join(entry, executableName);
|
|
50877
|
+
if (canExecute(candidate)) return { name, path: candidate };
|
|
50878
|
+
}
|
|
50879
|
+
}
|
|
50880
|
+
}
|
|
50881
|
+
return void 0;
|
|
50882
|
+
}
|
|
50883
|
+
function readCommandVersion(executablePath, args = ["--version"], env2 = process.env) {
|
|
50884
|
+
try {
|
|
50885
|
+
return (0, import_node_child_process2.execFileSync)(executablePath, args, {
|
|
50886
|
+
env: withAugmentedPathEnv(env2),
|
|
50887
|
+
timeout: 1e4
|
|
50888
|
+
}).toString().trim();
|
|
50889
|
+
} catch {
|
|
50890
|
+
return void 0;
|
|
50891
|
+
}
|
|
50892
|
+
}
|
|
50893
|
+
function probeCommand(name, args = ["--version"], env2 = process.env) {
|
|
50894
|
+
const resolved = resolveCommand([name], env2);
|
|
50895
|
+
if (!resolved) {
|
|
50896
|
+
return {
|
|
50897
|
+
name,
|
|
50898
|
+
ok: false,
|
|
50899
|
+
message: `${name} was not found on PATH`
|
|
50900
|
+
};
|
|
50901
|
+
}
|
|
50902
|
+
const version2 = readCommandVersion(resolved.path, args, env2);
|
|
50903
|
+
return {
|
|
50904
|
+
name,
|
|
50905
|
+
path: resolved.path,
|
|
50906
|
+
version: version2,
|
|
50907
|
+
ok: Boolean(version2),
|
|
50908
|
+
message: version2 ? void 0 : `${name} was found but did not run successfully`
|
|
50909
|
+
};
|
|
50910
|
+
}
|
|
50911
|
+
function resolveUserPath(input) {
|
|
50912
|
+
const home = getHomeDir();
|
|
50913
|
+
let value = input.trim();
|
|
50914
|
+
if (value === "~") value = home;
|
|
50915
|
+
else if (value.startsWith("~/") || value.startsWith("~\\")) value = joinHomePath(home, value.slice(2));
|
|
50916
|
+
else if (value === "$HOME") value = home;
|
|
50917
|
+
else if (value.startsWith("$HOME/") || value.startsWith("$HOME\\")) value = joinHomePath(home, value.slice(6));
|
|
50918
|
+
else if (value === "${HOME}") value = home;
|
|
50919
|
+
else if (value.startsWith("${HOME}/") || value.startsWith("${HOME}\\")) value = joinHomePath(home, value.slice(8));
|
|
50920
|
+
else if (value === "$env:USERPROFILE") value = home;
|
|
50921
|
+
else if (value.startsWith("$env:USERPROFILE\\") || value.startsWith("$env:USERPROFILE/")) {
|
|
50922
|
+
value = joinHomePath(home, value.slice("$env:USERPROFILE".length + 1));
|
|
50923
|
+
} else if (value === "%USERPROFILE%") value = home;
|
|
50924
|
+
else if (value.startsWith("%USERPROFILE%\\") || value.startsWith("%USERPROFILE%/")) {
|
|
50925
|
+
value = joinHomePath(home, value.slice("%USERPROFILE%".length + 1));
|
|
50926
|
+
}
|
|
50927
|
+
return import_node_path11.default.isAbsolute(value) ? import_node_path11.default.normalize(value) : import_node_path11.default.resolve(value);
|
|
50928
|
+
}
|
|
50929
|
+
function assertBridgeUserSlug(user) {
|
|
50930
|
+
const value = user.trim();
|
|
50931
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value)) {
|
|
50932
|
+
throw new Error('Bridge --user may only contain letters, numbers, "_" and "-"');
|
|
50933
|
+
}
|
|
50934
|
+
return value;
|
|
50935
|
+
}
|
|
50936
|
+
function resolveBridgeDataDir(opts) {
|
|
50937
|
+
if (opts.dataDir) return resolveUserPath(opts.dataDir);
|
|
50938
|
+
if (opts.user) return resolveUserPath(`~/.ahchat/users/${assertBridgeUserSlug(opts.user)}`);
|
|
50939
|
+
return void 0;
|
|
50940
|
+
}
|
|
50941
|
+
function normalizeBridgeServerUrls(rawUrl) {
|
|
50942
|
+
const url2 = new URL(rawUrl);
|
|
50943
|
+
if (url2.protocol === "http:" || url2.protocol === "https:") {
|
|
50944
|
+
url2.protocol = url2.protocol === "https:" ? "wss:" : "ws:";
|
|
50945
|
+
if (url2.pathname === "/" || url2.pathname === "") url2.pathname = "/ws/bridge";
|
|
50946
|
+
}
|
|
50947
|
+
if (url2.protocol !== "ws:" && url2.protocol !== "wss:") {
|
|
50948
|
+
throw new Error(`Unsupported bridge server URL protocol: ${url2.protocol}`);
|
|
50949
|
+
}
|
|
50950
|
+
const serverUrl = url2.toString();
|
|
50951
|
+
const serverApiUrl = `${url2.protocol === "wss:" ? "https" : "http"}://${url2.host}`;
|
|
50952
|
+
return { serverUrl, serverApiUrl };
|
|
50953
|
+
}
|
|
50954
|
+
|
|
50955
|
+
// src/listDir.ts
|
|
50757
50956
|
var logger17 = createModuleLogger("bridge.listDir");
|
|
50758
50957
|
function shouldIncludeEntry(name) {
|
|
50759
50958
|
if (!name.startsWith(".")) return true;
|
|
50760
50959
|
return name === ".ahchat-attachments";
|
|
50761
50960
|
}
|
|
50762
50961
|
async function listDirectoryEntries(dirPath) {
|
|
50763
|
-
|
|
50764
|
-
|
|
50962
|
+
const resolvedDirPath = resolveUserPath(dirPath);
|
|
50963
|
+
logger17.info("listDirectoryEntries start", { path: dirPath, resolvedPath: resolvedDirPath });
|
|
50964
|
+
const raw = await import_promises10.default.readdir(resolvedDirPath, { withFileTypes: true });
|
|
50765
50965
|
const entries = [];
|
|
50766
50966
|
for (const entry of raw) {
|
|
50767
50967
|
if (!shouldIncludeEntry(entry.name)) continue;
|
|
50768
|
-
const fullPath =
|
|
50968
|
+
const fullPath = import_node_path12.default.join(resolvedDirPath, entry.name);
|
|
50769
50969
|
const isDir = entry.isDirectory();
|
|
50770
50970
|
let size;
|
|
50771
50971
|
let mtime;
|
|
@@ -50784,6 +50984,7 @@ async function listDirectoryEntries(dirPath) {
|
|
|
50784
50984
|
});
|
|
50785
50985
|
logger17.info("listDirectoryEntries ok", {
|
|
50786
50986
|
path: dirPath,
|
|
50987
|
+
resolvedPath: resolvedDirPath,
|
|
50787
50988
|
count: entries.length,
|
|
50788
50989
|
dirCount: entries.filter((e7) => e7.type === "dir").length,
|
|
50789
50990
|
fileCount: entries.filter((e7) => e7.type === "file").length
|
|
@@ -50793,9 +50994,9 @@ async function listDirectoryEntries(dirPath) {
|
|
|
50793
50994
|
|
|
50794
50995
|
// src/logScanner.ts
|
|
50795
50996
|
init_cjs_shims();
|
|
50796
|
-
var
|
|
50797
|
-
var
|
|
50798
|
-
var
|
|
50997
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
50998
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
50999
|
+
var import_node_os9 = __toESM(require("os"), 1);
|
|
50799
51000
|
var import_node_readline = __toESM(require("readline"), 1);
|
|
50800
51001
|
var logger18 = createModuleLogger("bridge.logScanner");
|
|
50801
51002
|
var DEFAULT_LIMIT = 500;
|
|
@@ -50803,17 +51004,17 @@ var MAX_LIMIT = 2e3;
|
|
|
50803
51004
|
function listLogFiles(logsDir, baseName) {
|
|
50804
51005
|
let names;
|
|
50805
51006
|
try {
|
|
50806
|
-
names =
|
|
51007
|
+
names = import_node_fs5.default.readdirSync(logsDir);
|
|
50807
51008
|
} catch (e7) {
|
|
50808
51009
|
logger18.warn("listLogFiles: readdir failed", { logsDir, error: e7 });
|
|
50809
51010
|
return [];
|
|
50810
51011
|
}
|
|
50811
51012
|
const pattern = new RegExp(`^${baseName.replace(".", "\\.")}(\\.\\d+)?$`);
|
|
50812
|
-
return names.filter((n2) => pattern.test(n2)).map((n2) =>
|
|
51013
|
+
return names.filter((n2) => pattern.test(n2)).map((n2) => import_node_path13.default.join(logsDir, n2));
|
|
50813
51014
|
}
|
|
50814
51015
|
async function scanFile(filePath, source, filter, limit, state) {
|
|
50815
|
-
const file2 =
|
|
50816
|
-
const stream =
|
|
51016
|
+
const file2 = import_node_path13.default.basename(filePath);
|
|
51017
|
+
const stream = import_node_fs5.default.createReadStream(filePath, { encoding: "utf-8" });
|
|
50817
51018
|
const rl2 = import_node_readline.default.createInterface({ input: stream, crlfDelay: Infinity });
|
|
50818
51019
|
let lineNum = 0;
|
|
50819
51020
|
for await (const line of rl2) {
|
|
@@ -50851,7 +51052,7 @@ async function scanLocalLogs(logsDir, baseName, filter) {
|
|
|
50851
51052
|
};
|
|
50852
51053
|
}
|
|
50853
51054
|
async function scanBridgeLogs(filter) {
|
|
50854
|
-
const logDir =
|
|
51055
|
+
const logDir = import_node_path13.default.join(import_node_os9.default.homedir(), ".ahchat", "logs");
|
|
50855
51056
|
logger18.info("scanBridgeLogs start", {
|
|
50856
51057
|
logDir,
|
|
50857
51058
|
startIso: filter.startIso,
|
|
@@ -50869,15 +51070,15 @@ async function scanBridgeLogs(filter) {
|
|
|
50869
51070
|
|
|
50870
51071
|
// src/skillStore.ts
|
|
50871
51072
|
init_cjs_shims();
|
|
50872
|
-
var
|
|
50873
|
-
var
|
|
51073
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
51074
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
50874
51075
|
var logger19 = createModuleLogger("bridge.skillStore");
|
|
50875
51076
|
var ALLOWED_NAMES = /* @__PURE__ */ new Set(["log-analysis"]);
|
|
50876
51077
|
var SkillStore = class {
|
|
50877
51078
|
skillsDir;
|
|
50878
51079
|
constructor(dataDir) {
|
|
50879
|
-
this.skillsDir =
|
|
50880
|
-
|
|
51080
|
+
this.skillsDir = import_node_path14.default.join(dataDir, "skills");
|
|
51081
|
+
import_node_fs6.default.mkdirSync(this.skillsDir, { recursive: true });
|
|
50881
51082
|
logger19.info("SkillStore initialized", { skillsDir: this.skillsDir });
|
|
50882
51083
|
}
|
|
50883
51084
|
read(name) {
|
|
@@ -50885,9 +51086,9 @@ var SkillStore = class {
|
|
|
50885
51086
|
logger19.warn("Skill read: unknown name", { name, allowed: [...ALLOWED_NAMES] });
|
|
50886
51087
|
return "";
|
|
50887
51088
|
}
|
|
50888
|
-
const filePath =
|
|
51089
|
+
const filePath = import_node_path14.default.join(this.skillsDir, `${name}.md`);
|
|
50889
51090
|
try {
|
|
50890
|
-
const content =
|
|
51091
|
+
const content = import_node_fs6.default.readFileSync(filePath, "utf-8");
|
|
50891
51092
|
logger19.info("Skill read", { name, bytes: content.length });
|
|
50892
51093
|
return content;
|
|
50893
51094
|
} catch (e7) {
|
|
@@ -50900,19 +51101,19 @@ var SkillStore = class {
|
|
|
50900
51101
|
if (!ALLOWED_NAMES.has(name)) {
|
|
50901
51102
|
throw new Error(`Unknown skill name: ${name}`);
|
|
50902
51103
|
}
|
|
50903
|
-
const filePath =
|
|
51104
|
+
const filePath = import_node_path14.default.join(this.skillsDir, `${name}.md`);
|
|
50904
51105
|
const tmpPath = `${filePath}.tmp`;
|
|
50905
51106
|
let existing = "";
|
|
50906
51107
|
try {
|
|
50907
|
-
existing =
|
|
51108
|
+
existing = import_node_fs6.default.readFileSync(filePath, "utf-8");
|
|
50908
51109
|
} catch {
|
|
50909
51110
|
}
|
|
50910
51111
|
if (existing === content) {
|
|
50911
51112
|
logger19.info("Skill already in sync", { name, bytes: content.length });
|
|
50912
51113
|
return;
|
|
50913
51114
|
}
|
|
50914
|
-
|
|
50915
|
-
|
|
51115
|
+
import_node_fs6.default.writeFileSync(tmpPath, content, "utf-8");
|
|
51116
|
+
import_node_fs6.default.renameSync(tmpPath, filePath);
|
|
50916
51117
|
logger19.info("Skill seeded/re-synced", {
|
|
50917
51118
|
name,
|
|
50918
51119
|
bytes: content.length,
|
|
@@ -50923,8 +51124,8 @@ var SkillStore = class {
|
|
|
50923
51124
|
|
|
50924
51125
|
// src/lockfile.ts
|
|
50925
51126
|
init_cjs_shims();
|
|
50926
|
-
var
|
|
50927
|
-
var
|
|
51127
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
51128
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
50928
51129
|
var logger20 = createModuleLogger("bridge.lockfile");
|
|
50929
51130
|
var lockPath = null;
|
|
50930
51131
|
function isProcessAlive(pid) {
|
|
@@ -50938,10 +51139,10 @@ function isProcessAlive(pid) {
|
|
|
50938
51139
|
}
|
|
50939
51140
|
}
|
|
50940
51141
|
function acquireLock(dataDir) {
|
|
50941
|
-
const file2 =
|
|
51142
|
+
const file2 = import_node_path15.default.join(dataDir, "bridge.lock");
|
|
50942
51143
|
lockPath = file2;
|
|
50943
|
-
if (
|
|
50944
|
-
const raw =
|
|
51144
|
+
if (import_node_fs7.default.existsSync(file2)) {
|
|
51145
|
+
const raw = import_node_fs7.default.readFileSync(file2, "utf-8").trim();
|
|
50945
51146
|
const pid = Number.parseInt(raw, 10);
|
|
50946
51147
|
if (Number.isFinite(pid) && pid > 0) {
|
|
50947
51148
|
if (isProcessAlive(pid)) {
|
|
@@ -50950,15 +51151,15 @@ function acquireLock(dataDir) {
|
|
|
50950
51151
|
logger20.warn("Removing stale bridge.lock (process not found)", { pid, path: file2 });
|
|
50951
51152
|
}
|
|
50952
51153
|
}
|
|
50953
|
-
|
|
50954
|
-
|
|
51154
|
+
import_node_fs7.default.mkdirSync(import_node_path15.default.dirname(file2), { recursive: true });
|
|
51155
|
+
import_node_fs7.default.writeFileSync(file2, String(process.pid), "utf-8");
|
|
50955
51156
|
logger20.info("Acquired bridge lock", { path: file2, pid: process.pid });
|
|
50956
51157
|
const release = () => {
|
|
50957
51158
|
try {
|
|
50958
|
-
if (lockPath &&
|
|
50959
|
-
const current =
|
|
51159
|
+
if (lockPath && import_node_fs7.default.existsSync(lockPath)) {
|
|
51160
|
+
const current = import_node_fs7.default.readFileSync(lockPath, "utf-8").trim();
|
|
50960
51161
|
if (current === String(process.pid)) {
|
|
50961
|
-
|
|
51162
|
+
import_node_fs7.default.unlinkSync(lockPath);
|
|
50962
51163
|
logger20.info("Released bridge lock", { path: lockPath });
|
|
50963
51164
|
}
|
|
50964
51165
|
}
|
|
@@ -51319,14 +51520,14 @@ async function handleGroupArchivedPush(deps, payload) {
|
|
|
51319
51520
|
|
|
51320
51521
|
// src/sessionStore.ts
|
|
51321
51522
|
init_cjs_shims();
|
|
51322
|
-
var
|
|
51323
|
-
var
|
|
51523
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
51524
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
51324
51525
|
var logger23 = createModuleLogger("session.store");
|
|
51325
51526
|
var SessionStore = class {
|
|
51326
51527
|
filePath;
|
|
51327
51528
|
cache;
|
|
51328
51529
|
constructor(dataDir) {
|
|
51329
|
-
this.filePath =
|
|
51530
|
+
this.filePath = import_node_path16.default.join(dataDir, "sessions.json");
|
|
51330
51531
|
this.cache = this.loadFromDisk();
|
|
51331
51532
|
}
|
|
51332
51533
|
cacheKey(agentId, scope) {
|
|
@@ -51361,8 +51562,8 @@ var SessionStore = class {
|
|
|
51361
51562
|
}
|
|
51362
51563
|
loadFromDisk() {
|
|
51363
51564
|
try {
|
|
51364
|
-
if (!
|
|
51365
|
-
const raw =
|
|
51565
|
+
if (!import_node_fs8.default.existsSync(this.filePath)) return {};
|
|
51566
|
+
const raw = import_node_fs8.default.readFileSync(this.filePath, "utf-8");
|
|
51366
51567
|
const parsed = JSON.parse(raw);
|
|
51367
51568
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
51368
51569
|
const map2 = parsed;
|
|
@@ -51386,9 +51587,9 @@ var SessionStore = class {
|
|
|
51386
51587
|
}
|
|
51387
51588
|
saveToDisk() {
|
|
51388
51589
|
try {
|
|
51389
|
-
const dir =
|
|
51390
|
-
|
|
51391
|
-
|
|
51590
|
+
const dir = import_node_path16.default.dirname(this.filePath);
|
|
51591
|
+
import_node_fs8.default.mkdirSync(dir, { recursive: true });
|
|
51592
|
+
import_node_fs8.default.writeFileSync(this.filePath, JSON.stringify(this.cache, null, 2), "utf-8");
|
|
51392
51593
|
} catch (e7) {
|
|
51393
51594
|
logger23.error("Failed to save sessions file", { error: e7, path: this.filePath });
|
|
51394
51595
|
}
|
|
@@ -51397,9 +51598,9 @@ var SessionStore = class {
|
|
|
51397
51598
|
|
|
51398
51599
|
// src/ensureClaudeCli.ts
|
|
51399
51600
|
init_cjs_shims();
|
|
51400
|
-
var
|
|
51401
|
-
var
|
|
51402
|
-
var
|
|
51601
|
+
var import_node_child_process3 = require("child_process");
|
|
51602
|
+
var import_node_fs9 = require("fs");
|
|
51603
|
+
var import_node_path17 = require("path");
|
|
51403
51604
|
var logger24 = createModuleLogger("bridge.ensureCli");
|
|
51404
51605
|
var DEFAULT_INSTALL_TIMEOUT_MS = 6e5;
|
|
51405
51606
|
function getInstallTimeoutMs() {
|
|
@@ -51408,48 +51609,42 @@ function getInstallTimeoutMs() {
|
|
|
51408
51609
|
const parsed = Number.parseInt(raw, 10);
|
|
51409
51610
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INSTALL_TIMEOUT_MS;
|
|
51410
51611
|
}
|
|
51411
|
-
function detectClaudeCli() {
|
|
51412
|
-
try {
|
|
51413
|
-
return (0, import_node_child_process2.execFileSync)("claude", ["--version"], { timeout: 1e4 }).toString().trim();
|
|
51414
|
-
} catch {
|
|
51415
|
-
return void 0;
|
|
51416
|
-
}
|
|
51417
|
-
}
|
|
51418
51612
|
function getNpmGlobalBin() {
|
|
51613
|
+
const npm = resolveCommand(["npm"]);
|
|
51614
|
+
if (!npm) return void 0;
|
|
51419
51615
|
try {
|
|
51420
|
-
const bin = (0,
|
|
51616
|
+
const bin = (0, import_node_child_process3.execFileSync)(npm.path, ["bin", "-g"], {
|
|
51617
|
+
env: withAugmentedPathEnv(),
|
|
51618
|
+
timeout: 5e3
|
|
51619
|
+
}).toString().trim() || void 0;
|
|
51421
51620
|
if (bin) return bin;
|
|
51422
51621
|
} catch {
|
|
51423
51622
|
}
|
|
51424
51623
|
try {
|
|
51425
|
-
const prefix = (0,
|
|
51426
|
-
|
|
51624
|
+
const prefix = (0, import_node_child_process3.execFileSync)(npm.path, ["prefix", "-g"], {
|
|
51625
|
+
env: withAugmentedPathEnv(),
|
|
51626
|
+
timeout: 5e3
|
|
51627
|
+
}).toString().trim();
|
|
51628
|
+
if (prefix) return (0, import_node_path17.join)(prefix, "bin");
|
|
51427
51629
|
} catch {
|
|
51428
51630
|
}
|
|
51429
51631
|
return void 0;
|
|
51430
51632
|
}
|
|
51431
51633
|
function resolveClaudeBinary() {
|
|
51432
|
-
|
|
51433
|
-
try {
|
|
51434
|
-
const out = (0, import_node_child_process2.execFileSync)(whichCmd, ["claude"], { timeout: 5e3 }).toString();
|
|
51435
|
-
const first = out.split(/\r?\n/).map((l4) => l4.trim()).find(Boolean);
|
|
51436
|
-
if (first) return first;
|
|
51437
|
-
} catch {
|
|
51438
|
-
}
|
|
51439
|
-
return resolveViaNpmBin();
|
|
51634
|
+
return resolveCommand(["claude", "anthropic-cli"])?.path ?? resolveViaNpmBin();
|
|
51440
51635
|
}
|
|
51441
51636
|
function getNpmClaudeCandidates(bin) {
|
|
51442
51637
|
if (process.platform === "win32") {
|
|
51443
|
-
return ["claude.cmd", "claude.exe", "claude", "anthropic-cli.cmd", "anthropic-cli.exe", "anthropic-cli"].map((name) => (0,
|
|
51638
|
+
return ["claude.cmd", "claude.exe", "claude", "anthropic-cli.cmd", "anthropic-cli.exe", "anthropic-cli"].map((name) => (0, import_node_path17.join)(bin, name));
|
|
51444
51639
|
}
|
|
51445
|
-
return [(0,
|
|
51640
|
+
return [(0, import_node_path17.join)(bin, "claude"), (0, import_node_path17.join)(bin, "anthropic-cli")];
|
|
51446
51641
|
}
|
|
51447
51642
|
function resolveViaNpmBin() {
|
|
51448
51643
|
const bin = getNpmGlobalBin();
|
|
51449
51644
|
if (!bin) return void 0;
|
|
51450
51645
|
for (const candidate of getNpmClaudeCandidates(bin)) {
|
|
51451
51646
|
try {
|
|
51452
|
-
(0,
|
|
51647
|
+
(0, import_node_fs9.accessSync)(candidate, import_node_fs9.constants.X_OK);
|
|
51453
51648
|
return candidate;
|
|
51454
51649
|
} catch {
|
|
51455
51650
|
}
|
|
@@ -51459,40 +51654,32 @@ function resolveViaNpmBin() {
|
|
|
51459
51654
|
function detectViaNpmBin() {
|
|
51460
51655
|
const binPath = resolveViaNpmBin();
|
|
51461
51656
|
if (!binPath) return void 0;
|
|
51462
|
-
|
|
51463
|
-
return (0, import_node_child_process2.execFileSync)(binPath, ["--version"], { timeout: 1e4 }).toString().trim();
|
|
51464
|
-
} catch {
|
|
51465
|
-
}
|
|
51466
|
-
return void 0;
|
|
51657
|
+
return readCommandVersion(binPath);
|
|
51467
51658
|
}
|
|
51468
51659
|
function detectResolvedClaudeCli() {
|
|
51469
|
-
const
|
|
51470
|
-
if (
|
|
51471
|
-
|
|
51472
|
-
}
|
|
51473
|
-
const npmBinPath = resolveViaNpmBin();
|
|
51474
|
-
if (!npmBinPath) return void 0;
|
|
51475
|
-
try {
|
|
51476
|
-
const version2 = (0, import_node_child_process2.execFileSync)(npmBinPath, ["--version"], { timeout: 1e4 }).toString().trim();
|
|
51477
|
-
return { version: version2, path: npmBinPath };
|
|
51478
|
-
} catch {
|
|
51479
|
-
}
|
|
51660
|
+
const resolvedPath = resolveClaudeBinary();
|
|
51661
|
+
if (!resolvedPath) return void 0;
|
|
51662
|
+
const version2 = readCommandVersion(resolvedPath);
|
|
51663
|
+
if (version2) return { version: version2, path: resolvedPath };
|
|
51480
51664
|
return void 0;
|
|
51481
51665
|
}
|
|
51482
51666
|
function detectVersionFromResolvedCandidates() {
|
|
51483
51667
|
const candidates = [resolveClaudeBinary(), resolveViaNpmBin()].filter((p) => Boolean(p));
|
|
51484
51668
|
for (const p of candidates) {
|
|
51485
|
-
|
|
51486
|
-
|
|
51487
|
-
return (0, import_node_child_process2.execFileSync)(p, ["--version"], { timeout: 1e4 }).toString().trim();
|
|
51488
|
-
} catch {
|
|
51489
|
-
}
|
|
51669
|
+
const version2 = readCommandVersion(p);
|
|
51670
|
+
if (version2) return version2;
|
|
51490
51671
|
}
|
|
51491
51672
|
return void 0;
|
|
51492
51673
|
}
|
|
51493
51674
|
function installClaudeCli() {
|
|
51675
|
+
const npm = resolveCommand(["npm"]);
|
|
51676
|
+
if (!npm) {
|
|
51677
|
+
logger24.error("npm not found; cannot install Claude Code CLI");
|
|
51678
|
+
return void 0;
|
|
51679
|
+
}
|
|
51494
51680
|
logger24.info("Installing Claude Code CLI via npm...");
|
|
51495
|
-
const result = (0,
|
|
51681
|
+
const result = (0, import_node_child_process3.spawnSync)(npm.path, ["install", "-g", "@anthropic-ai/claude-code"], {
|
|
51682
|
+
env: withAugmentedPathEnv(),
|
|
51496
51683
|
stdio: "inherit",
|
|
51497
51684
|
timeout: getInstallTimeoutMs()
|
|
51498
51685
|
});
|
|
@@ -51524,7 +51711,10 @@ function installClaudeCli() {
|
|
|
51524
51711
|
logger24.error("claude not found after successful npm install -g", {
|
|
51525
51712
|
npmGlobalBin: npmBin ?? "unknown",
|
|
51526
51713
|
pathDirectories: envPath.split(process.platform === "win32" ? ";" : ":").slice(0, 10),
|
|
51527
|
-
npmPrefix: (0,
|
|
51714
|
+
npmPrefix: (0, import_node_child_process3.execFileSync)(npm.path, ["prefix", "-g"], {
|
|
51715
|
+
env: withAugmentedPathEnv(),
|
|
51716
|
+
timeout: 5e3
|
|
51717
|
+
}).toString().trim() || "unknown"
|
|
51528
51718
|
});
|
|
51529
51719
|
return void 0;
|
|
51530
51720
|
}
|
|
@@ -51554,21 +51744,21 @@ async function ensureClaudeCli() {
|
|
|
51554
51744
|
// src/forkAgentFiles.ts
|
|
51555
51745
|
init_cjs_shims();
|
|
51556
51746
|
var fs11 = __toESM(require("fs/promises"), 1);
|
|
51557
|
-
var
|
|
51747
|
+
var path18 = __toESM(require("path"), 1);
|
|
51558
51748
|
|
|
51559
51749
|
// src/sessionSlug.ts
|
|
51560
51750
|
init_cjs_shims();
|
|
51561
|
-
var
|
|
51562
|
-
var
|
|
51563
|
-
var CLAUDE_PROJECTS_DIR =
|
|
51751
|
+
var import_node_os10 = __toESM(require("os"), 1);
|
|
51752
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
51753
|
+
var CLAUDE_PROJECTS_DIR = import_node_path18.default.join(import_node_os10.default.homedir(), ".claude", "projects");
|
|
51564
51754
|
function cwdToSlug(cwd) {
|
|
51565
51755
|
return cwd.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
51566
51756
|
}
|
|
51567
51757
|
function sessionDirForCwd(cwd) {
|
|
51568
|
-
return
|
|
51758
|
+
return import_node_path18.default.join(CLAUDE_PROJECTS_DIR, cwdToSlug(cwd));
|
|
51569
51759
|
}
|
|
51570
51760
|
function sessionFilePath(cwd, sessionId) {
|
|
51571
|
-
return
|
|
51761
|
+
return import_node_path18.default.join(sessionDirForCwd(cwd), `${sessionId}.jsonl`);
|
|
51572
51762
|
}
|
|
51573
51763
|
|
|
51574
51764
|
// src/forkAgentFiles.ts
|
|
@@ -51600,9 +51790,9 @@ async function forkAgentFiles(sourceAgentId, newAgentId, sourceWorkdir, newWorkd
|
|
|
51600
51790
|
logger25.error("Workdir copy failed", { error: e7 });
|
|
51601
51791
|
throw e7;
|
|
51602
51792
|
}
|
|
51603
|
-
const srcNotebook =
|
|
51604
|
-
const dstNotebookDir =
|
|
51605
|
-
const dstNotebook =
|
|
51793
|
+
const srcNotebook = path18.join(dataDir, "agent-memory", sourceAgentId, "notebook.md");
|
|
51794
|
+
const dstNotebookDir = path18.join(dataDir, "agent-memory", newAgentId);
|
|
51795
|
+
const dstNotebook = path18.join(dstNotebookDir, "notebook.md");
|
|
51606
51796
|
try {
|
|
51607
51797
|
const nbStat = await fs11.stat(srcNotebook).catch(() => null);
|
|
51608
51798
|
if (nbStat?.isFile()) {
|
|
@@ -51629,7 +51819,7 @@ async function forkAgentFiles(sourceAgentId, newAgentId, sourceWorkdir, newWorkd
|
|
|
51629
51819
|
if (srcStat?.isFile()) {
|
|
51630
51820
|
const dstDir = sessionDirForCwd(newWorkdir);
|
|
51631
51821
|
await fs11.mkdir(dstDir, { recursive: true });
|
|
51632
|
-
const dstPath =
|
|
51822
|
+
const dstPath = path18.join(dstDir, `${sourceSessionId}.jsonl`);
|
|
51633
51823
|
await fs11.copyFile(srcPath, dstPath);
|
|
51634
51824
|
sessionStore.set(newAgentId, { kind: "single" }, sourceSessionId);
|
|
51635
51825
|
sessionCopied = true;
|
|
@@ -51677,12 +51867,12 @@ async function forkAgentFiles(sourceAgentId, newAgentId, sourceWorkdir, newWorkd
|
|
|
51677
51867
|
// src/modelQuerier.ts
|
|
51678
51868
|
init_cjs_shims();
|
|
51679
51869
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
51680
|
-
var
|
|
51681
|
-
var
|
|
51870
|
+
var import_node_os11 = __toESM(require("os"), 1);
|
|
51871
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
51682
51872
|
var logger26 = createModuleLogger("bridge.modelQuerier");
|
|
51683
51873
|
async function listModels(queryFn, opts = {}) {
|
|
51684
51874
|
const t0 = Date.now();
|
|
51685
|
-
const cwd = opts.cwd ??
|
|
51875
|
+
const cwd = opts.cwd ?? import_node_path19.default.join(import_node_os11.default.homedir(), ".ahchat", "workspaces", "_list_models");
|
|
51686
51876
|
await import_promises11.default.mkdir(cwd, { recursive: true });
|
|
51687
51877
|
const fn = queryFn ?? QA$;
|
|
51688
51878
|
const ic2 = new InputController();
|
|
@@ -51745,8 +51935,8 @@ async function listModels(queryFn, opts = {}) {
|
|
|
51745
51935
|
// src/promptOptimizer.ts
|
|
51746
51936
|
init_cjs_shims();
|
|
51747
51937
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
51748
|
-
var
|
|
51749
|
-
var
|
|
51938
|
+
var import_node_os12 = __toESM(require("os"), 1);
|
|
51939
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
51750
51940
|
var logger27 = createModuleLogger("bridge.promptOptimizer");
|
|
51751
51941
|
var OPTIMIZER_SYSTEM_PROMPT = `You are an expert prompt editor for AHChat Agent creation.
|
|
51752
51942
|
|
|
@@ -51789,7 +51979,7 @@ async function optimizePrompt(queryFn, opts) {
|
|
|
51789
51979
|
const prompt = opts.systemPrompt.trim();
|
|
51790
51980
|
if (!prompt) throw new Error("systemPrompt is required");
|
|
51791
51981
|
const t0 = Date.now();
|
|
51792
|
-
const cwd = opts.cwd ??
|
|
51982
|
+
const cwd = opts.cwd ?? import_node_path20.default.join(import_node_os12.default.homedir(), ".ahchat", "workspaces", "_prompt_optimizer");
|
|
51793
51983
|
await import_promises12.default.mkdir(cwd, { recursive: true });
|
|
51794
51984
|
const fn = queryFn ?? QA$;
|
|
51795
51985
|
const ic2 = new InputController();
|
|
@@ -51877,7 +52067,7 @@ function isRunningAsRoot2() {
|
|
|
51877
52067
|
}
|
|
51878
52068
|
}
|
|
51879
52069
|
async function syncClaudeCredentialsToNodeAccessibleDir(agentConfigDir) {
|
|
51880
|
-
const rootClaudeDir =
|
|
52070
|
+
const rootClaudeDir = import_node_path21.default.join(process.env.HOME ?? "/root", ".claude");
|
|
51881
52071
|
const fs16 = await import("fs/promises");
|
|
51882
52072
|
try {
|
|
51883
52073
|
await fs16.access(rootClaudeDir);
|
|
@@ -51887,8 +52077,8 @@ async function syncClaudeCredentialsToNodeAccessibleDir(agentConfigDir) {
|
|
|
51887
52077
|
}
|
|
51888
52078
|
const filesToSync = [".credentials.json", "settings.json", ".credentials.backup.json"];
|
|
51889
52079
|
for (const file2 of filesToSync) {
|
|
51890
|
-
const src =
|
|
51891
|
-
const dest =
|
|
52080
|
+
const src = import_node_path21.default.join(rootClaudeDir, file2);
|
|
52081
|
+
const dest = import_node_path21.default.join(agentConfigDir, file2);
|
|
51892
52082
|
try {
|
|
51893
52083
|
await fs16.copyFile(src, dest);
|
|
51894
52084
|
logger28.info("Synced credential file", { file: file2, from: src, to: dest });
|
|
@@ -51911,7 +52101,7 @@ async function chownRecursive(dirPath, uid, gid) {
|
|
|
51911
52101
|
return;
|
|
51912
52102
|
}
|
|
51913
52103
|
for (const entry of entries) {
|
|
51914
|
-
const fullPath =
|
|
52104
|
+
const fullPath = import_node_path21.default.join(dirPath, entry.name);
|
|
51915
52105
|
if (entry.isDirectory()) {
|
|
51916
52106
|
await chownRecursive(fullPath, uid, gid);
|
|
51917
52107
|
} else {
|
|
@@ -51926,7 +52116,7 @@ async function chownRecursive(dirPath, uid, gid) {
|
|
|
51926
52116
|
async function startBridge(config2) {
|
|
51927
52117
|
ensureDir(config2.dataDir);
|
|
51928
52118
|
ensureDir(config2.agentConfigDir);
|
|
51929
|
-
const workspacesDir =
|
|
52119
|
+
const workspacesDir = import_node_path21.default.join(config2.dataDir, "workspaces");
|
|
51930
52120
|
ensureDir(workspacesDir);
|
|
51931
52121
|
process.env.CLAUDE_CONFIG_DIR = config2.agentConfigDir;
|
|
51932
52122
|
installBridgeFetchAuth(config2.serverApiUrl, config2.bridgeToken);
|
|
@@ -51955,7 +52145,7 @@ Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\
|
|
|
51955
52145
|
`);
|
|
51956
52146
|
wsMetrics.start(5e3);
|
|
51957
52147
|
const sessionStore = new SessionStore(config2.dataDir);
|
|
51958
|
-
const memoryRoot =
|
|
52148
|
+
const memoryRoot = import_node_path21.default.join(config2.dataDir, "agent-memory");
|
|
51959
52149
|
const memoryStore = new AgentMemoryStore(memoryRoot);
|
|
51960
52150
|
logger28.info("Agent memory store initialized", { rootDir: memoryRoot });
|
|
51961
52151
|
const smithNotebook = memoryStore.read(SMITH_AGENT_ID);
|
|
@@ -52384,21 +52574,58 @@ function compactEnv(env2) {
|
|
|
52384
52574
|
|
|
52385
52575
|
// src/protocol.ts
|
|
52386
52576
|
init_cjs_shims();
|
|
52387
|
-
var
|
|
52388
|
-
var
|
|
52389
|
-
var
|
|
52390
|
-
var
|
|
52577
|
+
var import_node_child_process4 = require("child_process");
|
|
52578
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
52579
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
52580
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
52391
52581
|
var logger29 = createModuleLogger("bridge.protocol");
|
|
52582
|
+
function shellSingleQuote(value) {
|
|
52583
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
52584
|
+
}
|
|
52585
|
+
function psSingleQuote(value) {
|
|
52586
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
52587
|
+
}
|
|
52588
|
+
function desktopExecQuote(value) {
|
|
52589
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
52590
|
+
}
|
|
52591
|
+
function getStableCliPath() {
|
|
52592
|
+
return import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge", "cli.cjs");
|
|
52593
|
+
}
|
|
52392
52594
|
function getStableExePath() {
|
|
52393
|
-
const bridgeDir =
|
|
52394
|
-
|
|
52395
|
-
const stablePath =
|
|
52396
|
-
|
|
52397
|
-
if (process.platform !== "win32")
|
|
52595
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52596
|
+
import_node_fs10.default.mkdirSync(bridgeDir, { recursive: true });
|
|
52597
|
+
const stablePath = getStableCliPath();
|
|
52598
|
+
import_node_fs10.default.copyFileSync(__filename, stablePath);
|
|
52599
|
+
if (process.platform !== "win32") import_node_fs10.default.chmodSync(stablePath, 493);
|
|
52398
52600
|
return stablePath;
|
|
52399
52601
|
}
|
|
52602
|
+
function writePosixLauncher(bridgeDir, stableExePath) {
|
|
52603
|
+
const launchScriptPath = import_node_path22.default.join(bridgeDir, "launch-bridge.sh");
|
|
52604
|
+
const augmentedPath = buildAugmentedPath();
|
|
52605
|
+
import_node_fs10.default.writeFileSync(
|
|
52606
|
+
launchScriptPath,
|
|
52607
|
+
[
|
|
52608
|
+
"#!/bin/bash",
|
|
52609
|
+
"set -e",
|
|
52610
|
+
`export PATH=${shellSingleQuote(augmentedPath)}:"\${PATH:-}"`,
|
|
52611
|
+
`SAVED_NODE=${shellSingleQuote(process.execPath)}`,
|
|
52612
|
+
`BRIDGE_CLI=${shellSingleQuote(stableExePath)}`,
|
|
52613
|
+
'NODE_BIN=""',
|
|
52614
|
+
'if [ -x "$SAVED_NODE" ]; then NODE_BIN="$SAVED_NODE"; fi',
|
|
52615
|
+
'if [ -z "$NODE_BIN" ]; then NODE_BIN="$(command -v node || true)"; fi',
|
|
52616
|
+
'if [ -z "$NODE_BIN" ]; then',
|
|
52617
|
+
` echo "Node.js ${MIN_NODE_MAJOR}+ is required to launch AHChat Bridge. Install Node, then rerun: npx -y @fangyb/ahchat-bridge install" >&2`,
|
|
52618
|
+
" exit 1",
|
|
52619
|
+
"fi",
|
|
52620
|
+
'exec "$NODE_BIN" "$BRIDGE_CLI" launch --url "$1"',
|
|
52621
|
+
""
|
|
52622
|
+
].join("\n")
|
|
52623
|
+
);
|
|
52624
|
+
import_node_fs10.default.chmodSync(launchScriptPath, 493);
|
|
52625
|
+
return launchScriptPath;
|
|
52626
|
+
}
|
|
52400
52627
|
function registerProtocolHandler() {
|
|
52401
|
-
const platform =
|
|
52628
|
+
const platform = import_node_os13.default.platform();
|
|
52402
52629
|
if (platform === "win32") {
|
|
52403
52630
|
registerWindows();
|
|
52404
52631
|
} else if (platform === "darwin") {
|
|
@@ -52411,22 +52638,42 @@ function registerProtocolHandler() {
|
|
|
52411
52638
|
function registerWindows() {
|
|
52412
52639
|
const nodeExe = process.execPath;
|
|
52413
52640
|
const stableExePath = getStableExePath();
|
|
52414
|
-
const bridgeDir =
|
|
52415
|
-
const
|
|
52416
|
-
|
|
52641
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52642
|
+
const augmentedPath = buildAugmentedPath();
|
|
52643
|
+
const psLauncherPath = import_node_path22.default.join(bridgeDir, "launch-bridge.ps1");
|
|
52644
|
+
import_node_fs10.default.writeFileSync(
|
|
52417
52645
|
psLauncherPath,
|
|
52418
52646
|
[
|
|
52419
52647
|
`param([string]$url)`,
|
|
52420
|
-
|
|
52648
|
+
`$env:PATH = ${psSingleQuote(augmentedPath)} + [System.IO.Path]::PathSeparator + $env:PATH`,
|
|
52649
|
+
`$candidates = @(`,
|
|
52650
|
+
` ${psSingleQuote(nodeExe)},`,
|
|
52651
|
+
` "$env:NVM_SYMLINK\\node.exe",`,
|
|
52652
|
+
` "$env:ProgramFiles\\nodejs\\node.exe",`,
|
|
52653
|
+
` "$env:LOCALAPPDATA\\Programs\\nodejs\\node.exe"`,
|
|
52654
|
+
`)`,
|
|
52655
|
+
`$node = $null`,
|
|
52656
|
+
`foreach ($candidate in $candidates) {`,
|
|
52657
|
+
` if ($candidate -and (Test-Path $candidate)) { $node = $candidate; break }`,
|
|
52658
|
+
`}`,
|
|
52659
|
+
`if (-not $node) {`,
|
|
52660
|
+
` $cmd = Get-Command node -ErrorAction SilentlyContinue`,
|
|
52661
|
+
` if ($cmd) { $node = $cmd.Source }`,
|
|
52662
|
+
`}`,
|
|
52663
|
+
`if (-not $node) {`,
|
|
52664
|
+
` Write-Error 'Node.js ${MIN_NODE_MAJOR}+ is required to launch AHChat Bridge. Install Node, then rerun: npx -y @fangyb/ahchat-bridge install'`,
|
|
52665
|
+
` exit 1`,
|
|
52666
|
+
`}`,
|
|
52667
|
+
`& $node ${psSingleQuote(stableExePath)} launch --url $url`
|
|
52421
52668
|
].join("\r\n")
|
|
52422
52669
|
);
|
|
52423
52670
|
const handlerValue = `powershell -ExecutionPolicy Bypass -File "${psLauncherPath}" -url "%1"`;
|
|
52424
|
-
const psRegisterPath =
|
|
52425
|
-
|
|
52671
|
+
const psRegisterPath = import_node_path22.default.join(bridgeDir, "register-protocol.ps1");
|
|
52672
|
+
import_node_fs10.default.writeFileSync(
|
|
52426
52673
|
psRegisterPath,
|
|
52427
52674
|
[
|
|
52428
|
-
`$handler =
|
|
52429
|
-
`$icon =
|
|
52675
|
+
`$handler = ${psSingleQuote(handlerValue)}`,
|
|
52676
|
+
`$icon = ${psSingleQuote(nodeExe)}`,
|
|
52430
52677
|
`New-Item -Path 'HKCU:\\Software\\Classes\\ahchat' -Force | Out-Null`,
|
|
52431
52678
|
`Set-ItemProperty -Path 'HKCU:\\Software\\Classes\\ahchat' -Name '(Default)' -Value 'URL:ahchat' -Force`,
|
|
52432
52679
|
`New-ItemProperty -Path 'HKCU:\\Software\\Classes\\ahchat' -Name 'URL Protocol' -Value '' -PropertyType String -Force | Out-Null`,
|
|
@@ -52437,7 +52684,7 @@ function registerWindows() {
|
|
|
52437
52684
|
].join("\r\n")
|
|
52438
52685
|
);
|
|
52439
52686
|
try {
|
|
52440
|
-
(0,
|
|
52687
|
+
(0, import_node_child_process4.execSync)(`powershell -ExecutionPolicy Bypass -File "${psRegisterPath}"`, { stdio: "pipe" });
|
|
52441
52688
|
} catch (e7) {
|
|
52442
52689
|
logger29.error("Failed to register Windows protocol handler", { error: e7 });
|
|
52443
52690
|
throw new Error("Failed to register Windows protocol handler");
|
|
@@ -52445,18 +52692,10 @@ function registerWindows() {
|
|
|
52445
52692
|
logger29.info("Windows protocol handler registered", { psLauncherPath });
|
|
52446
52693
|
}
|
|
52447
52694
|
function registerMacOS() {
|
|
52448
|
-
const appDir =
|
|
52449
|
-
const nodeExe = process.execPath;
|
|
52695
|
+
const appDir = import_node_path22.default.join(import_node_os13.default.homedir(), "Applications", "AHChatBridge.app");
|
|
52450
52696
|
const stableExePath = getStableExePath();
|
|
52451
|
-
const bridgeDir =
|
|
52452
|
-
const launchScriptPath =
|
|
52453
|
-
import_node_fs9.default.writeFileSync(
|
|
52454
|
-
launchScriptPath,
|
|
52455
|
-
`#!/bin/bash
|
|
52456
|
-
exec ${JSON.stringify(nodeExe)} ${JSON.stringify(stableExePath)} launch --url "$1"
|
|
52457
|
-
`
|
|
52458
|
-
);
|
|
52459
|
-
import_node_fs9.default.chmodSync(launchScriptPath, 493);
|
|
52697
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52698
|
+
const launchScriptPath = writePosixLauncher(bridgeDir, stableExePath);
|
|
52460
52699
|
const escapedScriptPath = launchScriptPath.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
52461
52700
|
const appleScript = [
|
|
52462
52701
|
`on open location thisURL`,
|
|
@@ -52464,29 +52703,29 @@ exec ${JSON.stringify(nodeExe)} ${JSON.stringify(stableExePath)} launch --url "$
|
|
|
52464
52703
|
` do shell script "/bin/bash " & (quoted form of launchScript) & " " & (quoted form of thisURL) & " >/tmp/ahchat-bridge.log 2>&1 &"`,
|
|
52465
52704
|
`end open location`
|
|
52466
52705
|
].join("\n");
|
|
52467
|
-
const tmpScript =
|
|
52468
|
-
|
|
52706
|
+
const tmpScript = import_node_path22.default.join(import_node_os13.default.tmpdir(), "AHChatBridge.applescript");
|
|
52707
|
+
import_node_fs10.default.writeFileSync(tmpScript, appleScript);
|
|
52469
52708
|
try {
|
|
52470
|
-
|
|
52709
|
+
import_node_fs10.default.rmSync(appDir, { recursive: true, force: true });
|
|
52471
52710
|
} catch {
|
|
52472
52711
|
}
|
|
52473
52712
|
try {
|
|
52474
|
-
(0,
|
|
52713
|
+
(0, import_node_child_process4.execSync)(`osacompile -o ${JSON.stringify(appDir)} ${JSON.stringify(tmpScript)}`, { stdio: "pipe" });
|
|
52475
52714
|
} finally {
|
|
52476
52715
|
try {
|
|
52477
|
-
|
|
52716
|
+
import_node_fs10.default.unlinkSync(tmpScript);
|
|
52478
52717
|
} catch {
|
|
52479
52718
|
}
|
|
52480
52719
|
}
|
|
52481
|
-
const plistPath =
|
|
52720
|
+
const plistPath = import_node_path22.default.join(appDir, "Contents", "Info.plist");
|
|
52482
52721
|
const urlTypes = JSON.stringify([{ CFBundleURLName: "AHChat Bridge", CFBundleURLSchemes: ["ahchat"] }]);
|
|
52483
|
-
(0,
|
|
52722
|
+
(0, import_node_child_process4.execSync)(
|
|
52484
52723
|
`/usr/bin/plutil -insert CFBundleURLTypes -json ${JSON.stringify(urlTypes)} ${JSON.stringify(plistPath)}`,
|
|
52485
52724
|
{ stdio: "pipe" }
|
|
52486
52725
|
);
|
|
52487
52726
|
const lsregister = "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister";
|
|
52488
52727
|
try {
|
|
52489
|
-
(0,
|
|
52728
|
+
(0, import_node_child_process4.execSync)(`${lsregister} -f ${JSON.stringify(appDir)}`, { stdio: "pipe" });
|
|
52490
52729
|
} catch (e7) {
|
|
52491
52730
|
logger29.warn("lsregister failed; URL scheme registration may be delayed", { error: e7 });
|
|
52492
52731
|
}
|
|
@@ -52494,36 +52733,38 @@ exec ${JSON.stringify(nodeExe)} ${JSON.stringify(stableExePath)} launch --url "$
|
|
|
52494
52733
|
}
|
|
52495
52734
|
function registerLinux() {
|
|
52496
52735
|
const stableExePath = getStableExePath();
|
|
52736
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52737
|
+
const launchScriptPath = writePosixLauncher(bridgeDir, stableExePath);
|
|
52497
52738
|
const desktopFile = [
|
|
52498
52739
|
`[Desktop Entry]`,
|
|
52499
52740
|
`Name=AHChat Bridge`,
|
|
52500
|
-
`Exec=${
|
|
52741
|
+
`Exec=${desktopExecQuote(launchScriptPath)} %u`,
|
|
52501
52742
|
`Type=Application`,
|
|
52502
52743
|
`NoDisplay=true`,
|
|
52503
52744
|
`MimeType=x-scheme-handler/ahchat;`
|
|
52504
52745
|
].join("\n");
|
|
52505
|
-
const desktopPath =
|
|
52506
|
-
|
|
52507
|
-
|
|
52746
|
+
const desktopPath = import_node_path22.default.join(import_node_os13.default.homedir(), ".local", "share", "applications", "ahchat-bridge.desktop");
|
|
52747
|
+
import_node_fs10.default.mkdirSync(import_node_path22.default.dirname(desktopPath), { recursive: true });
|
|
52748
|
+
import_node_fs10.default.writeFileSync(desktopPath, desktopFile);
|
|
52508
52749
|
try {
|
|
52509
|
-
(0,
|
|
52750
|
+
(0, import_node_child_process4.execSync)("update-desktop-database ~/.local/share/applications/", { stdio: "pipe" });
|
|
52510
52751
|
} catch (e7) {
|
|
52511
52752
|
logger29.warn("update-desktop-database not available; run it manually if needed", { error: e7 });
|
|
52512
52753
|
}
|
|
52513
52754
|
logger29.info("Linux protocol handler registered", { desktopPath });
|
|
52514
52755
|
}
|
|
52515
52756
|
function unregisterProtocolHandler() {
|
|
52516
|
-
const platform =
|
|
52757
|
+
const platform = import_node_os13.default.platform();
|
|
52517
52758
|
if (platform === "win32") {
|
|
52518
52759
|
try {
|
|
52519
|
-
(0,
|
|
52760
|
+
(0, import_node_child_process4.execSync)(
|
|
52520
52761
|
`powershell -ExecutionPolicy Bypass -Command "Remove-Item -Path 'HKCU:\\Software\\Classes\\ahchat' -Recurse -Force -ErrorAction SilentlyContinue"`,
|
|
52521
52762
|
{ stdio: "pipe" }
|
|
52522
52763
|
);
|
|
52523
|
-
const bridgeDir =
|
|
52764
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52524
52765
|
for (const f7 of ["launch-bridge.ps1", "register-protocol.ps1"]) {
|
|
52525
52766
|
try {
|
|
52526
|
-
|
|
52767
|
+
import_node_fs10.default.unlinkSync(import_node_path22.default.join(bridgeDir, f7));
|
|
52527
52768
|
} catch {
|
|
52528
52769
|
}
|
|
52529
52770
|
}
|
|
@@ -52532,17 +52773,17 @@ function unregisterProtocolHandler() {
|
|
|
52532
52773
|
logger29.warn("Failed to unregister Windows protocol handler", { error: e7 });
|
|
52533
52774
|
}
|
|
52534
52775
|
} else if (platform === "darwin") {
|
|
52535
|
-
const appDir =
|
|
52776
|
+
const appDir = import_node_path22.default.join(import_node_os13.default.homedir(), "Applications", "AHChatBridge.app");
|
|
52536
52777
|
try {
|
|
52537
|
-
|
|
52778
|
+
import_node_fs10.default.rmSync(appDir, { recursive: true, force: true });
|
|
52538
52779
|
logger29.info("macOS protocol handler unregistered");
|
|
52539
52780
|
} catch (e7) {
|
|
52540
52781
|
logger29.warn("Failed to unregister macOS protocol handler", { error: e7 });
|
|
52541
52782
|
}
|
|
52542
52783
|
} else {
|
|
52543
|
-
const desktopPath =
|
|
52784
|
+
const desktopPath = import_node_path22.default.join(import_node_os13.default.homedir(), ".local", "share", "applications", "ahchat-bridge.desktop");
|
|
52544
52785
|
try {
|
|
52545
|
-
|
|
52786
|
+
import_node_fs10.default.unlinkSync(desktopPath);
|
|
52546
52787
|
logger29.info("Linux protocol handler unregistered");
|
|
52547
52788
|
} catch (e7) {
|
|
52548
52789
|
logger29.warn("Failed to unregister Linux protocol handler", { error: e7 });
|
|
@@ -52550,20 +52791,21 @@ function unregisterProtocolHandler() {
|
|
|
52550
52791
|
}
|
|
52551
52792
|
}
|
|
52552
52793
|
function isProtocolRegistered() {
|
|
52553
|
-
const platform =
|
|
52794
|
+
const platform = import_node_os13.default.platform();
|
|
52795
|
+
const stableCliExists = import_node_fs10.default.existsSync(getStableCliPath());
|
|
52554
52796
|
if (platform === "win32") {
|
|
52555
52797
|
try {
|
|
52556
|
-
(0,
|
|
52557
|
-
return
|
|
52798
|
+
(0, import_node_child_process4.execSync)('REG QUERY "HKCU\\Software\\Classes\\ahchat" /ve', { stdio: "pipe" });
|
|
52799
|
+
return stableCliExists;
|
|
52558
52800
|
} catch {
|
|
52559
52801
|
return false;
|
|
52560
52802
|
}
|
|
52561
52803
|
} else if (platform === "darwin") {
|
|
52562
|
-
const appDir =
|
|
52563
|
-
return
|
|
52804
|
+
const appDir = import_node_path22.default.join(import_node_os13.default.homedir(), "Applications", "AHChatBridge.app");
|
|
52805
|
+
return stableCliExists && import_node_fs10.default.existsSync(import_node_path22.default.join(appDir, "Contents", "Info.plist"));
|
|
52564
52806
|
} else {
|
|
52565
|
-
const desktopPath =
|
|
52566
|
-
return
|
|
52807
|
+
const desktopPath = import_node_path22.default.join(import_node_os13.default.homedir(), ".local", "share", "applications", "ahchat-bridge.desktop");
|
|
52808
|
+
return stableCliExists && import_node_fs10.default.existsSync(desktopPath);
|
|
52567
52809
|
}
|
|
52568
52810
|
}
|
|
52569
52811
|
|
|
@@ -52571,14 +52813,14 @@ function isProtocolRegistered() {
|
|
|
52571
52813
|
var logger30 = createModuleLogger("bridge");
|
|
52572
52814
|
function readCliVersion() {
|
|
52573
52815
|
const candidates = [
|
|
52574
|
-
|
|
52575
|
-
|
|
52576
|
-
|
|
52816
|
+
import_node_path23.default.resolve(__dirname, "../package.json"),
|
|
52817
|
+
import_node_path23.default.resolve(__dirname, "../../package.json"),
|
|
52818
|
+
import_node_path23.default.resolve(process.cwd(), "packages/bridge/package.json")
|
|
52577
52819
|
];
|
|
52578
52820
|
for (const candidate of candidates) {
|
|
52579
|
-
if (!
|
|
52821
|
+
if (!import_node_fs11.default.existsSync(candidate)) continue;
|
|
52580
52822
|
try {
|
|
52581
|
-
const parsed = JSON.parse(
|
|
52823
|
+
const parsed = JSON.parse(import_node_fs11.default.readFileSync(candidate, "utf8"));
|
|
52582
52824
|
if (parsed && typeof parsed === "object" && "version" in parsed && typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
52583
52825
|
return parsed.version;
|
|
52584
52826
|
}
|
|
@@ -52586,26 +52828,7 @@ function readCliVersion() {
|
|
|
52586
52828
|
logger30.warn("Unable to read CLI package version candidate", { error: e7, candidate });
|
|
52587
52829
|
}
|
|
52588
52830
|
}
|
|
52589
|
-
return "0.1.
|
|
52590
|
-
}
|
|
52591
|
-
function resolveDataDir(dataDir) {
|
|
52592
|
-
const userHome = process.env.USERPROFILE || import_node_os13.default.homedir();
|
|
52593
|
-
if (/^~[/\\]/.test(dataDir)) {
|
|
52594
|
-
return import_node_path22.default.join(import_node_os13.default.homedir(), dataDir.slice(2));
|
|
52595
|
-
}
|
|
52596
|
-
if (dataDir === "$env:USERPROFILE") {
|
|
52597
|
-
return userHome;
|
|
52598
|
-
}
|
|
52599
|
-
if (dataDir.startsWith("$env:USERPROFILE\\") || dataDir.startsWith("$env:USERPROFILE/")) {
|
|
52600
|
-
return import_node_path22.default.join(userHome, dataDir.slice("$env:USERPROFILE".length + 1));
|
|
52601
|
-
}
|
|
52602
|
-
if (dataDir === "%USERPROFILE%") {
|
|
52603
|
-
return userHome;
|
|
52604
|
-
}
|
|
52605
|
-
if (dataDir.startsWith("%USERPROFILE%\\") || dataDir.startsWith("%USERPROFILE%/")) {
|
|
52606
|
-
return import_node_path22.default.join(userHome, dataDir.slice("%USERPROFILE%".length + 1));
|
|
52607
|
-
}
|
|
52608
|
-
return dataDir;
|
|
52831
|
+
return "0.1.23";
|
|
52609
52832
|
}
|
|
52610
52833
|
function parseAhchatUrl(url2) {
|
|
52611
52834
|
try {
|
|
@@ -52620,29 +52843,107 @@ function parseAhchatUrl(url2) {
|
|
|
52620
52843
|
const token = decodeURIComponent(rest.slice(lastTilde + 1));
|
|
52621
52844
|
if (!serverUrl || !token) return null;
|
|
52622
52845
|
return { serverUrl, token };
|
|
52623
|
-
} catch {
|
|
52846
|
+
} catch (e7) {
|
|
52847
|
+
logger30.warn("Unable to parse ahchat launch URL", { error: e7 });
|
|
52624
52848
|
return null;
|
|
52625
52849
|
}
|
|
52626
52850
|
}
|
|
52851
|
+
function assertSupportedNode() {
|
|
52852
|
+
const status = getNodeRuntimeStatus();
|
|
52853
|
+
if (status.supported) return;
|
|
52854
|
+
throw new Error(
|
|
52855
|
+
`Node.js ${MIN_NODE_MAJOR}+ is required to run AHChat Bridge. Current version: ${status.version}`
|
|
52856
|
+
);
|
|
52857
|
+
}
|
|
52627
52858
|
async function run(args) {
|
|
52628
|
-
|
|
52859
|
+
assertSupportedNode();
|
|
52860
|
+
process.env.PATH = buildAugmentedPath();
|
|
52861
|
+
const dataDir = resolveBridgeDataDir(args);
|
|
52629
52862
|
let config2 = loadBridgeConfig(dataDir ? { dataDir } : void 0);
|
|
52630
52863
|
if (args.serverUrl) {
|
|
52631
|
-
const
|
|
52632
|
-
|
|
52633
|
-
config2 = { ...config2, serverUrl: args.serverUrl, serverApiUrl: httpBase };
|
|
52864
|
+
const urls = normalizeBridgeServerUrls(args.serverUrl);
|
|
52865
|
+
config2 = { ...config2, serverUrl: urls.serverUrl, serverApiUrl: urls.serverApiUrl };
|
|
52634
52866
|
}
|
|
52635
52867
|
if (args.token) config2 = { ...config2, bridgeToken: args.token };
|
|
52636
52868
|
if (args.logLevel) config2 = { ...config2, logLevel: args.logLevel };
|
|
52637
52869
|
await startBridge(config2);
|
|
52638
52870
|
}
|
|
52871
|
+
function buildDoctorReport(args) {
|
|
52872
|
+
process.env.PATH = buildAugmentedPath();
|
|
52873
|
+
const node = getNodeRuntimeStatus();
|
|
52874
|
+
let server = null;
|
|
52875
|
+
if (args.serverUrl) {
|
|
52876
|
+
try {
|
|
52877
|
+
server = { ok: true, ...normalizeBridgeServerUrls(args.serverUrl) };
|
|
52878
|
+
} catch (e7) {
|
|
52879
|
+
server = {
|
|
52880
|
+
ok: false,
|
|
52881
|
+
error: e7 instanceof Error ? e7.message : String(e7)
|
|
52882
|
+
};
|
|
52883
|
+
}
|
|
52884
|
+
}
|
|
52885
|
+
const claude = resolveCommand(["claude", "anthropic-cli"]);
|
|
52886
|
+
return {
|
|
52887
|
+
node,
|
|
52888
|
+
npm: probeCommand("npm"),
|
|
52889
|
+
npx: probeCommand("npx"),
|
|
52890
|
+
claude: claude ? { ok: true, name: claude.name, path: claude.path } : { ok: false, name: "claude", message: "claude was not found on PATH" },
|
|
52891
|
+
dataDir: resolveBridgeDataDir(args) ?? resolveUserPath("~/.ahchat"),
|
|
52892
|
+
server,
|
|
52893
|
+
tokenProvided: Boolean(args.token),
|
|
52894
|
+
pathPreview: (process.env.PATH ?? "").split(import_node_path23.default.delimiter).slice(0, 12)
|
|
52895
|
+
};
|
|
52896
|
+
}
|
|
52897
|
+
function writeDoctorText(report) {
|
|
52898
|
+
const node = report.node;
|
|
52899
|
+
const npm = report.npm;
|
|
52900
|
+
const npx = report.npx;
|
|
52901
|
+
const claude = report.claude;
|
|
52902
|
+
const server = report.server;
|
|
52903
|
+
const lines = [
|
|
52904
|
+
"AHChat Bridge doctor",
|
|
52905
|
+
`- Node: ${node.supported ? "ok" : "error"} (${node.version}, requires >=${MIN_NODE_MAJOR})`,
|
|
52906
|
+
`- npm: ${npm.ok ? `ok (${npm.version ?? npm.path})` : `missing (${npm.message ?? "not found"})`}`,
|
|
52907
|
+
`- npx: ${npx.ok ? `ok (${npx.version ?? npx.path})` : `missing (${npx.message ?? "not found"})`}`,
|
|
52908
|
+
`- Claude CLI: ${claude.ok ? `ok (${claude.path})` : `missing (${claude.message ?? "not found"})`}`,
|
|
52909
|
+
`- Data dir: ${String(report.dataDir)}`,
|
|
52910
|
+
`- Token: ${report.tokenProvided ? "provided" : "not provided"}`
|
|
52911
|
+
];
|
|
52912
|
+
if (server) {
|
|
52913
|
+
lines.push(
|
|
52914
|
+
server.ok ? `- Server: ok (${server.serverUrl}, api ${server.serverApiUrl})` : `- Server: error (${server.error ?? "invalid URL"})`
|
|
52915
|
+
);
|
|
52916
|
+
}
|
|
52917
|
+
if (!node.supported) {
|
|
52918
|
+
lines.push(`
|
|
52919
|
+
Install Node.js ${MIN_NODE_MAJOR}+ first, then rerun the bridge command.`);
|
|
52920
|
+
} else if (!npm.ok || !npx.ok) {
|
|
52921
|
+
lines.push("\nNode is installed, but npm/npx is not available on PATH. Reinstall Node.js or fix PATH.");
|
|
52922
|
+
} else if (!claude.ok) {
|
|
52923
|
+
lines.push("\nClaude Code CLI is missing. The bridge can try to install it on first run with npm.");
|
|
52924
|
+
}
|
|
52925
|
+
process.stdout.write(`${lines.join("\n")}
|
|
52926
|
+
`);
|
|
52927
|
+
}
|
|
52928
|
+
function doctor(args) {
|
|
52929
|
+
const report = buildDoctorReport(args);
|
|
52930
|
+
if (args.json) {
|
|
52931
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}
|
|
52932
|
+
`);
|
|
52933
|
+
return;
|
|
52934
|
+
}
|
|
52935
|
+
writeDoctorText(report);
|
|
52936
|
+
}
|
|
52639
52937
|
var cli = dist_default("ahchat-bridge");
|
|
52640
|
-
cli.command("run", "Start the bridge and connect to server").option("--server-url <url>", "WebSocket URL of the AHChat server").option("--token <token>", "Auth token for server registration").option("--data-dir <dir>", "Data directory (default: ~/.ahchat)").option("--log-level <level>", "Log level (default: INFO)").action((args) => {
|
|
52938
|
+
cli.command("run", "Start the bridge and connect to server").option("--server-url <url>", "WebSocket URL of the AHChat server").option("--token <token>", "Auth token for server registration").option("--user <slug>", "User data-dir slug; derives ~/.ahchat/users/<slug>").option("--data-dir <dir>", "Data directory (default: ~/.ahchat)").option("--log-level <level>", "Log level (default: INFO)").action((args) => {
|
|
52641
52939
|
void run(args).catch((e7) => {
|
|
52642
52940
|
logger30.error("Bridge failed to start", { error: e7 });
|
|
52643
52941
|
process.exit(1);
|
|
52644
52942
|
});
|
|
52645
52943
|
});
|
|
52944
|
+
cli.command("doctor", "Check Node, npm, Claude CLI, PATH, and bridge launch options").option("--server-url <url>", "WebSocket URL of the AHChat server").option("--token <token>", "Auth token for server registration").option("--user <slug>", "User data-dir slug; derives ~/.ahchat/users/<slug>").option("--data-dir <dir>", "Data directory (default: ~/.ahchat)").option("--json", "Print machine-readable JSON").action((args) => {
|
|
52945
|
+
doctor(args);
|
|
52946
|
+
});
|
|
52646
52947
|
cli.command("launch", "Launch bridge from ahchat:// URL (called by OS)").option("--url <url>", "ahchat:// URL with server and token params").action((args) => {
|
|
52647
52948
|
const parsed = parseAhchatUrl(args.url);
|
|
52648
52949
|
if (!parsed) {
|