@bike4mind/cli 0.2.30-fix-client-no-case-declarations.19216 → 0.2.30-fix-cli-ws-review-feedback.19211

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-C3K7SH2V.js";
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,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BadRequestError,
4
4
  secureParameters
5
- } from "./chunk-5HA4JEOV.js";
5
+ } from "./chunk-PIJR5GZP.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-C3K7SH2V.js";
15
+ } from "./chunk-55ZDRTGQ.js";
16
16
 
17
17
  // ../../b4m-core/packages/services/dist/src/creditService/subtractCredits.js
18
18
  import { z } from "zod";
@@ -6,12 +6,12 @@ import {
6
6
  getSettingsByNames,
7
7
  obfuscateApiKey,
8
8
  secureParameters
9
- } from "./chunk-5HA4JEOV.js";
9
+ } from "./chunk-PIJR5GZP.js";
10
10
  import {
11
11
  ApiKeyType,
12
12
  MementoTier,
13
13
  isSupportedEmbeddingModel
14
- } from "./chunk-C3K7SH2V.js";
14
+ } from "./chunk-55ZDRTGQ.js";
15
15
 
16
16
  // ../../b4m-core/packages/services/dist/src/apiKeyService/get.js
17
17
  import { z } from "zod";
@@ -7,11 +7,11 @@ import {
7
7
  getSettingsMap,
8
8
  getSettingsValue,
9
9
  secureParameters
10
- } from "./chunk-5HA4JEOV.js";
10
+ } from "./chunk-PIJR5GZP.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
14
- } from "./chunk-C3K7SH2V.js";
14
+ } from "./chunk-55ZDRTGQ.js";
15
15
 
16
16
  // ../../b4m-core/packages/services/dist/src/fabFileService/create.js
17
17
  import { z } from "zod";
@@ -16,7 +16,7 @@ import {
16
16
  dayjsConfig_default,
17
17
  extractSnippetMeta,
18
18
  settingsMap
19
- } from "./chunk-C3K7SH2V.js";
19
+ } from "./chunk-55ZDRTGQ.js";
20
20
  import {
21
21
  Logger
22
22
  } from "./chunk-OCYRD7D6.js";
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  createFabFile,
4
4
  createFabFileSchema
5
- } from "./chunk-B7Z2QQMD.js";
6
- import "./chunk-5HA4JEOV.js";
7
- import "./chunk-C3K7SH2V.js";
5
+ } from "./chunk-PD5RFLGO.js";
6
+ import "./chunk-PIJR5GZP.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-65DLNQY2.js";
8
+ } from "./chunk-NRQSEF3E.js";
9
9
  import "./chunk-RUI6HNLO.js";
10
10
  import {
11
11
  ConfigStore,
@@ -15,8 +15,8 @@ import {
15
15
  selectActiveBackgroundAgents,
16
16
  useCliStore
17
17
  } from "./chunk-TVW4ZESU.js";
18
- import "./chunk-BYLWQZ5S.js";
19
- import "./chunk-B7Z2QQMD.js";
18
+ import "./chunk-EAFOBAEJ.js";
19
+ import "./chunk-PD5RFLGO.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-5HA4JEOV.js";
31
+ } from "./chunk-PIJR5GZP.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-C3K7SH2V.js";
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 uuidv411 } from "uuid";
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";
@@ -12481,6 +12481,10 @@ var ServerToolExecutor = class {
12481
12481
  };
12482
12482
 
12483
12483
  // src/llm/ToolRouter.ts
12484
+ var wsToolExecutor = null;
12485
+ function setWebSocketToolExecutor(executor) {
12486
+ wsToolExecutor = executor;
12487
+ }
12484
12488
  var SERVER_TOOLS = ["weather_info", "web_search", "web_fetch"];
12485
12489
  var LOCAL_TOOLS = [
12486
12490
  "file_read",
@@ -12503,7 +12507,15 @@ function isLocalTool(toolName) {
12503
12507
  }
12504
12508
  async function executeTool(toolName, input, apiClient, localToolFn) {
12505
12509
  if (isServerTool(toolName)) {
12506
- logger.debug(`[ToolRouter] Routing ${toolName} to server`);
12510
+ if (wsToolExecutor) {
12511
+ logger.debug(`[ToolRouter] Routing ${toolName} to server via WebSocket`);
12512
+ const result = await wsToolExecutor.execute(toolName, input);
12513
+ if (!result.success) {
12514
+ return `Error executing ${toolName}: ${result.error || "Tool execution failed"}`;
12515
+ }
12516
+ return typeof result.content === "string" ? result.content : JSON.stringify(result.content ?? "");
12517
+ }
12518
+ logger.debug(`[ToolRouter] Routing ${toolName} to server via HTTP`);
12507
12519
  const executor = new ServerToolExecutor(apiClient);
12508
12520
  return await executor.executeTool(toolName, input);
12509
12521
  } else if (isLocalTool(toolName)) {
@@ -14465,6 +14477,171 @@ var ServerLlmBackend = class {
14465
14477
  }
14466
14478
  };
14467
14479
 
14480
+ // src/llm/WebSocketLlmBackend.ts
14481
+ import { v4 as uuidv411 } from "uuid";
14482
+ function stripThinkingBlocks2(text) {
14483
+ return text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
14484
+ }
14485
+ var WebSocketLlmBackend = class {
14486
+ constructor(options) {
14487
+ this.wsManager = options.wsManager;
14488
+ this.apiClient = options.apiClient;
14489
+ this.currentModel = options.model;
14490
+ this.tokenGetter = options.tokenGetter;
14491
+ this.wsCompletionUrl = options.wsCompletionUrl;
14492
+ }
14493
+ /**
14494
+ * Send completion request via HTTP POST, receive streaming response via WebSocket.
14495
+ * Collects all streamed chunks, then calls callback once at completion
14496
+ * with the full accumulated content.
14497
+ */
14498
+ async complete(model, messages, options, callback) {
14499
+ logger.debug(`[WebSocketLlmBackend] Starting complete() with model: ${model}`);
14500
+ if (options.abortSignal?.aborted) {
14501
+ logger.debug("[WebSocketLlmBackend] Request aborted before start");
14502
+ return;
14503
+ }
14504
+ if (!this.wsManager.isConnected) {
14505
+ throw new Error("WebSocket is not connected");
14506
+ }
14507
+ const requestId = uuidv411();
14508
+ return new Promise((resolve3, reject) => {
14509
+ const isVerbose = process.env.B4M_VERBOSE === "1";
14510
+ const isUltraVerbose = process.env.B4M_DEBUG_STREAM === "1";
14511
+ const streamLogger = new StreamLogger(logger, "WebSocketLlmBackend", isVerbose, isUltraVerbose);
14512
+ streamLogger.streamStart();
14513
+ let eventCount = 0;
14514
+ let accumulatedText = "";
14515
+ let lastUsageInfo = {};
14516
+ let toolsUsed = [];
14517
+ let thinkingBlocks = [];
14518
+ let settled = false;
14519
+ const settle = (action) => {
14520
+ if (settled) return;
14521
+ settled = true;
14522
+ this.wsManager.offRequest(requestId);
14523
+ this.wsManager.offDisconnect(onDisconnect);
14524
+ options.abortSignal?.removeEventListener("abort", abortHandler);
14525
+ action();
14526
+ };
14527
+ const settleResolve = () => settle(() => resolve3());
14528
+ const settleReject = (err) => settle(() => reject(err));
14529
+ const onDisconnect = () => {
14530
+ logger.debug("[WebSocketLlmBackend] Connection dropped during completion");
14531
+ settleReject(new Error("WebSocket connection lost during completion"));
14532
+ };
14533
+ this.wsManager.onDisconnect(onDisconnect);
14534
+ const abortHandler = () => {
14535
+ logger.debug("[WebSocketLlmBackend] Abort signal received");
14536
+ settleResolve();
14537
+ };
14538
+ if (options.abortSignal) {
14539
+ if (options.abortSignal.aborted) {
14540
+ settleResolve();
14541
+ return;
14542
+ }
14543
+ options.abortSignal.addEventListener("abort", abortHandler, { once: true });
14544
+ }
14545
+ const updateUsage = (usage) => {
14546
+ if (usage) {
14547
+ lastUsageInfo = { inputTokens: usage.inputTokens, outputTokens: usage.outputTokens };
14548
+ }
14549
+ };
14550
+ this.wsManager.onRequest(requestId, (message) => {
14551
+ if (options.abortSignal?.aborted) return;
14552
+ const action = message.action;
14553
+ if (action === "cli_completion_chunk") {
14554
+ eventCount++;
14555
+ const chunk = message.chunk;
14556
+ streamLogger.onEvent(eventCount, JSON.stringify(chunk));
14557
+ const textChunk = chunk.text || "";
14558
+ if (textChunk) accumulatedText += textChunk;
14559
+ updateUsage(chunk.usage);
14560
+ if (chunk.type === "content") {
14561
+ streamLogger.onContent(eventCount, textChunk, accumulatedText);
14562
+ } else if (chunk.type === "tool_use") {
14563
+ streamLogger.onCriticalEvent(eventCount, "TOOL_USE", `tools: ${chunk.tools?.length}`);
14564
+ if (chunk.tools && chunk.tools.length > 0) toolsUsed = chunk.tools;
14565
+ if (chunk.thinking && chunk.thinking.length > 0) thinkingBlocks = chunk.thinking;
14566
+ }
14567
+ } else if (action === "cli_completion_done") {
14568
+ streamLogger.streamComplete(accumulatedText);
14569
+ const cleanedText = stripThinkingBlocks2(accumulatedText);
14570
+ if (!cleanedText && toolsUsed.length === 0) {
14571
+ settleResolve();
14572
+ return;
14573
+ }
14574
+ const info = {
14575
+ ...lastUsageInfo,
14576
+ ...toolsUsed.length > 0 && { toolsUsed },
14577
+ ...thinkingBlocks.length > 0 && { thinking: thinkingBlocks }
14578
+ };
14579
+ callback([cleanedText], info).then(() => settleResolve()).catch((err) => settleReject(err));
14580
+ } else if (action === "cli_completion_error") {
14581
+ const errorMsg = message.error || "Server error";
14582
+ streamLogger.onCriticalEvent(eventCount, "ERROR", errorMsg);
14583
+ settleReject(new Error(errorMsg));
14584
+ }
14585
+ });
14586
+ const axiosInstance = this.apiClient.getAxiosInstance();
14587
+ axiosInstance.post(
14588
+ this.wsCompletionUrl,
14589
+ {
14590
+ requestId,
14591
+ model,
14592
+ messages,
14593
+ options: {
14594
+ temperature: options.temperature,
14595
+ maxTokens: options.maxTokens,
14596
+ stream: true,
14597
+ tools: options.tools || []
14598
+ }
14599
+ },
14600
+ { signal: options.abortSignal }
14601
+ ).catch((err) => {
14602
+ const msg = err instanceof Error ? err.message : String(err);
14603
+ settleReject(new Error(`HTTP request failed: ${msg}`));
14604
+ });
14605
+ });
14606
+ }
14607
+ /**
14608
+ * Get available models from server (REST call, not streaming).
14609
+ * Delegates to ApiClient -- same as ServerLlmBackend.
14610
+ */
14611
+ async getModelInfo() {
14612
+ try {
14613
+ logger.debug("[WebSocketLlmBackend] Fetching models from /api/models");
14614
+ const response = await this.apiClient.get("/api/models");
14615
+ if (!response || typeof response !== "object" || !Array.isArray(response.models)) {
14616
+ logger.warn("[WebSocketLlmBackend] Invalid API response format, using fallback models");
14617
+ return this.getFallbackModels();
14618
+ }
14619
+ const filteredModels = response.models.filter(
14620
+ (model) => model.type === "text" && model.supportsTools === true
14621
+ );
14622
+ if (filteredModels.length === 0) {
14623
+ logger.warn("[WebSocketLlmBackend] No CLI-compatible models found, using fallback");
14624
+ return this.getFallbackModels();
14625
+ }
14626
+ logger.debug(`[WebSocketLlmBackend] Loaded ${filteredModels.length} models`);
14627
+ return filteredModels;
14628
+ } catch (error) {
14629
+ logger.warn(
14630
+ `[WebSocketLlmBackend] Failed to fetch models: ${error instanceof Error ? error.message : String(error)}`
14631
+ );
14632
+ return this.getFallbackModels();
14633
+ }
14634
+ }
14635
+ getFallbackModels() {
14636
+ return [
14637
+ { id: "claude-sonnet-4-5-20250929", name: "Claude 4.5 Sonnet" },
14638
+ { id: "claude-3-5-haiku-20241022", name: "Claude 3.5 Haiku" },
14639
+ { id: "gpt-4o", name: "GPT-4o" },
14640
+ { id: "gpt-4o-mini", name: "GPT-4o Mini" }
14641
+ ];
14642
+ }
14643
+ };
14644
+
14468
14645
  // src/llm/NotifyingLlmBackend.ts
14469
14646
  var NotifyingLlmBackend = class {
14470
14647
  constructor(inner, backgroundManager) {
@@ -14499,6 +14676,261 @@ Please acknowledge these background agent results and incorporate them into your
14499
14676
  }
14500
14677
  };
14501
14678
 
14679
+ // src/ws/WebSocketConnectionManager.ts
14680
+ var WebSocketConnectionManager = class {
14681
+ constructor(wsUrl, getToken) {
14682
+ this.ws = null;
14683
+ this.heartbeatInterval = null;
14684
+ this.reconnectAttempts = 0;
14685
+ this.maxReconnectDelay = 3e4;
14686
+ this.handlers = /* @__PURE__ */ new Map();
14687
+ this.disconnectHandlers = /* @__PURE__ */ new Set();
14688
+ this.reconnectTimer = null;
14689
+ this.connected = false;
14690
+ this.connecting = false;
14691
+ this.closed = false;
14692
+ this.wsUrl = wsUrl;
14693
+ this.getToken = getToken;
14694
+ }
14695
+ /**
14696
+ * Connect to the WebSocket server.
14697
+ * Resolves when connection is established, rejects on failure.
14698
+ */
14699
+ async connect() {
14700
+ if (this.connected || this.connecting) return;
14701
+ this.connecting = true;
14702
+ const token = await this.getToken();
14703
+ if (!token) {
14704
+ this.connecting = false;
14705
+ throw new Error("No access token available for WebSocket connection");
14706
+ }
14707
+ return new Promise((resolve3, reject) => {
14708
+ logger.debug(`[WS] Connecting to ${this.wsUrl}...`);
14709
+ this.ws = new WebSocket(this.wsUrl, [`access_token.${token}`]);
14710
+ this.ws.onopen = () => {
14711
+ logger.debug("[WS] Connected");
14712
+ this.connected = true;
14713
+ this.connecting = false;
14714
+ this.reconnectAttempts = 0;
14715
+ this.startHeartbeat();
14716
+ resolve3();
14717
+ };
14718
+ this.ws.onmessage = (event) => {
14719
+ try {
14720
+ const data = typeof event.data === "string" ? event.data : event.data.toString();
14721
+ const message = JSON.parse(data);
14722
+ const requestId = message.requestId;
14723
+ if (requestId && this.handlers.has(requestId)) {
14724
+ this.handlers.get(requestId)(message);
14725
+ } else {
14726
+ logger.debug(`[WS] Unhandled message: ${message.action || "unknown"}`);
14727
+ }
14728
+ } catch (err) {
14729
+ logger.debug(`[WS] Failed to parse message: ${err}`);
14730
+ }
14731
+ };
14732
+ this.ws.onclose = () => {
14733
+ logger.debug("[WS] Connection closed");
14734
+ this.cleanup();
14735
+ this.notifyDisconnect();
14736
+ if (!this.closed) {
14737
+ this.scheduleReconnect();
14738
+ }
14739
+ };
14740
+ this.ws.onerror = (err) => {
14741
+ logger.debug(`[WS] Error: ${err}`);
14742
+ if (this.connecting) {
14743
+ this.connecting = false;
14744
+ this.connected = false;
14745
+ reject(new Error("WebSocket connection failed"));
14746
+ }
14747
+ };
14748
+ });
14749
+ }
14750
+ /** Whether the connection is currently established */
14751
+ get isConnected() {
14752
+ return this.connected;
14753
+ }
14754
+ /**
14755
+ * Send a JSON message over the WebSocket connection.
14756
+ */
14757
+ send(data) {
14758
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
14759
+ throw new Error("WebSocket is not connected");
14760
+ }
14761
+ const payload = JSON.stringify(data);
14762
+ const sizeKB = (payload.length / 1024).toFixed(1);
14763
+ logger.debug(`[WS] Sending ${sizeKB} KB (action: ${data.action})`);
14764
+ if (payload.length > 32e3) {
14765
+ logger.warn(`[WS] Payload ${sizeKB} KB exceeds API Gateway 32 KB frame limit \u2014 connection will be closed`);
14766
+ }
14767
+ this.ws.send(payload);
14768
+ }
14769
+ /**
14770
+ * Register a handler for messages matching a specific requestId.
14771
+ */
14772
+ onRequest(requestId, handler) {
14773
+ this.handlers.set(requestId, handler);
14774
+ }
14775
+ /**
14776
+ * Remove a handler for a specific requestId.
14777
+ */
14778
+ offRequest(requestId) {
14779
+ this.handlers.delete(requestId);
14780
+ }
14781
+ /**
14782
+ * Register a handler that fires when the connection drops.
14783
+ */
14784
+ onDisconnect(handler) {
14785
+ this.disconnectHandlers.add(handler);
14786
+ }
14787
+ /**
14788
+ * Remove a disconnect handler.
14789
+ */
14790
+ offDisconnect(handler) {
14791
+ this.disconnectHandlers.delete(handler);
14792
+ }
14793
+ /**
14794
+ * Close the connection and stop all heartbeat/reconnect logic.
14795
+ */
14796
+ disconnect() {
14797
+ this.closed = true;
14798
+ this.cleanup();
14799
+ if (this.ws) {
14800
+ this.ws.close();
14801
+ this.ws = null;
14802
+ }
14803
+ this.handlers.clear();
14804
+ this.disconnectHandlers.clear();
14805
+ }
14806
+ startHeartbeat() {
14807
+ this.stopHeartbeat();
14808
+ this.heartbeatInterval = setInterval(
14809
+ () => {
14810
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
14811
+ this.ws.send(JSON.stringify({ action: "heartbeat" }));
14812
+ logger.debug("[WS] Heartbeat sent");
14813
+ }
14814
+ },
14815
+ 5 * 60 * 1e3
14816
+ );
14817
+ }
14818
+ stopHeartbeat() {
14819
+ if (this.heartbeatInterval) {
14820
+ clearInterval(this.heartbeatInterval);
14821
+ this.heartbeatInterval = null;
14822
+ }
14823
+ }
14824
+ cleanup() {
14825
+ this.connected = false;
14826
+ this.connecting = false;
14827
+ this.stopHeartbeat();
14828
+ if (this.reconnectTimer) {
14829
+ clearTimeout(this.reconnectTimer);
14830
+ this.reconnectTimer = null;
14831
+ }
14832
+ }
14833
+ notifyDisconnect() {
14834
+ for (const handler of this.disconnectHandlers) {
14835
+ try {
14836
+ handler();
14837
+ } catch {
14838
+ }
14839
+ }
14840
+ }
14841
+ scheduleReconnect() {
14842
+ if (this.closed) return;
14843
+ this.reconnectAttempts++;
14844
+ const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts - 1), this.maxReconnectDelay);
14845
+ logger.debug(`[WS] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
14846
+ this.reconnectTimer = setTimeout(async () => {
14847
+ this.reconnectTimer = null;
14848
+ if (this.closed) return;
14849
+ try {
14850
+ await this.connect();
14851
+ } catch {
14852
+ logger.debug("[WS] Reconnection failed");
14853
+ }
14854
+ }, delay);
14855
+ }
14856
+ };
14857
+
14858
+ // src/ws/WebSocketToolExecutor.ts
14859
+ import { v4 as uuidv412 } from "uuid";
14860
+ var WebSocketToolExecutor = class {
14861
+ constructor(wsManager, tokenGetter) {
14862
+ this.wsManager = wsManager;
14863
+ this.tokenGetter = tokenGetter;
14864
+ }
14865
+ /**
14866
+ * Execute a server-side tool via WebSocket.
14867
+ * Returns the tool result or throws on error.
14868
+ */
14869
+ async execute(toolName, input, abortSignal) {
14870
+ if (!this.wsManager.isConnected) {
14871
+ throw new Error("WebSocket is not connected");
14872
+ }
14873
+ const token = await this.tokenGetter();
14874
+ if (!token) {
14875
+ throw new Error("No access token available");
14876
+ }
14877
+ const requestId = uuidv412();
14878
+ return new Promise((resolve3, reject) => {
14879
+ let settled = false;
14880
+ let timeoutTimer;
14881
+ const settle = (action) => {
14882
+ if (settled) return;
14883
+ settled = true;
14884
+ clearTimeout(timeoutTimer);
14885
+ this.wsManager.offRequest(requestId);
14886
+ this.wsManager.offDisconnect(onDisconnect);
14887
+ abortSignal?.removeEventListener("abort", abortHandler);
14888
+ action();
14889
+ };
14890
+ const settleResolve = (result) => settle(() => resolve3(result));
14891
+ const settleReject = (err) => settle(() => reject(err));
14892
+ const TOOL_TIMEOUT_MS = 5 * 60 * 1e3;
14893
+ timeoutTimer = setTimeout(() => {
14894
+ settleReject(new Error(`Tool execution timed out after ${TOOL_TIMEOUT_MS / 1e3}s`));
14895
+ }, TOOL_TIMEOUT_MS);
14896
+ const onDisconnect = () => {
14897
+ settleReject(new Error("WebSocket connection lost during tool execution"));
14898
+ };
14899
+ this.wsManager.onDisconnect(onDisconnect);
14900
+ const abortHandler = () => {
14901
+ settleReject(new Error("Tool execution aborted"));
14902
+ };
14903
+ if (abortSignal) {
14904
+ if (abortSignal.aborted) {
14905
+ settleReject(new Error("Tool execution aborted"));
14906
+ return;
14907
+ }
14908
+ abortSignal.addEventListener("abort", abortHandler, { once: true });
14909
+ }
14910
+ this.wsManager.onRequest(requestId, (message) => {
14911
+ if (message.action === "cli_tool_response") {
14912
+ settleResolve({
14913
+ success: message.success,
14914
+ content: message.content,
14915
+ error: message.error
14916
+ });
14917
+ }
14918
+ });
14919
+ try {
14920
+ this.wsManager.send({
14921
+ action: "cli_tool_request",
14922
+ accessToken: token,
14923
+ requestId,
14924
+ toolName,
14925
+ input
14926
+ });
14927
+ } catch (err) {
14928
+ settleReject(err instanceof Error ? err : new Error(String(err)));
14929
+ }
14930
+ });
14931
+ }
14932
+ };
14933
+
14502
14934
  // src/auth/ApiClient.ts
14503
14935
  import axios11 from "axios";
14504
14936
  var ApiClient = class {
@@ -14636,7 +15068,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
14636
15068
  // package.json
14637
15069
  var package_default = {
14638
15070
  name: "@bike4mind/cli",
14639
- version: "0.2.30-fix-client-no-case-declarations.19216+dd3ad798a",
15071
+ version: "0.2.30-fix-cli-ws-review-feedback.19211+642a3d3ee",
14640
15072
  type: "module",
14641
15073
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
14642
15074
  license: "UNLICENSED",
@@ -14747,10 +15179,10 @@ var package_default = {
14747
15179
  },
14748
15180
  devDependencies: {
14749
15181
  "@bike4mind/agents": "0.1.0",
14750
- "@bike4mind/common": "2.51.1-fix-client-no-case-declarations.19216+dd3ad798a",
14751
- "@bike4mind/mcp": "1.30.1-fix-client-no-case-declarations.19216+dd3ad798a",
14752
- "@bike4mind/services": "2.49.1-fix-client-no-case-declarations.19216+dd3ad798a",
14753
- "@bike4mind/utils": "2.6.1-fix-client-no-case-declarations.19216+dd3ad798a",
15182
+ "@bike4mind/common": "2.51.1-fix-cli-ws-review-feedback.19211+642a3d3ee",
15183
+ "@bike4mind/mcp": "1.30.1-fix-cli-ws-review-feedback.19211+642a3d3ee",
15184
+ "@bike4mind/services": "2.49.1-fix-cli-ws-review-feedback.19211+642a3d3ee",
15185
+ "@bike4mind/utils": "2.6.1-fix-cli-ws-review-feedback.19211+642a3d3ee",
14754
15186
  "@types/better-sqlite3": "^7.6.13",
14755
15187
  "@types/diff": "^5.0.9",
14756
15188
  "@types/jsonwebtoken": "^9.0.4",
@@ -14771,7 +15203,7 @@ var package_default = {
14771
15203
  optionalDependencies: {
14772
15204
  "@vscode/ripgrep": "^1.17.0"
14773
15205
  },
14774
- gitHead: "dd3ad798a81116729325cd878892e97d01a16ef4"
15206
+ gitHead: "642a3d3eed04f176711a88a1fb38e30a25d24148"
14775
15207
  };
14776
15208
 
14777
15209
  // src/config/constants.ts
@@ -16550,7 +16982,8 @@ function CliApp() {
16550
16982
  agentStore: null,
16551
16983
  abortController: null,
16552
16984
  contextContent: "",
16553
- backgroundManager: null
16985
+ backgroundManager: null,
16986
+ wsManager: null
16554
16987
  });
16555
16988
  const [isInitialized, setIsInitialized] = useState10(false);
16556
16989
  const [initError, setInitError] = useState10(null);
@@ -16578,6 +17011,10 @@ function CliApp() {
16578
17011
  })
16579
17012
  );
16580
17013
  }
17014
+ if (state.wsManager) {
17015
+ state.wsManager.disconnect();
17016
+ setWebSocketToolExecutor(null);
17017
+ }
16581
17018
  if (state.agent) {
16582
17019
  state.agent.removeAllListeners();
16583
17020
  }
@@ -16596,7 +17033,7 @@ function CliApp() {
16596
17033
  setTimeout(() => {
16597
17034
  process.exit(0);
16598
17035
  }, 100);
16599
- }, [state.session, state.sessionStore, state.mcpManager, state.agent, state.imageStore]);
17036
+ }, [state.session, state.sessionStore, state.mcpManager, state.agent, state.imageStore, state.wsManager]);
16600
17037
  useInput9((input, key) => {
16601
17038
  if (key.escape) {
16602
17039
  if (state.abortController) {
@@ -16666,7 +17103,7 @@ function CliApp() {
16666
17103
  if (!isAuthenticated) {
16667
17104
  console.log("\u2139\uFE0F AI features disabled. Available commands: /login, /help, /config\n");
16668
17105
  const minimalSession = {
16669
- id: uuidv411(),
17106
+ id: uuidv413(),
16670
17107
  name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
16671
17108
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
16672
17109
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -16694,10 +17131,45 @@ function CliApp() {
16694
17131
  console.log(`\u{1F30D} API Environment: ${envName} (${apiBaseURL})`);
16695
17132
  }
16696
17133
  const apiClient = new ApiClient(apiBaseURL, state.configStore);
16697
- const llm = new ServerLlmBackend({
16698
- apiClient,
16699
- model: config.defaultModel
16700
- });
17134
+ const tokenGetter = async () => {
17135
+ const tokens = await state.configStore.getAuthTokens();
17136
+ return tokens?.accessToken ?? null;
17137
+ };
17138
+ let wsManager = null;
17139
+ let llm;
17140
+ try {
17141
+ const serverConfig = await apiClient.get(
17142
+ "/api/settings/serverConfig"
17143
+ );
17144
+ const wsUrl = serverConfig?.websocketUrl;
17145
+ const wsCompletionUrl = serverConfig?.wsCompletionUrl;
17146
+ if (wsUrl && wsCompletionUrl) {
17147
+ wsManager = new WebSocketConnectionManager(wsUrl, tokenGetter);
17148
+ await wsManager.connect();
17149
+ const wsToolExecutor2 = new WebSocketToolExecutor(wsManager, tokenGetter);
17150
+ setWebSocketToolExecutor(wsToolExecutor2);
17151
+ llm = new WebSocketLlmBackend({
17152
+ wsManager,
17153
+ apiClient,
17154
+ model: config.defaultModel,
17155
+ tokenGetter,
17156
+ wsCompletionUrl
17157
+ });
17158
+ logger.debug("\u{1F50C} Using WebSocket transport (bypasses CloudFront timeout)");
17159
+ } else {
17160
+ throw new Error("No websocketUrl or wsCompletionUrl in server config");
17161
+ }
17162
+ } catch (wsError) {
17163
+ logger.debug(
17164
+ `[WS] WebSocket unavailable, using SSE fallback: ${wsError instanceof Error ? wsError.message : String(wsError)}`
17165
+ );
17166
+ wsManager = null;
17167
+ setWebSocketToolExecutor(null);
17168
+ llm = new ServerLlmBackend({
17169
+ apiClient,
17170
+ model: config.defaultModel
17171
+ });
17172
+ }
16701
17173
  const models = await llm.getModelInfo();
16702
17174
  if (models.length === 0) {
16703
17175
  throw new Error("No models available from server.");
@@ -16710,7 +17182,7 @@ function CliApp() {
16710
17182
  }
16711
17183
  llm.currentModel = modelInfo.id;
16712
17184
  const newSession = {
16713
- id: uuidv411(),
17185
+ id: uuidv413(),
16714
17186
  name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
16715
17187
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
16716
17188
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -16924,8 +17396,10 @@ function CliApp() {
16924
17396
  // Store agent store for agent management commands
16925
17397
  contextContent: contextResult.mergedContent,
16926
17398
  // Store raw context for compact instructions
16927
- backgroundManager
17399
+ backgroundManager,
16928
17400
  // Store for grouped notification turn tracking
17401
+ wsManager
17402
+ // WebSocket connection manager (null if using SSE fallback)
16929
17403
  }));
16930
17404
  setStoreSession(newSession);
16931
17405
  const bannerLines = [
@@ -17020,13 +17494,13 @@ function CliApp() {
17020
17494
  messageContent = multimodalMessage.content;
17021
17495
  }
17022
17496
  const userMessage = {
17023
- id: uuidv411(),
17497
+ id: uuidv413(),
17024
17498
  role: "user",
17025
17499
  content: userMessageContent,
17026
17500
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
17027
17501
  };
17028
17502
  const pendingAssistantMessage = {
17029
- id: uuidv411(),
17503
+ id: uuidv413(),
17030
17504
  role: "assistant",
17031
17505
  content: "...",
17032
17506
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -17239,13 +17713,13 @@ function CliApp() {
17239
17713
  userMessageContent = message;
17240
17714
  }
17241
17715
  const userMessage = {
17242
- id: uuidv411(),
17716
+ id: uuidv413(),
17243
17717
  role: "user",
17244
17718
  content: userMessageContent,
17245
17719
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
17246
17720
  };
17247
17721
  const pendingAssistantMessage = {
17248
- id: uuidv411(),
17722
+ id: uuidv413(),
17249
17723
  role: "assistant",
17250
17724
  content: "...",
17251
17725
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -17325,7 +17799,7 @@ function CliApp() {
17325
17799
  const currentSession = useCliStore.getState().session;
17326
17800
  if (currentSession) {
17327
17801
  const cancelMessage = {
17328
- id: uuidv411(),
17802
+ id: uuidv413(),
17329
17803
  role: "assistant",
17330
17804
  content: "\u26A0\uFE0F Operation cancelled by user",
17331
17805
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -17370,7 +17844,7 @@ function CliApp() {
17370
17844
  setState((prev) => ({ ...prev, abortController }));
17371
17845
  try {
17372
17846
  const pendingAssistantMessage = {
17373
- id: uuidv411(),
17847
+ id: uuidv413(),
17374
17848
  role: "assistant",
17375
17849
  content: "...",
17376
17850
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -17398,7 +17872,7 @@ function CliApp() {
17398
17872
  const currentSession = useCliStore.getState().session;
17399
17873
  if (!currentSession) return;
17400
17874
  const continuationMessage = {
17401
- id: uuidv411(),
17875
+ id: uuidv413(),
17402
17876
  role: "assistant",
17403
17877
  content: "---\n\n**Background Agent Results:**\n\n" + result.finalAnswer,
17404
17878
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -17459,13 +17933,13 @@ function CliApp() {
17459
17933
  isError = true;
17460
17934
  }
17461
17935
  const userMessage = {
17462
- id: uuidv411(),
17936
+ id: uuidv413(),
17463
17937
  role: "user",
17464
17938
  content: `$ ${command}`,
17465
17939
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
17466
17940
  };
17467
17941
  const assistantMessage = {
17468
- id: uuidv411(),
17942
+ id: uuidv413(),
17469
17943
  role: "assistant",
17470
17944
  content: isError ? `\u274C Error:
17471
17945
  ${output}` : output.trim() || "(no output)",
@@ -17934,7 +18408,7 @@ Keyboard Shortcuts:
17934
18408
  console.clear();
17935
18409
  const model = state.session?.model || state.config?.defaultModel || "claude-sonnet";
17936
18410
  const newSession = {
17937
- id: uuidv411(),
18411
+ id: uuidv413(),
17938
18412
  name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
17939
18413
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
17940
18414
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -18439,9 +18913,9 @@ No usage data available for the last ${USAGE_DAYS} days.`);
18439
18913
  return { ...prev, config: updatedConfig };
18440
18914
  });
18441
18915
  if (modelChanged && state.agent) {
18442
- const llm = state.agent.context.llm;
18443
- if (llm) {
18444
- llm.currentModel = updatedConfig.defaultModel;
18916
+ const backend = state.agent.context.llm;
18917
+ if (backend) {
18918
+ backend.currentModel = updatedConfig.defaultModel;
18445
18919
  }
18446
18920
  }
18447
18921
  };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-C3K7SH2V.js";
4
+ } from "./chunk-55ZDRTGQ.js";
5
5
 
6
6
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/llmMarkdownGenerator.js
7
7
  var DEFAULT_OPTIONS = {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-C3K7SH2V.js";
4
+ } from "./chunk-55ZDRTGQ.js";
5
5
 
6
6
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/markdownGenerator.js
7
7
  var DEFAULT_OPTIONS = {
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  findMostSimilarMemento,
4
4
  getRelevantMementos
5
- } from "./chunk-65DLNQY2.js";
6
- import "./chunk-5HA4JEOV.js";
7
- import "./chunk-C3K7SH2V.js";
5
+ } from "./chunk-NRQSEF3E.js";
6
+ import "./chunk-PIJR5GZP.js";
7
+ import "./chunk-55ZDRTGQ.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,
@@ -419,7 +425,7 @@ import {
419
425
  validateReactArtifactV2,
420
426
  validateSvgArtifactV2,
421
427
  wikiMarkupToAdf
422
- } from "./chunk-C3K7SH2V.js";
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,
@@ -134,12 +134,12 @@ import {
134
134
  validateMermaidSyntax,
135
135
  warmUpSettingsCache,
136
136
  withRetry
137
- } from "./chunk-5HA4JEOV.js";
137
+ } from "./chunk-PIJR5GZP.js";
138
138
  import {
139
139
  buildRateLimitLogEntry,
140
140
  isNearLimit,
141
141
  parseRateLimitHeaders
142
- } from "./chunk-C3K7SH2V.js";
142
+ } from "./chunk-55ZDRTGQ.js";
143
143
  import {
144
144
  Logger,
145
145
  NotificationDeduplicator,
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  SubtractCreditsSchema,
4
4
  subtractCredits
5
- } from "./chunk-BYLWQZ5S.js";
6
- import "./chunk-5HA4JEOV.js";
7
- import "./chunk-C3K7SH2V.js";
5
+ } from "./chunk-EAFOBAEJ.js";
6
+ import "./chunk-PIJR5GZP.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-fix-client-no-case-declarations.19216+dd3ad798a",
3
+ "version": "0.2.30-fix-cli-ws-review-feedback.19211+642a3d3ee",
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-fix-client-no-case-declarations.19216+dd3ad798a",
115
- "@bike4mind/mcp": "1.30.1-fix-client-no-case-declarations.19216+dd3ad798a",
116
- "@bike4mind/services": "2.49.1-fix-client-no-case-declarations.19216+dd3ad798a",
117
- "@bike4mind/utils": "2.6.1-fix-client-no-case-declarations.19216+dd3ad798a",
114
+ "@bike4mind/common": "2.51.1-fix-cli-ws-review-feedback.19211+642a3d3ee",
115
+ "@bike4mind/mcp": "1.30.1-fix-cli-ws-review-feedback.19211+642a3d3ee",
116
+ "@bike4mind/services": "2.49.1-fix-cli-ws-review-feedback.19211+642a3d3ee",
117
+ "@bike4mind/utils": "2.6.1-fix-cli-ws-review-feedback.19211+642a3d3ee",
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": "dd3ad798a81116729325cd878892e97d01a16ef4"
138
+ "gitHead": "642a3d3eed04f176711a88a1fb38e30a25d24148"
139
139
  }