mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-01 12:02:05 +00:00
The bootstrap-runner PowerShell spawn is formatted multiline (spawn(\n ps,\n fullArgs,...), so the literal substring 'spawn(ps, fullArgs' never matched and the assertion was failing on main independent of #54635. Convert it to a whitespace-tolerant regex like every other call-site assertion in this file.
93 lines
4.2 KiB
JavaScript
93 lines
4.2 KiB
JavaScript
'use strict'
|
|
|
|
const test = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
const fs = require('node:fs')
|
|
const path = require('node:path')
|
|
|
|
const ELECTRON_DIR = __dirname
|
|
|
|
function readElectronFile(name) {
|
|
return fs.readFileSync(path.join(ELECTRON_DIR, name), 'utf8').replace(/\r\n/g, '\n')
|
|
}
|
|
|
|
function requireHiddenChildOptions(source, needle) {
|
|
const match = needle instanceof RegExp ? needle.exec(source) : null
|
|
const index = needle instanceof RegExp ? (match?.index ?? -1) : source.indexOf(needle)
|
|
assert.notEqual(index, -1, `missing call site: ${needle}`)
|
|
const snippet = source.slice(index, index + 700)
|
|
assert.match(
|
|
snippet,
|
|
/hiddenWindowsChildOptions\(/,
|
|
`expected ${needle} to wrap child-process options with hiddenWindowsChildOptions`
|
|
)
|
|
}
|
|
|
|
test('desktop background child processes opt into hidden Windows consoles', () => {
|
|
const source = readElectronFile('main.cjs')
|
|
|
|
assert.match(source, /function hiddenWindowsChildOptions\(options = \{\}\)/)
|
|
|
|
requireHiddenChildOptions(source, "execFileSync(\n 'reg'")
|
|
requireHiddenChildOptions(source, /execFileSync\(\s*pyExe/)
|
|
requireHiddenChildOptions(source, /spawn\(\s*resolveGitBinary\(\)/)
|
|
requireHiddenChildOptions(source, "execFileSync('taskkill'")
|
|
requireHiddenChildOptions(source, /spawn\(\s*command,\s*args/)
|
|
requireHiddenChildOptions(source, "spawn('curl'")
|
|
requireHiddenChildOptions(source, /spawn\(\s*backend\.command,\s*backend\.args/)
|
|
requireHiddenChildOptions(source, /hermesProcess = spawn\(\s*backend\.command,\s*backend\.args/)
|
|
requireHiddenChildOptions(source, /spawn\(\s*py,\s*\['-m', 'hermes_cli\.main', 'uninstall', '--gui-summary'\]/)
|
|
|
|
assert.match(source, /function unwrapWindowsVenvHermesCommand\(command, backendArgs\)/)
|
|
assert.match(source, /function getVenvSitePackagesEntries\(venvRoot\)/)
|
|
assert.match(source, /path\.join\(venvRoot, 'Lib', 'site-packages'\)/)
|
|
assert.match(source, /args: \['-m', 'hermes_cli\.main', \.\.\.backendArgs\]/)
|
|
})
|
|
|
|
test('desktop backend launches console python so child consoles are inherited, not pythonw', () => {
|
|
const source = readElectronFile('main.cjs')
|
|
|
|
// The flash fix is structural: the backend runs as a console-subsystem
|
|
// python.exe under hiddenWindowsChildOptions() (-> CREATE_NO_WINDOW), so it
|
|
// owns ONE windowless console that every descendant spawn inherits. Launching
|
|
// it as GUI-subsystem pythonw.exe is what made each child allocate (and flash)
|
|
// its own console, so the backend command must never be pythonw.
|
|
assert.doesNotMatch(source, /pythonw\.exe'\)/, 'backend must not be launched via pythonw.exe')
|
|
assert.doesNotMatch(
|
|
source,
|
|
/function getNoConsoleVenvPython\b/,
|
|
'pythonw-conversion helper should be gone; console python is launched directly'
|
|
)
|
|
assert.doesNotMatch(
|
|
source,
|
|
/function applyWindowsNoConsoleSpawnHints\b/,
|
|
'pythonw spawn-hint rewriter should be gone'
|
|
)
|
|
|
|
// Console python restores stdout, so the port is announced on the normal
|
|
// HERMES_DASHBOARD_READY stdout line — no ready-file side channel is set.
|
|
assert.doesNotMatch(source, /readyFile: true/, 'no backend should opt into the pythonw ready-file path')
|
|
|
|
// Both desktop backend launches must still go through hiddenWindowsChildOptions
|
|
// so the single backend console is created windowless.
|
|
requireHiddenChildOptions(source, /spawn\(\s*backend\.command,\s*backend\.args/)
|
|
requireHiddenChildOptions(source, /hermesProcess = spawn\(\s*backend\.command,\s*backend\.args/)
|
|
})
|
|
|
|
test('intentional or interactive desktop child processes stay documented', () => {
|
|
const source = readElectronFile('main.cjs')
|
|
|
|
assert.match(source, /windowsHide: false/)
|
|
assert.match(source, /handOffWindowsBootstrapRecovery/)
|
|
assert.match(source, /'--repair', '--branch'/)
|
|
assert.match(source, /'--update', '--branch'/)
|
|
assert.match(source, /nodePty\.spawn\(command, args/)
|
|
assert.match(source, /spawn\('cmd\.exe', \['\/c', 'start'/)
|
|
})
|
|
|
|
test('bootstrap PowerShell runner hides Windows console children', () => {
|
|
const source = readElectronFile('bootstrap-runner.cjs')
|
|
|
|
assert.match(source, /function hiddenWindowsChildOptions\(options = \{\}\)/)
|
|
requireHiddenChildOptions(source, /spawn\(\s*ps,\s*fullArgs/)
|
|
})
|