winhelm-mcp 1.1.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/CHANGELOG.md +96 -0
- package/LICENSE +21 -0
- package/README.md +646 -0
- package/dist/config/config-manager.d.ts +50 -0
- package/dist/config/config-manager.d.ts.map +1 -0
- package/dist/config/config-manager.js +300 -0
- package/dist/config/config-manager.js.map +1 -0
- package/dist/config/default-config.d.ts +4 -0
- package/dist/config/default-config.d.ts.map +1 -0
- package/dist/config/default-config.js +48 -0
- package/dist/config/default-config.js.map +1 -0
- package/dist/config/profiles.d.ts +16 -0
- package/dist/config/profiles.d.ts.map +1 -0
- package/dist/config/profiles.js +208 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/engine/filesystem.d.ts +52 -0
- package/dist/engine/filesystem.d.ts.map +1 -0
- package/dist/engine/filesystem.js +499 -0
- package/dist/engine/filesystem.js.map +1 -0
- package/dist/engine/http-client.d.ts +10 -0
- package/dist/engine/http-client.d.ts.map +1 -0
- package/dist/engine/http-client.js +93 -0
- package/dist/engine/http-client.js.map +1 -0
- package/dist/engine/pdf-generator.d.ts +15 -0
- package/dist/engine/pdf-generator.d.ts.map +1 -0
- package/dist/engine/pdf-generator.js +325 -0
- package/dist/engine/pdf-generator.js.map +1 -0
- package/dist/engine/powershell-runner.d.ts +23 -0
- package/dist/engine/powershell-runner.d.ts.map +1 -0
- package/dist/engine/powershell-runner.js +148 -0
- package/dist/engine/powershell-runner.js.map +1 -0
- package/dist/engine/ripgrep.d.ts +20 -0
- package/dist/engine/ripgrep.d.ts.map +1 -0
- package/dist/engine/ripgrep.js +173 -0
- package/dist/engine/ripgrep.js.map +1 -0
- package/dist/engine/system.d.ts +67 -0
- package/dist/engine/system.d.ts.map +1 -0
- package/dist/engine/system.js +558 -0
- package/dist/engine/system.js.map +1 -0
- package/dist/engine/task-manager.d.ts +66 -0
- package/dist/engine/task-manager.d.ts.map +1 -0
- package/dist/engine/task-manager.js +203 -0
- package/dist/engine/task-manager.js.map +1 -0
- package/dist/gateway/dashboard-html.d.ts +7 -0
- package/dist/gateway/dashboard-html.d.ts.map +1 -0
- package/dist/gateway/dashboard-html.js +624 -0
- package/dist/gateway/dashboard-html.js.map +1 -0
- package/dist/gateway/preview-html.d.ts +5 -0
- package/dist/gateway/preview-html.d.ts.map +1 -0
- package/dist/gateway/preview-html.js +351 -0
- package/dist/gateway/preview-html.js.map +1 -0
- package/dist/gateway/rate-limiter.d.ts +8 -0
- package/dist/gateway/rate-limiter.d.ts.map +1 -0
- package/dist/gateway/rate-limiter.js +51 -0
- package/dist/gateway/rate-limiter.js.map +1 -0
- package/dist/gateway/server.d.ts +18 -0
- package/dist/gateway/server.d.ts.map +1 -0
- package/dist/gateway/server.js +337 -0
- package/dist/gateway/server.js.map +1 -0
- package/dist/gateway/sse-gateway.d.ts +43 -0
- package/dist/gateway/sse-gateway.d.ts.map +1 -0
- package/dist/gateway/sse-gateway.js +161 -0
- package/dist/gateway/sse-gateway.js.map +1 -0
- package/dist/gateway/streamable-gateway.d.ts +39 -0
- package/dist/gateway/streamable-gateway.d.ts.map +1 -0
- package/dist/gateway/streamable-gateway.js +176 -0
- package/dist/gateway/streamable-gateway.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +164 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/desktop-tools.d.ts +3 -0
- package/dist/tools/desktop-tools.d.ts.map +1 -0
- package/dist/tools/desktop-tools.js +280 -0
- package/dist/tools/desktop-tools.js.map +1 -0
- package/dist/tools/file-tools.d.ts +3 -0
- package/dist/tools/file-tools.d.ts.map +1 -0
- package/dist/tools/file-tools.js +433 -0
- package/dist/tools/file-tools.js.map +1 -0
- package/dist/tools/index.d.ts +12 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +16 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/network-tools.d.ts +3 -0
- package/dist/tools/network-tools.d.ts.map +1 -0
- package/dist/tools/network-tools.js +108 -0
- package/dist/tools/network-tools.js.map +1 -0
- package/dist/tools/registry.d.ts +50 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +54 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/terminal-tools.d.ts +3 -0
- package/dist/tools/terminal-tools.d.ts.map +1 -0
- package/dist/tools/terminal-tools.js +152 -0
- package/dist/tools/terminal-tools.js.map +1 -0
- package/dist/tools/tool-wrapper.d.ts +7 -0
- package/dist/tools/tool-wrapper.d.ts.map +1 -0
- package/dist/tools/tool-wrapper.js +47 -0
- package/dist/tools/tool-wrapper.js.map +1 -0
- package/dist/types/index.d.ts +261 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/file-logger.d.ts +24 -0
- package/dist/utils/file-logger.d.ts.map +1 -0
- package/dist/utils/file-logger.js +117 -0
- package/dist/utils/file-logger.js.map +1 -0
- package/dist/utils/logger.d.ts +51 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +189 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/sanitizer.d.ts +13 -0
- package/dist/utils/sanitizer.d.ts.map +1 -0
- package/dist/utils/sanitizer.js +60 -0
- package/dist/utils/sanitizer.js.map +1 -0
- package/docs/EXAMPLES.md +171 -0
- package/docs/PROFILES.md +423 -0
- package/docs/SECURITY.md +190 -0
- package/docs/TOOLS.md +366 -0
- package/manifest.json +74 -0
- package/package.json +89 -0
- package/scripts/build-exe.ps1 +37 -0
- package/scripts/manage-service.ps1 +112 -0
- package/server.json +23 -0
- package/winhelm.config.example.json +30 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { sanitizeText } from "./sanitizer.js";
|
|
5
|
+
export class FileLogger {
|
|
6
|
+
static instance = null;
|
|
7
|
+
logDir;
|
|
8
|
+
maxRetentionDays = 7;
|
|
9
|
+
writeQueue = Promise.resolve();
|
|
10
|
+
constructor() {
|
|
11
|
+
this.logDir = path.resolve(process.cwd(), "logs");
|
|
12
|
+
}
|
|
13
|
+
static getInstance() {
|
|
14
|
+
if (!FileLogger.instance) {
|
|
15
|
+
FileLogger.instance = new FileLogger();
|
|
16
|
+
}
|
|
17
|
+
return FileLogger.instance;
|
|
18
|
+
}
|
|
19
|
+
getTodayLogFileName() {
|
|
20
|
+
const d = new Date();
|
|
21
|
+
const yyyy = d.getFullYear();
|
|
22
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
23
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
24
|
+
return `winhelm-${yyyy}-${mm}-${dd}.log`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Append log entry to persistent log file asynchronously
|
|
28
|
+
*/
|
|
29
|
+
log(entry) {
|
|
30
|
+
// Chain writes to guarantee sequential, non-corrupting file writes
|
|
31
|
+
this.writeQueue = this.writeQueue
|
|
32
|
+
.then(async () => {
|
|
33
|
+
if (!existsSync(this.logDir)) {
|
|
34
|
+
await fs.mkdir(this.logDir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
const fileName = this.getTodayLogFileName();
|
|
37
|
+
const filePath = path.join(this.logDir, fileName);
|
|
38
|
+
const sanitizedTitle = sanitizeText(entry.title);
|
|
39
|
+
const sanitizedDetail = entry.detail ? sanitizeText(entry.detail) : "";
|
|
40
|
+
const sanitizedEntry = {
|
|
41
|
+
...entry,
|
|
42
|
+
title: sanitizedTitle,
|
|
43
|
+
detail: sanitizedDetail,
|
|
44
|
+
};
|
|
45
|
+
const line = JSON.stringify(sanitizedEntry) + "\n";
|
|
46
|
+
await fs.appendFile(filePath, line, "utf-8");
|
|
47
|
+
// Check if rotation or cleanup needed occasionally
|
|
48
|
+
if (Math.random() < 0.05) {
|
|
49
|
+
await this.cleanOldLogs();
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
.catch((err) => {
|
|
53
|
+
// Never throw from file logger to prevent crashing the server
|
|
54
|
+
console.error("[FileLogger] Error writing log file:", err.message);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Remove log files older than maxRetentionDays
|
|
59
|
+
*/
|
|
60
|
+
async cleanOldLogs() {
|
|
61
|
+
try {
|
|
62
|
+
if (!existsSync(this.logDir))
|
|
63
|
+
return;
|
|
64
|
+
const files = await fs.readdir(this.logDir);
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
const maxAgeMs = this.maxRetentionDays * 24 * 60 * 60 * 1000;
|
|
67
|
+
for (const file of files) {
|
|
68
|
+
if (file.endsWith(".log")) {
|
|
69
|
+
const fullPath = path.join(this.logDir, file);
|
|
70
|
+
const stat = await fs.stat(fullPath);
|
|
71
|
+
if (now - stat.mtimeMs > maxAgeMs) {
|
|
72
|
+
await fs.unlink(fullPath);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// ignore cleanup errors
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Export audit logs in JSON or CSV format
|
|
83
|
+
*/
|
|
84
|
+
async exportLogs(format = "json") {
|
|
85
|
+
const todayFile = path.join(this.logDir, this.getTodayLogFileName());
|
|
86
|
+
let rawContent = "";
|
|
87
|
+
if (existsSync(todayFile)) {
|
|
88
|
+
rawContent = await fs.readFile(todayFile, "utf-8");
|
|
89
|
+
}
|
|
90
|
+
const lines = rawContent.split(/\r?\n/).filter(Boolean);
|
|
91
|
+
const entries = [];
|
|
92
|
+
for (const line of lines) {
|
|
93
|
+
try {
|
|
94
|
+
entries.push(JSON.parse(line));
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// ignore parse error on bad line
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (format === "csv") {
|
|
101
|
+
const headers = ["Timestamp", "Type", "Level", "Title", "Status", "DurationMs", "Detail"];
|
|
102
|
+
const rows = entries.map((e) => [
|
|
103
|
+
`"${e.timestamp}"`,
|
|
104
|
+
`"${e.type}"`,
|
|
105
|
+
`"${e.level}"`,
|
|
106
|
+
`"${(e.title || "").replace(/"/g, '""')}"`,
|
|
107
|
+
`"${e.status ?? ""}"`,
|
|
108
|
+
e.durationMs ?? 0,
|
|
109
|
+
`"${(e.detail || "").replace(/"/g, '""')}"`,
|
|
110
|
+
]);
|
|
111
|
+
return [headers.join(","), ...rows.map((r) => r.join(","))].join("\n");
|
|
112
|
+
}
|
|
113
|
+
return JSON.stringify(entries, null, 2);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export const fileLogger = FileLogger.getInstance();
|
|
117
|
+
//# sourceMappingURL=file-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-logger.js","sourceRoot":"","sources":["../../src/utils/file-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface LogEntry {
|
|
2
|
+
id: string;
|
|
3
|
+
timestamp: string;
|
|
4
|
+
type: "tool" | "req" | "security" | "system" | "error";
|
|
5
|
+
level: "info" | "warn" | "error" | "success";
|
|
6
|
+
title: string;
|
|
7
|
+
detail?: string;
|
|
8
|
+
durationMs?: number;
|
|
9
|
+
status?: string | number;
|
|
10
|
+
}
|
|
11
|
+
export declare class Logger {
|
|
12
|
+
private static instance;
|
|
13
|
+
private logs;
|
|
14
|
+
private readonly maxLogs;
|
|
15
|
+
private constructor();
|
|
16
|
+
static getInstance(): Logger;
|
|
17
|
+
private getFormattedTime;
|
|
18
|
+
private addLog;
|
|
19
|
+
getRecentLogs(limit?: number): LogEntry[];
|
|
20
|
+
clearLogs(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Log incoming & completed HTTP requests
|
|
23
|
+
*/
|
|
24
|
+
req(method: string, url: string, statusCode: number, durationMs: number, ip?: string, sessionId?: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Log tool invocation start
|
|
27
|
+
*/
|
|
28
|
+
toolStart(name: string, args: Record<string, any>): void;
|
|
29
|
+
/**
|
|
30
|
+
* Log tool invocation success
|
|
31
|
+
*/
|
|
32
|
+
toolDone(name: string, durationMs: number, summary?: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Log tool invocation failure
|
|
35
|
+
*/
|
|
36
|
+
toolFail(name: string, durationMs: number, error: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* Log security events (e.g. command blocked, path denied, unauthorized)
|
|
39
|
+
*/
|
|
40
|
+
security(message: string, detail?: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* General info message
|
|
43
|
+
*/
|
|
44
|
+
info(message: string, detail?: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Error message
|
|
47
|
+
*/
|
|
48
|
+
error(message: string, detail?: string): void;
|
|
49
|
+
}
|
|
50
|
+
export declare const logger: Logger;
|
|
51
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC;IACvD,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAkBD,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAuB;IAC9C,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAO;IAE/B,OAAO,eAAiB;IAExB,OAAc,WAAW,IAAI,MAAM,CAKlC;IAED,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,MAAM;IAqBP,aAAa,CAAC,KAAK,SAAM,GAAG,QAAQ,EAAE,CAE5C;IAEM,SAAS,IAAI,IAAI,CAEvB;IAED;;OAEG;IACI,GAAG,CACR,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,EAAE,SAAM,EACR,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CA0BN;IAED;;OAEG;IACI,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAwB9D;IAED;;OAEG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAgBxE;IAED;;OAEG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAcrE;IAED;;OAEG;IACI,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAatD;IAED;;OAEG;IACI,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAYlD;IAED;;OAEG;IACI,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAYnD;CACF;AAED,eAAO,MAAM,MAAM,QAAuB,CAAC"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { sanitizeText } from "./sanitizer.js";
|
|
3
|
+
import { fileLogger } from "./file-logger.js";
|
|
4
|
+
// ANSI Escape Codes for Terminal Colors
|
|
5
|
+
const C = {
|
|
6
|
+
reset: "\x1b[0m",
|
|
7
|
+
bold: "\x1b[1m",
|
|
8
|
+
dim: "\x1b[2m",
|
|
9
|
+
green: "\x1b[32m",
|
|
10
|
+
yellow: "\x1b[33m",
|
|
11
|
+
blue: "\x1b[34m",
|
|
12
|
+
magenta: "\x1b[35m",
|
|
13
|
+
cyan: "\x1b[36m",
|
|
14
|
+
red: "\x1b[31m",
|
|
15
|
+
gray: "\x1b[90m",
|
|
16
|
+
bgRed: "\x1b[41m",
|
|
17
|
+
bgGreen: "\x1b[42m",
|
|
18
|
+
};
|
|
19
|
+
export class Logger {
|
|
20
|
+
static instance = null;
|
|
21
|
+
logs = [];
|
|
22
|
+
maxLogs = 200;
|
|
23
|
+
constructor() { }
|
|
24
|
+
static getInstance() {
|
|
25
|
+
if (!Logger.instance) {
|
|
26
|
+
Logger.instance = new Logger();
|
|
27
|
+
}
|
|
28
|
+
return Logger.instance;
|
|
29
|
+
}
|
|
30
|
+
getFormattedTime() {
|
|
31
|
+
const d = new Date();
|
|
32
|
+
const pad = (n, s = 2) => String(n).padStart(s, "0");
|
|
33
|
+
const h = pad(d.getHours());
|
|
34
|
+
const m = pad(d.getMinutes());
|
|
35
|
+
const s = pad(d.getSeconds());
|
|
36
|
+
const ms = pad(d.getMilliseconds(), 3);
|
|
37
|
+
return `${h}:${m}:${s}.${ms}`;
|
|
38
|
+
}
|
|
39
|
+
addLog(entry) {
|
|
40
|
+
const cleanTitle = sanitizeText(entry.title);
|
|
41
|
+
const cleanDetail = entry.detail ? sanitizeText(entry.detail) : undefined;
|
|
42
|
+
const fullEntry = {
|
|
43
|
+
id: randomUUID(),
|
|
44
|
+
timestamp: new Date().toISOString(),
|
|
45
|
+
...entry,
|
|
46
|
+
title: cleanTitle,
|
|
47
|
+
detail: cleanDetail,
|
|
48
|
+
};
|
|
49
|
+
this.logs.unshift(fullEntry);
|
|
50
|
+
if (this.logs.length > this.maxLogs) {
|
|
51
|
+
this.logs.pop();
|
|
52
|
+
}
|
|
53
|
+
// Persist to rotating disk log
|
|
54
|
+
fileLogger.log(fullEntry);
|
|
55
|
+
}
|
|
56
|
+
getRecentLogs(limit = 100) {
|
|
57
|
+
return this.logs.slice(0, limit);
|
|
58
|
+
}
|
|
59
|
+
clearLogs() {
|
|
60
|
+
this.logs = [];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Log incoming & completed HTTP requests
|
|
64
|
+
*/
|
|
65
|
+
req(method, url, statusCode, durationMs, ip = "-", sessionId) {
|
|
66
|
+
const time = this.getFormattedTime();
|
|
67
|
+
let statusColor = C.green;
|
|
68
|
+
let level = "info";
|
|
69
|
+
if (statusCode >= 500) {
|
|
70
|
+
statusColor = C.red;
|
|
71
|
+
level = "error";
|
|
72
|
+
}
|
|
73
|
+
else if (statusCode >= 400) {
|
|
74
|
+
statusColor = C.yellow;
|
|
75
|
+
level = "warn";
|
|
76
|
+
}
|
|
77
|
+
const sessTag = sessionId ? `${C.gray}[sess:${sessionId.slice(0, 8)}]${C.reset} ` : "";
|
|
78
|
+
const cleanUrl = sanitizeText(url);
|
|
79
|
+
const line = `${C.gray}[${time}]${C.reset} ${C.cyan}[HTTP]${C.reset} ${C.bold}${method}${C.reset} ${cleanUrl} ${statusColor}${statusCode}${C.reset} ${C.dim}(${durationMs}ms)${C.reset} ${sessTag}${C.gray}${ip}${C.reset}`;
|
|
80
|
+
console.log(line);
|
|
81
|
+
this.addLog({
|
|
82
|
+
type: "req",
|
|
83
|
+
level,
|
|
84
|
+
title: `${method} ${url}`,
|
|
85
|
+
detail: `IP: ${ip}${sessionId ? ` | Session: ${sessionId}` : ""}`,
|
|
86
|
+
durationMs,
|
|
87
|
+
status: statusCode,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Log tool invocation start
|
|
92
|
+
*/
|
|
93
|
+
toolStart(name, args) {
|
|
94
|
+
const time = this.getFormattedTime();
|
|
95
|
+
// Sanitize parameters so long content/base64 doesn't spam console
|
|
96
|
+
const cleanArgs = {};
|
|
97
|
+
for (const [key, val] of Object.entries(args || {})) {
|
|
98
|
+
if (typeof val === "string" && val.length > 80) {
|
|
99
|
+
cleanArgs[key] = val.slice(0, 77) + "...";
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
cleanArgs[key] = val;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const preview = sanitizeText(JSON.stringify(cleanArgs));
|
|
106
|
+
console.log(`${C.gray}[${time}]${C.reset} ${C.magenta}[TOOL-START]${C.reset} ${C.bold}${name}${C.reset} ${C.dim}${preview}${C.reset}`);
|
|
107
|
+
this.addLog({
|
|
108
|
+
type: "tool",
|
|
109
|
+
level: "info",
|
|
110
|
+
title: `tool_call: ${name}`,
|
|
111
|
+
detail: preview,
|
|
112
|
+
status: "RUNNING",
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Log tool invocation success
|
|
117
|
+
*/
|
|
118
|
+
toolDone(name, durationMs, summary) {
|
|
119
|
+
const time = this.getFormattedTime();
|
|
120
|
+
const cleanSummary = summary ? sanitizeText(summary) : undefined;
|
|
121
|
+
const sum = cleanSummary ? ` ${C.dim}-> ${cleanSummary.slice(0, 90)}${cleanSummary.length > 90 ? "..." : ""}${C.reset}` : "";
|
|
122
|
+
console.log(`${C.gray}[${time}]${C.reset} ${C.green}[TOOL-DONE]${C.reset} ${C.bold}${name}${C.reset} ${C.green}✔ OK${C.reset} ${C.dim}(${durationMs}ms)${C.reset}${sum}`);
|
|
123
|
+
this.addLog({
|
|
124
|
+
type: "tool",
|
|
125
|
+
level: "success",
|
|
126
|
+
title: `tool_done: ${name}`,
|
|
127
|
+
detail: cleanSummary ? cleanSummary.slice(0, 150) : "Success",
|
|
128
|
+
durationMs,
|
|
129
|
+
status: "SUCCESS",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Log tool invocation failure
|
|
134
|
+
*/
|
|
135
|
+
toolFail(name, durationMs, error) {
|
|
136
|
+
const time = this.getFormattedTime();
|
|
137
|
+
console.log(`${C.gray}[${time}]${C.reset} ${C.red}[TOOL-FAIL]${C.reset} ${C.bold}${name}${C.reset} ${C.red}✖ ERROR${C.reset} ${C.dim}(${durationMs}ms)${C.reset} ${C.red}${error}${C.reset}`);
|
|
138
|
+
this.addLog({
|
|
139
|
+
type: "tool",
|
|
140
|
+
level: "error",
|
|
141
|
+
title: `tool_fail: ${name}`,
|
|
142
|
+
detail: error,
|
|
143
|
+
durationMs,
|
|
144
|
+
status: "FAILED",
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Log security events (e.g. command blocked, path denied, unauthorized)
|
|
149
|
+
*/
|
|
150
|
+
security(message, detail) {
|
|
151
|
+
const time = this.getFormattedTime();
|
|
152
|
+
console.warn(`${C.gray}[${time}]${C.reset} ${C.yellow}${C.bold}[SECURITY]${C.reset} ${C.yellow}⚠️ ${message}${C.reset}${detail ? ` ${C.dim}(${detail})${C.reset}` : ""}`);
|
|
153
|
+
this.addLog({
|
|
154
|
+
type: "security",
|
|
155
|
+
level: "warn",
|
|
156
|
+
title: message,
|
|
157
|
+
detail,
|
|
158
|
+
status: "BLOCKED",
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* General info message
|
|
163
|
+
*/
|
|
164
|
+
info(message, detail) {
|
|
165
|
+
const time = this.getFormattedTime();
|
|
166
|
+
console.log(`${C.gray}[${time}]${C.reset} ${C.blue}[INFO]${C.reset} ${message}${detail ? ` ${C.dim}${detail}${C.reset}` : ""}`);
|
|
167
|
+
this.addLog({
|
|
168
|
+
type: "system",
|
|
169
|
+
level: "info",
|
|
170
|
+
title: message,
|
|
171
|
+
detail,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Error message
|
|
176
|
+
*/
|
|
177
|
+
error(message, detail) {
|
|
178
|
+
const time = this.getFormattedTime();
|
|
179
|
+
console.error(`${C.gray}[${time}]${C.reset} ${C.red}[ERROR]${C.reset} ${C.bold}${message}${C.reset}${detail ? ` ${C.dim}${detail}${C.reset}` : ""}`);
|
|
180
|
+
this.addLog({
|
|
181
|
+
type: "error",
|
|
182
|
+
level: "error",
|
|
183
|
+
title: message,
|
|
184
|
+
detail,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
export const logger = Logger.getInstance();
|
|
189
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret & Credential Redaction Utility for WinCommander
|
|
3
|
+
* Automatically detects and masks sensitive keys, tokens, and credentials in logs and outputs.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Mask sensitive credentials within a text string
|
|
7
|
+
*/
|
|
8
|
+
export declare function sanitizeText(text: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Deep-sanitize objects, payloads, or argument maps
|
|
11
|
+
*/
|
|
12
|
+
export declare function sanitizeObject<T>(obj: T): T;
|
|
13
|
+
//# sourceMappingURL=sanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../src/utils/sanitizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsBjD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAiC3C"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret & Credential Redaction Utility for WinCommander
|
|
3
|
+
* Automatically detects and masks sensitive keys, tokens, and credentials in logs and outputs.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Mask sensitive credentials within a text string
|
|
7
|
+
*/
|
|
8
|
+
export function sanitizeText(text) {
|
|
9
|
+
if (!text || typeof text !== "string")
|
|
10
|
+
return text;
|
|
11
|
+
return text
|
|
12
|
+
// Bearer tokens
|
|
13
|
+
.replace(/(bearer\s+)([a-zA-Z0-9_\-\.]{8,})/gi, (_m, p, s) => `${p}${"*".repeat(Math.min(s.length, 12))}`)
|
|
14
|
+
// AWS Access Key ID (AKIA...)
|
|
15
|
+
.replace(/\b(AKIA)([0-9A-Z]{16})\b/g, (_m, p, s) => `${p}${"*".repeat(Math.min(s.length, 12))}`)
|
|
16
|
+
// API keys (sk-..., ghp_...)
|
|
17
|
+
.replace(/(sk-[a-zA-Z0-9_\-]{4})([a-zA-Z0-9_\-]+)/gi, (_m, p) => `${p}${"*".repeat(12)}`)
|
|
18
|
+
.replace(/(gh[pousr]_[a-zA-Z0-9]{4})([a-zA-Z0-9]+)/gi, (_m, p) => `${p}${"*".repeat(12)}`)
|
|
19
|
+
// JSON quoted keys like "authToken": "...", "password": "...", "x-api-key": "..."
|
|
20
|
+
.replace(/((\\")|["'])([\w\-]*?(?:token|password|passwd|secret|api[_-]?key|auth(?!(?:or|ors)\b))[\w\-]*?)\1(\s*:\s*)((\\")|["'])([^"'\r\n]+?)\5/gi, (_m, q1, _g2, k, colon, q2, _g5, v) => `${q1}${k}${q1}${colon}${q2}${"*".repeat(Math.min(v.length, 12))}${q2}`)
|
|
21
|
+
// Query/unquoted fields like password=xyz, token=xyz
|
|
22
|
+
.replace(/((?:token|api[_-]?key|secret|password|passwd|auth(?!(?:or|ors)\b))\s*[:=]\s*["']?)([^"'&\s]{4,})(["']?)/gi, (_m, p, s, suf) => `${p}${"*".repeat(Math.min(s.length, 12))}${suf}`)
|
|
23
|
+
// CLI flags e.g. --auth xyz
|
|
24
|
+
.replace(/(--(?:auth|token|password|secret)\s+)([^\s]{4,})/gi, (_m, p, s) => `${p}${"*".repeat(Math.min(s.length, 12))}`)
|
|
25
|
+
// Basic Auth in URLs
|
|
26
|
+
.replace(/(https?:\/\/[^:]+:)([^@]+)(@)/gi, (_m, p, _s, at) => `${p}********${at}`);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Deep-sanitize objects, payloads, or argument maps
|
|
30
|
+
*/
|
|
31
|
+
export function sanitizeObject(obj) {
|
|
32
|
+
if (obj === null || obj === undefined)
|
|
33
|
+
return obj;
|
|
34
|
+
if (typeof obj === "string") {
|
|
35
|
+
return sanitizeText(obj);
|
|
36
|
+
}
|
|
37
|
+
if (Array.isArray(obj)) {
|
|
38
|
+
return obj.map((item) => sanitizeObject(item));
|
|
39
|
+
}
|
|
40
|
+
if (typeof obj === "object") {
|
|
41
|
+
const cleanObj = {};
|
|
42
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
43
|
+
const lowerKey = key.toLowerCase();
|
|
44
|
+
if (lowerKey.includes("password") ||
|
|
45
|
+
lowerKey.includes("token") ||
|
|
46
|
+
lowerKey.includes("secret") ||
|
|
47
|
+
(lowerKey.includes("auth") && !lowerKey.includes("author")) ||
|
|
48
|
+
(lowerKey.includes("key") && !lowerKey.includes("keyboard"))) {
|
|
49
|
+
if (typeof val === "string") {
|
|
50
|
+
cleanObj[key] = "************";
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
cleanObj[key] = sanitizeObject(val);
|
|
55
|
+
}
|
|
56
|
+
return cleanObj;
|
|
57
|
+
}
|
|
58
|
+
return obj;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/utils/sanitizer.ts"],"names":[],"mappings":"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"}
|
package/docs/EXAMPLES.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# WinHelm MCP — Real-World Agent Workflows & Use Cases
|
|
2
|
+
|
|
3
|
+
This guide demonstrates concrete workflows for LLM coding agents (e.g. Claude Desktop, Cursor, Cline, Windsurf) using WinHelm tools across different profiles.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Use Case 1: Autonomous Build, Test, and Self-Healing
|
|
8
|
+
**Recommended Profile:** `dev` (28 tools)
|
|
9
|
+
|
|
10
|
+
When an AI agent needs to compile a large project, monitor progress in the background, and fix build errors without blocking the conversation:
|
|
11
|
+
|
|
12
|
+
### Step 1: Start background build task
|
|
13
|
+
The agent starts the build asynchronously:
|
|
14
|
+
|
|
15
|
+
**Tool:** `terminal_task_start`
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"command": "npm run build",
|
|
19
|
+
"cwd": "D:\\Projects\\MyWebApp"
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
*WinHelm returns Task ID `a4f891b2` immediately.*
|
|
23
|
+
|
|
24
|
+
### Step 2: Poll live progress
|
|
25
|
+
The agent checks progress after 3 seconds:
|
|
26
|
+
|
|
27
|
+
**Tool:** `terminal_task_logs`
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"task_id": "a4f891b2",
|
|
31
|
+
"tail_lines": 15
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
*Output shows a TypeScript compilation error in `src/utils.ts:42`.*
|
|
35
|
+
|
|
36
|
+
### Step 3: Surgically fix the code
|
|
37
|
+
The agent patches the specific line without touching adjacent lines:
|
|
38
|
+
|
|
39
|
+
**Tool:** `file_edit`
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"path": "D:\\Projects\\MyWebApp\\src\\utils.ts",
|
|
43
|
+
"old_text": "const port = process.env.PORT || undefined;",
|
|
44
|
+
"new_text": "const port = Number(process.env.PORT) || 8080;"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Step 4: Verify test passes
|
|
49
|
+
The agent executes the test suite synchronously:
|
|
50
|
+
|
|
51
|
+
**Tool:** `terminal_run`
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"command": "npm test",
|
|
55
|
+
"cwd": "D:\\Projects\\MyWebApp"
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Use Case 2: System Health Inspection & Troubleshooting
|
|
62
|
+
**Recommended Profile:** `sysadmin` (37 tools)
|
|
63
|
+
|
|
64
|
+
When an AI agent is asked: *"Why is my Windows computer sluggish or why did my application crash?"*
|
|
65
|
+
|
|
66
|
+
### Step 1: Check hardware utilization
|
|
67
|
+
**Tool:** `system_info`
|
|
68
|
+
```json
|
|
69
|
+
{}
|
|
70
|
+
```
|
|
71
|
+
*Returns CPU utilization %, RAM usage (Total/Used/Free), OS version, and allowed drive capacities.*
|
|
72
|
+
|
|
73
|
+
### Step 2: Query GPU telemetry
|
|
74
|
+
**Tool:** `gpu_info`
|
|
75
|
+
```json
|
|
76
|
+
{}
|
|
77
|
+
```
|
|
78
|
+
*Returns NVIDIA GPU name, driver version, temperature, and VRAM utilization.*
|
|
79
|
+
|
|
80
|
+
### Step 3: Identify resource-heavy processes
|
|
81
|
+
**Tool:** `process_list`
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"sort_by": "memory",
|
|
85
|
+
"limit": 10
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
*Returns top 10 processes sorted by RAM usage.*
|
|
89
|
+
|
|
90
|
+
### Step 4: Query Windows Event Log for crashes
|
|
91
|
+
**Tool:** `eventlog_query`
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"log_name": "Application",
|
|
95
|
+
"level": "Error",
|
|
96
|
+
"limit": 5
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
*Identifies exact exception codes, faulted module names, and crash timestamps.*
|
|
100
|
+
|
|
101
|
+
### Step 5: Notify the developer
|
|
102
|
+
**Tool:** `notification_send`
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"title": "WinHelm Diagnostic Complete",
|
|
106
|
+
"message": "Found memory leak in rogue node.exe process (PID 4120). Recommending process_kill.",
|
|
107
|
+
"sound": true
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Use Case 3: Code Search & Automated PDF Report
|
|
114
|
+
**Recommended Profile:** `dev` (28 tools) or `full` (38 tools)
|
|
115
|
+
|
|
116
|
+
When an agent performs an audit and generates a client-ready PDF document:
|
|
117
|
+
|
|
118
|
+
### Step 1: High-speed code search across project
|
|
119
|
+
**Tool:** `file_search_ripgrep`
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"query": "TODO|FIXME|SECURITY",
|
|
123
|
+
"path": "D:\\mcp\\winhelm-mcp",
|
|
124
|
+
"page_size": 20
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Step 2: Write markdown report
|
|
129
|
+
**Tool:** `file_write`
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"path": "D:\\AuditReport.md",
|
|
133
|
+
"content": "# Codebase Audit Report\n\nFound 3 unresolved TODOs in codebase..."
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Step 3: Compile report to PDF using native Chromium
|
|
138
|
+
**Tool:** `pdf_generate`
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"source_path": "D:\\AuditReport.md",
|
|
142
|
+
"pdf_path": "D:\\AuditReport.pdf",
|
|
143
|
+
"title": "Security & Code Audit Report"
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
*Generates formatted, print-ready PDF using headless Microsoft Edge or Google Chrome.*
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Use Case 4: Safe File Operations & Archival
|
|
151
|
+
**Recommended Profile:** `dev` (28 tools) or `core` (15 tools)
|
|
152
|
+
|
|
153
|
+
Safe file management that avoids accidental permanent loss:
|
|
154
|
+
|
|
155
|
+
### Step 1: Zip backup before modifying
|
|
156
|
+
**Tool:** `archive_zip`
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"source_dir": "D:\\Projects\\ImportantData",
|
|
160
|
+
"zip_path": "D:\\Backups\\ImportantData-2026-09-27.zip"
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Step 2: Recycle old temporary files (safe delete)
|
|
165
|
+
**Tool:** `file_delete_safe`
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"path": "D:\\Projects\\TempCache"
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
*Item is moved to Windows Recycle Bin where it can be restored if needed.*
|