@bike4mind/cli 0.2.30-feat-cli-scrollable-command-autocomplete.19204 → 0.2.30-feat-cli-websocket-streaming.19243
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-SVFEWL53.js → artifactExtractor-PK2WNCBH.js} +1 -1
- package/dist/{chunk-C3K7SH2V.js → chunk-55ZDRTGQ.js} +67 -2
- package/dist/{chunk-5HA4JEOV.js → chunk-7EEPLDUG.js} +12 -3
- package/dist/{chunk-TVW4ZESU.js → chunk-BYXFQJYT.js} +10 -1
- package/dist/{chunk-B7Z2QQMD.js → chunk-K5IURWQT.js} +2 -2
- package/dist/{chunk-65DLNQY2.js → chunk-KBRR7H2K.js} +2 -2
- package/dist/{chunk-BYLWQZ5S.js → chunk-XXYKIX5X.js} +2 -2
- package/dist/{create-IDGWY5LO.js → create-IUID2337.js} +3 -3
- package/dist/index.js +582 -72
- package/dist/{llmMarkdownGenerator-BILRFSX6.js → llmMarkdownGenerator-Q3PRX6UR.js} +1 -1
- package/dist/{markdownGenerator-AI3EZ4Z3.js → markdownGenerator-TFFIS7MF.js} +1 -1
- package/dist/{mementoService-34S5SRX4.js → mementoService-5ZUSQ4B4.js} +3 -3
- package/dist/{src-MDS22ESD.js → src-LLWYZKB2.js} +2 -2
- package/dist/{src-QX72HMCT.js → src-QWRGDJYC.js} +13 -1
- package/dist/{store-FU6NDC2W.js → store-K5MB3SE7.js} +1 -1
- package/dist/{subtractCredits-6CK3FPNG.js → subtractCredits-LXVQL26O.js} +3 -3
- package/package.json +6 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CurationArtifactType
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-55ZDRTGQ.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;
|
|
@@ -1181,6 +1181,29 @@ var VoiceSessionSendTranscriptAction = z10.object({
|
|
|
1181
1181
|
conversationItemId: z10.string(),
|
|
1182
1182
|
timestamp: z10.coerce.date().optional()
|
|
1183
1183
|
});
|
|
1184
|
+
var CliCompletionRequestAction = z10.object({
|
|
1185
|
+
action: z10.literal("cli_completion_request"),
|
|
1186
|
+
accessToken: z10.string(),
|
|
1187
|
+
requestId: z10.string().uuid(),
|
|
1188
|
+
model: z10.string(),
|
|
1189
|
+
messages: z10.array(z10.object({
|
|
1190
|
+
role: z10.enum(["user", "assistant", "system"]),
|
|
1191
|
+
content: z10.union([z10.string(), z10.array(z10.unknown())])
|
|
1192
|
+
})),
|
|
1193
|
+
options: z10.object({
|
|
1194
|
+
temperature: z10.number().optional(),
|
|
1195
|
+
maxTokens: z10.number().optional(),
|
|
1196
|
+
stream: z10.boolean().optional(),
|
|
1197
|
+
tools: z10.array(z10.unknown()).optional()
|
|
1198
|
+
}).optional()
|
|
1199
|
+
});
|
|
1200
|
+
var CliToolRequestAction = z10.object({
|
|
1201
|
+
action: z10.literal("cli_tool_request"),
|
|
1202
|
+
accessToken: z10.string(),
|
|
1203
|
+
requestId: z10.string().uuid(),
|
|
1204
|
+
toolName: z10.string(),
|
|
1205
|
+
input: z10.record(z10.unknown())
|
|
1206
|
+
});
|
|
1184
1207
|
var VoiceSessionEndedAction = z10.object({
|
|
1185
1208
|
action: z10.literal("voice_session_ended"),
|
|
1186
1209
|
userId: z10.string(),
|
|
@@ -1469,6 +1492,36 @@ var VoiceCreditsExhaustedAction = z10.object({
|
|
|
1469
1492
|
creditsUsed: z10.number(),
|
|
1470
1493
|
clientId: z10.string().optional()
|
|
1471
1494
|
});
|
|
1495
|
+
var CliCompletionChunkAction = z10.object({
|
|
1496
|
+
action: z10.literal("cli_completion_chunk"),
|
|
1497
|
+
requestId: z10.string(),
|
|
1498
|
+
chunk: z10.object({
|
|
1499
|
+
type: z10.enum(["content", "tool_use"]),
|
|
1500
|
+
text: z10.string(),
|
|
1501
|
+
tools: z10.array(z10.unknown()).optional(),
|
|
1502
|
+
usage: z10.object({
|
|
1503
|
+
inputTokens: z10.number().optional(),
|
|
1504
|
+
outputTokens: z10.number().optional()
|
|
1505
|
+
}).optional(),
|
|
1506
|
+
thinking: z10.array(z10.unknown()).optional()
|
|
1507
|
+
})
|
|
1508
|
+
});
|
|
1509
|
+
var CliCompletionDoneAction = z10.object({
|
|
1510
|
+
action: z10.literal("cli_completion_done"),
|
|
1511
|
+
requestId: z10.string()
|
|
1512
|
+
});
|
|
1513
|
+
var CliCompletionErrorAction = z10.object({
|
|
1514
|
+
action: z10.literal("cli_completion_error"),
|
|
1515
|
+
requestId: z10.string(),
|
|
1516
|
+
error: z10.string()
|
|
1517
|
+
});
|
|
1518
|
+
var CliToolResponseAction = z10.object({
|
|
1519
|
+
action: z10.literal("cli_tool_response"),
|
|
1520
|
+
requestId: z10.string(),
|
|
1521
|
+
success: z10.boolean(),
|
|
1522
|
+
content: z10.unknown().optional(),
|
|
1523
|
+
error: z10.string().optional()
|
|
1524
|
+
});
|
|
1472
1525
|
var SessionCreatedAction = shareableDocumentSchema.extend({
|
|
1473
1526
|
action: z10.literal("session.created"),
|
|
1474
1527
|
id: z10.string(),
|
|
@@ -1503,7 +1556,9 @@ var MessageDataToServer = z10.discriminatedUnion("action", [
|
|
|
1503
1556
|
DataUnsubscribeRequestAction,
|
|
1504
1557
|
HeartbeatAction,
|
|
1505
1558
|
VoiceSessionSendTranscriptAction,
|
|
1506
|
-
VoiceSessionEndedAction
|
|
1559
|
+
VoiceSessionEndedAction,
|
|
1560
|
+
CliCompletionRequestAction,
|
|
1561
|
+
CliToolRequestAction
|
|
1507
1562
|
]);
|
|
1508
1563
|
var MessageDataToClient = z10.discriminatedUnion("action", [
|
|
1509
1564
|
DataSubscriptionUpdateAction,
|
|
@@ -1529,7 +1584,11 @@ var MessageDataToClient = z10.discriminatedUnion("action", [
|
|
|
1529
1584
|
PiHistoryCompleteAction,
|
|
1530
1585
|
PiHistoryErrorAction,
|
|
1531
1586
|
SessionCreatedAction,
|
|
1532
|
-
VoiceCreditsExhaustedAction
|
|
1587
|
+
VoiceCreditsExhaustedAction,
|
|
1588
|
+
CliCompletionChunkAction,
|
|
1589
|
+
CliCompletionDoneAction,
|
|
1590
|
+
CliCompletionErrorAction,
|
|
1591
|
+
CliToolResponseAction
|
|
1533
1592
|
]);
|
|
1534
1593
|
|
|
1535
1594
|
// ../../b4m-core/packages/common/dist/src/schemas/cliCompletions.js
|
|
@@ -8724,6 +8783,8 @@ export {
|
|
|
8724
8783
|
DataUnsubscribeRequestAction,
|
|
8725
8784
|
HeartbeatAction,
|
|
8726
8785
|
VoiceSessionSendTranscriptAction,
|
|
8786
|
+
CliCompletionRequestAction,
|
|
8787
|
+
CliToolRequestAction,
|
|
8727
8788
|
VoiceSessionEndedAction,
|
|
8728
8789
|
DataSubscriptionUpdateAction,
|
|
8729
8790
|
LLMStatusUpdateAction,
|
|
@@ -8748,6 +8809,10 @@ export {
|
|
|
8748
8809
|
ImportHistoryJobProgressUpdateAction,
|
|
8749
8810
|
ResearchModeStreamAction,
|
|
8750
8811
|
VoiceCreditsExhaustedAction,
|
|
8812
|
+
CliCompletionChunkAction,
|
|
8813
|
+
CliCompletionDoneAction,
|
|
8814
|
+
CliCompletionErrorAction,
|
|
8815
|
+
CliToolResponseAction,
|
|
8751
8816
|
SessionCreatedAction,
|
|
8752
8817
|
MessageDataToServer,
|
|
8753
8818
|
MessageDataToClient,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
dayjsConfig_default,
|
|
17
17
|
extractSnippetMeta,
|
|
18
18
|
settingsMap
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-55ZDRTGQ.js";
|
|
20
20
|
import {
|
|
21
21
|
Logger
|
|
22
22
|
} from "./chunk-OCYRD7D6.js";
|
|
@@ -2493,7 +2493,13 @@ var AnthropicBackend = class {
|
|
|
2493
2493
|
const rawTools = options.tools;
|
|
2494
2494
|
const normalizedTools = Array.isArray(rawTools) ? rawTools : rawTools ? [rawTools] : void 0;
|
|
2495
2495
|
options.tools = normalizedTools;
|
|
2496
|
-
|
|
2496
|
+
let system = this.consolidateSystemMessages(messages);
|
|
2497
|
+
if (system) {
|
|
2498
|
+
system += `
|
|
2499
|
+
IMPORTANT! Only when someone asks, remember that you are specifically the ${model} model.`;
|
|
2500
|
+
} else {
|
|
2501
|
+
system = `IMPORTANT! Only when someone asks, remember that you are specifically the ${model} model.`;
|
|
2502
|
+
}
|
|
2497
2503
|
let filteredMessages = ensureToolPairingIntegrity(this.filterRelevantMessages(messages), this.logger);
|
|
2498
2504
|
const countToolBlocks = (msgs) => {
|
|
2499
2505
|
let useCount = 0;
|
|
@@ -3852,7 +3858,10 @@ var AnthropicBedrockBackend = class extends BaseBedrockBackend {
|
|
|
3852
3858
|
}
|
|
3853
3859
|
return { ...m, content: "" };
|
|
3854
3860
|
}).filter((m) => m.content !== "" && (Array.isArray(m.content) ? m.content.length > 0 : true));
|
|
3855
|
-
|
|
3861
|
+
let systemMessage = messages.filter((m) => m.role === "system" && m.content).map((m) => typeof m.content === "string" ? m.content : JSON.stringify(m.content)).join("\n");
|
|
3862
|
+
const modelIdentity = `IMPORTANT! Only when someone asks, remember that you are specifically the ${model} model.`;
|
|
3863
|
+
systemMessage = systemMessage ? `${systemMessage}
|
|
3864
|
+
${modelIdentity}` : modelIdentity;
|
|
3856
3865
|
console.log(`[AnthropicBedrockBackend] Preparing payload for model: ${model}`);
|
|
3857
3866
|
const hasVendorPrefix = model.includes(":") || model.startsWith("global.") || model.startsWith("us.");
|
|
3858
3867
|
const modelId = hasVendorPrefix ? model : `anthropic.${model}`;
|
|
@@ -49,7 +49,16 @@ var useCliStore = create((set) => ({
|
|
|
49
49
|
// Input state (for Ctrl+C clearing)
|
|
50
50
|
inputValue: "",
|
|
51
51
|
setInputValue: (value) => set({ inputValue: value }),
|
|
52
|
-
clearInput: () => set({ inputValue: "" }),
|
|
52
|
+
clearInput: () => set({ inputValue: "", pastedContent: null, pastedLineCount: 0 }),
|
|
53
|
+
// Paste state
|
|
54
|
+
pastedContent: null,
|
|
55
|
+
pastedLineCount: 0,
|
|
56
|
+
setPastedContent: (content, lineCount) => set({
|
|
57
|
+
pastedContent: content,
|
|
58
|
+
pastedLineCount: lineCount,
|
|
59
|
+
inputValue: content
|
|
60
|
+
}),
|
|
61
|
+
clearPaste: () => set({ pastedContent: null, pastedLineCount: 0, inputValue: "" }),
|
|
53
62
|
// Permission prompt queue
|
|
54
63
|
permissionPrompt: null,
|
|
55
64
|
permissionQueue: [],
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
getSettingsMap,
|
|
8
8
|
getSettingsValue,
|
|
9
9
|
secureParameters
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-7EEPLDUG.js";
|
|
11
11
|
import {
|
|
12
12
|
KnowledgeType,
|
|
13
13
|
SupportedFabFileMimeTypes
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-55ZDRTGQ.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/fabFileService/create.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
getSettingsByNames,
|
|
7
7
|
obfuscateApiKey,
|
|
8
8
|
secureParameters
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7EEPLDUG.js";
|
|
10
10
|
import {
|
|
11
11
|
ApiKeyType,
|
|
12
12
|
MementoTier,
|
|
13
13
|
isSupportedEmbeddingModel
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-55ZDRTGQ.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/apiKeyService/get.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BadRequestError,
|
|
4
4
|
secureParameters
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7EEPLDUG.js";
|
|
6
6
|
import {
|
|
7
7
|
CompletionApiUsageTransaction,
|
|
8
8
|
GenericCreditDeductTransaction,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
TextGenerationUsageTransaction,
|
|
13
13
|
TransferCreditTransaction,
|
|
14
14
|
VideoGenerationUsageTransaction
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-55ZDRTGQ.js";
|
|
16
16
|
|
|
17
17
|
// ../../b4m-core/packages/services/dist/src/creditService/subtractCredits.js
|
|
18
18
|
import { z } from "zod";
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createFabFile,
|
|
4
4
|
createFabFileSchema
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-K5IURWQT.js";
|
|
6
|
+
import "./chunk-7EEPLDUG.js";
|
|
7
|
+
import "./chunk-55ZDRTGQ.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
createFabFile,
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
getEffectiveApiKey,
|
|
6
6
|
getOpenWeatherKey,
|
|
7
7
|
getSerperKey
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KBRR7H2K.js";
|
|
9
9
|
import "./chunk-RUI6HNLO.js";
|
|
10
10
|
import {
|
|
11
11
|
ConfigStore,
|
|
@@ -14,9 +14,9 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
selectActiveBackgroundAgents,
|
|
16
16
|
useCliStore
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-BYXFQJYT.js";
|
|
18
|
+
import "./chunk-XXYKIX5X.js";
|
|
19
|
+
import "./chunk-K5IURWQT.js";
|
|
20
20
|
import {
|
|
21
21
|
BFLImageService,
|
|
22
22
|
BaseStorage,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
OpenAIBackend,
|
|
29
29
|
OpenAIImageService,
|
|
30
30
|
XAIImageService
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-7EEPLDUG.js";
|
|
32
32
|
import {
|
|
33
33
|
AiEvents,
|
|
34
34
|
ApiKeyEvents,
|
|
@@ -84,7 +84,7 @@ import {
|
|
|
84
84
|
XAI_IMAGE_MODELS,
|
|
85
85
|
b4mLLMTools,
|
|
86
86
|
getMcpProviderMetadata
|
|
87
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-55ZDRTGQ.js";
|
|
88
88
|
import {
|
|
89
89
|
Logger
|
|
90
90
|
} from "./chunk-OCYRD7D6.js";
|
|
@@ -94,7 +94,7 @@ import React21, { useState as useState10, useEffect as useEffect7, useCallback a
|
|
|
94
94
|
import { render, Box as Box20, Text as Text20, useApp, useInput as useInput9 } from "ink";
|
|
95
95
|
import { execSync } from "child_process";
|
|
96
96
|
import { randomBytes as randomBytes5 } from "crypto";
|
|
97
|
-
import { v4 as
|
|
97
|
+
import { v4 as uuidv413 } from "uuid";
|
|
98
98
|
|
|
99
99
|
// src/components/App.tsx
|
|
100
100
|
import React15, { useState as useState6, useEffect as useEffect5 } from "react";
|
|
@@ -120,10 +120,22 @@ import { Box as Box4, Text as Text5, useInput as useInput2 } from "ink";
|
|
|
120
120
|
// src/components/CustomTextInput.tsx
|
|
121
121
|
import React2, { useEffect, useRef, useState } from "react";
|
|
122
122
|
import { Text as Text2, useInput } from "ink";
|
|
123
|
+
|
|
124
|
+
// src/config/constants.ts
|
|
125
|
+
var USAGE_DAYS = 30;
|
|
126
|
+
var MODEL_NAME_COLUMN_WIDTH = 18;
|
|
127
|
+
var USAGE_CACHE_TTL = 5 * 60 * 1e3;
|
|
128
|
+
var PASTE_LINE_THRESHOLD = 5;
|
|
129
|
+
var MAX_PASTE_SIZE = 5e5;
|
|
130
|
+
var IMAGE_DETECTION_MAX_LENGTH = 500;
|
|
131
|
+
|
|
132
|
+
// src/components/CustomTextInput.tsx
|
|
123
133
|
function CustomTextInput({
|
|
124
134
|
value,
|
|
125
135
|
onChange,
|
|
126
136
|
onSubmit,
|
|
137
|
+
onPaste,
|
|
138
|
+
pasteIndicator,
|
|
127
139
|
placeholder = "",
|
|
128
140
|
showCursor = true,
|
|
129
141
|
disabled = false
|
|
@@ -275,6 +287,11 @@ function CustomTextInput({
|
|
|
275
287
|
}
|
|
276
288
|
}
|
|
277
289
|
if (key.backspace || key.delete) {
|
|
290
|
+
if (pasteIndicator) {
|
|
291
|
+
onChange("");
|
|
292
|
+
setCursorOffset(0);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
278
295
|
if (cursorOffset > 0) {
|
|
279
296
|
const newValue = value.slice(0, cursorOffset - 1) + value.slice(cursorOffset);
|
|
280
297
|
onChange(newValue);
|
|
@@ -291,6 +308,20 @@ function CustomTextInput({
|
|
|
291
308
|
return;
|
|
292
309
|
}
|
|
293
310
|
if (!key.ctrl && !key.meta && input.length > 0) {
|
|
311
|
+
if (input.length > 1 && onPaste) {
|
|
312
|
+
const normalized = input.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
313
|
+
const lineCount = normalized.split("\n").length;
|
|
314
|
+
if (lineCount >= PASTE_LINE_THRESHOLD) {
|
|
315
|
+
onPaste(normalized);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (pasteIndicator) {
|
|
320
|
+
const sanitizedInput2 = input === "\r" ? "\n" : input;
|
|
321
|
+
onChange(sanitizedInput2);
|
|
322
|
+
setCursorOffset(sanitizedInput2.length);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
294
325
|
const sanitizedInput = input === "\r" ? "\n" : input;
|
|
295
326
|
const newValue = value.slice(0, cursorOffset) + sanitizedInput + value.slice(cursorOffset);
|
|
296
327
|
onChange(newValue);
|
|
@@ -299,6 +330,9 @@ function CustomTextInput({
|
|
|
299
330
|
},
|
|
300
331
|
{ isActive: !disabled }
|
|
301
332
|
);
|
|
333
|
+
if (pasteIndicator) {
|
|
334
|
+
return /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: "yellow" }, pasteIndicator), showCursor && /* @__PURE__ */ React2.createElement(Text2, { inverse: true }, " "));
|
|
335
|
+
}
|
|
302
336
|
const hasValue = value.length > 0;
|
|
303
337
|
if (!hasValue) {
|
|
304
338
|
return /* @__PURE__ */ React2.createElement(Text2, null, showCursor ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text2, { inverse: true }, " "), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, placeholder)) : /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, placeholder));
|
|
@@ -316,23 +350,9 @@ function CommandAutocomplete({ commands, selectedIndex }) {
|
|
|
316
350
|
if (commands.length === 0) {
|
|
317
351
|
return /* @__PURE__ */ React3.createElement(Box2, { marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No matching commands"));
|
|
318
352
|
}
|
|
319
|
-
|
|
320
|
-
const totalCommands = commands.length;
|
|
321
|
-
let startIndex = 0;
|
|
322
|
-
let endIndex = Math.min(VIEWPORT_SIZE, totalCommands);
|
|
323
|
-
if (totalCommands > VIEWPORT_SIZE) {
|
|
324
|
-
const halfViewport = Math.floor(VIEWPORT_SIZE / 2);
|
|
325
|
-
startIndex = Math.max(0, selectedIndex - halfViewport);
|
|
326
|
-
endIndex = Math.min(totalCommands, startIndex + VIEWPORT_SIZE);
|
|
327
|
-
if (endIndex === totalCommands) {
|
|
328
|
-
startIndex = Math.max(0, totalCommands - VIEWPORT_SIZE);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
const visibleCommands = commands.slice(startIndex, endIndex);
|
|
332
|
-
return /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React3.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, totalCommands === 1 ? "1 command" : `${totalCommands} commands`, totalCommands > VIEWPORT_SIZE && ` (${selectedIndex + 1}/${totalCommands})`, " \u2022 Use \u2191\u2193 to navigate, Enter to select")), visibleCommands.map((cmd, viewportIndex) => {
|
|
333
|
-
const actualIndex = startIndex + viewportIndex;
|
|
353
|
+
return /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React3.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, commands.length === 1 ? "1 command" : `${commands.length} commands`, " \u2022 Use \u2191\u2193 to navigate, Enter to select")), commands.map((cmd, index) => {
|
|
334
354
|
const args = cmd.args ? ` ${cmd.args}` : "";
|
|
335
|
-
const isSelected =
|
|
355
|
+
const isSelected = index === selectedIndex;
|
|
336
356
|
const sourceIcon = cmd.source === "global" ? "\u{1F3E0} " : cmd.source === "project" ? "\u{1F4C1} " : cmd.source === "built-in" ? "\u{1F527} " : "";
|
|
337
357
|
return /* @__PURE__ */ React3.createElement(Box2, { key: cmd.name, marginLeft: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: isSelected ? "cyan" : void 0, bold: isSelected }, isSelected ? "\u25B8 " : " ", sourceIcon, "/", cmd.name, args, " - ", cmd.description));
|
|
338
358
|
}));
|
|
@@ -1055,8 +1075,11 @@ function InputPrompt({
|
|
|
1055
1075
|
onBashModeChange
|
|
1056
1076
|
}) {
|
|
1057
1077
|
const value = useCliStore((state) => state.inputValue);
|
|
1058
|
-
const
|
|
1059
|
-
const
|
|
1078
|
+
const setValue = useCliStore((state) => state.setInputValue);
|
|
1079
|
+
const pastedContent = useCliStore((state) => state.pastedContent);
|
|
1080
|
+
const pastedLineCount = useCliStore((state) => state.pastedLineCount);
|
|
1081
|
+
const setPastedContent = useCliStore((state) => state.setPastedContent);
|
|
1082
|
+
const clearPaste = useCliStore((state) => state.clearPaste);
|
|
1060
1083
|
const [selectedIndex, setSelectedIndex] = useState3(0);
|
|
1061
1084
|
const [historyIndex, setHistoryIndex] = useState3(-1);
|
|
1062
1085
|
const [tempInput, setTempInput] = useState3("");
|
|
@@ -1073,8 +1096,8 @@ function InputPrompt({
|
|
|
1073
1096
|
useEffect3(() => {
|
|
1074
1097
|
onBashModeChange?.(isBashMode);
|
|
1075
1098
|
}, [isBashMode, onBashModeChange]);
|
|
1076
|
-
const
|
|
1077
|
-
const
|
|
1099
|
+
const shouldShowCommandAutocomplete = value.startsWith("/") && !disabled && !fileAutocomplete?.active && !looksLikeFilePath(value) && !pastedContent;
|
|
1100
|
+
const commandQuery = shouldShowCommandAutocomplete ? value.slice(1) : "";
|
|
1078
1101
|
const filteredCommands = useMemo(() => {
|
|
1079
1102
|
if (!shouldShowCommandAutocomplete) return [];
|
|
1080
1103
|
return searchCommands(commandQuery, commands);
|
|
@@ -1180,7 +1203,14 @@ function InputPrompt({
|
|
|
1180
1203
|
}
|
|
1181
1204
|
};
|
|
1182
1205
|
const handleSubmit = (input) => {
|
|
1183
|
-
if (disabled
|
|
1206
|
+
if (disabled) return;
|
|
1207
|
+
if (pastedContent) {
|
|
1208
|
+
const fullContent = pastedContent;
|
|
1209
|
+
clearPaste();
|
|
1210
|
+
onSubmit(fullContent);
|
|
1211
|
+
return;
|
|
1212
|
+
}
|
|
1213
|
+
if (!input.trim()) return;
|
|
1184
1214
|
if (fileAutocomplete?.active && filteredFiles.length > 0) {
|
|
1185
1215
|
const selectedFile = filteredFiles[fileSelectedIndex];
|
|
1186
1216
|
if (selectedFile) {
|
|
@@ -1216,13 +1246,23 @@ function InputPrompt({
|
|
|
1216
1246
|
setHistoryIndex(-1);
|
|
1217
1247
|
setFileAutocomplete(null);
|
|
1218
1248
|
};
|
|
1249
|
+
const handlePaste = (content) => {
|
|
1250
|
+
const truncated = content.length > MAX_PASTE_SIZE ? content.slice(0, MAX_PASTE_SIZE) : content;
|
|
1251
|
+
const lineCount = truncated.split("\n").length;
|
|
1252
|
+
setPastedContent(truncated, lineCount);
|
|
1253
|
+
};
|
|
1219
1254
|
const handleChange = async (newValue) => {
|
|
1220
|
-
if (
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1255
|
+
if (pastedContent) {
|
|
1256
|
+
clearPaste();
|
|
1257
|
+
}
|
|
1258
|
+
if (newValue.length <= IMAGE_DETECTION_MAX_LENGTH) {
|
|
1259
|
+
if (ImageInputDetector.containsImageData(newValue)) {
|
|
1260
|
+
const imageEvent = ImageInputDetector.extractImageData(newValue);
|
|
1261
|
+
if (imageEvent && onImageDetected) {
|
|
1262
|
+
const placeholder = await onImageDetected(imageEvent.data);
|
|
1263
|
+
setValue(`${placeholder} `);
|
|
1264
|
+
return;
|
|
1265
|
+
}
|
|
1226
1266
|
}
|
|
1227
1267
|
}
|
|
1228
1268
|
setValue(newValue);
|
|
@@ -1253,6 +1293,8 @@ function InputPrompt({
|
|
|
1253
1293
|
value,
|
|
1254
1294
|
onChange: handleChange,
|
|
1255
1295
|
onSubmit: handleSubmit,
|
|
1296
|
+
onPaste: handlePaste,
|
|
1297
|
+
pasteIndicator: pastedContent ? `[pasted +${pastedLineCount} lines]` : null,
|
|
1256
1298
|
placeholder: getPlaceholder(),
|
|
1257
1299
|
showCursor: !disabled,
|
|
1258
1300
|
disabled
|
|
@@ -12495,6 +12537,10 @@ var ServerToolExecutor = class {
|
|
|
12495
12537
|
};
|
|
12496
12538
|
|
|
12497
12539
|
// src/llm/ToolRouter.ts
|
|
12540
|
+
var wsToolExecutor = null;
|
|
12541
|
+
function setWebSocketToolExecutor(executor) {
|
|
12542
|
+
wsToolExecutor = executor;
|
|
12543
|
+
}
|
|
12498
12544
|
var SERVER_TOOLS = ["weather_info", "web_search", "web_fetch"];
|
|
12499
12545
|
var LOCAL_TOOLS = [
|
|
12500
12546
|
"file_read",
|
|
@@ -12517,7 +12563,15 @@ function isLocalTool(toolName) {
|
|
|
12517
12563
|
}
|
|
12518
12564
|
async function executeTool(toolName, input, apiClient, localToolFn) {
|
|
12519
12565
|
if (isServerTool(toolName)) {
|
|
12520
|
-
|
|
12566
|
+
if (wsToolExecutor) {
|
|
12567
|
+
logger.debug(`[ToolRouter] Routing ${toolName} to server via WebSocket`);
|
|
12568
|
+
const result = await wsToolExecutor.execute(toolName, input);
|
|
12569
|
+
if (!result.success) {
|
|
12570
|
+
return `Error executing ${toolName}: ${result.error || "Tool execution failed"}`;
|
|
12571
|
+
}
|
|
12572
|
+
return typeof result.content === "string" ? result.content : JSON.stringify(result.content ?? "");
|
|
12573
|
+
}
|
|
12574
|
+
logger.debug(`[ToolRouter] Routing ${toolName} to server via HTTP`);
|
|
12521
12575
|
const executor = new ServerToolExecutor(apiClient);
|
|
12522
12576
|
return await executor.executeTool(toolName, input);
|
|
12523
12577
|
} else if (isLocalTool(toolName)) {
|
|
@@ -12778,7 +12832,7 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
|
|
|
12778
12832
|
agentContext.observationQueue.push({ toolName, result: result2 });
|
|
12779
12833
|
return result2;
|
|
12780
12834
|
}
|
|
12781
|
-
const { useCliStore: useCliStore2 } = await import("./store-
|
|
12835
|
+
const { useCliStore: useCliStore2 } = await import("./store-K5MB3SE7.js");
|
|
12782
12836
|
if (useCliStore2.getState().autoAcceptEdits) {
|
|
12783
12837
|
const result2 = await executeTool(toolName, args, apiClient, originalFn);
|
|
12784
12838
|
agentContext.observationQueue.push({ toolName, result: result2 });
|
|
@@ -14479,6 +14533,173 @@ var ServerLlmBackend = class {
|
|
|
14479
14533
|
}
|
|
14480
14534
|
};
|
|
14481
14535
|
|
|
14536
|
+
// src/llm/WebSocketLlmBackend.ts
|
|
14537
|
+
import { v4 as uuidv411 } from "uuid";
|
|
14538
|
+
function stripThinkingBlocks2(text) {
|
|
14539
|
+
return text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
14540
|
+
}
|
|
14541
|
+
var WebSocketLlmBackend = class {
|
|
14542
|
+
constructor(options) {
|
|
14543
|
+
this.wsManager = options.wsManager;
|
|
14544
|
+
this.apiClient = options.apiClient;
|
|
14545
|
+
this.currentModel = options.model;
|
|
14546
|
+
this.tokenGetter = options.tokenGetter;
|
|
14547
|
+
this.wsCompletionUrl = options.wsCompletionUrl;
|
|
14548
|
+
}
|
|
14549
|
+
/**
|
|
14550
|
+
* Send completion request via HTTP POST, receive streaming response via WebSocket.
|
|
14551
|
+
* Collects all streamed chunks, then calls callback once at completion
|
|
14552
|
+
* with the full accumulated content.
|
|
14553
|
+
*/
|
|
14554
|
+
async complete(model, messages, options, callback) {
|
|
14555
|
+
logger.debug(`[WebSocketLlmBackend] Starting complete() with model: ${model}`);
|
|
14556
|
+
if (options.abortSignal?.aborted) {
|
|
14557
|
+
logger.debug("[WebSocketLlmBackend] Request aborted before start");
|
|
14558
|
+
return;
|
|
14559
|
+
}
|
|
14560
|
+
if (!this.wsManager.isConnected) {
|
|
14561
|
+
throw new Error("WebSocket is not connected");
|
|
14562
|
+
}
|
|
14563
|
+
const requestId = uuidv411();
|
|
14564
|
+
return new Promise((resolve3, reject) => {
|
|
14565
|
+
const isVerbose = process.env.B4M_VERBOSE === "1";
|
|
14566
|
+
const isUltraVerbose = process.env.B4M_DEBUG_STREAM === "1";
|
|
14567
|
+
const streamLogger = new StreamLogger(logger, "WebSocketLlmBackend", isVerbose, isUltraVerbose);
|
|
14568
|
+
streamLogger.streamStart();
|
|
14569
|
+
let eventCount = 0;
|
|
14570
|
+
let accumulatedText = "";
|
|
14571
|
+
let lastUsageInfo = {};
|
|
14572
|
+
let toolsUsed = [];
|
|
14573
|
+
let thinkingBlocks = [];
|
|
14574
|
+
let settled = false;
|
|
14575
|
+
const settle = (action) => {
|
|
14576
|
+
if (settled) return;
|
|
14577
|
+
settled = true;
|
|
14578
|
+
this.wsManager.offRequest(requestId);
|
|
14579
|
+
this.wsManager.offDisconnect(onDisconnect);
|
|
14580
|
+
action();
|
|
14581
|
+
};
|
|
14582
|
+
const settleResolve = () => settle(() => resolve3());
|
|
14583
|
+
const settleReject = (err) => settle(() => reject(err));
|
|
14584
|
+
const onDisconnect = () => {
|
|
14585
|
+
logger.debug("[WebSocketLlmBackend] Connection dropped during completion");
|
|
14586
|
+
settleReject(new Error("WebSocket connection lost during completion"));
|
|
14587
|
+
};
|
|
14588
|
+
this.wsManager.onDisconnect(onDisconnect);
|
|
14589
|
+
if (options.abortSignal) {
|
|
14590
|
+
if (options.abortSignal.aborted) {
|
|
14591
|
+
settleResolve();
|
|
14592
|
+
return;
|
|
14593
|
+
}
|
|
14594
|
+
options.abortSignal.addEventListener(
|
|
14595
|
+
"abort",
|
|
14596
|
+
() => {
|
|
14597
|
+
logger.debug("[WebSocketLlmBackend] Abort signal received");
|
|
14598
|
+
settleResolve();
|
|
14599
|
+
},
|
|
14600
|
+
{ once: true }
|
|
14601
|
+
);
|
|
14602
|
+
}
|
|
14603
|
+
const updateUsage = (usage) => {
|
|
14604
|
+
if (usage) {
|
|
14605
|
+
lastUsageInfo = { inputTokens: usage.inputTokens, outputTokens: usage.outputTokens };
|
|
14606
|
+
}
|
|
14607
|
+
};
|
|
14608
|
+
this.wsManager.onRequest(requestId, (message) => {
|
|
14609
|
+
if (options.abortSignal?.aborted) return;
|
|
14610
|
+
const action = message.action;
|
|
14611
|
+
if (action === "cli_completion_chunk") {
|
|
14612
|
+
eventCount++;
|
|
14613
|
+
const chunk = message.chunk;
|
|
14614
|
+
streamLogger.onEvent(eventCount, JSON.stringify(chunk));
|
|
14615
|
+
const textChunk = chunk.text || "";
|
|
14616
|
+
if (textChunk) accumulatedText += textChunk;
|
|
14617
|
+
updateUsage(chunk.usage);
|
|
14618
|
+
if (chunk.type === "content") {
|
|
14619
|
+
streamLogger.onContent(eventCount, textChunk, accumulatedText);
|
|
14620
|
+
} else if (chunk.type === "tool_use") {
|
|
14621
|
+
streamLogger.onCriticalEvent(eventCount, "TOOL_USE", `tools: ${chunk.tools?.length}`);
|
|
14622
|
+
if (chunk.tools && chunk.tools.length > 0) toolsUsed = chunk.tools;
|
|
14623
|
+
if (chunk.thinking && chunk.thinking.length > 0) thinkingBlocks = chunk.thinking;
|
|
14624
|
+
}
|
|
14625
|
+
} else if (action === "cli_completion_done") {
|
|
14626
|
+
streamLogger.streamComplete(accumulatedText);
|
|
14627
|
+
const cleanedText = stripThinkingBlocks2(accumulatedText);
|
|
14628
|
+
if (!cleanedText && toolsUsed.length === 0) {
|
|
14629
|
+
settleResolve();
|
|
14630
|
+
return;
|
|
14631
|
+
}
|
|
14632
|
+
const info = {
|
|
14633
|
+
...lastUsageInfo,
|
|
14634
|
+
...toolsUsed.length > 0 && { toolsUsed },
|
|
14635
|
+
...thinkingBlocks.length > 0 && { thinking: thinkingBlocks }
|
|
14636
|
+
};
|
|
14637
|
+
callback([cleanedText], info).then(() => settleResolve()).catch((err) => settleReject(err));
|
|
14638
|
+
} else if (action === "cli_completion_error") {
|
|
14639
|
+
const errorMsg = message.error || "Server error";
|
|
14640
|
+
streamLogger.onCriticalEvent(eventCount, "ERROR", errorMsg);
|
|
14641
|
+
settleReject(new Error(errorMsg));
|
|
14642
|
+
}
|
|
14643
|
+
});
|
|
14644
|
+
const axiosInstance = this.apiClient.getAxiosInstance();
|
|
14645
|
+
axiosInstance.post(
|
|
14646
|
+
this.wsCompletionUrl,
|
|
14647
|
+
{
|
|
14648
|
+
requestId,
|
|
14649
|
+
model,
|
|
14650
|
+
messages,
|
|
14651
|
+
options: {
|
|
14652
|
+
temperature: options.temperature,
|
|
14653
|
+
maxTokens: options.maxTokens,
|
|
14654
|
+
stream: true,
|
|
14655
|
+
tools: options.tools || []
|
|
14656
|
+
}
|
|
14657
|
+
},
|
|
14658
|
+
{ signal: options.abortSignal }
|
|
14659
|
+
).catch((err) => {
|
|
14660
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
14661
|
+
settleReject(new Error(`HTTP request failed: ${msg}`));
|
|
14662
|
+
});
|
|
14663
|
+
});
|
|
14664
|
+
}
|
|
14665
|
+
/**
|
|
14666
|
+
* Get available models from server (REST call, not streaming).
|
|
14667
|
+
* Delegates to ApiClient -- same as ServerLlmBackend.
|
|
14668
|
+
*/
|
|
14669
|
+
async getModelInfo() {
|
|
14670
|
+
try {
|
|
14671
|
+
logger.debug("[WebSocketLlmBackend] Fetching models from /api/models");
|
|
14672
|
+
const response = await this.apiClient.get("/api/models");
|
|
14673
|
+
if (!response || typeof response !== "object" || !Array.isArray(response.models)) {
|
|
14674
|
+
logger.warn("[WebSocketLlmBackend] Invalid API response format, using fallback models");
|
|
14675
|
+
return this.getFallbackModels();
|
|
14676
|
+
}
|
|
14677
|
+
const filteredModels = response.models.filter(
|
|
14678
|
+
(model) => model.type === "text" && model.supportsTools === true
|
|
14679
|
+
);
|
|
14680
|
+
if (filteredModels.length === 0) {
|
|
14681
|
+
logger.warn("[WebSocketLlmBackend] No CLI-compatible models found, using fallback");
|
|
14682
|
+
return this.getFallbackModels();
|
|
14683
|
+
}
|
|
14684
|
+
logger.debug(`[WebSocketLlmBackend] Loaded ${filteredModels.length} models`);
|
|
14685
|
+
return filteredModels;
|
|
14686
|
+
} catch (error) {
|
|
14687
|
+
logger.warn(
|
|
14688
|
+
`[WebSocketLlmBackend] Failed to fetch models: ${error instanceof Error ? error.message : String(error)}`
|
|
14689
|
+
);
|
|
14690
|
+
return this.getFallbackModels();
|
|
14691
|
+
}
|
|
14692
|
+
}
|
|
14693
|
+
getFallbackModels() {
|
|
14694
|
+
return [
|
|
14695
|
+
{ id: "claude-sonnet-4-5-20250929", name: "Claude 4.5 Sonnet" },
|
|
14696
|
+
{ id: "claude-3-5-haiku-20241022", name: "Claude 3.5 Haiku" },
|
|
14697
|
+
{ id: "gpt-4o", name: "GPT-4o" },
|
|
14698
|
+
{ id: "gpt-4o-mini", name: "GPT-4o Mini" }
|
|
14699
|
+
];
|
|
14700
|
+
}
|
|
14701
|
+
};
|
|
14702
|
+
|
|
14482
14703
|
// src/llm/NotifyingLlmBackend.ts
|
|
14483
14704
|
var NotifyingLlmBackend = class {
|
|
14484
14705
|
constructor(inner, backgroundManager) {
|
|
@@ -14513,6 +14734,253 @@ Please acknowledge these background agent results and incorporate them into your
|
|
|
14513
14734
|
}
|
|
14514
14735
|
};
|
|
14515
14736
|
|
|
14737
|
+
// src/ws/WebSocketConnectionManager.ts
|
|
14738
|
+
var WebSocketConnectionManager = class {
|
|
14739
|
+
constructor(wsUrl, getToken) {
|
|
14740
|
+
this.ws = null;
|
|
14741
|
+
this.heartbeatInterval = null;
|
|
14742
|
+
this.reconnectAttempts = 0;
|
|
14743
|
+
this.maxReconnectDelay = 3e4;
|
|
14744
|
+
this.handlers = /* @__PURE__ */ new Map();
|
|
14745
|
+
this.disconnectHandlers = /* @__PURE__ */ new Set();
|
|
14746
|
+
this.reconnectTimer = null;
|
|
14747
|
+
this.connected = false;
|
|
14748
|
+
this.connecting = false;
|
|
14749
|
+
this.closed = false;
|
|
14750
|
+
this.wsUrl = wsUrl;
|
|
14751
|
+
this.getToken = getToken;
|
|
14752
|
+
}
|
|
14753
|
+
/**
|
|
14754
|
+
* Connect to the WebSocket server.
|
|
14755
|
+
* Resolves when connection is established, rejects on failure.
|
|
14756
|
+
*/
|
|
14757
|
+
async connect() {
|
|
14758
|
+
if (this.connected || this.connecting) return;
|
|
14759
|
+
this.connecting = true;
|
|
14760
|
+
const token = await this.getToken();
|
|
14761
|
+
if (!token) {
|
|
14762
|
+
this.connecting = false;
|
|
14763
|
+
throw new Error("No access token available for WebSocket connection");
|
|
14764
|
+
}
|
|
14765
|
+
return new Promise((resolve3, reject) => {
|
|
14766
|
+
logger.debug(`[WS] Connecting to ${this.wsUrl}...`);
|
|
14767
|
+
this.ws = new WebSocket(this.wsUrl, [`access_token.${token}`]);
|
|
14768
|
+
this.ws.onopen = () => {
|
|
14769
|
+
logger.debug("[WS] Connected");
|
|
14770
|
+
this.connected = true;
|
|
14771
|
+
this.connecting = false;
|
|
14772
|
+
this.reconnectAttempts = 0;
|
|
14773
|
+
this.startHeartbeat();
|
|
14774
|
+
resolve3();
|
|
14775
|
+
};
|
|
14776
|
+
this.ws.onmessage = (event) => {
|
|
14777
|
+
try {
|
|
14778
|
+
const data = typeof event.data === "string" ? event.data : event.data.toString();
|
|
14779
|
+
const message = JSON.parse(data);
|
|
14780
|
+
const requestId = message.requestId;
|
|
14781
|
+
if (requestId && this.handlers.has(requestId)) {
|
|
14782
|
+
this.handlers.get(requestId)(message);
|
|
14783
|
+
} else {
|
|
14784
|
+
logger.debug(`[WS] Unhandled message: ${message.action || "unknown"}`);
|
|
14785
|
+
}
|
|
14786
|
+
} catch (err) {
|
|
14787
|
+
logger.debug(`[WS] Failed to parse message: ${err}`);
|
|
14788
|
+
}
|
|
14789
|
+
};
|
|
14790
|
+
this.ws.onclose = () => {
|
|
14791
|
+
logger.debug("[WS] Connection closed");
|
|
14792
|
+
this.cleanup();
|
|
14793
|
+
this.notifyDisconnect();
|
|
14794
|
+
if (!this.closed) {
|
|
14795
|
+
this.scheduleReconnect();
|
|
14796
|
+
}
|
|
14797
|
+
};
|
|
14798
|
+
this.ws.onerror = (err) => {
|
|
14799
|
+
logger.debug(`[WS] Error: ${err}`);
|
|
14800
|
+
if (this.connecting) {
|
|
14801
|
+
this.connecting = false;
|
|
14802
|
+
this.connected = false;
|
|
14803
|
+
reject(new Error("WebSocket connection failed"));
|
|
14804
|
+
}
|
|
14805
|
+
};
|
|
14806
|
+
});
|
|
14807
|
+
}
|
|
14808
|
+
/** Whether the connection is currently established */
|
|
14809
|
+
get isConnected() {
|
|
14810
|
+
return this.connected;
|
|
14811
|
+
}
|
|
14812
|
+
/**
|
|
14813
|
+
* Send a JSON message over the WebSocket connection.
|
|
14814
|
+
*/
|
|
14815
|
+
send(data) {
|
|
14816
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
14817
|
+
throw new Error("WebSocket is not connected");
|
|
14818
|
+
}
|
|
14819
|
+
const payload = JSON.stringify(data);
|
|
14820
|
+
const sizeKB = (payload.length / 1024).toFixed(1);
|
|
14821
|
+
logger.debug(`[WS] Sending ${sizeKB} KB (action: ${data.action})`);
|
|
14822
|
+
if (payload.length > 32e3) {
|
|
14823
|
+
logger.warn(`[WS] Payload ${sizeKB} KB exceeds API Gateway 32 KB frame limit \u2014 connection will be closed`);
|
|
14824
|
+
}
|
|
14825
|
+
this.ws.send(payload);
|
|
14826
|
+
}
|
|
14827
|
+
/**
|
|
14828
|
+
* Register a handler for messages matching a specific requestId.
|
|
14829
|
+
*/
|
|
14830
|
+
onRequest(requestId, handler) {
|
|
14831
|
+
this.handlers.set(requestId, handler);
|
|
14832
|
+
}
|
|
14833
|
+
/**
|
|
14834
|
+
* Remove a handler for a specific requestId.
|
|
14835
|
+
*/
|
|
14836
|
+
offRequest(requestId) {
|
|
14837
|
+
this.handlers.delete(requestId);
|
|
14838
|
+
}
|
|
14839
|
+
/**
|
|
14840
|
+
* Register a handler that fires when the connection drops.
|
|
14841
|
+
*/
|
|
14842
|
+
onDisconnect(handler) {
|
|
14843
|
+
this.disconnectHandlers.add(handler);
|
|
14844
|
+
}
|
|
14845
|
+
/**
|
|
14846
|
+
* Remove a disconnect handler.
|
|
14847
|
+
*/
|
|
14848
|
+
offDisconnect(handler) {
|
|
14849
|
+
this.disconnectHandlers.delete(handler);
|
|
14850
|
+
}
|
|
14851
|
+
/**
|
|
14852
|
+
* Close the connection and stop all heartbeat/reconnect logic.
|
|
14853
|
+
*/
|
|
14854
|
+
disconnect() {
|
|
14855
|
+
this.closed = true;
|
|
14856
|
+
this.cleanup();
|
|
14857
|
+
if (this.ws) {
|
|
14858
|
+
this.ws.close();
|
|
14859
|
+
this.ws = null;
|
|
14860
|
+
}
|
|
14861
|
+
this.handlers.clear();
|
|
14862
|
+
this.disconnectHandlers.clear();
|
|
14863
|
+
}
|
|
14864
|
+
startHeartbeat() {
|
|
14865
|
+
this.stopHeartbeat();
|
|
14866
|
+
this.heartbeatInterval = setInterval(
|
|
14867
|
+
() => {
|
|
14868
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
14869
|
+
this.ws.send(JSON.stringify({ action: "heartbeat" }));
|
|
14870
|
+
logger.debug("[WS] Heartbeat sent");
|
|
14871
|
+
}
|
|
14872
|
+
},
|
|
14873
|
+
5 * 60 * 1e3
|
|
14874
|
+
);
|
|
14875
|
+
}
|
|
14876
|
+
stopHeartbeat() {
|
|
14877
|
+
if (this.heartbeatInterval) {
|
|
14878
|
+
clearInterval(this.heartbeatInterval);
|
|
14879
|
+
this.heartbeatInterval = null;
|
|
14880
|
+
}
|
|
14881
|
+
}
|
|
14882
|
+
cleanup() {
|
|
14883
|
+
this.connected = false;
|
|
14884
|
+
this.connecting = false;
|
|
14885
|
+
this.stopHeartbeat();
|
|
14886
|
+
if (this.reconnectTimer) {
|
|
14887
|
+
clearTimeout(this.reconnectTimer);
|
|
14888
|
+
this.reconnectTimer = null;
|
|
14889
|
+
}
|
|
14890
|
+
}
|
|
14891
|
+
notifyDisconnect() {
|
|
14892
|
+
for (const handler of this.disconnectHandlers) {
|
|
14893
|
+
try {
|
|
14894
|
+
handler();
|
|
14895
|
+
} catch {
|
|
14896
|
+
}
|
|
14897
|
+
}
|
|
14898
|
+
}
|
|
14899
|
+
scheduleReconnect() {
|
|
14900
|
+
if (this.closed) return;
|
|
14901
|
+
this.reconnectAttempts++;
|
|
14902
|
+
const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts - 1), this.maxReconnectDelay);
|
|
14903
|
+
logger.debug(`[WS] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
|
|
14904
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
14905
|
+
this.reconnectTimer = null;
|
|
14906
|
+
if (this.closed) return;
|
|
14907
|
+
try {
|
|
14908
|
+
await this.connect();
|
|
14909
|
+
} catch {
|
|
14910
|
+
logger.debug("[WS] Reconnection failed");
|
|
14911
|
+
}
|
|
14912
|
+
}, delay);
|
|
14913
|
+
}
|
|
14914
|
+
};
|
|
14915
|
+
|
|
14916
|
+
// src/ws/WebSocketToolExecutor.ts
|
|
14917
|
+
import { v4 as uuidv412 } from "uuid";
|
|
14918
|
+
var WebSocketToolExecutor = class {
|
|
14919
|
+
constructor(wsManager, tokenGetter) {
|
|
14920
|
+
this.wsManager = wsManager;
|
|
14921
|
+
this.tokenGetter = tokenGetter;
|
|
14922
|
+
}
|
|
14923
|
+
/**
|
|
14924
|
+
* Execute a server-side tool via WebSocket.
|
|
14925
|
+
* Returns the tool result or throws on error.
|
|
14926
|
+
*/
|
|
14927
|
+
async execute(toolName, input, abortSignal) {
|
|
14928
|
+
if (!this.wsManager.isConnected) {
|
|
14929
|
+
throw new Error("WebSocket is not connected");
|
|
14930
|
+
}
|
|
14931
|
+
const token = await this.tokenGetter();
|
|
14932
|
+
if (!token) {
|
|
14933
|
+
throw new Error("No access token available");
|
|
14934
|
+
}
|
|
14935
|
+
const requestId = uuidv412();
|
|
14936
|
+
return new Promise((resolve3, reject) => {
|
|
14937
|
+
let settled = false;
|
|
14938
|
+
const settle = (action) => {
|
|
14939
|
+
if (settled) return;
|
|
14940
|
+
settled = true;
|
|
14941
|
+
this.wsManager.offRequest(requestId);
|
|
14942
|
+
this.wsManager.offDisconnect(onDisconnect);
|
|
14943
|
+
action();
|
|
14944
|
+
};
|
|
14945
|
+
const settleResolve = (result) => settle(() => resolve3(result));
|
|
14946
|
+
const settleReject = (err) => settle(() => reject(err));
|
|
14947
|
+
const onDisconnect = () => {
|
|
14948
|
+
settleReject(new Error("WebSocket connection lost during tool execution"));
|
|
14949
|
+
};
|
|
14950
|
+
this.wsManager.onDisconnect(onDisconnect);
|
|
14951
|
+
if (abortSignal) {
|
|
14952
|
+
if (abortSignal.aborted) {
|
|
14953
|
+
settleReject(new Error("Tool execution aborted"));
|
|
14954
|
+
return;
|
|
14955
|
+
}
|
|
14956
|
+
abortSignal.addEventListener("abort", () => settleReject(new Error("Tool execution aborted")), {
|
|
14957
|
+
once: true
|
|
14958
|
+
});
|
|
14959
|
+
}
|
|
14960
|
+
this.wsManager.onRequest(requestId, (message) => {
|
|
14961
|
+
if (message.action === "cli_tool_response") {
|
|
14962
|
+
settleResolve({
|
|
14963
|
+
success: message.success,
|
|
14964
|
+
content: message.content,
|
|
14965
|
+
error: message.error
|
|
14966
|
+
});
|
|
14967
|
+
}
|
|
14968
|
+
});
|
|
14969
|
+
try {
|
|
14970
|
+
this.wsManager.send({
|
|
14971
|
+
action: "cli_tool_request",
|
|
14972
|
+
accessToken: token,
|
|
14973
|
+
requestId,
|
|
14974
|
+
toolName,
|
|
14975
|
+
input
|
|
14976
|
+
});
|
|
14977
|
+
} catch (err) {
|
|
14978
|
+
settleReject(err instanceof Error ? err : new Error(String(err)));
|
|
14979
|
+
}
|
|
14980
|
+
});
|
|
14981
|
+
}
|
|
14982
|
+
};
|
|
14983
|
+
|
|
14516
14984
|
// src/auth/ApiClient.ts
|
|
14517
14985
|
import axios11 from "axios";
|
|
14518
14986
|
var ApiClient = class {
|
|
@@ -14650,7 +15118,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
|
|
|
14650
15118
|
// package.json
|
|
14651
15119
|
var package_default = {
|
|
14652
15120
|
name: "@bike4mind/cli",
|
|
14653
|
-
version: "0.2.30-feat-cli-
|
|
15121
|
+
version: "0.2.30-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
14654
15122
|
type: "module",
|
|
14655
15123
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
14656
15124
|
license: "UNLICENSED",
|
|
@@ -14761,10 +15229,10 @@ var package_default = {
|
|
|
14761
15229
|
},
|
|
14762
15230
|
devDependencies: {
|
|
14763
15231
|
"@bike4mind/agents": "0.1.0",
|
|
14764
|
-
"@bike4mind/common": "2.51.1-feat-cli-
|
|
14765
|
-
"@bike4mind/mcp": "1.30.1-feat-cli-
|
|
14766
|
-
"@bike4mind/services": "2.49.1-feat-cli-
|
|
14767
|
-
"@bike4mind/utils": "2.6.1-feat-cli-
|
|
15232
|
+
"@bike4mind/common": "2.51.1-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
15233
|
+
"@bike4mind/mcp": "1.30.1-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
15234
|
+
"@bike4mind/services": "2.49.1-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
15235
|
+
"@bike4mind/utils": "2.6.1-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
14768
15236
|
"@types/better-sqlite3": "^7.6.13",
|
|
14769
15237
|
"@types/diff": "^5.0.9",
|
|
14770
15238
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -14785,14 +15253,9 @@ var package_default = {
|
|
|
14785
15253
|
optionalDependencies: {
|
|
14786
15254
|
"@vscode/ripgrep": "^1.17.0"
|
|
14787
15255
|
},
|
|
14788
|
-
gitHead: "
|
|
15256
|
+
gitHead: "6a95a9d108b3eb161ebb1fe503ed9fb63585be72"
|
|
14789
15257
|
};
|
|
14790
15258
|
|
|
14791
|
-
// src/config/constants.ts
|
|
14792
|
-
var USAGE_DAYS = 30;
|
|
14793
|
-
var MODEL_NAME_COLUMN_WIDTH = 18;
|
|
14794
|
-
var USAGE_CACHE_TTL = 5 * 60 * 1e3;
|
|
14795
|
-
|
|
14796
15259
|
// src/agents/toolFilter.ts
|
|
14797
15260
|
function matchesToolPattern2(toolName, pattern) {
|
|
14798
15261
|
const regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
@@ -16564,7 +17027,8 @@ function CliApp() {
|
|
|
16564
17027
|
agentStore: null,
|
|
16565
17028
|
abortController: null,
|
|
16566
17029
|
contextContent: "",
|
|
16567
|
-
backgroundManager: null
|
|
17030
|
+
backgroundManager: null,
|
|
17031
|
+
wsManager: null
|
|
16568
17032
|
});
|
|
16569
17033
|
const [isInitialized, setIsInitialized] = useState10(false);
|
|
16570
17034
|
const [initError, setInitError] = useState10(null);
|
|
@@ -16592,6 +17056,10 @@ function CliApp() {
|
|
|
16592
17056
|
})
|
|
16593
17057
|
);
|
|
16594
17058
|
}
|
|
17059
|
+
if (state.wsManager) {
|
|
17060
|
+
state.wsManager.disconnect();
|
|
17061
|
+
setWebSocketToolExecutor(null);
|
|
17062
|
+
}
|
|
16595
17063
|
if (state.agent) {
|
|
16596
17064
|
state.agent.removeAllListeners();
|
|
16597
17065
|
}
|
|
@@ -16610,9 +17078,14 @@ function CliApp() {
|
|
|
16610
17078
|
setTimeout(() => {
|
|
16611
17079
|
process.exit(0);
|
|
16612
17080
|
}, 100);
|
|
16613
|
-
}, [state.session, state.sessionStore, state.mcpManager, state.agent, state.imageStore]);
|
|
17081
|
+
}, [state.session, state.sessionStore, state.mcpManager, state.agent, state.imageStore, state.wsManager]);
|
|
16614
17082
|
useInput9((input, key) => {
|
|
16615
17083
|
if (key.escape) {
|
|
17084
|
+
const store = useCliStore.getState();
|
|
17085
|
+
if (store.pastedContent) {
|
|
17086
|
+
store.clearPaste();
|
|
17087
|
+
return;
|
|
17088
|
+
}
|
|
16616
17089
|
if (state.abortController) {
|
|
16617
17090
|
logger.debug("[ABORT] ESC pressed - aborting current operation...");
|
|
16618
17091
|
state.abortController.abort();
|
|
@@ -16630,9 +17103,9 @@ function CliApp() {
|
|
|
16630
17103
|
});
|
|
16631
17104
|
} else {
|
|
16632
17105
|
logger.debug("[EXIT] First Ctrl+C - press again to exit");
|
|
16633
|
-
const
|
|
16634
|
-
if (
|
|
16635
|
-
|
|
17106
|
+
const store = useCliStore.getState();
|
|
17107
|
+
if (store.inputValue.length > 0 || store.pastedContent) {
|
|
17108
|
+
store.clearInput();
|
|
16636
17109
|
}
|
|
16637
17110
|
exitTimestamp = now;
|
|
16638
17111
|
setExitRequested(true);
|
|
@@ -16680,7 +17153,7 @@ function CliApp() {
|
|
|
16680
17153
|
if (!isAuthenticated) {
|
|
16681
17154
|
console.log("\u2139\uFE0F AI features disabled. Available commands: /login, /help, /config\n");
|
|
16682
17155
|
const minimalSession = {
|
|
16683
|
-
id:
|
|
17156
|
+
id: uuidv413(),
|
|
16684
17157
|
name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
|
|
16685
17158
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16686
17159
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -16708,10 +17181,45 @@ function CliApp() {
|
|
|
16708
17181
|
console.log(`\u{1F30D} API Environment: ${envName} (${apiBaseURL})`);
|
|
16709
17182
|
}
|
|
16710
17183
|
const apiClient = new ApiClient(apiBaseURL, state.configStore);
|
|
16711
|
-
const
|
|
16712
|
-
|
|
16713
|
-
|
|
16714
|
-
}
|
|
17184
|
+
const tokenGetter = async () => {
|
|
17185
|
+
const tokens = await state.configStore.getAuthTokens();
|
|
17186
|
+
return tokens?.accessToken ?? null;
|
|
17187
|
+
};
|
|
17188
|
+
let wsManager = null;
|
|
17189
|
+
let llm;
|
|
17190
|
+
try {
|
|
17191
|
+
const serverConfig = await apiClient.get(
|
|
17192
|
+
"/api/settings/serverConfig"
|
|
17193
|
+
);
|
|
17194
|
+
const wsUrl = serverConfig?.websocketUrl;
|
|
17195
|
+
const wsCompletionUrl = serverConfig?.wsCompletionUrl;
|
|
17196
|
+
if (wsUrl && wsCompletionUrl) {
|
|
17197
|
+
wsManager = new WebSocketConnectionManager(wsUrl, tokenGetter);
|
|
17198
|
+
await wsManager.connect();
|
|
17199
|
+
const wsToolExecutor2 = new WebSocketToolExecutor(wsManager, tokenGetter);
|
|
17200
|
+
setWebSocketToolExecutor(wsToolExecutor2);
|
|
17201
|
+
llm = new WebSocketLlmBackend({
|
|
17202
|
+
wsManager,
|
|
17203
|
+
apiClient,
|
|
17204
|
+
model: config.defaultModel,
|
|
17205
|
+
tokenGetter,
|
|
17206
|
+
wsCompletionUrl
|
|
17207
|
+
});
|
|
17208
|
+
logger.debug("\u{1F50C} Using WebSocket transport (bypasses CloudFront timeout)");
|
|
17209
|
+
} else {
|
|
17210
|
+
throw new Error("No websocketUrl or wsCompletionUrl in server config");
|
|
17211
|
+
}
|
|
17212
|
+
} catch (wsError) {
|
|
17213
|
+
logger.debug(
|
|
17214
|
+
`[WS] WebSocket unavailable, using SSE fallback: ${wsError instanceof Error ? wsError.message : String(wsError)}`
|
|
17215
|
+
);
|
|
17216
|
+
wsManager = null;
|
|
17217
|
+
setWebSocketToolExecutor(null);
|
|
17218
|
+
llm = new ServerLlmBackend({
|
|
17219
|
+
apiClient,
|
|
17220
|
+
model: config.defaultModel
|
|
17221
|
+
});
|
|
17222
|
+
}
|
|
16715
17223
|
const models = await llm.getModelInfo();
|
|
16716
17224
|
if (models.length === 0) {
|
|
16717
17225
|
throw new Error("No models available from server.");
|
|
@@ -16724,7 +17232,7 @@ function CliApp() {
|
|
|
16724
17232
|
}
|
|
16725
17233
|
llm.currentModel = modelInfo.id;
|
|
16726
17234
|
const newSession = {
|
|
16727
|
-
id:
|
|
17235
|
+
id: uuidv413(),
|
|
16728
17236
|
name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
|
|
16729
17237
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16730
17238
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -16938,8 +17446,10 @@ function CliApp() {
|
|
|
16938
17446
|
// Store agent store for agent management commands
|
|
16939
17447
|
contextContent: contextResult.mergedContent,
|
|
16940
17448
|
// Store raw context for compact instructions
|
|
16941
|
-
backgroundManager
|
|
17449
|
+
backgroundManager,
|
|
16942
17450
|
// Store for grouped notification turn tracking
|
|
17451
|
+
wsManager
|
|
17452
|
+
// WebSocket connection manager (null if using SSE fallback)
|
|
16943
17453
|
}));
|
|
16944
17454
|
setStoreSession(newSession);
|
|
16945
17455
|
const bannerLines = [
|
|
@@ -17034,13 +17544,13 @@ function CliApp() {
|
|
|
17034
17544
|
messageContent = multimodalMessage.content;
|
|
17035
17545
|
}
|
|
17036
17546
|
const userMessage = {
|
|
17037
|
-
id:
|
|
17547
|
+
id: uuidv413(),
|
|
17038
17548
|
role: "user",
|
|
17039
17549
|
content: userMessageContent,
|
|
17040
17550
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17041
17551
|
};
|
|
17042
17552
|
const pendingAssistantMessage = {
|
|
17043
|
-
id:
|
|
17553
|
+
id: uuidv413(),
|
|
17044
17554
|
role: "assistant",
|
|
17045
17555
|
content: "...",
|
|
17046
17556
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -17253,13 +17763,13 @@ function CliApp() {
|
|
|
17253
17763
|
userMessageContent = message;
|
|
17254
17764
|
}
|
|
17255
17765
|
const userMessage = {
|
|
17256
|
-
id:
|
|
17766
|
+
id: uuidv413(),
|
|
17257
17767
|
role: "user",
|
|
17258
17768
|
content: userMessageContent,
|
|
17259
17769
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17260
17770
|
};
|
|
17261
17771
|
const pendingAssistantMessage = {
|
|
17262
|
-
id:
|
|
17772
|
+
id: uuidv413(),
|
|
17263
17773
|
role: "assistant",
|
|
17264
17774
|
content: "...",
|
|
17265
17775
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -17339,7 +17849,7 @@ function CliApp() {
|
|
|
17339
17849
|
const currentSession = useCliStore.getState().session;
|
|
17340
17850
|
if (currentSession) {
|
|
17341
17851
|
const cancelMessage = {
|
|
17342
|
-
id:
|
|
17852
|
+
id: uuidv413(),
|
|
17343
17853
|
role: "assistant",
|
|
17344
17854
|
content: "\u26A0\uFE0F Operation cancelled by user",
|
|
17345
17855
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -17384,7 +17894,7 @@ function CliApp() {
|
|
|
17384
17894
|
setState((prev) => ({ ...prev, abortController }));
|
|
17385
17895
|
try {
|
|
17386
17896
|
const pendingAssistantMessage = {
|
|
17387
|
-
id:
|
|
17897
|
+
id: uuidv413(),
|
|
17388
17898
|
role: "assistant",
|
|
17389
17899
|
content: "...",
|
|
17390
17900
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -17412,7 +17922,7 @@ function CliApp() {
|
|
|
17412
17922
|
const currentSession = useCliStore.getState().session;
|
|
17413
17923
|
if (!currentSession) return;
|
|
17414
17924
|
const continuationMessage = {
|
|
17415
|
-
id:
|
|
17925
|
+
id: uuidv413(),
|
|
17416
17926
|
role: "assistant",
|
|
17417
17927
|
content: "---\n\n**Background Agent Results:**\n\n" + result.finalAnswer,
|
|
17418
17928
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -17473,13 +17983,13 @@ function CliApp() {
|
|
|
17473
17983
|
isError = true;
|
|
17474
17984
|
}
|
|
17475
17985
|
const userMessage = {
|
|
17476
|
-
id:
|
|
17986
|
+
id: uuidv413(),
|
|
17477
17987
|
role: "user",
|
|
17478
17988
|
content: `$ ${command}`,
|
|
17479
17989
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17480
17990
|
};
|
|
17481
17991
|
const assistantMessage = {
|
|
17482
|
-
id:
|
|
17992
|
+
id: uuidv413(),
|
|
17483
17993
|
role: "assistant",
|
|
17484
17994
|
content: isError ? `\u274C Error:
|
|
17485
17995
|
${output}` : output.trim() || "(no output)",
|
|
@@ -17948,7 +18458,7 @@ Keyboard Shortcuts:
|
|
|
17948
18458
|
console.clear();
|
|
17949
18459
|
const model = state.session?.model || state.config?.defaultModel || "claude-sonnet";
|
|
17950
18460
|
const newSession = {
|
|
17951
|
-
id:
|
|
18461
|
+
id: uuidv413(),
|
|
17952
18462
|
name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
|
|
17953
18463
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17954
18464
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -18453,9 +18963,9 @@ No usage data available for the last ${USAGE_DAYS} days.`);
|
|
|
18453
18963
|
return { ...prev, config: updatedConfig };
|
|
18454
18964
|
});
|
|
18455
18965
|
if (modelChanged && state.agent) {
|
|
18456
|
-
const
|
|
18457
|
-
if (
|
|
18458
|
-
|
|
18966
|
+
const backend = state.agent.context.llm;
|
|
18967
|
+
if (backend) {
|
|
18968
|
+
backend.currentModel = updatedConfig.defaultModel;
|
|
18459
18969
|
}
|
|
18460
18970
|
}
|
|
18461
18971
|
};
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
findMostSimilarMemento,
|
|
4
4
|
getRelevantMementos
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-KBRR7H2K.js";
|
|
6
|
+
import "./chunk-7EEPLDUG.js";
|
|
7
|
+
import "./chunk-55ZDRTGQ.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
findMostSimilarMemento,
|
|
@@ -134,12 +134,12 @@ import {
|
|
|
134
134
|
validateMermaidSyntax,
|
|
135
135
|
warmUpSettingsCache,
|
|
136
136
|
withRetry
|
|
137
|
-
} from "./chunk-
|
|
137
|
+
} from "./chunk-7EEPLDUG.js";
|
|
138
138
|
import {
|
|
139
139
|
buildRateLimitLogEntry,
|
|
140
140
|
isNearLimit,
|
|
141
141
|
parseRateLimitHeaders
|
|
142
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-55ZDRTGQ.js";
|
|
143
143
|
import {
|
|
144
144
|
Logger,
|
|
145
145
|
NotificationDeduplicator,
|
|
@@ -41,6 +41,12 @@ import {
|
|
|
41
41
|
ChatModels,
|
|
42
42
|
CitableSourceSchema,
|
|
43
43
|
ClaudeArtifactMimeTypes,
|
|
44
|
+
CliCompletionChunkAction,
|
|
45
|
+
CliCompletionDoneAction,
|
|
46
|
+
CliCompletionErrorAction,
|
|
47
|
+
CliCompletionRequestAction,
|
|
48
|
+
CliToolRequestAction,
|
|
49
|
+
CliToolResponseAction,
|
|
44
50
|
CollectionType,
|
|
45
51
|
CompletionApiUsageTransaction,
|
|
46
52
|
CompletionRequestSchema,
|
|
@@ -419,7 +425,7 @@ import {
|
|
|
419
425
|
validateReactArtifactV2,
|
|
420
426
|
validateSvgArtifactV2,
|
|
421
427
|
wikiMarkupToAdf
|
|
422
|
-
} from "./chunk-
|
|
428
|
+
} from "./chunk-55ZDRTGQ.js";
|
|
423
429
|
export {
|
|
424
430
|
ALL_IMAGE_MODELS,
|
|
425
431
|
ALL_IMAGE_SIZES,
|
|
@@ -463,6 +469,12 @@ export {
|
|
|
463
469
|
ChatModels,
|
|
464
470
|
CitableSourceSchema,
|
|
465
471
|
ClaudeArtifactMimeTypes,
|
|
472
|
+
CliCompletionChunkAction,
|
|
473
|
+
CliCompletionDoneAction,
|
|
474
|
+
CliCompletionErrorAction,
|
|
475
|
+
CliCompletionRequestAction,
|
|
476
|
+
CliToolRequestAction,
|
|
477
|
+
CliToolResponseAction,
|
|
466
478
|
CollectionType,
|
|
467
479
|
CompletionApiUsageTransaction,
|
|
468
480
|
CompletionRequestSchema,
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
SubtractCreditsSchema,
|
|
4
4
|
subtractCredits
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-XXYKIX5X.js";
|
|
6
|
+
import "./chunk-7EEPLDUG.js";
|
|
7
|
+
import "./chunk-55ZDRTGQ.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
SubtractCreditsSchema,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.2.30-feat-cli-
|
|
3
|
+
"version": "0.2.30-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -111,10 +111,10 @@
|
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
113
|
"@bike4mind/agents": "0.1.0",
|
|
114
|
-
"@bike4mind/common": "2.51.1-feat-cli-
|
|
115
|
-
"@bike4mind/mcp": "1.30.1-feat-cli-
|
|
116
|
-
"@bike4mind/services": "2.49.1-feat-cli-
|
|
117
|
-
"@bike4mind/utils": "2.6.1-feat-cli-
|
|
114
|
+
"@bike4mind/common": "2.51.1-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
115
|
+
"@bike4mind/mcp": "1.30.1-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
116
|
+
"@bike4mind/services": "2.49.1-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
117
|
+
"@bike4mind/utils": "2.6.1-feat-cli-websocket-streaming.19243+6a95a9d10",
|
|
118
118
|
"@types/better-sqlite3": "^7.6.13",
|
|
119
119
|
"@types/diff": "^5.0.9",
|
|
120
120
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -135,5 +135,5 @@
|
|
|
135
135
|
"optionalDependencies": {
|
|
136
136
|
"@vscode/ripgrep": "^1.17.0"
|
|
137
137
|
},
|
|
138
|
-
"gitHead": "
|
|
138
|
+
"gitHead": "6a95a9d108b3eb161ebb1fe503ed9fb63585be72"
|
|
139
139
|
}
|