@tractorscorch/clank 1.4.7 → 1.4.8
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 +8 -0
- package/README.md +2 -2
- package/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [1.4.8] — 2026-03-22
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **Model hangs permanently after tool calls** — provider timeout was bypassed when the engine passed its own AbortSignal (always); now uses `AbortSignal.any()` to combine the caller's signal with a hard 120s timeout so hung models are detected and reported instead of blocking forever
|
|
13
|
+
- **No retry on timeout** — engine no longer retries when a model times out (was doubling the wait to 240s with no chance of success); timeouts propagate immediately as errors
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
9
17
|
## [1.4.7] — 2026-03-22
|
|
10
18
|
|
|
11
19
|
### 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.8-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.8_macos](https://github.com/ItsTrag1c/Clank/releases/latest/download/Clank_1.4.8_macos) |
|
|
79
79
|
|
|
80
80
|
## Features
|
|
81
81
|
|
package/dist/index.js
CHANGED
|
@@ -561,7 +561,8 @@ var init_ollama = __esm({
|
|
|
561
561
|
if (this.maxResponseTokens) {
|
|
562
562
|
body.max_tokens = this.maxResponseTokens;
|
|
563
563
|
}
|
|
564
|
-
const
|
|
564
|
+
const timeoutSignal = AbortSignal.timeout(12e4);
|
|
565
|
+
const effectiveSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
565
566
|
const res = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
566
567
|
method: "POST",
|
|
567
568
|
headers: { "Content-Type": "application/json" },
|
|
@@ -947,7 +948,8 @@ var init_agent = __esm({
|
|
|
947
948
|
streamSuccess = true;
|
|
948
949
|
break;
|
|
949
950
|
} catch (streamErr) {
|
|
950
|
-
|
|
951
|
+
const isTimeout = streamErr instanceof Error && (streamErr.name === "TimeoutError" || streamErr.name === "AbortError" || streamErr.message.includes("timed out"));
|
|
952
|
+
if (attempt === 0 && !signal.aborted && !isTimeout) {
|
|
951
953
|
this.emit("error", {
|
|
952
954
|
message: `Model connection failed, retrying... (${streamErr instanceof Error ? streamErr.message : "unknown"})`,
|
|
953
955
|
recoverable: true
|
|
@@ -2757,7 +2759,8 @@ var init_anthropic = __esm({
|
|
|
2757
2759
|
if (tools.length > 0) {
|
|
2758
2760
|
body.tools = this.formatTools(tools);
|
|
2759
2761
|
}
|
|
2760
|
-
const
|
|
2762
|
+
const timeoutSignal = AbortSignal.timeout(9e4);
|
|
2763
|
+
const effectiveSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
2761
2764
|
const res = await fetch(`${this.baseUrl}/v1/messages`, {
|
|
2762
2765
|
method: "POST",
|
|
2763
2766
|
headers: {
|
|
@@ -2984,7 +2987,8 @@ var init_openai = __esm({
|
|
|
2984
2987
|
if (this.apiKey) {
|
|
2985
2988
|
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
2986
2989
|
}
|
|
2987
|
-
const
|
|
2990
|
+
const timeoutSignal = AbortSignal.timeout(9e4);
|
|
2991
|
+
const effectiveSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
2988
2992
|
const res = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
2989
2993
|
method: "POST",
|
|
2990
2994
|
headers,
|
|
@@ -3211,7 +3215,8 @@ var init_google = __esm({
|
|
|
3211
3215
|
body.tools = this.formatTools(tools);
|
|
3212
3216
|
}
|
|
3213
3217
|
const url = `https://generativelanguage.googleapis.com/v1beta/models/${this.model}:streamGenerateContent?key=${this.apiKey}&alt=sse`;
|
|
3214
|
-
const
|
|
3218
|
+
const timeoutSignal = AbortSignal.timeout(9e4);
|
|
3219
|
+
const effectiveSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
3215
3220
|
const res = await fetch(url, {
|
|
3216
3221
|
method: "POST",
|
|
3217
3222
|
headers: { "Content-Type": "application/json" },
|
|
@@ -6126,7 +6131,7 @@ var init_server = __esm({
|
|
|
6126
6131
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
6127
6132
|
res.end(JSON.stringify({
|
|
6128
6133
|
status: "ok",
|
|
6129
|
-
version: "1.4.
|
|
6134
|
+
version: "1.4.8",
|
|
6130
6135
|
uptime: process.uptime(),
|
|
6131
6136
|
clients: this.clients.size,
|
|
6132
6137
|
agents: this.engines.size
|
|
@@ -6238,7 +6243,7 @@ var init_server = __esm({
|
|
|
6238
6243
|
const hello = {
|
|
6239
6244
|
type: "hello",
|
|
6240
6245
|
protocol: PROTOCOL_VERSION,
|
|
6241
|
-
version: "1.4.
|
|
6246
|
+
version: "1.4.8",
|
|
6242
6247
|
agents: this.config.agents.list.map((a) => ({
|
|
6243
6248
|
id: a.id,
|
|
6244
6249
|
name: a.name || a.id,
|
|
@@ -7632,7 +7637,7 @@ async function runTui(opts) {
|
|
|
7632
7637
|
ws.on("open", () => {
|
|
7633
7638
|
ws.send(JSON.stringify({
|
|
7634
7639
|
type: "connect",
|
|
7635
|
-
params: { auth: { token }, mode: "tui", version: "1.4.
|
|
7640
|
+
params: { auth: { token }, mode: "tui", version: "1.4.8" }
|
|
7636
7641
|
}));
|
|
7637
7642
|
});
|
|
7638
7643
|
ws.on("message", (data) => {
|
|
@@ -8061,7 +8066,7 @@ import { fileURLToPath as fileURLToPath5 } from "url";
|
|
|
8061
8066
|
import { dirname as dirname5, join as join19 } from "path";
|
|
8062
8067
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
8063
8068
|
var __dirname3 = dirname5(__filename3);
|
|
8064
|
-
var version = "1.4.
|
|
8069
|
+
var version = "1.4.8";
|
|
8065
8070
|
try {
|
|
8066
8071
|
const pkg = JSON.parse(readFileSync(join19(__dirname3, "..", "package.json"), "utf-8"));
|
|
8067
8072
|
version = pkg.version;
|