@helmisatria/mcp-chrome-bridge 1.0.30
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 +183 -0
- package/dist/README.md +25 -0
- package/dist/agent/attachment-service.d.ts +83 -0
- package/dist/agent/attachment-service.js +370 -0
- package/dist/agent/attachment-service.js.map +1 -0
- package/dist/agent/ccr-detector.d.ts +59 -0
- package/dist/agent/ccr-detector.js +311 -0
- package/dist/agent/ccr-detector.js.map +1 -0
- package/dist/agent/chat-service.d.ts +50 -0
- package/dist/agent/chat-service.js +439 -0
- package/dist/agent/chat-service.js.map +1 -0
- package/dist/agent/db/client.d.ts +26 -0
- package/dist/agent/db/client.js +244 -0
- package/dist/agent/db/client.js.map +1 -0
- package/dist/agent/db/index.d.ts +5 -0
- package/dist/agent/db/index.js +22 -0
- package/dist/agent/db/index.js.map +1 -0
- package/dist/agent/db/schema.d.ts +711 -0
- package/dist/agent/db/schema.js +121 -0
- package/dist/agent/db/schema.js.map +1 -0
- package/dist/agent/directory-picker.d.ts +11 -0
- package/dist/agent/directory-picker.js +149 -0
- package/dist/agent/directory-picker.js.map +1 -0
- package/dist/agent/engines/claude.d.ts +79 -0
- package/dist/agent/engines/claude.js +1338 -0
- package/dist/agent/engines/claude.js.map +1 -0
- package/dist/agent/engines/codex.d.ts +48 -0
- package/dist/agent/engines/codex.js +822 -0
- package/dist/agent/engines/codex.js.map +1 -0
- package/dist/agent/engines/types.d.ts +133 -0
- package/dist/agent/engines/types.js +3 -0
- package/dist/agent/engines/types.js.map +1 -0
- package/dist/agent/message-service.d.ts +56 -0
- package/dist/agent/message-service.js +198 -0
- package/dist/agent/message-service.js.map +1 -0
- package/dist/agent/open-project.d.ts +25 -0
- package/dist/agent/open-project.js +469 -0
- package/dist/agent/open-project.js.map +1 -0
- package/dist/agent/project-service.d.ts +49 -0
- package/dist/agent/project-service.js +254 -0
- package/dist/agent/project-service.js.map +1 -0
- package/dist/agent/project-types.d.ts +27 -0
- package/dist/agent/project-types.js +3 -0
- package/dist/agent/project-types.js.map +1 -0
- package/dist/agent/session-service.d.ts +198 -0
- package/dist/agent/session-service.js +292 -0
- package/dist/agent/session-service.js.map +1 -0
- package/dist/agent/storage.d.ts +27 -0
- package/dist/agent/storage.js +73 -0
- package/dist/agent/storage.js.map +1 -0
- package/dist/agent/stream-manager.d.ts +42 -0
- package/dist/agent/stream-manager.js +243 -0
- package/dist/agent/stream-manager.js.map +1 -0
- package/dist/agent/tool-bridge.d.ts +44 -0
- package/dist/agent/tool-bridge.js +50 -0
- package/dist/agent/tool-bridge.js.map +1 -0
- package/dist/agent/types.d.ts +6 -0
- package/dist/agent/types.js +3 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +224 -0
- package/dist/cli.js.map +1 -0
- package/dist/constant/index.d.ts +60 -0
- package/dist/constant/index.js +80 -0
- package/dist/constant/index.js.map +1 -0
- package/dist/file-handler.d.ts +41 -0
- package/dist/file-handler.js +295 -0
- package/dist/file-handler.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/mcp-server-stdio.d.ts +72 -0
- package/dist/mcp/mcp-server-stdio.js +143 -0
- package/dist/mcp/mcp-server-stdio.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +36 -0
- package/dist/mcp/mcp-server.js +26 -0
- package/dist/mcp/mcp-server.js.map +1 -0
- package/dist/mcp/register-tools.d.ts +2 -0
- package/dist/mcp/register-tools.js +148 -0
- package/dist/mcp/register-tools.js.map +1 -0
- package/dist/mcp/stdio-config.json +3 -0
- package/dist/native-messaging-host.d.ts +42 -0
- package/dist/native-messaging-host.js +312 -0
- package/dist/native-messaging-host.js.map +1 -0
- package/dist/run_host.bat +194 -0
- package/dist/run_host.sh +264 -0
- package/dist/scripts/browser-config.d.ts +28 -0
- package/dist/scripts/browser-config.js +229 -0
- package/dist/scripts/browser-config.js.map +1 -0
- package/dist/scripts/build.d.ts +1 -0
- package/dist/scripts/build.js +126 -0
- package/dist/scripts/build.js.map +1 -0
- package/dist/scripts/constant.d.ts +4 -0
- package/dist/scripts/constant.js +8 -0
- package/dist/scripts/constant.js.map +1 -0
- package/dist/scripts/doctor.d.ts +70 -0
- package/dist/scripts/doctor.js +930 -0
- package/dist/scripts/doctor.js.map +1 -0
- package/dist/scripts/postinstall.d.ts +2 -0
- package/dist/scripts/postinstall.js +246 -0
- package/dist/scripts/postinstall.js.map +1 -0
- package/dist/scripts/register-dev.d.ts +1 -0
- package/dist/scripts/register-dev.js +5 -0
- package/dist/scripts/register-dev.js.map +1 -0
- package/dist/scripts/register.d.ts +2 -0
- package/dist/scripts/register.js +28 -0
- package/dist/scripts/register.js.map +1 -0
- package/dist/scripts/report.d.ts +96 -0
- package/dist/scripts/report.js +686 -0
- package/dist/scripts/report.js.map +1 -0
- package/dist/scripts/utils.d.ts +64 -0
- package/dist/scripts/utils.js +443 -0
- package/dist/scripts/utils.js.map +1 -0
- package/dist/server/index.d.ts +35 -0
- package/dist/server/index.js +312 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes/agent.d.ts +21 -0
- package/dist/server/routes/agent.js +971 -0
- package/dist/server/routes/agent.js.map +1 -0
- package/dist/server/routes/index.d.ts +4 -0
- package/dist/server/routes/index.js +9 -0
- package/dist/server/routes/index.js.map +1 -0
- package/dist/trace-analyzer.d.ts +14 -0
- package/dist/trace-analyzer.js +113 -0
- package/dist/trace-analyzer.js.map +1 -0
- package/dist/util/logger.d.ts +1 -0
- package/dist/util/logger.js +43 -0
- package/dist/util/logger.js.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* report.ts
|
|
5
|
+
*
|
|
6
|
+
* Export a diagnostic report for GitHub Issues.
|
|
7
|
+
* Collects system info, doctor output, logs, manifests, and registry info.
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.runReport = runReport;
|
|
14
|
+
const fs_1 = __importDefault(require("fs"));
|
|
15
|
+
const os_1 = __importDefault(require("os"));
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const child_process_1 = require("child_process");
|
|
18
|
+
const constant_1 = require("./constant");
|
|
19
|
+
const browser_config_1 = require("./browser-config");
|
|
20
|
+
const utils_1 = require("./utils");
|
|
21
|
+
const doctor_1 = require("./doctor");
|
|
22
|
+
const REPORT_SCHEMA_VERSION = 1;
|
|
23
|
+
const DEFAULT_LOG_LINES = 200;
|
|
24
|
+
const DEFAULT_TAIL_BYTES = 256 * 1024;
|
|
25
|
+
const MAX_LOG_FILES = 6;
|
|
26
|
+
const MAX_FULL_LOG_BYTES = 1024 * 1024;
|
|
27
|
+
function stringifyError(err) {
|
|
28
|
+
if (err instanceof Error)
|
|
29
|
+
return err.message;
|
|
30
|
+
return String(err);
|
|
31
|
+
}
|
|
32
|
+
function readPackageJson() {
|
|
33
|
+
try {
|
|
34
|
+
return require('../../package.json');
|
|
35
|
+
}
|
|
36
|
+
catch (_a) {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function getToolVersion() {
|
|
41
|
+
const pkg = readPackageJson();
|
|
42
|
+
const name = typeof pkg.name === 'string' ? pkg.name : constant_1.COMMAND_NAME;
|
|
43
|
+
const version = typeof pkg.version === 'string' ? pkg.version : 'unknown';
|
|
44
|
+
return { name, version };
|
|
45
|
+
}
|
|
46
|
+
function safeOsVersion() {
|
|
47
|
+
try {
|
|
48
|
+
return os_1.default.version();
|
|
49
|
+
}
|
|
50
|
+
catch (_a) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function safeExecVersion(command) {
|
|
55
|
+
try {
|
|
56
|
+
const out = (0, child_process_1.execFileSync)(command, ['-v'], {
|
|
57
|
+
encoding: 'utf8',
|
|
58
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
59
|
+
timeout: 2500,
|
|
60
|
+
windowsHide: true,
|
|
61
|
+
});
|
|
62
|
+
return { version: out.trim() };
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
return { error: stringifyError(e) };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function parseIncludeLogsMode(raw) {
|
|
69
|
+
const v = typeof raw === 'string' ? raw.toLowerCase() : '';
|
|
70
|
+
if (v === 'none' || v === 'tail' || v === 'full')
|
|
71
|
+
return v;
|
|
72
|
+
return 'tail';
|
|
73
|
+
}
|
|
74
|
+
function parsePositiveInt(raw, fallback) {
|
|
75
|
+
if (typeof raw === 'number' && Number.isFinite(raw) && raw > 0)
|
|
76
|
+
return Math.floor(raw);
|
|
77
|
+
if (typeof raw === 'string') {
|
|
78
|
+
const parsed = Number.parseInt(raw, 10);
|
|
79
|
+
if (Number.isFinite(parsed) && parsed > 0)
|
|
80
|
+
return parsed;
|
|
81
|
+
}
|
|
82
|
+
return fallback;
|
|
83
|
+
}
|
|
84
|
+
function resolveBrowsers(browserArg) {
|
|
85
|
+
if (!browserArg) {
|
|
86
|
+
const detected = (0, browser_config_1.detectInstalledBrowsers)();
|
|
87
|
+
return detected.length > 0 ? detected : [browser_config_1.BrowserType.CHROME, browser_config_1.BrowserType.CHROMIUM];
|
|
88
|
+
}
|
|
89
|
+
const normalized = browserArg.toLowerCase();
|
|
90
|
+
if (normalized === 'all')
|
|
91
|
+
return [browser_config_1.BrowserType.CHROME, browser_config_1.BrowserType.CHROMIUM];
|
|
92
|
+
if (normalized === 'detect' || normalized === 'auto') {
|
|
93
|
+
const detected = (0, browser_config_1.detectInstalledBrowsers)();
|
|
94
|
+
return detected.length > 0 ? detected : [browser_config_1.BrowserType.CHROME, browser_config_1.BrowserType.CHROMIUM];
|
|
95
|
+
}
|
|
96
|
+
const parsed = (0, browser_config_1.parseBrowserType)(normalized);
|
|
97
|
+
if (!parsed) {
|
|
98
|
+
throw new Error(`Invalid browser: ${browserArg}. Use 'chrome', 'chromium', or 'all'`);
|
|
99
|
+
}
|
|
100
|
+
return [parsed];
|
|
101
|
+
}
|
|
102
|
+
function readJsonSnapshot(filePath) {
|
|
103
|
+
try {
|
|
104
|
+
if (!fs_1.default.existsSync(filePath))
|
|
105
|
+
return { exists: false };
|
|
106
|
+
const raw = fs_1.default.readFileSync(filePath, 'utf8');
|
|
107
|
+
try {
|
|
108
|
+
const json = JSON.parse(raw);
|
|
109
|
+
return { exists: true, json };
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
return { exists: true, raw, error: `Failed to parse JSON: ${stringifyError(e)}` };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
return { exists: fs_1.default.existsSync(filePath), error: stringifyError(e) };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function collectManifests(browsers) {
|
|
120
|
+
const results = [];
|
|
121
|
+
for (const browser of browsers) {
|
|
122
|
+
const config = (0, browser_config_1.getBrowserConfig)(browser);
|
|
123
|
+
for (const scope of ['user', 'system']) {
|
|
124
|
+
const manifestPath = scope === 'user' ? config.userManifestPath : config.systemManifestPath;
|
|
125
|
+
const snap = readJsonSnapshot(manifestPath);
|
|
126
|
+
results.push({
|
|
127
|
+
browser,
|
|
128
|
+
scope,
|
|
129
|
+
path: manifestPath,
|
|
130
|
+
exists: snap.exists,
|
|
131
|
+
json: snap.json,
|
|
132
|
+
raw: snap.raw,
|
|
133
|
+
error: snap.error,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return results;
|
|
138
|
+
}
|
|
139
|
+
function readFileTail(filePath, maxBytes, maxLines) {
|
|
140
|
+
const stat = fs_1.default.statSync(filePath);
|
|
141
|
+
const size = stat.size;
|
|
142
|
+
const bytesToRead = Math.min(size, maxBytes);
|
|
143
|
+
const start = Math.max(0, size - bytesToRead);
|
|
144
|
+
const fd = fs_1.default.openSync(filePath, 'r');
|
|
145
|
+
try {
|
|
146
|
+
const buf = Buffer.alloc(bytesToRead);
|
|
147
|
+
fs_1.default.readSync(fd, buf, 0, bytesToRead, start);
|
|
148
|
+
const text = buf.toString('utf8');
|
|
149
|
+
const lines = text.split(/\r?\n/);
|
|
150
|
+
const tail = lines.slice(Math.max(0, lines.length - maxLines));
|
|
151
|
+
return { content: tail.join('\n'), truncated: size > maxBytes || lines.length > maxLines };
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
fs_1.default.closeSync(fd);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function readFileLastBytes(filePath, maxBytes) {
|
|
158
|
+
const stat = fs_1.default.statSync(filePath);
|
|
159
|
+
const size = stat.size;
|
|
160
|
+
if (size <= maxBytes) {
|
|
161
|
+
const content = fs_1.default.readFileSync(filePath, 'utf8');
|
|
162
|
+
return { content, truncated: false };
|
|
163
|
+
}
|
|
164
|
+
const bytesToRead = maxBytes;
|
|
165
|
+
const start = Math.max(0, size - bytesToRead);
|
|
166
|
+
const fd = fs_1.default.openSync(filePath, 'r');
|
|
167
|
+
try {
|
|
168
|
+
const buf = Buffer.alloc(bytesToRead);
|
|
169
|
+
fs_1.default.readSync(fd, buf, 0, bytesToRead, start);
|
|
170
|
+
const content = buf.toString('utf8');
|
|
171
|
+
return { content, truncated: true };
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
fs_1.default.closeSync(fd);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function collectWrapperLogs(logDir, mode, logLines) {
|
|
178
|
+
if (!fs_1.default.existsSync(logDir)) {
|
|
179
|
+
return { dir: logDir, mode, files: [], error: 'Log directory does not exist' };
|
|
180
|
+
}
|
|
181
|
+
const prefixes = ['native_host_wrapper_', 'native_host_stderr_'];
|
|
182
|
+
let entries = [];
|
|
183
|
+
try {
|
|
184
|
+
entries = fs_1.default.readdirSync(logDir, { withFileTypes: true });
|
|
185
|
+
}
|
|
186
|
+
catch (e) {
|
|
187
|
+
return { dir: logDir, mode, files: [], error: stringifyError(e) };
|
|
188
|
+
}
|
|
189
|
+
const candidates = entries
|
|
190
|
+
.filter((ent) => ent.isFile())
|
|
191
|
+
.map((ent) => ent.name)
|
|
192
|
+
.filter((name) => name.endsWith('.log') && prefixes.some((p) => name.startsWith(p)));
|
|
193
|
+
const filesWithStat = [];
|
|
194
|
+
for (const name of candidates) {
|
|
195
|
+
const fullPath = path_1.default.join(logDir, name);
|
|
196
|
+
try {
|
|
197
|
+
const stat = fs_1.default.statSync(fullPath);
|
|
198
|
+
filesWithStat.push({ name, fullPath, mtimeMs: stat.mtimeMs, size: stat.size });
|
|
199
|
+
}
|
|
200
|
+
catch (_a) {
|
|
201
|
+
// ignore
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
filesWithStat.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
205
|
+
const selected = filesWithStat.slice(0, MAX_LOG_FILES);
|
|
206
|
+
const snapshots = [];
|
|
207
|
+
for (const file of selected) {
|
|
208
|
+
const snap = {
|
|
209
|
+
name: file.name,
|
|
210
|
+
path: file.fullPath,
|
|
211
|
+
mtime: new Date(file.mtimeMs).toISOString(),
|
|
212
|
+
size: file.size,
|
|
213
|
+
};
|
|
214
|
+
if (mode !== 'none') {
|
|
215
|
+
try {
|
|
216
|
+
if (mode === 'tail') {
|
|
217
|
+
const read = readFileTail(file.fullPath, DEFAULT_TAIL_BYTES, logLines);
|
|
218
|
+
snap.content = read.content;
|
|
219
|
+
snap.truncated = read.truncated;
|
|
220
|
+
snap.note = `Tail: last ${logLines} lines (from last ${DEFAULT_TAIL_BYTES} bytes)`;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
const read = readFileLastBytes(file.fullPath, MAX_FULL_LOG_BYTES);
|
|
224
|
+
snap.content = read.content;
|
|
225
|
+
snap.truncated = read.truncated;
|
|
226
|
+
snap.note = read.truncated
|
|
227
|
+
? `Truncated: showing last ${MAX_FULL_LOG_BYTES} bytes`
|
|
228
|
+
: 'Full file';
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch (e) {
|
|
232
|
+
snap.error = stringifyError(e);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
snap.note = 'Content omitted';
|
|
237
|
+
}
|
|
238
|
+
snapshots.push(snap);
|
|
239
|
+
}
|
|
240
|
+
return { dir: logDir, mode, files: snapshots };
|
|
241
|
+
}
|
|
242
|
+
function queryWindowsRegistryDefaultValue(registryKey) {
|
|
243
|
+
try {
|
|
244
|
+
const output = (0, child_process_1.execFileSync)('reg', ['query', registryKey, '/ve'], {
|
|
245
|
+
encoding: 'utf8',
|
|
246
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
247
|
+
timeout: 2500,
|
|
248
|
+
windowsHide: true,
|
|
249
|
+
});
|
|
250
|
+
const lines = output
|
|
251
|
+
.split(/\r?\n/)
|
|
252
|
+
.map((l) => l.trim())
|
|
253
|
+
.filter(Boolean);
|
|
254
|
+
for (const line of lines) {
|
|
255
|
+
const match = line.match(/REG_SZ\s+(.*)$/i);
|
|
256
|
+
if (match === null || match === void 0 ? void 0 : match[1])
|
|
257
|
+
return { value: match[1].trim(), raw: output };
|
|
258
|
+
}
|
|
259
|
+
return { raw: output, error: 'No REG_SZ default value found' };
|
|
260
|
+
}
|
|
261
|
+
catch (e) {
|
|
262
|
+
return { error: stringifyError(e) };
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function collectWindowsRegistry(browsers) {
|
|
266
|
+
const entries = [];
|
|
267
|
+
for (const browser of browsers) {
|
|
268
|
+
const config = (0, browser_config_1.getBrowserConfig)(browser);
|
|
269
|
+
const keySpecs = [
|
|
270
|
+
config.registryKey
|
|
271
|
+
? { key: config.registryKey, scope: 'user', expected: config.userManifestPath }
|
|
272
|
+
: null,
|
|
273
|
+
config.systemRegistryKey
|
|
274
|
+
? {
|
|
275
|
+
key: config.systemRegistryKey,
|
|
276
|
+
scope: 'system',
|
|
277
|
+
expected: config.systemManifestPath,
|
|
278
|
+
}
|
|
279
|
+
: null,
|
|
280
|
+
].filter(Boolean);
|
|
281
|
+
for (const spec of keySpecs) {
|
|
282
|
+
const res = queryWindowsRegistryDefaultValue(spec.key);
|
|
283
|
+
entries.push({
|
|
284
|
+
browser,
|
|
285
|
+
scope: spec.scope,
|
|
286
|
+
key: spec.key,
|
|
287
|
+
expectedManifestPath: spec.expected,
|
|
288
|
+
value: res.value,
|
|
289
|
+
raw: res.raw,
|
|
290
|
+
error: res.error,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return { entries };
|
|
295
|
+
}
|
|
296
|
+
// ============================================================================
|
|
297
|
+
// Redaction
|
|
298
|
+
// ============================================================================
|
|
299
|
+
function escapeRegExp(input) {
|
|
300
|
+
return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
301
|
+
}
|
|
302
|
+
function buildLiteralReplacements() {
|
|
303
|
+
const replacements = [];
|
|
304
|
+
const ignoreCase = process.platform === 'win32';
|
|
305
|
+
const addLiteral = (literal, replacement) => {
|
|
306
|
+
if (!literal)
|
|
307
|
+
return;
|
|
308
|
+
const variants = new Set();
|
|
309
|
+
variants.add(literal);
|
|
310
|
+
variants.add(literal.replace(/\\/g, '/'));
|
|
311
|
+
variants.add(literal.replace(/\//g, '\\'));
|
|
312
|
+
for (const v of variants) {
|
|
313
|
+
if (!v)
|
|
314
|
+
continue;
|
|
315
|
+
replacements.push([new RegExp(escapeRegExp(v), ignoreCase ? 'gi' : 'g'), replacement]);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
addLiteral(os_1.default.homedir(), '<HOME>');
|
|
319
|
+
addLiteral(process.env.USERPROFILE, '<USERPROFILE>');
|
|
320
|
+
addLiteral(process.env.HOME, '<HOME>');
|
|
321
|
+
try {
|
|
322
|
+
const username = os_1.default.userInfo().username;
|
|
323
|
+
if (username) {
|
|
324
|
+
replacements.push([
|
|
325
|
+
new RegExp(`\\b${escapeRegExp(username)}\\b`, ignoreCase ? 'gi' : 'g'),
|
|
326
|
+
'<USER>',
|
|
327
|
+
]);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
catch (_a) {
|
|
331
|
+
// ignore
|
|
332
|
+
}
|
|
333
|
+
return replacements;
|
|
334
|
+
}
|
|
335
|
+
function createRedactor(enabled) {
|
|
336
|
+
if (!enabled)
|
|
337
|
+
return (s) => s;
|
|
338
|
+
const literalReplacements = buildLiteralReplacements();
|
|
339
|
+
const patternReplacements = [
|
|
340
|
+
// Sensitive key=value patterns (supports JSON-style "key": "value" and env-style KEY=value)
|
|
341
|
+
[
|
|
342
|
+
/(\b[A-Z0-9_]*(?:TOKEN|PASSWORD|SECRET|API_KEY|ACCESS_KEY|PRIVATE_KEY)\b)(\s*["']?\s*[:=]\s*["']?)([^\s"']+)/gi,
|
|
343
|
+
'$1$2<REDACTED>',
|
|
344
|
+
],
|
|
345
|
+
// HTTP Authorization headers
|
|
346
|
+
[/(Authorization:\s*Bearer\s+)[^\s]+/gi, '$1<REDACTED>'],
|
|
347
|
+
[/(Authorization:\s*Basic\s+)[^\s]+/gi, '$1<REDACTED>'],
|
|
348
|
+
// JSON-style Authorization fields ("Authorization": "Bearer ...")
|
|
349
|
+
[
|
|
350
|
+
/(\bAuthorization\b)(\s*["']?\s*[:=]\s*["']?)(Bearer\s+|Basic\s+)?[^\s"']+/gi,
|
|
351
|
+
'$1$2$3<REDACTED>',
|
|
352
|
+
],
|
|
353
|
+
// Cookies
|
|
354
|
+
[/(Cookie:\s*)[^\r\n]+/gi, '$1<REDACTED>'],
|
|
355
|
+
[/(Set-Cookie:\s*)[^\r\n]+/gi, '$1<REDACTED>'],
|
|
356
|
+
// JSON-style Cookie fields ("Cookie": "...")
|
|
357
|
+
[/(\b(?:Cookie|Set-Cookie)\b)(\s*["']?\s*[:=]\s*["']?)[^\r\n"']+/gi, '$1$2<REDACTED>'],
|
|
358
|
+
// Common API header patterns (supports JSON-style)
|
|
359
|
+
[
|
|
360
|
+
/(\b(?:x-api-key|api-key|x-auth-token|x-access-token)\b)(\s*["']?\s*[:=]\s*["']?)([^\s"']+)/gi,
|
|
361
|
+
'$1$2<REDACTED>',
|
|
362
|
+
],
|
|
363
|
+
// Email addresses
|
|
364
|
+
[/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, '<EMAIL>'],
|
|
365
|
+
// User paths (Windows and macOS/Linux)
|
|
366
|
+
[/[A-Z]:\\Users\\[^\\]+/gi, '<USERPROFILE>'],
|
|
367
|
+
[/\/Users\/[^/]+/g, '/Users/<USER>'],
|
|
368
|
+
];
|
|
369
|
+
return (input) => {
|
|
370
|
+
let out = input;
|
|
371
|
+
for (const [re, replacement] of literalReplacements) {
|
|
372
|
+
out = out.replace(re, replacement);
|
|
373
|
+
}
|
|
374
|
+
for (const [re, replacement] of patternReplacements) {
|
|
375
|
+
out = out.replace(re, replacement);
|
|
376
|
+
}
|
|
377
|
+
return out;
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function redactDeep(value, redact) {
|
|
381
|
+
if (typeof value === 'string')
|
|
382
|
+
return redact(value);
|
|
383
|
+
if (Array.isArray(value))
|
|
384
|
+
return value.map((v) => redactDeep(v, redact));
|
|
385
|
+
if (value && typeof value === 'object') {
|
|
386
|
+
const obj = value;
|
|
387
|
+
const out = {};
|
|
388
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
389
|
+
out[k] = redactDeep(v, redact);
|
|
390
|
+
}
|
|
391
|
+
return out;
|
|
392
|
+
}
|
|
393
|
+
return value;
|
|
394
|
+
}
|
|
395
|
+
// ============================================================================
|
|
396
|
+
// Output Rendering
|
|
397
|
+
// ============================================================================
|
|
398
|
+
function renderMarkdown(report) {
|
|
399
|
+
var _a, _b, _c, _d, _e;
|
|
400
|
+
const lines = [];
|
|
401
|
+
lines.push(`# ${report.tool.name} Diagnostic Report`);
|
|
402
|
+
lines.push('');
|
|
403
|
+
lines.push(`**Generated:** ${report.timestamp}`);
|
|
404
|
+
lines.push(`**Redaction:** ${report.redaction.enabled ? 'enabled (default)' : 'disabled'}`);
|
|
405
|
+
lines.push('');
|
|
406
|
+
lines.push('## Environment');
|
|
407
|
+
lines.push('');
|
|
408
|
+
lines.push(`- **Platform:** ${report.environment.platform} (${report.environment.arch})`);
|
|
409
|
+
lines.push(`- **OS:** ${report.environment.os.type} ${report.environment.os.release}${report.environment.os.version ? ` (${report.environment.os.version})` : ''}`);
|
|
410
|
+
lines.push(`- **Node:** ${report.environment.node.version}`);
|
|
411
|
+
lines.push(`- **Node execPath:** \`${report.environment.node.execPath}\``);
|
|
412
|
+
lines.push(`- **CWD:** \`${report.environment.cwd}\``);
|
|
413
|
+
lines.push('');
|
|
414
|
+
lines.push('## Package Managers');
|
|
415
|
+
lines.push('');
|
|
416
|
+
lines.push(`- **npm:** ${(_a = report.packageManager.npm.version) !== null && _a !== void 0 ? _a : `ERROR: ${(_b = report.packageManager.npm.error) !== null && _b !== void 0 ? _b : 'unknown'}`}`);
|
|
417
|
+
lines.push(`- **pnpm:** ${(_c = report.packageManager.pnpm.version) !== null && _c !== void 0 ? _c : `ERROR: ${(_d = report.packageManager.pnpm.error) !== null && _d !== void 0 ? _d : 'unknown'}`}`);
|
|
418
|
+
lines.push('');
|
|
419
|
+
lines.push('## Relevant Environment Variables');
|
|
420
|
+
lines.push('');
|
|
421
|
+
for (const [k, v] of Object.entries(report.environment.env)) {
|
|
422
|
+
lines.push(`- \`${k}\`: ${v !== null && v !== void 0 ? v : '<unset>'}`);
|
|
423
|
+
}
|
|
424
|
+
lines.push('');
|
|
425
|
+
lines.push('## Doctor Output');
|
|
426
|
+
lines.push('');
|
|
427
|
+
if (report.doctor) {
|
|
428
|
+
lines.push('<details>');
|
|
429
|
+
lines.push('<summary>Click to expand doctor JSON</summary>');
|
|
430
|
+
lines.push('');
|
|
431
|
+
lines.push('```json');
|
|
432
|
+
lines.push(JSON.stringify(report.doctor, null, 2));
|
|
433
|
+
lines.push('```');
|
|
434
|
+
lines.push('</details>');
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
lines.push(`**Doctor failed:** ${(_e = report.doctorError) !== null && _e !== void 0 ? _e : 'unknown error'}`);
|
|
438
|
+
}
|
|
439
|
+
lines.push('');
|
|
440
|
+
lines.push('## Wrapper Logs');
|
|
441
|
+
lines.push('');
|
|
442
|
+
lines.push(`**Log directory:** \`${report.wrapperLogs.dir}\``);
|
|
443
|
+
lines.push(`**Mode:** ${report.wrapperLogs.mode}`);
|
|
444
|
+
if (report.wrapperLogs.error) {
|
|
445
|
+
lines.push(`**Error:** ${report.wrapperLogs.error}`);
|
|
446
|
+
}
|
|
447
|
+
lines.push('');
|
|
448
|
+
if (report.wrapperLogs.files.length === 0) {
|
|
449
|
+
lines.push('No wrapper logs found.');
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
for (const f of report.wrapperLogs.files) {
|
|
453
|
+
lines.push(`### ${f.name}`);
|
|
454
|
+
lines.push('');
|
|
455
|
+
lines.push(`- **Path:** \`${f.path}\``);
|
|
456
|
+
if (f.mtime)
|
|
457
|
+
lines.push(`- **Modified:** ${f.mtime}`);
|
|
458
|
+
if (typeof f.size === 'number')
|
|
459
|
+
lines.push(`- **Size:** ${f.size} bytes`);
|
|
460
|
+
if (f.note)
|
|
461
|
+
lines.push(`- **Note:** ${f.note}`);
|
|
462
|
+
if (f.error) {
|
|
463
|
+
lines.push(`- **Error:** ${f.error}`);
|
|
464
|
+
lines.push('');
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
if (typeof f.content === 'string') {
|
|
468
|
+
if (f.truncated)
|
|
469
|
+
lines.push('*(Truncated)*');
|
|
470
|
+
lines.push('');
|
|
471
|
+
lines.push('<details>');
|
|
472
|
+
lines.push('<summary>Click to expand log content</summary>');
|
|
473
|
+
lines.push('');
|
|
474
|
+
lines.push('```text');
|
|
475
|
+
lines.push(f.content);
|
|
476
|
+
lines.push('```');
|
|
477
|
+
lines.push('</details>');
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
lines.push('*(Content omitted)*');
|
|
481
|
+
}
|
|
482
|
+
lines.push('');
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
lines.push('');
|
|
486
|
+
lines.push('## Manifests');
|
|
487
|
+
lines.push('');
|
|
488
|
+
for (const m of report.manifests) {
|
|
489
|
+
lines.push(`### ${m.browser} (${m.scope})`);
|
|
490
|
+
lines.push('');
|
|
491
|
+
lines.push(`- **Path:** \`${m.path}\``);
|
|
492
|
+
if (!m.exists) {
|
|
493
|
+
lines.push('- **Status:** not found');
|
|
494
|
+
lines.push('');
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (m.error) {
|
|
498
|
+
lines.push(`- **Status:** error (${m.error})`);
|
|
499
|
+
}
|
|
500
|
+
if (m.json !== undefined) {
|
|
501
|
+
lines.push('');
|
|
502
|
+
lines.push('```json');
|
|
503
|
+
lines.push(JSON.stringify(m.json, null, 2));
|
|
504
|
+
lines.push('```');
|
|
505
|
+
}
|
|
506
|
+
else if (typeof m.raw === 'string') {
|
|
507
|
+
lines.push('');
|
|
508
|
+
lines.push('```text');
|
|
509
|
+
lines.push(m.raw);
|
|
510
|
+
lines.push('```');
|
|
511
|
+
}
|
|
512
|
+
lines.push('');
|
|
513
|
+
}
|
|
514
|
+
if (report.windowsRegistry) {
|
|
515
|
+
lines.push('## Windows Registry');
|
|
516
|
+
lines.push('');
|
|
517
|
+
for (const entry of report.windowsRegistry.entries) {
|
|
518
|
+
lines.push(`### ${entry.browser} (${entry.scope})`);
|
|
519
|
+
lines.push('');
|
|
520
|
+
lines.push(`- **Key:** \`${entry.key}\``);
|
|
521
|
+
lines.push(`- **Expected manifest:** \`${entry.expectedManifestPath}\``);
|
|
522
|
+
if (entry.error) {
|
|
523
|
+
lines.push(`- **Error:** ${entry.error}`);
|
|
524
|
+
lines.push('');
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
if (entry.value)
|
|
528
|
+
lines.push(`- **Default value:** \`${entry.value}\``);
|
|
529
|
+
if (entry.raw) {
|
|
530
|
+
lines.push('');
|
|
531
|
+
lines.push('```text');
|
|
532
|
+
lines.push(entry.raw);
|
|
533
|
+
lines.push('```');
|
|
534
|
+
}
|
|
535
|
+
lines.push('');
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
lines.push('---');
|
|
539
|
+
lines.push('');
|
|
540
|
+
lines.push('> If you are opening a GitHub Issue, paste everything above. ' +
|
|
541
|
+
`You can disable redaction with: \`${report.tool.name} report --no-redact\``);
|
|
542
|
+
return lines.join('\n');
|
|
543
|
+
}
|
|
544
|
+
function writeOutput(outputPath, content) {
|
|
545
|
+
if (!outputPath || outputPath === '-' || outputPath.toLowerCase() === 'stdout') {
|
|
546
|
+
process.stdout.write(content);
|
|
547
|
+
return { ok: true, destination: 'stdout' };
|
|
548
|
+
}
|
|
549
|
+
try {
|
|
550
|
+
const resolved = path_1.default.resolve(outputPath);
|
|
551
|
+
fs_1.default.writeFileSync(resolved, content, 'utf8');
|
|
552
|
+
return { ok: true, destination: resolved };
|
|
553
|
+
}
|
|
554
|
+
catch (e) {
|
|
555
|
+
return { ok: false, error: stringifyError(e) };
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
function tryCopyToClipboard(text) {
|
|
559
|
+
const spawn = (cmd, args) => {
|
|
560
|
+
var _a;
|
|
561
|
+
const res = (0, child_process_1.spawnSync)(cmd, args, {
|
|
562
|
+
input: text,
|
|
563
|
+
encoding: 'utf8',
|
|
564
|
+
timeout: 3000,
|
|
565
|
+
windowsHide: true,
|
|
566
|
+
});
|
|
567
|
+
if (res.error)
|
|
568
|
+
return { ok: false, error: stringifyError(res.error) };
|
|
569
|
+
if (res.status !== 0)
|
|
570
|
+
return { ok: false, error: `Exit code ${(_a = res.status) !== null && _a !== void 0 ? _a : 'unknown'}` };
|
|
571
|
+
return { ok: true };
|
|
572
|
+
};
|
|
573
|
+
if (process.platform === 'darwin') {
|
|
574
|
+
const r = spawn('pbcopy', []);
|
|
575
|
+
return r.ok ? { ok: true, method: 'pbcopy' } : { ok: false, method: 'pbcopy', error: r.error };
|
|
576
|
+
}
|
|
577
|
+
if (process.platform === 'win32') {
|
|
578
|
+
const r = spawn('clip', []);
|
|
579
|
+
return r.ok ? { ok: true, method: 'clip' } : { ok: false, method: 'clip', error: r.error };
|
|
580
|
+
}
|
|
581
|
+
// Linux: try wl-copy, xclip, xsel
|
|
582
|
+
for (const cmd of [
|
|
583
|
+
{ cmd: 'wl-copy', args: [] },
|
|
584
|
+
{ cmd: 'xclip', args: ['-selection', 'clipboard'] },
|
|
585
|
+
{ cmd: 'xsel', args: ['--clipboard', '--input'] },
|
|
586
|
+
]) {
|
|
587
|
+
const r = spawn(cmd.cmd, cmd.args);
|
|
588
|
+
if (r.ok)
|
|
589
|
+
return { ok: true, method: cmd.cmd };
|
|
590
|
+
}
|
|
591
|
+
return { ok: false, error: 'No clipboard command available (tried wl-copy, xclip, xsel)' };
|
|
592
|
+
}
|
|
593
|
+
// ============================================================================
|
|
594
|
+
// Main Report Function
|
|
595
|
+
// ============================================================================
|
|
596
|
+
async function runReport(options) {
|
|
597
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
598
|
+
try {
|
|
599
|
+
const includeLogs = parseIncludeLogsMode(options.includeLogs);
|
|
600
|
+
const logLines = parsePositiveInt(options.logLines, DEFAULT_LOG_LINES);
|
|
601
|
+
const redactionEnabled = options.redact !== false;
|
|
602
|
+
const tool = getToolVersion();
|
|
603
|
+
const browsers = resolveBrowsers(options.browser);
|
|
604
|
+
// Collect doctor report
|
|
605
|
+
let doctor;
|
|
606
|
+
let doctorError;
|
|
607
|
+
try {
|
|
608
|
+
doctor = await (0, doctor_1.collectDoctorReport)({
|
|
609
|
+
json: true,
|
|
610
|
+
fix: false,
|
|
611
|
+
browser: options.browser,
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
catch (e) {
|
|
615
|
+
doctorError = stringifyError(e);
|
|
616
|
+
}
|
|
617
|
+
// Build the report
|
|
618
|
+
const report = {
|
|
619
|
+
schemaVersion: REPORT_SCHEMA_VERSION,
|
|
620
|
+
timestamp: new Date().toISOString(),
|
|
621
|
+
tool,
|
|
622
|
+
environment: {
|
|
623
|
+
platform: process.platform,
|
|
624
|
+
arch: process.arch,
|
|
625
|
+
node: { version: process.version, execPath: process.execPath },
|
|
626
|
+
os: { type: os_1.default.type(), release: os_1.default.release(), version: safeOsVersion() },
|
|
627
|
+
cwd: process.cwd(),
|
|
628
|
+
env: {
|
|
629
|
+
CHROME_MCP_NODE_PATH: (_a = process.env.CHROME_MCP_NODE_PATH) !== null && _a !== void 0 ? _a : null,
|
|
630
|
+
VOLTA_HOME: (_b = process.env.VOLTA_HOME) !== null && _b !== void 0 ? _b : null,
|
|
631
|
+
ASDF_DATA_DIR: (_c = process.env.ASDF_DATA_DIR) !== null && _c !== void 0 ? _c : null,
|
|
632
|
+
FNM_DIR: (_d = process.env.FNM_DIR) !== null && _d !== void 0 ? _d : null,
|
|
633
|
+
NVM_DIR: (_e = process.env.NVM_DIR) !== null && _e !== void 0 ? _e : null,
|
|
634
|
+
// nvm-windows uses different environment variables
|
|
635
|
+
NVM_HOME: (_f = process.env.NVM_HOME) !== null && _f !== void 0 ? _f : null,
|
|
636
|
+
NVM_SYMLINK: (_g = process.env.NVM_SYMLINK) !== null && _g !== void 0 ? _g : null,
|
|
637
|
+
npm_config_user_agent: (_h = process.env.npm_config_user_agent) !== null && _h !== void 0 ? _h : null,
|
|
638
|
+
},
|
|
639
|
+
},
|
|
640
|
+
packageManager: {
|
|
641
|
+
npm: safeExecVersion('npm'),
|
|
642
|
+
pnpm: safeExecVersion('pnpm'),
|
|
643
|
+
},
|
|
644
|
+
doctor,
|
|
645
|
+
doctorError,
|
|
646
|
+
manifests: collectManifests(browsers),
|
|
647
|
+
wrapperLogs: collectWrapperLogs((0, utils_1.getLogDir)(), includeLogs, logLines),
|
|
648
|
+
windowsRegistry: process.platform === 'win32' ? collectWindowsRegistry(browsers) : undefined,
|
|
649
|
+
redaction: { enabled: redactionEnabled },
|
|
650
|
+
};
|
|
651
|
+
// Apply redaction
|
|
652
|
+
const redact = createRedactor(redactionEnabled);
|
|
653
|
+
const finalReport = redactionEnabled
|
|
654
|
+
? redactDeep(report, redact)
|
|
655
|
+
: report;
|
|
656
|
+
// Render output
|
|
657
|
+
const output = options.json
|
|
658
|
+
? JSON.stringify(finalReport, null, 2) + '\n'
|
|
659
|
+
: renderMarkdown(finalReport) + '\n';
|
|
660
|
+
// Write output
|
|
661
|
+
const write = writeOutput(options.output, output);
|
|
662
|
+
if (!write.ok) {
|
|
663
|
+
process.stderr.write(`Failed to write report: ${write.error}\n`);
|
|
664
|
+
process.stdout.write(output);
|
|
665
|
+
}
|
|
666
|
+
else if (write.destination !== 'stdout') {
|
|
667
|
+
process.stderr.write(`Report written to: ${write.destination}\n`);
|
|
668
|
+
}
|
|
669
|
+
// Copy to clipboard if requested
|
|
670
|
+
if (options.copy) {
|
|
671
|
+
const copied = tryCopyToClipboard(output);
|
|
672
|
+
if (copied.ok) {
|
|
673
|
+
process.stderr.write(`Copied to clipboard (${copied.method})\n`);
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
process.stderr.write(`Failed to copy to clipboard: ${(_j = copied.error) !== null && _j !== void 0 ? _j : 'unknown error'}\n`);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return 0;
|
|
680
|
+
}
|
|
681
|
+
catch (e) {
|
|
682
|
+
process.stderr.write(`Report failed: ${stringifyError(e)}\n`);
|
|
683
|
+
return 1;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
//# sourceMappingURL=report.js.map
|