@wonderwhy-er/desktop-commander 0.1.18 → 0.1.19
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/dist/terminal-manager.d.ts +10 -0
- package/dist/terminal-manager.js +31 -6
- package/dist/tools/progress.d.ts +20 -0
- package/dist/tools/progress.js +59 -0
- package/dist/types.d.ts +7 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { CommandExecutionResult, ActiveSession } from './types.js';
|
|
2
|
+
interface CompletedSession {
|
|
3
|
+
pid: number;
|
|
4
|
+
output: string;
|
|
5
|
+
exitCode: number | null;
|
|
6
|
+
startTime: Date;
|
|
7
|
+
endTime: Date;
|
|
8
|
+
}
|
|
2
9
|
export declare class TerminalManager {
|
|
3
10
|
private sessions;
|
|
11
|
+
private completedSessions;
|
|
4
12
|
executeCommand(command: string, timeoutMs?: number): Promise<CommandExecutionResult>;
|
|
5
13
|
getNewOutput(pid: number): string | null;
|
|
6
14
|
forceTerminate(pid: number): boolean;
|
|
7
15
|
listActiveSessions(): ActiveSession[];
|
|
16
|
+
listCompletedSessions(): CompletedSession[];
|
|
8
17
|
}
|
|
9
18
|
export declare const terminalManager: TerminalManager;
|
|
19
|
+
export {};
|
package/dist/terminal-manager.js
CHANGED
|
@@ -3,6 +3,7 @@ import { DEFAULT_COMMAND_TIMEOUT } from './config.js';
|
|
|
3
3
|
export class TerminalManager {
|
|
4
4
|
constructor() {
|
|
5
5
|
this.sessions = new Map();
|
|
6
|
+
this.completedSessions = new Map();
|
|
6
7
|
}
|
|
7
8
|
async executeCommand(command, timeoutMs = DEFAULT_COMMAND_TIMEOUT) {
|
|
8
9
|
const process = spawn(command, [], { shell: true });
|
|
@@ -38,8 +39,21 @@ export class TerminalManager {
|
|
|
38
39
|
isBlocked: true
|
|
39
40
|
});
|
|
40
41
|
}, timeoutMs);
|
|
41
|
-
process.on('exit', () => {
|
|
42
|
+
process.on('exit', (code) => {
|
|
42
43
|
if (process.pid) {
|
|
44
|
+
// Store completed session before removing active session
|
|
45
|
+
this.completedSessions.set(process.pid, {
|
|
46
|
+
pid: process.pid,
|
|
47
|
+
output: output + session.lastOutput, // Combine all output
|
|
48
|
+
exitCode: code,
|
|
49
|
+
startTime: session.startTime,
|
|
50
|
+
endTime: new Date()
|
|
51
|
+
});
|
|
52
|
+
// Keep only last 100 completed sessions
|
|
53
|
+
if (this.completedSessions.size > 100) {
|
|
54
|
+
const oldestKey = Array.from(this.completedSessions.keys())[0];
|
|
55
|
+
this.completedSessions.delete(oldestKey);
|
|
56
|
+
}
|
|
43
57
|
this.sessions.delete(process.pid);
|
|
44
58
|
}
|
|
45
59
|
resolve({
|
|
@@ -51,13 +65,21 @@ export class TerminalManager {
|
|
|
51
65
|
});
|
|
52
66
|
}
|
|
53
67
|
getNewOutput(pid) {
|
|
68
|
+
// First check active sessions
|
|
54
69
|
const session = this.sessions.get(pid);
|
|
55
|
-
if (
|
|
56
|
-
|
|
70
|
+
if (session) {
|
|
71
|
+
const output = session.lastOutput;
|
|
72
|
+
session.lastOutput = '';
|
|
73
|
+
return output;
|
|
74
|
+
}
|
|
75
|
+
// Then check completed sessions
|
|
76
|
+
const completedSession = this.completedSessions.get(pid);
|
|
77
|
+
if (completedSession) {
|
|
78
|
+
// Format completion message with exit code and runtime
|
|
79
|
+
const runtime = (completedSession.endTime.getTime() - completedSession.startTime.getTime()) / 1000;
|
|
80
|
+
return `Process completed with exit code ${completedSession.exitCode}\nRuntime: ${runtime}s\nFinal output:\n${completedSession.output}`;
|
|
57
81
|
}
|
|
58
|
-
|
|
59
|
-
session.lastOutput = '';
|
|
60
|
-
return output;
|
|
82
|
+
return null;
|
|
61
83
|
}
|
|
62
84
|
forceTerminate(pid) {
|
|
63
85
|
const session = this.sessions.get(pid);
|
|
@@ -86,5 +108,8 @@ export class TerminalManager {
|
|
|
86
108
|
runtime: now.getTime() - session.startTime.getTime()
|
|
87
109
|
}));
|
|
88
110
|
}
|
|
111
|
+
listCompletedSessions() {
|
|
112
|
+
return Array.from(this.completedSessions.values());
|
|
113
|
+
}
|
|
89
114
|
}
|
|
90
115
|
export const terminalManager = new TerminalManager();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const LongRunningTaskSchema: z.ZodObject<{
|
|
3
|
+
total_steps: z.ZodDefault<z.ZodNumber>;
|
|
4
|
+
step_duration: z.ZodDefault<z.ZodNumber>;
|
|
5
|
+
should_fail: z.ZodDefault<z.ZodBoolean>;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
total_steps: number;
|
|
8
|
+
step_duration: number;
|
|
9
|
+
should_fail: boolean;
|
|
10
|
+
}, {
|
|
11
|
+
total_steps?: number | undefined;
|
|
12
|
+
step_duration?: number | undefined;
|
|
13
|
+
should_fail?: boolean | undefined;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function executeLongRunning(args: unknown, server: any, progressToken?: string): Promise<{
|
|
16
|
+
content: {
|
|
17
|
+
type: string;
|
|
18
|
+
text: string;
|
|
19
|
+
}[];
|
|
20
|
+
}>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const LongRunningTaskSchema = z.object({
|
|
3
|
+
total_steps: z.number().default(5).describe("Total number of steps to execute"),
|
|
4
|
+
step_duration: z.number().default(1000).describe("Duration of each step in milliseconds"),
|
|
5
|
+
should_fail: z.boolean().default(false).describe("Whether the task should fail midway through"),
|
|
6
|
+
});
|
|
7
|
+
export async function executeLongRunning(args, server, progressToken) {
|
|
8
|
+
const parsed = LongRunningTaskSchema.safeParse(args);
|
|
9
|
+
if (!parsed.success) {
|
|
10
|
+
throw new Error(`Invalid arguments for long_running_task: ${parsed.error}`);
|
|
11
|
+
}
|
|
12
|
+
const { total_steps, step_duration, should_fail } = parsed.data;
|
|
13
|
+
try {
|
|
14
|
+
for (let step = 1; step <= total_steps; step++) {
|
|
15
|
+
// Simulate work
|
|
16
|
+
await new Promise(resolve => setTimeout(resolve, step_duration));
|
|
17
|
+
// Send progress notification if we have a token
|
|
18
|
+
if (progressToken) {
|
|
19
|
+
await server.notification({
|
|
20
|
+
method: "notifications/progress",
|
|
21
|
+
params: {
|
|
22
|
+
progress: step,
|
|
23
|
+
total: total_steps,
|
|
24
|
+
progressToken,
|
|
25
|
+
detail: `Completed step ${step} of ${total_steps}${should_fail && step === Math.floor(total_steps / 2)
|
|
26
|
+
? ' (about to fail)'
|
|
27
|
+
: ''}`
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
// If should_fail is true, fail halfway through
|
|
32
|
+
if (should_fail && step === Math.floor(total_steps / 2)) {
|
|
33
|
+
throw new Error("Task failed halfway through as requested");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
content: [{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: `Long running task completed successfully after ${total_steps} steps`
|
|
40
|
+
}]
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
// Send error notification if we have a token
|
|
45
|
+
if (progressToken) {
|
|
46
|
+
await server.notification({
|
|
47
|
+
method: "notifications/progress",
|
|
48
|
+
params: {
|
|
49
|
+
progress: Math.floor(total_steps / 2),
|
|
50
|
+
total: total_steps,
|
|
51
|
+
progressToken,
|
|
52
|
+
detail: error instanceof Error ? error.message : 'Unknown error',
|
|
53
|
+
error: true
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
package/dist/types.d.ts
CHANGED
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.19";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.1.
|
|
1
|
+
export const VERSION = '0.1.19';
|