claude-threads 1.9.1 → 1.9.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 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.9.2] - 2026-04-24
9
+
10
+ ### Fixed
11
+ - **Unreadable `[object ErrorEvent]` in WebSocket error logs.** Recent Node / undici deliver a browser-style `ErrorEvent` (not a plain `Error`) to `ws.onerror`, and `` `${event}` `` stringifies that wrapper to `[object ErrorEvent]` — the original failure cause was being dropped. New `formatWebSocketError(err)` helper in `src/platform/utils.ts` pulls the first usable signal (`.message` → `.error.message` → `.type (code: .code)` → `String(err)`), wired into all five WebSocket error sites across Slack + Mattermost main clients, both MCP permission-server clients, and the UI re-emit. The Slack client's rejection and re-emitted `Error` now carry the underlying message too, instead of the opaque `"Socket Mode WebSocket error"`. (#347)
12
+ - **Worktree creation under a parent branch gave a generic "Failed to create worktree" message.** When a flat branch `test` already exists and the user requests `test/add-unit-coverage`, git refuses with `fatal: 'refs/heads/test' exists; cannot create 'refs/heads/test/add-unit-coverage'`. `parseWorktreeError` now matches this specific shape and reports `Branch <parent> already exists and blocks <nested>` with the suggestion to pick a non-nested name or delete the parent branch first. (#347)
13
+
8
14
  ## [1.9.1] - 2026-04-24
9
15
 
10
16
  ### Internals
package/dist/index.js CHANGED
@@ -51565,6 +51565,23 @@ function truncateAtWord(str2, maxLength) {
51565
51565
  function escapeRegExp(string) {
51566
51566
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
51567
51567
  }
51568
+ function formatWebSocketError(err) {
51569
+ if (err instanceof Error)
51570
+ return err.message;
51571
+ if (err && typeof err === "object") {
51572
+ const e = err;
51573
+ if (typeof e.message === "string" && e.message)
51574
+ return e.message;
51575
+ if (e.error instanceof Error)
51576
+ return e.error.message;
51577
+ if (typeof e.error === "string" && e.error)
51578
+ return e.error;
51579
+ if (typeof e.type === "string" && e.type) {
51580
+ return typeof e.code === "string" || typeof e.code === "number" ? `${e.type} (code: ${e.code})` : e.type;
51581
+ }
51582
+ }
51583
+ return String(err);
51584
+ }
51568
51585
  function getPlatformIcon(platformType) {
51569
51586
  switch (platformType) {
51570
51587
  case "slack":
@@ -52110,9 +52127,10 @@ class MattermostClient extends BasePlatformClient {
52110
52127
  this.onConnectionClosed();
52111
52128
  };
52112
52129
  this.ws.onerror = (event) => {
52113
- wsLogger.warn(`WebSocket error: ${event}`);
52114
- this.emit("error", event);
52115
- reject(event);
52130
+ const msg = formatWebSocketError(event);
52131
+ wsLogger.warn(`WebSocket error: ${msg}`);
52132
+ this.emit("error", new Error(`WebSocket error: ${msg}`));
52133
+ reject(new Error(`WebSocket error: ${msg}`));
52116
52134
  };
52117
52135
  });
52118
52136
  }
@@ -52540,11 +52558,12 @@ class SlackClient extends BasePlatformClient {
52540
52558
  };
52541
52559
  this.ws.onerror = (event) => {
52542
52560
  clearTimeout(connectionTimeout);
52543
- wsLogger.warn(`Socket Mode: WebSocket error: ${event}`);
52561
+ const msg = formatWebSocketError(event);
52562
+ wsLogger.warn(`Socket Mode: WebSocket error: ${msg}`);
52544
52563
  if (!this.isIntentionalDisconnect && !this.isReconnecting) {
52545
- this.emit("error", new Error("Socket Mode WebSocket error"));
52564
+ this.emit("error", new Error(`Socket Mode WebSocket error: ${msg}`));
52546
52565
  }
52547
- doReject(new Error("Socket Mode WebSocket error"));
52566
+ doReject(new Error(`Socket Mode WebSocket error: ${msg}`));
52548
52567
  };
52549
52568
  });
52550
52569
  }
@@ -53160,7 +53179,7 @@ class MattermostPermissionApi {
53160
53179
  }
53161
53180
  };
53162
53181
  ws.onerror = (event) => {
53163
- mcpLogger.error(`WebSocket error: ${event}`);
53182
+ mcpLogger.error(`WebSocket error: ${formatWebSocketError(event)}`);
53164
53183
  if (!resolved) {
53165
53184
  resolved = true;
53166
53185
  clearTimeout(timeout);
@@ -53356,7 +53375,7 @@ class SlackPermissionApi {
53356
53375
  }
53357
53376
  };
53358
53377
  ws.onerror = (event) => {
53359
- mcpLogger.error(`Socket Mode WebSocket error: ${event}`);
53378
+ mcpLogger.error(`Socket Mode WebSocket error: ${formatWebSocketError(event)}`);
53360
53379
  if (!resolved) {
53361
53380
  resolved = true;
53362
53381
  clearTimeout(timeout);
@@ -66318,6 +66337,15 @@ function parseWorktreeError(error) {
66318
66337
  suggestion: "Try a different branch name, or use `!worktree list` to see existing worktrees"
66319
66338
  };
66320
66339
  }
66340
+ const parentBlocksMatch = message.match(/'refs\/heads\/([^']+)' exists; cannot create '(?:refs\/heads\/)?([^']+)'/i);
66341
+ if (parentBlocksMatch) {
66342
+ const parent = parentBlocksMatch[1];
66343
+ const nested = parentBlocksMatch[2];
66344
+ return {
66345
+ summary: `Branch ${parent} already exists and blocks ${nested}`,
66346
+ suggestion: `Pick a name that does not start with ${parent}/, or delete the existing ${parent} branch first.`
66347
+ };
66348
+ }
66321
66349
  if (lowerMessage.includes("already exists")) {
66322
66350
  return {
66323
66351
  summary: "A worktree or branch with this name already exists",
@@ -80104,7 +80132,8 @@ function wirePlatformEvents(platformId, client, session, ui) {
80104
80132
  ui.setPlatformStatus(platformId, { reconnecting: true, reconnectAttempts: attempt });
80105
80133
  });
80106
80134
  client.on("error", (e) => {
80107
- ui.addLog({ level: "error", component: platformId, message: String(e) });
80135
+ const message = e instanceof Error ? e.message : String(e);
80136
+ ui.addLog({ level: "error", component: platformId, message });
80108
80137
  });
80109
80138
  }
80110
80139
  program.name("claude-threads").version(VERSION).description("Share Claude Code sessions in Mattermost").option("--url <url>", "Mattermost server URL").option("--token <token>", "Mattermost bot token").option("--channel <id>", "Mattermost channel ID").option("--bot-name <name>", "Bot mention name (default: claude-code)").option("--allowed-users <users>", "Comma-separated allowed usernames").option("--permission-mode <mode>", "Permission mode: default | auto | bypass (default: from config)").option("--skip-permissions", "[deprecated] Alias for --permission-mode bypass").option("--no-skip-permissions", "[deprecated] Alias for --permission-mode default").option("--chrome", "Enable Claude in Chrome integration").option("--no-chrome", "Disable Claude in Chrome integration").option("--worktree-mode <mode>", "Git worktree mode: off, prompt, require (default: prompt)").option("--keep-alive", "Enable system sleep prevention (default: enabled)").option("--no-keep-alive", "Disable system sleep prevention").option("--setup", "Run interactive setup wizard (reconfigure existing settings)").option("--debug", "Enable debug logging").option("--skip-version-check", "Skip Claude CLI version compatibility check").option("--auto-restart", "Enable auto-restart on updates (default when autoUpdate enabled)").option("--no-auto-restart", "Disable auto-restart on updates").option("--headless", "Run without interactive UI (logs to stdout)").parse();
@@ -50456,6 +50456,23 @@ class BaseExecutor {
50456
50456
  }
50457
50457
  }
50458
50458
  // src/platform/utils.ts
50459
+ function formatWebSocketError(err) {
50460
+ if (err instanceof Error)
50461
+ return err.message;
50462
+ if (err && typeof err === "object") {
50463
+ const e = err;
50464
+ if (typeof e.message === "string" && e.message)
50465
+ return e.message;
50466
+ if (e.error instanceof Error)
50467
+ return e.error.message;
50468
+ if (typeof e.error === "string" && e.error)
50469
+ return e.error;
50470
+ if (typeof e.type === "string" && e.type) {
50471
+ return typeof e.code === "string" || typeof e.code === "number" ? `${e.type} (code: ${e.code})` : e.type;
50472
+ }
50473
+ }
50474
+ return String(err);
50475
+ }
50459
50476
  function truncateMessageSafely(message, maxLength, truncationIndicator = "... (truncated)") {
50460
50477
  if (message.length <= maxLength)
50461
50478
  return message;
@@ -57487,7 +57504,7 @@ class MattermostPermissionApi {
57487
57504
  }
57488
57505
  };
57489
57506
  ws.onerror = (event) => {
57490
- mcpLogger.error(`WebSocket error: ${event}`);
57507
+ mcpLogger.error(`WebSocket error: ${formatWebSocketError(event)}`);
57491
57508
  if (!resolved) {
57492
57509
  resolved = true;
57493
57510
  clearTimeout(timeout);
@@ -57754,7 +57771,7 @@ class SlackPermissionApi {
57754
57771
  }
57755
57772
  };
57756
57773
  ws.onerror = (event) => {
57757
- mcpLogger.error(`Socket Mode WebSocket error: ${event}`);
57774
+ mcpLogger.error(`Socket Mode WebSocket error: ${formatWebSocketError(event)}`);
57758
57775
  if (!resolved) {
57759
57776
  resolved = true;
57760
57777
  clearTimeout(timeout);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-threads",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Share Claude Code sessions live in a Mattermost channel with interactive features",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",