@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,434 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Mock ACP Client - Simulates an editor/client communicating with ACP agents
5
+ *
6
+ * This utility can be used to test ACP agents by simulating realistic
7
+ * editor interactions, including user prompts, tool usage, and session management.
8
+ *
9
+ * Usage:
10
+ * mock-acp-client --agent "node agent.js --acp"
11
+ * mock-acp-client --agent "my-agent-binary" --interactive
12
+ */
13
+
14
+ import { spawn } from 'child_process';
15
+ import { randomUUID } from 'crypto';
16
+ import { createInterface } from 'readline';
17
+
18
+ class MockACPClient {
19
+ constructor(options = {}) {
20
+ this.options = {
21
+ agentCommand: options.agentCommand,
22
+ interactive: options.interactive || false,
23
+ timeout: options.timeout || 30000,
24
+ debug: options.debug || false
25
+ };
26
+
27
+ this.agent = null;
28
+ this.messageId = 1;
29
+ this.pendingRequests = new Map();
30
+ this.buffer = '';
31
+ this.sessionId = null;
32
+ this.initialized = false;
33
+ this.rl = null;
34
+
35
+ if (this.options.interactive) {
36
+ this.rl = createInterface({
37
+ input: process.stdin,
38
+ output: process.stdout
39
+ });
40
+ }
41
+ }
42
+
43
+ log(message, data = null) {
44
+ const timestamp = new Date().toISOString().split('T')[1].split('.')[0];
45
+ console.log(`[${timestamp}] ${message}`);
46
+
47
+ if (data && this.options.debug) {
48
+ console.log(JSON.stringify(data, null, 2));
49
+ }
50
+ }
51
+
52
+ async startAgent() {
53
+ if (!this.options.agentCommand) {
54
+ throw new Error('Agent command required');
55
+ }
56
+
57
+ this.log(`šŸš€ Starting agent: ${this.options.agentCommand}`);
58
+
59
+ const parts = this.options.agentCommand.split(' ');
60
+ const command = parts[0];
61
+ const args = parts.slice(1);
62
+
63
+ this.agent = spawn(command, args, {
64
+ stdio: ['pipe', 'pipe', 'pipe']
65
+ });
66
+
67
+ this.agent.stdout.on('data', (data) => {
68
+ this.buffer += data.toString();
69
+ this.processBuffer();
70
+ });
71
+
72
+ this.agent.stderr.on('data', (data) => {
73
+ const output = data.toString().trim();
74
+ if (output && this.options.debug) {
75
+ this.log(`šŸ” Agent debug: ${output}`);
76
+ }
77
+ });
78
+
79
+ this.agent.on('close', (code) => {
80
+ this.log(`šŸ““ Agent closed with code ${code}`);
81
+ });
82
+
83
+ // Wait for agent to be ready
84
+ await new Promise(resolve => setTimeout(resolve, 1000));
85
+ }
86
+
87
+ processBuffer() {
88
+ const lines = this.buffer.split('\n');
89
+ this.buffer = lines.pop() || '';
90
+
91
+ for (const line of lines) {
92
+ if (line.trim()) {
93
+ try {
94
+ const message = JSON.parse(line);
95
+ this.handleMessage(message);
96
+ } catch (error) {
97
+ if (this.options.debug) {
98
+ this.log(`āš ļø Invalid JSON from agent: ${line.substring(0, 100)}...`);
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+
105
+ handleMessage(message) {
106
+ if (message.id && this.pendingRequests.has(message.id)) {
107
+ // Response to our request
108
+ const { resolve, reject } = this.pendingRequests.get(message.id);
109
+ this.pendingRequests.delete(message.id);
110
+
111
+ if (message.error) {
112
+ reject(new Error(`RPC Error ${message.error.code}: ${message.error.message}`));
113
+ } else {
114
+ resolve(message.result);
115
+ }
116
+ } else if (message.method) {
117
+ // Notification from agent
118
+ this.handleNotification(message);
119
+ }
120
+ }
121
+
122
+ handleNotification(notification) {
123
+ const { method, params } = notification;
124
+
125
+ switch (method) {
126
+ case 'sessionUpdated':
127
+ this.log(`šŸ“ Session updated: ${params.sessionId} → ${params.mode}`);
128
+ break;
129
+
130
+ case 'toolCallProgress':
131
+ const { toolCallId, status, result, error } = params;
132
+ const icon = {
133
+ pending: 'ā³',
134
+ in_progress: 'šŸ”„',
135
+ completed: 'āœ…',
136
+ failed: 'āŒ'
137
+ }[status] || 'ā“';
138
+
139
+ this.log(`${icon} Tool ${toolCallId.substring(0, 8)}: ${status}`);
140
+
141
+ if (status === 'completed' && result) {
142
+ const preview = typeof result === 'string'
143
+ ? result.substring(0, 100) + (result.length > 100 ? '...' : '')
144
+ : '[Object result]';
145
+ this.log(` šŸ“‹ Result: ${preview}`);
146
+ }
147
+
148
+ if (status === 'failed' && error) {
149
+ this.log(` šŸ’„ Error: ${error}`);
150
+ }
151
+ break;
152
+
153
+ case 'messageChunk':
154
+ // Streaming response chunk
155
+ process.stdout.write(params.chunk);
156
+ break;
157
+
158
+ default:
159
+ this.log(`šŸ“Ø Notification: ${method}`, params);
160
+ }
161
+ }
162
+
163
+ async sendRequest(method, params = null) {
164
+ const id = this.messageId++;
165
+ const message = {
166
+ jsonrpc: '2.0',
167
+ method,
168
+ id
169
+ };
170
+
171
+ if (params !== null) {
172
+ message.params = params;
173
+ }
174
+
175
+ return new Promise((resolve, reject) => {
176
+ this.pendingRequests.set(id, { resolve, reject });
177
+
178
+ this.agent.stdin.write(JSON.stringify(message) + '\n');
179
+
180
+ setTimeout(() => {
181
+ if (this.pendingRequests.has(id)) {
182
+ this.pendingRequests.delete(id);
183
+ reject(new Error('Request timeout'));
184
+ }
185
+ }, this.options.timeout);
186
+ });
187
+ }
188
+
189
+ async initialize() {
190
+ this.log('šŸ”§ Initializing ACP connection...');
191
+
192
+ const result = await this.sendRequest('initialize', {
193
+ protocolVersion: '1'
194
+ });
195
+
196
+ this.initialized = true;
197
+
198
+ this.log(`āœ… Connected to ${result.serverInfo.name} v${result.serverInfo.version}`);
199
+ this.log(`šŸ› ļø Available tools: ${result.capabilities.tools.map(t => t.name).join(', ')}`);
200
+
201
+ return result;
202
+ }
203
+
204
+ async createSession() {
205
+ this.log('šŸ“ Creating new session...');
206
+
207
+ const result = await this.sendRequest('newSession', {});
208
+ this.sessionId = result.sessionId;
209
+
210
+ this.log(`āœ… Session created: ${this.sessionId}`);
211
+
212
+ return result;
213
+ }
214
+
215
+ async sendPrompt(message) {
216
+ if (!this.sessionId) {
217
+ throw new Error('No active session');
218
+ }
219
+
220
+ this.log(`šŸ’¬ Sending: "${message}"`);
221
+
222
+ const result = await this.sendRequest('prompt', {
223
+ sessionId: this.sessionId,
224
+ message
225
+ });
226
+
227
+ // Display response
228
+ this.log('šŸ¤– Agent response:');
229
+ for (const block of result.content) {
230
+ if (block.type === 'text') {
231
+ console.log('━'.repeat(60));
232
+ console.log(block.text);
233
+ console.log('━'.repeat(60));
234
+ }
235
+ }
236
+ console.log();
237
+
238
+ return result;
239
+ }
240
+
241
+ async setSessionMode(mode) {
242
+ if (!this.sessionId) {
243
+ throw new Error('No active session');
244
+ }
245
+
246
+ this.log(`āš™ļø Setting session mode to: ${mode}`);
247
+
248
+ const result = await this.sendRequest('setSessionMode', {
249
+ sessionId: this.sessionId,
250
+ mode
251
+ });
252
+
253
+ return result;
254
+ }
255
+
256
+ async runInteractiveSession() {
257
+ this.log('šŸŽ® Starting interactive session...');
258
+ this.log('Type "help" for commands, "quit" to exit');
259
+ console.log();
260
+
261
+ while (true) {
262
+ const input = await this.prompt('> ');
263
+ const trimmed = input.trim();
264
+
265
+ if (!trimmed) continue;
266
+
267
+ if (trimmed === 'quit' || trimmed === 'exit') {
268
+ break;
269
+ }
270
+
271
+ if (trimmed === 'help') {
272
+ this.showHelp();
273
+ continue;
274
+ }
275
+
276
+ if (trimmed.startsWith('mode ')) {
277
+ const mode = trimmed.substring(5);
278
+ try {
279
+ await this.setSessionMode(mode);
280
+ } catch (error) {
281
+ this.log(`āŒ Mode change failed: ${error.message}`);
282
+ }
283
+ continue;
284
+ }
285
+
286
+ if (trimmed === 'status') {
287
+ this.log(`Session: ${this.sessionId}`);
288
+ this.log(`Initialized: ${this.initialized}`);
289
+ continue;
290
+ }
291
+
292
+ // Default: send as prompt
293
+ try {
294
+ await this.sendPrompt(trimmed);
295
+ } catch (error) {
296
+ this.log(`āŒ Prompt failed: ${error.message}`);
297
+ }
298
+ }
299
+ }
300
+
301
+ showHelp() {
302
+ console.log(`
303
+ Available commands:
304
+ help Show this help
305
+ quit, exit Exit the client
306
+ mode <mode> Set session mode (normal, planning)
307
+ status Show connection status
308
+
309
+ Any other text will be sent as a prompt to the agent.
310
+ `);
311
+ }
312
+
313
+ async prompt(question) {
314
+ return new Promise(resolve => {
315
+ this.rl.question(question, resolve);
316
+ });
317
+ }
318
+
319
+ async runDemoSession() {
320
+ this.log('šŸŽ¬ Running demo session...');
321
+
322
+ // Demo conversation
323
+ const prompts = [
324
+ 'Hello! Can you tell me about yourself?',
325
+ 'What files are in this project?',
326
+ 'Find all TypeScript files',
327
+ 'Show me the main entry point'
328
+ ];
329
+
330
+ for (const prompt of prompts) {
331
+ try {
332
+ await this.sendPrompt(prompt);
333
+ await new Promise(resolve => setTimeout(resolve, 1000));
334
+ } catch (error) {
335
+ this.log(`āŒ Demo prompt failed: ${error.message}`);
336
+ if (error.message.includes('API key')) {
337
+ this.log('ā„¹ļø Demo requires AI API keys to be set');
338
+ break;
339
+ }
340
+ }
341
+ }
342
+ }
343
+
344
+ async run() {
345
+ try {
346
+ await this.startAgent();
347
+ await this.initialize();
348
+ await this.createSession();
349
+
350
+ if (this.options.interactive) {
351
+ await this.runInteractiveSession();
352
+ } else {
353
+ await this.runDemoSession();
354
+ }
355
+
356
+ } catch (error) {
357
+ this.log(`āŒ Client error: ${error.message}`);
358
+ } finally {
359
+ this.cleanup();
360
+ }
361
+ }
362
+
363
+ cleanup() {
364
+ if (this.rl) {
365
+ this.rl.close();
366
+ }
367
+
368
+ if (this.agent) {
369
+ this.agent.stdin.end();
370
+ this.agent.kill();
371
+ }
372
+ }
373
+ }
374
+
375
+ // CLI handling
376
+ async function main() {
377
+ const args = process.argv.slice(2);
378
+ const options = {};
379
+
380
+ for (let i = 0; i < args.length; i++) {
381
+ const arg = args[i];
382
+
383
+ if (arg === '--agent' && i + 1 < args.length) {
384
+ options.agentCommand = args[++i];
385
+ } else if (arg === '--interactive' || arg === '-i') {
386
+ options.interactive = true;
387
+ } else if (arg === '--debug' || arg === '-d') {
388
+ options.debug = true;
389
+ } else if (arg === '--timeout' && i + 1 < args.length) {
390
+ options.timeout = parseInt(args[++i], 10) * 1000;
391
+ } else if (arg === '--help' || arg === '-h') {
392
+ console.log(`
393
+ Mock ACP Client - Test tool for ACP agents
394
+
395
+ Usage:
396
+ mock-acp-client --agent "command to start agent"
397
+
398
+ Options:
399
+ --agent <command> Command to start the ACP agent (required)
400
+ --interactive, -i Start interactive session
401
+ --debug, -d Enable debug output
402
+ --timeout <seconds> Request timeout (default: 30)
403
+ --help, -h Show this help
404
+
405
+ Examples:
406
+ mock-acp-client --agent "node agent.js --acp"
407
+ mock-acp-client --agent "python my_agent.py" --interactive
408
+ mock-acp-client --agent "./agent-binary" --debug
409
+ `);
410
+ process.exit(0);
411
+ }
412
+ }
413
+
414
+ if (!options.agentCommand) {
415
+ console.error('āŒ Error: --agent is required');
416
+ console.error('Use --help for usage information');
417
+ process.exit(1);
418
+ }
419
+
420
+ const client = new MockACPClient(options);
421
+ await client.run();
422
+ }
423
+
424
+ // Handle Ctrl+C gracefully
425
+ process.on('SIGINT', () => {
426
+ console.log('\nšŸ‘‹ Goodbye!');
427
+ process.exit(0);
428
+ });
429
+
430
+ if (import.meta.url === `file://${process.argv[1]}`) {
431
+ main().catch(console.error);
432
+ }
433
+
434
+ export { MockACPClient };