claude-threads 1.0.10 → 1.0.12
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 +72 -23
- package/dist/mcp/permission-server.js +71 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,22 @@ 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.12] - 2026-01-15
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **Skipped file feedback posting** - Fixed swapped arguments in createPost call that caused "Invalid RootId parameter" errors when posting feedback for skipped files (#221)
|
|
12
|
+
|
|
13
|
+
## [1.0.11] - 2026-01-15
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **Improved gzip error handling** - Uses streaming decompression for better error messages when gzip files are corrupt or truncated (#219)
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- **Shorter initial session message** - Session start message is now more concise for popup-friendly display (#218)
|
|
20
|
+
|
|
21
|
+
### Dependencies
|
|
22
|
+
- **Bump diff from 8.0.2 to 8.0.3** (#220)
|
|
23
|
+
|
|
8
24
|
## [1.0.10] - 2026-01-14
|
|
9
25
|
|
|
10
26
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -51257,15 +51257,6 @@ class ClaudeCli extends EventEmitter2 {
|
|
|
51257
51257
|
}
|
|
51258
51258
|
}
|
|
51259
51259
|
|
|
51260
|
-
// src/logo.ts
|
|
51261
|
-
function getLogo(version) {
|
|
51262
|
-
return `\`\`\`
|
|
51263
|
-
\u2734 \u2584\u2588\u2580 \u2588\u2588\u2588 \u2734 claude-threads v${version}
|
|
51264
|
-
\u2734 \u2588\u2580 \u2588 \u2734 Chat \xD7 Claude Code
|
|
51265
|
-
\u2734 \u2580\u2588\u2584 \u2588 \u2734
|
|
51266
|
-
\`\`\``;
|
|
51267
|
-
}
|
|
51268
|
-
|
|
51269
51260
|
// src/version.ts
|
|
51270
51261
|
import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
|
|
51271
51262
|
import { dirname as dirname6, resolve as resolve3 } from "path";
|
|
@@ -55471,12 +55462,15 @@ function createMessageManagerEvents() {
|
|
|
55471
55462
|
|
|
55472
55463
|
// src/operations/streaming/handler.ts
|
|
55473
55464
|
var import_yauzl = __toESM(require_yauzl(), 1);
|
|
55474
|
-
import {
|
|
55465
|
+
import { createGunzip } from "zlib";
|
|
55466
|
+
import { pipeline } from "stream/promises";
|
|
55467
|
+
import { Readable, Writable } from "stream";
|
|
55475
55468
|
var log17 = createLogger("streaming");
|
|
55476
55469
|
var MAX_PDF_SIZE = 32 * 1024 * 1024;
|
|
55477
55470
|
var MAX_TEXT_FILE_SIZE = 1 * 1024 * 1024;
|
|
55478
55471
|
var MAX_DECOMPRESSED_SIZE = 10 * 1024 * 1024;
|
|
55479
55472
|
var MAX_ZIP_SIZE = 50 * 1024 * 1024;
|
|
55473
|
+
var MAX_GZIP_SIZE = 50 * 1024 * 1024;
|
|
55480
55474
|
var MAX_ZIP_FILES = 20;
|
|
55481
55475
|
var SUPPORTED_IMAGE_TYPES = [
|
|
55482
55476
|
"image/jpeg",
|
|
@@ -55709,6 +55703,25 @@ function formatTextFileContent(filename, content) {
|
|
|
55709
55703
|
${content}
|
|
55710
55704
|
\`\`\``;
|
|
55711
55705
|
}
|
|
55706
|
+
async function decompressGzipStream(compressedBuffer) {
|
|
55707
|
+
const chunks = [];
|
|
55708
|
+
let totalSize = 0;
|
|
55709
|
+
const gunzip = createGunzip();
|
|
55710
|
+
const source = Readable.from(compressedBuffer);
|
|
55711
|
+
const collector = new Writable({
|
|
55712
|
+
write(chunk, _encoding, callback) {
|
|
55713
|
+
totalSize += chunk.length;
|
|
55714
|
+
if (totalSize > MAX_DECOMPRESSED_SIZE) {
|
|
55715
|
+
callback(new Error(`Decompressed size exceeds ${Math.round(MAX_DECOMPRESSED_SIZE / 1024 / 1024)}MB limit`));
|
|
55716
|
+
return;
|
|
55717
|
+
}
|
|
55718
|
+
chunks.push(chunk);
|
|
55719
|
+
callback();
|
|
55720
|
+
}
|
|
55721
|
+
});
|
|
55722
|
+
await pipeline(source, gunzip, collector);
|
|
55723
|
+
return Buffer.concat(chunks);
|
|
55724
|
+
}
|
|
55712
55725
|
async function processGzipFile(file, platform, debug = false) {
|
|
55713
55726
|
try {
|
|
55714
55727
|
if (!platform.downloadFile) {
|
|
@@ -55719,24 +55732,60 @@ async function processGzipFile(file, platform, debug = false) {
|
|
|
55719
55732
|
}
|
|
55720
55733
|
};
|
|
55721
55734
|
}
|
|
55722
|
-
|
|
55723
|
-
|
|
55735
|
+
if (file.size && file.size > MAX_GZIP_SIZE) {
|
|
55736
|
+
return {
|
|
55737
|
+
skipped: {
|
|
55738
|
+
name: file.name,
|
|
55739
|
+
reason: `Gzip file exceeds ${Math.round(MAX_GZIP_SIZE / 1024 / 1024)}MB limit (${Math.round(file.size / 1024 / 1024)}MB)`,
|
|
55740
|
+
suggestion: "Try compressing a smaller file or splitting the content"
|
|
55741
|
+
}
|
|
55742
|
+
};
|
|
55743
|
+
}
|
|
55744
|
+
let compressedBuffer;
|
|
55724
55745
|
try {
|
|
55725
|
-
|
|
55746
|
+
compressedBuffer = await platform.downloadFile(file.id);
|
|
55726
55747
|
} catch (err) {
|
|
55748
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
55749
|
+
log17.error(`Failed to download gzip file ${file.name}: ${errorMessage}`);
|
|
55727
55750
|
return {
|
|
55728
55751
|
skipped: {
|
|
55729
55752
|
name: file.name,
|
|
55730
|
-
reason: `
|
|
55753
|
+
reason: `Download failed: ${errorMessage}`,
|
|
55754
|
+
suggestion: "Check if the file is still available and try again"
|
|
55731
55755
|
}
|
|
55732
55756
|
};
|
|
55733
55757
|
}
|
|
55734
|
-
if (
|
|
55758
|
+
if (file.size && compressedBuffer.length !== file.size) {
|
|
55759
|
+
log17.warn(`Downloaded size mismatch for ${file.name}: expected ${file.size}, got ${compressedBuffer.length}`);
|
|
55760
|
+
}
|
|
55761
|
+
let decompressedBuffer;
|
|
55762
|
+
try {
|
|
55763
|
+
decompressedBuffer = await decompressGzipStream(compressedBuffer);
|
|
55764
|
+
} catch (err) {
|
|
55765
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
55766
|
+
let reason;
|
|
55767
|
+
let suggestion;
|
|
55768
|
+
if (errorMessage.includes("incorrect header check")) {
|
|
55769
|
+
reason = "Invalid gzip file: the file header is corrupted or this is not a gzip file";
|
|
55770
|
+
suggestion = "Verify the file is a valid gzip archive";
|
|
55771
|
+
} else if (errorMessage.includes("unexpected end of file")) {
|
|
55772
|
+
reason = "Incomplete gzip file: the file appears to be truncated";
|
|
55773
|
+
suggestion = "Re-download the file or check if the upload completed";
|
|
55774
|
+
} else if (errorMessage.includes("invalid stored block lengths")) {
|
|
55775
|
+
reason = "Corrupted gzip file: the compressed data is damaged";
|
|
55776
|
+
suggestion = "Try re-compressing the original file";
|
|
55777
|
+
} else if (errorMessage.includes("exceeds") && errorMessage.includes("limit")) {
|
|
55778
|
+
reason = errorMessage;
|
|
55779
|
+
suggestion = "Try extracting only the relevant portions of the file";
|
|
55780
|
+
} else {
|
|
55781
|
+
reason = `Decompression failed: ${errorMessage}`;
|
|
55782
|
+
suggestion = "Verify the file is a valid gzip archive";
|
|
55783
|
+
}
|
|
55735
55784
|
return {
|
|
55736
55785
|
skipped: {
|
|
55737
55786
|
name: file.name,
|
|
55738
|
-
reason
|
|
55739
|
-
suggestion
|
|
55787
|
+
reason,
|
|
55788
|
+
suggestion
|
|
55740
55789
|
}
|
|
55741
55790
|
};
|
|
55742
55791
|
}
|
|
@@ -55777,11 +55826,13 @@ async function processGzipFile(file, platform, debug = false) {
|
|
|
55777
55826
|
};
|
|
55778
55827
|
}
|
|
55779
55828
|
} catch (err) {
|
|
55780
|
-
|
|
55829
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
55830
|
+
log17.error(`Failed to process gzip file ${file.name}: ${errorMessage}`);
|
|
55781
55831
|
return {
|
|
55782
55832
|
skipped: {
|
|
55783
55833
|
name: file.name,
|
|
55784
|
-
reason: `Processing failed: ${
|
|
55834
|
+
reason: `Processing failed: ${errorMessage}`,
|
|
55835
|
+
suggestion: "An unexpected error occurred. Please try again or contact support if the issue persists"
|
|
55785
55836
|
}
|
|
55786
55837
|
};
|
|
55787
55838
|
}
|
|
@@ -56538,7 +56589,7 @@ class MessageManager {
|
|
|
56538
56589
|
this.session.claude.sendMessage(content);
|
|
56539
56590
|
if (skippedFiles.length > 0) {
|
|
56540
56591
|
const feedback = this.formatSkippedFilesFeedback(skippedFiles);
|
|
56541
|
-
await this.platform.createPost(this.threadId
|
|
56592
|
+
await this.platform.createPost(feedback, this.threadId);
|
|
56542
56593
|
}
|
|
56543
56594
|
this.session.lastActivityAt = new Date;
|
|
56544
56595
|
this.session.isProcessing = true;
|
|
@@ -63294,9 +63345,7 @@ async function startSession(options2, username, displayName, replyToPostId, plat
|
|
|
63294
63345
|
return;
|
|
63295
63346
|
}
|
|
63296
63347
|
const startFormatter = platform.getFormatter();
|
|
63297
|
-
const startPost = await withErrorHandling(() => platform.createPost(
|
|
63298
|
-
|
|
63299
|
-
${startFormatter.formatItalic("Starting session...")}`, replyToPostId), { action: "Create session post" });
|
|
63348
|
+
const startPost = await withErrorHandling(() => platform.createPost(startFormatter.formatItalic("Claude Threads session starting..."), replyToPostId), { action: "Create session post" });
|
|
63300
63349
|
if (!startPost)
|
|
63301
63350
|
return;
|
|
63302
63351
|
const actualThreadId = replyToPostId || startPost.id;
|
|
@@ -40344,12 +40344,15 @@ function createMessageManagerEvents() {
|
|
|
40344
40344
|
|
|
40345
40345
|
// src/operations/streaming/handler.ts
|
|
40346
40346
|
var import_yauzl = __toESM(require_yauzl(), 1);
|
|
40347
|
-
import {
|
|
40347
|
+
import { createGunzip } from "zlib";
|
|
40348
|
+
import { pipeline as pipeline2 } from "stream/promises";
|
|
40349
|
+
import { Readable, Writable } from "stream";
|
|
40348
40350
|
var log2 = createLogger("streaming");
|
|
40349
40351
|
var MAX_PDF_SIZE = 32 * 1024 * 1024;
|
|
40350
40352
|
var MAX_TEXT_FILE_SIZE = 1 * 1024 * 1024;
|
|
40351
40353
|
var MAX_DECOMPRESSED_SIZE = 10 * 1024 * 1024;
|
|
40352
40354
|
var MAX_ZIP_SIZE = 50 * 1024 * 1024;
|
|
40355
|
+
var MAX_GZIP_SIZE = 50 * 1024 * 1024;
|
|
40353
40356
|
var MAX_ZIP_FILES = 20;
|
|
40354
40357
|
var SUPPORTED_IMAGE_TYPES = [
|
|
40355
40358
|
"image/jpeg",
|
|
@@ -40582,6 +40585,25 @@ function formatTextFileContent(filename, content) {
|
|
|
40582
40585
|
${content}
|
|
40583
40586
|
\`\`\``;
|
|
40584
40587
|
}
|
|
40588
|
+
async function decompressGzipStream(compressedBuffer) {
|
|
40589
|
+
const chunks = [];
|
|
40590
|
+
let totalSize = 0;
|
|
40591
|
+
const gunzip = createGunzip();
|
|
40592
|
+
const source = Readable.from(compressedBuffer);
|
|
40593
|
+
const collector = new Writable({
|
|
40594
|
+
write(chunk, _encoding, callback) {
|
|
40595
|
+
totalSize += chunk.length;
|
|
40596
|
+
if (totalSize > MAX_DECOMPRESSED_SIZE) {
|
|
40597
|
+
callback(new Error(`Decompressed size exceeds ${Math.round(MAX_DECOMPRESSED_SIZE / 1024 / 1024)}MB limit`));
|
|
40598
|
+
return;
|
|
40599
|
+
}
|
|
40600
|
+
chunks.push(chunk);
|
|
40601
|
+
callback();
|
|
40602
|
+
}
|
|
40603
|
+
});
|
|
40604
|
+
await pipeline2(source, gunzip, collector);
|
|
40605
|
+
return Buffer.concat(chunks);
|
|
40606
|
+
}
|
|
40585
40607
|
async function processGzipFile(file2, platform, debug = false) {
|
|
40586
40608
|
try {
|
|
40587
40609
|
if (!platform.downloadFile) {
|
|
@@ -40592,24 +40614,60 @@ async function processGzipFile(file2, platform, debug = false) {
|
|
|
40592
40614
|
}
|
|
40593
40615
|
};
|
|
40594
40616
|
}
|
|
40595
|
-
|
|
40596
|
-
|
|
40617
|
+
if (file2.size && file2.size > MAX_GZIP_SIZE) {
|
|
40618
|
+
return {
|
|
40619
|
+
skipped: {
|
|
40620
|
+
name: file2.name,
|
|
40621
|
+
reason: `Gzip file exceeds ${Math.round(MAX_GZIP_SIZE / 1024 / 1024)}MB limit (${Math.round(file2.size / 1024 / 1024)}MB)`,
|
|
40622
|
+
suggestion: "Try compressing a smaller file or splitting the content"
|
|
40623
|
+
}
|
|
40624
|
+
};
|
|
40625
|
+
}
|
|
40626
|
+
let compressedBuffer;
|
|
40597
40627
|
try {
|
|
40598
|
-
|
|
40628
|
+
compressedBuffer = await platform.downloadFile(file2.id);
|
|
40599
40629
|
} catch (err) {
|
|
40630
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
40631
|
+
log2.error(`Failed to download gzip file ${file2.name}: ${errorMessage}`);
|
|
40600
40632
|
return {
|
|
40601
40633
|
skipped: {
|
|
40602
40634
|
name: file2.name,
|
|
40603
|
-
reason: `
|
|
40635
|
+
reason: `Download failed: ${errorMessage}`,
|
|
40636
|
+
suggestion: "Check if the file is still available and try again"
|
|
40604
40637
|
}
|
|
40605
40638
|
};
|
|
40606
40639
|
}
|
|
40607
|
-
if (
|
|
40640
|
+
if (file2.size && compressedBuffer.length !== file2.size) {
|
|
40641
|
+
log2.warn(`Downloaded size mismatch for ${file2.name}: expected ${file2.size}, got ${compressedBuffer.length}`);
|
|
40642
|
+
}
|
|
40643
|
+
let decompressedBuffer;
|
|
40644
|
+
try {
|
|
40645
|
+
decompressedBuffer = await decompressGzipStream(compressedBuffer);
|
|
40646
|
+
} catch (err) {
|
|
40647
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
40648
|
+
let reason;
|
|
40649
|
+
let suggestion;
|
|
40650
|
+
if (errorMessage.includes("incorrect header check")) {
|
|
40651
|
+
reason = "Invalid gzip file: the file header is corrupted or this is not a gzip file";
|
|
40652
|
+
suggestion = "Verify the file is a valid gzip archive";
|
|
40653
|
+
} else if (errorMessage.includes("unexpected end of file")) {
|
|
40654
|
+
reason = "Incomplete gzip file: the file appears to be truncated";
|
|
40655
|
+
suggestion = "Re-download the file or check if the upload completed";
|
|
40656
|
+
} else if (errorMessage.includes("invalid stored block lengths")) {
|
|
40657
|
+
reason = "Corrupted gzip file: the compressed data is damaged";
|
|
40658
|
+
suggestion = "Try re-compressing the original file";
|
|
40659
|
+
} else if (errorMessage.includes("exceeds") && errorMessage.includes("limit")) {
|
|
40660
|
+
reason = errorMessage;
|
|
40661
|
+
suggestion = "Try extracting only the relevant portions of the file";
|
|
40662
|
+
} else {
|
|
40663
|
+
reason = `Decompression failed: ${errorMessage}`;
|
|
40664
|
+
suggestion = "Verify the file is a valid gzip archive";
|
|
40665
|
+
}
|
|
40608
40666
|
return {
|
|
40609
40667
|
skipped: {
|
|
40610
40668
|
name: file2.name,
|
|
40611
|
-
reason
|
|
40612
|
-
suggestion
|
|
40669
|
+
reason,
|
|
40670
|
+
suggestion
|
|
40613
40671
|
}
|
|
40614
40672
|
};
|
|
40615
40673
|
}
|
|
@@ -40650,11 +40708,13 @@ async function processGzipFile(file2, platform, debug = false) {
|
|
|
40650
40708
|
};
|
|
40651
40709
|
}
|
|
40652
40710
|
} catch (err) {
|
|
40653
|
-
|
|
40711
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
40712
|
+
log2.error(`Failed to process gzip file ${file2.name}: ${errorMessage}`);
|
|
40654
40713
|
return {
|
|
40655
40714
|
skipped: {
|
|
40656
40715
|
name: file2.name,
|
|
40657
|
-
reason: `Processing failed: ${
|
|
40716
|
+
reason: `Processing failed: ${errorMessage}`,
|
|
40717
|
+
suggestion: "An unexpected error occurred. Please try again or contact support if the issue persists"
|
|
40658
40718
|
}
|
|
40659
40719
|
};
|
|
40660
40720
|
}
|
|
@@ -41384,7 +41444,7 @@ class MessageManager {
|
|
|
41384
41444
|
this.session.claude.sendMessage(content);
|
|
41385
41445
|
if (skippedFiles.length > 0) {
|
|
41386
41446
|
const feedback = this.formatSkippedFilesFeedback(skippedFiles);
|
|
41387
|
-
await this.platform.createPost(this.threadId
|
|
41447
|
+
await this.platform.createPost(feedback, this.threadId);
|
|
41388
41448
|
}
|
|
41389
41449
|
this.session.lastActivityAt = new Date;
|
|
41390
41450
|
this.session.isProcessing = true;
|