@bike4mind/cli 0.2.49-fix-cli-stream-resilience.21035 → 0.2.49-fix-telemetry-alert-debug.21031
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/dist/{chunk-KE2DKWPR.js → chunk-4ZO5RNWO.js} +21 -63
- package/dist/{chunk-KR6Q7BEQ.js → chunk-5SZI2XFM.js} +6 -6
- package/dist/{chunk-7VEI22BF.js → chunk-F6IY547T.js} +1 -1
- package/dist/{chunk-UDBM5N7V.js → chunk-M7QGYBN7.js} +22 -58
- package/dist/{chunk-X26VCD3A.js → chunk-OFKZXY6L.js} +1 -1
- package/dist/{chunk-MP3FYWMR.js → chunk-WKPO5JDF.js} +1 -1
- package/dist/commands/doctorCommand.js +1 -1
- package/dist/commands/headlessCommand.js +5 -5
- package/dist/commands/updateCommand.js +1 -1
- package/dist/{create-PA2DIVCF.js → create-6Z46TX3C.js} +2 -2
- package/dist/index.js +13 -44
- package/dist/{mementoService-W76KVRGE.js → mementoService-XAAA3Q54.js} +2 -2
- package/dist/{src-XUTQ6N2T.js → src-FDPAPWTO.js} +1 -1
- package/dist/{subtractCredits-3V5REXEH.js → subtractCredits-7SHS6DXL.js} +2 -2
- package/package.json +6 -6
- package/dist/terminalSetup-C5FHMLC3.js +0 -214
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getOpenWeatherKey,
|
|
5
5
|
getSerperKey,
|
|
6
6
|
getWolframAlphaKey
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-F6IY547T.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-
|
|
19
|
+
} from "./chunk-M7QGYBN7.js";
|
|
20
20
|
import {
|
|
21
21
|
Logger
|
|
22
22
|
} from "./chunk-PFBYGCOW.js";
|
|
@@ -503,10 +503,6 @@ var COMMANDS = [
|
|
|
503
503
|
name: "sandbox:violations:clear",
|
|
504
504
|
description: "Clear all recorded sandbox violations"
|
|
505
505
|
},
|
|
506
|
-
{
|
|
507
|
-
name: "terminal-setup",
|
|
508
|
-
description: "Configure Shift+Enter for multi-line input"
|
|
509
|
-
},
|
|
510
506
|
{
|
|
511
507
|
name: "add-dir",
|
|
512
508
|
description: "Add a directory for file access",
|
|
@@ -14021,25 +14017,40 @@ var AnomalyAlertService = class _AnomalyAlertService {
|
|
|
14021
14017
|
* Check if an alert should be sent and send it if appropriate
|
|
14022
14018
|
*/
|
|
14023
14019
|
async checkAndAlert(telemetry) {
|
|
14020
|
+
console.log("[AnomalyAlert] DEBUG: checkAndAlert called", {
|
|
14021
|
+
enabled: this.config.enabled,
|
|
14022
|
+
isSlackConfigured: this.isSlackConfigured()
|
|
14023
|
+
});
|
|
14024
14024
|
if (!this.config.enabled || !this.isSlackConfigured()) {
|
|
14025
|
+
console.log("[AnomalyAlert] DEBUG: Early return - not enabled or Slack not configured");
|
|
14025
14026
|
return false;
|
|
14026
14027
|
}
|
|
14027
14028
|
const { anomalies } = telemetry;
|
|
14028
14029
|
const threshold = this.config.alertThreshold ?? ALERT_THRESHOLDS.warning;
|
|
14030
|
+
console.log("[AnomalyAlert] DEBUG: Threshold check", {
|
|
14031
|
+
anomalyScore: anomalies.anomalyScore,
|
|
14032
|
+
threshold
|
|
14033
|
+
});
|
|
14029
14034
|
if (anomalies.anomalyScore < threshold) {
|
|
14035
|
+
console.log("[AnomalyAlert] DEBUG: Score below threshold");
|
|
14030
14036
|
return false;
|
|
14031
14037
|
}
|
|
14038
|
+
console.log("[AnomalyAlert] DEBUG: Checking deduplication", { dedupKey: anomalies.dedupKey });
|
|
14032
14039
|
const isDup = await this.checkDeduplication(anomalies.dedupKey);
|
|
14040
|
+
console.log("[AnomalyAlert] DEBUG: Dedup result", { isDup });
|
|
14033
14041
|
if (isDup) {
|
|
14034
14042
|
this.logger.info(`\u{1F4CA} [AnomalyAlert] Suppressed duplicate alert: ${anomalies.dedupKey}`);
|
|
14035
14043
|
return false;
|
|
14036
14044
|
}
|
|
14037
14045
|
try {
|
|
14046
|
+
console.log("[AnomalyAlert] DEBUG: Sending Slack alert");
|
|
14038
14047
|
const message = this.formatSlackMessage(telemetry);
|
|
14039
14048
|
await this.sendSlackAlert(message);
|
|
14040
14049
|
this.logger.info(`\u{1F4CA} [AnomalyAlert] Alert sent for ${anomalies.primaryAnomaly} (score: ${anomalies.anomalyScore})`);
|
|
14050
|
+
console.log("[AnomalyAlert] DEBUG: Alert sent successfully");
|
|
14041
14051
|
return true;
|
|
14042
14052
|
} catch (error) {
|
|
14053
|
+
console.log("[AnomalyAlert] DEBUG: Failed to send alert", { error: String(error) });
|
|
14043
14054
|
this.logger.error(`\u{1F4CA} [AnomalyAlert] Failed to send alert:`, error);
|
|
14044
14055
|
return false;
|
|
14045
14056
|
}
|
|
@@ -16146,48 +16157,17 @@ function extractUsageInfo(parsed) {
|
|
|
16146
16157
|
usdCost: parsed.credits?.usdCost
|
|
16147
16158
|
};
|
|
16148
16159
|
}
|
|
16149
|
-
var ServerLlmBackend = class
|
|
16160
|
+
var ServerLlmBackend = class {
|
|
16150
16161
|
constructor(options) {
|
|
16151
16162
|
this.completionsEndpoint = "/api/ai/v1/completions";
|
|
16152
16163
|
this.apiClient = options.apiClient;
|
|
16153
16164
|
this.currentModel = options.model;
|
|
16154
16165
|
}
|
|
16155
|
-
static {
|
|
16156
|
-
/** Max retries for transient stream failures (e.g. missing [DONE]) */
|
|
16157
|
-
this.MAX_STREAM_RETRIES = 2;
|
|
16158
|
-
}
|
|
16159
16166
|
/**
|
|
16160
16167
|
* Make authenticated LLM completion request via server
|
|
16161
|
-
* Parses SSE stream and invokes callback for each event
|
|
16162
|
-
* Automatically retries on transient stream failures (e.g. stream ending prematurely).
|
|
16168
|
+
* Parses SSE stream and invokes callback for each event
|
|
16163
16169
|
*/
|
|
16164
16170
|
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) {
|
|
16191
16171
|
logger.debug(`[ServerLlmBackend] Starting complete() with model: ${model}`);
|
|
16192
16172
|
if (options.abortSignal?.aborted) {
|
|
16193
16173
|
logger.debug("[ServerLlmBackend] Request aborted before start");
|
|
@@ -16388,30 +16368,8 @@ var ServerLlmBackend = class _ServerLlmBackend {
|
|
|
16388
16368
|
});
|
|
16389
16369
|
response.data.on("end", () => {
|
|
16390
16370
|
if (!receivedDone) {
|
|
16391
|
-
|
|
16392
|
-
|
|
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
|
-
}
|
|
16371
|
+
logger.debug("[ServerLlmBackend] Stream ended without [DONE], resolving anyway");
|
|
16372
|
+
resolve3();
|
|
16415
16373
|
} else {
|
|
16416
16374
|
logger.debug("[ServerLlmBackend] Stream ended, [DONE] handler will resolve");
|
|
16417
16375
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@bike4mind/cli",
|
|
6
|
-
version: "0.2.49-fix-
|
|
6
|
+
version: "0.2.49-fix-telemetry-alert-debug.21031+766fdd35a",
|
|
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-
|
|
122
|
-
"@bike4mind/mcp": "1.33.11-fix-
|
|
123
|
-
"@bike4mind/services": "2.63.1-fix-
|
|
124
|
-
"@bike4mind/utils": "2.15.4-fix-
|
|
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",
|
|
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: "
|
|
143
|
+
gitHead: "766fdd35a8018f32ebf70db963625dcc6ea2d653"
|
|
144
144
|
};
|
|
145
145
|
|
|
146
146
|
// src/utils/updateChecker.ts
|
|
@@ -6578,57 +6578,6 @@ 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 convertMessageToOpenAIFormat(msg) {
|
|
6584
|
-
if (msg.role === "assistant" && msg.tool_calls) {
|
|
6585
|
-
return [
|
|
6586
|
-
{
|
|
6587
|
-
...msg,
|
|
6588
|
-
content: null,
|
|
6589
|
-
tool_calls: msg.tool_calls
|
|
6590
|
-
}
|
|
6591
|
-
];
|
|
6592
|
-
}
|
|
6593
|
-
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
6594
|
-
const contentBlocks = msg.content;
|
|
6595
|
-
const toolUseBlocks = contentBlocks.filter((b) => b.type === "tool_use");
|
|
6596
|
-
if (toolUseBlocks.length > 0) {
|
|
6597
|
-
const textParts = contentBlocks.filter((b) => b.type === "text").map((b) => b.text).filter(Boolean);
|
|
6598
|
-
return [
|
|
6599
|
-
{
|
|
6600
|
-
role: "assistant",
|
|
6601
|
-
content: textParts.length > 0 ? textParts.join("\n") : null,
|
|
6602
|
-
tool_calls: toolUseBlocks.map((b) => ({
|
|
6603
|
-
id: b.id,
|
|
6604
|
-
type: "function",
|
|
6605
|
-
function: {
|
|
6606
|
-
name: b.name,
|
|
6607
|
-
arguments: typeof b.input === "string" ? b.input : JSON.stringify(b.input)
|
|
6608
|
-
}
|
|
6609
|
-
}))
|
|
6610
|
-
}
|
|
6611
|
-
];
|
|
6612
|
-
}
|
|
6613
|
-
}
|
|
6614
|
-
if (msg.role === "user" && Array.isArray(msg.content)) {
|
|
6615
|
-
const contentBlocks = msg.content;
|
|
6616
|
-
const toolResultBlocks = contentBlocks.filter((b) => b.type === "tool_result");
|
|
6617
|
-
if (toolResultBlocks.length > 0) {
|
|
6618
|
-
return toolResultBlocks.map((b) => ({
|
|
6619
|
-
role: "tool",
|
|
6620
|
-
content: typeof b.content === "string" ? b.content : JSON.stringify(b.content),
|
|
6621
|
-
tool_call_id: b.tool_use_id
|
|
6622
|
-
}));
|
|
6623
|
-
}
|
|
6624
|
-
}
|
|
6625
|
-
return [msg];
|
|
6626
|
-
}
|
|
6627
|
-
function convertMessagesToOpenAIFormat(messages) {
|
|
6628
|
-
return messages.flatMap(convertMessageToOpenAIFormat);
|
|
6629
|
-
}
|
|
6630
|
-
|
|
6631
|
-
// ../../b4m-core/packages/utils/dist/src/llm/ollamaBackend.js
|
|
6632
6581
|
var OllamaBackend = class {
|
|
6633
6582
|
_host;
|
|
6634
6583
|
_api;
|
|
@@ -6792,12 +6741,9 @@ var OllamaBackend = class {
|
|
|
6792
6741
|
/**
|
|
6793
6742
|
* Map IMessage[] to Ollama's Message[], preserving tool_calls for multi-turn
|
|
6794
6743
|
* tool conversations (added by pushToolMessages).
|
|
6795
|
-
* First converts B4M standard format (tool_use/tool_result) to OpenAI-compatible
|
|
6796
|
-
* format since Ollama uses the same tool_calls/role:tool convention.
|
|
6797
6744
|
*/
|
|
6798
6745
|
buildMessages(messages) {
|
|
6799
|
-
|
|
6800
|
-
return converted.map((msg) => {
|
|
6746
|
+
return messages.map((msg) => {
|
|
6801
6747
|
const raw = msg;
|
|
6802
6748
|
const mapped = {
|
|
6803
6749
|
role: msg.role,
|
|
@@ -7891,8 +7837,16 @@ Only when someone asks, remember that you are specifically the ${model} model.`;
|
|
|
7891
7837
|
role: "system",
|
|
7892
7838
|
content: systemContent
|
|
7893
7839
|
};
|
|
7894
|
-
const
|
|
7895
|
-
|
|
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
|
+
});
|
|
7896
7850
|
return isO1Model ? formattedMessages : [systemMessage, ...formattedMessages];
|
|
7897
7851
|
}
|
|
7898
7852
|
pushToolMessages(messages, tool, result, _thinkingBlocks) {
|
|
@@ -8415,7 +8369,17 @@ var XAIBackend = class {
|
|
|
8415
8369
|
}
|
|
8416
8370
|
}
|
|
8417
8371
|
formatMessages(messages) {
|
|
8418
|
-
|
|
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;
|
|
8419
8383
|
}
|
|
8420
8384
|
formatTools(tools = []) {
|
|
8421
8385
|
return tools.map((tool) => ({
|
|
@@ -36,13 +36,13 @@ import {
|
|
|
36
36
|
isReadOnlyTool,
|
|
37
37
|
loadContextFiles,
|
|
38
38
|
setWebSocketToolExecutor
|
|
39
|
-
} from "../chunk-
|
|
39
|
+
} from "../chunk-4ZO5RNWO.js";
|
|
40
40
|
import "../chunk-BDQBOLYG.js";
|
|
41
|
-
import "../chunk-
|
|
41
|
+
import "../chunk-F6IY547T.js";
|
|
42
42
|
import "../chunk-GQGOWACU.js";
|
|
43
|
-
import "../chunk-
|
|
44
|
-
import "../chunk-
|
|
45
|
-
import "../chunk-
|
|
43
|
+
import "../chunk-OFKZXY6L.js";
|
|
44
|
+
import "../chunk-WKPO5JDF.js";
|
|
45
|
+
import "../chunk-M7QGYBN7.js";
|
|
46
46
|
import "../chunk-PFBYGCOW.js";
|
|
47
47
|
import "../chunk-BPFEGDC7.js";
|
|
48
48
|
import {
|
package/dist/index.js
CHANGED
|
@@ -46,15 +46,15 @@ import {
|
|
|
46
46
|
setWebSocketToolExecutor,
|
|
47
47
|
substituteArguments,
|
|
48
48
|
warmFileCache
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-4ZO5RNWO.js";
|
|
50
50
|
import "./chunk-BDQBOLYG.js";
|
|
51
|
-
import "./chunk-
|
|
51
|
+
import "./chunk-F6IY547T.js";
|
|
52
52
|
import "./chunk-GQGOWACU.js";
|
|
53
|
-
import "./chunk-
|
|
54
|
-
import "./chunk-
|
|
53
|
+
import "./chunk-OFKZXY6L.js";
|
|
54
|
+
import "./chunk-WKPO5JDF.js";
|
|
55
55
|
import {
|
|
56
56
|
OllamaBackend
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-M7QGYBN7.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-
|
|
67
|
+
} from "./chunk-5SZI2XFM.js";
|
|
68
68
|
import {
|
|
69
69
|
selectActiveBackgroundAgents,
|
|
70
70
|
useCliStore
|
|
@@ -169,21 +169,9 @@ function CustomTextInput({
|
|
|
169
169
|
useInput(
|
|
170
170
|
(input, key) => {
|
|
171
171
|
if (key.return && !key.meta && !key.shift) {
|
|
172
|
-
if (value.length > 0 && value[cursorOffset - 1] === "\\") {
|
|
173
|
-
const newValue = value.slice(0, cursorOffset - 1) + "\n" + value.slice(cursorOffset);
|
|
174
|
-
emitChange(newValue);
|
|
175
|
-
setCursorOffset(cursorOffset);
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
172
|
onSubmit(value);
|
|
179
173
|
return;
|
|
180
174
|
}
|
|
181
|
-
if (key.return && (key.shift || key.meta)) {
|
|
182
|
-
const newValue = value.slice(0, cursorOffset) + "\n" + value.slice(cursorOffset);
|
|
183
|
-
emitChange(newValue);
|
|
184
|
-
setCursorOffset(cursorOffset + 1);
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
175
|
if (key.meta && !key.ctrl) {
|
|
188
176
|
if (key.shift) {
|
|
189
177
|
if (key.leftArrow) {
|
|
@@ -847,10 +835,7 @@ function InputPrompt({
|
|
|
847
835
|
const handlePaste = (content) => {
|
|
848
836
|
const truncated = content.length > MAX_PASTE_SIZE ? content.slice(0, MAX_PASTE_SIZE) : content;
|
|
849
837
|
const lineCount = truncated.split("\n").length;
|
|
850
|
-
|
|
851
|
-
const combined = prefix ? `${prefix}
|
|
852
|
-
${truncated}` : truncated;
|
|
853
|
-
setPastedContent(combined, lineCount);
|
|
838
|
+
setPastedContent(truncated, lineCount);
|
|
854
839
|
};
|
|
855
840
|
const handleChange = async (newValue) => {
|
|
856
841
|
if (pastedContent) {
|
|
@@ -2955,10 +2940,11 @@ function CliApp() {
|
|
|
2955
2940
|
throw new Error("No websocketUrl or wsCompletionUrl in server config");
|
|
2956
2941
|
}
|
|
2957
2942
|
} catch (wsError) {
|
|
2958
|
-
|
|
2959
|
-
|
|
2943
|
+
console.error(
|
|
2944
|
+
`\u26A0\uFE0F WebSocket unavailable, using SSE fallback: ${wsError instanceof Error ? wsError.message : String(wsError)}`
|
|
2945
|
+
);
|
|
2960
2946
|
if (wsError instanceof Error && wsError.stack) {
|
|
2961
|
-
|
|
2947
|
+
console.error(wsError.stack);
|
|
2962
2948
|
}
|
|
2963
2949
|
wsManager = null;
|
|
2964
2950
|
setWebSocketToolExecutor(null);
|
|
@@ -3742,11 +3728,7 @@ Pull a model: ollama pull qwen3.5`
|
|
|
3742
3728
|
return;
|
|
3743
3729
|
}
|
|
3744
3730
|
}
|
|
3745
|
-
|
|
3746
|
-
console.error(`
|
|
3747
|
-
\u274C ${errorMessage}
|
|
3748
|
-
`);
|
|
3749
|
-
logger.debug(`Full error details: ${error instanceof Error ? error.stack || error.message : String(error)}`);
|
|
3731
|
+
console.error("Error processing message:", error);
|
|
3750
3732
|
} finally {
|
|
3751
3733
|
setState((prev) => ({ ...prev, abortController: null }));
|
|
3752
3734
|
useCliStore.getState().setIsThinking(false);
|
|
@@ -4043,9 +4025,6 @@ Custom Commands:
|
|
|
4043
4025
|
/commands:new <name> - Create a new custom command
|
|
4044
4026
|
/commands:reload - Reload custom commands from disk
|
|
4045
4027
|
|
|
4046
|
-
Terminal Setup:
|
|
4047
|
-
/terminal-setup - Configure Shift+Enter for multi-line input
|
|
4048
|
-
|
|
4049
4028
|
Keyboard Shortcuts:
|
|
4050
4029
|
Ctrl+C - Press twice to exit
|
|
4051
4030
|
Esc - Abort current operation
|
|
@@ -4061,12 +4040,7 @@ Keyboard Shortcuts:
|
|
|
4061
4040
|
Ctrl+L - Clear input
|
|
4062
4041
|
\u2191 / \u2193 - Navigate history / autocomplete
|
|
4063
4042
|
Tab - Accept autocomplete suggestion
|
|
4064
|
-
Shift+Cmd+Click - Open links in browser
|
|
4065
|
-
|
|
4066
|
-
Multi-line Input:
|
|
4067
|
-
\\ + Enter - Insert newline (works everywhere)
|
|
4068
|
-
Option + Enter - Insert newline (macOS standard terminals)
|
|
4069
|
-
Shift + Enter - Insert newline (iTerm2, WezTerm, Ghostty, Kitty)${hasCustomCommands ? "\n\n\u{1F4DD} Custom Commands Available:" : ""}${hasCustomCommands ? customCommands.map((cmd) => {
|
|
4043
|
+
Shift+Cmd+Click - Open links in browser${hasCustomCommands ? "\n\n\u{1F4DD} Custom Commands Available:" : ""}${hasCustomCommands ? customCommands.map((cmd) => {
|
|
4070
4044
|
const source = cmd.source === "global" ? "\u{1F3E0}" : "\u{1F4C1}";
|
|
4071
4045
|
const argHint = cmd.argumentHint ? ` ${cmd.argumentHint}` : "";
|
|
4072
4046
|
return `
|
|
@@ -5081,11 +5055,6 @@ Allowed domains (${domains.length}):`);
|
|
|
5081
5055
|
console.log("");
|
|
5082
5056
|
break;
|
|
5083
5057
|
}
|
|
5084
|
-
case "terminal-setup": {
|
|
5085
|
-
const { runTerminalSetup } = await import("./terminalSetup-C5FHMLC3.js");
|
|
5086
|
-
await runTerminalSetup();
|
|
5087
|
-
break;
|
|
5088
|
-
}
|
|
5089
5058
|
case "add-dir": {
|
|
5090
5059
|
let dirPath = args.join(" ").trim();
|
|
5091
5060
|
if (!dirPath) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.2.49-fix-
|
|
3
|
+
"version": "0.2.49-fix-telemetry-alert-debug.21031+766fdd35a",
|
|
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-
|
|
119
|
-
"@bike4mind/mcp": "1.33.11-fix-
|
|
120
|
-
"@bike4mind/services": "2.63.1-fix-
|
|
121
|
-
"@bike4mind/utils": "2.15.4-fix-
|
|
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",
|
|
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": "
|
|
140
|
+
"gitHead": "766fdd35a8018f32ebf70db963625dcc6ea2d653"
|
|
141
141
|
}
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/utils/terminalSetup.ts
|
|
4
|
-
import { existsSync, promises as fs } from "fs";
|
|
5
|
-
import path from "path";
|
|
6
|
-
import { homedir } from "os";
|
|
7
|
-
var TERMINAL_INFO = {
|
|
8
|
-
iterm2: { name: "iTerm2", status: "native" },
|
|
9
|
-
wezterm: { name: "WezTerm", status: "native" },
|
|
10
|
-
ghostty: { name: "Ghostty", status: "native" },
|
|
11
|
-
kitty: { name: "Kitty", status: "native" },
|
|
12
|
-
vscode: { name: "VS Code", status: "configurable" },
|
|
13
|
-
alacritty: { name: "Alacritty", status: "configurable" },
|
|
14
|
-
zed: { name: "Zed", status: "manual" },
|
|
15
|
-
terminal_app: { name: "Terminal.app", status: "manual" },
|
|
16
|
-
warp: { name: "Warp", status: "manual" },
|
|
17
|
-
unknown: { name: "Unknown", status: "unknown" }
|
|
18
|
-
};
|
|
19
|
-
function detectTerminal() {
|
|
20
|
-
const termProgram = process.env["TERM_PROGRAM"] ?? "";
|
|
21
|
-
const term = process.env["TERM"] ?? "";
|
|
22
|
-
if (termProgram === "vscode" || process.env["VSCODE_PID"]) {
|
|
23
|
-
return { id: "vscode", ...TERMINAL_INFO.vscode };
|
|
24
|
-
}
|
|
25
|
-
if (termProgram === "iTerm.app" || process.env["ITERM_SESSION_ID"]) {
|
|
26
|
-
return { id: "iterm2", ...TERMINAL_INFO.iterm2 };
|
|
27
|
-
}
|
|
28
|
-
if (termProgram === "WezTerm" || process.env["WEZTERM_PANE"]) {
|
|
29
|
-
return { id: "wezterm", ...TERMINAL_INFO.wezterm };
|
|
30
|
-
}
|
|
31
|
-
if (termProgram === "ghostty" || term === "xterm-ghostty") {
|
|
32
|
-
return { id: "ghostty", ...TERMINAL_INFO.ghostty };
|
|
33
|
-
}
|
|
34
|
-
if (term === "xterm-kitty" || process.env["KITTY_PID"]) {
|
|
35
|
-
return { id: "kitty", ...TERMINAL_INFO.kitty };
|
|
36
|
-
}
|
|
37
|
-
if (termProgram === "Alacritty" || term === "alacritty") {
|
|
38
|
-
return { id: "alacritty", ...TERMINAL_INFO.alacritty };
|
|
39
|
-
}
|
|
40
|
-
if (termProgram === "WarpTerminal" || process.env["WARP_IS_LOCAL_SHELL_SESSION"]) {
|
|
41
|
-
return { id: "warp", ...TERMINAL_INFO.warp };
|
|
42
|
-
}
|
|
43
|
-
if (termProgram === "zed") {
|
|
44
|
-
return { id: "zed", ...TERMINAL_INFO.zed };
|
|
45
|
-
}
|
|
46
|
-
if (termProgram === "Apple_Terminal") {
|
|
47
|
-
return { id: "terminal_app", ...TERMINAL_INFO.terminal_app };
|
|
48
|
-
}
|
|
49
|
-
return { id: "unknown", ...TERMINAL_INFO.unknown };
|
|
50
|
-
}
|
|
51
|
-
var VSCODE_KEYBINDING = {
|
|
52
|
-
key: "shift+enter",
|
|
53
|
-
command: "workbench.action.terminal.sendSequence",
|
|
54
|
-
args: { text: "\x1B[13;2u" },
|
|
55
|
-
when: "terminalFocus"
|
|
56
|
-
};
|
|
57
|
-
async function setupVSCode() {
|
|
58
|
-
const vscodeDirs = [
|
|
59
|
-
path.join(homedir(), "Library", "Application Support", "Code", "User"),
|
|
60
|
-
// macOS
|
|
61
|
-
path.join(homedir(), ".config", "Code", "User"),
|
|
62
|
-
// Linux
|
|
63
|
-
path.join(homedir(), "AppData", "Roaming", "Code", "User")
|
|
64
|
-
// Windows
|
|
65
|
-
];
|
|
66
|
-
const vscodeDir = vscodeDirs.find((dir) => existsSync(dir));
|
|
67
|
-
if (!vscodeDir) {
|
|
68
|
-
return {
|
|
69
|
-
success: false,
|
|
70
|
-
message: "Could not find VS Code settings directory.\nManually add this to your keybindings.json (Cmd+K Cmd+S \u2192 Open Keyboard Shortcuts JSON):\n\n" + JSON.stringify(VSCODE_KEYBINDING, null, 2)
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
const keybindingsPath = path.join(vscodeDir, "keybindings.json");
|
|
74
|
-
let keybindings = [];
|
|
75
|
-
if (existsSync(keybindingsPath)) {
|
|
76
|
-
const content = await fs.readFile(keybindingsPath, "utf-8");
|
|
77
|
-
const stripped = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
78
|
-
try {
|
|
79
|
-
keybindings = JSON.parse(stripped);
|
|
80
|
-
} catch {
|
|
81
|
-
return {
|
|
82
|
-
success: false,
|
|
83
|
-
message: "Could not parse keybindings.json. Manually add this entry:\n\n" + JSON.stringify(VSCODE_KEYBINDING, null, 2)
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
const alreadyConfigured = keybindings.some(
|
|
88
|
-
(binding) => binding["key"] === "shift+enter" && binding["command"] === "workbench.action.terminal.sendSequence" && binding["when"] === "terminalFocus"
|
|
89
|
-
);
|
|
90
|
-
if (alreadyConfigured) {
|
|
91
|
-
return {
|
|
92
|
-
success: true,
|
|
93
|
-
message: "VS Code is already configured for Shift+Enter newlines."
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
keybindings.push(VSCODE_KEYBINDING);
|
|
97
|
-
await fs.writeFile(keybindingsPath, JSON.stringify(keybindings, null, 2) + "\n", "utf-8");
|
|
98
|
-
return {
|
|
99
|
-
success: true,
|
|
100
|
-
message: `Updated ${keybindingsPath}
|
|
101
|
-
Shift+Enter will now insert a newline in the B4M CLI.
|
|
102
|
-
Restart your VS Code terminal for the change to take effect.`
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
var ALACRITTY_TOML_SNIPPET = `
|
|
106
|
-
# B4M CLI: Shift+Enter sends Kitty-protocol sequence for newline
|
|
107
|
-
[[keyboard.bindings]]
|
|
108
|
-
key = "Return"
|
|
109
|
-
mods = "Shift"
|
|
110
|
-
chars = "\\u001b[13;2u"
|
|
111
|
-
`.trim();
|
|
112
|
-
async function setupAlacritty() {
|
|
113
|
-
const configPaths = [
|
|
114
|
-
path.join(homedir(), ".config", "alacritty", "alacritty.toml"),
|
|
115
|
-
path.join(homedir(), ".alacritty.toml")
|
|
116
|
-
];
|
|
117
|
-
const existingConfig = configPaths.find((p) => existsSync(p));
|
|
118
|
-
const configPath = existingConfig ?? configPaths[0];
|
|
119
|
-
let content = "";
|
|
120
|
-
if (existingConfig) {
|
|
121
|
-
content = await fs.readFile(configPath, "utf-8");
|
|
122
|
-
if (content.includes("[13;2u") || content.includes("\\u001b[13;2u")) {
|
|
123
|
-
return {
|
|
124
|
-
success: true,
|
|
125
|
-
message: "Alacritty is already configured for Shift+Enter newlines."
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
const newContent = content ? content.trimEnd() + "\n\n" + ALACRITTY_TOML_SNIPPET + "\n" : ALACRITTY_TOML_SNIPPET + "\n";
|
|
130
|
-
const configDir = path.dirname(configPath);
|
|
131
|
-
if (!existsSync(configDir)) {
|
|
132
|
-
await fs.mkdir(configDir, { recursive: true });
|
|
133
|
-
}
|
|
134
|
-
await fs.writeFile(configPath, newContent, "utf-8");
|
|
135
|
-
return {
|
|
136
|
-
success: true,
|
|
137
|
-
message: `Updated ${configPath}
|
|
138
|
-
Shift+Enter will now insert a newline in the B4M CLI.
|
|
139
|
-
Restart Alacritty for the change to take effect.`
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
function getManualInstructions(terminal) {
|
|
143
|
-
switch (terminal.id) {
|
|
144
|
-
case "zed":
|
|
145
|
-
return "Add this to your Zed keymap.json (Zed \u2192 Settings \u2192 Open Key Bindings):\n\n" + JSON.stringify(
|
|
146
|
-
[
|
|
147
|
-
{
|
|
148
|
-
context: "Terminal",
|
|
149
|
-
bindings: {
|
|
150
|
-
"shift-enter": ["terminal::SendText", "\\u001b[13;2u"]
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
],
|
|
154
|
-
null,
|
|
155
|
-
2
|
|
156
|
-
);
|
|
157
|
-
case "terminal_app":
|
|
158
|
-
return "macOS Terminal.app cannot send distinct Shift+Enter sequences.\n\nAlternatives:\n \u2022 Use Option+Enter (\u2325+Enter) to insert newlines\n \u2022 Type \\ then Enter to insert newlines\n \u2022 Switch to iTerm2, WezTerm, or Ghostty for native Shift+Enter support";
|
|
159
|
-
case "warp":
|
|
160
|
-
return "Warp terminal has limited keybinding customization.\n\nAlternatives:\n \u2022 Use Option+Enter (\u2325+Enter) to insert newlines\n \u2022 Type \\ then Enter to insert newlines";
|
|
161
|
-
default:
|
|
162
|
-
return "Your terminal needs to be configured to send a distinct escape sequence for Shift+Enter.\nConfigure Shift+Enter to send: \\x1b[13;2u (Kitty keyboard protocol)\n\nAlternatives that work in all terminals:\n \u2022 Option/Alt+Enter to insert newlines\n \u2022 Type \\ then Enter to insert newlines";
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
async function runTerminalSetup() {
|
|
166
|
-
const terminal = detectTerminal();
|
|
167
|
-
console.log(`
|
|
168
|
-
Detected terminal: ${terminal.name}
|
|
169
|
-
`);
|
|
170
|
-
switch (terminal.status) {
|
|
171
|
-
case "native":
|
|
172
|
-
console.log(`\u2705 ${terminal.name} natively supports Shift+Enter for newlines.
|
|
173
|
-
No configuration needed!
|
|
174
|
-
`);
|
|
175
|
-
break;
|
|
176
|
-
case "configurable": {
|
|
177
|
-
console.log(`Configuring ${terminal.name} for Shift+Enter support...
|
|
178
|
-
`);
|
|
179
|
-
let result;
|
|
180
|
-
switch (terminal.id) {
|
|
181
|
-
case "vscode":
|
|
182
|
-
result = await setupVSCode();
|
|
183
|
-
break;
|
|
184
|
-
case "alacritty":
|
|
185
|
-
result = await setupAlacritty();
|
|
186
|
-
break;
|
|
187
|
-
default:
|
|
188
|
-
result = { success: false, message: "No auto-configuration available." };
|
|
189
|
-
}
|
|
190
|
-
console.log(result.success ? `\u2705 ${result.message}` : `\u26A0\uFE0F ${result.message}`);
|
|
191
|
-
console.log();
|
|
192
|
-
break;
|
|
193
|
-
}
|
|
194
|
-
case "manual":
|
|
195
|
-
console.log(`\u26A0\uFE0F ${terminal.name} requires manual configuration.
|
|
196
|
-
`);
|
|
197
|
-
console.log(getManualInstructions(terminal));
|
|
198
|
-
console.log();
|
|
199
|
-
break;
|
|
200
|
-
case "unknown":
|
|
201
|
-
console.log(getManualInstructions(terminal));
|
|
202
|
-
console.log();
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
console.log("Universal newline methods (work in all terminals):");
|
|
206
|
-
console.log(" \u2022 Option/Alt + Enter \u2014 insert newline");
|
|
207
|
-
console.log(" \u2022 \\ + Enter \u2014 insert newline (backslash-escape)");
|
|
208
|
-
console.log(" \u2022 Shift + Enter \u2014 insert newline (if terminal supports Kitty protocol)");
|
|
209
|
-
console.log();
|
|
210
|
-
}
|
|
211
|
-
export {
|
|
212
|
-
detectTerminal,
|
|
213
|
-
runTerminalSetup
|
|
214
|
-
};
|