claude-threads 1.0.2 → 1.0.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 +6 -0
- package/dist/index.js +120 -56
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.3] - 2026-01-13
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **WebSocket reconnection after long idle** - Improved reconnection reliability with forceful cleanup of stale connections, automatic retry on failure, and more compact UI (#206)
|
|
12
|
+
- **Metadata suggestion retry logic** - Added retry logic for title/description/tags fetching on session start with up to 2 retries (#207)
|
|
13
|
+
|
|
8
14
|
## [1.0.2] - 2026-01-13
|
|
9
15
|
|
|
10
16
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -47158,19 +47158,36 @@ class MattermostClient extends EventEmitter {
|
|
|
47158
47158
|
}
|
|
47159
47159
|
}
|
|
47160
47160
|
}
|
|
47161
|
+
cleanupWebSocket() {
|
|
47162
|
+
this.stopHeartbeat();
|
|
47163
|
+
if (this.ws) {
|
|
47164
|
+
this.ws.onopen = null;
|
|
47165
|
+
this.ws.onmessage = null;
|
|
47166
|
+
this.ws.onclose = null;
|
|
47167
|
+
this.ws.onerror = null;
|
|
47168
|
+
if (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING) {
|
|
47169
|
+
try {
|
|
47170
|
+
this.ws.close();
|
|
47171
|
+
} catch {}
|
|
47172
|
+
}
|
|
47173
|
+
this.ws = null;
|
|
47174
|
+
}
|
|
47175
|
+
}
|
|
47161
47176
|
scheduleReconnect() {
|
|
47162
47177
|
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
47163
47178
|
log.error("Max reconnection attempts reached");
|
|
47164
47179
|
return;
|
|
47165
47180
|
}
|
|
47181
|
+
this.cleanupWebSocket();
|
|
47166
47182
|
this.isReconnecting = true;
|
|
47167
47183
|
this.reconnectAttempts++;
|
|
47168
47184
|
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
|
|
47169
|
-
|
|
47185
|
+
wsLogger.info(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
|
|
47170
47186
|
this.emit("reconnecting", this.reconnectAttempts);
|
|
47171
47187
|
setTimeout(() => {
|
|
47172
47188
|
this.connect().catch((err) => {
|
|
47173
|
-
|
|
47189
|
+
wsLogger.error(`Reconnection failed: ${err}`);
|
|
47190
|
+
this.scheduleReconnect();
|
|
47174
47191
|
});
|
|
47175
47192
|
}, delay);
|
|
47176
47193
|
}
|
|
@@ -47689,6 +47706,21 @@ class SlackClient extends EventEmitter2 {
|
|
|
47689
47706
|
});
|
|
47690
47707
|
}
|
|
47691
47708
|
}
|
|
47709
|
+
cleanupWebSocket() {
|
|
47710
|
+
this.stopHeartbeat();
|
|
47711
|
+
if (this.ws) {
|
|
47712
|
+
this.ws.onopen = null;
|
|
47713
|
+
this.ws.onmessage = null;
|
|
47714
|
+
this.ws.onclose = null;
|
|
47715
|
+
this.ws.onerror = null;
|
|
47716
|
+
if (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING) {
|
|
47717
|
+
try {
|
|
47718
|
+
this.ws.close();
|
|
47719
|
+
} catch {}
|
|
47720
|
+
}
|
|
47721
|
+
this.ws = null;
|
|
47722
|
+
}
|
|
47723
|
+
}
|
|
47692
47724
|
scheduleReconnect() {
|
|
47693
47725
|
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
47694
47726
|
log2.error("Max reconnection attempts reached");
|
|
@@ -47698,10 +47730,11 @@ class SlackClient extends EventEmitter2 {
|
|
|
47698
47730
|
clearTimeout(this.reconnectTimeout);
|
|
47699
47731
|
this.reconnectTimeout = null;
|
|
47700
47732
|
}
|
|
47733
|
+
this.cleanupWebSocket();
|
|
47701
47734
|
this.isReconnecting = true;
|
|
47702
47735
|
this.reconnectAttempts++;
|
|
47703
47736
|
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
|
|
47704
|
-
|
|
47737
|
+
wsLogger.info(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
|
|
47705
47738
|
this.emit("reconnecting", this.reconnectAttempts);
|
|
47706
47739
|
this.reconnectTimeout = setTimeout(() => {
|
|
47707
47740
|
this.reconnectTimeout = null;
|
|
@@ -47710,7 +47743,8 @@ class SlackClient extends EventEmitter2 {
|
|
|
47710
47743
|
return;
|
|
47711
47744
|
}
|
|
47712
47745
|
this.connect().catch((err) => {
|
|
47713
|
-
|
|
47746
|
+
wsLogger.error(`Reconnection failed: ${err}`);
|
|
47747
|
+
this.scheduleReconnect();
|
|
47714
47748
|
});
|
|
47715
47749
|
}, delay);
|
|
47716
47750
|
}
|
|
@@ -60971,35 +61005,76 @@ function createMessageManager(session, ctx) {
|
|
|
60971
61005
|
});
|
|
60972
61006
|
return messageManager;
|
|
60973
61007
|
}
|
|
61008
|
+
var METADATA_RETRY_DELAY_MS = 2000;
|
|
61009
|
+
var METADATA_MAX_RETRIES = 2;
|
|
61010
|
+
async function attemptMetadataFetch(session, prompt, ctx, attempt = 1, options = {}) {
|
|
61011
|
+
const sessionId = session.sessionId;
|
|
61012
|
+
const suggestMetadataFn = options.suggestMetadata ?? suggestSessionMetadata;
|
|
61013
|
+
const suggestTagsFn = options.suggestTags ?? suggestSessionTags;
|
|
61014
|
+
const [metadata, tags] = await Promise.all([
|
|
61015
|
+
suggestMetadataFn(prompt),
|
|
61016
|
+
suggestTagsFn(prompt)
|
|
61017
|
+
]);
|
|
61018
|
+
const currentSession = ctx.state.sessions.get(sessionId);
|
|
61019
|
+
if (!currentSession) {
|
|
61020
|
+
sessionLog6(session).debug("Session gone before metadata suggestions completed");
|
|
61021
|
+
return { success: false, metadataSet: false, tagsSet: false };
|
|
61022
|
+
}
|
|
61023
|
+
let metadataSet = false;
|
|
61024
|
+
let tagsSet = false;
|
|
61025
|
+
let updated = false;
|
|
61026
|
+
if (metadata && !currentSession.sessionTitle) {
|
|
61027
|
+
currentSession.sessionTitle = metadata.title;
|
|
61028
|
+
currentSession.sessionDescription = metadata.description;
|
|
61029
|
+
sessionLog6(currentSession).debug(`Set title: "${metadata.title}" (attempt ${attempt})`);
|
|
61030
|
+
metadataSet = true;
|
|
61031
|
+
updated = true;
|
|
61032
|
+
} else if (currentSession.sessionTitle) {
|
|
61033
|
+
metadataSet = true;
|
|
61034
|
+
}
|
|
61035
|
+
if (tags.length > 0 && (!currentSession.sessionTags || currentSession.sessionTags.length === 0)) {
|
|
61036
|
+
currentSession.sessionTags = tags;
|
|
61037
|
+
sessionLog6(currentSession).debug(`Set tags: ${tags.join(", ")} (attempt ${attempt})`);
|
|
61038
|
+
tagsSet = true;
|
|
61039
|
+
updated = true;
|
|
61040
|
+
} else if (currentSession.sessionTags && currentSession.sessionTags.length > 0) {
|
|
61041
|
+
tagsSet = true;
|
|
61042
|
+
}
|
|
61043
|
+
if (updated) {
|
|
61044
|
+
ctx.ops.persistSession(currentSession);
|
|
61045
|
+
await ctx.ops.updateStickyMessage();
|
|
61046
|
+
await ctx.ops.updateSessionHeader(currentSession);
|
|
61047
|
+
}
|
|
61048
|
+
return { success: metadataSet && tagsSet, metadataSet, tagsSet };
|
|
61049
|
+
}
|
|
60974
61050
|
function fireMetadataSuggestions(session, prompt, ctx) {
|
|
60975
61051
|
(async () => {
|
|
60976
61052
|
try {
|
|
60977
|
-
|
|
60978
|
-
|
|
60979
|
-
|
|
60980
|
-
|
|
60981
|
-
|
|
60982
|
-
|
|
60983
|
-
|
|
60984
|
-
|
|
60985
|
-
|
|
60986
|
-
|
|
60987
|
-
|
|
60988
|
-
|
|
60989
|
-
|
|
60990
|
-
|
|
60991
|
-
sessionLog6(
|
|
60992
|
-
|
|
60993
|
-
|
|
60994
|
-
|
|
60995
|
-
|
|
60996
|
-
|
|
60997
|
-
|
|
60998
|
-
|
|
60999
|
-
|
|
61000
|
-
|
|
61001
|
-
|
|
61002
|
-
await ctx.ops.updateSessionHeader(currentSession);
|
|
61053
|
+
let result = await attemptMetadataFetch(session, prompt, ctx, 1);
|
|
61054
|
+
let attempt = 1;
|
|
61055
|
+
while (!result.success && attempt < METADATA_MAX_RETRIES + 1) {
|
|
61056
|
+
attempt++;
|
|
61057
|
+
const currentSession = ctx.state.sessions.get(session.sessionId);
|
|
61058
|
+
if (!currentSession) {
|
|
61059
|
+
sessionLog6(session).debug("Session gone, stopping metadata retries");
|
|
61060
|
+
return;
|
|
61061
|
+
}
|
|
61062
|
+
const missing = [];
|
|
61063
|
+
if (!result.metadataSet)
|
|
61064
|
+
missing.push("title/description");
|
|
61065
|
+
if (!result.tagsSet)
|
|
61066
|
+
missing.push("tags");
|
|
61067
|
+
sessionLog6(session).debug(`Retrying metadata fetch for ${missing.join(", ")} (attempt ${attempt}/${METADATA_MAX_RETRIES + 1})`);
|
|
61068
|
+
await new Promise((resolve6) => setTimeout(resolve6, METADATA_RETRY_DELAY_MS));
|
|
61069
|
+
result = await attemptMetadataFetch(session, prompt, ctx, attempt);
|
|
61070
|
+
}
|
|
61071
|
+
if (!result.success) {
|
|
61072
|
+
const missing = [];
|
|
61073
|
+
if (!result.metadataSet)
|
|
61074
|
+
missing.push("title/description");
|
|
61075
|
+
if (!result.tagsSet)
|
|
61076
|
+
missing.push("tags");
|
|
61077
|
+
sessionLog6(session).debug(`Metadata fetch incomplete after ${attempt} attempts: missing ${missing.join(", ")}`);
|
|
61003
61078
|
}
|
|
61004
61079
|
} catch (err) {
|
|
61005
61080
|
sessionLog6(session).debug(`Metadata suggestion error: ${err}`);
|
|
@@ -71118,9 +71193,8 @@ function Platforms({ platforms }) {
|
|
|
71118
71193
|
!platform2.enabled ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
71119
71194
|
dimColor: true,
|
|
71120
71195
|
children: "\u25CB"
|
|
71121
|
-
}, undefined, false, undefined, this) : platform2.reconnecting ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(
|
|
71122
|
-
|
|
71123
|
-
children: "\u25CC"
|
|
71196
|
+
}, undefined, false, undefined, this) : platform2.reconnecting ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Spinner2, {
|
|
71197
|
+
type: "dots"
|
|
71124
71198
|
}, undefined, false, undefined, this) : platform2.connected ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
71125
71199
|
color: "green",
|
|
71126
71200
|
children: "\u25CF"
|
|
@@ -71136,30 +71210,20 @@ function Platforms({ platforms }) {
|
|
|
71136
71210
|
platform2.botName
|
|
71137
71211
|
]
|
|
71138
71212
|
}, undefined, true, undefined, this),
|
|
71139
|
-
|
|
71140
|
-
|
|
71141
|
-
|
|
71142
|
-
|
|
71143
|
-
|
|
71144
|
-
|
|
71145
|
-
|
|
71146
|
-
|
|
71147
|
-
|
|
71148
|
-
|
|
71149
|
-
")"
|
|
71150
|
-
]
|
|
71151
|
-
}, undefined, true, undefined, this)
|
|
71152
|
-
]
|
|
71153
|
-
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(jsx_dev_runtime3.Fragment, {
|
|
71213
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
71214
|
+
dimColor: true,
|
|
71215
|
+
children: "on"
|
|
71216
|
+
}, undefined, false, undefined, this),
|
|
71217
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
71218
|
+
dimColor: !platform2.enabled,
|
|
71219
|
+
children: platform2.displayName
|
|
71220
|
+
}, undefined, false, undefined, this),
|
|
71221
|
+
platform2.reconnecting && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
71222
|
+
dimColor: true,
|
|
71154
71223
|
children: [
|
|
71155
|
-
|
|
71156
|
-
|
|
71157
|
-
|
|
71158
|
-
}, undefined, false, undefined, this),
|
|
71159
|
-
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
|
|
71160
|
-
dimColor: !platform2.enabled,
|
|
71161
|
-
children: platform2.displayName
|
|
71162
|
-
}, undefined, false, undefined, this)
|
|
71224
|
+
"(retry ",
|
|
71225
|
+
platform2.reconnectAttempts,
|
|
71226
|
+
")"
|
|
71163
71227
|
]
|
|
71164
71228
|
}, undefined, true, undefined, this)
|
|
71165
71229
|
]
|