@tractorscorch/clank 1.4.4 → 1.4.6
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/README.md +2 -2
- package/dist/index.js +36 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [1.4.6] — 2026-03-22
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **Telegram stutter (for real)** — when the model responds fast, the initial `sendMessage` promise hasn't resolved by the time the full response is ready, causing a duplicate message via the fallback path; now waits for the in-flight message ID before falling back
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## [1.4.5] — 2026-03-22
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- **Gateway unresponsive after messages** — WebSocket frame handler was not awaited, causing unhandled promise rejections that silently killed the gateway process
|
|
20
|
+
- **Added `unhandledRejection` handler** — gateway now logs rejected promises instead of dying silently
|
|
21
|
+
- **Provider timeout fallback** — all providers (Ollama, Anthropic, OpenAI, Google) now have a fallback timeout (120s local, 90s cloud) if no abort signal is provided, preventing indefinite hangs when a model is unresponsive
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
9
25
|
## [1.4.4] — 2026-03-22
|
|
10
26
|
|
|
11
27
|
### 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.
|
|
12
|
+
<a href="https://github.com/ItsTrag1c/Clank/releases/latest"><img src="https://img.shields.io/badge/version-1.4.6-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.
|
|
78
|
+
| **macOS** (Apple Silicon) | [Clank_1.4.6_macos](https://github.com/ItsTrag1c/Clank/releases/latest/download/Clank_1.4.6_macos) |
|
|
79
79
|
|
|
80
80
|
## Features
|
|
81
81
|
|
package/dist/index.js
CHANGED
|
@@ -513,11 +513,12 @@ var init_ollama = __esm({
|
|
|
513
513
|
if (this.maxResponseTokens) {
|
|
514
514
|
body.max_tokens = this.maxResponseTokens;
|
|
515
515
|
}
|
|
516
|
+
const effectiveSignal = signal || AbortSignal.timeout(12e4);
|
|
516
517
|
const res = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
517
518
|
method: "POST",
|
|
518
519
|
headers: { "Content-Type": "application/json" },
|
|
519
520
|
body: JSON.stringify(body),
|
|
520
|
-
signal
|
|
521
|
+
signal: effectiveSignal
|
|
521
522
|
});
|
|
522
523
|
if (!res.ok) {
|
|
523
524
|
const text = await res.text().catch(() => "Unknown error");
|
|
@@ -2708,6 +2709,7 @@ var init_anthropic = __esm({
|
|
|
2708
2709
|
if (tools.length > 0) {
|
|
2709
2710
|
body.tools = this.formatTools(tools);
|
|
2710
2711
|
}
|
|
2712
|
+
const effectiveSignal = signal || AbortSignal.timeout(9e4);
|
|
2711
2713
|
const res = await fetch(`${this.baseUrl}/v1/messages`, {
|
|
2712
2714
|
method: "POST",
|
|
2713
2715
|
headers: {
|
|
@@ -2716,7 +2718,7 @@ var init_anthropic = __esm({
|
|
|
2716
2718
|
"anthropic-version": "2023-06-01"
|
|
2717
2719
|
},
|
|
2718
2720
|
body: JSON.stringify(body),
|
|
2719
|
-
signal
|
|
2721
|
+
signal: effectiveSignal
|
|
2720
2722
|
});
|
|
2721
2723
|
if (!res.ok) {
|
|
2722
2724
|
const text = await res.text().catch(() => "Unknown error");
|
|
@@ -2934,11 +2936,12 @@ var init_openai = __esm({
|
|
|
2934
2936
|
if (this.apiKey) {
|
|
2935
2937
|
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
2936
2938
|
}
|
|
2939
|
+
const effectiveSignal = signal || AbortSignal.timeout(9e4);
|
|
2937
2940
|
const res = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
2938
2941
|
method: "POST",
|
|
2939
2942
|
headers,
|
|
2940
2943
|
body: JSON.stringify(body),
|
|
2941
|
-
signal
|
|
2944
|
+
signal: effectiveSignal
|
|
2942
2945
|
});
|
|
2943
2946
|
if (!res.ok) {
|
|
2944
2947
|
const text = await res.text().catch(() => "Unknown error");
|
|
@@ -3160,11 +3163,12 @@ var init_google = __esm({
|
|
|
3160
3163
|
body.tools = this.formatTools(tools);
|
|
3161
3164
|
}
|
|
3162
3165
|
const url = `https://generativelanguage.googleapis.com/v1beta/models/${this.model}:streamGenerateContent?key=${this.apiKey}&alt=sse`;
|
|
3166
|
+
const effectiveSignal = signal || AbortSignal.timeout(9e4);
|
|
3163
3167
|
const res = await fetch(url, {
|
|
3164
3168
|
method: "POST",
|
|
3165
3169
|
headers: { "Content-Type": "application/json" },
|
|
3166
3170
|
body: JSON.stringify(body),
|
|
3167
|
-
signal
|
|
3171
|
+
signal: effectiveSignal
|
|
3168
3172
|
});
|
|
3169
3173
|
if (!res.ok) {
|
|
3170
3174
|
const text = await res.text().catch(() => "Unknown error");
|
|
@@ -5271,6 +5275,20 @@ var init_telegram = __esm({
|
|
|
5271
5275
|
}
|
|
5272
5276
|
}
|
|
5273
5277
|
);
|
|
5278
|
+
if (sendingInitial && !streamMsgId) {
|
|
5279
|
+
await new Promise((r) => {
|
|
5280
|
+
const check2 = setInterval(() => {
|
|
5281
|
+
if (streamMsgId) {
|
|
5282
|
+
clearInterval(check2);
|
|
5283
|
+
r();
|
|
5284
|
+
}
|
|
5285
|
+
}, 50);
|
|
5286
|
+
setTimeout(() => {
|
|
5287
|
+
clearInterval(check2);
|
|
5288
|
+
r();
|
|
5289
|
+
}, 3e3);
|
|
5290
|
+
});
|
|
5291
|
+
}
|
|
5274
5292
|
if (streamMsgId && response) {
|
|
5275
5293
|
const finalText = response.length > 4e3 ? response.slice(0, 3950) + "\n... (truncated)" : response;
|
|
5276
5294
|
await bot.api.editMessageText(chatId, streamMsgId, finalText).catch(() => {
|
|
@@ -5893,6 +5911,9 @@ var init_server = __esm({
|
|
|
5893
5911
|
}
|
|
5894
5912
|
/** Start the gateway server */
|
|
5895
5913
|
async start() {
|
|
5914
|
+
process.on("unhandledRejection", (err) => {
|
|
5915
|
+
console.error(` Unhandled rejection: ${err instanceof Error ? err.message : err}`);
|
|
5916
|
+
});
|
|
5896
5917
|
if (this.config.gateway.auth.mode === "token" && !this.config.gateway.auth.token) {
|
|
5897
5918
|
const { randomBytes: randomBytes2 } = await import("crypto");
|
|
5898
5919
|
this.config.gateway.auth.token = randomBytes2(16).toString("hex");
|
|
@@ -6057,7 +6078,7 @@ var init_server = __esm({
|
|
|
6057
6078
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
6058
6079
|
res.end(JSON.stringify({
|
|
6059
6080
|
status: "ok",
|
|
6060
|
-
version: "1.4.
|
|
6081
|
+
version: "1.4.6",
|
|
6061
6082
|
uptime: process.uptime(),
|
|
6062
6083
|
clients: this.clients.size,
|
|
6063
6084
|
agents: this.engines.size
|
|
@@ -6118,7 +6139,11 @@ var init_server = __esm({
|
|
|
6118
6139
|
this.clients.set(ws, client);
|
|
6119
6140
|
ws.on("message", (data) => {
|
|
6120
6141
|
const frame = parseFrame(data.toString());
|
|
6121
|
-
if (frame)
|
|
6142
|
+
if (frame) {
|
|
6143
|
+
this.handleFrame(client, frame).catch((err) => {
|
|
6144
|
+
console.error(` Frame handler error: ${err instanceof Error ? err.message : err}`);
|
|
6145
|
+
});
|
|
6146
|
+
}
|
|
6122
6147
|
});
|
|
6123
6148
|
ws.on("close", () => {
|
|
6124
6149
|
this.clients.delete(ws);
|
|
@@ -6165,7 +6190,7 @@ var init_server = __esm({
|
|
|
6165
6190
|
const hello = {
|
|
6166
6191
|
type: "hello",
|
|
6167
6192
|
protocol: PROTOCOL_VERSION,
|
|
6168
|
-
version: "1.4.
|
|
6193
|
+
version: "1.4.6",
|
|
6169
6194
|
agents: this.config.agents.list.map((a) => ({
|
|
6170
6195
|
id: a.id,
|
|
6171
6196
|
name: a.name || a.id,
|
|
@@ -7559,7 +7584,7 @@ async function runTui(opts) {
|
|
|
7559
7584
|
ws.on("open", () => {
|
|
7560
7585
|
ws.send(JSON.stringify({
|
|
7561
7586
|
type: "connect",
|
|
7562
|
-
params: { auth: { token }, mode: "tui", version: "1.4.
|
|
7587
|
+
params: { auth: { token }, mode: "tui", version: "1.4.6" }
|
|
7563
7588
|
}));
|
|
7564
7589
|
});
|
|
7565
7590
|
ws.on("message", (data) => {
|
|
@@ -7861,14 +7886,14 @@ async function runUpdate() {
|
|
|
7861
7886
|
}
|
|
7862
7887
|
console.log(dim9(" Pulling latest version..."));
|
|
7863
7888
|
try {
|
|
7864
|
-
const output = execSync2("npm install -g @tractorscorch/clank@latest --force", {
|
|
7889
|
+
const output = execSync2("npm install -g @tractorscorch/clank@latest --force --prefer-online", {
|
|
7865
7890
|
encoding: "utf-8",
|
|
7866
7891
|
timeout: 12e4
|
|
7867
7892
|
});
|
|
7868
7893
|
console.log(dim9(` ${output.trim()}`));
|
|
7869
7894
|
} catch (err) {
|
|
7870
7895
|
console.error(red6(` Update failed: ${err instanceof Error ? err.message : err}`));
|
|
7871
|
-
console.error(dim9(" Try manually: npm install -g @tractorscorch/clank@latest --force"));
|
|
7896
|
+
console.error(dim9(" Try manually: npm install -g @tractorscorch/clank@latest --force --prefer-online"));
|
|
7872
7897
|
return;
|
|
7873
7898
|
}
|
|
7874
7899
|
try {
|
|
@@ -7988,7 +8013,7 @@ import { fileURLToPath as fileURLToPath5 } from "url";
|
|
|
7988
8013
|
import { dirname as dirname5, join as join19 } from "path";
|
|
7989
8014
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
7990
8015
|
var __dirname3 = dirname5(__filename3);
|
|
7991
|
-
var version = "1.4.
|
|
8016
|
+
var version = "1.4.6";
|
|
7992
8017
|
try {
|
|
7993
8018
|
const pkg = JSON.parse(readFileSync(join19(__dirname3, "..", "package.json"), "utf-8"));
|
|
7994
8019
|
version = pkg.version;
|