claude-threads 0.33.1 → 0.33.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 +16 -0
- package/dist/index.js +47 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.33.3] - 2026-01-04
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Graceful shutdown sends two SIGINTs** - Claude CLI requires two Ctrl+C presses to exit in interactive mode. Updated kill() to send two SIGINTs (100ms apart) before falling back to SIGTERM after 2 seconds.
|
|
14
|
+
|
|
15
|
+
## [0.33.2] - 2026-01-04
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **Session resume "No conversation found" errors** - Fixed issue where cancelled sessions would fail to resume with "No conversation found with session ID" error. Root cause: sessions were persisted before Claude had a chance to save the conversation.
|
|
19
|
+
- **Graceful session termination** - When killing a session (cancel, !stop, etc.), Claude now gets 2 seconds to save the conversation (SIGINT then SIGTERM) instead of being killed immediately.
|
|
20
|
+
- **Detect invalid session IDs immediately** - Sessions with "No conversation found" errors are now recognized as permanent failures and removed from persistence immediately, instead of retrying 3 times.
|
|
21
|
+
- **User notification for early exits** - When a session ends before Claude responds, the user is now notified: "Session ended before Claude could respond. Please start a new session."
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- **Delayed session persistence** - Sessions are only persisted after Claude has actually responded (first `assistant` or `tool_use` event), preventing dangling session records that can't be resumed.
|
|
25
|
+
|
|
10
26
|
## [0.33.1] - 2026-01-04
|
|
11
27
|
|
|
12
28
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -15282,6 +15282,10 @@ function extractAndUpdatePullRequest(text, session, ctx) {
|
|
|
15282
15282
|
function handleEvent(session, event, ctx) {
|
|
15283
15283
|
session.lastActivityAt = new Date;
|
|
15284
15284
|
session.timeoutWarningPosted = false;
|
|
15285
|
+
if (!session.hasClaudeResponded && (event.type === "assistant" || event.type === "tool_use")) {
|
|
15286
|
+
session.hasClaudeResponded = true;
|
|
15287
|
+
ctx.ops.persistSession(session);
|
|
15288
|
+
}
|
|
15285
15289
|
if (event.type === "assistant") {
|
|
15286
15290
|
const msg = event.message;
|
|
15287
15291
|
let hasSpecialTool = false;
|
|
@@ -16084,6 +16088,9 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
16084
16088
|
if (stderr.includes("claude-mcp-browser-bridge") && (stderr.includes("EOPNOTSUPP") || stderr.includes("ENOENT"))) {
|
|
16085
16089
|
return true;
|
|
16086
16090
|
}
|
|
16091
|
+
if (stderr.includes("No conversation found with session ID")) {
|
|
16092
|
+
return true;
|
|
16093
|
+
}
|
|
16087
16094
|
return false;
|
|
16088
16095
|
}
|
|
16089
16096
|
getPermanentFailureReason() {
|
|
@@ -16091,12 +16098,32 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
16091
16098
|
if (stderr.includes("claude-mcp-browser-bridge") && (stderr.includes("EOPNOTSUPP") || stderr.includes("ENOENT"))) {
|
|
16092
16099
|
return "Claude browser bridge state from a previous session is no longer accessible. This typically happens when a session with Chrome integration is resumed after a restart.";
|
|
16093
16100
|
}
|
|
16101
|
+
if (stderr.includes("No conversation found with session ID")) {
|
|
16102
|
+
return "The conversation history for this session no longer exists. This can happen if Claude's history was cleared or if the session was created on a different machine.";
|
|
16103
|
+
}
|
|
16094
16104
|
return null;
|
|
16095
16105
|
}
|
|
16096
16106
|
kill() {
|
|
16097
16107
|
this.stopStatusWatch();
|
|
16098
|
-
this.process
|
|
16108
|
+
if (!this.process)
|
|
16109
|
+
return;
|
|
16110
|
+
const proc = this.process;
|
|
16099
16111
|
this.process = null;
|
|
16112
|
+
proc.kill("SIGINT");
|
|
16113
|
+
const secondSigint = setTimeout(() => {
|
|
16114
|
+
try {
|
|
16115
|
+
proc.kill("SIGINT");
|
|
16116
|
+
} catch {}
|
|
16117
|
+
}, 100);
|
|
16118
|
+
const forceKillTimeout = setTimeout(() => {
|
|
16119
|
+
try {
|
|
16120
|
+
proc.kill("SIGTERM");
|
|
16121
|
+
} catch {}
|
|
16122
|
+
}, 2000);
|
|
16123
|
+
proc.once("exit", () => {
|
|
16124
|
+
clearTimeout(secondSigint);
|
|
16125
|
+
clearTimeout(forceKillTimeout);
|
|
16126
|
+
});
|
|
16100
16127
|
}
|
|
16101
16128
|
interrupt() {
|
|
16102
16129
|
if (!this.process)
|
|
@@ -20578,6 +20605,7 @@ async function startSession(options, username, displayName, replyToPostId, platf
|
|
|
20578
20605
|
isResumed: false,
|
|
20579
20606
|
resumeFailCount: 0,
|
|
20580
20607
|
wasInterrupted: false,
|
|
20608
|
+
hasClaudeResponded: false,
|
|
20581
20609
|
inProgressTaskStart: null,
|
|
20582
20610
|
activeToolStarts: new Map,
|
|
20583
20611
|
firstPrompt: options.prompt,
|
|
@@ -20621,7 +20649,6 @@ async function startSession(options, username, displayName, replyToPostId, platf
|
|
|
20621
20649
|
}
|
|
20622
20650
|
session.messageCount++;
|
|
20623
20651
|
claude.sendMessage(content);
|
|
20624
|
-
ctx.ops.persistSession(session);
|
|
20625
20652
|
}
|
|
20626
20653
|
async function resumeSession(state, ctx) {
|
|
20627
20654
|
const shortId = state.threadId.substring(0, 8);
|
|
@@ -20700,6 +20727,7 @@ Please start a new session.`, state.threadId), { action: "Post resume failure no
|
|
|
20700
20727
|
isResumed: true,
|
|
20701
20728
|
resumeFailCount: state.resumeFailCount || 0,
|
|
20702
20729
|
wasInterrupted: false,
|
|
20730
|
+
hasClaudeResponded: true,
|
|
20703
20731
|
inProgressTaskStart: null,
|
|
20704
20732
|
activeToolStarts: new Map,
|
|
20705
20733
|
worktreeInfo: state.worktreeInfo,
|
|
@@ -20808,15 +20836,30 @@ async function handleExit(sessionId, code, ctx) {
|
|
|
20808
20836
|
log10.debug(`Session ${shortId}... exited after interrupt, preserving for resume`);
|
|
20809
20837
|
ctx.ops.stopTyping(session);
|
|
20810
20838
|
cleanupSessionTimers(session);
|
|
20811
|
-
|
|
20839
|
+
if (session.hasClaudeResponded) {
|
|
20840
|
+
ctx.ops.persistSession(session);
|
|
20841
|
+
}
|
|
20812
20842
|
mutableSessions(ctx).delete(session.sessionId);
|
|
20813
20843
|
cleanupPostIndex(ctx, session.threadId);
|
|
20814
20844
|
keepAlive.sessionEnded();
|
|
20815
|
-
|
|
20845
|
+
const message = session.hasClaudeResponded ? `\u2139\uFE0F Session paused. Send a new message to continue.` : `\u2139\uFE0F Session ended before Claude could respond. Send a new message to start fresh.`;
|
|
20846
|
+
await withErrorHandling(() => postInfo(session, message), { action: "Post session pause notification", session });
|
|
20816
20847
|
log10.info(`Session paused (${shortId}\u2026) \u2014 ${ctx.state.sessions.size} active`);
|
|
20817
20848
|
await ctx.ops.updateStickyMessage();
|
|
20818
20849
|
return;
|
|
20819
20850
|
}
|
|
20851
|
+
if (!session.hasClaudeResponded && !session.isResumed) {
|
|
20852
|
+
log10.debug(`Session ${shortId}... exited before Claude responded, not persisting`);
|
|
20853
|
+
ctx.ops.stopTyping(session);
|
|
20854
|
+
cleanupSessionTimers(session);
|
|
20855
|
+
mutableSessions(ctx).delete(session.sessionId);
|
|
20856
|
+
cleanupPostIndex(ctx, session.threadId);
|
|
20857
|
+
keepAlive.sessionEnded();
|
|
20858
|
+
await withErrorHandling(() => postWarning(session, `**Session ended** before Claude could respond (exit code ${code}). Please start a new session.`), { action: "Post early exit notification", session });
|
|
20859
|
+
log10.info(`Session ended early (${shortId}\u2026) \u2014 ${ctx.state.sessions.size} active`);
|
|
20860
|
+
await ctx.ops.updateStickyMessage();
|
|
20861
|
+
return;
|
|
20862
|
+
}
|
|
20820
20863
|
if (session.isResumed && code !== 0) {
|
|
20821
20864
|
const MAX_RESUME_FAILURES = 3;
|
|
20822
20865
|
session.resumeFailCount = (session.resumeFailCount || 0) + 1;
|