// @vitest-environment node import { afterEach, describe, expect, it } from 'vitest'; import { realpathSync } from 'node:fs'; import { mkdir, mkdtemp, readFile, rm } from 'node:fs/promises'; import { createRequire } from 'node:module'; import { tmpdir } from 'node:os'; import { join, resolve } from 'node:path'; import { PiWorkerProcess } from '../../electron/coding-runtime/pi/worker-process'; import { PiManagedExtensionHost } from '../../electron/coding-runtime/pi/extension-host'; const scratchRoots: string[] = []; afterEach(async () => { await Promise.all(scratchRoots.splice(0).map((root) => rm(root, { recursive: true, force: true, maxRetries: 3, }))); }); describe('locked Pi worker process smoke', () => { it('loads the real Pi 0.84.2 entry through Electron Node and exits by closing stdin', async () => { const requireFromProject = createRequire(resolve('package.json')); const electronExecutable = requireFromProject('electron') as string; const packageRoot = realpathSync(resolve( 'node_modules', '@earendil-works', 'pi-coding-agent', )); const packageJson = JSON.parse(await readFile(join(packageRoot, 'package.json'), 'utf8')) as { version: string; }; expect(packageJson.version).toBe('0.84.2'); const root = await mkdtemp(join(tmpdir(), 'makelore-pi-real-worker-')); scratchRoots.push(root); const configDir = join(root, 'config'); const sessionDir = join(root, 'sessions'); const cwd = join(root, 'project'); await Promise.all([mkdir(configDir), mkdir(sessionDir), mkdir(cwd)]); const extensionHost = new PiManagedExtensionHost(); const extension = await extensionHost.registerWorker({ conversationId: 'real-conversation', generation: 1, projectId: 'real-project', extensionsDir: join(root, 'extensions'), }); await extensionHost.bindRun('real-conversation', 1, 'real-run'); const worker = await new PiWorkerProcess({ executablePath: electronExecutable, cliPath: join(packageRoot, 'dist', 'cli.js'), cwd, configDir, sessionDir, additionalArgs: ['--extension', extension.extensionPath], env: extension.env, sensitiveValues: extension.sensitiveValues, commandTimeoutMs: 5_000, }).start(); try { await expect(worker.request({ type: 'get_state' })).resolves.toMatchObject({ type: 'response', command: 'get_state', success: true, }); expect(worker.stderrDiagnostic).not.toContain('Failed to load extension'); await expect(worker.stop()).resolves.toMatchObject({ mode: 'stdin-close', code: 0 }); } finally { await worker.stop().catch(() => undefined); await extension.dispose(); await extensionHost.close(); } }, 15_000); });