@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.
- package/README.md +583 -0
- package/bin/.gitkeep +0 -0
- package/bin/probe +158 -0
- package/bin/probe-binary +0 -0
- package/build/agent/ProbeAgent.d.ts +199 -0
- package/build/agent/ProbeAgent.js +1486 -0
- package/build/agent/acp/README.md +347 -0
- package/build/agent/acp/connection.js +237 -0
- package/build/agent/acp/connection.test.js +311 -0
- package/build/agent/acp/examples/simple-client.js +212 -0
- package/build/agent/acp/examples/tool-lifecycle.js +230 -0
- package/build/agent/acp/final-test.js +173 -0
- package/build/agent/acp/index.js +5 -0
- package/build/agent/acp/integration.test.js +385 -0
- package/build/agent/acp/manual-test.js +410 -0
- package/build/agent/acp/protocol-test.js +190 -0
- package/build/agent/acp/server.js +448 -0
- package/build/agent/acp/server.test.js +371 -0
- package/build/agent/acp/test-runner.js +216 -0
- package/build/agent/acp/test-utils/README.md +315 -0
- package/build/agent/acp/test-utils/acp-tester.js +484 -0
- package/build/agent/acp/test-utils/mock-acp-client.js +434 -0
- package/build/agent/acp/tools.js +368 -0
- package/build/agent/acp/tools.test.js +334 -0
- package/build/agent/acp/types.js +218 -0
- package/build/agent/acp/types.test.js +327 -0
- package/build/agent/appTracer.js +360 -0
- package/build/agent/fileSpanExporter.js +169 -0
- package/build/agent/index.js +7426 -0
- package/build/agent/mcp/client.js +338 -0
- package/build/agent/mcp/config.js +313 -0
- package/build/agent/mcp/index.js +64 -0
- package/build/agent/mcp/xmlBridge.js +371 -0
- package/build/agent/mockProvider.js +53 -0
- package/build/agent/probeTool.js +257 -0
- package/build/agent/schemaUtils.js +1726 -0
- package/build/agent/simpleTelemetry.js +267 -0
- package/build/agent/telemetry.js +225 -0
- package/build/agent/tokenCounter.js +395 -0
- package/build/agent/tools.js +163 -0
- package/build/cli.js +49 -0
- package/build/delegate.js +267 -0
- package/build/directory-resolver.js +237 -0
- package/build/downloader.js +750 -0
- package/build/extract.js +149 -0
- package/build/index.js +70 -0
- package/build/mcp/index.js +514 -0
- package/build/mcp/index.ts +608 -0
- package/build/query.js +116 -0
- package/build/search.js +247 -0
- package/build/tools/common.js +410 -0
- package/build/tools/index.js +40 -0
- package/build/tools/langchain.js +88 -0
- package/build/tools/system-message.js +121 -0
- package/build/tools/vercel.js +271 -0
- package/build/utils/file-lister.js +193 -0
- package/build/utils.js +128 -0
- package/cjs/agent/ProbeAgent.cjs +5829 -0
- package/cjs/index.cjs +6217 -0
- package/cjs/package.json +3 -0
- package/index.d.ts +401 -0
- package/package.json +114 -0
- package/scripts/postinstall.js +172 -0
- package/src/agent/ProbeAgent.d.ts +199 -0
- package/src/agent/ProbeAgent.js +1486 -0
- package/src/agent/acp/README.md +347 -0
- package/src/agent/acp/connection.js +237 -0
- package/src/agent/acp/connection.test.js +311 -0
- package/src/agent/acp/examples/simple-client.js +212 -0
- package/src/agent/acp/examples/tool-lifecycle.js +230 -0
- package/src/agent/acp/final-test.js +173 -0
- package/src/agent/acp/index.js +5 -0
- package/src/agent/acp/integration.test.js +385 -0
- package/src/agent/acp/manual-test.js +410 -0
- package/src/agent/acp/protocol-test.js +190 -0
- package/src/agent/acp/server.js +448 -0
- package/src/agent/acp/server.test.js +371 -0
- package/src/agent/acp/test-runner.js +216 -0
- package/src/agent/acp/test-utils/README.md +315 -0
- package/src/agent/acp/test-utils/acp-tester.js +484 -0
- package/src/agent/acp/test-utils/mock-acp-client.js +434 -0
- package/src/agent/acp/tools.js +368 -0
- package/src/agent/acp/tools.test.js +334 -0
- package/src/agent/acp/types.js +218 -0
- package/src/agent/acp/types.test.js +327 -0
- package/src/agent/appTracer.js +360 -0
- package/src/agent/fileSpanExporter.js +169 -0
- package/src/agent/index.js +813 -0
- package/src/agent/mcp/client.js +338 -0
- package/src/agent/mcp/config.js +313 -0
- package/src/agent/mcp/index.js +64 -0
- package/src/agent/mcp/xmlBridge.js +371 -0
- package/src/agent/mockProvider.js +53 -0
- package/src/agent/probeTool.js +257 -0
- package/src/agent/schemaUtils.js +1726 -0
- package/src/agent/simpleTelemetry.js +267 -0
- package/src/agent/telemetry.js +225 -0
- package/src/agent/tokenCounter.js +395 -0
- package/src/agent/tools.js +163 -0
- package/src/cli.js +49 -0
- package/src/delegate.js +267 -0
- package/src/directory-resolver.js +237 -0
- package/src/downloader.js +750 -0
- package/src/extract.js +149 -0
- package/src/index.js +70 -0
- package/src/mcp/index.ts +608 -0
- package/src/query.js +116 -0
- package/src/search.js +247 -0
- package/src/tools/common.js +410 -0
- package/src/tools/index.js +40 -0
- package/src/tools/langchain.js +88 -0
- package/src/tools/system-message.js +121 -0
- package/src/tools/vercel.js +271 -0
- package/src/utils/file-lister.js +193 -0
- 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 };
|