@tractorscorch/clank 1.5.7 → 1.5.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 CHANGED
@@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
6
6
 
7
7
  ---
8
8
 
9
+ ## [1.5.8] — 2026-03-23
10
+
11
+ ### Added
12
+ - **Collapsible thinking blocks** — model thinking/reasoning is now displayed in a separate clickable block above the response instead of being streamed into the message text. Click the "Thought" toggle to expand/collapse. Shows "Thinking..." while streaming, "Thought" when complete
13
+
14
+ ### Fixed
15
+ - **Thinking events were disconnected** — the full thinking pipeline (provider → agent → gateway → frontend) was broken at 3 points: provider yielded thinking as text for local models, agent only emitted a one-shot start event without content, and gateway didn't forward thinking events to clients. All 3 fixed
16
+ - **Empty responses from thinking-only models** — when a model puts all output in `reasoning_content` with empty `content` (Qwen3.5), the thinking text is now used as the response instead of showing a blank message
17
+
18
+ ---
19
+
9
20
  ## [1.5.7] — 2026-03-23
10
21
 
11
22
  ### 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.7-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.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.5.7_macos](https://github.com/ItsTrag1c/Clank/releases/latest/download/Clank_1.5.7_macos) |
78
+ | **macOS** (Apple Silicon) | [Clank_1.5.8_macos](https://github.com/ItsTrag1c/Clank/releases/latest/download/Clank_1.5.8_macos) |
79
79
 
80
80
  ## Features
81
81
 
package/dist/index.js CHANGED
@@ -934,6 +934,7 @@ var init_agent = __esm({
934
934
  denylist: this.identity.tools?.deny
935
935
  });
936
936
  let iterationText = "";
937
+ let thinkingText = "";
937
938
  const toolCalls = [];
938
939
  let promptTokens = 0;
939
940
  let outputTokens = 0;
@@ -942,6 +943,7 @@ var init_agent = __esm({
942
943
  for (let attempt = 0; attempt < 2; attempt++) {
943
944
  if (attempt > 0) {
944
945
  iterationText = "";
946
+ thinkingText = "";
945
947
  toolCalls.length = 0;
946
948
  promptTokens = 0;
947
949
  outputTokens = 0;
@@ -960,7 +962,8 @@ var init_agent = __esm({
960
962
  this.emit("token", { content: event.content });
961
963
  break;
962
964
  case "thinking":
963
- this.emit("thinking-start");
965
+ thinkingText += event.content;
966
+ this.emit("thinking", { content: event.content });
964
967
  break;
965
968
  case "tool_call":
966
969
  toolCalls.push({
@@ -1005,6 +1008,10 @@ var init_agent = __esm({
1005
1008
  contextPercent: Math.round(this.contextEngine.utilizationPercent())
1006
1009
  });
1007
1010
  if (toolCalls.length === 0) {
1011
+ if (!iterationText && thinkingText) {
1012
+ iterationText = thinkingText;
1013
+ this.emit("token", { content: iterationText });
1014
+ }
1008
1015
  fullResponse = iterationText;
1009
1016
  this.contextEngine.ingest({ role: "assistant", content: iterationText });
1010
1017
  this.emit("response-end", { text: iterationText });
@@ -3112,11 +3119,7 @@ var init_openai = __esm({
3112
3119
  }
3113
3120
  if (choice?.delta?.reasoning_content) {
3114
3121
  hasContent = true;
3115
- if (this.isLocal) {
3116
- yield { type: "text", content: choice.delta.reasoning_content };
3117
- } else {
3118
- yield { type: "thinking", content: choice.delta.reasoning_content };
3119
- }
3122
+ yield { type: "thinking", content: choice.delta.reasoning_content };
3120
3123
  }
3121
3124
  if (choice?.delta?.content) {
3122
3125
  hasContent = true;
@@ -6242,7 +6245,7 @@ var init_server = __esm({
6242
6245
  res.writeHead(200, { "Content-Type": "application/json" });
6243
6246
  res.end(JSON.stringify({
6244
6247
  status: "ok",
6245
- version: "1.5.7",
6248
+ version: "1.5.8",
6246
6249
  uptime: process.uptime(),
6247
6250
  clients: this.clients.size,
6248
6251
  agents: this.engines.size
@@ -6354,7 +6357,7 @@ var init_server = __esm({
6354
6357
  const hello = {
6355
6358
  type: "hello",
6356
6359
  protocol: PROTOCOL_VERSION,
6357
- version: "1.5.7",
6360
+ version: "1.5.8",
6358
6361
  agents: this.config.agents.list.map((a) => ({
6359
6362
  id: a.id,
6360
6363
  name: a.name || a.id,
@@ -6619,6 +6622,7 @@ var init_server = __esm({
6619
6622
  wireEngineEvents(engine, client) {
6620
6623
  const eventMap = {
6621
6624
  "token": "token",
6625
+ "thinking": "thinking",
6622
6626
  "response-start": "response-start",
6623
6627
  "response-end": "response-end",
6624
6628
  "tool-start": "tool-start",
@@ -7749,7 +7753,7 @@ async function runTui(opts) {
7749
7753
  ws.on("open", () => {
7750
7754
  ws.send(JSON.stringify({
7751
7755
  type: "connect",
7752
- params: { auth: { token }, mode: "tui", version: "1.5.7" }
7756
+ params: { auth: { token }, mode: "tui", version: "1.5.8" }
7753
7757
  }));
7754
7758
  });
7755
7759
  ws.on("message", (data) => {
@@ -8178,7 +8182,7 @@ import { fileURLToPath as fileURLToPath5 } from "url";
8178
8182
  import { dirname as dirname5, join as join19 } from "path";
8179
8183
  var __filename3 = fileURLToPath5(import.meta.url);
8180
8184
  var __dirname3 = dirname5(__filename3);
8181
- var version = "1.5.7";
8185
+ var version = "1.5.8";
8182
8186
  try {
8183
8187
  const pkg = JSON.parse(readFileSync(join19(__dirname3, "..", "package.json"), "utf-8"));
8184
8188
  version = pkg.version;