cc-viewer 1.9.16 → 1.9.18
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/cli.js +17 -1
- package/dist/assets/{App-CYdOioAz.js → App-COyZwmVt.js} +2 -2
- package/dist/assets/{MdxEditorPanel-CuCAe1OG.js → MdxEditorPanel-BsHDgZCY.js} +1 -1
- package/dist/assets/Mobile-B1H_PrNl.js +1 -0
- package/dist/assets/{ProxyStatsModal-Dhj4EVnh.js → ProxyStatsModal-CSQNNwpU.js} +1 -1
- package/dist/assets/index-CPn0gvr6.js +2 -0
- package/dist/assets/seqResourceLoaders-Cm1JnNsu.js +2 -0
- package/dist/assets/{seqResourceLoaders-B-5xGs9q.css → seqResourceLoaders-DZA-JHK0.css} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/server/lib/file-access-policy.js +108 -3
- package/server/lib/os-open.js +66 -0
- package/server/lib/plugin-loader.js +34 -2
- package/server/lib/sdk-manager.js +450 -45
- package/server/lib/target-scope.js +174 -0
- package/server/proxy.js +52 -8
- package/server/routes/files-content.js +80 -133
- package/server/routes/files-fs.js +8 -54
- package/server/routes/target-files-fs.js +332 -0
- package/server/server.js +59 -12
- package/dist/assets/Mobile-CfNYOgRa.js +0 -1
- package/dist/assets/index-sgW8MlD3.js +0 -2
- package/dist/assets/seqResourceLoaders-Cj0pdz-l.js +0 -2
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Shared OS-integration helpers (open in file manager / terminal) used by both
|
|
2
|
+
// the project-scoped routes (files-fs.js) and the target-mode write routes
|
|
3
|
+
// (target-files-fs.js). Centralizing the platform branches keeps the two call
|
|
4
|
+
// surfaces from drifting apart (a Windows quoting or Linux terminal-fallback fix
|
|
5
|
+
// must apply to both). Pure argv spawning — no shell — so no metachar injection.
|
|
6
|
+
//
|
|
7
|
+
// L1 (lib): must NOT import from routes/ (verify:boundaries).
|
|
8
|
+
import { execFile, spawn } from 'node:child_process';
|
|
9
|
+
import { dirname } from 'node:path';
|
|
10
|
+
import { reportSwallowed } from './error-report.js';
|
|
11
|
+
|
|
12
|
+
// Reveal a file (select it) or open a directory in the OS file manager.
|
|
13
|
+
// - macOS: `open -R <path>` selects files AND opens directories in place.
|
|
14
|
+
// - Windows: `explorer /select,"<path>"` (verbatim args; a dir path opens it).
|
|
15
|
+
// - Linux: no select concept — open the path itself when it is a directory,
|
|
16
|
+
// otherwise its parent. (xdg-open on a FILE would launch the default app, so
|
|
17
|
+
// callers pass `isDir` to pick the directory to show.)
|
|
18
|
+
export function revealInOs(fullPath, { isDir = false } = {}) {
|
|
19
|
+
const plat = process.platform;
|
|
20
|
+
if (plat === 'darwin') {
|
|
21
|
+
execFile('open', ['-R', fullPath], () => {});
|
|
22
|
+
} else if (plat === 'win32') {
|
|
23
|
+
// windowsVerbatimArguments: Node would otherwise re-quote the spaced path into
|
|
24
|
+
// a form explorer cannot parse. No cmd.exe is involved, so no metachar risk;
|
|
25
|
+
// Windows filenames cannot contain `"`.
|
|
26
|
+
const child = spawn('explorer.exe', [`/select,"${fullPath}"`], { windowsVerbatimArguments: true, windowsHide: true });
|
|
27
|
+
child.on('error', (err) => { reportSwallowed('osOpen.reveal', err); });
|
|
28
|
+
} else {
|
|
29
|
+
execFile('xdg-open', [isDir ? fullPath : dirname(fullPath)], () => {});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Open an OS terminal with cwd = dir. Linux probes common emulators with piped
|
|
34
|
+
// stdio so the next candidate is tried after ENOENT, falling back to xdg-open.
|
|
35
|
+
export function openTerminalAt(dir) {
|
|
36
|
+
const plat = process.platform;
|
|
37
|
+
if (plat === 'darwin') {
|
|
38
|
+
const child = spawn('open', ['-a', 'Terminal', dir], { stdio: 'ignore', detached: true });
|
|
39
|
+
child.on('error', (err) => { reportSwallowed('osOpen.terminal', err, { terminal: 'Terminal.app' }); });
|
|
40
|
+
child.unref();
|
|
41
|
+
} else if (plat === 'win32') {
|
|
42
|
+
const child = spawn('cmd.exe', ['/c', 'start', 'cmd.exe'], { cwd: dir, stdio: 'ignore', detached: true, windowsHide: true });
|
|
43
|
+
child.on('error', (err) => { reportSwallowed('osOpen.terminal', err, { terminal: 'cmd.exe' }); });
|
|
44
|
+
child.unref();
|
|
45
|
+
} else {
|
|
46
|
+
const terminals = ['gnome-terminal', 'konsole', 'xfce4-terminal', 'xterm'];
|
|
47
|
+
const tryTerminal = (index) => {
|
|
48
|
+
if (index >= terminals.length) {
|
|
49
|
+
const child = spawn('xdg-open', [dir], { stdio: 'ignore', detached: true });
|
|
50
|
+
child.on('error', (err) => { reportSwallowed('osOpen.terminal', err, { terminal: 'xdg-open' }); });
|
|
51
|
+
child.unref();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const term = terminals[index];
|
|
55
|
+
let child;
|
|
56
|
+
try {
|
|
57
|
+
if (term === 'gnome-terminal') child = spawn(term, ['--working-directory=' + dir], { stdio: 'pipe' });
|
|
58
|
+
else if (term === 'konsole') child = spawn(term, ['--workdir', dir], { stdio: 'pipe' });
|
|
59
|
+
else child = spawn(term, [], { cwd: dir, stdio: 'pipe' });
|
|
60
|
+
} catch { tryTerminal(index + 1); return; }
|
|
61
|
+
child.once('error', (err) => { reportSwallowed('osOpen.terminal', err, { terminal: term }); tryTerminal(index + 1); });
|
|
62
|
+
child.once('spawn', () => { for (const s of [child.stdin, child.stdout, child.stderr]) s?.destroy(); child.unref(); });
|
|
63
|
+
};
|
|
64
|
+
tryTerminal(0);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -33,6 +33,13 @@ const HOOK_TYPES = {
|
|
|
33
33
|
onStreamChunk: 'parallel',
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
// Approval hooks gate an interactive UI modal, so a hung plugin must not park the approval
|
|
37
|
+
// forever: each invocation times out and falls back to the normal approval modal.
|
|
38
|
+
// Non-approval waterfall hooks (beforeRequest/httpsOptions/localUrl) are startup/auth-critical
|
|
39
|
+
// and stay UNTIMED.
|
|
40
|
+
const APPROVAL_HOOK_TIMEOUT_MS = 15 * 1000;
|
|
41
|
+
const APPROVAL_HOOKS = new Set(['onPlanRequest', 'onAskRequest', 'onPermRequest']);
|
|
42
|
+
|
|
36
43
|
let _plugins = [];
|
|
37
44
|
// Full result of the last loadPlugins (directory service/panel plugins and failures included)
|
|
38
45
|
let _entries = [];
|
|
@@ -312,14 +319,39 @@ export async function loadPlugins(opts = {}) {
|
|
|
312
319
|
|
|
313
320
|
/**
|
|
314
321
|
* waterfall hook:串行管道执行,前一个的返回值传给下一个
|
|
322
|
+
* `timeoutMsOverride` is test-only; approval hooks default to APPROVAL_HOOK_TIMEOUT_MS.
|
|
315
323
|
*/
|
|
316
|
-
export async function runWaterfallHook(name, initialValue) {
|
|
324
|
+
export async function runWaterfallHook(name, initialValue, timeoutMsOverride) {
|
|
317
325
|
let value = initialValue;
|
|
326
|
+
// Only approval hooks are timed out; the override is ignored for the other hooks.
|
|
327
|
+
const timeoutMs = APPROVAL_HOOKS.has(name)
|
|
328
|
+
? (timeoutMsOverride ?? APPROVAL_HOOK_TIMEOUT_MS)
|
|
329
|
+
: undefined;
|
|
318
330
|
for (const plugin of _plugins) {
|
|
319
331
|
const hookFn = plugin.hooks[name];
|
|
320
332
|
if (typeof hookFn !== 'function') continue;
|
|
321
333
|
try {
|
|
322
|
-
|
|
334
|
+
let result;
|
|
335
|
+
if (timeoutMs !== undefined) {
|
|
336
|
+
// A timed-out hook promise itself is not cancellable (bounded leak: it may keep
|
|
337
|
+
// running in the background); the timer is cleared as soon as the hook settles.
|
|
338
|
+
let timer;
|
|
339
|
+
try {
|
|
340
|
+
result = await Promise.race([
|
|
341
|
+
Promise.resolve().then(() => hookFn(value)),
|
|
342
|
+
new Promise((_, reject) => {
|
|
343
|
+
timer = setTimeout(
|
|
344
|
+
() => reject(new Error(`hook timed out after ${timeoutMs} ms`)),
|
|
345
|
+
timeoutMs
|
|
346
|
+
);
|
|
347
|
+
}),
|
|
348
|
+
]);
|
|
349
|
+
} finally {
|
|
350
|
+
clearTimeout(timer);
|
|
351
|
+
}
|
|
352
|
+
} else {
|
|
353
|
+
result = await hookFn(value);
|
|
354
|
+
}
|
|
323
355
|
if (result != null && typeof result === 'object') {
|
|
324
356
|
value = { ...value, ...result };
|
|
325
357
|
}
|