@bike4mind/cli 0.2.11-fix-tool-pairing-integrity.17312 → 0.2.11-fix-cli-edit-file.17321

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-DJPXSSP4.js";
4
+ } from "./chunk-WCYNJOOX.js";
5
5
  import "./chunk-PDX44BCA.js";
6
6
 
7
7
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/artifactExtractor.js
@@ -6,12 +6,12 @@ import {
6
6
  getSettingsByNames,
7
7
  obfuscateApiKey,
8
8
  secureParameters
9
- } from "./chunk-TFONTTOE.js";
9
+ } from "./chunk-SQBLLN7K.js";
10
10
  import {
11
11
  ApiKeyType,
12
12
  MementoTier,
13
13
  isSupportedEmbeddingModel
14
- } from "./chunk-DJPXSSP4.js";
14
+ } from "./chunk-WCYNJOOX.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-TFONTTOE.js";
10
+ } from "./chunk-SQBLLN7K.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
14
- } from "./chunk-DJPXSSP4.js";
14
+ } from "./chunk-WCYNJOOX.js";
15
15
 
16
16
  // ../../b4m-core/packages/services/dist/src/fabFileService/create.js
17
17
  import { z } from "zod";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BadRequestError,
4
4
  secureParameters
5
- } from "./chunk-TFONTTOE.js";
5
+ } from "./chunk-SQBLLN7K.js";
6
6
  import {
7
7
  GenericCreditDeductTransaction,
8
8
  ImageEditUsageTransaction,
@@ -10,7 +10,7 @@ import {
10
10
  RealtimeVoiceUsageTransaction,
11
11
  TextGenerationUsageTransaction,
12
12
  TransferCreditTransaction
13
- } from "./chunk-DJPXSSP4.js";
13
+ } from "./chunk-WCYNJOOX.js";
14
14
 
15
15
  // ../../b4m-core/packages/services/dist/src/creditService/subtractCredits.js
16
16
  import { z } from "zod";
@@ -16,7 +16,7 @@ import {
16
16
  dayjsConfig_default,
17
17
  extractSnippetMeta,
18
18
  settingsMap
19
- } from "./chunk-DJPXSSP4.js";
19
+ } from "./chunk-WCYNJOOX.js";
20
20
 
21
21
  // ../../b4m-core/packages/utils/dist/src/storage/S3Storage.js
22
22
  import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";
@@ -249,6 +249,17 @@ var AnthropicBackend = class {
249
249
  this._api = new Anthropic({ apiKey });
250
250
  this.logger = logger ?? new Logger();
251
251
  }
252
+ /**
253
+ * Get thinking blocks from the last assistant content.
254
+ * Filters to only include thinking/redacted_thinking blocks.
255
+ * Returns undefined if thinking is disabled or no blocks are present.
256
+ */
257
+ getThinkingBlocks() {
258
+ if (!this.isThinkingEnabled)
259
+ return void 0;
260
+ const blocks = this.lastAssistantContent.filter((block) => block?.type === "thinking" || block?.type === "redacted_thinking");
261
+ return blocks.length > 0 ? blocks : void 0;
262
+ }
252
263
  async getModelInfo() {
253
264
  return [
254
265
  {
@@ -701,8 +712,12 @@ var AnthropicBackend = class {
701
712
  this.logger.debug(`[Tool Execution] Last few messages:`, JSON.stringify(messages.slice(-3), null, 2));
702
713
  await this.complete(model, messages, options, cb, toolsUsed);
703
714
  } else {
704
- this.logger.debug(`[Tool Execution] executeTools=false, passing tool calls to callback`);
705
- await cb([null], { toolsUsed });
715
+ const thinkingBlocks = this.getThinkingBlocks();
716
+ this.logger.debug(`[Tool Execution] executeTools=false, passing tool calls to callback with ${thinkingBlocks?.length || 0} thinking blocks`);
717
+ await cb([null], {
718
+ toolsUsed,
719
+ thinking: thinkingBlocks
720
+ });
706
721
  }
707
722
  return;
708
723
  }
@@ -774,8 +789,12 @@ var AnthropicBackend = class {
774
789
  await this.complete(model, messages, { ...options, tools: void 0, _internal: void 0 }, cb, toolsUsed);
775
790
  }
776
791
  } else {
777
- this.logger.debug(`[Tool Execution] executeTools=false, passing tool calls to callback`);
778
- await cb([null], { toolsUsed });
792
+ const thinkingBlocks = this.getThinkingBlocks();
793
+ this.logger.debug(`[Tool Execution] executeTools=false, passing tool calls to callback with ${thinkingBlocks?.length || 0} thinking blocks`);
794
+ await cb([null], {
795
+ toolsUsed,
796
+ thinking: thinkingBlocks
797
+ });
779
798
  }
780
799
  return;
781
800
  }
@@ -6248,8 +6267,6 @@ var ensureToolPairingIntegrity = (messages, logger) => {
6248
6267
  return messages;
6249
6268
  }
6250
6269
  const toolUseIds = /* @__PURE__ */ new Set();
6251
- const toolResultIds = /* @__PURE__ */ new Set();
6252
- let hasToolUseBlocks = false;
6253
6270
  let hasToolResultBlocks = false;
6254
6271
  for (let i = 0; i < messages.length; i++) {
6255
6272
  const message = messages[i];
@@ -6259,111 +6276,65 @@ var ensureToolPairingIntegrity = (messages, logger) => {
6259
6276
  const block = content[j];
6260
6277
  if (block.type === "tool_use" && "id" in block) {
6261
6278
  toolUseIds.add(block.id);
6262
- hasToolUseBlocks = true;
6263
6279
  }
6264
6280
  }
6265
6281
  } else if (message.role === "user" && Array.isArray(message.content)) {
6266
6282
  const content = message.content;
6267
6283
  for (let j = 0; j < content.length; j++) {
6268
- const block = content[j];
6269
- if (block.type === "tool_result" && "tool_use_id" in block) {
6270
- toolResultIds.add(block.tool_use_id);
6284
+ if (content[j].type === "tool_result") {
6271
6285
  hasToolResultBlocks = true;
6286
+ break;
6272
6287
  }
6273
6288
  }
6274
6289
  }
6275
6290
  }
6276
- if (!hasToolUseBlocks && !hasToolResultBlocks) {
6291
+ if (!hasToolResultBlocks) {
6277
6292
  return messages;
6278
6293
  }
6279
- let orphanedToolResultCount = 0;
6280
- let orphanedToolUseCount = 0;
6294
+ let orphanedCount = 0;
6281
6295
  const result = [];
6282
6296
  for (let i = 0; i < messages.length; i++) {
6283
6297
  const message = messages[i];
6284
- if (message.role === "assistant" && Array.isArray(message.content)) {
6285
- const content = message.content;
6286
- let hasOrphanedToolUse = false;
6287
- for (let j = 0; j < content.length; j++) {
6288
- const block = content[j];
6289
- if (block.type === "tool_use" && "id" in block) {
6290
- if (!toolResultIds.has(block.id)) {
6291
- hasOrphanedToolUse = true;
6292
- break;
6293
- }
6294
- }
6295
- }
6296
- if (!hasOrphanedToolUse) {
6297
- result.push(message);
6298
- continue;
6299
- }
6300
- const filteredContent = [];
6301
- for (let j = 0; j < content.length; j++) {
6302
- const block = content[j];
6303
- if (block.type === "tool_use" && "id" in block) {
6304
- const toolId = block.id;
6305
- if (!toolResultIds.has(toolId)) {
6306
- orphanedToolUseCount++;
6307
- if (logger) {
6308
- logger.warn(`Removing orphaned tool_use block with id: ${toolId} (no matching tool_result)`);
6309
- }
6310
- continue;
6311
- }
6312
- }
6313
- filteredContent.push(block);
6314
- }
6315
- if (filteredContent.length > 0) {
6316
- result.push({ ...message, content: filteredContent });
6317
- }
6298
+ if (message.role !== "user" || !Array.isArray(message.content)) {
6299
+ result.push(message);
6318
6300
  continue;
6319
6301
  }
6320
- if (message.role === "user" && Array.isArray(message.content)) {
6321
- const content = message.content;
6322
- let hasOrphanedToolResult = false;
6323
- for (let j = 0; j < content.length; j++) {
6324
- const block = content[j];
6325
- if (block.type === "tool_result" && "tool_use_id" in block) {
6326
- if (!toolUseIds.has(block.tool_use_id)) {
6327
- hasOrphanedToolResult = true;
6328
- break;
6329
- }
6302
+ const content = message.content;
6303
+ let hasOrphans = false;
6304
+ for (let j = 0; j < content.length; j++) {
6305
+ const block = content[j];
6306
+ if (block.type === "tool_result" && "tool_use_id" in block) {
6307
+ if (!toolUseIds.has(block.tool_use_id)) {
6308
+ hasOrphans = true;
6309
+ break;
6330
6310
  }
6331
6311
  }
6332
- if (!hasOrphanedToolResult) {
6333
- result.push(message);
6334
- continue;
6335
- }
6336
- const filteredContent = [];
6337
- for (let j = 0; j < content.length; j++) {
6338
- const block = content[j];
6339
- if (block.type === "tool_result" && "tool_use_id" in block) {
6340
- const toolUseId = block.tool_use_id;
6341
- if (!toolUseIds.has(toolUseId)) {
6342
- orphanedToolResultCount++;
6343
- if (logger) {
6344
- logger.warn(`Removing orphaned tool_result block referencing missing tool_use_id: ${toolUseId}`);
6345
- }
6346
- continue;
6312
+ }
6313
+ if (!hasOrphans) {
6314
+ result.push(message);
6315
+ continue;
6316
+ }
6317
+ const filteredContent = [];
6318
+ for (let j = 0; j < content.length; j++) {
6319
+ const block = content[j];
6320
+ if (block.type === "tool_result" && "tool_use_id" in block) {
6321
+ const toolUseId = block.tool_use_id;
6322
+ if (!toolUseIds.has(toolUseId)) {
6323
+ orphanedCount++;
6324
+ if (logger) {
6325
+ logger.warn(`Removing orphaned tool_result block referencing missing tool_use_id: ${toolUseId}`);
6347
6326
  }
6327
+ continue;
6348
6328
  }
6349
- filteredContent.push(block);
6350
- }
6351
- if (filteredContent.length > 0) {
6352
- result.push({ ...message, content: filteredContent });
6353
6329
  }
6354
- continue;
6330
+ filteredContent.push(block);
6355
6331
  }
6356
- result.push(message);
6357
- }
6358
- if ((orphanedToolResultCount > 0 || orphanedToolUseCount > 0) && logger) {
6359
- const parts = [];
6360
- if (orphanedToolResultCount > 0) {
6361
- parts.push(`${orphanedToolResultCount} orphaned tool_result block(s)`);
6362
- }
6363
- if (orphanedToolUseCount > 0) {
6364
- parts.push(`${orphanedToolUseCount} orphaned tool_use block(s)`);
6332
+ if (filteredContent.length > 0) {
6333
+ result.push({ ...message, content: filteredContent });
6365
6334
  }
6366
- logger.log(`Tool pairing integrity: removed ${parts.join(" and ")} after truncation`);
6335
+ }
6336
+ if (orphanedCount > 0 && logger) {
6337
+ logger.log(`Tool pairing integrity: removed ${orphanedCount} orphaned tool_result block(s) after truncation`);
6367
6338
  }
6368
6339
  return result;
6369
6340
  };
@@ -228,6 +228,7 @@ var b4mLLMTools = z3.enum([
228
228
  // File operation tools
229
229
  "file_read",
230
230
  "create_file",
231
+ "edit_local_file",
231
232
  "glob_files",
232
233
  "grep_search",
233
234
  "delete_file",
@@ -5901,6 +5902,9 @@ function buildSSEEvent(text, info) {
5901
5902
  outputTokens: info.outputTokens
5902
5903
  };
5903
5904
  }
5905
+ if (info?.thinking && info.thinking.length > 0) {
5906
+ event.thinking = info.thinking;
5907
+ }
5904
5908
  return event;
5905
5909
  }
5906
5910
  function formatSSEError(error) {
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  createFabFile,
4
4
  createFabFileSchema
5
- } from "./chunk-CQW42LY2.js";
6
- import "./chunk-TFONTTOE.js";
5
+ } from "./chunk-RA3CZOUX.js";
6
+ import "./chunk-SQBLLN7K.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
- import "./chunk-DJPXSSP4.js";
8
+ import "./chunk-WCYNJOOX.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  createFabFile,
package/dist/index.js CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  getEffectiveApiKey,
5
5
  getOpenWeatherKey,
6
6
  getSerperKey
7
- } from "./chunk-MU4EEXAL.js";
8
- import "./chunk-A3VAT7TT.js";
9
- import "./chunk-CQW42LY2.js";
7
+ } from "./chunk-DGAIF2QC.js";
8
+ import "./chunk-RBZRTCAY.js";
9
+ import "./chunk-RA3CZOUX.js";
10
10
  import {
11
11
  BFLImageService,
12
12
  BaseStorage,
@@ -15,7 +15,7 @@ import {
15
15
  OpenAIBackend,
16
16
  OpenAIImageService,
17
17
  XAIImageService
18
- } from "./chunk-TFONTTOE.js";
18
+ } from "./chunk-SQBLLN7K.js";
19
19
  import {
20
20
  Logger
21
21
  } from "./chunk-AMDXHL6S.js";
@@ -73,7 +73,7 @@ import {
73
73
  XAI_IMAGE_MODELS,
74
74
  b4mLLMTools,
75
75
  getMcpProviderMetadata
76
- } from "./chunk-DJPXSSP4.js";
76
+ } from "./chunk-WCYNJOOX.js";
77
77
  import {
78
78
  __require
79
79
  } from "./chunk-PDX44BCA.js";
@@ -107,7 +107,8 @@ function CustomTextInput({
107
107
  onChange,
108
108
  onSubmit,
109
109
  placeholder = "",
110
- showCursor = true
110
+ showCursor = true,
111
+ disabled = false
111
112
  }) {
112
113
  const [cursorOffset, setCursorOffset] = useState(value.length);
113
114
  useInput(
@@ -188,7 +189,7 @@ function CustomTextInput({
188
189
  setCursorOffset(cursorOffset + 1);
189
190
  }
190
191
  },
191
- { isActive: true }
192
+ { isActive: !disabled }
192
193
  );
193
194
  const hasValue = value.length > 0;
194
195
  if (!hasValue) {
@@ -827,56 +828,59 @@ function InputPrompt({
827
828
  useEffect(() => {
828
829
  setFileSelectedIndex(0);
829
830
  }, [filteredFiles]);
830
- useInput2((_input, key) => {
831
- if (fileAutocomplete?.active && filteredFiles.length > 0) {
832
- if (key.upArrow) {
833
- setFileSelectedIndex((prev) => prev > 0 ? prev - 1 : filteredFiles.length - 1);
834
- return;
835
- } else if (key.downArrow) {
836
- setFileSelectedIndex((prev) => prev < filteredFiles.length - 1 ? prev + 1 : 0);
837
- return;
838
- } else if (key.tab) {
839
- const selectedFile = filteredFiles[fileSelectedIndex];
840
- if (selectedFile) {
841
- insertSelectedFile(selectedFile);
831
+ useInput2(
832
+ (_input, key) => {
833
+ if (fileAutocomplete?.active && filteredFiles.length > 0) {
834
+ if (key.upArrow) {
835
+ setFileSelectedIndex((prev) => prev > 0 ? prev - 1 : filteredFiles.length - 1);
836
+ return;
837
+ } else if (key.downArrow) {
838
+ setFileSelectedIndex((prev) => prev < filteredFiles.length - 1 ? prev + 1 : 0);
839
+ return;
840
+ } else if (key.tab) {
841
+ const selectedFile = filteredFiles[fileSelectedIndex];
842
+ if (selectedFile) {
843
+ insertSelectedFile(selectedFile);
844
+ }
845
+ return;
846
+ } else if (key.escape) {
847
+ setFileAutocomplete(null);
848
+ return;
842
849
  }
843
- return;
844
- } else if (key.escape) {
845
- setFileAutocomplete(null);
846
- return;
847
850
  }
848
- }
849
- if (shouldShowCommandAutocomplete && filteredCommands.length > 0) {
850
- if (key.upArrow) {
851
- setSelectedIndex((prev) => prev > 0 ? prev - 1 : filteredCommands.length - 1);
852
- } else if (key.downArrow) {
853
- setSelectedIndex((prev) => prev < filteredCommands.length - 1 ? prev + 1 : 0);
854
- }
855
- return;
856
- }
857
- if (!shouldShowCommandAutocomplete && !fileAutocomplete?.active && history.length > 0) {
858
- if (key.upArrow) {
859
- if (historyIndex === -1) {
860
- setTempInput(value);
861
- setHistoryIndex(0);
862
- setValue(history[0]);
863
- } else if (historyIndex < history.length - 1) {
864
- const newIndex = historyIndex + 1;
865
- setHistoryIndex(newIndex);
866
- setValue(history[newIndex]);
851
+ if (shouldShowCommandAutocomplete && filteredCommands.length > 0) {
852
+ if (key.upArrow) {
853
+ setSelectedIndex((prev) => prev > 0 ? prev - 1 : filteredCommands.length - 1);
854
+ } else if (key.downArrow) {
855
+ setSelectedIndex((prev) => prev < filteredCommands.length - 1 ? prev + 1 : 0);
867
856
  }
868
- } else if (key.downArrow) {
869
- if (historyIndex > 0) {
870
- const newIndex = historyIndex - 1;
871
- setHistoryIndex(newIndex);
872
- setValue(history[newIndex]);
873
- } else if (historyIndex === 0) {
874
- setHistoryIndex(-1);
875
- setValue(tempInput);
857
+ return;
858
+ }
859
+ if (!shouldShowCommandAutocomplete && !fileAutocomplete?.active && history.length > 0) {
860
+ if (key.upArrow) {
861
+ if (historyIndex === -1) {
862
+ setTempInput(value);
863
+ setHistoryIndex(0);
864
+ setValue(history[0]);
865
+ } else if (historyIndex < history.length - 1) {
866
+ const newIndex = historyIndex + 1;
867
+ setHistoryIndex(newIndex);
868
+ setValue(history[newIndex]);
869
+ }
870
+ } else if (key.downArrow) {
871
+ if (historyIndex > 0) {
872
+ const newIndex = historyIndex - 1;
873
+ setHistoryIndex(newIndex);
874
+ setValue(history[newIndex]);
875
+ } else if (historyIndex === 0) {
876
+ setHistoryIndex(-1);
877
+ setValue(tempInput);
878
+ }
876
879
  }
877
880
  }
878
- }
879
- });
881
+ },
882
+ { isActive: !disabled }
883
+ );
880
884
  const insertSelectedFile = (file) => {
881
885
  if (!fileAutocomplete) return;
882
886
  const beforeAt = value.slice(0, fileAutocomplete.startIndex);
@@ -970,7 +974,8 @@ function InputPrompt({
970
974
  onChange: handleChange,
971
975
  onSubmit: handleSubmit,
972
976
  placeholder: getPlaceholder(),
973
- showCursor: !disabled
977
+ showCursor: !disabled,
978
+ disabled
974
979
  }
975
980
  )), shouldShowCommandAutocomplete && /* @__PURE__ */ React5.createElement(CommandAutocomplete, { commands: filteredCommands, selectedIndex }), fileAutocomplete?.active && /* @__PURE__ */ React5.createElement(FileAutocomplete, { files: filteredFiles, selectedIndex: fileSelectedIndex, query: fileAutocomplete.query }));
976
981
  }
@@ -983,8 +988,8 @@ import { Box as Box6 } from "ink";
983
988
  import React6 from "react";
984
989
  import { Box as Box5, Text as Text6 } from "ink";
985
990
  import Spinner from "ink-spinner";
986
- var ThoughtStream = React6.memo(function ThoughtStream2({ steps }) {
987
- return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column", gap: 1 }, steps.map((step, index) => /* @__PURE__ */ React6.createElement(Box5, { key: index, flexDirection: "column" }, step.type === "thought" && /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, "\u{1F914} Thought: "), /* @__PURE__ */ React6.createElement(Text6, null, step.content)), step.type === "action" && /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, "\u26A1 Action: "), /* @__PURE__ */ React6.createElement(Text6, { bold: true }, step.metadata?.toolName || "unknown")), step.metadata?.toolInput && /* @__PURE__ */ React6.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, JSON.stringify(step.metadata.toolInput, null, 2)))), step.type === "observation" && /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, "\u{1F4CA} Observation: ")), /* @__PURE__ */ React6.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React6.createElement(Text6, null, step.content))), step.type === "final_answer" && /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green", bold: true }, "\u2705 Final Answer:", " ")), /* @__PURE__ */ React6.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React6.createElement(Text6, null, step.content)), step.metadata?.tokenUsage && /* @__PURE__ */ React6.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "(", step.metadata.tokenUsage.total, " tokens)"))))), !steps.some((s) => s.type === "final_answer") && /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, /* @__PURE__ */ React6.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React6.createElement(Text6, null, " ", steps.length === 0 ? "Thinking..." : "Processing...")));
991
+ var ThoughtStream = React6.memo(function ThoughtStream2({ isThinking }) {
992
+ return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column", gap: 1 }, isThinking && /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, /* @__PURE__ */ React6.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React6.createElement(Text6, null, " Thinking...")));
988
993
  });
989
994
 
990
995
  // src/store/index.ts
@@ -1029,12 +1034,6 @@ var useCliStore = create((set) => ({
1029
1034
  // UI state
1030
1035
  isThinking: false,
1031
1036
  setIsThinking: (thinking) => set({ isThinking: thinking }),
1032
- agentSteps: [],
1033
- addAgentStep: (step) => set((state) => ({
1034
- agentSteps: [...state.agentSteps, step]
1035
- })),
1036
- setAgentSteps: (steps) => set({ agentSteps: steps }),
1037
- clearAgentSteps: () => set({ agentSteps: [] }),
1038
1037
  // Permission prompt
1039
1038
  permissionPrompt: null,
1040
1039
  setPermissionPrompt: (prompt) => set({ permissionPrompt: prompt }),
@@ -1049,11 +1048,10 @@ var useCliStore = create((set) => ({
1049
1048
  // src/components/AgentThinking.tsx
1050
1049
  var AgentThinking = React7.memo(function AgentThinking2() {
1051
1050
  const isThinking = useCliStore((state) => state.isThinking);
1052
- const agentSteps = useCliStore((state) => state.agentSteps);
1053
1051
  if (!isThinking) {
1054
1052
  return null;
1055
1053
  }
1056
- return /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React7.createElement(ThoughtStream, { steps: agentSteps }));
1054
+ return /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React7.createElement(ThoughtStream, { isThinking }));
1057
1055
  });
1058
1056
 
1059
1057
  // src/components/PermissionPrompt.tsx
@@ -1091,7 +1089,10 @@ function PermissionPrompt({
1091
1089
  { label: "\u2713 Allow once", value: "allow-once" },
1092
1090
  { label: "\u2717 Deny", value: "deny" }
1093
1091
  ];
1094
- const argsString = typeof args === "string" ? args : JSON.stringify(args, null, 2);
1092
+ const MAX_ARGS_LENGTH = 500;
1093
+ const rawArgsString = typeof args === "string" ? args : JSON.stringify(args, null, 2);
1094
+ const argsString = rawArgsString.length > MAX_ARGS_LENGTH ? rawArgsString.slice(0, MAX_ARGS_LENGTH) + `
1095
+ ... (${rawArgsString.length - MAX_ARGS_LENGTH} more chars)` : rawArgsString;
1095
1096
  return /* @__PURE__ */ React8.createElement(Box7, { flexDirection: "column", borderStyle: "bold", borderColor: "yellow", padding: 1, marginY: 1 }, /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text7, { bold: true, color: "yellow" }, "\u26A0\uFE0F Permission Required")), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, "Tool: "), /* @__PURE__ */ React8.createElement(Text7, { bold: true, color: "cyan" }, toolName)), toolDescription && /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, "Action: "), /* @__PURE__ */ React8.createElement(Text7, null, toolDescription)), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text7, { bold: true }, "Arguments:"), /* @__PURE__ */ React8.createElement(Box7, { paddingLeft: 2, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, argsString))), preview && /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text7, { bold: true }, "Preview:"), /* @__PURE__ */ React8.createElement(Box7, { borderStyle: "single", borderColor: "gray", paddingX: 1, flexDirection: "column" }, renderDiffPreview(preview))), !canBeTrusted && /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text7, { color: "red", dimColor: true }, "Note: This tool cannot be trusted due to its dangerous nature.")), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(SelectInput, { items, onSelect: (item) => onResponse(item.value) })));
1096
1097
  }
1097
1098
 
@@ -1538,7 +1539,7 @@ ${errorBlock}`;
1538
1539
  onSubmit: handleSubmit,
1539
1540
  onBashCommand,
1540
1541
  onImageDetected,
1541
- disabled: isThinking,
1542
+ disabled: isThinking || !!permissionPrompt,
1542
1543
  history: commandHistory,
1543
1544
  commands,
1544
1545
  prefillInput,
@@ -3144,6 +3145,7 @@ ${options.context}` : this.getSystemPrompt()
3144
3145
  }
3145
3146
  if (completionInfo.toolsUsed && completionInfo.toolsUsed.length > 0) {
3146
3147
  hadToolCalls = true;
3148
+ const thinkingBlocks = completionInfo.thinking || [];
3147
3149
  for (const toolUse of completionInfo.toolsUsed) {
3148
3150
  const toolCallId = `${toolUse.name}_${JSON.stringify(toolUse.arguments)}`;
3149
3151
  if (processedToolIds.has(toolCallId)) {
@@ -3176,16 +3178,23 @@ ${options.context}` : this.getSystemPrompt()
3176
3178
  const params = typeof toolUse.arguments === "string" ? JSON.parse(toolUse.arguments) : toolUse.arguments;
3177
3179
  observation = await tool.toolFn(params);
3178
3180
  const toolCallId2 = `${toolUse.name}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
3181
+ const assistantContent = [
3182
+ // Include thinking blocks first (required by Anthropic when thinking is enabled)
3183
+ ...thinkingBlocks,
3184
+ // Then the tool use
3185
+ {
3186
+ type: "tool_use",
3187
+ id: toolCallId2,
3188
+ name: toolUse.name,
3189
+ input: params
3190
+ }
3191
+ ];
3192
+ this.context.logger.debug(
3193
+ `[assistantContent] ${assistantContent.length} blocks (${thinkingBlocks.length} thinking, 1 tool_use)`
3194
+ );
3179
3195
  messages.push({
3180
3196
  role: "assistant",
3181
- content: [
3182
- {
3183
- type: "tool_use",
3184
- id: toolCallId2,
3185
- name: toolUse.name,
3186
- input: params
3187
- }
3188
- ]
3197
+ content: assistantContent
3189
3198
  });
3190
3199
  messages.push({
3191
3200
  role: "user",
@@ -5476,8 +5485,8 @@ async function processAndStoreImages(images, context) {
5476
5485
  const buffer = await downloadImage(image);
5477
5486
  const fileType = await fileTypeFromBuffer2(buffer);
5478
5487
  const filename = `${uuidv46()}.${fileType?.ext}`;
5479
- const path16 = await context.imageGenerateStorage.upload(buffer, filename, {});
5480
- return path16;
5488
+ const path17 = await context.imageGenerateStorage.upload(buffer, filename, {});
5489
+ return path17;
5481
5490
  }));
5482
5491
  }
5483
5492
  async function updateQuestAndReturnMarkdown(storedImageUrls, context) {
@@ -6689,8 +6698,8 @@ async function processAndStoreImage(imageUrl, context) {
6689
6698
  const buffer = await downloadImage2(imageUrl);
6690
6699
  const fileType = await fileTypeFromBuffer3(buffer);
6691
6700
  const filename = `${uuidv47()}.${fileType?.ext}`;
6692
- const path16 = await context.imageGenerateStorage.upload(buffer, filename, {});
6693
- return path16;
6701
+ const path17 = await context.imageGenerateStorage.upload(buffer, filename, {});
6702
+ return path17;
6694
6703
  }
6695
6704
  async function updateQuestAndReturnMarkdown2(storedImagePath, context) {
6696
6705
  await context.onFinish?.("edit_image", storedImagePath);
@@ -9478,6 +9487,104 @@ BLOCKED OPERATIONS:
9478
9487
  })
9479
9488
  };
9480
9489
 
9490
+ // ../../b4m-core/packages/services/dist/src/llm/tools/implementation/editLocalFile/index.js
9491
+ import { promises as fs11 } from "fs";
9492
+ import { existsSync as existsSync7 } from "fs";
9493
+ import path13 from "path";
9494
+ import { diffLines as diffLines3 } from "diff";
9495
+ function generateDiff(original, modified) {
9496
+ const differences = diffLines3(original, modified);
9497
+ let diffString = "";
9498
+ let additions = 0;
9499
+ let deletions = 0;
9500
+ differences.forEach((part) => {
9501
+ if (part.added) {
9502
+ additions += part.count || 0;
9503
+ diffString += part.value.split("\n").filter((line) => line).map((line) => `+ ${line}`).join("\n");
9504
+ if (diffString && !diffString.endsWith("\n"))
9505
+ diffString += "\n";
9506
+ } else if (part.removed) {
9507
+ deletions += part.count || 0;
9508
+ diffString += part.value.split("\n").filter((line) => line).map((line) => `- ${line}`).join("\n");
9509
+ if (diffString && !diffString.endsWith("\n"))
9510
+ diffString += "\n";
9511
+ }
9512
+ });
9513
+ return { additions, deletions, diff: diffString.trim() };
9514
+ }
9515
+ async function editLocalFile(params) {
9516
+ const { path: filePath, old_string, new_string } = params;
9517
+ const normalizedPath = path13.normalize(filePath);
9518
+ const resolvedPath = path13.resolve(process.cwd(), normalizedPath);
9519
+ const cwd = path13.resolve(process.cwd());
9520
+ if (!resolvedPath.startsWith(cwd)) {
9521
+ throw new Error(`Access denied: Cannot edit files outside of current working directory`);
9522
+ }
9523
+ if (!existsSync7(resolvedPath)) {
9524
+ throw new Error(`File not found: ${filePath}`);
9525
+ }
9526
+ const currentContent = await fs11.readFile(resolvedPath, "utf-8");
9527
+ if (!currentContent.includes(old_string)) {
9528
+ const preview = old_string.length > 100 ? old_string.substring(0, 100) + "..." : old_string;
9529
+ throw new Error(`String to replace not found in file. Make sure the old_string matches exactly (including whitespace and line endings). Searched for: "${preview}"`);
9530
+ }
9531
+ const occurrences = currentContent.split(old_string).length - 1;
9532
+ if (occurrences > 1) {
9533
+ throw new Error(`Found ${occurrences} occurrences of the string to replace. Please provide a more specific old_string that matches exactly one location.`);
9534
+ }
9535
+ const newContent = currentContent.replace(old_string, new_string);
9536
+ await fs11.writeFile(resolvedPath, newContent, "utf-8");
9537
+ const diffResult = generateDiff(old_string, new_string);
9538
+ return `File edited successfully: ${filePath}
9539
+ Changes: +${diffResult.additions} lines, -${diffResult.deletions} lines
9540
+
9541
+ Diff:
9542
+ ${diffResult.diff}`;
9543
+ }
9544
+ var editLocalFileTool = {
9545
+ name: "edit_local_file",
9546
+ implementation: (context) => ({
9547
+ toolFn: async (value) => {
9548
+ const params = value;
9549
+ context.logger.info(`\u{1F4DD} EditLocalFile: Editing file`, {
9550
+ path: params.path,
9551
+ oldStringLength: params.old_string.length,
9552
+ newStringLength: params.new_string.length
9553
+ });
9554
+ try {
9555
+ const result = await editLocalFile(params);
9556
+ context.logger.info("\u2705 EditLocalFile: Success", { path: params.path });
9557
+ return result;
9558
+ } catch (error) {
9559
+ context.logger.error("\u274C EditLocalFile: Failed", error);
9560
+ throw error;
9561
+ }
9562
+ },
9563
+ toolSchema: {
9564
+ name: "edit_local_file",
9565
+ description: "Edit a file by replacing a specific string with new content. The old_string must match exactly one location in the file (including whitespace). Use this for precise edits to existing files. For creating new files or complete rewrites, use create_file instead.",
9566
+ parameters: {
9567
+ type: "object",
9568
+ properties: {
9569
+ path: {
9570
+ type: "string",
9571
+ description: "Path to the file to edit (relative to current working directory)"
9572
+ },
9573
+ old_string: {
9574
+ type: "string",
9575
+ description: "The exact string to find and replace. Must match exactly one location in the file, including all whitespace and line endings."
9576
+ },
9577
+ new_string: {
9578
+ type: "string",
9579
+ description: "The string to replace old_string with. Can be empty to delete the old_string."
9580
+ }
9581
+ },
9582
+ required: ["path", "old_string", "new_string"]
9583
+ }
9584
+ }
9585
+ })
9586
+ };
9587
+
9481
9588
  // ../../b4m-core/packages/services/dist/src/llm/tools/index.js
9482
9589
  var tools = {
9483
9590
  dice_roll: diceRollTool,
@@ -9503,6 +9610,7 @@ var tools = {
9503
9610
  planet_visibility: planetVisibilityTool,
9504
9611
  file_read: fileReadTool,
9505
9612
  create_file: createFileTool,
9613
+ edit_local_file: editLocalFileTool,
9506
9614
  glob_files: globFilesTool,
9507
9615
  grep_search: grepSearchTool,
9508
9616
  delete_file: deleteFileTool,
@@ -9746,10 +9854,10 @@ var ToolErrorType;
9746
9854
  // src/utils/diffPreview.ts
9747
9855
  import * as Diff from "diff";
9748
9856
  import { readFile } from "fs/promises";
9749
- import { existsSync as existsSync7 } from "fs";
9857
+ import { existsSync as existsSync8 } from "fs";
9750
9858
  async function generateFileDiffPreview(args) {
9751
9859
  try {
9752
- if (!existsSync7(args.path)) {
9860
+ if (!existsSync8(args.path)) {
9753
9861
  const lines2 = args.content.split("\n");
9754
9862
  const preview = lines2.slice(0, 20).join("\n");
9755
9863
  const hasMore = lines2.length > 20;
@@ -9771,18 +9879,26 @@ ${preview}${hasMore ? `
9771
9879
  // Show 3 lines of context around changes
9772
9880
  );
9773
9881
  const lines = patch.split("\n");
9774
- const diffLines3 = lines.slice(4);
9775
- return diffLines3.join("\n");
9882
+ const diffLines4 = lines.slice(4);
9883
+ return diffLines4.join("\n");
9776
9884
  } catch (error) {
9777
9885
  return `[Error generating diff preview: ${error instanceof Error ? error.message : "Unknown error"}]`;
9778
9886
  }
9779
9887
  }
9888
+ function generateEditLocalFilePreview(args) {
9889
+ const patch = Diff.createPatch(args.path, args.old_string, args.new_string, "Current", "Proposed", { context: 3 });
9890
+ const lines = patch.split("\n");
9891
+ const diffLines4 = lines.slice(4);
9892
+ return `[Edit in: ${args.path}]
9893
+
9894
+ ${diffLines4.join("\n")}`;
9895
+ }
9780
9896
  async function generateFileDeletePreview(args) {
9781
9897
  try {
9782
- if (!existsSync7(args.path)) {
9898
+ if (!existsSync8(args.path)) {
9783
9899
  return `[File does not exist: ${args.path}]`;
9784
9900
  }
9785
- const stats = await import("fs/promises").then((fs13) => fs13.stat(args.path));
9901
+ const stats = await import("fs/promises").then((fs14) => fs14.stat(args.path));
9786
9902
  return `[File will be deleted]
9787
9903
 
9788
9904
  Path: ${args.path}
@@ -9794,8 +9910,8 @@ Last modified: ${stats.mtime.toLocaleString()}`;
9794
9910
  }
9795
9911
 
9796
9912
  // src/utils/Logger.ts
9797
- import fs11 from "fs/promises";
9798
- import path13 from "path";
9913
+ import fs12 from "fs/promises";
9914
+ import path14 from "path";
9799
9915
  import os2 from "os";
9800
9916
  var Logger2 = class _Logger {
9801
9917
  constructor() {
@@ -9818,9 +9934,9 @@ var Logger2 = class _Logger {
9818
9934
  */
9819
9935
  async initialize(sessionId) {
9820
9936
  this.sessionId = sessionId;
9821
- const debugDir = path13.join(os2.homedir(), ".bike4mind", "debug");
9822
- await fs11.mkdir(debugDir, { recursive: true });
9823
- this.logFilePath = path13.join(debugDir, `${sessionId}.txt`);
9937
+ const debugDir = path14.join(os2.homedir(), ".bike4mind", "debug");
9938
+ await fs12.mkdir(debugDir, { recursive: true });
9939
+ this.logFilePath = path14.join(debugDir, `${sessionId}.txt`);
9824
9940
  await this.writeToFile("INFO", "=== CLI SESSION START ===");
9825
9941
  }
9826
9942
  /**
@@ -9884,7 +10000,7 @@ var Logger2 = class _Logger {
9884
10000
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19);
9885
10001
  const logEntry = `[${timestamp}] [${level}] ${message}
9886
10002
  `;
9887
- await fs11.appendFile(this.logFilePath, logEntry, "utf-8");
10003
+ await fs12.appendFile(this.logFilePath, logEntry, "utf-8");
9888
10004
  } catch (error) {
9889
10005
  console.error("File logging failed:", error);
9890
10006
  }
@@ -10030,15 +10146,15 @@ var Logger2 = class _Logger {
10030
10146
  async cleanupOldLogs() {
10031
10147
  if (!this.fileLoggingEnabled) return;
10032
10148
  try {
10033
- const debugDir = path13.join(os2.homedir(), ".bike4mind", "debug");
10034
- const files = await fs11.readdir(debugDir);
10149
+ const debugDir = path14.join(os2.homedir(), ".bike4mind", "debug");
10150
+ const files = await fs12.readdir(debugDir);
10035
10151
  const now = Date.now();
10036
10152
  const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1e3;
10037
10153
  for (const file of files) {
10038
- const filePath = path13.join(debugDir, file);
10039
- const stats = await fs11.stat(filePath);
10154
+ const filePath = path14.join(debugDir, file);
10155
+ const stats = await fs12.stat(filePath);
10040
10156
  if (stats.mtime.getTime() < thirtyDaysAgo) {
10041
- await fs11.unlink(filePath);
10157
+ await fs12.unlink(filePath);
10042
10158
  }
10043
10159
  }
10044
10160
  } catch (error) {
@@ -10095,10 +10211,10 @@ var SERVER_TOOLS = ["weather_info", "web_search"];
10095
10211
  var LOCAL_TOOLS = [
10096
10212
  "file_read",
10097
10213
  "create_file",
10214
+ "edit_local_file",
10098
10215
  "glob_files",
10099
10216
  "grep_search",
10100
10217
  "delete_file",
10101
- "edit_file",
10102
10218
  "dice_roll",
10103
10219
  "math_evaluate",
10104
10220
  "current_datetime",
@@ -10132,21 +10248,21 @@ var NoOpStorage = class extends BaseStorage {
10132
10248
  async upload(input, destination, options) {
10133
10249
  return `/tmp/${destination}`;
10134
10250
  }
10135
- async download(path16) {
10251
+ async download(path17) {
10136
10252
  throw new Error("Download not supported in CLI");
10137
10253
  }
10138
- async delete(path16) {
10254
+ async delete(path17) {
10139
10255
  }
10140
- async getSignedUrl(path16) {
10141
- return `/tmp/${path16}`;
10256
+ async getSignedUrl(path17) {
10257
+ return `/tmp/${path17}`;
10142
10258
  }
10143
- getPublicUrl(path16) {
10144
- return `/tmp/${path16}`;
10259
+ getPublicUrl(path17) {
10260
+ return `/tmp/${path17}`;
10145
10261
  }
10146
- async getPreview(path16) {
10147
- return `/tmp/${path16}`;
10262
+ async getPreview(path17) {
10263
+ return `/tmp/${path17}`;
10148
10264
  }
10149
- async getMetadata(path16) {
10265
+ async getMetadata(path17) {
10150
10266
  return { size: 0, contentType: "application/octet-stream" };
10151
10267
  }
10152
10268
  };
@@ -10178,11 +10294,12 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
10178
10294
  return result2;
10179
10295
  }
10180
10296
  let preview;
10181
- if (toolName === "edit_file" && args?.path && args?.content) {
10297
+ if (toolName === "edit_local_file" && args?.path && args?.old_string && typeof args?.new_string === "string") {
10182
10298
  try {
10183
- preview = await generateFileDiffPreview({
10299
+ preview = generateEditLocalFilePreview({
10184
10300
  path: args.path,
10185
- content: args.content
10301
+ old_string: args.old_string,
10302
+ new_string: args.new_string
10186
10303
  });
10187
10304
  } catch (error) {
10188
10305
  preview = `[Could not generate preview: ${error instanceof Error ? error.message : "Unknown error"}]`;
@@ -10299,6 +10416,7 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
10299
10416
  // File operation tools (CLI-specific, local execution)
10300
10417
  file_read: {},
10301
10418
  create_file: {},
10419
+ edit_local_file: {},
10302
10420
  glob_files: {},
10303
10421
  grep_search: {},
10304
10422
  delete_file: {},
@@ -10381,6 +10499,7 @@ var DEFAULT_TOOL_CATEGORIES = {
10381
10499
  // These tools can modify files, execute code, or have other dangerous side effects
10382
10500
  // They ALWAYS require permission and cannot be trusted automatically
10383
10501
  edit_file: "prompt_always",
10502
+ edit_local_file: "prompt_always",
10384
10503
  create_file: "prompt_always",
10385
10504
  delete_file: "prompt_always",
10386
10505
  shell_execute: "prompt_always",
@@ -10547,8 +10666,8 @@ function getEnvironmentName(configApiConfig) {
10547
10666
  }
10548
10667
 
10549
10668
  // src/utils/contextLoader.ts
10550
- import * as fs12 from "fs";
10551
- import * as path14 from "path";
10669
+ import * as fs13 from "fs";
10670
+ import * as path15 from "path";
10552
10671
  import { homedir as homedir4 } from "os";
10553
10672
  var CONTEXT_FILE_SIZE_LIMIT = 100 * 1024;
10554
10673
  var PROJECT_CONTEXT_FILES = [
@@ -10569,9 +10688,9 @@ function formatFileSize2(bytes) {
10569
10688
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
10570
10689
  }
10571
10690
  function tryReadContextFile(dir, filename, source) {
10572
- const filePath = path14.join(dir, filename);
10691
+ const filePath = path15.join(dir, filename);
10573
10692
  try {
10574
- const stats = fs12.lstatSync(filePath);
10693
+ const stats = fs13.lstatSync(filePath);
10575
10694
  if (stats.isDirectory()) {
10576
10695
  return null;
10577
10696
  }
@@ -10585,7 +10704,7 @@ function tryReadContextFile(dir, filename, source) {
10585
10704
  error: `${source === "global" ? "Global" : "Project"} ${filename} exceeds 100KB limit (${formatFileSize2(stats.size)})`
10586
10705
  };
10587
10706
  }
10588
- const content = fs12.readFileSync(filePath, "utf-8");
10707
+ const content = fs13.readFileSync(filePath, "utf-8");
10589
10708
  return {
10590
10709
  filename,
10591
10710
  content,
@@ -10637,7 +10756,7 @@ ${project.content}`;
10637
10756
  }
10638
10757
  async function loadContextFiles(projectDir) {
10639
10758
  const errors = [];
10640
- const globalDir = path14.join(homedir4(), ".bike4mind");
10759
+ const globalDir = path15.join(homedir4(), ".bike4mind");
10641
10760
  const projectDirectory = projectDir || process.cwd();
10642
10761
  const [globalResult, projectResult] = await Promise.all([
10643
10762
  Promise.resolve(findContextFile(globalDir, GLOBAL_CONTEXT_FILES, "global")),
@@ -10673,8 +10792,8 @@ function substituteArguments(template, args) {
10673
10792
  // ../../b4m-core/packages/mcp/dist/src/client.js
10674
10793
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
10675
10794
  import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
10676
- import path15 from "path";
10677
- import { existsSync as existsSync8, readdirSync as readdirSync3 } from "fs";
10795
+ import path16 from "path";
10796
+ import { existsSync as existsSync9, readdirSync as readdirSync3 } from "fs";
10678
10797
  var MCPClient = class {
10679
10798
  // Note: This class handles MCP server communication with repository filtering
10680
10799
  mcp;
@@ -10714,18 +10833,18 @@ var MCPClient = class {
10714
10833
  const root = process.env.INIT_CWD || process.cwd();
10715
10834
  const candidatePaths = [
10716
10835
  // When running from SST Lambda with node_modules structure (copyFiles)
10717
- path15.join(root, `node_modules/@bike4mind/mcp/dist/src/${this.serverName}/index.js`),
10836
+ path16.join(root, `node_modules/@bike4mind/mcp/dist/src/${this.serverName}/index.js`),
10718
10837
  // When running from SST Lambda deployed environment (/var/task)
10719
- path15.join(root, `b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
10838
+ path16.join(root, `b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
10720
10839
  // When running from SST Lambda (.sst/artifacts/mcpHandler-dev), navigate to monorepo root (3 levels up)
10721
- path15.join(root, `../../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
10840
+ path16.join(root, `../../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
10722
10841
  // When running from packages/client (Next.js app), navigate to monorepo root (2 levels up)
10723
- path15.join(root, `../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
10842
+ path16.join(root, `../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
10724
10843
  // Original paths (backward compatibility)
10725
- path15.join(root, `/b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
10726
- path15.join(root, "core", "mcp", "servers", this.serverName, "dist", "index.js")
10844
+ path16.join(root, `/b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
10845
+ path16.join(root, "core", "mcp", "servers", this.serverName, "dist", "index.js")
10727
10846
  ];
10728
- const serverScriptPath = candidatePaths.find((p) => existsSync8(p));
10847
+ const serverScriptPath = candidatePaths.find((p) => existsSync9(p));
10729
10848
  if (!serverScriptPath) {
10730
10849
  const getDirectories = (source) => readdirSync3(source, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
10731
10850
  console.error(`[MCP] Server script not found. Tried paths:`, candidatePaths);
@@ -11134,6 +11253,7 @@ var ServerLlmBackend = class {
11134
11253
  let accumulatedText = "";
11135
11254
  let lastUsageInfo = {};
11136
11255
  let toolsUsed = [];
11256
+ let thinkingBlocks = [];
11137
11257
  let receivedDone = false;
11138
11258
  const parser = createParser({
11139
11259
  onEvent: (event) => {
@@ -11147,9 +11267,12 @@ var ServerLlmBackend = class {
11147
11267
  if (toolsUsed.length > 0) {
11148
11268
  const info = {
11149
11269
  toolsUsed,
11270
+ thinking: thinkingBlocks.length > 0 ? thinkingBlocks : void 0,
11150
11271
  ...lastUsageInfo
11151
11272
  };
11152
- logger.debug("[ServerLlmBackend] Calling callback with tools, will wait for completion");
11273
+ logger.debug(
11274
+ `[ServerLlmBackend] Calling callback with tools, thinking blocks: ${thinkingBlocks.length}`
11275
+ );
11153
11276
  callback([cleanedText], info).catch((err) => {
11154
11277
  logger.error("[ServerLlmBackend] Callback error:", err);
11155
11278
  reject(err);
@@ -11205,6 +11328,10 @@ var ServerLlmBackend = class {
11205
11328
  if (parsed.tools && parsed.tools.length > 0) {
11206
11329
  toolsUsed = parsed.tools;
11207
11330
  }
11331
+ if (parsed.thinking && parsed.thinking.length > 0) {
11332
+ thinkingBlocks = parsed.thinking;
11333
+ logger.debug(`[ServerLlmBackend] Received ${thinkingBlocks.length} thinking blocks`);
11334
+ }
11208
11335
  if (parsed.usage) {
11209
11336
  lastUsageInfo = {
11210
11337
  inputTokens: parsed.usage.inputTokens,
@@ -11527,7 +11654,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
11527
11654
  // package.json
11528
11655
  var package_default = {
11529
11656
  name: "@bike4mind/cli",
11530
- version: "0.2.11-fix-tool-pairing-integrity.17312+7bfc5c80f",
11657
+ version: "0.2.11-fix-cli-edit-file.17321+e2e930d6a",
11531
11658
  type: "module",
11532
11659
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
11533
11660
  license: "UNLICENSED",
@@ -11631,10 +11758,10 @@ var package_default = {
11631
11758
  },
11632
11759
  devDependencies: {
11633
11760
  "@bike4mind/agents": "0.1.0",
11634
- "@bike4mind/common": "2.40.1-fix-tool-pairing-integrity.17312+7bfc5c80f",
11635
- "@bike4mind/mcp": "1.20.5-fix-tool-pairing-integrity.17312+7bfc5c80f",
11636
- "@bike4mind/services": "2.35.1-fix-tool-pairing-integrity.17312+7bfc5c80f",
11637
- "@bike4mind/utils": "2.1.5-fix-tool-pairing-integrity.17312+7bfc5c80f",
11761
+ "@bike4mind/common": "2.40.1-fix-cli-edit-file.17321+e2e930d6a",
11762
+ "@bike4mind/mcp": "1.20.5-fix-cli-edit-file.17321+e2e930d6a",
11763
+ "@bike4mind/services": "2.35.1-fix-cli-edit-file.17321+e2e930d6a",
11764
+ "@bike4mind/utils": "2.1.5-fix-cli-edit-file.17321+e2e930d6a",
11638
11765
  "@types/better-sqlite3": "^7.6.13",
11639
11766
  "@types/diff": "^5.0.9",
11640
11767
  "@types/jsonwebtoken": "^9.0.4",
@@ -11647,7 +11774,7 @@ var package_default = {
11647
11774
  typescript: "^5.9.3",
11648
11775
  vitest: "^3.2.4"
11649
11776
  },
11650
- gitHead: "7bfc5c80fed342996ecbfb0c7974795bdaa75132"
11777
+ gitHead: "e2e930d6a6add8a7c1ffa5ebc415a82dabca82e9"
11651
11778
  };
11652
11779
 
11653
11780
  // src/config/constants.ts
@@ -11889,6 +12016,7 @@ Focus on:
11889
12016
  - Creating logical sequence of steps
11890
12017
  - Estimating scope and priorities
11891
12018
 
12019
+ You have read-only access to analyze code.
11892
12020
  You can explore the codebase to understand the current architecture before planning.
11893
12021
 
11894
12022
  Provide a structured plan that the main agent can execute.`,
@@ -12032,7 +12160,8 @@ function CliApp() {
12032
12160
  permissionPrompt: null,
12033
12161
  trustLocationSelector: null,
12034
12162
  rewindSelector: null,
12035
- sessionSelector: null
12163
+ sessionSelector: null,
12164
+ orchestrator: null
12036
12165
  });
12037
12166
  const [isInitialized, setIsInitialized] = useState8(false);
12038
12167
  const [initError, setInitError] = useState8(null);
@@ -12354,20 +12483,38 @@ Remember: Use context from previous messages to understand follow-up questions.$
12354
12483
  const lastIdx = pendingMessages.length - 1;
12355
12484
  if (lastIdx >= 0 && pendingMessages[lastIdx].role === "assistant") {
12356
12485
  const existingSteps = pendingMessages[lastIdx].metadata?.steps || [];
12486
+ const MAX_INPUT_LENGTH = 500;
12487
+ let truncatedStep = step;
12488
+ if (step.type === "action" && step.metadata?.toolInput) {
12489
+ const inputStr = typeof step.metadata.toolInput === "string" ? step.metadata.toolInput : JSON.stringify(step.metadata.toolInput);
12490
+ if (inputStr.length > MAX_INPUT_LENGTH) {
12491
+ const truncatedInput = inputStr.slice(0, MAX_INPUT_LENGTH) + `... (${inputStr.length - MAX_INPUT_LENGTH} more chars)`;
12492
+ truncatedStep = {
12493
+ ...step,
12494
+ metadata: {
12495
+ ...step.metadata,
12496
+ toolInput: truncatedInput
12497
+ }
12498
+ };
12499
+ }
12500
+ }
12357
12501
  updatePendingMessage(lastIdx, {
12358
12502
  ...pendingMessages[lastIdx],
12359
12503
  metadata: {
12360
12504
  ...pendingMessages[lastIdx].metadata,
12361
- steps: [...existingSteps, step]
12505
+ steps: [...existingSteps, truncatedStep]
12362
12506
  }
12363
12507
  });
12364
12508
  }
12365
12509
  };
12510
+ agent.on("thought", stepHandler);
12366
12511
  agent.on("action", stepHandler);
12367
12512
  orchestrator.setBeforeRunCallback((subagent, _subagentType) => {
12513
+ subagent.on("thought", stepHandler);
12368
12514
  subagent.on("action", stepHandler);
12369
12515
  });
12370
12516
  orchestrator.setAfterRunCallback((subagent, _subagentType) => {
12517
+ subagent.off("thought", stepHandler);
12371
12518
  subagent.off("action", stepHandler);
12372
12519
  });
12373
12520
  setState((prev) => ({
@@ -12378,8 +12525,10 @@ Remember: Use context from previous messages to understand follow-up questions.$
12378
12525
  permissionManager,
12379
12526
  config,
12380
12527
  // Store config for synchronous access
12381
- availableModels: models
12528
+ availableModels: models,
12382
12529
  // Store models for ConfigEditor
12530
+ orchestrator
12531
+ // Store orchestrator for step handler updates
12383
12532
  }));
12384
12533
  setStoreSession(newSession);
12385
12534
  setIsInitialized(true);
@@ -12434,6 +12583,7 @@ Remember: Use context from previous messages to understand follow-up questions.$
12434
12583
  }
12435
12584
  }
12436
12585
  };
12586
+ state.agent.on("thought", stepHandler);
12437
12587
  state.agent.on("action", stepHandler);
12438
12588
  try {
12439
12589
  let messageContent = fullTemplate;
@@ -12555,6 +12705,7 @@ Remember: Use context from previous messages to understand follow-up questions.$
12555
12705
  setState((prev) => ({ ...prev, session: sessionWithError }));
12556
12706
  setStoreSession(sessionWithError);
12557
12707
  } finally {
12708
+ state.agent.off("thought", stepHandler);
12558
12709
  state.agent.off("action", stepHandler);
12559
12710
  }
12560
12711
  };
@@ -12876,7 +13027,6 @@ Custom Commands:
12876
13027
  logger.debug("=== Session Resumed ===");
12877
13028
  setState((prev) => ({ ...prev, session: loadedSession }));
12878
13029
  setStoreSession(loadedSession);
12879
- useCliStore.getState().clearAgentSteps();
12880
13030
  useCliStore.getState().clearPendingMessages();
12881
13031
  usageCache = null;
12882
13032
  console.log(`
@@ -13112,7 +13262,6 @@ Custom Commands:
13112
13262
  logger.debug("=== New Session Started via /clear ===");
13113
13263
  setState((prev) => ({ ...prev, session: newSession }));
13114
13264
  setStoreSession(newSession);
13115
- useCliStore.getState().clearAgentSteps();
13116
13265
  useCliStore.getState().clearPendingMessages();
13117
13266
  usageCache = null;
13118
13267
  console.log("New session started.");
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-DJPXSSP4.js";
4
+ } from "./chunk-WCYNJOOX.js";
5
5
  import "./chunk-PDX44BCA.js";
6
6
 
7
7
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/llmMarkdownGenerator.js
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-DJPXSSP4.js";
4
+ } from "./chunk-WCYNJOOX.js";
5
5
  import "./chunk-PDX44BCA.js";
6
6
 
7
7
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/markdownGenerator.js
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  findMostSimilarMemento,
4
4
  getRelevantMementos
5
- } from "./chunk-MU4EEXAL.js";
6
- import "./chunk-TFONTTOE.js";
5
+ } from "./chunk-DGAIF2QC.js";
6
+ import "./chunk-SQBLLN7K.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
- import "./chunk-DJPXSSP4.js";
8
+ import "./chunk-WCYNJOOX.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  findMostSimilarMemento,
@@ -120,7 +120,7 @@ import {
120
120
  validateMermaidSyntax,
121
121
  warmUpSettingsCache,
122
122
  withRetry
123
- } from "./chunk-TFONTTOE.js";
123
+ } from "./chunk-SQBLLN7K.js";
124
124
  import {
125
125
  Logger,
126
126
  NotificationDeduplicator,
@@ -129,7 +129,7 @@ import {
129
129
  postLowCreditsNotificationToSlack,
130
130
  postMessageToSlack
131
131
  } from "./chunk-AMDXHL6S.js";
132
- import "./chunk-DJPXSSP4.js";
132
+ import "./chunk-WCYNJOOX.js";
133
133
  import "./chunk-PDX44BCA.js";
134
134
  export {
135
135
  AWSBackend,
@@ -293,7 +293,7 @@ import {
293
293
  validateQuestMasterArtifactV2,
294
294
  validateReactArtifactV2,
295
295
  validateSvgArtifactV2
296
- } from "./chunk-DJPXSSP4.js";
296
+ } from "./chunk-WCYNJOOX.js";
297
297
  import "./chunk-PDX44BCA.js";
298
298
  export {
299
299
  ALL_IMAGE_MODELS,
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  SubtractCreditsSchema,
4
4
  subtractCredits
5
- } from "./chunk-A3VAT7TT.js";
6
- import "./chunk-TFONTTOE.js";
5
+ } from "./chunk-RBZRTCAY.js";
6
+ import "./chunk-SQBLLN7K.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
- import "./chunk-DJPXSSP4.js";
8
+ import "./chunk-WCYNJOOX.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  SubtractCreditsSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.11-fix-tool-pairing-integrity.17312+7bfc5c80f",
3
+ "version": "0.2.11-fix-cli-edit-file.17321+e2e930d6a",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -104,10 +104,10 @@
104
104
  },
105
105
  "devDependencies": {
106
106
  "@bike4mind/agents": "0.1.0",
107
- "@bike4mind/common": "2.40.1-fix-tool-pairing-integrity.17312+7bfc5c80f",
108
- "@bike4mind/mcp": "1.20.5-fix-tool-pairing-integrity.17312+7bfc5c80f",
109
- "@bike4mind/services": "2.35.1-fix-tool-pairing-integrity.17312+7bfc5c80f",
110
- "@bike4mind/utils": "2.1.5-fix-tool-pairing-integrity.17312+7bfc5c80f",
107
+ "@bike4mind/common": "2.40.1-fix-cli-edit-file.17321+e2e930d6a",
108
+ "@bike4mind/mcp": "1.20.5-fix-cli-edit-file.17321+e2e930d6a",
109
+ "@bike4mind/services": "2.35.1-fix-cli-edit-file.17321+e2e930d6a",
110
+ "@bike4mind/utils": "2.1.5-fix-cli-edit-file.17321+e2e930d6a",
111
111
  "@types/better-sqlite3": "^7.6.13",
112
112
  "@types/diff": "^5.0.9",
113
113
  "@types/jsonwebtoken": "^9.0.4",
@@ -120,5 +120,5 @@
120
120
  "typescript": "^5.9.3",
121
121
  "vitest": "^3.2.4"
122
122
  },
123
- "gitHead": "7bfc5c80fed342996ecbfb0c7974795bdaa75132"
123
+ "gitHead": "e2e930d6a6add8a7c1ffa5ebc415a82dabca82e9"
124
124
  }