@defai.digital/ax-cli 3.8.34 → 3.8.36

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.
@@ -0,0 +1,417 @@
1
+ /**
2
+ * VS Code IPC Client
3
+ *
4
+ * WebSocket client that connects to the VS Code extension's IPC server.
5
+ * Enables the CLI to:
6
+ * - Show diff previews in VS Code before file modifications
7
+ * - Display task completion summaries in VS Code
8
+ * - Update status in VS Code status bar
9
+ *
10
+ * Falls back gracefully if extension is not running.
11
+ */
12
+ import { EventEmitter } from 'events';
13
+ import WebSocket from 'ws';
14
+ import * as fs from 'fs';
15
+ import * as path from 'path';
16
+ import * as os from 'os';
17
+ const IPC_PORT_FILE = path.join(os.homedir(), '.ax-cli', 'vscode-ipc.json');
18
+ const CONNECTION_TIMEOUT = 5000; // 5 seconds to connect
19
+ const REQUEST_TIMEOUT = 120000; // 2 minutes for approval (user may need time to review)
20
+ export class VSCodeIPCClient extends EventEmitter {
21
+ ws = null;
22
+ port = 0;
23
+ connected = false;
24
+ connecting = false;
25
+ pendingRequests = new Map();
26
+ requestCounter = 0;
27
+ constructor() {
28
+ super();
29
+ }
30
+ /**
31
+ * Attempt to connect to VS Code extension IPC server
32
+ * Returns true if connected, false if extension not available
33
+ */
34
+ async connect() {
35
+ if (this.connected)
36
+ return true;
37
+ if (this.connecting)
38
+ return false;
39
+ this.connecting = true;
40
+ try {
41
+ // Read port file
42
+ const portInfo = this.readPortFile();
43
+ if (!portInfo) {
44
+ this.connecting = false;
45
+ return false;
46
+ }
47
+ this.port = portInfo.port;
48
+ // Connect to WebSocket server
49
+ return await this.establishConnection();
50
+ }
51
+ catch {
52
+ // Silently fail - CLI works standalone without VS Code extension
53
+ this.connecting = false;
54
+ return false;
55
+ }
56
+ }
57
+ /**
58
+ * Establish WebSocket connection
59
+ */
60
+ establishConnection() {
61
+ return new Promise((resolve) => {
62
+ const timeout = setTimeout(() => {
63
+ if (this.ws) {
64
+ this.ws.close();
65
+ }
66
+ this.connecting = false;
67
+ resolve(false);
68
+ }, CONNECTION_TIMEOUT);
69
+ try {
70
+ this.ws = new WebSocket(`ws://127.0.0.1:${this.port}`);
71
+ this.ws.on('open', () => {
72
+ clearTimeout(timeout);
73
+ this.connected = true;
74
+ this.connecting = false;
75
+ // Don't log to console - would interfere with TUI
76
+ this.emit('connected');
77
+ resolve(true);
78
+ });
79
+ this.ws.on('message', (data) => {
80
+ try {
81
+ const response = JSON.parse(data.toString());
82
+ this.handleResponse(response);
83
+ }
84
+ catch {
85
+ // Silently ignore parse errors - malformed responses shouldn't crash CLI
86
+ }
87
+ });
88
+ this.ws.on('close', () => {
89
+ clearTimeout(timeout);
90
+ this.handleDisconnect();
91
+ if (this.connecting) {
92
+ this.connecting = false;
93
+ resolve(false);
94
+ }
95
+ });
96
+ this.ws.on('error', () => {
97
+ clearTimeout(timeout);
98
+ // Silently fail - CLI works standalone without VS Code extension
99
+ if (this.connecting) {
100
+ this.connecting = false;
101
+ resolve(false);
102
+ }
103
+ });
104
+ }
105
+ catch (error) {
106
+ clearTimeout(timeout);
107
+ this.connecting = false;
108
+ resolve(false);
109
+ }
110
+ });
111
+ }
112
+ /**
113
+ * Handle disconnection
114
+ */
115
+ handleDisconnect() {
116
+ const wasConnected = this.connected;
117
+ this.connected = false;
118
+ this.ws = null;
119
+ // Reject all pending requests
120
+ for (const [, pending] of this.pendingRequests) {
121
+ clearTimeout(pending.timeout);
122
+ pending.reject(new Error('Connection closed'));
123
+ }
124
+ this.pendingRequests.clear();
125
+ if (wasConnected) {
126
+ // Don't log to console - would interfere with TUI
127
+ this.emit('disconnected');
128
+ }
129
+ }
130
+ /**
131
+ * Handle incoming response
132
+ */
133
+ handleResponse(response) {
134
+ const pending = this.pendingRequests.get(response.requestId);
135
+ if (pending) {
136
+ clearTimeout(pending.timeout);
137
+ this.pendingRequests.delete(response.requestId);
138
+ pending.resolve(response);
139
+ }
140
+ }
141
+ /**
142
+ * Send diff preview and wait for approval
143
+ * Returns true if approved, false if rejected or timeout
144
+ */
145
+ async requestDiffApproval(payload) {
146
+ if (!this.connected) {
147
+ // Not connected to VS Code, auto-approve (CLI standalone mode)
148
+ return true;
149
+ }
150
+ try {
151
+ const response = await this.sendRequest({
152
+ type: 'diff_preview',
153
+ payload,
154
+ requestId: this.generateRequestId()
155
+ });
156
+ return response.type === 'approved';
157
+ }
158
+ catch {
159
+ // On error, fall back to auto-approve to not block the user
160
+ return true;
161
+ }
162
+ }
163
+ /**
164
+ * Send task completion summary
165
+ */
166
+ async sendTaskComplete(payload) {
167
+ if (!this.connected)
168
+ return;
169
+ try {
170
+ await this.sendRequest({
171
+ type: 'task_complete',
172
+ payload,
173
+ requestId: this.generateRequestId()
174
+ });
175
+ }
176
+ catch {
177
+ // Task complete is fire-and-forget, don't throw
178
+ }
179
+ }
180
+ /**
181
+ * Send status update
182
+ */
183
+ sendStatusUpdate(status) {
184
+ if (!this.connected || !this.ws)
185
+ return;
186
+ const message = {
187
+ type: 'status_update',
188
+ payload: { status },
189
+ requestId: this.generateRequestId()
190
+ };
191
+ try {
192
+ this.ws.send(JSON.stringify(message));
193
+ }
194
+ catch {
195
+ // Status updates are fire-and-forget, silently ignore failures
196
+ }
197
+ }
198
+ /**
199
+ * Send streaming chunk to VS Code extension
200
+ * Used for real-time streaming in the chat panel
201
+ */
202
+ sendStreamChunk(payload) {
203
+ if (!this.connected || !this.ws)
204
+ return;
205
+ const message = {
206
+ type: 'stream_chunk',
207
+ payload,
208
+ requestId: this.generateRequestId()
209
+ };
210
+ try {
211
+ this.ws.send(JSON.stringify(message));
212
+ }
213
+ catch {
214
+ // Stream chunks are fire-and-forget, silently ignore failures
215
+ }
216
+ }
217
+ /**
218
+ * Create a streaming session and return a helper for sending chunks
219
+ */
220
+ createStreamSession() {
221
+ const sessionId = `stream-${Date.now()}-${Math.random().toString(36).slice(2)}`;
222
+ return new StreamSession(this, sessionId);
223
+ }
224
+ /**
225
+ * Send request and wait for response
226
+ */
227
+ sendRequest(message) {
228
+ return new Promise((resolve, reject) => {
229
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
230
+ reject(new Error('Not connected'));
231
+ return;
232
+ }
233
+ const timeout = setTimeout(() => {
234
+ this.pendingRequests.delete(message.requestId);
235
+ // On timeout, auto-approve to not block forever
236
+ resolve({ type: 'approved', requestId: message.requestId });
237
+ }, REQUEST_TIMEOUT);
238
+ this.pendingRequests.set(message.requestId, { resolve, reject, timeout });
239
+ try {
240
+ this.ws.send(JSON.stringify(message));
241
+ }
242
+ catch {
243
+ // Send failed - clean up and reject
244
+ clearTimeout(timeout);
245
+ this.pendingRequests.delete(message.requestId);
246
+ reject(new Error('Failed to send message'));
247
+ }
248
+ });
249
+ }
250
+ /**
251
+ * Generate unique request ID
252
+ */
253
+ generateRequestId() {
254
+ return `req-${Date.now()}-${++this.requestCounter}`;
255
+ }
256
+ /**
257
+ * Read port file to find server port
258
+ */
259
+ readPortFile() {
260
+ try {
261
+ if (!fs.existsSync(IPC_PORT_FILE)) {
262
+ return null;
263
+ }
264
+ const content = fs.readFileSync(IPC_PORT_FILE, 'utf-8');
265
+ const portInfo = JSON.parse(content);
266
+ // Check if the port file is stale (more than 1 hour old)
267
+ const started = new Date(portInfo.started);
268
+ const startedTime = started.getTime();
269
+ // If date is invalid (NaN) or stale, reject the port file
270
+ if (isNaN(startedTime)) {
271
+ // Corrupted date string in port file
272
+ return null;
273
+ }
274
+ const age = Date.now() - startedTime;
275
+ if (age > 60 * 60 * 1000) {
276
+ // Stale port file, extension may have crashed
277
+ return null;
278
+ }
279
+ return portInfo;
280
+ }
281
+ catch {
282
+ // Silently fail - port file may not exist or be corrupted
283
+ return null;
284
+ }
285
+ }
286
+ /**
287
+ * Check if connected to VS Code extension
288
+ */
289
+ isConnected() {
290
+ return this.connected;
291
+ }
292
+ /**
293
+ * Disconnect from server
294
+ */
295
+ disconnect() {
296
+ if (this.ws) {
297
+ this.ws.close();
298
+ this.ws = null;
299
+ }
300
+ this.connected = false;
301
+ this.connecting = false;
302
+ // Clear pending request timeouts to prevent memory leaks
303
+ for (const [, pending] of this.pendingRequests) {
304
+ clearTimeout(pending.timeout);
305
+ }
306
+ this.pendingRequests.clear();
307
+ }
308
+ /**
309
+ * Ping server to check connection
310
+ */
311
+ async ping() {
312
+ if (!this.connected)
313
+ return false;
314
+ try {
315
+ const response = await this.sendRequest({
316
+ type: 'ping',
317
+ payload: null,
318
+ requestId: this.generateRequestId()
319
+ });
320
+ return response.type === 'pong';
321
+ }
322
+ catch {
323
+ return false;
324
+ }
325
+ }
326
+ }
327
+ /**
328
+ * Helper class for sending streaming chunks with a consistent session ID
329
+ */
330
+ export class StreamSession {
331
+ client;
332
+ sessionId;
333
+ constructor(client, sessionId) {
334
+ this.client = client;
335
+ this.sessionId = sessionId;
336
+ }
337
+ /**
338
+ * Send thinking/reasoning content
339
+ */
340
+ sendThinking(content) {
341
+ this.client.sendStreamChunk({
342
+ sessionId: this.sessionId,
343
+ type: 'thinking',
344
+ content
345
+ });
346
+ }
347
+ /**
348
+ * Send response content
349
+ */
350
+ sendContent(content) {
351
+ this.client.sendStreamChunk({
352
+ sessionId: this.sessionId,
353
+ type: 'content',
354
+ content
355
+ });
356
+ }
357
+ /**
358
+ * Send tool call notification
359
+ */
360
+ sendToolCall(id, name, args) {
361
+ this.client.sendStreamChunk({
362
+ sessionId: this.sessionId,
363
+ type: 'tool_call',
364
+ toolCall: { id, name, arguments: args }
365
+ });
366
+ }
367
+ /**
368
+ * Send tool result
369
+ */
370
+ sendToolResult(id, result, isError = false) {
371
+ this.client.sendStreamChunk({
372
+ sessionId: this.sessionId,
373
+ type: 'tool_result',
374
+ toolResult: { id, result, isError }
375
+ });
376
+ }
377
+ /**
378
+ * Send completion signal
379
+ */
380
+ sendDone() {
381
+ this.client.sendStreamChunk({
382
+ sessionId: this.sessionId,
383
+ type: 'done'
384
+ });
385
+ }
386
+ /**
387
+ * Send error
388
+ */
389
+ sendError(error) {
390
+ this.client.sendStreamChunk({
391
+ sessionId: this.sessionId,
392
+ type: 'error',
393
+ error
394
+ });
395
+ }
396
+ }
397
+ // Singleton instance
398
+ let instance = null;
399
+ /**
400
+ * Get or create the VS Code IPC client singleton
401
+ */
402
+ export function getVSCodeIPCClient() {
403
+ if (!instance) {
404
+ instance = new VSCodeIPCClient();
405
+ }
406
+ return instance;
407
+ }
408
+ /**
409
+ * Cleanup the IPC client on process exit
410
+ */
411
+ export function disposeVSCodeIPCClient() {
412
+ if (instance) {
413
+ instance.disconnect();
414
+ instance = null;
415
+ }
416
+ }
417
+ //# sourceMappingURL=vscode-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vscode-client.js","sourceRoot":"","sources":["../../src/ipc/vscode-client.ts"],"names":[],"mappings":"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"}
@@ -265,6 +265,10 @@ export class TextEditorTool {
265
265
  showVSCodeOpen: false,
266
266
  content: diffContent,
267
267
  alwaysConfirm: shouldAlwaysConfirm, // Force confirmation for destructive ops
268
+ // VS Code IPC diff preview fields
269
+ oldContent: content,
270
+ newContent: newContent,
271
+ diffOperation: 'edit',
268
272
  });
269
273
  // Phase 2: Log to audit logger
270
274
  if (autoAcceptConfig && autoAcceptConfig.auditLog?.enabled) {
@@ -341,6 +345,10 @@ export class TextEditorTool {
341
345
  showVSCodeOpen: false,
342
346
  content: diffContent,
343
347
  alwaysConfirm: shouldAlwaysConfirm, // Force confirmation for destructive ops
348
+ // VS Code IPC diff preview fields
349
+ oldContent: '', // Empty for new file
350
+ newContent: content,
351
+ diffOperation: 'create',
344
352
  });
345
353
  // Phase 2: Log to audit logger
346
354
  if (autoAcceptConfig && autoAcceptConfig.auditLog?.enabled) {
@@ -415,6 +423,11 @@ export class TextEditorTool {
415
423
  filename: filePath,
416
424
  showVSCodeOpen: false,
417
425
  content: diffContent,
426
+ oldContent: fileContent,
427
+ newContent: newLines.join("\n"),
428
+ diffOperation: 'edit',
429
+ lineStart: startLine,
430
+ lineEnd: endLine,
418
431
  }, "file");
419
432
  if (!confirmationResult.confirmed) {
420
433
  return {
@@ -487,6 +500,11 @@ export class TextEditorTool {
487
500
  filename: filePath,
488
501
  showVSCodeOpen: false,
489
502
  content: diffContent,
503
+ oldContent: fileContent,
504
+ newContent: newContent,
505
+ diffOperation: 'edit',
506
+ lineStart: insertLine,
507
+ lineEnd: insertLine,
490
508
  });
491
509
  if (!shouldProceed) {
492
510
  return {
@@ -625,6 +643,10 @@ export class TextEditorTool {
625
643
  showVSCodeOpen: false,
626
644
  content: diffContent,
627
645
  alwaysConfirm: shouldAlwaysConfirm,
646
+ // VS Code IPC diff preview fields
647
+ oldContent: originalContent,
648
+ newContent: workingContent,
649
+ diffOperation: 'edit',
628
650
  });
629
651
  // Audit logging
630
652
  if (autoAcceptConfig && autoAcceptConfig.auditLog?.enabled) {