| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- import { spawn } from 'node:child_process'
- import type { Buffer } from 'node:buffer'
- import { existsSync } from 'node:fs'
- import { resolve } from 'node:path'
- import { fileURLToPath } from 'node:url'
- import { describe, expect, it } from 'vitest'
- import type { SubprocessSpawnSpec } from '@deepseek-ai/dsh-subprocess'
- import {
- cleanupLinuxLaunchFiles,
- createLinuxLaunchFiles,
- } from '../src/runner-protocol.ts'
- import {
- runnerEnvironment,
- runnerInvocationAvailable,
- SUBPROCESS_RUNNER_ENV,
- targetEnvironment,
- } from '../src/runner-launch.ts'
- import type { RunnerInvocation } from '../src/runner-launch.ts'
- import { bindManagedProcess } from '../src/spawn.ts'
- import { launchWindowsJob } from '../src/windows-job.ts'
- const repoRoot = resolve(import.meta.dirname, '../../../..')
- const sourceRunner = resolve(repoRoot, 'packages/subprocess/subprocess-local/src/bin.ts')
- const builtRunner = fileURLToPath(import.meta.resolve('@deepseek-ai/dsh-subprocess-local/runner'))
- function targetEnv(): Record<string, string> {
- return {
- ...Object.fromEntries(Object.entries(process.env).filter((entry): entry is [string, string] => entry[1] !== undefined)),
- [SUBPROCESS_RUNNER_ENV]: 'target-collision-restored',
- }
- }
- async function executePosix(invocation: RunnerInvocation): Promise<{ status: number | null; stdout: string; stderr: string }> {
- const files = createLinuxLaunchFiles({ cwd: repoRoot, env: targetEnv() })
- try {
- const child = spawn(invocation[0], [
- ...invocation.slice(1),
- '--',
- process.execPath,
- '--input-type=module',
- '--eval',
- `process.stdout.write(process.argv[0]+'|'+process.cwd()+'|'+process.env.${SUBPROCESS_RUNNER_ENV})`,
- ], {
- env: runnerEnvironment(files.requestPath, invocation),
- stdio: ['ignore', 'pipe', 'pipe'],
- })
- let stdout = ''
- let stderr = ''
- child.stdout.on('data', (chunk: Buffer) => { stdout += chunk.toString() })
- child.stderr.on('data', (chunk: Buffer) => { stderr += chunk.toString() })
- const status = await new Promise<number | null>((resolveExit, rejectExit) => {
- child.once('error', rejectExit)
- child.once('exit', resolveExit)
- })
- return { status, stdout, stderr }
- } finally {
- cleanupLinuxLaunchFiles(files)
- }
- }
- async function executeWindows(invocation: RunnerInvocation): Promise<{ status: number | null; stdout: string; stderr: string }> {
- const request: SubprocessSpawnSpec = {
- argv: [
- process.execPath,
- '--input-type=module',
- '--eval',
- `process.stdout.write(process.argv[0]+'|'+process.cwd()+'|'+process.env.${SUBPROCESS_RUNNER_ENV})`,
- ],
- cwd: repoRoot,
- env: targetEnv(),
- stdio: {
- stdin: 'ignore',
- stdout: { maxBytes: 64_000 },
- stderr: { maxBytes: 64_000 },
- },
- graceMs: 3_000,
- }
- const handle = bindManagedProcess(request, launchWindowsJob(
- request,
- targetEnvironment(request),
- { runnerInvocation: invocation },
- ))
- const outcome = await handle.done
- await handle.waitForExit()
- const stdout = handle.collected.stdout?.readFrom(0).text ?? ''
- const stderr = handle.collected.stderr?.readFrom(0).text ?? ''
- return { status: outcome.exitCode, stdout, stderr }
- }
- async function execute(invocation: RunnerInvocation): Promise<{ status: number | null; stdout: string; stderr: string }> {
- return process.platform === 'win32'
- ? executeWindows(invocation)
- : executePosix(invocation)
- }
- describe('subprocess-local runner artifacts', () => {
- it('executes the source entry through the provider-owned core', async () => {
- const result = await execute([process.execPath, '--import', 'tsx/esm', sourceRunner])
- expect(result).toEqual({
- status: 0,
- stdout: `${process.execPath}|${repoRoot}|target-collision-restored`,
- stderr: '',
- })
- }, 30_000)
- it.skipIf(!existsSync(builtRunner))('executes the built ./runner subpath through the same core', async () => {
- const invocation: RunnerInvocation = [process.execPath, builtRunner]
- expect(runnerInvocationAvailable(invocation)).toBe(true)
- const result = await execute(invocation)
- expect(result).toEqual({
- status: 0,
- stdout: `${process.execPath}|${repoRoot}|target-collision-restored`,
- stderr: '',
- })
- }, 30_000)
- })
|