claude-threads 1.27.0 → 1.28.0
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 +14 -2
- package/dist/index.js +901 -592
- package/dist/mcp/mcp-server.js +270 -189
- package/docs/CONFIGURATION.md +20 -0
- package/package.json +1 -1
package/dist/mcp/mcp-server.js
CHANGED
|
@@ -50772,6 +50772,144 @@ class SystemExecutor extends BaseExecutor {
|
|
|
50772
50772
|
}
|
|
50773
50773
|
// src/operations/executors/question-approval.ts
|
|
50774
50774
|
init_emoji();
|
|
50775
|
+
|
|
50776
|
+
// src/persistence/audit-log.ts
|
|
50777
|
+
import { chmodSync, closeSync, constants as fsConstants, fchmodSync, lstatSync, mkdirSync, openSync, writeSync } from "fs";
|
|
50778
|
+
import { join as join2 } from "path";
|
|
50779
|
+
import { homedir } from "os";
|
|
50780
|
+
|
|
50781
|
+
// src/utils/logger.ts
|
|
50782
|
+
var globalLogHandler = null;
|
|
50783
|
+
var COMPONENT_WIDTH = 10;
|
|
50784
|
+
function createLogger(component, useStderr = false, sessionId) {
|
|
50785
|
+
const isDebug = () => process.env.DEBUG === "1";
|
|
50786
|
+
const consoleLog = useStderr ? console.error : console.log;
|
|
50787
|
+
const paddedComponent = component.length > COMPONENT_WIDTH ? component.substring(0, COMPONENT_WIDTH) : component.padEnd(COMPONENT_WIDTH);
|
|
50788
|
+
const formatMessage = (msg, args) => {
|
|
50789
|
+
if (args.length === 0)
|
|
50790
|
+
return msg;
|
|
50791
|
+
return `${msg} ${args.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}`;
|
|
50792
|
+
};
|
|
50793
|
+
const DEFAULT_JSON_MAX_LEN = 60;
|
|
50794
|
+
return {
|
|
50795
|
+
debug: (msg, ...args) => {
|
|
50796
|
+
if (isDebug()) {
|
|
50797
|
+
const fullMsg = formatMessage(msg, args);
|
|
50798
|
+
if (globalLogHandler) {
|
|
50799
|
+
globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
|
|
50800
|
+
} else {
|
|
50801
|
+
consoleLog(`[${paddedComponent}] ${fullMsg}`);
|
|
50802
|
+
}
|
|
50803
|
+
}
|
|
50804
|
+
},
|
|
50805
|
+
debugJson: (label, data, maxLen = DEFAULT_JSON_MAX_LEN) => {
|
|
50806
|
+
if (isDebug()) {
|
|
50807
|
+
const json2 = JSON.stringify(data);
|
|
50808
|
+
const truncated = json2.length > maxLen ? `${json2.substring(0, maxLen)}…` : json2;
|
|
50809
|
+
const fullMsg = `${label}: ${truncated}`;
|
|
50810
|
+
if (globalLogHandler) {
|
|
50811
|
+
globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
|
|
50812
|
+
} else {
|
|
50813
|
+
consoleLog(`[${paddedComponent}] ${fullMsg}`);
|
|
50814
|
+
}
|
|
50815
|
+
}
|
|
50816
|
+
},
|
|
50817
|
+
info: (msg, ...args) => {
|
|
50818
|
+
const fullMsg = formatMessage(msg, args);
|
|
50819
|
+
if (globalLogHandler) {
|
|
50820
|
+
globalLogHandler("info", paddedComponent, fullMsg, sessionId);
|
|
50821
|
+
} else {
|
|
50822
|
+
consoleLog(`[${paddedComponent}] ${fullMsg}`);
|
|
50823
|
+
}
|
|
50824
|
+
},
|
|
50825
|
+
warn: (msg, ...args) => {
|
|
50826
|
+
const fullMsg = formatMessage(msg, args);
|
|
50827
|
+
if (globalLogHandler) {
|
|
50828
|
+
globalLogHandler("warn", paddedComponent, fullMsg, sessionId);
|
|
50829
|
+
} else {
|
|
50830
|
+
console.warn(`[${paddedComponent}] ⚠️ ${fullMsg}`);
|
|
50831
|
+
}
|
|
50832
|
+
},
|
|
50833
|
+
error: (msg, err) => {
|
|
50834
|
+
const fullMsg = err && isDebug() ? `${msg}
|
|
50835
|
+
${err.stack || err.message}` : msg;
|
|
50836
|
+
if (globalLogHandler) {
|
|
50837
|
+
globalLogHandler("error", paddedComponent, fullMsg, sessionId);
|
|
50838
|
+
} else {
|
|
50839
|
+
console.error(`[${paddedComponent}] ❌ ${msg}`);
|
|
50840
|
+
if (err && isDebug()) {
|
|
50841
|
+
console.error(err);
|
|
50842
|
+
}
|
|
50843
|
+
}
|
|
50844
|
+
},
|
|
50845
|
+
forSession: (sid) => createLogger(component, useStderr, sid)
|
|
50846
|
+
};
|
|
50847
|
+
}
|
|
50848
|
+
var mcpLogger = createLogger("MCP", true);
|
|
50849
|
+
var wsLogger = createLogger("ws", false);
|
|
50850
|
+
|
|
50851
|
+
// src/persistence/audit-log.ts
|
|
50852
|
+
var log = createLogger("audit");
|
|
50853
|
+
var DETAIL_MAX = 500;
|
|
50854
|
+
var enabledPlatforms = new Set;
|
|
50855
|
+
var preparedDirs = new Set;
|
|
50856
|
+
var openFds = new Map;
|
|
50857
|
+
function auditDir() {
|
|
50858
|
+
return process.env.CLAUDE_THREADS_AUDIT_DIR || join2(homedir(), ".claude-threads", "audit");
|
|
50859
|
+
}
|
|
50860
|
+
function openAuditFd(platformId) {
|
|
50861
|
+
const cached3 = openFds.get(platformId);
|
|
50862
|
+
if (cached3 !== undefined)
|
|
50863
|
+
return cached3;
|
|
50864
|
+
const dir = auditDir();
|
|
50865
|
+
if (!preparedDirs.has(dir)) {
|
|
50866
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
50867
|
+
chmodSync(dir, 448);
|
|
50868
|
+
preparedDirs.add(dir);
|
|
50869
|
+
}
|
|
50870
|
+
const file2 = join2(dir, `${encodeURIComponent(platformId)}.jsonl`);
|
|
50871
|
+
try {
|
|
50872
|
+
const st = lstatSync(file2);
|
|
50873
|
+
if (st.isSymbolicLink() || !st.isFile()) {
|
|
50874
|
+
throw new Error(`audit path exists but is not a regular file: ${file2}`);
|
|
50875
|
+
}
|
|
50876
|
+
} catch (err) {
|
|
50877
|
+
if (err.code !== "ENOENT")
|
|
50878
|
+
throw err;
|
|
50879
|
+
}
|
|
50880
|
+
const noFollow = typeof fsConstants.O_NOFOLLOW === "number" ? fsConstants.O_NOFOLLOW : 0;
|
|
50881
|
+
const fd = openSync(file2, fsConstants.O_WRONLY | fsConstants.O_APPEND | fsConstants.O_CREAT | noFollow, 384);
|
|
50882
|
+
try {
|
|
50883
|
+
fchmodSync(fd, 384);
|
|
50884
|
+
} catch {}
|
|
50885
|
+
openFds.set(platformId, fd);
|
|
50886
|
+
return fd;
|
|
50887
|
+
}
|
|
50888
|
+
function auditLog(platformId, entry) {
|
|
50889
|
+
if (!enabledPlatforms.has(platformId))
|
|
50890
|
+
return;
|
|
50891
|
+
try {
|
|
50892
|
+
const full = {
|
|
50893
|
+
ts: new Date().toISOString(),
|
|
50894
|
+
platformId,
|
|
50895
|
+
...entry,
|
|
50896
|
+
...entry.detail !== undefined ? { detail: entry.detail.slice(0, DETAIL_MAX) } : {}
|
|
50897
|
+
};
|
|
50898
|
+
writeSync(openAuditFd(platformId), JSON.stringify(full) + `
|
|
50899
|
+
`);
|
|
50900
|
+
} catch (err) {
|
|
50901
|
+
const fd = openFds.get(platformId);
|
|
50902
|
+
if (fd !== undefined) {
|
|
50903
|
+
openFds.delete(platformId);
|
|
50904
|
+
try {
|
|
50905
|
+
closeSync(fd);
|
|
50906
|
+
} catch {}
|
|
50907
|
+
}
|
|
50908
|
+
log.warn(`audit write failed for ${platformId}: ${err}`);
|
|
50909
|
+
}
|
|
50910
|
+
}
|
|
50911
|
+
|
|
50912
|
+
// src/operations/executors/question-approval.ts
|
|
50775
50913
|
class QuestionApprovalExecutor extends BaseExecutor {
|
|
50776
50914
|
constructor(options) {
|
|
50777
50915
|
super(options, QuestionApprovalExecutor.createInitialState());
|
|
@@ -50986,14 +51124,29 @@ class QuestionApprovalExecutor extends BaseExecutor {
|
|
|
50986
51124
|
return false;
|
|
50987
51125
|
}
|
|
50988
51126
|
if (this.state.pendingApproval?.postId === postId) {
|
|
51127
|
+
const approvalType = this.state.pendingApproval.type;
|
|
51128
|
+
const auditDecision = (approved) => {
|
|
51129
|
+
if (approvalType !== "plan")
|
|
51130
|
+
return;
|
|
51131
|
+
auditLog(ctx.platform.platformId, {
|
|
51132
|
+
threadId: ctx.threadId,
|
|
51133
|
+
sessionId: ctx.sessionId,
|
|
51134
|
+
actor: user,
|
|
51135
|
+
kind: "plan_approval",
|
|
51136
|
+
approved,
|
|
51137
|
+
detail: "via reaction"
|
|
51138
|
+
});
|
|
51139
|
+
};
|
|
50989
51140
|
if (isApprovalEmoji(emoji4)) {
|
|
50990
51141
|
ctx.logger.debug(`Approval reaction from @${user}: approved`);
|
|
51142
|
+
auditDecision(true);
|
|
50991
51143
|
const handled = await this.handleApprovalResponse(postId, true, ctx);
|
|
50992
51144
|
ctx.logger.debug(`QuestionApprovalExecutor: approval outcome=approved, handled=${handled}`);
|
|
50993
51145
|
return handled;
|
|
50994
51146
|
}
|
|
50995
51147
|
if (isDenialEmoji(emoji4)) {
|
|
50996
51148
|
ctx.logger.debug(`Approval reaction from @${user}: denied`);
|
|
51149
|
+
auditDecision(false);
|
|
50997
51150
|
const handled = await this.handleApprovalResponse(postId, false, ctx);
|
|
50998
51151
|
ctx.logger.debug(`QuestionApprovalExecutor: approval outcome=denied, handled=${handled}`);
|
|
50999
51152
|
return handled;
|
|
@@ -51450,79 +51603,7 @@ class BugReportExecutor extends BaseExecutor {
|
|
|
51450
51603
|
}
|
|
51451
51604
|
// src/operations/executors/worktree-prompt.ts
|
|
51452
51605
|
init_emoji();
|
|
51453
|
-
|
|
51454
|
-
// src/utils/logger.ts
|
|
51455
|
-
var globalLogHandler = null;
|
|
51456
|
-
var COMPONENT_WIDTH = 10;
|
|
51457
|
-
function createLogger(component, useStderr = false, sessionId) {
|
|
51458
|
-
const isDebug = () => process.env.DEBUG === "1";
|
|
51459
|
-
const consoleLog = useStderr ? console.error : console.log;
|
|
51460
|
-
const paddedComponent = component.length > COMPONENT_WIDTH ? component.substring(0, COMPONENT_WIDTH) : component.padEnd(COMPONENT_WIDTH);
|
|
51461
|
-
const formatMessage = (msg, args) => {
|
|
51462
|
-
if (args.length === 0)
|
|
51463
|
-
return msg;
|
|
51464
|
-
return `${msg} ${args.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}`;
|
|
51465
|
-
};
|
|
51466
|
-
const DEFAULT_JSON_MAX_LEN = 60;
|
|
51467
|
-
return {
|
|
51468
|
-
debug: (msg, ...args) => {
|
|
51469
|
-
if (isDebug()) {
|
|
51470
|
-
const fullMsg = formatMessage(msg, args);
|
|
51471
|
-
if (globalLogHandler) {
|
|
51472
|
-
globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
|
|
51473
|
-
} else {
|
|
51474
|
-
consoleLog(`[${paddedComponent}] ${fullMsg}`);
|
|
51475
|
-
}
|
|
51476
|
-
}
|
|
51477
|
-
},
|
|
51478
|
-
debugJson: (label, data, maxLen = DEFAULT_JSON_MAX_LEN) => {
|
|
51479
|
-
if (isDebug()) {
|
|
51480
|
-
const json2 = JSON.stringify(data);
|
|
51481
|
-
const truncated = json2.length > maxLen ? `${json2.substring(0, maxLen)}…` : json2;
|
|
51482
|
-
const fullMsg = `${label}: ${truncated}`;
|
|
51483
|
-
if (globalLogHandler) {
|
|
51484
|
-
globalLogHandler("debug", paddedComponent, fullMsg, sessionId);
|
|
51485
|
-
} else {
|
|
51486
|
-
consoleLog(`[${paddedComponent}] ${fullMsg}`);
|
|
51487
|
-
}
|
|
51488
|
-
}
|
|
51489
|
-
},
|
|
51490
|
-
info: (msg, ...args) => {
|
|
51491
|
-
const fullMsg = formatMessage(msg, args);
|
|
51492
|
-
if (globalLogHandler) {
|
|
51493
|
-
globalLogHandler("info", paddedComponent, fullMsg, sessionId);
|
|
51494
|
-
} else {
|
|
51495
|
-
consoleLog(`[${paddedComponent}] ${fullMsg}`);
|
|
51496
|
-
}
|
|
51497
|
-
},
|
|
51498
|
-
warn: (msg, ...args) => {
|
|
51499
|
-
const fullMsg = formatMessage(msg, args);
|
|
51500
|
-
if (globalLogHandler) {
|
|
51501
|
-
globalLogHandler("warn", paddedComponent, fullMsg, sessionId);
|
|
51502
|
-
} else {
|
|
51503
|
-
console.warn(`[${paddedComponent}] ⚠️ ${fullMsg}`);
|
|
51504
|
-
}
|
|
51505
|
-
},
|
|
51506
|
-
error: (msg, err) => {
|
|
51507
|
-
const fullMsg = err && isDebug() ? `${msg}
|
|
51508
|
-
${err.stack || err.message}` : msg;
|
|
51509
|
-
if (globalLogHandler) {
|
|
51510
|
-
globalLogHandler("error", paddedComponent, fullMsg, sessionId);
|
|
51511
|
-
} else {
|
|
51512
|
-
console.error(`[${paddedComponent}] ❌ ${msg}`);
|
|
51513
|
-
if (err && isDebug()) {
|
|
51514
|
-
console.error(err);
|
|
51515
|
-
}
|
|
51516
|
-
}
|
|
51517
|
-
},
|
|
51518
|
-
forSession: (sid) => createLogger(component, useStderr, sid)
|
|
51519
|
-
};
|
|
51520
|
-
}
|
|
51521
|
-
var mcpLogger = createLogger("MCP", true);
|
|
51522
|
-
var wsLogger = createLogger("ws", false);
|
|
51523
|
-
|
|
51524
|
-
// src/operations/executors/worktree-prompt.ts
|
|
51525
|
-
var log = createLogger("wt-prompt");
|
|
51606
|
+
var log2 = createLogger("wt-prompt");
|
|
51526
51607
|
// src/operations/message-manager-events.ts
|
|
51527
51608
|
import { EventEmitter } from "events";
|
|
51528
51609
|
|
|
@@ -51571,7 +51652,7 @@ function formatBytes(bytes) {
|
|
|
51571
51652
|
}
|
|
51572
51653
|
|
|
51573
51654
|
// src/operations/streaming/handler.ts
|
|
51574
|
-
var
|
|
51655
|
+
var log3 = createLogger("streaming");
|
|
51575
51656
|
async function postSkippedFilesFeedback(platform, threadId, skipped) {
|
|
51576
51657
|
if (skipped.length === 0)
|
|
51577
51658
|
return;
|
|
@@ -51639,7 +51720,7 @@ function formatRelativeTime(date8) {
|
|
|
51639
51720
|
return `${diffMin} min ago`;
|
|
51640
51721
|
}
|
|
51641
51722
|
// src/operations/message-manager.ts
|
|
51642
|
-
var
|
|
51723
|
+
var log4 = createLogger("msg-mgr");
|
|
51643
51724
|
|
|
51644
51725
|
class MessageManager {
|
|
51645
51726
|
platform;
|
|
@@ -51732,7 +51813,7 @@ class MessageManager {
|
|
|
51732
51813
|
});
|
|
51733
51814
|
}
|
|
51734
51815
|
async handleEvent(event) {
|
|
51735
|
-
const logger =
|
|
51816
|
+
const logger = log4.forSession(this.sessionId);
|
|
51736
51817
|
const transformCtx = {
|
|
51737
51818
|
sessionId: this.sessionId,
|
|
51738
51819
|
formatter: this.platform.getFormatter(),
|
|
@@ -51786,7 +51867,7 @@ class MessageManager {
|
|
|
51786
51867
|
}
|
|
51787
51868
|
}
|
|
51788
51869
|
async executeOperation(op) {
|
|
51789
|
-
const logger =
|
|
51870
|
+
const logger = log4.forSession(this.sessionId);
|
|
51790
51871
|
const ctx = this.getExecutorContext();
|
|
51791
51872
|
try {
|
|
51792
51873
|
if (isContentOp(op)) {
|
|
@@ -51854,7 +51935,7 @@ class MessageManager {
|
|
|
51854
51935
|
threadId: this.threadId,
|
|
51855
51936
|
platform: this.platform,
|
|
51856
51937
|
formatter: this.platform.getFormatter(),
|
|
51857
|
-
logger:
|
|
51938
|
+
logger: log4.forSession(this.sessionId),
|
|
51858
51939
|
postTracker: this.postTracker,
|
|
51859
51940
|
contentBreaker: this.contentBreaker,
|
|
51860
51941
|
threadLogger: this.session.threadLogger,
|
|
@@ -52074,13 +52155,13 @@ class MessageManager {
|
|
|
52074
52155
|
return this.systemExecutor.postSuccess(message, this.getExecutorContext());
|
|
52075
52156
|
}
|
|
52076
52157
|
async prepareForUserMessage() {
|
|
52077
|
-
const logger =
|
|
52158
|
+
const logger = log4.forSession(this.sessionId);
|
|
52078
52159
|
logger.debug("Preparing for new user message");
|
|
52079
52160
|
await this.closeCurrentPost();
|
|
52080
52161
|
await this.bumpTaskList();
|
|
52081
52162
|
}
|
|
52082
52163
|
async handleUserMessage(message, files, username, displayName) {
|
|
52083
|
-
const logger =
|
|
52164
|
+
const logger = log4.forSession(this.sessionId);
|
|
52084
52165
|
if (!this.session.claude.isRunning()) {
|
|
52085
52166
|
logger.debug("Claude not running, ignoring user message");
|
|
52086
52167
|
return false;
|
|
@@ -52123,7 +52204,7 @@ class MessageManager {
|
|
|
52123
52204
|
];
|
|
52124
52205
|
}
|
|
52125
52206
|
async handleReaction(postId, emoji4, user, action) {
|
|
52126
|
-
const logger =
|
|
52207
|
+
const logger = log4.forSession(this.sessionId);
|
|
52127
52208
|
const ctx = this.getExecutorContext();
|
|
52128
52209
|
logger.debug(`Routing reaction: postId=${postId}, emoji=${emoji4}, user=${user}, action=${action}`);
|
|
52129
52210
|
for (const { name, executor } of this.reactionDispatchList()) {
|
|
@@ -52220,7 +52301,7 @@ class MessageManager {
|
|
|
52220
52301
|
}
|
|
52221
52302
|
}
|
|
52222
52303
|
// src/session/lifecycle-fsm.ts
|
|
52223
|
-
var
|
|
52304
|
+
var log5 = createLogger("fsm");
|
|
52224
52305
|
var ALLOWED_TRANSITIONS = {
|
|
52225
52306
|
starting: new Set(["active", "paused", "interrupted", "cancelling", "restarting"]),
|
|
52226
52307
|
active: new Set([
|
|
@@ -52247,7 +52328,7 @@ var ALLOWED_TRANSITIONS = {
|
|
|
52247
52328
|
};
|
|
52248
52329
|
// src/config/index.ts
|
|
52249
52330
|
import { resolve as resolve2, dirname as dirname2 } from "path";
|
|
52250
|
-
import { homedir } from "os";
|
|
52331
|
+
import { homedir as homedir2 } from "os";
|
|
52251
52332
|
|
|
52252
52333
|
// node_modules/js-yaml/dist/js-yaml.mjs
|
|
52253
52334
|
function getDefaultExportFromCjs(x) {
|
|
@@ -55359,7 +55440,7 @@ var jsYamlExports = requireJsYaml();
|
|
|
55359
55440
|
var yaml = /* @__PURE__ */ getDefaultExportFromCjs(jsYamlExports);
|
|
55360
55441
|
|
|
55361
55442
|
// src/config/index.ts
|
|
55362
|
-
var CONFIG_PATH = resolve2(
|
|
55443
|
+
var CONFIG_PATH = resolve2(homedir2(), ".config", "claude-threads", "config.yaml");
|
|
55363
55444
|
|
|
55364
55445
|
// src/utils/battery.ts
|
|
55365
55446
|
import { exec } from "child_process";
|
|
@@ -55464,7 +55545,7 @@ function formatReleaseNotes(notes, formatter) {
|
|
|
55464
55545
|
|
|
55465
55546
|
// src/utils/keep-alive.ts
|
|
55466
55547
|
import { spawn } from "child_process";
|
|
55467
|
-
var
|
|
55548
|
+
var log6 = createLogger("keepalive");
|
|
55468
55549
|
function keepAliveSpawnSpec(platform, parentPid) {
|
|
55469
55550
|
switch (platform) {
|
|
55470
55551
|
case "darwin":
|
|
@@ -55520,7 +55601,7 @@ class KeepAliveManager {
|
|
|
55520
55601
|
if (!enabled && this.keepAliveProcess) {
|
|
55521
55602
|
this.stopKeepAlive();
|
|
55522
55603
|
}
|
|
55523
|
-
|
|
55604
|
+
log6.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
|
|
55524
55605
|
}
|
|
55525
55606
|
isEnabled() {
|
|
55526
55607
|
return this.enabled;
|
|
@@ -55530,7 +55611,7 @@ class KeepAliveManager {
|
|
|
55530
55611
|
}
|
|
55531
55612
|
sessionStarted() {
|
|
55532
55613
|
this.activeSessionCount++;
|
|
55533
|
-
|
|
55614
|
+
log6.debug(`Session started (${this.activeSessionCount} active)`);
|
|
55534
55615
|
if (this.activeSessionCount === 1) {
|
|
55535
55616
|
this.startKeepAlive();
|
|
55536
55617
|
}
|
|
@@ -55539,7 +55620,7 @@ class KeepAliveManager {
|
|
|
55539
55620
|
if (this.activeSessionCount > 0) {
|
|
55540
55621
|
this.activeSessionCount--;
|
|
55541
55622
|
}
|
|
55542
|
-
|
|
55623
|
+
log6.debug(`Session ended (${this.activeSessionCount} active)`);
|
|
55543
55624
|
if (this.activeSessionCount === 0) {
|
|
55544
55625
|
this.stopKeepAlive();
|
|
55545
55626
|
}
|
|
@@ -55553,11 +55634,11 @@ class KeepAliveManager {
|
|
|
55553
55634
|
}
|
|
55554
55635
|
startKeepAlive() {
|
|
55555
55636
|
if (!this.enabled) {
|
|
55556
|
-
|
|
55637
|
+
log6.debug("Keep-alive disabled, skipping");
|
|
55557
55638
|
return;
|
|
55558
55639
|
}
|
|
55559
55640
|
if (this.keepAliveProcess) {
|
|
55560
|
-
|
|
55641
|
+
log6.debug("Keep-alive already running");
|
|
55561
55642
|
return;
|
|
55562
55643
|
}
|
|
55563
55644
|
switch (this.platform) {
|
|
@@ -55571,12 +55652,12 @@ class KeepAliveManager {
|
|
|
55571
55652
|
this.startWindowsKeepAlive();
|
|
55572
55653
|
break;
|
|
55573
55654
|
default:
|
|
55574
|
-
|
|
55655
|
+
log6.warn(`Keep-alive not supported on ${this.platform}`);
|
|
55575
55656
|
}
|
|
55576
55657
|
}
|
|
55577
55658
|
stopKeepAlive() {
|
|
55578
55659
|
if (this.keepAliveProcess) {
|
|
55579
|
-
|
|
55660
|
+
log6.debug("Stopping keep-alive");
|
|
55580
55661
|
this.keepAliveProcess.kill();
|
|
55581
55662
|
this.keepAliveProcess = null;
|
|
55582
55663
|
}
|
|
@@ -55591,18 +55672,18 @@ class KeepAliveManager {
|
|
|
55591
55672
|
detached: false
|
|
55592
55673
|
});
|
|
55593
55674
|
this.keepAliveProcess.on("error", (err) => {
|
|
55594
|
-
|
|
55675
|
+
log6.error(`Failed to start caffeinate: ${err.message}`);
|
|
55595
55676
|
this.keepAliveProcess = null;
|
|
55596
55677
|
});
|
|
55597
55678
|
this.keepAliveProcess.on("exit", (code) => {
|
|
55598
55679
|
if (code !== null && code !== 0 && this.activeSessionCount > 0) {
|
|
55599
|
-
|
|
55680
|
+
log6.debug(`caffeinate exited with code ${code}`);
|
|
55600
55681
|
}
|
|
55601
55682
|
this.keepAliveProcess = null;
|
|
55602
55683
|
});
|
|
55603
|
-
|
|
55684
|
+
log6.info("Sleep prevention active (caffeinate)");
|
|
55604
55685
|
} catch (err) {
|
|
55605
|
-
|
|
55686
|
+
log6.error(`Failed to start caffeinate: ${err}`);
|
|
55606
55687
|
}
|
|
55607
55688
|
}
|
|
55608
55689
|
startLinuxKeepAlive() {
|
|
@@ -55615,19 +55696,19 @@ class KeepAliveManager {
|
|
|
55615
55696
|
detached: false
|
|
55616
55697
|
});
|
|
55617
55698
|
this.keepAliveProcess.on("error", (err) => {
|
|
55618
|
-
|
|
55699
|
+
log6.debug(`systemd-inhibit not available: ${err.message}`);
|
|
55619
55700
|
this.keepAliveProcess = null;
|
|
55620
55701
|
this.startLinuxKeepAliveFallback();
|
|
55621
55702
|
});
|
|
55622
55703
|
this.keepAliveProcess.on("exit", (code) => {
|
|
55623
55704
|
if (code !== null && code !== 0 && this.activeSessionCount > 0) {
|
|
55624
|
-
|
|
55705
|
+
log6.debug(`systemd-inhibit exited with code ${code}`);
|
|
55625
55706
|
}
|
|
55626
55707
|
this.keepAliveProcess = null;
|
|
55627
55708
|
});
|
|
55628
|
-
|
|
55709
|
+
log6.info("Sleep prevention active (systemd-inhibit)");
|
|
55629
55710
|
} catch (err) {
|
|
55630
|
-
|
|
55711
|
+
log6.debug(`Failed to start systemd-inhibit: ${err}`);
|
|
55631
55712
|
this.startLinuxKeepAliveFallback();
|
|
55632
55713
|
}
|
|
55633
55714
|
}
|
|
@@ -55638,15 +55719,15 @@ class KeepAliveManager {
|
|
|
55638
55719
|
detached: false
|
|
55639
55720
|
});
|
|
55640
55721
|
this.keepAliveProcess.on("error", (err) => {
|
|
55641
|
-
|
|
55722
|
+
log6.warn(`Linux keep-alive fallback not available: ${err.message}`);
|
|
55642
55723
|
this.keepAliveProcess = null;
|
|
55643
55724
|
});
|
|
55644
55725
|
this.keepAliveProcess.on("exit", () => {
|
|
55645
55726
|
this.keepAliveProcess = null;
|
|
55646
55727
|
});
|
|
55647
|
-
|
|
55728
|
+
log6.info("Sleep prevention active (xdg-screensaver)");
|
|
55648
55729
|
} catch (err) {
|
|
55649
|
-
|
|
55730
|
+
log6.warn(`Linux keep-alive not available: ${err}`);
|
|
55650
55731
|
}
|
|
55651
55732
|
}
|
|
55652
55733
|
startWindowsKeepAlive() {
|
|
@@ -55658,18 +55739,18 @@ class KeepAliveManager {
|
|
|
55658
55739
|
windowsHide: true
|
|
55659
55740
|
});
|
|
55660
55741
|
this.keepAliveProcess.on("error", (err) => {
|
|
55661
|
-
|
|
55742
|
+
log6.warn(`Windows keep-alive not available: ${err.message}`);
|
|
55662
55743
|
this.keepAliveProcess = null;
|
|
55663
55744
|
});
|
|
55664
55745
|
this.keepAliveProcess.on("exit", (code) => {
|
|
55665
55746
|
if (code !== null && code !== 0 && this.activeSessionCount > 0) {
|
|
55666
|
-
|
|
55747
|
+
log6.debug(`PowerShell keep-alive exited with code ${code}`);
|
|
55667
55748
|
}
|
|
55668
55749
|
this.keepAliveProcess = null;
|
|
55669
55750
|
});
|
|
55670
|
-
|
|
55751
|
+
log6.info("Sleep prevention active (SetThreadExecutionState)");
|
|
55671
55752
|
} catch (err) {
|
|
55672
|
-
|
|
55753
|
+
log6.warn(`Windows keep-alive not available: ${err}`);
|
|
55673
55754
|
}
|
|
55674
55755
|
}
|
|
55675
55756
|
}
|
|
@@ -55683,7 +55764,7 @@ function formatSponsorFooter(formatter) {
|
|
|
55683
55764
|
}
|
|
55684
55765
|
|
|
55685
55766
|
// src/operations/sticky-message/handler.ts
|
|
55686
|
-
var
|
|
55767
|
+
var log7 = createLogger("sticky");
|
|
55687
55768
|
var botStartedAt = new Date;
|
|
55688
55769
|
var stickyPostIds = new Map;
|
|
55689
55770
|
var needsBump = new Map;
|
|
@@ -55922,10 +56003,10 @@ class Redactor {
|
|
|
55922
56003
|
}
|
|
55923
56004
|
|
|
55924
56005
|
// src/persistence/thread-logger.ts
|
|
55925
|
-
import { homedir as
|
|
55926
|
-
import { join as
|
|
55927
|
-
var
|
|
55928
|
-
var LOGS_BASE_DIR =
|
|
56006
|
+
import { homedir as homedir3 } from "os";
|
|
56007
|
+
import { join as join3, dirname as dirname4 } from "path";
|
|
56008
|
+
var log8 = createLogger("thread-log");
|
|
56009
|
+
var LOGS_BASE_DIR = join3(homedir3(), ".claude-threads", "logs");
|
|
55929
56010
|
|
|
55930
56011
|
// src/operations/bug-report/handler.ts
|
|
55931
56012
|
var piiRedactor = new Redactor({ aggressive: true });
|
|
@@ -55948,7 +56029,7 @@ class UsernameAnonymizer {
|
|
|
55948
56029
|
// src/mcp/decision-bridge.ts
|
|
55949
56030
|
import { createServer, createConnection } from "node:net";
|
|
55950
56031
|
import { tmpdir } from "node:os";
|
|
55951
|
-
import { join as
|
|
56032
|
+
import { join as join4 } from "node:path";
|
|
55952
56033
|
import { randomUUID } from "node:crypto";
|
|
55953
56034
|
import { mkdtempSync } from "node:fs";
|
|
55954
56035
|
import { rm } from "node:fs/promises";
|
|
@@ -55959,8 +56040,8 @@ function bridgeSocketPath() {
|
|
|
55959
56040
|
if (process.platform === "win32") {
|
|
55960
56041
|
return `\\\\.\\pipe\\ctb-${randomUUID()}`;
|
|
55961
56042
|
}
|
|
55962
|
-
const dir = mkdtempSync(
|
|
55963
|
-
return
|
|
56043
|
+
const dir = mkdtempSync(join4(tmpdir(), "ctb-"));
|
|
56044
|
+
return join4(dir, "b.sock");
|
|
55964
56045
|
}
|
|
55965
56046
|
|
|
55966
56047
|
class DecisionBridgeServer {
|
|
@@ -56030,7 +56111,7 @@ class DecisionBridgeServer {
|
|
|
56030
56111
|
});
|
|
56031
56112
|
} catch (err) {
|
|
56032
56113
|
if (process.platform !== "win32") {
|
|
56033
|
-
await rm(
|
|
56114
|
+
await rm(join4(path, ".."), { recursive: true, force: true }).catch(() => {});
|
|
56034
56115
|
}
|
|
56035
56116
|
throw err;
|
|
56036
56117
|
}
|
|
@@ -56043,7 +56124,7 @@ class DecisionBridgeServer {
|
|
|
56043
56124
|
socket.destroy();
|
|
56044
56125
|
await new Promise((resolve4) => this.server.close(() => resolve4()));
|
|
56045
56126
|
if (process.platform !== "win32") {
|
|
56046
|
-
await rm(
|
|
56127
|
+
await rm(join4(this.path, ".."), { recursive: true, force: true }).catch(() => {});
|
|
56047
56128
|
}
|
|
56048
56129
|
}
|
|
56049
56130
|
}
|
|
@@ -56106,7 +56187,7 @@ import { resolve as resolve4, dirname as dirname5 } from "path";
|
|
|
56106
56187
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
56107
56188
|
import { existsSync as existsSync4, readFileSync as readFileSync3, watchFile, unwatchFile, unlinkSync, statSync, readdirSync, writeFileSync } from "fs";
|
|
56108
56189
|
import { tmpdir as tmpdir2 } from "os";
|
|
56109
|
-
import { join as
|
|
56190
|
+
import { join as join5 } from "path";
|
|
56110
56191
|
|
|
56111
56192
|
// src/mcp/outbound-env.ts
|
|
56112
56193
|
var OUTBOUND_ENV = {
|
|
@@ -56197,25 +56278,25 @@ function parseRateLimitEvent(event, now = Date.now()) {
|
|
|
56197
56278
|
}
|
|
56198
56279
|
|
|
56199
56280
|
// src/claude/cli.ts
|
|
56200
|
-
var
|
|
56281
|
+
var log9 = createLogger("claude");
|
|
56201
56282
|
function cleanupBrowserBridgeSockets() {
|
|
56202
56283
|
try {
|
|
56203
56284
|
const tempDir = tmpdir2();
|
|
56204
56285
|
const files = readdirSync(tempDir);
|
|
56205
56286
|
for (const file2 of files) {
|
|
56206
56287
|
if (file2.startsWith("claude-mcp-browser-bridge-")) {
|
|
56207
|
-
const filePath =
|
|
56288
|
+
const filePath = join5(tempDir, file2);
|
|
56208
56289
|
try {
|
|
56209
56290
|
const stats = statSync(filePath);
|
|
56210
56291
|
if (stats.isSocket()) {
|
|
56211
56292
|
unlinkSync(filePath);
|
|
56212
|
-
|
|
56293
|
+
log9.debug(`Removed stale browser bridge socket: ${file2}`);
|
|
56213
56294
|
}
|
|
56214
56295
|
} catch {}
|
|
56215
56296
|
}
|
|
56216
56297
|
}
|
|
56217
56298
|
} catch (err) {
|
|
56218
|
-
|
|
56299
|
+
log9.debug(`Browser bridge cleanup failed: ${err}`);
|
|
56219
56300
|
}
|
|
56220
56301
|
}
|
|
56221
56302
|
function buildClaudeChildEnv(parentEnv, account, opts) {
|
|
@@ -56274,7 +56355,7 @@ function materializeMcpConfig(config3, sessionId, opts = {}) {
|
|
|
56274
56355
|
return { mode: "inline", value: JSON.stringify(config3) };
|
|
56275
56356
|
}
|
|
56276
56357
|
const dir = opts.tmpDirOverride ?? tmpdir2();
|
|
56277
|
-
const path =
|
|
56358
|
+
const path = join5(dir, `claude-threads-mcp-${sessionId ?? process.pid}-${Date.now()}.json`);
|
|
56278
56359
|
writeFileSync(path, JSON.stringify(config3), { mode: 384 });
|
|
56279
56360
|
return { mode: "file", path };
|
|
56280
56361
|
}
|
|
@@ -56457,7 +56538,7 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
56457
56538
|
}
|
|
56458
56539
|
let statusLineCommand;
|
|
56459
56540
|
if (this.options.sessionId) {
|
|
56460
|
-
this.statusFilePath =
|
|
56541
|
+
this.statusFilePath = join5(tmpdir2(), `claude-threads-status-${this.options.sessionId}.json`);
|
|
56461
56542
|
const statusLineWriterPath = this.getStatusLineWriterPath();
|
|
56462
56543
|
const runtime = runtimeForScriptPath(statusLineWriterPath);
|
|
56463
56544
|
statusLineCommand = `${runtime} ${statusLineWriterPath} ${this.options.sessionId}`;
|
|
@@ -57379,7 +57460,7 @@ handlers.set("compact", createPassthroughHandler("compact"));
|
|
|
57379
57460
|
handlers.set("model", createPassthroughHandler("model"));
|
|
57380
57461
|
handlers.set("effort", createPassthroughHandler("effort"));
|
|
57381
57462
|
// src/commands/system-prompt-generator.ts
|
|
57382
|
-
var
|
|
57463
|
+
var log10 = createLogger("system-prompt");
|
|
57383
57464
|
function formatUserCommand(cmd) {
|
|
57384
57465
|
const cmdStr = cmd.args ? `\`!${cmd.command} ${cmd.args}\`` : `\`!${cmd.command}\``;
|
|
57385
57466
|
const description = cmd.description;
|
|
@@ -57464,7 +57545,7 @@ ${avoidCommands.map((c) => `- \`!${c.command}\` - ${c.reason}`).join(`
|
|
|
57464
57545
|
`.trim();
|
|
57465
57546
|
}
|
|
57466
57547
|
// src/utils/error-handler/index.ts
|
|
57467
|
-
var
|
|
57548
|
+
var log11 = createLogger("error");
|
|
57468
57549
|
|
|
57469
57550
|
// src/utils/session-log.ts
|
|
57470
57551
|
function createSessionLog(baseLog) {
|
|
@@ -57481,45 +57562,45 @@ init_emoji();
|
|
|
57481
57562
|
|
|
57482
57563
|
// src/git/worktree.ts
|
|
57483
57564
|
import * as path from "path";
|
|
57484
|
-
import { homedir as
|
|
57485
|
-
var
|
|
57486
|
-
var WORKTREES_DIR = path.join(
|
|
57487
|
-
var METADATA_STORE_PATH = path.join(
|
|
57565
|
+
import { homedir as homedir4 } from "os";
|
|
57566
|
+
var log12 = createLogger("git-wt");
|
|
57567
|
+
var WORKTREES_DIR = path.join(homedir4(), ".claude-threads", "worktrees");
|
|
57568
|
+
var METADATA_STORE_PATH = path.join(homedir4(), ".claude-threads", "worktree-metadata.json");
|
|
57488
57569
|
|
|
57489
57570
|
// src/operations/post-helpers/index.ts
|
|
57490
|
-
var
|
|
57491
|
-
var sessionLog = createSessionLog(
|
|
57571
|
+
var log13 = createLogger("helpers");
|
|
57572
|
+
var sessionLog = createSessionLog(log13);
|
|
57492
57573
|
|
|
57493
57574
|
// src/claude/quick-query.ts
|
|
57494
|
-
var
|
|
57575
|
+
var log14 = createLogger("query");
|
|
57495
57576
|
|
|
57496
57577
|
// src/operations/suggestions/title.ts
|
|
57497
|
-
var
|
|
57578
|
+
var log15 = createLogger("title");
|
|
57498
57579
|
|
|
57499
57580
|
// src/operations/suggestions/tag.ts
|
|
57500
|
-
var
|
|
57581
|
+
var log16 = createLogger("tags");
|
|
57501
57582
|
|
|
57502
57583
|
// src/operations/context-prompt/handler.ts
|
|
57503
57584
|
init_emoji();
|
|
57504
|
-
var
|
|
57505
|
-
var sessionLog2 = createSessionLog(
|
|
57585
|
+
var log17 = createLogger("context");
|
|
57586
|
+
var sessionLog2 = createSessionLog(log17);
|
|
57506
57587
|
var contextPromptTimeouts = new Map;
|
|
57507
57588
|
var contextPromptFiles = new Map;
|
|
57508
57589
|
// src/memory/store.ts
|
|
57509
57590
|
import { createHash } from "crypto";
|
|
57510
57591
|
import {
|
|
57511
|
-
chmodSync,
|
|
57592
|
+
chmodSync as chmodSync2,
|
|
57512
57593
|
existsSync as existsSync5,
|
|
57513
|
-
mkdirSync,
|
|
57594
|
+
mkdirSync as mkdirSync2,
|
|
57514
57595
|
readFileSync as readFileSync4,
|
|
57515
57596
|
renameSync,
|
|
57516
57597
|
realpathSync,
|
|
57517
57598
|
writeFileSync as writeFileSync2
|
|
57518
57599
|
} from "fs";
|
|
57519
|
-
import { homedir as
|
|
57520
|
-
import { basename as basename3, dirname as dirname7, join as
|
|
57521
|
-
var
|
|
57522
|
-
var DEFAULT_ROOT =
|
|
57600
|
+
import { homedir as homedir5 } from "os";
|
|
57601
|
+
import { basename as basename3, dirname as dirname7, join as join7, sep as sep2 } from "path";
|
|
57602
|
+
var log18 = createLogger("memory");
|
|
57603
|
+
var DEFAULT_ROOT = join7(homedir5(), ".config", "claude-threads", "memory");
|
|
57523
57604
|
var CHANNEL_BLOCK_MAX_LINES = 200;
|
|
57524
57605
|
var CHANNEL_BLOCK_MAX_BYTES = 25 * 1024;
|
|
57525
57606
|
var CHANNEL_FILE_MAX_ENTRIES = 400;
|
|
@@ -57562,10 +57643,10 @@ class MemoryStore {
|
|
|
57562
57643
|
return this.root;
|
|
57563
57644
|
}
|
|
57564
57645
|
channelMemoryPath(platformId) {
|
|
57565
|
-
return
|
|
57646
|
+
return join7(this.root, platformSegment(platformId), "channel", "MEMORY.md");
|
|
57566
57647
|
}
|
|
57567
57648
|
repoMemoryDir(platformId, repoKey) {
|
|
57568
|
-
const dir =
|
|
57649
|
+
const dir = join7(this.root, platformSegment(platformId), "repos", repoKey);
|
|
57569
57650
|
this.ensureDir(dir);
|
|
57570
57651
|
return dir;
|
|
57571
57652
|
}
|
|
@@ -57612,7 +57693,7 @@ class MemoryStore {
|
|
|
57612
57693
|
if (result.added.length > 0) {
|
|
57613
57694
|
this.enforceFileCap(lines);
|
|
57614
57695
|
this.writeLines(platformId, lines);
|
|
57615
|
-
|
|
57696
|
+
log18.debug(`Channel memory for ${platformId}: +${result.added.length} entries` + (result.duplicates.length ? ` (${result.duplicates.length} duplicates skipped)` : ""));
|
|
57616
57697
|
}
|
|
57617
57698
|
return result;
|
|
57618
57699
|
});
|
|
@@ -57651,14 +57732,14 @@ class MemoryStore {
|
|
|
57651
57732
|
}
|
|
57652
57733
|
lines.splice(target.lineIndex, 1);
|
|
57653
57734
|
this.writeLines(platformId, lines);
|
|
57654
|
-
|
|
57735
|
+
log18.debug(`Channel memory for ${platformId}: removed one entry`);
|
|
57655
57736
|
return { ok: true, removed: target.entry };
|
|
57656
57737
|
});
|
|
57657
57738
|
}
|
|
57658
57739
|
clearChannel(platformId) {
|
|
57659
57740
|
return this.runExclusive(platformId, () => {
|
|
57660
57741
|
this.writeLines(platformId, []);
|
|
57661
|
-
|
|
57742
|
+
log18.debug(`Channel memory for ${platformId}: cleared`);
|
|
57662
57743
|
});
|
|
57663
57744
|
}
|
|
57664
57745
|
buildChannelMemoryBlock(platformId) {
|
|
@@ -57666,7 +57747,7 @@ class MemoryStore {
|
|
|
57666
57747
|
try {
|
|
57667
57748
|
lines = this.loadLines(platformId);
|
|
57668
57749
|
} catch (err) {
|
|
57669
|
-
|
|
57750
|
+
log18.warn(`Failed to read channel memory for ${platformId}: ${err.message}`);
|
|
57670
57751
|
return null;
|
|
57671
57752
|
}
|
|
57672
57753
|
if (lines.length === 0)
|
|
@@ -57741,21 +57822,21 @@ _(older entries omitted — \`!memory\` shows all)_` : rendered;
|
|
|
57741
57822
|
const tempFile = `${file2}.tmp`;
|
|
57742
57823
|
writeFileSync2(tempFile, content, { encoding: "utf-8", mode: 384 });
|
|
57743
57824
|
renameSync(tempFile, file2);
|
|
57744
|
-
|
|
57825
|
+
chmodSync2(file2, 384);
|
|
57745
57826
|
}
|
|
57746
57827
|
ensureDir(dir) {
|
|
57747
57828
|
if (!existsSync5(dir)) {
|
|
57748
|
-
|
|
57829
|
+
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
57749
57830
|
}
|
|
57750
57831
|
}
|
|
57751
57832
|
}
|
|
57752
57833
|
|
|
57753
57834
|
// src/memory/distiller.ts
|
|
57754
|
-
var
|
|
57835
|
+
var log19 = createLogger("memory");
|
|
57755
57836
|
|
|
57756
57837
|
// src/session/lifecycle.ts
|
|
57757
|
-
var
|
|
57758
|
-
var sessionLog3 = createSessionLog(
|
|
57838
|
+
var log20 = createLogger("lifecycle");
|
|
57839
|
+
var sessionLog3 = createSessionLog(log20);
|
|
57759
57840
|
var _inFlightSessionStarts = new Map;
|
|
57760
57841
|
var CHAT_PLATFORM_PROMPT = generateChatPlatformPrompt();
|
|
57761
57842
|
// src/update-notifier.ts
|
|
@@ -57765,20 +57846,20 @@ var import_semver2 = __toESM(require_semver2(), 1);
|
|
|
57765
57846
|
init_emoji();
|
|
57766
57847
|
|
|
57767
57848
|
// src/persistence/github-emails-store.ts
|
|
57768
|
-
import { homedir as homedir5 } from "os";
|
|
57769
|
-
import { join as join7 } from "path";
|
|
57770
|
-
var log20 = createLogger("gh-emails");
|
|
57771
|
-
var DEFAULT_CONFIG_DIR = join7(homedir5(), ".config", "claude-threads");
|
|
57772
|
-
var DEFAULT_FILE = join7(DEFAULT_CONFIG_DIR, "github-emails.yaml");
|
|
57773
|
-
|
|
57774
|
-
// src/persistence/routines-store.ts
|
|
57775
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "fs";
|
|
57776
57849
|
import { homedir as homedir6 } from "os";
|
|
57777
57850
|
import { join as join8 } from "path";
|
|
57851
|
+
var log21 = createLogger("gh-emails");
|
|
57852
|
+
var DEFAULT_CONFIG_DIR = join8(homedir6(), ".config", "claude-threads");
|
|
57853
|
+
var DEFAULT_FILE = join8(DEFAULT_CONFIG_DIR, "github-emails.yaml");
|
|
57854
|
+
|
|
57855
|
+
// src/persistence/routines-store.ts
|
|
57856
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5 } from "fs";
|
|
57857
|
+
import { homedir as homedir7 } from "os";
|
|
57858
|
+
import { join as join9 } from "path";
|
|
57778
57859
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
57779
57860
|
|
|
57780
57861
|
// src/persistence/atomic-file.ts
|
|
57781
|
-
import { chmodSync as
|
|
57862
|
+
import { chmodSync as chmodSync3, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
57782
57863
|
|
|
57783
57864
|
class SerialQueue {
|
|
57784
57865
|
tail = Promise.resolve();
|
|
@@ -57794,13 +57875,13 @@ function writeFileAtomic(file2, content) {
|
|
|
57794
57875
|
const tempFile = `${file2}.tmp`;
|
|
57795
57876
|
writeFileSync3(tempFile, content, { encoding: "utf-8", mode: 384 });
|
|
57796
57877
|
renameSync2(tempFile, file2);
|
|
57797
|
-
|
|
57878
|
+
chmodSync3(file2, 384);
|
|
57798
57879
|
}
|
|
57799
57880
|
|
|
57800
57881
|
// src/persistence/routines-store.ts
|
|
57801
|
-
var
|
|
57802
|
-
var DEFAULT_CONFIG_DIR2 =
|
|
57803
|
-
var DEFAULT_FILE2 =
|
|
57882
|
+
var log22 = createLogger("routines");
|
|
57883
|
+
var DEFAULT_CONFIG_DIR2 = join9(homedir7(), ".config", "claude-threads");
|
|
57884
|
+
var DEFAULT_FILE2 = join9(DEFAULT_CONFIG_DIR2, "routines.yaml");
|
|
57804
57885
|
var STORE_VERSION = 1;
|
|
57805
57886
|
var DEFAULT_MAX_ROUTINES = 10;
|
|
57806
57887
|
var SCHEDULE_PRESETS = ["hourly", "daily", "weekdays", "weekly"];
|
|
@@ -57844,13 +57925,13 @@ class RoutinesStore {
|
|
|
57844
57925
|
const effective = filePath ?? process.env.CLAUDE_THREADS_ROUTINES_PATH;
|
|
57845
57926
|
if (effective) {
|
|
57846
57927
|
this.file = effective;
|
|
57847
|
-
this.configDir =
|
|
57928
|
+
this.configDir = join9(effective, "..");
|
|
57848
57929
|
} else {
|
|
57849
57930
|
this.file = DEFAULT_FILE2;
|
|
57850
57931
|
this.configDir = DEFAULT_CONFIG_DIR2;
|
|
57851
57932
|
}
|
|
57852
57933
|
if (!existsSync6(this.configDir)) {
|
|
57853
|
-
|
|
57934
|
+
mkdirSync3(this.configDir, { recursive: true, mode: 448 });
|
|
57854
57935
|
}
|
|
57855
57936
|
}
|
|
57856
57937
|
list(platformId) {
|
|
@@ -57884,7 +57965,7 @@ class RoutinesStore {
|
|
|
57884
57965
|
};
|
|
57885
57966
|
data.routines[platformId] = [...existing, full];
|
|
57886
57967
|
this.writeAtomic(data);
|
|
57887
|
-
|
|
57968
|
+
log22.info(`Routine "${full.name}" created on ${platformId} by @${full.createdBy}`);
|
|
57888
57969
|
return { ok: true, routine: full };
|
|
57889
57970
|
});
|
|
57890
57971
|
}
|
|
@@ -57911,7 +57992,7 @@ class RoutinesStore {
|
|
|
57911
57992
|
if (routines.length === 0)
|
|
57912
57993
|
delete data.routines[platformId];
|
|
57913
57994
|
this.writeAtomic(data);
|
|
57914
|
-
|
|
57995
|
+
log22.info(`Routine "${removed.name}" removed from ${platformId}`);
|
|
57915
57996
|
return removed;
|
|
57916
57997
|
});
|
|
57917
57998
|
}
|
|
@@ -57936,7 +58017,7 @@ class RoutinesStore {
|
|
|
57936
58017
|
}
|
|
57937
58018
|
return { version: parsed.version ?? STORE_VERSION, routines };
|
|
57938
58019
|
} catch (err) {
|
|
57939
|
-
|
|
58020
|
+
log22.warn(`Failed to read ${this.file}: ${err.message} — starting empty`);
|
|
57940
58021
|
return { version: STORE_VERSION, routines: {} };
|
|
57941
58022
|
}
|
|
57942
58023
|
}
|
|
@@ -57946,25 +58027,25 @@ class RoutinesStore {
|
|
|
57946
58027
|
}
|
|
57947
58028
|
|
|
57948
58029
|
// src/routines/parser.ts
|
|
57949
|
-
var
|
|
58030
|
+
var log23 = createLogger("routines");
|
|
57950
58031
|
|
|
57951
58032
|
// src/operations/commands/handler.ts
|
|
57952
|
-
var
|
|
57953
|
-
var sessionLog4 = createSessionLog(
|
|
58033
|
+
var log24 = createLogger("commands");
|
|
58034
|
+
var sessionLog4 = createSessionLog(log24);
|
|
57954
58035
|
// src/operations/suggestions/branch.ts
|
|
57955
58036
|
import { exec as exec2 } from "child_process";
|
|
57956
58037
|
import { promisify as promisify2 } from "util";
|
|
57957
58038
|
var execAsync2 = promisify2(exec2);
|
|
57958
|
-
var
|
|
58039
|
+
var log25 = createLogger("branch");
|
|
57959
58040
|
|
|
57960
58041
|
// src/operations/worktree/handler.ts
|
|
57961
|
-
var
|
|
57962
|
-
var sessionLog5 = createSessionLog(
|
|
58042
|
+
var log26 = createLogger("worktree");
|
|
58043
|
+
var sessionLog5 = createSessionLog(log26);
|
|
57963
58044
|
// src/operations/events/handler.ts
|
|
57964
|
-
var
|
|
57965
|
-
var sessionLog6 = createSessionLog(
|
|
58045
|
+
var log27 = createLogger("events");
|
|
58046
|
+
var sessionLog6 = createSessionLog(log27);
|
|
57966
58047
|
// src/operations/monitor/handler.ts
|
|
57967
|
-
var
|
|
58048
|
+
var log28 = createLogger("monitor");
|
|
57968
58049
|
var DEFAULT_INTERVAL_MS = 60 * 1000;
|
|
57969
58050
|
// src/utils/websocket.ts
|
|
57970
58051
|
var WS;
|
|
@@ -58046,7 +58127,7 @@ ${code}
|
|
|
58046
58127
|
|
|
58047
58128
|
// src/platform/mattermost/upload.ts
|
|
58048
58129
|
import { readFile } from "fs/promises";
|
|
58049
|
-
var
|
|
58130
|
+
var log29 = createLogger("mm-upload");
|
|
58050
58131
|
async function uploadFileMattermost(args) {
|
|
58051
58132
|
const { url: url2, token, channelId, threadId, filePath, filename, caption } = args;
|
|
58052
58133
|
const buffer = await readFile(filePath);
|
|
@@ -58054,7 +58135,7 @@ async function uploadFileMattermost(args) {
|
|
|
58054
58135
|
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
58055
58136
|
const formData = new FormData;
|
|
58056
58137
|
formData.append("files", new Blob([arrayBuffer]), filename);
|
|
58057
|
-
|
|
58138
|
+
log29.debug(`POST /files (${buffer.length} bytes, ${filename})`);
|
|
58058
58139
|
const uploadResponse = await fetch(uploadUrl, {
|
|
58059
58140
|
method: "POST",
|
|
58060
58141
|
headers: {
|
|
@@ -58078,7 +58159,7 @@ async function uploadFileMattermost(args) {
|
|
|
58078
58159
|
root_id: resolvePostThreadId(threadId),
|
|
58079
58160
|
file_ids: [fileInfo.id]
|
|
58080
58161
|
};
|
|
58081
|
-
|
|
58162
|
+
log29.debug(`POST /posts (file_ids=[${fileInfo.id}])`);
|
|
58082
58163
|
const postResponse = await fetch(postUrl, {
|
|
58083
58164
|
method: "POST",
|
|
58084
58165
|
headers: {
|
|
@@ -58572,7 +58653,7 @@ ${code}
|
|
|
58572
58653
|
|
|
58573
58654
|
// src/platform/slack/upload.ts
|
|
58574
58655
|
import { readFile as readFile2 } from "fs/promises";
|
|
58575
|
-
var
|
|
58656
|
+
var log30 = createLogger("slack-upload");
|
|
58576
58657
|
var DEFAULT_API_URL = "https://slack.com/api";
|
|
58577
58658
|
async function uploadFileSlack(args) {
|
|
58578
58659
|
const { botToken, channelId, threadTs, filePath, filename, caption } = args;
|
|
@@ -58580,7 +58661,7 @@ async function uploadFileSlack(args) {
|
|
|
58580
58661
|
const buffer = await readFile2(filePath);
|
|
58581
58662
|
const params = new URLSearchParams({ filename, length: String(buffer.length) });
|
|
58582
58663
|
const step1Url = `${apiUrl}/files.getUploadURLExternal?${params.toString()}`;
|
|
58583
|
-
|
|
58664
|
+
log30.debug(`GET files.getUploadURLExternal (${buffer.length} bytes, ${filename})`);
|
|
58584
58665
|
const step1Response = await fetch(step1Url, {
|
|
58585
58666
|
method: "GET",
|
|
58586
58667
|
headers: {
|
|
@@ -58598,7 +58679,7 @@ async function uploadFileSlack(args) {
|
|
|
58598
58679
|
const uploadUrl = step1Data.upload_url;
|
|
58599
58680
|
const fileId = step1Data.file_id;
|
|
58600
58681
|
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
58601
|
-
|
|
58682
|
+
log30.debug(`POST <upload_url>`);
|
|
58602
58683
|
const step2Response = await fetch(uploadUrl, {
|
|
58603
58684
|
method: "POST",
|
|
58604
58685
|
headers: {
|
|
@@ -58618,7 +58699,7 @@ async function uploadFileSlack(args) {
|
|
|
58618
58699
|
if (caption !== undefined) {
|
|
58619
58700
|
step3Body.initial_comment = caption;
|
|
58620
58701
|
}
|
|
58621
|
-
|
|
58702
|
+
log30.debug(`POST files.completeUploadExternal (file_id=${fileId}, thread_ts=${threadTs})`);
|
|
58622
58703
|
const step3Response = await fetch(`${apiUrl}/files.completeUploadExternal`, {
|
|
58623
58704
|
method: "POST",
|
|
58624
58705
|
headers: {
|
|
@@ -58636,7 +58717,7 @@ async function uploadFileSlack(args) {
|
|
|
58636
58717
|
throw new Error(`Slack completeUploadExternal error: ${step3Data.error || "unknown"}`);
|
|
58637
58718
|
}
|
|
58638
58719
|
if (!step3Data.ts) {
|
|
58639
|
-
|
|
58720
|
+
log30.warn(`Slack completeUploadExternal returned no ts; using fileId ${fileId} as postId. ` + `Do not use this id for updatePost/addReaction.`);
|
|
58640
58721
|
}
|
|
58641
58722
|
return { fileId, postId: step3Data.ts ?? fileId };
|
|
58642
58723
|
}
|