import { mkdirSync, mkdtempSync, realpathSync } from 'node:fs' import { tmpdir } from 'node:os' import { join, resolve } from 'node:path' import { removeHostTree } from '../../src/main/host-tree-removal' import { decodePairingOffer, type PairingOffer } from '../../src/shared/pairing' import { sendRemoteRuntimeRequest } from '../../src/shared/remote-runtime-client' import type { RuntimeStatus, RuntimeTerminalRead } from '../../src/shared/runtime-types' import { verifyInstalledCliProfileBehavior } from './node-server-installed-cli-oracle' import { stopNodeServerVerifierDaemons } from './node-server-verifier-daemon-cleanup' import { initializeNodeServerVerifierGitWorkspace } from './node-server-verifier-git-fixture' import { isSameExistingHostPath } from './node-server-verifier-host-path' import { startNodeServerVerifierProcess, stopNodeServerVerifierProcess, terminateNodeServerVerifierProcess, type NodeServerVerifierProcess } from './node-server-verifier-server-process' const cliPath = resolve(readArgument('--cli') ?? 'resources/npm-server/dist/cli.js') const expectedVersion = readArgument('--expected-version') ?? packageVersionFromEnvironment() // Keep Unix daemon socket paths below platform limits while preserving Windows-native temp paths. const shortTemporaryRoot = process.platform === 'win32' ? tmpdir() : '/tmp' const ownedRoot = realpathSync.native(mkdtempSync(join(shortTemporaryRoot, 'orca-nsv-'))) const dataPath = join(ownedRoot, 'state') const gitPath = join(ownedRoot, 'git-workspace') const folderPath = join(ownedRoot, 'folder-workspace') async function main(): Promise { let activeServer: NodeServerVerifierProcess | null = null try { initializeNodeServerVerifierGitWorkspace(gitPath) mkdirSync(folderPath) const first = await startNodeServerVerifierProcess({ cliPath, dataPath }) activeServer = first const pairing = decodePairingOffer(first.ready.pairing.url) await verifyWebClient(first.ready.pairing.webClientUrl) await verifyStatus(pairing, first.ready.runtimeId, expectedVersion) await verifyBrowserUnavailable(pairing) await verifyGitWorkspace(pairing) const terminal = await verifyFolderWorkspaceAndTerminal(pairing) await verifyInstalledCliProfileBehavior({ cliPath, dataPath, expectedRuntimeId: first.ready.runtimeId, expectedVersion, pairingUrl: first.ready.pairing.url, terminalHandle: terminal.handle, temporaryRoot: ownedRoot }) await stopNodeServerVerifierProcess(first) activeServer = null const second = await startNodeServerVerifierProcess({ cliPath, dataPath }) activeServer = second assert( second.ready.runtimeId !== first.ready.runtimeId, 'runtime process identity did not rotate' ) const reconnectedPairing = { ...pairing, endpoint: second.ready.boundEndpoint } await verifyStatus(reconnectedPairing, second.ready.runtimeId, expectedVersion) const restored = await call<{ terminals: { handle: string; ptyId?: string }[] }>( reconnectedPairing, 'terminal.list', { worktree: terminal.workspaceSelector } ) assert(terminal.ptyId, 'created terminal did not expose its daemon identity') const reattached = restored.terminals.find((candidate) => candidate.ptyId === terminal.ptyId) assert(reattached, 'terminal daemon session was not adopted') await waitForTerminalMarker(reconnectedPairing, reattached.handle, terminal.marker) await stopNodeServerVerifierProcess(second) activeServer = null process.stdout.write('Node server runtime verification passed\n') } finally { if (activeServer?.child.exitCode === null && activeServer.child.signalCode === null) { await stopNodeServerVerifierProcess(activeServer).catch(() => terminateNodeServerVerifierProcess(activeServer.child) ) } await stopNodeServerVerifierDaemons(dataPath) await removeHostTree(ownedRoot) } } void main().catch((error) => { process.stderr.write( `${error instanceof Error ? (error.stack ?? error.message) : String(error)}\n` ) process.exitCode = 1 }) function readArgument(flag: string): string | undefined { const index = process.argv.indexOf(flag) return index === -1 ? undefined : process.argv[index + 1] } function packageVersionFromEnvironment(): string { return process.env.npm_package_version ?? '0.0.0-dev' } async function verifyWebClient(url: string): Promise { const response = await fetch(url, { signal: AbortSignal.timeout(15_000) }) assert(response.ok, `web client returned ${response.status}`) assert((await response.text()).includes(''), 'web client HTML was not served') } async function verifyStatus( pairing: PairingOffer, expectedRuntimeId: string, expectedAppVersion: string ): Promise { const status = await call(pairing, 'status.get') assert(status.runtimeId === expectedRuntimeId, 'status returned the wrong runtime') assert(status.appVersion === expectedAppVersion, 'status returned the wrong package version') assert(status.desktopWindowStatus === 'blocked', 'desktop status is not blocked') const capabilities = status.capabilities ?? [] for (const capability of [ 'browser.screencast.v1', 'browser.headless.v1', 'browser.certificate-trust.v1' ]) { assert( !capabilities.some((candidate) => candidate === capability), `browser capability leaked: ${capability}` ) } } async function verifyBrowserUnavailable(pairing: PairingOffer): Promise { try { await call(pairing, 'browser.tabCreate', { url: 'about:blank' }) } catch (error) { assert( error instanceof Error && error.message.includes('does not support browser panes'), 'browser request did not fail with an unsupported-host error' ) return } throw new Error('browser request unexpectedly succeeded') } async function verifyGitWorkspace(pairing: PairingOffer): Promise { const added = await call<{ repo: { id: string; path: string } }>(pairing, 'repo.add', { path: gitPath, kind: 'git' }) assert( isSameExistingHostPath(added.repo.path, gitPath), `repo.add returned an unexpected path: ${JSON.stringify(added.repo.path)}` ) const listed = await call<{ worktrees: { id: string; path: string }[] }>( pairing, 'worktree.list', { repo: `id:${added.repo.id}` } ) assert( listed.worktrees.length > 0, `Git worktree unavailable: ${JSON.stringify(listed.worktrees.map((worktree) => worktree.path))}` ) } async function verifyFolderWorkspaceAndTerminal(pairing: PairingOffer): Promise<{ handle: string marker: string ptyId: string | undefined workspaceSelector: string }> { const group = await call<{ group: { id: string } }>(pairing, 'projectGroup.create', { name: 'Package verification', parentPath: folderPath, createdFrom: 'manual' }) const workspace = await call<{ folderWorkspace: { id: string } }>( pairing, 'folderWorkspace.create', { projectGroupId: group.group.id, name: 'Folder workspace', folderPath } ) const marker = `orca-node-server-${Date.now()}` const workspaceSelector = `id:folder:${workspace.folderWorkspace.id}` const created = await call<{ terminal: { handle: string; ptyId?: string } }>( pairing, 'terminal.create', { worktree: workspaceSelector, command: `node -p "'${marker}:'+process.env.TERM_PROGRAM_VERSION"` } ) const versionedMarker = `${marker}:${expectedVersion}` await waitForTerminalMarker(pairing, created.terminal.handle, versionedMarker) return { handle: created.terminal.handle, marker: versionedMarker, ptyId: created.terminal.ptyId, workspaceSelector } } async function waitForTerminalMarker( pairing: PairingOffer, handle: string, marker: string ): Promise { const deadline = Date.now() + 20_000 while (Date.now() < deadline) { const result = await call<{ terminal: RuntimeTerminalRead }>(pairing, 'terminal.read', { terminal: handle, limit: 200 }) if (result.terminal.tail.join('\n').includes(marker)) { return } await new Promise((resolveWait) => setTimeout(resolveWait, 100)) } throw new Error('terminal marker was not observed') } async function call( pairing: PairingOffer, method: string, params?: unknown ): Promise { const response = await sendRemoteRuntimeRequest(pairing, method, params, 15_000) if (!response.ok) { throw new Error(`${method} failed: ${response.error.message}`) } return response.result } function assert(condition: unknown, message: string): asserts condition { if (!condition) { throw new Error(message) } }