@bike4mind/cli 0.2.49-fix-cli-stream-resilience-v2.21033 → 0.2.49-prod.21090
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/{artifactExtractor-SIFIV3ZN.js → artifactExtractor-VRHQFYPK.js} +1 -1
- package/dist/{chunk-7VEI22BF.js → chunk-2K6DFEPJ.js} +2 -2
- package/dist/{chunk-AINGID72.js → chunk-DVVQ3AZN.js} +7 -7
- package/dist/{chunk-MP3FYWMR.js → chunk-EOOKQOLY.js} +2 -2
- package/dist/{chunk-W5MJV36K.js → chunk-LZBANFHR.js} +1 -1
- package/dist/{chunk-UDBM5N7V.js → chunk-QU3ADG2K.js} +23 -59
- package/dist/{chunk-X26VCD3A.js → chunk-UVP4KCPD.js} +2 -2
- package/dist/{chunk-QLY3LGPA.js → chunk-YRYNVLXM.js} +4 -2
- package/dist/{chunk-2WNNPZZS.js → chunk-ZCOPMHYC.js} +64 -63
- package/dist/commands/doctorCommand.js +1 -1
- package/dist/commands/headlessCommand.js +7 -7
- package/dist/commands/mcpCommand.js +2 -2
- package/dist/commands/updateCommand.js +1 -1
- package/dist/{create-PA2DIVCF.js → create-GZMDYERE.js} +3 -3
- package/dist/index.js +43 -18
- package/dist/{llmMarkdownGenerator-WOAXMXDB.js → llmMarkdownGenerator-GUV467LM.js} +1 -1
- package/dist/{markdownGenerator-HZIPL4XS.js → markdownGenerator-MSDIQLK2.js} +1 -1
- package/dist/{mementoService-W76KVRGE.js → mementoService-K2MKVU4Z.js} +3 -3
- package/dist/{src-XUTQ6N2T.js → src-4HG4RMU4.js} +2 -2
- package/dist/{src-ODP5CCCC.js → src-GYWZKBK7.js} +1 -1
- package/dist/{subtractCredits-3V5REXEH.js → subtractCredits-FBO5JUX3.js} +3 -3
- package/dist/terminalSetup-C5FHMLC3.js +214 -0
- package/package.json +7 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CurationArtifactType
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YRYNVLXM.js";
|
|
5
5
|
|
|
6
6
|
// ../../b4m-core/packages/services/dist/src/notebookCurationService/artifactExtractor.js
|
|
7
7
|
var ARTIFACT_TAG_REGEX = /<artifact\s+(.*?)>([\s\S]*?)<\/artifact>/gi;
|
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
getSettingsByNames,
|
|
7
7
|
obfuscateApiKey,
|
|
8
8
|
secureParameters
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-QU3ADG2K.js";
|
|
10
10
|
import {
|
|
11
11
|
ApiKeyType,
|
|
12
12
|
MementoTier,
|
|
13
13
|
isSupportedEmbeddingModel
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-YRYNVLXM.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/apiKeyService/get.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@bike4mind/cli",
|
|
6
|
-
version: "0.2.49-
|
|
6
|
+
version: "0.2.49-prod.21090+4ff436a32",
|
|
7
7
|
type: "module",
|
|
8
8
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
9
9
|
license: "UNLICENSED",
|
|
@@ -64,7 +64,7 @@ var package_default = {
|
|
|
64
64
|
"@smithy/node-http-handler": "^4.4.14",
|
|
65
65
|
"async-mutex": "^0.5.0",
|
|
66
66
|
axios: "^1.13.6",
|
|
67
|
-
bcryptjs: "^
|
|
67
|
+
bcryptjs: "^3.0.2",
|
|
68
68
|
"better-sqlite3": "^12.6.2",
|
|
69
69
|
cheerio: "1.0.0-rc.12",
|
|
70
70
|
"cli-highlight": "^2.1.11",
|
|
@@ -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-
|
|
122
|
-
"@bike4mind/mcp": "1.33.11-
|
|
123
|
-
"@bike4mind/services": "2.63.1-
|
|
124
|
-
"@bike4mind/utils": "2.15.4-
|
|
121
|
+
"@bike4mind/common": "2.67.1-prod.21090+4ff436a32",
|
|
122
|
+
"@bike4mind/mcp": "1.33.11-prod.21090+4ff436a32",
|
|
123
|
+
"@bike4mind/services": "2.63.1-prod.21090+4ff436a32",
|
|
124
|
+
"@bike4mind/utils": "2.15.4-prod.21090+4ff436a32",
|
|
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: "4ff436a32269365aba08bda30e846fad8c6142ee"
|
|
144
144
|
};
|
|
145
145
|
|
|
146
146
|
// src/utils/updateChecker.ts
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
getSettingsMap,
|
|
8
8
|
getSettingsValue,
|
|
9
9
|
secureParameters
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QU3ADG2K.js";
|
|
11
11
|
import {
|
|
12
12
|
KnowledgeType,
|
|
13
13
|
SupportedFabFileMimeTypes
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-YRYNVLXM.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/fabFileService/create.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
extractSnippetMeta,
|
|
21
21
|
isGPTImageModel,
|
|
22
22
|
settingsMap
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-YRYNVLXM.js";
|
|
24
24
|
|
|
25
25
|
// ../../b4m-core/packages/utils/dist/src/storage/S3Storage.js
|
|
26
26
|
import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";
|
|
@@ -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) => ({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BadRequestError,
|
|
4
4
|
secureParameters
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QU3ADG2K.js";
|
|
6
6
|
import {
|
|
7
7
|
CompletionApiUsageTransaction,
|
|
8
8
|
GenericCreditDeductTransaction,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
ToolUsageTransaction,
|
|
14
14
|
TransferCreditTransaction,
|
|
15
15
|
VideoGenerationUsageTransaction
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-YRYNVLXM.js";
|
|
17
17
|
|
|
18
18
|
// ../../b4m-core/packages/services/dist/src/creditService/subtractCredits.js
|
|
19
19
|
import { z } from "zod";
|
|
@@ -1284,8 +1284,10 @@ var SreAgentConfigSchema = z10.object({
|
|
|
1284
1284
|
/** Repository name (e.g. "lumina5") */
|
|
1285
1285
|
repo: z10.string().default(""),
|
|
1286
1286
|
/** Comma-separated GitHub usernames to request as PR reviewers */
|
|
1287
|
-
reviewers: z10.string().default("")
|
|
1288
|
-
|
|
1287
|
+
reviewers: z10.string().default(""),
|
|
1288
|
+
/** HMAC secret for the system-level SRE webhook endpoint (encrypted at rest with SECRET_ENCRYPTION_KEY) */
|
|
1289
|
+
webhookSecret: z10.string().default("")
|
|
1290
|
+
}).default({ owner: "", repo: "", reviewers: "", webhookSecret: "" }),
|
|
1289
1291
|
/** Per-source toggles */
|
|
1290
1292
|
sources: z10.object({
|
|
1291
1293
|
cloudwatch: z10.object({ enabled: z10.boolean().default(false) }).default({ enabled: false }),
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getOpenWeatherKey,
|
|
5
5
|
getSerperKey,
|
|
6
6
|
getWolframAlphaKey
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2K6DFEPJ.js";
|
|
8
8
|
import {
|
|
9
9
|
BFLImageService,
|
|
10
10
|
BaseStorage,
|
|
@@ -16,14 +16,14 @@ import {
|
|
|
16
16
|
OpenAIBackend,
|
|
17
17
|
OpenAIImageService,
|
|
18
18
|
XAIImageService
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-QU3ADG2K.js";
|
|
20
20
|
import {
|
|
21
21
|
Logger
|
|
22
22
|
} from "./chunk-PFBYGCOW.js";
|
|
23
23
|
import {
|
|
24
24
|
ConfigStore,
|
|
25
25
|
logger
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-LZBANFHR.js";
|
|
27
27
|
import {
|
|
28
28
|
ALERT_THRESHOLDS,
|
|
29
29
|
AiEvents,
|
|
@@ -84,7 +84,7 @@ import {
|
|
|
84
84
|
getViewById,
|
|
85
85
|
resolveNavigationIntents,
|
|
86
86
|
sanitizeTelemetryError
|
|
87
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-YRYNVLXM.js";
|
|
88
88
|
|
|
89
89
|
// src/utils/fileSearch.ts
|
|
90
90
|
import * as fs from "fs";
|
|
@@ -503,6 +503,10 @@ 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
|
+
},
|
|
506
510
|
{
|
|
507
511
|
name: "add-dir",
|
|
508
512
|
description: "Add a directory for file access",
|
|
@@ -14017,25 +14021,40 @@ var AnomalyAlertService = class _AnomalyAlertService {
|
|
|
14017
14021
|
* Check if an alert should be sent and send it if appropriate
|
|
14018
14022
|
*/
|
|
14019
14023
|
async checkAndAlert(telemetry) {
|
|
14024
|
+
console.log("[AnomalyAlert] DEBUG: checkAndAlert called", {
|
|
14025
|
+
enabled: this.config.enabled,
|
|
14026
|
+
isSlackConfigured: this.isSlackConfigured()
|
|
14027
|
+
});
|
|
14020
14028
|
if (!this.config.enabled || !this.isSlackConfigured()) {
|
|
14029
|
+
console.log("[AnomalyAlert] DEBUG: Early return - not enabled or Slack not configured");
|
|
14021
14030
|
return false;
|
|
14022
14031
|
}
|
|
14023
14032
|
const { anomalies } = telemetry;
|
|
14024
14033
|
const threshold = this.config.alertThreshold ?? ALERT_THRESHOLDS.warning;
|
|
14034
|
+
console.log("[AnomalyAlert] DEBUG: Threshold check", {
|
|
14035
|
+
anomalyScore: anomalies.anomalyScore,
|
|
14036
|
+
threshold
|
|
14037
|
+
});
|
|
14025
14038
|
if (anomalies.anomalyScore < threshold) {
|
|
14039
|
+
console.log("[AnomalyAlert] DEBUG: Score below threshold");
|
|
14026
14040
|
return false;
|
|
14027
14041
|
}
|
|
14042
|
+
console.log("[AnomalyAlert] DEBUG: Checking deduplication", { dedupKey: anomalies.dedupKey });
|
|
14028
14043
|
const isDup = await this.checkDeduplication(anomalies.dedupKey);
|
|
14044
|
+
console.log("[AnomalyAlert] DEBUG: Dedup result", { isDup });
|
|
14029
14045
|
if (isDup) {
|
|
14030
14046
|
this.logger.info(`\u{1F4CA} [AnomalyAlert] Suppressed duplicate alert: ${anomalies.dedupKey}`);
|
|
14031
14047
|
return false;
|
|
14032
14048
|
}
|
|
14033
14049
|
try {
|
|
14050
|
+
console.log("[AnomalyAlert] DEBUG: Sending Slack alert");
|
|
14034
14051
|
const message = this.formatSlackMessage(telemetry);
|
|
14035
14052
|
await this.sendSlackAlert(message);
|
|
14036
14053
|
this.logger.info(`\u{1F4CA} [AnomalyAlert] Alert sent for ${anomalies.primaryAnomaly} (score: ${anomalies.anomalyScore})`);
|
|
14054
|
+
console.log("[AnomalyAlert] DEBUG: Alert sent successfully");
|
|
14037
14055
|
return true;
|
|
14038
14056
|
} catch (error) {
|
|
14057
|
+
console.log("[AnomalyAlert] DEBUG: Failed to send alert", { error: String(error) });
|
|
14039
14058
|
this.logger.error(`\u{1F4CA} [AnomalyAlert] Failed to send alert:`, error);
|
|
14040
14059
|
return false;
|
|
14041
14060
|
}
|
|
@@ -16142,48 +16161,17 @@ function extractUsageInfo(parsed) {
|
|
|
16142
16161
|
usdCost: parsed.credits?.usdCost
|
|
16143
16162
|
};
|
|
16144
16163
|
}
|
|
16145
|
-
var ServerLlmBackend = class
|
|
16164
|
+
var ServerLlmBackend = class {
|
|
16146
16165
|
constructor(options) {
|
|
16147
16166
|
this.completionsEndpoint = "/api/ai/v1/completions";
|
|
16148
16167
|
this.apiClient = options.apiClient;
|
|
16149
16168
|
this.currentModel = options.model;
|
|
16150
16169
|
}
|
|
16151
|
-
static {
|
|
16152
|
-
/** Max retries for transient stream failures (e.g. missing [DONE]) */
|
|
16153
|
-
this.MAX_STREAM_RETRIES = 2;
|
|
16154
|
-
}
|
|
16155
16170
|
/**
|
|
16156
16171
|
* Make authenticated LLM completion request via server
|
|
16157
|
-
* Parses SSE stream and invokes callback for each event
|
|
16158
|
-
* Automatically retries on transient stream failures (e.g. stream ending prematurely).
|
|
16172
|
+
* Parses SSE stream and invokes callback for each event
|
|
16159
16173
|
*/
|
|
16160
16174
|
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) {
|
|
16187
16175
|
logger.debug(`[ServerLlmBackend] Starting complete() with model: ${model}`);
|
|
16188
16176
|
if (options.abortSignal?.aborted) {
|
|
16189
16177
|
logger.debug("[ServerLlmBackend] Request aborted before start");
|
|
@@ -16384,30 +16372,8 @@ var ServerLlmBackend = class _ServerLlmBackend {
|
|
|
16384
16372
|
});
|
|
16385
16373
|
response.data.on("end", () => {
|
|
16386
16374
|
if (!receivedDone) {
|
|
16387
|
-
|
|
16388
|
-
|
|
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).catch((err) => reject(err)).then(() => resolve3());
|
|
16401
|
-
} else if (cleanedText) {
|
|
16402
|
-
callback([cleanedText], lastUsageInfo).catch((err) => reject(err)).then(() => resolve3());
|
|
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
|
-
}
|
|
16375
|
+
logger.debug("[ServerLlmBackend] Stream ended without [DONE], resolving anyway");
|
|
16376
|
+
resolve3();
|
|
16411
16377
|
} else {
|
|
16412
16378
|
logger.debug("[ServerLlmBackend] Stream ended, [DONE] handler will resolve");
|
|
16413
16379
|
}
|
|
@@ -16665,8 +16631,43 @@ var WebSocketLlmBackend = class {
|
|
|
16665
16631
|
});
|
|
16666
16632
|
});
|
|
16667
16633
|
}
|
|
16668
|
-
pushToolMessages(
|
|
16669
|
-
|
|
16634
|
+
pushToolMessages(messages, tool, result, thinkingBlocks) {
|
|
16635
|
+
if (thinkingBlocks && thinkingBlocks.length > 0) {
|
|
16636
|
+
messages.push({
|
|
16637
|
+
role: "assistant",
|
|
16638
|
+
content: [
|
|
16639
|
+
...thinkingBlocks,
|
|
16640
|
+
{
|
|
16641
|
+
type: "tool_use",
|
|
16642
|
+
id: tool.id,
|
|
16643
|
+
name: tool.name,
|
|
16644
|
+
input: JSON.parse(tool.parameters || "{}")
|
|
16645
|
+
}
|
|
16646
|
+
]
|
|
16647
|
+
});
|
|
16648
|
+
} else {
|
|
16649
|
+
messages.push({
|
|
16650
|
+
role: "assistant",
|
|
16651
|
+
content: [
|
|
16652
|
+
{
|
|
16653
|
+
type: "tool_use",
|
|
16654
|
+
id: tool.id,
|
|
16655
|
+
name: tool.name,
|
|
16656
|
+
input: JSON.parse(tool.parameters || "{}")
|
|
16657
|
+
}
|
|
16658
|
+
]
|
|
16659
|
+
});
|
|
16660
|
+
}
|
|
16661
|
+
messages.push({
|
|
16662
|
+
role: "user",
|
|
16663
|
+
content: [
|
|
16664
|
+
{
|
|
16665
|
+
type: "tool_result",
|
|
16666
|
+
tool_use_id: tool.id,
|
|
16667
|
+
content: result
|
|
16668
|
+
}
|
|
16669
|
+
]
|
|
16670
|
+
});
|
|
16670
16671
|
}
|
|
16671
16672
|
/**
|
|
16672
16673
|
* Get available models from server (REST call, not streaming).
|
|
@@ -36,20 +36,20 @@ import {
|
|
|
36
36
|
isReadOnlyTool,
|
|
37
37
|
loadContextFiles,
|
|
38
38
|
setWebSocketToolExecutor
|
|
39
|
-
} from "../chunk-
|
|
39
|
+
} from "../chunk-ZCOPMHYC.js";
|
|
40
40
|
import "../chunk-BDQBOLYG.js";
|
|
41
|
-
import "../chunk-
|
|
41
|
+
import "../chunk-2K6DFEPJ.js";
|
|
42
42
|
import "../chunk-GQGOWACU.js";
|
|
43
|
-
import "../chunk-
|
|
44
|
-
import "../chunk-
|
|
45
|
-
import "../chunk-
|
|
43
|
+
import "../chunk-UVP4KCPD.js";
|
|
44
|
+
import "../chunk-EOOKQOLY.js";
|
|
45
|
+
import "../chunk-QU3ADG2K.js";
|
|
46
46
|
import "../chunk-PFBYGCOW.js";
|
|
47
47
|
import "../chunk-BPFEGDC7.js";
|
|
48
48
|
import {
|
|
49
49
|
ConfigStore,
|
|
50
50
|
logger
|
|
51
|
-
} from "../chunk-
|
|
52
|
-
import "../chunk-
|
|
51
|
+
} from "../chunk-LZBANFHR.js";
|
|
52
|
+
import "../chunk-YRYNVLXM.js";
|
|
53
53
|
import {
|
|
54
54
|
DEFAULT_SANDBOX_CONFIG
|
|
55
55
|
} from "../chunk-4BIBE3J7.js";
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createFabFile,
|
|
4
4
|
createFabFileSchema
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-EOOKQOLY.js";
|
|
6
|
+
import "./chunk-QU3ADG2K.js";
|
|
7
7
|
import "./chunk-PFBYGCOW.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-YRYNVLXM.js";
|
|
9
9
|
export {
|
|
10
10
|
createFabFile,
|
|
11
11
|
createFabFileSchema
|
package/dist/index.js
CHANGED
|
@@ -46,25 +46,25 @@ import {
|
|
|
46
46
|
setWebSocketToolExecutor,
|
|
47
47
|
substituteArguments,
|
|
48
48
|
warmFileCache
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-ZCOPMHYC.js";
|
|
50
50
|
import "./chunk-BDQBOLYG.js";
|
|
51
|
-
import "./chunk-
|
|
51
|
+
import "./chunk-2K6DFEPJ.js";
|
|
52
52
|
import "./chunk-GQGOWACU.js";
|
|
53
|
-
import "./chunk-
|
|
54
|
-
import "./chunk-
|
|
53
|
+
import "./chunk-UVP4KCPD.js";
|
|
54
|
+
import "./chunk-EOOKQOLY.js";
|
|
55
55
|
import {
|
|
56
56
|
OllamaBackend
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-QU3ADG2K.js";
|
|
58
58
|
import "./chunk-PFBYGCOW.js";
|
|
59
59
|
import "./chunk-BPFEGDC7.js";
|
|
60
60
|
import {
|
|
61
61
|
ConfigStore,
|
|
62
62
|
logger
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-LZBANFHR.js";
|
|
64
64
|
import {
|
|
65
65
|
checkForUpdate,
|
|
66
66
|
package_default
|
|
67
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-DVVQ3AZN.js";
|
|
68
68
|
import {
|
|
69
69
|
selectActiveBackgroundAgents,
|
|
70
70
|
useCliStore
|
|
@@ -72,7 +72,7 @@ import {
|
|
|
72
72
|
import {
|
|
73
73
|
CREDIT_DEDUCT_TRANSACTION_TYPES,
|
|
74
74
|
ChatModels
|
|
75
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-YRYNVLXM.js";
|
|
76
76
|
import "./chunk-4BIBE3J7.js";
|
|
77
77
|
|
|
78
78
|
// src/index.tsx
|
|
@@ -169,9 +169,21 @@ 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
|
+
}
|
|
172
178
|
onSubmit(value);
|
|
173
179
|
return;
|
|
174
180
|
}
|
|
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
|
+
}
|
|
175
187
|
if (key.meta && !key.ctrl) {
|
|
176
188
|
if (key.shift) {
|
|
177
189
|
if (key.leftArrow) {
|
|
@@ -835,7 +847,10 @@ function InputPrompt({
|
|
|
835
847
|
const handlePaste = (content) => {
|
|
836
848
|
const truncated = content.length > MAX_PASTE_SIZE ? content.slice(0, MAX_PASTE_SIZE) : content;
|
|
837
849
|
const lineCount = truncated.split("\n").length;
|
|
838
|
-
|
|
850
|
+
const prefix = value.trim();
|
|
851
|
+
const combined = prefix ? `${prefix}
|
|
852
|
+
${truncated}` : truncated;
|
|
853
|
+
setPastedContent(combined, lineCount);
|
|
839
854
|
};
|
|
840
855
|
const handleChange = async (newValue) => {
|
|
841
856
|
if (pastedContent) {
|
|
@@ -2940,10 +2955,11 @@ function CliApp() {
|
|
|
2940
2955
|
throw new Error("No websocketUrl or wsCompletionUrl in server config");
|
|
2941
2956
|
}
|
|
2942
2957
|
} catch (wsError) {
|
|
2943
|
-
|
|
2944
|
-
|
|
2958
|
+
console.error(
|
|
2959
|
+
`\u26A0\uFE0F WebSocket unavailable, using SSE fallback: ${wsError instanceof Error ? wsError.message : String(wsError)}`
|
|
2960
|
+
);
|
|
2945
2961
|
if (wsError instanceof Error && wsError.stack) {
|
|
2946
|
-
|
|
2962
|
+
console.error(wsError.stack);
|
|
2947
2963
|
}
|
|
2948
2964
|
wsManager = null;
|
|
2949
2965
|
setWebSocketToolExecutor(null);
|
|
@@ -3727,11 +3743,7 @@ Pull a model: ollama pull qwen3.5`
|
|
|
3727
3743
|
return;
|
|
3728
3744
|
}
|
|
3729
3745
|
}
|
|
3730
|
-
|
|
3731
|
-
console.error(`
|
|
3732
|
-
\u274C ${errorMessage}
|
|
3733
|
-
`);
|
|
3734
|
-
logger.debug(`Full error details: ${error instanceof Error ? error.stack || error.message : String(error)}`);
|
|
3746
|
+
console.error("Error processing message:", error);
|
|
3735
3747
|
} finally {
|
|
3736
3748
|
setState((prev) => ({ ...prev, abortController: null }));
|
|
3737
3749
|
useCliStore.getState().setIsThinking(false);
|
|
@@ -4028,6 +4040,9 @@ Custom Commands:
|
|
|
4028
4040
|
/commands:new <name> - Create a new custom command
|
|
4029
4041
|
/commands:reload - Reload custom commands from disk
|
|
4030
4042
|
|
|
4043
|
+
Terminal Setup:
|
|
4044
|
+
/terminal-setup - Configure Shift+Enter for multi-line input
|
|
4045
|
+
|
|
4031
4046
|
Keyboard Shortcuts:
|
|
4032
4047
|
Ctrl+C - Press twice to exit
|
|
4033
4048
|
Esc - Abort current operation
|
|
@@ -4043,7 +4058,12 @@ Keyboard Shortcuts:
|
|
|
4043
4058
|
Ctrl+L - Clear input
|
|
4044
4059
|
\u2191 / \u2193 - Navigate history / autocomplete
|
|
4045
4060
|
Tab - Accept autocomplete suggestion
|
|
4046
|
-
Shift+Cmd+Click - Open links in browser
|
|
4061
|
+
Shift+Cmd+Click - Open links in browser
|
|
4062
|
+
|
|
4063
|
+
Multi-line Input:
|
|
4064
|
+
\\ + Enter - Insert newline (works everywhere)
|
|
4065
|
+
Option + Enter - Insert newline (macOS standard terminals)
|
|
4066
|
+
Shift + Enter - Insert newline (iTerm2, WezTerm, Ghostty, Kitty)${hasCustomCommands ? "\n\n\u{1F4DD} Custom Commands Available:" : ""}${hasCustomCommands ? customCommands.map((cmd) => {
|
|
4047
4067
|
const source = cmd.source === "global" ? "\u{1F3E0}" : "\u{1F4C1}";
|
|
4048
4068
|
const argHint = cmd.argumentHint ? ` ${cmd.argumentHint}` : "";
|
|
4049
4069
|
return `
|
|
@@ -5058,6 +5078,11 @@ Allowed domains (${domains.length}):`);
|
|
|
5058
5078
|
console.log("");
|
|
5059
5079
|
break;
|
|
5060
5080
|
}
|
|
5081
|
+
case "terminal-setup": {
|
|
5082
|
+
const { runTerminalSetup } = await import("./terminalSetup-C5FHMLC3.js");
|
|
5083
|
+
await runTerminalSetup();
|
|
5084
|
+
break;
|
|
5085
|
+
}
|
|
5061
5086
|
case "add-dir": {
|
|
5062
5087
|
let dirPath = args.join(" ").trim();
|
|
5063
5088
|
if (!dirPath) {
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
findMostSimilarMemento,
|
|
4
4
|
getRelevantMementos
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-2K6DFEPJ.js";
|
|
6
|
+
import "./chunk-QU3ADG2K.js";
|
|
7
7
|
import "./chunk-PFBYGCOW.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-YRYNVLXM.js";
|
|
9
9
|
export {
|
|
10
10
|
findMostSimilarMemento,
|
|
11
11
|
getRelevantMementos
|
|
@@ -143,7 +143,7 @@ import {
|
|
|
143
143
|
validateUrlForFetch,
|
|
144
144
|
warmUpSettingsCache,
|
|
145
145
|
withRetry
|
|
146
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-QU3ADG2K.js";
|
|
147
147
|
import {
|
|
148
148
|
Logger,
|
|
149
149
|
NotificationDeduplicator,
|
|
@@ -156,7 +156,7 @@ import {
|
|
|
156
156
|
buildRateLimitLogEntry,
|
|
157
157
|
isNearLimit,
|
|
158
158
|
parseRateLimitHeaders
|
|
159
|
-
} from "./chunk-
|
|
159
|
+
} from "./chunk-YRYNVLXM.js";
|
|
160
160
|
export {
|
|
161
161
|
AIVideoService,
|
|
162
162
|
AWSBackend,
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
SubtractCreditsSchema,
|
|
4
4
|
subtractCredits
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-UVP4KCPD.js";
|
|
6
|
+
import "./chunk-QU3ADG2K.js";
|
|
7
7
|
import "./chunk-PFBYGCOW.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-YRYNVLXM.js";
|
|
9
9
|
export {
|
|
10
10
|
SubtractCreditsSchema,
|
|
11
11
|
subtractCredits
|
|
@@ -0,0 +1,214 @@
|
|
|
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
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.2.49-
|
|
3
|
+
"version": "0.2.49-prod.21090+4ff436a32",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@smithy/node-http-handler": "^4.4.14",
|
|
62
62
|
"async-mutex": "^0.5.0",
|
|
63
63
|
"axios": "^1.13.6",
|
|
64
|
-
"bcryptjs": "^
|
|
64
|
+
"bcryptjs": "^3.0.2",
|
|
65
65
|
"better-sqlite3": "^12.6.2",
|
|
66
66
|
"cheerio": "1.0.0-rc.12",
|
|
67
67
|
"cli-highlight": "^2.1.11",
|
|
@@ -115,10 +115,10 @@
|
|
|
115
115
|
},
|
|
116
116
|
"devDependencies": {
|
|
117
117
|
"@bike4mind/agents": "0.1.0",
|
|
118
|
-
"@bike4mind/common": "2.67.1-
|
|
119
|
-
"@bike4mind/mcp": "1.33.11-
|
|
120
|
-
"@bike4mind/services": "2.63.1-
|
|
121
|
-
"@bike4mind/utils": "2.15.4-
|
|
118
|
+
"@bike4mind/common": "2.67.1-prod.21090+4ff436a32",
|
|
119
|
+
"@bike4mind/mcp": "1.33.11-prod.21090+4ff436a32",
|
|
120
|
+
"@bike4mind/services": "2.63.1-prod.21090+4ff436a32",
|
|
121
|
+
"@bike4mind/utils": "2.15.4-prod.21090+4ff436a32",
|
|
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": "4ff436a32269365aba08bda30e846fad8c6142ee"
|
|
141
141
|
}
|