@bike4mind/cli 0.2.49-feat-cli-multiline-input.21032 → 0.2.49-fix-cli-stream-resilience.21033

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.
@@ -3,7 +3,7 @@
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@bike4mind/cli",
6
- version: "0.2.49-feat-cli-multiline-input.21032+23042ba16",
6
+ version: "0.2.49-fix-cli-stream-resilience.21033+09a303405",
7
7
  type: "module",
8
8
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
9
9
  license: "UNLICENSED",
@@ -118,10 +118,10 @@ var package_default = {
118
118
  },
119
119
  devDependencies: {
120
120
  "@bike4mind/agents": "0.1.0",
121
- "@bike4mind/common": "2.67.1-feat-cli-multiline-input.21032+23042ba16",
122
- "@bike4mind/mcp": "1.33.11-feat-cli-multiline-input.21032+23042ba16",
123
- "@bike4mind/services": "2.63.1-feat-cli-multiline-input.21032+23042ba16",
124
- "@bike4mind/utils": "2.15.4-feat-cli-multiline-input.21032+23042ba16",
121
+ "@bike4mind/common": "2.67.1-fix-cli-stream-resilience.21033+09a303405",
122
+ "@bike4mind/mcp": "1.33.11-fix-cli-stream-resilience.21033+09a303405",
123
+ "@bike4mind/services": "2.63.1-fix-cli-stream-resilience.21033+09a303405",
124
+ "@bike4mind/utils": "2.15.4-fix-cli-stream-resilience.21033+09a303405",
125
125
  "@types/better-sqlite3": "^7.6.13",
126
126
  "@types/diff": "^5.0.9",
127
127
  "@types/jsonwebtoken": "^9.0.4",
@@ -140,7 +140,7 @@ var package_default = {
140
140
  optionalDependencies: {
141
141
  "@vscode/ripgrep": "^1.17.0"
142
142
  },
143
- gitHead: "23042ba16b9f76d05f18dcdc3d5ccfd4df93dfc3"
143
+ gitHead: "09a303405a914a691b6d40257f2837e42be4e8ab"
144
144
  };
145
145
 
146
146
  // src/utils/updateChecker.ts
@@ -16146,17 +16146,48 @@ function extractUsageInfo(parsed) {
16146
16146
  usdCost: parsed.credits?.usdCost
16147
16147
  };
16148
16148
  }
16149
- var ServerLlmBackend = class {
16149
+ var ServerLlmBackend = class _ServerLlmBackend {
16150
16150
  constructor(options) {
16151
16151
  this.completionsEndpoint = "/api/ai/v1/completions";
16152
16152
  this.apiClient = options.apiClient;
16153
16153
  this.currentModel = options.model;
16154
16154
  }
16155
+ static {
16156
+ /** Max retries for transient stream failures (e.g. missing [DONE]) */
16157
+ this.MAX_STREAM_RETRIES = 2;
16158
+ }
16155
16159
  /**
16156
16160
  * Make authenticated LLM completion request via server
16157
- * Parses SSE stream and invokes callback for each event
16161
+ * Parses SSE stream and invokes callback for each event.
16162
+ * Automatically retries on transient stream failures (e.g. stream ending prematurely).
16158
16163
  */
16159
16164
  async complete(model, messages, options, callback) {
16165
+ let lastError;
16166
+ for (let attempt = 0; attempt <= _ServerLlmBackend.MAX_STREAM_RETRIES; attempt++) {
16167
+ if (attempt > 0) {
16168
+ logger.warn(
16169
+ `[ServerLlmBackend] Retrying stream (attempt ${attempt + 1}/${_ServerLlmBackend.MAX_STREAM_RETRIES + 1})...`
16170
+ );
16171
+ }
16172
+ try {
16173
+ await this.completeOnce(model, messages, options, callback);
16174
+ return;
16175
+ } catch (error) {
16176
+ lastError = error instanceof Error ? error : new Error(String(error));
16177
+ const isTransientStreamError = lastError.message.includes("Stream ended prematurely");
16178
+ const isAborted = options.abortSignal?.aborted;
16179
+ if (!isTransientStreamError || isAborted) {
16180
+ throw lastError;
16181
+ }
16182
+ logger.warn(`[ServerLlmBackend] Transient stream failure: ${lastError.message}`);
16183
+ }
16184
+ }
16185
+ throw lastError ?? new Error("Stream failed after all retry attempts");
16186
+ }
16187
+ /**
16188
+ * Single attempt at completing a streaming request.
16189
+ */
16190
+ async completeOnce(model, messages, options, callback) {
16160
16191
  logger.debug(`[ServerLlmBackend] Starting complete() with model: ${model}`);
16161
16192
  if (options.abortSignal?.aborted) {
16162
16193
  logger.debug("[ServerLlmBackend] Request aborted before start");
@@ -16357,8 +16388,30 @@ var ServerLlmBackend = class {
16357
16388
  });
16358
16389
  response.data.on("end", () => {
16359
16390
  if (!receivedDone) {
16360
- logger.debug("[ServerLlmBackend] Stream ended without [DONE], resolving anyway");
16361
- resolve3();
16391
+ const hasAccumulatedData = accumulatedText.trim().length > 0 || toolsUsed.length > 0;
16392
+ logger.warn(
16393
+ `[ServerLlmBackend] Stream ended without [DONE] signal. Accumulated text: ${accumulatedText.length} chars, tools: ${toolsUsed.length}`
16394
+ );
16395
+ if (hasAccumulatedData) {
16396
+ const cleanedText = stripThinkingBlocks(accumulatedText);
16397
+ streamLogger.streamComplete(accumulatedText);
16398
+ if (toolsUsed.length > 0) {
16399
+ const info = {
16400
+ toolsUsed,
16401
+ thinking: thinkingBlocks.length > 0 ? thinkingBlocks : void 0,
16402
+ ...lastUsageInfo
16403
+ };
16404
+ callback([cleanedText], info).catch((err) => reject(err)).then(() => resolve3());
16405
+ } else if (cleanedText) {
16406
+ callback([cleanedText], lastUsageInfo).catch((err) => reject(err)).then(() => resolve3());
16407
+ } else {
16408
+ resolve3();
16409
+ }
16410
+ } else {
16411
+ reject(
16412
+ new Error("Stream ended prematurely without receiving any data. The server may be experiencing issues.")
16413
+ );
16414
+ }
16362
16415
  } else {
16363
16416
  logger.debug("[ServerLlmBackend] Stream ended, [DONE] handler will resolve");
16364
16417
  }
@@ -3,7 +3,7 @@ import {
3
3
  fetchLatestVersion,
4
4
  forceCheckForUpdate,
5
5
  package_default
6
- } from "../chunk-U3MM4PII.js";
6
+ } from "../chunk-INXVKDZ5.js";
7
7
 
8
8
  // src/commands/doctorCommand.ts
9
9
  import { execSync } from "child_process";
@@ -36,7 +36,7 @@ import {
36
36
  isReadOnlyTool,
37
37
  loadContextFiles,
38
38
  setWebSocketToolExecutor
39
- } from "../chunk-623C44JW.js";
39
+ } from "../chunk-QJ47T42W.js";
40
40
  import "../chunk-BDQBOLYG.js";
41
41
  import "../chunk-F6IY547T.js";
42
42
  import "../chunk-GQGOWACU.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  forceCheckForUpdate,
4
4
  package_default
5
- } from "../chunk-U3MM4PII.js";
5
+ } from "../chunk-INXVKDZ5.js";
6
6
 
7
7
  // src/commands/updateCommand.ts
8
8
  import { execSync } from "child_process";
package/dist/index.js CHANGED
@@ -46,7 +46,7 @@ import {
46
46
  setWebSocketToolExecutor,
47
47
  substituteArguments,
48
48
  warmFileCache
49
- } from "./chunk-623C44JW.js";
49
+ } from "./chunk-QJ47T42W.js";
50
50
  import "./chunk-BDQBOLYG.js";
51
51
  import "./chunk-F6IY547T.js";
52
52
  import "./chunk-GQGOWACU.js";
@@ -64,7 +64,7 @@ import {
64
64
  import {
65
65
  checkForUpdate,
66
66
  package_default
67
- } from "./chunk-U3MM4PII.js";
67
+ } from "./chunk-INXVKDZ5.js";
68
68
  import {
69
69
  selectActiveBackgroundAgents,
70
70
  useCliStore
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.49-feat-cli-multiline-input.21032+23042ba16",
3
+ "version": "0.2.49-fix-cli-stream-resilience.21033+09a303405",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -115,10 +115,10 @@
115
115
  },
116
116
  "devDependencies": {
117
117
  "@bike4mind/agents": "0.1.0",
118
- "@bike4mind/common": "2.67.1-feat-cli-multiline-input.21032+23042ba16",
119
- "@bike4mind/mcp": "1.33.11-feat-cli-multiline-input.21032+23042ba16",
120
- "@bike4mind/services": "2.63.1-feat-cli-multiline-input.21032+23042ba16",
121
- "@bike4mind/utils": "2.15.4-feat-cli-multiline-input.21032+23042ba16",
118
+ "@bike4mind/common": "2.67.1-fix-cli-stream-resilience.21033+09a303405",
119
+ "@bike4mind/mcp": "1.33.11-fix-cli-stream-resilience.21033+09a303405",
120
+ "@bike4mind/services": "2.63.1-fix-cli-stream-resilience.21033+09a303405",
121
+ "@bike4mind/utils": "2.15.4-fix-cli-stream-resilience.21033+09a303405",
122
122
  "@types/better-sqlite3": "^7.6.13",
123
123
  "@types/diff": "^5.0.9",
124
124
  "@types/jsonwebtoken": "^9.0.4",
@@ -137,5 +137,5 @@
137
137
  "optionalDependencies": {
138
138
  "@vscode/ripgrep": "^1.17.0"
139
139
  },
140
- "gitHead": "23042ba16b9f76d05f18dcdc3d5ccfd4df93dfc3"
140
+ "gitHead": "09a303405a914a691b6d40257f2837e42be4e8ab"
141
141
  }