@probelabs/probe 0.6.0-rc100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +583 -0
  2. package/bin/.gitkeep +0 -0
  3. package/bin/probe +158 -0
  4. package/bin/probe-binary +0 -0
  5. package/build/agent/ProbeAgent.d.ts +199 -0
  6. package/build/agent/ProbeAgent.js +1486 -0
  7. package/build/agent/acp/README.md +347 -0
  8. package/build/agent/acp/connection.js +237 -0
  9. package/build/agent/acp/connection.test.js +311 -0
  10. package/build/agent/acp/examples/simple-client.js +212 -0
  11. package/build/agent/acp/examples/tool-lifecycle.js +230 -0
  12. package/build/agent/acp/final-test.js +173 -0
  13. package/build/agent/acp/index.js +5 -0
  14. package/build/agent/acp/integration.test.js +385 -0
  15. package/build/agent/acp/manual-test.js +410 -0
  16. package/build/agent/acp/protocol-test.js +190 -0
  17. package/build/agent/acp/server.js +448 -0
  18. package/build/agent/acp/server.test.js +371 -0
  19. package/build/agent/acp/test-runner.js +216 -0
  20. package/build/agent/acp/test-utils/README.md +315 -0
  21. package/build/agent/acp/test-utils/acp-tester.js +484 -0
  22. package/build/agent/acp/test-utils/mock-acp-client.js +434 -0
  23. package/build/agent/acp/tools.js +368 -0
  24. package/build/agent/acp/tools.test.js +334 -0
  25. package/build/agent/acp/types.js +218 -0
  26. package/build/agent/acp/types.test.js +327 -0
  27. package/build/agent/appTracer.js +360 -0
  28. package/build/agent/fileSpanExporter.js +169 -0
  29. package/build/agent/index.js +7426 -0
  30. package/build/agent/mcp/client.js +338 -0
  31. package/build/agent/mcp/config.js +313 -0
  32. package/build/agent/mcp/index.js +64 -0
  33. package/build/agent/mcp/xmlBridge.js +371 -0
  34. package/build/agent/mockProvider.js +53 -0
  35. package/build/agent/probeTool.js +257 -0
  36. package/build/agent/schemaUtils.js +1726 -0
  37. package/build/agent/simpleTelemetry.js +267 -0
  38. package/build/agent/telemetry.js +225 -0
  39. package/build/agent/tokenCounter.js +395 -0
  40. package/build/agent/tools.js +163 -0
  41. package/build/cli.js +49 -0
  42. package/build/delegate.js +267 -0
  43. package/build/directory-resolver.js +237 -0
  44. package/build/downloader.js +750 -0
  45. package/build/extract.js +149 -0
  46. package/build/index.js +70 -0
  47. package/build/mcp/index.js +514 -0
  48. package/build/mcp/index.ts +608 -0
  49. package/build/query.js +116 -0
  50. package/build/search.js +247 -0
  51. package/build/tools/common.js +410 -0
  52. package/build/tools/index.js +40 -0
  53. package/build/tools/langchain.js +88 -0
  54. package/build/tools/system-message.js +121 -0
  55. package/build/tools/vercel.js +271 -0
  56. package/build/utils/file-lister.js +193 -0
  57. package/build/utils.js +128 -0
  58. package/cjs/agent/ProbeAgent.cjs +5829 -0
  59. package/cjs/index.cjs +6217 -0
  60. package/cjs/package.json +3 -0
  61. package/index.d.ts +401 -0
  62. package/package.json +114 -0
  63. package/scripts/postinstall.js +172 -0
  64. package/src/agent/ProbeAgent.d.ts +199 -0
  65. package/src/agent/ProbeAgent.js +1486 -0
  66. package/src/agent/acp/README.md +347 -0
  67. package/src/agent/acp/connection.js +237 -0
  68. package/src/agent/acp/connection.test.js +311 -0
  69. package/src/agent/acp/examples/simple-client.js +212 -0
  70. package/src/agent/acp/examples/tool-lifecycle.js +230 -0
  71. package/src/agent/acp/final-test.js +173 -0
  72. package/src/agent/acp/index.js +5 -0
  73. package/src/agent/acp/integration.test.js +385 -0
  74. package/src/agent/acp/manual-test.js +410 -0
  75. package/src/agent/acp/protocol-test.js +190 -0
  76. package/src/agent/acp/server.js +448 -0
  77. package/src/agent/acp/server.test.js +371 -0
  78. package/src/agent/acp/test-runner.js +216 -0
  79. package/src/agent/acp/test-utils/README.md +315 -0
  80. package/src/agent/acp/test-utils/acp-tester.js +484 -0
  81. package/src/agent/acp/test-utils/mock-acp-client.js +434 -0
  82. package/src/agent/acp/tools.js +368 -0
  83. package/src/agent/acp/tools.test.js +334 -0
  84. package/src/agent/acp/types.js +218 -0
  85. package/src/agent/acp/types.test.js +327 -0
  86. package/src/agent/appTracer.js +360 -0
  87. package/src/agent/fileSpanExporter.js +169 -0
  88. package/src/agent/index.js +813 -0
  89. package/src/agent/mcp/client.js +338 -0
  90. package/src/agent/mcp/config.js +313 -0
  91. package/src/agent/mcp/index.js +64 -0
  92. package/src/agent/mcp/xmlBridge.js +371 -0
  93. package/src/agent/mockProvider.js +53 -0
  94. package/src/agent/probeTool.js +257 -0
  95. package/src/agent/schemaUtils.js +1726 -0
  96. package/src/agent/simpleTelemetry.js +267 -0
  97. package/src/agent/telemetry.js +225 -0
  98. package/src/agent/tokenCounter.js +395 -0
  99. package/src/agent/tools.js +163 -0
  100. package/src/cli.js +49 -0
  101. package/src/delegate.js +267 -0
  102. package/src/directory-resolver.js +237 -0
  103. package/src/downloader.js +750 -0
  104. package/src/extract.js +149 -0
  105. package/src/index.js +70 -0
  106. package/src/mcp/index.ts +608 -0
  107. package/src/query.js +116 -0
  108. package/src/search.js +247 -0
  109. package/src/tools/common.js +410 -0
  110. package/src/tools/index.js +40 -0
  111. package/src/tools/langchain.js +88 -0
  112. package/src/tools/system-message.js +121 -0
  113. package/src/tools/vercel.js +271 -0
  114. package/src/utils/file-lister.js +193 -0
  115. package/src/utils.js +128 -0
@@ -0,0 +1,410 @@
1
+ /**
2
+ * Common schemas and definitions for AI tools
3
+ * @module tools/common
4
+ */
5
+
6
+ import { z } from 'zod';
7
+
8
+ // Common schemas for tool parameters (used for internal execution after XML parsing)
9
+ export const searchSchema = z.object({
10
+ query: z.string().describe('Search query with Elasticsearch syntax. Use + for important terms.'),
11
+ path: z.string().optional().default('.').describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
12
+ allow_tests: z.boolean().optional().default(false).describe('Allow test files in search results'),
13
+ exact: z.boolean().optional().default(false).describe('Perform exact search without tokenization (case-insensitive)'),
14
+ maxResults: z.number().optional().describe('Maximum number of results to return'),
15
+ maxTokens: z.number().optional().default(10000).describe('Maximum number of tokens to return'),
16
+ language: z.string().optional().describe('Limit search to files of a specific programming language')
17
+ });
18
+
19
+ export const querySchema = z.object({
20
+ pattern: z.string().describe('AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc.'),
21
+ path: z.string().optional().default('.').describe('Path to search in'),
22
+ language: z.string().optional().default('rust').describe('Programming language to use for parsing'),
23
+ allow_tests: z.boolean().optional().default(false).describe('Allow test files in search results')
24
+ });
25
+
26
+ export const extractSchema = z.object({
27
+ targets: z.string().optional().describe('File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets'),
28
+ input_content: z.string().optional().describe('Text content to extract file paths from'),
29
+ line: z.number().optional().describe('Start line number to extract a specific code block'),
30
+ end_line: z.number().optional().describe('End line number for extracting a range of lines'),
31
+ allow_tests: z.boolean().optional().default(false).describe('Allow test files and test code blocks'),
32
+ context_lines: z.number().optional().default(10).describe('Number of context lines to include'),
33
+ format: z.string().optional().default('plain').describe('Output format (plain, markdown, json, color)')
34
+ });
35
+
36
+ export const delegateSchema = z.object({
37
+ task: z.string().describe('The task to delegate to a subagent. Be specific about what needs to be accomplished.')
38
+ });
39
+
40
+ // Schema for the attempt_completion tool - flexible validation for direct XML response
41
+ export const attemptCompletionSchema = {
42
+ // Custom validation that requires result parameter but allows direct XML response
43
+ safeParse: (params) => {
44
+ // Validate that params is an object
45
+ if (!params || typeof params !== 'object') {
46
+ return {
47
+ success: false,
48
+ error: {
49
+ issues: [{
50
+ code: 'invalid_type',
51
+ expected: 'object',
52
+ received: typeof params,
53
+ path: [],
54
+ message: 'Expected object'
55
+ }]
56
+ }
57
+ };
58
+ }
59
+
60
+ // Validate that result parameter exists and is a string
61
+ if (!('result' in params)) {
62
+ return {
63
+ success: false,
64
+ error: {
65
+ issues: [{
66
+ code: 'invalid_type',
67
+ expected: 'string',
68
+ received: 'undefined',
69
+ path: ['result'],
70
+ message: 'Required'
71
+ }]
72
+ }
73
+ };
74
+ }
75
+
76
+ if (typeof params.result !== 'string') {
77
+ return {
78
+ success: false,
79
+ error: {
80
+ issues: [{
81
+ code: 'invalid_type',
82
+ expected: 'string',
83
+ received: typeof params.result,
84
+ path: ['result'],
85
+ message: 'Expected string'
86
+ }]
87
+ }
88
+ };
89
+ }
90
+
91
+ // Filter out command parameter if present (legacy compatibility)
92
+ const filteredData = { result: params.result };
93
+
94
+ return {
95
+ success: true,
96
+ data: filteredData
97
+ };
98
+ }
99
+ };
100
+
101
+
102
+ // Tool descriptions for the system prompt (using XML format)
103
+
104
+ export const searchToolDefinition = `
105
+ ## search
106
+ Description: Search code in the repository using Elasticsearch query syntax (except field based queries, e.g. "filename:..." NOT supported).
107
+
108
+ You need to focus on main keywords when constructing the query, and always use elastic search syntax like OR AND and brackets to group keywords.
109
+
110
+ **Session Management & Caching:**
111
+ - Ensure not to re-read the same symbols twice - reuse context from previous tool calls
112
+ - Probe returns a session ID on first run - reuse it for subsequent calls to avoid redundant searches
113
+ - Once data is returned, it's cached and won't return on next runs (this is expected behavior)
114
+
115
+ Parameters:
116
+ - query: (required) Search query with Elasticsearch syntax. You can use + for important terms, and - for negation.
117
+ - path: (required) Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc. YOU SHOULD ALWAYS provide FULL PATH when searching dependencies, including depency name.
118
+ - allow_tests: (optional, default: false) Allow test files in search results (true/false).
119
+ - exact: (optional, default: false) Perform exact pricise search. Use it when you already know function or struct name, or some other code block, and want exact match.
120
+ - maxResults: (optional) Maximum number of results to return (number).
121
+ - maxTokens: (optional, default: 10000) Maximum number of tokens to return (number).
122
+ - language: (optional) Limit search to files of a specific programming language (e.g., 'rust', 'js', 'python', 'go' etc.).
123
+
124
+ **Workflow:** Always start with search, then use extract for detailed context when needed.
125
+
126
+ Usage Example:
127
+
128
+ <examples>
129
+
130
+ User: Where is the login logic?
131
+ Assistant workflow:
132
+ 1. <search>
133
+ <query>login AND auth AND token</query>
134
+ <path>.</path>
135
+ </search>
136
+ 2. Now lets look closer: <extract>
137
+ <targets>session.rs#AuthService.login auth.rs:2-100</targets>
138
+ </extract>
139
+
140
+ User: How to calculate the total amount in the payments module?
141
+ <search>
142
+ <query>calculate AND payment</query>
143
+ <path>src/utils</path>
144
+ <allow_tests>false</allow_tests>
145
+ </search>
146
+
147
+ User: How do the user authentication and authorization work?
148
+ <search>
149
+ <query>+user and (authentification OR authroization OR authz)</query>
150
+ <path>.</path>
151
+ <allow_tests>true</allow_tests>
152
+ <language>go</language>
153
+ </search>
154
+
155
+ User: Find all react imports in the project.
156
+ <search>
157
+ <query>import { react }</query>
158
+ <path>.</path>
159
+ <exact>true</exact>
160
+ <language>js</language>
161
+ </search>
162
+
163
+ User: Find how decompoud library works?
164
+ <search>
165
+ <query>import { react }</query>
166
+ <path>/dep/rust/decompound</path>
167
+ <language>rust</language>
168
+ </search>
169
+
170
+ </examples>
171
+ `;
172
+
173
+ export const queryToolDefinition = `
174
+ ## query
175
+ Description: Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.
176
+ Parameters:
177
+ - pattern: (required) AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc.
178
+ - path: (optional, default: '.') Path to search in.
179
+ - language: (optional, default: 'rust') Programming language to use for parsing.
180
+ - allow_tests: (optional, default: false) Allow test files in search results (true/false).
181
+ Usage Example:
182
+
183
+ <examples>
184
+
185
+ <query>
186
+ <pattern>function $FUNC($$$PARAMS) { $$$BODY }</pattern>
187
+ <path>src/parser</path>
188
+ <language>js</language>
189
+ </query>
190
+
191
+ </examples>
192
+ `;
193
+
194
+ export const extractToolDefinition = `
195
+ ## extract
196
+ Description: Extract code blocks from files based on file paths and optional line numbers. Use this tool to see complete context after finding relevant files. It can be used to read full files as well.
197
+ Full file extraction should be the LAST RESORT! Always prefer search.
198
+
199
+ **Multiple Extraction:** You can extract multiple symbols/files in one call by providing multiple file paths separated by spaces.
200
+
201
+ **Session Awareness:** Reuse context from previous tool calls. Don't re-extract the same symbols you already have.
202
+
203
+ Parameters:
204
+ - targets: (required) File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets (e.g., 'src/main.rs:10-20', 'src/utils.js#myFunction').
205
+ For multiple extractions: 'session.rs#AuthService.login auth.rs:2-100 config.rs#DatabaseConfig'
206
+ - line: (optional) Start line number to extract a specific code block. Use with end_line for ranges.
207
+ - end_line: (optional) End line number for extracting a range of lines.
208
+ - allow_tests: (optional, default: false) Allow test files and test code blocks (true/false).
209
+ Usage Example:
210
+
211
+ <examples>
212
+
213
+ User: Where is the login logic? (After search found relevant files)
214
+ <extract>
215
+ <targets>session.rs#AuthService.login auth.rs:2-100 config.rs#DatabaseConfig</targets>
216
+ </extract>
217
+
218
+ User: How does error handling work? (After search identified files)
219
+ <extract>
220
+ <targets>error.rs#ErrorType utils.rs#handle_error src/main.rs:50-80</targets>
221
+ </extract>
222
+
223
+ User: How RankManager works
224
+ <extract>
225
+ <targets>src/search/ranking.rs#RankManager</targets>
226
+ </extract>
227
+
228
+ User: Lets read the whole file
229
+ <extract>
230
+ <targets>src/search/ranking.rs</targets>
231
+ </extract>
232
+
233
+ User: Read the first 10 lines of the file
234
+ <extract>
235
+ <targets>src/search/ranking.rs</targets>
236
+ <line>1</line>
237
+ <end_line>10</end_line>
238
+ </extract>
239
+
240
+ User: Read file inside the dependency
241
+ <extract>
242
+ <targets>/dep/go/github.com/gorilla/mux/router.go</targets>
243
+ </extract>
244
+
245
+ </examples>
246
+ `;
247
+
248
+ export const delegateToolDefinition = `
249
+ ## delegate
250
+ Description: Automatically delegate big distinct tasks to specialized probe subagents within the agentic loop. Use this when you recognize that a user's request involves multiple large, distinct components that would benefit from parallel processing or specialized focus. The AI agent should automatically identify opportunities for task separation and use delegation without explicit user instruction.
251
+
252
+ Parameters:
253
+ - task: (required) A complete, self-contained task that can be executed independently by a subagent. Should be specific and focused on one area of expertise.
254
+
255
+ Usage Pattern:
256
+ When the AI agent encounters complex multi-part requests, it should automatically break them down and delegate:
257
+
258
+ <delegate>
259
+ <task>Analyze all authentication and authorization code in the codebase for security vulnerabilities and provide specific remediation recommendations</task>
260
+ </delegate>
261
+
262
+ <delegate>
263
+ <task>Review database queries and API endpoints for performance bottlenecks and suggest optimization strategies</task>
264
+ </delegate>
265
+
266
+ The agent uses this tool automatically when it identifies that work can be separated into distinct, parallel tasks for more efficient processing.
267
+ `;
268
+
269
+ export const attemptCompletionToolDefinition = `
270
+ ## attempt_completion
271
+ Description: Use this tool ONLY when the task is fully complete and you have received confirmation of success for all previous tool uses. Presents the final result to the user. You can provide your response directly inside the XML tags without any parameter wrapper.
272
+ Parameters:
273
+ - No validation required - provide your complete answer directly inside the XML tags.
274
+ Usage Example:
275
+ <attempt_completion>
276
+ I have refactored the search module according to the requirements and verified the tests pass. The module now uses the new BM25 ranking algorithm and has improved error handling.
277
+ </attempt_completion>
278
+ `;
279
+
280
+ export const searchDescription = 'Search code in the repository using Elasticsearch-like query syntax. Use this tool first for any code-related questions.';
281
+ 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
+ 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
+ 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.';
284
+
285
+ // Valid tool names that should be parsed as tool calls
286
+ const DEFAULT_VALID_TOOLS = [
287
+ 'search',
288
+ 'query',
289
+ 'extract',
290
+ 'delegate',
291
+ 'listFiles',
292
+ 'searchFiles',
293
+ 'implement',
294
+ 'attempt_completion'
295
+ ];
296
+
297
+ // Simple XML parser helper - safer string-based approach
298
+ export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
299
+ // Look for each valid tool name specifically using string search
300
+ for (const toolName of validTools) {
301
+ const openTag = `<${toolName}>`;
302
+ const closeTag = `</${toolName}>`;
303
+
304
+ const openIndex = xmlString.indexOf(openTag);
305
+ if (openIndex === -1) {
306
+ continue; // Tool not found, try next tool
307
+ }
308
+
309
+ const closeIndex = xmlString.indexOf(closeTag, openIndex + openTag.length);
310
+ if (closeIndex === -1) {
311
+ continue; // No closing tag found, try next tool
312
+ }
313
+
314
+ // Extract the content between tags
315
+ const innerContent = xmlString.substring(
316
+ openIndex + openTag.length,
317
+ closeIndex
318
+ );
319
+
320
+ const params = {};
321
+
322
+ // Parse parameters using string-based approach for better safety
323
+ // Common parameter names to look for (can be extended as needed)
324
+ // Note: includes both camelCase and underscore_case variants to handle inconsistencies
325
+ const commonParams = ['query', 'file_path', 'line', 'end_line', 'path', 'recursive', 'includeHidden',
326
+ 'max_results', 'maxResults', 'result', 'command', 'description', 'task', 'param', 'pattern',
327
+ 'allow_tests', 'exact', 'maxTokens', 'language', 'input_content',
328
+ 'context_lines', 'format', 'directory', 'autoCommits', 'files', 'targets'];
329
+
330
+ for (const paramName of commonParams) {
331
+ const paramOpenTag = `<${paramName}>`;
332
+ const paramCloseTag = `</${paramName}>`;
333
+
334
+ const paramOpenIndex = innerContent.indexOf(paramOpenTag);
335
+ if (paramOpenIndex === -1) {
336
+ continue; // Parameter not found
337
+ }
338
+
339
+ const paramCloseIndex = innerContent.indexOf(paramCloseTag, paramOpenIndex + paramOpenTag.length);
340
+ if (paramCloseIndex === -1) {
341
+ continue; // No closing tag found
342
+ }
343
+
344
+ let paramValue = innerContent.substring(
345
+ paramOpenIndex + paramOpenTag.length,
346
+ paramCloseIndex
347
+ ).trim();
348
+
349
+ // Basic type inference (can be improved)
350
+ if (paramValue.toLowerCase() === 'true') {
351
+ paramValue = true;
352
+ } else if (paramValue.toLowerCase() === 'false') {
353
+ paramValue = false;
354
+ } else if (!isNaN(paramValue) && paramValue.trim() !== '') {
355
+ // Check if it's potentially a number (handle integers and floats)
356
+ const num = Number(paramValue);
357
+ if (Number.isFinite(num)) { // Use Number.isFinite to avoid Infinity/NaN
358
+ paramValue = num;
359
+ }
360
+ // Keep as string if not a valid finite number
361
+ }
362
+
363
+ params[paramName] = paramValue;
364
+ }
365
+
366
+ // Special handling for attempt_completion - use entire inner content as result
367
+ if (toolName === 'attempt_completion') {
368
+ params['result'] = innerContent.trim();
369
+ // Remove command parameter if it was parsed by generic logic above (legacy compatibility)
370
+ if (params.command) {
371
+ delete params.command;
372
+ }
373
+ }
374
+
375
+ // Return the first valid tool found
376
+ return { toolName, params };
377
+ }
378
+
379
+ // No valid tool found
380
+ return null;
381
+ }
382
+
383
+ /**
384
+ * Creates an improved preview of a message showing start and end portions
385
+ * @param {string} message - The message to preview
386
+ * @param {number} charsPerSide - Number of characters to show from start and end (default: 200)
387
+ * @returns {string} Formatted preview string
388
+ */
389
+ export function createMessagePreview(message, charsPerSide = 200) {
390
+ if (message === null || message === undefined) {
391
+ return 'null/undefined';
392
+ }
393
+
394
+ if (typeof message !== 'string') {
395
+ return 'null/undefined';
396
+ }
397
+
398
+ const totalChars = charsPerSide * 2;
399
+
400
+ if (message.length <= totalChars) {
401
+ // Message is short enough to show completely
402
+ return message;
403
+ }
404
+
405
+ // Message is longer - show start and end with ... in between
406
+ const start = message.substring(0, charsPerSide);
407
+ const end = message.substring(message.length - charsPerSide);
408
+
409
+ return `${start}...${end}`;
410
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Main tools module
3
+ * @module tools
4
+ */
5
+
6
+ // Export Vercel AI SDK tool generators
7
+ export { searchTool, queryTool, extractTool, delegateTool } from './vercel.js';
8
+
9
+ // Export LangChain tools
10
+ export { createSearchTool, createQueryTool, createExtractTool } from './langchain.js';
11
+
12
+ // Export common schemas
13
+ export {
14
+ searchSchema,
15
+ querySchema,
16
+ extractSchema,
17
+ delegateSchema,
18
+ delegateDescription,
19
+ delegateToolDefinition,
20
+ attemptCompletionSchema,
21
+ attemptCompletionToolDefinition
22
+ } from './common.js';
23
+
24
+ // Export system message
25
+ export { DEFAULT_SYSTEM_MESSAGE } from './system-message.js';
26
+
27
+ // For backward compatibility, create and export pre-configured tools
28
+ import { searchTool as searchToolGenerator, queryTool as queryToolGenerator, extractTool as extractToolGenerator, delegateTool as delegateToolGenerator } from './vercel.js';
29
+ import { DEFAULT_SYSTEM_MESSAGE } from './system-message.js';
30
+
31
+ // Create default tool instances (for backward compatibility)
32
+ const tools = {
33
+ searchTool: searchToolGenerator(),
34
+ queryTool: queryToolGenerator(),
35
+ extractTool: extractToolGenerator(),
36
+ delegateTool: delegateToolGenerator(),
37
+ DEFAULT_SYSTEM_MESSAGE
38
+ };
39
+
40
+ export { tools };
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Tools for LangChain
3
+ * @module tools/langchain
4
+ */
5
+
6
+ import { search } from '../search.js';
7
+ import { query } from '../query.js';
8
+ import { extract } from '../extract.js';
9
+ import { searchSchema, querySchema, extractSchema, searchDescription, queryDescription, extractDescription } from './common.js';
10
+
11
+ // LangChain tool for searching code
12
+ export function createSearchTool() {
13
+ return {
14
+ name: 'search',
15
+ description: searchDescription,
16
+ schema: searchSchema,
17
+ func: async ({ query: searchQuery, path, allow_tests, exact, maxResults, maxTokens = 10000, language }) => {
18
+ try {
19
+ const results = await search({
20
+ query: searchQuery,
21
+ path,
22
+ allow_tests,
23
+ exact,
24
+ json: false,
25
+ maxResults,
26
+ maxTokens,
27
+ language
28
+ });
29
+
30
+ return results;
31
+ } catch (error) {
32
+ console.error('Error executing search command:', error);
33
+ return `Error executing search command: ${error.message}`;
34
+ }
35
+ }
36
+ };
37
+ }
38
+
39
+ // LangChain tool for querying code
40
+ export function createQueryTool() {
41
+ return {
42
+ name: 'query',
43
+ description: queryDescription,
44
+ schema: querySchema,
45
+ func: async ({ pattern, path, language, allow_tests }) => {
46
+ try {
47
+ const results = await query({
48
+ pattern,
49
+ path,
50
+ language,
51
+ allow_tests,
52
+ json: false
53
+ });
54
+
55
+ return results;
56
+ } catch (error) {
57
+ console.error('Error executing query command:', error);
58
+ return `Error executing query command: ${error.message}`;
59
+ }
60
+ }
61
+ };
62
+ }
63
+
64
+ // LangChain tool for extracting code
65
+ export function createExtractTool() {
66
+ return {
67
+ name: 'extract',
68
+ description: extractDescription,
69
+ schema: extractSchema,
70
+ func: async ({ targets, line, end_line, allow_tests, context_lines, format }) => {
71
+ try {
72
+ const files = [targets];
73
+
74
+ const results = await extract({
75
+ files,
76
+ allowTests: allow_tests,
77
+ contextLines: context_lines,
78
+ format
79
+ });
80
+
81
+ return results;
82
+ } catch (error) {
83
+ console.error('Error executing extract command:', error);
84
+ return `Error executing extract command: ${error.message}`;
85
+ }
86
+ }
87
+ };
88
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Default system message for code intelligence assistants
3
+ * @module tools/system-message
4
+ */
5
+ export const DEFAULT_SYSTEM_MESSAGE = `[Persona & Objective]
6
+
7
+ You are Probe, a specialized code intelligence assistant. Your objective is to accurately answer questions about multi-language codebases by effectively using your available tools: \`search\`, \`query\`, and \`extract\`.
8
+
9
+ [Core Workflow & Principles]
10
+
11
+ 1. **Tool-First Always:** Immediately use tools for any code-related query. Do not guess or use general knowledge.
12
+ 2. **Mandatory Path:** ALL tool calls (\`search\`, \`query\`, \`extract\`) MUST include the \`path\` argument. Use \`"."\` for the whole project, specific directories/files (e.g., \`"src/api"\`, \`"pkg/utils/helpers.py"\`), or dependency syntax (e.g., \`"go:github.com/gin-gonic/gin"\`, \`"js:@ai-sdk/anthropic"\`, \`"rust:serde"\`).
13
+ 3. **Start with \`search\`:**
14
+ * **Keywords are Key:** Formulate queries like you would in Elasticsearch. Use specific keywords, boolean operators (\`AND\`, \`OR\`, \`NOT\`), and exact phrases (\`""\`). This is NOT a simple text search.
15
+ * **Iterate if Needed:** If initial results are too broad or insufficient, **repeat the exact same \`search\` query** to get the next page of results (pagination). Reuse the \`sessionID\` if provided by the previous identical search. If results are irrelevant, refine the keywords (add terms, use \`NOT\`, try synonyms).
16
+ 4. **Analyze & Refine:** Review \`search\` results (snippets, file paths).
17
+ * Use \`query\` if you need code based on *structure* (AST patterns) within specific files/directories identified by \`search\`.
18
+ * Use \`extract\` if \`search\` or \`query\` identified the exact location (file, symbol, line range) and you need the full definition or more context.
19
+ 5. **Synthesize & Cite:** Construct the answer *only* from tool outputs. ALWAYS cite the specific file paths and relevant locations (symbols, line numbers) found. Adapt detail to the likely user role (developer vs. PM).
20
+ 6. **Clarify Sparingly:** If an initial \`search\` attempt completely fails due to ambiguity, ask a *specific* question to guide the next search. Don't ask before trying a search first.
21
+
22
+ [Tool Reference]
23
+
24
+ * \`search\`
25
+ * **Purpose:** Find relevant code snippets/files using keyword-based search (like Elasticsearch). Locate named symbols. Search project code or dependencies.
26
+ * **Syntax:** \`query\` (Elasticsearch-like string: keywords, \`AND\`, \`OR\`, \`NOT\`, \`""\` exact phrases), \`path\` (Mandatory: \`"."\`, \`"path/to/dir"\`, \`"path/to/file.ext"\`, \`"go:pkg"\`, \`"js:npm_module"\`, \`"rust:crate"\`), \`exact\` (Optional: Set to \`true\` for case-insensitive exact matching without tokenization).
27
+ * **Features:** Returns snippets/paths. Supports pagination (repeat query). Caching via \`sessionID\` (reuse if returned). Use \`exact\` flag when you need precise matching of terms.
28
+ * \`query\`
29
+ * **Purpose:** Find code by its *structure* (AST patterns) within specific files/directories, typically after \`search\`.
30
+ * **Syntax:** \`pattern\` (ast-grep pattern), \`language\` (e.g., "go", "python").
31
+ * **Mandatory Argument:** \`path\` (file or directory path, e.g., \`"src/services"\`, \`"app/main.py"\`).
32
+ * \`extract\`
33
+ * **Purpose:** Retrieve specific code blocks or entire files *after* \`search\` or \`query\` identifies the target.
34
+ * **Syntax:** Optional \`#symbol\` (e.g., \`#MyClass\`), \`#Lstart-Lend\` (e.g., \`#L50-L75\`).
35
+ * **Mandatory Argument:** \`path\` (specific file path, e.g., \`"src/utils/helpers.go"\`, or dependency file like \`"go:github.com/gin-gonic/gin/context.go"\`).
36
+
37
+ [Examples]
38
+
39
+ * **Example 1: Finding a Specific Function Definition**
40
+ * User: "Show me the code for the \`calculate_total\` function in our payments module."
41
+ * Probe Action 1: \`search\` query: \`"calculate_total"\`, path: \`"src/payments"\` (Targeted search in the likely directory)
42
+ * (Analysis: Search returns a clear hit in \`src/payments/logic.py\`.)
43
+ * Probe Action 2: \`extract\` path: \`"src/payments/logic.py#calculate_total"\`
44
+ * (Response: Provide the extracted function code, citing \`src/payments/logic.py#calculate_total\`.)
45
+
46
+ * **Example 2: Investigating Initialization**
47
+ * User: "Where is the primary configuration for the Redis cache loaded?"
48
+ * Probe Action 1: \`search\` query: \`redis AND (config OR load OR init OR setup) NOT test\`, path: \`"."\`
49
+ * (Analysis: Results point towards \`pkg/cache/redis.go\` and a function \`LoadRedisConfig\`.)
50
+ * Probe Action 2: \`extract\` path: \`"pkg/cache/redis.go#LoadRedisConfig"\`
51
+ * (Response: Explain config loading based on the extracted \`LoadRedisConfig\` function, citing \`pkg/cache/redis.go#LoadRedisConfig\`.)
52
+
53
+ * **Example 3: Understanding Usage of a Dependency Feature**
54
+ * User: "How are we using the \`createAnthropic\` function from the \`@ai-sdk/anthropic\` library?"
55
+ * Probe Action 1: \`search\` query: \`"createAnthropic"\`, path: \`"."\` (Search project code for usage)
56
+ * (Analysis: Find usage in \`src/ai/providers.ts\`. Want to understand the library function itself better.)
57
+ * Probe Action 2: \`search\` query: \`"createAnthropic"\`, path: \`"js:@ai-sdk/anthropic"\` (Search within the specific dependency)
58
+ * (Analysis: Search locates the definition within the dependency code, e.g., \`node_modules/@ai-sdk/anthropic/dist/index.js\` or similar mapped path.)
59
+ * Probe Action 3: \`extract\` path: \`"js:@ai-sdk/anthropic/dist/index.js#createAnthropic"\` (Extract the specific function *from the dependency*. Note: Actual file path within dependency might vary, use the one found by search).
60
+ * (Response: Show how \`createAnthropic\` is used in \`src/ai/providers.ts\`, and explain its purpose based on the extracted definition from the \`@ai-sdk/anthropic\` library, citing both files.)
61
+
62
+ * **Example 4: Exploring Error Handling Patterns**
63
+ * User: "What's the standard way errors are wrapped or handled in our Go backend services?"
64
+ * Probe Action 1: \`search\` query: \`error AND (wrap OR handle OR new) AND lang:go NOT test\`, path: \`"service/"\` (Focus on service directories)
65
+ * (Analysis: Many results. See frequent use of \`fmt.Errorf\` and a custom \`errors.Wrap\` in several files like \`service/user/handler.go\`.)
66
+ * Probe Action 2: \`search\` query: \`import AND "pkg/errors"\`, path: \`"service/"\` (Check where a potential custom error package is used)
67
+ * (Analysis: Confirms \`pkg/errors\` is widely used.)
68
+ * Probe Action 3: \`query\` language: \`go\`, pattern: \`errors.Wrap($$$)\`, path: \`"service/"\` (Find structural usage of the custom wrapper)
69
+ * (Response: Summarize error handling: Mention standard \`fmt.Errorf\` and the prevalent use of a custom \`errors.Wrap\` function from \`pkg/errors\`, providing examples from locations found by search/query like \`service/user/handler.go\`.)
70
+
71
+ <mermaid-instructions>
72
+ For GitHub-compatible mermaid diagrams, avoid single quotes and parentheses in node labels:
73
+
74
+ **Rules:**
75
+ - NO single quotes in any node labels: 'text' → "text" or text
76
+ - NO parentheses in square brackets: [Text (detail)] → [Text - detail]
77
+ - NO complex expressions in diamonds: {a && b} → {condition}
78
+ - USE single quotes for styles and classes: classDef highlight fill:'#ff9999'
79
+
80
+ **Examples:**
81
+ - ✅ [Load Config] ["Run command"] {Valid?}
82
+ - ❌ [Load (config)] [Run 'command'] {isValid('x')}
83
+
84
+ **Diagram Type Selection:**
85
+
86
+ *Process & Flow:*
87
+ - **flowchart**: processes, workflows, decision trees (flowchart TD/LR)
88
+ - **graph**: simple relationships, network structures
89
+ - **gitgraph**: git branching, version control flows
90
+
91
+ *Interactions & Time:*
92
+ - **sequenceDiagram**: API calls, system interactions over time
93
+ - **timeline**: chronological events, project phases
94
+ - **userJourney**: user experience flows, customer journeys
95
+
96
+ *Structure & Design:*
97
+ - **classDiagram**: OOP design, class relationships
98
+ - **erDiagram**: database schemas, entity relationships
99
+ - **c4**: system architecture, component views
100
+ - **architecture**: system topology, infrastructure
101
+ - **block**: system components, data flow
102
+
103
+ *Data & Analytics:*
104
+ - **pie**: percentage breakdowns, categorical data
105
+ - **xyChart**: trend analysis, scatter plots
106
+ - **quadrant**: 2x2 matrices, decision frameworks
107
+ - **sankey**: flow analysis, resource allocation
108
+ - **radar**: multi-dimensional comparisons
109
+ - **treemap**: hierarchical data, size relationships
110
+
111
+ *Project Management:*
112
+ - **gantt**: project timelines, task scheduling
113
+ - **kanban**: workflow states, task boards
114
+
115
+ *Specialized:*
116
+ - **stateDiagram**: state machines, system states
117
+ - **mindmap**: brainstorming, concept mapping
118
+ - **requirement**: system requirements, traceability
119
+ - **packet**: network protocols, data packets
120
+ - **zenuml**: UML sequence diagrams
121
+ </mermaid-instructions>`