claude-threads 0.33.7 → 0.33.9
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 +7 -0
- package/dist/index.js +51 -18
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.33.8] - 2026-01-04
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Session resume broken after v0.33.7** - Fixed migration issue where sessions persisted with the old `timeoutPostId` field name couldn't be resumed after upgrading to v0.33.7. The `timeoutPostId` → `lifecyclePostId` rename now includes a proper migration that converts existing sessions on first load.
|
|
14
|
+
- **Defensive defaults for persisted session fields** - Session resume now uses safe defaults for all optional fields, preventing crashes when loading sessions from older versions that may have missing fields. Fields like `sessionAllowedUsers`, `planApproved`, `forceInteractivePermissions`, etc. now gracefully default instead of potentially causing undefined errors.
|
|
15
|
+
- **Validate required fields before resume** - Sessions with missing critical fields (`threadId`, `platformId`, `claudeSessionId`, `workingDir`) are now skipped gracefully with a warning instead of crashing.
|
|
16
|
+
|
|
10
17
|
## [0.33.7] - 2026-01-04
|
|
11
18
|
|
|
12
19
|
### Changed
|
package/dist/index.js
CHANGED
|
@@ -13792,6 +13792,20 @@ class SessionStore {
|
|
|
13792
13792
|
log3.warn(`Sessions file version ${data.version} not supported, starting fresh`);
|
|
13793
13793
|
return sessions;
|
|
13794
13794
|
}
|
|
13795
|
+
let needsSave = false;
|
|
13796
|
+
for (const session of Object.values(data.sessions)) {
|
|
13797
|
+
const legacySession = session;
|
|
13798
|
+
if (legacySession.timeoutPostId && !session.lifecyclePostId) {
|
|
13799
|
+
session.lifecyclePostId = legacySession.timeoutPostId;
|
|
13800
|
+
delete legacySession.timeoutPostId;
|
|
13801
|
+
needsSave = true;
|
|
13802
|
+
log3.debug(`Migrated timeoutPostId to lifecyclePostId for session ${session.threadId.substring(0, 8)}...`);
|
|
13803
|
+
}
|
|
13804
|
+
}
|
|
13805
|
+
if (needsSave) {
|
|
13806
|
+
log3.info("Migrated session(s) from timeoutPostId to lifecyclePostId");
|
|
13807
|
+
this.writeAtomic(data);
|
|
13808
|
+
}
|
|
13795
13809
|
for (const session of Object.values(data.sessions)) {
|
|
13796
13810
|
if (session.cleanedAt)
|
|
13797
13811
|
continue;
|
|
@@ -13877,7 +13891,9 @@ class SessionStore {
|
|
|
13877
13891
|
historySessions.push(session);
|
|
13878
13892
|
continue;
|
|
13879
13893
|
}
|
|
13880
|
-
|
|
13894
|
+
const legacySession = session;
|
|
13895
|
+
const hasLifecyclePost = session.lifecyclePostId || legacySession.timeoutPostId;
|
|
13896
|
+
if (hasLifecyclePost && activeSessions && !activeSessions.has(sessionId)) {
|
|
13881
13897
|
historySessions.push(session);
|
|
13882
13898
|
}
|
|
13883
13899
|
}
|
|
@@ -13923,7 +13939,12 @@ class SessionStore {
|
|
|
13923
13939
|
for (const session of Object.values(data.sessions)) {
|
|
13924
13940
|
if (session.platformId !== platformId)
|
|
13925
13941
|
continue;
|
|
13926
|
-
|
|
13942
|
+
const legacySession = session;
|
|
13943
|
+
const lifecycleId = session.lifecyclePostId || legacySession.timeoutPostId;
|
|
13944
|
+
if (lifecycleId === postId || session.sessionStartPostId === postId) {
|
|
13945
|
+
if (legacySession.timeoutPostId && !session.lifecyclePostId) {
|
|
13946
|
+
session.lifecyclePostId = legacySession.timeoutPostId;
|
|
13947
|
+
}
|
|
13927
13948
|
return session;
|
|
13928
13949
|
}
|
|
13929
13950
|
}
|
|
@@ -20687,6 +20708,16 @@ async function startSession(options, username, displayName, replyToPostId, platf
|
|
|
20687
20708
|
claude.sendMessage(content);
|
|
20688
20709
|
}
|
|
20689
20710
|
async function resumeSession(state, ctx) {
|
|
20711
|
+
if (!state.threadId || !state.platformId || !state.claudeSessionId || !state.workingDir) {
|
|
20712
|
+
const missing = [
|
|
20713
|
+
!state.threadId && "threadId",
|
|
20714
|
+
!state.platformId && "platformId",
|
|
20715
|
+
!state.claudeSessionId && "claudeSessionId",
|
|
20716
|
+
!state.workingDir && "workingDir"
|
|
20717
|
+
].filter(Boolean).join(", ");
|
|
20718
|
+
log10.warn(`Skipping session with missing required fields: ${missing}`);
|
|
20719
|
+
return;
|
|
20720
|
+
}
|
|
20690
20721
|
const shortId = state.threadId.substring(0, 8);
|
|
20691
20722
|
const platforms = ctx.state.platforms;
|
|
20692
20723
|
const platform = platforms.get(state.platformId);
|
|
@@ -20735,11 +20766,11 @@ Please start a new session.`, state.threadId), { action: "Post resume failure no
|
|
|
20735
20766
|
sessionId,
|
|
20736
20767
|
platform,
|
|
20737
20768
|
claudeSessionId: state.claudeSessionId,
|
|
20738
|
-
startedBy: state.startedBy,
|
|
20769
|
+
startedBy: state.startedBy || "unknown",
|
|
20739
20770
|
startedByDisplayName: state.startedByDisplayName,
|
|
20740
|
-
startedAt: new Date(state.startedAt),
|
|
20771
|
+
startedAt: state.startedAt ? new Date(state.startedAt) : new Date,
|
|
20741
20772
|
lastActivityAt: new Date,
|
|
20742
|
-
sessionNumber: state.sessionNumber,
|
|
20773
|
+
sessionNumber: state.sessionNumber ?? 1,
|
|
20743
20774
|
workingDir: state.workingDir,
|
|
20744
20775
|
claude,
|
|
20745
20776
|
currentPostId: null,
|
|
@@ -20747,11 +20778,11 @@ Please start a new session.`, state.threadId), { action: "Post resume failure no
|
|
|
20747
20778
|
pendingApproval: null,
|
|
20748
20779
|
pendingQuestionSet: null,
|
|
20749
20780
|
pendingMessageApproval: null,
|
|
20750
|
-
planApproved: state.planApproved,
|
|
20751
|
-
sessionAllowedUsers: new Set(state.sessionAllowedUsers),
|
|
20752
|
-
forceInteractivePermissions: state.forceInteractivePermissions,
|
|
20753
|
-
sessionStartPostId: state.sessionStartPostId,
|
|
20754
|
-
tasksPostId: state.tasksPostId,
|
|
20781
|
+
planApproved: state.planApproved ?? false,
|
|
20782
|
+
sessionAllowedUsers: new Set(state.sessionAllowedUsers || [state.startedBy].filter(Boolean)),
|
|
20783
|
+
forceInteractivePermissions: state.forceInteractivePermissions ?? false,
|
|
20784
|
+
sessionStartPostId: state.sessionStartPostId ?? null,
|
|
20785
|
+
tasksPostId: state.tasksPostId ?? null,
|
|
20755
20786
|
lastTasksContent: state.lastTasksContent ?? null,
|
|
20756
20787
|
tasksCompleted: state.tasksCompleted ?? false,
|
|
20757
20788
|
tasksMinimized: state.tasksMinimized ?? false,
|
|
@@ -20761,7 +20792,7 @@ Please start a new session.`, state.threadId), { action: "Post resume failure no
|
|
|
20761
20792
|
timeoutWarningPosted: false,
|
|
20762
20793
|
isRestarting: false,
|
|
20763
20794
|
isResumed: true,
|
|
20764
|
-
resumeFailCount: state.resumeFailCount
|
|
20795
|
+
resumeFailCount: state.resumeFailCount ?? 0,
|
|
20765
20796
|
wasInterrupted: false,
|
|
20766
20797
|
hasClaudeResponded: true,
|
|
20767
20798
|
inProgressTaskStart: null,
|
|
@@ -20776,6 +20807,7 @@ Please start a new session.`, state.threadId), { action: "Post resume failure no
|
|
|
20776
20807
|
sessionDescription: state.sessionDescription,
|
|
20777
20808
|
pullRequestUrl: state.pullRequestUrl,
|
|
20778
20809
|
messageCount: state.messageCount ?? 0,
|
|
20810
|
+
lifecyclePostId: state.lifecyclePostId,
|
|
20779
20811
|
statusBarTimer: null
|
|
20780
20812
|
};
|
|
20781
20813
|
mutableSessions(ctx).set(sessionId, session);
|
|
@@ -20791,8 +20823,8 @@ Please start a new session.`, state.threadId), { action: "Post resume failure no
|
|
|
20791
20823
|
try {
|
|
20792
20824
|
claude.start();
|
|
20793
20825
|
log10.info(`Resumed session ${shortId}... (@${state.startedBy})`);
|
|
20794
|
-
if (
|
|
20795
|
-
await withErrorHandling(() => session.platform.updatePost(
|
|
20826
|
+
if (session.lifecyclePostId) {
|
|
20827
|
+
await withErrorHandling(() => session.platform.updatePost(session.lifecyclePostId, `\uD83D\uDD04 **Session resumed** by @${session.startedBy}
|
|
20796
20828
|
*Reconnected to Claude session. You can continue where you left off.*`), { action: "Update timeout/shutdown post for resume", session });
|
|
20797
20829
|
session.lifecyclePostId = undefined;
|
|
20798
20830
|
} else {
|
|
@@ -21581,8 +21613,9 @@ function formatHistoryEntry(session) {
|
|
|
21581
21613
|
const topic = getHistorySessionTopic(session);
|
|
21582
21614
|
const threadLink = `[${topic}](/_redirect/pl/${session.threadId})`;
|
|
21583
21615
|
const displayName = session.startedByDisplayName || session.startedBy;
|
|
21584
|
-
const
|
|
21585
|
-
const
|
|
21616
|
+
const legacySession = session;
|
|
21617
|
+
const isTimedOut = !session.cleanedAt && (session.lifecyclePostId || legacySession.timeoutPostId);
|
|
21618
|
+
const lastActivity = session.lastActivityAt ? new Date(session.lastActivityAt) : new Date;
|
|
21586
21619
|
const time = formatRelativeTimeShort(lastActivity);
|
|
21587
21620
|
const prStr = session.pullRequestUrl ? ` \xB7 ${formatPullRequestLink(session.pullRequestUrl)}` : "";
|
|
21588
21621
|
const indicator = isTimedOut ? "\u23F8\uFE0F" : "\u2713";
|
|
@@ -21969,7 +22002,7 @@ class SessionManager {
|
|
|
21969
22002
|
}
|
|
21970
22003
|
return false;
|
|
21971
22004
|
}
|
|
21972
|
-
const allowedUsers = new Set(persistedSession.sessionAllowedUsers);
|
|
22005
|
+
const allowedUsers = new Set(persistedSession.sessionAllowedUsers || []);
|
|
21973
22006
|
const platform = this.platforms.get(platformId);
|
|
21974
22007
|
if (!allowedUsers.has(username) && !platform?.isUserAllowed(username)) {
|
|
21975
22008
|
if (platform) {
|
|
@@ -22380,7 +22413,7 @@ class SessionManager {
|
|
|
22380
22413
|
if (!session) {
|
|
22381
22414
|
const persisted = this.getPersistedSession(threadId);
|
|
22382
22415
|
if (persisted) {
|
|
22383
|
-
return persisted.sessionAllowedUsers.includes(username) || this.platforms.get(persisted.platformId)?.isUserAllowed(username) || false;
|
|
22416
|
+
return (persisted.sessionAllowedUsers || []).includes(username) || this.platforms.get(persisted.platformId)?.isUserAllowed(username) || false;
|
|
22384
22417
|
}
|
|
22385
22418
|
return false;
|
|
22386
22419
|
}
|
|
@@ -22672,7 +22705,7 @@ Release notes not available. See [GitHub releases](https://github.com/anneschuth
|
|
|
22672
22705
|
const content = mattermost.isBotMentioned(message) ? mattermost.extractPrompt(message) : message.trim();
|
|
22673
22706
|
const persistedSession = session.getPersistedSession(threadRoot);
|
|
22674
22707
|
if (persistedSession) {
|
|
22675
|
-
const allowedUsers = new Set(persistedSession.sessionAllowedUsers);
|
|
22708
|
+
const allowedUsers = new Set(persistedSession.sessionAllowedUsers || []);
|
|
22676
22709
|
if (!allowedUsers.has(username) && !mattermost.isUserAllowed(username)) {
|
|
22677
22710
|
await mattermost.createPost(`\u26A0\uFE0F @${username} is not authorized to resume this session`, threadRoot);
|
|
22678
22711
|
return;
|