claude-threads 1.39.0 → 1.39.1

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 CHANGED
@@ -5,6 +5,11 @@ 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.39.1] - 2026-09-25
9
+
10
+ ### Fixed
11
+ - **A long burst or a long code block no longer overflows one post** (#617, #619). When a lot of text reached a reply that already had a post, the part that did not fit went into one new post of any size, and a code block Claude was still writing kept growing the last post without limit. Slack cut such a post off; Mattermost refused it, and the text was posted twice later. Both now split over posts that fit, with code blocks closed and reopened with their language. Normal replies below the limit are unchanged.
12
+
8
13
  ## [1.39.0] - 2026-09-25
9
14
 
10
15
  ### Added
package/dist/index.js CHANGED
@@ -60490,26 +60490,51 @@ ${body}` : this.state.header;
60490
60490
  chunkCount: chunks.length,
60491
60491
  reason: "no_currentPostId"
60492
60492
  }, "flush");
60493
- let lastPosted = null;
60494
- for (let i = 0;i < chunks.length; i++) {
60495
- const created = await this.createNewPost(ctx, chunks[i], lastPosted ? "" : pendingAtFlushStart);
60496
- if (!created) {
60497
- if (lastPosted) {
60498
- this.state.pendingContent = chunks.slice(i).join(`
60493
+ await this.postChunks(ctx, chunks, pendingAtFlushStart, false);
60494
+ }
60495
+ }
60496
+ async splitOversized(ctx, content, pendingAtFlushStart, hardThreshold) {
60497
+ const postId = this.state.currentPostId;
60498
+ if (!postId)
60499
+ return false;
60500
+ const reserve = this.headerReserve(postId);
60501
+ if (content.length + reserve <= ctx.platform.getMessageLimits().maxLength)
60502
+ return false;
60503
+ const [firstPiece, ...rest] = splitByLength(content, hardThreshold - reserve);
60504
+ let landed = false;
60505
+ await this.tryUpdatePost(ctx, postId, firstPiece, "handleSplit", { reason: "oversized_code_block", contentLength: content.length, pieces: rest.length + 1 }, { reason: "oversized_code_block_failed" }, () => {
60506
+ landed = true;
60507
+ }, () => {
60508
+ if (postId === this.state.headerPostId)
60509
+ this.state.headerBody = firstPiece;
60510
+ });
60511
+ this.state.currentPostId = null;
60512
+ this.state.currentPostContent = "";
60513
+ if (landed)
60514
+ this.clearFlushedContent(pendingAtFlushStart);
60515
+ await this.postChunks(ctx, rest, pendingAtFlushStart, landed);
60516
+ return true;
60517
+ }
60518
+ async postChunks(ctx, chunks, pendingAtFlushStart, flushCleared) {
60519
+ let cleared = flushCleared;
60520
+ for (let i = 0;i < chunks.length; i++) {
60521
+ const created = await this.createNewPost(ctx, chunks[i], cleared ? "" : pendingAtFlushStart);
60522
+ if (!created) {
60523
+ if (cleared) {
60524
+ this.state.pendingContent = chunks.slice(i).join(`
60499
60525
 
60500
60526
  `) + (this.state.pendingContent ? `
60501
60527
 
60502
60528
  ${this.state.pendingContent}` : "");
60503
- }
60504
- this.state.currentPostId = null;
60505
- this.state.currentPostContent = "";
60506
- break;
60507
- }
60508
- lastPosted = { id: this.state.currentPostId, content: this.state.currentPostContent };
60509
- if (i < chunks.length - 1) {
60510
- this.state.currentPostId = null;
60511
- this.state.currentPostContent = "";
60512
60529
  }
60530
+ this.state.currentPostId = null;
60531
+ this.state.currentPostContent = "";
60532
+ return;
60533
+ }
60534
+ cleared = true;
60535
+ if (i < chunks.length - 1) {
60536
+ this.state.currentPostId = null;
60537
+ this.state.currentPostContent = "";
60513
60538
  }
60514
60539
  }
60515
60540
  }
@@ -60570,6 +60595,8 @@ ${this.state.pendingContent}` : "");
60570
60595
  }
60571
60596
  if (codeBlockOpenPosition !== undefined) {
60572
60597
  if (codeBlockOpenPosition === 0) {
60598
+ if (await this.splitOversized(ctx, content, pendingAtFlushStart, hardThreshold))
60599
+ return;
60573
60600
  if (this.state.currentPostId) {
60574
60601
  const postId = this.state.currentPostId;
60575
60602
  await this.tryUpdatePost(ctx, postId, content, "handleSplit", { reason: "code_block_at_start", contentLength: content.length }, { reason: "code_block_at_start_failed" }, () => {
@@ -60587,6 +60614,8 @@ ${this.state.pendingContent}` : "");
60587
60614
  if (breakBeforeCodeBlock > 0) {
60588
60615
  breakPoint = breakBeforeCodeBlock;
60589
60616
  } else {
60617
+ if (await this.splitOversized(ctx, content, pendingAtFlushStart, hardThreshold))
60618
+ return;
60590
60619
  if (this.state.currentPostId) {
60591
60620
  const postId = this.state.currentPostId;
60592
60621
  await this.tryUpdatePost(ctx, postId, content, "handleSplit", { reason: "no_break_before_code_block", contentLength: content.length }, { reason: "no_break_before_code_block_failed" }, () => {
@@ -60602,9 +60631,12 @@ ${this.state.pendingContent}` : "");
60602
60631
  }
60603
60632
  const firstPart = content.substring(0, breakPoint).trim();
60604
60633
  const remainder = content.substring(breakPoint).trim();
60634
+ let firstPartLanded = false;
60605
60635
  if (this.state.currentPostId) {
60606
60636
  const postId = this.state.currentPostId;
60607
- await this.tryUpdatePost(ctx, postId, firstPart, "handleSplit", { reason: "split_first_part", firstPartLength: firstPart.length, remainderLength: remainder.length }, { reason: "split_first_part_failed" }, () => {}, () => {
60637
+ await this.tryUpdatePost(ctx, postId, firstPart, "handleSplit", { reason: "split_first_part", firstPartLength: firstPart.length, remainderLength: remainder.length }, { reason: "split_first_part_failed" }, () => {
60638
+ firstPartLanded = true;
60639
+ }, () => {
60608
60640
  if (postId === this.state.headerPostId) {
60609
60641
  this.state.headerBody = firstPart;
60610
60642
  }
@@ -60613,7 +60645,14 @@ ${this.state.pendingContent}` : "");
60613
60645
  this.state.currentPostId = null;
60614
60646
  this.state.currentPostContent = "";
60615
60647
  if (remainder) {
60616
- await this.createNewPost(ctx, remainder, pendingAtFlushStart);
60648
+ const MAX_POST_LENGTH = ctx.platform.getMessageLimits().maxLength;
60649
+ const reserve = this.headerReserve(null);
60650
+ const chunks = remainder.length + reserve > MAX_POST_LENGTH ? splitByLength(remainder, hardThreshold - reserve) : [remainder];
60651
+ if (firstPartLanded)
60652
+ this.clearFlushedContent(pendingAtFlushStart);
60653
+ await this.postChunks(ctx, chunks, pendingAtFlushStart, firstPartLanded);
60654
+ } else if (firstPartLanded) {
60655
+ this.clearFlushedContent(pendingAtFlushStart);
60617
60656
  }
60618
60657
  }
60619
60658
  async createNewPost(ctx, content, pendingAtFlushStart) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-threads",
3
- "version": "1.39.0",
3
+ "version": "1.39.1",
4
4
  "description": "Run Claude Code from Slack or Mattermost. Sessions stream live into threads where your whole team can watch and steer.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",