mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-11 04:00:38 +00:00
117 lines
4.2 KiB
TypeScript
117 lines
4.2 KiB
TypeScript
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)
|
|
})
|