claude-threads 1.0.11 → 1.0.13
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/CHANGELOG.md +15 -0
- package/dist/index.js +178 -55
- package/dist/mcp/permission-server.js +69 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.13] - 2026-01-16
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **Claude CLI detection for non-standard installations** - Improved detection for users who installed Claude CLI via non-npm methods (#222)
|
|
12
|
+
- Searches common installation paths (`/usr/local/bin`, `~/.local/bin`, `~/.bun/bin`, etc.)
|
|
13
|
+
- Uses `which claude` to resolve symlinks
|
|
14
|
+
- Parses multiple version output formats
|
|
15
|
+
- Shows helpful debug info (PATH directories) when not found
|
|
16
|
+
- Added `getClaudePath()` helper shared between version check and CLI spawning
|
|
17
|
+
|
|
18
|
+
## [1.0.12] - 2026-01-15
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- **Skipped file feedback posting** - Fixed swapped arguments in createPost call that caused "Invalid RootId parameter" errors when posting feedback for skipped files (#221)
|
|
22
|
+
|
|
8
23
|
## [1.0.11] - 2026-01-15
|
|
9
24
|
|
|
10
25
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -46546,7 +46546,7 @@ function configExists() {
|
|
|
46546
46546
|
|
|
46547
46547
|
// src/onboarding.ts
|
|
46548
46548
|
var import_prompts = __toESM(require_prompts3(), 1);
|
|
46549
|
-
import { existsSync as
|
|
46549
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
46550
46550
|
import { join, dirname as dirname2 } from "path";
|
|
46551
46551
|
import { fileURLToPath } from "url";
|
|
46552
46552
|
|
|
@@ -46570,52 +46570,147 @@ var red = (s) => `${colors.red}${s}${colors.reset}`;
|
|
|
46570
46570
|
// src/claude/version-check.ts
|
|
46571
46571
|
var import_semver = __toESM(require_semver2(), 1);
|
|
46572
46572
|
import { execSync } from "child_process";
|
|
46573
|
+
import { existsSync as existsSync2 } from "fs";
|
|
46574
|
+
var COMMON_CLAUDE_PATHS = [
|
|
46575
|
+
"/usr/local/bin/claude",
|
|
46576
|
+
"/opt/homebrew/bin/claude",
|
|
46577
|
+
`${process.env.HOME}/.local/bin/claude`,
|
|
46578
|
+
`${process.env.HOME}/.npm-global/bin/claude`,
|
|
46579
|
+
`${process.env.HOME}/.bun/bin/claude`,
|
|
46580
|
+
"/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
46581
|
+
];
|
|
46573
46582
|
var CLAUDE_CLI_VERSION_RANGE = ">=2.0.74 <2.2.0";
|
|
46574
|
-
function
|
|
46575
|
-
|
|
46583
|
+
function tryClaudeVersion(claudePath) {
|
|
46584
|
+
try {
|
|
46585
|
+
const output = execSync(`"${claudePath}" --version`, {
|
|
46586
|
+
encoding: "utf8",
|
|
46587
|
+
timeout: 5000,
|
|
46588
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
46589
|
+
}).trim();
|
|
46590
|
+
const patterns = [
|
|
46591
|
+
/^([\d]+\.[\d]+\.[\d]+)/,
|
|
46592
|
+
/version\s+([\d]+\.[\d]+\.[\d]+)/i,
|
|
46593
|
+
/v?([\d]+\.[\d]+\.[\d]+)/
|
|
46594
|
+
];
|
|
46595
|
+
for (const pattern of patterns) {
|
|
46596
|
+
const match = output.match(pattern);
|
|
46597
|
+
if (match) {
|
|
46598
|
+
return { version: match[1], rawOutput: output, error: null, foundAt: claudePath };
|
|
46599
|
+
}
|
|
46600
|
+
}
|
|
46601
|
+
return { version: null, rawOutput: output, error: null, foundAt: claudePath };
|
|
46602
|
+
} catch (err) {
|
|
46603
|
+
const errorMessage = err instanceof Error ? err.message : "Unknown error";
|
|
46604
|
+
return { version: null, rawOutput: null, error: errorMessage };
|
|
46605
|
+
}
|
|
46606
|
+
}
|
|
46607
|
+
function findClaudeInPath() {
|
|
46576
46608
|
try {
|
|
46577
|
-
const
|
|
46609
|
+
const result = execSync("which claude", {
|
|
46578
46610
|
encoding: "utf8",
|
|
46579
46611
|
timeout: 5000,
|
|
46580
46612
|
stdio: ["pipe", "pipe", "pipe"]
|
|
46581
46613
|
}).trim();
|
|
46582
|
-
|
|
46583
|
-
return match ? match[1] : null;
|
|
46614
|
+
return result || null;
|
|
46584
46615
|
} catch {
|
|
46585
46616
|
return null;
|
|
46586
46617
|
}
|
|
46587
46618
|
}
|
|
46619
|
+
function getClaudeCliVersion() {
|
|
46620
|
+
if (process.env.CLAUDE_PATH) {
|
|
46621
|
+
const result = tryClaudeVersion(process.env.CLAUDE_PATH);
|
|
46622
|
+
if (!result.error) {
|
|
46623
|
+
return result;
|
|
46624
|
+
}
|
|
46625
|
+
}
|
|
46626
|
+
const whichResult = findClaudeInPath();
|
|
46627
|
+
if (whichResult) {
|
|
46628
|
+
const result = tryClaudeVersion(whichResult);
|
|
46629
|
+
if (!result.error) {
|
|
46630
|
+
return result;
|
|
46631
|
+
}
|
|
46632
|
+
}
|
|
46633
|
+
const pathResult = tryClaudeVersion("claude");
|
|
46634
|
+
if (!pathResult.error) {
|
|
46635
|
+
return pathResult;
|
|
46636
|
+
}
|
|
46637
|
+
for (const path of COMMON_CLAUDE_PATHS) {
|
|
46638
|
+
if (existsSync2(path)) {
|
|
46639
|
+
const result = tryClaudeVersion(path);
|
|
46640
|
+
if (!result.error) {
|
|
46641
|
+
return result;
|
|
46642
|
+
}
|
|
46643
|
+
}
|
|
46644
|
+
}
|
|
46645
|
+
const checkedPaths = process.env.CLAUDE_PATH ? [process.env.CLAUDE_PATH, "claude (in PATH)", ...COMMON_CLAUDE_PATHS] : ["claude (in PATH)", ...COMMON_CLAUDE_PATHS];
|
|
46646
|
+
return {
|
|
46647
|
+
version: null,
|
|
46648
|
+
rawOutput: null,
|
|
46649
|
+
error: `Command 'claude' not found. Searched: ${checkedPaths.slice(0, 3).join(", ")}...`
|
|
46650
|
+
};
|
|
46651
|
+
}
|
|
46588
46652
|
function isVersionCompatible(version) {
|
|
46589
46653
|
const semverVersion = import_semver.coerce(version);
|
|
46590
46654
|
if (!semverVersion)
|
|
46591
46655
|
return false;
|
|
46592
46656
|
return import_semver.satisfies(semverVersion, CLAUDE_CLI_VERSION_RANGE);
|
|
46593
46657
|
}
|
|
46658
|
+
function getClaudePath() {
|
|
46659
|
+
if (process.env.CLAUDE_PATH) {
|
|
46660
|
+
return process.env.CLAUDE_PATH;
|
|
46661
|
+
}
|
|
46662
|
+
const whichResult = findClaudeInPath();
|
|
46663
|
+
if (whichResult) {
|
|
46664
|
+
return whichResult;
|
|
46665
|
+
}
|
|
46666
|
+
for (const path of COMMON_CLAUDE_PATHS) {
|
|
46667
|
+
if (existsSync2(path)) {
|
|
46668
|
+
const result = tryClaudeVersion(path);
|
|
46669
|
+
if (!result.error) {
|
|
46670
|
+
return path;
|
|
46671
|
+
}
|
|
46672
|
+
}
|
|
46673
|
+
}
|
|
46674
|
+
return "claude";
|
|
46675
|
+
}
|
|
46594
46676
|
function validateClaudeCli() {
|
|
46595
|
-
const
|
|
46596
|
-
if (
|
|
46677
|
+
const result = getClaudeCliVersion();
|
|
46678
|
+
if (result.error) {
|
|
46679
|
+
const claudePath = process.env.CLAUDE_PATH || "claude";
|
|
46597
46680
|
return {
|
|
46598
46681
|
installed: false,
|
|
46599
46682
|
version: null,
|
|
46600
46683
|
compatible: false,
|
|
46601
|
-
message:
|
|
46684
|
+
message: `Claude CLI not found at '${claudePath}'. Install it with: npm install -g @anthropic-ai/claude-code`,
|
|
46685
|
+
error: result.error
|
|
46686
|
+
};
|
|
46687
|
+
}
|
|
46688
|
+
if (!result.version && result.rawOutput) {
|
|
46689
|
+
return {
|
|
46690
|
+
installed: true,
|
|
46691
|
+
version: null,
|
|
46692
|
+
compatible: true,
|
|
46693
|
+
message: `Claude CLI found (version unknown)`,
|
|
46694
|
+
rawOutput: result.rawOutput
|
|
46602
46695
|
};
|
|
46603
46696
|
}
|
|
46604
|
-
const compatible = isVersionCompatible(version);
|
|
46697
|
+
const compatible = isVersionCompatible(result.version);
|
|
46605
46698
|
if (!compatible) {
|
|
46606
46699
|
return {
|
|
46607
46700
|
installed: true,
|
|
46608
|
-
version,
|
|
46701
|
+
version: result.version,
|
|
46609
46702
|
compatible: false,
|
|
46610
|
-
message: `Claude CLI version ${version} is not compatible. Required: ${CLAUDE_CLI_VERSION_RANGE}
|
|
46611
|
-
` + `Install a compatible version:
|
|
46703
|
+
message: `Claude CLI version ${result.version} is not compatible. Required: ${CLAUDE_CLI_VERSION_RANGE}
|
|
46704
|
+
` + `Install a compatible version: npm install -g @anthropic-ai/claude-code@2.1.1`,
|
|
46705
|
+
rawOutput: result.rawOutput ?? undefined
|
|
46612
46706
|
};
|
|
46613
46707
|
}
|
|
46614
46708
|
return {
|
|
46615
46709
|
installed: true,
|
|
46616
|
-
version,
|
|
46710
|
+
version: result.version,
|
|
46617
46711
|
compatible: true,
|
|
46618
|
-
message: `Claude CLI ${version} \u2713
|
|
46712
|
+
message: `Claude CLI ${result.version} \u2713`,
|
|
46713
|
+
rawOutput: result.rawOutput ?? undefined
|
|
46619
46714
|
};
|
|
46620
46715
|
}
|
|
46621
46716
|
|
|
@@ -46759,7 +46854,7 @@ async function runOnboarding(reconfigure = false) {
|
|
|
46759
46854
|
console.log(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
46760
46855
|
console.log("");
|
|
46761
46856
|
let existingConfig = null;
|
|
46762
|
-
if (reconfigure &&
|
|
46857
|
+
if (reconfigure && existsSync3(CONFIG_PATH)) {
|
|
46763
46858
|
try {
|
|
46764
46859
|
const content = readFileSync2(CONFIG_PATH, "utf-8");
|
|
46765
46860
|
existingConfig = Bun.YAML.parse(content);
|
|
@@ -46785,25 +46880,52 @@ async function runOnboarding(reconfigure = false) {
|
|
|
46785
46880
|
console.log("");
|
|
46786
46881
|
console.log(dim(" \u274C Claude Code CLI not found"));
|
|
46787
46882
|
console.log("");
|
|
46788
|
-
|
|
46789
|
-
|
|
46883
|
+
if (claudeCheck.error) {
|
|
46884
|
+
console.log(dim(` Error: ${claudeCheck.error}`));
|
|
46885
|
+
console.log("");
|
|
46886
|
+
}
|
|
46887
|
+
console.log(dim(" Debug info:"));
|
|
46888
|
+
const pathDirs = (process.env.PATH || "").split(":").slice(0, 5);
|
|
46889
|
+
console.log(dim(` PATH (first 5 dirs): ${pathDirs.join(":")}`));
|
|
46890
|
+
console.log("");
|
|
46891
|
+
console.log(dim(" Solutions:"));
|
|
46790
46892
|
console.log("");
|
|
46791
|
-
console.log(dim("
|
|
46893
|
+
console.log(dim(" 1. Install Claude Code CLI:"));
|
|
46894
|
+
console.log(dim(" npm install -g @anthropic-ai/claude-code"));
|
|
46895
|
+
console.log("");
|
|
46896
|
+
console.log(dim(" 2. If already installed, find it and set CLAUDE_PATH:"));
|
|
46897
|
+
console.log(dim(" # Find where it is:"));
|
|
46898
|
+
console.log(dim(" which claude"));
|
|
46899
|
+
console.log(dim(" # Or search common locations:"));
|
|
46900
|
+
console.log(dim(" ls ~/.local/bin/claude ~/.bun/bin/claude /usr/local/bin/claude 2>/dev/null"));
|
|
46901
|
+
console.log(dim(" # Then run with the path:"));
|
|
46902
|
+
console.log(dim(" CLAUDE_PATH=/path/to/claude claude-threads"));
|
|
46903
|
+
console.log("");
|
|
46904
|
+
console.log(dim(" 3. Add Claude's directory to PATH in your shell config"));
|
|
46792
46905
|
console.log("");
|
|
46793
46906
|
process.exit(1);
|
|
46794
46907
|
}
|
|
46795
46908
|
if (!claudeCheck.compatible) {
|
|
46796
46909
|
console.log("");
|
|
46797
|
-
|
|
46798
|
-
|
|
46799
|
-
|
|
46800
|
-
|
|
46910
|
+
if (claudeCheck.version) {
|
|
46911
|
+
console.log(dim(` \u26A0\uFE0F Claude Code CLI ${claudeCheck.version} is not compatible`));
|
|
46912
|
+
console.log("");
|
|
46913
|
+
console.log(dim(` Install a compatible version:`));
|
|
46914
|
+
console.log(dim(" npm install -g @anthropic-ai/claude-code@2.1.1"));
|
|
46915
|
+
} else {
|
|
46916
|
+
console.log(dim(" \u26A0\uFE0F Claude Code CLI found but version could not be determined"));
|
|
46917
|
+
if (claudeCheck.rawOutput) {
|
|
46918
|
+
console.log(dim(` Output from "claude --version": ${claudeCheck.rawOutput}`));
|
|
46919
|
+
}
|
|
46920
|
+
console.log("");
|
|
46921
|
+
console.log(dim(" This may work fine - Claude was installed in a non-standard way."));
|
|
46922
|
+
}
|
|
46801
46923
|
console.log("");
|
|
46802
46924
|
const { continueAnyway } = await import_prompts.default({
|
|
46803
46925
|
type: "confirm",
|
|
46804
46926
|
name: "continueAnyway",
|
|
46805
46927
|
message: "Continue anyway? (may not work correctly)",
|
|
46806
|
-
initial:
|
|
46928
|
+
initial: !claudeCheck.version
|
|
46807
46929
|
}, { onCancel });
|
|
46808
46930
|
if (!continueAnyway) {
|
|
46809
46931
|
console.log("");
|
|
@@ -46811,7 +46933,8 @@ async function runOnboarding(reconfigure = false) {
|
|
|
46811
46933
|
process.exit(0);
|
|
46812
46934
|
}
|
|
46813
46935
|
} else {
|
|
46814
|
-
|
|
46936
|
+
const versionInfo = claudeCheck.version ?? "version unknown";
|
|
46937
|
+
console.log(dim(` \u2713 Claude Code CLI ${versionInfo}`));
|
|
46815
46938
|
}
|
|
46816
46939
|
console.log("");
|
|
46817
46940
|
console.log(dim(" \uD83D\uDCD6 Need help creating a bot?"));
|
|
@@ -49911,7 +50034,7 @@ class SlackPermissionApi {
|
|
|
49911
50034
|
import { EventEmitter as EventEmitter4 } from "events";
|
|
49912
50035
|
|
|
49913
50036
|
// src/persistence/session-store.ts
|
|
49914
|
-
import { existsSync as
|
|
50037
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync } from "fs";
|
|
49915
50038
|
import { homedir as homedir2 } from "os";
|
|
49916
50039
|
import { join as join2 } from "path";
|
|
49917
50040
|
var log5 = createLogger("persist");
|
|
@@ -49932,13 +50055,13 @@ class SessionStore {
|
|
|
49932
50055
|
this.sessionsFile = DEFAULT_SESSIONS_FILE;
|
|
49933
50056
|
this.configDir = DEFAULT_CONFIG_DIR;
|
|
49934
50057
|
}
|
|
49935
|
-
if (!
|
|
50058
|
+
if (!existsSync4(this.configDir)) {
|
|
49936
50059
|
mkdirSync2(this.configDir, { recursive: true });
|
|
49937
50060
|
}
|
|
49938
50061
|
}
|
|
49939
50062
|
load() {
|
|
49940
50063
|
const sessions = new Map;
|
|
49941
|
-
if (!
|
|
50064
|
+
if (!existsSync4(this.sessionsFile)) {
|
|
49942
50065
|
log5.debug("No sessions file found");
|
|
49943
50066
|
return sessions;
|
|
49944
50067
|
}
|
|
@@ -50117,7 +50240,7 @@ class SessionStore {
|
|
|
50117
50240
|
return;
|
|
50118
50241
|
}
|
|
50119
50242
|
loadRaw() {
|
|
50120
|
-
if (!
|
|
50243
|
+
if (!existsSync4(this.sessionsFile)) {
|
|
50121
50244
|
return { version: STORE_VERSION, sessions: {} };
|
|
50122
50245
|
}
|
|
50123
50246
|
try {
|
|
@@ -50136,12 +50259,12 @@ class SessionStore {
|
|
|
50136
50259
|
init_emoji();
|
|
50137
50260
|
|
|
50138
50261
|
// src/cleanup/scheduler.ts
|
|
50139
|
-
import { existsSync as
|
|
50262
|
+
import { existsSync as existsSync6 } from "fs";
|
|
50140
50263
|
import { readdir, rm } from "fs/promises";
|
|
50141
50264
|
import { join as join5 } from "path";
|
|
50142
50265
|
|
|
50143
50266
|
// src/persistence/thread-logger.ts
|
|
50144
|
-
import { existsSync as
|
|
50267
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, appendFileSync, readdirSync, statSync, unlinkSync, rmdirSync, readFileSync as readFileSync4 } from "fs";
|
|
50145
50268
|
import { homedir as homedir3 } from "os";
|
|
50146
50269
|
import { join as join3, dirname as dirname3 } from "path";
|
|
50147
50270
|
var log6 = createLogger("thread-log");
|
|
@@ -50168,7 +50291,7 @@ class ThreadLoggerImpl {
|
|
|
50168
50291
|
this.logPath = join3(LOGS_BASE_DIR, platformId, `${claudeSessionId}.jsonl`);
|
|
50169
50292
|
if (this.enabled) {
|
|
50170
50293
|
const dir = dirname3(this.logPath);
|
|
50171
|
-
if (!
|
|
50294
|
+
if (!existsSync5(dir)) {
|
|
50172
50295
|
mkdirSync3(dir, { recursive: true });
|
|
50173
50296
|
}
|
|
50174
50297
|
this.flushTimer = setInterval(() => {
|
|
@@ -50337,7 +50460,7 @@ function createThreadLogger(platformId, threadId, claudeSessionId, options2) {
|
|
|
50337
50460
|
function cleanupOldLogs(retentionDays = 30) {
|
|
50338
50461
|
const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000;
|
|
50339
50462
|
let deletedCount = 0;
|
|
50340
|
-
if (!
|
|
50463
|
+
if (!existsSync5(LOGS_BASE_DIR)) {
|
|
50341
50464
|
return 0;
|
|
50342
50465
|
}
|
|
50343
50466
|
try {
|
|
@@ -50385,7 +50508,7 @@ function getLogFilePath(platformId, sessionId) {
|
|
|
50385
50508
|
function readRecentLogEntries(platformId, sessionId, maxLines = 50) {
|
|
50386
50509
|
const logPath = getLogFilePath(platformId, sessionId);
|
|
50387
50510
|
log6.debug(`Reading log entries from: ${logPath}`);
|
|
50388
|
-
if (!
|
|
50511
|
+
if (!existsSync5(logPath)) {
|
|
50389
50512
|
log6.debug(`Log file does not exist: ${logPath}`);
|
|
50390
50513
|
return [];
|
|
50391
50514
|
}
|
|
@@ -50809,7 +50932,7 @@ class CleanupScheduler {
|
|
|
50809
50932
|
async cleanupOrphanedWorktrees() {
|
|
50810
50933
|
const worktreesDir = getWorktreesDir();
|
|
50811
50934
|
const result = { cleaned: 0, metadata: 0 };
|
|
50812
|
-
if (!
|
|
50935
|
+
if (!existsSync6(worktreesDir)) {
|
|
50813
50936
|
log8.debug("No worktrees directory exists, nothing to clean");
|
|
50814
50937
|
return result;
|
|
50815
50938
|
}
|
|
@@ -50951,7 +51074,7 @@ import { spawn as spawn2 } from "child_process";
|
|
|
50951
51074
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
50952
51075
|
import { resolve as resolve2, dirname as dirname5 } from "path";
|
|
50953
51076
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
50954
|
-
import { existsSync as
|
|
51077
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, watchFile, unwatchFile, unlinkSync as unlinkSync2, statSync as statSync2, readdirSync as readdirSync2 } from "fs";
|
|
50955
51078
|
import { tmpdir } from "os";
|
|
50956
51079
|
import { join as join6 } from "path";
|
|
50957
51080
|
var log9 = createLogger("claude");
|
|
@@ -50997,7 +51120,7 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
50997
51120
|
if (!this.statusFilePath)
|
|
50998
51121
|
return null;
|
|
50999
51122
|
try {
|
|
51000
|
-
if (
|
|
51123
|
+
if (existsSync7(this.statusFilePath)) {
|
|
51001
51124
|
const data = readFileSync5(this.statusFilePath, "utf8");
|
|
51002
51125
|
this.lastStatusData = JSON.parse(data);
|
|
51003
51126
|
}
|
|
@@ -51025,7 +51148,7 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
51025
51148
|
if (this.statusFilePath) {
|
|
51026
51149
|
unwatchFile(this.statusFilePath);
|
|
51027
51150
|
try {
|
|
51028
|
-
if (
|
|
51151
|
+
if (existsSync7(this.statusFilePath)) {
|
|
51029
51152
|
unlinkSync2(this.statusFilePath);
|
|
51030
51153
|
}
|
|
51031
51154
|
} catch {}
|
|
@@ -51036,7 +51159,7 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
51036
51159
|
throw new Error("Already running");
|
|
51037
51160
|
this.stderrBuffer = "";
|
|
51038
51161
|
cleanupBrowserBridgeSockets();
|
|
51039
|
-
const claudePath =
|
|
51162
|
+
const claudePath = getClaudePath();
|
|
51040
51163
|
const args = [
|
|
51041
51164
|
"--input-format",
|
|
51042
51165
|
"stream-json",
|
|
@@ -51258,7 +51381,7 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
51258
51381
|
}
|
|
51259
51382
|
|
|
51260
51383
|
// src/version.ts
|
|
51261
|
-
import { readFileSync as readFileSync6, existsSync as
|
|
51384
|
+
import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
|
|
51262
51385
|
import { dirname as dirname6, resolve as resolve3 } from "path";
|
|
51263
51386
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
51264
51387
|
var __dirname3 = dirname6(fileURLToPath3(import.meta.url));
|
|
@@ -51269,7 +51392,7 @@ function loadPackageJson() {
|
|
|
51269
51392
|
resolve3(process.cwd(), "package.json")
|
|
51270
51393
|
];
|
|
51271
51394
|
for (const candidate of candidates) {
|
|
51272
|
-
if (
|
|
51395
|
+
if (existsSync8(candidate)) {
|
|
51273
51396
|
try {
|
|
51274
51397
|
const pkg = JSON.parse(readFileSync6(candidate, "utf-8"));
|
|
51275
51398
|
if (pkg.name === "claude-threads") {
|
|
@@ -51614,7 +51737,7 @@ ${avoidCommands.map((c) => `- \`!${c.command}\` - ${c.reason}`).join(`
|
|
|
51614
51737
|
}
|
|
51615
51738
|
// src/session/lifecycle.ts
|
|
51616
51739
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
51617
|
-
import { existsSync as
|
|
51740
|
+
import { existsSync as existsSync11 } from "fs";
|
|
51618
51741
|
|
|
51619
51742
|
// src/utils/keep-alive.ts
|
|
51620
51743
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -56589,7 +56712,7 @@ class MessageManager {
|
|
|
56589
56712
|
this.session.claude.sendMessage(content);
|
|
56590
56713
|
if (skippedFiles.length > 0) {
|
|
56591
56714
|
const feedback = this.formatSkippedFilesFeedback(skippedFiles);
|
|
56592
|
-
await this.platform.createPost(this.threadId
|
|
56715
|
+
await this.platform.createPost(feedback, this.threadId);
|
|
56593
56716
|
}
|
|
56594
56717
|
this.session.lastActivityAt = new Date;
|
|
56595
56718
|
this.session.isProcessing = true;
|
|
@@ -56748,7 +56871,7 @@ function formatUptime(startedAt) {
|
|
|
56748
56871
|
}
|
|
56749
56872
|
|
|
56750
56873
|
// src/changelog.ts
|
|
56751
|
-
import { readFileSync as readFileSync7, existsSync as
|
|
56874
|
+
import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
|
|
56752
56875
|
import { dirname as dirname7, resolve as resolve4 } from "path";
|
|
56753
56876
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
56754
56877
|
var __dirname4 = dirname7(fileURLToPath4(import.meta.url));
|
|
@@ -56759,7 +56882,7 @@ function getReleaseNotes(version) {
|
|
|
56759
56882
|
];
|
|
56760
56883
|
let changelogPath = null;
|
|
56761
56884
|
for (const p of possiblePaths) {
|
|
56762
|
-
if (
|
|
56885
|
+
if (existsSync9(p)) {
|
|
56763
56886
|
changelogPath = p;
|
|
56764
56887
|
break;
|
|
56765
56888
|
}
|
|
@@ -57106,7 +57229,7 @@ async function buildStatusBar(sessionCount, config, formatter, platformId) {
|
|
|
57106
57229
|
items.push(formatter.formatCode(`\u23F8\uFE0F Update deferred`));
|
|
57107
57230
|
}
|
|
57108
57231
|
}
|
|
57109
|
-
const claudeVersion = getClaudeCliVersion();
|
|
57232
|
+
const claudeVersion = getClaudeCliVersion().version;
|
|
57110
57233
|
const versionStr = claudeVersion ? `v${VERSION} \xB7 CLI ${claudeVersion}` : `v${VERSION}`;
|
|
57111
57234
|
items.push(formatter.formatCode(versionStr));
|
|
57112
57235
|
items.push(formatter.formatCode(`${sessionCount}/${config.maxSessions} sessions`));
|
|
@@ -57799,7 +57922,7 @@ async function collectBugReportContext(session, errorContext) {
|
|
|
57799
57922
|
const recentLogEntries = readRecentLogEntries(platformId, sessionId, BUG_REPORT_LOG_ENTRIES);
|
|
57800
57923
|
return {
|
|
57801
57924
|
version: VERSION,
|
|
57802
|
-
claudeCliVersion: getClaudeCliVersion(),
|
|
57925
|
+
claudeCliVersion: getClaudeCliVersion().version ?? "unknown",
|
|
57803
57926
|
platform: session.platform.displayName,
|
|
57804
57927
|
platformType: session.platform.platformType,
|
|
57805
57928
|
nodeVersion: process.version,
|
|
@@ -58096,7 +58219,7 @@ function formatBugPreview(title, description, context, imageUrls, imageErrors, f
|
|
|
58096
58219
|
// src/operations/commands/handler.ts
|
|
58097
58220
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
58098
58221
|
import { resolve as resolve5 } from "path";
|
|
58099
|
-
import { existsSync as
|
|
58222
|
+
import { existsSync as existsSync10, statSync as statSync3 } from "fs";
|
|
58100
58223
|
|
|
58101
58224
|
// node_modules/update-notifier/update-notifier.js
|
|
58102
58225
|
import process10 from "process";
|
|
@@ -61616,7 +61739,7 @@ async function changeDirectory(session, newDir, username, ctx) {
|
|
|
61616
61739
|
const expandedDir = newDir.startsWith("~") ? newDir.replace("~", process.env.HOME || "") : newDir;
|
|
61617
61740
|
const absoluteDir = resolve5(expandedDir);
|
|
61618
61741
|
const formatter = session.platform.getFormatter();
|
|
61619
|
-
if (!
|
|
61742
|
+
if (!existsSync10(absoluteDir)) {
|
|
61620
61743
|
await postError(session, `Directory does not exist: ${formatter.formatCode(newDir)}`);
|
|
61621
61744
|
sessionLog2(session).warn(`\uD83D\uDCC2 Directory does not exist: ${newDir}`);
|
|
61622
61745
|
return;
|
|
@@ -61771,7 +61894,7 @@ async function updateSessionHeader(session, ctx) {
|
|
|
61771
61894
|
const permMode = isInteractive ? "\uD83D\uDD10 Interactive" : "\u26A1 Auto";
|
|
61772
61895
|
const otherParticipants = [...session.sessionAllowedUsers].filter((u) => u !== session.startedBy).map((u) => formatter.formatUserMention(u)).join(", ");
|
|
61773
61896
|
const statusItems = [];
|
|
61774
|
-
const claudeVersion = getClaudeCliVersion();
|
|
61897
|
+
const claudeVersion = getClaudeCliVersion().version;
|
|
61775
61898
|
const versionStr = claudeVersion ? `v${VERSION} \xB7 CLI ${claudeVersion}` : `v${VERSION}`;
|
|
61776
61899
|
statusItems.push(formatter.formatCode(versionStr));
|
|
61777
61900
|
if (session.usageStats) {
|
|
@@ -63472,7 +63595,7 @@ async function resumeSession(state, ctx) {
|
|
|
63472
63595
|
log25.warn(`Max sessions reached, skipping resume for ${shortId}...`);
|
|
63473
63596
|
return;
|
|
63474
63597
|
}
|
|
63475
|
-
if (!
|
|
63598
|
+
if (!existsSync11(state.workingDir)) {
|
|
63476
63599
|
log25.warn(`Working directory ${state.workingDir} no longer exists, skipping resume for ${shortId}...`);
|
|
63477
63600
|
ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
|
|
63478
63601
|
const resumeFormatter = platform.getFormatter();
|
|
@@ -75927,7 +76050,7 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
75927
76050
|
|
|
75928
76051
|
// src/auto-update/installer.ts
|
|
75929
76052
|
import { spawn as spawn6 } from "child_process";
|
|
75930
|
-
import { existsSync as
|
|
76053
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4 } from "fs";
|
|
75931
76054
|
import { dirname as dirname8, resolve as resolve6 } from "path";
|
|
75932
76055
|
import { homedir as homedir5 } from "os";
|
|
75933
76056
|
var log30 = createLogger("installer");
|
|
@@ -75935,7 +76058,7 @@ var STATE_PATH = resolve6(homedir5(), ".config", "claude-threads", UPDATE_STATE_
|
|
|
75935
76058
|
var PACKAGE_NAME2 = "claude-threads";
|
|
75936
76059
|
function loadUpdateState() {
|
|
75937
76060
|
try {
|
|
75938
|
-
if (
|
|
76061
|
+
if (existsSync13(STATE_PATH)) {
|
|
75939
76062
|
const content = readFileSync9(STATE_PATH, "utf-8");
|
|
75940
76063
|
return JSON.parse(content);
|
|
75941
76064
|
}
|
|
@@ -75947,7 +76070,7 @@ function loadUpdateState() {
|
|
|
75947
76070
|
function saveUpdateState(state) {
|
|
75948
76071
|
try {
|
|
75949
76072
|
const dir = dirname8(STATE_PATH);
|
|
75950
|
-
if (!
|
|
76073
|
+
if (!existsSync13(dir)) {
|
|
75951
76074
|
mkdirSync4(dir, { recursive: true });
|
|
75952
76075
|
}
|
|
75953
76076
|
writeFileSync5(STATE_PATH, JSON.stringify(state, null, 2), "utf-8");
|
|
@@ -75958,7 +76081,7 @@ function saveUpdateState(state) {
|
|
|
75958
76081
|
}
|
|
75959
76082
|
function clearUpdateState() {
|
|
75960
76083
|
try {
|
|
75961
|
-
if (
|
|
76084
|
+
if (existsSync13(STATE_PATH)) {
|
|
75962
76085
|
writeFileSync5(STATE_PATH, "{}", "utf-8");
|
|
75963
76086
|
}
|
|
75964
76087
|
} catch (err) {
|
|
@@ -41444,7 +41444,7 @@ class MessageManager {
|
|
|
41444
41444
|
this.session.claude.sendMessage(content);
|
|
41445
41445
|
if (skippedFiles.length > 0) {
|
|
41446
41446
|
const feedback = this.formatSkippedFilesFeedback(skippedFiles);
|
|
41447
|
-
await this.platform.createPost(this.threadId
|
|
41447
|
+
await this.platform.createPost(feedback, this.threadId);
|
|
41448
41448
|
}
|
|
41449
41449
|
this.session.lastActivityAt = new Date;
|
|
41450
41450
|
this.session.isProcessing = true;
|
|
@@ -41554,6 +41554,70 @@ var __dirname3 = dirname2(fileURLToPath2(import.meta.url));
|
|
|
41554
41554
|
|
|
41555
41555
|
// src/claude/version-check.ts
|
|
41556
41556
|
var import_semver = __toESM(require_semver2(), 1);
|
|
41557
|
+
import { execSync } from "child_process";
|
|
41558
|
+
import { existsSync as existsSync2 } from "fs";
|
|
41559
|
+
var COMMON_CLAUDE_PATHS = [
|
|
41560
|
+
"/usr/local/bin/claude",
|
|
41561
|
+
"/opt/homebrew/bin/claude",
|
|
41562
|
+
`${process.env.HOME}/.local/bin/claude`,
|
|
41563
|
+
`${process.env.HOME}/.npm-global/bin/claude`,
|
|
41564
|
+
`${process.env.HOME}/.bun/bin/claude`,
|
|
41565
|
+
"/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
41566
|
+
];
|
|
41567
|
+
function tryClaudeVersion(claudePath) {
|
|
41568
|
+
try {
|
|
41569
|
+
const output = execSync(`"${claudePath}" --version`, {
|
|
41570
|
+
encoding: "utf8",
|
|
41571
|
+
timeout: 5000,
|
|
41572
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
41573
|
+
}).trim();
|
|
41574
|
+
const patterns = [
|
|
41575
|
+
/^([\d]+\.[\d]+\.[\d]+)/,
|
|
41576
|
+
/version\s+([\d]+\.[\d]+\.[\d]+)/i,
|
|
41577
|
+
/v?([\d]+\.[\d]+\.[\d]+)/
|
|
41578
|
+
];
|
|
41579
|
+
for (const pattern of patterns) {
|
|
41580
|
+
const match = output.match(pattern);
|
|
41581
|
+
if (match) {
|
|
41582
|
+
return { version: match[1], rawOutput: output, error: null, foundAt: claudePath };
|
|
41583
|
+
}
|
|
41584
|
+
}
|
|
41585
|
+
return { version: null, rawOutput: output, error: null, foundAt: claudePath };
|
|
41586
|
+
} catch (err) {
|
|
41587
|
+
const errorMessage = err instanceof Error ? err.message : "Unknown error";
|
|
41588
|
+
return { version: null, rawOutput: null, error: errorMessage };
|
|
41589
|
+
}
|
|
41590
|
+
}
|
|
41591
|
+
function findClaudeInPath() {
|
|
41592
|
+
try {
|
|
41593
|
+
const result = execSync("which claude", {
|
|
41594
|
+
encoding: "utf8",
|
|
41595
|
+
timeout: 5000,
|
|
41596
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
41597
|
+
}).trim();
|
|
41598
|
+
return result || null;
|
|
41599
|
+
} catch {
|
|
41600
|
+
return null;
|
|
41601
|
+
}
|
|
41602
|
+
}
|
|
41603
|
+
function getClaudePath() {
|
|
41604
|
+
if (process.env.CLAUDE_PATH) {
|
|
41605
|
+
return process.env.CLAUDE_PATH;
|
|
41606
|
+
}
|
|
41607
|
+
const whichResult = findClaudeInPath();
|
|
41608
|
+
if (whichResult) {
|
|
41609
|
+
return whichResult;
|
|
41610
|
+
}
|
|
41611
|
+
for (const path of COMMON_CLAUDE_PATHS) {
|
|
41612
|
+
if (existsSync2(path)) {
|
|
41613
|
+
const result = tryClaudeVersion(path);
|
|
41614
|
+
if (!result.error) {
|
|
41615
|
+
return path;
|
|
41616
|
+
}
|
|
41617
|
+
}
|
|
41618
|
+
}
|
|
41619
|
+
return "claude";
|
|
41620
|
+
}
|
|
41557
41621
|
|
|
41558
41622
|
// src/utils/keep-alive.ts
|
|
41559
41623
|
import { spawn } from "child_process";
|
|
@@ -42007,7 +42071,7 @@ import { spawn as spawn2 } from "child_process";
|
|
|
42007
42071
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
42008
42072
|
import { resolve as resolve3, dirname as dirname4 } from "path";
|
|
42009
42073
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
42010
|
-
import { existsSync as
|
|
42074
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, watchFile, unwatchFile, unlinkSync, statSync, readdirSync } from "fs";
|
|
42011
42075
|
import { tmpdir } from "os";
|
|
42012
42076
|
import { join as join2 } from "path";
|
|
42013
42077
|
var log7 = createLogger("claude");
|
|
@@ -42053,7 +42117,7 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
42053
42117
|
if (!this.statusFilePath)
|
|
42054
42118
|
return null;
|
|
42055
42119
|
try {
|
|
42056
|
-
if (
|
|
42120
|
+
if (existsSync3(this.statusFilePath)) {
|
|
42057
42121
|
const data = readFileSync2(this.statusFilePath, "utf8");
|
|
42058
42122
|
this.lastStatusData = JSON.parse(data);
|
|
42059
42123
|
}
|
|
@@ -42081,7 +42145,7 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
42081
42145
|
if (this.statusFilePath) {
|
|
42082
42146
|
unwatchFile(this.statusFilePath);
|
|
42083
42147
|
try {
|
|
42084
|
-
if (
|
|
42148
|
+
if (existsSync3(this.statusFilePath)) {
|
|
42085
42149
|
unlinkSync(this.statusFilePath);
|
|
42086
42150
|
}
|
|
42087
42151
|
} catch {}
|
|
@@ -42092,7 +42156,7 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
42092
42156
|
throw new Error("Already running");
|
|
42093
42157
|
this.stderrBuffer = "";
|
|
42094
42158
|
cleanupBrowserBridgeSockets();
|
|
42095
|
-
const claudePath =
|
|
42159
|
+
const claudePath = getClaudePath();
|
|
42096
42160
|
const args = [
|
|
42097
42161
|
"--input-format",
|
|
42098
42162
|
"stream-json",
|