claude-threads 1.40.1 → 1.40.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,14 @@ 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.40.2] - 2026-10-30
9
+
10
+ ### Changed
11
+ - `hono` 4.13.14, plus dev tooling (#655, #656).
12
+
13
+ ### Fixed
14
+ - **Auto-update respects `engines`.** The updater now skips a release this host's Node or Bun cannot run, logs why, and `!update` says so instead of reporting "Up to date". npm only warns about `engines`, so an update used to install anyway. A host that is held back gets no further releases until its runtime is upgraded (#659).
15
+
8
16
  ## [1.40.1] - 2026-10-30
9
17
 
10
18
  ### Added
package/dist/index.js CHANGED
@@ -67430,6 +67430,11 @@ async function showUpdateStatus(session, updateManager, ctx) {
67430
67430
  }
67431
67431
  const updateInfo = await updateManager.checkNow();
67432
67432
  if (!updateInfo || !updateInfo.available) {
67433
+ const blocked = updateManager.getBlockedUpdate();
67434
+ if (blocked) {
67435
+ await post(session, "warning", `${formatter.formatBold(`v${blocked.latestVersion} is available but not installable`)}: ${blocked.reason}`);
67436
+ return;
67437
+ }
67433
67438
  await post(session, "success", `${formatter.formatBold("Up to date")} - no updates available`);
67434
67439
  return;
67435
67440
  }
@@ -67463,7 +67468,8 @@ async function forceUpdateNow(session, username, updateManager) {
67463
67468
  }
67464
67469
  const updateInfo = await updateManager.checkNow();
67465
67470
  if (!updateInfo || !updateInfo.available) {
67466
- await post(session, "info", `No update available to install`);
67471
+ const blocked = updateManager.getBlockedUpdate();
67472
+ await post(session, "info", blocked ? `Not installing v${blocked.latestVersion}: ${blocked.reason}` : `No update available to install`);
67467
67473
  return;
67468
67474
  }
67469
67475
  await post(session, "info", `\uD83D\uDD04 ${formatter.formatBold("Forcing update")} to v${updateInfo.latestVersion} - restarting shortly...
@@ -74829,7 +74835,8 @@ class SessionManager extends EventEmitter4 {
74829
74835
  }
74830
74836
  const updateInfo = await this.autoUpdateManager.checkNow();
74831
74837
  if (!updateInfo || !updateInfo.available) {
74832
- await platform.createPost(`✅ ${formatter.formatBold("Up to date")} - no updates available`, threadId);
74838
+ const blocked = this.autoUpdateManager.getBlockedUpdate();
74839
+ await platform.createPost(blocked ? `⚠️ ${formatter.formatBold(`v${blocked.latestVersion} is available but not installable`)}: ${blocked.reason}` : `✅ ${formatter.formatBold("Up to date")} - no updates available`, threadId);
74833
74840
  return;
74834
74841
  }
74835
74842
  const scheduledAt = this.autoUpdateManager.getScheduledRestartAt();
@@ -89801,6 +89808,7 @@ import { EventEmitter as EventEmitter9 } from "events";
89801
89808
 
89802
89809
  // src/auto-update/checker.ts
89803
89810
  init_logger();
89811
+ var import_semver5 = __toESM(require_semver2(), 1);
89804
89812
  import { EventEmitter as EventEmitter7 } from "events";
89805
89813
  var log54 = createLogger("checker");
89806
89814
  var PACKAGE_NAME = "claude-threads";
@@ -89817,7 +89825,16 @@ function compareVersions(a, b) {
89817
89825
  }
89818
89826
  return 0;
89819
89827
  }
89820
- async function fetchLatestVersion() {
89828
+ function unmetEngine(engines, versions = process.versions) {
89829
+ const [runtime, running] = versions.bun ? ["bun", versions.bun] : ["node", versions.node];
89830
+ const required = engines?.[runtime];
89831
+ if (!required || !import_semver5.validRange(required))
89832
+ return null;
89833
+ if (import_semver5.satisfies(running, required, { includePrerelease: true }))
89834
+ return null;
89835
+ return `requires ${runtime} ${required}, this host runs ${running}`;
89836
+ }
89837
+ async function fetchLatestRelease() {
89821
89838
  try {
89822
89839
  const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {
89823
89840
  headers: {
@@ -89829,7 +89846,7 @@ async function fetchLatestVersion() {
89829
89846
  return null;
89830
89847
  }
89831
89848
  const data = await response.json();
89832
- return data.version ?? null;
89849
+ return data.version ? { version: data.version, engines: data.engines } : null;
89833
89850
  } catch (err) {
89834
89851
  log54.warn(`Failed to fetch latest version: ${err}`);
89835
89852
  return null;
@@ -89841,6 +89858,7 @@ class UpdateChecker extends EventEmitter7 {
89841
89858
  checkInterval = null;
89842
89859
  lastCheck = null;
89843
89860
  lastUpdateInfo = null;
89861
+ blockedUpdate = null;
89844
89862
  isChecking = false;
89845
89863
  constructor(config) {
89846
89864
  super();
@@ -89880,14 +89898,25 @@ class UpdateChecker extends EventEmitter7 {
89880
89898
  this.emit("check:start");
89881
89899
  try {
89882
89900
  log54.debug("Checking for updates...");
89883
- const latestVersion = await fetchLatestVersion();
89884
- if (!latestVersion) {
89901
+ const latest = await fetchLatestRelease();
89902
+ if (!latest) {
89885
89903
  this.emit("check:complete", false);
89886
89904
  return null;
89887
89905
  }
89888
89906
  this.lastCheck = new Date;
89907
+ const latestVersion = latest.version;
89889
89908
  const currentVersion = VERSION;
89890
89909
  const hasUpdate = compareVersions(latestVersion, currentVersion) > 0;
89910
+ const blockedReason = hasUpdate ? unmetEngine(latest.engines) : null;
89911
+ if (blockedReason) {
89912
+ if (this.blockedUpdate?.latestVersion !== latestVersion) {
89913
+ log54.warn(`⚠️ Not updating to v${latestVersion}: ${blockedReason}`);
89914
+ }
89915
+ this.blockedUpdate = { latestVersion, reason: blockedReason };
89916
+ this.emit("check:complete", false);
89917
+ return null;
89918
+ }
89919
+ this.blockedUpdate = null;
89891
89920
  if (hasUpdate) {
89892
89921
  const updateInfo = {
89893
89922
  available: true,
@@ -89917,6 +89946,9 @@ class UpdateChecker extends EventEmitter7 {
89917
89946
  getLastUpdateInfo() {
89918
89947
  return this.lastUpdateInfo;
89919
89948
  }
89949
+ getBlockedUpdate() {
89950
+ return this.blockedUpdate;
89951
+ }
89920
89952
  getLastCheckTime() {
89921
89953
  return this.lastCheck;
89922
89954
  }
@@ -90624,6 +90656,9 @@ class AutoUpdateManager extends EventEmitter9 {
90624
90656
  getUpdateInfo() {
90625
90657
  return this.state.updateInfo;
90626
90658
  }
90659
+ getBlockedUpdate() {
90660
+ return this.checker.getBlockedUpdate();
90661
+ }
90627
90662
  getScheduledRestartAt() {
90628
90663
  return this.scheduler.getScheduledRestartAt();
90629
90664
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-threads",
3
- "version": "1.40.1",
3
+ "version": "1.40.2",
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",
@@ -78,7 +78,7 @@
78
78
  "cross-spawn": "^7.0.6",
79
79
  "diff": "^8.0.3",
80
80
  "express-rate-limit": "^8.7.1",
81
- "hono": "4.13.13",
81
+ "hono": "4.13.14",
82
82
  "ink": "^8.0.0",
83
83
  "js-yaml": "^4.3.1",
84
84
  "prompts": "^2.4.2",
@@ -101,7 +101,7 @@
101
101
  "@types/ws": "^8.18.2",
102
102
  "eslint": "^10.13.0",
103
103
  "husky": "^9.1.7",
104
- "knip": "6.41.0",
104
+ "knip": "6.43.0",
105
105
  "lint-staged": "^17.0.4",
106
106
  "prettier": "^3.9.10",
107
107
  "react-devtools-core": "^8.0.0",