@bike4mind/cli 0.2.49-fix-telemetry-alert-debug.21031 → 0.2.49-fix-cli-stream-resilience-v2.21035

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.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BadRequestError,
4
4
  secureParameters
5
- } from "./chunk-M7QGYBN7.js";
5
+ } from "./chunk-FXIXD2A6.js";
6
6
  import {
7
7
  CompletionApiUsageTransaction,
8
8
  GenericCreditDeductTransaction,
@@ -6578,6 +6578,63 @@ var GeminiBackend = class {
6578
6578
  // ../../b4m-core/packages/utils/dist/src/llm/ollamaBackend.js
6579
6579
  import { Ollama } from "ollama";
6580
6580
  import { Agent as Agent2 } from "undici";
6581
+
6582
+ // ../../b4m-core/packages/utils/dist/src/llm/messageFormatConverter.js
6583
+ function hasToolCalls(msg) {
6584
+ return msg.role === "assistant" && "tool_calls" in msg;
6585
+ }
6586
+ function isToolUseBlock(block) {
6587
+ return block.type === "tool_use";
6588
+ }
6589
+ function isToolResultBlock(block) {
6590
+ return block.type === "tool_result";
6591
+ }
6592
+ function isTextBlock(block) {
6593
+ return block.type === "text";
6594
+ }
6595
+ function convertMessageToOpenAIFormat(msg) {
6596
+ if (hasToolCalls(msg)) {
6597
+ return [{ role: "assistant", content: null, tool_calls: msg.tool_calls }];
6598
+ }
6599
+ if (msg.role === "assistant" && Array.isArray(msg.content)) {
6600
+ const contentBlocks = msg.content;
6601
+ const toolUseBlocks = contentBlocks.filter(isToolUseBlock);
6602
+ if (toolUseBlocks.length > 0) {
6603
+ const textParts = contentBlocks.filter(isTextBlock).map((block) => block.text).filter(Boolean);
6604
+ return [
6605
+ {
6606
+ role: "assistant",
6607
+ content: textParts.length > 0 ? textParts.join("\n") : null,
6608
+ tool_calls: toolUseBlocks.map((block) => ({
6609
+ id: block.id,
6610
+ type: "function",
6611
+ function: {
6612
+ name: block.name,
6613
+ arguments: JSON.stringify(block.input)
6614
+ }
6615
+ }))
6616
+ }
6617
+ ];
6618
+ }
6619
+ }
6620
+ if (msg.role === "user" && Array.isArray(msg.content)) {
6621
+ const contentBlocks = msg.content;
6622
+ const toolResultBlocks = contentBlocks.filter(isToolResultBlock);
6623
+ if (toolResultBlocks.length > 0) {
6624
+ return toolResultBlocks.map((block) => ({
6625
+ role: "tool",
6626
+ content: block.content,
6627
+ tool_call_id: block.tool_use_id
6628
+ }));
6629
+ }
6630
+ }
6631
+ return [msg];
6632
+ }
6633
+ function convertMessagesToOpenAIFormat(messages) {
6634
+ return messages.flatMap(convertMessageToOpenAIFormat);
6635
+ }
6636
+
6637
+ // ../../b4m-core/packages/utils/dist/src/llm/ollamaBackend.js
6581
6638
  var OllamaBackend = class {
6582
6639
  _host;
6583
6640
  _api;
@@ -6741,9 +6798,12 @@ var OllamaBackend = class {
6741
6798
  /**
6742
6799
  * Map IMessage[] to Ollama's Message[], preserving tool_calls for multi-turn
6743
6800
  * tool conversations (added by pushToolMessages).
6801
+ * First converts B4M standard format (tool_use/tool_result) to OpenAI-compatible
6802
+ * format since Ollama uses the same tool_calls/role:tool convention.
6744
6803
  */
6745
6804
  buildMessages(messages) {
6746
- return messages.map((msg) => {
6805
+ const converted = convertMessagesToOpenAIFormat(messages);
6806
+ return converted.map((msg) => {
6747
6807
  const raw = msg;
6748
6808
  const mapped = {
6749
6809
  role: msg.role,
@@ -7837,16 +7897,8 @@ Only when someone asks, remember that you are specifically the ${model} model.`;
7837
7897
  role: "system",
7838
7898
  content: systemContent
7839
7899
  };
7840
- const formattedMessages = filteredMessages.map((msg) => {
7841
- if (msg.role === "assistant" && msg.tool_calls) {
7842
- return {
7843
- ...msg,
7844
- content: null,
7845
- tool_calls: msg.tool_calls
7846
- };
7847
- }
7848
- return msg;
7849
- });
7900
+ const convertedMessages = convertMessagesToOpenAIFormat(filteredMessages);
7901
+ const formattedMessages = convertedMessages;
7850
7902
  return isO1Model ? formattedMessages : [systemMessage, ...formattedMessages];
7851
7903
  }
7852
7904
  pushToolMessages(messages, tool, result, _thinkingBlocks) {
@@ -8369,17 +8421,7 @@ var XAIBackend = class {
8369
8421
  }
8370
8422
  }
8371
8423
  formatMessages(messages) {
8372
- const formattedMessages = messages.map((msg) => {
8373
- if (msg.role === "assistant" && msg.tool_calls) {
8374
- return {
8375
- ...msg,
8376
- content: null,
8377
- tool_calls: msg.tool_calls
8378
- };
8379
- }
8380
- return msg;
8381
- });
8382
- return formattedMessages;
8424
+ return convertMessagesToOpenAIFormat(messages);
8383
8425
  }
8384
8426
  formatTools(tools = []) {
8385
8427
  return tools.map((tool) => ({
@@ -3,7 +3,7 @@
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@bike4mind/cli",
6
- version: "0.2.49-fix-telemetry-alert-debug.21031+766fdd35a",
6
+ version: "0.2.49-fix-cli-stream-resilience-v2.21035+a2916622a",
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-fix-telemetry-alert-debug.21031+766fdd35a",
122
- "@bike4mind/mcp": "1.33.11-fix-telemetry-alert-debug.21031+766fdd35a",
123
- "@bike4mind/services": "2.63.1-fix-telemetry-alert-debug.21031+766fdd35a",
124
- "@bike4mind/utils": "2.15.4-fix-telemetry-alert-debug.21031+766fdd35a",
121
+ "@bike4mind/common": "2.67.1-fix-cli-stream-resilience-v2.21035+a2916622a",
122
+ "@bike4mind/mcp": "1.33.11-fix-cli-stream-resilience-v2.21035+a2916622a",
123
+ "@bike4mind/services": "2.63.1-fix-cli-stream-resilience-v2.21035+a2916622a",
124
+ "@bike4mind/utils": "2.15.4-fix-cli-stream-resilience-v2.21035+a2916622a",
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: "766fdd35a8018f32ebf70db963625dcc6ea2d653"
143
+ gitHead: "a2916622a2bca713ac78a8c40ae58bdf92c0785f"
144
144
  };
145
145
 
146
146
  // src/utils/updateChecker.ts
@@ -6,7 +6,7 @@ import {
6
6
  getSettingsByNames,
7
7
  obfuscateApiKey,
8
8
  secureParameters
9
- } from "./chunk-M7QGYBN7.js";
9
+ } from "./chunk-FXIXD2A6.js";
10
10
  import {
11
11
  ApiKeyType,
12
12
  MementoTier,
@@ -4,7 +4,7 @@ import {
4
4
  getOpenWeatherKey,
5
5
  getSerperKey,
6
6
  getWolframAlphaKey
7
- } from "./chunk-F6IY547T.js";
7
+ } from "./chunk-QDHVYPMB.js";
8
8
  import {
9
9
  BFLImageService,
10
10
  BaseStorage,
@@ -16,7 +16,7 @@ import {
16
16
  OpenAIBackend,
17
17
  OpenAIImageService,
18
18
  XAIImageService
19
- } from "./chunk-M7QGYBN7.js";
19
+ } from "./chunk-FXIXD2A6.js";
20
20
  import {
21
21
  Logger
22
22
  } from "./chunk-PFBYGCOW.js";
@@ -14017,40 +14017,25 @@ var AnomalyAlertService = class _AnomalyAlertService {
14017
14017
  * Check if an alert should be sent and send it if appropriate
14018
14018
  */
14019
14019
  async checkAndAlert(telemetry) {
14020
- console.log("[AnomalyAlert] DEBUG: checkAndAlert called", {
14021
- enabled: this.config.enabled,
14022
- isSlackConfigured: this.isSlackConfigured()
14023
- });
14024
14020
  if (!this.config.enabled || !this.isSlackConfigured()) {
14025
- console.log("[AnomalyAlert] DEBUG: Early return - not enabled or Slack not configured");
14026
14021
  return false;
14027
14022
  }
14028
14023
  const { anomalies } = telemetry;
14029
14024
  const threshold = this.config.alertThreshold ?? ALERT_THRESHOLDS.warning;
14030
- console.log("[AnomalyAlert] DEBUG: Threshold check", {
14031
- anomalyScore: anomalies.anomalyScore,
14032
- threshold
14033
- });
14034
14025
  if (anomalies.anomalyScore < threshold) {
14035
- console.log("[AnomalyAlert] DEBUG: Score below threshold");
14036
14026
  return false;
14037
14027
  }
14038
- console.log("[AnomalyAlert] DEBUG: Checking deduplication", { dedupKey: anomalies.dedupKey });
14039
14028
  const isDup = await this.checkDeduplication(anomalies.dedupKey);
14040
- console.log("[AnomalyAlert] DEBUG: Dedup result", { isDup });
14041
14029
  if (isDup) {
14042
14030
  this.logger.info(`\u{1F4CA} [AnomalyAlert] Suppressed duplicate alert: ${anomalies.dedupKey}`);
14043
14031
  return false;
14044
14032
  }
14045
14033
  try {
14046
- console.log("[AnomalyAlert] DEBUG: Sending Slack alert");
14047
14034
  const message = this.formatSlackMessage(telemetry);
14048
14035
  await this.sendSlackAlert(message);
14049
14036
  this.logger.info(`\u{1F4CA} [AnomalyAlert] Alert sent for ${anomalies.primaryAnomaly} (score: ${anomalies.anomalyScore})`);
14050
- console.log("[AnomalyAlert] DEBUG: Alert sent successfully");
14051
14037
  return true;
14052
14038
  } catch (error) {
14053
- console.log("[AnomalyAlert] DEBUG: Failed to send alert", { error: String(error) });
14054
14039
  this.logger.error(`\u{1F4CA} [AnomalyAlert] Failed to send alert:`, error);
14055
14040
  return false;
14056
14041
  }
@@ -16157,17 +16142,48 @@ function extractUsageInfo(parsed) {
16157
16142
  usdCost: parsed.credits?.usdCost
16158
16143
  };
16159
16144
  }
16160
- var ServerLlmBackend = class {
16145
+ var ServerLlmBackend = class _ServerLlmBackend {
16161
16146
  constructor(options) {
16162
16147
  this.completionsEndpoint = "/api/ai/v1/completions";
16163
16148
  this.apiClient = options.apiClient;
16164
16149
  this.currentModel = options.model;
16165
16150
  }
16151
+ static {
16152
+ /** Max retries for transient stream failures (e.g. missing [DONE]) */
16153
+ this.MAX_STREAM_RETRIES = 2;
16154
+ }
16166
16155
  /**
16167
16156
  * Make authenticated LLM completion request via server
16168
- * Parses SSE stream and invokes callback for each event
16157
+ * Parses SSE stream and invokes callback for each event.
16158
+ * Automatically retries on transient stream failures (e.g. stream ending prematurely).
16169
16159
  */
16170
16160
  async complete(model, messages, options, callback) {
16161
+ let lastError;
16162
+ for (let attempt = 0; attempt <= _ServerLlmBackend.MAX_STREAM_RETRIES; attempt++) {
16163
+ if (attempt > 0) {
16164
+ logger.warn(
16165
+ `[ServerLlmBackend] Retrying stream (attempt ${attempt + 1}/${_ServerLlmBackend.MAX_STREAM_RETRIES + 1})...`
16166
+ );
16167
+ }
16168
+ try {
16169
+ await this.completeOnce(model, messages, options, callback);
16170
+ return;
16171
+ } catch (error) {
16172
+ lastError = error instanceof Error ? error : new Error(String(error));
16173
+ const isTransientStreamError = lastError.message.includes("Stream ended prematurely");
16174
+ const isAborted = options.abortSignal?.aborted;
16175
+ if (!isTransientStreamError || isAborted) {
16176
+ throw lastError;
16177
+ }
16178
+ logger.warn(`[ServerLlmBackend] Transient stream failure: ${lastError.message}`);
16179
+ }
16180
+ }
16181
+ throw lastError ?? new Error("Stream failed after all retry attempts");
16182
+ }
16183
+ /**
16184
+ * Single attempt at completing a streaming request.
16185
+ */
16186
+ async completeOnce(model, messages, options, callback) {
16171
16187
  logger.debug(`[ServerLlmBackend] Starting complete() with model: ${model}`);
16172
16188
  if (options.abortSignal?.aborted) {
16173
16189
  logger.debug("[ServerLlmBackend] Request aborted before start");
@@ -16368,8 +16384,30 @@ var ServerLlmBackend = class {
16368
16384
  });
16369
16385
  response.data.on("end", () => {
16370
16386
  if (!receivedDone) {
16371
- logger.debug("[ServerLlmBackend] Stream ended without [DONE], resolving anyway");
16372
- resolve3();
16387
+ const hasAccumulatedData = accumulatedText.trim().length > 0 || toolsUsed.length > 0;
16388
+ logger.warn(
16389
+ `[ServerLlmBackend] Stream ended without [DONE] signal. Accumulated text: ${accumulatedText.length} chars, tools: ${toolsUsed.length}`
16390
+ );
16391
+ if (hasAccumulatedData) {
16392
+ const cleanedText = stripThinkingBlocks(accumulatedText);
16393
+ streamLogger.streamComplete(accumulatedText);
16394
+ if (toolsUsed.length > 0) {
16395
+ const info = {
16396
+ toolsUsed,
16397
+ thinking: thinkingBlocks.length > 0 ? thinkingBlocks : void 0,
16398
+ ...lastUsageInfo
16399
+ };
16400
+ callback([cleanedText], info).then(() => resolve3(), reject);
16401
+ } else if (cleanedText) {
16402
+ callback([cleanedText], lastUsageInfo).then(() => resolve3(), reject);
16403
+ } else {
16404
+ resolve3();
16405
+ }
16406
+ } else {
16407
+ reject(
16408
+ new Error("Stream ended prematurely without receiving any data. The server may be experiencing issues.")
16409
+ );
16410
+ }
16373
16411
  } else {
16374
16412
  logger.debug("[ServerLlmBackend] Stream ended, [DONE] handler will resolve");
16375
16413
  }
@@ -7,7 +7,7 @@ import {
7
7
  getSettingsMap,
8
8
  getSettingsValue,
9
9
  secureParameters
10
- } from "./chunk-M7QGYBN7.js";
10
+ } from "./chunk-FXIXD2A6.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
@@ -3,7 +3,7 @@ import {
3
3
  fetchLatestVersion,
4
4
  forceCheckForUpdate,
5
5
  package_default
6
- } from "../chunk-5SZI2XFM.js";
6
+ } from "../chunk-MIPUEVI4.js";
7
7
 
8
8
  // src/commands/doctorCommand.ts
9
9
  import { execSync } from "child_process";
@@ -36,13 +36,13 @@ import {
36
36
  isReadOnlyTool,
37
37
  loadContextFiles,
38
38
  setWebSocketToolExecutor
39
- } from "../chunk-4ZO5RNWO.js";
39
+ } from "../chunk-XCWGH6DY.js";
40
40
  import "../chunk-BDQBOLYG.js";
41
- import "../chunk-F6IY547T.js";
41
+ import "../chunk-QDHVYPMB.js";
42
42
  import "../chunk-GQGOWACU.js";
43
- import "../chunk-OFKZXY6L.js";
44
- import "../chunk-WKPO5JDF.js";
45
- import "../chunk-M7QGYBN7.js";
43
+ import "../chunk-E3SJSVGD.js";
44
+ import "../chunk-YF76VW3F.js";
45
+ import "../chunk-FXIXD2A6.js";
46
46
  import "../chunk-PFBYGCOW.js";
47
47
  import "../chunk-BPFEGDC7.js";
48
48
  import {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  forceCheckForUpdate,
4
4
  package_default
5
- } from "../chunk-5SZI2XFM.js";
5
+ } from "../chunk-MIPUEVI4.js";
6
6
 
7
7
  // src/commands/updateCommand.ts
8
8
  import { execSync } from "child_process";
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  createFabFile,
4
4
  createFabFileSchema
5
- } from "./chunk-WKPO5JDF.js";
6
- import "./chunk-M7QGYBN7.js";
5
+ } from "./chunk-YF76VW3F.js";
6
+ import "./chunk-FXIXD2A6.js";
7
7
  import "./chunk-PFBYGCOW.js";
8
8
  import "./chunk-QLY3LGPA.js";
9
9
  export {
package/dist/index.js CHANGED
@@ -46,15 +46,15 @@ import {
46
46
  setWebSocketToolExecutor,
47
47
  substituteArguments,
48
48
  warmFileCache
49
- } from "./chunk-4ZO5RNWO.js";
49
+ } from "./chunk-XCWGH6DY.js";
50
50
  import "./chunk-BDQBOLYG.js";
51
- import "./chunk-F6IY547T.js";
51
+ import "./chunk-QDHVYPMB.js";
52
52
  import "./chunk-GQGOWACU.js";
53
- import "./chunk-OFKZXY6L.js";
54
- import "./chunk-WKPO5JDF.js";
53
+ import "./chunk-E3SJSVGD.js";
54
+ import "./chunk-YF76VW3F.js";
55
55
  import {
56
56
  OllamaBackend
57
- } from "./chunk-M7QGYBN7.js";
57
+ } from "./chunk-FXIXD2A6.js";
58
58
  import "./chunk-PFBYGCOW.js";
59
59
  import "./chunk-BPFEGDC7.js";
60
60
  import {
@@ -64,7 +64,7 @@ import {
64
64
  import {
65
65
  checkForUpdate,
66
66
  package_default
67
- } from "./chunk-5SZI2XFM.js";
67
+ } from "./chunk-MIPUEVI4.js";
68
68
  import {
69
69
  selectActiveBackgroundAgents,
70
70
  useCliStore
@@ -2940,11 +2940,10 @@ function CliApp() {
2940
2940
  throw new Error("No websocketUrl or wsCompletionUrl in server config");
2941
2941
  }
2942
2942
  } catch (wsError) {
2943
- console.error(
2944
- `\u26A0\uFE0F WebSocket unavailable, using SSE fallback: ${wsError instanceof Error ? wsError.message : String(wsError)}`
2945
- );
2943
+ logger.info("\u26A0\uFE0F WebSocket unavailable, using SSE fallback");
2944
+ logger.debug(`[WebSocket] Fallback reason: ${wsError instanceof Error ? wsError.message : String(wsError)}`);
2946
2945
  if (wsError instanceof Error && wsError.stack) {
2947
- console.error(wsError.stack);
2946
+ logger.debug(`[WebSocket] Stack: ${wsError.stack}`);
2948
2947
  }
2949
2948
  wsManager = null;
2950
2949
  setWebSocketToolExecutor(null);
@@ -3728,7 +3727,11 @@ Pull a model: ollama pull qwen3.5`
3728
3727
  return;
3729
3728
  }
3730
3729
  }
3731
- console.error("Error processing message:", error);
3730
+ const errorMessage = error instanceof Error ? error.message : String(error);
3731
+ console.error(`
3732
+ \u274C ${errorMessage}
3733
+ `);
3734
+ logger.debug(`Full error details: ${error instanceof Error ? error.stack || error.message : String(error)}`);
3732
3735
  } finally {
3733
3736
  setState((prev) => ({ ...prev, abortController: null }));
3734
3737
  useCliStore.getState().setIsThinking(false);
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  findMostSimilarMemento,
4
4
  getRelevantMementos
5
- } from "./chunk-F6IY547T.js";
6
- import "./chunk-M7QGYBN7.js";
5
+ } from "./chunk-QDHVYPMB.js";
6
+ import "./chunk-FXIXD2A6.js";
7
7
  import "./chunk-PFBYGCOW.js";
8
8
  import "./chunk-QLY3LGPA.js";
9
9
  export {
@@ -143,7 +143,7 @@ import {
143
143
  validateUrlForFetch,
144
144
  warmUpSettingsCache,
145
145
  withRetry
146
- } from "./chunk-M7QGYBN7.js";
146
+ } from "./chunk-FXIXD2A6.js";
147
147
  import {
148
148
  Logger,
149
149
  NotificationDeduplicator,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  SubtractCreditsSchema,
4
4
  subtractCredits
5
- } from "./chunk-OFKZXY6L.js";
6
- import "./chunk-M7QGYBN7.js";
5
+ } from "./chunk-E3SJSVGD.js";
6
+ import "./chunk-FXIXD2A6.js";
7
7
  import "./chunk-PFBYGCOW.js";
8
8
  import "./chunk-QLY3LGPA.js";
9
9
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.49-fix-telemetry-alert-debug.21031+766fdd35a",
3
+ "version": "0.2.49-fix-cli-stream-resilience-v2.21035+a2916622a",
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-fix-telemetry-alert-debug.21031+766fdd35a",
119
- "@bike4mind/mcp": "1.33.11-fix-telemetry-alert-debug.21031+766fdd35a",
120
- "@bike4mind/services": "2.63.1-fix-telemetry-alert-debug.21031+766fdd35a",
121
- "@bike4mind/utils": "2.15.4-fix-telemetry-alert-debug.21031+766fdd35a",
118
+ "@bike4mind/common": "2.67.1-fix-cli-stream-resilience-v2.21035+a2916622a",
119
+ "@bike4mind/mcp": "1.33.11-fix-cli-stream-resilience-v2.21035+a2916622a",
120
+ "@bike4mind/services": "2.63.1-fix-cli-stream-resilience-v2.21035+a2916622a",
121
+ "@bike4mind/utils": "2.15.4-fix-cli-stream-resilience-v2.21035+a2916622a",
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": "766fdd35a8018f32ebf70db963625dcc6ea2d653"
140
+ "gitHead": "a2916622a2bca713ac78a8c40ae58bdf92c0785f"
141
141
  }