@wonderwhy-er/desktop-commander 0.2.17 → 0.2.18-alpha.0
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 +29 -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
package/dist/server.js
CHANGED
|
@@ -591,12 +591,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
591
591
|
|
|
592
592
|
STATES DETECTED:
|
|
593
593
|
Process waiting for input (shows prompt)
|
|
594
|
-
Process finished execution
|
|
594
|
+
Process finished execution
|
|
595
595
|
Process running (use read_process_output)
|
|
596
|
-
|
|
596
|
+
|
|
597
|
+
PERFORMANCE DEBUGGING (verbose_timing parameter):
|
|
598
|
+
Set verbose_timing: true to get detailed timing information including:
|
|
599
|
+
- Exit reason (early_exit_quick_pattern, early_exit_periodic_check, process_exit, timeout)
|
|
600
|
+
- Total duration and time to first output
|
|
601
|
+
- Complete timeline of all output events with timestamps
|
|
602
|
+
- Which detection mechanism triggered early exit
|
|
603
|
+
Use this to identify missed optimization opportunities and improve detection patterns.
|
|
604
|
+
|
|
597
605
|
ALWAYS USE FOR: Local file analysis, CSV processing, data exploration, system commands
|
|
598
606
|
NEVER USE ANALYSIS TOOL FOR: Local file access (analysis tool is browser-only and WILL FAIL)
|
|
599
|
-
|
|
607
|
+
|
|
600
608
|
${PATH_GUIDANCE}
|
|
601
609
|
${CMD_PREFIX_DESCRIPTION}`,
|
|
602
610
|
inputSchema: zodToJsonSchema(StartProcessArgsSchema),
|
|
@@ -630,7 +638,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
630
638
|
Process waiting for input (ready for interact_with_process)
|
|
631
639
|
Process finished execution
|
|
632
640
|
Timeout reached (may still be running)
|
|
633
|
-
|
|
641
|
+
|
|
642
|
+
PERFORMANCE DEBUGGING (verbose_timing parameter):
|
|
643
|
+
Set verbose_timing: true to get detailed timing information including:
|
|
644
|
+
- Exit reason (early_exit_quick_pattern, early_exit_periodic_check, process_finished, timeout)
|
|
645
|
+
- Total duration and time to first output
|
|
646
|
+
- Complete timeline of all output events with timestamps
|
|
647
|
+
- Which detection mechanism triggered early exit
|
|
648
|
+
Use this to identify when timeouts could be reduced or detection patterns improved.
|
|
649
|
+
|
|
634
650
|
${CMD_PREFIX_DESCRIPTION}`,
|
|
635
651
|
inputSchema: zodToJsonSchema(ReadProcessOutputArgsSchema),
|
|
636
652
|
annotations: {
|
|
@@ -681,12 +697,21 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
681
697
|
- input: Code/command to execute
|
|
682
698
|
- timeout_ms: Max wait (default: 8000ms)
|
|
683
699
|
- wait_for_prompt: Auto-wait for response (default: true)
|
|
684
|
-
|
|
700
|
+
- verbose_timing: Enable detailed performance telemetry (default: false)
|
|
701
|
+
|
|
685
702
|
Returns execution result with status indicators.
|
|
686
|
-
|
|
703
|
+
|
|
704
|
+
PERFORMANCE DEBUGGING (verbose_timing parameter):
|
|
705
|
+
Set verbose_timing: true to get detailed timing information including:
|
|
706
|
+
- Exit reason (early_exit_quick_pattern, early_exit_periodic_check, process_finished, timeout, no_wait)
|
|
707
|
+
- Total duration and time to first output
|
|
708
|
+
- Complete timeline of all output events with timestamps
|
|
709
|
+
- Which detection mechanism triggered early exit
|
|
710
|
+
Use this to identify slow interactions and optimize detection patterns.
|
|
711
|
+
|
|
687
712
|
ALWAYS USE FOR: CSV analysis, JSON processing, file statistics, data visualization prep, ANY local file work
|
|
688
713
|
NEVER USE ANALYSIS TOOL FOR: Local file access (it cannot read files from disk and WILL FAIL)
|
|
689
|
-
|
|
714
|
+
|
|
690
715
|
${CMD_PREFIX_DESCRIPTION}`,
|
|
691
716
|
inputSchema: zodToJsonSchema(InteractWithProcessArgsSchema),
|
|
692
717
|
annotations: {
|
|
@@ -44,7 +44,7 @@ async function initConfigFile() {
|
|
|
44
44
|
// Ensure config directory exists
|
|
45
45
|
const configDir = path.dirname(CONFIG_FILE);
|
|
46
46
|
if (!existsSync(configDir)) {
|
|
47
|
-
|
|
47
|
+
mkdirSync(configDir, { recursive: true });
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// Check if config file exists
|
|
@@ -206,6 +206,28 @@ function detectShell() {
|
|
|
206
206
|
return 'unknown-shell';
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
+
// Function to get the package spec that was used to run this script
|
|
210
|
+
function getPackageSpec() {
|
|
211
|
+
// Check if running via npx - look for the package spec in process.argv
|
|
212
|
+
// e.g., npx @wonderwhy-er/desktop-commander@0.2.18-alpha setup
|
|
213
|
+
const argv = process.argv;
|
|
214
|
+
|
|
215
|
+
// Look for the package name in argv
|
|
216
|
+
for (let i = 0; i < argv.length; i++) {
|
|
217
|
+
const arg = argv[i];
|
|
218
|
+
if (arg.includes('@wonderwhy-er/desktop-commander')) {
|
|
219
|
+
// Extract just the package spec (e.g., @wonderwhy-er/desktop-commander@0.2.18-alpha)
|
|
220
|
+
const match = arg.match(/(@wonderwhy-er\/desktop-commander(@[^\/\s]+)?)/);
|
|
221
|
+
if (match) {
|
|
222
|
+
return match[1];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Fallback to @latest if we can't detect
|
|
228
|
+
return '@wonderwhy-er/desktop-commander@latest';
|
|
229
|
+
}
|
|
230
|
+
|
|
209
231
|
// Function to determine execution context
|
|
210
232
|
function getExecutionContext() {
|
|
211
233
|
// Check if running from npx
|
|
@@ -728,6 +750,7 @@ export default async function setup() {
|
|
|
728
750
|
"DEBUG": "*"
|
|
729
751
|
};
|
|
730
752
|
|
|
753
|
+
const packageSpec = getPackageSpec();
|
|
731
754
|
serverConfig = {
|
|
732
755
|
"command": isWindows ? "node.exe" : "node",
|
|
733
756
|
"args": [
|
|
@@ -735,11 +758,11 @@ export default async function setup() {
|
|
|
735
758
|
isWindows ?
|
|
736
759
|
join(process.env.APPDATA || '', "npm", "npx.cmd").replace(/\\/g, '\\\\') :
|
|
737
760
|
"$(which npx)",
|
|
738
|
-
|
|
761
|
+
packageSpec
|
|
739
762
|
],
|
|
740
763
|
"env": debugEnv
|
|
741
764
|
};
|
|
742
|
-
await trackEvent('npx_setup_config_debug_npx');
|
|
765
|
+
await trackEvent('npx_setup_config_debug_npx', { packageSpec });
|
|
743
766
|
} else {
|
|
744
767
|
// Debug with local installation path
|
|
745
768
|
const indexPath = join(__dirname, 'dist', 'index.js');
|
|
@@ -763,13 +786,14 @@ export default async function setup() {
|
|
|
763
786
|
} else {
|
|
764
787
|
// Standard configuration without debug
|
|
765
788
|
if (isNpx) {
|
|
789
|
+
const packageSpec = getPackageSpec();
|
|
766
790
|
serverConfig = {
|
|
767
791
|
"command": isWindows ? "npx.cmd" : "npx",
|
|
768
792
|
"args": [
|
|
769
|
-
|
|
793
|
+
packageSpec
|
|
770
794
|
]
|
|
771
795
|
};
|
|
772
|
-
await trackEvent('npx_setup_config_standard_npx');
|
|
796
|
+
await trackEvent('npx_setup_config_standard_npx', { packageSpec });
|
|
773
797
|
} else {
|
|
774
798
|
// For local installation, use absolute path to handle Windows properly
|
|
775
799
|
const indexPath = join(__dirname, 'dist', 'index.js');
|
|
@@ -16,7 +16,7 @@ export declare class TerminalManager {
|
|
|
16
16
|
* @returns Whether input was successfully sent
|
|
17
17
|
*/
|
|
18
18
|
sendInputToProcess(pid: number, input: string): boolean;
|
|
19
|
-
executeCommand(command: string, timeoutMs?: number, shell?: string): Promise<CommandExecutionResult>;
|
|
19
|
+
executeCommand(command: string, timeoutMs?: number, shell?: string, collectTiming?: boolean): Promise<CommandExecutionResult>;
|
|
20
20
|
getNewOutput(pid: number): string | null;
|
|
21
21
|
/**
|
|
22
22
|
* Get a session by PID
|
package/dist/terminal-manager.js
CHANGED
|
@@ -33,7 +33,7 @@ export class TerminalManager {
|
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
async executeCommand(command, timeoutMs = DEFAULT_COMMAND_TIMEOUT, shell) {
|
|
36
|
+
async executeCommand(command, timeoutMs = DEFAULT_COMMAND_TIMEOUT, shell, collectTiming = false) {
|
|
37
37
|
// Get the shell from config if not specified
|
|
38
38
|
let shellToUse = shell;
|
|
39
39
|
if (!shellToUse) {
|
|
@@ -81,6 +81,12 @@ export class TerminalManager {
|
|
|
81
81
|
startTime: new Date()
|
|
82
82
|
};
|
|
83
83
|
this.sessions.set(childProcess.pid, session);
|
|
84
|
+
// Timing telemetry
|
|
85
|
+
const startTime = Date.now();
|
|
86
|
+
let firstOutputTime;
|
|
87
|
+
let lastOutputTime;
|
|
88
|
+
const outputEvents = [];
|
|
89
|
+
let exitReason = 'timeout';
|
|
84
90
|
return new Promise((resolve) => {
|
|
85
91
|
let resolved = false;
|
|
86
92
|
let periodicCheck = null;
|
|
@@ -92,15 +98,47 @@ export class TerminalManager {
|
|
|
92
98
|
resolved = true;
|
|
93
99
|
if (periodicCheck)
|
|
94
100
|
clearInterval(periodicCheck);
|
|
101
|
+
// Add timing info if requested
|
|
102
|
+
if (collectTiming) {
|
|
103
|
+
const endTime = Date.now();
|
|
104
|
+
result.timingInfo = {
|
|
105
|
+
startTime,
|
|
106
|
+
endTime,
|
|
107
|
+
totalDurationMs: endTime - startTime,
|
|
108
|
+
exitReason,
|
|
109
|
+
firstOutputTime,
|
|
110
|
+
lastOutputTime,
|
|
111
|
+
timeToFirstOutputMs: firstOutputTime ? firstOutputTime - startTime : undefined,
|
|
112
|
+
outputEvents: outputEvents.length > 0 ? outputEvents : undefined
|
|
113
|
+
};
|
|
114
|
+
}
|
|
95
115
|
resolve(result);
|
|
96
116
|
};
|
|
97
117
|
childProcess.stdout.on('data', (data) => {
|
|
98
118
|
const text = data.toString();
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
if (!firstOutputTime)
|
|
121
|
+
firstOutputTime = now;
|
|
122
|
+
lastOutputTime = now;
|
|
99
123
|
output += text;
|
|
100
124
|
session.lastOutput += text;
|
|
125
|
+
// Record output event if collecting timing
|
|
126
|
+
if (collectTiming) {
|
|
127
|
+
outputEvents.push({
|
|
128
|
+
timestamp: now,
|
|
129
|
+
deltaMs: now - startTime,
|
|
130
|
+
source: 'stdout',
|
|
131
|
+
length: text.length,
|
|
132
|
+
snippet: text.slice(0, 50).replace(/\n/g, '\\n')
|
|
133
|
+
});
|
|
134
|
+
}
|
|
101
135
|
// Immediate check for obvious prompts
|
|
102
136
|
if (quickPromptPatterns.test(text)) {
|
|
103
137
|
session.isBlocked = true;
|
|
138
|
+
exitReason = 'early_exit_quick_pattern';
|
|
139
|
+
if (collectTiming && outputEvents.length > 0) {
|
|
140
|
+
outputEvents[outputEvents.length - 1].matchedPattern = 'quick_pattern';
|
|
141
|
+
}
|
|
104
142
|
resolveOnce({
|
|
105
143
|
pid: childProcess.pid,
|
|
106
144
|
output,
|
|
@@ -110,8 +148,22 @@ export class TerminalManager {
|
|
|
110
148
|
});
|
|
111
149
|
childProcess.stderr.on('data', (data) => {
|
|
112
150
|
const text = data.toString();
|
|
151
|
+
const now = Date.now();
|
|
152
|
+
if (!firstOutputTime)
|
|
153
|
+
firstOutputTime = now;
|
|
154
|
+
lastOutputTime = now;
|
|
113
155
|
output += text;
|
|
114
156
|
session.lastOutput += text;
|
|
157
|
+
// Record output event if collecting timing
|
|
158
|
+
if (collectTiming) {
|
|
159
|
+
outputEvents.push({
|
|
160
|
+
timestamp: now,
|
|
161
|
+
deltaMs: now - startTime,
|
|
162
|
+
source: 'stderr',
|
|
163
|
+
length: text.length,
|
|
164
|
+
snippet: text.slice(0, 50).replace(/\n/g, '\\n')
|
|
165
|
+
});
|
|
166
|
+
}
|
|
115
167
|
});
|
|
116
168
|
// Periodic comprehensive check every 100ms
|
|
117
169
|
periodicCheck = setInterval(() => {
|
|
@@ -119,6 +171,7 @@ export class TerminalManager {
|
|
|
119
171
|
const processState = analyzeProcessState(output, childProcess.pid);
|
|
120
172
|
if (processState.isWaitingForInput) {
|
|
121
173
|
session.isBlocked = true;
|
|
174
|
+
exitReason = 'early_exit_periodic_check';
|
|
122
175
|
resolveOnce({
|
|
123
176
|
pid: childProcess.pid,
|
|
124
177
|
output,
|
|
@@ -130,6 +183,7 @@ export class TerminalManager {
|
|
|
130
183
|
// Timeout fallback
|
|
131
184
|
setTimeout(() => {
|
|
132
185
|
session.isBlocked = true;
|
|
186
|
+
exitReason = 'timeout';
|
|
133
187
|
resolveOnce({
|
|
134
188
|
pid: childProcess.pid,
|
|
135
189
|
output,
|
|
@@ -153,6 +207,7 @@ export class TerminalManager {
|
|
|
153
207
|
}
|
|
154
208
|
this.sessions.delete(childProcess.pid);
|
|
155
209
|
}
|
|
210
|
+
exitReason = 'process_exit';
|
|
156
211
|
resolveOnce({
|
|
157
212
|
pid: childProcess.pid,
|
|
158
213
|
output,
|
package/dist/tools/config.js
CHANGED
|
@@ -2,6 +2,7 @@ import { configManager } from '../config-manager.js';
|
|
|
2
2
|
import { SetConfigValueArgsSchema } from './schemas.js';
|
|
3
3
|
import { getSystemInfo } from '../utils/system-info.js';
|
|
4
4
|
import { currentClient } from '../server.js';
|
|
5
|
+
import { featureFlagManager } from '../utils/feature-flags.js';
|
|
5
6
|
/**
|
|
6
7
|
* Get the entire config including system information
|
|
7
8
|
*/
|
|
@@ -23,6 +24,7 @@ export async function getConfig() {
|
|
|
23
24
|
const configWithSystemInfo = {
|
|
24
25
|
...config,
|
|
25
26
|
currentClient,
|
|
27
|
+
featureFlags: featureFlagManager.getAll(),
|
|
26
28
|
systemInfo: {
|
|
27
29
|
...systemInfo,
|
|
28
30
|
memory
|
package/dist/tools/feedback.js
CHANGED
|
@@ -73,7 +73,7 @@ export async function giveFeedbackToDesktopCommander(params = {}) {
|
|
|
73
73
|
content: [{
|
|
74
74
|
type: "text",
|
|
75
75
|
text: `❌ **Error opening feedback form**: ${error instanceof Error ? error.message : String(error)}\n\n` +
|
|
76
|
-
`You can still access our feedback form directly at: https://tally.so/r/
|
|
76
|
+
`You can still access our feedback form directly at: https://tally.so/r/mKqoKg\n\n` +
|
|
77
77
|
`We appreciate your willingness to provide feedback!`
|
|
78
78
|
}],
|
|
79
79
|
isError: true
|
|
@@ -84,7 +84,7 @@ export async function giveFeedbackToDesktopCommander(params = {}) {
|
|
|
84
84
|
* Build Tally.so URL with pre-filled parameters
|
|
85
85
|
*/
|
|
86
86
|
async function buildTallyUrl(params, stats) {
|
|
87
|
-
const baseUrl = 'https://tally.so/r/
|
|
87
|
+
const baseUrl = 'https://tally.so/r/mKqoKg';
|
|
88
88
|
const urlParams = new URLSearchParams();
|
|
89
89
|
// Only auto-filled hidden fields remain
|
|
90
90
|
urlParams.set('tool_call_count', stats.totalToolCalls.toString());
|