@tractorscorch/clank 1.4.3 → 1.4.4

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
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
6
6
 
7
7
  ---
8
8
 
9
+ ## [1.4.4] — 2026-03-22
10
+
11
+ ### Fixed
12
+ - **Gateway crash after 4-5 messages** — confirmation handler WebSocket listeners were never removed on timeout, accumulating orphaned handlers per message until the process crashed
13
+ - **Engine listener limit** — set `maxListeners` to 30 on AgentEngine (Node.js default of 10 was too low since each message cycle wires 10 event listeners)
14
+ - **Rate limiter memory leak** — stale session entries in the rate limiter Map were never purged; added periodic cleanup when map exceeds 100 entries
15
+
16
+ ---
17
+
9
18
  ## [1.4.3] — 2026-03-22
10
19
 
11
20
  ### Fixed
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <a href="https://github.com/ItsTrag1c/Clank/releases/latest"><img src="https://img.shields.io/badge/version-1.4.3-blue.svg" alt="Version" /></a>
12
+ <a href="https://github.com/ItsTrag1c/Clank/releases/latest"><img src="https://img.shields.io/badge/version-1.4.4-blue.svg" alt="Version" /></a>
13
13
  <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License" /></a>
14
14
  <a href="https://www.npmjs.com/package/@tractorscorch/clank"><img src="https://img.shields.io/npm/v/@tractorscorch/clank.svg" alt="npm" /></a>
15
15
  <a href="https://github.com/ItsTrag1c/Clank/stargazers"><img src="https://img.shields.io/github/stars/ItsTrag1c/Clank.svg" alt="Stars" /></a>
@@ -75,7 +75,7 @@ That's it. Setup auto-detects your local models, configures the gateway, and get
75
75
  | Platform | Download |
76
76
  |----------|----------|
77
77
  | **npm** (all platforms) | `npm install -g @tractorscorch/clank` |
78
- | **macOS** (Apple Silicon) | [Clank_1.4.3_macos](https://github.com/ItsTrag1c/Clank/releases/latest/download/Clank_1.4.3_macos) |
78
+ | **macOS** (Apple Silicon) | [Clank_1.4.4_macos](https://github.com/ItsTrag1c/Clank/releases/latest/download/Clank_1.4.4_macos) |
79
79
 
80
80
  ## Features
81
81
 
package/dist/index.js CHANGED
@@ -764,6 +764,7 @@ var init_agent = __esm({
764
764
  alwaysApproved = /* @__PURE__ */ new Set();
765
765
  constructor(opts) {
766
766
  super();
767
+ this.setMaxListeners(30);
767
768
  this.identity = opts.identity;
768
769
  this.toolRegistry = opts.toolRegistry;
769
770
  this.sessionStore = opts.sessionStore;
@@ -6056,7 +6057,7 @@ var init_server = __esm({
6056
6057
  res.writeHead(200, { "Content-Type": "application/json" });
6057
6058
  res.end(JSON.stringify({
6058
6059
  status: "ok",
6059
- version: "1.4.3",
6060
+ version: "1.4.4",
6060
6061
  uptime: process.uptime(),
6061
6062
  clients: this.clients.size,
6062
6063
  agents: this.engines.size
@@ -6164,7 +6165,7 @@ var init_server = __esm({
6164
6165
  const hello = {
6165
6166
  type: "hello",
6166
6167
  protocol: PROTOCOL_VERSION,
6167
- version: "1.4.3",
6168
+ version: "1.4.4",
6168
6169
  agents: this.config.agents.list.map((a) => ({
6169
6170
  id: a.id,
6170
6171
  name: a.name || a.id,
@@ -6363,6 +6364,13 @@ var init_server = __esm({
6363
6364
  const recent = timestamps.filter((t) => now - t < this.RATE_LIMIT_WINDOW);
6364
6365
  recent.push(now);
6365
6366
  this.rateLimiter.set(sessionKey, recent);
6367
+ if (this.rateLimiter.size > 100) {
6368
+ for (const [key, ts] of this.rateLimiter) {
6369
+ if (ts.length === 0 || now - ts[ts.length - 1] > this.RATE_LIMIT_WINDOW * 2) {
6370
+ this.rateLimiter.delete(key);
6371
+ }
6372
+ }
6373
+ }
6366
6374
  return recent.length > this.RATE_LIMIT_MAX;
6367
6375
  }
6368
6376
  /** Cancel current request for a client */
@@ -6448,7 +6456,6 @@ var init_server = __esm({
6448
6456
  }
6449
6457
  const confirmId = `confirm_${Date.now()}`;
6450
6458
  this.sendEvent(client, "confirm-needed", { id: confirmId, actions });
6451
- const timeout = setTimeout(() => resolve4(false), 3e4);
6452
6459
  const resolveHandler = (raw) => {
6453
6460
  const frame = parseFrame(raw.toString());
6454
6461
  if (frame?.type === "req" && frame.method === "confirm.resolve") {
@@ -6461,6 +6468,10 @@ var init_server = __esm({
6461
6468
  }
6462
6469
  };
6463
6470
  client.ws.on("message", resolveHandler);
6471
+ const timeout = setTimeout(() => {
6472
+ client.ws.removeListener("message", resolveHandler);
6473
+ resolve4(false);
6474
+ }, 3e4);
6464
6475
  };
6465
6476
  engine.on("confirm-needed", confirmListener);
6466
6477
  listeners.push(["confirm-needed", confirmListener]);
@@ -7548,7 +7559,7 @@ async function runTui(opts) {
7548
7559
  ws.on("open", () => {
7549
7560
  ws.send(JSON.stringify({
7550
7561
  type: "connect",
7551
- params: { auth: { token }, mode: "tui", version: "1.4.3" }
7562
+ params: { auth: { token }, mode: "tui", version: "1.4.4" }
7552
7563
  }));
7553
7564
  });
7554
7565
  ws.on("message", (data) => {
@@ -7977,7 +7988,7 @@ import { fileURLToPath as fileURLToPath5 } from "url";
7977
7988
  import { dirname as dirname5, join as join19 } from "path";
7978
7989
  var __filename3 = fileURLToPath5(import.meta.url);
7979
7990
  var __dirname3 = dirname5(__filename3);
7980
- var version = "1.4.3";
7991
+ var version = "1.4.4";
7981
7992
  try {
7982
7993
  const pkg = JSON.parse(readFileSync(join19(__dirname3, "..", "package.json"), "utf-8"));
7983
7994
  version = pkg.version;