@wonderwhy-er/desktop-commander 0.2.17 ā 0.2.18-alpha.1
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 +1 -4
- package/dist/http-server-auto-tunnel.d.ts +1 -0
- package/dist/http-server-auto-tunnel.js +667 -0
- package/dist/http-server-named-tunnel.d.ts +2 -0
- package/dist/http-server-named-tunnel.js +167 -0
- package/dist/http-server-tunnel.d.ts +2 -0
- package/dist/http-server-tunnel.js +111 -0
- package/dist/http-server.d.ts +2 -0
- package/dist/http-server.js +270 -0
- package/dist/index.js +4 -0
- package/dist/oauth/auth-middleware.d.ts +20 -0
- package/dist/oauth/auth-middleware.js +62 -0
- package/dist/oauth/index.d.ts +3 -0
- package/dist/oauth/index.js +3 -0
- package/dist/oauth/oauth-manager.d.ts +80 -0
- package/dist/oauth/oauth-manager.js +179 -0
- package/dist/oauth/oauth-routes.d.ts +3 -0
- package/dist/oauth/oauth-routes.js +377 -0
- package/dist/server.js +32 -7
- package/dist/setup-claude-server.js +43 -5
- package/dist/terminal-manager.d.ts +1 -1
- package/dist/terminal-manager.js +56 -1
- package/dist/tools/config.js +2 -0
- package/dist/tools/feedback.js +2 -2
- package/dist/tools/improved-process-tools.js +179 -58
- package/dist/tools/schemas.d.ts +9 -0
- package/dist/tools/schemas.js +3 -0
- package/dist/types.d.ts +19 -0
- package/dist/utils/feature-flags.d.ts +43 -0
- package/dist/utils/feature-flags.js +147 -0
- package/dist/utils/toolHistory.js +3 -8
- package/dist/utils/usageTracker.d.ts +4 -0
- package/dist/utils/usageTracker.js +63 -37
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
|
@@ -56,7 +56,7 @@ export async function startProcess(args) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
const result = await terminalManager.executeCommand(parsed.data.command, parsed.data.timeout_ms, shellUsed);
|
|
59
|
+
const result = await terminalManager.executeCommand(parsed.data.command, parsed.data.timeout_ms, shellUsed, parsed.data.verbose_timing || false);
|
|
60
60
|
if (result.pid === -1) {
|
|
61
61
|
return {
|
|
62
62
|
content: [{ type: "text", text: result.output }],
|
|
@@ -75,13 +75,40 @@ export async function startProcess(args) {
|
|
|
75
75
|
else if (result.isBlocked) {
|
|
76
76
|
statusMessage = '\nā³ Process is running. Use read_process_output to get more output.';
|
|
77
77
|
}
|
|
78
|
+
// Add timing information if requested
|
|
79
|
+
let timingMessage = '';
|
|
80
|
+
if (result.timingInfo) {
|
|
81
|
+
timingMessage = formatTimingInfo(result.timingInfo);
|
|
82
|
+
}
|
|
78
83
|
return {
|
|
79
84
|
content: [{
|
|
80
85
|
type: "text",
|
|
81
|
-
text: `Process started with PID ${result.pid} (shell: ${shellUsed})\nInitial output:\n${result.output}${statusMessage}`
|
|
86
|
+
text: `Process started with PID ${result.pid} (shell: ${shellUsed})\nInitial output:\n${result.output}${statusMessage}${timingMessage}`
|
|
82
87
|
}],
|
|
83
88
|
};
|
|
84
89
|
}
|
|
90
|
+
function formatTimingInfo(timing) {
|
|
91
|
+
let msg = '\n\nš Timing Information:\n';
|
|
92
|
+
msg += ` Exit Reason: ${timing.exitReason}\n`;
|
|
93
|
+
msg += ` Total Duration: ${timing.totalDurationMs}ms\n`;
|
|
94
|
+
if (timing.timeToFirstOutputMs !== undefined) {
|
|
95
|
+
msg += ` Time to First Output: ${timing.timeToFirstOutputMs}ms\n`;
|
|
96
|
+
}
|
|
97
|
+
if (timing.firstOutputTime && timing.lastOutputTime) {
|
|
98
|
+
msg += ` Output Window: ${timing.lastOutputTime - timing.firstOutputTime}ms\n`;
|
|
99
|
+
}
|
|
100
|
+
if (timing.outputEvents && timing.outputEvents.length > 0) {
|
|
101
|
+
msg += `\n Output Events (${timing.outputEvents.length} total):\n`;
|
|
102
|
+
timing.outputEvents.forEach((event, idx) => {
|
|
103
|
+
msg += ` [${idx + 1}] +${event.deltaMs}ms | ${event.source} | ${event.length}b`;
|
|
104
|
+
if (event.matchedPattern) {
|
|
105
|
+
msg += ` | šÆ ${event.matchedPattern}`;
|
|
106
|
+
}
|
|
107
|
+
msg += `\n "${event.snippet}"\n`;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return msg;
|
|
111
|
+
}
|
|
85
112
|
/**
|
|
86
113
|
* Read output from a running process (renamed from read_output)
|
|
87
114
|
* Includes early detection of process waiting for input
|
|
@@ -94,7 +121,7 @@ export async function readProcessOutput(args) {
|
|
|
94
121
|
isError: true,
|
|
95
122
|
};
|
|
96
123
|
}
|
|
97
|
-
const { pid, timeout_ms = 5000 } = parsed.data;
|
|
124
|
+
const { pid, timeout_ms = 5000, verbose_timing = false } = parsed.data;
|
|
98
125
|
const session = terminalManager.getSession(pid);
|
|
99
126
|
if (!session) {
|
|
100
127
|
// Check if this is a completed session
|
|
@@ -117,15 +144,35 @@ export async function readProcessOutput(args) {
|
|
|
117
144
|
let timeoutReached = false;
|
|
118
145
|
let earlyExit = false;
|
|
119
146
|
let processState;
|
|
147
|
+
// Timing telemetry
|
|
148
|
+
const startTime = Date.now();
|
|
149
|
+
let firstOutputTime;
|
|
150
|
+
let lastOutputTime;
|
|
151
|
+
const outputEvents = [];
|
|
152
|
+
let exitReason = 'timeout';
|
|
120
153
|
try {
|
|
121
154
|
const outputPromise = new Promise((resolve) => {
|
|
122
155
|
const initialOutput = terminalManager.getNewOutput(pid);
|
|
123
156
|
if (initialOutput && initialOutput.length > 0) {
|
|
157
|
+
const now = Date.now();
|
|
158
|
+
if (!firstOutputTime)
|
|
159
|
+
firstOutputTime = now;
|
|
160
|
+
lastOutputTime = now;
|
|
161
|
+
if (verbose_timing) {
|
|
162
|
+
outputEvents.push({
|
|
163
|
+
timestamp: now,
|
|
164
|
+
deltaMs: now - startTime,
|
|
165
|
+
source: 'initial_poll',
|
|
166
|
+
length: initialOutput.length,
|
|
167
|
+
snippet: initialOutput.slice(0, 50).replace(/\n/g, '\\n')
|
|
168
|
+
});
|
|
169
|
+
}
|
|
124
170
|
// Immediate check on existing output
|
|
125
171
|
const state = analyzeProcessState(initialOutput, pid);
|
|
126
172
|
if (state.isWaitingForInput) {
|
|
127
173
|
earlyExit = true;
|
|
128
174
|
processState = state;
|
|
175
|
+
exitReason = 'early_exit_periodic_check';
|
|
129
176
|
}
|
|
130
177
|
resolve(initialOutput);
|
|
131
178
|
return;
|
|
@@ -147,13 +194,28 @@ export async function readProcessOutput(args) {
|
|
|
147
194
|
resolved = true;
|
|
148
195
|
cleanup();
|
|
149
196
|
timeoutReached = isTimeout;
|
|
197
|
+
if (isTimeout)
|
|
198
|
+
exitReason = 'timeout';
|
|
150
199
|
resolve(value);
|
|
151
200
|
};
|
|
152
201
|
// Monitor for new output with immediate detection
|
|
153
202
|
const session = terminalManager.getSession(pid);
|
|
154
203
|
if (session && session.process && session.process.stdout && session.process.stderr) {
|
|
155
|
-
const immediateDetector = (data) => {
|
|
204
|
+
const immediateDetector = (data, source) => {
|
|
156
205
|
const text = data.toString();
|
|
206
|
+
const now = Date.now();
|
|
207
|
+
if (!firstOutputTime)
|
|
208
|
+
firstOutputTime = now;
|
|
209
|
+
lastOutputTime = now;
|
|
210
|
+
if (verbose_timing) {
|
|
211
|
+
outputEvents.push({
|
|
212
|
+
timestamp: now,
|
|
213
|
+
deltaMs: now - startTime,
|
|
214
|
+
source,
|
|
215
|
+
length: text.length,
|
|
216
|
+
snippet: text.slice(0, 50).replace(/\n/g, '\\n')
|
|
217
|
+
});
|
|
218
|
+
}
|
|
157
219
|
// Immediate check for obvious prompts
|
|
158
220
|
if (quickPromptPatterns.test(text)) {
|
|
159
221
|
const newOutput = terminalManager.getNewOutput(pid) || text;
|
|
@@ -161,21 +223,27 @@ export async function readProcessOutput(args) {
|
|
|
161
223
|
if (state.isWaitingForInput) {
|
|
162
224
|
earlyExit = true;
|
|
163
225
|
processState = state;
|
|
226
|
+
exitReason = 'early_exit_quick_pattern';
|
|
227
|
+
if (verbose_timing && outputEvents.length > 0) {
|
|
228
|
+
outputEvents[outputEvents.length - 1].matchedPattern = 'quick_pattern';
|
|
229
|
+
}
|
|
164
230
|
resolveOnce(newOutput);
|
|
165
231
|
return;
|
|
166
232
|
}
|
|
167
233
|
}
|
|
168
234
|
};
|
|
169
|
-
|
|
170
|
-
|
|
235
|
+
const stdoutDetector = (data) => immediateDetector(data, 'stdout');
|
|
236
|
+
const stderrDetector = (data) => immediateDetector(data, 'stderr');
|
|
237
|
+
session.process.stdout.on('data', stdoutDetector);
|
|
238
|
+
session.process.stderr.on('data', stderrDetector);
|
|
171
239
|
// Cleanup immediate detectors when done
|
|
172
240
|
const originalResolveOnce = resolveOnce;
|
|
173
241
|
const cleanupDetectors = () => {
|
|
174
242
|
if (session.process.stdout) {
|
|
175
|
-
session.process.stdout.
|
|
243
|
+
session.process.stdout.off('data', stdoutDetector);
|
|
176
244
|
}
|
|
177
245
|
if (session.process.stderr) {
|
|
178
|
-
session.process.stderr.
|
|
246
|
+
session.process.stderr.off('data', stderrDetector);
|
|
179
247
|
}
|
|
180
248
|
};
|
|
181
249
|
// Override resolveOnce to include cleanup
|
|
@@ -189,12 +257,29 @@ export async function readProcessOutput(args) {
|
|
|
189
257
|
interval = setInterval(() => {
|
|
190
258
|
const newOutput = terminalManager.getNewOutput(pid);
|
|
191
259
|
if (newOutput && newOutput.length > 0) {
|
|
260
|
+
const now = Date.now();
|
|
261
|
+
if (!firstOutputTime)
|
|
262
|
+
firstOutputTime = now;
|
|
263
|
+
lastOutputTime = now;
|
|
264
|
+
if (verbose_timing) {
|
|
265
|
+
outputEvents.push({
|
|
266
|
+
timestamp: now,
|
|
267
|
+
deltaMs: now - startTime,
|
|
268
|
+
source: 'periodic_poll',
|
|
269
|
+
length: newOutput.length,
|
|
270
|
+
snippet: newOutput.slice(0, 50).replace(/\n/g, '\\n')
|
|
271
|
+
});
|
|
272
|
+
}
|
|
192
273
|
const currentOutput = output + newOutput;
|
|
193
274
|
const state = analyzeProcessState(currentOutput, pid);
|
|
194
275
|
// Early exit if process is clearly waiting for input
|
|
195
276
|
if (state.isWaitingForInput) {
|
|
196
277
|
earlyExit = true;
|
|
197
278
|
processState = state;
|
|
279
|
+
exitReason = 'early_exit_periodic_check';
|
|
280
|
+
if (verbose_timing && outputEvents.length > 0) {
|
|
281
|
+
outputEvents[outputEvents.length - 1].matchedPattern = 'periodic_check';
|
|
282
|
+
}
|
|
198
283
|
resolveOnce(newOutput);
|
|
199
284
|
return;
|
|
200
285
|
}
|
|
@@ -205,9 +290,10 @@ export async function readProcessOutput(args) {
|
|
|
205
290
|
}
|
|
206
291
|
// Process finished
|
|
207
292
|
processState = state;
|
|
293
|
+
exitReason = 'process_finished';
|
|
208
294
|
resolveOnce(newOutput);
|
|
209
295
|
}
|
|
210
|
-
},
|
|
296
|
+
}, 50); // Check every 50ms for faster response
|
|
211
297
|
timeout = setTimeout(() => {
|
|
212
298
|
const finalOutput = terminalManager.getNewOutput(pid) || "";
|
|
213
299
|
resolveOnce(finalOutput, true);
|
|
@@ -237,11 +323,27 @@ export async function readProcessOutput(args) {
|
|
|
237
323
|
else if (timeoutReached) {
|
|
238
324
|
statusMessage = '\nā±ļø Timeout reached - process may still be running';
|
|
239
325
|
}
|
|
326
|
+
// Add timing information if requested
|
|
327
|
+
let timingMessage = '';
|
|
328
|
+
if (verbose_timing) {
|
|
329
|
+
const endTime = Date.now();
|
|
330
|
+
const timingInfo = {
|
|
331
|
+
startTime,
|
|
332
|
+
endTime,
|
|
333
|
+
totalDurationMs: endTime - startTime,
|
|
334
|
+
exitReason,
|
|
335
|
+
firstOutputTime,
|
|
336
|
+
lastOutputTime,
|
|
337
|
+
timeToFirstOutputMs: firstOutputTime ? firstOutputTime - startTime : undefined,
|
|
338
|
+
outputEvents: outputEvents.length > 0 ? outputEvents : undefined
|
|
339
|
+
};
|
|
340
|
+
timingMessage = formatTimingInfo(timingInfo);
|
|
341
|
+
}
|
|
240
342
|
const responseText = output || 'No new output available';
|
|
241
343
|
return {
|
|
242
344
|
content: [{
|
|
243
345
|
type: "text",
|
|
244
|
-
text: `${responseText}${statusMessage}`
|
|
346
|
+
text: `${responseText}${statusMessage}${timingMessage}`
|
|
245
347
|
}],
|
|
246
348
|
};
|
|
247
349
|
}
|
|
@@ -260,7 +362,13 @@ export async function interactWithProcess(args) {
|
|
|
260
362
|
isError: true,
|
|
261
363
|
};
|
|
262
364
|
}
|
|
263
|
-
const { pid, input, timeout_ms = 8000, wait_for_prompt = true } = parsed.data;
|
|
365
|
+
const { pid, input, timeout_ms = 8000, wait_for_prompt = true, verbose_timing = false } = parsed.data;
|
|
366
|
+
// Timing telemetry
|
|
367
|
+
const startTime = Date.now();
|
|
368
|
+
let firstOutputTime;
|
|
369
|
+
let lastOutputTime;
|
|
370
|
+
const outputEvents = [];
|
|
371
|
+
let exitReason = 'timeout';
|
|
264
372
|
try {
|
|
265
373
|
capture('server_interact_with_process', {
|
|
266
374
|
pid: pid,
|
|
@@ -275,10 +383,26 @@ export async function interactWithProcess(args) {
|
|
|
275
383
|
}
|
|
276
384
|
// If not waiting for response, return immediately
|
|
277
385
|
if (!wait_for_prompt) {
|
|
386
|
+
exitReason = 'no_wait';
|
|
387
|
+
let timingMessage = '';
|
|
388
|
+
if (verbose_timing) {
|
|
389
|
+
const endTime = Date.now();
|
|
390
|
+
const timingInfo = {
|
|
391
|
+
startTime,
|
|
392
|
+
endTime,
|
|
393
|
+
totalDurationMs: endTime - startTime,
|
|
394
|
+
exitReason,
|
|
395
|
+
firstOutputTime,
|
|
396
|
+
lastOutputTime,
|
|
397
|
+
timeToFirstOutputMs: undefined,
|
|
398
|
+
outputEvents: undefined
|
|
399
|
+
};
|
|
400
|
+
timingMessage = formatTimingInfo(timingInfo);
|
|
401
|
+
}
|
|
278
402
|
return {
|
|
279
403
|
content: [{
|
|
280
404
|
type: "text",
|
|
281
|
-
text: `ā
Input sent to process ${pid}. Use read_process_output to get the response
|
|
405
|
+
text: `ā
Input sent to process ${pid}. Use read_process_output to get the response.${timingMessage}`
|
|
282
406
|
}],
|
|
283
407
|
};
|
|
284
408
|
}
|
|
@@ -292,7 +416,8 @@ export async function interactWithProcess(args) {
|
|
|
292
416
|
return new Promise((resolve) => {
|
|
293
417
|
let resolved = false;
|
|
294
418
|
let attempts = 0;
|
|
295
|
-
const
|
|
419
|
+
const pollIntervalMs = 50; // Poll every 50ms for faster response
|
|
420
|
+
const maxAttempts = Math.ceil(timeout_ms / pollIntervalMs);
|
|
296
421
|
let interval = null;
|
|
297
422
|
let resolveOnce = () => {
|
|
298
423
|
if (resolved)
|
|
@@ -302,74 +427,51 @@ export async function interactWithProcess(args) {
|
|
|
302
427
|
clearInterval(interval);
|
|
303
428
|
resolve();
|
|
304
429
|
};
|
|
305
|
-
//
|
|
306
|
-
const session = terminalManager.getSession(pid);
|
|
307
|
-
if (session && session.process && session.process.stdout && session.process.stderr) {
|
|
308
|
-
const immediateDetector = (data) => {
|
|
309
|
-
const text = data.toString();
|
|
310
|
-
// Immediate check for obvious prompts
|
|
311
|
-
if (quickPromptPatterns.test(text)) {
|
|
312
|
-
// Get the latest output and analyze
|
|
313
|
-
setTimeout(() => {
|
|
314
|
-
const newOutput = terminalManager.getNewOutput(pid);
|
|
315
|
-
if (newOutput) {
|
|
316
|
-
output += newOutput;
|
|
317
|
-
const state = analyzeProcessState(output, pid);
|
|
318
|
-
if (state.isWaitingForInput) {
|
|
319
|
-
processState = state;
|
|
320
|
-
earlyExit = true;
|
|
321
|
-
resolveOnce();
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}, 50); // Small delay to ensure output is captured
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
session.process.stdout.on('data', immediateDetector);
|
|
328
|
-
session.process.stderr.on('data', immediateDetector);
|
|
329
|
-
// Cleanup when done
|
|
330
|
-
const cleanupDetectors = () => {
|
|
331
|
-
if (session.process.stdout) {
|
|
332
|
-
session.process.stdout.removeListener('data', immediateDetector);
|
|
333
|
-
}
|
|
334
|
-
if (session.process.stderr) {
|
|
335
|
-
session.process.stderr.removeListener('data', immediateDetector);
|
|
336
|
-
}
|
|
337
|
-
};
|
|
338
|
-
// Override resolveOnce to include cleanup
|
|
339
|
-
const originalResolveOnce = resolveOnce;
|
|
340
|
-
const resolveOnceWithCleanup = () => {
|
|
341
|
-
cleanupDetectors();
|
|
342
|
-
originalResolveOnce();
|
|
343
|
-
};
|
|
344
|
-
// Replace the local resolveOnce reference
|
|
345
|
-
resolveOnce = resolveOnceWithCleanup;
|
|
346
|
-
}
|
|
347
|
-
// Periodic check as fallback
|
|
430
|
+
// Fast-polling check - check every 50ms for quick responses
|
|
348
431
|
interval = setInterval(() => {
|
|
349
432
|
if (resolved)
|
|
350
433
|
return;
|
|
351
434
|
const newOutput = terminalManager.getNewOutput(pid);
|
|
352
435
|
if (newOutput && newOutput.length > 0) {
|
|
436
|
+
const now = Date.now();
|
|
437
|
+
if (!firstOutputTime)
|
|
438
|
+
firstOutputTime = now;
|
|
439
|
+
lastOutputTime = now;
|
|
440
|
+
if (verbose_timing) {
|
|
441
|
+
outputEvents.push({
|
|
442
|
+
timestamp: now,
|
|
443
|
+
deltaMs: now - startTime,
|
|
444
|
+
source: 'periodic_poll',
|
|
445
|
+
length: newOutput.length,
|
|
446
|
+
snippet: newOutput.slice(0, 50).replace(/\n/g, '\\n')
|
|
447
|
+
});
|
|
448
|
+
}
|
|
353
449
|
output += newOutput;
|
|
354
450
|
// Analyze current state
|
|
355
451
|
processState = analyzeProcessState(output, pid);
|
|
356
452
|
// Exit early if we detect the process is waiting for input
|
|
357
453
|
if (processState.isWaitingForInput) {
|
|
358
454
|
earlyExit = true;
|
|
455
|
+
exitReason = 'early_exit_periodic_check';
|
|
456
|
+
if (verbose_timing && outputEvents.length > 0) {
|
|
457
|
+
outputEvents[outputEvents.length - 1].matchedPattern = 'periodic_check';
|
|
458
|
+
}
|
|
359
459
|
resolveOnce();
|
|
360
460
|
return;
|
|
361
461
|
}
|
|
362
462
|
// Also exit if process finished
|
|
363
463
|
if (processState.isFinished) {
|
|
464
|
+
exitReason = 'process_finished';
|
|
364
465
|
resolveOnce();
|
|
365
466
|
return;
|
|
366
467
|
}
|
|
367
468
|
}
|
|
368
469
|
attempts++;
|
|
369
470
|
if (attempts >= maxAttempts) {
|
|
471
|
+
exitReason = 'timeout';
|
|
370
472
|
resolveOnce();
|
|
371
473
|
}
|
|
372
|
-
},
|
|
474
|
+
}, pollIntervalMs);
|
|
373
475
|
});
|
|
374
476
|
};
|
|
375
477
|
await waitForResponse();
|
|
@@ -390,11 +492,27 @@ export async function interactWithProcess(args) {
|
|
|
390
492
|
else if (timeoutReached) {
|
|
391
493
|
statusMessage = '\nā±ļø Response may be incomplete (timeout reached)';
|
|
392
494
|
}
|
|
495
|
+
// Add timing information if requested
|
|
496
|
+
let timingMessage = '';
|
|
497
|
+
if (verbose_timing) {
|
|
498
|
+
const endTime = Date.now();
|
|
499
|
+
const timingInfo = {
|
|
500
|
+
startTime,
|
|
501
|
+
endTime,
|
|
502
|
+
totalDurationMs: endTime - startTime,
|
|
503
|
+
exitReason,
|
|
504
|
+
firstOutputTime,
|
|
505
|
+
lastOutputTime,
|
|
506
|
+
timeToFirstOutputMs: firstOutputTime ? firstOutputTime - startTime : undefined,
|
|
507
|
+
outputEvents: outputEvents.length > 0 ? outputEvents : undefined
|
|
508
|
+
};
|
|
509
|
+
timingMessage = formatTimingInfo(timingInfo);
|
|
510
|
+
}
|
|
393
511
|
if (cleanOutput.trim().length === 0 && !timeoutReached) {
|
|
394
512
|
return {
|
|
395
513
|
content: [{
|
|
396
514
|
type: "text",
|
|
397
|
-
text: `ā
Input executed in process ${pid}.\nš (No output produced)${statusMessage}`
|
|
515
|
+
text: `ā
Input executed in process ${pid}.\nš (No output produced)${statusMessage}${timingMessage}`
|
|
398
516
|
}],
|
|
399
517
|
};
|
|
400
518
|
}
|
|
@@ -409,6 +527,9 @@ export async function interactWithProcess(args) {
|
|
|
409
527
|
if (statusMessage) {
|
|
410
528
|
responseText += `\n\n${statusMessage}`;
|
|
411
529
|
}
|
|
530
|
+
if (timingMessage) {
|
|
531
|
+
responseText += timingMessage;
|
|
532
|
+
}
|
|
412
533
|
return {
|
|
413
534
|
content: [{
|
|
414
535
|
type: "text",
|
package/dist/tools/schemas.d.ts
CHANGED
|
@@ -15,24 +15,30 @@ export declare const StartProcessArgsSchema: z.ZodObject<{
|
|
|
15
15
|
command: z.ZodString;
|
|
16
16
|
timeout_ms: z.ZodNumber;
|
|
17
17
|
shell: z.ZodOptional<z.ZodString>;
|
|
18
|
+
verbose_timing: z.ZodOptional<z.ZodBoolean>;
|
|
18
19
|
}, "strip", z.ZodTypeAny, {
|
|
19
20
|
command: string;
|
|
20
21
|
timeout_ms: number;
|
|
21
22
|
shell?: string | undefined;
|
|
23
|
+
verbose_timing?: boolean | undefined;
|
|
22
24
|
}, {
|
|
23
25
|
command: string;
|
|
24
26
|
timeout_ms: number;
|
|
25
27
|
shell?: string | undefined;
|
|
28
|
+
verbose_timing?: boolean | undefined;
|
|
26
29
|
}>;
|
|
27
30
|
export declare const ReadProcessOutputArgsSchema: z.ZodObject<{
|
|
28
31
|
pid: z.ZodNumber;
|
|
29
32
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
verbose_timing: z.ZodOptional<z.ZodBoolean>;
|
|
30
34
|
}, "strip", z.ZodTypeAny, {
|
|
31
35
|
pid: number;
|
|
32
36
|
timeout_ms?: number | undefined;
|
|
37
|
+
verbose_timing?: boolean | undefined;
|
|
33
38
|
}, {
|
|
34
39
|
pid: number;
|
|
35
40
|
timeout_ms?: number | undefined;
|
|
41
|
+
verbose_timing?: boolean | undefined;
|
|
36
42
|
}>;
|
|
37
43
|
export declare const ForceTerminateArgsSchema: z.ZodObject<{
|
|
38
44
|
pid: z.ZodNumber;
|
|
@@ -140,15 +146,18 @@ export declare const InteractWithProcessArgsSchema: z.ZodObject<{
|
|
|
140
146
|
input: z.ZodString;
|
|
141
147
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
142
148
|
wait_for_prompt: z.ZodOptional<z.ZodBoolean>;
|
|
149
|
+
verbose_timing: z.ZodOptional<z.ZodBoolean>;
|
|
143
150
|
}, "strip", z.ZodTypeAny, {
|
|
144
151
|
pid: number;
|
|
145
152
|
input: string;
|
|
146
153
|
timeout_ms?: number | undefined;
|
|
154
|
+
verbose_timing?: boolean | undefined;
|
|
147
155
|
wait_for_prompt?: boolean | undefined;
|
|
148
156
|
}, {
|
|
149
157
|
pid: number;
|
|
150
158
|
input: string;
|
|
151
159
|
timeout_ms?: number | undefined;
|
|
160
|
+
verbose_timing?: boolean | undefined;
|
|
152
161
|
wait_for_prompt?: boolean | undefined;
|
|
153
162
|
}>;
|
|
154
163
|
export declare const GetUsageStatsArgsSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
package/dist/tools/schemas.js
CHANGED
|
@@ -18,10 +18,12 @@ export const StartProcessArgsSchema = z.object({
|
|
|
18
18
|
command: z.string(),
|
|
19
19
|
timeout_ms: z.number(),
|
|
20
20
|
shell: z.string().optional(),
|
|
21
|
+
verbose_timing: z.boolean().optional(),
|
|
21
22
|
});
|
|
22
23
|
export const ReadProcessOutputArgsSchema = z.object({
|
|
23
24
|
pid: z.number(),
|
|
24
25
|
timeout_ms: z.number().optional(),
|
|
26
|
+
verbose_timing: z.boolean().optional(),
|
|
25
27
|
});
|
|
26
28
|
export const ForceTerminateArgsSchema = z.object({
|
|
27
29
|
pid: z.number(),
|
|
@@ -72,6 +74,7 @@ export const InteractWithProcessArgsSchema = z.object({
|
|
|
72
74
|
input: z.string(),
|
|
73
75
|
timeout_ms: z.number().optional(),
|
|
74
76
|
wait_for_prompt: z.boolean().optional(),
|
|
77
|
+
verbose_timing: z.boolean().optional(),
|
|
75
78
|
});
|
|
76
79
|
// Usage stats schema
|
|
77
80
|
export const GetUsageStatsArgsSchema = z.object({});
|
package/dist/types.d.ts
CHANGED
|
@@ -21,6 +21,25 @@ export interface CommandExecutionResult {
|
|
|
21
21
|
pid: number;
|
|
22
22
|
output: string;
|
|
23
23
|
isBlocked: boolean;
|
|
24
|
+
timingInfo?: TimingInfo;
|
|
25
|
+
}
|
|
26
|
+
export interface TimingInfo {
|
|
27
|
+
startTime: number;
|
|
28
|
+
endTime: number;
|
|
29
|
+
totalDurationMs: number;
|
|
30
|
+
exitReason: 'early_exit_quick_pattern' | 'early_exit_periodic_check' | 'process_exit' | 'timeout';
|
|
31
|
+
firstOutputTime?: number;
|
|
32
|
+
lastOutputTime?: number;
|
|
33
|
+
timeToFirstOutputMs?: number;
|
|
34
|
+
outputEvents?: OutputEvent[];
|
|
35
|
+
}
|
|
36
|
+
export interface OutputEvent {
|
|
37
|
+
timestamp: number;
|
|
38
|
+
deltaMs: number;
|
|
39
|
+
source: 'stdout' | 'stderr';
|
|
40
|
+
length: number;
|
|
41
|
+
snippet: string;
|
|
42
|
+
matchedPattern?: string;
|
|
24
43
|
}
|
|
25
44
|
export interface ActiveSession {
|
|
26
45
|
pid: number;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
declare class FeatureFlagManager {
|
|
2
|
+
private flags;
|
|
3
|
+
private lastFetch;
|
|
4
|
+
private cachePath;
|
|
5
|
+
private cacheMaxAge;
|
|
6
|
+
private flagUrl;
|
|
7
|
+
private refreshInterval;
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Initialize - load from cache and start background refresh
|
|
11
|
+
*/
|
|
12
|
+
initialize(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Get a flag value
|
|
15
|
+
*/
|
|
16
|
+
get(flagName: string, defaultValue?: any): any;
|
|
17
|
+
/**
|
|
18
|
+
* Get all flags for debugging
|
|
19
|
+
*/
|
|
20
|
+
getAll(): Record<string, any>;
|
|
21
|
+
/**
|
|
22
|
+
* Manually refresh flags immediately (for testing)
|
|
23
|
+
*/
|
|
24
|
+
refresh(): Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Load flags from local cache
|
|
27
|
+
*/
|
|
28
|
+
private loadFromCache;
|
|
29
|
+
/**
|
|
30
|
+
* Fetch flags from remote URL
|
|
31
|
+
*/
|
|
32
|
+
private fetchFlags;
|
|
33
|
+
/**
|
|
34
|
+
* Save flags to local cache
|
|
35
|
+
*/
|
|
36
|
+
private saveToCache;
|
|
37
|
+
/**
|
|
38
|
+
* Cleanup on shutdown
|
|
39
|
+
*/
|
|
40
|
+
destroy(): void;
|
|
41
|
+
}
|
|
42
|
+
export declare const featureFlagManager: FeatureFlagManager;
|
|
43
|
+
export {};
|