@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,347 @@
1
+ # Agent Client Protocol (ACP) Implementation
2
+
3
+ This directory contains the implementation of the Agent Client Protocol (ACP) for the Probe AI agent. ACP is a standardized protocol for communication between code editors and AI coding agents, developed by Zed Industries.
4
+
5
+ ## Overview
6
+
7
+ The ACP implementation enables Probe to work as an AI coding agent compatible with ACP-enabled editors like Zed and Neovim. It provides a JSON-RPC 2.0 based communication protocol with rich features including:
8
+
9
+ - Session management for conversation contexts
10
+ - Tool execution with lifecycle tracking
11
+ - Streaming responses and notifications
12
+ - Permission system for code modifications
13
+ - Rich content types (text, images, resources)
14
+
15
+ ## Architecture
16
+
17
+ ### Core Components
18
+
19
+ - **`types.js`** - Protocol constants, types, and utility functions
20
+ - **`connection.js`** - JSON-RPC 2.0 communication over stdio
21
+ - **`server.js`** - Main ACP server implementation with session management
22
+ - **`tools.js`** - Tool integration and execution lifecycle management
23
+ - **`index.js`** - Module exports
24
+
25
+ ### Protocol Flow
26
+
27
+ 1. **Initialization**: Client negotiates protocol version and capabilities
28
+ 2. **Session Management**: Create/load conversation contexts
29
+ 3. **Tool Execution**: Execute code search/analysis tools with progress tracking
30
+ 4. **AI Interaction**: Process user prompts using ProbeAgent
31
+ 5. **Cleanup**: Handle disconnection and resource cleanup
32
+
33
+ ## Usage
34
+
35
+ ### Starting ACP Server
36
+
37
+ ```bash
38
+ # Start as ACP server
39
+ probe agent --acp
40
+
41
+ # With custom configuration
42
+ probe agent --acp --provider anthropic --path ./src --allow-edit
43
+ ```
44
+
45
+ ### Environment Variables
46
+
47
+ ```bash
48
+ ANTHROPIC_API_KEY=your_key_here
49
+ OPENAI_API_KEY=your_key_here
50
+ GOOGLE_API_KEY=your_key_here
51
+ DEBUG=1 # Enable debug logging
52
+ ```
53
+
54
+ ## Protocol Messages
55
+
56
+ ### Initialize Request
57
+
58
+ ```json
59
+ {
60
+ "jsonrpc": "2.0",
61
+ "method": "initialize",
62
+ "params": {
63
+ "protocolVersion": "1"
64
+ },
65
+ "id": 1
66
+ }
67
+ ```
68
+
69
+ ### Initialize Response
70
+
71
+ ```json
72
+ {
73
+ "jsonrpc": "2.0",
74
+ "id": 1,
75
+ "result": {
76
+ "protocolVersion": "1",
77
+ "serverInfo": {
78
+ "name": "probe-agent-acp",
79
+ "version": "1.0.0",
80
+ "description": "Probe AI agent with code search capabilities"
81
+ },
82
+ "capabilities": {
83
+ "tools": [
84
+ {
85
+ "name": "search",
86
+ "description": "Search for code patterns and content",
87
+ "kind": "search"
88
+ }
89
+ ],
90
+ "sessionManagement": true,
91
+ "streaming": true,
92
+ "permissions": false
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### New Session Request
99
+
100
+ ```json
101
+ {
102
+ "jsonrpc": "2.0",
103
+ "method": "newSession",
104
+ "params": {
105
+ "sessionId": "optional-custom-id",
106
+ "mode": "normal"
107
+ },
108
+ "id": 2
109
+ }
110
+ ```
111
+
112
+ ### Prompt Request
113
+
114
+ ```json
115
+ {
116
+ "jsonrpc": "2.0",
117
+ "method": "prompt",
118
+ "params": {
119
+ "sessionId": "session-123",
120
+ "message": "How does authentication work in this codebase?"
121
+ },
122
+ "id": 3
123
+ }
124
+ ```
125
+
126
+ ### Prompt Response
127
+
128
+ ```json
129
+ {
130
+ "jsonrpc": "2.0",
131
+ "id": 3,
132
+ "result": {
133
+ "content": [
134
+ {
135
+ "type": "text",
136
+ "text": "Authentication in this codebase uses JWT tokens..."
137
+ }
138
+ ],
139
+ "sessionId": "session-123",
140
+ "timestamp": "2025-01-15T10:30:00Z"
141
+ }
142
+ }
143
+ ```
144
+
145
+ ## Tool Integration
146
+
147
+ ### Available Tools
148
+
149
+ 1. **Search Tool** (`search`)
150
+ - Flexible text search with stemming
151
+ - Supports regex patterns and elastic search syntax
152
+ - Parameters: `query`, `path`, `max_results`, `allow_tests`
153
+
154
+ 2. **Query Tool** (`query`)
155
+ - AST-based structural pattern matching
156
+ - Language-aware code structure search
157
+ - Parameters: `pattern`, `path`, `language`, `max_results`
158
+
159
+ 3. **Extract Tool** (`extract`)
160
+ - Extract specific code blocks from files
161
+ - Line-based extraction with context
162
+ - Parameters: `files`, `context_lines`, `allow_tests`, `format`
163
+
164
+ ### Tool Call Lifecycle
165
+
166
+ Tools execute with full lifecycle tracking:
167
+
168
+ 1. **Pending** - Tool call queued for execution
169
+ 2. **In Progress** - Tool is actively executing
170
+ 3. **Completed** - Tool finished successfully with results
171
+ 4. **Failed** - Tool execution failed with error
172
+
173
+ Progress is communicated via notifications:
174
+
175
+ ```json
176
+ {
177
+ "jsonrpc": "2.0",
178
+ "method": "toolCallProgress",
179
+ "params": {
180
+ "sessionId": "session-123",
181
+ "toolCallId": "tool-456",
182
+ "status": "completed",
183
+ "result": "search results here..."
184
+ }
185
+ }
186
+ ```
187
+
188
+ ## Session Management
189
+
190
+ ### Session Types
191
+
192
+ - **Normal Mode**: Standard AI interaction
193
+ - **Planning Mode**: Strategic planning and design discussions
194
+
195
+ ### Session Features
196
+
197
+ - Persistent conversation history
198
+ - Tool call tracking and status
199
+ - Session metadata (creation time, last update)
200
+ - Resource cleanup on disconnect
201
+
202
+ ### Session Operations
203
+
204
+ ```javascript
205
+ // Create new session
206
+ await server.handleNewSession({
207
+ sessionId: 'custom-id', // optional
208
+ mode: 'normal' // optional
209
+ });
210
+
211
+ // Load existing session
212
+ await server.handleLoadSession({
213
+ sessionId: 'existing-id'
214
+ });
215
+
216
+ // Set session mode
217
+ await server.handleSetSessionMode({
218
+ sessionId: 'session-id',
219
+ mode: 'planning'
220
+ });
221
+ ```
222
+
223
+ ## Error Handling
224
+
225
+ The implementation follows JSON-RPC 2.0 error handling:
226
+
227
+ ### Standard Error Codes
228
+
229
+ - `-32700` Parse Error - Invalid JSON
230
+ - `-32600` Invalid Request - Invalid JSON-RPC format
231
+ - `-32601` Method Not Found - Unknown method
232
+ - `-32602` Invalid Params - Invalid parameters
233
+ - `-32603` Internal Error - Server error
234
+
235
+ ### Custom Error Codes
236
+
237
+ - `-32001` Unsupported Protocol Version
238
+ - `-32002` Session Not Found
239
+ - `-32003` Permission Denied
240
+ - `-32004` Tool Execution Failed
241
+
242
+ ### Error Response Example
243
+
244
+ ```json
245
+ {
246
+ "jsonrpc": "2.0",
247
+ "id": 1,
248
+ "error": {
249
+ "code": -32602,
250
+ "message": "Invalid params: sessionId required",
251
+ "data": {
252
+ "received": {},
253
+ "expected": "object with sessionId field"
254
+ }
255
+ }
256
+ }
257
+ ```
258
+
259
+ ## Testing
260
+
261
+ The implementation includes comprehensive tests:
262
+
263
+ - **Unit Tests** - Individual component testing
264
+ - **Integration Tests** - Full protocol flow testing
265
+ - **Error Handling Tests** - Edge cases and error conditions
266
+ - **Mock Testing** - Isolated testing with mocked dependencies
267
+
268
+ Run tests:
269
+
270
+ ```bash
271
+ npm test npm/src/agent/acp/
272
+ ```
273
+
274
+ ## Development
275
+
276
+ ### Adding New Methods
277
+
278
+ 1. Add method constant to `types.js`
279
+ 2. Implement handler in `server.js`
280
+ 3. Add to request routing in `handleRequest()`
281
+ 4. Write tests for the new method
282
+
283
+ ### Adding New Tools
284
+
285
+ 1. Implement tool in ProbeAgent's tool system
286
+ 2. Add tool definition to `ACPToolManager.getToolDefinitions()`
287
+ 3. Add execution case in `executeProbeTool()`
288
+ 4. Update capabilities in server
289
+
290
+ ### Debugging
291
+
292
+ Enable debug mode for detailed logging:
293
+
294
+ ```bash
295
+ DEBUG=1 probe agent --acp
296
+ ```
297
+
298
+ Debug logs include:
299
+ - Message send/receive
300
+ - Tool execution progress
301
+ - Session lifecycle events
302
+ - Error details and stack traces
303
+
304
+ ## Compatibility
305
+
306
+ ### Protocol Versions
307
+
308
+ - **ACP v1** - Full support for core protocol features
309
+ - Backwards compatible with future minor versions
310
+ - Forward compatible design for protocol evolution
311
+
312
+ ### Editor Integration
313
+
314
+ - **Zed** - Native ACP support
315
+ - **Neovim** - Via ACP plugins (CodeCompanion, Avante.nvim)
316
+ - **VS Code** - Potential future support
317
+ - **Other Editors** - Any editor implementing ACP client
318
+
319
+ ### AI Model Support
320
+
321
+ - **Anthropic Claude** - Full support (Haiku, Sonnet, Opus)
322
+ - **OpenAI GPT** - Full support (GPT-4, GPT-4 Turbo)
323
+ - **Google Gemini** - Full support (Pro, Ultra)
324
+ - Model selection via `--provider` and `--model` flags
325
+
326
+ ## Migration from MCP
327
+
328
+ For users migrating from MCP to ACP:
329
+
330
+ ### Similarities
331
+ - Both use JSON-RPC for communication
332
+ - Similar tool execution concepts
333
+ - Maintain conversation context
334
+
335
+ ### Key Differences
336
+ - ACP has richer session management
337
+ - Tool lifecycle tracking with status updates
338
+ - More granular permission system
339
+ - Enhanced content types and metadata
340
+
341
+ ### Migration Steps
342
+ 1. Update client to use ACP protocol
343
+ 2. Change startup flag from `--mcp` to `--acp`
344
+ 3. Adapt to new message formats (mostly compatible)
345
+ 4. Leverage enhanced session and tool features
346
+
347
+ The ACP implementation maintains feature parity with MCP while adding enhanced capabilities for modern AI-assisted coding workflows.
@@ -0,0 +1,237 @@
1
+ // ACP Connection - handles JSON-RPC 2.0 communication over stdio
2
+ import { EventEmitter } from 'events';
3
+ import { validateMessage, createResponse, createError, ErrorCode } from './types.js';
4
+
5
+ /**
6
+ * ACP Connection class for handling bidirectional JSON-RPC communication
7
+ */
8
+ export class ACPConnection extends EventEmitter {
9
+ constructor(inputStream = process.stdin, outputStream = process.stdout) {
10
+ super();
11
+
12
+ this.inputStream = inputStream;
13
+ this.outputStream = outputStream;
14
+ this.buffer = '';
15
+ this.messageId = 1;
16
+ this.pendingRequests = new Map();
17
+ this.isConnected = false;
18
+ this.debug = process.env.DEBUG === '1';
19
+
20
+ this.setupStreams();
21
+ }
22
+
23
+ /**
24
+ * Setup input/output streams
25
+ */
26
+ setupStreams() {
27
+ this.inputStream.setEncoding('utf8');
28
+ this.inputStream.on('data', this.handleData.bind(this));
29
+ this.inputStream.on('end', () => {
30
+ this.isConnected = false;
31
+ this.emit('disconnect');
32
+ });
33
+
34
+ this.inputStream.on('error', (error) => {
35
+ if (this.debug) {
36
+ console.error('[ACP] Input stream error:', error);
37
+ }
38
+ this.emit('error', error);
39
+ });
40
+
41
+ this.outputStream.on('error', (error) => {
42
+ if (this.debug) {
43
+ console.error('[ACP] Output stream error:', error);
44
+ }
45
+ this.emit('error', error);
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Start the connection
51
+ */
52
+ start() {
53
+ this.isConnected = true;
54
+ this.emit('connect');
55
+
56
+ if (this.debug) {
57
+ console.error('[ACP] Connection started');
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Handle incoming data
63
+ */
64
+ handleData(chunk) {
65
+ this.buffer += chunk;
66
+
67
+ // Process complete messages (separated by newlines)
68
+ const lines = this.buffer.split('\n');
69
+ this.buffer = lines.pop() || ''; // Keep incomplete line in buffer
70
+
71
+ for (const line of lines) {
72
+ if (line.trim()) {
73
+ try {
74
+ const message = JSON.parse(line);
75
+ this.handleMessage(message);
76
+ } catch (error) {
77
+ if (this.debug) {
78
+ console.error('[ACP] Failed to parse message:', line, error);
79
+ }
80
+ this.sendError(null, ErrorCode.PARSE_ERROR, 'Parse error');
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Handle a parsed JSON-RPC message
88
+ */
89
+ handleMessage(message) {
90
+ const validation = validateMessage(message);
91
+ if (!validation.valid) {
92
+ if (this.debug) {
93
+ console.error('[ACP] Invalid message:', validation.error, message);
94
+ }
95
+ this.sendError(message.id || null, ErrorCode.INVALID_REQUEST, validation.error);
96
+ return;
97
+ }
98
+
99
+ if (this.debug) {
100
+ console.error('[ACP] Received message:', JSON.stringify(message));
101
+ }
102
+
103
+ // Handle response to our request
104
+ if (message.id && (message.result !== undefined || message.error !== undefined)) {
105
+ this.handleResponse(message);
106
+ return;
107
+ }
108
+
109
+ // Handle request or notification
110
+ if (message.method) {
111
+ if (message.id !== undefined) {
112
+ // Request - needs response
113
+ this.emit('request', message);
114
+ } else {
115
+ // Notification - no response needed
116
+ this.emit('notification', message);
117
+ }
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Handle response to our request
123
+ */
124
+ handleResponse(message) {
125
+ const { id, result, error } = message;
126
+ const pendingRequest = this.pendingRequests.get(id);
127
+
128
+ if (pendingRequest) {
129
+ this.pendingRequests.delete(id);
130
+
131
+ if (error) {
132
+ pendingRequest.reject(new Error(`RPC Error ${error.code}: ${error.message}`));
133
+ } else {
134
+ pendingRequest.resolve(result);
135
+ }
136
+ } else if (this.debug) {
137
+ console.error('[ACP] Received response for unknown request ID:', id);
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Send a message
143
+ */
144
+ sendMessage(message) {
145
+ if (!this.isConnected) {
146
+ throw new Error('Connection not established');
147
+ }
148
+
149
+ const json = JSON.stringify(message);
150
+
151
+ if (this.debug) {
152
+ console.error('[ACP] Sending message:', json);
153
+ }
154
+
155
+ this.outputStream.write(json + '\n');
156
+ }
157
+
158
+ /**
159
+ * Send a request and wait for response
160
+ */
161
+ async sendRequest(method, params = null) {
162
+ const id = this.messageId++;
163
+ const message = {
164
+ jsonrpc: '2.0',
165
+ method,
166
+ id
167
+ };
168
+
169
+ if (params !== null) {
170
+ message.params = params;
171
+ }
172
+
173
+ return new Promise((resolve, reject) => {
174
+ // Store the pending request
175
+ this.pendingRequests.set(id, { resolve, reject });
176
+
177
+ // Send the message
178
+ this.sendMessage(message);
179
+
180
+ // Set timeout
181
+ setTimeout(() => {
182
+ if (this.pendingRequests.has(id)) {
183
+ this.pendingRequests.delete(id);
184
+ reject(new Error('Request timeout'));
185
+ }
186
+ }, 30000); // 30 second timeout
187
+ });
188
+ }
189
+
190
+ /**
191
+ * Send a notification (no response expected)
192
+ */
193
+ sendNotification(method, params = null) {
194
+ const message = {
195
+ jsonrpc: '2.0',
196
+ method
197
+ };
198
+
199
+ if (params !== null) {
200
+ message.params = params;
201
+ }
202
+
203
+ this.sendMessage(message);
204
+ }
205
+
206
+ /**
207
+ * Send a response to a request
208
+ */
209
+ sendResponse(id, result) {
210
+ const response = createResponse(id, result);
211
+ this.sendMessage(response);
212
+ }
213
+
214
+ /**
215
+ * Send an error response
216
+ */
217
+ sendError(id, code, message, data = null) {
218
+ const error = createError(code, message, data);
219
+ const response = createResponse(id, null, error);
220
+ this.sendMessage(response);
221
+ }
222
+
223
+ /**
224
+ * Close the connection
225
+ */
226
+ close() {
227
+ this.isConnected = false;
228
+
229
+ // Reject all pending requests
230
+ for (const [id, pendingRequest] of this.pendingRequests) {
231
+ pendingRequest.reject(new Error('Connection closed'));
232
+ }
233
+ this.pendingRequests.clear();
234
+
235
+ this.emit('disconnect');
236
+ }
237
+ }