diff --git a/packages/subprocess/subprocess-local/src/index.ts b/packages/subprocess/subprocess-local/src/index.ts index 40d2f52552..03755cd9ea 100644 --- a/packages/subprocess/subprocess-local/src/index.ts +++ b/packages/subprocess/subprocess-local/src/index.ts @@ -11,7 +11,7 @@ import { constants } from 'node:fs' import { mkdtempSync } from 'node:fs' import { access, rm, stat } from 'node:fs/promises' import { tmpdir } from 'node:os' -import { delimiter, extname, isAbsolute, join } from 'node:path' +import { delimiter, extname, isAbsolute, join, resolve } from 'node:path' import { Context } from 'cordis' import * as nodePty from 'node-pty' import type { IPtyForkOptions } from 'node-pty' @@ -107,7 +107,7 @@ export class LocalSubprocessService extends SubprocessService { ? (env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD').split(';') : [''] return path.split(delimiter).flatMap(directory => - directory === '' ? [] : extensions.map(extension => join(directory, command + extension))) + directory === '' ? [] : extensions.map(extension => resolve(this.cwd, directory, command + extension))) } spawn(spec: SubprocessSpawnSpec): SubprocessHandle { diff --git a/packages/subprocess/subprocess-local/tests/local.spec.ts b/packages/subprocess/subprocess-local/tests/local.spec.ts index 93be25acd0..6ce3d06b8e 100644 --- a/packages/subprocess/subprocess-local/tests/local.spec.ts +++ b/packages/subprocess/subprocess-local/tests/local.spec.ts @@ -1,7 +1,7 @@ import { PassThrough } from 'node:stream' import { describe, expect, it, vi } from 'vitest' import { stat } from 'node:fs/promises' -import { basename, delimiter, dirname } from 'node:path' +import { basename, delimiter, dirname, relative } from 'node:path' import { Context } from 'cordis' import LocalSubprocessService from '@deepseek-ai/dsh-subprocess-local' import type { SubprocessSpawnSpec, SubprocessTerminalHandle, SubprocessTerminalSpawnSpec } from '@deepseek-ai/dsh-subprocess' @@ -38,6 +38,9 @@ describe('LocalSubprocessService', () => { expect(await ctx.subprocess.resolveExecutable(basename(process.execPath), { PATH: dirname(process.execPath), })).toBe(process.execPath) + expect(await ctx.subprocess.resolveExecutable(basename(process.execPath), { + PATH: relative(process.cwd(), dirname(process.execPath)) || '.', + })).toBe(process.execPath) await expect(ctx.subprocess.resolveExecutable('')).rejects.toThrow('must be non-empty') await expect(ctx.subprocess.resolveExecutable('dsh-command-that-does-not-exist', { PATH: '' })) .rejects.toThrow('was not found on PATH')