@fangyb/ahchat-bridge 0.1.20 → 0.1.22
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 +616 -297
- package/dist/index.js +341 -181
- package/package.json +11 -11
- 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();
|
|
@@ -6928,7 +6927,7 @@ var import_node_crypto3 = require("crypto");
|
|
|
6928
6927
|
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
6929
6928
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
6930
6929
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
6931
|
-
var
|
|
6930
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
6932
6931
|
|
|
6933
6932
|
// ../../node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.2.141_zod@4.4.3/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
|
|
6934
6933
|
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
|
}
|
|
@@ -46979,6 +46978,53 @@ function buildForkHistorySection(messages) {
|
|
|
46979
46978
|
return lines.join("\n");
|
|
46980
46979
|
}
|
|
46981
46980
|
|
|
46981
|
+
// src/workdirMapper.ts
|
|
46982
|
+
init_cjs_shims();
|
|
46983
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
46984
|
+
function extractAhchatWorkspaceParts(requestedPath) {
|
|
46985
|
+
const normalized = requestedPath.trim().replace(/\\/g, "/");
|
|
46986
|
+
const marker = "/.ahchat/users/";
|
|
46987
|
+
const markerIndex = normalized.indexOf(marker);
|
|
46988
|
+
if (markerIndex >= 0) {
|
|
46989
|
+
const afterUsers = normalized.slice(markerIndex + marker.length);
|
|
46990
|
+
const workspaceMarker = "/workspaces/";
|
|
46991
|
+
const workspaceIndex = afterUsers.indexOf(workspaceMarker);
|
|
46992
|
+
if (workspaceIndex >= 0) {
|
|
46993
|
+
const suffix = afterUsers.slice(workspaceIndex + workspaceMarker.length);
|
|
46994
|
+
const parts = suffix.split("/").filter((part) => part && part !== "." && part !== "..");
|
|
46995
|
+
return parts;
|
|
46996
|
+
}
|
|
46997
|
+
const workspacesRootMarker = "/workspaces";
|
|
46998
|
+
const rootIndex = afterUsers.indexOf(workspacesRootMarker);
|
|
46999
|
+
if (rootIndex >= 0 && afterUsers.slice(rootIndex + workspacesRootMarker.length).length === 0) {
|
|
47000
|
+
return [];
|
|
47001
|
+
}
|
|
47002
|
+
}
|
|
47003
|
+
const legacyMarker = "/.ahchat/";
|
|
47004
|
+
const legacyIndex = normalized.indexOf(legacyMarker);
|
|
47005
|
+
if (legacyIndex >= 0) {
|
|
47006
|
+
const firstSegment = normalized.slice(legacyIndex + legacyMarker.length).split("/").find(Boolean);
|
|
47007
|
+
if (firstSegment && /^(Agent|Group)-/.test(firstSegment)) {
|
|
47008
|
+
return [firstSegment];
|
|
47009
|
+
}
|
|
47010
|
+
}
|
|
47011
|
+
return null;
|
|
47012
|
+
}
|
|
47013
|
+
function extractAhchatWorkspaceSuffix(requestedPath) {
|
|
47014
|
+
const parts = extractAhchatWorkspaceParts(requestedPath);
|
|
47015
|
+
if (!parts || parts.length === 0) return null;
|
|
47016
|
+
return import_node_path8.default.join(...parts);
|
|
47017
|
+
}
|
|
47018
|
+
function remapServerWorkspacePath(requestedPath, workspacesDir) {
|
|
47019
|
+
const parts = extractAhchatWorkspaceParts(requestedPath);
|
|
47020
|
+
if (!parts) return { path: requestedPath, remapped: false };
|
|
47021
|
+
const remappedPath = parts.length > 0 ? import_node_path8.default.join(workspacesDir, ...parts) : workspacesDir;
|
|
47022
|
+
return {
|
|
47023
|
+
path: remappedPath,
|
|
47024
|
+
remapped: import_node_path8.default.normalize(requestedPath) !== import_node_path8.default.normalize(remappedPath)
|
|
47025
|
+
};
|
|
47026
|
+
}
|
|
47027
|
+
|
|
46982
47028
|
// src/wsMetrics.ts
|
|
46983
47029
|
init_cjs_shims();
|
|
46984
47030
|
var import_node_perf_hooks = require("perf_hooks");
|
|
@@ -47073,7 +47119,7 @@ async function chownForRootSpawn(targetPath, target) {
|
|
|
47073
47119
|
}
|
|
47074
47120
|
function readCronLockSnapshot() {
|
|
47075
47121
|
try {
|
|
47076
|
-
const lockPath2 =
|
|
47122
|
+
const lockPath2 = import_node_path9.default.join(import_node_os5.default.homedir(), ".claude", "scheduled_tasks.lock");
|
|
47077
47123
|
if (!import_node_fs3.default.existsSync(lockPath2)) {
|
|
47078
47124
|
return { exists: false, sessionId: null, pid: null };
|
|
47079
47125
|
}
|
|
@@ -47141,8 +47187,8 @@ var AgentManager = class {
|
|
|
47141
47187
|
this.emit = emit;
|
|
47142
47188
|
if (typeof options === "function") {
|
|
47143
47189
|
this.queryFn = options;
|
|
47144
|
-
this.workspacesDir =
|
|
47145
|
-
this.agentConfigDir =
|
|
47190
|
+
this.workspacesDir = import_node_path9.default.join(import_node_os5.default.homedir(), ".ahchat", "workspaces");
|
|
47191
|
+
this.agentConfigDir = import_node_path9.default.join(import_node_os5.default.homedir(), ".ahchat", "agent-config");
|
|
47146
47192
|
this.queryConfig = DEFAULT_QUERY_CONFIG;
|
|
47147
47193
|
this.askQuestionRegistry = new AskQuestionRegistry();
|
|
47148
47194
|
this.groupRegistry = null;
|
|
@@ -47153,11 +47199,11 @@ var AgentManager = class {
|
|
|
47153
47199
|
this.serverApiUrl = null;
|
|
47154
47200
|
this.bridgeToken = null;
|
|
47155
47201
|
this.defaultModel = null;
|
|
47156
|
-
this.dataDir =
|
|
47202
|
+
this.dataDir = import_node_path9.default.join(import_node_os5.default.homedir(), ".ahchat");
|
|
47157
47203
|
} else {
|
|
47158
47204
|
this.queryFn = options?.queryFn ?? null;
|
|
47159
|
-
this.workspacesDir = options?.workspacesDir ??
|
|
47160
|
-
this.agentConfigDir = options?.agentConfigDir ??
|
|
47205
|
+
this.workspacesDir = options?.workspacesDir ?? import_node_path9.default.join(import_node_os5.default.homedir(), ".ahchat", "workspaces");
|
|
47206
|
+
this.agentConfigDir = options?.agentConfigDir ?? import_node_path9.default.join(import_node_os5.default.homedir(), ".ahchat", "agent-config");
|
|
47161
47207
|
this.queryConfig = options?.queryConfig ?? DEFAULT_QUERY_CONFIG;
|
|
47162
47208
|
this.askQuestionRegistry = options?.askQuestionRegistry ?? new AskQuestionRegistry();
|
|
47163
47209
|
this.groupRegistry = options?.groupRegistry ?? null;
|
|
@@ -47168,7 +47214,7 @@ var AgentManager = class {
|
|
|
47168
47214
|
this.serverApiUrl = options?.serverApiUrl ?? null;
|
|
47169
47215
|
this.bridgeToken = options?.bridgeToken ?? null;
|
|
47170
47216
|
this.defaultModel = options?.defaultModel ?? null;
|
|
47171
|
-
this.dataDir = options?.dataDir ??
|
|
47217
|
+
this.dataDir = options?.dataDir ?? import_node_path9.default.join(import_node_os5.default.homedir(), ".ahchat");
|
|
47172
47218
|
}
|
|
47173
47219
|
this.evictionTimer = setInterval(() => {
|
|
47174
47220
|
void this.evictIdle();
|
|
@@ -47179,52 +47225,26 @@ var AgentManager = class {
|
|
|
47179
47225
|
this.queryFn = QA$;
|
|
47180
47226
|
return this.queryFn;
|
|
47181
47227
|
}
|
|
47182
|
-
extractAhchatWorkspaceSuffix(requestedCwd) {
|
|
47183
|
-
const normalized = requestedCwd.trim().replace(/\\/g, "/");
|
|
47184
|
-
const marker = "/.ahchat/users/";
|
|
47185
|
-
const markerIndex = normalized.indexOf(marker);
|
|
47186
|
-
if (markerIndex >= 0) {
|
|
47187
|
-
const afterUsers = normalized.slice(markerIndex + marker.length);
|
|
47188
|
-
const workspaceMarker = "/workspaces/";
|
|
47189
|
-
const workspaceIndex = afterUsers.indexOf(workspaceMarker);
|
|
47190
|
-
if (workspaceIndex >= 0) {
|
|
47191
|
-
const suffix = afterUsers.slice(workspaceIndex + workspaceMarker.length);
|
|
47192
|
-
const parts = suffix.split("/").filter((part) => part && part !== "." && part !== "..");
|
|
47193
|
-
return parts.length > 0 ? parts.join(import_node_path8.default.sep) : null;
|
|
47194
|
-
}
|
|
47195
|
-
}
|
|
47196
|
-
const legacyMarker = "/.ahchat/";
|
|
47197
|
-
const legacyIndex = normalized.indexOf(legacyMarker);
|
|
47198
|
-
if (legacyIndex >= 0) {
|
|
47199
|
-
const firstSegment = normalized.slice(legacyIndex + legacyMarker.length).split("/").find(Boolean);
|
|
47200
|
-
if (firstSegment && /^(Agent|Group)-/.test(firstSegment)) {
|
|
47201
|
-
return firstSegment;
|
|
47202
|
-
}
|
|
47203
|
-
}
|
|
47204
|
-
return null;
|
|
47205
|
-
}
|
|
47206
47228
|
fallbackCwd(agentConfig, scope, requestedCwd) {
|
|
47207
47229
|
const normalized = requestedCwd.trim();
|
|
47208
|
-
const ahchatSuffix =
|
|
47230
|
+
const ahchatSuffix = extractAhchatWorkspaceSuffix(normalized);
|
|
47209
47231
|
if (ahchatSuffix) {
|
|
47210
|
-
return
|
|
47232
|
+
return import_node_path9.default.join(this.workspacesDir, ahchatSuffix);
|
|
47211
47233
|
}
|
|
47212
|
-
const basename = normalized ?
|
|
47213
|
-
const suffix = basename && basename !== "." && basename !==
|
|
47214
|
-
return
|
|
47234
|
+
const basename = normalized ? import_node_path9.default.basename(import_node_path9.default.normalize(normalized)) : "";
|
|
47235
|
+
const suffix = basename && basename !== "." && basename !== import_node_path9.default.sep ? basename : scope.kind === "group" ? `Group-${scope.groupId}` : agentConfig.id;
|
|
47236
|
+
return import_node_path9.default.join(this.workspacesDir, suffix);
|
|
47215
47237
|
}
|
|
47216
47238
|
remapServerWorkspaceCwd(agentConfig, scope, requestedCwd) {
|
|
47217
|
-
const remapped =
|
|
47218
|
-
|
|
47219
|
-
const normalizedRemapped = import_node_path8.default.normalize(remapped);
|
|
47220
|
-
if (this.extractAhchatWorkspaceSuffix(requestedCwd) && normalizedRequested !== normalizedRemapped) {
|
|
47239
|
+
const remapped = remapServerWorkspacePath(requestedCwd, this.workspacesDir);
|
|
47240
|
+
if (remapped.remapped) {
|
|
47221
47241
|
logger10.info("Server working directory remapped to local Bridge workspace", {
|
|
47222
47242
|
agentId: agentConfig.id,
|
|
47223
47243
|
scope: scopeKey(scope),
|
|
47224
47244
|
requested: requestedCwd,
|
|
47225
|
-
remapped
|
|
47245
|
+
remapped: remapped.path
|
|
47226
47246
|
});
|
|
47227
|
-
return remapped;
|
|
47247
|
+
return remapped.path;
|
|
47228
47248
|
}
|
|
47229
47249
|
return requestedCwd;
|
|
47230
47250
|
}
|
|
@@ -47465,12 +47485,12 @@ var AgentManager = class {
|
|
|
47465
47485
|
const agentCwd = await this.resolveRuntimeCwd(agentConfig, scope, cwd);
|
|
47466
47486
|
const cfg = await this.resolveAgentConfig(agentConfig);
|
|
47467
47487
|
if (cfg.instructions?.trim()) {
|
|
47468
|
-
await import_promises8.default.writeFile(
|
|
47488
|
+
await import_promises8.default.writeFile(import_node_path9.default.join(agentCwd, "CLAUDE.md"), cfg.instructions.trim(), "utf-8");
|
|
47469
47489
|
logger10.info("CLAUDE.md written", { agentId: agentConfig.id, bytes: cfg.instructions.trim().length });
|
|
47470
47490
|
}
|
|
47471
47491
|
let effectiveConfigDir = this.agentConfigDir;
|
|
47472
47492
|
if (cfg.subscriptionType !== "system" && cfg.apiKey) {
|
|
47473
|
-
effectiveConfigDir =
|
|
47493
|
+
effectiveConfigDir = import_node_path9.default.join(this.agentConfigDir, "api-key-agents", agentConfig.id);
|
|
47474
47494
|
let isNew = false;
|
|
47475
47495
|
try {
|
|
47476
47496
|
await import_promises8.default.access(effectiveConfigDir);
|
|
@@ -47483,7 +47503,7 @@ var AgentManager = class {
|
|
|
47483
47503
|
this.dispatchMemory.deleteScope(agentConfig.id, scope);
|
|
47484
47504
|
logger10.info("New API-key agent config dir; cleared stale session", { agentId: agentConfig.id });
|
|
47485
47505
|
}
|
|
47486
|
-
const settingsPath =
|
|
47506
|
+
const settingsPath = import_node_path9.default.join(effectiveConfigDir, "settings.json");
|
|
47487
47507
|
const envEntries = {};
|
|
47488
47508
|
if (cfg.apiKey) envEntries.ANTHROPIC_API_KEY = cfg.apiKey;
|
|
47489
47509
|
if (cfg.apiBaseUrl) envEntries.ANTHROPIC_BASE_URL = cfg.apiBaseUrl;
|
|
@@ -47790,7 +47810,7 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
47790
47810
|
settings: (() => {
|
|
47791
47811
|
const isolated = cfg.subscriptionType === "project" && Boolean(cfg.apiKey ?? cfg.apiBaseUrl);
|
|
47792
47812
|
if (!isolated) return void 0;
|
|
47793
|
-
return
|
|
47813
|
+
return import_node_path9.default.join(effectiveConfigDir, "settings.json");
|
|
47794
47814
|
})(),
|
|
47795
47815
|
canUseTool: async (toolName, input) => {
|
|
47796
47816
|
if (toolName === "AskUserQuestion") {
|
|
@@ -47864,7 +47884,7 @@ Do NOT use "..." as content \u2014 write specific, project-relevant content.`;
|
|
|
47864
47884
|
if (isRunningAsRoot()) {
|
|
47865
47885
|
await chownForRootSpawn(effectiveConfigDir, "configDir");
|
|
47866
47886
|
await chownForRootSpawn(agentCwd, "agentCwd");
|
|
47867
|
-
const settingsFilePath =
|
|
47887
|
+
const settingsFilePath = import_node_path9.default.join(effectiveConfigDir, "settings.json");
|
|
47868
47888
|
await chownForRootSpawn(settingsFilePath, "settingsFile");
|
|
47869
47889
|
options.spawnClaudeCodeProcess = (spawnOptions) => {
|
|
47870
47890
|
const env2 = { ...spawnOptions.env, HOME: "/home/node" };
|
|
@@ -48031,7 +48051,7 @@ ${trimmed}`;
|
|
|
48031
48051
|
lines.push(` workdir: ${currentCwd}`);
|
|
48032
48052
|
} else {
|
|
48033
48053
|
const a = this.agentRegistry?.getById(agentId);
|
|
48034
|
-
const singleCwd = a?.workingDirectory ||
|
|
48054
|
+
const singleCwd = a?.workingDirectory || import_node_path9.default.join(this.workspacesDir, agentId);
|
|
48035
48055
|
lines.push(` workdir: ${singleCwd}`);
|
|
48036
48056
|
}
|
|
48037
48057
|
let rosterCount = 0;
|
|
@@ -48043,7 +48063,7 @@ ${trimmed}`;
|
|
|
48043
48063
|
if (key === curKey) {
|
|
48044
48064
|
lines.push(` workdir: ${currentCwd}`);
|
|
48045
48065
|
} else {
|
|
48046
|
-
const groupCwd = g2.workingDirectory ||
|
|
48066
|
+
const groupCwd = g2.workingDirectory || import_node_path9.default.join(this.workspacesDir, g2.groupId);
|
|
48047
48067
|
lines.push(` workdir: ${groupCwd}`);
|
|
48048
48068
|
}
|
|
48049
48069
|
const others = g2.members.filter((id) => id !== agentId).map((id) => {
|
|
@@ -48494,14 +48514,14 @@ ${lines.join("\n")}`;
|
|
|
48494
48514
|
}
|
|
48495
48515
|
async materializeAttachment(runtime, attachment, buffer) {
|
|
48496
48516
|
const safeFileName = this.safeAttachmentFileName(attachment.fileName);
|
|
48497
|
-
const dir =
|
|
48517
|
+
const dir = import_node_path9.default.join(runtime.cwd, ".ahchat-attachments", attachment.id);
|
|
48498
48518
|
await import_promises8.default.mkdir(dir, { recursive: true });
|
|
48499
|
-
const filePath =
|
|
48519
|
+
const filePath = import_node_path9.default.join(dir, safeFileName);
|
|
48500
48520
|
await import_promises8.default.writeFile(filePath, buffer);
|
|
48501
48521
|
return filePath;
|
|
48502
48522
|
}
|
|
48503
48523
|
safeAttachmentFileName(fileName) {
|
|
48504
|
-
const baseName =
|
|
48524
|
+
const baseName = import_node_path9.default.basename(fileName).replace(/[\0/:\\]/g, "_").trim();
|
|
48505
48525
|
return baseName || "attachment";
|
|
48506
48526
|
}
|
|
48507
48527
|
/**
|
|
@@ -48516,7 +48536,7 @@ ${lines.join("\n")}`;
|
|
|
48516
48536
|
async detectVisionSupport() {
|
|
48517
48537
|
if (process.env.ANTHROPIC_BASE_URL) return false;
|
|
48518
48538
|
try {
|
|
48519
|
-
const settingsPath =
|
|
48539
|
+
const settingsPath = import_node_path9.default.join(import_node_os5.default.homedir(), ".claude", "settings.json");
|
|
48520
48540
|
const raw = await import_promises8.default.readFile(settingsPath, "utf-8");
|
|
48521
48541
|
const parsed = JSON.parse(raw);
|
|
48522
48542
|
if (parsed.env?.ANTHROPIC_BASE_URL) return false;
|
|
@@ -48882,7 +48902,7 @@ ${lines.join("\n")}`;
|
|
|
48882
48902
|
}
|
|
48883
48903
|
cwd = payload.targetCwd;
|
|
48884
48904
|
} else {
|
|
48885
|
-
cwd = agentConfig.workingDirectory ||
|
|
48905
|
+
cwd = agentConfig.workingDirectory || import_node_path9.default.join(this.workspacesDir, agentConfig.id);
|
|
48886
48906
|
}
|
|
48887
48907
|
void this.acquire(agentConfig, targetScope, cwd).then(() => {
|
|
48888
48908
|
logger10.info("Neural send new runtime acquired", {
|
|
@@ -48988,7 +49008,7 @@ ${lines.join("\n")}`;
|
|
|
48988
49008
|
conversationId,
|
|
48989
49009
|
traceId
|
|
48990
49010
|
});
|
|
48991
|
-
const cwd = newAgent.workingDirectory ||
|
|
49011
|
+
const cwd = newAgent.workingDirectory || import_node_path9.default.join(this.workspacesDir, newAgent.id);
|
|
48992
49012
|
const scope = { kind: "single" };
|
|
48993
49013
|
try {
|
|
48994
49014
|
await this.acquire(newAgent, scope, cwd);
|
|
@@ -49270,12 +49290,12 @@ ${lines.join("\n")}`;
|
|
|
49270
49290
|
break;
|
|
49271
49291
|
}
|
|
49272
49292
|
try {
|
|
49273
|
-
let cwd = agent.workingDirectory ||
|
|
49293
|
+
let cwd = agent.workingDirectory || import_node_path9.default.join(this.workspacesDir, agent.id);
|
|
49274
49294
|
if (agent.workingDirectory) {
|
|
49275
49295
|
try {
|
|
49276
49296
|
await import_promises8.default.mkdir(cwd, { recursive: true });
|
|
49277
49297
|
} catch {
|
|
49278
|
-
cwd =
|
|
49298
|
+
cwd = import_node_path9.default.join(this.workspacesDir, agent.id);
|
|
49279
49299
|
logger10.warn("Stored workingDirectory inaccessible, falling back", {
|
|
49280
49300
|
agentId: agent.id,
|
|
49281
49301
|
stored: agent.workingDirectory,
|
|
@@ -49750,8 +49770,8 @@ var HttpAgentRegistry = class {
|
|
|
49750
49770
|
agents = /* @__PURE__ */ new Map();
|
|
49751
49771
|
apiUrl(suffix) {
|
|
49752
49772
|
const base = this.serverApiUrl.replace(/\/$/, "");
|
|
49753
|
-
const
|
|
49754
|
-
return `${base}${
|
|
49773
|
+
const path24 = suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
49774
|
+
return `${base}${path24}`;
|
|
49755
49775
|
}
|
|
49756
49776
|
async refresh() {
|
|
49757
49777
|
const attempt = async () => {
|
|
@@ -49843,8 +49863,8 @@ var HttpSubscriptionRegistry = class {
|
|
|
49843
49863
|
subscriptions = /* @__PURE__ */ new Map();
|
|
49844
49864
|
apiUrl(suffix) {
|
|
49845
49865
|
const base = this.serverApiUrl.replace(/\/$/, "");
|
|
49846
|
-
const
|
|
49847
|
-
return `${base}${
|
|
49866
|
+
const path24 = suffix.startsWith("/") ? suffix : `/${suffix}`;
|
|
49867
|
+
return `${base}${path24}`;
|
|
49848
49868
|
}
|
|
49849
49869
|
async refresh() {
|
|
49850
49870
|
const attempt = async () => {
|
|
@@ -50331,7 +50351,7 @@ var ServerConnector = class {
|
|
|
50331
50351
|
init_cjs_shims();
|
|
50332
50352
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
50333
50353
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
50334
|
-
var
|
|
50354
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
50335
50355
|
var logger16 = createModuleLogger("bridge.contextDumper");
|
|
50336
50356
|
var TRUNCATE_THRESHOLD = 5e4;
|
|
50337
50357
|
var TRUNCATE_HEAD = 8e3;
|
|
@@ -50360,7 +50380,7 @@ function cwdToProjectSlug(cwd) {
|
|
|
50360
50380
|
}
|
|
50361
50381
|
function resolveJsonlPath(sessionId, cwd) {
|
|
50362
50382
|
const slug = cwdToProjectSlug(cwd);
|
|
50363
|
-
return
|
|
50383
|
+
return import_node_path10.default.join(import_node_os7.default.homedir(), ".claude", "projects", slug, `${sessionId}.jsonl`);
|
|
50364
50384
|
}
|
|
50365
50385
|
var RENDERABLE_TYPES = /* @__PURE__ */ new Set(["user", "assistant", "system", "attachment"]);
|
|
50366
50386
|
async function readJsonlEntries(filePath) {
|
|
@@ -50620,7 +50640,7 @@ async function dumpAgentContext(agentId, deps) {
|
|
|
50620
50640
|
if (!workdir) {
|
|
50621
50641
|
return { ok: false, files: [], scopeErrors: [], error: "agent has no working directory" };
|
|
50622
50642
|
}
|
|
50623
|
-
const dumpDir =
|
|
50643
|
+
const dumpDir = import_node_path10.default.join(workdir, "sessioninfo");
|
|
50624
50644
|
await import_promises9.default.mkdir(dumpDir, { recursive: true });
|
|
50625
50645
|
const prefix = `${agentId}::`;
|
|
50626
50646
|
const scopeEntries = [];
|
|
@@ -50690,7 +50710,7 @@ async function dumpAgentContext(agentId, deps) {
|
|
|
50690
50710
|
jsonlPath
|
|
50691
50711
|
});
|
|
50692
50712
|
const filename = scopeFilename(agent.name, scopeKey2, groupName);
|
|
50693
|
-
const filePath =
|
|
50713
|
+
const filePath = import_node_path10.default.join(dumpDir, filename);
|
|
50694
50714
|
await import_promises9.default.writeFile(filePath, html, "utf-8");
|
|
50695
50715
|
dumpedFiles.push(filename);
|
|
50696
50716
|
const stat3 = await import_promises9.default.stat(filePath);
|
|
@@ -50732,19 +50752,208 @@ async function dumpAgentContext(agentId, deps) {
|
|
|
50732
50752
|
// src/listDir.ts
|
|
50733
50753
|
init_cjs_shims();
|
|
50734
50754
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
50735
|
-
var
|
|
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);
|
|
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 normalizeBridgeServerUrls(rawUrl) {
|
|
50930
|
+
const url2 = new URL(rawUrl);
|
|
50931
|
+
if (url2.protocol === "http:" || url2.protocol === "https:") {
|
|
50932
|
+
url2.protocol = url2.protocol === "https:" ? "wss:" : "ws:";
|
|
50933
|
+
if (url2.pathname === "/" || url2.pathname === "") url2.pathname = "/ws/bridge";
|
|
50934
|
+
}
|
|
50935
|
+
if (url2.protocol !== "ws:" && url2.protocol !== "wss:") {
|
|
50936
|
+
throw new Error(`Unsupported bridge server URL protocol: ${url2.protocol}`);
|
|
50937
|
+
}
|
|
50938
|
+
const serverUrl = url2.toString();
|
|
50939
|
+
const serverApiUrl = `${url2.protocol === "wss:" ? "https" : "http"}://${url2.host}`;
|
|
50940
|
+
return { serverUrl, serverApiUrl };
|
|
50941
|
+
}
|
|
50942
|
+
|
|
50943
|
+
// src/listDir.ts
|
|
50736
50944
|
var logger17 = createModuleLogger("bridge.listDir");
|
|
50737
50945
|
function shouldIncludeEntry(name) {
|
|
50738
50946
|
if (!name.startsWith(".")) return true;
|
|
50739
50947
|
return name === ".ahchat-attachments";
|
|
50740
50948
|
}
|
|
50741
50949
|
async function listDirectoryEntries(dirPath) {
|
|
50742
|
-
|
|
50743
|
-
|
|
50950
|
+
const resolvedDirPath = resolveUserPath(dirPath);
|
|
50951
|
+
logger17.info("listDirectoryEntries start", { path: dirPath, resolvedPath: resolvedDirPath });
|
|
50952
|
+
const raw = await import_promises10.default.readdir(resolvedDirPath, { withFileTypes: true });
|
|
50744
50953
|
const entries = [];
|
|
50745
50954
|
for (const entry of raw) {
|
|
50746
50955
|
if (!shouldIncludeEntry(entry.name)) continue;
|
|
50747
|
-
const fullPath =
|
|
50956
|
+
const fullPath = import_node_path12.default.join(resolvedDirPath, entry.name);
|
|
50748
50957
|
const isDir = entry.isDirectory();
|
|
50749
50958
|
let size;
|
|
50750
50959
|
let mtime;
|
|
@@ -50763,6 +50972,7 @@ async function listDirectoryEntries(dirPath) {
|
|
|
50763
50972
|
});
|
|
50764
50973
|
logger17.info("listDirectoryEntries ok", {
|
|
50765
50974
|
path: dirPath,
|
|
50975
|
+
resolvedPath: resolvedDirPath,
|
|
50766
50976
|
count: entries.length,
|
|
50767
50977
|
dirCount: entries.filter((e7) => e7.type === "dir").length,
|
|
50768
50978
|
fileCount: entries.filter((e7) => e7.type === "file").length
|
|
@@ -50772,9 +50982,9 @@ async function listDirectoryEntries(dirPath) {
|
|
|
50772
50982
|
|
|
50773
50983
|
// src/logScanner.ts
|
|
50774
50984
|
init_cjs_shims();
|
|
50775
|
-
var
|
|
50776
|
-
var
|
|
50777
|
-
var
|
|
50985
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
50986
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
50987
|
+
var import_node_os9 = __toESM(require("os"), 1);
|
|
50778
50988
|
var import_node_readline = __toESM(require("readline"), 1);
|
|
50779
50989
|
var logger18 = createModuleLogger("bridge.logScanner");
|
|
50780
50990
|
var DEFAULT_LIMIT = 500;
|
|
@@ -50782,17 +50992,17 @@ var MAX_LIMIT = 2e3;
|
|
|
50782
50992
|
function listLogFiles(logsDir, baseName) {
|
|
50783
50993
|
let names;
|
|
50784
50994
|
try {
|
|
50785
|
-
names =
|
|
50995
|
+
names = import_node_fs5.default.readdirSync(logsDir);
|
|
50786
50996
|
} catch (e7) {
|
|
50787
50997
|
logger18.warn("listLogFiles: readdir failed", { logsDir, error: e7 });
|
|
50788
50998
|
return [];
|
|
50789
50999
|
}
|
|
50790
51000
|
const pattern = new RegExp(`^${baseName.replace(".", "\\.")}(\\.\\d+)?$`);
|
|
50791
|
-
return names.filter((n2) => pattern.test(n2)).map((n2) =>
|
|
51001
|
+
return names.filter((n2) => pattern.test(n2)).map((n2) => import_node_path13.default.join(logsDir, n2));
|
|
50792
51002
|
}
|
|
50793
51003
|
async function scanFile(filePath, source, filter, limit, state) {
|
|
50794
|
-
const file2 =
|
|
50795
|
-
const stream =
|
|
51004
|
+
const file2 = import_node_path13.default.basename(filePath);
|
|
51005
|
+
const stream = import_node_fs5.default.createReadStream(filePath, { encoding: "utf-8" });
|
|
50796
51006
|
const rl2 = import_node_readline.default.createInterface({ input: stream, crlfDelay: Infinity });
|
|
50797
51007
|
let lineNum = 0;
|
|
50798
51008
|
for await (const line of rl2) {
|
|
@@ -50830,7 +51040,7 @@ async function scanLocalLogs(logsDir, baseName, filter) {
|
|
|
50830
51040
|
};
|
|
50831
51041
|
}
|
|
50832
51042
|
async function scanBridgeLogs(filter) {
|
|
50833
|
-
const logDir =
|
|
51043
|
+
const logDir = import_node_path13.default.join(import_node_os9.default.homedir(), ".ahchat", "logs");
|
|
50834
51044
|
logger18.info("scanBridgeLogs start", {
|
|
50835
51045
|
logDir,
|
|
50836
51046
|
startIso: filter.startIso,
|
|
@@ -50848,15 +51058,15 @@ async function scanBridgeLogs(filter) {
|
|
|
50848
51058
|
|
|
50849
51059
|
// src/skillStore.ts
|
|
50850
51060
|
init_cjs_shims();
|
|
50851
|
-
var
|
|
50852
|
-
var
|
|
51061
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
51062
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
50853
51063
|
var logger19 = createModuleLogger("bridge.skillStore");
|
|
50854
51064
|
var ALLOWED_NAMES = /* @__PURE__ */ new Set(["log-analysis"]);
|
|
50855
51065
|
var SkillStore = class {
|
|
50856
51066
|
skillsDir;
|
|
50857
51067
|
constructor(dataDir) {
|
|
50858
|
-
this.skillsDir =
|
|
50859
|
-
|
|
51068
|
+
this.skillsDir = import_node_path14.default.join(dataDir, "skills");
|
|
51069
|
+
import_node_fs6.default.mkdirSync(this.skillsDir, { recursive: true });
|
|
50860
51070
|
logger19.info("SkillStore initialized", { skillsDir: this.skillsDir });
|
|
50861
51071
|
}
|
|
50862
51072
|
read(name) {
|
|
@@ -50864,9 +51074,9 @@ var SkillStore = class {
|
|
|
50864
51074
|
logger19.warn("Skill read: unknown name", { name, allowed: [...ALLOWED_NAMES] });
|
|
50865
51075
|
return "";
|
|
50866
51076
|
}
|
|
50867
|
-
const filePath =
|
|
51077
|
+
const filePath = import_node_path14.default.join(this.skillsDir, `${name}.md`);
|
|
50868
51078
|
try {
|
|
50869
|
-
const content =
|
|
51079
|
+
const content = import_node_fs6.default.readFileSync(filePath, "utf-8");
|
|
50870
51080
|
logger19.info("Skill read", { name, bytes: content.length });
|
|
50871
51081
|
return content;
|
|
50872
51082
|
} catch (e7) {
|
|
@@ -50879,19 +51089,19 @@ var SkillStore = class {
|
|
|
50879
51089
|
if (!ALLOWED_NAMES.has(name)) {
|
|
50880
51090
|
throw new Error(`Unknown skill name: ${name}`);
|
|
50881
51091
|
}
|
|
50882
|
-
const filePath =
|
|
51092
|
+
const filePath = import_node_path14.default.join(this.skillsDir, `${name}.md`);
|
|
50883
51093
|
const tmpPath = `${filePath}.tmp`;
|
|
50884
51094
|
let existing = "";
|
|
50885
51095
|
try {
|
|
50886
|
-
existing =
|
|
51096
|
+
existing = import_node_fs6.default.readFileSync(filePath, "utf-8");
|
|
50887
51097
|
} catch {
|
|
50888
51098
|
}
|
|
50889
51099
|
if (existing === content) {
|
|
50890
51100
|
logger19.info("Skill already in sync", { name, bytes: content.length });
|
|
50891
51101
|
return;
|
|
50892
51102
|
}
|
|
50893
|
-
|
|
50894
|
-
|
|
51103
|
+
import_node_fs6.default.writeFileSync(tmpPath, content, "utf-8");
|
|
51104
|
+
import_node_fs6.default.renameSync(tmpPath, filePath);
|
|
50895
51105
|
logger19.info("Skill seeded/re-synced", {
|
|
50896
51106
|
name,
|
|
50897
51107
|
bytes: content.length,
|
|
@@ -50902,8 +51112,8 @@ var SkillStore = class {
|
|
|
50902
51112
|
|
|
50903
51113
|
// src/lockfile.ts
|
|
50904
51114
|
init_cjs_shims();
|
|
50905
|
-
var
|
|
50906
|
-
var
|
|
51115
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
51116
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
50907
51117
|
var logger20 = createModuleLogger("bridge.lockfile");
|
|
50908
51118
|
var lockPath = null;
|
|
50909
51119
|
function isProcessAlive(pid) {
|
|
@@ -50917,10 +51127,10 @@ function isProcessAlive(pid) {
|
|
|
50917
51127
|
}
|
|
50918
51128
|
}
|
|
50919
51129
|
function acquireLock(dataDir) {
|
|
50920
|
-
const file2 =
|
|
51130
|
+
const file2 = import_node_path15.default.join(dataDir, "bridge.lock");
|
|
50921
51131
|
lockPath = file2;
|
|
50922
|
-
if (
|
|
50923
|
-
const raw =
|
|
51132
|
+
if (import_node_fs7.default.existsSync(file2)) {
|
|
51133
|
+
const raw = import_node_fs7.default.readFileSync(file2, "utf-8").trim();
|
|
50924
51134
|
const pid = Number.parseInt(raw, 10);
|
|
50925
51135
|
if (Number.isFinite(pid) && pid > 0) {
|
|
50926
51136
|
if (isProcessAlive(pid)) {
|
|
@@ -50929,15 +51139,15 @@ function acquireLock(dataDir) {
|
|
|
50929
51139
|
logger20.warn("Removing stale bridge.lock (process not found)", { pid, path: file2 });
|
|
50930
51140
|
}
|
|
50931
51141
|
}
|
|
50932
|
-
|
|
50933
|
-
|
|
51142
|
+
import_node_fs7.default.mkdirSync(import_node_path15.default.dirname(file2), { recursive: true });
|
|
51143
|
+
import_node_fs7.default.writeFileSync(file2, String(process.pid), "utf-8");
|
|
50934
51144
|
logger20.info("Acquired bridge lock", { path: file2, pid: process.pid });
|
|
50935
51145
|
const release = () => {
|
|
50936
51146
|
try {
|
|
50937
|
-
if (lockPath &&
|
|
50938
|
-
const current =
|
|
51147
|
+
if (lockPath && import_node_fs7.default.existsSync(lockPath)) {
|
|
51148
|
+
const current = import_node_fs7.default.readFileSync(lockPath, "utf-8").trim();
|
|
50939
51149
|
if (current === String(process.pid)) {
|
|
50940
|
-
|
|
51150
|
+
import_node_fs7.default.unlinkSync(lockPath);
|
|
50941
51151
|
logger20.info("Released bridge lock", { path: lockPath });
|
|
50942
51152
|
}
|
|
50943
51153
|
}
|
|
@@ -51298,14 +51508,14 @@ async function handleGroupArchivedPush(deps, payload) {
|
|
|
51298
51508
|
|
|
51299
51509
|
// src/sessionStore.ts
|
|
51300
51510
|
init_cjs_shims();
|
|
51301
|
-
var
|
|
51302
|
-
var
|
|
51511
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
51512
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
51303
51513
|
var logger23 = createModuleLogger("session.store");
|
|
51304
51514
|
var SessionStore = class {
|
|
51305
51515
|
filePath;
|
|
51306
51516
|
cache;
|
|
51307
51517
|
constructor(dataDir) {
|
|
51308
|
-
this.filePath =
|
|
51518
|
+
this.filePath = import_node_path16.default.join(dataDir, "sessions.json");
|
|
51309
51519
|
this.cache = this.loadFromDisk();
|
|
51310
51520
|
}
|
|
51311
51521
|
cacheKey(agentId, scope) {
|
|
@@ -51340,8 +51550,8 @@ var SessionStore = class {
|
|
|
51340
51550
|
}
|
|
51341
51551
|
loadFromDisk() {
|
|
51342
51552
|
try {
|
|
51343
|
-
if (!
|
|
51344
|
-
const raw =
|
|
51553
|
+
if (!import_node_fs8.default.existsSync(this.filePath)) return {};
|
|
51554
|
+
const raw = import_node_fs8.default.readFileSync(this.filePath, "utf-8");
|
|
51345
51555
|
const parsed = JSON.parse(raw);
|
|
51346
51556
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
51347
51557
|
const map2 = parsed;
|
|
@@ -51365,9 +51575,9 @@ var SessionStore = class {
|
|
|
51365
51575
|
}
|
|
51366
51576
|
saveToDisk() {
|
|
51367
51577
|
try {
|
|
51368
|
-
const dir =
|
|
51369
|
-
|
|
51370
|
-
|
|
51578
|
+
const dir = import_node_path16.default.dirname(this.filePath);
|
|
51579
|
+
import_node_fs8.default.mkdirSync(dir, { recursive: true });
|
|
51580
|
+
import_node_fs8.default.writeFileSync(this.filePath, JSON.stringify(this.cache, null, 2), "utf-8");
|
|
51371
51581
|
} catch (e7) {
|
|
51372
51582
|
logger23.error("Failed to save sessions file", { error: e7, path: this.filePath });
|
|
51373
51583
|
}
|
|
@@ -51376,9 +51586,9 @@ var SessionStore = class {
|
|
|
51376
51586
|
|
|
51377
51587
|
// src/ensureClaudeCli.ts
|
|
51378
51588
|
init_cjs_shims();
|
|
51379
|
-
var
|
|
51380
|
-
var
|
|
51381
|
-
var
|
|
51589
|
+
var import_node_child_process3 = require("child_process");
|
|
51590
|
+
var import_node_fs9 = require("fs");
|
|
51591
|
+
var import_node_path17 = require("path");
|
|
51382
51592
|
var logger24 = createModuleLogger("bridge.ensureCli");
|
|
51383
51593
|
var DEFAULT_INSTALL_TIMEOUT_MS = 6e5;
|
|
51384
51594
|
function getInstallTimeoutMs() {
|
|
@@ -51387,48 +51597,42 @@ function getInstallTimeoutMs() {
|
|
|
51387
51597
|
const parsed = Number.parseInt(raw, 10);
|
|
51388
51598
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INSTALL_TIMEOUT_MS;
|
|
51389
51599
|
}
|
|
51390
|
-
function detectClaudeCli() {
|
|
51391
|
-
try {
|
|
51392
|
-
return (0, import_node_child_process2.execFileSync)("claude", ["--version"], { timeout: 1e4 }).toString().trim();
|
|
51393
|
-
} catch {
|
|
51394
|
-
return void 0;
|
|
51395
|
-
}
|
|
51396
|
-
}
|
|
51397
51600
|
function getNpmGlobalBin() {
|
|
51601
|
+
const npm = resolveCommand(["npm"]);
|
|
51602
|
+
if (!npm) return void 0;
|
|
51398
51603
|
try {
|
|
51399
|
-
const bin = (0,
|
|
51604
|
+
const bin = (0, import_node_child_process3.execFileSync)(npm.path, ["bin", "-g"], {
|
|
51605
|
+
env: withAugmentedPathEnv(),
|
|
51606
|
+
timeout: 5e3
|
|
51607
|
+
}).toString().trim() || void 0;
|
|
51400
51608
|
if (bin) return bin;
|
|
51401
51609
|
} catch {
|
|
51402
51610
|
}
|
|
51403
51611
|
try {
|
|
51404
|
-
const prefix = (0,
|
|
51405
|
-
|
|
51612
|
+
const prefix = (0, import_node_child_process3.execFileSync)(npm.path, ["prefix", "-g"], {
|
|
51613
|
+
env: withAugmentedPathEnv(),
|
|
51614
|
+
timeout: 5e3
|
|
51615
|
+
}).toString().trim();
|
|
51616
|
+
if (prefix) return (0, import_node_path17.join)(prefix, "bin");
|
|
51406
51617
|
} catch {
|
|
51407
51618
|
}
|
|
51408
51619
|
return void 0;
|
|
51409
51620
|
}
|
|
51410
51621
|
function resolveClaudeBinary() {
|
|
51411
|
-
|
|
51412
|
-
try {
|
|
51413
|
-
const out = (0, import_node_child_process2.execFileSync)(whichCmd, ["claude"], { timeout: 5e3 }).toString();
|
|
51414
|
-
const first = out.split(/\r?\n/).map((l4) => l4.trim()).find(Boolean);
|
|
51415
|
-
if (first) return first;
|
|
51416
|
-
} catch {
|
|
51417
|
-
}
|
|
51418
|
-
return resolveViaNpmBin();
|
|
51622
|
+
return resolveCommand(["claude", "anthropic-cli"])?.path ?? resolveViaNpmBin();
|
|
51419
51623
|
}
|
|
51420
51624
|
function getNpmClaudeCandidates(bin) {
|
|
51421
51625
|
if (process.platform === "win32") {
|
|
51422
|
-
return ["claude.cmd", "claude.exe", "claude", "anthropic-cli.cmd", "anthropic-cli.exe", "anthropic-cli"].map((name) => (0,
|
|
51626
|
+
return ["claude.cmd", "claude.exe", "claude", "anthropic-cli.cmd", "anthropic-cli.exe", "anthropic-cli"].map((name) => (0, import_node_path17.join)(bin, name));
|
|
51423
51627
|
}
|
|
51424
|
-
return [(0,
|
|
51628
|
+
return [(0, import_node_path17.join)(bin, "claude"), (0, import_node_path17.join)(bin, "anthropic-cli")];
|
|
51425
51629
|
}
|
|
51426
51630
|
function resolveViaNpmBin() {
|
|
51427
51631
|
const bin = getNpmGlobalBin();
|
|
51428
51632
|
if (!bin) return void 0;
|
|
51429
51633
|
for (const candidate of getNpmClaudeCandidates(bin)) {
|
|
51430
51634
|
try {
|
|
51431
|
-
(0,
|
|
51635
|
+
(0, import_node_fs9.accessSync)(candidate, import_node_fs9.constants.X_OK);
|
|
51432
51636
|
return candidate;
|
|
51433
51637
|
} catch {
|
|
51434
51638
|
}
|
|
@@ -51438,40 +51642,32 @@ function resolveViaNpmBin() {
|
|
|
51438
51642
|
function detectViaNpmBin() {
|
|
51439
51643
|
const binPath = resolveViaNpmBin();
|
|
51440
51644
|
if (!binPath) return void 0;
|
|
51441
|
-
|
|
51442
|
-
return (0, import_node_child_process2.execFileSync)(binPath, ["--version"], { timeout: 1e4 }).toString().trim();
|
|
51443
|
-
} catch {
|
|
51444
|
-
}
|
|
51445
|
-
return void 0;
|
|
51645
|
+
return readCommandVersion(binPath);
|
|
51446
51646
|
}
|
|
51447
51647
|
function detectResolvedClaudeCli() {
|
|
51448
|
-
const
|
|
51449
|
-
if (
|
|
51450
|
-
|
|
51451
|
-
}
|
|
51452
|
-
const npmBinPath = resolveViaNpmBin();
|
|
51453
|
-
if (!npmBinPath) return void 0;
|
|
51454
|
-
try {
|
|
51455
|
-
const version2 = (0, import_node_child_process2.execFileSync)(npmBinPath, ["--version"], { timeout: 1e4 }).toString().trim();
|
|
51456
|
-
return { version: version2, path: npmBinPath };
|
|
51457
|
-
} catch {
|
|
51458
|
-
}
|
|
51648
|
+
const resolvedPath = resolveClaudeBinary();
|
|
51649
|
+
if (!resolvedPath) return void 0;
|
|
51650
|
+
const version2 = readCommandVersion(resolvedPath);
|
|
51651
|
+
if (version2) return { version: version2, path: resolvedPath };
|
|
51459
51652
|
return void 0;
|
|
51460
51653
|
}
|
|
51461
51654
|
function detectVersionFromResolvedCandidates() {
|
|
51462
51655
|
const candidates = [resolveClaudeBinary(), resolveViaNpmBin()].filter((p) => Boolean(p));
|
|
51463
51656
|
for (const p of candidates) {
|
|
51464
|
-
|
|
51465
|
-
|
|
51466
|
-
return (0, import_node_child_process2.execFileSync)(p, ["--version"], { timeout: 1e4 }).toString().trim();
|
|
51467
|
-
} catch {
|
|
51468
|
-
}
|
|
51657
|
+
const version2 = readCommandVersion(p);
|
|
51658
|
+
if (version2) return version2;
|
|
51469
51659
|
}
|
|
51470
51660
|
return void 0;
|
|
51471
51661
|
}
|
|
51472
51662
|
function installClaudeCli() {
|
|
51663
|
+
const npm = resolveCommand(["npm"]);
|
|
51664
|
+
if (!npm) {
|
|
51665
|
+
logger24.error("npm not found; cannot install Claude Code CLI");
|
|
51666
|
+
return void 0;
|
|
51667
|
+
}
|
|
51473
51668
|
logger24.info("Installing Claude Code CLI via npm...");
|
|
51474
|
-
const result = (0,
|
|
51669
|
+
const result = (0, import_node_child_process3.spawnSync)(npm.path, ["install", "-g", "@anthropic-ai/claude-code"], {
|
|
51670
|
+
env: withAugmentedPathEnv(),
|
|
51475
51671
|
stdio: "inherit",
|
|
51476
51672
|
timeout: getInstallTimeoutMs()
|
|
51477
51673
|
});
|
|
@@ -51503,7 +51699,10 @@ function installClaudeCli() {
|
|
|
51503
51699
|
logger24.error("claude not found after successful npm install -g", {
|
|
51504
51700
|
npmGlobalBin: npmBin ?? "unknown",
|
|
51505
51701
|
pathDirectories: envPath.split(process.platform === "win32" ? ";" : ":").slice(0, 10),
|
|
51506
|
-
npmPrefix: (0,
|
|
51702
|
+
npmPrefix: (0, import_node_child_process3.execFileSync)(npm.path, ["prefix", "-g"], {
|
|
51703
|
+
env: withAugmentedPathEnv(),
|
|
51704
|
+
timeout: 5e3
|
|
51705
|
+
}).toString().trim() || "unknown"
|
|
51507
51706
|
});
|
|
51508
51707
|
return void 0;
|
|
51509
51708
|
}
|
|
@@ -51533,21 +51732,21 @@ async function ensureClaudeCli() {
|
|
|
51533
51732
|
// src/forkAgentFiles.ts
|
|
51534
51733
|
init_cjs_shims();
|
|
51535
51734
|
var fs11 = __toESM(require("fs/promises"), 1);
|
|
51536
|
-
var
|
|
51735
|
+
var path18 = __toESM(require("path"), 1);
|
|
51537
51736
|
|
|
51538
51737
|
// src/sessionSlug.ts
|
|
51539
51738
|
init_cjs_shims();
|
|
51540
|
-
var
|
|
51541
|
-
var
|
|
51542
|
-
var CLAUDE_PROJECTS_DIR =
|
|
51739
|
+
var import_node_os10 = __toESM(require("os"), 1);
|
|
51740
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
51741
|
+
var CLAUDE_PROJECTS_DIR = import_node_path18.default.join(import_node_os10.default.homedir(), ".claude", "projects");
|
|
51543
51742
|
function cwdToSlug(cwd) {
|
|
51544
51743
|
return cwd.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
51545
51744
|
}
|
|
51546
51745
|
function sessionDirForCwd(cwd) {
|
|
51547
|
-
return
|
|
51746
|
+
return import_node_path18.default.join(CLAUDE_PROJECTS_DIR, cwdToSlug(cwd));
|
|
51548
51747
|
}
|
|
51549
51748
|
function sessionFilePath(cwd, sessionId) {
|
|
51550
|
-
return
|
|
51749
|
+
return import_node_path18.default.join(sessionDirForCwd(cwd), `${sessionId}.jsonl`);
|
|
51551
51750
|
}
|
|
51552
51751
|
|
|
51553
51752
|
// src/forkAgentFiles.ts
|
|
@@ -51579,9 +51778,9 @@ async function forkAgentFiles(sourceAgentId, newAgentId, sourceWorkdir, newWorkd
|
|
|
51579
51778
|
logger25.error("Workdir copy failed", { error: e7 });
|
|
51580
51779
|
throw e7;
|
|
51581
51780
|
}
|
|
51582
|
-
const srcNotebook =
|
|
51583
|
-
const dstNotebookDir =
|
|
51584
|
-
const dstNotebook =
|
|
51781
|
+
const srcNotebook = path18.join(dataDir, "agent-memory", sourceAgentId, "notebook.md");
|
|
51782
|
+
const dstNotebookDir = path18.join(dataDir, "agent-memory", newAgentId);
|
|
51783
|
+
const dstNotebook = path18.join(dstNotebookDir, "notebook.md");
|
|
51585
51784
|
try {
|
|
51586
51785
|
const nbStat = await fs11.stat(srcNotebook).catch(() => null);
|
|
51587
51786
|
if (nbStat?.isFile()) {
|
|
@@ -51608,7 +51807,7 @@ async function forkAgentFiles(sourceAgentId, newAgentId, sourceWorkdir, newWorkd
|
|
|
51608
51807
|
if (srcStat?.isFile()) {
|
|
51609
51808
|
const dstDir = sessionDirForCwd(newWorkdir);
|
|
51610
51809
|
await fs11.mkdir(dstDir, { recursive: true });
|
|
51611
|
-
const dstPath =
|
|
51810
|
+
const dstPath = path18.join(dstDir, `${sourceSessionId}.jsonl`);
|
|
51612
51811
|
await fs11.copyFile(srcPath, dstPath);
|
|
51613
51812
|
sessionStore.set(newAgentId, { kind: "single" }, sourceSessionId);
|
|
51614
51813
|
sessionCopied = true;
|
|
@@ -51656,12 +51855,12 @@ async function forkAgentFiles(sourceAgentId, newAgentId, sourceWorkdir, newWorkd
|
|
|
51656
51855
|
// src/modelQuerier.ts
|
|
51657
51856
|
init_cjs_shims();
|
|
51658
51857
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
51659
|
-
var
|
|
51660
|
-
var
|
|
51858
|
+
var import_node_os11 = __toESM(require("os"), 1);
|
|
51859
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
51661
51860
|
var logger26 = createModuleLogger("bridge.modelQuerier");
|
|
51662
51861
|
async function listModels(queryFn, opts = {}) {
|
|
51663
51862
|
const t0 = Date.now();
|
|
51664
|
-
const cwd = opts.cwd ??
|
|
51863
|
+
const cwd = opts.cwd ?? import_node_path19.default.join(import_node_os11.default.homedir(), ".ahchat", "workspaces", "_list_models");
|
|
51665
51864
|
await import_promises11.default.mkdir(cwd, { recursive: true });
|
|
51666
51865
|
const fn = queryFn ?? QA$;
|
|
51667
51866
|
const ic2 = new InputController();
|
|
@@ -51724,8 +51923,8 @@ async function listModels(queryFn, opts = {}) {
|
|
|
51724
51923
|
// src/promptOptimizer.ts
|
|
51725
51924
|
init_cjs_shims();
|
|
51726
51925
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
51727
|
-
var
|
|
51728
|
-
var
|
|
51926
|
+
var import_node_os12 = __toESM(require("os"), 1);
|
|
51927
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
51729
51928
|
var logger27 = createModuleLogger("bridge.promptOptimizer");
|
|
51730
51929
|
var OPTIMIZER_SYSTEM_PROMPT = `You are an expert prompt editor for AHChat Agent creation.
|
|
51731
51930
|
|
|
@@ -51768,7 +51967,7 @@ async function optimizePrompt(queryFn, opts) {
|
|
|
51768
51967
|
const prompt = opts.systemPrompt.trim();
|
|
51769
51968
|
if (!prompt) throw new Error("systemPrompt is required");
|
|
51770
51969
|
const t0 = Date.now();
|
|
51771
|
-
const cwd = opts.cwd ??
|
|
51970
|
+
const cwd = opts.cwd ?? import_node_path20.default.join(import_node_os12.default.homedir(), ".ahchat", "workspaces", "_prompt_optimizer");
|
|
51772
51971
|
await import_promises12.default.mkdir(cwd, { recursive: true });
|
|
51773
51972
|
const fn = queryFn ?? QA$;
|
|
51774
51973
|
const ic2 = new InputController();
|
|
@@ -51856,7 +52055,7 @@ function isRunningAsRoot2() {
|
|
|
51856
52055
|
}
|
|
51857
52056
|
}
|
|
51858
52057
|
async function syncClaudeCredentialsToNodeAccessibleDir(agentConfigDir) {
|
|
51859
|
-
const rootClaudeDir =
|
|
52058
|
+
const rootClaudeDir = import_node_path21.default.join(process.env.HOME ?? "/root", ".claude");
|
|
51860
52059
|
const fs16 = await import("fs/promises");
|
|
51861
52060
|
try {
|
|
51862
52061
|
await fs16.access(rootClaudeDir);
|
|
@@ -51866,8 +52065,8 @@ async function syncClaudeCredentialsToNodeAccessibleDir(agentConfigDir) {
|
|
|
51866
52065
|
}
|
|
51867
52066
|
const filesToSync = [".credentials.json", "settings.json", ".credentials.backup.json"];
|
|
51868
52067
|
for (const file2 of filesToSync) {
|
|
51869
|
-
const src =
|
|
51870
|
-
const dest =
|
|
52068
|
+
const src = import_node_path21.default.join(rootClaudeDir, file2);
|
|
52069
|
+
const dest = import_node_path21.default.join(agentConfigDir, file2);
|
|
51871
52070
|
try {
|
|
51872
52071
|
await fs16.copyFile(src, dest);
|
|
51873
52072
|
logger28.info("Synced credential file", { file: file2, from: src, to: dest });
|
|
@@ -51890,7 +52089,7 @@ async function chownRecursive(dirPath, uid, gid) {
|
|
|
51890
52089
|
return;
|
|
51891
52090
|
}
|
|
51892
52091
|
for (const entry of entries) {
|
|
51893
|
-
const fullPath =
|
|
52092
|
+
const fullPath = import_node_path21.default.join(dirPath, entry.name);
|
|
51894
52093
|
if (entry.isDirectory()) {
|
|
51895
52094
|
await chownRecursive(fullPath, uid, gid);
|
|
51896
52095
|
} else {
|
|
@@ -51905,7 +52104,7 @@ async function chownRecursive(dirPath, uid, gid) {
|
|
|
51905
52104
|
async function startBridge(config2) {
|
|
51906
52105
|
ensureDir(config2.dataDir);
|
|
51907
52106
|
ensureDir(config2.agentConfigDir);
|
|
51908
|
-
const workspacesDir =
|
|
52107
|
+
const workspacesDir = import_node_path21.default.join(config2.dataDir, "workspaces");
|
|
51909
52108
|
ensureDir(workspacesDir);
|
|
51910
52109
|
process.env.CLAUDE_CONFIG_DIR = config2.agentConfigDir;
|
|
51911
52110
|
installBridgeFetchAuth(config2.serverApiUrl, config2.bridgeToken);
|
|
@@ -51934,7 +52133,7 @@ Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\
|
|
|
51934
52133
|
`);
|
|
51935
52134
|
wsMetrics.start(5e3);
|
|
51936
52135
|
const sessionStore = new SessionStore(config2.dataDir);
|
|
51937
|
-
const memoryRoot =
|
|
52136
|
+
const memoryRoot = import_node_path21.default.join(config2.dataDir, "agent-memory");
|
|
51938
52137
|
const memoryStore = new AgentMemoryStore(memoryRoot);
|
|
51939
52138
|
logger28.info("Agent memory store initialized", { rootDir: memoryRoot });
|
|
51940
52139
|
const smithNotebook = memoryStore.read(SMITH_AGENT_ID);
|
|
@@ -52111,7 +52310,16 @@ Bridge token (register this machine at Settings \u2192 \u5DF2\u8FDE\u63A5\u7684\
|
|
|
52111
52310
|
const { requestId, path: dirPath } = msg.payload;
|
|
52112
52311
|
logger28.info("list_dir request received", { requestId, path: dirPath });
|
|
52113
52312
|
try {
|
|
52114
|
-
const
|
|
52313
|
+
const resolved = remapServerWorkspacePath(dirPath, workspacesDir);
|
|
52314
|
+
if (resolved.remapped) {
|
|
52315
|
+
ensureDir(resolved.path);
|
|
52316
|
+
logger28.info("list_dir path remapped to local Bridge workspace", {
|
|
52317
|
+
requestId,
|
|
52318
|
+
requested: dirPath,
|
|
52319
|
+
remapped: resolved.path
|
|
52320
|
+
});
|
|
52321
|
+
}
|
|
52322
|
+
const entries = await listDirectoryEntries(resolved.path);
|
|
52115
52323
|
connector?.send({
|
|
52116
52324
|
type: "bridge:list_dir_response",
|
|
52117
52325
|
payload: { requestId, entries }
|
|
@@ -52354,21 +52562,58 @@ function compactEnv(env2) {
|
|
|
52354
52562
|
|
|
52355
52563
|
// src/protocol.ts
|
|
52356
52564
|
init_cjs_shims();
|
|
52357
|
-
var
|
|
52358
|
-
var
|
|
52359
|
-
var
|
|
52360
|
-
var
|
|
52565
|
+
var import_node_child_process4 = require("child_process");
|
|
52566
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
52567
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
52568
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
52361
52569
|
var logger29 = createModuleLogger("bridge.protocol");
|
|
52570
|
+
function shellSingleQuote(value) {
|
|
52571
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
52572
|
+
}
|
|
52573
|
+
function psSingleQuote(value) {
|
|
52574
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
52575
|
+
}
|
|
52576
|
+
function desktopExecQuote(value) {
|
|
52577
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
52578
|
+
}
|
|
52579
|
+
function getStableCliPath() {
|
|
52580
|
+
return import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge", "cli.cjs");
|
|
52581
|
+
}
|
|
52362
52582
|
function getStableExePath() {
|
|
52363
|
-
const bridgeDir =
|
|
52364
|
-
|
|
52365
|
-
const stablePath =
|
|
52366
|
-
|
|
52367
|
-
if (process.platform !== "win32")
|
|
52583
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52584
|
+
import_node_fs10.default.mkdirSync(bridgeDir, { recursive: true });
|
|
52585
|
+
const stablePath = getStableCliPath();
|
|
52586
|
+
import_node_fs10.default.copyFileSync(__filename, stablePath);
|
|
52587
|
+
if (process.platform !== "win32") import_node_fs10.default.chmodSync(stablePath, 493);
|
|
52368
52588
|
return stablePath;
|
|
52369
52589
|
}
|
|
52590
|
+
function writePosixLauncher(bridgeDir, stableExePath) {
|
|
52591
|
+
const launchScriptPath = import_node_path22.default.join(bridgeDir, "launch-bridge.sh");
|
|
52592
|
+
const augmentedPath = buildAugmentedPath();
|
|
52593
|
+
import_node_fs10.default.writeFileSync(
|
|
52594
|
+
launchScriptPath,
|
|
52595
|
+
[
|
|
52596
|
+
"#!/bin/bash",
|
|
52597
|
+
"set -e",
|
|
52598
|
+
`export PATH=${shellSingleQuote(augmentedPath)}:"\${PATH:-}"`,
|
|
52599
|
+
`SAVED_NODE=${shellSingleQuote(process.execPath)}`,
|
|
52600
|
+
`BRIDGE_CLI=${shellSingleQuote(stableExePath)}`,
|
|
52601
|
+
'NODE_BIN=""',
|
|
52602
|
+
'if [ -x "$SAVED_NODE" ]; then NODE_BIN="$SAVED_NODE"; fi',
|
|
52603
|
+
'if [ -z "$NODE_BIN" ]; then NODE_BIN="$(command -v node || true)"; fi',
|
|
52604
|
+
'if [ -z "$NODE_BIN" ]; then',
|
|
52605
|
+
` echo "Node.js ${MIN_NODE_MAJOR}+ is required to launch AHChat Bridge. Install Node, then rerun: npx -y @fangyb/ahchat-bridge install" >&2`,
|
|
52606
|
+
" exit 1",
|
|
52607
|
+
"fi",
|
|
52608
|
+
'exec "$NODE_BIN" "$BRIDGE_CLI" launch --url "$1"',
|
|
52609
|
+
""
|
|
52610
|
+
].join("\n")
|
|
52611
|
+
);
|
|
52612
|
+
import_node_fs10.default.chmodSync(launchScriptPath, 493);
|
|
52613
|
+
return launchScriptPath;
|
|
52614
|
+
}
|
|
52370
52615
|
function registerProtocolHandler() {
|
|
52371
|
-
const platform =
|
|
52616
|
+
const platform = import_node_os13.default.platform();
|
|
52372
52617
|
if (platform === "win32") {
|
|
52373
52618
|
registerWindows();
|
|
52374
52619
|
} else if (platform === "darwin") {
|
|
@@ -52381,22 +52626,42 @@ function registerProtocolHandler() {
|
|
|
52381
52626
|
function registerWindows() {
|
|
52382
52627
|
const nodeExe = process.execPath;
|
|
52383
52628
|
const stableExePath = getStableExePath();
|
|
52384
|
-
const bridgeDir =
|
|
52385
|
-
const
|
|
52386
|
-
|
|
52629
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52630
|
+
const augmentedPath = buildAugmentedPath();
|
|
52631
|
+
const psLauncherPath = import_node_path22.default.join(bridgeDir, "launch-bridge.ps1");
|
|
52632
|
+
import_node_fs10.default.writeFileSync(
|
|
52387
52633
|
psLauncherPath,
|
|
52388
52634
|
[
|
|
52389
52635
|
`param([string]$url)`,
|
|
52390
|
-
|
|
52636
|
+
`$env:PATH = ${psSingleQuote(augmentedPath)} + [System.IO.Path]::PathSeparator + $env:PATH`,
|
|
52637
|
+
`$candidates = @(`,
|
|
52638
|
+
` ${psSingleQuote(nodeExe)},`,
|
|
52639
|
+
` "$env:NVM_SYMLINK\\node.exe",`,
|
|
52640
|
+
` "$env:ProgramFiles\\nodejs\\node.exe",`,
|
|
52641
|
+
` "$env:LOCALAPPDATA\\Programs\\nodejs\\node.exe"`,
|
|
52642
|
+
`)`,
|
|
52643
|
+
`$node = $null`,
|
|
52644
|
+
`foreach ($candidate in $candidates) {`,
|
|
52645
|
+
` if ($candidate -and (Test-Path $candidate)) { $node = $candidate; break }`,
|
|
52646
|
+
`}`,
|
|
52647
|
+
`if (-not $node) {`,
|
|
52648
|
+
` $cmd = Get-Command node -ErrorAction SilentlyContinue`,
|
|
52649
|
+
` if ($cmd) { $node = $cmd.Source }`,
|
|
52650
|
+
`}`,
|
|
52651
|
+
`if (-not $node) {`,
|
|
52652
|
+
` Write-Error 'Node.js ${MIN_NODE_MAJOR}+ is required to launch AHChat Bridge. Install Node, then rerun: npx -y @fangyb/ahchat-bridge install'`,
|
|
52653
|
+
` exit 1`,
|
|
52654
|
+
`}`,
|
|
52655
|
+
`& $node ${psSingleQuote(stableExePath)} launch --url $url`
|
|
52391
52656
|
].join("\r\n")
|
|
52392
52657
|
);
|
|
52393
52658
|
const handlerValue = `powershell -ExecutionPolicy Bypass -File "${psLauncherPath}" -url "%1"`;
|
|
52394
|
-
const psRegisterPath =
|
|
52395
|
-
|
|
52659
|
+
const psRegisterPath = import_node_path22.default.join(bridgeDir, "register-protocol.ps1");
|
|
52660
|
+
import_node_fs10.default.writeFileSync(
|
|
52396
52661
|
psRegisterPath,
|
|
52397
52662
|
[
|
|
52398
|
-
`$handler =
|
|
52399
|
-
`$icon =
|
|
52663
|
+
`$handler = ${psSingleQuote(handlerValue)}`,
|
|
52664
|
+
`$icon = ${psSingleQuote(nodeExe)}`,
|
|
52400
52665
|
`New-Item -Path 'HKCU:\\Software\\Classes\\ahchat' -Force | Out-Null`,
|
|
52401
52666
|
`Set-ItemProperty -Path 'HKCU:\\Software\\Classes\\ahchat' -Name '(Default)' -Value 'URL:ahchat' -Force`,
|
|
52402
52667
|
`New-ItemProperty -Path 'HKCU:\\Software\\Classes\\ahchat' -Name 'URL Protocol' -Value '' -PropertyType String -Force | Out-Null`,
|
|
@@ -52407,7 +52672,7 @@ function registerWindows() {
|
|
|
52407
52672
|
].join("\r\n")
|
|
52408
52673
|
);
|
|
52409
52674
|
try {
|
|
52410
|
-
(0,
|
|
52675
|
+
(0, import_node_child_process4.execSync)(`powershell -ExecutionPolicy Bypass -File "${psRegisterPath}"`, { stdio: "pipe" });
|
|
52411
52676
|
} catch (e7) {
|
|
52412
52677
|
logger29.error("Failed to register Windows protocol handler", { error: e7 });
|
|
52413
52678
|
throw new Error("Failed to register Windows protocol handler");
|
|
@@ -52415,18 +52680,10 @@ function registerWindows() {
|
|
|
52415
52680
|
logger29.info("Windows protocol handler registered", { psLauncherPath });
|
|
52416
52681
|
}
|
|
52417
52682
|
function registerMacOS() {
|
|
52418
|
-
const appDir =
|
|
52419
|
-
const nodeExe = process.execPath;
|
|
52683
|
+
const appDir = import_node_path22.default.join(import_node_os13.default.homedir(), "Applications", "AHChatBridge.app");
|
|
52420
52684
|
const stableExePath = getStableExePath();
|
|
52421
|
-
const bridgeDir =
|
|
52422
|
-
const launchScriptPath =
|
|
52423
|
-
import_node_fs9.default.writeFileSync(
|
|
52424
|
-
launchScriptPath,
|
|
52425
|
-
`#!/bin/bash
|
|
52426
|
-
exec ${JSON.stringify(nodeExe)} ${JSON.stringify(stableExePath)} launch --url "$1"
|
|
52427
|
-
`
|
|
52428
|
-
);
|
|
52429
|
-
import_node_fs9.default.chmodSync(launchScriptPath, 493);
|
|
52685
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52686
|
+
const launchScriptPath = writePosixLauncher(bridgeDir, stableExePath);
|
|
52430
52687
|
const escapedScriptPath = launchScriptPath.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
52431
52688
|
const appleScript = [
|
|
52432
52689
|
`on open location thisURL`,
|
|
@@ -52434,29 +52691,29 @@ exec ${JSON.stringify(nodeExe)} ${JSON.stringify(stableExePath)} launch --url "$
|
|
|
52434
52691
|
` do shell script "/bin/bash " & (quoted form of launchScript) & " " & (quoted form of thisURL) & " >/tmp/ahchat-bridge.log 2>&1 &"`,
|
|
52435
52692
|
`end open location`
|
|
52436
52693
|
].join("\n");
|
|
52437
|
-
const tmpScript =
|
|
52438
|
-
|
|
52694
|
+
const tmpScript = import_node_path22.default.join(import_node_os13.default.tmpdir(), "AHChatBridge.applescript");
|
|
52695
|
+
import_node_fs10.default.writeFileSync(tmpScript, appleScript);
|
|
52439
52696
|
try {
|
|
52440
|
-
|
|
52697
|
+
import_node_fs10.default.rmSync(appDir, { recursive: true, force: true });
|
|
52441
52698
|
} catch {
|
|
52442
52699
|
}
|
|
52443
52700
|
try {
|
|
52444
|
-
(0,
|
|
52701
|
+
(0, import_node_child_process4.execSync)(`osacompile -o ${JSON.stringify(appDir)} ${JSON.stringify(tmpScript)}`, { stdio: "pipe" });
|
|
52445
52702
|
} finally {
|
|
52446
52703
|
try {
|
|
52447
|
-
|
|
52704
|
+
import_node_fs10.default.unlinkSync(tmpScript);
|
|
52448
52705
|
} catch {
|
|
52449
52706
|
}
|
|
52450
52707
|
}
|
|
52451
|
-
const plistPath =
|
|
52708
|
+
const plistPath = import_node_path22.default.join(appDir, "Contents", "Info.plist");
|
|
52452
52709
|
const urlTypes = JSON.stringify([{ CFBundleURLName: "AHChat Bridge", CFBundleURLSchemes: ["ahchat"] }]);
|
|
52453
|
-
(0,
|
|
52710
|
+
(0, import_node_child_process4.execSync)(
|
|
52454
52711
|
`/usr/bin/plutil -insert CFBundleURLTypes -json ${JSON.stringify(urlTypes)} ${JSON.stringify(plistPath)}`,
|
|
52455
52712
|
{ stdio: "pipe" }
|
|
52456
52713
|
);
|
|
52457
52714
|
const lsregister = "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister";
|
|
52458
52715
|
try {
|
|
52459
|
-
(0,
|
|
52716
|
+
(0, import_node_child_process4.execSync)(`${lsregister} -f ${JSON.stringify(appDir)}`, { stdio: "pipe" });
|
|
52460
52717
|
} catch (e7) {
|
|
52461
52718
|
logger29.warn("lsregister failed; URL scheme registration may be delayed", { error: e7 });
|
|
52462
52719
|
}
|
|
@@ -52464,36 +52721,38 @@ exec ${JSON.stringify(nodeExe)} ${JSON.stringify(stableExePath)} launch --url "$
|
|
|
52464
52721
|
}
|
|
52465
52722
|
function registerLinux() {
|
|
52466
52723
|
const stableExePath = getStableExePath();
|
|
52724
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52725
|
+
const launchScriptPath = writePosixLauncher(bridgeDir, stableExePath);
|
|
52467
52726
|
const desktopFile = [
|
|
52468
52727
|
`[Desktop Entry]`,
|
|
52469
52728
|
`Name=AHChat Bridge`,
|
|
52470
|
-
`Exec=${
|
|
52729
|
+
`Exec=${desktopExecQuote(launchScriptPath)} %u`,
|
|
52471
52730
|
`Type=Application`,
|
|
52472
52731
|
`NoDisplay=true`,
|
|
52473
52732
|
`MimeType=x-scheme-handler/ahchat;`
|
|
52474
52733
|
].join("\n");
|
|
52475
|
-
const desktopPath =
|
|
52476
|
-
|
|
52477
|
-
|
|
52734
|
+
const desktopPath = import_node_path22.default.join(import_node_os13.default.homedir(), ".local", "share", "applications", "ahchat-bridge.desktop");
|
|
52735
|
+
import_node_fs10.default.mkdirSync(import_node_path22.default.dirname(desktopPath), { recursive: true });
|
|
52736
|
+
import_node_fs10.default.writeFileSync(desktopPath, desktopFile);
|
|
52478
52737
|
try {
|
|
52479
|
-
(0,
|
|
52738
|
+
(0, import_node_child_process4.execSync)("update-desktop-database ~/.local/share/applications/", { stdio: "pipe" });
|
|
52480
52739
|
} catch (e7) {
|
|
52481
52740
|
logger29.warn("update-desktop-database not available; run it manually if needed", { error: e7 });
|
|
52482
52741
|
}
|
|
52483
52742
|
logger29.info("Linux protocol handler registered", { desktopPath });
|
|
52484
52743
|
}
|
|
52485
52744
|
function unregisterProtocolHandler() {
|
|
52486
|
-
const platform =
|
|
52745
|
+
const platform = import_node_os13.default.platform();
|
|
52487
52746
|
if (platform === "win32") {
|
|
52488
52747
|
try {
|
|
52489
|
-
(0,
|
|
52748
|
+
(0, import_node_child_process4.execSync)(
|
|
52490
52749
|
`powershell -ExecutionPolicy Bypass -Command "Remove-Item -Path 'HKCU:\\Software\\Classes\\ahchat' -Recurse -Force -ErrorAction SilentlyContinue"`,
|
|
52491
52750
|
{ stdio: "pipe" }
|
|
52492
52751
|
);
|
|
52493
|
-
const bridgeDir =
|
|
52752
|
+
const bridgeDir = import_node_path22.default.join(import_node_os13.default.homedir(), ".ahchat", "bridge");
|
|
52494
52753
|
for (const f7 of ["launch-bridge.ps1", "register-protocol.ps1"]) {
|
|
52495
52754
|
try {
|
|
52496
|
-
|
|
52755
|
+
import_node_fs10.default.unlinkSync(import_node_path22.default.join(bridgeDir, f7));
|
|
52497
52756
|
} catch {
|
|
52498
52757
|
}
|
|
52499
52758
|
}
|
|
@@ -52502,17 +52761,17 @@ function unregisterProtocolHandler() {
|
|
|
52502
52761
|
logger29.warn("Failed to unregister Windows protocol handler", { error: e7 });
|
|
52503
52762
|
}
|
|
52504
52763
|
} else if (platform === "darwin") {
|
|
52505
|
-
const appDir =
|
|
52764
|
+
const appDir = import_node_path22.default.join(import_node_os13.default.homedir(), "Applications", "AHChatBridge.app");
|
|
52506
52765
|
try {
|
|
52507
|
-
|
|
52766
|
+
import_node_fs10.default.rmSync(appDir, { recursive: true, force: true });
|
|
52508
52767
|
logger29.info("macOS protocol handler unregistered");
|
|
52509
52768
|
} catch (e7) {
|
|
52510
52769
|
logger29.warn("Failed to unregister macOS protocol handler", { error: e7 });
|
|
52511
52770
|
}
|
|
52512
52771
|
} else {
|
|
52513
|
-
const desktopPath =
|
|
52772
|
+
const desktopPath = import_node_path22.default.join(import_node_os13.default.homedir(), ".local", "share", "applications", "ahchat-bridge.desktop");
|
|
52514
52773
|
try {
|
|
52515
|
-
|
|
52774
|
+
import_node_fs10.default.unlinkSync(desktopPath);
|
|
52516
52775
|
logger29.info("Linux protocol handler unregistered");
|
|
52517
52776
|
} catch (e7) {
|
|
52518
52777
|
logger29.warn("Failed to unregister Linux protocol handler", { error: e7 });
|
|
@@ -52520,20 +52779,21 @@ function unregisterProtocolHandler() {
|
|
|
52520
52779
|
}
|
|
52521
52780
|
}
|
|
52522
52781
|
function isProtocolRegistered() {
|
|
52523
|
-
const platform =
|
|
52782
|
+
const platform = import_node_os13.default.platform();
|
|
52783
|
+
const stableCliExists = import_node_fs10.default.existsSync(getStableCliPath());
|
|
52524
52784
|
if (platform === "win32") {
|
|
52525
52785
|
try {
|
|
52526
|
-
(0,
|
|
52527
|
-
return
|
|
52786
|
+
(0, import_node_child_process4.execSync)('REG QUERY "HKCU\\Software\\Classes\\ahchat" /ve', { stdio: "pipe" });
|
|
52787
|
+
return stableCliExists;
|
|
52528
52788
|
} catch {
|
|
52529
52789
|
return false;
|
|
52530
52790
|
}
|
|
52531
52791
|
} else if (platform === "darwin") {
|
|
52532
|
-
const appDir =
|
|
52533
|
-
return
|
|
52792
|
+
const appDir = import_node_path22.default.join(import_node_os13.default.homedir(), "Applications", "AHChatBridge.app");
|
|
52793
|
+
return stableCliExists && import_node_fs10.default.existsSync(import_node_path22.default.join(appDir, "Contents", "Info.plist"));
|
|
52534
52794
|
} else {
|
|
52535
|
-
const desktopPath =
|
|
52536
|
-
return
|
|
52795
|
+
const desktopPath = import_node_path22.default.join(import_node_os13.default.homedir(), ".local", "share", "applications", "ahchat-bridge.desktop");
|
|
52796
|
+
return stableCliExists && import_node_fs10.default.existsSync(desktopPath);
|
|
52537
52797
|
}
|
|
52538
52798
|
}
|
|
52539
52799
|
|
|
@@ -52541,14 +52801,14 @@ function isProtocolRegistered() {
|
|
|
52541
52801
|
var logger30 = createModuleLogger("bridge");
|
|
52542
52802
|
function readCliVersion() {
|
|
52543
52803
|
const candidates = [
|
|
52544
|
-
|
|
52545
|
-
|
|
52546
|
-
|
|
52804
|
+
import_node_path23.default.resolve(__dirname, "../package.json"),
|
|
52805
|
+
import_node_path23.default.resolve(__dirname, "../../package.json"),
|
|
52806
|
+
import_node_path23.default.resolve(process.cwd(), "packages/bridge/package.json")
|
|
52547
52807
|
];
|
|
52548
52808
|
for (const candidate of candidates) {
|
|
52549
|
-
if (!
|
|
52809
|
+
if (!import_node_fs11.default.existsSync(candidate)) continue;
|
|
52550
52810
|
try {
|
|
52551
|
-
const parsed = JSON.parse(
|
|
52811
|
+
const parsed = JSON.parse(import_node_fs11.default.readFileSync(candidate, "utf8"));
|
|
52552
52812
|
if (parsed && typeof parsed === "object" && "version" in parsed && typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
52553
52813
|
return parsed.version;
|
|
52554
52814
|
}
|
|
@@ -52556,26 +52816,7 @@ function readCliVersion() {
|
|
|
52556
52816
|
logger30.warn("Unable to read CLI package version candidate", { error: e7, candidate });
|
|
52557
52817
|
}
|
|
52558
52818
|
}
|
|
52559
|
-
return "0.1.
|
|
52560
|
-
}
|
|
52561
|
-
function resolveDataDir(dataDir) {
|
|
52562
|
-
const userHome = process.env.USERPROFILE || import_node_os13.default.homedir();
|
|
52563
|
-
if (/^~[/\\]/.test(dataDir)) {
|
|
52564
|
-
return import_node_path21.default.join(import_node_os13.default.homedir(), dataDir.slice(2));
|
|
52565
|
-
}
|
|
52566
|
-
if (dataDir === "$env:USERPROFILE") {
|
|
52567
|
-
return userHome;
|
|
52568
|
-
}
|
|
52569
|
-
if (dataDir.startsWith("$env:USERPROFILE\\") || dataDir.startsWith("$env:USERPROFILE/")) {
|
|
52570
|
-
return import_node_path21.default.join(userHome, dataDir.slice("$env:USERPROFILE".length + 1));
|
|
52571
|
-
}
|
|
52572
|
-
if (dataDir === "%USERPROFILE%") {
|
|
52573
|
-
return userHome;
|
|
52574
|
-
}
|
|
52575
|
-
if (dataDir.startsWith("%USERPROFILE%\\") || dataDir.startsWith("%USERPROFILE%/")) {
|
|
52576
|
-
return import_node_path21.default.join(userHome, dataDir.slice("%USERPROFILE%".length + 1));
|
|
52577
|
-
}
|
|
52578
|
-
return dataDir;
|
|
52819
|
+
return "0.1.21";
|
|
52579
52820
|
}
|
|
52580
52821
|
function parseAhchatUrl(url2) {
|
|
52581
52822
|
try {
|
|
@@ -52590,22 +52831,97 @@ function parseAhchatUrl(url2) {
|
|
|
52590
52831
|
const token = decodeURIComponent(rest.slice(lastTilde + 1));
|
|
52591
52832
|
if (!serverUrl || !token) return null;
|
|
52592
52833
|
return { serverUrl, token };
|
|
52593
|
-
} catch {
|
|
52834
|
+
} catch (e7) {
|
|
52835
|
+
logger30.warn("Unable to parse ahchat launch URL", { error: e7 });
|
|
52594
52836
|
return null;
|
|
52595
52837
|
}
|
|
52596
52838
|
}
|
|
52839
|
+
function assertSupportedNode() {
|
|
52840
|
+
const status = getNodeRuntimeStatus();
|
|
52841
|
+
if (status.supported) return;
|
|
52842
|
+
throw new Error(
|
|
52843
|
+
`Node.js ${MIN_NODE_MAJOR}+ is required to run AHChat Bridge. Current version: ${status.version}`
|
|
52844
|
+
);
|
|
52845
|
+
}
|
|
52597
52846
|
async function run(args) {
|
|
52598
|
-
|
|
52847
|
+
assertSupportedNode();
|
|
52848
|
+
process.env.PATH = buildAugmentedPath();
|
|
52849
|
+
const dataDir = args.dataDir ? resolveUserPath(args.dataDir) : void 0;
|
|
52599
52850
|
let config2 = loadBridgeConfig(dataDir ? { dataDir } : void 0);
|
|
52600
52851
|
if (args.serverUrl) {
|
|
52601
|
-
const
|
|
52602
|
-
|
|
52603
|
-
config2 = { ...config2, serverUrl: args.serverUrl, serverApiUrl: httpBase };
|
|
52852
|
+
const urls = normalizeBridgeServerUrls(args.serverUrl);
|
|
52853
|
+
config2 = { ...config2, serverUrl: urls.serverUrl, serverApiUrl: urls.serverApiUrl };
|
|
52604
52854
|
}
|
|
52605
52855
|
if (args.token) config2 = { ...config2, bridgeToken: args.token };
|
|
52606
52856
|
if (args.logLevel) config2 = { ...config2, logLevel: args.logLevel };
|
|
52607
52857
|
await startBridge(config2);
|
|
52608
52858
|
}
|
|
52859
|
+
function buildDoctorReport(args) {
|
|
52860
|
+
process.env.PATH = buildAugmentedPath();
|
|
52861
|
+
const node = getNodeRuntimeStatus();
|
|
52862
|
+
let server = null;
|
|
52863
|
+
if (args.serverUrl) {
|
|
52864
|
+
try {
|
|
52865
|
+
server = { ok: true, ...normalizeBridgeServerUrls(args.serverUrl) };
|
|
52866
|
+
} catch (e7) {
|
|
52867
|
+
server = {
|
|
52868
|
+
ok: false,
|
|
52869
|
+
error: e7 instanceof Error ? e7.message : String(e7)
|
|
52870
|
+
};
|
|
52871
|
+
}
|
|
52872
|
+
}
|
|
52873
|
+
const claude = resolveCommand(["claude", "anthropic-cli"]);
|
|
52874
|
+
return {
|
|
52875
|
+
node,
|
|
52876
|
+
npm: probeCommand("npm"),
|
|
52877
|
+
npx: probeCommand("npx"),
|
|
52878
|
+
claude: claude ? { ok: true, name: claude.name, path: claude.path } : { ok: false, name: "claude", message: "claude was not found on PATH" },
|
|
52879
|
+
dataDir: args.dataDir ? resolveUserPath(args.dataDir) : resolveUserPath("~/.ahchat"),
|
|
52880
|
+
server,
|
|
52881
|
+
tokenProvided: Boolean(args.token),
|
|
52882
|
+
pathPreview: (process.env.PATH ?? "").split(import_node_path23.default.delimiter).slice(0, 12)
|
|
52883
|
+
};
|
|
52884
|
+
}
|
|
52885
|
+
function writeDoctorText(report) {
|
|
52886
|
+
const node = report.node;
|
|
52887
|
+
const npm = report.npm;
|
|
52888
|
+
const npx = report.npx;
|
|
52889
|
+
const claude = report.claude;
|
|
52890
|
+
const server = report.server;
|
|
52891
|
+
const lines = [
|
|
52892
|
+
"AHChat Bridge doctor",
|
|
52893
|
+
`- Node: ${node.supported ? "ok" : "error"} (${node.version}, requires >=${MIN_NODE_MAJOR})`,
|
|
52894
|
+
`- npm: ${npm.ok ? `ok (${npm.version ?? npm.path})` : `missing (${npm.message ?? "not found"})`}`,
|
|
52895
|
+
`- npx: ${npx.ok ? `ok (${npx.version ?? npx.path})` : `missing (${npx.message ?? "not found"})`}`,
|
|
52896
|
+
`- Claude CLI: ${claude.ok ? `ok (${claude.path})` : `missing (${claude.message ?? "not found"})`}`,
|
|
52897
|
+
`- Data dir: ${String(report.dataDir)}`,
|
|
52898
|
+
`- Token: ${report.tokenProvided ? "provided" : "not provided"}`
|
|
52899
|
+
];
|
|
52900
|
+
if (server) {
|
|
52901
|
+
lines.push(
|
|
52902
|
+
server.ok ? `- Server: ok (${server.serverUrl}, api ${server.serverApiUrl})` : `- Server: error (${server.error ?? "invalid URL"})`
|
|
52903
|
+
);
|
|
52904
|
+
}
|
|
52905
|
+
if (!node.supported) {
|
|
52906
|
+
lines.push(`
|
|
52907
|
+
Install Node.js ${MIN_NODE_MAJOR}+ first, then rerun the bridge command.`);
|
|
52908
|
+
} else if (!npm.ok || !npx.ok) {
|
|
52909
|
+
lines.push("\nNode is installed, but npm/npx is not available on PATH. Reinstall Node.js or fix PATH.");
|
|
52910
|
+
} else if (!claude.ok) {
|
|
52911
|
+
lines.push("\nClaude Code CLI is missing. The bridge can try to install it on first run with npm.");
|
|
52912
|
+
}
|
|
52913
|
+
process.stdout.write(`${lines.join("\n")}
|
|
52914
|
+
`);
|
|
52915
|
+
}
|
|
52916
|
+
function doctor(args) {
|
|
52917
|
+
const report = buildDoctorReport(args);
|
|
52918
|
+
if (args.json) {
|
|
52919
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}
|
|
52920
|
+
`);
|
|
52921
|
+
return;
|
|
52922
|
+
}
|
|
52923
|
+
writeDoctorText(report);
|
|
52924
|
+
}
|
|
52609
52925
|
var cli = dist_default("ahchat-bridge");
|
|
52610
52926
|
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) => {
|
|
52611
52927
|
void run(args).catch((e7) => {
|
|
@@ -52613,6 +52929,9 @@ cli.command("run", "Start the bridge and connect to server").option("--server-ur
|
|
|
52613
52929
|
process.exit(1);
|
|
52614
52930
|
});
|
|
52615
52931
|
});
|
|
52932
|
+
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("--data-dir <dir>", "Data directory (default: ~/.ahchat)").option("--json", "Print machine-readable JSON").action((args) => {
|
|
52933
|
+
doctor(args);
|
|
52934
|
+
});
|
|
52616
52935
|
cli.command("launch", "Launch bridge from ahchat:// URL (called by OS)").option("--url <url>", "ahchat:// URL with server and token params").action((args) => {
|
|
52617
52936
|
const parsed = parseAhchatUrl(args.url);
|
|
52618
52937
|
if (!parsed) {
|