claude-threads 1.16.1 → 1.16.2
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 +21 -2
- package/dist/mcp/mcp-server.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.16.2] - 2026-05-31
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Sturdier retry budget for the Mattermost post-save race.** Under load Mattermost can return a burst of 500s on `POST /posts` (the threads write race: duplicate key on `threads_pkey` / `app.post.save.app_error`) when several posts stream to the same thread. The retry budget was 3 attempts with plain exponential backoff; a heavy burst exhausted it and dropped a post, which surfaced as flaky task-list / sticky / context-prompt behavior. The budget is now 6 attempts with a capped (2s), equal-jittered backoff. The cap keeps the total wait bounded so a long retry chain can't itself stall things, and the jitter decorrelates concurrent posts that would otherwise re-collide on the same row lock every round. (#394)
|
|
14
|
+
- **Two remaining memory leaks after #351.** First, `MessageManager.dispose()` cleared the post tracker but never called `this.events.removeAllListeners()` on the per-session emitter. Each session attaches a handful of listeners (`question:complete`, `task:update`, `approval:complete`, and the rest), and their closures kept session state reachable after the session ended, so the heap grew with every session. `dispose()` now removes the listeners before resetting. Second, React 19 enables user timing when both `console.timeStamp` and `performance.measure` exist (the case on Node.js 25+), so every component re-render calls `performance.measure()` with a structured-clone'd prop-diff detail that Node buffers indefinitely (~50-205 KB per entry, ~2 GB after a long uptime). Nothing in the bot reads those entries, so a guarded `setInterval` clears them every 60 seconds with `.unref()` so it never blocks a clean exit. (#394)
|
|
15
|
+
|
|
10
16
|
## [1.16.1] - 2026-05-22
|
|
11
17
|
|
|
12
18
|
### Security
|
package/dist/index.js
CHANGED
|
@@ -50607,8 +50607,9 @@ class MattermostClient extends BasePlatformClient {
|
|
|
50607
50607
|
this.emit("channel_post", normalizedPost, user);
|
|
50608
50608
|
}
|
|
50609
50609
|
}
|
|
50610
|
-
MAX_RETRIES =
|
|
50610
|
+
MAX_RETRIES = 6;
|
|
50611
50611
|
RETRY_DELAY_MS = 500;
|
|
50612
|
+
RETRY_DELAY_CAP_MS = 2000;
|
|
50612
50613
|
async api(method, path, body, retryCount = 0, options) {
|
|
50613
50614
|
const url = `${this.url}/api/v4${path}`;
|
|
50614
50615
|
log3.debug(`API ${method} ${path}`);
|
|
@@ -50623,7 +50624,7 @@ class MattermostClient extends BasePlatformClient {
|
|
|
50623
50624
|
if (!response.ok) {
|
|
50624
50625
|
const text = await response.text();
|
|
50625
50626
|
if (response.status === 500 && retryCount < this.MAX_RETRIES) {
|
|
50626
|
-
const delay = this.
|
|
50627
|
+
const delay = this.retryDelayMs(retryCount);
|
|
50627
50628
|
log3.warn(`API ${method} ${path} failed with 500, retrying in ${delay}ms (attempt ${retryCount + 1}/${this.MAX_RETRIES})`);
|
|
50628
50629
|
await new Promise((resolve3) => setTimeout(resolve3, delay));
|
|
50629
50630
|
return this.api(method, path, body, retryCount + 1, options);
|
|
@@ -50639,6 +50640,11 @@ class MattermostClient extends BasePlatformClient {
|
|
|
50639
50640
|
log3.debug(`API ${method} ${path} → ${response.status}`);
|
|
50640
50641
|
return response.json();
|
|
50641
50642
|
}
|
|
50643
|
+
retryDelayMs(retryCount) {
|
|
50644
|
+
const ceil = Math.min(this.RETRY_DELAY_MS * Math.pow(2, retryCount), this.RETRY_DELAY_CAP_MS);
|
|
50645
|
+
const half = ceil / 2;
|
|
50646
|
+
return Math.floor(half + Math.random() * half);
|
|
50647
|
+
}
|
|
50642
50648
|
async getBotUser() {
|
|
50643
50649
|
const user = await this.api("GET", "/users/me");
|
|
50644
50650
|
this.botUserId = user.id;
|
|
@@ -63796,6 +63802,7 @@ class MessageManager {
|
|
|
63796
63802
|
dispose() {
|
|
63797
63803
|
this.cancelScheduledFlush();
|
|
63798
63804
|
this.postTracker.clearSession(this.sessionId);
|
|
63805
|
+
this.events.removeAllListeners();
|
|
63799
63806
|
this.reset();
|
|
63800
63807
|
}
|
|
63801
63808
|
}
|
|
@@ -68733,6 +68740,17 @@ Mention me to start a session in this worktree.`, threadId);
|
|
|
68733
68740
|
this.registry.clear();
|
|
68734
68741
|
}
|
|
68735
68742
|
}
|
|
68743
|
+
// src/utils/perf-cleanup.ts
|
|
68744
|
+
function startReactMeasureCleanup(intervalMs = 60000) {
|
|
68745
|
+
if (typeof performance === "undefined" || typeof performance.clearMeasures !== "function") {
|
|
68746
|
+
return null;
|
|
68747
|
+
}
|
|
68748
|
+
const timer = setInterval(() => {
|
|
68749
|
+
performance.clearMeasures();
|
|
68750
|
+
}, intervalMs);
|
|
68751
|
+
timer.unref?.();
|
|
68752
|
+
return timer;
|
|
68753
|
+
}
|
|
68736
68754
|
// src/ui/providers/ink-provider.ts
|
|
68737
68755
|
var import_react62 = __toESM(require_react(), 1);
|
|
68738
68756
|
|
|
@@ -79525,6 +79543,7 @@ async function startWithoutDaemon() {
|
|
|
79525
79543
|
}
|
|
79526
79544
|
}
|
|
79527
79545
|
let triggerShutdown = null;
|
|
79546
|
+
startReactMeasureCleanup();
|
|
79528
79547
|
const updateState = loadUpdateState();
|
|
79529
79548
|
const restoredSettings = updateState.justUpdated ? updateState.runtimeSettings : undefined;
|
|
79530
79549
|
if (restoredSettings) {
|
package/dist/mcp/mcp-server.js
CHANGED
|
@@ -51553,6 +51553,7 @@ class MessageManager {
|
|
|
51553
51553
|
dispose() {
|
|
51554
51554
|
this.cancelScheduledFlush();
|
|
51555
51555
|
this.postTracker.clearSession(this.sessionId);
|
|
51556
|
+
this.events.removeAllListeners();
|
|
51556
51557
|
this.reset();
|
|
51557
51558
|
}
|
|
51558
51559
|
}
|