fix: prevent Windows terminal popups with windowsHide option
Add windowsHide: true to all spawn/execFile calls in bin and server code to prevent new console windows from appearing on Windows. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -86,6 +86,7 @@ function startDaemon(port) {
|
|||||||
detached: true,
|
detached: true,
|
||||||
stdio: ['ignore', logStream, logStream],
|
stdio: ['ignore', logStream, logStream],
|
||||||
env: { ...process.env, PORT: String(port) },
|
env: { ...process.env, PORT: String(port) },
|
||||||
|
windowsHide: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
child.on('error', (err) => {
|
child.on('error', (err) => {
|
||||||
@@ -199,6 +200,7 @@ function doUpdate() {
|
|||||||
|
|
||||||
const child = spawn(isWin ? 'cmd' : 'sh', isWin ? ['/c', ...cmd.split(' ')] : ['-c', cmd], {
|
const child = spawn(isWin ? 'cmd' : 'sh', isWin ? ['/c', ...cmd.split(' ')] : ['-c', cmd], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
|
windowsHide: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
child.on('exit', (code) => {
|
child.on('exit', (code) => {
|
||||||
@@ -235,6 +237,7 @@ switch (command) {
|
|||||||
const child = spawn(process.execPath, [serverEntry], {
|
const child = spawn(process.execPath, [serverEntry], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
env: { ...process.env, PORT: String(port) },
|
env: { ...process.env, PORT: String(port) },
|
||||||
|
windowsHide: true,
|
||||||
})
|
})
|
||||||
child.on('exit', (code) => process.exit(code ?? 1))
|
child.on('exit', (code) => process.exit(code ?? 1))
|
||||||
process.on('SIGTERM', () => child.kill('SIGTERM'))
|
process.on('SIGTERM', () => child.kill('SIGTERM'))
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
"start": "vite --host --port 8648",
|
"start": "vite --host --port 8648",
|
||||||
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
|
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
|
||||||
"dev:client": "vite --host",
|
"dev:client": "vite --host",
|
||||||
"dev:server": "nodemon --watch server/src --ext ts --exec node -r ts-node/register server/src/index.ts",
|
"dev:server": "nodemon --watch server/src --ext ts --exec node -r ts-node/register server/src/index.ts --no-warnings",
|
||||||
"build": "vue-tsc -b && vite build && tsc -p server/tsconfig.json",
|
"build": "vue-tsc -b && vite build && tsc -p server/tsconfig.json",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { promisify } from 'util'
|
|||||||
|
|
||||||
const execFileAsync = promisify(execFile)
|
const execFileAsync = promisify(execFile)
|
||||||
|
|
||||||
|
const execOpts = { windowsHide: true }
|
||||||
|
|
||||||
export interface HermesSession {
|
export interface HermesSession {
|
||||||
id: string
|
id: string
|
||||||
source: string
|
source: string
|
||||||
@@ -65,6 +67,7 @@ export async function listSessions(source?: string, limit?: number): Promise<Her
|
|||||||
const { stdout } = await execFileAsync('hermes', args, {
|
const { stdout } = await execFileAsync('hermes', args, {
|
||||||
maxBuffer: 50 * 1024 * 1024, // 50MB
|
maxBuffer: 50 * 1024 * 1024, // 50MB
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
|
...execOpts,
|
||||||
})
|
})
|
||||||
|
|
||||||
const lines = stdout.trim().split('\n').filter(Boolean)
|
const lines = stdout.trim().split('\n').filter(Boolean)
|
||||||
@@ -128,6 +131,7 @@ export async function getSession(id: string): Promise<HermesSession | null> {
|
|||||||
const { stdout } = await execFileAsync('hermes', args, {
|
const { stdout } = await execFileAsync('hermes', args, {
|
||||||
maxBuffer: 50 * 1024 * 1024,
|
maxBuffer: 50 * 1024 * 1024,
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
|
...execOpts,
|
||||||
})
|
})
|
||||||
|
|
||||||
const lines = stdout.trim().split('\n').filter(Boolean)
|
const lines = stdout.trim().split('\n').filter(Boolean)
|
||||||
@@ -170,6 +174,7 @@ export async function deleteSession(id: string): Promise<boolean> {
|
|||||||
try {
|
try {
|
||||||
await execFileAsync('hermes', ['sessions', 'delete', id, '--yes'], {
|
await execFileAsync('hermes', ['sessions', 'delete', id, '--yes'], {
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
|
...execOpts,
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
@@ -185,6 +190,7 @@ export async function renameSession(id: string, title: string): Promise<boolean>
|
|||||||
try {
|
try {
|
||||||
await execFileAsync('hermes', ['sessions', 'rename', id, title], {
|
await execFileAsync('hermes', ['sessions', 'rename', id, title], {
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
|
...execOpts,
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
@@ -204,7 +210,7 @@ export interface LogFileInfo {
|
|||||||
*/
|
*/
|
||||||
export async function getVersion(): Promise<string> {
|
export async function getVersion(): Promise<string> {
|
||||||
try {
|
try {
|
||||||
const { stdout } = await execFileAsync('hermes', ['--version'], { timeout: 5000 })
|
const { stdout } = await execFileAsync('hermes', ['--version'], { timeout: 5000, ...execOpts })
|
||||||
return stdout.trim()
|
return stdout.trim()
|
||||||
} catch {
|
} catch {
|
||||||
return ''
|
return ''
|
||||||
@@ -217,6 +223,7 @@ export async function getVersion(): Promise<string> {
|
|||||||
export async function startGateway(): Promise<string> {
|
export async function startGateway(): Promise<string> {
|
||||||
const { stdout, stderr } = await execFileAsync('hermes', ['gateway', 'start'], {
|
const { stdout, stderr } = await execFileAsync('hermes', ['gateway', 'start'], {
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
|
...execOpts,
|
||||||
})
|
})
|
||||||
return stdout || stderr
|
return stdout || stderr
|
||||||
}
|
}
|
||||||
@@ -230,6 +237,7 @@ export async function startGatewayBackground(): Promise<number | null> {
|
|||||||
const child = spawn('hermes', ['gateway', 'run'], {
|
const child = spawn('hermes', ['gateway', 'run'], {
|
||||||
detached: true,
|
detached: true,
|
||||||
stdio: 'ignore',
|
stdio: 'ignore',
|
||||||
|
windowsHide: true,
|
||||||
})
|
})
|
||||||
child.unref()
|
child.unref()
|
||||||
return child.pid ?? null
|
return child.pid ?? null
|
||||||
@@ -241,6 +249,7 @@ export async function startGatewayBackground(): Promise<number | null> {
|
|||||||
export async function restartGateway(): Promise<string> {
|
export async function restartGateway(): Promise<string> {
|
||||||
const { stdout, stderr } = await execFileAsync('hermes', ['gateway', 'restart'], {
|
const { stdout, stderr } = await execFileAsync('hermes', ['gateway', 'restart'], {
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
|
...execOpts,
|
||||||
})
|
})
|
||||||
return stdout || stderr
|
return stdout || stderr
|
||||||
}
|
}
|
||||||
@@ -252,6 +261,7 @@ export async function listLogFiles(): Promise<LogFileInfo[]> {
|
|||||||
try {
|
try {
|
||||||
const { stdout } = await execFileAsync('hermes', ['logs', 'list'], {
|
const { stdout } = await execFileAsync('hermes', ['logs', 'list'], {
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
|
...execOpts,
|
||||||
})
|
})
|
||||||
const files: LogFileInfo[] = []
|
const files: LogFileInfo[] = []
|
||||||
const lines = stdout.trim().split('\n').filter(l => l.includes('.log'))
|
const lines = stdout.trim().split('\n').filter(l => l.includes('.log'))
|
||||||
@@ -291,6 +301,7 @@ export async function readLogs(
|
|||||||
const { stdout } = await execFileAsync('hermes', args, {
|
const { stdout } = await execFileAsync('hermes', args, {
|
||||||
maxBuffer: 10 * 1024 * 1024,
|
maxBuffer: 10 * 1024 * 1024,
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
|
...execOpts,
|
||||||
})
|
})
|
||||||
return stdout
|
return stdout
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
|||||||
Reference in New Issue
Block a user