mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-14 17:05:28 +02:00
Add windowsHide:true at every remaining direct child_process call in browse/src that could flash a console window on Windows: - project-slug.ts (execSync gstack-slug) - browser-skills.ts (cp.spawnSync git rev-parse) - security-sidecar-client.ts (spawn — the LONG-LIVED Node sidecar, whose missing flag parked a console window on the taskbar for the daemon's whole lifetime) - find-security-sidecar.ts (execFileSync node --version) - meta-commands.ts (execSync git rev-parse in inbox + the osascript activate call) - browse-client.ts (cp.spawnSync git rev-parse) - file-permissions.ts (execFileSync whoami.exe — Windows-only, ran bare) - cli.ts (nodeSpawn osascript) windows-spawn-hide.test.ts gains a SWEEP test on top of the existing needles: it censuses EVERY child_process binding in src/ (static imports incl. aliases, `await import()` / require destructures, and `import * as cp` namespaces — 15 call sites across 10 files today) and fails CI on any call without windowsHide within its options window. Exemptions carry reasons — the one today is domain-skill-commands' interactive $EDITOR spawn (stdio:'inherit'; CREATE_NO_WINDOW would detach a console editor into an invisible console). Tests: windows-spawn-hide 5 pass; file-permissions 19 pass; browse-client 28 pass; browser-skill-commands 29 pass (81/81 combined). Fixes the app-side half of #2160; closes out #2415's residuals. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
79 lines
2.6 KiB
TypeScript
79 lines
2.6 KiB
TypeScript
/**
|
|
* find-security-sidecar — resolve the Node entry that runs the L4 ML
|
|
* classifier sidecar.
|
|
*
|
|
* The sidecar can't be bundled into the compiled browse binary because
|
|
* onnxruntime-node fails to dlopen from Bun's compile extract dir. It runs
|
|
* as a separate Node subprocess instead. This module resolves the right
|
|
* path + interpreter on each platform:
|
|
*
|
|
* 1. Prefer node on PATH + a bundled JS entry at
|
|
* browse/dist/security-sidecar.js (built by package.json's
|
|
* build:security-sidecar script).
|
|
* 2. Dev fallback: node + browse/src/security-sidecar-entry.ts via tsx
|
|
* (only available in the source checkout, not the compiled install).
|
|
* 3. If Node is missing or no entry resolves, return null. The /pty-inject-scan
|
|
* endpoint then responds with l4 { available: false } and the extension
|
|
* degrades to WARN+confirm (D7).
|
|
*/
|
|
|
|
import { existsSync } from "fs";
|
|
import { join, dirname } from "path";
|
|
import { execFileSync } from "child_process";
|
|
|
|
export interface SidecarLocation {
|
|
node: string;
|
|
entry: string;
|
|
/** "compiled" if running from browse/dist/, "dev" if running from src */
|
|
mode: "compiled" | "dev";
|
|
}
|
|
|
|
function nodeOnPath(): string | null {
|
|
try {
|
|
execFileSync("node", ["--version"], { stdio: "ignore", timeout: 2000, windowsHide: true });
|
|
return "node";
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function browseRoot(): string {
|
|
// When running compiled, __dirname (via import.meta.dir) points at the
|
|
// Bun extract temp. Walk up until we find a directory containing
|
|
// browse/dist/ or browse/src/.
|
|
let candidate = dirname(import.meta.path || "");
|
|
for (let i = 0; i < 6; i += 1) {
|
|
if (existsSync(join(candidate, "browse", "dist", "security-sidecar.js"))) {
|
|
return candidate;
|
|
}
|
|
if (existsSync(join(candidate, "src", "security-sidecar-entry.ts"))) {
|
|
return candidate;
|
|
}
|
|
const next = dirname(candidate);
|
|
if (next === candidate) break;
|
|
candidate = next;
|
|
}
|
|
return process.cwd();
|
|
}
|
|
|
|
export function findSecuritySidecar(): SidecarLocation | null {
|
|
const node = nodeOnPath();
|
|
if (!node) return null;
|
|
|
|
const root = browseRoot();
|
|
|
|
const compiled = join(root, "browse", "dist", "security-sidecar.js");
|
|
if (existsSync(compiled)) {
|
|
return { node, entry: compiled, mode: "compiled" };
|
|
}
|
|
|
|
// Dev fallback. Compiled installs won't have src/ on disk so this only
|
|
// resolves when running from the source checkout.
|
|
const devEntry = join(root, "src", "security-sidecar-entry.ts");
|
|
if (existsSync(devEntry)) {
|
|
return { node, entry: devEntry, mode: "dev" };
|
|
}
|
|
|
|
return null;
|
|
}
|