@bike4mind/cli 0.9.0 → 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.
- package/dist/{BubblewrapRuntime-BHbtqvLx.mjs → BubblewrapRuntime-CUD3bsgG.mjs} +1 -1
- package/dist/ProxyManager-DIAAw902.mjs +3 -0
- package/dist/{SandboxOrchestrator-CHZgSR3P.mjs → SandboxOrchestrator-C4oDqltp.mjs} +1 -1
- package/dist/{SandboxRuntimeAdapter-C1B4t20N.mjs → SandboxRuntimeAdapter-D1RUReNL.mjs} +2 -2
- package/dist/{SandboxRuntimeAdapter-D7UAG13n.mjs → SandboxRuntimeAdapter-DXa3nFOw.mjs} +1 -1
- package/dist/{SeatbeltRuntime-D4m0VOcD.mjs → SeatbeltRuntime-CTElMR9Q.mjs} +1 -1
- package/dist/commands/doctorCommand.mjs +13 -1
- package/dist/commands/headlessCommand.mjs +4 -4
- package/dist/commands/updateCommand.mjs +33 -15
- package/dist/{grepSearch-DMuEcUSq-D3RsGLCg.mjs → grepSearch-BxucZWO8-lPRv6R6F.mjs} +15 -26
- package/dist/index.mjs +87 -80
- package/dist/ripgrepCheck-DIu4apVE.mjs +39 -0
- package/dist/{tools-B0Y_zziv.mjs → tools-AWSBVqG5.mjs} +251 -20
- package/dist/{updateChecker-CtczXQeW.mjs → updateChecker-Bml_XTCM.mjs} +1 -1
- package/package.json +6 -6
- package/dist/ProxyManager-kiOD1X8-.mjs +0 -3
- /package/dist/{ImageStore-DaKT_Ew8.mjs → ImageStore-BFp_d12J.mjs} +0 -0
- /package/dist/{ProxyManager-Dl2nFk-A.mjs → ProxyManager-BsCoxpns.mjs} +0 -0
- /package/dist/{SandboxOrchestrator-BEW3rqYi.mjs → SandboxOrchestrator-B4GcZdBc.mjs} +0 -0
- /package/dist/{StderrViolationParser-D0afQ3-1.mjs → StderrViolationParser-BFP4bo7I.mjs} +0 -0
- /package/dist/{ViolationLogStore-CZl35HcA.mjs → ViolationLogStore-Dp6HF0nz.mjs} +0 -0
- /package/dist/{bashExecute-pYljpfPn-Bsh-jb3S.mjs → bashExecute-pYljpfPn-BZXHMQEl.mjs} +0 -0
- /package/dist/{createFile-C1JoeuYh-LvIRJtxM.mjs → createFile-C1JoeuYh-metInFKd.mjs} +0 -0
- /package/dist/{deleteFile-BTberNGj-BpBvrcoC.mjs → deleteFile-BTberNGj-CW922hRM.mjs} +0 -0
- /package/dist/{globFiles-Bez8QCbS-DyZsKEJB.mjs → globFiles-Bez8QCbS-DZb6McbJ.mjs} +0 -0
- /package/dist/{terminalSetup-rmr1P8KF.mjs → terminalSetup-DxloCowq.mjs} +0 -0
- /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-
|
|
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
|
/**
|
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
6
|
-
import { t as SandboxOrchestrator } from "../SandboxOrchestrator-
|
|
7
|
-
import { t as ProxyManager } from "../ProxyManager-
|
|
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-
|
|
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
|
-
|
|
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}
|
|
24
|
-
console.log("
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
console.
|
|
31
|
-
|
|
32
|
-
console.error(
|
|
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
|
|
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
|
-
|
|
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
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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-
|
|
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-
|
|
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";
|
|
@@ -1022,7 +1022,7 @@ function renderDiffPreview(preview) {
|
|
|
1022
1022
|
}, line);
|
|
1023
1023
|
});
|
|
1024
1024
|
}
|
|
1025
|
-
const TOOLS_WITH_HIDDEN_ARGS$1 = new Set(["edit_local_file"]);
|
|
1025
|
+
const TOOLS_WITH_HIDDEN_ARGS$1 = new Set(["edit_local_file", "bash_execute"]);
|
|
1026
1026
|
/**
|
|
1027
1027
|
* Permission prompt component
|
|
1028
1028
|
*
|
|
@@ -2075,11 +2075,10 @@ const MessageItem = React.memo(function MessageItem({ message, showThoughts = tr
|
|
|
2075
2075
|
const { stdout } = useStdout();
|
|
2076
2076
|
const terminalCols = stdout?.columns ?? 80;
|
|
2077
2077
|
const userPromptText = `❯ ${message.content}`;
|
|
2078
|
-
const paddedUserPromptText = userPromptText.length >= terminalCols
|
|
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",
|
|
@@ -2209,15 +2208,13 @@ function App({ onMessage, onBackgroundCompletion, onCommand, onBashCommand, onPe
|
|
|
2209
2208
|
onClose: () => setShowMcpViewer(false)
|
|
2210
2209
|
})) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Static, { items: messages }, (message) => /* @__PURE__ */ React.createElement(Box, {
|
|
2211
2210
|
key: message.id,
|
|
2212
|
-
flexDirection: "column"
|
|
2213
|
-
paddingX: 1
|
|
2211
|
+
flexDirection: "column"
|
|
2214
2212
|
}, /* @__PURE__ */ React.createElement(MessageItem, {
|
|
2215
2213
|
message,
|
|
2216
2214
|
showThoughts
|
|
2217
2215
|
}))), /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, pendingMessages.map((message) => /* @__PURE__ */ React.createElement(Box, {
|
|
2218
2216
|
key: message.id,
|
|
2219
|
-
flexDirection: "column"
|
|
2220
|
-
paddingX: 1
|
|
2217
|
+
flexDirection: "column"
|
|
2221
2218
|
}, /* @__PURE__ */ React.createElement(MessageItem, {
|
|
2222
2219
|
message,
|
|
2223
2220
|
showThoughts
|
|
@@ -2281,7 +2278,9 @@ function App({ onMessage, onBackgroundCompletion, onCommand, onBashCommand, onPe
|
|
|
2281
2278
|
borderStyle: "single",
|
|
2282
2279
|
borderColor: isBashMode ? "yellow" : "cyan",
|
|
2283
2280
|
borderTop: true,
|
|
2284
|
-
borderBottom: true
|
|
2281
|
+
borderBottom: true,
|
|
2282
|
+
borderLeft: false,
|
|
2283
|
+
borderRight: false
|
|
2285
2284
|
}, /* @__PURE__ */ React.createElement(InputPrompt, {
|
|
2286
2285
|
onSubmit: handleSubmit,
|
|
2287
2286
|
onBashCommand,
|
|
@@ -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;
|
|
@@ -5582,8 +5642,6 @@ function CliApp() {
|
|
|
5582
5642
|
setCommandHistory(await state.commandHistoryStore.load());
|
|
5583
5643
|
try {
|
|
5584
5644
|
await state.customCommandStore.loadCommands();
|
|
5585
|
-
const customCommandCount = state.customCommandStore.getCommandCount();
|
|
5586
|
-
if (customCommandCount > 0) startupLog.push(`📝 Loaded ${customCommandCount} custom command${customCommandCount !== 1 ? "s" : ""}`);
|
|
5587
5645
|
} catch (error) {
|
|
5588
5646
|
console.warn("Failed to load custom commands:", error instanceof Error ? error.message : String(error));
|
|
5589
5647
|
}
|
|
@@ -5612,7 +5670,7 @@ function CliApp() {
|
|
|
5612
5670
|
startupLog.push(`✅ Authenticated (expires in ${daysUntilExpiry} day${daysUntilExpiry !== 1 ? "s" : ""})`);
|
|
5613
5671
|
const apiBaseURL = getApiUrl(config.apiConfig);
|
|
5614
5672
|
const envName = getEnvironmentName(config.apiConfig);
|
|
5615
|
-
if (import.meta.url.includes("/src/") || process.env.NODE_ENV === "development" || envName !== "Bike4Mind")
|
|
5673
|
+
if (import.meta.url.includes("/src/") || process.env.NODE_ENV === "development" || envName !== "Bike4Mind") startupLog.unshift(`🌍 API Environment: ${envName} (${apiBaseURL})`);
|
|
5616
5674
|
const apiClient = new ApiClient(apiBaseURL, state.configStore);
|
|
5617
5675
|
const tokenGetter = async () => {
|
|
5618
5676
|
return (await state.configStore.getAuthTokens())?.accessToken ?? null;
|
|
@@ -5796,11 +5854,11 @@ function CliApp() {
|
|
|
5796
5854
|
};
|
|
5797
5855
|
const permissionManager = new PermissionManager(config.trustedTools || [], void 0, config.tools.disabled || []);
|
|
5798
5856
|
const [{ createSandboxRuntime }, { SandboxOrchestrator }, { DEFAULT_SANDBOX_CONFIG }, { ProxyManager }, { ViolationLogStore }] = await Promise.all([
|
|
5799
|
-
import("./SandboxRuntimeAdapter-
|
|
5800
|
-
import("./SandboxOrchestrator-
|
|
5857
|
+
import("./SandboxRuntimeAdapter-DXa3nFOw.mjs"),
|
|
5858
|
+
import("./SandboxOrchestrator-C4oDqltp.mjs"),
|
|
5801
5859
|
import("./types-DK3P88Px.mjs"),
|
|
5802
|
-
import("./ProxyManager-
|
|
5803
|
-
import("./ViolationLogStore-
|
|
5860
|
+
import("./ProxyManager-DIAAw902.mjs"),
|
|
5861
|
+
import("./ViolationLogStore-Dp6HF0nz.mjs")
|
|
5804
5862
|
]);
|
|
5805
5863
|
const sandboxConfig = config.sandbox ?? DEFAULT_SANDBOX_CONFIG;
|
|
5806
5864
|
const checkpointStore = new CheckpointStore(state.configStore.getProjectConfigDir() || process.cwd());
|
|
@@ -5906,7 +5964,6 @@ function CliApp() {
|
|
|
5906
5964
|
observationQueue: []
|
|
5907
5965
|
};
|
|
5908
5966
|
const { tools: b4mTools } = await generateCliTools(config.userId, llm, modelInfo.id, permissionManager, promptFn, agentContext, state.configStore, apiClient, void 0, userQuestionFn, checkpointStore, sandboxOrchestrator, additionalDirectories);
|
|
5909
|
-
startupLog.push(`🛠️ Loaded ${b4mTools.length} B4M tool(s)`);
|
|
5910
5967
|
const mcpManager = new McpManager(config);
|
|
5911
5968
|
const builtinAgentsDir = new URL("./agents/defaults/", import.meta.url).pathname;
|
|
5912
5969
|
const agentProjectDir = state.configStore.getProjectConfigDir();
|
|
@@ -5919,8 +5976,8 @@ function CliApp() {
|
|
|
5919
5976
|
const mcpTools = mcpManager.getTools();
|
|
5920
5977
|
if (mcpTools.length > 0) {
|
|
5921
5978
|
const serverSummaries = mcpManager.getToolCount().map((s) => `${s.serverName} (${s.count})`).join(", ");
|
|
5922
|
-
startupLog.push(
|
|
5923
|
-
} else startupLog.push(
|
|
5979
|
+
startupLog.push(`🛠️ Loaded ${b4mTools.length} B4M + ${mcpTools.length} MCP tool(s): ${serverSummaries}`);
|
|
5980
|
+
} else startupLog.push(`🛠️ Loaded ${b4mTools.length} B4M tool(s), no MCP tools`);
|
|
5924
5981
|
const agentSummary = agentStore.getSummary();
|
|
5925
5982
|
startupLog.push(`🤖 Loaded ${agentSummary.total} agent(s): ${agentSummary.builtin} built-in, ${agentSummary.global} global, ${agentSummary.project} project`);
|
|
5926
5983
|
const orchestrator = new SubagentOrchestrator({
|
|
@@ -6002,11 +6059,9 @@ function CliApp() {
|
|
|
6002
6059
|
];
|
|
6003
6060
|
startupLog.push(`📂 Working directory: ${process.cwd()}`);
|
|
6004
6061
|
if (additionalDirectories.length > 0) startupLog.push(`📁 Additional directories: ${additionalDirectories.length}`);
|
|
6005
|
-
const agentNamesList = agentStore.getAgentNames().join(", ");
|
|
6006
|
-
startupLog.push(`🤖 Subagent delegation enabled (${agentNamesList}) + background execution`);
|
|
6007
6062
|
if (skillTool) {
|
|
6008
6063
|
const skillCount = state.customCommandStore.getCommandCount();
|
|
6009
|
-
if (skillCount > 0) startupLog.push(`🛠️
|
|
6064
|
+
if (skillCount > 0) startupLog.push(`🛠️ Skill tool enabled (${skillCount} skills available)`);
|
|
6010
6065
|
}
|
|
6011
6066
|
if (dynamicAgentTool) startupLog.push(`🧪 Dynamic agent creation enabled (experimental)`);
|
|
6012
6067
|
if (featureRegistry.hasModules) {
|
|
@@ -6175,60 +6230,7 @@ function CliApp() {
|
|
|
6175
6230
|
featureRegistry
|
|
6176
6231
|
}));
|
|
6177
6232
|
setStoreSession(newSession);
|
|
6178
|
-
|
|
6179
|
-
{
|
|
6180
|
-
text: "██████╗ ██╗ ██╗███╗ ███╗",
|
|
6181
|
-
ansi: "\x1B[36m\x1B[1m"
|
|
6182
|
-
},
|
|
6183
|
-
{
|
|
6184
|
-
text: "██╔══██╗██║ ██║████╗ ████║",
|
|
6185
|
-
ansi: "\x1B[36m\x1B[1m"
|
|
6186
|
-
},
|
|
6187
|
-
{
|
|
6188
|
-
text: "██████╔╝███████║██╔████╔██║",
|
|
6189
|
-
ansi: "\x1B[36m\x1B[1m"
|
|
6190
|
-
},
|
|
6191
|
-
{
|
|
6192
|
-
text: "██╔══██╗╚════██║██║╚██╔╝██║",
|
|
6193
|
-
ansi: "\x1B[36m\x1B[1m"
|
|
6194
|
-
},
|
|
6195
|
-
{
|
|
6196
|
-
text: "██████╔╝ ██║██║ ╚═╝ ██║",
|
|
6197
|
-
ansi: "\x1B[36m\x1B[1m"
|
|
6198
|
-
},
|
|
6199
|
-
{
|
|
6200
|
-
text: "╚═════╝ ╚═╝╚═╝ ╚═╝",
|
|
6201
|
-
ansi: "\x1B[36m\x1B[1m"
|
|
6202
|
-
},
|
|
6203
|
-
{
|
|
6204
|
-
text: "",
|
|
6205
|
-
ansi: ""
|
|
6206
|
-
},
|
|
6207
|
-
{
|
|
6208
|
-
text: `v${version} - AI-Powered CLI`,
|
|
6209
|
-
ansi: "\x1B[2m"
|
|
6210
|
-
},
|
|
6211
|
-
{
|
|
6212
|
-
text: "/help for more information",
|
|
6213
|
-
ansi: "\x1B[2m"
|
|
6214
|
-
}
|
|
6215
|
-
];
|
|
6216
|
-
const bannerWidth = 30;
|
|
6217
|
-
const rightColWidth = (process.stdout.columns || 80) - bannerWidth - 2;
|
|
6218
|
-
const truncate = (str, max) => {
|
|
6219
|
-
if (str.length > max) return str.slice(0, max - 1) + "…";
|
|
6220
|
-
return str;
|
|
6221
|
-
};
|
|
6222
|
-
const totalLines = Math.max(bannerLines.length, startupLog.length);
|
|
6223
|
-
for (let i = 0; i < totalLines; i++) {
|
|
6224
|
-
const banner = bannerLines[i];
|
|
6225
|
-
const leftText = banner?.text || "";
|
|
6226
|
-
const leftAnsi = banner?.ansi || "";
|
|
6227
|
-
const right = startupLog[i] || "";
|
|
6228
|
-
const coloredLeft = leftText ? `${leftAnsi}${leftText}\x1b[0m` : "";
|
|
6229
|
-
const gap = " ".repeat(bannerWidth - leftText.length + 2);
|
|
6230
|
-
console.log(coloredLeft + gap + truncate(right, rightColWidth));
|
|
6231
|
-
}
|
|
6233
|
+
renderBanner(startupLog);
|
|
6232
6234
|
setIsInitialized(true);
|
|
6233
6235
|
console.log("");
|
|
6234
6236
|
} catch (error) {
|
|
@@ -6873,7 +6875,7 @@ function CliApp() {
|
|
|
6873
6875
|
let imageStore = state.imageStore;
|
|
6874
6876
|
if (!imageStore) {
|
|
6875
6877
|
if (!imageStoreInitPromise.current) imageStoreInitPromise.current = (async () => {
|
|
6876
|
-
const { ImageStore: ImageStoreClass } = await import("./ImageStore-
|
|
6878
|
+
const { ImageStore: ImageStoreClass } = await import("./ImageStore-BFp_d12J.mjs");
|
|
6877
6879
|
const newImageStore = new ImageStoreClass();
|
|
6878
6880
|
setState((prev) => ({
|
|
6879
6881
|
...prev,
|
|
@@ -7480,6 +7482,7 @@ Multi-line Input:
|
|
|
7480
7482
|
case "clear":
|
|
7481
7483
|
case "new": {
|
|
7482
7484
|
console.clear();
|
|
7485
|
+
renderBanner();
|
|
7483
7486
|
const model = state.session?.model || state.config?.defaultModel || ChatModels.CLAUDE_4_5_SONNET;
|
|
7484
7487
|
const newSession = {
|
|
7485
7488
|
id: v4(),
|
|
@@ -8151,7 +8154,7 @@ Multi-line Input:
|
|
|
8151
8154
|
break;
|
|
8152
8155
|
}
|
|
8153
8156
|
case "terminal-setup": {
|
|
8154
|
-
const { runTerminalSetup } = await import("./terminalSetup-
|
|
8157
|
+
const { runTerminalSetup } = await import("./terminalSetup-DxloCowq.mjs");
|
|
8155
8158
|
await runTerminalSetup();
|
|
8156
8159
|
break;
|
|
8157
8160
|
}
|
|
@@ -8465,6 +8468,10 @@ Multi-line Input:
|
|
|
8465
8468
|
allow: response !== "deny",
|
|
8466
8469
|
resolvedBy: "user"
|
|
8467
8470
|
});
|
|
8471
|
+
if (response === "deny") {
|
|
8472
|
+
abortControllerRef.current?.abort();
|
|
8473
|
+
return;
|
|
8474
|
+
}
|
|
8468
8475
|
emitNextAwaitingStatus();
|
|
8469
8476
|
},
|
|
8470
8477
|
onUserQuestionResponse: (response, promptId) => {
|
|
@@ -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
|
|
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
|
-
-
|
|
3084
|
-
-
|
|
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)
|
|
@@ -3262,7 +3433,11 @@ You have tools for tracking decisions, blockers, and human review gates during y
|
|
|
3262
3433
|
|
|
3263
3434
|
- request_review_gate: Pause for explicit human approval before crossing a significant decision point — one that affects interpretation, evidence, cost, credentials, platform, or public commitment (e.g., narrowing research scope after synthesis, hard-to-reverse refactors, architectural pivots, dependency swaps). Do NOT use for routine operations or actions already covered by the standard permission system (file edits, bash commands). Treat a rejection as a hard stop — re-plan, do not retry.
|
|
3264
3435
|
|
|
3265
|
-
These tools are lightweight — use them naturally as part of your work, not as a ceremony
|
|
3436
|
+
These tools are lightweight — use them naturally as part of your work, not as a ceremony.
|
|
3437
|
+
|
|
3438
|
+
## Working Directory
|
|
3439
|
+
|
|
3440
|
+
The current working directory is \`${process.cwd()}\`. All relative paths in tool calls resolve from here. When using \`${TOOL_GLOB_FILES}\` or \`${TOOL_GREP_SEARCH}\` without an explicit \`dir_path\`, they search from this directory.${directoriesSection}${projectContextSection}${skillsSection}${featureModulesSection}${planModeSection}`;
|
|
3266
3441
|
}
|
|
3267
3442
|
/**
|
|
3268
3443
|
* Build the minimal-variant system prompt. Reuses the project context,
|
|
@@ -3286,7 +3461,11 @@ function buildMinimalSystemPrompt(config = {}) {
|
|
|
3286
3461
|
Guidelines:
|
|
3287
3462
|
- Be concise in your responses.
|
|
3288
3463
|
- Show file paths clearly when working with files.
|
|
3289
|
-
- When the task is done, give the user a direct answer — no recap of steps already visible in the tool history
|
|
3464
|
+
- When the task is done, give the user a direct answer — no recap of steps already visible in the tool history.
|
|
3465
|
+
|
|
3466
|
+
## Working Directory
|
|
3467
|
+
|
|
3468
|
+
The current working directory is \`${process.cwd()}\`. All relative paths in tool calls resolve from here. When using \`${TOOL_GLOB_FILES}\` or \`${TOOL_GREP_SEARCH}\` without an explicit \`dir_path\`, they search from this directory.${directoriesSection}${projectContextSection}${skillsSection}${featureModulesSection}${planModeSection}`;
|
|
3290
3469
|
}
|
|
3291
3470
|
/**
|
|
3292
3471
|
* Pick a system prompt by variant. The dispatch point for the
|
|
@@ -3381,6 +3560,42 @@ function isWriteTargetingPlanFile(toolName, args, cwd = process.cwd()) {
|
|
|
3381
3560
|
return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
3382
3561
|
}
|
|
3383
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
|
|
3384
3599
|
//#region ../../b4m-core/utils/dist/imageGeneration/AIImageService.mjs
|
|
3385
3600
|
/**
|
|
3386
3601
|
* Abstract class for AI Image Service
|
|
@@ -5526,6 +5741,12 @@ var OpenAIBackend = class {
|
|
|
5526
5741
|
tool_call_id: tool.id
|
|
5527
5742
|
});
|
|
5528
5743
|
}
|
|
5744
|
+
replaceLastToolResultObservation(messages, toolCallId, newObservation) {
|
|
5745
|
+
replaceLastToolResultObservationOpenAI(messages, toolCallId, newObservation);
|
|
5746
|
+
}
|
|
5747
|
+
getLatestToolCallId(messages, toolName) {
|
|
5748
|
+
return getLatestToolCallIdOpenAI(messages, toolName);
|
|
5749
|
+
}
|
|
5529
5750
|
formatTools(tools = []) {
|
|
5530
5751
|
return tools.map((tool) => ({
|
|
5531
5752
|
type: "function",
|
|
@@ -18421,11 +18642,11 @@ function parseQuery(query) {
|
|
|
18421
18642
|
*/
|
|
18422
18643
|
const getCliOnlyTools = async () => {
|
|
18423
18644
|
const [{ createFileTool }, { globFilesTool }, { grepSearchTool }, { deleteFileTool }, { bashExecuteTool }] = await Promise.all([
|
|
18424
|
-
import("./createFile-C1JoeuYh-
|
|
18425
|
-
import("./globFiles-Bez8QCbS-
|
|
18426
|
-
import("./grepSearch-
|
|
18427
|
-
import("./deleteFile-BTberNGj-
|
|
18428
|
-
import("./bashExecute-pYljpfPn-
|
|
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")
|
|
18429
18650
|
]);
|
|
18430
18651
|
return {
|
|
18431
18652
|
file_read: fileReadTool,
|
|
@@ -19081,7 +19302,7 @@ function cleanupSandboxFiles(paths) {
|
|
|
19081
19302
|
*/
|
|
19082
19303
|
async function captureViolations(isSandboxed, result, command, orchestrator) {
|
|
19083
19304
|
if (!isSandboxed || !orchestrator || !command) return;
|
|
19084
|
-
const { parseSandboxStderr, toSandboxViolations } = await import("./StderrViolationParser-
|
|
19305
|
+
const { parseSandboxStderr, toSandboxViolations } = await import("./StderrViolationParser-BFP4bo7I.mjs");
|
|
19085
19306
|
const parsed = parseSandboxStderr(result);
|
|
19086
19307
|
if (parsed.length > 0) {
|
|
19087
19308
|
const violations = toSandboxViolations(parsed, command);
|
|
@@ -23514,7 +23735,8 @@ function createTodoStore(onUpdate) {
|
|
|
23514
23735
|
//#endregion
|
|
23515
23736
|
//#region src/tools/findDefinitionTool.ts
|
|
23516
23737
|
const execFileAsync = promisify(execFile);
|
|
23517
|
-
|
|
23738
|
+
/** Cached ripgrep binary path after first resolution */
|
|
23739
|
+
let cachedRgPath = null;
|
|
23518
23740
|
const VALID_KINDS = [
|
|
23519
23741
|
"class",
|
|
23520
23742
|
"function",
|
|
@@ -23558,14 +23780,23 @@ const KIND_KEYWORDS = {
|
|
|
23558
23780
|
]
|
|
23559
23781
|
};
|
|
23560
23782
|
const ALL_KEYWORDS = Object.values(KIND_KEYWORDS).flat();
|
|
23561
|
-
|
|
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;
|
|
23562
23792
|
try {
|
|
23563
|
-
|
|
23564
|
-
const ripgrepDir = path.dirname(ripgrepPath);
|
|
23565
|
-
return path.join(ripgrepDir, "..", "bin", "rg" + (process.platform === "win32" ? ".exe" : ""));
|
|
23793
|
+
({rgPath} = await import("@vscode/ripgrep"));
|
|
23566
23794
|
} catch {
|
|
23567
|
-
throw new Error("ripgrep is not available.
|
|
23795
|
+
throw new Error("ripgrep is not available. Install the optional dependency: pnpm add @vscode/ripgrep --filter @bike4mind/cli");
|
|
23568
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;
|
|
23569
23800
|
}
|
|
23570
23801
|
function isPathWithinWorkspace(targetPath, baseCwd) {
|
|
23571
23802
|
const resolvedTarget = path.resolve(targetPath);
|
|
@@ -23619,7 +23850,7 @@ async function findDefinitions(params) {
|
|
|
23619
23850
|
if (error.code === "ENOENT") throw new Error(`Path does not exist: ${search_path}`);
|
|
23620
23851
|
throw error;
|
|
23621
23852
|
}
|
|
23622
|
-
const rgPath = getRipgrepPath();
|
|
23853
|
+
const rgPath = await getRipgrepPath();
|
|
23623
23854
|
const rgArgs = [
|
|
23624
23855
|
"--json",
|
|
23625
23856
|
"--max-count",
|
|
@@ -23796,7 +24027,7 @@ function createGetFileStructureTool() {
|
|
|
23796
24027
|
if (stats.isDirectory()) return `Error: Path is a directory, not a file: ${params.path}`;
|
|
23797
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`;
|
|
23798
24029
|
const ext = path.extname(resolvedPath).toLowerCase();
|
|
23799
|
-
const { getLanguageForExtension, parseFileStructure, getSupportedLanguages } = await import("./treeSitterEngine-
|
|
24030
|
+
const { getLanguageForExtension, parseFileStructure, getSupportedLanguages } = await import("./treeSitterEngine-Cw2LbVZT.mjs");
|
|
23800
24031
|
const languageId = getLanguageForExtension(ext);
|
|
23801
24032
|
if (!languageId) return `Error: Unsupported file type "${ext}". Supported languages: ${getSupportedLanguages().join(", ")}`;
|
|
23802
24033
|
const sourceCode = await promises.readFile(resolvedPath, "utf-8");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.9.
|
|
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.
|
|
125
|
-
"@bike4mind/common": "2.
|
|
126
|
-
"@bike4mind/mcp": "1.37.
|
|
127
|
-
"@bike4mind/services": "2.
|
|
128
|
-
"@bike4mind/utils": "2.
|
|
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"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|