claude-threads 1.9.1 → 1.9.3
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 +517 -440
- package/dist/mcp/permission-server.js +93 -50
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11747,76 +11747,6 @@ var require_ws = __commonJS((exports, module) => {
|
|
|
11747
11747
|
module.exports = WebSocket;
|
|
11748
11748
|
});
|
|
11749
11749
|
|
|
11750
|
-
// src/utils/emoji.ts
|
|
11751
|
-
var exports_emoji = {};
|
|
11752
|
-
__export(exports_emoji, {
|
|
11753
|
-
isResumeEmoji: () => isResumeEmoji,
|
|
11754
|
-
isMinimizeToggleEmoji: () => isMinimizeToggleEmoji,
|
|
11755
|
-
isEscapeEmoji: () => isEscapeEmoji,
|
|
11756
|
-
isDenialEmoji: () => isDenialEmoji,
|
|
11757
|
-
isCancelEmoji: () => isCancelEmoji,
|
|
11758
|
-
isBugReportEmoji: () => isBugReportEmoji,
|
|
11759
|
-
isApprovalEmoji: () => isApprovalEmoji,
|
|
11760
|
-
isAllowAllEmoji: () => isAllowAllEmoji,
|
|
11761
|
-
getNumberEmojiIndex: () => getNumberEmojiIndex,
|
|
11762
|
-
RESUME_EMOJIS: () => RESUME_EMOJIS,
|
|
11763
|
-
NUMBER_EMOJIS: () => NUMBER_EMOJIS,
|
|
11764
|
-
MINIMIZE_TOGGLE_EMOJIS: () => MINIMIZE_TOGGLE_EMOJIS,
|
|
11765
|
-
ESCAPE_EMOJIS: () => ESCAPE_EMOJIS,
|
|
11766
|
-
DENIAL_EMOJIS: () => DENIAL_EMOJIS,
|
|
11767
|
-
CANCEL_EMOJIS: () => CANCEL_EMOJIS,
|
|
11768
|
-
BUG_REPORT_EMOJI: () => BUG_REPORT_EMOJI,
|
|
11769
|
-
APPROVAL_EMOJIS: () => APPROVAL_EMOJIS,
|
|
11770
|
-
ALLOW_ALL_EMOJIS: () => ALLOW_ALL_EMOJIS
|
|
11771
|
-
});
|
|
11772
|
-
function isApprovalEmoji(emoji) {
|
|
11773
|
-
return APPROVAL_EMOJIS.includes(emoji);
|
|
11774
|
-
}
|
|
11775
|
-
function isDenialEmoji(emoji) {
|
|
11776
|
-
return DENIAL_EMOJIS.includes(emoji);
|
|
11777
|
-
}
|
|
11778
|
-
function isAllowAllEmoji(emoji) {
|
|
11779
|
-
return ALLOW_ALL_EMOJIS.includes(emoji);
|
|
11780
|
-
}
|
|
11781
|
-
function isCancelEmoji(emoji) {
|
|
11782
|
-
return CANCEL_EMOJIS.includes(emoji);
|
|
11783
|
-
}
|
|
11784
|
-
function isEscapeEmoji(emoji) {
|
|
11785
|
-
return ESCAPE_EMOJIS.includes(emoji);
|
|
11786
|
-
}
|
|
11787
|
-
function isResumeEmoji(emoji) {
|
|
11788
|
-
return RESUME_EMOJIS.includes(emoji);
|
|
11789
|
-
}
|
|
11790
|
-
function isMinimizeToggleEmoji(emoji) {
|
|
11791
|
-
return MINIMIZE_TOGGLE_EMOJIS.includes(emoji);
|
|
11792
|
-
}
|
|
11793
|
-
function isBugReportEmoji(emoji) {
|
|
11794
|
-
return emoji === BUG_REPORT_EMOJI || emoji === "\uD83D\uDC1B";
|
|
11795
|
-
}
|
|
11796
|
-
function getNumberEmojiIndex(emoji) {
|
|
11797
|
-
const textIndex = NUMBER_EMOJIS.indexOf(emoji);
|
|
11798
|
-
if (textIndex >= 0)
|
|
11799
|
-
return textIndex;
|
|
11800
|
-
return UNICODE_NUMBER_EMOJIS[emoji] ?? -1;
|
|
11801
|
-
}
|
|
11802
|
-
var APPROVAL_EMOJIS, DENIAL_EMOJIS, ALLOW_ALL_EMOJIS, NUMBER_EMOJIS, CANCEL_EMOJIS, ESCAPE_EMOJIS, RESUME_EMOJIS, MINIMIZE_TOGGLE_EMOJIS, BUG_REPORT_EMOJI = "bug", UNICODE_NUMBER_EMOJIS;
|
|
11803
|
-
var init_emoji = __esm(() => {
|
|
11804
|
-
APPROVAL_EMOJIS = ["+1", "thumbsup"];
|
|
11805
|
-
DENIAL_EMOJIS = ["-1", "thumbsdown"];
|
|
11806
|
-
ALLOW_ALL_EMOJIS = ["white_check_mark", "heavy_check_mark"];
|
|
11807
|
-
NUMBER_EMOJIS = ["one", "two", "three", "four"];
|
|
11808
|
-
CANCEL_EMOJIS = ["x", "octagonal_sign", "stop_sign", "stop"];
|
|
11809
|
-
ESCAPE_EMOJIS = ["double_vertical_bar", "pause_button", "pause"];
|
|
11810
|
-
RESUME_EMOJIS = ["arrows_counterclockwise", "arrow_forward", "repeat"];
|
|
11811
|
-
MINIMIZE_TOGGLE_EMOJIS = ["arrow_down_small", "small_red_triangle_down"];
|
|
11812
|
-
UNICODE_NUMBER_EMOJIS = {
|
|
11813
|
-
"1️⃣": 0,
|
|
11814
|
-
"2️⃣": 1,
|
|
11815
|
-
"3️⃣": 2,
|
|
11816
|
-
"4️⃣": 3
|
|
11817
|
-
};
|
|
11818
|
-
});
|
|
11819
|
-
|
|
11820
11750
|
// src/utils/spawn.ts
|
|
11821
11751
|
import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "child_process";
|
|
11822
11752
|
function addWindowsShell(options2) {
|
|
@@ -12161,6 +12091,76 @@ var init_worktree = __esm(() => {
|
|
|
12161
12091
|
METADATA_STORE_PATH = path.join(homedir4(), ".claude-threads", "worktree-metadata.json");
|
|
12162
12092
|
});
|
|
12163
12093
|
|
|
12094
|
+
// src/utils/emoji.ts
|
|
12095
|
+
var exports_emoji = {};
|
|
12096
|
+
__export(exports_emoji, {
|
|
12097
|
+
isResumeEmoji: () => isResumeEmoji,
|
|
12098
|
+
isMinimizeToggleEmoji: () => isMinimizeToggleEmoji,
|
|
12099
|
+
isEscapeEmoji: () => isEscapeEmoji,
|
|
12100
|
+
isDenialEmoji: () => isDenialEmoji,
|
|
12101
|
+
isCancelEmoji: () => isCancelEmoji,
|
|
12102
|
+
isBugReportEmoji: () => isBugReportEmoji,
|
|
12103
|
+
isApprovalEmoji: () => isApprovalEmoji,
|
|
12104
|
+
isAllowAllEmoji: () => isAllowAllEmoji,
|
|
12105
|
+
getNumberEmojiIndex: () => getNumberEmojiIndex,
|
|
12106
|
+
RESUME_EMOJIS: () => RESUME_EMOJIS,
|
|
12107
|
+
NUMBER_EMOJIS: () => NUMBER_EMOJIS,
|
|
12108
|
+
MINIMIZE_TOGGLE_EMOJIS: () => MINIMIZE_TOGGLE_EMOJIS,
|
|
12109
|
+
ESCAPE_EMOJIS: () => ESCAPE_EMOJIS,
|
|
12110
|
+
DENIAL_EMOJIS: () => DENIAL_EMOJIS,
|
|
12111
|
+
CANCEL_EMOJIS: () => CANCEL_EMOJIS,
|
|
12112
|
+
BUG_REPORT_EMOJI: () => BUG_REPORT_EMOJI,
|
|
12113
|
+
APPROVAL_EMOJIS: () => APPROVAL_EMOJIS,
|
|
12114
|
+
ALLOW_ALL_EMOJIS: () => ALLOW_ALL_EMOJIS
|
|
12115
|
+
});
|
|
12116
|
+
function isApprovalEmoji(emoji) {
|
|
12117
|
+
return APPROVAL_EMOJIS.includes(emoji);
|
|
12118
|
+
}
|
|
12119
|
+
function isDenialEmoji(emoji) {
|
|
12120
|
+
return DENIAL_EMOJIS.includes(emoji);
|
|
12121
|
+
}
|
|
12122
|
+
function isAllowAllEmoji(emoji) {
|
|
12123
|
+
return ALLOW_ALL_EMOJIS.includes(emoji);
|
|
12124
|
+
}
|
|
12125
|
+
function isCancelEmoji(emoji) {
|
|
12126
|
+
return CANCEL_EMOJIS.includes(emoji);
|
|
12127
|
+
}
|
|
12128
|
+
function isEscapeEmoji(emoji) {
|
|
12129
|
+
return ESCAPE_EMOJIS.includes(emoji);
|
|
12130
|
+
}
|
|
12131
|
+
function isResumeEmoji(emoji) {
|
|
12132
|
+
return RESUME_EMOJIS.includes(emoji);
|
|
12133
|
+
}
|
|
12134
|
+
function isMinimizeToggleEmoji(emoji) {
|
|
12135
|
+
return MINIMIZE_TOGGLE_EMOJIS.includes(emoji);
|
|
12136
|
+
}
|
|
12137
|
+
function isBugReportEmoji(emoji) {
|
|
12138
|
+
return emoji === BUG_REPORT_EMOJI || emoji === "\uD83D\uDC1B";
|
|
12139
|
+
}
|
|
12140
|
+
function getNumberEmojiIndex(emoji) {
|
|
12141
|
+
const textIndex = NUMBER_EMOJIS.indexOf(emoji);
|
|
12142
|
+
if (textIndex >= 0)
|
|
12143
|
+
return textIndex;
|
|
12144
|
+
return UNICODE_NUMBER_EMOJIS[emoji] ?? -1;
|
|
12145
|
+
}
|
|
12146
|
+
var APPROVAL_EMOJIS, DENIAL_EMOJIS, ALLOW_ALL_EMOJIS, NUMBER_EMOJIS, CANCEL_EMOJIS, ESCAPE_EMOJIS, RESUME_EMOJIS, MINIMIZE_TOGGLE_EMOJIS, BUG_REPORT_EMOJI = "bug", UNICODE_NUMBER_EMOJIS;
|
|
12147
|
+
var init_emoji = __esm(() => {
|
|
12148
|
+
APPROVAL_EMOJIS = ["+1", "thumbsup"];
|
|
12149
|
+
DENIAL_EMOJIS = ["-1", "thumbsdown"];
|
|
12150
|
+
ALLOW_ALL_EMOJIS = ["white_check_mark", "heavy_check_mark"];
|
|
12151
|
+
NUMBER_EMOJIS = ["one", "two", "three", "four"];
|
|
12152
|
+
CANCEL_EMOJIS = ["x", "octagonal_sign", "stop_sign", "stop"];
|
|
12153
|
+
ESCAPE_EMOJIS = ["double_vertical_bar", "pause_button", "pause"];
|
|
12154
|
+
RESUME_EMOJIS = ["arrows_counterclockwise", "arrow_forward", "repeat"];
|
|
12155
|
+
MINIMIZE_TOGGLE_EMOJIS = ["arrow_down_small", "small_red_triangle_down"];
|
|
12156
|
+
UNICODE_NUMBER_EMOJIS = {
|
|
12157
|
+
"1️⃣": 0,
|
|
12158
|
+
"2️⃣": 1,
|
|
12159
|
+
"3️⃣": 2,
|
|
12160
|
+
"4️⃣": 3
|
|
12161
|
+
};
|
|
12162
|
+
});
|
|
12163
|
+
|
|
12164
12164
|
// node_modules/pend/index.js
|
|
12165
12165
|
var require_pend = __commonJS((exports, module) => {
|
|
12166
12166
|
module.exports = Pend;
|
|
@@ -19496,7 +19496,7 @@ var require_react_reconciler_development = __commonJS((exports, module) => {
|
|
|
19496
19496
|
return hook.checkDCE ? true : false;
|
|
19497
19497
|
}
|
|
19498
19498
|
function setIsStrictModeForDevtools(newIsStrictMode) {
|
|
19499
|
-
typeof
|
|
19499
|
+
typeof log32 === "function" && unstable_setDisableYieldValue2(newIsStrictMode);
|
|
19500
19500
|
if (injectedHook && typeof injectedHook.setStrictMode === "function")
|
|
19501
19501
|
try {
|
|
19502
19502
|
injectedHook.setStrictMode(rendererID, newIsStrictMode);
|
|
@@ -22381,7 +22381,7 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
|
|
|
22381
22381
|
if (queue === null)
|
|
22382
22382
|
throw Error("Should have a queue. You are likely calling Hooks conditionally, which is not allowed. (https://react.dev/link/invalid-hook-call)");
|
|
22383
22383
|
queue.lastRenderedReducer = reducer;
|
|
22384
|
-
var { dispatch, pending: lastRenderPhaseUpdate } = queue, newState = hook.memoizedState;
|
|
22384
|
+
var { dispatch: dispatch2, pending: lastRenderPhaseUpdate } = queue, newState = hook.memoizedState;
|
|
22385
22385
|
if (lastRenderPhaseUpdate !== null) {
|
|
22386
22386
|
queue.pending = null;
|
|
22387
22387
|
var update = lastRenderPhaseUpdate = lastRenderPhaseUpdate.next;
|
|
@@ -22393,7 +22393,7 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
|
|
|
22393
22393
|
hook.baseQueue === null && (hook.baseState = newState);
|
|
22394
22394
|
queue.lastRenderedState = newState;
|
|
22395
22395
|
}
|
|
22396
|
-
return [newState,
|
|
22396
|
+
return [newState, dispatch2];
|
|
22397
22397
|
}
|
|
22398
22398
|
function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) {
|
|
22399
22399
|
var fiber = currentlyRenderingFiber, hook = mountWorkInProgressHook();
|
|
@@ -22497,9 +22497,9 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
|
|
|
22497
22497
|
}
|
|
22498
22498
|
function mountState(initialState) {
|
|
22499
22499
|
initialState = mountStateImpl(initialState);
|
|
22500
|
-
var queue = initialState.queue,
|
|
22501
|
-
queue.dispatch =
|
|
22502
|
-
return [initialState.memoizedState,
|
|
22500
|
+
var queue = initialState.queue, dispatch2 = dispatchSetState.bind(null, currentlyRenderingFiber, queue);
|
|
22501
|
+
queue.dispatch = dispatch2;
|
|
22502
|
+
return [initialState.memoizedState, dispatch2];
|
|
22503
22503
|
}
|
|
22504
22504
|
function mountOptimistic(passthrough) {
|
|
22505
22505
|
var hook = mountWorkInProgressHook();
|
|
@@ -22678,9 +22678,9 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
|
|
|
22678
22678
|
else
|
|
22679
22679
|
state = currentStateHook;
|
|
22680
22680
|
currentStateHook = updateWorkInProgressHook();
|
|
22681
|
-
var actionQueue = currentStateHook.queue,
|
|
22681
|
+
var actionQueue = currentStateHook.queue, dispatch2 = actionQueue.dispatch;
|
|
22682
22682
|
action !== currentStateHook.memoizedState && (currentlyRenderingFiber.flags |= 2048, pushSimpleEffect(HasEffect | Passive, { destroy: undefined }, actionStateActionEffect.bind(null, actionQueue, action), null));
|
|
22683
|
-
return [state,
|
|
22683
|
+
return [state, dispatch2, stateHook];
|
|
22684
22684
|
}
|
|
22685
22685
|
function actionStateActionEffect(actionQueue, action) {
|
|
22686
22686
|
actionQueue.action = action;
|
|
@@ -22692,9 +22692,9 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
|
|
|
22692
22692
|
updateWorkInProgressHook();
|
|
22693
22693
|
stateHook = stateHook.memoizedState;
|
|
22694
22694
|
currentStateHook = updateWorkInProgressHook();
|
|
22695
|
-
var
|
|
22695
|
+
var dispatch2 = currentStateHook.queue.dispatch;
|
|
22696
22696
|
currentStateHook.memoizedState = action;
|
|
22697
|
-
return [stateHook,
|
|
22697
|
+
return [stateHook, dispatch2, false];
|
|
22698
22698
|
}
|
|
22699
22699
|
function pushSimpleEffect(tag, inst, create, deps) {
|
|
22700
22700
|
tag = { tag, create, deps, inst, next: null };
|
|
@@ -27580,7 +27580,7 @@ Check the render method of %s.`, getComponentNameFromFiber(current) || "Unknown"
|
|
|
27580
27580
|
var fiberStack = [];
|
|
27581
27581
|
var index$jscomp$0 = -1, emptyContextObject = {};
|
|
27582
27582
|
Object.freeze(emptyContextObject);
|
|
27583
|
-
var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, log$1 = Math.log, LN2 = Math.LN2, nextTransitionUpdateLane = 256, nextTransitionDeferredLane = 262144, nextRetryLane = 4194304, scheduleCallback$3 = Scheduler.unstable_scheduleCallback, cancelCallback$1 = Scheduler.unstable_cancelCallback, shouldYield = Scheduler.unstable_shouldYield, requestPaint = Scheduler.unstable_requestPaint, now$1 = Scheduler.unstable_now, ImmediatePriority = Scheduler.unstable_ImmediatePriority, UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, NormalPriority$1 = Scheduler.unstable_NormalPriority, IdlePriority = Scheduler.unstable_IdlePriority,
|
|
27583
|
+
var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, log$1 = Math.log, LN2 = Math.LN2, nextTransitionUpdateLane = 256, nextTransitionDeferredLane = 262144, nextRetryLane = 4194304, scheduleCallback$3 = Scheduler.unstable_scheduleCallback, cancelCallback$1 = Scheduler.unstable_cancelCallback, shouldYield = Scheduler.unstable_shouldYield, requestPaint = Scheduler.unstable_requestPaint, now$1 = Scheduler.unstable_now, ImmediatePriority = Scheduler.unstable_ImmediatePriority, UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, NormalPriority$1 = Scheduler.unstable_NormalPriority, IdlePriority = Scheduler.unstable_IdlePriority, log32 = Scheduler.log, unstable_setDisableYieldValue2 = Scheduler.unstable_setDisableYieldValue, rendererID = null, injectedHook = null, hasLoggedError = false, isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined", lastResetTime = 0;
|
|
27584
27584
|
if (typeof performance === "object" && typeof performance.now === "function") {
|
|
27585
27585
|
var localPerformance = performance;
|
|
27586
27586
|
var getCurrentTime = function() {
|
|
@@ -51565,6 +51565,23 @@ function truncateAtWord(str2, maxLength) {
|
|
|
51565
51565
|
function escapeRegExp(string) {
|
|
51566
51566
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
51567
51567
|
}
|
|
51568
|
+
function formatWebSocketError(err) {
|
|
51569
|
+
if (err instanceof Error)
|
|
51570
|
+
return err.message;
|
|
51571
|
+
if (err && typeof err === "object") {
|
|
51572
|
+
const e = err;
|
|
51573
|
+
if (typeof e.message === "string" && e.message)
|
|
51574
|
+
return e.message;
|
|
51575
|
+
if (e.error instanceof Error)
|
|
51576
|
+
return e.error.message;
|
|
51577
|
+
if (typeof e.error === "string" && e.error)
|
|
51578
|
+
return e.error;
|
|
51579
|
+
if (typeof e.type === "string" && e.type) {
|
|
51580
|
+
return typeof e.code === "string" || typeof e.code === "number" ? `${e.type} (code: ${e.code})` : e.type;
|
|
51581
|
+
}
|
|
51582
|
+
}
|
|
51583
|
+
return String(err);
|
|
51584
|
+
}
|
|
51568
51585
|
function getPlatformIcon(platformType) {
|
|
51569
51586
|
switch (platformType) {
|
|
51570
51587
|
case "slack":
|
|
@@ -52110,9 +52127,10 @@ class MattermostClient extends BasePlatformClient {
|
|
|
52110
52127
|
this.onConnectionClosed();
|
|
52111
52128
|
};
|
|
52112
52129
|
this.ws.onerror = (event) => {
|
|
52113
|
-
|
|
52114
|
-
|
|
52115
|
-
|
|
52130
|
+
const msg = formatWebSocketError(event);
|
|
52131
|
+
wsLogger.warn(`WebSocket error: ${msg}`);
|
|
52132
|
+
this.emit("error", new Error(`WebSocket error: ${msg}`));
|
|
52133
|
+
reject(new Error(`WebSocket error: ${msg}`));
|
|
52116
52134
|
};
|
|
52117
52135
|
});
|
|
52118
52136
|
}
|
|
@@ -52540,11 +52558,12 @@ class SlackClient extends BasePlatformClient {
|
|
|
52540
52558
|
};
|
|
52541
52559
|
this.ws.onerror = (event) => {
|
|
52542
52560
|
clearTimeout(connectionTimeout);
|
|
52543
|
-
|
|
52561
|
+
const msg = formatWebSocketError(event);
|
|
52562
|
+
wsLogger.warn(`Socket Mode: WebSocket error: ${msg}`);
|
|
52544
52563
|
if (!this.isIntentionalDisconnect && !this.isReconnecting) {
|
|
52545
|
-
this.emit("error", new Error(
|
|
52564
|
+
this.emit("error", new Error(`Socket Mode WebSocket error: ${msg}`));
|
|
52546
52565
|
}
|
|
52547
|
-
doReject(new Error(
|
|
52566
|
+
doReject(new Error(`Socket Mode WebSocket error: ${msg}`));
|
|
52548
52567
|
};
|
|
52549
52568
|
});
|
|
52550
52569
|
}
|
|
@@ -53160,7 +53179,7 @@ class MattermostPermissionApi {
|
|
|
53160
53179
|
}
|
|
53161
53180
|
};
|
|
53162
53181
|
ws.onerror = (event) => {
|
|
53163
|
-
mcpLogger.error(`WebSocket error: ${event}`);
|
|
53182
|
+
mcpLogger.error(`WebSocket error: ${formatWebSocketError(event)}`);
|
|
53164
53183
|
if (!resolved) {
|
|
53165
53184
|
resolved = true;
|
|
53166
53185
|
clearTimeout(timeout);
|
|
@@ -53356,7 +53375,7 @@ class SlackPermissionApi {
|
|
|
53356
53375
|
}
|
|
53357
53376
|
};
|
|
53358
53377
|
ws.onerror = (event) => {
|
|
53359
|
-
mcpLogger.error(`Socket Mode WebSocket error: ${event}`);
|
|
53378
|
+
mcpLogger.error(`Socket Mode WebSocket error: ${formatWebSocketError(event)}`);
|
|
53360
53379
|
if (!resolved) {
|
|
53361
53380
|
resolved = true;
|
|
53362
53381
|
clearTimeout(timeout);
|
|
@@ -53731,9 +53750,6 @@ class AccountPool {
|
|
|
53731
53750
|
}
|
|
53732
53751
|
}
|
|
53733
53752
|
|
|
53734
|
-
// src/session/manager.ts
|
|
53735
|
-
init_emoji();
|
|
53736
|
-
|
|
53737
53753
|
// src/cleanup/scheduler.ts
|
|
53738
53754
|
init_logger();
|
|
53739
53755
|
import { existsSync as existsSync7 } from "fs";
|
|
@@ -54194,6 +54210,50 @@ class CleanupScheduler {
|
|
|
54194
54210
|
// src/operations/monitor/handler.ts
|
|
54195
54211
|
init_logger();
|
|
54196
54212
|
|
|
54213
|
+
// src/session/lifecycle-fsm.ts
|
|
54214
|
+
init_logger();
|
|
54215
|
+
var log9 = createLogger("fsm");
|
|
54216
|
+
var ALLOWED_TRANSITIONS = {
|
|
54217
|
+
starting: new Set(["active", "paused", "interrupted", "cancelling", "restarting"]),
|
|
54218
|
+
active: new Set([
|
|
54219
|
+
"active",
|
|
54220
|
+
"processing",
|
|
54221
|
+
"paused",
|
|
54222
|
+
"interrupted",
|
|
54223
|
+
"restarting",
|
|
54224
|
+
"cancelling",
|
|
54225
|
+
"ending"
|
|
54226
|
+
]),
|
|
54227
|
+
processing: new Set([
|
|
54228
|
+
"active",
|
|
54229
|
+
"paused",
|
|
54230
|
+
"interrupted",
|
|
54231
|
+
"restarting",
|
|
54232
|
+
"cancelling"
|
|
54233
|
+
]),
|
|
54234
|
+
paused: new Set(["active", "cancelling", "restarting"]),
|
|
54235
|
+
interrupted: new Set(["active", "cancelling", "restarting", "paused"]),
|
|
54236
|
+
restarting: new Set(["active", "paused", "cancelling"]),
|
|
54237
|
+
cancelling: new Set(["ending"]),
|
|
54238
|
+
ending: new Set
|
|
54239
|
+
};
|
|
54240
|
+
function checkTransition(from, to, sessionId) {
|
|
54241
|
+
const allowed = ALLOWED_TRANSITIONS[from];
|
|
54242
|
+
if (allowed.has(to))
|
|
54243
|
+
return;
|
|
54244
|
+
const msg = `illegal lifecycle transition ${from} -> ${to}`;
|
|
54245
|
+
const payload = {
|
|
54246
|
+
event: "fsm.illegal_transition",
|
|
54247
|
+
from,
|
|
54248
|
+
to,
|
|
54249
|
+
sessionId
|
|
54250
|
+
};
|
|
54251
|
+
if (process.env.CLAUDE_THREADS_FSM_STRICT === "1") {
|
|
54252
|
+
throw new Error(`${msg} (sessionId=${sessionId})`);
|
|
54253
|
+
}
|
|
54254
|
+
log9.warn(msg, payload);
|
|
54255
|
+
}
|
|
54256
|
+
|
|
54197
54257
|
// src/session/timer-manager.ts
|
|
54198
54258
|
function createSessionTimers() {
|
|
54199
54259
|
return {
|
|
@@ -54239,6 +54299,7 @@ function isSessionCancelled(session) {
|
|
|
54239
54299
|
return session.lifecycle.state === "cancelling";
|
|
54240
54300
|
}
|
|
54241
54301
|
function transitionTo(session, newState) {
|
|
54302
|
+
checkTransition(session.lifecycle.state, newState, session.sessionId);
|
|
54242
54303
|
session.lifecycle.state = newState;
|
|
54243
54304
|
}
|
|
54244
54305
|
function markClaudeResponded(session) {
|
|
@@ -54326,7 +54387,7 @@ function extractResetAt(text, now) {
|
|
|
54326
54387
|
}
|
|
54327
54388
|
|
|
54328
54389
|
// src/claude/cli.ts
|
|
54329
|
-
var
|
|
54390
|
+
var log10 = createLogger("claude");
|
|
54330
54391
|
function cleanupBrowserBridgeSockets() {
|
|
54331
54392
|
try {
|
|
54332
54393
|
const tempDir = tmpdir();
|
|
@@ -54338,13 +54399,13 @@ function cleanupBrowserBridgeSockets() {
|
|
|
54338
54399
|
const stats = statSync2(filePath);
|
|
54339
54400
|
if (stats.isSocket()) {
|
|
54340
54401
|
unlinkSync2(filePath);
|
|
54341
|
-
|
|
54402
|
+
log10.debug(`Removed stale browser bridge socket: ${file}`);
|
|
54342
54403
|
}
|
|
54343
54404
|
} catch {}
|
|
54344
54405
|
}
|
|
54345
54406
|
}
|
|
54346
54407
|
} catch (err) {
|
|
54347
|
-
|
|
54408
|
+
log10.debug(`Browser bridge cleanup failed: ${err}`);
|
|
54348
54409
|
}
|
|
54349
54410
|
}
|
|
54350
54411
|
function buildClaudeChildEnv(parentEnv, account) {
|
|
@@ -54375,7 +54436,7 @@ function isErrorResultEvent(event) {
|
|
|
54375
54436
|
return false;
|
|
54376
54437
|
}
|
|
54377
54438
|
function materializeMcpConfig(config, sessionId, opts = {}) {
|
|
54378
|
-
if (opts.inline
|
|
54439
|
+
if (opts.inline) {
|
|
54379
54440
|
return { mode: "inline", value: JSON.stringify(config) };
|
|
54380
54441
|
}
|
|
54381
54442
|
const dir = opts.tmpDirOverride ?? tmpdir();
|
|
@@ -55580,7 +55641,7 @@ import { existsSync as existsSync11 } from "fs";
|
|
|
55580
55641
|
// src/utils/keep-alive.ts
|
|
55581
55642
|
init_logger();
|
|
55582
55643
|
import { spawn as spawn2 } from "child_process";
|
|
55583
|
-
var
|
|
55644
|
+
var log11 = createLogger("keepalive");
|
|
55584
55645
|
|
|
55585
55646
|
class KeepAliveManager {
|
|
55586
55647
|
activeSessionCount = 0;
|
|
@@ -55595,7 +55656,7 @@ class KeepAliveManager {
|
|
|
55595
55656
|
if (!enabled && this.keepAliveProcess) {
|
|
55596
55657
|
this.stopKeepAlive();
|
|
55597
55658
|
}
|
|
55598
|
-
|
|
55659
|
+
log11.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
|
|
55599
55660
|
}
|
|
55600
55661
|
isEnabled() {
|
|
55601
55662
|
return this.enabled;
|
|
@@ -55605,7 +55666,7 @@ class KeepAliveManager {
|
|
|
55605
55666
|
}
|
|
55606
55667
|
sessionStarted() {
|
|
55607
55668
|
this.activeSessionCount++;
|
|
55608
|
-
|
|
55669
|
+
log11.debug(`Session started (${this.activeSessionCount} active)`);
|
|
55609
55670
|
if (this.activeSessionCount === 1) {
|
|
55610
55671
|
this.startKeepAlive();
|
|
55611
55672
|
}
|
|
@@ -55614,7 +55675,7 @@ class KeepAliveManager {
|
|
|
55614
55675
|
if (this.activeSessionCount > 0) {
|
|
55615
55676
|
this.activeSessionCount--;
|
|
55616
55677
|
}
|
|
55617
|
-
|
|
55678
|
+
log11.debug(`Session ended (${this.activeSessionCount} active)`);
|
|
55618
55679
|
if (this.activeSessionCount === 0) {
|
|
55619
55680
|
this.stopKeepAlive();
|
|
55620
55681
|
}
|
|
@@ -55628,11 +55689,11 @@ class KeepAliveManager {
|
|
|
55628
55689
|
}
|
|
55629
55690
|
startKeepAlive() {
|
|
55630
55691
|
if (!this.enabled) {
|
|
55631
|
-
|
|
55692
|
+
log11.debug("Keep-alive disabled, skipping");
|
|
55632
55693
|
return;
|
|
55633
55694
|
}
|
|
55634
55695
|
if (this.keepAliveProcess) {
|
|
55635
|
-
|
|
55696
|
+
log11.debug("Keep-alive already running");
|
|
55636
55697
|
return;
|
|
55637
55698
|
}
|
|
55638
55699
|
switch (this.platform) {
|
|
@@ -55646,12 +55707,12 @@ class KeepAliveManager {
|
|
|
55646
55707
|
this.startWindowsKeepAlive();
|
|
55647
55708
|
break;
|
|
55648
55709
|
default:
|
|
55649
|
-
|
|
55710
|
+
log11.warn(`Keep-alive not supported on ${this.platform}`);
|
|
55650
55711
|
}
|
|
55651
55712
|
}
|
|
55652
55713
|
stopKeepAlive() {
|
|
55653
55714
|
if (this.keepAliveProcess) {
|
|
55654
|
-
|
|
55715
|
+
log11.debug("Stopping keep-alive");
|
|
55655
55716
|
this.keepAliveProcess.kill();
|
|
55656
55717
|
this.keepAliveProcess = null;
|
|
55657
55718
|
}
|
|
@@ -55663,18 +55724,18 @@ class KeepAliveManager {
|
|
|
55663
55724
|
detached: false
|
|
55664
55725
|
});
|
|
55665
55726
|
this.keepAliveProcess.on("error", (err) => {
|
|
55666
|
-
|
|
55727
|
+
log11.error(`Failed to start caffeinate: ${err.message}`);
|
|
55667
55728
|
this.keepAliveProcess = null;
|
|
55668
55729
|
});
|
|
55669
55730
|
this.keepAliveProcess.on("exit", (code) => {
|
|
55670
55731
|
if (code !== null && code !== 0 && this.activeSessionCount > 0) {
|
|
55671
|
-
|
|
55732
|
+
log11.debug(`caffeinate exited with code ${code}`);
|
|
55672
55733
|
}
|
|
55673
55734
|
this.keepAliveProcess = null;
|
|
55674
55735
|
});
|
|
55675
|
-
|
|
55736
|
+
log11.info("Sleep prevention active (caffeinate)");
|
|
55676
55737
|
} catch (err) {
|
|
55677
|
-
|
|
55738
|
+
log11.error(`Failed to start caffeinate: ${err}`);
|
|
55678
55739
|
}
|
|
55679
55740
|
}
|
|
55680
55741
|
startLinuxKeepAlive() {
|
|
@@ -55690,19 +55751,19 @@ class KeepAliveManager {
|
|
|
55690
55751
|
detached: false
|
|
55691
55752
|
});
|
|
55692
55753
|
this.keepAliveProcess.on("error", (err) => {
|
|
55693
|
-
|
|
55754
|
+
log11.debug(`systemd-inhibit not available: ${err.message}`);
|
|
55694
55755
|
this.keepAliveProcess = null;
|
|
55695
55756
|
this.startLinuxKeepAliveFallback();
|
|
55696
55757
|
});
|
|
55697
55758
|
this.keepAliveProcess.on("exit", (code) => {
|
|
55698
55759
|
if (code !== null && code !== 0 && this.activeSessionCount > 0) {
|
|
55699
|
-
|
|
55760
|
+
log11.debug(`systemd-inhibit exited with code ${code}`);
|
|
55700
55761
|
}
|
|
55701
55762
|
this.keepAliveProcess = null;
|
|
55702
55763
|
});
|
|
55703
|
-
|
|
55764
|
+
log11.info("Sleep prevention active (systemd-inhibit)");
|
|
55704
55765
|
} catch (err) {
|
|
55705
|
-
|
|
55766
|
+
log11.debug(`Failed to start systemd-inhibit: ${err}`);
|
|
55706
55767
|
this.startLinuxKeepAliveFallback();
|
|
55707
55768
|
}
|
|
55708
55769
|
}
|
|
@@ -55716,15 +55777,15 @@ class KeepAliveManager {
|
|
|
55716
55777
|
detached: false
|
|
55717
55778
|
});
|
|
55718
55779
|
this.keepAliveProcess.on("error", (err) => {
|
|
55719
|
-
|
|
55780
|
+
log11.warn(`Linux keep-alive fallback not available: ${err.message}`);
|
|
55720
55781
|
this.keepAliveProcess = null;
|
|
55721
55782
|
});
|
|
55722
55783
|
this.keepAliveProcess.on("exit", () => {
|
|
55723
55784
|
this.keepAliveProcess = null;
|
|
55724
55785
|
});
|
|
55725
|
-
|
|
55786
|
+
log11.info("Sleep prevention active (xdg-screensaver)");
|
|
55726
55787
|
} catch (err) {
|
|
55727
|
-
|
|
55788
|
+
log11.warn(`Linux keep-alive not available: ${err}`);
|
|
55728
55789
|
}
|
|
55729
55790
|
}
|
|
55730
55791
|
startWindowsKeepAlive() {
|
|
@@ -55749,18 +55810,18 @@ class KeepAliveManager {
|
|
|
55749
55810
|
windowsHide: true
|
|
55750
55811
|
});
|
|
55751
55812
|
this.keepAliveProcess.on("error", (err) => {
|
|
55752
|
-
|
|
55813
|
+
log11.warn(`Windows keep-alive not available: ${err.message}`);
|
|
55753
55814
|
this.keepAliveProcess = null;
|
|
55754
55815
|
});
|
|
55755
55816
|
this.keepAliveProcess.on("exit", (code) => {
|
|
55756
55817
|
if (code !== null && code !== 0 && this.activeSessionCount > 0) {
|
|
55757
|
-
|
|
55818
|
+
log11.debug(`PowerShell keep-alive exited with code ${code}`);
|
|
55758
55819
|
}
|
|
55759
55820
|
this.keepAliveProcess = null;
|
|
55760
55821
|
});
|
|
55761
|
-
|
|
55822
|
+
log11.info("Sleep prevention active (SetThreadExecutionState)");
|
|
55762
55823
|
} catch (err) {
|
|
55763
|
-
|
|
55824
|
+
log11.warn(`Windows keep-alive not available: ${err}`);
|
|
55764
55825
|
}
|
|
55765
55826
|
}
|
|
55766
55827
|
}
|
|
@@ -55768,7 +55829,7 @@ var keepAlive = new KeepAliveManager;
|
|
|
55768
55829
|
|
|
55769
55830
|
// src/utils/error-handler/index.ts
|
|
55770
55831
|
init_logger();
|
|
55771
|
-
var
|
|
55832
|
+
var log12 = createLogger("error");
|
|
55772
55833
|
|
|
55773
55834
|
class SessionError extends Error {
|
|
55774
55835
|
sessionId;
|
|
@@ -55794,19 +55855,19 @@ async function handleError(error, context, severity = "recoverable") {
|
|
|
55794
55855
|
const sessionPart = sessionId ? ` (${formatShortId(sessionId)})` : "";
|
|
55795
55856
|
const logMessage = `${context.action}${sessionPart}: ${message}`;
|
|
55796
55857
|
if (severity === "recoverable") {
|
|
55797
|
-
|
|
55858
|
+
log12.warn(logMessage);
|
|
55798
55859
|
} else {
|
|
55799
|
-
|
|
55860
|
+
log12.error(logMessage, error instanceof Error ? error : undefined);
|
|
55800
55861
|
}
|
|
55801
55862
|
if (context.details) {
|
|
55802
|
-
|
|
55863
|
+
log12.debugJson("Error details", context.details);
|
|
55803
55864
|
}
|
|
55804
55865
|
if (context.notifyUser && context.session) {
|
|
55805
55866
|
try {
|
|
55806
55867
|
const fmt = context.session.platform.getFormatter();
|
|
55807
55868
|
await context.session.platform.createPost(`⚠️ ${fmt.formatBold("Error")}: ${context.action} failed - ${message}`, context.session.threadId);
|
|
55808
55869
|
} catch (notifyError) {
|
|
55809
|
-
|
|
55870
|
+
log12.warn(`Could not notify user: ${notifyError}`);
|
|
55810
55871
|
}
|
|
55811
55872
|
}
|
|
55812
55873
|
if (severity === "session-fatal" || severity === "system-fatal") {
|
|
@@ -55833,7 +55894,7 @@ async function logAndNotify(error, context) {
|
|
|
55833
55894
|
}
|
|
55834
55895
|
function logSilentError(context, error) {
|
|
55835
55896
|
const message = error instanceof Error ? error.message : String(error);
|
|
55836
|
-
|
|
55897
|
+
log12.debug(`[${context}] Silently caught: ${message}`);
|
|
55837
55898
|
}
|
|
55838
55899
|
|
|
55839
55900
|
// src/session/lifecycle.ts
|
|
@@ -55853,8 +55914,8 @@ function createSessionLog(baseLog) {
|
|
|
55853
55914
|
init_logger();
|
|
55854
55915
|
init_emoji();
|
|
55855
55916
|
init_worktree();
|
|
55856
|
-
var
|
|
55857
|
-
var sessionLog = createSessionLog(
|
|
55917
|
+
var log13 = createLogger("helpers");
|
|
55918
|
+
var sessionLog = createSessionLog(log13);
|
|
55858
55919
|
var POST_TYPES = {
|
|
55859
55920
|
info: "",
|
|
55860
55921
|
success: "✅",
|
|
@@ -55938,7 +55999,7 @@ function updateLastMessage(session, post2) {
|
|
|
55938
55999
|
// src/claude/quick-query.ts
|
|
55939
56000
|
init_spawn();
|
|
55940
56001
|
init_logger();
|
|
55941
|
-
var
|
|
56002
|
+
var log14 = createLogger("query");
|
|
55942
56003
|
async function quickQuery(options2) {
|
|
55943
56004
|
const {
|
|
55944
56005
|
prompt,
|
|
@@ -55954,7 +56015,7 @@ async function quickQuery(options2) {
|
|
|
55954
56015
|
args.push("--system-prompt", systemPrompt);
|
|
55955
56016
|
}
|
|
55956
56017
|
args.push(prompt);
|
|
55957
|
-
|
|
56018
|
+
log14.debug(`Quick query: model=${model}, timeout=${timeout}ms, prompt="${prompt.substring(0, 50)}..."`);
|
|
55958
56019
|
return new Promise((resolve5) => {
|
|
55959
56020
|
let stdout = "";
|
|
55960
56021
|
let stderr = "";
|
|
@@ -55968,7 +56029,7 @@ async function quickQuery(options2) {
|
|
|
55968
56029
|
if (!resolved) {
|
|
55969
56030
|
resolved = true;
|
|
55970
56031
|
proc.kill("SIGTERM");
|
|
55971
|
-
|
|
56032
|
+
log14.debug(`Quick query timed out after ${timeout}ms`);
|
|
55972
56033
|
resolve5({
|
|
55973
56034
|
success: false,
|
|
55974
56035
|
error: "timeout",
|
|
@@ -55986,7 +56047,7 @@ async function quickQuery(options2) {
|
|
|
55986
56047
|
if (!resolved) {
|
|
55987
56048
|
resolved = true;
|
|
55988
56049
|
clearTimeout(timeoutId);
|
|
55989
|
-
|
|
56050
|
+
log14.debug(`Quick query error: ${err.message}`);
|
|
55990
56051
|
resolve5({
|
|
55991
56052
|
success: false,
|
|
55992
56053
|
error: err.message,
|
|
@@ -56000,14 +56061,14 @@ async function quickQuery(options2) {
|
|
|
56000
56061
|
clearTimeout(timeoutId);
|
|
56001
56062
|
const durationMs = Date.now() - startTime;
|
|
56002
56063
|
if (code === 0 && stdout.trim()) {
|
|
56003
|
-
|
|
56064
|
+
log14.debug(`Quick query success: ${durationMs}ms, ${stdout.length} chars`);
|
|
56004
56065
|
resolve5({
|
|
56005
56066
|
success: true,
|
|
56006
56067
|
response: stdout.trim(),
|
|
56007
56068
|
durationMs
|
|
56008
56069
|
});
|
|
56009
56070
|
} else {
|
|
56010
|
-
|
|
56071
|
+
log14.debug(`Quick query failed: code=${code}, stderr=${stderr.substring(0, 100)}`);
|
|
56011
56072
|
resolve5({
|
|
56012
56073
|
success: false,
|
|
56013
56074
|
error: stderr || `exit code ${code}`,
|
|
@@ -56022,7 +56083,7 @@ async function quickQuery(options2) {
|
|
|
56022
56083
|
|
|
56023
56084
|
// src/operations/suggestions/title.ts
|
|
56024
56085
|
init_logger();
|
|
56025
|
-
var
|
|
56086
|
+
var log15 = createLogger("title");
|
|
56026
56087
|
var SUGGESTION_TIMEOUT = 15000;
|
|
56027
56088
|
var MIN_TITLE_LENGTH = 3;
|
|
56028
56089
|
var MAX_TITLE_LENGTH = 50;
|
|
@@ -56086,32 +56147,32 @@ function parseMetadata(response) {
|
|
|
56086
56147
|
const titleMatch = response.match(/TITLE:\s*(.+)/i);
|
|
56087
56148
|
const descMatch = response.match(/DESC:\s*(.+)/i);
|
|
56088
56149
|
if (!titleMatch || !descMatch) {
|
|
56089
|
-
|
|
56150
|
+
log15.debug("Failed to parse title/description from response");
|
|
56090
56151
|
return null;
|
|
56091
56152
|
}
|
|
56092
56153
|
let title = titleMatch[1].trim();
|
|
56093
56154
|
let description = descMatch[1].trim();
|
|
56094
56155
|
if (title.length < MIN_TITLE_LENGTH) {
|
|
56095
|
-
|
|
56156
|
+
log15.debug(`Title too short: ${title.length} chars`);
|
|
56096
56157
|
return null;
|
|
56097
56158
|
}
|
|
56098
56159
|
if (title.length > MAX_TITLE_LENGTH) {
|
|
56099
|
-
|
|
56160
|
+
log15.debug(`Title too long (${title.length} chars), truncating`);
|
|
56100
56161
|
title = truncateAtWord(title, MAX_TITLE_LENGTH);
|
|
56101
56162
|
}
|
|
56102
56163
|
if (description.length < MIN_DESC_LENGTH) {
|
|
56103
|
-
|
|
56164
|
+
log15.debug(`Description too short: ${description.length} chars`);
|
|
56104
56165
|
return null;
|
|
56105
56166
|
}
|
|
56106
56167
|
if (description.length > MAX_DESC_LENGTH) {
|
|
56107
|
-
|
|
56168
|
+
log15.debug(`Description too long (${description.length} chars), truncating`);
|
|
56108
56169
|
description = truncateAtWord(description, MAX_DESC_LENGTH);
|
|
56109
56170
|
}
|
|
56110
56171
|
return { title, description };
|
|
56111
56172
|
}
|
|
56112
56173
|
async function suggestSessionMetadata(context) {
|
|
56113
56174
|
const logContext = typeof context === "string" ? context.substring(0, 50) : context.originalTask.substring(0, 50);
|
|
56114
|
-
|
|
56175
|
+
log15.debug(`Suggesting title for: "${logContext}..."`);
|
|
56115
56176
|
try {
|
|
56116
56177
|
const result = await quickQuery({
|
|
56117
56178
|
prompt: buildTitlePrompt(context),
|
|
@@ -56119,23 +56180,23 @@ async function suggestSessionMetadata(context) {
|
|
|
56119
56180
|
timeout: SUGGESTION_TIMEOUT
|
|
56120
56181
|
});
|
|
56121
56182
|
if (!result.success || !result.response) {
|
|
56122
|
-
|
|
56183
|
+
log15.debug(`Title suggestion failed: ${result.error || "no response"}`);
|
|
56123
56184
|
return null;
|
|
56124
56185
|
}
|
|
56125
56186
|
const metadata = parseMetadata(result.response);
|
|
56126
56187
|
if (metadata) {
|
|
56127
|
-
|
|
56188
|
+
log15.debug(`Got title: "${metadata.title}" (${result.durationMs}ms)`);
|
|
56128
56189
|
}
|
|
56129
56190
|
return metadata;
|
|
56130
56191
|
} catch (err) {
|
|
56131
|
-
|
|
56192
|
+
log15.debug(`Title suggestion error: ${err}`);
|
|
56132
56193
|
return null;
|
|
56133
56194
|
}
|
|
56134
56195
|
}
|
|
56135
56196
|
|
|
56136
56197
|
// src/operations/suggestions/tag.ts
|
|
56137
56198
|
init_logger();
|
|
56138
|
-
var
|
|
56199
|
+
var log16 = createLogger("tags");
|
|
56139
56200
|
var SUGGESTION_TIMEOUT2 = 15000;
|
|
56140
56201
|
var MAX_TAGS = 3;
|
|
56141
56202
|
var VALID_TAGS = [
|
|
@@ -56167,7 +56228,7 @@ function parseTags(response) {
|
|
|
56167
56228
|
return [...new Set(tags)].slice(0, MAX_TAGS);
|
|
56168
56229
|
}
|
|
56169
56230
|
async function suggestSessionTags(userMessage) {
|
|
56170
|
-
|
|
56231
|
+
log16.debug(`Suggesting tags for: "${userMessage.substring(0, 50)}..."`);
|
|
56171
56232
|
try {
|
|
56172
56233
|
const result = await quickQuery({
|
|
56173
56234
|
prompt: buildTagPrompt(userMessage),
|
|
@@ -56175,14 +56236,14 @@ async function suggestSessionTags(userMessage) {
|
|
|
56175
56236
|
timeout: SUGGESTION_TIMEOUT2
|
|
56176
56237
|
});
|
|
56177
56238
|
if (!result.success || !result.response) {
|
|
56178
|
-
|
|
56239
|
+
log16.debug(`Tag suggestion failed: ${result.error || "no response"}`);
|
|
56179
56240
|
return [];
|
|
56180
56241
|
}
|
|
56181
56242
|
const tags = parseTags(result.response);
|
|
56182
|
-
|
|
56243
|
+
log16.debug(`Got tags: ${tags.join(", ")} (${result.durationMs}ms)`);
|
|
56183
56244
|
return tags;
|
|
56184
56245
|
} catch (err) {
|
|
56185
|
-
|
|
56246
|
+
log16.debug(`Tag suggestion error: ${err}`);
|
|
56186
56247
|
return [];
|
|
56187
56248
|
}
|
|
56188
56249
|
}
|
|
@@ -59702,7 +59763,7 @@ class BugReportExecutor extends BaseExecutor {
|
|
|
59702
59763
|
// src/operations/executors/worktree-prompt.ts
|
|
59703
59764
|
init_emoji();
|
|
59704
59765
|
init_logger();
|
|
59705
|
-
var
|
|
59766
|
+
var log17 = createLogger("wt-prompt");
|
|
59706
59767
|
// src/operations/message-manager.ts
|
|
59707
59768
|
init_logger();
|
|
59708
59769
|
|
|
@@ -59739,7 +59800,7 @@ var import_yauzl = __toESM(require_yauzl(), 1);
|
|
|
59739
59800
|
import { createGunzip } from "zlib";
|
|
59740
59801
|
import { pipeline } from "stream/promises";
|
|
59741
59802
|
import { Readable, Writable } from "stream";
|
|
59742
|
-
var
|
|
59803
|
+
var log18 = createLogger("streaming");
|
|
59743
59804
|
var MAX_PDF_SIZE = 32 * 1024 * 1024;
|
|
59744
59805
|
var MAX_TEXT_FILE_SIZE = 1 * 1024 * 1024;
|
|
59745
59806
|
var MAX_DECOMPRESSED_SIZE = 10 * 1024 * 1024;
|
|
@@ -59865,7 +59926,7 @@ async function processImageFile(file, platform, debug = false) {
|
|
|
59865
59926
|
const buffer = await platform.downloadFile(file.id);
|
|
59866
59927
|
const base64 = buffer.toString("base64");
|
|
59867
59928
|
if (debug) {
|
|
59868
|
-
|
|
59929
|
+
log18.debug(`Attached image: ${file.name} (${file.mimeType}, ${Math.round(buffer.length / 1024)}KB)`);
|
|
59869
59930
|
}
|
|
59870
59931
|
return {
|
|
59871
59932
|
block: {
|
|
@@ -59878,7 +59939,7 @@ async function processImageFile(file, platform, debug = false) {
|
|
|
59878
59939
|
}
|
|
59879
59940
|
};
|
|
59880
59941
|
} catch (err) {
|
|
59881
|
-
|
|
59942
|
+
log18.error(`Failed to download image ${file.name}: ${err}`);
|
|
59882
59943
|
return {
|
|
59883
59944
|
skipped: {
|
|
59884
59945
|
name: file.name,
|
|
@@ -59909,7 +59970,7 @@ async function processPdfFile(file, platform, debug = false) {
|
|
|
59909
59970
|
}
|
|
59910
59971
|
const base64 = buffer.toString("base64");
|
|
59911
59972
|
if (debug) {
|
|
59912
|
-
|
|
59973
|
+
log18.debug(`Attached PDF: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
|
|
59913
59974
|
}
|
|
59914
59975
|
return {
|
|
59915
59976
|
block: {
|
|
@@ -59923,7 +59984,7 @@ async function processPdfFile(file, platform, debug = false) {
|
|
|
59923
59984
|
}
|
|
59924
59985
|
};
|
|
59925
59986
|
} catch (err) {
|
|
59926
|
-
|
|
59987
|
+
log18.error(`Failed to process PDF ${file.name}: ${err}`);
|
|
59927
59988
|
return {
|
|
59928
59989
|
skipped: {
|
|
59929
59990
|
name: file.name,
|
|
@@ -59954,7 +60015,7 @@ async function processTextFile(file, platform, debug = false) {
|
|
|
59954
60015
|
}
|
|
59955
60016
|
const content = buffer.toString("utf-8");
|
|
59956
60017
|
if (debug) {
|
|
59957
|
-
|
|
60018
|
+
log18.debug(`Attached text file: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
|
|
59958
60019
|
}
|
|
59959
60020
|
const wrappedContent = formatTextFileContent(file.name, content);
|
|
59960
60021
|
return {
|
|
@@ -59964,7 +60025,7 @@ async function processTextFile(file, platform, debug = false) {
|
|
|
59964
60025
|
}
|
|
59965
60026
|
};
|
|
59966
60027
|
} catch (err) {
|
|
59967
|
-
|
|
60028
|
+
log18.error(`Failed to process text file ${file.name}: ${err}`);
|
|
59968
60029
|
return {
|
|
59969
60030
|
skipped: {
|
|
59970
60031
|
name: file.name,
|
|
@@ -60022,7 +60083,7 @@ async function processGzipFile(file, platform, debug = false) {
|
|
|
60022
60083
|
compressedBuffer = await platform.downloadFile(file.id);
|
|
60023
60084
|
} catch (err) {
|
|
60024
60085
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
60025
|
-
|
|
60086
|
+
log18.error(`Failed to download gzip file ${file.name}: ${errorMessage}`);
|
|
60026
60087
|
return {
|
|
60027
60088
|
skipped: {
|
|
60028
60089
|
name: file.name,
|
|
@@ -60032,7 +60093,7 @@ async function processGzipFile(file, platform, debug = false) {
|
|
|
60032
60093
|
};
|
|
60033
60094
|
}
|
|
60034
60095
|
if (file.size && compressedBuffer.length !== file.size) {
|
|
60035
|
-
|
|
60096
|
+
log18.warn(`Downloaded size mismatch for ${file.name}: expected ${file.size}, got ${compressedBuffer.length}`);
|
|
60036
60097
|
}
|
|
60037
60098
|
let decompressedBuffer;
|
|
60038
60099
|
try {
|
|
@@ -60068,7 +60129,7 @@ async function processGzipFile(file, platform, debug = false) {
|
|
|
60068
60129
|
const innerFilename = file.name.toLowerCase().endsWith(".gz") ? file.name.slice(0, -3) : file.name;
|
|
60069
60130
|
const contentType = detectDecompressedContentType(decompressedBuffer, innerFilename);
|
|
60070
60131
|
if (debug) {
|
|
60071
|
-
|
|
60132
|
+
log18.debug(`Decompressed ${file.name}: ${Math.round(decompressedBuffer.length / 1024)}KB, detected type: ${contentType}`);
|
|
60072
60133
|
}
|
|
60073
60134
|
if (contentType === "pdf") {
|
|
60074
60135
|
const base64 = decompressedBuffer.toString("base64");
|
|
@@ -60103,7 +60164,7 @@ async function processGzipFile(file, platform, debug = false) {
|
|
|
60103
60164
|
}
|
|
60104
60165
|
} catch (err) {
|
|
60105
60166
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
60106
|
-
|
|
60167
|
+
log18.error(`Failed to process gzip file ${file.name}: ${errorMessage}`);
|
|
60107
60168
|
return {
|
|
60108
60169
|
skipped: {
|
|
60109
60170
|
name: file.name,
|
|
@@ -60155,7 +60216,7 @@ async function processZipFile(file, platform, debug = false) {
|
|
|
60155
60216
|
}
|
|
60156
60217
|
const zipBuffer = await platform.downloadFile(file.id);
|
|
60157
60218
|
if (debug) {
|
|
60158
|
-
|
|
60219
|
+
log18.debug(`Processing zip file ${file.name}: ${Math.round(zipBuffer.length / 1024)}KB`);
|
|
60159
60220
|
}
|
|
60160
60221
|
const zipfile = await new Promise((resolve5, reject) => {
|
|
60161
60222
|
import_yauzl.default.fromBuffer(zipBuffer, { lazyEntries: true }, (err, zf) => {
|
|
@@ -60229,7 +60290,7 @@ async function processZipFile(file, platform, debug = false) {
|
|
|
60229
60290
|
const buffer = await extractZipEntry(zipfile2, entry);
|
|
60230
60291
|
const contentType = detectDecompressedContentType(buffer, entry.fileName);
|
|
60231
60292
|
if (debug) {
|
|
60232
|
-
|
|
60293
|
+
log18.debug(`Extracted ${entry.fileName}: ${Math.round(buffer.length / 1024)}KB, type: ${contentType}`);
|
|
60233
60294
|
}
|
|
60234
60295
|
if (contentType === "pdf") {
|
|
60235
60296
|
const base64 = buffer.toString("base64");
|
|
@@ -60272,11 +60333,11 @@ async function processZipFile(file, platform, debug = false) {
|
|
|
60272
60333
|
});
|
|
60273
60334
|
zipfile2.close();
|
|
60274
60335
|
if (debug) {
|
|
60275
|
-
|
|
60336
|
+
log18.debug(`Zip ${file.name}: processed ${processedCount} files, skipped ${skipped.length}`);
|
|
60276
60337
|
}
|
|
60277
60338
|
return { blocks, skipped };
|
|
60278
60339
|
} catch (err) {
|
|
60279
|
-
|
|
60340
|
+
log18.error(`Failed to process zip file ${file.name}: ${err}`);
|
|
60280
60341
|
return {
|
|
60281
60342
|
blocks: [],
|
|
60282
60343
|
skipped: [{
|
|
@@ -60373,7 +60434,7 @@ async function processFiles(platform, files, debug = false) {
|
|
|
60373
60434
|
blocks.push(...zipResult.blocks);
|
|
60374
60435
|
for (const s of zipResult.skipped) {
|
|
60375
60436
|
skipped.push(s);
|
|
60376
|
-
|
|
60437
|
+
log18.warn(`Skipped file ${s.name}: ${s.reason}`);
|
|
60377
60438
|
}
|
|
60378
60439
|
continue;
|
|
60379
60440
|
}
|
|
@@ -60407,7 +60468,7 @@ async function processFiles(platform, files, debug = false) {
|
|
|
60407
60468
|
}
|
|
60408
60469
|
if (result.skipped) {
|
|
60409
60470
|
skipped.push(result.skipped);
|
|
60410
|
-
|
|
60471
|
+
log18.warn(`Skipped file ${result.skipped.name}: ${result.skipped.reason}`);
|
|
60411
60472
|
}
|
|
60412
60473
|
}
|
|
60413
60474
|
return { blocks, skipped };
|
|
@@ -60440,7 +60501,7 @@ function stopTyping(session) {
|
|
|
60440
60501
|
}
|
|
60441
60502
|
|
|
60442
60503
|
// src/operations/message-manager.ts
|
|
60443
|
-
var
|
|
60504
|
+
var log19 = createLogger("msg-mgr");
|
|
60444
60505
|
|
|
60445
60506
|
class MessageManager {
|
|
60446
60507
|
platform;
|
|
@@ -60530,7 +60591,7 @@ class MessageManager {
|
|
|
60530
60591
|
});
|
|
60531
60592
|
}
|
|
60532
60593
|
async handleEvent(event) {
|
|
60533
|
-
const logger =
|
|
60594
|
+
const logger = log19.forSession(this.sessionId);
|
|
60534
60595
|
const transformCtx = {
|
|
60535
60596
|
sessionId: this.sessionId,
|
|
60536
60597
|
formatter: this.platform.getFormatter(),
|
|
@@ -60580,7 +60641,7 @@ class MessageManager {
|
|
|
60580
60641
|
}
|
|
60581
60642
|
}
|
|
60582
60643
|
async executeOperation(op) {
|
|
60583
|
-
const logger =
|
|
60644
|
+
const logger = log19.forSession(this.sessionId);
|
|
60584
60645
|
const ctx = this.getExecutorContext();
|
|
60585
60646
|
try {
|
|
60586
60647
|
if (isContentOp(op)) {
|
|
@@ -60648,7 +60709,7 @@ class MessageManager {
|
|
|
60648
60709
|
threadId: this.threadId,
|
|
60649
60710
|
platform: this.platform,
|
|
60650
60711
|
formatter: this.platform.getFormatter(),
|
|
60651
|
-
logger:
|
|
60712
|
+
logger: log19.forSession(this.sessionId),
|
|
60652
60713
|
postTracker: this.postTracker,
|
|
60653
60714
|
contentBreaker: this.contentBreaker,
|
|
60654
60715
|
threadLogger: this.session.threadLogger,
|
|
@@ -60859,13 +60920,13 @@ class MessageManager {
|
|
|
60859
60920
|
return this.systemExecutor.postSuccess(message, this.getExecutorContext());
|
|
60860
60921
|
}
|
|
60861
60922
|
async prepareForUserMessage() {
|
|
60862
|
-
const logger =
|
|
60923
|
+
const logger = log19.forSession(this.sessionId);
|
|
60863
60924
|
logger.debug("Preparing for new user message");
|
|
60864
60925
|
await this.closeCurrentPost();
|
|
60865
60926
|
await this.bumpTaskList();
|
|
60866
60927
|
}
|
|
60867
60928
|
async handleUserMessage(message, files, username, displayName) {
|
|
60868
|
-
const logger =
|
|
60929
|
+
const logger = log19.forSession(this.sessionId);
|
|
60869
60930
|
if (!this.session.claude.isRunning()) {
|
|
60870
60931
|
logger.debug("Claude not running, ignoring user message");
|
|
60871
60932
|
return false;
|
|
@@ -60902,7 +60963,7 @@ class MessageManager {
|
|
|
60902
60963
|
];
|
|
60903
60964
|
}
|
|
60904
60965
|
async handleReaction(postId, emoji, user, action) {
|
|
60905
|
-
const logger =
|
|
60966
|
+
const logger = log19.forSession(this.sessionId);
|
|
60906
60967
|
const ctx = this.getExecutorContext();
|
|
60907
60968
|
logger.debug(`Routing reaction: postId=${postId}, emoji=${emoji}, user=${user}, action=${action}`);
|
|
60908
60969
|
for (const { name, executor } of this.reactionDispatchList()) {
|
|
@@ -61082,7 +61143,7 @@ function formatPullRequestLink(url, formatter) {
|
|
|
61082
61143
|
}
|
|
61083
61144
|
|
|
61084
61145
|
// src/operations/sticky-message/handler.ts
|
|
61085
|
-
var
|
|
61146
|
+
var log20 = createLogger("sticky");
|
|
61086
61147
|
var botStartedAt = new Date;
|
|
61087
61148
|
function getPendingPrompts(session) {
|
|
61088
61149
|
const prompts2 = [];
|
|
@@ -61157,21 +61218,21 @@ function initialize(store) {
|
|
|
61157
61218
|
stickyPostIds.set(platformId, postId);
|
|
61158
61219
|
}
|
|
61159
61220
|
if (persistedIds.size > 0) {
|
|
61160
|
-
|
|
61221
|
+
log20.info(`\uD83D\uDCCC Restored ${persistedIds.size} sticky post ID(s) from persistence`);
|
|
61161
61222
|
}
|
|
61162
61223
|
}
|
|
61163
61224
|
function setPlatformPaused(platformId, paused) {
|
|
61164
61225
|
if (paused) {
|
|
61165
61226
|
pausedPlatforms.set(platformId, true);
|
|
61166
|
-
|
|
61227
|
+
log20.debug(`Platform ${platformId} marked as paused`);
|
|
61167
61228
|
} else {
|
|
61168
61229
|
pausedPlatforms.delete(platformId);
|
|
61169
|
-
|
|
61230
|
+
log20.debug(`Platform ${platformId} marked as active`);
|
|
61170
61231
|
}
|
|
61171
61232
|
}
|
|
61172
61233
|
function setShuttingDown(shuttingDown) {
|
|
61173
61234
|
isShuttingDown = shuttingDown;
|
|
61174
|
-
|
|
61235
|
+
log20.debug(`Bot shutdown state: ${shuttingDown}`);
|
|
61175
61236
|
}
|
|
61176
61237
|
function getTaskContent(session) {
|
|
61177
61238
|
const taskState = session.messageManager?.getTaskListState();
|
|
@@ -61482,12 +61543,12 @@ async function validateLastMessageIds(platform, sessions) {
|
|
|
61482
61543
|
try {
|
|
61483
61544
|
const post2 = await platform.getPost(lastMessageId);
|
|
61484
61545
|
if (!post2) {
|
|
61485
|
-
|
|
61546
|
+
log20.debug(`lastMessageId ${lastMessageId.substring(0, 8)} for session ${session.sessionId} was deleted, clearing`);
|
|
61486
61547
|
session.lastMessageId = undefined;
|
|
61487
61548
|
session.lastMessageTs = undefined;
|
|
61488
61549
|
}
|
|
61489
61550
|
} catch (err) {
|
|
61490
|
-
|
|
61551
|
+
log20.debug(`Failed to validate lastMessageId for session ${session.sessionId}, clearing: ${err}`);
|
|
61491
61552
|
session.lastMessageId = undefined;
|
|
61492
61553
|
session.lastMessageTs = undefined;
|
|
61493
61554
|
}
|
|
@@ -61496,63 +61557,63 @@ async function validateLastMessageIds(platform, sessions) {
|
|
|
61496
61557
|
}
|
|
61497
61558
|
async function updateStickyMessageImpl(platform, sessions, config) {
|
|
61498
61559
|
const platformSessions = [...sessions.values()].filter((s) => s.platformId === platform.platformId);
|
|
61499
|
-
|
|
61560
|
+
log20.debug(`updateStickyMessage for ${platform.platformId}, ${platformSessions.length} sessions`);
|
|
61500
61561
|
for (const s of platformSessions) {
|
|
61501
|
-
|
|
61562
|
+
log20.debug(` - ${s.sessionId}: title="${s.sessionTitle}" firstPrompt="${s.firstPrompt?.substring(0, 30)}..."`);
|
|
61502
61563
|
}
|
|
61503
61564
|
await validateLastMessageIds(platform, platformSessions);
|
|
61504
61565
|
const formatter = platform.getFormatter();
|
|
61505
61566
|
const content = await buildStickyMessage(sessions, platform.platformId, config, formatter, (threadId) => platform.getThreadLink(threadId));
|
|
61506
61567
|
const existingPostId = stickyPostIds.get(platform.platformId);
|
|
61507
61568
|
const shouldBump = needsBump.get(platform.platformId) ?? false;
|
|
61508
|
-
|
|
61569
|
+
log20.debug(`existingPostId: ${existingPostId || "(none)"}, needsBump: ${shouldBump}`);
|
|
61509
61570
|
try {
|
|
61510
61571
|
if (existingPostId && !shouldBump) {
|
|
61511
|
-
|
|
61572
|
+
log20.debug(`Updating existing post in place...`);
|
|
61512
61573
|
try {
|
|
61513
61574
|
await platform.updatePost(existingPostId, content);
|
|
61514
61575
|
try {
|
|
61515
61576
|
await platform.pinPost(existingPostId);
|
|
61516
|
-
|
|
61577
|
+
log20.debug(`Re-pinned post`);
|
|
61517
61578
|
} catch (pinErr) {
|
|
61518
|
-
|
|
61579
|
+
log20.debug(`Re-pin failed (might already be pinned): ${pinErr}`);
|
|
61519
61580
|
}
|
|
61520
|
-
|
|
61581
|
+
log20.debug(`Updated successfully`);
|
|
61521
61582
|
return;
|
|
61522
61583
|
} catch (err) {
|
|
61523
|
-
|
|
61584
|
+
log20.debug(`Update failed, will create new: ${err}`);
|
|
61524
61585
|
}
|
|
61525
61586
|
}
|
|
61526
61587
|
needsBump.set(platform.platformId, false);
|
|
61527
61588
|
if (existingPostId) {
|
|
61528
|
-
|
|
61589
|
+
log20.debug(`Unpinning and deleting existing post ${existingPostId.substring(0, 8)}...`);
|
|
61529
61590
|
try {
|
|
61530
61591
|
await platform.unpinPost(existingPostId);
|
|
61531
|
-
|
|
61592
|
+
log20.debug(`Unpinned successfully`);
|
|
61532
61593
|
} catch (err) {
|
|
61533
|
-
|
|
61594
|
+
log20.debug(`Unpin failed (probably already unpinned): ${err}`);
|
|
61534
61595
|
}
|
|
61535
61596
|
try {
|
|
61536
61597
|
await platform.deletePost(existingPostId);
|
|
61537
|
-
|
|
61598
|
+
log20.debug(`Deleted successfully`);
|
|
61538
61599
|
} catch (err) {
|
|
61539
|
-
|
|
61600
|
+
log20.debug(`Delete failed (probably already deleted): ${err}`);
|
|
61540
61601
|
}
|
|
61541
61602
|
stickyPostIds.delete(platform.platformId);
|
|
61542
61603
|
}
|
|
61543
|
-
|
|
61604
|
+
log20.debug(`Creating new post...`);
|
|
61544
61605
|
const post2 = await platform.createPost(content);
|
|
61545
61606
|
stickyPostIds.set(platform.platformId, post2.id);
|
|
61546
61607
|
try {
|
|
61547
61608
|
await platform.pinPost(post2.id);
|
|
61548
|
-
|
|
61609
|
+
log20.debug(`Pinned post successfully`);
|
|
61549
61610
|
} catch (err) {
|
|
61550
|
-
|
|
61611
|
+
log20.debug(`Failed to pin post: ${err}`);
|
|
61551
61612
|
}
|
|
61552
61613
|
if (sessionStore) {
|
|
61553
61614
|
sessionStore.saveStickyPostId(platform.platformId, post2.id);
|
|
61554
61615
|
}
|
|
61555
|
-
|
|
61616
|
+
log20.info(`\uD83D\uDCCC Created sticky message for ${platform.platformId}: ${formatShortId(post2.id)}`);
|
|
61556
61617
|
const excludePostIds = new Set;
|
|
61557
61618
|
if (sessionStore) {
|
|
61558
61619
|
for (const session of sessionStore.load().values()) {
|
|
@@ -61568,10 +61629,10 @@ async function updateStickyMessageImpl(platform, sessions, config) {
|
|
|
61568
61629
|
}
|
|
61569
61630
|
const botUser = await platform.getBotUser();
|
|
61570
61631
|
cleanupOldStickyMessages(platform, botUser.id, false, excludePostIds).catch((err) => {
|
|
61571
|
-
|
|
61632
|
+
log20.debug(`Background cleanup failed: ${err}`);
|
|
61572
61633
|
});
|
|
61573
61634
|
} catch (err) {
|
|
61574
|
-
|
|
61635
|
+
log20.error(`Failed to update sticky message for ${platform.platformId}`, err instanceof Error ? err : undefined);
|
|
61575
61636
|
}
|
|
61576
61637
|
}
|
|
61577
61638
|
async function updateAllStickyMessages(platforms, sessions, config) {
|
|
@@ -61596,7 +61657,7 @@ async function cleanupOldStickyMessages(platform, botUserId, forceRun = false, e
|
|
|
61596
61657
|
if (!forceRun) {
|
|
61597
61658
|
const lastRun = lastCleanupTime.get(platformId) || 0;
|
|
61598
61659
|
if (now - lastRun < CLEANUP_THROTTLE_MS) {
|
|
61599
|
-
|
|
61660
|
+
log20.debug(`Cleanup throttled for ${platformId} (last run ${Math.round((now - lastRun) / 1000)}s ago)`);
|
|
61600
61661
|
return;
|
|
61601
61662
|
}
|
|
61602
61663
|
}
|
|
@@ -61606,31 +61667,31 @@ async function cleanupOldStickyMessages(platform, botUserId, forceRun = false, e
|
|
|
61606
61667
|
const pinnedPostIds = await platform.getPinnedPosts();
|
|
61607
61668
|
const recentPinnedIds = pinnedPostIds.filter((id) => id !== currentStickyId && !excludePostIds?.has(id) && isRecentPost(id));
|
|
61608
61669
|
if (recentPinnedIds.length === 0) {
|
|
61609
|
-
|
|
61670
|
+
log20.debug(`No recent pinned posts to check (${pinnedPostIds.length} total, current: ${currentStickyId?.substring(0, 8) || "(none)"})`);
|
|
61610
61671
|
return;
|
|
61611
61672
|
}
|
|
61612
|
-
|
|
61673
|
+
log20.debug(`Checking ${recentPinnedIds.length} recent pinned posts (of ${pinnedPostIds.length} total)`);
|
|
61613
61674
|
for (const postId of recentPinnedIds) {
|
|
61614
61675
|
try {
|
|
61615
61676
|
const post2 = await platform.getPost(postId);
|
|
61616
61677
|
if (!post2)
|
|
61617
61678
|
continue;
|
|
61618
61679
|
if (post2.userId === botUserId) {
|
|
61619
|
-
|
|
61680
|
+
log20.debug(`Cleaning up old sticky: ${postId.substring(0, 8)}...`);
|
|
61620
61681
|
try {
|
|
61621
61682
|
await platform.unpinPost(postId);
|
|
61622
61683
|
await platform.deletePost(postId);
|
|
61623
|
-
|
|
61684
|
+
log20.info(`\uD83E\uDDF9 Cleaned up old sticky message: ${postId.substring(0, 8)}...`);
|
|
61624
61685
|
} catch (err) {
|
|
61625
|
-
|
|
61686
|
+
log20.debug(`Failed to cleanup ${postId}: ${err}`);
|
|
61626
61687
|
}
|
|
61627
61688
|
}
|
|
61628
61689
|
} catch (err) {
|
|
61629
|
-
|
|
61690
|
+
log20.debug(`Could not check post ${postId}: ${err}`);
|
|
61630
61691
|
}
|
|
61631
61692
|
}
|
|
61632
61693
|
} catch (err) {
|
|
61633
|
-
|
|
61694
|
+
log20.error(`Failed to cleanup old sticky messages`, err instanceof Error ? err : undefined);
|
|
61634
61695
|
}
|
|
61635
61696
|
}
|
|
61636
61697
|
// src/operations/bug-report/handler.ts
|
|
@@ -65693,8 +65754,8 @@ function getUpdateInfo() {
|
|
|
65693
65754
|
init_emoji();
|
|
65694
65755
|
init_logger();
|
|
65695
65756
|
init_worktree();
|
|
65696
|
-
var
|
|
65697
|
-
var sessionLog2 = createSessionLog(
|
|
65757
|
+
var log21 = createLogger("commands");
|
|
65758
|
+
var sessionLog2 = createSessionLog(log21);
|
|
65698
65759
|
function sessionAccountOption(session, ctx) {
|
|
65699
65760
|
if (!session.claudeAccountId)
|
|
65700
65761
|
return;
|
|
@@ -66228,7 +66289,7 @@ init_logger();
|
|
|
66228
66289
|
import { exec as exec3 } from "child_process";
|
|
66229
66290
|
import { promisify as promisify3 } from "util";
|
|
66230
66291
|
var execAsync2 = promisify3(exec3);
|
|
66231
|
-
var
|
|
66292
|
+
var log22 = createLogger("branch");
|
|
66232
66293
|
var SUGGESTION_TIMEOUT3 = 15000;
|
|
66233
66294
|
var MAX_SUGGESTIONS = 3;
|
|
66234
66295
|
async function getCurrentBranch3(workingDir) {
|
|
@@ -66277,7 +66338,7 @@ function parseBranchSuggestions(response) {
|
|
|
66277
66338
|
return lines.slice(0, MAX_SUGGESTIONS);
|
|
66278
66339
|
}
|
|
66279
66340
|
async function suggestBranchNames(workingDir, userMessage) {
|
|
66280
|
-
|
|
66341
|
+
log22.debug(`Suggesting branch names for: "${userMessage.substring(0, 50)}..."`);
|
|
66281
66342
|
try {
|
|
66282
66343
|
const [currentBranch, recentCommits] = await Promise.all([
|
|
66283
66344
|
getCurrentBranch3(workingDir),
|
|
@@ -66291,14 +66352,14 @@ async function suggestBranchNames(workingDir, userMessage) {
|
|
|
66291
66352
|
workingDir
|
|
66292
66353
|
});
|
|
66293
66354
|
if (!result.success || !result.response) {
|
|
66294
|
-
|
|
66355
|
+
log22.debug(`Branch suggestion failed: ${result.error || "no response"}`);
|
|
66295
66356
|
return [];
|
|
66296
66357
|
}
|
|
66297
66358
|
const suggestions = parseBranchSuggestions(result.response);
|
|
66298
|
-
|
|
66359
|
+
log22.debug(`Got ${suggestions.length} branch suggestions: ${suggestions.join(", ")}`);
|
|
66299
66360
|
return suggestions;
|
|
66300
66361
|
} catch (err) {
|
|
66301
|
-
|
|
66362
|
+
log22.debug(`Branch suggestion error: ${err}`);
|
|
66302
66363
|
return [];
|
|
66303
66364
|
}
|
|
66304
66365
|
}
|
|
@@ -66307,8 +66368,8 @@ async function suggestBranchNames(workingDir, userMessage) {
|
|
|
66307
66368
|
init_worktree();
|
|
66308
66369
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
66309
66370
|
init_logger();
|
|
66310
|
-
var
|
|
66311
|
-
var sessionLog3 = createSessionLog(
|
|
66371
|
+
var log23 = createLogger("worktree");
|
|
66372
|
+
var sessionLog3 = createSessionLog(log23);
|
|
66312
66373
|
function parseWorktreeError(error) {
|
|
66313
66374
|
const message = error instanceof Error ? error.message : String(error);
|
|
66314
66375
|
const lowerMessage = message.toLowerCase();
|
|
@@ -66318,6 +66379,15 @@ function parseWorktreeError(error) {
|
|
|
66318
66379
|
suggestion: "Try a different branch name, or use `!worktree list` to see existing worktrees"
|
|
66319
66380
|
};
|
|
66320
66381
|
}
|
|
66382
|
+
const parentBlocksMatch = message.match(/'refs\/heads\/([^']+)' exists; cannot create '(?:refs\/heads\/)?([^']+)'/i);
|
|
66383
|
+
if (parentBlocksMatch) {
|
|
66384
|
+
const parent = parentBlocksMatch[1];
|
|
66385
|
+
const nested = parentBlocksMatch[2];
|
|
66386
|
+
return {
|
|
66387
|
+
summary: `Branch ${parent} already exists and blocks ${nested}`,
|
|
66388
|
+
suggestion: `Pick a name that does not start with ${parent}/, or delete the existing ${parent} branch first.`
|
|
66389
|
+
};
|
|
66390
|
+
}
|
|
66321
66391
|
if (lowerMessage.includes("already exists")) {
|
|
66322
66392
|
return {
|
|
66323
66393
|
summary: "A worktree or branch with this name already exists",
|
|
@@ -66867,8 +66937,8 @@ async function cleanupWorktreeCommand(session, username, hasOtherSessionsUsingWo
|
|
|
66867
66937
|
}
|
|
66868
66938
|
// src/operations/events/handler.ts
|
|
66869
66939
|
init_logger();
|
|
66870
|
-
var
|
|
66871
|
-
var sessionLog4 = createSessionLog(
|
|
66940
|
+
var log24 = createLogger("events");
|
|
66941
|
+
var sessionLog4 = createSessionLog(log24);
|
|
66872
66942
|
function detectAndExecuteClaudeCommands(text, session, ctx) {
|
|
66873
66943
|
const parsed = parseClaudeCommand(text);
|
|
66874
66944
|
if (parsed && isClaudeAllowedCommand(parsed.command)) {
|
|
@@ -67116,8 +67186,8 @@ function createSessionContext(config, state, ops) {
|
|
|
67116
67186
|
// src/operations/context-prompt/handler.ts
|
|
67117
67187
|
init_emoji();
|
|
67118
67188
|
init_logger();
|
|
67119
|
-
var
|
|
67120
|
-
var sessionLog5 = createSessionLog(
|
|
67189
|
+
var log25 = createLogger("context");
|
|
67190
|
+
var sessionLog5 = createSessionLog(log25);
|
|
67121
67191
|
var CONTEXT_PROMPT_TIMEOUT_MS = 30000;
|
|
67122
67192
|
var CONTEXT_OPTIONS = [3, 5, 10];
|
|
67123
67193
|
var contextPromptTimeouts = new Map;
|
|
@@ -67367,8 +67437,8 @@ function formatRelativeTime(date) {
|
|
|
67367
67437
|
}
|
|
67368
67438
|
// src/session/lifecycle.ts
|
|
67369
67439
|
init_worktree();
|
|
67370
|
-
var
|
|
67371
|
-
var sessionLog6 = createSessionLog(
|
|
67440
|
+
var log26 = createLogger("lifecycle");
|
|
67441
|
+
var sessionLog6 = createSessionLog(log26);
|
|
67372
67442
|
function mutableSessions(ctx) {
|
|
67373
67443
|
return ctx.state.sessions;
|
|
67374
67444
|
}
|
|
@@ -67753,17 +67823,17 @@ async function startSession(options2, username, displayName, replyToPostId, plat
|
|
|
67753
67823
|
return;
|
|
67754
67824
|
}
|
|
67755
67825
|
workingDir = resolvedDir;
|
|
67756
|
-
|
|
67826
|
+
log26.info(`Starting session in directory: ${workingDir} (from !cd command)`);
|
|
67757
67827
|
}
|
|
67758
67828
|
if (initialOptions?.permissionMode) {
|
|
67759
67829
|
permissionMode = initialOptions.permissionMode;
|
|
67760
67830
|
forceInteractivePermissions = permissionMode === "default";
|
|
67761
67831
|
sessionPermissionModeOverride = permissionMode;
|
|
67762
|
-
|
|
67832
|
+
log26.info(`Starting session with permission mode "${permissionMode}" (from !permissions command)`);
|
|
67763
67833
|
} else if (initialOptions?.forceInteractivePermissions) {
|
|
67764
67834
|
forceInteractivePermissions = true;
|
|
67765
67835
|
permissionMode = "default";
|
|
67766
|
-
|
|
67836
|
+
log26.info(`Starting session with interactive permissions (from !permissions command)`);
|
|
67767
67837
|
}
|
|
67768
67838
|
const sessionContext = buildSessionContext(platform, workingDir);
|
|
67769
67839
|
const systemPrompt = `${sessionContext}
|
|
@@ -67772,7 +67842,7 @@ ${CHAT_PLATFORM_PROMPT}`;
|
|
|
67772
67842
|
const platformMcpConfig = platform.getMcpConfig();
|
|
67773
67843
|
const claudeAccount = ctx.ops.acquireClaudeAccount();
|
|
67774
67844
|
if (claudeAccount) {
|
|
67775
|
-
|
|
67845
|
+
log26.info(`Session ${sessionId.substring(0, 20)} reserved Claude account "${claudeAccount.id}"`);
|
|
67776
67846
|
}
|
|
67777
67847
|
const cliOptions = {
|
|
67778
67848
|
workingDir,
|
|
@@ -67877,28 +67947,28 @@ async function resumeSession(state, ctx) {
|
|
|
67877
67947
|
!state.claudeSessionId && "claudeSessionId",
|
|
67878
67948
|
!state.workingDir && "workingDir"
|
|
67879
67949
|
].filter(Boolean).join(", ");
|
|
67880
|
-
|
|
67950
|
+
log26.warn(`Skipping session with missing required fields: ${missing}`);
|
|
67881
67951
|
return;
|
|
67882
67952
|
}
|
|
67883
67953
|
const shortId = state.threadId.substring(0, 8);
|
|
67884
67954
|
const platforms = ctx.state.platforms;
|
|
67885
67955
|
const platform = platforms.get(state.platformId);
|
|
67886
67956
|
if (!platform) {
|
|
67887
|
-
|
|
67957
|
+
log26.warn(`Platform ${state.platformId} not registered, skipping resume for ${shortId}...`);
|
|
67888
67958
|
return;
|
|
67889
67959
|
}
|
|
67890
67960
|
const threadPost = await platform.getPost(state.threadId);
|
|
67891
67961
|
if (!threadPost) {
|
|
67892
|
-
|
|
67962
|
+
log26.warn(`Thread ${shortId}... deleted, skipping resume`);
|
|
67893
67963
|
ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
|
|
67894
67964
|
return;
|
|
67895
67965
|
}
|
|
67896
67966
|
if (ctx.state.sessions.size >= ctx.config.maxSessions) {
|
|
67897
|
-
|
|
67967
|
+
log26.warn(`Max sessions reached, skipping resume for ${shortId}...`);
|
|
67898
67968
|
return;
|
|
67899
67969
|
}
|
|
67900
67970
|
if (!existsSync11(state.workingDir)) {
|
|
67901
|
-
|
|
67971
|
+
log26.warn(`Working directory ${state.workingDir} no longer exists, skipping resume for ${shortId}...`);
|
|
67902
67972
|
ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
|
|
67903
67973
|
const resumeFormatter = platform.getFormatter();
|
|
67904
67974
|
const tempSession = {
|
|
@@ -67922,7 +67992,7 @@ Please start a new session.`), { action: "Post resume failure notification" });
|
|
|
67922
67992
|
${CHAT_PLATFORM_PROMPT}`;
|
|
67923
67993
|
const claudeAccount = ctx.ops.acquireClaudeAccount(state.claudeAccountId);
|
|
67924
67994
|
if (state.claudeAccountId && !claudeAccount) {
|
|
67925
|
-
|
|
67995
|
+
log26.warn(`Persisted session referenced Claude account "${state.claudeAccountId}" ` + `which is no longer configured — resuming under default env`);
|
|
67926
67996
|
}
|
|
67927
67997
|
const cliOptions = {
|
|
67928
67998
|
workingDir: state.workingDir,
|
|
@@ -67987,7 +68057,7 @@ ${CHAT_PLATFORM_PROMPT}`;
|
|
|
67987
68057
|
worktreePath: detected.worktreePath,
|
|
67988
68058
|
branch: detected.branch
|
|
67989
68059
|
};
|
|
67990
|
-
|
|
68060
|
+
log26.info(`Auto-detected worktree info for resumed session: branch=${detected.branch}`);
|
|
67991
68061
|
}
|
|
67992
68062
|
}
|
|
67993
68063
|
session.messageManager = createMessageManager(session, ctx);
|
|
@@ -68043,7 +68113,7 @@ ${sessionFormatter.formatItalic("Reconnected to Claude session. You can continue
|
|
|
68043
68113
|
await ctx.ops.updateStickyMessage();
|
|
68044
68114
|
ctx.ops.persistSession(session);
|
|
68045
68115
|
} catch (err) {
|
|
68046
|
-
|
|
68116
|
+
log26.error(`Failed to resume session ${shortId}`, err instanceof Error ? err : undefined);
|
|
68047
68117
|
ctx.ops.emitSessionRemove(sessionId);
|
|
68048
68118
|
mutableSessions(ctx).delete(sessionId);
|
|
68049
68119
|
ctx.state.sessionStore.remove(sessionId);
|
|
@@ -68083,18 +68153,18 @@ async function resumePausedSession(threadId, message, files, ctx) {
|
|
|
68083
68153
|
const persisted = ctx.state.sessionStore.load();
|
|
68084
68154
|
const state = findPersistedByThreadId(persisted, threadId);
|
|
68085
68155
|
if (!state) {
|
|
68086
|
-
|
|
68156
|
+
log26.debug(`No persisted session found for ${threadId.substring(0, 8)}...`);
|
|
68087
68157
|
return;
|
|
68088
68158
|
}
|
|
68089
68159
|
const shortId = threadId.substring(0, 8);
|
|
68090
|
-
|
|
68160
|
+
log26.info(`\uD83D\uDD04 Resuming paused session ${shortId}... for new message`);
|
|
68091
68161
|
await resumeSession(state, ctx);
|
|
68092
68162
|
const session = ctx.ops.findSessionByThreadId(threadId);
|
|
68093
68163
|
if (session && session.claude.isRunning() && session.messageManager) {
|
|
68094
68164
|
session.messageCount++;
|
|
68095
68165
|
await session.messageManager.handleUserMessage(message, files, state.startedBy);
|
|
68096
68166
|
} else {
|
|
68097
|
-
|
|
68167
|
+
log26.warn(`Failed to resume session ${shortId}..., could not send message`);
|
|
68098
68168
|
}
|
|
68099
68169
|
}
|
|
68100
68170
|
async function handleExit(sessionId, code, ctx) {
|
|
@@ -68102,7 +68172,7 @@ async function handleExit(sessionId, code, ctx) {
|
|
|
68102
68172
|
const shortId = sessionId.substring(0, 8);
|
|
68103
68173
|
sessionLog6(session).debug(`handleExit called code=${code} isShuttingDown=${ctx.state.isShuttingDown}`);
|
|
68104
68174
|
if (!session) {
|
|
68105
|
-
|
|
68175
|
+
log26.debug(`Session ${shortId}... not found (already cleaned up)`);
|
|
68106
68176
|
return;
|
|
68107
68177
|
}
|
|
68108
68178
|
if (isSessionRestarting(session)) {
|
|
@@ -68295,7 +68365,7 @@ async function cleanupIdleSessions(timeoutMs, warningMs, ctx) {
|
|
|
68295
68365
|
}
|
|
68296
68366
|
|
|
68297
68367
|
// src/operations/monitor/handler.ts
|
|
68298
|
-
var
|
|
68368
|
+
var log27 = createLogger("monitor");
|
|
68299
68369
|
var DEFAULT_INTERVAL_MS = 60 * 1000;
|
|
68300
68370
|
|
|
68301
68371
|
class SessionMonitor {
|
|
@@ -68317,14 +68387,14 @@ class SessionMonitor {
|
|
|
68317
68387
|
}
|
|
68318
68388
|
start() {
|
|
68319
68389
|
if (this.isRunning) {
|
|
68320
|
-
|
|
68390
|
+
log27.debug("Session monitor already running");
|
|
68321
68391
|
return;
|
|
68322
68392
|
}
|
|
68323
68393
|
this.isRunning = true;
|
|
68324
|
-
|
|
68394
|
+
log27.debug(`Session monitor started (interval: ${this.intervalMs / 1000}s)`);
|
|
68325
68395
|
this.timer = setInterval(() => {
|
|
68326
68396
|
this.runCheck().catch((err) => {
|
|
68327
|
-
|
|
68397
|
+
log27.error(`Error during session monitoring: ${err}`);
|
|
68328
68398
|
});
|
|
68329
68399
|
}, this.intervalMs);
|
|
68330
68400
|
}
|
|
@@ -68334,7 +68404,7 @@ class SessionMonitor {
|
|
|
68334
68404
|
this.timer = null;
|
|
68335
68405
|
}
|
|
68336
68406
|
this.isRunning = false;
|
|
68337
|
-
|
|
68407
|
+
log27.debug("Session monitor stopped");
|
|
68338
68408
|
}
|
|
68339
68409
|
async runCheck() {
|
|
68340
68410
|
await cleanupIdleSessions(this.sessionTimeoutMs, this.sessionWarningMs, this.getContext());
|
|
@@ -68346,8 +68416,8 @@ class SessionMonitor {
|
|
|
68346
68416
|
// src/operations/plugin/handler.ts
|
|
68347
68417
|
init_spawn();
|
|
68348
68418
|
init_logger();
|
|
68349
|
-
var
|
|
68350
|
-
var sessionLog7 = createSessionLog(
|
|
68419
|
+
var log28 = createLogger("plugin");
|
|
68420
|
+
var sessionLog7 = createSessionLog(log28);
|
|
68351
68421
|
async function runPluginCommand(args, cwd, timeout2 = 60000) {
|
|
68352
68422
|
return new Promise((resolve6) => {
|
|
68353
68423
|
const claudePath = process.env.CLAUDE_PATH || "claude";
|
|
@@ -68368,7 +68438,7 @@ async function runPluginCommand(args, cwd, timeout2 = 60000) {
|
|
|
68368
68438
|
});
|
|
68369
68439
|
proc.on("error", (err) => {
|
|
68370
68440
|
resolve6({ stdout, stderr, exitCode: 1 });
|
|
68371
|
-
|
|
68441
|
+
log28.error(`Plugin command error: ${err.message}`);
|
|
68372
68442
|
});
|
|
68373
68443
|
});
|
|
68374
68444
|
}
|
|
@@ -68567,9 +68637,105 @@ class SessionRegistry {
|
|
|
68567
68637
|
}
|
|
68568
68638
|
}
|
|
68569
68639
|
|
|
68640
|
+
// src/session/reaction-router.ts
|
|
68641
|
+
init_emoji();
|
|
68642
|
+
init_logger();
|
|
68643
|
+
var log29 = createLogger("manager");
|
|
68644
|
+
async function handleReaction(deps, platformId, postId, emojiName, username, action) {
|
|
68645
|
+
const normalizedEmoji = normalizeEmojiName(emojiName);
|
|
68646
|
+
if (action === "added" && isResumeEmoji(normalizedEmoji)) {
|
|
68647
|
+
const resumed = await tryResumeFromReaction(deps, platformId, postId, username);
|
|
68648
|
+
if (resumed)
|
|
68649
|
+
return;
|
|
68650
|
+
}
|
|
68651
|
+
const session = deps.registry.findByPost(postId);
|
|
68652
|
+
if (!session)
|
|
68653
|
+
return;
|
|
68654
|
+
if (session.platformId !== platformId)
|
|
68655
|
+
return;
|
|
68656
|
+
if (!session.sessionAllowedUsers.has(username) && !session.platform.isUserAllowed(username)) {
|
|
68657
|
+
log29.info(`\uD83D\uDEAB rejected reaction from unauthorized user`, {
|
|
68658
|
+
event: "reaction.rejected",
|
|
68659
|
+
platformId,
|
|
68660
|
+
sessionId: session.sessionId,
|
|
68661
|
+
postId,
|
|
68662
|
+
emoji: normalizedEmoji,
|
|
68663
|
+
action,
|
|
68664
|
+
user: username
|
|
68665
|
+
});
|
|
68666
|
+
return;
|
|
68667
|
+
}
|
|
68668
|
+
await dispatch(deps, session, postId, normalizedEmoji, username, action);
|
|
68669
|
+
}
|
|
68670
|
+
async function tryResumeFromReaction(deps, platformId, postId, username) {
|
|
68671
|
+
const persistedSession = deps.sessionStore.findByPostId(platformId, postId);
|
|
68672
|
+
if (!persistedSession)
|
|
68673
|
+
return false;
|
|
68674
|
+
const sessionId = `${platformId}:${persistedSession.threadId}`;
|
|
68675
|
+
if (deps.registry.hasById(sessionId))
|
|
68676
|
+
return false;
|
|
68677
|
+
const allowedUsers = new Set(persistedSession.sessionAllowedUsers);
|
|
68678
|
+
const platform = deps.platforms.get(platformId);
|
|
68679
|
+
if (!allowedUsers.has(username) && !platform?.isUserAllowed(username)) {
|
|
68680
|
+
if (platform) {
|
|
68681
|
+
await platform.createPost(`⚠️ @${username} is not authorized to resume this session`, persistedSession.threadId);
|
|
68682
|
+
}
|
|
68683
|
+
return false;
|
|
68684
|
+
}
|
|
68685
|
+
if (deps.registry.size >= deps.limits.maxSessions) {
|
|
68686
|
+
if (platform) {
|
|
68687
|
+
const fmt = platform.getFormatter();
|
|
68688
|
+
await platform.createPost(`⚠️ ${fmt.formatBold("Too busy")} - ${deps.registry.size} sessions active. Please try again later.`, persistedSession.threadId);
|
|
68689
|
+
}
|
|
68690
|
+
return false;
|
|
68691
|
+
}
|
|
68692
|
+
const shortId = persistedSession.threadId.substring(0, 8);
|
|
68693
|
+
log29.info(`\uD83D\uDD04 Resuming session ${shortId}... via emoji reaction by @${username}`);
|
|
68694
|
+
await resumeSession(persistedSession, deps.getContext());
|
|
68695
|
+
return true;
|
|
68696
|
+
}
|
|
68697
|
+
async function dispatch(deps, session, postId, emojiName, username, action) {
|
|
68698
|
+
if (action === "added") {
|
|
68699
|
+
if (session.sessionStartPostId === postId) {
|
|
68700
|
+
if (isCancelEmoji(emojiName)) {
|
|
68701
|
+
await cancelSession(session, username, deps.getContext());
|
|
68702
|
+
return;
|
|
68703
|
+
}
|
|
68704
|
+
if (isEscapeEmoji(emojiName)) {
|
|
68705
|
+
await interruptSession(session, username);
|
|
68706
|
+
return;
|
|
68707
|
+
}
|
|
68708
|
+
}
|
|
68709
|
+
if (session.worktreePromptPostId === postId && emojiName === "x") {
|
|
68710
|
+
await handleWorktreeSkip(session, username, (s) => deps.persistSession(s), (s, q) => offerContextPrompt(s, q, undefined, deps.getContextPromptHandler()));
|
|
68711
|
+
return;
|
|
68712
|
+
}
|
|
68713
|
+
if (session.pendingWorktreeSuggestions?.postId === postId) {
|
|
68714
|
+
const emojiIndex = getNumberEmojiIndex(emojiName);
|
|
68715
|
+
if (emojiIndex >= 0) {
|
|
68716
|
+
const handled = await handleBranchSuggestionReaction(session, postId, emojiIndex, username, (tid, branch, user) => deps.createAndSwitchToWorktree(tid, branch, user));
|
|
68717
|
+
if (handled)
|
|
68718
|
+
return;
|
|
68719
|
+
}
|
|
68720
|
+
}
|
|
68721
|
+
if (session.lastError?.postId === postId && isBugReportEmoji(emojiName)) {
|
|
68722
|
+
if (session.startedBy === username || session.platform.isUserAllowed(username) || session.sessionAllowedUsers.has(username)) {
|
|
68723
|
+
log29.info(`\uD83D\uDC1B @${username} triggered bug report from error reaction`);
|
|
68724
|
+
await reportBug(session, undefined, username, deps.getContext(), session.lastError);
|
|
68725
|
+
return;
|
|
68726
|
+
}
|
|
68727
|
+
}
|
|
68728
|
+
}
|
|
68729
|
+
if (session.messageManager) {
|
|
68730
|
+
const handled = await session.messageManager.handleReaction(postId, emojiName, username, action);
|
|
68731
|
+
if (handled)
|
|
68732
|
+
return;
|
|
68733
|
+
}
|
|
68734
|
+
}
|
|
68735
|
+
|
|
68570
68736
|
// src/session/manager.ts
|
|
68571
68737
|
init_logger();
|
|
68572
|
-
var
|
|
68738
|
+
var log30 = createLogger("manager");
|
|
68573
68739
|
|
|
68574
68740
|
class SessionManager extends EventEmitter4 {
|
|
68575
68741
|
platforms = new Map;
|
|
@@ -68638,7 +68804,7 @@ class SessionManager extends EventEmitter4 {
|
|
|
68638
68804
|
markNeedsBump(platformId);
|
|
68639
68805
|
this.updateStickyMessage();
|
|
68640
68806
|
});
|
|
68641
|
-
|
|
68807
|
+
log30.info(`\uD83D\uDCE1 Platform "${platformId}" registered`);
|
|
68642
68808
|
}
|
|
68643
68809
|
removePlatform(platformId) {
|
|
68644
68810
|
this.platforms.delete(platformId);
|
|
@@ -68654,7 +68820,7 @@ class SessionManager extends EventEmitter4 {
|
|
|
68654
68820
|
if (users) {
|
|
68655
68821
|
users.add(sessionId);
|
|
68656
68822
|
}
|
|
68657
|
-
|
|
68823
|
+
log30.debug(`Registered session ${sessionId.substring(0, 20)} as worktree user for ${worktreePath}`);
|
|
68658
68824
|
}
|
|
68659
68825
|
unregisterWorktreeUser(worktreePath, sessionId) {
|
|
68660
68826
|
const users = this.worktreeUsers.get(worktreePath);
|
|
@@ -68768,95 +68934,19 @@ class SessionManager extends EventEmitter4 {
|
|
|
68768
68934
|
}
|
|
68769
68935
|
async handleMessage(_platformId, _post, _user) {}
|
|
68770
68936
|
async handleReaction(platformId, postId, emojiName, username, action) {
|
|
68771
|
-
|
|
68772
|
-
if (action === "added" && isResumeEmoji(normalizedEmoji)) {
|
|
68773
|
-
const resumed = await this.tryResumeFromReaction(platformId, postId, username);
|
|
68774
|
-
if (resumed)
|
|
68775
|
-
return;
|
|
68776
|
-
}
|
|
68777
|
-
const session = this.getSessionByPost(postId);
|
|
68778
|
-
if (!session)
|
|
68779
|
-
return;
|
|
68780
|
-
if (session.platformId !== platformId)
|
|
68781
|
-
return;
|
|
68782
|
-
if (!session.sessionAllowedUsers.has(username) && !session.platform.isUserAllowed(username)) {
|
|
68783
|
-
log28.info(`\uD83D\uDEAB rejected reaction from unauthorized user`, {
|
|
68784
|
-
event: "reaction.rejected",
|
|
68785
|
-
platformId,
|
|
68786
|
-
sessionId: session.sessionId,
|
|
68787
|
-
postId,
|
|
68788
|
-
emoji: normalizedEmoji,
|
|
68789
|
-
action,
|
|
68790
|
-
user: username
|
|
68791
|
-
});
|
|
68792
|
-
return;
|
|
68793
|
-
}
|
|
68794
|
-
await this.handleSessionReaction(session, postId, normalizedEmoji, username, action);
|
|
68937
|
+
await handleReaction(this.getReactionRouterDeps(), platformId, postId, emojiName, username, action);
|
|
68795
68938
|
}
|
|
68796
|
-
|
|
68797
|
-
|
|
68798
|
-
|
|
68799
|
-
|
|
68800
|
-
|
|
68801
|
-
|
|
68802
|
-
|
|
68803
|
-
|
|
68804
|
-
|
|
68805
|
-
|
|
68806
|
-
|
|
68807
|
-
await platform.createPost(`⚠️ @${username} is not authorized to resume this session`, persistedSession.threadId);
|
|
68808
|
-
}
|
|
68809
|
-
return false;
|
|
68810
|
-
}
|
|
68811
|
-
if (this.registry.size >= this.limits.maxSessions) {
|
|
68812
|
-
if (platform) {
|
|
68813
|
-
const fmt = platform.getFormatter();
|
|
68814
|
-
await platform.createPost(`⚠️ ${fmt.formatBold("Too busy")} - ${this.registry.size} sessions active. Please try again later.`, persistedSession.threadId);
|
|
68815
|
-
}
|
|
68816
|
-
return false;
|
|
68817
|
-
}
|
|
68818
|
-
const shortId = persistedSession.threadId.substring(0, 8);
|
|
68819
|
-
log28.info(`\uD83D\uDD04 Resuming session ${shortId}... via emoji reaction by @${username}`);
|
|
68820
|
-
await resumeSession(persistedSession, this.getContext());
|
|
68821
|
-
return true;
|
|
68822
|
-
}
|
|
68823
|
-
async handleSessionReaction(session, postId, emojiName, username, action) {
|
|
68824
|
-
if (action === "added") {
|
|
68825
|
-
if (session.sessionStartPostId === postId) {
|
|
68826
|
-
if (isCancelEmoji(emojiName)) {
|
|
68827
|
-
await cancelSession(session, username, this.getContext());
|
|
68828
|
-
return;
|
|
68829
|
-
}
|
|
68830
|
-
if (isEscapeEmoji(emojiName)) {
|
|
68831
|
-
await interruptSession(session, username);
|
|
68832
|
-
return;
|
|
68833
|
-
}
|
|
68834
|
-
}
|
|
68835
|
-
if (session.worktreePromptPostId === postId && emojiName === "x") {
|
|
68836
|
-
await handleWorktreeSkip(session, username, (s) => this.persistSession(s), (s, q) => offerContextPrompt(s, q, undefined, this.getContextPromptHandler()));
|
|
68837
|
-
return;
|
|
68838
|
-
}
|
|
68839
|
-
if (session.pendingWorktreeSuggestions?.postId === postId) {
|
|
68840
|
-
const emojiIndex = getNumberEmojiIndex(emojiName);
|
|
68841
|
-
if (emojiIndex >= 0) {
|
|
68842
|
-
const handled = await handleBranchSuggestionReaction(session, postId, emojiIndex, username, (tid, branch, user) => this.createAndSwitchToWorktree(tid, branch, user));
|
|
68843
|
-
if (handled)
|
|
68844
|
-
return;
|
|
68845
|
-
}
|
|
68846
|
-
}
|
|
68847
|
-
if (session.lastError?.postId === postId && isBugReportEmoji(emojiName)) {
|
|
68848
|
-
if (session.startedBy === username || session.platform.isUserAllowed(username) || session.sessionAllowedUsers.has(username)) {
|
|
68849
|
-
log28.info(`\uD83D\uDC1B @${username} triggered bug report from error reaction`);
|
|
68850
|
-
await reportBug(session, undefined, username, this.getContext(), session.lastError);
|
|
68851
|
-
return;
|
|
68852
|
-
}
|
|
68853
|
-
}
|
|
68854
|
-
}
|
|
68855
|
-
if (session.messageManager) {
|
|
68856
|
-
const handled = await session.messageManager.handleReaction(postId, emojiName, username, action);
|
|
68857
|
-
if (handled)
|
|
68858
|
-
return;
|
|
68859
|
-
}
|
|
68939
|
+
getReactionRouterDeps() {
|
|
68940
|
+
return {
|
|
68941
|
+
registry: this.registry,
|
|
68942
|
+
sessionStore: this.sessionStore,
|
|
68943
|
+
platforms: this.platforms,
|
|
68944
|
+
limits: this.limits,
|
|
68945
|
+
getContext: () => this.getContext(),
|
|
68946
|
+
getContextPromptHandler: () => this.getContextPromptHandler(),
|
|
68947
|
+
persistSession: (s) => this.persistSession(s),
|
|
68948
|
+
createAndSwitchToWorktree: (tid, branch, user) => this.createAndSwitchToWorktree(tid, branch, user)
|
|
68949
|
+
};
|
|
68860
68950
|
}
|
|
68861
68951
|
getContextPromptHandler() {
|
|
68862
68952
|
return {
|
|
@@ -68915,28 +69005,14 @@ class SessionManager extends EventEmitter4 {
|
|
|
68915
69005
|
this.stopTyping(session);
|
|
68916
69006
|
}
|
|
68917
69007
|
persistSession(session) {
|
|
68918
|
-
const useSerializeV2 = process.env.CLAUDE_THREADS_SERIALIZE_V2 !== "0";
|
|
68919
69008
|
let taskListSnapshot;
|
|
68920
69009
|
let contextPromptSnapshot;
|
|
68921
|
-
if (
|
|
69010
|
+
if (session.messageManager) {
|
|
68922
69011
|
const serialized = session.messageManager.serialize();
|
|
68923
69012
|
taskListSnapshot = serialized.taskList;
|
|
68924
69013
|
if (serialized.contextPrompt) {
|
|
68925
69014
|
contextPromptSnapshot = serialized.contextPrompt;
|
|
68926
69015
|
}
|
|
68927
|
-
} else {
|
|
68928
|
-
const legacyPrompt = session.messageManager?.getPendingContextPrompt();
|
|
68929
|
-
if (legacyPrompt) {
|
|
68930
|
-
contextPromptSnapshot = {
|
|
68931
|
-
postId: legacyPrompt.postId,
|
|
68932
|
-
queuedPrompt: legacyPrompt.queuedPrompt,
|
|
68933
|
-
queuedFiles: legacyPrompt.queuedFiles,
|
|
68934
|
-
threadMessageCount: legacyPrompt.threadMessageCount,
|
|
68935
|
-
createdAt: legacyPrompt.createdAt,
|
|
68936
|
-
availableOptions: legacyPrompt.availableOptions
|
|
68937
|
-
};
|
|
68938
|
-
}
|
|
68939
|
-
taskListSnapshot = session.messageManager?.getTaskListState();
|
|
68940
69016
|
}
|
|
68941
69017
|
const state = {
|
|
68942
69018
|
platformId: session.platformId,
|
|
@@ -69030,11 +69106,11 @@ class SessionManager extends EventEmitter4 {
|
|
|
69030
69106
|
}
|
|
69031
69107
|
}
|
|
69032
69108
|
if (sessionsToKill.length === 0) {
|
|
69033
|
-
|
|
69109
|
+
log30.info(`No active sessions to pause for platform ${platformId}`);
|
|
69034
69110
|
await this.updateStickyMessage();
|
|
69035
69111
|
return;
|
|
69036
69112
|
}
|
|
69037
|
-
|
|
69113
|
+
log30.info(`⏸️ Pausing ${sessionsToKill.length} session(s) for platform ${platformId}`);
|
|
69038
69114
|
for (const session of sessionsToKill) {
|
|
69039
69115
|
try {
|
|
69040
69116
|
const fmt = session.platform.getFormatter();
|
|
@@ -69050,9 +69126,9 @@ class SessionManager extends EventEmitter4 {
|
|
|
69050
69126
|
session.claude.kill();
|
|
69051
69127
|
this.registry.unregister(session.sessionId);
|
|
69052
69128
|
this.emitSessionRemove(session.sessionId);
|
|
69053
|
-
|
|
69129
|
+
log30.info(`⏸️ Paused session ${session.threadId.substring(0, 8)}`);
|
|
69054
69130
|
} catch (err) {
|
|
69055
|
-
|
|
69131
|
+
log30.warn(`Failed to pause session ${session.threadId}: ${err}`);
|
|
69056
69132
|
}
|
|
69057
69133
|
}
|
|
69058
69134
|
for (const session of sessionsToKill) {
|
|
@@ -69073,17 +69149,17 @@ class SessionManager extends EventEmitter4 {
|
|
|
69073
69149
|
sessionsToResume.push(state);
|
|
69074
69150
|
}
|
|
69075
69151
|
if (sessionsToResume.length === 0) {
|
|
69076
|
-
|
|
69152
|
+
log30.info(`No paused sessions to resume for platform ${platformId}`);
|
|
69077
69153
|
await this.updateStickyMessage();
|
|
69078
69154
|
return;
|
|
69079
69155
|
}
|
|
69080
|
-
|
|
69156
|
+
log30.info(`▶️ Resuming ${sessionsToResume.length} paused session(s) for platform ${platformId}`);
|
|
69081
69157
|
for (const state of sessionsToResume) {
|
|
69082
69158
|
try {
|
|
69083
69159
|
await resumeSession(state, this.getContext());
|
|
69084
|
-
|
|
69160
|
+
log30.info(`▶️ Resumed session ${state.threadId.substring(0, 8)}`);
|
|
69085
69161
|
} catch (err) {
|
|
69086
|
-
|
|
69162
|
+
log30.warn(`Failed to resume session ${state.threadId}: ${err}`);
|
|
69087
69163
|
}
|
|
69088
69164
|
}
|
|
69089
69165
|
await this.updateStickyMessage();
|
|
@@ -69095,14 +69171,14 @@ class SessionManager extends EventEmitter4 {
|
|
|
69095
69171
|
const sessionTimeoutMs = this.limits.sessionTimeoutMinutes * 60 * 1000;
|
|
69096
69172
|
const staleIds = this.sessionStore.cleanStale(sessionTimeoutMs * 2);
|
|
69097
69173
|
if (staleIds.length > 0) {
|
|
69098
|
-
|
|
69174
|
+
log30.info(`\uD83E\uDDF9 Soft-deleted ${staleIds.length} stale session(s) (kept for history)`);
|
|
69099
69175
|
}
|
|
69100
69176
|
const removedCount = this.sessionStore.cleanHistory();
|
|
69101
69177
|
if (removedCount > 0) {
|
|
69102
|
-
|
|
69178
|
+
log30.info(`\uD83D\uDDD1️ Permanently removed ${removedCount} old session(s) from history`);
|
|
69103
69179
|
}
|
|
69104
69180
|
const persisted = this.sessionStore.load();
|
|
69105
|
-
|
|
69181
|
+
log30.info(`\uD83D\uDCC2 Loaded ${persisted.size} session(s) from persistence`);
|
|
69106
69182
|
const excludePostIdsByPlatform = new Map;
|
|
69107
69183
|
for (const session of persisted.values()) {
|
|
69108
69184
|
const platformId = session.platformId;
|
|
@@ -69122,10 +69198,10 @@ class SessionManager extends EventEmitter4 {
|
|
|
69122
69198
|
const excludePostIds = excludePostIdsByPlatform.get(platform.platformId);
|
|
69123
69199
|
platform.getBotUser().then((botUser) => {
|
|
69124
69200
|
cleanupOldStickyMessages(platform, botUser.id, true, excludePostIds).catch((err) => {
|
|
69125
|
-
|
|
69201
|
+
log30.warn(`Failed to cleanup old sticky messages for ${platform.platformId}: ${err}`);
|
|
69126
69202
|
});
|
|
69127
69203
|
}).catch((err) => {
|
|
69128
|
-
|
|
69204
|
+
log30.warn(`Failed to get bot user for cleanup on ${platform.platformId}: ${err}`);
|
|
69129
69205
|
});
|
|
69130
69206
|
}
|
|
69131
69207
|
if (persisted.size > 0) {
|
|
@@ -69139,10 +69215,10 @@ class SessionManager extends EventEmitter4 {
|
|
|
69139
69215
|
}
|
|
69140
69216
|
}
|
|
69141
69217
|
if (pausedToSkip.length > 0) {
|
|
69142
|
-
|
|
69218
|
+
log30.info(`⏸️ ${pausedToSkip.length} session(s) remain paused (waiting for user message)`);
|
|
69143
69219
|
}
|
|
69144
69220
|
if (activeToResume.length > 0) {
|
|
69145
|
-
|
|
69221
|
+
log30.info(`\uD83D\uDD04 Attempting to resume ${activeToResume.length} active session(s)...`);
|
|
69146
69222
|
for (const state of activeToResume) {
|
|
69147
69223
|
await resumeSession(state, this.getContext());
|
|
69148
69224
|
}
|
|
@@ -69567,7 +69643,7 @@ Mention me to start a session in this worktree.`, threadId);
|
|
|
69567
69643
|
const message = messageBuilder(formatter);
|
|
69568
69644
|
await post(session, "info", message);
|
|
69569
69645
|
} catch (err) {
|
|
69570
|
-
|
|
69646
|
+
log30.warn(`Failed to broadcast to session ${session.threadId}: ${err}`);
|
|
69571
69647
|
}
|
|
69572
69648
|
}
|
|
69573
69649
|
}
|
|
@@ -69586,7 +69662,7 @@ Mention me to start a session in this worktree.`, threadId);
|
|
|
69586
69662
|
session.messageManager?.setPendingUpdatePrompt({ postId: post2.id });
|
|
69587
69663
|
this.registerPost(post2.id, session.threadId);
|
|
69588
69664
|
} catch (err) {
|
|
69589
|
-
|
|
69665
|
+
log30.warn(`Failed to post ask message to ${threadId}: ${err}`);
|
|
69590
69666
|
}
|
|
69591
69667
|
}
|
|
69592
69668
|
}
|
|
@@ -77182,29 +77258,29 @@ function SessionLog({ logs, maxLines = 20 }) {
|
|
|
77182
77258
|
return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
77183
77259
|
flexDirection: "column",
|
|
77184
77260
|
flexShrink: 0,
|
|
77185
|
-
children: displayLogs.map((
|
|
77261
|
+
children: displayLogs.map((log31) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
77186
77262
|
flexShrink: 0,
|
|
77187
77263
|
children: [
|
|
77188
77264
|
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
77189
|
-
color: getColorForLevel(
|
|
77265
|
+
color: getColorForLevel(log31.level),
|
|
77190
77266
|
dimColor: true,
|
|
77191
77267
|
wrap: "truncate",
|
|
77192
77268
|
children: [
|
|
77193
77269
|
"[",
|
|
77194
|
-
padComponent(
|
|
77270
|
+
padComponent(log31.component),
|
|
77195
77271
|
"]"
|
|
77196
77272
|
]
|
|
77197
77273
|
}, undefined, true, undefined, this),
|
|
77198
77274
|
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
77199
|
-
color: getColorForLevel(
|
|
77275
|
+
color: getColorForLevel(log31.level),
|
|
77200
77276
|
wrap: "truncate",
|
|
77201
77277
|
children: [
|
|
77202
77278
|
" ",
|
|
77203
|
-
|
|
77279
|
+
log31.message
|
|
77204
77280
|
]
|
|
77205
77281
|
}, undefined, true, undefined, this)
|
|
77206
77282
|
]
|
|
77207
|
-
},
|
|
77283
|
+
}, log31.id, true, undefined, this))
|
|
77208
77284
|
}, undefined, false, undefined, this);
|
|
77209
77285
|
}
|
|
77210
77286
|
// src/ui/components/Footer.tsx
|
|
@@ -77728,7 +77804,7 @@ function LogPanel({ logs, maxLines = 10, focused = false }) {
|
|
|
77728
77804
|
const scrollRef = import_react59.default.useRef(null);
|
|
77729
77805
|
const { stdout } = use_stdout_default();
|
|
77730
77806
|
const isDebug = process.env.DEBUG === "1";
|
|
77731
|
-
const displayLogs = logs.filter((
|
|
77807
|
+
const displayLogs = logs.filter((log31) => isDebug || log31.level !== "debug");
|
|
77732
77808
|
const visibleLogs = displayLogs.slice(-Math.max(maxLines * 3, 100));
|
|
77733
77809
|
import_react59.default.useEffect(() => {
|
|
77734
77810
|
const handleResize = () => scrollRef.current?.remeasure();
|
|
@@ -77768,25 +77844,25 @@ function LogPanel({ logs, maxLines = 10, focused = false }) {
|
|
|
77768
77844
|
overflow: "hidden",
|
|
77769
77845
|
children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(ScrollView, {
|
|
77770
77846
|
ref: scrollRef,
|
|
77771
|
-
children: visibleLogs.map((
|
|
77847
|
+
children: visibleLogs.map((log31) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
77772
77848
|
children: [
|
|
77773
77849
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
77774
77850
|
dimColor: true,
|
|
77775
77851
|
children: [
|
|
77776
77852
|
"[",
|
|
77777
|
-
padComponent2(
|
|
77853
|
+
padComponent2(log31.component),
|
|
77778
77854
|
"]"
|
|
77779
77855
|
]
|
|
77780
77856
|
}, undefined, true, undefined, this),
|
|
77781
77857
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
77782
|
-
color: getLevelColor(
|
|
77858
|
+
color: getLevelColor(log31.level),
|
|
77783
77859
|
children: [
|
|
77784
77860
|
" ",
|
|
77785
|
-
|
|
77861
|
+
log31.message
|
|
77786
77862
|
]
|
|
77787
77863
|
}, undefined, true, undefined, this)
|
|
77788
77864
|
]
|
|
77789
|
-
},
|
|
77865
|
+
}, log31.id, true, undefined, this))
|
|
77790
77866
|
}, undefined, false, undefined, this)
|
|
77791
77867
|
}, undefined, false, undefined, this);
|
|
77792
77868
|
}
|
|
@@ -78303,10 +78379,10 @@ function useAppState(initialConfig) {
|
|
|
78303
78379
|
});
|
|
78304
78380
|
}, []);
|
|
78305
78381
|
const getLogsForSession = import_react60.useCallback((sessionId) => {
|
|
78306
|
-
return state.logs.filter((
|
|
78382
|
+
return state.logs.filter((log31) => log31.sessionId === sessionId);
|
|
78307
78383
|
}, [state.logs]);
|
|
78308
78384
|
const getGlobalLogs = import_react60.useCallback(() => {
|
|
78309
|
-
return state.logs.filter((
|
|
78385
|
+
return state.logs.filter((log31) => !log31.sessionId);
|
|
78310
78386
|
}, [state.logs]);
|
|
78311
78387
|
const togglePlatformEnabled = import_react60.useCallback((platformId) => {
|
|
78312
78388
|
let newEnabled = false;
|
|
@@ -79313,7 +79389,7 @@ import { EventEmitter as EventEmitter9 } from "events";
|
|
|
79313
79389
|
// src/auto-update/checker.ts
|
|
79314
79390
|
init_logger();
|
|
79315
79391
|
import { EventEmitter as EventEmitter7 } from "events";
|
|
79316
|
-
var
|
|
79392
|
+
var log31 = createLogger("checker");
|
|
79317
79393
|
var PACKAGE_NAME = "claude-threads";
|
|
79318
79394
|
function compareVersions(a, b) {
|
|
79319
79395
|
const partsA = a.replace(/^v/, "").split(".").map(Number);
|
|
@@ -79336,13 +79412,13 @@ async function fetchLatestVersion() {
|
|
|
79336
79412
|
}
|
|
79337
79413
|
});
|
|
79338
79414
|
if (!response.ok) {
|
|
79339
|
-
|
|
79415
|
+
log31.warn(`Failed to fetch latest version: HTTP ${response.status}`);
|
|
79340
79416
|
return null;
|
|
79341
79417
|
}
|
|
79342
79418
|
const data = await response.json();
|
|
79343
79419
|
return data.version ?? null;
|
|
79344
79420
|
} catch (err) {
|
|
79345
|
-
|
|
79421
|
+
log31.warn(`Failed to fetch latest version: ${err}`);
|
|
79346
79422
|
return null;
|
|
79347
79423
|
}
|
|
79348
79424
|
}
|
|
@@ -79359,38 +79435,38 @@ class UpdateChecker extends EventEmitter7 {
|
|
|
79359
79435
|
}
|
|
79360
79436
|
start() {
|
|
79361
79437
|
if (!this.config.enabled) {
|
|
79362
|
-
|
|
79438
|
+
log31.debug("Auto-update disabled, not starting checker");
|
|
79363
79439
|
return;
|
|
79364
79440
|
}
|
|
79365
79441
|
setTimeout(() => {
|
|
79366
79442
|
this.check().catch((err) => {
|
|
79367
|
-
|
|
79443
|
+
log31.warn(`Initial update check failed: ${err}`);
|
|
79368
79444
|
});
|
|
79369
79445
|
}, 5000);
|
|
79370
79446
|
const intervalMs = this.config.checkIntervalMinutes * 60 * 1000;
|
|
79371
79447
|
this.checkInterval = setInterval(() => {
|
|
79372
79448
|
this.check().catch((err) => {
|
|
79373
|
-
|
|
79449
|
+
log31.warn(`Periodic update check failed: ${err}`);
|
|
79374
79450
|
});
|
|
79375
79451
|
}, intervalMs);
|
|
79376
|
-
|
|
79452
|
+
log31.info(`\uD83D\uDD04 Update checker started (every ${this.config.checkIntervalMinutes} minutes)`);
|
|
79377
79453
|
}
|
|
79378
79454
|
stop() {
|
|
79379
79455
|
if (this.checkInterval) {
|
|
79380
79456
|
clearInterval(this.checkInterval);
|
|
79381
79457
|
this.checkInterval = null;
|
|
79382
79458
|
}
|
|
79383
|
-
|
|
79459
|
+
log31.debug("Update checker stopped");
|
|
79384
79460
|
}
|
|
79385
79461
|
async check() {
|
|
79386
79462
|
if (this.isChecking) {
|
|
79387
|
-
|
|
79463
|
+
log31.debug("Check already in progress, skipping");
|
|
79388
79464
|
return this.lastUpdateInfo;
|
|
79389
79465
|
}
|
|
79390
79466
|
this.isChecking = true;
|
|
79391
79467
|
this.emit("check:start");
|
|
79392
79468
|
try {
|
|
79393
|
-
|
|
79469
|
+
log31.debug("Checking for updates...");
|
|
79394
79470
|
const latestVersion2 = await fetchLatestVersion();
|
|
79395
79471
|
if (!latestVersion2) {
|
|
79396
79472
|
this.emit("check:complete", false);
|
|
@@ -79407,18 +79483,18 @@ class UpdateChecker extends EventEmitter7 {
|
|
|
79407
79483
|
detectedAt: new Date
|
|
79408
79484
|
};
|
|
79409
79485
|
if (!this.lastUpdateInfo || this.lastUpdateInfo.latestVersion !== latestVersion2) {
|
|
79410
|
-
|
|
79486
|
+
log31.info(`\uD83C\uDD95 Update available: v${currentVersion} → v${latestVersion2}`);
|
|
79411
79487
|
this.lastUpdateInfo = updateInfo;
|
|
79412
79488
|
this.emit("update", updateInfo);
|
|
79413
79489
|
}
|
|
79414
79490
|
this.emit("check:complete", true);
|
|
79415
79491
|
return updateInfo;
|
|
79416
79492
|
}
|
|
79417
|
-
|
|
79493
|
+
log31.debug(`Up to date (v${currentVersion})`);
|
|
79418
79494
|
this.emit("check:complete", false);
|
|
79419
79495
|
return null;
|
|
79420
79496
|
} catch (err) {
|
|
79421
|
-
|
|
79497
|
+
log31.warn(`Update check failed: ${err}`);
|
|
79422
79498
|
this.emit("check:error", err);
|
|
79423
79499
|
return null;
|
|
79424
79500
|
} finally {
|
|
@@ -79489,7 +79565,7 @@ function isInScheduledWindow(window2) {
|
|
|
79489
79565
|
}
|
|
79490
79566
|
|
|
79491
79567
|
// src/auto-update/scheduler.ts
|
|
79492
|
-
var
|
|
79568
|
+
var log32 = createLogger("scheduler");
|
|
79493
79569
|
|
|
79494
79570
|
class UpdateScheduler extends EventEmitter8 {
|
|
79495
79571
|
config;
|
|
@@ -79513,7 +79589,7 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79513
79589
|
scheduleUpdate(updateInfo) {
|
|
79514
79590
|
this.pendingUpdate = updateInfo;
|
|
79515
79591
|
if (this.config.autoRestartMode === "immediate") {
|
|
79516
|
-
|
|
79592
|
+
log32.info("Immediate mode: triggering update now");
|
|
79517
79593
|
this.emit("ready", updateInfo);
|
|
79518
79594
|
return;
|
|
79519
79595
|
}
|
|
@@ -79526,19 +79602,19 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79526
79602
|
this.scheduledRestartAt = null;
|
|
79527
79603
|
this.askApprovals.clear();
|
|
79528
79604
|
this.askStartTime = null;
|
|
79529
|
-
|
|
79605
|
+
log32.debug("Update schedule cancelled");
|
|
79530
79606
|
}
|
|
79531
79607
|
deferUpdate(minutes) {
|
|
79532
79608
|
const deferUntil = new Date(Date.now() + minutes * 60 * 1000);
|
|
79533
79609
|
this.scheduledRestartAt = null;
|
|
79534
79610
|
this.idleStartTime = null;
|
|
79535
79611
|
this.emit("deferred", deferUntil);
|
|
79536
|
-
|
|
79612
|
+
log32.info(`Update deferred until ${deferUntil.toLocaleTimeString()}`);
|
|
79537
79613
|
return deferUntil;
|
|
79538
79614
|
}
|
|
79539
79615
|
recordAskResponse(threadId, approved) {
|
|
79540
79616
|
this.askApprovals.set(threadId, approved);
|
|
79541
|
-
|
|
79617
|
+
log32.debug(`Thread ${threadId.substring(0, 8)} ${approved ? "approved" : "denied"} update`);
|
|
79542
79618
|
this.checkAskCondition();
|
|
79543
79619
|
}
|
|
79544
79620
|
getScheduledRestartAt() {
|
|
@@ -79559,7 +79635,7 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79559
79635
|
return;
|
|
79560
79636
|
this.checkCondition();
|
|
79561
79637
|
this.checkTimer = setInterval(() => this.checkCondition(), 1e4);
|
|
79562
|
-
|
|
79638
|
+
log32.debug(`Started checking for ${this.config.autoRestartMode} condition`);
|
|
79563
79639
|
}
|
|
79564
79640
|
stopChecking() {
|
|
79565
79641
|
if (this.checkTimer) {
|
|
@@ -79590,17 +79666,17 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79590
79666
|
if (activity.activeSessionCount === 0) {
|
|
79591
79667
|
if (!this.idleStartTime) {
|
|
79592
79668
|
this.idleStartTime = new Date;
|
|
79593
|
-
|
|
79669
|
+
log32.debug("No active sessions, starting idle timer");
|
|
79594
79670
|
}
|
|
79595
79671
|
const idleMs = Date.now() - this.idleStartTime.getTime();
|
|
79596
79672
|
const requiredMs = this.config.idleTimeoutMinutes * 60 * 1000;
|
|
79597
79673
|
if (idleMs >= requiredMs) {
|
|
79598
|
-
|
|
79674
|
+
log32.info(`Idle for ${this.config.idleTimeoutMinutes} minutes, triggering update`);
|
|
79599
79675
|
this.triggerCountdown();
|
|
79600
79676
|
}
|
|
79601
79677
|
} else {
|
|
79602
79678
|
if (this.idleStartTime) {
|
|
79603
|
-
|
|
79679
|
+
log32.debug("Sessions became active, resetting idle timer");
|
|
79604
79680
|
this.idleStartTime = null;
|
|
79605
79681
|
}
|
|
79606
79682
|
}
|
|
@@ -79611,7 +79687,7 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79611
79687
|
const quietMs = Date.now() - activity.lastActivityAt.getTime();
|
|
79612
79688
|
const requiredMs = this.config.quietTimeoutMinutes * 60 * 1000;
|
|
79613
79689
|
if (quietMs >= requiredMs && !activity.anySessionBusy) {
|
|
79614
|
-
|
|
79690
|
+
log32.info(`Sessions quiet for ${this.config.quietTimeoutMinutes} minutes, triggering update`);
|
|
79615
79691
|
this.triggerCountdown();
|
|
79616
79692
|
}
|
|
79617
79693
|
} else if (activity.activeSessionCount === 0) {
|
|
@@ -79621,7 +79697,7 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79621
79697
|
const idleMs = Date.now() - this.idleStartTime.getTime();
|
|
79622
79698
|
const requiredMs = this.config.quietTimeoutMinutes * 60 * 1000;
|
|
79623
79699
|
if (idleMs >= requiredMs) {
|
|
79624
|
-
|
|
79700
|
+
log32.info("No sessions and quiet timeout reached, triggering update");
|
|
79625
79701
|
this.triggerCountdown();
|
|
79626
79702
|
}
|
|
79627
79703
|
}
|
|
@@ -79632,13 +79708,13 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79632
79708
|
}
|
|
79633
79709
|
const activity = this.getSessionActivity();
|
|
79634
79710
|
if (activity.activeSessionCount === 0) {
|
|
79635
|
-
|
|
79711
|
+
log32.info("Within scheduled window and no active sessions, triggering update");
|
|
79636
79712
|
this.triggerCountdown();
|
|
79637
79713
|
} else if (activity.lastActivityAt) {
|
|
79638
79714
|
const quietMs = Date.now() - activity.lastActivityAt.getTime();
|
|
79639
79715
|
const requiredMs = this.config.idleTimeoutMinutes * 60 * 1000;
|
|
79640
79716
|
if (quietMs >= requiredMs && !activity.anySessionBusy) {
|
|
79641
|
-
|
|
79717
|
+
log32.info("Within scheduled window and sessions quiet, triggering update");
|
|
79642
79718
|
this.triggerCountdown();
|
|
79643
79719
|
}
|
|
79644
79720
|
}
|
|
@@ -79646,14 +79722,14 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79646
79722
|
checkAskCondition() {
|
|
79647
79723
|
const threadIds = this.getActiveThreadIds();
|
|
79648
79724
|
if (threadIds.length === 0) {
|
|
79649
|
-
|
|
79725
|
+
log32.info("No active threads, proceeding with update");
|
|
79650
79726
|
this.triggerCountdown();
|
|
79651
79727
|
return;
|
|
79652
79728
|
}
|
|
79653
79729
|
if (!this.askStartTime && this.pendingUpdate) {
|
|
79654
79730
|
this.askStartTime = new Date;
|
|
79655
79731
|
this.postAskMessage(threadIds, this.pendingUpdate.latestVersion).catch((err) => {
|
|
79656
|
-
|
|
79732
|
+
log32.warn(`Failed to post ask message: ${err}`);
|
|
79657
79733
|
});
|
|
79658
79734
|
return;
|
|
79659
79735
|
}
|
|
@@ -79666,12 +79742,12 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79666
79742
|
denials++;
|
|
79667
79743
|
}
|
|
79668
79744
|
if (approvals > threadIds.length / 2) {
|
|
79669
|
-
|
|
79745
|
+
log32.info(`Majority approved (${approvals}/${threadIds.length}), triggering update`);
|
|
79670
79746
|
this.triggerCountdown();
|
|
79671
79747
|
return;
|
|
79672
79748
|
}
|
|
79673
79749
|
if (denials > threadIds.length / 2) {
|
|
79674
|
-
|
|
79750
|
+
log32.info(`Majority denied (${denials}/${threadIds.length}), deferring update`);
|
|
79675
79751
|
this.deferUpdate(60);
|
|
79676
79752
|
return;
|
|
79677
79753
|
}
|
|
@@ -79679,7 +79755,7 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79679
79755
|
const elapsedMs = Date.now() - this.askStartTime.getTime();
|
|
79680
79756
|
const timeoutMs = this.config.askTimeoutMinutes * 60 * 1000;
|
|
79681
79757
|
if (elapsedMs >= timeoutMs) {
|
|
79682
|
-
|
|
79758
|
+
log32.info(`Ask timeout reached (${this.config.askTimeoutMinutes} min), triggering update`);
|
|
79683
79759
|
this.triggerCountdown();
|
|
79684
79760
|
}
|
|
79685
79761
|
}
|
|
@@ -79699,7 +79775,7 @@ class UpdateScheduler extends EventEmitter8 {
|
|
|
79699
79775
|
this.emit("ready", this.pendingUpdate);
|
|
79700
79776
|
}
|
|
79701
79777
|
}, 1000);
|
|
79702
|
-
|
|
79778
|
+
log32.info("Update countdown started (60 seconds)");
|
|
79703
79779
|
}
|
|
79704
79780
|
stopCountdown() {
|
|
79705
79781
|
if (this.countdownTimer) {
|
|
@@ -79715,24 +79791,24 @@ import { spawn as spawn4, spawnSync } from "child_process";
|
|
|
79715
79791
|
import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync4 } from "fs";
|
|
79716
79792
|
import { dirname as dirname8, resolve as resolve6 } from "path";
|
|
79717
79793
|
import { homedir as homedir5 } from "os";
|
|
79718
|
-
var
|
|
79794
|
+
var log33 = createLogger("installer");
|
|
79719
79795
|
function detectPackageManager() {
|
|
79720
79796
|
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
79721
79797
|
const originalInstaller = detectOriginalInstaller();
|
|
79722
79798
|
if (originalInstaller) {
|
|
79723
|
-
|
|
79799
|
+
log33.debug(`Detected original installer: ${originalInstaller}`);
|
|
79724
79800
|
if (originalInstaller === "bun") {
|
|
79725
79801
|
const bunCheck2 = spawnSync("bun", ["--version"], { stdio: "ignore" });
|
|
79726
79802
|
if (bunCheck2.status === 0) {
|
|
79727
79803
|
return { cmd: "bun", isBun: true };
|
|
79728
79804
|
}
|
|
79729
|
-
|
|
79805
|
+
log33.warn("Originally installed with bun, but bun not found. Falling back to npm.");
|
|
79730
79806
|
} else {
|
|
79731
79807
|
const npmCheck2 = spawnSync(npmCmd, ["--version"], { stdio: "ignore" });
|
|
79732
79808
|
if (npmCheck2.status === 0) {
|
|
79733
79809
|
return { cmd: npmCmd, isBun: false };
|
|
79734
79810
|
}
|
|
79735
|
-
|
|
79811
|
+
log33.warn("Originally installed with npm, but npm not found. Falling back to bun.");
|
|
79736
79812
|
}
|
|
79737
79813
|
}
|
|
79738
79814
|
const bunCheck = spawnSync("bun", ["--version"], { stdio: "ignore" });
|
|
@@ -79783,7 +79859,7 @@ function loadUpdateState() {
|
|
|
79783
79859
|
return JSON.parse(content);
|
|
79784
79860
|
}
|
|
79785
79861
|
} catch (err) {
|
|
79786
|
-
|
|
79862
|
+
log33.warn(`Failed to load update state: ${err}`);
|
|
79787
79863
|
}
|
|
79788
79864
|
return {};
|
|
79789
79865
|
}
|
|
@@ -79794,9 +79870,9 @@ function saveUpdateState(state) {
|
|
|
79794
79870
|
mkdirSync4(dir, { recursive: true });
|
|
79795
79871
|
}
|
|
79796
79872
|
writeFileSync6(STATE_PATH, JSON.stringify(state, null, 2), "utf-8");
|
|
79797
|
-
|
|
79873
|
+
log33.debug("Update state saved");
|
|
79798
79874
|
} catch (err) {
|
|
79799
|
-
|
|
79875
|
+
log33.warn(`Failed to save update state: ${err}`);
|
|
79800
79876
|
}
|
|
79801
79877
|
}
|
|
79802
79878
|
function clearUpdateState() {
|
|
@@ -79805,7 +79881,7 @@ function clearUpdateState() {
|
|
|
79805
79881
|
writeFileSync6(STATE_PATH, "{}", "utf-8");
|
|
79806
79882
|
}
|
|
79807
79883
|
} catch (err) {
|
|
79808
|
-
|
|
79884
|
+
log33.warn(`Failed to clear update state: ${err}`);
|
|
79809
79885
|
}
|
|
79810
79886
|
}
|
|
79811
79887
|
function checkJustUpdated() {
|
|
@@ -79837,11 +79913,11 @@ function clearRuntimeSettings() {
|
|
|
79837
79913
|
}
|
|
79838
79914
|
}
|
|
79839
79915
|
async function installVersion(version) {
|
|
79840
|
-
|
|
79916
|
+
log33.info(`\uD83D\uDCE6 Installing ${PACKAGE_NAME2}@${version}...`);
|
|
79841
79917
|
const pm = detectPackageManager();
|
|
79842
79918
|
if (!pm) {
|
|
79843
79919
|
const error = "Neither bun nor npm found in PATH. Cannot install update.";
|
|
79844
|
-
|
|
79920
|
+
log33.error(`❌ ${error}`);
|
|
79845
79921
|
return { success: false, error };
|
|
79846
79922
|
}
|
|
79847
79923
|
saveUpdateState({
|
|
@@ -79853,7 +79929,7 @@ async function installVersion(version) {
|
|
|
79853
79929
|
return new Promise((resolve7) => {
|
|
79854
79930
|
const { cmd, isBun: isBun3 } = pm;
|
|
79855
79931
|
const args = ["install", "-g", `${PACKAGE_NAME2}@${version}`];
|
|
79856
|
-
|
|
79932
|
+
log33.debug(`Using ${isBun3 ? "bun" : "npm"} for installation`);
|
|
79857
79933
|
const child = spawn4(cmd, args, {
|
|
79858
79934
|
stdio: ["ignore", "pipe", "pipe"],
|
|
79859
79935
|
env: {
|
|
@@ -79871,7 +79947,7 @@ async function installVersion(version) {
|
|
|
79871
79947
|
});
|
|
79872
79948
|
child.on("close", (code) => {
|
|
79873
79949
|
if (code === 0) {
|
|
79874
|
-
|
|
79950
|
+
log33.info(`✅ Successfully installed ${PACKAGE_NAME2}@${version}`);
|
|
79875
79951
|
saveUpdateState({
|
|
79876
79952
|
previousVersion: VERSION,
|
|
79877
79953
|
targetVersion: version,
|
|
@@ -79881,20 +79957,20 @@ async function installVersion(version) {
|
|
|
79881
79957
|
resolve7({ success: true });
|
|
79882
79958
|
} else {
|
|
79883
79959
|
const errorMsg = stderr || stdout || `Exit code: ${code}`;
|
|
79884
|
-
|
|
79960
|
+
log33.error(`❌ Installation failed: ${errorMsg}`);
|
|
79885
79961
|
clearUpdateState();
|
|
79886
79962
|
resolve7({ success: false, error: errorMsg });
|
|
79887
79963
|
}
|
|
79888
79964
|
});
|
|
79889
79965
|
child.on("error", (err) => {
|
|
79890
|
-
|
|
79966
|
+
log33.error(`❌ Failed to spawn npm: ${err}`);
|
|
79891
79967
|
clearUpdateState();
|
|
79892
79968
|
resolve7({ success: false, error: err.message });
|
|
79893
79969
|
});
|
|
79894
79970
|
setTimeout(() => {
|
|
79895
79971
|
if (child.exitCode === null) {
|
|
79896
79972
|
child.kill();
|
|
79897
|
-
|
|
79973
|
+
log33.error("❌ Installation timed out");
|
|
79898
79974
|
clearUpdateState();
|
|
79899
79975
|
resolve7({ success: false, error: "Installation timed out" });
|
|
79900
79976
|
}
|
|
@@ -79936,7 +80012,7 @@ class UpdateInstaller {
|
|
|
79936
80012
|
}
|
|
79937
80013
|
|
|
79938
80014
|
// src/auto-update/manager.ts
|
|
79939
|
-
var
|
|
80015
|
+
var log34 = createLogger("updater");
|
|
79940
80016
|
|
|
79941
80017
|
class AutoUpdateManager extends EventEmitter9 {
|
|
79942
80018
|
config;
|
|
@@ -79959,23 +80035,23 @@ class AutoUpdateManager extends EventEmitter9 {
|
|
|
79959
80035
|
}
|
|
79960
80036
|
start() {
|
|
79961
80037
|
if (!this.config.enabled) {
|
|
79962
|
-
|
|
80038
|
+
log34.info("Auto-update is disabled");
|
|
79963
80039
|
return;
|
|
79964
80040
|
}
|
|
79965
80041
|
const updateResult = this.installer.checkJustUpdated();
|
|
79966
80042
|
if (updateResult) {
|
|
79967
|
-
|
|
80043
|
+
log34.info(`\uD83C\uDF89 Updated from v${updateResult.previousVersion} to v${updateResult.currentVersion}`);
|
|
79968
80044
|
this.callbacks.broadcastUpdate((fmt) => `\uD83C\uDF89 ${fmt.formatBold("Bot updated")} from v${updateResult.previousVersion} to v${updateResult.currentVersion}`).catch((err) => {
|
|
79969
|
-
|
|
80045
|
+
log34.warn(`Failed to broadcast update notification: ${err}`);
|
|
79970
80046
|
});
|
|
79971
80047
|
}
|
|
79972
80048
|
this.checker.start();
|
|
79973
|
-
|
|
80049
|
+
log34.info(`\uD83D\uDD04 Auto-update manager started (mode: ${this.config.autoRestartMode})`);
|
|
79974
80050
|
}
|
|
79975
80051
|
stop() {
|
|
79976
80052
|
this.checker.stop();
|
|
79977
80053
|
this.scheduler.stop();
|
|
79978
|
-
|
|
80054
|
+
log34.debug("Auto-update manager stopped");
|
|
79979
80055
|
}
|
|
79980
80056
|
getState() {
|
|
79981
80057
|
return { ...this.state };
|
|
@@ -79989,10 +80065,10 @@ class AutoUpdateManager extends EventEmitter9 {
|
|
|
79989
80065
|
async forceUpdate() {
|
|
79990
80066
|
const updateInfo = this.state.updateInfo || await this.checker.check();
|
|
79991
80067
|
if (!updateInfo) {
|
|
79992
|
-
|
|
80068
|
+
log34.info("No update available");
|
|
79993
80069
|
return;
|
|
79994
80070
|
}
|
|
79995
|
-
|
|
80071
|
+
log34.info("Forcing immediate update");
|
|
79996
80072
|
await this.performUpdate(updateInfo);
|
|
79997
80073
|
}
|
|
79998
80074
|
deferUpdate(minutes = 60) {
|
|
@@ -80047,7 +80123,7 @@ class AutoUpdateManager extends EventEmitter9 {
|
|
|
80047
80123
|
await this.callbacks.broadcastUpdate((fmt) => `✅ ${fmt.formatBold("Update installed")} - restarting now. ${fmt.formatItalic("Sessions will resume automatically.")}`).catch(() => {});
|
|
80048
80124
|
await new Promise((resolve7) => setTimeout(resolve7, 1000));
|
|
80049
80125
|
await this.callbacks.prepareForRestart();
|
|
80050
|
-
|
|
80126
|
+
log34.info(`\uD83D\uDD04 Restarting for update to v${updateInfo.latestVersion}`);
|
|
80051
80127
|
process.stdout.write("\x1B[2J\x1B[H");
|
|
80052
80128
|
process.stdout.write("\x1B[?25h");
|
|
80053
80129
|
process.exit(RESTART_EXIT_CODE);
|
|
@@ -80104,7 +80180,8 @@ function wirePlatformEvents(platformId, client, session, ui) {
|
|
|
80104
80180
|
ui.setPlatformStatus(platformId, { reconnecting: true, reconnectAttempts: attempt });
|
|
80105
80181
|
});
|
|
80106
80182
|
client.on("error", (e) => {
|
|
80107
|
-
|
|
80183
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
80184
|
+
ui.addLog({ level: "error", component: platformId, message });
|
|
80108
80185
|
});
|
|
80109
80186
|
}
|
|
80110
80187
|
program.name("claude-threads").version(VERSION).description("Share Claude Code sessions in Mattermost").option("--url <url>", "Mattermost server URL").option("--token <token>", "Mattermost bot token").option("--channel <id>", "Mattermost channel ID").option("--bot-name <name>", "Bot mention name (default: claude-code)").option("--allowed-users <users>", "Comma-separated allowed usernames").option("--permission-mode <mode>", "Permission mode: default | auto | bypass (default: from config)").option("--skip-permissions", "[deprecated] Alias for --permission-mode bypass").option("--no-skip-permissions", "[deprecated] Alias for --permission-mode default").option("--chrome", "Enable Claude in Chrome integration").option("--no-chrome", "Disable Claude in Chrome integration").option("--worktree-mode <mode>", "Git worktree mode: off, prompt, require (default: prompt)").option("--keep-alive", "Enable system sleep prevention (default: enabled)").option("--no-keep-alive", "Disable system sleep prevention").option("--setup", "Run interactive setup wizard (reconfigure existing settings)").option("--debug", "Enable debug logging").option("--skip-version-check", "Skip Claude CLI version compatibility check").option("--auto-restart", "Enable auto-restart on updates (default when autoUpdate enabled)").option("--no-auto-restart", "Disable auto-restart on updates").option("--headless", "Run without interactive UI (logs to stdout)").parse();
|