@bike4mind/cli 0.2.4 → 0.2.5-cli-bash-tools.17096

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/README.md CHANGED
@@ -160,6 +160,7 @@ export SERPER_API_KEY="your-key-here"
160
160
  - ✅ `math_evaluate` - No API key needed
161
161
  - ✅ `current_datetime` - No API key needed
162
162
  - ✅ `prompt_enhancement` - No API key needed
163
+ - ✅ `bash_execute` - No API key needed
163
164
  - 🔑 `weather_info` - Requires `toolApiKeys.openweather`
164
165
  - 🔑 `web_search` - Requires `toolApiKeys.serper`
165
166
  - 🔑 `deep_research` - Requires `toolApiKeys.serper`
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-WR6YZRQV.js";
4
+ } from "./chunk-KUMTSAUN.js";
5
5
  import "./chunk-PDX44BCA.js";
6
6
 
7
7
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/artifactExtractor.js
File without changes
File without changes
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BadRequestError,
4
4
  secureParameters
5
- } from "./chunk-LYNNVNEC.js";
5
+ } from "./chunk-TQUGMSCZ.js";
6
6
  import {
7
7
  GenericCreditDeductTransaction,
8
8
  ImageEditUsageTransaction,
@@ -10,7 +10,7 @@ import {
10
10
  RealtimeVoiceUsageTransaction,
11
11
  TextGenerationUsageTransaction,
12
12
  TransferCreditTransaction
13
- } from "./chunk-WR6YZRQV.js";
13
+ } from "./chunk-KUMTSAUN.js";
14
14
 
15
15
  // ../../b4m-core/packages/services/dist/src/creditService/subtractCredits.js
16
16
  import { z } from "zod";
File without changes
@@ -7,11 +7,11 @@ import {
7
7
  getSettingsMap,
8
8
  getSettingsValue,
9
9
  secureParameters
10
- } from "./chunk-LYNNVNEC.js";
10
+ } from "./chunk-TQUGMSCZ.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
14
- } from "./chunk-WR6YZRQV.js";
14
+ } from "./chunk-KUMTSAUN.js";
15
15
 
16
16
  // ../../b4m-core/packages/services/dist/src/fabFileService/create.js
17
17
  import { z } from "zod";
@@ -230,7 +230,9 @@ var b4mLLMTools = z3.enum([
230
230
  "create_file",
231
231
  "glob_files",
232
232
  "grep_search",
233
- "delete_file"
233
+ "delete_file",
234
+ // Shell execution
235
+ "bash_execute"
234
236
  ]);
235
237
  var B4MLLMToolsList = b4mLLMTools.options.map((tool) => tool);
236
238
  var RechartsChartTypeSchema = z3.enum([
@@ -6,12 +6,12 @@ import {
6
6
  getSettingsByNames,
7
7
  obfuscateApiKey,
8
8
  secureParameters
9
- } from "./chunk-LYNNVNEC.js";
9
+ } from "./chunk-TQUGMSCZ.js";
10
10
  import {
11
11
  ApiKeyType,
12
12
  MementoTier,
13
13
  isSupportedEmbeddingModel
14
- } from "./chunk-WR6YZRQV.js";
14
+ } from "./chunk-KUMTSAUN.js";
15
15
 
16
16
  // ../../b4m-core/packages/services/dist/src/apiKeyService/get.js
17
17
  import { z } from "zod";
File without changes
@@ -16,7 +16,7 @@ import {
16
16
  dayjsConfig_default,
17
17
  extractSnippetMeta,
18
18
  settingsMap
19
- } from "./chunk-WR6YZRQV.js";
19
+ } from "./chunk-KUMTSAUN.js";
20
20
 
21
21
  // ../../b4m-core/packages/utils/dist/src/storage/S3Storage.js
22
22
  import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  createFabFile,
4
4
  createFabFileSchema
5
- } from "./chunk-6AJODFPC.js";
6
- import "./chunk-LYNNVNEC.js";
5
+ } from "./chunk-FJ6BRMJD.js";
6
+ import "./chunk-TQUGMSCZ.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
- import "./chunk-WR6YZRQV.js";
8
+ import "./chunk-KUMTSAUN.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  createFabFile,
File without changes
package/dist/index.js CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  getEffectiveApiKey,
5
5
  getOpenWeatherKey,
6
6
  getSerperKey
7
- } from "./chunk-WNBKV4FX.js";
8
- import "./chunk-LEG2UM5Q.js";
9
- import "./chunk-6AJODFPC.js";
7
+ } from "./chunk-L2Q4BSIU.js";
8
+ import "./chunk-BNFSIXHY.js";
9
+ import "./chunk-FJ6BRMJD.js";
10
10
  import {
11
11
  BFLImageService,
12
12
  BaseStorage,
@@ -15,7 +15,7 @@ import {
15
15
  OpenAIBackend,
16
16
  OpenAIImageService,
17
17
  XAIImageService
18
- } from "./chunk-LYNNVNEC.js";
18
+ } from "./chunk-TQUGMSCZ.js";
19
19
  import {
20
20
  Logger
21
21
  } from "./chunk-AMDXHL6S.js";
@@ -73,7 +73,7 @@ import {
73
73
  XAI_IMAGE_MODELS,
74
74
  b4mLLMTools,
75
75
  getMcpProviderMetadata
76
- } from "./chunk-WR6YZRQV.js";
76
+ } from "./chunk-KUMTSAUN.js";
77
77
  import {
78
78
  __require
79
79
  } from "./chunk-PDX44BCA.js";
@@ -4281,8 +4281,8 @@ async function processAndStoreImages(images, context) {
4281
4281
  const buffer = await downloadImage(image);
4282
4282
  const fileType = await fileTypeFromBuffer2(buffer);
4283
4283
  const filename = `${uuidv45()}.${fileType?.ext}`;
4284
- const path13 = await context.imageGenerateStorage.upload(buffer, filename, {});
4285
- return path13;
4284
+ const path14 = await context.imageGenerateStorage.upload(buffer, filename, {});
4285
+ return path14;
4286
4286
  }));
4287
4287
  }
4288
4288
  async function updateQuestAndReturnMarkdown(storedImageUrls, context) {
@@ -5466,8 +5466,8 @@ async function processAndStoreImage(imageUrl, context) {
5466
5466
  const buffer = await downloadImage2(imageUrl);
5467
5467
  const fileType = await fileTypeFromBuffer3(buffer);
5468
5468
  const filename = `${uuidv46()}.${fileType?.ext}`;
5469
- const path13 = await context.imageGenerateStorage.upload(buffer, filename, {});
5470
- return path13;
5469
+ const path14 = await context.imageGenerateStorage.upload(buffer, filename, {});
5470
+ return path14;
5471
5471
  }
5472
5472
  async function updateQuestAndReturnMarkdown2(storedImagePath, context) {
5473
5473
  await context.onFinish?.("edit_image", storedImagePath);
@@ -7879,6 +7879,391 @@ var deleteFileTool = {
7879
7879
  })
7880
7880
  };
7881
7881
 
7882
+ // ../../b4m-core/packages/services/dist/src/llm/tools/implementation/bashExecute/index.js
7883
+ import { spawn } from "child_process";
7884
+ import path11 from "path";
7885
+ var DEFAULT_TIMEOUT_MS = 6e4;
7886
+ var MAX_OUTPUT_SIZE = 100 * 1024;
7887
+ var DANGEROUS_PATTERNS = [
7888
+ // Destructive file operations
7889
+ {
7890
+ pattern: /\brm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+|.*\s+-[a-zA-Z]*r).*\//i,
7891
+ reason: "Recursive delete with path",
7892
+ block: true
7893
+ },
7894
+ {
7895
+ pattern: /\brm\s+(-[a-zA-Z]*f[a-zA-Z]*\s+|.*\s+-[a-zA-Z]*f).*--no-preserve-root/i,
7896
+ reason: "Force delete without preserve root",
7897
+ block: true
7898
+ },
7899
+ {
7900
+ pattern: /\brm\s+-[a-zA-Z]*r[a-zA-Z]*f[a-zA-Z]*\s+\//i,
7901
+ reason: "Recursive force delete on root paths",
7902
+ block: true
7903
+ },
7904
+ {
7905
+ pattern: /\brm\s+-[a-zA-Z]*f[a-zA-Z]*r[a-zA-Z]*\s+\//i,
7906
+ reason: "Force recursive delete on root paths",
7907
+ block: true
7908
+ },
7909
+ // System-level dangerous commands
7910
+ { pattern: /\bsudo\b/i, reason: "Elevated privileges (sudo)", block: true },
7911
+ { pattern: /\bsu\s+(-|root)/i, reason: "Switch to root user", block: true },
7912
+ { pattern: /\bchmod\s+777\b/i, reason: "Overly permissive chmod", block: false },
7913
+ { pattern: /\bchown\s+-R\s+root/i, reason: "Recursive chown to root", block: true },
7914
+ // Disk/partition operations
7915
+ { pattern: /\bmkfs\b/i, reason: "Filesystem creation", block: true },
7916
+ { pattern: /\bfdisk\b/i, reason: "Disk partitioning", block: true },
7917
+ { pattern: /\bdd\s+.*of=\/dev\//i, reason: "Direct disk write", block: true },
7918
+ // Network attacks
7919
+ { pattern: /\b(nc|netcat)\s+.*-e\s+\/bin\/(ba)?sh/i, reason: "Reverse shell attempt", block: true },
7920
+ { pattern: /\bcurl\s+.*\|\s*(ba)?sh/i, reason: "Piping remote script to shell", block: true },
7921
+ { pattern: /\bwget\s+.*\|\s*(ba)?sh/i, reason: "Piping remote script to shell", block: true },
7922
+ // Fork bombs and resource exhaustion
7923
+ { pattern: /:\(\)\s*\{\s*:\|:&\s*\}\s*;/i, reason: "Fork bomb", block: true },
7924
+ { pattern: /\bwhile\s+true.*do.*done.*&/i, reason: "Infinite loop in background", block: false },
7925
+ // Credential/sensitive data access
7926
+ { pattern: /\/etc\/shadow/i, reason: "Access to shadow file", block: true },
7927
+ { pattern: /\/etc\/passwd.*>/i, reason: "Modifying passwd file", block: true },
7928
+ { pattern: /\baws\s+.*--profile\s+/i, reason: "AWS profile access", block: false },
7929
+ // History/log manipulation
7930
+ { pattern: /\bhistory\s+-c\b/i, reason: "Clearing shell history", block: false },
7931
+ { pattern: />\s*\/var\/log\//i, reason: "Overwriting system logs", block: true },
7932
+ // Dangerous redirects
7933
+ { pattern: />\s*\/dev\/sda/i, reason: "Writing to block device", block: true },
7934
+ { pattern: />\s*\/dev\/null.*2>&1.*</i, reason: "Potentially hiding output", block: false },
7935
+ // Environment manipulation
7936
+ { pattern: /\bexport\s+PATH\s*=\s*[^$]/i, reason: "Overwriting PATH", block: false },
7937
+ { pattern: /\bexport\s+LD_PRELOAD/i, reason: "LD_PRELOAD manipulation", block: true },
7938
+ // Process/system control
7939
+ { pattern: /\bkill\s+-9\s+(-1|1)\b/i, reason: "Killing all processes", block: true },
7940
+ { pattern: /\bkillall\s+-9\b/i, reason: "Force killing processes", block: false },
7941
+ { pattern: /\bshutdown\b/i, reason: "System shutdown", block: true },
7942
+ { pattern: /\breboot\b/i, reason: "System reboot", block: true },
7943
+ { pattern: /\binit\s+[06]\b/i, reason: "System runlevel change", block: true }
7944
+ ];
7945
+ var SAFE_COMMAND_PREFIXES = [
7946
+ "ls",
7947
+ "cat",
7948
+ "head",
7949
+ "tail",
7950
+ "grep",
7951
+ "find",
7952
+ "echo",
7953
+ "pwd",
7954
+ "whoami",
7955
+ "date",
7956
+ "cal",
7957
+ "wc",
7958
+ "sort",
7959
+ "uniq",
7960
+ "cut",
7961
+ "tr",
7962
+ "sed",
7963
+ "awk",
7964
+ "git",
7965
+ "npm",
7966
+ "pnpm",
7967
+ "yarn",
7968
+ "node",
7969
+ "npx",
7970
+ "tsx",
7971
+ "ts-node",
7972
+ "python",
7973
+ "python3",
7974
+ "pip",
7975
+ "pip3",
7976
+ "docker",
7977
+ "docker-compose",
7978
+ "curl",
7979
+ "wget",
7980
+ // These are safe for fetching, blocked when piped to shell
7981
+ "mkdir",
7982
+ "touch",
7983
+ "cp",
7984
+ "mv",
7985
+ // File operations (still require permission)
7986
+ "which",
7987
+ "whereis",
7988
+ "type",
7989
+ "file",
7990
+ "stat",
7991
+ "env",
7992
+ "printenv",
7993
+ "set",
7994
+ "man",
7995
+ "help",
7996
+ "info",
7997
+ "diff",
7998
+ "comm",
7999
+ "cmp",
8000
+ "tar",
8001
+ "zip",
8002
+ "unzip",
8003
+ "gzip",
8004
+ "gunzip",
8005
+ "ssh",
8006
+ "scp",
8007
+ "rsync",
8008
+ // Network tools
8009
+ "make",
8010
+ "cmake",
8011
+ "cargo",
8012
+ "go",
8013
+ "rustc",
8014
+ "gcc",
8015
+ "g++",
8016
+ // Build tools
8017
+ "jest",
8018
+ "vitest",
8019
+ "mocha",
8020
+ "pytest",
8021
+ // Test runners
8022
+ "eslint",
8023
+ "prettier",
8024
+ "tsc"
8025
+ // Linters/formatters
8026
+ ];
8027
+ function checkDangerousPatterns(command) {
8028
+ for (const { pattern, reason, block } of DANGEROUS_PATTERNS) {
8029
+ if (pattern.test(command)) {
8030
+ return { blocked: block, reason };
8031
+ }
8032
+ }
8033
+ return { blocked: false };
8034
+ }
8035
+ function getBaseCommand(command) {
8036
+ const trimmed = command.trim();
8037
+ const match = trimmed.match(/^(\S+)/);
8038
+ return match ? match[1] : "";
8039
+ }
8040
+ function isSafeCommandPrefix(command) {
8041
+ const baseCommand = getBaseCommand(command);
8042
+ return SAFE_COMMAND_PREFIXES.some((safe) => baseCommand === safe || baseCommand.endsWith(`/${safe}`));
8043
+ }
8044
+ async function executeBashCommand(params) {
8045
+ const { command, cwd: relativeCwd, timeout = DEFAULT_TIMEOUT_MS } = params;
8046
+ if (!command || command.trim().length === 0) {
8047
+ return {
8048
+ stdout: "",
8049
+ stderr: "Error: Command cannot be empty",
8050
+ exitCode: 1,
8051
+ timedOut: false,
8052
+ blocked: true,
8053
+ blockedReason: "Empty command"
8054
+ };
8055
+ }
8056
+ const dangerCheck = checkDangerousPatterns(command);
8057
+ if (dangerCheck.blocked) {
8058
+ return {
8059
+ stdout: "",
8060
+ stderr: `Command blocked for safety: ${dangerCheck.reason}`,
8061
+ exitCode: 1,
8062
+ timedOut: false,
8063
+ blocked: true,
8064
+ blockedReason: dangerCheck.reason
8065
+ };
8066
+ }
8067
+ const baseCwd = process.cwd();
8068
+ const targetCwd = relativeCwd ? path11.resolve(baseCwd, path11.normalize(relativeCwd)) : baseCwd;
8069
+ if (!targetCwd.startsWith(baseCwd)) {
8070
+ return {
8071
+ stdout: "",
8072
+ stderr: "Error: Cannot execute commands outside of current working directory",
8073
+ exitCode: 1,
8074
+ timedOut: false,
8075
+ blocked: true,
8076
+ blockedReason: "Path traversal attempt"
8077
+ };
8078
+ }
8079
+ const effectiveTimeout = Math.min(timeout, 5 * 60 * 1e3);
8080
+ return new Promise((resolve3) => {
8081
+ let stdout = "";
8082
+ let stderr = "";
8083
+ let timedOut = false;
8084
+ const proc = spawn("bash", ["-c", command], {
8085
+ cwd: targetCwd,
8086
+ env: {
8087
+ ...process.env,
8088
+ // Prevent color codes that might be hard to read
8089
+ NO_COLOR: "1",
8090
+ FORCE_COLOR: "0"
8091
+ },
8092
+ stdio: ["ignore", "pipe", "pipe"]
8093
+ });
8094
+ const timeoutId = setTimeout(() => {
8095
+ timedOut = true;
8096
+ proc.kill("SIGTERM");
8097
+ setTimeout(() => {
8098
+ if (!proc.killed) {
8099
+ proc.kill("SIGKILL");
8100
+ }
8101
+ }, 5e3);
8102
+ }, effectiveTimeout);
8103
+ proc.stdout.on("data", (data) => {
8104
+ if (stdout.length < MAX_OUTPUT_SIZE) {
8105
+ stdout += data.toString();
8106
+ if (stdout.length > MAX_OUTPUT_SIZE) {
8107
+ stdout = stdout.slice(0, MAX_OUTPUT_SIZE) + "\n... [output truncated]";
8108
+ }
8109
+ }
8110
+ });
8111
+ proc.stderr.on("data", (data) => {
8112
+ if (stderr.length < MAX_OUTPUT_SIZE) {
8113
+ stderr += data.toString();
8114
+ if (stderr.length > MAX_OUTPUT_SIZE) {
8115
+ stderr = stderr.slice(0, MAX_OUTPUT_SIZE) + "\n... [output truncated]";
8116
+ }
8117
+ }
8118
+ });
8119
+ proc.on("close", (exitCode) => {
8120
+ clearTimeout(timeoutId);
8121
+ resolve3({
8122
+ stdout: stdout.trim(),
8123
+ stderr: stderr.trim(),
8124
+ exitCode,
8125
+ timedOut,
8126
+ blocked: false
8127
+ });
8128
+ });
8129
+ proc.on("error", (error) => {
8130
+ clearTimeout(timeoutId);
8131
+ resolve3({
8132
+ stdout: "",
8133
+ stderr: `Failed to execute command: ${error.message}`,
8134
+ exitCode: 1,
8135
+ timedOut: false,
8136
+ blocked: false
8137
+ });
8138
+ });
8139
+ });
8140
+ }
8141
+ function formatResult(result, command) {
8142
+ const parts = [];
8143
+ parts.push(`$ ${command}`);
8144
+ parts.push("");
8145
+ if (result.blocked) {
8146
+ parts.push(`BLOCKED: ${result.blockedReason}`);
8147
+ parts.push("");
8148
+ parts.push("This command was blocked for safety reasons.");
8149
+ parts.push("If you believe this is a false positive, please run the command manually.");
8150
+ return parts.join("\n");
8151
+ }
8152
+ if (result.timedOut) {
8153
+ parts.push("WARNING: Command timed out and was terminated.");
8154
+ parts.push("");
8155
+ }
8156
+ if (result.stdout) {
8157
+ parts.push(result.stdout);
8158
+ }
8159
+ if (result.stderr) {
8160
+ if (result.stdout) {
8161
+ parts.push("");
8162
+ }
8163
+ parts.push("STDERR:");
8164
+ parts.push(result.stderr);
8165
+ }
8166
+ if (result.exitCode !== 0 && result.exitCode !== null) {
8167
+ parts.push("");
8168
+ parts.push(`Exit code: ${result.exitCode}`);
8169
+ }
8170
+ if (!result.stdout && !result.stderr && !result.timedOut) {
8171
+ parts.push("(command completed with no output)");
8172
+ }
8173
+ return parts.join("\n");
8174
+ }
8175
+ var bashExecuteTool = {
8176
+ name: "bash_execute",
8177
+ implementation: (context) => ({
8178
+ toolFn: async (value) => {
8179
+ const params = value;
8180
+ const isSafe = isSafeCommandPrefix(params.command);
8181
+ context.logger.info("Bash: Executing command", {
8182
+ command: params.command,
8183
+ cwd: params.cwd || ".",
8184
+ timeout: params.timeout || DEFAULT_TIMEOUT_MS,
8185
+ isSafeCommand: isSafe
8186
+ });
8187
+ if (context.onStart) {
8188
+ await context.onStart("bash_execute", {
8189
+ command: params.command,
8190
+ cwd: params.cwd
8191
+ });
8192
+ }
8193
+ try {
8194
+ const result = await executeBashCommand(params);
8195
+ const formattedResult = formatResult(result, params.command);
8196
+ context.logger.info("Bash: Command completed", {
8197
+ exitCode: result.exitCode,
8198
+ timedOut: result.timedOut,
8199
+ blocked: result.blocked
8200
+ });
8201
+ if (context.onFinish) {
8202
+ await context.onFinish("bash_execute", {
8203
+ command: params.command,
8204
+ exitCode: result.exitCode,
8205
+ blocked: result.blocked
8206
+ });
8207
+ }
8208
+ return formattedResult;
8209
+ } catch (error) {
8210
+ context.logger.error("Bash: Command failed", error);
8211
+ if (context.onFinish) {
8212
+ await context.onFinish("bash_execute", {
8213
+ command: params.command,
8214
+ error: error instanceof Error ? error.message : "Unknown error"
8215
+ });
8216
+ }
8217
+ throw error;
8218
+ }
8219
+ },
8220
+ toolSchema: {
8221
+ name: "bash_execute",
8222
+ description: `Execute a bash command in the terminal. Use this for running shell commands, scripts, build tools, git operations, and other CLI tasks.
8223
+
8224
+ SAFETY NOTES:
8225
+ - Commands are executed in the current working directory (or specified cwd)
8226
+ - Dangerous commands (sudo, rm -rf /, etc.) are automatically blocked
8227
+ - Commands have a default timeout of 60 seconds (max 5 minutes)
8228
+ - Output is limited to prevent overwhelming responses
8229
+ - This tool ALWAYS requires user permission before execution
8230
+
8231
+ COMMON USE CASES:
8232
+ - Running build commands: npm run build, make, cargo build
8233
+ - Git operations: git status, git log, git diff
8234
+ - Viewing system info: ls, pwd, cat, head, tail
8235
+ - Running tests: npm test, pytest, cargo test
8236
+ - Package management: npm install, pip install
8237
+ - File operations: mkdir, cp, mv (with permission)
8238
+
8239
+ BLOCKED OPERATIONS:
8240
+ - sudo and privilege escalation
8241
+ - Recursive deletes on system paths
8242
+ - Direct disk operations
8243
+ - Fork bombs and resource exhaustion
8244
+ - Piping remote scripts to shell`,
8245
+ parameters: {
8246
+ type: "object",
8247
+ properties: {
8248
+ command: {
8249
+ type: "string",
8250
+ description: "The bash command to execute. Can include pipes, redirects, and chained commands."
8251
+ },
8252
+ cwd: {
8253
+ type: "string",
8254
+ description: "Working directory for the command, relative to the current directory (optional). Defaults to current directory. Cannot traverse outside project root."
8255
+ },
8256
+ timeout: {
8257
+ type: "number",
8258
+ description: "Timeout in milliseconds (optional, default: 60000, max: 300000). Command will be terminated if it exceeds this time."
8259
+ }
8260
+ },
8261
+ required: ["command"]
8262
+ }
8263
+ }
8264
+ })
8265
+ };
8266
+
7882
8267
  // ../../b4m-core/packages/services/dist/src/llm/tools/index.js
7883
8268
  var tools = {
7884
8269
  dice_roll: diceRollTool,
@@ -7906,7 +8291,9 @@ var tools = {
7906
8291
  create_file: createFileTool,
7907
8292
  glob_files: globFilesTool,
7908
8293
  grep_search: grepSearchTool,
7909
- delete_file: deleteFileTool
8294
+ delete_file: deleteFileTool,
8295
+ // Shell execution
8296
+ bash_execute: bashExecuteTool
7910
8297
  };
7911
8298
  var generateTools = (userId, user, logger2, { db }, storage, imageGenerateStorage, statusUpdate, onStart, onFinish, llm, config, model) => {
7912
8299
  const context = {
@@ -8186,21 +8573,21 @@ var NoOpStorage = class extends BaseStorage {
8186
8573
  async upload(input, destination, options) {
8187
8574
  return `/tmp/${destination}`;
8188
8575
  }
8189
- async download(path13) {
8576
+ async download(path14) {
8190
8577
  throw new Error("Download not supported in CLI");
8191
8578
  }
8192
- async delete(path13) {
8579
+ async delete(path14) {
8193
8580
  }
8194
- async getSignedUrl(path13) {
8195
- return `/tmp/${path13}`;
8581
+ async getSignedUrl(path14) {
8582
+ return `/tmp/${path14}`;
8196
8583
  }
8197
- getPublicUrl(path13) {
8198
- return `/tmp/${path13}`;
8584
+ getPublicUrl(path14) {
8585
+ return `/tmp/${path14}`;
8199
8586
  }
8200
- async getPreview(path13) {
8201
- return `/tmp/${path13}`;
8587
+ async getPreview(path14) {
8588
+ return `/tmp/${path14}`;
8202
8589
  }
8203
- async getMetadata(path13) {
8590
+ async getMetadata(path14) {
8204
8591
  return { size: 0, contentType: "application/octet-stream" };
8205
8592
  }
8206
8593
  };
@@ -8258,6 +8645,10 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
8258
8645
  } catch (error) {
8259
8646
  preview = `[Could not generate preview: ${error instanceof Error ? error.message : "Unknown error"}]`;
8260
8647
  }
8648
+ } else if (toolName === "bash_execute" && args?.command) {
8649
+ const cwd = args.cwd ? ` (in ${args.cwd})` : "";
8650
+ const timeout = args.timeout ? ` [timeout: ${args.timeout}ms]` : "";
8651
+ preview = `$ ${args.command}${cwd}${timeout}`;
8261
8652
  }
8262
8653
  const response = await showPermissionPrompt(toolName, args, preview);
8263
8654
  if (response.action === "deny") {
@@ -8324,6 +8715,8 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
8324
8715
  glob_files: {},
8325
8716
  grep_search: {},
8326
8717
  delete_file: {},
8718
+ // Shell execution (always requires permission)
8719
+ bash_execute: {},
8327
8720
  // Tools requiring API keys (only include if API key is available)
8328
8721
  ...hasSerperKey && { web_search: {} },
8329
8722
  // Requires SERPER_API_KEY
@@ -8389,6 +8782,7 @@ var DEFAULT_TOOL_CATEGORIES = {
8389
8782
  create_file: "prompt_always",
8390
8783
  delete_file: "prompt_always",
8391
8784
  shell_execute: "prompt_always",
8785
+ bash_execute: "prompt_always",
8392
8786
  git_commit: "prompt_always",
8393
8787
  git_push: "prompt_always",
8394
8788
  // ===== PROMPT DEFAULT (Repository read tools) =====
@@ -8527,7 +8921,7 @@ function getEnvironmentName(configApiConfig) {
8527
8921
 
8528
8922
  // src/utils/Logger.ts
8529
8923
  import fs10 from "fs/promises";
8530
- import path11 from "path";
8924
+ import path12 from "path";
8531
8925
  import os from "os";
8532
8926
  var Logger2 = class _Logger {
8533
8927
  constructor() {
@@ -8550,9 +8944,9 @@ var Logger2 = class _Logger {
8550
8944
  */
8551
8945
  async initialize(sessionId) {
8552
8946
  this.sessionId = sessionId;
8553
- const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
8947
+ const debugDir = path12.join(os.homedir(), ".bike4mind", "debug");
8554
8948
  await fs10.mkdir(debugDir, { recursive: true });
8555
- this.logFilePath = path11.join(debugDir, `${sessionId}.txt`);
8949
+ this.logFilePath = path12.join(debugDir, `${sessionId}.txt`);
8556
8950
  await this.writeToFile("INFO", "=== CLI SESSION START ===");
8557
8951
  }
8558
8952
  /**
@@ -8762,12 +9156,12 @@ var Logger2 = class _Logger {
8762
9156
  async cleanupOldLogs() {
8763
9157
  if (!this.fileLoggingEnabled) return;
8764
9158
  try {
8765
- const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
9159
+ const debugDir = path12.join(os.homedir(), ".bike4mind", "debug");
8766
9160
  const files = await fs10.readdir(debugDir);
8767
9161
  const now = Date.now();
8768
9162
  const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1e3;
8769
9163
  for (const file of files) {
8770
- const filePath = path11.join(debugDir, file);
9164
+ const filePath = path12.join(debugDir, file);
8771
9165
  const stats = await fs10.stat(filePath);
8772
9166
  if (stats.mtime.getTime() < thirtyDaysAgo) {
8773
9167
  await fs10.unlink(filePath);
@@ -8783,7 +9177,7 @@ var logger = Logger2.getInstance();
8783
9177
  // ../../b4m-core/packages/mcp/dist/src/client.js
8784
9178
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
8785
9179
  import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
8786
- import path12 from "path";
9180
+ import path13 from "path";
8787
9181
  import { existsSync as existsSync6, readdirSync as readdirSync3 } from "fs";
8788
9182
  var MCPClient = class {
8789
9183
  // Note: This class handles MCP server communication with repository filtering
@@ -8809,16 +9203,16 @@ var MCPClient = class {
8809
9203
  const root = process.env.INIT_CWD || process.cwd();
8810
9204
  const candidatePaths = [
8811
9205
  // When running from SST Lambda with node_modules structure (copyFiles)
8812
- path12.join(root, `node_modules/@bike4mind/mcp/dist/src/${this.serverName}/index.js`),
9206
+ path13.join(root, `node_modules/@bike4mind/mcp/dist/src/${this.serverName}/index.js`),
8813
9207
  // When running from SST Lambda deployed environment (/var/task)
8814
- path12.join(root, `b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9208
+ path13.join(root, `b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
8815
9209
  // When running from SST Lambda (.sst/artifacts/mcpHandler-dev), navigate to monorepo root (3 levels up)
8816
- path12.join(root, `../../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9210
+ path13.join(root, `../../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
8817
9211
  // When running from packages/client (Next.js app), navigate to monorepo root (2 levels up)
8818
- path12.join(root, `../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9212
+ path13.join(root, `../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
8819
9213
  // Original paths (backward compatibility)
8820
- path12.join(root, `/b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
8821
- path12.join(root, "core", "mcp", "servers", this.serverName, "dist", "index.js")
9214
+ path13.join(root, `/b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9215
+ path13.join(root, "core", "mcp", "servers", this.serverName, "dist", "index.js")
8822
9216
  ];
8823
9217
  const serverScriptPath = candidatePaths.find((p) => existsSync6(p));
8824
9218
  if (!serverScriptPath) {
@@ -9402,7 +9796,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
9402
9796
  // package.json
9403
9797
  var package_default = {
9404
9798
  name: "@bike4mind/cli",
9405
- version: "0.2.4",
9799
+ version: "0.2.5-cli-bash-tools.17096+f35bd3290",
9406
9800
  type: "module",
9407
9801
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
9408
9802
  license: "UNLICENSED",
@@ -9503,11 +9897,11 @@ var package_default = {
9503
9897
  zustand: "^4.5.4"
9504
9898
  },
9505
9899
  devDependencies: {
9506
- "@bike4mind/agents": "workspace:*",
9507
- "@bike4mind/common": "workspace:*",
9508
- "@bike4mind/mcp": "workspace:*",
9509
- "@bike4mind/services": "workspace:*",
9510
- "@bike4mind/utils": "workspace:*",
9900
+ "@bike4mind/agents": "0.1.0",
9901
+ "@bike4mind/common": "2.37.1-cli-bash-tools.17096+f35bd3290",
9902
+ "@bike4mind/mcp": "1.19.6-cli-bash-tools.17096+f35bd3290",
9903
+ "@bike4mind/services": "2.32.2-cli-bash-tools.17096+f35bd3290",
9904
+ "@bike4mind/utils": "2.1.1-cli-bash-tools.17096+f35bd3290",
9511
9905
  "@types/diff": "^5.0.9",
9512
9906
  "@types/jsonwebtoken": "^9.0.4",
9513
9907
  "@types/node": "^22.9.0",
@@ -9518,7 +9912,8 @@ var package_default = {
9518
9912
  tsx: "^4.21.0",
9519
9913
  typescript: "^5.9.3",
9520
9914
  vitest: "^3.2.4"
9521
- }
9915
+ },
9916
+ gitHead: "f35bd3290ab13624a00aae18adbbbb2439bb5bae"
9522
9917
  };
9523
9918
 
9524
9919
  // src/config/constants.ts
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-WR6YZRQV.js";
4
+ } from "./chunk-KUMTSAUN.js";
5
5
  import "./chunk-PDX44BCA.js";
6
6
 
7
7
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/llmMarkdownGenerator.js
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-WR6YZRQV.js";
4
+ } from "./chunk-KUMTSAUN.js";
5
5
  import "./chunk-PDX44BCA.js";
6
6
 
7
7
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/markdownGenerator.js
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  findMostSimilarMemento,
4
4
  getRelevantMementos
5
- } from "./chunk-WNBKV4FX.js";
6
- import "./chunk-LYNNVNEC.js";
5
+ } from "./chunk-L2Q4BSIU.js";
6
+ import "./chunk-TQUGMSCZ.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
- import "./chunk-WR6YZRQV.js";
8
+ import "./chunk-KUMTSAUN.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  findMostSimilarMemento,
File without changes
@@ -291,7 +291,7 @@ import {
291
291
  validateQuestMasterArtifactV2,
292
292
  validateReactArtifactV2,
293
293
  validateSvgArtifactV2
294
- } from "./chunk-WR6YZRQV.js";
294
+ } from "./chunk-KUMTSAUN.js";
295
295
  import "./chunk-PDX44BCA.js";
296
296
  export {
297
297
  ALL_IMAGE_MODELS,
@@ -120,7 +120,7 @@ import {
120
120
  validateMermaidSyntax,
121
121
  warmUpSettingsCache,
122
122
  withRetry
123
- } from "./chunk-LYNNVNEC.js";
123
+ } from "./chunk-TQUGMSCZ.js";
124
124
  import {
125
125
  Logger,
126
126
  NotificationDeduplicator,
@@ -129,7 +129,7 @@ import {
129
129
  postLowCreditsNotificationToSlack,
130
130
  postMessageToSlack
131
131
  } from "./chunk-AMDXHL6S.js";
132
- import "./chunk-WR6YZRQV.js";
132
+ import "./chunk-KUMTSAUN.js";
133
133
  import "./chunk-PDX44BCA.js";
134
134
  export {
135
135
  AWSBackend,
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  SubtractCreditsSchema,
4
4
  subtractCredits
5
- } from "./chunk-LEG2UM5Q.js";
6
- import "./chunk-LYNNVNEC.js";
5
+ } from "./chunk-BNFSIXHY.js";
6
+ import "./chunk-TQUGMSCZ.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
- import "./chunk-WR6YZRQV.js";
8
+ import "./chunk-KUMTSAUN.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  SubtractCreditsSchema,
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.5-cli-bash-tools.17096+f35bd3290",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -30,6 +30,15 @@
30
30
  "dist",
31
31
  "bin"
32
32
  ],
33
+ "scripts": {
34
+ "dev": "tsx src/index.tsx",
35
+ "build": "tsup",
36
+ "typecheck": "tsc --noEmit",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest",
39
+ "start": "node dist/index.js",
40
+ "prepublishOnly": "pnpm build"
41
+ },
33
42
  "dependencies": {
34
43
  "@anthropic-ai/sdk": "^0.22.0",
35
44
  "@aws-sdk/client-apigatewaymanagementapi": "3.654.0",
@@ -92,6 +101,11 @@
92
101
  "zustand": "^4.5.4"
93
102
  },
94
103
  "devDependencies": {
104
+ "@bike4mind/agents": "0.1.0",
105
+ "@bike4mind/common": "2.37.1-cli-bash-tools.17096+f35bd3290",
106
+ "@bike4mind/mcp": "1.19.6-cli-bash-tools.17096+f35bd3290",
107
+ "@bike4mind/services": "2.32.2-cli-bash-tools.17096+f35bd3290",
108
+ "@bike4mind/utils": "2.1.1-cli-bash-tools.17096+f35bd3290",
95
109
  "@types/diff": "^5.0.9",
96
110
  "@types/jsonwebtoken": "^9.0.4",
97
111
  "@types/node": "^22.9.0",
@@ -101,19 +115,7 @@
101
115
  "tsup": "^8.5.1",
102
116
  "tsx": "^4.21.0",
103
117
  "typescript": "^5.9.3",
104
- "vitest": "^3.2.4",
105
- "@bike4mind/agents": "0.1.0",
106
- "@bike4mind/mcp": "1.19.5",
107
- "@bike4mind/services": "2.32.1",
108
- "@bike4mind/utils": "2.1.0",
109
- "@bike4mind/common": "2.37.0"
118
+ "vitest": "^3.2.4"
110
119
  },
111
- "scripts": {
112
- "dev": "tsx src/index.tsx",
113
- "build": "tsup",
114
- "typecheck": "tsc --noEmit",
115
- "test": "vitest run",
116
- "test:watch": "vitest",
117
- "start": "node dist/index.js"
118
- }
119
- }
120
+ "gitHead": "f35bd3290ab13624a00aae18adbbbb2439bb5bae"
121
+ }