@bike4mind/cli 0.2.10-fix-b4m-cli-flicker.17230 → 0.2.10-fix-b4m-cli-flicker.17243

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.
Files changed (2) hide show
  1. package/dist/index.js +121 -48
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -79,23 +79,24 @@ import {
79
79
  } from "./chunk-PDX44BCA.js";
80
80
 
81
81
  // src/index.tsx
82
- import React17, { useState as useState7, useEffect as useEffect3, useCallback, useRef } from "react";
82
+ import React17, { useState as useState8, useEffect as useEffect3, useCallback, useRef as useRef2 } from "react";
83
83
  import { render, Box as Box16, Text as Text16, useApp, useInput as useInput6 } from "ink";
84
+ import { execSync } from "child_process";
84
85
  import { v4 as uuidv49 } from "uuid";
85
86
 
86
87
  // src/components/App.tsx
87
- import React11 from "react";
88
+ import React11, { useState as useState4 } from "react";
88
89
  import { Box as Box10, Text as Text10, Static } from "ink";
89
90
 
90
91
  // src/components/StatusBar.tsx
91
92
  import React from "react";
92
93
  import { Box, Text } from "ink";
93
94
  var StatusBar = React.memo(function StatusBar2({ sessionName, model, tokenUsage }) {
94
- return /* @__PURE__ */ React.createElement(Box, { borderStyle: "single", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { gap: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "green", bold: true }, "\u{1F4DD} Session:"), /* @__PURE__ */ React.createElement(Text, null, sessionName)), /* @__PURE__ */ React.createElement(Box, { gap: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "blue", bold: true }, "\u{1F916} Model:"), /* @__PURE__ */ React.createElement(Text, null, model)), /* @__PURE__ */ React.createElement(Box, { gap: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "yellow", bold: true }, "\u{1F4CA} Tokens:"), /* @__PURE__ */ React.createElement(Text, null, tokenUsage.toLocaleString()))));
95
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", justifyContent: "space-between", width: "100%", paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, sessionName), /* @__PURE__ */ React.createElement(Box, { gap: 2 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, tokenUsage.toLocaleString(), " tokens"), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, model)));
95
96
  });
96
97
 
97
98
  // src/components/InputPrompt.tsx
98
- import React5, { useState as useState2, useMemo, useEffect } from "react";
99
+ import React5, { useState as useState2, useMemo, useEffect, useRef } from "react";
99
100
  import { Box as Box4, Text as Text5, useInput as useInput2 } from "ink";
100
101
 
101
102
  // src/components/CustomTextInput.tsx
@@ -732,17 +733,19 @@ function findAtTrigger(value) {
732
733
  }
733
734
  function InputPrompt({
734
735
  onSubmit,
736
+ onBashCommand,
735
737
  onImageDetected,
736
738
  disabled = false,
737
739
  history = [],
738
740
  prefillInput,
739
- onPrefillConsumed
741
+ onPrefillConsumed,
742
+ onBashModeChange
740
743
  }) {
741
744
  const [value, setValue] = useState2("");
742
745
  const [selectedIndex, setSelectedIndex] = useState2(0);
743
746
  const [historyIndex, setHistoryIndex] = useState2(-1);
744
747
  const [tempInput, setTempInput] = useState2("");
745
- const [inputKey, setInputKey] = useState2(0);
748
+ const inputKey = useRef(0);
746
749
  useEffect(() => {
747
750
  if (prefillInput) {
748
751
  setValue(prefillInput);
@@ -751,6 +754,10 @@ function InputPrompt({
751
754
  }, [prefillInput, onPrefillConsumed]);
752
755
  const [fileAutocomplete, setFileAutocomplete] = useState2(null);
753
756
  const [fileSelectedIndex, setFileSelectedIndex] = useState2(0);
757
+ const isBashMode = value.startsWith("!");
758
+ useEffect(() => {
759
+ onBashModeChange?.(isBashMode);
760
+ }, [isBashMode, onBashModeChange]);
754
761
  const shouldShowCommandAutocomplete = value.startsWith("/") && !disabled && !fileAutocomplete?.active;
755
762
  const commandQuery = shouldShowCommandAutocomplete ? value.slice(1) : "";
756
763
  const filteredCommands = useMemo(() => {
@@ -857,6 +864,16 @@ function InputPrompt({
857
864
  onSubmit(commandText);
858
865
  return;
859
866
  }
867
+ if (isBashMode && onBashCommand) {
868
+ const command = input.slice(1).trim();
869
+ if (command) {
870
+ onBashCommand(command);
871
+ setValue("");
872
+ setHistoryIndex(-1);
873
+ setFileAutocomplete(null);
874
+ }
875
+ return;
876
+ }
860
877
  onSubmit(input);
861
878
  setValue("");
862
879
  setHistoryIndex(-1);
@@ -887,14 +904,19 @@ function InputPrompt({
887
904
  setFileAutocomplete(null);
888
905
  }
889
906
  };
890
- return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { bold: true, color: "cyan" }, "> "), /* @__PURE__ */ React5.createElement(
907
+ const getPlaceholder = () => {
908
+ if (disabled) return "Thinking...";
909
+ if (isBashMode) return "Enter shell command to execute...";
910
+ return "Type your message, /help for commands, @file to reference, or ! for bash";
911
+ };
912
+ return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { bold: true, color: isBashMode ? "yellow" : "cyan" }, isBashMode ? "$ " : "> "), /* @__PURE__ */ React5.createElement(
891
913
  CustomTextInput,
892
914
  {
893
- key: inputKey,
915
+ key: inputKey.current,
894
916
  value,
895
917
  onChange: handleChange,
896
918
  onSubmit: handleSubmit,
897
- placeholder: disabled ? "" : "Type your message, /help for commands, or @file to reference",
919
+ placeholder: getPlaceholder(),
898
920
  showCursor: !disabled
899
921
  }
900
922
  )), shouldShowCommandAutocomplete && /* @__PURE__ */ React5.createElement(CommandAutocomplete, { commands: filteredCommands, selectedIndex }), fileAutocomplete?.active && /* @__PURE__ */ React5.createElement(FileAutocomplete, { files: filteredFiles, selectedIndex: fileSelectedIndex, query: fileAutocomplete.query }));
@@ -918,6 +940,16 @@ var useCliStore = create((set) => ({
918
940
  // Session state
919
941
  session: null,
920
942
  setSession: (session) => set({ session }),
943
+ addMessage: (message) => set((state) => {
944
+ if (!state.session) return state;
945
+ return {
946
+ session: {
947
+ ...state.session,
948
+ messages: [...state.session.messages, message],
949
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
950
+ }
951
+ };
952
+ }),
921
953
  // Pending messages
922
954
  pendingMessages: [],
923
955
  addPendingMessage: (message) => set((state) => ({ pendingMessages: [...state.pendingMessages, message] })),
@@ -1245,7 +1277,7 @@ import React10 from "react";
1245
1277
  import { Box as Box9, Text as Text9 } from "ink";
1246
1278
  function MessageItem({ message }) {
1247
1279
  const isUser = message.role === "user";
1248
- return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text9, { bold: true, color: isUser ? "cyan" : "green" }, isUser ? "\u{1F464} You" : "\u{1F916} Assistant"), /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), isUser && message.content && /* @__PURE__ */ React10.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React10.createElement(Text9, { backgroundColor: "whiteBright", color: "black" }, " ", message.content, " ")), !isUser && message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React10.createElement(Box9, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true, bold: true }, "\u{1F527} Agent Reasoning Trace (", message.metadata.steps.filter((s) => s.type === "action").length, " ", "tools used, ", message.metadata.steps.length, " total steps)", message.metadata.tokenUsage && ` \u2022 ${message.metadata.tokenUsage.total} tokens`), /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
1280
+ return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text9, { bold: true, color: isUser ? "cyan" : "green" }, isUser ? "\u{1F464} You" : "\u{1F916} Assistant"), isUser && /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), isUser && message.content && /* @__PURE__ */ React10.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React10.createElement(Text9, { backgroundColor: "whiteBright", color: "black" }, " ", message.content, " ")), !isUser && message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React10.createElement(Box9, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true, bold: true }, "\u{1F527} Agent Reasoning Trace (", message.metadata.steps.filter((s) => s.type === "action").length, " ", "tools used, ", message.metadata.steps.length, " total steps)", message.metadata.tokenUsage && ` \u2022 ${message.metadata.tokenUsage.total} tokens`), /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
1249
1281
  if (step.type === "thought") {
1250
1282
  return /* @__PURE__ */ React10.createElement(Box9, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text9, { color: "blue" }, "\u{1F4AD} Thought:"), /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, ` ${step.content.slice(0, 200)}${step.content.length > 200 ? "..." : ""}`));
1251
1283
  }
@@ -1378,6 +1410,7 @@ function hasFileReferences(message) {
1378
1410
  function App({
1379
1411
  onMessage,
1380
1412
  onCommand,
1413
+ onBashCommand,
1381
1414
  onPermissionResponse,
1382
1415
  onImageDetected,
1383
1416
  commandHistory = [],
@@ -1398,6 +1431,7 @@ function App({
1398
1431
  const setShowConfigEditor = useCliStore((state) => state.setShowConfigEditor);
1399
1432
  const exitRequested = useCliStore((state) => state.exitRequested);
1400
1433
  const setIsThinking = useCliStore((state) => state.setIsThinking);
1434
+ const [isBashMode, setIsBashMode] = useState4(false);
1401
1435
  const handleSubmit = React11.useCallback(
1402
1436
  async (input) => {
1403
1437
  const trimmed = input.trim();
@@ -1444,17 +1478,19 @@ ${errorBlock}`;
1444
1478
  canBeTrusted: permissionPrompt.canBeTrusted,
1445
1479
  onResponse: onPermissionResponse
1446
1480
  }
1447
- )) : /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Static, { items: messages }, (message, index) => /* @__PURE__ */ React11.createElement(Box10, { key: `${message.timestamp}-${message.role}-${index}`, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(MessageItem, { message }))), /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, pendingMessages.map((message, index) => /* @__PURE__ */ React11.createElement(Box10, { key: `pending-${message.timestamp}-${index}`, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(MessageItem, { message })))), /* @__PURE__ */ React11.createElement(AgentThinking, null), exitRequested && /* @__PURE__ */ React11.createElement(Box10, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "yellow", bold: true }, "Press Ctrl+C again to exit")), /* @__PURE__ */ React11.createElement(StatusBar, { sessionName, model: currentModel, tokenUsage: totalTokens }), /* @__PURE__ */ React11.createElement(Box10, { borderStyle: "single", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React11.createElement(
1481
+ )) : /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Static, { items: messages }, (message, index) => /* @__PURE__ */ React11.createElement(Box10, { key: `${message.timestamp}-${message.role}-${index}`, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(MessageItem, { message }))), /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, pendingMessages.map((message, index) => /* @__PURE__ */ React11.createElement(Box10, { key: `pending-${message.timestamp}-${index}`, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(MessageItem, { message })))), /* @__PURE__ */ React11.createElement(AgentThinking, null), exitRequested && /* @__PURE__ */ React11.createElement(Box10, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "yellow", bold: true }, "Press Ctrl+C again to exit")), /* @__PURE__ */ React11.createElement(Box10, { borderStyle: "single", borderColor: isBashMode ? "yellow" : "cyan", paddingX: 1 }, /* @__PURE__ */ React11.createElement(
1448
1482
  InputPrompt,
1449
1483
  {
1450
1484
  onSubmit: handleSubmit,
1485
+ onBashCommand,
1451
1486
  onImageDetected,
1452
1487
  disabled: isThinking,
1453
1488
  history: commandHistory,
1454
1489
  prefillInput,
1455
- onPrefillConsumed
1490
+ onPrefillConsumed,
1491
+ onBashModeChange: setIsBashMode
1456
1492
  }
1457
- ))));
1493
+ )), /* @__PURE__ */ React11.createElement(StatusBar, { sessionName, model: currentModel, tokenUsage: totalTokens })));
1458
1494
  }
1459
1495
 
1460
1496
  // src/components/MessageList.tsx
@@ -1530,12 +1566,12 @@ function TrustLocationSelector({ inProject, onSelect, onCancel }) {
1530
1566
  }
1531
1567
 
1532
1568
  // src/components/RewindSelector.tsx
1533
- import React14, { useState as useState4 } from "react";
1569
+ import React14, { useState as useState5 } from "react";
1534
1570
  import { Box as Box13, Text as Text13, useInput as useInput4 } from "ink";
1535
1571
  import SelectInput3 from "ink-select-input";
1536
1572
  function RewindSelector({ messages, onSelect, onCancel }) {
1537
- const [step, setStep] = useState4("selection");
1538
- const [selectedMessageIndex, setSelectedMessageIndex] = useState4(null);
1573
+ const [step, setStep] = useState5("selection");
1574
+ const [selectedMessageIndex, setSelectedMessageIndex] = useState5(null);
1539
1575
  useInput4((input, key) => {
1540
1576
  if (key.escape) {
1541
1577
  if (step === "confirmation") {
@@ -1599,12 +1635,12 @@ function RewindSelector({ messages, onSelect, onCancel }) {
1599
1635
  }
1600
1636
 
1601
1637
  // src/components/SessionSelector.tsx
1602
- import React15, { useState as useState5 } from "react";
1638
+ import React15, { useState as useState6 } from "react";
1603
1639
  import { Box as Box14, Text as Text14, useInput as useInput5 } from "ink";
1604
1640
  import SelectInput4 from "ink-select-input";
1605
1641
  function SessionSelector({ sessions, currentSession, onSelect, onCancel }) {
1606
- const [step, setStep] = useState5("selection");
1607
- const [selectedSession, setSelectedSession] = useState5(null);
1642
+ const [step, setStep] = useState6("selection");
1643
+ const [selectedSession, setSelectedSession] = useState6(null);
1608
1644
  useInput5((input, key) => {
1609
1645
  if (key.escape) {
1610
1646
  if (step === "confirmation") {
@@ -1662,7 +1698,7 @@ function SessionSelector({ sessions, currentSession, onSelect, onCancel }) {
1662
1698
  }
1663
1699
 
1664
1700
  // src/components/LoginFlow.tsx
1665
- import React16, { useState as useState6, useEffect as useEffect2 } from "react";
1701
+ import React16, { useState as useState7, useEffect as useEffect2 } from "react";
1666
1702
  import { Box as Box15, Text as Text15 } from "ink";
1667
1703
  import Spinner2 from "ink-spinner";
1668
1704
  import jwt from "jsonwebtoken";
@@ -1779,10 +1815,10 @@ var OAuthClient = class {
1779
1815
 
1780
1816
  // src/components/LoginFlow.tsx
1781
1817
  function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, onError }) {
1782
- const [status, setStatus] = useState6("initiating");
1783
- const [deviceFlow, setDeviceFlow] = useState6(null);
1784
- const [statusMessage, setStatusMessage] = useState6("Initiating device authorization...");
1785
- const [error, setError] = useState6(null);
1818
+ const [status, setStatus] = useState7("initiating");
1819
+ const [deviceFlow, setDeviceFlow] = useState7(null);
1820
+ const [statusMessage, setStatusMessage] = useState7("Initiating device authorization...");
1821
+ const [error, setError] = useState7(null);
1786
1822
  useEffect2(() => {
1787
1823
  const runLoginFlow = async () => {
1788
1824
  const oauth = new OAuthClient(apiUrl);
@@ -9685,6 +9721,7 @@ var Logger2 = class _Logger {
9685
9721
  }
9686
9722
  };
9687
9723
  var logger = Logger2.getInstance();
9724
+ logger.setVerbose(process.env.B4M_VERBOSE === "1");
9688
9725
 
9689
9726
  // src/llm/ServerToolExecutor.ts
9690
9727
  var ServerToolExecutor = class {
@@ -11113,7 +11150,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
11113
11150
  // package.json
11114
11151
  var package_default = {
11115
11152
  name: "@bike4mind/cli",
11116
- version: "0.2.10-fix-b4m-cli-flicker.17230+316343590",
11153
+ version: "0.2.10-fix-b4m-cli-flicker.17243+cbbca593a",
11117
11154
  type: "module",
11118
11155
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
11119
11156
  license: "UNLICENSED",
@@ -11216,10 +11253,10 @@ var package_default = {
11216
11253
  },
11217
11254
  devDependencies: {
11218
11255
  "@bike4mind/agents": "0.1.0",
11219
- "@bike4mind/common": "2.39.1-fix-b4m-cli-flicker.17230+316343590",
11220
- "@bike4mind/mcp": "1.20.4-fix-b4m-cli-flicker.17230+316343590",
11221
- "@bike4mind/services": "2.34.2-fix-b4m-cli-flicker.17230+316343590",
11222
- "@bike4mind/utils": "2.1.4-fix-b4m-cli-flicker.17230+316343590",
11256
+ "@bike4mind/common": "2.39.1-fix-b4m-cli-flicker.17243+cbbca593a",
11257
+ "@bike4mind/mcp": "1.20.4-fix-b4m-cli-flicker.17243+cbbca593a",
11258
+ "@bike4mind/services": "2.34.2-fix-b4m-cli-flicker.17243+cbbca593a",
11259
+ "@bike4mind/utils": "2.1.4-fix-b4m-cli-flicker.17243+cbbca593a",
11223
11260
  "@types/better-sqlite3": "^7.6.13",
11224
11261
  "@types/diff": "^5.0.9",
11225
11262
  "@types/jsonwebtoken": "^9.0.4",
@@ -11232,7 +11269,7 @@ var package_default = {
11232
11269
  typescript: "^5.9.3",
11233
11270
  vitest: "^3.2.4"
11234
11271
  },
11235
- gitHead: "316343590be145ba6cfa891271ed491b27f9c7d0"
11272
+ gitHead: "cbbca593a8f5107d0ff9ca4a7911de7616a61a91"
11236
11273
  };
11237
11274
 
11238
11275
  // src/config/constants.ts
@@ -11254,7 +11291,7 @@ var usageCache = null;
11254
11291
  function CliApp() {
11255
11292
  const { exit } = useApp();
11256
11293
  const imageRenderer = new ImageRenderer();
11257
- const [state, setState] = useState7({
11294
+ const [state, setState] = useState8({
11258
11295
  session: null,
11259
11296
  sessionStore: new SessionStore(),
11260
11297
  configStore: new ConfigStore(),
@@ -11271,10 +11308,10 @@ function CliApp() {
11271
11308
  rewindSelector: null,
11272
11309
  sessionSelector: null
11273
11310
  });
11274
- const [isInitialized, setIsInitialized] = useState7(false);
11275
- const [initError, setInitError] = useState7(null);
11276
- const [commandHistory, setCommandHistory] = useState7([]);
11277
- const imageStoreInitPromise = useRef(null);
11311
+ const [isInitialized, setIsInitialized] = useState8(false);
11312
+ const [initError, setInitError] = useState8(null);
11313
+ const [commandHistory, setCommandHistory] = useState8([]);
11314
+ const imageStoreInitPromise = useRef2(null);
11278
11315
  const setStoreSession = useCliStore((state2) => state2.setSession);
11279
11316
  const setPermissionPrompt = useCliStore((state2) => state2.setPermissionPrompt);
11280
11317
  const setShowConfigEditor = useCliStore((state2) => state2.setShowConfigEditor);
@@ -11396,13 +11433,11 @@ function CliApp() {
11396
11433
  if (models.length === 0) {
11397
11434
  throw new Error("No models available from server.");
11398
11435
  }
11399
- console.log(`\u{1F4CB} Available models: ${models.map((m) => m.id).join(", ")}`);
11436
+ logger.debug(`\u{1F4CB} Available models: ${models.map((m) => m.id).join(", ")}`);
11400
11437
  const modelInfo = models.find((m) => m.id === config.defaultModel) || models[0];
11401
11438
  if (modelInfo.id !== config.defaultModel) {
11402
- console.log(`\u26A0\uFE0F Requested model '${config.defaultModel}' not available`);
11403
- console.log(`\u{1F916} Using fallback model: ${modelInfo.id}`);
11404
- } else {
11405
- console.log(`\u{1F916} Using model: ${modelInfo.id}`);
11439
+ logger.warn(`\u26A0\uFE0F Requested model '${config.defaultModel}' not available`);
11440
+ logger.warn(`\u{1F916} Using fallback model: ${modelInfo.id}`);
11406
11441
  }
11407
11442
  llm.currentModel = modelInfo.id;
11408
11443
  const newSession = {
@@ -11421,9 +11456,6 @@ function CliApp() {
11421
11456
  };
11422
11457
  await logger.initialize(newSession.id);
11423
11458
  logger.setVerbose(process.env.B4M_VERBOSE === "1");
11424
- logger.info(`API: ${apiBaseURL}`);
11425
- logger.info(`Environment: ${envName}`);
11426
- logger.info(`Model: ${modelInfo.id}`);
11427
11459
  logger.debug("=== Session Configuration Complete ===");
11428
11460
  logger.cleanupOldLogs().catch(() => {
11429
11461
  });
@@ -11472,7 +11504,7 @@ function CliApp() {
11472
11504
  state.configStore,
11473
11505
  apiClient
11474
11506
  );
11475
- console.log(`\u{1F6E0}\uFE0F Loaded ${b4mTools.length} B4M tool(s)`);
11507
+ console.log(`\u{1F6E0}\uFE0F Loaded ${b4mTools.length} B4M tool(s)`);
11476
11508
  const mcpManager = new McpManager(config);
11477
11509
  await mcpManager.initialize();
11478
11510
  const mcpTools = mcpManager.getTools();
@@ -11483,7 +11515,6 @@ function CliApp() {
11483
11515
  });
11484
11516
  }
11485
11517
  const allTools = [...b4mTools, ...mcpTools];
11486
- console.log(`\u2705 Total: ${allTools.length} tool(s) available`);
11487
11518
  const projectDir = state.configStore.getProjectConfigDir();
11488
11519
  const contextResult = await loadContextFiles(projectDir);
11489
11520
  if (contextResult.globalContext) {
@@ -11559,6 +11590,7 @@ Remember: Use context from previous messages to understand follow-up questions.$
11559
11590
  }));
11560
11591
  setStoreSession(newSession);
11561
11592
  setIsInitialized(true);
11593
+ console.log("\n");
11562
11594
  } catch (error) {
11563
11595
  console.error("Initialization error:", error);
11564
11596
  setInitError(error instanceof Error ? error.message : "Unknown error");
@@ -11687,6 +11719,46 @@ Remember: Use context from previous messages to understand follow-up questions.$
11687
11719
  state.agent.off("action", stepHandler);
11688
11720
  }
11689
11721
  };
11722
+ const handleBashCommand = useCallback(
11723
+ (command) => {
11724
+ if (!state.session) return;
11725
+ let output;
11726
+ let isError = false;
11727
+ try {
11728
+ output = execSync(command, {
11729
+ encoding: "utf-8",
11730
+ stdio: ["pipe", "pipe", "pipe"],
11731
+ cwd: process.cwd(),
11732
+ maxBuffer: 10 * 1024 * 1024
11733
+ // 10MB buffer
11734
+ });
11735
+ } catch (error) {
11736
+ const execError = error;
11737
+ output = execError.stderr || execError.message || "Command failed";
11738
+ isError = true;
11739
+ }
11740
+ const userMessage = {
11741
+ role: "user",
11742
+ content: `$ ${command}`,
11743
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
11744
+ };
11745
+ const assistantMessage = {
11746
+ role: "assistant",
11747
+ content: isError ? `\u274C Error:
11748
+ ${output}` : output.trim() || "(no output)",
11749
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
11750
+ };
11751
+ const updatedSession = {
11752
+ ...state.session,
11753
+ messages: [...state.session.messages, userMessage, assistantMessage],
11754
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
11755
+ };
11756
+ setState((prev) => ({ ...prev, session: updatedSession }));
11757
+ setStoreSession(updatedSession);
11758
+ state.sessionStore.save(updatedSession);
11759
+ },
11760
+ [state.session, state.sessionStore]
11761
+ );
11690
11762
  const handleImageDetected = async (imageData) => {
11691
11763
  try {
11692
11764
  let imageStore = state.imageStore;
@@ -12359,6 +12431,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
12359
12431
  {
12360
12432
  onMessage: handleMessage,
12361
12433
  onCommand: handleCommand,
12434
+ onBashCommand: handleBashCommand,
12362
12435
  onImageDetected: handleImageDetected,
12363
12436
  commandHistory,
12364
12437
  config: state.config,
@@ -12387,11 +12460,11 @@ var BANNER = `
12387
12460
  \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
12388
12461
  `;
12389
12462
  console.log("\x1B[36m\x1B[1m%s\x1B[0m", BANNER);
12390
- console.log(`\x1B[2m v${package_default.version} - AI-Powered CLI\x1B[0m
12391
- `);
12463
+ console.log(`\x1B[2m v${package_default.version} - AI-Powered CLI\x1B[0m`);
12464
+ console.log(" /help for more information\n");
12392
12465
  var isDevMode = import.meta.url.includes("/src/") || process.env.NODE_ENV === "development";
12393
12466
  if (isDevMode) {
12394
- console.log("\u{1F527} Running in development mode (using TypeScript source)\n");
12467
+ logger.debug("\u{1F527} Running in development mode (using TypeScript source)\n");
12395
12468
  }
12396
12469
  render(/* @__PURE__ */ React17.createElement(CliApp, null), {
12397
12470
  exitOnCtrlC: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.10-fix-b4m-cli-flicker.17230+316343590",
3
+ "version": "0.2.10-fix-b4m-cli-flicker.17243+cbbca593a",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -103,10 +103,10 @@
103
103
  },
104
104
  "devDependencies": {
105
105
  "@bike4mind/agents": "0.1.0",
106
- "@bike4mind/common": "2.39.1-fix-b4m-cli-flicker.17230+316343590",
107
- "@bike4mind/mcp": "1.20.4-fix-b4m-cli-flicker.17230+316343590",
108
- "@bike4mind/services": "2.34.2-fix-b4m-cli-flicker.17230+316343590",
109
- "@bike4mind/utils": "2.1.4-fix-b4m-cli-flicker.17230+316343590",
106
+ "@bike4mind/common": "2.39.1-fix-b4m-cli-flicker.17243+cbbca593a",
107
+ "@bike4mind/mcp": "1.20.4-fix-b4m-cli-flicker.17243+cbbca593a",
108
+ "@bike4mind/services": "2.34.2-fix-b4m-cli-flicker.17243+cbbca593a",
109
+ "@bike4mind/utils": "2.1.4-fix-b4m-cli-flicker.17243+cbbca593a",
110
110
  "@types/better-sqlite3": "^7.6.13",
111
111
  "@types/diff": "^5.0.9",
112
112
  "@types/jsonwebtoken": "^9.0.4",
@@ -119,5 +119,5 @@
119
119
  "typescript": "^5.9.3",
120
120
  "vitest": "^3.2.4"
121
121
  },
122
- "gitHead": "316343590be145ba6cfa891271ed491b27f9c7d0"
122
+ "gitHead": "cbbca593a8f5107d0ff9ca4a7911de7616a61a91"
123
123
  }