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,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fast HTTP health check ping for local/remote servers
|
|
3
|
+
*/
|
|
4
|
+
export async function pingEndpoint(url, timeoutMs = 5000, expectedStatus) {
|
|
5
|
+
const start = Date.now();
|
|
6
|
+
try {
|
|
7
|
+
const res = await fetch(url, {
|
|
8
|
+
method: "GET",
|
|
9
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
10
|
+
});
|
|
11
|
+
const latencyMs = Date.now() - start;
|
|
12
|
+
const isExpected = expectedStatus ? res.status === expectedStatus : res.ok;
|
|
13
|
+
return {
|
|
14
|
+
ok: isExpected,
|
|
15
|
+
status: res.status,
|
|
16
|
+
statusText: res.statusText,
|
|
17
|
+
latencyMs,
|
|
18
|
+
url,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
return {
|
|
23
|
+
ok: false,
|
|
24
|
+
status: 0,
|
|
25
|
+
statusText: err?.message || "Connection failed or timed out",
|
|
26
|
+
latencyMs: Date.now() - start,
|
|
27
|
+
url,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Execute HTTP request to test APIs, microservices, and web endpoints
|
|
33
|
+
*/
|
|
34
|
+
export async function executeHttpRequest(options) {
|
|
35
|
+
const { url, method = "GET", headers = {}, body, timeoutMs = 15000 } = options;
|
|
36
|
+
const start = Date.now();
|
|
37
|
+
const fetchOptions = {
|
|
38
|
+
method: method.toUpperCase(),
|
|
39
|
+
headers: { ...headers },
|
|
40
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
41
|
+
};
|
|
42
|
+
if (body && !["GET", "HEAD"].includes(method.toUpperCase())) {
|
|
43
|
+
fetchOptions.body = body;
|
|
44
|
+
if (!fetchOptions.headers || !fetchOptions.headers["Content-Type"]) {
|
|
45
|
+
// Auto-detect JSON
|
|
46
|
+
try {
|
|
47
|
+
JSON.parse(body);
|
|
48
|
+
fetchOptions.headers["Content-Type"] = "application/json";
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
fetchOptions.headers["Content-Type"] = "text/plain";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const res = await fetch(url, fetchOptions);
|
|
57
|
+
const durationMs = Date.now() - start;
|
|
58
|
+
const resHeaders = {};
|
|
59
|
+
res.headers.forEach((v, k) => {
|
|
60
|
+
resHeaders[k] = v;
|
|
61
|
+
});
|
|
62
|
+
const text = await res.text();
|
|
63
|
+
let isJson = false;
|
|
64
|
+
let json = undefined;
|
|
65
|
+
try {
|
|
66
|
+
json = JSON.parse(text);
|
|
67
|
+
isJson = true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// plain text
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
status: res.status,
|
|
74
|
+
statusText: res.statusText,
|
|
75
|
+
durationMs,
|
|
76
|
+
headers: resHeaders,
|
|
77
|
+
body: text.length > 50000 ? text.slice(0, 50000) + "\n...[truncated]" : text,
|
|
78
|
+
isJson,
|
|
79
|
+
json,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return {
|
|
84
|
+
status: 0,
|
|
85
|
+
statusText: err?.message || "HTTP request failed",
|
|
86
|
+
durationMs: Date.now() - start,
|
|
87
|
+
headers: {},
|
|
88
|
+
body: "",
|
|
89
|
+
isJson: false,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../src/engine/http-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PdfGenerateOptions, PdfGenerateResult } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Locate system Chromium browser (Edge or Chrome)
|
|
4
|
+
*/
|
|
5
|
+
export declare function findChromiumPath(): string | null;
|
|
6
|
+
/**
|
|
7
|
+
* Lightweight, robust Markdown to HTML converter with print styling
|
|
8
|
+
*/
|
|
9
|
+
export declare function markdownToHtml(md: string, title?: string): string;
|
|
10
|
+
export declare function sanitizeHref(url: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Generate a PDF from a Markdown, HTML, or Text file using native Chromium headless
|
|
13
|
+
*/
|
|
14
|
+
export declare function generatePdf(options: PdfGenerateOptions): Promise<PdfGenerateResult>;
|
|
15
|
+
//# sourceMappingURL=pdf-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf-generator.d.ts","sourceRoot":"","sources":["../../src/engine/pdf-generator.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAI/E;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAiBhD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,SAAa,GAAG,MAAM,CA2LrE;AAWD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiBhD;AAaD;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA6EzF"}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import { existsSync, statSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import { promisify } from "node:util";
|
|
7
|
+
import { ConfigManager } from "../config/config-manager.js";
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
/**
|
|
10
|
+
* Locate system Chromium browser (Edge or Chrome)
|
|
11
|
+
*/
|
|
12
|
+
export function findChromiumPath() {
|
|
13
|
+
const localAppData = process.env.LOCALAPPDATA || "";
|
|
14
|
+
const candidates = [
|
|
15
|
+
"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
|
|
16
|
+
"C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
|
|
17
|
+
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
18
|
+
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
|
|
19
|
+
path.join(localAppData, "Google\\Chrome\\Application\\chrome.exe"),
|
|
20
|
+
path.join(localAppData, "Microsoft\\Edge\\Application\\msedge.exe"),
|
|
21
|
+
];
|
|
22
|
+
for (const p of candidates) {
|
|
23
|
+
if (existsSync(p)) {
|
|
24
|
+
return p;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Lightweight, robust Markdown to HTML converter with print styling
|
|
31
|
+
*/
|
|
32
|
+
export function markdownToHtml(md, title = "Document") {
|
|
33
|
+
// Convert Markdown blocks
|
|
34
|
+
const lines = md.split(/\r?\n/);
|
|
35
|
+
const htmlParts = [];
|
|
36
|
+
let inCodeBlock = false;
|
|
37
|
+
let codeBlockLang = "";
|
|
38
|
+
let codeBuffer = [];
|
|
39
|
+
let inList = false;
|
|
40
|
+
let inTable = false;
|
|
41
|
+
for (let i = 0; i < lines.length; i++) {
|
|
42
|
+
const line = lines[i];
|
|
43
|
+
// Code blocks
|
|
44
|
+
if (line.trim().startsWith("```")) {
|
|
45
|
+
if (inCodeBlock) {
|
|
46
|
+
const safeLang = escapeHtml(codeBlockLang.replace(/[^\w\-]/g, ""));
|
|
47
|
+
htmlParts.push(`<pre class="code-block ${safeLang}"><code>${escapeHtml(codeBuffer.join("\n"))}</code></pre>`);
|
|
48
|
+
codeBuffer = [];
|
|
49
|
+
inCodeBlock = false;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
inCodeBlock = true;
|
|
53
|
+
codeBlockLang = line.trim().slice(3).trim();
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (inCodeBlock) {
|
|
58
|
+
codeBuffer.push(line);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// Tables
|
|
62
|
+
if (line.trim().startsWith("|") && line.trim().endsWith("|")) {
|
|
63
|
+
if (!inTable) {
|
|
64
|
+
inTable = true;
|
|
65
|
+
htmlParts.push("<table>");
|
|
66
|
+
}
|
|
67
|
+
// Check if delimiter row
|
|
68
|
+
if (/^\|[\s\-:|]+\|$/.test(line.trim())) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const cells = line
|
|
72
|
+
.trim()
|
|
73
|
+
.slice(1, -1)
|
|
74
|
+
.split("|")
|
|
75
|
+
.map((c) => c.trim());
|
|
76
|
+
const isHeader = i > 0 && lines[i + 1] && /^\|[\s\-:|]+\|$/.test(lines[i + 1].trim());
|
|
77
|
+
const tag = isHeader ? "th" : "td";
|
|
78
|
+
htmlParts.push(`<tr>${cells.map((c) => `<${tag}>${formatInline(c)}</${tag}>`).join("")}</tr>`);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
else if (inTable) {
|
|
82
|
+
inTable = false;
|
|
83
|
+
htmlParts.push("</table>");
|
|
84
|
+
}
|
|
85
|
+
// Lists
|
|
86
|
+
if (/^\s*[\*\-]\s+(.*)$/.test(line)) {
|
|
87
|
+
if (!inList) {
|
|
88
|
+
inList = true;
|
|
89
|
+
htmlParts.push("<ul>");
|
|
90
|
+
}
|
|
91
|
+
const itemText = line.replace(/^\s*[\*\-]\s+/, "");
|
|
92
|
+
htmlParts.push(`<li>${formatInline(itemText)}</li>`);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
else if (inList) {
|
|
96
|
+
inList = false;
|
|
97
|
+
htmlParts.push("</ul>");
|
|
98
|
+
}
|
|
99
|
+
// Headings
|
|
100
|
+
if (/^######\s+(.*)$/.test(line)) {
|
|
101
|
+
htmlParts.push(`<h6>${formatInline(line.replace(/^######\s+/, ""))}</h6>`);
|
|
102
|
+
}
|
|
103
|
+
else if (/^#####\s+(.*)$/.test(line)) {
|
|
104
|
+
htmlParts.push(`<h5>${formatInline(line.replace(/^#####\s+/, ""))}</h5>`);
|
|
105
|
+
}
|
|
106
|
+
else if (/^####\s+(.*)$/.test(line)) {
|
|
107
|
+
htmlParts.push(`<h4>${formatInline(line.replace(/^####\s+/, ""))}</h4>`);
|
|
108
|
+
}
|
|
109
|
+
else if (/^###\s+(.*)$/.test(line)) {
|
|
110
|
+
htmlParts.push(`<h3>${formatInline(line.replace(/^###\s+/, ""))}</h3>`);
|
|
111
|
+
}
|
|
112
|
+
else if (/^##\s+(.*)$/.test(line)) {
|
|
113
|
+
htmlParts.push(`<h2>${formatInline(line.replace(/^##\s+/, ""))}</h2>`);
|
|
114
|
+
}
|
|
115
|
+
else if (/^#\s+(.*)$/.test(line)) {
|
|
116
|
+
htmlParts.push(`<h1>${formatInline(line.replace(/^#\s+/, ""))}</h1>`);
|
|
117
|
+
}
|
|
118
|
+
else if (/^>\s*(.*)$/.test(line)) {
|
|
119
|
+
htmlParts.push(`<blockquote>${formatInline(line.replace(/^>\s*/, ""))}</blockquote>`);
|
|
120
|
+
}
|
|
121
|
+
else if (/^---|\*\*\*|___$/.test(line.trim())) {
|
|
122
|
+
htmlParts.push("<hr />");
|
|
123
|
+
}
|
|
124
|
+
else if (line.trim().length > 0) {
|
|
125
|
+
htmlParts.push(`<p>${formatInline(line)}</p>`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (inList)
|
|
129
|
+
htmlParts.push("</ul>");
|
|
130
|
+
if (inTable)
|
|
131
|
+
htmlParts.push("</table>");
|
|
132
|
+
return `<!DOCTYPE html>
|
|
133
|
+
<html lang="en">
|
|
134
|
+
<head>
|
|
135
|
+
<meta charset="UTF-8">
|
|
136
|
+
<title>${escapeHtml(title)}</title>
|
|
137
|
+
<style>
|
|
138
|
+
@page {
|
|
139
|
+
margin: 15mm 20mm;
|
|
140
|
+
size: A4 portrait;
|
|
141
|
+
}
|
|
142
|
+
body {
|
|
143
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
144
|
+
font-size: 11pt;
|
|
145
|
+
line-height: 1.6;
|
|
146
|
+
color: #24292f;
|
|
147
|
+
background: #ffffff;
|
|
148
|
+
padding: 0;
|
|
149
|
+
margin: 0;
|
|
150
|
+
}
|
|
151
|
+
h1, h2, h3, h4, h5, h6 {
|
|
152
|
+
color: #1f2328;
|
|
153
|
+
margin-top: 1.4em;
|
|
154
|
+
margin-bottom: 0.6em;
|
|
155
|
+
font-weight: 600;
|
|
156
|
+
page-break-after: avoid;
|
|
157
|
+
}
|
|
158
|
+
h1 { font-size: 20pt; border-bottom: 1.5px solid #d0d7de; padding-bottom: 0.3em; }
|
|
159
|
+
h2 { font-size: 15pt; border-bottom: 1px solid #eaeef2; padding-bottom: 0.2em; }
|
|
160
|
+
h3 { font-size: 13pt; }
|
|
161
|
+
p, ul, ol { margin-top: 0; margin-bottom: 1em; }
|
|
162
|
+
ul { padding-left: 2em; }
|
|
163
|
+
li { margin-bottom: 0.25em; }
|
|
164
|
+
code {
|
|
165
|
+
font-family: "Cascadia Code", Consolas, "Courier New", monospace;
|
|
166
|
+
font-size: 9.5pt;
|
|
167
|
+
background-color: #f6f8fa;
|
|
168
|
+
padding: 0.2em 0.4em;
|
|
169
|
+
border-radius: 4px;
|
|
170
|
+
border: 1px solid #e1e4e8;
|
|
171
|
+
}
|
|
172
|
+
pre.code-block {
|
|
173
|
+
background-color: #f6f8fa;
|
|
174
|
+
border: 1px solid #d0d7de;
|
|
175
|
+
border-radius: 6px;
|
|
176
|
+
padding: 14px;
|
|
177
|
+
overflow-x: auto;
|
|
178
|
+
font-size: 9pt;
|
|
179
|
+
line-height: 1.45;
|
|
180
|
+
page-break-inside: avoid;
|
|
181
|
+
}
|
|
182
|
+
pre.code-block code {
|
|
183
|
+
background: none;
|
|
184
|
+
border: none;
|
|
185
|
+
padding: 0;
|
|
186
|
+
}
|
|
187
|
+
table {
|
|
188
|
+
border-collapse: collapse;
|
|
189
|
+
width: 100%;
|
|
190
|
+
margin: 1em 0;
|
|
191
|
+
font-size: 10pt;
|
|
192
|
+
page-break-inside: avoid;
|
|
193
|
+
}
|
|
194
|
+
th, td {
|
|
195
|
+
border: 1px solid #d0d7de;
|
|
196
|
+
padding: 8px 12px;
|
|
197
|
+
text-align: left;
|
|
198
|
+
}
|
|
199
|
+
th {
|
|
200
|
+
background-color: #f6f8fa;
|
|
201
|
+
font-weight: 600;
|
|
202
|
+
}
|
|
203
|
+
blockquote {
|
|
204
|
+
border-left: 4px solid #0969da;
|
|
205
|
+
margin: 1em 0;
|
|
206
|
+
padding: 0.5em 1em;
|
|
207
|
+
color: #57606a;
|
|
208
|
+
background-color: #f6f8fa;
|
|
209
|
+
}
|
|
210
|
+
hr {
|
|
211
|
+
border: 0;
|
|
212
|
+
height: 1px;
|
|
213
|
+
background: #d0d7de;
|
|
214
|
+
margin: 1.5em 0;
|
|
215
|
+
}
|
|
216
|
+
</style>
|
|
217
|
+
</head>
|
|
218
|
+
<body>
|
|
219
|
+
${htmlParts.join("\n")}
|
|
220
|
+
</body>
|
|
221
|
+
</html>`;
|
|
222
|
+
}
|
|
223
|
+
function escapeHtml(str) {
|
|
224
|
+
return str
|
|
225
|
+
.replace(/&/g, "&")
|
|
226
|
+
.replace(/</g, "<")
|
|
227
|
+
.replace(/>/g, ">")
|
|
228
|
+
.replace(/"/g, """)
|
|
229
|
+
.replace(/'/g, "'");
|
|
230
|
+
}
|
|
231
|
+
export function sanitizeHref(url) {
|
|
232
|
+
const clean = url.trim().replace(/[\u0000-\u001F\u007F-\u009F]/g, "");
|
|
233
|
+
const normalized = clean.replace(/&#x?[0-9a-f]+;?/gi, (match) => {
|
|
234
|
+
try {
|
|
235
|
+
if (match.startsWith("&#x") || match.startsWith("&#X")) {
|
|
236
|
+
return String.fromCharCode(parseInt(match.slice(3), 16));
|
|
237
|
+
}
|
|
238
|
+
else if (match.startsWith("&#")) {
|
|
239
|
+
return String.fromCharCode(parseInt(match.slice(2), 10));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch { }
|
|
243
|
+
return match;
|
|
244
|
+
});
|
|
245
|
+
if (/^(?:javascript|vbscript|data)\s*:/i.test(normalized.trim())) {
|
|
246
|
+
return "#";
|
|
247
|
+
}
|
|
248
|
+
return clean;
|
|
249
|
+
}
|
|
250
|
+
function formatInline(str) {
|
|
251
|
+
return escapeHtml(str)
|
|
252
|
+
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
|
253
|
+
.replace(/\*(.*?)\*/g, "<em>$1</em>")
|
|
254
|
+
.replace(/~~(.*?)~~/g, "<del>$1</del>")
|
|
255
|
+
.replace(/`([^`]+)`/g, "<code>$1</code>")
|
|
256
|
+
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, text, href) => {
|
|
257
|
+
return `<a href="${sanitizeHref(href)}">${text}</a>`;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Generate a PDF from a Markdown, HTML, or Text file using native Chromium headless
|
|
262
|
+
*/
|
|
263
|
+
export async function generatePdf(options) {
|
|
264
|
+
const configManager = ConfigManager.getInstance();
|
|
265
|
+
if (configManager.isReadOnly()) {
|
|
266
|
+
throw new Error("Operation blocked: Server is running in read-only mode.");
|
|
267
|
+
}
|
|
268
|
+
const resolvedSource = path.resolve(options.sourcePath);
|
|
269
|
+
const resolvedPdf = path.resolve(options.pdfPath);
|
|
270
|
+
if (!existsSync(resolvedSource)) {
|
|
271
|
+
throw new Error(`Source file not found: ${options.sourcePath}`);
|
|
272
|
+
}
|
|
273
|
+
const dstCheck = configManager.isPathAllowed(resolvedPdf);
|
|
274
|
+
if (!dstCheck.allowed) {
|
|
275
|
+
throw new Error(dstCheck.reason);
|
|
276
|
+
}
|
|
277
|
+
const browserPath = findChromiumPath();
|
|
278
|
+
if (!browserPath) {
|
|
279
|
+
throw new Error("No Chromium-based browser (Microsoft Edge or Google Chrome) found on this Windows system.");
|
|
280
|
+
}
|
|
281
|
+
// Ensure output directory exists
|
|
282
|
+
await fs.mkdir(path.dirname(resolvedPdf), { recursive: true });
|
|
283
|
+
const ext = path.extname(resolvedSource).toLowerCase();
|
|
284
|
+
let htmlPath = resolvedSource;
|
|
285
|
+
let tempHtmlPath = null;
|
|
286
|
+
if (ext === ".md" || ext === ".markdown" || ext === ".txt") {
|
|
287
|
+
const rawContent = await fs.readFile(resolvedSource, "utf-8");
|
|
288
|
+
const docTitle = options.title || path.basename(resolvedSource, ext);
|
|
289
|
+
const htmlContent = markdownToHtml(rawContent, docTitle);
|
|
290
|
+
tempHtmlPath = path.join(os.tmpdir(), `wincommander_pdf_${Date.now()}_${Math.random().toString(36).slice(2)}.html`);
|
|
291
|
+
await fs.writeFile(tempHtmlPath, htmlContent, "utf-8");
|
|
292
|
+
htmlPath = tempHtmlPath;
|
|
293
|
+
}
|
|
294
|
+
const args = [
|
|
295
|
+
"--headless",
|
|
296
|
+
"--disable-gpu",
|
|
297
|
+
"--no-pdf-header-footer",
|
|
298
|
+
"--run-all-compositor-stages-before-draw",
|
|
299
|
+
`--print-to-pdf=${resolvedPdf}`,
|
|
300
|
+
htmlPath,
|
|
301
|
+
];
|
|
302
|
+
try {
|
|
303
|
+
await execFileAsync(browserPath, args, {
|
|
304
|
+
timeout: 30000,
|
|
305
|
+
windowsHide: true,
|
|
306
|
+
});
|
|
307
|
+
if (!existsSync(resolvedPdf)) {
|
|
308
|
+
throw new Error(`PDF generation completed but target file was not created at ${resolvedPdf}`);
|
|
309
|
+
}
|
|
310
|
+
const stat = statSync(resolvedPdf);
|
|
311
|
+
return {
|
|
312
|
+
success: true,
|
|
313
|
+
pdfPath: resolvedPdf,
|
|
314
|
+
sourcePath: resolvedSource,
|
|
315
|
+
sizeBytes: stat.size,
|
|
316
|
+
browserUsed: path.basename(browserPath),
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
finally {
|
|
320
|
+
if (tempHtmlPath && existsSync(tempHtmlPath)) {
|
|
321
|
+
await fs.unlink(tempHtmlPath).catch(() => { });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=pdf-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf-generator.js","sourceRoot":"","sources":["../../src/engine/pdf-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ExecutionResult } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check whether PowerShell 7+ (pwsh.exe) is installed on the host system.
|
|
4
|
+
* Cached in memory after the initial check to eliminate recurring spawn overhead.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isPwshAvailable(): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Reset or set pwsh availability cache (useful for testing and mocking)
|
|
9
|
+
*/
|
|
10
|
+
export declare function setPwshAvailableCache(val: boolean | null): void;
|
|
11
|
+
/**
|
|
12
|
+
* Select preferred PowerShell executable: pwsh.exe if available and preferred, else powershell.exe
|
|
13
|
+
*/
|
|
14
|
+
export declare function getPowerShellExecutable(preferPwsh?: boolean): string;
|
|
15
|
+
export interface PowerShellOptions {
|
|
16
|
+
cwd?: string;
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Execute a PowerShell command with UTF-8 encoding, security guard, and timeout protection
|
|
21
|
+
*/
|
|
22
|
+
export declare function runPowerShell(command: string, options?: PowerShellOptions): Promise<ExecutionResult>;
|
|
23
|
+
//# sourceMappingURL=powershell-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"powershell-runner.d.ts","sourceRoot":"","sources":["../../src/engine/powershell-runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMzD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAezC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAE/D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,UAAO,GAAG,MAAM,CAKjE;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAmH1B"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { ConfigManager } from "../config/config-manager.js";
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
6
|
+
let cachedPwshAvailable = null;
|
|
7
|
+
/**
|
|
8
|
+
* Check whether PowerShell 7+ (pwsh.exe) is installed on the host system.
|
|
9
|
+
* Cached in memory after the initial check to eliminate recurring spawn overhead.
|
|
10
|
+
*/
|
|
11
|
+
export function isPwshAvailable() {
|
|
12
|
+
if (cachedPwshAvailable !== null) {
|
|
13
|
+
return cachedPwshAvailable;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const res = spawnSync("pwsh.exe", ["-NoProfile", "-Version"], {
|
|
17
|
+
windowsHide: true,
|
|
18
|
+
stdio: "ignore",
|
|
19
|
+
timeout: 2000,
|
|
20
|
+
});
|
|
21
|
+
cachedPwshAvailable = res.status === 0;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
cachedPwshAvailable = false;
|
|
25
|
+
}
|
|
26
|
+
return cachedPwshAvailable;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Reset or set pwsh availability cache (useful for testing and mocking)
|
|
30
|
+
*/
|
|
31
|
+
export function setPwshAvailableCache(val) {
|
|
32
|
+
cachedPwshAvailable = val;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Select preferred PowerShell executable: pwsh.exe if available and preferred, else powershell.exe
|
|
36
|
+
*/
|
|
37
|
+
export function getPowerShellExecutable(preferPwsh = true) {
|
|
38
|
+
if (preferPwsh && isPwshAvailable()) {
|
|
39
|
+
return "pwsh.exe";
|
|
40
|
+
}
|
|
41
|
+
return "powershell.exe";
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Execute a PowerShell command with UTF-8 encoding, security guard, and timeout protection
|
|
45
|
+
*/
|
|
46
|
+
export function runPowerShell(command, options = {}) {
|
|
47
|
+
const configManager = ConfigManager.getInstance();
|
|
48
|
+
const config = configManager.getConfig();
|
|
49
|
+
// 1. Security Check
|
|
50
|
+
const check = configManager.isCommandAllowed(command);
|
|
51
|
+
if (!check.allowed) {
|
|
52
|
+
const reason = check.reason || "Command blocked by security policy";
|
|
53
|
+
logger.security(reason, command);
|
|
54
|
+
return Promise.reject(new Error(reason));
|
|
55
|
+
}
|
|
56
|
+
// 2. Validate CWD against allowedDirectories
|
|
57
|
+
let cwd;
|
|
58
|
+
if (options.cwd) {
|
|
59
|
+
const cwdCheck = configManager.isPathAllowed(options.cwd);
|
|
60
|
+
if (!cwdCheck.allowed && config.allowSystemExecution === false) {
|
|
61
|
+
const reason = cwdCheck.reason || `Working directory "${options.cwd}" is not permitted`;
|
|
62
|
+
logger.security(reason, command);
|
|
63
|
+
return Promise.reject(new Error(reason));
|
|
64
|
+
}
|
|
65
|
+
cwd = options.cwd;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const currentCwd = process.cwd();
|
|
69
|
+
const currentCheck = configManager.isPathAllowed(currentCwd);
|
|
70
|
+
if (currentCheck.allowed) {
|
|
71
|
+
cwd = currentCwd;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const allowed = config.allowedDirectories;
|
|
75
|
+
if (allowed && allowed.length > 0) {
|
|
76
|
+
let first = allowed[0].trim();
|
|
77
|
+
if (/^[a-zA-Z]:?[\\/]?$/.test(first)) {
|
|
78
|
+
first = first[0].toUpperCase() + ":\\";
|
|
79
|
+
}
|
|
80
|
+
cwd = path.resolve(first);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
cwd = currentCwd;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const timeoutMs = options.timeoutMs || config.defaultTimeoutMs || 60000;
|
|
88
|
+
const startTime = Date.now();
|
|
89
|
+
const executionId = randomUUID();
|
|
90
|
+
return new Promise((resolve, reject) => {
|
|
91
|
+
// UTF-8 setup preamble for Windows PowerShell to prevent garbled Unicode / Thai characters
|
|
92
|
+
const utf8Setup = "[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new(); " +
|
|
93
|
+
"[Console]::InputEncoding = [System.Text.UTF8Encoding]::new(); " +
|
|
94
|
+
"$OutputEncoding = [System.Text.UTF8Encoding]::new(); ";
|
|
95
|
+
const fullCommand = utf8Setup + command;
|
|
96
|
+
const preferPwsh = config.preferPwsh !== false;
|
|
97
|
+
const executable = getPowerShellExecutable(preferPwsh);
|
|
98
|
+
const child = spawn(executable, ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", fullCommand], {
|
|
99
|
+
cwd,
|
|
100
|
+
windowsHide: true,
|
|
101
|
+
env: { ...process.env, PYTHONIOENCODING: "utf-8" },
|
|
102
|
+
});
|
|
103
|
+
let stdout = "";
|
|
104
|
+
let stderr = "";
|
|
105
|
+
let timedOut = false;
|
|
106
|
+
const timer = setTimeout(() => {
|
|
107
|
+
timedOut = true;
|
|
108
|
+
try {
|
|
109
|
+
child.kill("SIGKILL");
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Process might already be dead
|
|
113
|
+
}
|
|
114
|
+
}, timeoutMs);
|
|
115
|
+
child.stdout.on("data", (chunk) => {
|
|
116
|
+
stdout += chunk.toString("utf-8");
|
|
117
|
+
});
|
|
118
|
+
child.stderr.on("data", (chunk) => {
|
|
119
|
+
stderr += chunk.toString("utf-8");
|
|
120
|
+
});
|
|
121
|
+
child.on("close", (code) => {
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
const exitCode = code ?? (timedOut ? -1 : 0);
|
|
124
|
+
const durationMs = Date.now() - startTime;
|
|
125
|
+
// Log execution for auditing
|
|
126
|
+
configManager.logExecution({
|
|
127
|
+
id: executionId,
|
|
128
|
+
timestamp: new Date().toISOString(),
|
|
129
|
+
command,
|
|
130
|
+
cwd,
|
|
131
|
+
exitCode,
|
|
132
|
+
durationMs,
|
|
133
|
+
timedOut,
|
|
134
|
+
});
|
|
135
|
+
resolve({
|
|
136
|
+
stdout: stdout.trim(),
|
|
137
|
+
stderr: stderr.trim(),
|
|
138
|
+
exitCode,
|
|
139
|
+
timedOut,
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
child.on("error", (err) => {
|
|
143
|
+
clearTimeout(timer);
|
|
144
|
+
reject(err);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=powershell-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"powershell-runner.js","sourceRoot":"","sources":["../../src/engine/powershell-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RipgrepSearchResult } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Locate ripgrep executable (rg.exe) with multi-path resolution
|
|
4
|
+
*/
|
|
5
|
+
export declare function findRipgrepPath(): string | null;
|
|
6
|
+
export interface RipgrepOptions {
|
|
7
|
+
query: string;
|
|
8
|
+
searchPath?: string;
|
|
9
|
+
filePattern?: string;
|
|
10
|
+
caseSensitive?: boolean;
|
|
11
|
+
isRegex?: boolean;
|
|
12
|
+
page?: number;
|
|
13
|
+
pageSize?: number;
|
|
14
|
+
contextLines?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Execute paginated high-speed codebase search using ripgrep with fallback
|
|
18
|
+
*/
|
|
19
|
+
export declare function searchCodebase(options: RipgrepOptions): Promise<RipgrepSearchResult>;
|
|
20
|
+
//# sourceMappingURL=ripgrep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ripgrep.d.ts","sourceRoot":"","sources":["../../src/engine/ripgrep.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAM3E;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAoC/C;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,mBAAmB,CAAC,CA4I9B"}
|