@bike4mind/cli 0.2.29-feat-session-permission.18841 → 0.2.29-feat-cli-websocket-streaming.18842
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-EE753J4D.js → artifactExtractor-SNWW3EVH.js} +1 -1
- package/dist/{chunk-PKKJ44C5.js → chunk-BXCARBUQ.js} +2 -2
- package/dist/{chunk-ELTTBWAQ.js → chunk-EC2VEDD2.js} +2 -2
- package/dist/{chunk-5GSDPBTM.js → chunk-KPOK6V6E.js} +67 -2
- package/dist/{chunk-BCOGDPUB.js → chunk-QQL3OBKL.js} +2 -2
- package/dist/{chunk-S7BPPS33.js → chunk-TY6Z2UV2.js} +1 -1
- package/dist/{create-O3PVSKFE.js → create-QOJPAIOR.js} +3 -3
- package/dist/index.js +455 -67
- package/dist/{llmMarkdownGenerator-IJKJYJ3U.js → llmMarkdownGenerator-JPDNDGE4.js} +1 -1
- package/dist/{markdownGenerator-SJT7AXLT.js → markdownGenerator-NHN4MNEA.js} +1 -1
- package/dist/{mementoService-PKCNMN4V.js → mementoService-EN7FZK7B.js} +3 -3
- package/dist/{src-GRO5NIC3.js → src-36AL3BJR.js} +13 -1
- package/dist/{src-C5CZFXVM.js → src-JZN5O6F3.js} +2 -2
- package/dist/{subtractCredits-WZZAP57N.js → subtractCredits-FCBMFPIP.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-KPOK6V6E.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;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BadRequestError,
|
|
4
4
|
secureParameters
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-TY6Z2UV2.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-KPOK6V6E.js";
|
|
16
16
|
|
|
17
17
|
// ../../b4m-core/packages/services/dist/src/creditService/subtractCredits.js
|
|
18
18
|
import { z } from "zod";
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
getSettingsMap,
|
|
8
8
|
getSettingsValue,
|
|
9
9
|
secureParameters
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-TY6Z2UV2.js";
|
|
11
11
|
import {
|
|
12
12
|
KnowledgeType,
|
|
13
13
|
SupportedFabFileMimeTypes
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-KPOK6V6E.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/fabFileService/create.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -1012,6 +1012,29 @@ var VoiceSessionSendTranscriptAction = z10.object({
|
|
|
1012
1012
|
conversationItemId: z10.string(),
|
|
1013
1013
|
timestamp: z10.coerce.date().optional()
|
|
1014
1014
|
});
|
|
1015
|
+
var CliCompletionRequestAction = z10.object({
|
|
1016
|
+
action: z10.literal("cli_completion_request"),
|
|
1017
|
+
accessToken: z10.string(),
|
|
1018
|
+
requestId: z10.string().uuid(),
|
|
1019
|
+
model: z10.string(),
|
|
1020
|
+
messages: z10.array(z10.object({
|
|
1021
|
+
role: z10.enum(["user", "assistant", "system"]),
|
|
1022
|
+
content: z10.union([z10.string(), z10.array(z10.unknown())])
|
|
1023
|
+
})),
|
|
1024
|
+
options: z10.object({
|
|
1025
|
+
temperature: z10.number().optional(),
|
|
1026
|
+
maxTokens: z10.number().optional(),
|
|
1027
|
+
stream: z10.boolean().optional(),
|
|
1028
|
+
tools: z10.array(z10.unknown()).optional()
|
|
1029
|
+
}).optional()
|
|
1030
|
+
});
|
|
1031
|
+
var CliToolRequestAction = z10.object({
|
|
1032
|
+
action: z10.literal("cli_tool_request"),
|
|
1033
|
+
accessToken: z10.string(),
|
|
1034
|
+
requestId: z10.string().uuid(),
|
|
1035
|
+
toolName: z10.string(),
|
|
1036
|
+
input: z10.record(z10.unknown())
|
|
1037
|
+
});
|
|
1015
1038
|
var VoiceSessionEndedAction = z10.object({
|
|
1016
1039
|
action: z10.literal("voice_session_ended"),
|
|
1017
1040
|
userId: z10.string(),
|
|
@@ -1258,6 +1281,36 @@ var ResearchModeStreamAction = z10.object({
|
|
|
1258
1281
|
completionInfo: z10.any().optional()
|
|
1259
1282
|
}).optional()
|
|
1260
1283
|
});
|
|
1284
|
+
var CliCompletionChunkAction = z10.object({
|
|
1285
|
+
action: z10.literal("cli_completion_chunk"),
|
|
1286
|
+
requestId: z10.string(),
|
|
1287
|
+
chunk: z10.object({
|
|
1288
|
+
type: z10.enum(["content", "tool_use"]),
|
|
1289
|
+
text: z10.string(),
|
|
1290
|
+
tools: z10.array(z10.unknown()).optional(),
|
|
1291
|
+
usage: z10.object({
|
|
1292
|
+
inputTokens: z10.number().optional(),
|
|
1293
|
+
outputTokens: z10.number().optional()
|
|
1294
|
+
}).optional(),
|
|
1295
|
+
thinking: z10.array(z10.unknown()).optional()
|
|
1296
|
+
})
|
|
1297
|
+
});
|
|
1298
|
+
var CliCompletionDoneAction = z10.object({
|
|
1299
|
+
action: z10.literal("cli_completion_done"),
|
|
1300
|
+
requestId: z10.string()
|
|
1301
|
+
});
|
|
1302
|
+
var CliCompletionErrorAction = z10.object({
|
|
1303
|
+
action: z10.literal("cli_completion_error"),
|
|
1304
|
+
requestId: z10.string(),
|
|
1305
|
+
error: z10.string()
|
|
1306
|
+
});
|
|
1307
|
+
var CliToolResponseAction = z10.object({
|
|
1308
|
+
action: z10.literal("cli_tool_response"),
|
|
1309
|
+
requestId: z10.string(),
|
|
1310
|
+
success: z10.boolean(),
|
|
1311
|
+
content: z10.unknown().optional(),
|
|
1312
|
+
error: z10.string().optional()
|
|
1313
|
+
});
|
|
1261
1314
|
var SessionCreatedAction = shareableDocumentSchema.extend({
|
|
1262
1315
|
action: z10.literal("session.created"),
|
|
1263
1316
|
id: z10.string(),
|
|
@@ -1292,7 +1345,9 @@ var MessageDataToServer = z10.discriminatedUnion("action", [
|
|
|
1292
1345
|
DataUnsubscribeRequestAction,
|
|
1293
1346
|
HeartbeatAction,
|
|
1294
1347
|
VoiceSessionSendTranscriptAction,
|
|
1295
|
-
VoiceSessionEndedAction
|
|
1348
|
+
VoiceSessionEndedAction,
|
|
1349
|
+
CliCompletionRequestAction,
|
|
1350
|
+
CliToolRequestAction
|
|
1296
1351
|
]);
|
|
1297
1352
|
var MessageDataToClient = z10.discriminatedUnion("action", [
|
|
1298
1353
|
DataSubscriptionUpdateAction,
|
|
@@ -1314,7 +1369,11 @@ var MessageDataToClient = z10.discriminatedUnion("action", [
|
|
|
1314
1369
|
SpiderProgressUpdateAction,
|
|
1315
1370
|
SpiderCompleteAction,
|
|
1316
1371
|
SpiderErrorAction,
|
|
1317
|
-
SessionCreatedAction
|
|
1372
|
+
SessionCreatedAction,
|
|
1373
|
+
CliCompletionChunkAction,
|
|
1374
|
+
CliCompletionDoneAction,
|
|
1375
|
+
CliCompletionErrorAction,
|
|
1376
|
+
CliToolResponseAction
|
|
1318
1377
|
]);
|
|
1319
1378
|
|
|
1320
1379
|
// ../../b4m-core/packages/common/dist/src/schemas/cliCompletions.js
|
|
@@ -7926,6 +7985,8 @@ export {
|
|
|
7926
7985
|
DataUnsubscribeRequestAction,
|
|
7927
7986
|
HeartbeatAction,
|
|
7928
7987
|
VoiceSessionSendTranscriptAction,
|
|
7988
|
+
CliCompletionRequestAction,
|
|
7989
|
+
CliToolRequestAction,
|
|
7929
7990
|
VoiceSessionEndedAction,
|
|
7930
7991
|
DataSubscriptionUpdateAction,
|
|
7931
7992
|
LLMStatusUpdateAction,
|
|
@@ -7946,6 +8007,10 @@ export {
|
|
|
7946
8007
|
UpdateResearchTaskStatusAction,
|
|
7947
8008
|
ImportHistoryJobProgressUpdateAction,
|
|
7948
8009
|
ResearchModeStreamAction,
|
|
8010
|
+
CliCompletionChunkAction,
|
|
8011
|
+
CliCompletionDoneAction,
|
|
8012
|
+
CliCompletionErrorAction,
|
|
8013
|
+
CliToolResponseAction,
|
|
7949
8014
|
SessionCreatedAction,
|
|
7950
8015
|
MessageDataToServer,
|
|
7951
8016
|
MessageDataToClient,
|
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
getSettingsByNames,
|
|
7
7
|
obfuscateApiKey,
|
|
8
8
|
secureParameters
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-TY6Z2UV2.js";
|
|
10
10
|
import {
|
|
11
11
|
ApiKeyType,
|
|
12
12
|
MementoTier,
|
|
13
13
|
isSupportedEmbeddingModel
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-KPOK6V6E.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/apiKeyService/get.js
|
|
17
17
|
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-EC2VEDD2.js";
|
|
6
|
+
import "./chunk-TY6Z2UV2.js";
|
|
7
|
+
import "./chunk-KPOK6V6E.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-QQL3OBKL.js";
|
|
9
9
|
import {
|
|
10
10
|
ConfigStore,
|
|
11
11
|
logger
|
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
selectActiveBackgroundAgents,
|
|
15
15
|
useCliStore
|
|
16
16
|
} from "./chunk-TVW4ZESU.js";
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-BXCARBUQ.js";
|
|
18
|
+
import "./chunk-EC2VEDD2.js";
|
|
19
19
|
import {
|
|
20
20
|
BFLImageService,
|
|
21
21
|
BaseStorage,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
OpenAIBackend,
|
|
28
28
|
OpenAIImageService,
|
|
29
29
|
XAIImageService
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-TY6Z2UV2.js";
|
|
31
31
|
import {
|
|
32
32
|
AiEvents,
|
|
33
33
|
ApiKeyEvents,
|
|
@@ -83,7 +83,7 @@ import {
|
|
|
83
83
|
XAI_IMAGE_MODELS,
|
|
84
84
|
b4mLLMTools,
|
|
85
85
|
getMcpProviderMetadata
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-KPOK6V6E.js";
|
|
87
87
|
import {
|
|
88
88
|
Logger
|
|
89
89
|
} from "./chunk-OCYRD7D6.js";
|
|
@@ -93,7 +93,7 @@ import React21, { useState as useState9, useEffect as useEffect6, useCallback as
|
|
|
93
93
|
import { render, Box as Box20, Text as Text20, useApp, useInput as useInput9 } from "ink";
|
|
94
94
|
import { execSync } from "child_process";
|
|
95
95
|
import { randomBytes as randomBytes5 } from "crypto";
|
|
96
|
-
import { v4 as
|
|
96
|
+
import { v4 as uuidv413 } from "uuid";
|
|
97
97
|
|
|
98
98
|
// src/components/App.tsx
|
|
99
99
|
import React15, { useState as useState5, useEffect as useEffect4 } from "react";
|
|
@@ -1260,12 +1260,10 @@ function PermissionPrompt({
|
|
|
1260
1260
|
}) {
|
|
1261
1261
|
const items = canBeTrusted ? [
|
|
1262
1262
|
{ label: "\u2713 Allow once", value: "allow-once" },
|
|
1263
|
-
{ label: "\u2713 Allow for this session", value: "allow-session" },
|
|
1264
1263
|
{ label: "\u2713 Always allow (trust this tool)", value: "allow-always" },
|
|
1265
1264
|
{ label: "\u2717 Deny", value: "deny" }
|
|
1266
1265
|
] : [
|
|
1267
1266
|
{ label: "\u2713 Allow once", value: "allow-once" },
|
|
1268
|
-
{ label: "\u2713 Allow for this session", value: "allow-session" },
|
|
1269
1267
|
{ label: "\u2717 Deny", value: "deny" }
|
|
1270
1268
|
];
|
|
1271
1269
|
const [selectedIndex, setSelectedIndex] = useState3(0);
|
|
@@ -11440,6 +11438,10 @@ var ServerToolExecutor = class {
|
|
|
11440
11438
|
};
|
|
11441
11439
|
|
|
11442
11440
|
// src/llm/ToolRouter.ts
|
|
11441
|
+
var wsToolExecutor = null;
|
|
11442
|
+
function setWebSocketToolExecutor(executor) {
|
|
11443
|
+
wsToolExecutor = executor;
|
|
11444
|
+
}
|
|
11443
11445
|
var SERVER_TOOLS = ["weather_info", "web_search", "web_fetch"];
|
|
11444
11446
|
var LOCAL_TOOLS = [
|
|
11445
11447
|
"file_read",
|
|
@@ -11462,7 +11464,15 @@ function isLocalTool(toolName) {
|
|
|
11462
11464
|
}
|
|
11463
11465
|
async function executeTool(toolName, input, apiClient, localToolFn) {
|
|
11464
11466
|
if (isServerTool(toolName)) {
|
|
11465
|
-
|
|
11467
|
+
if (wsToolExecutor) {
|
|
11468
|
+
logger.debug(`[ToolRouter] Routing ${toolName} to server via WebSocket`);
|
|
11469
|
+
const result = await wsToolExecutor.execute(toolName, input);
|
|
11470
|
+
if (!result.success) {
|
|
11471
|
+
return `Error executing ${toolName}: ${result.error || "Tool execution failed"}`;
|
|
11472
|
+
}
|
|
11473
|
+
return typeof result.content === "string" ? result.content : JSON.stringify(result.content ?? "");
|
|
11474
|
+
}
|
|
11475
|
+
logger.debug(`[ToolRouter] Routing ${toolName} to server via HTTP`);
|
|
11466
11476
|
const executor = new ServerToolExecutor(apiClient);
|
|
11467
11477
|
return await executor.executeTool(toolName, input);
|
|
11468
11478
|
} else if (isLocalTool(toolName)) {
|
|
@@ -11766,9 +11776,6 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
|
|
|
11766
11776
|
if (response.action === "deny") {
|
|
11767
11777
|
throw new PermissionDeniedError(toolName, args);
|
|
11768
11778
|
}
|
|
11769
|
-
if (response.action === "allow-session") {
|
|
11770
|
-
permissionManager.trustToolForSession(toolName);
|
|
11771
|
-
}
|
|
11772
11779
|
if (response.action === "allow-always") {
|
|
11773
11780
|
const canTrust = permissionManager.trustTool(toolName);
|
|
11774
11781
|
if (canTrust) {
|
|
@@ -11973,7 +11980,6 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
|
|
|
11973
11980
|
var PermissionManager = class {
|
|
11974
11981
|
constructor(trustedTools = [], customCategories, deniedTools) {
|
|
11975
11982
|
this.trustedTools = /* @__PURE__ */ new Set();
|
|
11976
|
-
this.sessionTrustedTools = /* @__PURE__ */ new Set();
|
|
11977
11983
|
this.deniedTools = /* @__PURE__ */ new Set();
|
|
11978
11984
|
this.trustedTools = new Set(trustedTools);
|
|
11979
11985
|
this.customCategories = new Map(Object.entries(customCategories || {}));
|
|
@@ -11999,9 +12005,6 @@ var PermissionManager = class {
|
|
|
11999
12005
|
if (category === "auto_approve") {
|
|
12000
12006
|
return false;
|
|
12001
12007
|
}
|
|
12002
|
-
if (this.sessionTrustedTools.has(toolName)) {
|
|
12003
|
-
return false;
|
|
12004
|
-
}
|
|
12005
12008
|
if (category === "prompt_always") {
|
|
12006
12009
|
return true;
|
|
12007
12010
|
}
|
|
@@ -12069,29 +12072,6 @@ var PermissionManager = class {
|
|
|
12069
12072
|
getDeniedTools() {
|
|
12070
12073
|
return Array.from(this.deniedTools).sort();
|
|
12071
12074
|
}
|
|
12072
|
-
/**
|
|
12073
|
-
* Trust a tool for the current session only (in-memory, no persistence)
|
|
12074
|
-
* Works for all tool categories including prompt_always, but NOT project-denied tools
|
|
12075
|
-
*/
|
|
12076
|
-
trustToolForSession(toolName) {
|
|
12077
|
-
if (this.deniedTools.has(toolName)) {
|
|
12078
|
-
return false;
|
|
12079
|
-
}
|
|
12080
|
-
this.sessionTrustedTools.add(toolName);
|
|
12081
|
-
return true;
|
|
12082
|
-
}
|
|
12083
|
-
/**
|
|
12084
|
-
* Check if a tool is trusted for the current session
|
|
12085
|
-
*/
|
|
12086
|
-
isSessionTrusted(toolName) {
|
|
12087
|
-
return this.sessionTrustedTools.has(toolName);
|
|
12088
|
-
}
|
|
12089
|
-
/**
|
|
12090
|
-
* Clear all session-scoped trust (called on exit or session reset)
|
|
12091
|
-
*/
|
|
12092
|
-
clearSessionTrust() {
|
|
12093
|
-
this.sessionTrustedTools.clear();
|
|
12094
|
-
}
|
|
12095
12075
|
/**
|
|
12096
12076
|
* Clear all trusted tools
|
|
12097
12077
|
*/
|
|
@@ -13422,6 +13402,168 @@ var ServerLlmBackend = class {
|
|
|
13422
13402
|
}
|
|
13423
13403
|
};
|
|
13424
13404
|
|
|
13405
|
+
// src/llm/WebSocketLlmBackend.ts
|
|
13406
|
+
import { v4 as uuidv411 } from "uuid";
|
|
13407
|
+
function stripThinkingBlocks2(text) {
|
|
13408
|
+
return text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
13409
|
+
}
|
|
13410
|
+
var WebSocketLlmBackend = class {
|
|
13411
|
+
constructor(options) {
|
|
13412
|
+
this.wsManager = options.wsManager;
|
|
13413
|
+
this.apiClient = options.apiClient;
|
|
13414
|
+
this.currentModel = options.model;
|
|
13415
|
+
this.tokenGetter = options.tokenGetter;
|
|
13416
|
+
}
|
|
13417
|
+
/**
|
|
13418
|
+
* Make LLM completion request via WebSocket.
|
|
13419
|
+
* Collects all streamed chunks, then calls callback once at completion
|
|
13420
|
+
* with the full accumulated content.
|
|
13421
|
+
*/
|
|
13422
|
+
async complete(model, messages, options, callback) {
|
|
13423
|
+
logger.debug(`[WebSocketLlmBackend] Starting complete() with model: ${model}`);
|
|
13424
|
+
if (options.abortSignal?.aborted) {
|
|
13425
|
+
logger.debug("[WebSocketLlmBackend] Request aborted before start");
|
|
13426
|
+
return;
|
|
13427
|
+
}
|
|
13428
|
+
if (!this.wsManager.isConnected) {
|
|
13429
|
+
throw new Error("WebSocket is not connected");
|
|
13430
|
+
}
|
|
13431
|
+
const requestId = uuidv411();
|
|
13432
|
+
const token = await this.tokenGetter();
|
|
13433
|
+
if (!token) {
|
|
13434
|
+
throw new Error("No access token available");
|
|
13435
|
+
}
|
|
13436
|
+
return new Promise((resolve3, reject) => {
|
|
13437
|
+
const isVerbose = process.env.B4M_VERBOSE === "1";
|
|
13438
|
+
const isUltraVerbose = process.env.B4M_DEBUG_STREAM === "1";
|
|
13439
|
+
const streamLogger = new StreamLogger(logger, "WebSocketLlmBackend", isVerbose, isUltraVerbose);
|
|
13440
|
+
streamLogger.streamStart();
|
|
13441
|
+
let eventCount = 0;
|
|
13442
|
+
let accumulatedText = "";
|
|
13443
|
+
let lastUsageInfo = {};
|
|
13444
|
+
let toolsUsed = [];
|
|
13445
|
+
let thinkingBlocks = [];
|
|
13446
|
+
let settled = false;
|
|
13447
|
+
const settle = (action) => {
|
|
13448
|
+
if (settled) return;
|
|
13449
|
+
settled = true;
|
|
13450
|
+
this.wsManager.offRequest(requestId);
|
|
13451
|
+
action();
|
|
13452
|
+
};
|
|
13453
|
+
const settleResolve = () => settle(() => resolve3());
|
|
13454
|
+
const settleReject = (err) => settle(() => reject(err));
|
|
13455
|
+
if (options.abortSignal) {
|
|
13456
|
+
if (options.abortSignal.aborted) {
|
|
13457
|
+
settleResolve();
|
|
13458
|
+
return;
|
|
13459
|
+
}
|
|
13460
|
+
options.abortSignal.addEventListener(
|
|
13461
|
+
"abort",
|
|
13462
|
+
() => {
|
|
13463
|
+
logger.debug("[WebSocketLlmBackend] Abort signal received");
|
|
13464
|
+
settleResolve();
|
|
13465
|
+
},
|
|
13466
|
+
{ once: true }
|
|
13467
|
+
);
|
|
13468
|
+
}
|
|
13469
|
+
const updateUsage = (usage) => {
|
|
13470
|
+
if (usage) {
|
|
13471
|
+
lastUsageInfo = { inputTokens: usage.inputTokens, outputTokens: usage.outputTokens };
|
|
13472
|
+
}
|
|
13473
|
+
};
|
|
13474
|
+
this.wsManager.onRequest(requestId, (message) => {
|
|
13475
|
+
if (options.abortSignal?.aborted) return;
|
|
13476
|
+
const action = message.action;
|
|
13477
|
+
if (action === "cli_completion_chunk") {
|
|
13478
|
+
eventCount++;
|
|
13479
|
+
const chunk = message.chunk;
|
|
13480
|
+
streamLogger.onEvent(eventCount, JSON.stringify(chunk));
|
|
13481
|
+
const textChunk = chunk.text || "";
|
|
13482
|
+
if (textChunk) accumulatedText += textChunk;
|
|
13483
|
+
updateUsage(chunk.usage);
|
|
13484
|
+
if (chunk.type === "content") {
|
|
13485
|
+
streamLogger.onContent(eventCount, textChunk, accumulatedText);
|
|
13486
|
+
} else if (chunk.type === "tool_use") {
|
|
13487
|
+
streamLogger.onCriticalEvent(eventCount, "TOOL_USE", `tools: ${chunk.tools?.length}`);
|
|
13488
|
+
if (chunk.tools && chunk.tools.length > 0) toolsUsed = chunk.tools;
|
|
13489
|
+
if (chunk.thinking && chunk.thinking.length > 0) thinkingBlocks = chunk.thinking;
|
|
13490
|
+
}
|
|
13491
|
+
} else if (action === "cli_completion_done") {
|
|
13492
|
+
streamLogger.streamComplete(accumulatedText);
|
|
13493
|
+
const cleanedText = stripThinkingBlocks2(accumulatedText);
|
|
13494
|
+
if (!cleanedText && toolsUsed.length === 0) {
|
|
13495
|
+
settleResolve();
|
|
13496
|
+
return;
|
|
13497
|
+
}
|
|
13498
|
+
const info = {
|
|
13499
|
+
...lastUsageInfo,
|
|
13500
|
+
...toolsUsed.length > 0 && { toolsUsed },
|
|
13501
|
+
...thinkingBlocks.length > 0 && { thinking: thinkingBlocks }
|
|
13502
|
+
};
|
|
13503
|
+
callback([cleanedText], info).then(() => settleResolve()).catch((err) => settleReject(err));
|
|
13504
|
+
} else if (action === "cli_completion_error") {
|
|
13505
|
+
const errorMsg = message.error || "Server error";
|
|
13506
|
+
streamLogger.onCriticalEvent(eventCount, "ERROR", errorMsg);
|
|
13507
|
+
settleReject(new Error(errorMsg));
|
|
13508
|
+
}
|
|
13509
|
+
});
|
|
13510
|
+
try {
|
|
13511
|
+
this.wsManager.send({
|
|
13512
|
+
action: "cli_completion_request",
|
|
13513
|
+
accessToken: token,
|
|
13514
|
+
requestId,
|
|
13515
|
+
model,
|
|
13516
|
+
messages,
|
|
13517
|
+
options: {
|
|
13518
|
+
temperature: options.temperature,
|
|
13519
|
+
maxTokens: options.maxTokens,
|
|
13520
|
+
stream: true,
|
|
13521
|
+
tools: options.tools || []
|
|
13522
|
+
}
|
|
13523
|
+
});
|
|
13524
|
+
} catch (err) {
|
|
13525
|
+
settleReject(err instanceof Error ? err : new Error(String(err)));
|
|
13526
|
+
}
|
|
13527
|
+
});
|
|
13528
|
+
}
|
|
13529
|
+
/**
|
|
13530
|
+
* Get available models from server (REST call, not streaming).
|
|
13531
|
+
* Delegates to ApiClient -- same as ServerLlmBackend.
|
|
13532
|
+
*/
|
|
13533
|
+
async getModelInfo() {
|
|
13534
|
+
try {
|
|
13535
|
+
logger.debug("[WebSocketLlmBackend] Fetching models from /api/models");
|
|
13536
|
+
const response = await this.apiClient.get("/api/models");
|
|
13537
|
+
if (!response || typeof response !== "object" || !Array.isArray(response.models)) {
|
|
13538
|
+
logger.warn("[WebSocketLlmBackend] Invalid API response format, using fallback models");
|
|
13539
|
+
return this.getFallbackModels();
|
|
13540
|
+
}
|
|
13541
|
+
const filteredModels = response.models.filter(
|
|
13542
|
+
(model) => model.type === "text" && model.supportsTools === true
|
|
13543
|
+
);
|
|
13544
|
+
if (filteredModels.length === 0) {
|
|
13545
|
+
logger.warn("[WebSocketLlmBackend] No CLI-compatible models found, using fallback");
|
|
13546
|
+
return this.getFallbackModels();
|
|
13547
|
+
}
|
|
13548
|
+
logger.debug(`[WebSocketLlmBackend] Loaded ${filteredModels.length} models`);
|
|
13549
|
+
return filteredModels;
|
|
13550
|
+
} catch (error) {
|
|
13551
|
+
logger.warn(
|
|
13552
|
+
`[WebSocketLlmBackend] Failed to fetch models: ${error instanceof Error ? error.message : String(error)}`
|
|
13553
|
+
);
|
|
13554
|
+
return this.getFallbackModels();
|
|
13555
|
+
}
|
|
13556
|
+
}
|
|
13557
|
+
getFallbackModels() {
|
|
13558
|
+
return [
|
|
13559
|
+
{ id: "claude-sonnet-4-5-20250929", name: "Claude 4.5 Sonnet" },
|
|
13560
|
+
{ id: "claude-3-5-haiku-20241022", name: "Claude 3.5 Haiku" },
|
|
13561
|
+
{ id: "gpt-4o", name: "GPT-4o" },
|
|
13562
|
+
{ id: "gpt-4o-mini", name: "GPT-4o Mini" }
|
|
13563
|
+
];
|
|
13564
|
+
}
|
|
13565
|
+
};
|
|
13566
|
+
|
|
13425
13567
|
// src/llm/NotifyingLlmBackend.ts
|
|
13426
13568
|
var NotifyingLlmBackend = class {
|
|
13427
13569
|
constructor(inner, backgroundManager) {
|
|
@@ -13456,6 +13598,214 @@ Please acknowledge these background agent results and incorporate them into your
|
|
|
13456
13598
|
}
|
|
13457
13599
|
};
|
|
13458
13600
|
|
|
13601
|
+
// src/ws/WebSocketConnectionManager.ts
|
|
13602
|
+
var WebSocketConnectionManager = class {
|
|
13603
|
+
constructor(wsUrl, getToken) {
|
|
13604
|
+
this.ws = null;
|
|
13605
|
+
this.heartbeatInterval = null;
|
|
13606
|
+
this.reconnectAttempts = 0;
|
|
13607
|
+
this.maxReconnectDelay = 3e4;
|
|
13608
|
+
this.handlers = /* @__PURE__ */ new Map();
|
|
13609
|
+
this.connected = false;
|
|
13610
|
+
this.connecting = false;
|
|
13611
|
+
this.closed = false;
|
|
13612
|
+
this.wsUrl = wsUrl;
|
|
13613
|
+
this.getToken = getToken;
|
|
13614
|
+
}
|
|
13615
|
+
/**
|
|
13616
|
+
* Connect to the WebSocket server.
|
|
13617
|
+
* Resolves when connection is established, rejects on failure.
|
|
13618
|
+
*/
|
|
13619
|
+
async connect() {
|
|
13620
|
+
if (this.connected || this.connecting) return;
|
|
13621
|
+
this.connecting = true;
|
|
13622
|
+
const token = await this.getToken();
|
|
13623
|
+
if (!token) {
|
|
13624
|
+
this.connecting = false;
|
|
13625
|
+
throw new Error("No access token available for WebSocket connection");
|
|
13626
|
+
}
|
|
13627
|
+
return new Promise((resolve3, reject) => {
|
|
13628
|
+
const url = `${this.wsUrl}?token=${token}`;
|
|
13629
|
+
logger.debug(`[WS] Connecting to ${this.wsUrl}...`);
|
|
13630
|
+
this.ws = new WebSocket(url);
|
|
13631
|
+
this.ws.onopen = () => {
|
|
13632
|
+
logger.debug("[WS] Connected");
|
|
13633
|
+
this.connected = true;
|
|
13634
|
+
this.connecting = false;
|
|
13635
|
+
this.reconnectAttempts = 0;
|
|
13636
|
+
this.startHeartbeat();
|
|
13637
|
+
resolve3();
|
|
13638
|
+
};
|
|
13639
|
+
this.ws.onmessage = (event) => {
|
|
13640
|
+
try {
|
|
13641
|
+
const data = typeof event.data === "string" ? event.data : event.data.toString();
|
|
13642
|
+
const message = JSON.parse(data);
|
|
13643
|
+
const requestId = message.requestId;
|
|
13644
|
+
if (requestId && this.handlers.has(requestId)) {
|
|
13645
|
+
this.handlers.get(requestId)(message);
|
|
13646
|
+
} else {
|
|
13647
|
+
logger.debug(`[WS] Unhandled message: ${message.action || "unknown"}`);
|
|
13648
|
+
}
|
|
13649
|
+
} catch (err) {
|
|
13650
|
+
logger.debug(`[WS] Failed to parse message: ${err}`);
|
|
13651
|
+
}
|
|
13652
|
+
};
|
|
13653
|
+
this.ws.onclose = () => {
|
|
13654
|
+
logger.debug("[WS] Connection closed");
|
|
13655
|
+
this.cleanup();
|
|
13656
|
+
if (!this.closed) {
|
|
13657
|
+
this.scheduleReconnect();
|
|
13658
|
+
}
|
|
13659
|
+
};
|
|
13660
|
+
this.ws.onerror = (err) => {
|
|
13661
|
+
logger.debug(`[WS] Error: ${err}`);
|
|
13662
|
+
if (this.connecting) {
|
|
13663
|
+
this.connecting = false;
|
|
13664
|
+
this.connected = false;
|
|
13665
|
+
reject(new Error("WebSocket connection failed"));
|
|
13666
|
+
}
|
|
13667
|
+
};
|
|
13668
|
+
});
|
|
13669
|
+
}
|
|
13670
|
+
/** Whether the connection is currently established */
|
|
13671
|
+
get isConnected() {
|
|
13672
|
+
return this.connected;
|
|
13673
|
+
}
|
|
13674
|
+
/**
|
|
13675
|
+
* Send a JSON message over the WebSocket connection.
|
|
13676
|
+
*/
|
|
13677
|
+
send(data) {
|
|
13678
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
13679
|
+
throw new Error("WebSocket is not connected");
|
|
13680
|
+
}
|
|
13681
|
+
this.ws.send(JSON.stringify(data));
|
|
13682
|
+
}
|
|
13683
|
+
/**
|
|
13684
|
+
* Register a handler for messages matching a specific requestId.
|
|
13685
|
+
*/
|
|
13686
|
+
onRequest(requestId, handler) {
|
|
13687
|
+
this.handlers.set(requestId, handler);
|
|
13688
|
+
}
|
|
13689
|
+
/**
|
|
13690
|
+
* Remove a handler for a specific requestId.
|
|
13691
|
+
*/
|
|
13692
|
+
offRequest(requestId) {
|
|
13693
|
+
this.handlers.delete(requestId);
|
|
13694
|
+
}
|
|
13695
|
+
/**
|
|
13696
|
+
* Close the connection and stop all heartbeat/reconnect logic.
|
|
13697
|
+
*/
|
|
13698
|
+
disconnect() {
|
|
13699
|
+
this.closed = true;
|
|
13700
|
+
this.cleanup();
|
|
13701
|
+
if (this.ws) {
|
|
13702
|
+
this.ws.close();
|
|
13703
|
+
this.ws = null;
|
|
13704
|
+
}
|
|
13705
|
+
this.handlers.clear();
|
|
13706
|
+
}
|
|
13707
|
+
startHeartbeat() {
|
|
13708
|
+
this.stopHeartbeat();
|
|
13709
|
+
this.heartbeatInterval = setInterval(
|
|
13710
|
+
() => {
|
|
13711
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
13712
|
+
this.ws.send(JSON.stringify({ action: "heartbeat" }));
|
|
13713
|
+
logger.debug("[WS] Heartbeat sent");
|
|
13714
|
+
}
|
|
13715
|
+
},
|
|
13716
|
+
5 * 60 * 1e3
|
|
13717
|
+
);
|
|
13718
|
+
}
|
|
13719
|
+
stopHeartbeat() {
|
|
13720
|
+
if (this.heartbeatInterval) {
|
|
13721
|
+
clearInterval(this.heartbeatInterval);
|
|
13722
|
+
this.heartbeatInterval = null;
|
|
13723
|
+
}
|
|
13724
|
+
}
|
|
13725
|
+
cleanup() {
|
|
13726
|
+
this.connected = false;
|
|
13727
|
+
this.connecting = false;
|
|
13728
|
+
this.stopHeartbeat();
|
|
13729
|
+
}
|
|
13730
|
+
scheduleReconnect() {
|
|
13731
|
+
if (this.closed) return;
|
|
13732
|
+
this.reconnectAttempts++;
|
|
13733
|
+
const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts - 1), this.maxReconnectDelay);
|
|
13734
|
+
logger.debug(`[WS] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
|
|
13735
|
+
setTimeout(async () => {
|
|
13736
|
+
if (this.closed) return;
|
|
13737
|
+
try {
|
|
13738
|
+
await this.connect();
|
|
13739
|
+
} catch {
|
|
13740
|
+
logger.debug("[WS] Reconnection failed");
|
|
13741
|
+
}
|
|
13742
|
+
}, delay);
|
|
13743
|
+
}
|
|
13744
|
+
};
|
|
13745
|
+
|
|
13746
|
+
// src/ws/WebSocketToolExecutor.ts
|
|
13747
|
+
import { v4 as uuidv412 } from "uuid";
|
|
13748
|
+
var WebSocketToolExecutor = class {
|
|
13749
|
+
constructor(wsManager, tokenGetter) {
|
|
13750
|
+
this.wsManager = wsManager;
|
|
13751
|
+
this.tokenGetter = tokenGetter;
|
|
13752
|
+
}
|
|
13753
|
+
/**
|
|
13754
|
+
* Execute a server-side tool via WebSocket.
|
|
13755
|
+
* Returns the tool result or throws on error.
|
|
13756
|
+
*/
|
|
13757
|
+
async execute(toolName, input, abortSignal) {
|
|
13758
|
+
if (!this.wsManager.isConnected) {
|
|
13759
|
+
throw new Error("WebSocket is not connected");
|
|
13760
|
+
}
|
|
13761
|
+
const token = await this.tokenGetter();
|
|
13762
|
+
if (!token) {
|
|
13763
|
+
throw new Error("No access token available");
|
|
13764
|
+
}
|
|
13765
|
+
const requestId = uuidv412();
|
|
13766
|
+
return new Promise((resolve3, reject) => {
|
|
13767
|
+
let settled = false;
|
|
13768
|
+
const settle = (action) => {
|
|
13769
|
+
if (settled) return;
|
|
13770
|
+
settled = true;
|
|
13771
|
+
this.wsManager.offRequest(requestId);
|
|
13772
|
+
action();
|
|
13773
|
+
};
|
|
13774
|
+
const settleResolve = (result) => settle(() => resolve3(result));
|
|
13775
|
+
const settleReject = (err) => settle(() => reject(err));
|
|
13776
|
+
if (abortSignal) {
|
|
13777
|
+
if (abortSignal.aborted) {
|
|
13778
|
+
settleReject(new Error("Tool execution aborted"));
|
|
13779
|
+
return;
|
|
13780
|
+
}
|
|
13781
|
+
abortSignal.addEventListener("abort", () => settleReject(new Error("Tool execution aborted")), {
|
|
13782
|
+
once: true
|
|
13783
|
+
});
|
|
13784
|
+
}
|
|
13785
|
+
this.wsManager.onRequest(requestId, (message) => {
|
|
13786
|
+
if (message.action === "cli_tool_response") {
|
|
13787
|
+
settleResolve({
|
|
13788
|
+
success: message.success,
|
|
13789
|
+
content: message.content,
|
|
13790
|
+
error: message.error
|
|
13791
|
+
});
|
|
13792
|
+
}
|
|
13793
|
+
});
|
|
13794
|
+
try {
|
|
13795
|
+
this.wsManager.send({
|
|
13796
|
+
action: "cli_tool_request",
|
|
13797
|
+
accessToken: token,
|
|
13798
|
+
requestId,
|
|
13799
|
+
toolName,
|
|
13800
|
+
input
|
|
13801
|
+
});
|
|
13802
|
+
} catch (err) {
|
|
13803
|
+
settleReject(err instanceof Error ? err : new Error(String(err)));
|
|
13804
|
+
}
|
|
13805
|
+
});
|
|
13806
|
+
}
|
|
13807
|
+
};
|
|
13808
|
+
|
|
13459
13809
|
// src/auth/ApiClient.ts
|
|
13460
13810
|
import axios11 from "axios";
|
|
13461
13811
|
var ApiClient = class {
|
|
@@ -13593,7 +13943,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
|
|
|
13593
13943
|
// package.json
|
|
13594
13944
|
var package_default = {
|
|
13595
13945
|
name: "@bike4mind/cli",
|
|
13596
|
-
version: "0.2.29-feat-
|
|
13946
|
+
version: "0.2.29-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
13597
13947
|
type: "module",
|
|
13598
13948
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
13599
13949
|
license: "UNLICENSED",
|
|
@@ -13703,10 +14053,10 @@ var package_default = {
|
|
|
13703
14053
|
},
|
|
13704
14054
|
devDependencies: {
|
|
13705
14055
|
"@bike4mind/agents": "0.1.0",
|
|
13706
|
-
"@bike4mind/common": "2.50.1-feat-
|
|
13707
|
-
"@bike4mind/mcp": "1.29.1-feat-
|
|
13708
|
-
"@bike4mind/services": "2.48.1-feat-
|
|
13709
|
-
"@bike4mind/utils": "2.5.1-feat-
|
|
14056
|
+
"@bike4mind/common": "2.50.1-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
14057
|
+
"@bike4mind/mcp": "1.29.1-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
14058
|
+
"@bike4mind/services": "2.48.1-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
14059
|
+
"@bike4mind/utils": "2.5.1-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
13710
14060
|
"@types/better-sqlite3": "^7.6.13",
|
|
13711
14061
|
"@types/diff": "^5.0.9",
|
|
13712
14062
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -13723,7 +14073,7 @@ var package_default = {
|
|
|
13723
14073
|
optionalDependencies: {
|
|
13724
14074
|
"@vscode/ripgrep": "^1.17.0"
|
|
13725
14075
|
},
|
|
13726
|
-
gitHead: "
|
|
14076
|
+
gitHead: "8ba59c22293ec8857baaba3c7c6d96db1fbb4b15"
|
|
13727
14077
|
};
|
|
13728
14078
|
|
|
13729
14079
|
// src/config/constants.ts
|
|
@@ -15531,7 +15881,8 @@ function CliApp() {
|
|
|
15531
15881
|
agentStore: null,
|
|
15532
15882
|
abortController: null,
|
|
15533
15883
|
contextContent: "",
|
|
15534
|
-
backgroundManager: null
|
|
15884
|
+
backgroundManager: null,
|
|
15885
|
+
wsManager: null
|
|
15535
15886
|
});
|
|
15536
15887
|
const [isInitialized, setIsInitialized] = useState9(false);
|
|
15537
15888
|
const [initError, setInitError] = useState9(null);
|
|
@@ -15559,6 +15910,10 @@ function CliApp() {
|
|
|
15559
15910
|
})
|
|
15560
15911
|
);
|
|
15561
15912
|
}
|
|
15913
|
+
if (state.wsManager) {
|
|
15914
|
+
state.wsManager.disconnect();
|
|
15915
|
+
setWebSocketToolExecutor(null);
|
|
15916
|
+
}
|
|
15562
15917
|
if (state.agent) {
|
|
15563
15918
|
state.agent.removeAllListeners();
|
|
15564
15919
|
}
|
|
@@ -15577,7 +15932,7 @@ function CliApp() {
|
|
|
15577
15932
|
setTimeout(() => {
|
|
15578
15933
|
process.exit(0);
|
|
15579
15934
|
}, 100);
|
|
15580
|
-
}, [state.session, state.sessionStore, state.mcpManager, state.agent, state.imageStore]);
|
|
15935
|
+
}, [state.session, state.sessionStore, state.mcpManager, state.agent, state.imageStore, state.wsManager]);
|
|
15581
15936
|
useInput9((input, key) => {
|
|
15582
15937
|
if (key.escape) {
|
|
15583
15938
|
if (state.abortController) {
|
|
@@ -15647,7 +16002,7 @@ function CliApp() {
|
|
|
15647
16002
|
if (!isAuthenticated) {
|
|
15648
16003
|
console.log("\u2139\uFE0F AI features disabled. Available commands: /login, /help, /config\n");
|
|
15649
16004
|
const minimalSession = {
|
|
15650
|
-
id:
|
|
16005
|
+
id: uuidv413(),
|
|
15651
16006
|
name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
|
|
15652
16007
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15653
16008
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -15675,10 +16030,41 @@ function CliApp() {
|
|
|
15675
16030
|
console.log(`\u{1F30D} API Environment: ${envName} (${apiBaseURL})`);
|
|
15676
16031
|
}
|
|
15677
16032
|
const apiClient = new ApiClient(apiBaseURL, state.configStore);
|
|
15678
|
-
const
|
|
15679
|
-
|
|
15680
|
-
|
|
15681
|
-
}
|
|
16033
|
+
const tokenGetter = async () => {
|
|
16034
|
+
const tokens = await state.configStore.getAuthTokens();
|
|
16035
|
+
return tokens?.accessToken ?? null;
|
|
16036
|
+
};
|
|
16037
|
+
let wsManager = null;
|
|
16038
|
+
let llm;
|
|
16039
|
+
try {
|
|
16040
|
+
const serverConfig = await apiClient.get("/api/settings/serverConfig");
|
|
16041
|
+
const wsUrl = serverConfig?.websocketUrl;
|
|
16042
|
+
if (wsUrl) {
|
|
16043
|
+
wsManager = new WebSocketConnectionManager(wsUrl, tokenGetter);
|
|
16044
|
+
await wsManager.connect();
|
|
16045
|
+
const wsToolExecutor2 = new WebSocketToolExecutor(wsManager, tokenGetter);
|
|
16046
|
+
setWebSocketToolExecutor(wsToolExecutor2);
|
|
16047
|
+
llm = new WebSocketLlmBackend({
|
|
16048
|
+
wsManager,
|
|
16049
|
+
apiClient,
|
|
16050
|
+
model: config.defaultModel,
|
|
16051
|
+
tokenGetter
|
|
16052
|
+
});
|
|
16053
|
+
logger.debug("\u{1F50C} Using WebSocket transport (bypasses CloudFront timeout)");
|
|
16054
|
+
} else {
|
|
16055
|
+
throw new Error("No websocketUrl in server config");
|
|
16056
|
+
}
|
|
16057
|
+
} catch (wsError) {
|
|
16058
|
+
logger.debug(
|
|
16059
|
+
`[WS] WebSocket unavailable, using SSE fallback: ${wsError instanceof Error ? wsError.message : String(wsError)}`
|
|
16060
|
+
);
|
|
16061
|
+
wsManager = null;
|
|
16062
|
+
setWebSocketToolExecutor(null);
|
|
16063
|
+
llm = new ServerLlmBackend({
|
|
16064
|
+
apiClient,
|
|
16065
|
+
model: config.defaultModel
|
|
16066
|
+
});
|
|
16067
|
+
}
|
|
15682
16068
|
const models = await llm.getModelInfo();
|
|
15683
16069
|
if (models.length === 0) {
|
|
15684
16070
|
throw new Error("No models available from server.");
|
|
@@ -15691,7 +16077,7 @@ function CliApp() {
|
|
|
15691
16077
|
}
|
|
15692
16078
|
llm.currentModel = modelInfo.id;
|
|
15693
16079
|
const newSession = {
|
|
15694
|
-
id:
|
|
16080
|
+
id: uuidv413(),
|
|
15695
16081
|
name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
|
|
15696
16082
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15697
16083
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -15911,8 +16297,10 @@ ${contextResult.mergedContent}` : "";
|
|
|
15911
16297
|
// Store agent store for agent management commands
|
|
15912
16298
|
contextContent: contextResult.mergedContent,
|
|
15913
16299
|
// Store raw context for compact instructions
|
|
15914
|
-
backgroundManager
|
|
16300
|
+
backgroundManager,
|
|
15915
16301
|
// Store for grouped notification turn tracking
|
|
16302
|
+
wsManager
|
|
16303
|
+
// WebSocket connection manager (null if using SSE fallback)
|
|
15916
16304
|
}));
|
|
15917
16305
|
setStoreSession(newSession);
|
|
15918
16306
|
const bannerLines = [
|
|
@@ -16007,13 +16395,13 @@ ${contextResult.mergedContent}` : "";
|
|
|
16007
16395
|
messageContent = multimodalMessage.content;
|
|
16008
16396
|
}
|
|
16009
16397
|
const userMessage = {
|
|
16010
|
-
id:
|
|
16398
|
+
id: uuidv413(),
|
|
16011
16399
|
role: "user",
|
|
16012
16400
|
content: userMessageContent,
|
|
16013
16401
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
16014
16402
|
};
|
|
16015
16403
|
const pendingAssistantMessage = {
|
|
16016
|
-
id:
|
|
16404
|
+
id: uuidv413(),
|
|
16017
16405
|
role: "assistant",
|
|
16018
16406
|
content: "...",
|
|
16019
16407
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -16219,13 +16607,13 @@ ${contextResult.mergedContent}` : "";
|
|
|
16219
16607
|
userMessageContent = message;
|
|
16220
16608
|
}
|
|
16221
16609
|
const userMessage = {
|
|
16222
|
-
id:
|
|
16610
|
+
id: uuidv413(),
|
|
16223
16611
|
role: "user",
|
|
16224
16612
|
content: userMessageContent,
|
|
16225
16613
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
16226
16614
|
};
|
|
16227
16615
|
const pendingAssistantMessage = {
|
|
16228
|
-
id:
|
|
16616
|
+
id: uuidv413(),
|
|
16229
16617
|
role: "assistant",
|
|
16230
16618
|
content: "...",
|
|
16231
16619
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -16303,7 +16691,7 @@ ${contextResult.mergedContent}` : "";
|
|
|
16303
16691
|
const currentSession = useCliStore.getState().session;
|
|
16304
16692
|
if (currentSession) {
|
|
16305
16693
|
const cancelMessage = {
|
|
16306
|
-
id:
|
|
16694
|
+
id: uuidv413(),
|
|
16307
16695
|
role: "assistant",
|
|
16308
16696
|
content: "\u26A0\uFE0F Operation cancelled by user",
|
|
16309
16697
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -16348,7 +16736,7 @@ ${contextResult.mergedContent}` : "";
|
|
|
16348
16736
|
setState((prev) => ({ ...prev, abortController }));
|
|
16349
16737
|
try {
|
|
16350
16738
|
const pendingAssistantMessage = {
|
|
16351
|
-
id:
|
|
16739
|
+
id: uuidv413(),
|
|
16352
16740
|
role: "assistant",
|
|
16353
16741
|
content: "...",
|
|
16354
16742
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -16376,7 +16764,7 @@ ${contextResult.mergedContent}` : "";
|
|
|
16376
16764
|
const currentSession = useCliStore.getState().session;
|
|
16377
16765
|
if (!currentSession) return;
|
|
16378
16766
|
const continuationMessage = {
|
|
16379
|
-
id:
|
|
16767
|
+
id: uuidv413(),
|
|
16380
16768
|
role: "assistant",
|
|
16381
16769
|
content: "---\n\n**Background Agent Results:**\n\n" + result.finalAnswer,
|
|
16382
16770
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -16435,13 +16823,13 @@ ${contextResult.mergedContent}` : "";
|
|
|
16435
16823
|
isError = true;
|
|
16436
16824
|
}
|
|
16437
16825
|
const userMessage = {
|
|
16438
|
-
id:
|
|
16826
|
+
id: uuidv413(),
|
|
16439
16827
|
role: "user",
|
|
16440
16828
|
content: `$ ${command}`,
|
|
16441
16829
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
16442
16830
|
};
|
|
16443
16831
|
const assistantMessage = {
|
|
16444
|
-
id:
|
|
16832
|
+
id: uuidv413(),
|
|
16445
16833
|
role: "assistant",
|
|
16446
16834
|
content: isError ? `\u274C Error:
|
|
16447
16835
|
${output}` : output.trim() || "(no output)",
|
|
@@ -16910,7 +17298,7 @@ Keyboard Shortcuts:
|
|
|
16910
17298
|
console.clear();
|
|
16911
17299
|
const model = state.session?.model || state.config?.defaultModel || "claude-sonnet";
|
|
16912
17300
|
const newSession = {
|
|
16913
|
-
id:
|
|
17301
|
+
id: uuidv413(),
|
|
16914
17302
|
name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
|
|
16915
17303
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16916
17304
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -17405,9 +17793,9 @@ No usage data available for the last ${USAGE_DAYS} days.`);
|
|
|
17405
17793
|
return { ...prev, config: updatedConfig };
|
|
17406
17794
|
});
|
|
17407
17795
|
if (modelChanged && state.agent) {
|
|
17408
|
-
const
|
|
17409
|
-
if (
|
|
17410
|
-
|
|
17796
|
+
const backend = state.agent.context.llm;
|
|
17797
|
+
if (backend) {
|
|
17798
|
+
backend.currentModel = updatedConfig.defaultModel;
|
|
17411
17799
|
}
|
|
17412
17800
|
}
|
|
17413
17801
|
};
|
|
@@ -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-QQL3OBKL.js";
|
|
6
|
+
import "./chunk-TY6Z2UV2.js";
|
|
7
|
+
import "./chunk-KPOK6V6E.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
findMostSimilarMemento,
|
|
@@ -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,
|
|
@@ -340,7 +346,7 @@ import {
|
|
|
340
346
|
validateReactArtifactV2,
|
|
341
347
|
validateSvgArtifactV2,
|
|
342
348
|
wikiMarkupToAdf
|
|
343
|
-
} from "./chunk-
|
|
349
|
+
} from "./chunk-KPOK6V6E.js";
|
|
344
350
|
export {
|
|
345
351
|
ALL_IMAGE_MODELS,
|
|
346
352
|
ALL_IMAGE_SIZES,
|
|
@@ -384,6 +390,12 @@ export {
|
|
|
384
390
|
ChatModels,
|
|
385
391
|
CitableSourceSchema,
|
|
386
392
|
ClaudeArtifactMimeTypes,
|
|
393
|
+
CliCompletionChunkAction,
|
|
394
|
+
CliCompletionDoneAction,
|
|
395
|
+
CliCompletionErrorAction,
|
|
396
|
+
CliCompletionRequestAction,
|
|
397
|
+
CliToolRequestAction,
|
|
398
|
+
CliToolResponseAction,
|
|
387
399
|
CollectionType,
|
|
388
400
|
CompletionApiUsageTransaction,
|
|
389
401
|
CompletionRequestSchema,
|
|
@@ -134,8 +134,8 @@ import {
|
|
|
134
134
|
validateMermaidSyntax,
|
|
135
135
|
warmUpSettingsCache,
|
|
136
136
|
withRetry
|
|
137
|
-
} from "./chunk-
|
|
138
|
-
import "./chunk-
|
|
137
|
+
} from "./chunk-TY6Z2UV2.js";
|
|
138
|
+
import "./chunk-KPOK6V6E.js";
|
|
139
139
|
import {
|
|
140
140
|
Logger,
|
|
141
141
|
NotificationDeduplicator,
|
|
@@ -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-BXCARBUQ.js";
|
|
6
|
+
import "./chunk-TY6Z2UV2.js";
|
|
7
|
+
import "./chunk-KPOK6V6E.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.29-feat-
|
|
3
|
+
"version": "0.2.29-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -110,10 +110,10 @@
|
|
|
110
110
|
},
|
|
111
111
|
"devDependencies": {
|
|
112
112
|
"@bike4mind/agents": "0.1.0",
|
|
113
|
-
"@bike4mind/common": "2.50.1-feat-
|
|
114
|
-
"@bike4mind/mcp": "1.29.1-feat-
|
|
115
|
-
"@bike4mind/services": "2.48.1-feat-
|
|
116
|
-
"@bike4mind/utils": "2.5.1-feat-
|
|
113
|
+
"@bike4mind/common": "2.50.1-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
114
|
+
"@bike4mind/mcp": "1.29.1-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
115
|
+
"@bike4mind/services": "2.48.1-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
116
|
+
"@bike4mind/utils": "2.5.1-feat-cli-websocket-streaming.18842+8ba59c222",
|
|
117
117
|
"@types/better-sqlite3": "^7.6.13",
|
|
118
118
|
"@types/diff": "^5.0.9",
|
|
119
119
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -130,5 +130,5 @@
|
|
|
130
130
|
"optionalDependencies": {
|
|
131
131
|
"@vscode/ripgrep": "^1.17.0"
|
|
132
132
|
},
|
|
133
|
-
"gitHead": "
|
|
133
|
+
"gitHead": "8ba59c22293ec8857baaba3c7c6d96db1fbb4b15"
|
|
134
134
|
}
|