@bike4mind/cli 0.2.5-citables-display-web-search.17093 → 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-MVGLS65O.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
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BadRequestError,
4
4
  secureParameters
5
- } from "./chunk-MV6KQD6A.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-MVGLS65O.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";
@@ -7,11 +7,11 @@ import {
7
7
  getSettingsMap,
8
8
  getSettingsValue,
9
9
  secureParameters
10
- } from "./chunk-MV6KQD6A.js";
10
+ } from "./chunk-TQUGMSCZ.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
14
- } from "./chunk-MVGLS65O.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([
@@ -3745,35 +3747,6 @@ var ToolHealthSchema = z21.object({
3745
3747
  lastExecutionTime: z21.number().optional(),
3746
3748
  successRate: z21.number().optional()
3747
3749
  });
3748
- var CitableSourceSchema = z21.object({
3749
- /** Unique identifier - can be URL, UUID, or composite key */
3750
- id: z21.string(),
3751
- /** Source classification for UI rendering */
3752
- type: z21.enum(["web_url", "document", "dataset", "mcp"]),
3753
- /** Human-readable title/name */
3754
- title: z21.string(),
3755
- /** Navigation target (external URL, deep link, or hash route) */
3756
- url: z21.string().optional(),
3757
- /** Brief description or excerpt (1-2 sentences) */
3758
- description: z21.string().optional(),
3759
- /** ISO 8601 timestamp for freshness indication */
3760
- timestamp: z21.string().optional(),
3761
- /** Attribution for non-report sources */
3762
- author: z21.string().optional(),
3763
- /** Processing status for real-time updates */
3764
- status: z21.enum(["pending", "processing", "complete", "error"]).optional(),
3765
- /** Extensibility metadata */
3766
- metadata: z21.object({
3767
- sourceSystem: z21.string().optional(),
3768
- icon: z21.string().optional(),
3769
- tags: z21.array(z21.string()).optional(),
3770
- confidence: z21.number().optional(),
3771
- practiceAreas: z21.array(z21.string()).optional(),
3772
- chunkId: z21.string().optional(),
3773
- relevanceScore: z21.number().optional(),
3774
- fullContext: z21.string().optional()
3775
- }).passthrough().optional()
3776
- });
3777
3750
  var PromptMetaZodSchema = z21.object({
3778
3751
  model: PromptMetaModelSchema.optional(),
3779
3752
  tokenUsage: PromptMetaTokenUsageSchema.optional(),
@@ -3816,9 +3789,7 @@ var PromptMetaZodSchema = z21.object({
3816
3789
  failedSteps: z21.array(z21.string()).optional()
3817
3790
  }).optional(),
3818
3791
  // Phase 2: Tool health tracking
3819
- toolHealth: z21.array(ToolHealthSchema).optional(),
3820
- // Citable sources referenced in AI responses (from web_search, deep_research, RAG, MCP)
3821
- citables: z21.array(CitableSourceSchema).optional()
3792
+ toolHealth: z21.array(ToolHealthSchema).optional()
3822
3793
  });
3823
3794
 
3824
3795
  // ../../b4m-core/packages/common/dist/src/schemas/analytics/events/ai.js
@@ -6090,7 +6061,6 @@ export {
6090
6061
  API_SERVICE_GROUPS,
6091
6062
  settingsMap,
6092
6063
  StringBooleanSchema,
6093
- CitableSourceSchema,
6094
6064
  PromptMetaZodSchema,
6095
6065
  AiEvents,
6096
6066
  ApiKeyEvents,
@@ -6,12 +6,12 @@ import {
6
6
  getSettingsByNames,
7
7
  obfuscateApiKey,
8
8
  secureParameters
9
- } from "./chunk-MV6KQD6A.js";
9
+ } from "./chunk-TQUGMSCZ.js";
10
10
  import {
11
11
  ApiKeyType,
12
12
  MementoTier,
13
13
  isSupportedEmbeddingModel
14
- } from "./chunk-MVGLS65O.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";
@@ -16,7 +16,7 @@ import {
16
16
  dayjsConfig_default,
17
17
  extractSnippetMeta,
18
18
  settingsMap
19
- } from "./chunk-MVGLS65O.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-KXHWFSYD.js";
6
- import "./chunk-MV6KQD6A.js";
5
+ } from "./chunk-FJ6BRMJD.js";
6
+ import "./chunk-TQUGMSCZ.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
- import "./chunk-MVGLS65O.js";
8
+ import "./chunk-KUMTSAUN.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  createFabFile,
package/dist/index.js CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  getEffectiveApiKey,
5
5
  getOpenWeatherKey,
6
6
  getSerperKey
7
- } from "./chunk-4PHLXSN3.js";
8
- import "./chunk-2R6BM6L6.js";
9
- import "./chunk-KXHWFSYD.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-MV6KQD6A.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-MVGLS65O.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) {
@@ -4471,30 +4471,13 @@ async function performWebSearch(adapters, params) {
4471
4471
  link: result.link,
4472
4472
  snippet: result.snippet
4473
4473
  })) || [];
4474
- const citables = results.map((result, index) => ({
4475
- id: result.link,
4476
- // Use URL as unique identifier
4477
- type: "web_url",
4478
- title: result.title,
4479
- url: result.link,
4480
- description: result.snippet,
4481
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4482
- status: "complete",
4483
- metadata: {
4484
- sourceSystem: "web_search",
4485
- relevanceScore: 1 - index * 0.1,
4486
- // Higher relevance for earlier results
4487
- fullContext: result.snippet
4488
- }
4489
- }));
4490
4474
  const formattedResults = results.map((result, index) => `${index + 1}. **${result.title}**
4491
4475
  ${result.snippet}
4492
4476
  Source: [${new URL(result.link).hostname}](${result.link})
4493
4477
  `).join("\n");
4494
- const formattedOutput = formattedResults ? `Here's what I found from searching the web:
4478
+ return formattedResults ? `Here's what I found from searching the web:
4495
4479
 
4496
4480
  ${formattedResults}` : "No results found from web search.";
4497
- return { formattedResults: formattedOutput, citables };
4498
4481
  } catch (error) {
4499
4482
  console.error("\u274C WebSearch Tool: Error during search:", error);
4500
4483
  throw error;
@@ -4505,18 +4488,7 @@ var webSearchTool = {
4505
4488
  implementation: (context) => ({
4506
4489
  toolFn: async (value) => {
4507
4490
  const params = value;
4508
- const { formattedResults, citables } = await performWebSearch({ db: context.db }, params);
4509
- if (citables.length > 0) {
4510
- await context.statusUpdate({
4511
- // Store citables in promptMeta - statusUpdate will Object.assign this
4512
- // The receiving code needs to handle merging promptMeta.citables
4513
- promptMeta: {
4514
- citables
4515
- }
4516
- }, "Web search complete");
4517
- console.log(`\u{1F4DA} WebSearch Tool: Stored ${citables.length} citables`);
4518
- }
4519
- return formattedResults;
4491
+ return performWebSearch({ db: context.db }, params);
4520
4492
  },
4521
4493
  toolSchema: {
4522
4494
  name: "web_search",
@@ -5494,8 +5466,8 @@ async function processAndStoreImage(imageUrl, context) {
5494
5466
  const buffer = await downloadImage2(imageUrl);
5495
5467
  const fileType = await fileTypeFromBuffer3(buffer);
5496
5468
  const filename = `${uuidv46()}.${fileType?.ext}`;
5497
- const path13 = await context.imageGenerateStorage.upload(buffer, filename, {});
5498
- return path13;
5469
+ const path14 = await context.imageGenerateStorage.upload(buffer, filename, {});
5470
+ return path14;
5499
5471
  }
5500
5472
  async function updateQuestAndReturnMarkdown2(storedImagePath, context) {
5501
5473
  await context.onFinish?.("edit_image", storedImagePath);
@@ -7907,6 +7879,391 @@ var deleteFileTool = {
7907
7879
  })
7908
7880
  };
7909
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
+
7910
8267
  // ../../b4m-core/packages/services/dist/src/llm/tools/index.js
7911
8268
  var tools = {
7912
8269
  dice_roll: diceRollTool,
@@ -7934,7 +8291,9 @@ var tools = {
7934
8291
  create_file: createFileTool,
7935
8292
  glob_files: globFilesTool,
7936
8293
  grep_search: grepSearchTool,
7937
- delete_file: deleteFileTool
8294
+ delete_file: deleteFileTool,
8295
+ // Shell execution
8296
+ bash_execute: bashExecuteTool
7938
8297
  };
7939
8298
  var generateTools = (userId, user, logger2, { db }, storage, imageGenerateStorage, statusUpdate, onStart, onFinish, llm, config, model) => {
7940
8299
  const context = {
@@ -8214,21 +8573,21 @@ var NoOpStorage = class extends BaseStorage {
8214
8573
  async upload(input, destination, options) {
8215
8574
  return `/tmp/${destination}`;
8216
8575
  }
8217
- async download(path13) {
8576
+ async download(path14) {
8218
8577
  throw new Error("Download not supported in CLI");
8219
8578
  }
8220
- async delete(path13) {
8579
+ async delete(path14) {
8221
8580
  }
8222
- async getSignedUrl(path13) {
8223
- return `/tmp/${path13}`;
8581
+ async getSignedUrl(path14) {
8582
+ return `/tmp/${path14}`;
8224
8583
  }
8225
- getPublicUrl(path13) {
8226
- return `/tmp/${path13}`;
8584
+ getPublicUrl(path14) {
8585
+ return `/tmp/${path14}`;
8227
8586
  }
8228
- async getPreview(path13) {
8229
- return `/tmp/${path13}`;
8587
+ async getPreview(path14) {
8588
+ return `/tmp/${path14}`;
8230
8589
  }
8231
- async getMetadata(path13) {
8590
+ async getMetadata(path14) {
8232
8591
  return { size: 0, contentType: "application/octet-stream" };
8233
8592
  }
8234
8593
  };
@@ -8286,6 +8645,10 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
8286
8645
  } catch (error) {
8287
8646
  preview = `[Could not generate preview: ${error instanceof Error ? error.message : "Unknown error"}]`;
8288
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}`;
8289
8652
  }
8290
8653
  const response = await showPermissionPrompt(toolName, args, preview);
8291
8654
  if (response.action === "deny") {
@@ -8352,6 +8715,8 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
8352
8715
  glob_files: {},
8353
8716
  grep_search: {},
8354
8717
  delete_file: {},
8718
+ // Shell execution (always requires permission)
8719
+ bash_execute: {},
8355
8720
  // Tools requiring API keys (only include if API key is available)
8356
8721
  ...hasSerperKey && { web_search: {} },
8357
8722
  // Requires SERPER_API_KEY
@@ -8417,6 +8782,7 @@ var DEFAULT_TOOL_CATEGORIES = {
8417
8782
  create_file: "prompt_always",
8418
8783
  delete_file: "prompt_always",
8419
8784
  shell_execute: "prompt_always",
8785
+ bash_execute: "prompt_always",
8420
8786
  git_commit: "prompt_always",
8421
8787
  git_push: "prompt_always",
8422
8788
  // ===== PROMPT DEFAULT (Repository read tools) =====
@@ -8555,7 +8921,7 @@ function getEnvironmentName(configApiConfig) {
8555
8921
 
8556
8922
  // src/utils/Logger.ts
8557
8923
  import fs10 from "fs/promises";
8558
- import path11 from "path";
8924
+ import path12 from "path";
8559
8925
  import os from "os";
8560
8926
  var Logger2 = class _Logger {
8561
8927
  constructor() {
@@ -8578,9 +8944,9 @@ var Logger2 = class _Logger {
8578
8944
  */
8579
8945
  async initialize(sessionId) {
8580
8946
  this.sessionId = sessionId;
8581
- const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
8947
+ const debugDir = path12.join(os.homedir(), ".bike4mind", "debug");
8582
8948
  await fs10.mkdir(debugDir, { recursive: true });
8583
- this.logFilePath = path11.join(debugDir, `${sessionId}.txt`);
8949
+ this.logFilePath = path12.join(debugDir, `${sessionId}.txt`);
8584
8950
  await this.writeToFile("INFO", "=== CLI SESSION START ===");
8585
8951
  }
8586
8952
  /**
@@ -8790,12 +9156,12 @@ var Logger2 = class _Logger {
8790
9156
  async cleanupOldLogs() {
8791
9157
  if (!this.fileLoggingEnabled) return;
8792
9158
  try {
8793
- const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
9159
+ const debugDir = path12.join(os.homedir(), ".bike4mind", "debug");
8794
9160
  const files = await fs10.readdir(debugDir);
8795
9161
  const now = Date.now();
8796
9162
  const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1e3;
8797
9163
  for (const file of files) {
8798
- const filePath = path11.join(debugDir, file);
9164
+ const filePath = path12.join(debugDir, file);
8799
9165
  const stats = await fs10.stat(filePath);
8800
9166
  if (stats.mtime.getTime() < thirtyDaysAgo) {
8801
9167
  await fs10.unlink(filePath);
@@ -8811,7 +9177,7 @@ var logger = Logger2.getInstance();
8811
9177
  // ../../b4m-core/packages/mcp/dist/src/client.js
8812
9178
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
8813
9179
  import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
8814
- import path12 from "path";
9180
+ import path13 from "path";
8815
9181
  import { existsSync as existsSync6, readdirSync as readdirSync3 } from "fs";
8816
9182
  var MCPClient = class {
8817
9183
  // Note: This class handles MCP server communication with repository filtering
@@ -8837,16 +9203,16 @@ var MCPClient = class {
8837
9203
  const root = process.env.INIT_CWD || process.cwd();
8838
9204
  const candidatePaths = [
8839
9205
  // When running from SST Lambda with node_modules structure (copyFiles)
8840
- 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`),
8841
9207
  // When running from SST Lambda deployed environment (/var/task)
8842
- 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`),
8843
9209
  // When running from SST Lambda (.sst/artifacts/mcpHandler-dev), navigate to monorepo root (3 levels up)
8844
- 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`),
8845
9211
  // When running from packages/client (Next.js app), navigate to monorepo root (2 levels up)
8846
- 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`),
8847
9213
  // Original paths (backward compatibility)
8848
- path12.join(root, `/b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
8849
- 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")
8850
9216
  ];
8851
9217
  const serverScriptPath = candidatePaths.find((p) => existsSync6(p));
8852
9218
  if (!serverScriptPath) {
@@ -9430,7 +9796,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
9430
9796
  // package.json
9431
9797
  var package_default = {
9432
9798
  name: "@bike4mind/cli",
9433
- version: "0.2.5-citables-display-web-search.17093+01315691b",
9799
+ version: "0.2.5-cli-bash-tools.17096+f35bd3290",
9434
9800
  type: "module",
9435
9801
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
9436
9802
  license: "UNLICENSED",
@@ -9532,10 +9898,10 @@ var package_default = {
9532
9898
  },
9533
9899
  devDependencies: {
9534
9900
  "@bike4mind/agents": "0.1.0",
9535
- "@bike4mind/common": "2.37.1-citables-display-web-search.17093+01315691b",
9536
- "@bike4mind/mcp": "1.19.6-citables-display-web-search.17093+01315691b",
9537
- "@bike4mind/services": "2.32.2-citables-display-web-search.17093+01315691b",
9538
- "@bike4mind/utils": "2.1.1-citables-display-web-search.17093+01315691b",
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",
9539
9905
  "@types/diff": "^5.0.9",
9540
9906
  "@types/jsonwebtoken": "^9.0.4",
9541
9907
  "@types/node": "^22.9.0",
@@ -9547,7 +9913,7 @@ var package_default = {
9547
9913
  typescript: "^5.9.3",
9548
9914
  vitest: "^3.2.4"
9549
9915
  },
9550
- gitHead: "01315691bda21256368539f634c17c96cafe413b"
9916
+ gitHead: "f35bd3290ab13624a00aae18adbbbb2439bb5bae"
9551
9917
  };
9552
9918
 
9553
9919
  // src/config/constants.ts
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-MVGLS65O.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-MVGLS65O.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-4PHLXSN3.js";
6
- import "./chunk-MV6KQD6A.js";
5
+ } from "./chunk-L2Q4BSIU.js";
6
+ import "./chunk-TQUGMSCZ.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
- import "./chunk-MVGLS65O.js";
8
+ import "./chunk-KUMTSAUN.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  findMostSimilarMemento,
@@ -37,7 +37,6 @@ import {
37
37
  ChatCompletionInvokeParamsSchema,
38
38
  ChatHistoryItemWithArtifactsSchema,
39
39
  ChatModels,
40
- CitableSourceSchema,
41
40
  ClaudeArtifactMimeTypes,
42
41
  CollectionType,
43
42
  CompletionRequestSchema,
@@ -292,7 +291,7 @@ import {
292
291
  validateQuestMasterArtifactV2,
293
292
  validateReactArtifactV2,
294
293
  validateSvgArtifactV2
295
- } from "./chunk-MVGLS65O.js";
294
+ } from "./chunk-KUMTSAUN.js";
296
295
  import "./chunk-PDX44BCA.js";
297
296
  export {
298
297
  ALL_IMAGE_MODELS,
@@ -332,7 +331,6 @@ export {
332
331
  ChatCompletionInvokeParamsSchema,
333
332
  ChatHistoryItemWithArtifactsSchema,
334
333
  ChatModels,
335
- CitableSourceSchema,
336
334
  ClaudeArtifactMimeTypes,
337
335
  CollectionType,
338
336
  CompletionRequestSchema,
@@ -120,7 +120,7 @@ import {
120
120
  validateMermaidSyntax,
121
121
  warmUpSettingsCache,
122
122
  withRetry
123
- } from "./chunk-MV6KQD6A.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-MVGLS65O.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-2R6BM6L6.js";
6
- import "./chunk-MV6KQD6A.js";
5
+ } from "./chunk-BNFSIXHY.js";
6
+ import "./chunk-TQUGMSCZ.js";
7
7
  import "./chunk-AMDXHL6S.js";
8
- import "./chunk-MVGLS65O.js";
8
+ import "./chunk-KUMTSAUN.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  SubtractCreditsSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.5-citables-display-web-search.17093+01315691b",
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",
@@ -102,10 +102,10 @@
102
102
  },
103
103
  "devDependencies": {
104
104
  "@bike4mind/agents": "0.1.0",
105
- "@bike4mind/common": "2.37.1-citables-display-web-search.17093+01315691b",
106
- "@bike4mind/mcp": "1.19.6-citables-display-web-search.17093+01315691b",
107
- "@bike4mind/services": "2.32.2-citables-display-web-search.17093+01315691b",
108
- "@bike4mind/utils": "2.1.1-citables-display-web-search.17093+01315691b",
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",
109
109
  "@types/diff": "^5.0.9",
110
110
  "@types/jsonwebtoken": "^9.0.4",
111
111
  "@types/node": "^22.9.0",
@@ -117,5 +117,5 @@
117
117
  "typescript": "^5.9.3",
118
118
  "vitest": "^3.2.4"
119
119
  },
120
- "gitHead": "01315691bda21256368539f634c17c96cafe413b"
120
+ "gitHead": "f35bd3290ab13624a00aae18adbbbb2439bb5bae"
121
121
  }