@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
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Manual ACP Test - Comprehensive testing of the ACP implementation
5
+ *
6
+ * This test spawns the ACP server and sends real protocol messages to verify
7
+ * the complete functionality including initialization, sessions, and AI interactions.
8
+ */
9
+
10
+ import { spawn } from 'child_process';
11
+ import { randomUUID } from 'crypto';
12
+
13
+ class ACPManualTest {
14
+ constructor() {
15
+ this.server = null;
16
+ this.messageId = 1;
17
+ this.pendingRequests = new Map();
18
+ this.buffer = '';
19
+ this.sessionId = null;
20
+ this.testResults = [];
21
+ }
22
+
23
+ async startServer() {
24
+ console.log('๐Ÿš€ Starting ACP Server...');
25
+
26
+ // Start the ACP server with verbose output
27
+ this.server = spawn('node', ['src/agent/index.js', '--acp', '--verbose'], {
28
+ cwd: '/Users/leonidbugaev/conductor/repo/probe/buger-belgrade/npm',
29
+ stdio: ['pipe', 'pipe', 'pipe']
30
+ });
31
+
32
+ // Handle server debug output
33
+ this.server.stderr.on('data', (data) => {
34
+ const output = data.toString().trim();
35
+ if (output) {
36
+ // Check if this looks like a JSON-RPC message that was mislabeled
37
+ const lines = output.split('\n');
38
+ for (const line of lines) {
39
+ if (line.trim().startsWith('{"jsonrpc"')) {
40
+ this.buffer += line + '\n';
41
+ this.processBuffer();
42
+ } else if (line.trim()) {
43
+ console.log(`๐Ÿ” Server: ${line}`);
44
+ }
45
+ }
46
+ }
47
+ });
48
+
49
+ // Handle server responses (JSON-RPC messages on stdout)
50
+ this.server.stdout.on('data', (data) => {
51
+ this.buffer += data.toString();
52
+ this.processBuffer();
53
+ });
54
+
55
+ this.server.on('close', (code) => {
56
+ console.log(`๐Ÿ“ด Server closed with code ${code}`);
57
+ });
58
+
59
+ // Wait for server to start
60
+ await new Promise(resolve => setTimeout(resolve, 2000));
61
+ console.log('โœ… Server started\n');
62
+ }
63
+
64
+ processBuffer() {
65
+ const lines = this.buffer.split('\n');
66
+ this.buffer = lines.pop() || ''; // Keep incomplete line in buffer
67
+
68
+ for (const line of lines) {
69
+ if (line.trim()) {
70
+ try {
71
+ const message = JSON.parse(line);
72
+ this.handleMessage(message);
73
+ } catch (error) {
74
+ console.log(`โš ๏ธ Failed to parse: ${line}`);
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ handleMessage(message) {
81
+ if (message.id && this.pendingRequests.has(message.id)) {
82
+ // Response to our request
83
+ const { resolve, reject } = this.pendingRequests.get(message.id);
84
+ this.pendingRequests.delete(message.id);
85
+
86
+ if (message.error) {
87
+ reject(new Error(`RPC Error ${message.error.code}: ${message.error.message}`));
88
+ } else {
89
+ resolve(message.result);
90
+ }
91
+ } else if (message.method) {
92
+ // Notification from server
93
+ console.log(`๐Ÿ“จ Notification: ${message.method}`, JSON.stringify(message.params, null, 2));
94
+ }
95
+ }
96
+
97
+ async sendRequest(method, params = null, description = '') {
98
+ const id = this.messageId++;
99
+ const message = {
100
+ jsonrpc: '2.0',
101
+ method,
102
+ id
103
+ };
104
+
105
+ if (params !== null) {
106
+ message.params = params;
107
+ }
108
+
109
+ console.log(`๐Ÿ“ค Sending: ${description || method}`);
110
+ if (params) {
111
+ console.log(` Params: ${JSON.stringify(params, null, 2)}`);
112
+ }
113
+
114
+ return new Promise((resolve, reject) => {
115
+ this.pendingRequests.set(id, { resolve, reject });
116
+
117
+ // Send to server
118
+ this.server.stdin.write(JSON.stringify(message) + '\n');
119
+
120
+ // Timeout after 30 seconds
121
+ setTimeout(() => {
122
+ if (this.pendingRequests.has(id)) {
123
+ this.pendingRequests.delete(id);
124
+ reject(new Error('Request timeout'));
125
+ }
126
+ }, 30000);
127
+ });
128
+ }
129
+
130
+ async runTest(testName, testFn) {
131
+ try {
132
+ console.log(`\n๐Ÿงช Running: ${testName}`);
133
+ console.log('-'.repeat(50));
134
+
135
+ const result = await testFn();
136
+
137
+ console.log(`โœ… ${testName} - PASSED`);
138
+ this.testResults.push({ name: testName, status: 'PASSED', result });
139
+
140
+ return result;
141
+ } catch (error) {
142
+ console.log(`โŒ ${testName} - FAILED`);
143
+ console.log(` Error: ${error.message}`);
144
+ this.testResults.push({ name: testName, status: 'FAILED', error: error.message });
145
+
146
+ throw error;
147
+ }
148
+ }
149
+
150
+ async test1_Initialize() {
151
+ return this.runTest('Initialize Protocol', async () => {
152
+ const result = await this.sendRequest('initialize', {
153
+ protocolVersion: '1'
154
+ }, 'Initialize ACP protocol');
155
+
156
+ console.log(`๐Ÿ“ฅ Response:`, JSON.stringify(result, null, 2));
157
+
158
+ // Verify response
159
+ if (result.protocolVersion !== '1') {
160
+ throw new Error('Wrong protocol version in response');
161
+ }
162
+
163
+ if (!result.serverInfo || result.serverInfo.name !== 'probe-agent-acp') {
164
+ throw new Error('Invalid server info');
165
+ }
166
+
167
+ if (!result.capabilities || !Array.isArray(result.capabilities.tools)) {
168
+ throw new Error('Invalid capabilities');
169
+ }
170
+
171
+ console.log(` โœ“ Protocol version: ${result.protocolVersion}`);
172
+ console.log(` โœ“ Server: ${result.serverInfo.name} v${result.serverInfo.version}`);
173
+ console.log(` โœ“ Tools: ${result.capabilities.tools.length} available`);
174
+ console.log(` โœ“ Sessions: ${result.capabilities.sessionManagement}`);
175
+
176
+ return result;
177
+ });
178
+ }
179
+
180
+ async test2_CreateSession() {
181
+ return this.runTest('Create New Session', async () => {
182
+ const result = await this.sendRequest('newSession', {}, 'Create new session');
183
+
184
+ console.log(`๐Ÿ“ฅ Response:`, JSON.stringify(result, null, 2));
185
+
186
+ if (!result.sessionId) {
187
+ throw new Error('No session ID returned');
188
+ }
189
+
190
+ if (result.mode !== 'normal') {
191
+ throw new Error('Wrong default mode');
192
+ }
193
+
194
+ this.sessionId = result.sessionId;
195
+
196
+ console.log(` โœ“ Session ID: ${this.sessionId}`);
197
+ console.log(` โœ“ Mode: ${result.mode}`);
198
+ console.log(` โœ“ Created: ${result.createdAt}`);
199
+
200
+ return result;
201
+ });
202
+ }
203
+
204
+ async test3_LoadSession() {
205
+ return this.runTest('Load Existing Session', async () => {
206
+ const result = await this.sendRequest('loadSession', {
207
+ sessionId: this.sessionId
208
+ }, 'Load session');
209
+
210
+ console.log(`๐Ÿ“ฅ Response:`, JSON.stringify(result, null, 2));
211
+
212
+ if (result.id !== this.sessionId) {
213
+ throw new Error('Wrong session ID in response');
214
+ }
215
+
216
+ console.log(` โœ“ Loaded session: ${result.id}`);
217
+ console.log(` โœ“ Mode: ${result.mode}`);
218
+ console.log(` โœ“ History length: ${result.historyLength}`);
219
+
220
+ return result;
221
+ });
222
+ }
223
+
224
+ async test4_SetSessionMode() {
225
+ return this.runTest('Set Session Mode', async () => {
226
+ const result = await this.sendRequest('setSessionMode', {
227
+ sessionId: this.sessionId,
228
+ mode: 'planning'
229
+ }, 'Set session to planning mode');
230
+
231
+ console.log(`๐Ÿ“ฅ Response:`, JSON.stringify(result, null, 2));
232
+
233
+ if (!result.success) {
234
+ throw new Error('Mode change failed');
235
+ }
236
+
237
+ console.log(` โœ“ Mode changed to: planning`);
238
+
239
+ return result;
240
+ });
241
+ }
242
+
243
+ async test5_SimplePrompt() {
244
+ return this.runTest('Simple Prompt (No AI)', async () => {
245
+ // Use a simple question that doesn't require AI API calls
246
+ const result = await this.sendRequest('prompt', {
247
+ sessionId: this.sessionId,
248
+ message: 'List the files in the current directory'
249
+ }, 'Send simple prompt');
250
+
251
+ console.log(`๐Ÿ“ฅ Response:`, JSON.stringify(result, null, 2));
252
+
253
+ if (!result.content || !Array.isArray(result.content)) {
254
+ throw new Error('Invalid content format');
255
+ }
256
+
257
+ if (result.content.length === 0) {
258
+ throw new Error('Empty content array');
259
+ }
260
+
261
+ const textContent = result.content.find(c => c.type === 'text');
262
+ if (!textContent) {
263
+ throw new Error('No text content found');
264
+ }
265
+
266
+ console.log(` โœ“ Content blocks: ${result.content.length}`);
267
+ console.log(` โœ“ Response length: ${textContent.text.length} chars`);
268
+ console.log(` โœ“ Session ID: ${result.sessionId}`);
269
+ console.log(` โœ“ Timestamp: ${result.timestamp}`);
270
+
271
+ return result;
272
+ });
273
+ }
274
+
275
+ async test6_Cancel() {
276
+ return this.runTest('Cancel Operation', async () => {
277
+ const result = await this.sendRequest('cancel', {
278
+ sessionId: this.sessionId
279
+ }, 'Cancel session operations');
280
+
281
+ console.log(`๐Ÿ“ฅ Response:`, JSON.stringify(result, null, 2));
282
+
283
+ if (!result.success) {
284
+ throw new Error('Cancel failed');
285
+ }
286
+
287
+ console.log(` โœ“ Cancellation successful`);
288
+
289
+ return result;
290
+ });
291
+ }
292
+
293
+ async test7_ErrorHandling() {
294
+ return this.runTest('Error Handling', async () => {
295
+ try {
296
+ await this.sendRequest('invalidMethod', {}, 'Send invalid method');
297
+ throw new Error('Should have failed with invalid method');
298
+ } catch (error) {
299
+ if (!error.message.includes('RPC Error -32601')) {
300
+ throw new Error(`Wrong error type: ${error.message}`);
301
+ }
302
+
303
+ console.log(` โœ“ Correctly rejected invalid method`);
304
+ console.log(` โœ“ Error: ${error.message}`);
305
+
306
+ return { error: error.message };
307
+ }
308
+ });
309
+ }
310
+
311
+ async test8_InvalidSession() {
312
+ return this.runTest('Invalid Session Handling', async () => {
313
+ try {
314
+ await this.sendRequest('loadSession', {
315
+ sessionId: 'nonexistent-session-id'
316
+ }, 'Try to load nonexistent session');
317
+ throw new Error('Should have failed with invalid session');
318
+ } catch (error) {
319
+ if (!error.message.includes('Session not found')) {
320
+ throw new Error(`Wrong error type: ${error.message}`);
321
+ }
322
+
323
+ console.log(` โœ“ Correctly rejected invalid session`);
324
+ console.log(` โœ“ Error: ${error.message}`);
325
+
326
+ return { error: error.message };
327
+ }
328
+ });
329
+ }
330
+
331
+ async runAllTests() {
332
+ console.log('๐Ÿงช ACP Manual Test Suite');
333
+ console.log('='.repeat(60));
334
+ console.log('This will test the complete ACP implementation with a real server');
335
+ console.log();
336
+
337
+ try {
338
+ await this.startServer();
339
+
340
+ // Run tests in sequence
341
+ await this.test1_Initialize();
342
+ await this.test2_CreateSession();
343
+ await this.test3_LoadSession();
344
+ await this.test4_SetSessionMode();
345
+ await this.test5_SimplePrompt();
346
+ await this.test6_Cancel();
347
+ await this.test7_ErrorHandling();
348
+ await this.test8_InvalidSession();
349
+
350
+ } catch (error) {
351
+ console.log(`\n๐Ÿ’ฅ Test suite failed: ${error.message}`);
352
+ } finally {
353
+ this.cleanup();
354
+ }
355
+
356
+ this.showResults();
357
+ }
358
+
359
+ cleanup() {
360
+ console.log('\n๐Ÿงน Cleaning up...');
361
+ if (this.server) {
362
+ this.server.stdin.end();
363
+ this.server.kill('SIGTERM');
364
+
365
+ // Force kill if still running after 2 seconds
366
+ setTimeout(() => {
367
+ if (this.server && !this.server.killed) {
368
+ this.server.kill('SIGKILL');
369
+ }
370
+ }, 2000);
371
+ }
372
+ }
373
+
374
+ showResults() {
375
+ console.log('\n๐Ÿ“Š Test Results Summary');
376
+ console.log('='.repeat(40));
377
+
378
+ const passed = this.testResults.filter(t => t.status === 'PASSED').length;
379
+ const failed = this.testResults.filter(t => t.status === 'FAILED').length;
380
+
381
+ for (const result of this.testResults) {
382
+ const icon = result.status === 'PASSED' ? 'โœ…' : 'โŒ';
383
+ console.log(`${icon} ${result.name}`);
384
+ if (result.error) {
385
+ console.log(` ${result.error}`);
386
+ }
387
+ }
388
+
389
+ console.log();
390
+ console.log(`Passed: ${passed}`);
391
+ console.log(`Failed: ${failed}`);
392
+ console.log(`Total: ${this.testResults.length}`);
393
+
394
+ if (failed === 0) {
395
+ console.log('\n๐ŸŽ‰ All tests passed! ACP implementation is working correctly.');
396
+ } else {
397
+ console.log(`\nโš ๏ธ ${failed} test(s) failed. Check the errors above.`);
398
+ }
399
+ }
400
+ }
401
+
402
+ // Handle Ctrl+C gracefully
403
+ process.on('SIGINT', () => {
404
+ console.log('\nโน๏ธ Test interrupted');
405
+ process.exit(0);
406
+ });
407
+
408
+ // Run the manual test
409
+ const test = new ACPManualTest();
410
+ test.runAllTests().catch(console.error);
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Protocol-Only Test - Tests ACP implementation without AI dependencies
5
+ * This focuses on the protocol mechanics without requiring API keys
6
+ */
7
+
8
+ import { spawn } from 'child_process';
9
+
10
+ class ProtocolTest {
11
+ constructor() {
12
+ this.server = null;
13
+ this.messageId = 1;
14
+ this.pendingRequests = new Map();
15
+ this.buffer = '';
16
+ }
17
+
18
+ async startServer() {
19
+ console.log('๐Ÿš€ Starting ACP Server (Protocol Test)...');
20
+
21
+ this.server = spawn('node', ['src/agent/index.js', '--acp'], {
22
+ cwd: '/Users/leonidbugaev/conductor/repo/probe/buger-belgrade/npm',
23
+ stdio: ['pipe', 'pipe', 'pipe']
24
+ });
25
+
26
+ this.server.stderr.on('data', (data) => {
27
+ const output = data.toString().trim();
28
+ if (output && output.includes('[ACP]')) {
29
+ console.log(`๐Ÿ” ${output}`);
30
+ }
31
+ });
32
+
33
+ this.server.stdout.on('data', (data) => {
34
+ this.buffer += data.toString();
35
+ this.processBuffer();
36
+ });
37
+
38
+ await new Promise(resolve => setTimeout(resolve, 1000));
39
+ console.log('โœ… Server ready\n');
40
+ }
41
+
42
+ processBuffer() {
43
+ const lines = this.buffer.split('\n');
44
+ this.buffer = lines.pop() || '';
45
+
46
+ for (const line of lines) {
47
+ if (line.trim()) {
48
+ try {
49
+ const message = JSON.parse(line);
50
+ this.handleMessage(message);
51
+ } catch (error) {
52
+ console.log(`โš ๏ธ Non-JSON: ${line.substring(0, 50)}...`);
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ handleMessage(message) {
59
+ if (message.id && this.pendingRequests.has(message.id)) {
60
+ const { resolve, reject } = this.pendingRequests.get(message.id);
61
+ this.pendingRequests.delete(message.id);
62
+
63
+ if (message.error) {
64
+ reject(new Error(`${message.error.code}: ${message.error.message}`));
65
+ } else {
66
+ resolve(message.result);
67
+ }
68
+ } else if (message.method) {
69
+ console.log(`๐Ÿ“จ Notification: ${message.method}`);
70
+ if (message.params) {
71
+ console.log(` ${JSON.stringify(message.params, null, 4)}`);
72
+ }
73
+ }
74
+ }
75
+
76
+ async sendRequest(method, params = null) {
77
+ const id = this.messageId++;
78
+ const message = { jsonrpc: '2.0', method, id };
79
+ if (params !== null) message.params = params;
80
+
81
+ return new Promise((resolve, reject) => {
82
+ this.pendingRequests.set(id, { resolve, reject });
83
+ this.server.stdin.write(JSON.stringify(message) + '\n');
84
+
85
+ setTimeout(() => {
86
+ if (this.pendingRequests.has(id)) {
87
+ this.pendingRequests.delete(id);
88
+ reject(new Error('Timeout'));
89
+ }
90
+ }, 10000);
91
+ });
92
+ }
93
+
94
+ async runProtocolTest() {
95
+ console.log('๐Ÿงช ACP Protocol Functionality Test');
96
+ console.log('='.repeat(50));
97
+
98
+ try {
99
+ await this.startServer();
100
+
101
+ // Test 1: Initialize
102
+ console.log('1๏ธโƒฃ Testing Protocol Initialization');
103
+ const initResult = await this.sendRequest('initialize', { protocolVersion: '1' });
104
+ console.log(` โœ… Version: ${initResult.protocolVersion}`);
105
+ console.log(` โœ… Server: ${initResult.serverInfo.name}`);
106
+ console.log(` โœ… Tools: ${initResult.capabilities.tools.length}`);
107
+ console.log();
108
+
109
+ // Test 2: Session Creation
110
+ console.log('2๏ธโƒฃ Testing Session Management');
111
+ const sessionResult = await this.sendRequest('newSession', {});
112
+ const sessionId = sessionResult.sessionId;
113
+ console.log(` โœ… Created session: ${sessionId.substring(0, 8)}...`);
114
+ console.log();
115
+
116
+ // Test 3: Session Loading
117
+ console.log('3๏ธโƒฃ Testing Session Loading');
118
+ const loadResult = await this.sendRequest('loadSession', { sessionId });
119
+ console.log(` โœ… Loaded session: ${loadResult.id.substring(0, 8)}...`);
120
+ console.log(` โœ… History length: ${loadResult.historyLength}`);
121
+ console.log();
122
+
123
+ // Test 4: Mode Changes
124
+ console.log('4๏ธโƒฃ Testing Session Mode Changes');
125
+ await this.sendRequest('setSessionMode', { sessionId, mode: 'planning' });
126
+ console.log(` โœ… Mode changed to planning`);
127
+ console.log();
128
+
129
+ // Test 5: Error Handling
130
+ console.log('5๏ธโƒฃ Testing Error Handling');
131
+ try {
132
+ await this.sendRequest('unknownMethod', {});
133
+ console.log(` โŒ Should have failed`);
134
+ } catch (error) {
135
+ if (error.message.includes('-32601')) {
136
+ console.log(` โœ… Correctly rejected unknown method`);
137
+ } else {
138
+ console.log(` โŒ Wrong error: ${error.message}`);
139
+ }
140
+ }
141
+ console.log();
142
+
143
+ // Test 6: Invalid Session
144
+ console.log('6๏ธโƒฃ Testing Invalid Session Handling');
145
+ try {
146
+ await this.sendRequest('loadSession', { sessionId: 'invalid' });
147
+ console.log(` โŒ Should have failed`);
148
+ } catch (error) {
149
+ if (error.message.includes('Session not found')) {
150
+ console.log(` โœ… Correctly rejected invalid session`);
151
+ } else {
152
+ console.log(` โŒ Wrong error: ${error.message}`);
153
+ }
154
+ }
155
+ console.log();
156
+
157
+ // Test 7: Cancellation
158
+ console.log('7๏ธโƒฃ Testing Cancellation');
159
+ const cancelResult = await this.sendRequest('cancel', { sessionId });
160
+ console.log(` โœ… Cancel successful: ${cancelResult.success}`);
161
+ console.log();
162
+
163
+ console.log('๐ŸŽ‰ All Protocol Tests Passed!');
164
+ console.log();
165
+ console.log('๐Ÿ“‹ Summary:');
166
+ console.log(' โ€ข JSON-RPC 2.0 communication: โœ…');
167
+ console.log(' โ€ข Protocol initialization: โœ…');
168
+ console.log(' โ€ข Session management: โœ…');
169
+ console.log(' โ€ข Mode changes with notifications: โœ…');
170
+ console.log(' โ€ข Error handling: โœ…');
171
+ console.log(' โ€ข Request validation: โœ…');
172
+ console.log(' โ€ข Cancellation support: โœ…');
173
+
174
+ } catch (error) {
175
+ console.log(`โŒ Test failed: ${error.message}`);
176
+ } finally {
177
+ this.cleanup();
178
+ }
179
+ }
180
+
181
+ cleanup() {
182
+ if (this.server) {
183
+ this.server.stdin.end();
184
+ this.server.kill();
185
+ }
186
+ }
187
+ }
188
+
189
+ const test = new ProtocolTest();
190
+ test.runProtocolTest().catch(console.error);