cli-remote-agent 1.0.6 → 1.0.7
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.js +139 -92
- package/dist/cli.js.map +1 -1
- package/dist/index.js +123 -84
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -251,20 +251,58 @@ function startLocalControl(port, onHook) {
|
|
|
251
251
|
return server;
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
// src/pty-helper-fix.ts
|
|
255
|
+
var import_node_module = require("module");
|
|
256
|
+
var import_node_child_process = require("child_process");
|
|
257
|
+
var import_fs3 = __toESM(require("fs"));
|
|
258
|
+
var import_path3 = __toESM(require("path"));
|
|
259
|
+
function ensurePtyHelperExecutable() {
|
|
260
|
+
if (process.platform === "win32") return;
|
|
261
|
+
try {
|
|
262
|
+
const nodeRequire = (0, import_node_module.createRequire)(__filename);
|
|
263
|
+
const ptyMain = nodeRequire.resolve("node-pty");
|
|
264
|
+
const ptyDir = import_path3.default.dirname(import_path3.default.dirname(ptyMain));
|
|
265
|
+
const candidates = [import_path3.default.join(ptyDir, "build", "Release", "spawn-helper")];
|
|
266
|
+
const prebuilds = import_path3.default.join(ptyDir, "prebuilds");
|
|
267
|
+
try {
|
|
268
|
+
for (const d of import_fs3.default.readdirSync(prebuilds)) {
|
|
269
|
+
candidates.push(import_path3.default.join(prebuilds, d, "spawn-helper"));
|
|
270
|
+
}
|
|
271
|
+
} catch {
|
|
272
|
+
}
|
|
273
|
+
for (const file of candidates) {
|
|
274
|
+
try {
|
|
275
|
+
const mode = import_fs3.default.statSync(file).mode;
|
|
276
|
+
if (!(mode & 73)) {
|
|
277
|
+
import_fs3.default.chmodSync(file, mode | 493);
|
|
278
|
+
logger.info({ file }, "Restored execute bit on node-pty spawn-helper");
|
|
279
|
+
}
|
|
280
|
+
} catch {
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (process.platform === "darwin") {
|
|
284
|
+
(0, import_node_child_process.execFile)("xattr", ["-dr", "com.apple.quarantine", ptyDir], () => {
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
} catch (err) {
|
|
288
|
+
logger.warn({ error: err?.message }, "Could not verify node-pty spawn-helper permissions");
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
254
292
|
// src/tmux.ts
|
|
255
293
|
var import_child_process2 = require("child_process");
|
|
256
294
|
var import_util2 = require("util");
|
|
257
|
-
var
|
|
258
|
-
var
|
|
295
|
+
var import_fs5 = __toESM(require("fs"));
|
|
296
|
+
var import_path5 = __toESM(require("path"));
|
|
259
297
|
|
|
260
298
|
// src/claude-live.ts
|
|
261
|
-
var
|
|
262
|
-
var
|
|
299
|
+
var import_fs4 = __toESM(require("fs"));
|
|
300
|
+
var import_path4 = __toESM(require("path"));
|
|
263
301
|
var import_os2 = __toESM(require("os"));
|
|
264
302
|
var import_child_process = require("child_process");
|
|
265
303
|
var import_util = require("util");
|
|
266
304
|
var execFileAsync = (0, import_util.promisify)(import_child_process.execFile);
|
|
267
|
-
var LIVE_SESSIONS_DIR =
|
|
305
|
+
var LIVE_SESSIONS_DIR = import_path4.default.join(import_os2.default.homedir(), ".claude", "sessions");
|
|
268
306
|
function isAlive(pid) {
|
|
269
307
|
try {
|
|
270
308
|
process.kill(pid, 0);
|
|
@@ -276,14 +314,14 @@ function isAlive(pid) {
|
|
|
276
314
|
function getLiveClaudeSessions() {
|
|
277
315
|
let files;
|
|
278
316
|
try {
|
|
279
|
-
files =
|
|
317
|
+
files = import_fs4.default.readdirSync(LIVE_SESSIONS_DIR).filter((f) => f.endsWith(".json"));
|
|
280
318
|
} catch {
|
|
281
319
|
return [];
|
|
282
320
|
}
|
|
283
321
|
const out = [];
|
|
284
322
|
for (const f of files) {
|
|
285
323
|
try {
|
|
286
|
-
const obj = JSON.parse(
|
|
324
|
+
const obj = JSON.parse(import_fs4.default.readFileSync(import_path4.default.join(LIVE_SESSIONS_DIR, f), "utf-8"));
|
|
287
325
|
if (typeof obj?.pid !== "number" || !isAlive(obj.pid)) continue;
|
|
288
326
|
out.push({
|
|
289
327
|
pid: obj.pid,
|
|
@@ -325,14 +363,14 @@ var IS_WIN = process.platform === "win32";
|
|
|
325
363
|
var cachedTmuxPath;
|
|
326
364
|
function resolveTmuxPath() {
|
|
327
365
|
if (cachedTmuxPath !== void 0) return cachedTmuxPath;
|
|
328
|
-
const dirs = (process.env.PATH || "").split(
|
|
366
|
+
const dirs = (process.env.PATH || "").split(import_path5.default.delimiter).filter(Boolean);
|
|
329
367
|
for (const extra of ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin", "/opt/local/bin"]) {
|
|
330
368
|
if (!dirs.includes(extra)) dirs.push(extra);
|
|
331
369
|
}
|
|
332
370
|
for (const dir of dirs) {
|
|
333
|
-
const candidate =
|
|
371
|
+
const candidate = import_path5.default.join(dir, "tmux");
|
|
334
372
|
try {
|
|
335
|
-
|
|
373
|
+
import_fs5.default.accessSync(candidate, import_fs5.default.constants.X_OK);
|
|
336
374
|
cachedTmuxPath = candidate;
|
|
337
375
|
return candidate;
|
|
338
376
|
} catch {
|
|
@@ -382,8 +420,8 @@ async function enrichWithPanesAndClaude(sessions2) {
|
|
|
382
420
|
const { file, args } = tmuxCmd(["list-panes", "-a", "-F", paneFmt]);
|
|
383
421
|
const { stdout } = await execFileAsync2(file, args, { timeout: 6e3 });
|
|
384
422
|
const panes = stdout.split("\n").map((line) => line.replace(/\r$/, "").trim()).filter(Boolean).map((line) => {
|
|
385
|
-
const [session, pid,
|
|
386
|
-
return { session, pid: parseInt(pid, 10) || 0, path:
|
|
423
|
+
const [session, pid, path10, activeFlags] = line.split(" ");
|
|
424
|
+
return { session, pid: parseInt(pid, 10) || 0, path: path10 || "", active: activeFlags === "11" };
|
|
387
425
|
});
|
|
388
426
|
const byName = new Map(sessions2.map((s) => [s.name, s]));
|
|
389
427
|
for (const pane of panes) {
|
|
@@ -425,13 +463,13 @@ function buildTmuxLaunch(name, launch) {
|
|
|
425
463
|
|
|
426
464
|
// src/heartbeat.ts
|
|
427
465
|
var import_os4 = __toESM(require("os"));
|
|
428
|
-
var
|
|
466
|
+
var import_path7 = __toESM(require("path"));
|
|
429
467
|
var import_child_process4 = require("child_process");
|
|
430
468
|
|
|
431
469
|
// src/pty-session.ts
|
|
432
470
|
var pty = __toESM(require("node-pty"));
|
|
433
|
-
var
|
|
434
|
-
var
|
|
471
|
+
var import_fs6 = require("fs");
|
|
472
|
+
var import_path6 = require("path");
|
|
435
473
|
var import_os3 = require("os");
|
|
436
474
|
|
|
437
475
|
// src/shell.ts
|
|
@@ -451,22 +489,22 @@ function detectShell(preference) {
|
|
|
451
489
|
|
|
452
490
|
// src/pty-session.ts
|
|
453
491
|
var THRESHOLD = 3;
|
|
454
|
-
var INIT_DIR = (0,
|
|
455
|
-
var BASH_INIT = (0,
|
|
456
|
-
var ZSH_DIR = (0,
|
|
457
|
-
var ZSH_RC = (0,
|
|
458
|
-
var ZSH_ENV = (0,
|
|
492
|
+
var INIT_DIR = (0, import_path6.join)((0, import_os3.tmpdir)(), "crc-shell-init");
|
|
493
|
+
var BASH_INIT = (0, import_path6.join)(INIT_DIR, "bashrc");
|
|
494
|
+
var ZSH_DIR = (0, import_path6.join)(INIT_DIR, "zsh");
|
|
495
|
+
var ZSH_RC = (0, import_path6.join)(ZSH_DIR, ".zshrc");
|
|
496
|
+
var ZSH_ENV = (0, import_path6.join)(ZSH_DIR, ".zshenv");
|
|
459
497
|
var INIT_VERSION = "2";
|
|
460
498
|
function ensureInitFiles() {
|
|
461
|
-
const versionFile = (0,
|
|
462
|
-
if ((0,
|
|
499
|
+
const versionFile = (0, import_path6.join)(INIT_DIR, ".version");
|
|
500
|
+
if ((0, import_fs6.existsSync)(versionFile)) {
|
|
463
501
|
try {
|
|
464
|
-
if ((0,
|
|
502
|
+
if ((0, import_fs6.readFileSync)(versionFile, "utf-8").trim() === INIT_VERSION) return;
|
|
465
503
|
} catch {
|
|
466
504
|
}
|
|
467
505
|
}
|
|
468
|
-
(0,
|
|
469
|
-
(0,
|
|
506
|
+
(0, import_fs6.mkdirSync)(ZSH_DIR, { recursive: true });
|
|
507
|
+
(0, import_fs6.writeFileSync)(BASH_INIT, [
|
|
470
508
|
"[ -f ~/.bash_profile ] && source ~/.bash_profile",
|
|
471
509
|
"[ -f ~/.bashrc ] && source ~/.bashrc",
|
|
472
510
|
"__crc_s=$SECONDS",
|
|
@@ -477,11 +515,11 @@ function ensureInitFiles() {
|
|
|
477
515
|
`PROMPT_COMMAND='[ "$__crc_armed" = 1 ] && [ \${__crc_elapsed:-0} -ge ${THRESHOLD} ] && printf "\\a"; __crc_armed=1; eval "$__crc_orig_pc"'`,
|
|
478
516
|
""
|
|
479
517
|
].join("\n"), "utf-8");
|
|
480
|
-
(0,
|
|
518
|
+
(0, import_fs6.writeFileSync)(ZSH_ENV, [
|
|
481
519
|
'[ -f "${ZDOTDIR_ORIG:-$HOME}/.zshenv" ] && source "${ZDOTDIR_ORIG:-$HOME}/.zshenv"',
|
|
482
520
|
""
|
|
483
521
|
].join("\n"), "utf-8");
|
|
484
|
-
(0,
|
|
522
|
+
(0, import_fs6.writeFileSync)(ZSH_RC, [
|
|
485
523
|
'[ -f "${ZDOTDIR_ORIG:-$HOME}/.zshrc" ] && source "${ZDOTDIR_ORIG:-$HOME}/.zshrc"',
|
|
486
524
|
"__crc_s=$SECONDS",
|
|
487
525
|
"__crc_armed=0",
|
|
@@ -494,14 +532,14 @@ function ensureInitFiles() {
|
|
|
494
532
|
"fi",
|
|
495
533
|
""
|
|
496
534
|
].join("\n"), "utf-8");
|
|
497
|
-
(0,
|
|
535
|
+
(0, import_fs6.writeFileSync)(versionFile, INIT_VERSION, "utf-8");
|
|
498
536
|
}
|
|
499
537
|
function resolveCwd(cwd) {
|
|
500
538
|
const candidates = process.platform === "win32" ? [cwd, (0, import_os3.homedir)(), process.env.USERPROFILE, process.env.HOME] : [cwd, (0, import_os3.homedir)(), process.env.HOME, process.env.USERPROFILE];
|
|
501
539
|
for (const c of candidates) {
|
|
502
540
|
if (c) {
|
|
503
541
|
try {
|
|
504
|
-
if ((0,
|
|
542
|
+
if ((0, import_fs6.existsSync)(c)) return c;
|
|
505
543
|
} catch {
|
|
506
544
|
}
|
|
507
545
|
}
|
|
@@ -727,7 +765,7 @@ function buildHeartbeat(homeDir) {
|
|
|
727
765
|
memoryUsage: Math.round((totalMem - freeMem) / totalMem * 100),
|
|
728
766
|
uptime: Math.round(import_os4.default.uptime()),
|
|
729
767
|
activeSessions: getActiveSessionCount(),
|
|
730
|
-
pathSeparator:
|
|
768
|
+
pathSeparator: import_path7.default.sep,
|
|
731
769
|
homeDirectory: homeDir || import_os4.default.homedir(),
|
|
732
770
|
rootPaths: getRootPaths(),
|
|
733
771
|
capabilities: { terminal: true, fileTransfer: false }
|
|
@@ -735,33 +773,33 @@ function buildHeartbeat(homeDir) {
|
|
|
735
773
|
}
|
|
736
774
|
|
|
737
775
|
// src/file-explorer.ts
|
|
738
|
-
var
|
|
739
|
-
var
|
|
776
|
+
var import_fs7 = __toESM(require("fs"));
|
|
777
|
+
var import_path8 = __toESM(require("path"));
|
|
740
778
|
var import_os5 = __toESM(require("os"));
|
|
741
|
-
var SECRET_DIR =
|
|
779
|
+
var SECRET_DIR = import_path8.default.join(import_os5.default.homedir(), ".crc-agent");
|
|
742
780
|
function isInSecretDir(resolved) {
|
|
743
|
-
const rel =
|
|
744
|
-
return rel === "" || !rel.startsWith(".." +
|
|
781
|
+
const rel = import_path8.default.relative(SECRET_DIR, resolved);
|
|
782
|
+
return rel === "" || !rel.startsWith(".." + import_path8.default.sep) && rel !== ".." && !import_path8.default.isAbsolute(rel);
|
|
745
783
|
}
|
|
746
784
|
function listDirectory(dirPath) {
|
|
747
785
|
try {
|
|
748
|
-
const resolved =
|
|
786
|
+
const resolved = import_path8.default.resolve(dirPath);
|
|
749
787
|
if (isInSecretDir(resolved)) {
|
|
750
788
|
return { entries: [], error: "Access denied" };
|
|
751
789
|
}
|
|
752
|
-
if (!
|
|
790
|
+
if (!import_fs7.default.existsSync(resolved)) {
|
|
753
791
|
return { entries: [], error: "Path does not exist" };
|
|
754
792
|
}
|
|
755
|
-
const stat =
|
|
793
|
+
const stat = import_fs7.default.statSync(resolved);
|
|
756
794
|
if (!stat.isDirectory()) {
|
|
757
795
|
return { entries: [], error: "Not a directory" };
|
|
758
796
|
}
|
|
759
|
-
const dirents =
|
|
797
|
+
const dirents = import_fs7.default.readdirSync(resolved, { withFileTypes: true });
|
|
760
798
|
const entries = [];
|
|
761
799
|
for (const dirent of dirents) {
|
|
762
800
|
try {
|
|
763
|
-
const fullPath =
|
|
764
|
-
const s =
|
|
801
|
+
const fullPath = import_path8.default.join(resolved, dirent.name);
|
|
802
|
+
const s = import_fs7.default.statSync(fullPath);
|
|
765
803
|
entries.push({
|
|
766
804
|
name: dirent.name,
|
|
767
805
|
isDirectory: dirent.isDirectory(),
|
|
@@ -783,22 +821,22 @@ function listDirectory(dirPath) {
|
|
|
783
821
|
}
|
|
784
822
|
async function downloadFile(filePath, serverUrl, secret, agentId) {
|
|
785
823
|
try {
|
|
786
|
-
const resolved =
|
|
824
|
+
const resolved = import_path8.default.resolve(filePath);
|
|
787
825
|
if (isInSecretDir(resolved)) {
|
|
788
826
|
return { error: "Access denied" };
|
|
789
827
|
}
|
|
790
|
-
if (!
|
|
828
|
+
if (!import_fs7.default.existsSync(resolved)) {
|
|
791
829
|
return { error: "File does not exist" };
|
|
792
830
|
}
|
|
793
|
-
const stat =
|
|
831
|
+
const stat = import_fs7.default.statSync(resolved);
|
|
794
832
|
if (stat.isDirectory()) {
|
|
795
833
|
return { error: "Cannot download a directory" };
|
|
796
834
|
}
|
|
797
835
|
if (stat.size > FILE_MAX_SIZE) {
|
|
798
836
|
return { error: `File too large (max ${FILE_MAX_SIZE} bytes)` };
|
|
799
837
|
}
|
|
800
|
-
const fileName =
|
|
801
|
-
const fileStream =
|
|
838
|
+
const fileName = import_path8.default.basename(resolved);
|
|
839
|
+
const fileStream = import_fs7.default.createReadStream(resolved);
|
|
802
840
|
const baseUrl = serverUrl.replace("wss://", "https://").replace("ws://", "http://");
|
|
803
841
|
const url = `${baseUrl}/api/files/receive`;
|
|
804
842
|
const res = await fetch(url, {
|
|
@@ -831,12 +869,12 @@ async function downloadFile(filePath, serverUrl, secret, agentId) {
|
|
|
831
869
|
// src/vpn-manager.ts
|
|
832
870
|
var import_child_process5 = require("child_process");
|
|
833
871
|
var import_util3 = require("util");
|
|
834
|
-
var
|
|
835
|
-
var
|
|
872
|
+
var import_fs8 = __toESM(require("fs"));
|
|
873
|
+
var import_path9 = __toESM(require("path"));
|
|
836
874
|
var import_os6 = __toESM(require("os"));
|
|
837
875
|
var execAsync = (0, import_util3.promisify)(import_child_process5.exec);
|
|
838
876
|
var isWindows = process.platform === "win32";
|
|
839
|
-
var VPN_DIR =
|
|
877
|
+
var VPN_DIR = import_path9.default.join(import_os6.default.homedir(), ".crc-agent", "vpn");
|
|
840
878
|
function shq(value) {
|
|
841
879
|
return value.replace(/'/g, "'\\''");
|
|
842
880
|
}
|
|
@@ -855,8 +893,8 @@ async function runCmd(cmd, shell) {
|
|
|
855
893
|
}
|
|
856
894
|
function getConfigPath(profile) {
|
|
857
895
|
const file = profile.configFile || `${profile.id}.conf`;
|
|
858
|
-
if (
|
|
859
|
-
return
|
|
896
|
+
if (import_path9.default.isAbsolute(file)) return file;
|
|
897
|
+
return import_path9.default.join(VPN_DIR, file);
|
|
860
898
|
}
|
|
861
899
|
async function getScutilStatus(serviceName) {
|
|
862
900
|
const { stdout } = await runCmd(`scutil --nc status '${shq(serviceName)}'`);
|
|
@@ -972,7 +1010,7 @@ async function connectWireGuard(profile) {
|
|
|
972
1010
|
const tunnelName = profile.tunnelName || profile.id;
|
|
973
1011
|
if (isWindows) {
|
|
974
1012
|
const confPath2 = getConfigPath(profile);
|
|
975
|
-
if (!
|
|
1013
|
+
if (!import_fs8.default.existsSync(confPath2)) {
|
|
976
1014
|
return `Config file not found: ${confPath2}`;
|
|
977
1015
|
}
|
|
978
1016
|
const script = `
|
|
@@ -998,7 +1036,7 @@ async function connectWireGuard(profile) {
|
|
|
998
1036
|
async function connectOpenVpn(profile) {
|
|
999
1037
|
if (isWindows) {
|
|
1000
1038
|
const confPath2 = getConfigPath(profile);
|
|
1001
|
-
if (!
|
|
1039
|
+
if (!import_fs8.default.existsSync(confPath2)) {
|
|
1002
1040
|
return `Config file not found: ${confPath2}`;
|
|
1003
1041
|
}
|
|
1004
1042
|
const connector = "C:\\Program Files\\OpenVPN Connect\\ovpnconnector.exe";
|
|
@@ -1025,7 +1063,7 @@ async function connectOpenVpn(profile) {
|
|
|
1025
1063
|
return scutilStart(profile.serviceName);
|
|
1026
1064
|
}
|
|
1027
1065
|
const confPath = getConfigPath(profile);
|
|
1028
|
-
if (!
|
|
1066
|
+
if (!import_fs8.default.existsSync(confPath)) {
|
|
1029
1067
|
return `Config file not found: ${confPath}`;
|
|
1030
1068
|
}
|
|
1031
1069
|
const { stderr } = await runCmd(`sudo openvpn --config '${shq(confPath)}' --daemon`);
|
|
@@ -1034,7 +1072,7 @@ async function connectOpenVpn(profile) {
|
|
|
1034
1072
|
async function connectAzure(profile) {
|
|
1035
1073
|
if (isWindows) {
|
|
1036
1074
|
const confPath = getConfigPath(profile);
|
|
1037
|
-
if (!
|
|
1075
|
+
if (!import_fs8.default.existsSync(confPath)) {
|
|
1038
1076
|
return `Config file not found: ${confPath}`;
|
|
1039
1077
|
}
|
|
1040
1078
|
await runCmd(`& 'AzureVpn.exe' -i '${psq(confPath)}' 2>&1`);
|
|
@@ -1156,8 +1194,8 @@ async function disconnectVpn(configs, profileId) {
|
|
|
1156
1194
|
}
|
|
1157
1195
|
|
|
1158
1196
|
// src/claude-sessions.ts
|
|
1159
|
-
var
|
|
1160
|
-
var
|
|
1197
|
+
var import_fs9 = __toESM(require("fs"));
|
|
1198
|
+
var import_path10 = __toESM(require("path"));
|
|
1161
1199
|
var import_os7 = __toESM(require("os"));
|
|
1162
1200
|
var import_readline = __toESM(require("readline"));
|
|
1163
1201
|
|
|
@@ -1185,10 +1223,10 @@ function findProjectDirs(allDirs, filterProjectPath) {
|
|
|
1185
1223
|
}
|
|
1186
1224
|
|
|
1187
1225
|
// src/claude-sessions.ts
|
|
1188
|
-
var CLAUDE_PROJECTS_DIR =
|
|
1226
|
+
var CLAUDE_PROJECTS_DIR = import_path10.default.join(import_os7.default.homedir(), ".claude", "projects");
|
|
1189
1227
|
async function parseSessionFile(filePath) {
|
|
1190
1228
|
try {
|
|
1191
|
-
const stream =
|
|
1229
|
+
const stream = import_fs9.default.createReadStream(filePath, { encoding: "utf-8" });
|
|
1192
1230
|
const rl = import_readline.default.createInterface({ input: stream, crlfDelay: Infinity });
|
|
1193
1231
|
let firstMessage = "";
|
|
1194
1232
|
let lastTimestamp = "";
|
|
@@ -1236,17 +1274,17 @@ async function parseSessionFile(filePath) {
|
|
|
1236
1274
|
}
|
|
1237
1275
|
async function listClaudeSessions(filterProjectPath) {
|
|
1238
1276
|
const sessions2 = [];
|
|
1239
|
-
if (!
|
|
1277
|
+
if (!import_fs9.default.existsSync(CLAUDE_PROJECTS_DIR)) return sessions2;
|
|
1240
1278
|
const isDirSafe = (d) => {
|
|
1241
1279
|
try {
|
|
1242
|
-
return
|
|
1280
|
+
return import_fs9.default.statSync(import_path10.default.join(CLAUDE_PROJECTS_DIR, d)).isDirectory();
|
|
1243
1281
|
} catch {
|
|
1244
1282
|
return false;
|
|
1245
1283
|
}
|
|
1246
1284
|
};
|
|
1247
1285
|
let allEntries;
|
|
1248
1286
|
try {
|
|
1249
|
-
allEntries =
|
|
1287
|
+
allEntries = import_fs9.default.readdirSync(CLAUDE_PROJECTS_DIR);
|
|
1250
1288
|
} catch {
|
|
1251
1289
|
return sessions2;
|
|
1252
1290
|
}
|
|
@@ -1259,16 +1297,16 @@ async function listClaudeSessions(filterProjectPath) {
|
|
|
1259
1297
|
projectDirs = allEntries.filter((d) => isDirSafe(d) && !d.startsWith("-private-"));
|
|
1260
1298
|
}
|
|
1261
1299
|
for (const dirName of projectDirs) {
|
|
1262
|
-
const dirPath =
|
|
1300
|
+
const dirPath = import_path10.default.join(CLAUDE_PROJECTS_DIR, dirName);
|
|
1263
1301
|
let files;
|
|
1264
1302
|
try {
|
|
1265
|
-
files =
|
|
1303
|
+
files = import_fs9.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
|
|
1266
1304
|
} catch {
|
|
1267
1305
|
continue;
|
|
1268
1306
|
}
|
|
1269
1307
|
for (const file of files) {
|
|
1270
1308
|
const sessionId = file.replace(".jsonl", "");
|
|
1271
|
-
const parsed = await parseSessionFile(
|
|
1309
|
+
const parsed = await parseSessionFile(import_path10.default.join(dirPath, file));
|
|
1272
1310
|
if (!parsed) continue;
|
|
1273
1311
|
const projectPath = parsed.cwd || dirName.replace(/^-/, "/").replace(/-/g, "/");
|
|
1274
1312
|
sessions2.push({
|
|
@@ -1288,21 +1326,21 @@ async function listClaudeSessions(filterProjectPath) {
|
|
|
1288
1326
|
}
|
|
1289
1327
|
|
|
1290
1328
|
// src/claude-conversation.ts
|
|
1291
|
-
var
|
|
1292
|
-
var
|
|
1329
|
+
var import_fs10 = __toESM(require("fs"));
|
|
1330
|
+
var import_path11 = __toESM(require("path"));
|
|
1293
1331
|
var import_os8 = __toESM(require("os"));
|
|
1294
1332
|
var import_readline2 = __toESM(require("readline"));
|
|
1295
|
-
var CLAUDE_PROJECTS_DIR2 =
|
|
1333
|
+
var CLAUDE_PROJECTS_DIR2 = import_path11.default.join(import_os8.default.homedir(), ".claude", "projects");
|
|
1296
1334
|
function findProjectDir(projectPath) {
|
|
1297
1335
|
const encoded = encodeProjectPath(projectPath);
|
|
1298
|
-
const dirPath =
|
|
1299
|
-
if (
|
|
1300
|
-
if (!
|
|
1336
|
+
const dirPath = import_path11.default.join(CLAUDE_PROJECTS_DIR2, encoded);
|
|
1337
|
+
if (import_fs10.default.existsSync(dirPath)) return dirPath;
|
|
1338
|
+
if (!import_fs10.default.existsSync(CLAUDE_PROJECTS_DIR2)) return null;
|
|
1301
1339
|
let allDirs;
|
|
1302
1340
|
try {
|
|
1303
|
-
allDirs =
|
|
1341
|
+
allDirs = import_fs10.default.readdirSync(CLAUDE_PROJECTS_DIR2).filter((d) => {
|
|
1304
1342
|
try {
|
|
1305
|
-
return
|
|
1343
|
+
return import_fs10.default.statSync(import_path11.default.join(CLAUDE_PROJECTS_DIR2, d)).isDirectory();
|
|
1306
1344
|
} catch {
|
|
1307
1345
|
return false;
|
|
1308
1346
|
}
|
|
@@ -1312,23 +1350,23 @@ function findProjectDir(projectPath) {
|
|
|
1312
1350
|
}
|
|
1313
1351
|
const matches = findProjectDirs(allDirs, projectPath);
|
|
1314
1352
|
if (matches.length > 0) {
|
|
1315
|
-
return
|
|
1353
|
+
return import_path11.default.join(CLAUDE_PROJECTS_DIR2, matches[0]);
|
|
1316
1354
|
}
|
|
1317
1355
|
return null;
|
|
1318
1356
|
}
|
|
1319
1357
|
function findSessionFileById(sessionId) {
|
|
1320
1358
|
if (!/^[A-Za-z0-9._-]+$/.test(sessionId)) return null;
|
|
1321
|
-
if (!
|
|
1359
|
+
if (!import_fs10.default.existsSync(CLAUDE_PROJECTS_DIR2)) return null;
|
|
1322
1360
|
let dirs;
|
|
1323
1361
|
try {
|
|
1324
|
-
dirs =
|
|
1362
|
+
dirs = import_fs10.default.readdirSync(CLAUDE_PROJECTS_DIR2);
|
|
1325
1363
|
} catch {
|
|
1326
1364
|
return null;
|
|
1327
1365
|
}
|
|
1328
1366
|
for (const dir of dirs) {
|
|
1329
|
-
const candidate =
|
|
1367
|
+
const candidate = import_path11.default.join(CLAUDE_PROJECTS_DIR2, dir, `${sessionId}.jsonl`);
|
|
1330
1368
|
try {
|
|
1331
|
-
if (
|
|
1369
|
+
if (import_fs10.default.statSync(candidate).isFile()) return candidate;
|
|
1332
1370
|
} catch {
|
|
1333
1371
|
}
|
|
1334
1372
|
}
|
|
@@ -1339,20 +1377,20 @@ function findLatestSessionFile(projectPath) {
|
|
|
1339
1377
|
if (!dirPath) return null;
|
|
1340
1378
|
let entries;
|
|
1341
1379
|
try {
|
|
1342
|
-
entries =
|
|
1380
|
+
entries = import_fs10.default.readdirSync(dirPath);
|
|
1343
1381
|
} catch {
|
|
1344
1382
|
return null;
|
|
1345
1383
|
}
|
|
1346
1384
|
const files = entries.filter((f) => f.endsWith(".jsonl") && !f.includes("/")).map((f) => {
|
|
1347
1385
|
try {
|
|
1348
|
-
return { name: f, mtime:
|
|
1386
|
+
return { name: f, mtime: import_fs10.default.statSync(import_path11.default.join(dirPath, f)).mtimeMs };
|
|
1349
1387
|
} catch {
|
|
1350
1388
|
return null;
|
|
1351
1389
|
}
|
|
1352
1390
|
}).filter((f) => f !== null).sort((a, b) => b.mtime - a.mtime);
|
|
1353
1391
|
if (files.length === 0) return null;
|
|
1354
1392
|
return {
|
|
1355
|
-
filePath:
|
|
1393
|
+
filePath: import_path11.default.join(dirPath, files[0].name),
|
|
1356
1394
|
sessionId: files[0].name.replace(".jsonl", "")
|
|
1357
1395
|
};
|
|
1358
1396
|
}
|
|
@@ -1362,8 +1400,8 @@ async function readConversation(projectPath, afterLine = 0, specificSessionId) {
|
|
|
1362
1400
|
if (specificSessionId) {
|
|
1363
1401
|
sessionId = specificSessionId;
|
|
1364
1402
|
const dirPath = findProjectDir(projectPath);
|
|
1365
|
-
const direct = dirPath ?
|
|
1366
|
-
if (direct &&
|
|
1403
|
+
const direct = dirPath ? import_path11.default.join(dirPath, `${specificSessionId}.jsonl`) : null;
|
|
1404
|
+
if (direct && import_fs10.default.existsSync(direct)) {
|
|
1367
1405
|
filePath = direct;
|
|
1368
1406
|
} else {
|
|
1369
1407
|
const byId = findSessionFileById(specificSessionId);
|
|
@@ -1377,7 +1415,7 @@ async function readConversation(projectPath, afterLine = 0, specificSessionId) {
|
|
|
1377
1415
|
sessionId = found.sessionId;
|
|
1378
1416
|
}
|
|
1379
1417
|
try {
|
|
1380
|
-
const stream =
|
|
1418
|
+
const stream = import_fs10.default.createReadStream(filePath, { encoding: "utf-8" });
|
|
1381
1419
|
const rl = import_readline2.default.createInterface({ input: stream, crlfDelay: Infinity });
|
|
1382
1420
|
const messages = [];
|
|
1383
1421
|
let lineNum = 0;
|
|
@@ -1466,6 +1504,7 @@ if (!isConfigured()) {
|
|
|
1466
1504
|
}
|
|
1467
1505
|
var config = loadConfig();
|
|
1468
1506
|
logger.info({ agentId: config.agentId, serverUrl: config.serverUrl }, "Starting agent");
|
|
1507
|
+
ensurePtyHelperExecutable();
|
|
1469
1508
|
process.on("unhandledRejection", (reason) => {
|
|
1470
1509
|
logger.error({ reason }, "Unhandled promise rejection (agent kept alive)");
|
|
1471
1510
|
});
|