@tractorscorch/clank 1.5.1 → 1.5.3

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,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
6
6
 
7
7
  ---
8
8
 
9
+ ## [1.5.3] — 2026-03-23
10
+
11
+ ### Fixed
12
+ - **Local thinking models return empty responses** — Qwen3.5 puts all output in `reasoning_content` with empty `content`, and `enable_thinking:false` doesn't work (chat template overrides it). Now treats `reasoning_content` as text for local models so the user actually sees a response
13
+
14
+ ---
15
+
16
+ ## [1.5.2] — 2026-03-23
17
+
18
+ ### Fixed
19
+ - **Thinking models (Qwen3.5) exhaust tokens on reasoning** — the model generates `<think>` reasoning tokens that eat the entire context window, leaving nothing for actual content. Added default `max_tokens: 4096` for local models and `reasoning_effort: "low"` to reduce thinking overhead
20
+ - **Telegram shows nothing during model thinking** — added periodic "typing" indicator every 4 seconds so the bot doesn't appear dead while the model processes internally
21
+ - **Root cause found via direct API testing** — Qwen3.5-35B returns empty `content` with all output in `reasoning_content`; without a max_tokens cap, the model spends all its budget on thinking
22
+
23
+ ---
24
+
9
25
  ## [1.5.1] — 2026-03-23
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.5.1-blue.svg" alt="Version" /></a>
12
+ <a href="https://github.com/ItsTrag1c/Clank/releases/latest"><img src="https://img.shields.io/badge/version-1.5.3-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.5.1_macos](https://github.com/ItsTrag1c/Clank/releases/latest/download/Clank_1.5.1_macos) |
78
+ | **macOS** (Apple Silicon) | [Clank_1.5.3_macos](https://github.com/ItsTrag1c/Clank/releases/latest/download/Clank_1.5.3_macos) |
79
79
 
80
80
  ## Features
81
81
 
package/dist/index.js CHANGED
@@ -2987,11 +2987,16 @@ var init_openai = __esm({
2987
2987
  stream: true,
2988
2988
  stream_options: { include_usage: true }
2989
2989
  };
2990
+ if (this.isLocal) {
2991
+ body.reasoning_effort = "low";
2992
+ }
2990
2993
  if (tools.length > 0) {
2991
2994
  body.tools = this.formatTools(tools);
2992
2995
  }
2993
2996
  if (this.maxResponseTokens) {
2994
2997
  body.max_tokens = this.maxResponseTokens;
2998
+ } else if (this.isLocal) {
2999
+ body.max_tokens = 4096;
2995
3000
  }
2996
3001
  const headers = {
2997
3002
  "Content-Type": "application/json"
@@ -3045,7 +3050,11 @@ var init_openai = __esm({
3045
3050
  const chunk = JSON.parse(data);
3046
3051
  const choice = chunk.choices?.[0];
3047
3052
  if (choice?.delta?.reasoning_content) {
3048
- yield { type: "thinking", content: choice.delta.reasoning_content };
3053
+ if (this.isLocal) {
3054
+ yield { type: "text", content: choice.delta.reasoning_content };
3055
+ } else {
3056
+ yield { type: "thinking", content: choice.delta.reasoning_content };
3057
+ }
3049
3058
  }
3050
3059
  if (choice?.delta?.content) {
3051
3060
  yield { type: "text", content: choice.delta.content };
@@ -5298,6 +5307,10 @@ var init_telegram = __esm({
5298
5307
  try {
5299
5308
  console.log(` Telegram: processing message from ${userId} in ${chatId}`);
5300
5309
  await ctx.api.sendChatAction(chatId, "typing");
5310
+ const typingInterval2 = setInterval(() => {
5311
+ bot.api.sendChatAction(chatId, "typing").catch(() => {
5312
+ });
5313
+ }, 4e3);
5301
5314
  let streamMsgId = null;
5302
5315
  let sendingInitial = false;
5303
5316
  let accumulated = "";
@@ -5366,8 +5379,10 @@ var init_telegram = __esm({
5366
5379
  await ctx.api.sendMessage(chatId, chunk);
5367
5380
  }
5368
5381
  }
5382
+ clearInterval(typingInterval2);
5369
5383
  console.log(` Telegram: response complete (${response?.length || 0} chars)`);
5370
5384
  } catch (err) {
5385
+ clearInterval(typingInterval);
5371
5386
  const errMsg = err instanceof Error ? err.message : String(err);
5372
5387
  console.error(` Telegram: message handler error \u2014 ${errMsg}`);
5373
5388
  await ctx.api.sendMessage(chatId, `Error: ${errMsg.slice(0, 200)}`).catch(() => {
@@ -6155,7 +6170,7 @@ var init_server = __esm({
6155
6170
  res.writeHead(200, { "Content-Type": "application/json" });
6156
6171
  res.end(JSON.stringify({
6157
6172
  status: "ok",
6158
- version: "1.5.1",
6173
+ version: "1.5.3",
6159
6174
  uptime: process.uptime(),
6160
6175
  clients: this.clients.size,
6161
6176
  agents: this.engines.size
@@ -6267,7 +6282,7 @@ var init_server = __esm({
6267
6282
  const hello = {
6268
6283
  type: "hello",
6269
6284
  protocol: PROTOCOL_VERSION,
6270
- version: "1.5.1",
6285
+ version: "1.5.3",
6271
6286
  agents: this.config.agents.list.map((a) => ({
6272
6287
  id: a.id,
6273
6288
  name: a.name || a.id,
@@ -7662,7 +7677,7 @@ async function runTui(opts) {
7662
7677
  ws.on("open", () => {
7663
7678
  ws.send(JSON.stringify({
7664
7679
  type: "connect",
7665
- params: { auth: { token }, mode: "tui", version: "1.5.1" }
7680
+ params: { auth: { token }, mode: "tui", version: "1.5.3" }
7666
7681
  }));
7667
7682
  });
7668
7683
  ws.on("message", (data) => {
@@ -8091,7 +8106,7 @@ import { fileURLToPath as fileURLToPath5 } from "url";
8091
8106
  import { dirname as dirname5, join as join19 } from "path";
8092
8107
  var __filename3 = fileURLToPath5(import.meta.url);
8093
8108
  var __dirname3 = dirname5(__filename3);
8094
- var version = "1.5.1";
8109
+ var version = "1.5.3";
8095
8110
  try {
8096
8111
  const pkg = JSON.parse(readFileSync(join19(__dirname3, "..", "package.json"), "utf-8"));
8097
8112
  version = pkg.version;