@bike4mind/cli 0.9.1 → 0.9.2

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 (27) hide show
  1. package/dist/{BubblewrapRuntime-BHbtqvLx.mjs → BubblewrapRuntime-CUD3bsgG.mjs} +1 -1
  2. package/dist/ProxyManager-DIAAw902.mjs +3 -0
  3. package/dist/{SandboxOrchestrator-CHZgSR3P.mjs → SandboxOrchestrator-C4oDqltp.mjs} +1 -1
  4. package/dist/{SandboxRuntimeAdapter-C1B4t20N.mjs → SandboxRuntimeAdapter-D1RUReNL.mjs} +2 -2
  5. package/dist/{SandboxRuntimeAdapter-D7UAG13n.mjs → SandboxRuntimeAdapter-DXa3nFOw.mjs} +1 -1
  6. package/dist/{SeatbeltRuntime-D4m0VOcD.mjs → SeatbeltRuntime-CTElMR9Q.mjs} +1 -1
  7. package/dist/commands/doctorCommand.mjs +13 -1
  8. package/dist/commands/headlessCommand.mjs +4 -4
  9. package/dist/commands/updateCommand.mjs +33 -15
  10. package/dist/{grepSearch-DMuEcUSq-D3RsGLCg.mjs → grepSearch-BxucZWO8-lPRv6R6F.mjs} +15 -26
  11. package/dist/index.mjs +72 -64
  12. package/dist/ripgrepCheck-DIu4apVE.mjs +39 -0
  13. package/dist/{tools-ICW0xW8W.mjs → tools-AWSBVqG5.mjs} +241 -18
  14. package/dist/{updateChecker-Dproz7j-.mjs → updateChecker-Bml_XTCM.mjs} +1 -1
  15. package/package.json +6 -6
  16. package/dist/ProxyManager-kiOD1X8-.mjs +0 -3
  17. /package/dist/{ImageStore-DaKT_Ew8.mjs → ImageStore-BFp_d12J.mjs} +0 -0
  18. /package/dist/{ProxyManager-Dl2nFk-A.mjs → ProxyManager-BsCoxpns.mjs} +0 -0
  19. /package/dist/{SandboxOrchestrator-BEW3rqYi.mjs → SandboxOrchestrator-B4GcZdBc.mjs} +0 -0
  20. /package/dist/{StderrViolationParser-D0afQ3-1.mjs → StderrViolationParser-BFP4bo7I.mjs} +0 -0
  21. /package/dist/{ViolationLogStore-CZl35HcA.mjs → ViolationLogStore-Dp6HF0nz.mjs} +0 -0
  22. /package/dist/{bashExecute-pYljpfPn-Bsh-jb3S.mjs → bashExecute-pYljpfPn-BZXHMQEl.mjs} +0 -0
  23. /package/dist/{createFile-C1JoeuYh-LvIRJtxM.mjs → createFile-C1JoeuYh-metInFKd.mjs} +0 -0
  24. /package/dist/{deleteFile-BTberNGj-BpBvrcoC.mjs → deleteFile-BTberNGj-CW922hRM.mjs} +0 -0
  25. /package/dist/{globFiles-Bez8QCbS-DyZsKEJB.mjs → globFiles-Bez8QCbS-DZb6McbJ.mjs} +0 -0
  26. /package/dist/{terminalSetup-rmr1P8KF.mjs → terminalSetup-DxloCowq.mjs} +0 -0
  27. /package/dist/{treeSitterEngine-BFTHnDwH.mjs → treeSitterEngine-Cw2LbVZT.mjs} +0 -0
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as isBinaryAvailable, r as expandPath } from "./SandboxRuntimeAdapter-C1B4t20N.mjs";
2
+ import { i as isBinaryAvailable, r as expandPath } from "./SandboxRuntimeAdapter-D1RUReNL.mjs";
3
3
  import os from "os";
4
4
  //#region src/sandbox/runtime/BubblewrapRuntime.ts
5
5
  /**
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { t as ProxyManager } from "./ProxyManager-BsCoxpns.mjs";
3
+ export { ProxyManager };
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { t as SandboxOrchestrator } from "./SandboxOrchestrator-BEW3rqYi.mjs";
2
+ import { t as SandboxOrchestrator } from "./SandboxOrchestrator-B4GcZdBc.mjs";
3
3
  export { SandboxOrchestrator };
@@ -42,12 +42,12 @@ async function createSandboxRuntime() {
42
42
  const platform = detectPlatform();
43
43
  if (!platform) return null;
44
44
  if (platform === "darwin") {
45
- const { SeatbeltRuntime } = await import("./SeatbeltRuntime-D4m0VOcD.mjs");
45
+ const { SeatbeltRuntime } = await import("./SeatbeltRuntime-CTElMR9Q.mjs");
46
46
  const runtime = new SeatbeltRuntime();
47
47
  return runtime.isAvailable() ? runtime : null;
48
48
  }
49
49
  if (platform === "linux") {
50
- const { BubblewrapRuntime } = await import("./BubblewrapRuntime-BHbtqvLx.mjs");
50
+ const { BubblewrapRuntime } = await import("./BubblewrapRuntime-CUD3bsgG.mjs");
51
51
  const runtime = new BubblewrapRuntime();
52
52
  return runtime.isAvailable() ? runtime : null;
53
53
  }
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { i as isBinaryAvailable, n as detectPlatform, r as expandPath, t as createSandboxRuntime } from "./SandboxRuntimeAdapter-C1B4t20N.mjs";
2
+ import { i as isBinaryAvailable, n as detectPlatform, r as expandPath, t as createSandboxRuntime } from "./SandboxRuntimeAdapter-D1RUReNL.mjs";
3
3
  export { createSandboxRuntime, detectPlatform, expandPath, isBinaryAvailable };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as isBinaryAvailable, r as expandPath } from "./SandboxRuntimeAdapter-C1B4t20N.mjs";
2
+ import { i as isBinaryAvailable, r as expandPath } from "./SandboxRuntimeAdapter-D1RUReNL.mjs";
3
3
  import { mkdtempSync, writeFileSync } from "fs";
4
4
  import os from "os";
5
5
  import path from "path";
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { a as version, n as compareSemver, r as fetchLatestVersion } from "../updateChecker-Dproz7j-.mjs";
2
+ import { a as version, n as compareSemver, r as fetchLatestVersion } from "../updateChecker-Bml_XTCM.mjs";
3
+ import { t as checkRipgrep } from "../ripgrepCheck-DIu4apVE.mjs";
3
4
  import { execSync } from "child_process";
4
5
  import { constants, existsSync, promises } from "fs";
5
6
  import { homedir } from "os";
@@ -74,6 +75,17 @@ async function handleDoctorCommand() {
74
75
  message: "Could not determine npm prefix"
75
76
  });
76
77
  }
78
+ const rg = await checkRipgrep();
79
+ if (rg.available) results.push({
80
+ name: "ripgrep (grep_search)",
81
+ status: "pass",
82
+ message: rg.path
83
+ });
84
+ else results.push({
85
+ name: "ripgrep (grep_search)",
86
+ status: "warn",
87
+ message: `${rg.error ?? "not found"} — run: b4m update`
88
+ });
77
89
  const configFile = path.join(homedir(), ".bike4mind", "config.json");
78
90
  if (existsSync(configFile)) results.push({
79
91
  name: "Config file",
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, I as generateCliTools, M as loadContextFiles, N as getApiUrl, O as McpManager, Q as CheckpointStore, S as ApiClient, T as FallbackLlmBackend, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, b as createSkillTool, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, m as createCoordinateTaskTool, p as createWriteTodosTool, q as buildSystemPrompt, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, y as SubagentOrchestrator } from "../tools-ICW0xW8W.mjs";
2
+ import { C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, I as generateCliTools, M as loadContextFiles, N as getApiUrl, O as McpManager, Q as CheckpointStore, S as ApiClient, T as FallbackLlmBackend, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, b as createSkillTool, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, m as createCoordinateTaskTool, p as createWriteTodosTool, q as buildSystemPrompt, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, y as SubagentOrchestrator } from "../tools-AWSBVqG5.mjs";
3
3
  import { n as logger, t as ConfigStore } from "../ConfigStore-CAKSUXCi.mjs";
4
4
  import { t as DEFAULT_SANDBOX_CONFIG } from "../types-DBEjF9YS.mjs";
5
- import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-C1B4t20N.mjs";
6
- import { t as SandboxOrchestrator } from "../SandboxOrchestrator-BEW3rqYi.mjs";
7
- import { t as ProxyManager } from "../ProxyManager-Dl2nFk-A.mjs";
5
+ import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-D1RUReNL.mjs";
6
+ import { t as SandboxOrchestrator } from "../SandboxOrchestrator-B4GcZdBc.mjs";
7
+ import { t as ProxyManager } from "../ProxyManager-BsCoxpns.mjs";
8
8
  import { randomBytes } from "crypto";
9
9
  import { v4 } from "uuid";
10
10
  //#region src/commands/headlessCommand.ts
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { a as version, i as forceCheckForUpdate } from "../updateChecker-Dproz7j-.mjs";
2
+ import { a as version, i as forceCheckForUpdate } from "../updateChecker-Bml_XTCM.mjs";
3
+ import { t as checkRipgrep } from "../ripgrepCheck-DIu4apVE.mjs";
3
4
  import { execSync } from "child_process";
4
5
  //#region src/commands/updateCommand.ts
5
6
  /**
@@ -7,6 +8,22 @@ import { execSync } from "child_process";
7
8
  * Checks for and installs CLI updates.
8
9
  * Runs outside the interactive CLI session.
9
10
  */
11
+ const INSTALL_CMD = "npm install -g @bike4mind/cli@latest";
12
+ function runGlobalInstall() {
13
+ try {
14
+ execSync(INSTALL_CMD, {
15
+ stdio: "inherit",
16
+ timeout: 12e4
17
+ });
18
+ return true;
19
+ } catch {
20
+ console.error("\nInstall failed. Try running manually:");
21
+ console.error(` ${INSTALL_CMD}`);
22
+ console.error("\nIf you get permission errors, try:");
23
+ console.error(` sudo ${INSTALL_CMD}`);
24
+ return false;
25
+ }
26
+ }
10
27
  async function handleUpdateCommand() {
11
28
  const currentVersion = version;
12
29
  console.log(`Current version: v${currentVersion}`);
@@ -16,25 +33,26 @@ async function handleUpdateCommand() {
16
33
  console.error("Failed to check for updates. Check your internet connection.");
17
34
  process.exit(1);
18
35
  }
19
- if (!result.updateAvailable) {
36
+ const rgBefore = await checkRipgrep();
37
+ const needsRepair = !rgBefore.available;
38
+ if (!result.updateAvailable && !needsRepair) {
20
39
  console.log(`Already on the latest version (v${currentVersion}).`);
21
40
  return;
22
41
  }
23
- console.log(`Update available: v${currentVersion} → v${result.latestVersion}\n`);
24
- console.log("Installing update...\n");
25
- try {
26
- execSync("npm install -g @bike4mind/cli@latest", {
27
- stdio: "inherit",
28
- timeout: 12e4
29
- });
30
- console.log(`\nSuccessfully updated to v${result.latestVersion}.`);
31
- } catch {
32
- console.error("\nUpdate failed. Try running manually:");
33
- console.error(" npm install -g @bike4mind/cli@latest");
34
- console.error("\nIf you get permission errors, try:");
35
- console.error(" sudo npm install -g @bike4mind/cli@latest");
42
+ if (result.updateAvailable) console.log(`Update available: v${currentVersion} → v${result.latestVersion}`);
43
+ if (needsRepair) console.log(`Repairing missing ripgrep binary (${rgBefore.error ?? "unknown reason"})`);
44
+ console.log("\nInstalling...\n");
45
+ if (!runGlobalInstall()) process.exit(1);
46
+ const rgAfter = await checkRipgrep();
47
+ if (!rgAfter.available) {
48
+ console.error("\nWarning: ripgrep is still unavailable after install.");
49
+ console.error(` ${rgAfter.error ?? "unknown reason"}`);
50
+ console.error("The grep_search tool will not work. Try a forced reinstall:");
51
+ console.error(` ${INSTALL_CMD} --force`);
36
52
  process.exit(1);
37
53
  }
54
+ if (result.updateAvailable) console.log(`\nSuccessfully updated to v${result.latestVersion}.`);
55
+ else console.log("\nRipgrep restored.");
38
56
  }
39
57
  //#endregion
40
58
  export { handleUpdateCommand };
@@ -1,42 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as isPathAllowed } from "./pathValidation-CIytuhr3-Dt5dntLx.mjs";
3
- import { execFile, execFileSync } from "child_process";
3
+ import { execFile } from "child_process";
4
4
  import { existsSync } from "fs";
5
5
  import path from "path";
6
6
  import { stat } from "fs/promises";
7
7
  import { promisify } from "util";
8
- import { createRequire } from "module";
9
- //#region ../../b4m-core/services/dist/grepSearch-DMuEcUSq.mjs
8
+ //#region ../../b4m-core/services/dist/grepSearch-BxucZWO8.mjs
10
9
  const execFileAsync = promisify(execFile);
11
- const require = createRequire(import.meta.url);
12
10
  /** Cached ripgrep binary path after first resolution */
13
11
  let cachedRgPath = null;
14
12
  /**
15
- * Get ripgrep binary path
16
- * This is an optional dependency (CLI-only), so we load it lazily.
17
- * If the binary is missing (postinstall was skipped), auto-downloads it.
13
+ * Resolve ripgrep binary path via the package's exported `rgPath`.
14
+ * `@vscode/ripgrep` is an optional dependency, so we load it lazily; in 1.18+
15
+ * the binary lives in a platform-specific sibling package and is resolved by
16
+ * the package itself — we just have to ask for it.
18
17
  */
19
- function getRipgrepPath() {
18
+ async function getRipgrepPath() {
20
19
  if (cachedRgPath) return cachedRgPath;
20
+ let rgPath;
21
21
  try {
22
- const ripgrepPath = require.resolve("@vscode/ripgrep");
23
- const ripgrepDir = path.dirname(ripgrepPath);
24
- const rgBinary = path.join(ripgrepDir, "..", "bin", "rg" + (process.platform === "win32" ? ".exe" : ""));
25
- if (!existsSync(rgBinary)) {
26
- const postinstallScript = path.join(ripgrepDir, "..", "lib", "postinstall.js");
27
- if (existsSync(postinstallScript)) execFileSync(process.execPath, [postinstallScript], {
28
- cwd: path.join(ripgrepDir, ".."),
29
- stdio: "pipe",
30
- timeout: 3e4
31
- });
32
- if (!existsSync(rgBinary)) throw new Error(`ripgrep binary not found at ${rgBinary}. The postinstall download may have failed. Try running: cd ${path.join(ripgrepDir, "..")} && node lib/postinstall.js`);
33
- }
34
- cachedRgPath = rgBinary;
35
- return rgBinary;
36
- } catch (error) {
37
- if (error instanceof Error && error.message.includes("ripgrep binary not found")) throw error;
38
- throw new Error("ripgrep is not available. Please install @vscode/ripgrep: pnpm add @vscode/ripgrep --filter @bike4mind/services");
22
+ ({rgPath} = await import("@vscode/ripgrep"));
23
+ } catch {
24
+ throw new Error("ripgrep is not available. Install the optional dependency: pnpm add @vscode/ripgrep --filter @bike4mind/services");
39
25
  }
26
+ if (!rgPath || !existsSync(rgPath)) throw new Error(`ripgrep binary not found at ${rgPath ?? "<unresolved>"}. Ensure @vscode/ripgrep platform optional dependencies are installed for ${process.platform}-${process.arch}.`);
27
+ cachedRgPath = rgPath;
28
+ return rgPath;
40
29
  }
41
30
  /**
42
31
  * Converts a glob pattern to ripgrep glob patterns
@@ -62,7 +51,7 @@ async function searchFiles(params, allowedDirectories) {
62
51
  if (error.code === "ENOENT") throw new Error(`Path does not exist: ${dir_path}`);
63
52
  throw error;
64
53
  }
65
- const rgPath = getRipgrepPath();
54
+ const rgPath = await getRipgrepPath();
66
55
  const rgArgs = [
67
56
  "--json",
68
57
  "--max-count",
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-DLduYYGR.mjs";
3
- import { $ as CommandHistoryStore, A as formatStep, B as DEFAULT_RETRY_CONFIG, C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, G as OllamaBackend, H as clearFeatureModuleTools, I as generateCliTools, J as buildSkillsPromptSection, K as getPlanModeFilePath, L as ALWAYS_DENIED_FOR_AGENTS, M as loadContextFiles, N as getApiUrl, O as McpManager, P as getEnvironmentName, Q as CheckpointStore, R as DEFAULT_AGENT_MODEL, S as ApiClient, T as FallbackLlmBackend, U as registerFeatureModuleTools, V as DEFAULT_THOROUGHNESS, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, a as createBlockerTools, at as mergeCommands, b as createSkillTool, c as createDecisionStore, ct as warmFileCache, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, i as createBlockerStore, it as searchCommands, j as extractCompactInstructions, k as substituteArguments, l as formatDecisionsOutput, m as createCoordinateTaskTool, n as createReviewGateTool, nt as hasFileReferences, o as formatBlockersOutput, ot as formatFileSize, p as createWriteTodosTool, q as buildSystemPrompt, r as formatReviewGatesOutput, rt as processFileReferences, s as createDecisionLogTool, st as searchFiles, t as createReviewGateStore, tt as OAuthClient, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, x as parseAgentConfig, y as SubagentOrchestrator, z as DEFAULT_MAX_ITERATIONS } from "./tools-ICW0xW8W.mjs";
3
+ import { $ as CommandHistoryStore, A as formatStep, B as DEFAULT_RETRY_CONFIG, C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, G as OllamaBackend, H as clearFeatureModuleTools, I as generateCliTools, J as buildSkillsPromptSection, K as getPlanModeFilePath, L as ALWAYS_DENIED_FOR_AGENTS, M as loadContextFiles, N as getApiUrl, O as McpManager, P as getEnvironmentName, Q as CheckpointStore, R as DEFAULT_AGENT_MODEL, S as ApiClient, T as FallbackLlmBackend, U as registerFeatureModuleTools, V as DEFAULT_THOROUGHNESS, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, a as createBlockerTools, at as mergeCommands, b as createSkillTool, c as createDecisionStore, ct as warmFileCache, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, i as createBlockerStore, it as searchCommands, j as extractCompactInstructions, k as substituteArguments, l as formatDecisionsOutput, m as createCoordinateTaskTool, n as createReviewGateTool, nt as hasFileReferences, o as formatBlockersOutput, ot as formatFileSize, p as createWriteTodosTool, q as buildSystemPrompt, r as formatReviewGatesOutput, rt as processFileReferences, s as createDecisionLogTool, st as searchFiles, t as createReviewGateStore, tt as OAuthClient, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, x as parseAgentConfig, y as SubagentOrchestrator, z as DEFAULT_MAX_ITERATIONS } from "./tools-AWSBVqG5.mjs";
4
4
  import { Nt as validateJupyterKernelName, Pt as validateNotebookPath$1, g as ChatModels, m as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore } from "./ConfigStore-CAKSUXCi.mjs";
5
- import { a as version, t as checkForUpdate } from "./updateChecker-Dproz7j-.mjs";
5
+ import { a as version, t as checkForUpdate } from "./updateChecker-Bml_XTCM.mjs";
6
6
  import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
7
7
  import { Box, Static, Text, render, useApp, useInput, usePaste, useStdout } from "ink";
8
8
  import { execSync } from "child_process";
@@ -2078,8 +2078,7 @@ const MessageItem = React.memo(function MessageItem({ message, showThoughts = tr
2078
2078
  const paddedUserPromptText = userPromptText.length >= terminalCols ? userPromptText : userPromptText.padEnd(terminalCols);
2079
2079
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, isUser && message.content && /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, {
2080
2080
  backgroundColor: "whiteBright",
2081
- color: "black",
2082
- wrap: "truncate-end"
2081
+ color: "black"
2083
2082
  }, paddedUserPromptText)), !isUser && message.metadata?.steps && message.metadata.steps.filter((s) => showThoughts && s.type === "thought" || s.type === "action").length > 0 && /* @__PURE__ */ React.createElement(Box, {
2084
2083
  paddingLeft: 2,
2085
2084
  flexDirection: "column",
@@ -5442,6 +5441,67 @@ function summarizeUserQuestion(payload) {
5442
5441
  const first = payload.questions?.[0]?.question;
5443
5442
  return first ? first.slice(0, 240) : void 0;
5444
5443
  }
5444
+ /**
5445
+ * Render the B4M ASCII banner with an optional startup log column to the right.
5446
+ * Used on startup and after /clear so the user always sees the banner at the
5447
+ * top of a fresh session.
5448
+ */
5449
+ function renderBanner(startupLog = []) {
5450
+ const bannerLines = [
5451
+ {
5452
+ text: "██████╗ ██╗ ██╗███╗ ███╗",
5453
+ ansi: "\x1B[36m\x1B[1m"
5454
+ },
5455
+ {
5456
+ text: "██╔══██╗██║ ██║████╗ ████║",
5457
+ ansi: "\x1B[36m\x1B[1m"
5458
+ },
5459
+ {
5460
+ text: "██████╔╝███████║██╔████╔██║",
5461
+ ansi: "\x1B[36m\x1B[1m"
5462
+ },
5463
+ {
5464
+ text: "██╔══██╗╚════██║██║╚██╔╝██║",
5465
+ ansi: "\x1B[36m\x1B[1m"
5466
+ },
5467
+ {
5468
+ text: "██████╔╝ ██║██║ ╚═╝ ██║",
5469
+ ansi: "\x1B[36m\x1B[1m"
5470
+ },
5471
+ {
5472
+ text: "╚═════╝ ╚═╝╚═╝ ╚═╝",
5473
+ ansi: "\x1B[36m\x1B[1m"
5474
+ },
5475
+ {
5476
+ text: "",
5477
+ ansi: ""
5478
+ },
5479
+ {
5480
+ text: `v${version} - AI-Powered CLI`,
5481
+ ansi: "\x1B[2m"
5482
+ },
5483
+ {
5484
+ text: "/help for more information",
5485
+ ansi: "\x1B[2m"
5486
+ }
5487
+ ];
5488
+ const bannerWidth = 30;
5489
+ const rightColWidth = (process.stdout.columns || 80) - bannerWidth - 2;
5490
+ const truncate = (str, max) => {
5491
+ if (str.length > max) return str.slice(0, max - 1) + "…";
5492
+ return str;
5493
+ };
5494
+ const totalLines = Math.max(bannerLines.length, startupLog.length);
5495
+ for (let i = 0; i < totalLines; i++) {
5496
+ const banner = bannerLines[i];
5497
+ const leftText = banner?.text || "";
5498
+ const leftAnsi = banner?.ansi || "";
5499
+ const right = startupLog[i] || "";
5500
+ const coloredLeft = leftText ? `${leftAnsi}${leftText}\x1b[0m` : "";
5501
+ const gap = " ".repeat(bannerWidth - leftText.length + 2);
5502
+ console.log(coloredLeft + gap + truncate(right, rightColWidth));
5503
+ }
5504
+ }
5445
5505
  let exitTimestamp = null;
5446
5506
  let exitInProgress = false;
5447
5507
  const EXIT_TIMEOUT_MS = 2e3;
@@ -5794,11 +5854,11 @@ function CliApp() {
5794
5854
  };
5795
5855
  const permissionManager = new PermissionManager(config.trustedTools || [], void 0, config.tools.disabled || []);
5796
5856
  const [{ createSandboxRuntime }, { SandboxOrchestrator }, { DEFAULT_SANDBOX_CONFIG }, { ProxyManager }, { ViolationLogStore }] = await Promise.all([
5797
- import("./SandboxRuntimeAdapter-D7UAG13n.mjs"),
5798
- import("./SandboxOrchestrator-CHZgSR3P.mjs"),
5857
+ import("./SandboxRuntimeAdapter-DXa3nFOw.mjs"),
5858
+ import("./SandboxOrchestrator-C4oDqltp.mjs"),
5799
5859
  import("./types-DK3P88Px.mjs"),
5800
- import("./ProxyManager-kiOD1X8-.mjs"),
5801
- import("./ViolationLogStore-CZl35HcA.mjs")
5860
+ import("./ProxyManager-DIAAw902.mjs"),
5861
+ import("./ViolationLogStore-Dp6HF0nz.mjs")
5802
5862
  ]);
5803
5863
  const sandboxConfig = config.sandbox ?? DEFAULT_SANDBOX_CONFIG;
5804
5864
  const checkpointStore = new CheckpointStore(state.configStore.getProjectConfigDir() || process.cwd());
@@ -6170,60 +6230,7 @@ function CliApp() {
6170
6230
  featureRegistry
6171
6231
  }));
6172
6232
  setStoreSession(newSession);
6173
- const bannerLines = [
6174
- {
6175
- text: "██████╗ ██╗ ██╗███╗ ███╗",
6176
- ansi: "\x1B[36m\x1B[1m"
6177
- },
6178
- {
6179
- text: "██╔══██╗██║ ██║████╗ ████║",
6180
- ansi: "\x1B[36m\x1B[1m"
6181
- },
6182
- {
6183
- text: "██████╔╝███████║██╔████╔██║",
6184
- ansi: "\x1B[36m\x1B[1m"
6185
- },
6186
- {
6187
- text: "██╔══██╗╚════██║██║╚██╔╝██║",
6188
- ansi: "\x1B[36m\x1B[1m"
6189
- },
6190
- {
6191
- text: "██████╔╝ ██║██║ ╚═╝ ██║",
6192
- ansi: "\x1B[36m\x1B[1m"
6193
- },
6194
- {
6195
- text: "╚═════╝ ╚═╝╚═╝ ╚═╝",
6196
- ansi: "\x1B[36m\x1B[1m"
6197
- },
6198
- {
6199
- text: "",
6200
- ansi: ""
6201
- },
6202
- {
6203
- text: `v${version} - AI-Powered CLI`,
6204
- ansi: "\x1B[2m"
6205
- },
6206
- {
6207
- text: "/help for more information",
6208
- ansi: "\x1B[2m"
6209
- }
6210
- ];
6211
- const bannerWidth = 30;
6212
- const rightColWidth = (process.stdout.columns || 80) - bannerWidth - 2;
6213
- const truncate = (str, max) => {
6214
- if (str.length > max) return str.slice(0, max - 1) + "…";
6215
- return str;
6216
- };
6217
- const totalLines = Math.max(bannerLines.length, startupLog.length);
6218
- for (let i = 0; i < totalLines; i++) {
6219
- const banner = bannerLines[i];
6220
- const leftText = banner?.text || "";
6221
- const leftAnsi = banner?.ansi || "";
6222
- const right = startupLog[i] || "";
6223
- const coloredLeft = leftText ? `${leftAnsi}${leftText}\x1b[0m` : "";
6224
- const gap = " ".repeat(bannerWidth - leftText.length + 2);
6225
- console.log(coloredLeft + gap + truncate(right, rightColWidth));
6226
- }
6233
+ renderBanner(startupLog);
6227
6234
  setIsInitialized(true);
6228
6235
  console.log("");
6229
6236
  } catch (error) {
@@ -6868,7 +6875,7 @@ function CliApp() {
6868
6875
  let imageStore = state.imageStore;
6869
6876
  if (!imageStore) {
6870
6877
  if (!imageStoreInitPromise.current) imageStoreInitPromise.current = (async () => {
6871
- const { ImageStore: ImageStoreClass } = await import("./ImageStore-DaKT_Ew8.mjs");
6878
+ const { ImageStore: ImageStoreClass } = await import("./ImageStore-BFp_d12J.mjs");
6872
6879
  const newImageStore = new ImageStoreClass();
6873
6880
  setState((prev) => ({
6874
6881
  ...prev,
@@ -7475,6 +7482,7 @@ Multi-line Input:
7475
7482
  case "clear":
7476
7483
  case "new": {
7477
7484
  console.clear();
7485
+ renderBanner();
7478
7486
  const model = state.session?.model || state.config?.defaultModel || ChatModels.CLAUDE_4_5_SONNET;
7479
7487
  const newSession = {
7480
7488
  id: v4(),
@@ -8146,7 +8154,7 @@ Multi-line Input:
8146
8154
  break;
8147
8155
  }
8148
8156
  case "terminal-setup": {
8149
- const { runTerminalSetup } = await import("./terminalSetup-rmr1P8KF.mjs");
8157
+ const { runTerminalSetup } = await import("./terminalSetup-DxloCowq.mjs");
8150
8158
  await runTerminalSetup();
8151
8159
  break;
8152
8160
  }
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ import { access, constants } from "fs/promises";
3
+ //#region src/utils/ripgrepCheck.ts
4
+ /**
5
+ * Probe `@vscode/ripgrep` the same way `grep_search` does: dynamic-import the
6
+ * package, take its exported `rgPath`, and verify it's executable on disk.
7
+ * The package is an optional dependency, so any failure mode (missing package,
8
+ * missing platform sibling, missing binary) is reported as `available: false`.
9
+ */
10
+ async function checkRipgrep() {
11
+ let rgPath;
12
+ try {
13
+ ({rgPath} = await import("@vscode/ripgrep"));
14
+ } catch (err) {
15
+ return {
16
+ available: false,
17
+ error: err instanceof Error ? err.message : String(err)
18
+ };
19
+ }
20
+ if (!rgPath) return {
21
+ available: false,
22
+ error: "@vscode/ripgrep did not export rgPath"
23
+ };
24
+ try {
25
+ await access(rgPath, constants.X_OK);
26
+ return {
27
+ available: true,
28
+ path: rgPath
29
+ };
30
+ } catch {
31
+ return {
32
+ available: false,
33
+ path: rgPath,
34
+ error: `binary not executable at ${rgPath}`
35
+ };
36
+ }
37
+ }
38
+ //#endregion
39
+ export { checkRipgrep as t };
@@ -83,7 +83,6 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
83
83
  import { fileURLToPath } from "url";
84
84
  import WsWebSocket from "ws";
85
85
  import { createParser } from "eventsource-parser";
86
- import { createRequire } from "module";
87
86
  //#region src/utils/fileSearch.ts
88
87
  /**
89
88
  * Load gitignore rules from project root
@@ -2286,6 +2285,31 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
2286
2285
  return this.iterations;
2287
2286
  }
2288
2287
  /**
2288
+ * Surgically replace the observation content of the most recent tool_result
2289
+ * message matching `toolCallId`. Used to inject a Lambda-dispatched
2290
+ * subagent's terminal answer into the parent's message history without
2291
+ * appending a new message (Anthropic rejects consecutive user-role messages,
2292
+ * so we replace the placeholder observation in place).
2293
+ *
2294
+ * Throws if the underlying backend doesn't support this surgery or if no
2295
+ * matching message is found.
2296
+ */
2297
+ replaceLastToolResultObservation(toolCallId, newObservation) {
2298
+ if (!this.context.llm.replaceLastToolResultObservation) throw new Error(`ReActAgent.replaceLastToolResultObservation: backend (${this.context.llm.currentModel}) does not implement replaceLastToolResultObservation — cannot resume after subagent handoff`);
2299
+ this.context.llm.replaceLastToolResultObservation(this.messages, toolCallId, newObservation);
2300
+ }
2301
+ /**
2302
+ * Locate the LLM-assigned id of the most recent tool call with the given name.
2303
+ * Delegates to the backend so each provider's message shape (Anthropic
2304
+ * content-block `tool_use` vs OpenAI `assistant.tool_calls`) is handled
2305
+ * correctly. Returns `undefined` if the backend doesn't implement the lookup
2306
+ * or no matching call exists.
2307
+ */
2308
+ getLatestToolCallId(toolName) {
2309
+ if (!this.context.llm.getLatestToolCallId) return void 0;
2310
+ return this.context.llm.getLatestToolCallId(this.messages, toolName);
2311
+ }
2312
+ /**
2289
2313
  * Serialize the agent's current execution state for persistence.
2290
2314
  *
2291
2315
  * Call this after each iteration to create a durable checkpoint that can
@@ -2884,6 +2908,153 @@ function trimConversationHistory(messages, maxIterations, protectedPrefixCount)
2884
2908
  const keepFrom = dynamicStart + nudgeIndices[nudgeIndices.length - maxIterations];
2885
2909
  messages.splice(dynamicStart, keepFrom - dynamicStart);
2886
2910
  }
2911
+ String.raw`
2912
+ const { parentPort } = require('node:worker_threads');
2913
+ const vm = require('node:vm');
2914
+
2915
+ const STDOUT_HEAD_BYTES = ${5e3};
2916
+ const STDOUT_TAIL_BYTES = ${2e3};
2917
+ const HARD_PER_LINE_BYTES = ${5e4};
2918
+
2919
+ let stdoutChunks = [];
2920
+ let stdoutBytes = 0;
2921
+ let truncated = false;
2922
+ function captureLine(args) {
2923
+ const line = args.map(a => {
2924
+ if (typeof a === 'string') return a;
2925
+ if (a === undefined) return 'undefined';
2926
+ if (a === null) return 'null';
2927
+ try { return JSON.stringify(a, jsonReplacer, 2); } catch { return String(a); }
2928
+ }).join(' ');
2929
+ const capped = line.length > HARD_PER_LINE_BYTES
2930
+ ? line.slice(0, HARD_PER_LINE_BYTES) + ' [...line truncated]'
2931
+ : line;
2932
+ stdoutChunks.push(capped);
2933
+ stdoutBytes += capped.length + 1;
2934
+ }
2935
+ function jsonReplacer(_k, v) {
2936
+ if (v instanceof Error) return { name: v.name, message: v.message };
2937
+ if (typeof v === 'bigint') return v.toString() + 'n';
2938
+ return v;
2939
+ }
2940
+ function collectStdout() {
2941
+ const joined = stdoutChunks.join('\n');
2942
+ if (joined.length <= STDOUT_HEAD_BYTES + STDOUT_TAIL_BYTES) return joined;
2943
+ truncated = true;
2944
+ const head = joined.slice(0, STDOUT_HEAD_BYTES);
2945
+ const tail = joined.slice(joined.length - STDOUT_TAIL_BYTES);
2946
+ const elidedBytes = joined.length - STDOUT_HEAD_BYTES - STDOUT_TAIL_BYTES;
2947
+ return head + '\n[...' + elidedBytes + ' bytes truncated...]\n' + tail;
2948
+ }
2949
+
2950
+ const sandbox = {
2951
+ console: {
2952
+ log: (...a) => captureLine(a),
2953
+ warn: (...a) => captureLine(a),
2954
+ error: (...a) => captureLine(a),
2955
+ info: (...a) => captureLine(a),
2956
+ },
2957
+ Math, JSON, Date, RegExp, Error, TypeError, RangeError, Promise,
2958
+ Array, Object, String, Number, Boolean, Map, Set, WeakMap, WeakSet, Symbol,
2959
+ // Number coercion / validation builtins — kept in sync with ReplContext
2960
+ // sandbox so worker and in-process backends behave identically.
2961
+ parseInt, parseFloat, isNaN, isFinite,
2962
+ structuredClone: globalThis.structuredClone,
2963
+ };
2964
+ // strings: false disables eval / new Function inside the worker context.
2965
+ // Same posture as the in-process ReplContext (Ken's P2 #2).
2966
+ const ctx = vm.createContext(sandbox, { codeGeneration: { strings: false, wasm: false } });
2967
+
2968
+ // Tool stubs: each in-REPL call posts a toolCall and awaits matching toolResult.
2969
+ let nextToolCallId = 0;
2970
+ const pendingToolCalls = new Map();
2971
+ function makeToolStub(name) {
2972
+ return (...args) => {
2973
+ const id = nextToolCallId++;
2974
+ return new Promise((resolve, reject) => {
2975
+ pendingToolCalls.set(id, { resolve, reject });
2976
+ // Args go through structured cloning. Functions, classes, etc. don't
2977
+ // survive the boundary — that's fine for our tool surface.
2978
+ try {
2979
+ parentPort.postMessage({ type: 'toolCall', id, name, args });
2980
+ } catch (e) {
2981
+ pendingToolCalls.delete(id);
2982
+ reject(new Error('postMessage failed for tool ' + name + ': ' + (e && e.message)));
2983
+ }
2984
+ });
2985
+ };
2986
+ }
2987
+ function setToolStubs(toolNames) {
2988
+ for (const name of toolNames) {
2989
+ sandbox[name] = makeToolStub(name);
2990
+ }
2991
+ }
2992
+
2993
+ function serializeError(e) {
2994
+ if (e instanceof Error) {
2995
+ const stack = e.stack ? '\n' + e.stack.split('\n').slice(0, 6).join('\n') : '';
2996
+ return e.name + ': ' + e.message + stack;
2997
+ }
2998
+ const t = typeof e;
2999
+ if (t === 'object' && e !== null) {
3000
+ let s = '';
3001
+ try { s = JSON.stringify(e); } catch { s = '[unserializable]'; }
3002
+ if (s === '{}' || s === '[]') {
3003
+ const ctor = (e && e.constructor && e.constructor.name) || 'Object';
3004
+ return '[non-Error throw: empty ' + ctor + ' — likely \`throw {}\` or thrown DOM exception]';
3005
+ }
3006
+ return '[non-Error throw: ' + s.slice(0, 500) + ']';
3007
+ }
3008
+ return '[' + t + ' throw: ' + String(e).slice(0, 200) + ']';
3009
+ }
3010
+
3011
+ let timeoutMsDefault = 30000;
3012
+
3013
+ parentPort.on('message', async (msg) => {
3014
+ if (msg.type === 'init') {
3015
+ timeoutMsDefault = msg.timeoutMs || 30000;
3016
+ setToolStubs(msg.toolNames || []);
3017
+ parentPort.postMessage({ type: 'ready' });
3018
+ return;
3019
+ }
3020
+ if (msg.type === 'setTools') {
3021
+ setToolStubs(msg.toolNames || []);
3022
+ return;
3023
+ }
3024
+ if (msg.type === 'toolResult') {
3025
+ const pending = pendingToolCalls.get(msg.id);
3026
+ if (!pending) return;
3027
+ pendingToolCalls.delete(msg.id);
3028
+ if (msg.ok) pending.resolve(msg.value);
3029
+ else pending.reject(new Error(msg.error || 'tool call failed'));
3030
+ return;
3031
+ }
3032
+ if (msg.type === 'runCode') {
3033
+ const t0 = Date.now();
3034
+ stdoutChunks = []; stdoutBytes = 0; truncated = false;
3035
+ let error = null;
3036
+ const wrapped = '(async () => {\n' + msg.code + '\n})()';
3037
+ try {
3038
+ const promise = vm.runInContext(wrapped, ctx, {
3039
+ timeout: msg.timeoutMs || timeoutMsDefault,
3040
+ displayErrors: true,
3041
+ });
3042
+ await promise;
3043
+ } catch (e) {
3044
+ error = serializeError(e);
3045
+ }
3046
+ parentPort.postMessage({
3047
+ type: 'runResult',
3048
+ id: msg.id,
3049
+ stdout: collectStdout(),
3050
+ error,
3051
+ truncated,
3052
+ durationMs: Date.now() - t0,
3053
+ });
3054
+ return;
3055
+ }
3056
+ });
3057
+ `;
2887
3058
  //#endregion
2888
3059
  //#region src/config/toolSafety.ts
2889
3060
  /**
@@ -3055,7 +3226,7 @@ function buildPlanModePromptSection(planModeFilePath) {
3055
3226
 
3056
3227
  The user has cycled into plan mode (Shift+Tab). Plan mode restricts WRITING, not READING. You still have a complete read toolkit — use it.
3057
3228
 
3058
- **Tools available in plan mode (use these aggressively):**
3229
+ **Tools available in plan mode:**
3059
3230
  - \`grep_search\` — find symbols, strings, patterns across files
3060
3231
  - \`glob_files\` — list files by pattern (use this instead of \`ls\` / \`find\`)
3061
3232
  - \`file_read\` — read file contents
@@ -3080,8 +3251,8 @@ Ground every claim in files you have actually read. Do not write pseudocode in c
3080
3251
  Follow this phased workflow. Do not skip phases.
3081
3252
 
3082
3253
  ### Phase 1 — Understand
3083
- - Read the relevant code before forming opinions. Use grep_search / glob_files / file_read directly for narrow lookups.
3084
- - For broad or uncertain scope, delegate to the 'explore' subagent via agent_delegate so the main context stays focused.
3254
+ - **Default to delegation.** For any task touching more than 2-3 files, delegate to the 'explore' subagent via agent_delegate *first*. Read directly only for narrow single-file lookups or to verify a specific line after the subagent reports back.
3255
+ - **Read budget: each file at most once.** If you've used ~5 read tools and still feel uncertain about scope, the spec is ambiguous call ask_user_question instead of reading more. Additional reads will not resolve ambiguity; they will just bloat context.
3085
3256
  - Identify what already exists vs. what needs to be built. Reuse existing functions and patterns rather than proposing new ones.
3086
3257
 
3087
3258
  ### Phase 2 — Clarify (REQUIRED if anything is ambiguous)
@@ -3389,6 +3560,42 @@ function isWriteTargetingPlanFile(toolName, args, cwd = process.cwd()) {
3389
3560
  return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
3390
3561
  }
3391
3562
  //#endregion
3563
+ //#region ../../b4m-core/utils/dist/llm/backend.mjs
3564
+ /**
3565
+ * Shared implementation for OpenAI-style backends that store separate
3566
+ * `role: 'tool'` messages with `tool_call_id`. Mutates in place.
3567
+ */
3568
+ function replaceLastToolResultObservationOpenAI(messages, toolCallId, newObservation) {
3569
+ for (let i = messages.length - 1; i >= 0; i--) {
3570
+ const msg = messages[i];
3571
+ if (msg.role === "tool" && msg.tool_call_id === toolCallId) {
3572
+ msg.content = newObservation;
3573
+ return;
3574
+ }
3575
+ }
3576
+ throw new Error(`replaceLastToolResultObservation: no role=tool message with tool_call_id="${toolCallId}" found in messages`);
3577
+ }
3578
+ /**
3579
+ * Shared implementation for `getLatestToolCallId` on OpenAI-style backends.
3580
+ * Scans assistant messages backwards for a `tool_calls` array (set by
3581
+ * `pushToolMessages`) containing a function call with matching `name`.
3582
+ *
3583
+ * Tie-break: when a single assistant message contains multiple matching calls
3584
+ * (parallel tool use), this returns the LAST entry in `tool_calls` array order.
3585
+ * Callers that need to disambiguate between parallel calls must track the id
3586
+ * at dispatch time rather than recover it from history.
3587
+ */
3588
+ function getLatestToolCallIdOpenAI(messages, toolName) {
3589
+ for (let i = messages.length - 1; i >= 0; i--) {
3590
+ const msg = messages[i];
3591
+ if (msg.role !== "assistant" || !Array.isArray(msg.tool_calls)) continue;
3592
+ for (let j = msg.tool_calls.length - 1; j >= 0; j--) {
3593
+ const call = msg.tool_calls[j];
3594
+ if (call.function?.name === toolName && call.id) return call.id;
3595
+ }
3596
+ }
3597
+ }
3598
+ //#endregion
3392
3599
  //#region ../../b4m-core/utils/dist/imageGeneration/AIImageService.mjs
3393
3600
  /**
3394
3601
  * Abstract class for AI Image Service
@@ -5534,6 +5741,12 @@ var OpenAIBackend = class {
5534
5741
  tool_call_id: tool.id
5535
5742
  });
5536
5743
  }
5744
+ replaceLastToolResultObservation(messages, toolCallId, newObservation) {
5745
+ replaceLastToolResultObservationOpenAI(messages, toolCallId, newObservation);
5746
+ }
5747
+ getLatestToolCallId(messages, toolName) {
5748
+ return getLatestToolCallIdOpenAI(messages, toolName);
5749
+ }
5537
5750
  formatTools(tools = []) {
5538
5751
  return tools.map((tool) => ({
5539
5752
  type: "function",
@@ -18429,11 +18642,11 @@ function parseQuery(query) {
18429
18642
  */
18430
18643
  const getCliOnlyTools = async () => {
18431
18644
  const [{ createFileTool }, { globFilesTool }, { grepSearchTool }, { deleteFileTool }, { bashExecuteTool }] = await Promise.all([
18432
- import("./createFile-C1JoeuYh-LvIRJtxM.mjs"),
18433
- import("./globFiles-Bez8QCbS-DyZsKEJB.mjs"),
18434
- import("./grepSearch-DMuEcUSq-D3RsGLCg.mjs"),
18435
- import("./deleteFile-BTberNGj-BpBvrcoC.mjs"),
18436
- import("./bashExecute-pYljpfPn-Bsh-jb3S.mjs")
18645
+ import("./createFile-C1JoeuYh-metInFKd.mjs"),
18646
+ import("./globFiles-Bez8QCbS-DZb6McbJ.mjs"),
18647
+ import("./grepSearch-BxucZWO8-lPRv6R6F.mjs"),
18648
+ import("./deleteFile-BTberNGj-CW922hRM.mjs"),
18649
+ import("./bashExecute-pYljpfPn-BZXHMQEl.mjs")
18437
18650
  ]);
18438
18651
  return {
18439
18652
  file_read: fileReadTool,
@@ -19089,7 +19302,7 @@ function cleanupSandboxFiles(paths) {
19089
19302
  */
19090
19303
  async function captureViolations(isSandboxed, result, command, orchestrator) {
19091
19304
  if (!isSandboxed || !orchestrator || !command) return;
19092
- const { parseSandboxStderr, toSandboxViolations } = await import("./StderrViolationParser-D0afQ3-1.mjs");
19305
+ const { parseSandboxStderr, toSandboxViolations } = await import("./StderrViolationParser-BFP4bo7I.mjs");
19093
19306
  const parsed = parseSandboxStderr(result);
19094
19307
  if (parsed.length > 0) {
19095
19308
  const violations = toSandboxViolations(parsed, command);
@@ -23522,7 +23735,8 @@ function createTodoStore(onUpdate) {
23522
23735
  //#endregion
23523
23736
  //#region src/tools/findDefinitionTool.ts
23524
23737
  const execFileAsync = promisify(execFile);
23525
- const require = createRequire(import.meta.url);
23738
+ /** Cached ripgrep binary path after first resolution */
23739
+ let cachedRgPath = null;
23526
23740
  const VALID_KINDS = [
23527
23741
  "class",
23528
23742
  "function",
@@ -23566,14 +23780,23 @@ const KIND_KEYWORDS = {
23566
23780
  ]
23567
23781
  };
23568
23782
  const ALL_KEYWORDS = Object.values(KIND_KEYWORDS).flat();
23569
- function getRipgrepPath() {
23783
+ /**
23784
+ * Resolve ripgrep binary path via the package's exported `rgPath`.
23785
+ * `@vscode/ripgrep` is an optional dependency, so we load it lazily; in 1.18+
23786
+ * the binary lives in a platform-specific sibling package and is resolved by
23787
+ * the package itself — we just have to ask for it.
23788
+ */
23789
+ async function getRipgrepPath() {
23790
+ if (cachedRgPath) return cachedRgPath;
23791
+ let rgPath;
23570
23792
  try {
23571
- const ripgrepPath = require.resolve("@vscode/ripgrep");
23572
- const ripgrepDir = path.dirname(ripgrepPath);
23573
- return path.join(ripgrepDir, "..", "bin", "rg" + (process.platform === "win32" ? ".exe" : ""));
23793
+ ({rgPath} = await import("@vscode/ripgrep"));
23574
23794
  } catch {
23575
- throw new Error("ripgrep is not available. Please install @vscode/ripgrep: pnpm add @vscode/ripgrep --filter @bike4mind/services");
23795
+ throw new Error("ripgrep is not available. Install the optional dependency: pnpm add @vscode/ripgrep --filter @bike4mind/cli");
23576
23796
  }
23797
+ if (!rgPath || !existsSync(rgPath)) throw new Error(`ripgrep binary not found at ${rgPath ?? "<unresolved>"}. Ensure @vscode/ripgrep platform optional dependencies are installed for ${process.platform}-${process.arch}.`);
23798
+ cachedRgPath = rgPath;
23799
+ return rgPath;
23577
23800
  }
23578
23801
  function isPathWithinWorkspace(targetPath, baseCwd) {
23579
23802
  const resolvedTarget = path.resolve(targetPath);
@@ -23627,7 +23850,7 @@ async function findDefinitions(params) {
23627
23850
  if (error.code === "ENOENT") throw new Error(`Path does not exist: ${search_path}`);
23628
23851
  throw error;
23629
23852
  }
23630
- const rgPath = getRipgrepPath();
23853
+ const rgPath = await getRipgrepPath();
23631
23854
  const rgArgs = [
23632
23855
  "--json",
23633
23856
  "--max-count",
@@ -23804,7 +24027,7 @@ function createGetFileStructureTool() {
23804
24027
  if (stats.isDirectory()) return `Error: Path is a directory, not a file: ${params.path}`;
23805
24028
  if (stats.size > MAX_FILE_SIZE) return `Error: File too large (${(stats.size / 1024 / 1024).toFixed(2)}MB). Max: ${MAX_FILE_SIZE / 1024 / 1024}MB`;
23806
24029
  const ext = path.extname(resolvedPath).toLowerCase();
23807
- const { getLanguageForExtension, parseFileStructure, getSupportedLanguages } = await import("./treeSitterEngine-BFTHnDwH.mjs");
24030
+ const { getLanguageForExtension, parseFileStructure, getSupportedLanguages } = await import("./treeSitterEngine-Cw2LbVZT.mjs");
23808
24031
  const languageId = getLanguageForExtension(ext);
23809
24032
  if (!languageId) return `Error: Unsupported file type "${ext}". Supported languages: ${getSupportedLanguages().join(", ")}`;
23810
24033
  const sourceCode = await promises.readFile(resolvedPath, "utf-8");
@@ -4,7 +4,7 @@ import { homedir } from "os";
4
4
  import path from "path";
5
5
  import axios from "axios";
6
6
  //#region package.json
7
- var version = "0.9.1";
7
+ var version = "0.9.2";
8
8
  //#endregion
9
9
  //#region src/utils/updateChecker.ts
10
10
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -121,11 +121,11 @@
121
121
  "tsx": "^4.21.0",
122
122
  "typescript": "^5.9.3",
123
123
  "vitest": "^4.1.2",
124
- "@bike4mind/agents": "0.8.3",
125
- "@bike4mind/common": "2.94.0",
126
- "@bike4mind/mcp": "1.37.7",
127
- "@bike4mind/services": "2.82.0",
128
- "@bike4mind/utils": "2.20.0"
124
+ "@bike4mind/agents": "0.9.0",
125
+ "@bike4mind/common": "2.95.0",
126
+ "@bike4mind/mcp": "1.37.8",
127
+ "@bike4mind/services": "2.83.0",
128
+ "@bike4mind/utils": "2.21.0"
129
129
  },
130
130
  "optionalDependencies": {
131
131
  "@vscode/ripgrep": "^1.17.1"
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- import { t as ProxyManager } from "./ProxyManager-Dl2nFk-A.mjs";
3
- export { ProxyManager };