@probelabs/probe 0.6.0-rc105 → 0.6.0-rc107

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.
@@ -14,6 +14,7 @@ const HTML_ENTITY_MAP = {
14
14
  '&': '&',
15
15
  '"': '"',
16
16
  ''': "'",
17
+ ''': "'", // Also handle XML/HTML5 apostrophe entity
17
18
  ' ': ' '
18
19
  };
19
20
 
@@ -1183,16 +1184,35 @@ export async function validateAndFixMermaidResponse(response, options = {}) {
1183
1184
  // Enhanced auto-fixing for square bracket nodes [...]
1184
1185
  if (trimmedLine.match(/\[[^\]]*\]/)) {
1185
1186
  modifiedLine = modifiedLine.replace(/\[([^\]]*)\]/g, (match, content) => {
1186
- // Skip if already properly quoted
1187
+ // Check if already properly quoted with outer quotes
1187
1188
  if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
1189
+ // Extract the inner content (between the outer quotes)
1190
+ const innerContent = content.trim().slice(1, -1);
1191
+ // Check if inner content has unescaped quotes that need escaping
1192
+ if (innerContent.includes('"') || innerContent.includes("'")) {
1193
+ wasFixed = true;
1194
+ // Decode any existing HTML entities first, then re-encode ALL quotes
1195
+ const decodedContent = decodeHtmlEntities(innerContent);
1196
+ const safeContent = decodedContent
1197
+ .replace(/"/g, '"') // Replace ALL double quotes with HTML entity
1198
+ .replace(/'/g, '''); // Replace ALL single quotes with HTML entity
1199
+ return `["${safeContent}"]`;
1200
+ }
1188
1201
  return match;
1189
1202
  }
1190
1203
 
1191
1204
  // Check if content needs quoting (contains problematic patterns)
1192
1205
  if (needsQuoting(content)) {
1193
1206
  wasFixed = true;
1194
- // Replace internal double quotes with single quotes to avoid nesting
1195
- const safeContent = content.replace(/"/g, "'");
1207
+ // Use HTML entities for quotes as per Mermaid best practices:
1208
+ // - GitHub doesn't support single quotes in node labels (causes 'got PS' error)
1209
+ // - HTML entities are the official way to escape quotes in Mermaid
1210
+ // - Always use double quotes with square brackets ["..."] for node labels
1211
+ // IMPORTANT: Decode any existing HTML entities first to avoid double-encoding
1212
+ const decodedContent = decodeHtmlEntities(content);
1213
+ const safeContent = decodedContent
1214
+ .replace(/"/g, '"') // Replace double quotes with HTML entity
1215
+ .replace(/'/g, '''); // Replace single quotes with HTML entity
1196
1216
  return `["${safeContent}"]`;
1197
1217
  }
1198
1218
 
@@ -1203,16 +1223,35 @@ export async function validateAndFixMermaidResponse(response, options = {}) {
1203
1223
  // Enhanced auto-fixing for diamond nodes {...}
1204
1224
  if (trimmedLine.match(/\{[^{}]*\}/)) {
1205
1225
  modifiedLine = modifiedLine.replace(/\{([^{}]*)\}/g, (match, content) => {
1206
- // Skip if already properly quoted
1226
+ // Check if already properly quoted with outer quotes
1207
1227
  if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
1228
+ // Extract the inner content (between the outer quotes)
1229
+ const innerContent = content.trim().slice(1, -1);
1230
+ // Check if inner content has unescaped quotes that need escaping
1231
+ if (innerContent.includes('"') || innerContent.includes("'")) {
1232
+ wasFixed = true;
1233
+ // Decode any existing HTML entities first, then re-encode ALL quotes
1234
+ const decodedContent = decodeHtmlEntities(innerContent);
1235
+ const safeContent = decodedContent
1236
+ .replace(/"/g, '"') // Replace ALL double quotes with HTML entity
1237
+ .replace(/'/g, '''); // Replace ALL single quotes with HTML entity
1238
+ return `{"${safeContent}"}`;
1239
+ }
1208
1240
  return match;
1209
1241
  }
1210
1242
 
1211
1243
  // Check if content needs quoting (contains problematic patterns)
1212
1244
  if (needsQuoting(content)) {
1213
1245
  wasFixed = true;
1214
- // Replace internal double quotes with single quotes to avoid nesting
1215
- const safeContent = content.replace(/"/g, "'");
1246
+ // Use HTML entities for quotes as per Mermaid best practices:
1247
+ // - GitHub doesn't support single quotes in node labels (causes 'got PS' error)
1248
+ // - HTML entities are the official way to escape quotes in Mermaid
1249
+ // - Always use double quotes with curly brackets {"..."} for diamond nodes
1250
+ // IMPORTANT: Decode any existing HTML entities first to avoid double-encoding
1251
+ const decodedContent = decodeHtmlEntities(content);
1252
+ const safeContent = decodedContent
1253
+ .replace(/"/g, '"') // Replace double quotes with HTML entity
1254
+ .replace(/'/g, '''); // Replace single quotes with HTML entity
1216
1255
  return `{"${safeContent}"}`;
1217
1256
  }
1218
1257
 
@@ -1438,16 +1477,35 @@ export async function validateAndFixMermaidResponse(response, options = {}) {
1438
1477
  // Look for any node labels that contain special characters and aren't already quoted
1439
1478
  if (trimmedLine.match(/\[[^\]]*\]/)) {
1440
1479
  modifiedLine = modifiedLine.replace(/\[([^\]]*)\]/g, (match, content) => {
1441
- // Skip if already properly quoted
1480
+ // Check if already properly quoted with outer quotes
1442
1481
  if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
1482
+ // Extract the inner content (between the outer quotes)
1483
+ const innerContent = content.trim().slice(1, -1);
1484
+ // Check if inner content has unescaped quotes that need escaping
1485
+ if (innerContent.includes('"') || innerContent.includes("'")) {
1486
+ wasFixed = true;
1487
+ // Decode any existing HTML entities first, then re-encode ALL quotes
1488
+ const decodedContent = decodeHtmlEntities(innerContent);
1489
+ const safeContent = decodedContent
1490
+ .replace(/"/g, '"') // Replace ALL double quotes with HTML entity
1491
+ .replace(/'/g, '''); // Replace ALL single quotes with HTML entity
1492
+ return `["${safeContent}"]`;
1493
+ }
1443
1494
  return match;
1444
1495
  }
1445
1496
 
1446
1497
  // Check if content needs quoting (contains problematic patterns)
1447
1498
  if (needsQuoting(content)) {
1448
1499
  wasFixed = true;
1449
- // Replace internal double quotes with single quotes to avoid nesting
1450
- const safeContent = content.replace(/"/g, "'");
1500
+ // Use HTML entities for quotes as per Mermaid best practices:
1501
+ // - GitHub doesn't support single quotes in node labels (causes 'got PS' error)
1502
+ // - HTML entities are the official way to escape quotes in Mermaid
1503
+ // - Always use double quotes with square brackets ["..."] for node labels
1504
+ // IMPORTANT: Decode any existing HTML entities first to avoid double-encoding
1505
+ const decodedContent = decodeHtmlEntities(content);
1506
+ const safeContent = decodedContent
1507
+ .replace(/"/g, '"') // Replace double quotes with HTML entity
1508
+ .replace(/'/g, '''); // Replace single quotes with HTML entity
1451
1509
  return `["${safeContent}"]`;
1452
1510
  }
1453
1511
 
@@ -1458,16 +1516,35 @@ export async function validateAndFixMermaidResponse(response, options = {}) {
1458
1516
  // Enhanced auto-fixing for diamond nodes {...}
1459
1517
  if (trimmedLine.match(/\{[^{}]*\}/)) {
1460
1518
  modifiedLine = modifiedLine.replace(/\{([^{}]*)\}/g, (match, content) => {
1461
- // Skip if already properly quoted
1519
+ // Check if already properly quoted with outer quotes
1462
1520
  if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
1521
+ // Extract the inner content (between the outer quotes)
1522
+ const innerContent = content.trim().slice(1, -1);
1523
+ // Check if inner content has unescaped quotes that need escaping
1524
+ if (innerContent.includes('"') || innerContent.includes("'")) {
1525
+ wasFixed = true;
1526
+ // Decode any existing HTML entities first, then re-encode ALL quotes
1527
+ const decodedContent = decodeHtmlEntities(innerContent);
1528
+ const safeContent = decodedContent
1529
+ .replace(/"/g, '"') // Replace ALL double quotes with HTML entity
1530
+ .replace(/'/g, '''); // Replace ALL single quotes with HTML entity
1531
+ return `{"${safeContent}"}`;
1532
+ }
1463
1533
  return match;
1464
1534
  }
1465
1535
 
1466
1536
  // Check if content needs quoting (contains problematic patterns)
1467
1537
  if (needsQuoting(content)) {
1468
1538
  wasFixed = true;
1469
- // Replace internal double quotes with single quotes to avoid nesting
1470
- const safeContent = content.replace(/"/g, "'");
1539
+ // Use HTML entities for quotes as per Mermaid best practices:
1540
+ // - GitHub doesn't support single quotes in node labels (causes 'got PS' error)
1541
+ // - HTML entities are the official way to escape quotes in Mermaid
1542
+ // - Always use double quotes with curly brackets {"..."} for diamond nodes
1543
+ // IMPORTANT: Decode any existing HTML entities first to avoid double-encoding
1544
+ const decodedContent = decodeHtmlEntities(content);
1545
+ const safeContent = decodedContent
1546
+ .replace(/"/g, '"') // Replace double quotes with HTML entity
1547
+ .replace(/'/g, '''); // Replace single quotes with HTML entity
1471
1548
  return `{"${safeContent}"}`;
1472
1549
  }
1473
1550
 
@@ -4,6 +4,7 @@ import {
4
4
  queryTool,
5
5
  extractTool,
6
6
  delegateTool,
7
+ bashTool,
7
8
  DEFAULT_SYSTEM_MESSAGE,
8
9
  attemptCompletionSchema,
9
10
  attemptCompletionToolDefinition,
@@ -11,10 +12,12 @@ import {
11
12
  querySchema,
12
13
  extractSchema,
13
14
  delegateSchema,
15
+ bashSchema,
14
16
  searchToolDefinition,
15
17
  queryToolDefinition,
16
18
  extractToolDefinition,
17
19
  delegateToolDefinition,
20
+ bashToolDefinition,
18
21
  parseXmlToolCall
19
22
  } from '../index.js';
20
23
  import { randomUUID } from 'crypto';
@@ -22,12 +25,19 @@ import { processXmlWithThinkingAndRecovery } from './xmlParsingUtils.js';
22
25
 
23
26
  // Create configured tool instances
24
27
  export function createTools(configOptions) {
25
- return {
28
+ const tools = {
26
29
  searchTool: searchTool(configOptions),
27
30
  queryTool: queryTool(configOptions),
28
31
  extractTool: extractTool(configOptions),
29
32
  delegateTool: delegateTool(configOptions)
30
33
  };
34
+
35
+ // Add bash tool if enabled
36
+ if (configOptions.enableBash) {
37
+ tools.bashTool = bashTool(configOptions);
38
+ }
39
+
40
+ return tools;
31
41
  }
32
42
 
33
43
  // Export tool definitions and schemas
@@ -37,11 +47,13 @@ export {
37
47
  querySchema,
38
48
  extractSchema,
39
49
  delegateSchema,
50
+ bashSchema,
40
51
  attemptCompletionSchema,
41
52
  searchToolDefinition,
42
53
  queryToolDefinition,
43
54
  extractToolDefinition,
44
55
  delegateToolDefinition,
56
+ bashToolDefinition,
45
57
  attemptCompletionToolDefinition,
46
58
  parseXmlToolCall
47
59
  };
package/src/index.js CHANGED
@@ -21,14 +21,17 @@ import {
21
21
  extractSchema,
22
22
  delegateSchema,
23
23
  attemptCompletionSchema,
24
+ bashSchema,
24
25
  searchToolDefinition,
25
26
  queryToolDefinition,
26
27
  extractToolDefinition,
27
28
  delegateToolDefinition,
28
29
  attemptCompletionToolDefinition,
30
+ bashToolDefinition,
29
31
  parseXmlToolCall
30
32
  } from './tools/common.js';
31
33
  import { searchTool, queryTool, extractTool, delegateTool } from './tools/vercel.js';
34
+ import { bashTool } from './tools/bash.js';
32
35
  import { ProbeAgent } from './agent/ProbeAgent.js';
33
36
  import { SimpleTelemetry, SimpleAppTracer, initializeSimpleTelemetryFromOptions } from './agent/simpleTelemetry.js';
34
37
 
@@ -53,18 +56,21 @@ export {
53
56
  queryTool,
54
57
  extractTool,
55
58
  delegateTool,
59
+ bashTool,
56
60
  // Export schemas
57
61
  searchSchema,
58
62
  querySchema,
59
63
  extractSchema,
60
64
  delegateSchema,
61
65
  attemptCompletionSchema,
66
+ bashSchema,
62
67
  // Export tool definitions
63
68
  searchToolDefinition,
64
69
  queryToolDefinition,
65
70
  extractToolDefinition,
66
71
  delegateToolDefinition,
67
72
  attemptCompletionToolDefinition,
73
+ bashToolDefinition,
68
74
  // Export parser function
69
75
  parseXmlToolCall
70
76
  };
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Bash command execution tool for Vercel AI SDK
3
+ * @module tools/bash
4
+ */
5
+
6
+ import { tool } from 'ai';
7
+ import { resolve } from 'path';
8
+ import { BashPermissionChecker } from '../agent/bashPermissions.js';
9
+ import { executeBashCommand, formatExecutionResult, validateExecutionOptions } from '../agent/bashExecutor.js';
10
+
11
+ /**
12
+ * Bash tool generator
13
+ *
14
+ * @param {Object} [options] - Configuration options
15
+ * @param {Object} [options.bashConfig] - Bash-specific configuration
16
+ * @param {string[]} [options.bashConfig.allow] - Additional allow patterns
17
+ * @param {string[]} [options.bashConfig.deny] - Additional deny patterns
18
+ * @param {boolean} [options.bashConfig.disableDefaultAllow] - Disable default allow list
19
+ * @param {boolean} [options.bashConfig.disableDefaultDeny] - Disable default deny list
20
+ * @param {number} [options.bashConfig.timeout=120000] - Command timeout in milliseconds
21
+ * @param {string} [options.bashConfig.workingDirectory] - Default working directory
22
+ * @param {Object} [options.bashConfig.env={}] - Default environment variables
23
+ * @param {number} [options.bashConfig.maxBuffer] - Maximum output buffer size
24
+ * @param {boolean} [options.debug=false] - Enable debug logging
25
+ * @param {string} [options.defaultPath] - Default working directory from probe config
26
+ * @param {string[]} [options.allowedFolders] - Allowed directories for execution
27
+ * @returns {Object} Configured bash tool
28
+ */
29
+ export const bashTool = (options = {}) => {
30
+ const {
31
+ bashConfig = {},
32
+ debug = false,
33
+ defaultPath,
34
+ allowedFolders = []
35
+ } = options;
36
+
37
+ // Create permission checker
38
+ const permissionChecker = new BashPermissionChecker({
39
+ allow: bashConfig.allow,
40
+ deny: bashConfig.deny,
41
+ disableDefaultAllow: bashConfig.disableDefaultAllow,
42
+ disableDefaultDeny: bashConfig.disableDefaultDeny,
43
+ debug
44
+ });
45
+
46
+ // Determine default working directory
47
+ const getDefaultWorkingDirectory = () => {
48
+ if (bashConfig.workingDirectory) {
49
+ return bashConfig.workingDirectory;
50
+ }
51
+ if (defaultPath) {
52
+ return defaultPath;
53
+ }
54
+ if (allowedFolders && allowedFolders.length > 0) {
55
+ return allowedFolders[0];
56
+ }
57
+ return process.cwd();
58
+ };
59
+
60
+ return tool({
61
+ name: 'bash',
62
+ description: `Execute bash commands for system exploration and development tasks.
63
+
64
+ Security: This tool has built-in security with allow/deny lists. By default, only safe read-only commands are allowed for code exploration.
65
+
66
+ Parameters:
67
+ - command: (required) The bash command to execute
68
+ - workingDirectory: (optional) Directory to execute command in
69
+ - timeout: (optional) Command timeout in milliseconds
70
+ - env: (optional) Additional environment variables
71
+
72
+ Examples of allowed commands by default:
73
+ - File exploration: ls, cat, head, tail, find, grep
74
+ - Git operations: git status, git log, git diff, git show
75
+ - Package info: npm list, pip list, cargo --version
76
+ - System info: whoami, pwd, uname, date
77
+
78
+ Dangerous commands are blocked by default (rm -rf, sudo, npm install, etc.)`,
79
+
80
+ inputSchema: {
81
+ type: 'object',
82
+ properties: {
83
+ command: {
84
+ type: 'string',
85
+ description: 'The bash command to execute'
86
+ },
87
+ workingDirectory: {
88
+ type: 'string',
89
+ description: 'Directory to execute the command in (optional)'
90
+ },
91
+ timeout: {
92
+ type: 'number',
93
+ description: 'Command timeout in milliseconds (optional)',
94
+ minimum: 1000,
95
+ maximum: 600000
96
+ },
97
+ env: {
98
+ type: 'object',
99
+ description: 'Additional environment variables (optional)',
100
+ additionalProperties: {
101
+ type: 'string'
102
+ }
103
+ }
104
+ },
105
+ required: ['command'],
106
+ additionalProperties: false
107
+ },
108
+
109
+ execute: async ({ command, workingDirectory, timeout, env }) => {
110
+ try {
111
+ // Validate command
112
+ if (command === null || command === undefined || typeof command !== 'string') {
113
+ return 'Error: Command is required and must be a string';
114
+ }
115
+
116
+ if (command.trim().length === 0) {
117
+ return 'Error: Command cannot be empty';
118
+ }
119
+
120
+ // Check permissions
121
+ const permissionResult = permissionChecker.check(command.trim());
122
+ if (!permissionResult.allowed) {
123
+ if (debug) {
124
+ console.log(`[BashTool] Permission denied for command: "${command}"`);
125
+ console.log(`[BashTool] Reason: ${permissionResult.reason}`);
126
+ }
127
+ return `Permission denied: ${permissionResult.reason}
128
+
129
+ This command is not allowed by the current security policy.
130
+
131
+ Common reasons:
132
+ 1. The command is in the deny list (potentially dangerous)
133
+ 2. The command is not in the allow list (not a recognized safe command)
134
+
135
+ If you believe this command should be allowed, you can:
136
+ - Use the --bash-allow option to add specific patterns
137
+ - Use the --no-default-bash-deny flag to remove default restrictions (not recommended)
138
+
139
+ For code exploration, try these safe alternatives:
140
+ - ls, cat, head, tail for file operations
141
+ - find, grep, rg for searching
142
+ - git status, git log, git show for git operations
143
+ - npm list, pip list for package information`;
144
+ }
145
+
146
+ // Determine working directory
147
+ const workingDir = workingDirectory || getDefaultWorkingDirectory();
148
+
149
+ // Validate working directory is within allowed folders if specified
150
+ if (allowedFolders && allowedFolders.length > 0) {
151
+ const resolvedWorkingDir = resolve(workingDir);
152
+ const isAllowed = allowedFolders.some(folder => {
153
+ const resolvedFolder = resolve(folder);
154
+ return resolvedWorkingDir.startsWith(resolvedFolder);
155
+ });
156
+
157
+ if (!isAllowed) {
158
+ return `Error: Working directory "${workingDir}" is not within allowed folders: ${allowedFolders.join(', ')}`;
159
+ }
160
+ }
161
+
162
+ // Prepare execution options
163
+ const executionOptions = {
164
+ workingDirectory: workingDir,
165
+ timeout: timeout || bashConfig.timeout || 120000,
166
+ env: { ...bashConfig.env, ...env },
167
+ maxBuffer: bashConfig.maxBuffer,
168
+ debug
169
+ };
170
+
171
+ // Validate execution options
172
+ const validation = validateExecutionOptions(executionOptions);
173
+ if (!validation.valid) {
174
+ return `Error: Invalid execution options: ${validation.errors.join(', ')}`;
175
+ }
176
+
177
+ if (validation.warnings.length > 0 && debug) {
178
+ console.log('[BashTool] Warnings:', validation.warnings);
179
+ }
180
+
181
+ if (debug) {
182
+ console.log(`[BashTool] Executing command: "${command}"`);
183
+ console.log(`[BashTool] Working directory: "${workingDir}"`);
184
+ console.log(`[BashTool] Timeout: ${executionOptions.timeout}ms`);
185
+ }
186
+
187
+ // Execute command
188
+ const result = await executeBashCommand(command.trim(), executionOptions);
189
+
190
+ if (debug) {
191
+ console.log(`[BashTool] Command completed - Success: ${result.success}, Duration: ${result.duration}ms`);
192
+ }
193
+
194
+ // Format and return result
195
+ const formattedResult = formatExecutionResult(result, debug);
196
+
197
+ // Add metadata for failed commands
198
+ if (!result.success) {
199
+ let errorInfo = `\n\nCommand failed with exit code ${result.exitCode}`;
200
+ if (result.killed) {
201
+ errorInfo += ` (${result.error})`;
202
+ }
203
+ return formattedResult + errorInfo;
204
+ }
205
+
206
+ return formattedResult;
207
+
208
+ } catch (error) {
209
+ if (debug) {
210
+ console.error('[BashTool] Execution error:', error);
211
+ }
212
+ return `Error executing bash command: ${error.message}`;
213
+ }
214
+ }
215
+ });
216
+ };
@@ -37,6 +37,13 @@ export const delegateSchema = z.object({
37
37
  task: z.string().describe('The task to delegate to a subagent. Be specific about what needs to be accomplished.')
38
38
  });
39
39
 
40
+ export const bashSchema = z.object({
41
+ command: z.string().describe('The bash command to execute'),
42
+ workingDirectory: z.string().optional().describe('Directory to execute the command in (optional)'),
43
+ timeout: z.number().optional().describe('Command timeout in milliseconds (optional)'),
44
+ env: z.record(z.string()).optional().describe('Additional environment variables (optional)')
45
+ });
46
+
40
47
  // Schema for the attempt_completion tool - flexible validation for direct XML response
41
48
  export const attemptCompletionSchema = {
42
49
  // Custom validation that requires result parameter but allows direct XML response
@@ -277,10 +284,67 @@ I have refactored the search module according to the requirements and verified t
277
284
  </attempt_completion>
278
285
  `;
279
286
 
287
+ export const bashToolDefinition = `
288
+ ## bash
289
+ Description: Execute bash commands for system exploration and development tasks. This tool has built-in security with allow/deny lists. By default, only safe read-only commands are allowed for code exploration.
290
+
291
+ Parameters:
292
+ - command: (required) The bash command to execute
293
+ - workingDirectory: (optional) Directory to execute the command in
294
+ - timeout: (optional) Command timeout in milliseconds
295
+ - env: (optional) Additional environment variables as an object
296
+
297
+ Security: Commands are filtered through allow/deny lists for safety:
298
+ - Allowed by default: ls, cat, git status, npm list, find, grep, etc.
299
+ - Denied by default: rm -rf, sudo, npm install, dangerous system commands
300
+
301
+ Usage Examples:
302
+
303
+ <examples>
304
+
305
+ User: What files are in the src directory?
306
+ <bash>
307
+ <command>ls -la src/</command>
308
+ </bash>
309
+
310
+ User: Show me the git status
311
+ <bash>
312
+ <command>git status</command>
313
+ </bash>
314
+
315
+ User: Find all TypeScript files
316
+ <bash>
317
+ <command>find . -name "*.ts" -type f</command>
318
+ </bash>
319
+
320
+ User: Check installed npm packages
321
+ <bash>
322
+ <command>npm list --depth=0</command>
323
+ </bash>
324
+
325
+ User: Search for TODO comments in code
326
+ <bash>
327
+ <command>grep -r "TODO" src/</command>
328
+ </bash>
329
+
330
+ User: Show recent git commits
331
+ <bash>
332
+ <command>git log --oneline -10</command>
333
+ </bash>
334
+
335
+ User: Check system info
336
+ <bash>
337
+ <command>uname -a</command>
338
+ </bash>
339
+
340
+ </examples>
341
+ `;
342
+
280
343
  export const searchDescription = 'Search code in the repository using Elasticsearch-like query syntax. Use this tool first for any code-related questions.';
281
344
  export const queryDescription = 'Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.';
282
345
  export const extractDescription = 'Extract code blocks from files based on file paths and optional line numbers. Use this tool to see complete context after finding relevant files.';
283
346
  export const delegateDescription = 'Automatically delegate big distinct tasks to specialized probe subagents within the agentic loop. Used by AI agents to break down complex requests into focused, parallel tasks.';
347
+ export const bashDescription = 'Execute bash commands for system exploration and development tasks. Secure by default with built-in allow/deny lists.';
284
348
 
285
349
  // Valid tool names that should be parsed as tool calls
286
350
  const DEFAULT_VALID_TOOLS = [
@@ -5,6 +5,7 @@
5
5
 
6
6
  // Export Vercel AI SDK tool generators
7
7
  export { searchTool, queryTool, extractTool, delegateTool } from './vercel.js';
8
+ export { bashTool } from './bash.js';
8
9
 
9
10
  // Export LangChain tools
10
11
  export { createSearchTool, createQueryTool, createExtractTool } from './langchain.js';
@@ -15,8 +16,11 @@ export {
15
16
  querySchema,
16
17
  extractSchema,
17
18
  delegateSchema,
19
+ bashSchema,
18
20
  delegateDescription,
19
21
  delegateToolDefinition,
22
+ bashDescription,
23
+ bashToolDefinition,
20
24
  attemptCompletionSchema,
21
25
  attemptCompletionToolDefinition
22
26
  } from './common.js';
@@ -26,6 +30,7 @@ export { DEFAULT_SYSTEM_MESSAGE } from './system-message.js';
26
30
 
27
31
  // For backward compatibility, create and export pre-configured tools
28
32
  import { searchTool as searchToolGenerator, queryTool as queryToolGenerator, extractTool as extractToolGenerator, delegateTool as delegateToolGenerator } from './vercel.js';
33
+ import { bashTool as bashToolGenerator } from './bash.js';
29
34
  import { DEFAULT_SYSTEM_MESSAGE } from './system-message.js';
30
35
 
31
36
  // Create default tool instances (for backward compatibility)
@@ -34,6 +39,7 @@ const tools = {
34
39
  queryTool: queryToolGenerator(),
35
40
  extractTool: extractToolGenerator(),
36
41
  delegateTool: delegateToolGenerator(),
42
+ bashTool: bashToolGenerator(),
37
43
  DEFAULT_SYSTEM_MESSAGE
38
44
  };
39
45