Merge pull request #2517 from deepseek-harness/xtr/node-pty-1.2-beta
chore(subprocess-local): bump node-pty beta
This commit is contained in:
@@ -194,6 +194,7 @@ jobs:
|
|||||||
*) echo "::error::Unsupported Linux runner architecture $RUNNER_ARCH"; exit 1 ;;
|
*) echo "::error::Unsupported Linux runner architecture $RUNNER_ARCH"; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
addon_dir="$(realpath packages/subprocess/subprocess-local/node_modules/node-pty)"
|
addon_dir="$(realpath packages/subprocess/subprocess-local/node_modules/node-pty)"
|
||||||
|
(cd "$addon_dir" && npm_config_build_from_source=true pnpm run install)
|
||||||
addon="$addon_dir/build/Release/pty.node"
|
addon="$addon_dir/build/Release/pty.node"
|
||||||
[ -f "$addon_dir/build/Makefile" ] || {
|
[ -f "$addon_dir/build/Makefile" ] || {
|
||||||
echo "::error::node-pty install did not generate $addon_dir/build/Makefile"
|
echo "::error::node-pty install did not generate $addon_dir/build/Makefile"
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ External packages that a workspace package resolves at runtime. The tier covers
|
|||||||
|
|
||||||
pnpm applies local patches to the following packages at install time, so shipped artifacts carry modified copies; each patch file is the complete record of the modification:
|
pnpm applies local patches to the following packages at install time, so shipped artifacts carry modified copies; each patch file is the complete record of the modification:
|
||||||
|
|
||||||
- `node-pty@1.1.0` — [`patches/node-pty@1.1.0.patch`](patches/node-pty@1.1.0.patch)
|
- `node-pty@1.2.0-beta.15` — [`patches/node-pty@1.2.0-beta.15.patch`](patches/node-pty@1.2.0-beta.15.patch)
|
||||||
|
|
||||||
## Official Claude Code platform payloads
|
## Official Claude Code platform payloads
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
"@deepseek-ai/cordis": "workspace:^"
|
"@deepseek-ai/cordis": "workspace:^"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-pty": "^1.1.0"
|
"node-pty": "1.2.0-beta.15"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@deepseek-ai/dsh-invariants": "workspace:^",
|
"@deepseek-ai/dsh-invariants": "workspace:^",
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
diff --git a/lib/unixTerminal.js b/lib/unixTerminal.js
|
|
||||||
index 1ec12f796a822c78fba9ad7f6448c3987e325c23..5cd6b7d635f4752be5a6c5ff9cf9edf988cf94c5 100644
|
|
||||||
--- a/lib/unixTerminal.js
|
|
||||||
+++ b/lib/unixTerminal.js
|
|
||||||
@@ -26,10 +26,23 @@ var terminal_1 = require("./terminal");
|
|
||||||
var utils_1 = require("./utils");
|
|
||||||
var native = utils_1.loadNativeModule('pty');
|
|
||||||
var pty = native.module;
|
|
||||||
-var helperPath = native.dir + '/spawn-helper';
|
|
||||||
-helperPath = path.resolve(__dirname, helperPath);
|
|
||||||
-helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
|
|
||||||
-helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');
|
|
||||||
+// A current external embedded-runtime consumer supplies a non-sibling helper.
|
|
||||||
+var helperPath = process.env.DSH_NODE_PTY_SPAWN_HELPER;
|
|
||||||
+if (helperPath) {
|
|
||||||
+ helperPath = path.resolve(helperPath);
|
|
||||||
+}
|
|
||||||
+else {
|
|
||||||
+ var executableSibling = process.execPath + '-spawn-helper';
|
|
||||||
+ if (fs.existsSync(executableSibling)) {
|
|
||||||
+ helperPath = executableSibling;
|
|
||||||
+ }
|
|
||||||
+ else {
|
|
||||||
+ helperPath = native.dir + '/spawn-helper';
|
|
||||||
+ helperPath = path.resolve(__dirname, helperPath);
|
|
||||||
+ helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
|
|
||||||
+ helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
var DEFAULT_FILE = 'sh';
|
|
||||||
var DEFAULT_NAME = 'xterm';
|
|
||||||
var DESTROY_SOCKET_TIMEOUT_MS = 200;
|
|
||||||
diff --git a/src/unixTerminal.ts b/src/unixTerminal.ts
|
|
||||||
index 98733dc0cd752b554bd94e45904ca341ad141bba..fa234291206617ae5a6d8605abf9771220392d17 100644
|
|
||||||
--- a/src/unixTerminal.ts
|
|
||||||
+++ b/src/unixTerminal.ts
|
|
||||||
@@ -14,10 +14,21 @@ import { assign, loadNativeModule } from './utils';
|
|
||||||
|
|
||||||
const native = loadNativeModule('pty');
|
|
||||||
const pty: IUnixNative = native.module;
|
|
||||||
-let helperPath = native.dir + '/spawn-helper';
|
|
||||||
-helperPath = path.resolve(__dirname, helperPath);
|
|
||||||
-helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
|
|
||||||
-helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');
|
|
||||||
+// A current external embedded-runtime consumer supplies a non-sibling helper.
|
|
||||||
+let helperPath = process.env.DSH_NODE_PTY_SPAWN_HELPER;
|
|
||||||
+if (helperPath) {
|
|
||||||
+ helperPath = path.resolve(helperPath);
|
|
||||||
+} else {
|
|
||||||
+ const executableSibling = process.execPath + '-spawn-helper';
|
|
||||||
+ if (fs.existsSync(executableSibling)) {
|
|
||||||
+ helperPath = executableSibling;
|
|
||||||
+ } else {
|
|
||||||
+ helperPath = native.dir + '/spawn-helper';
|
|
||||||
+ helperPath = path.resolve(__dirname, helperPath);
|
|
||||||
+ helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
|
|
||||||
+ helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
|
|
||||||
const DEFAULT_FILE = 'sh';
|
|
||||||
const DEFAULT_NAME = 'xterm';
|
|
||||||
32
patches/node-pty@1.2.0-beta.15.patch
Normal file
32
patches/node-pty@1.2.0-beta.15.patch
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
diff --git a/lib/unixTerminal.js b/lib/unixTerminal.js
|
||||||
|
index 6966d24..18f1d25 100644
|
||||||
|
--- a/lib/unixTerminal.js
|
||||||
|
+++ b/lib/unixTerminal.js
|
||||||
|
@@ -28,10 +28,23 @@ var terminal_1 = require("./terminal");
|
||||||
|
var utils_1 = require("./utils");
|
||||||
|
var native = (0, utils_1.loadNativeModule)('pty');
|
||||||
|
var pty = native.module;
|
||||||
|
-var helperPath = native.dir + '/spawn-helper';
|
||||||
|
-helperPath = path.resolve(__dirname, helperPath);
|
||||||
|
-helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
|
||||||
|
-helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');
|
||||||
|
+// A current external embedded-runtime consumer supplies a non-sibling helper.
|
||||||
|
+var helperPath = process.env.DSH_NODE_PTY_SPAWN_HELPER;
|
||||||
|
+if (helperPath) {
|
||||||
|
+ helperPath = path.resolve(helperPath);
|
||||||
|
+}
|
||||||
|
+else {
|
||||||
|
+ var executableSibling = process.execPath + '-spawn-helper';
|
||||||
|
+ if (fs.existsSync(executableSibling)) {
|
||||||
|
+ helperPath = executableSibling;
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ helperPath = native.dir + '/spawn-helper';
|
||||||
|
+ helperPath = path.resolve(__dirname, helperPath);
|
||||||
|
+ helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
|
||||||
|
+ helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
var DEFAULT_FILE = 'sh';
|
||||||
|
var DEFAULT_NAME = 'xterm';
|
||||||
|
var DESTROY_SOCKET_TIMEOUT_MS = 200;
|
||||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -9,7 +9,7 @@ overrides:
|
|||||||
'@deepseek-ai/schemastery': link:vendor/schemastery
|
'@deepseek-ai/schemastery': link:vendor/schemastery
|
||||||
|
|
||||||
patchedDependencies:
|
patchedDependencies:
|
||||||
node-pty@1.1.0: 7a0c04f1f49d798a9ffe2f7f414c01064a44ca2489772d0c3e1235ab336755e6
|
node-pty@1.2.0-beta.15: b40ae545608897914bd25fb009c97eeac478c34e8a910298ddcb01b746534bb0
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
@@ -7493,8 +7493,8 @@ importers:
|
|||||||
packages/subprocess/subprocess-local:
|
packages/subprocess/subprocess-local:
|
||||||
dependencies:
|
dependencies:
|
||||||
node-pty:
|
node-pty:
|
||||||
specifier: ^1.1.0
|
specifier: 1.2.0-beta.15
|
||||||
version: 1.1.0(patch_hash=7a0c04f1f49d798a9ffe2f7f414c01064a44ca2489772d0c3e1235ab336755e6)
|
version: 1.2.0-beta.15(patch_hash=b40ae545608897914bd25fb009c97eeac478c34e8a910298ddcb01b746534bb0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@deepseek-ai/cordis':
|
'@deepseek-ai/cordis':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@@ -13164,8 +13164,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
|
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
|
||||||
node-pty@1.1.0:
|
node-pty@1.2.0-beta.15:
|
||||||
resolution: {integrity: sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg==}
|
resolution: {integrity: sha512-vORSzHXi4Ofl7HemVWpuudLqCPdaQb4LfpRCUpE5HPxhp4JYscl8zZwxh11p26v2wvW24WMwnMfLjhRLixrfxA==}
|
||||||
|
|
||||||
node-releases@2.0.51:
|
node-releases@2.0.51:
|
||||||
resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==}
|
resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==}
|
||||||
@@ -18588,7 +18588,7 @@ snapshots:
|
|||||||
fetch-blob: 3.2.0
|
fetch-blob: 3.2.0
|
||||||
formdata-polyfill: 4.0.10
|
formdata-polyfill: 4.0.10
|
||||||
|
|
||||||
node-pty@1.1.0(patch_hash=7a0c04f1f49d798a9ffe2f7f414c01064a44ca2489772d0c3e1235ab336755e6):
|
node-pty@1.2.0-beta.15(patch_hash=b40ae545608897914bd25fb009c97eeac478c34e8a910298ddcb01b746534bb0):
|
||||||
dependencies:
|
dependencies:
|
||||||
node-addon-api: 7.1.1
|
node-addon-api: 7.1.1
|
||||||
|
|
||||||
|
|||||||
@@ -69,4 +69,4 @@ minimumReleaseAgeExclude:
|
|||||||
- node-addon-require-builtin@0.1.4
|
- node-addon-require-builtin@0.1.4
|
||||||
|
|
||||||
patchedDependencies:
|
patchedDependencies:
|
||||||
node-pty@1.1.0: patches/node-pty@1.1.0.patch
|
node-pty@1.2.0-beta.15: patches/node-pty@1.2.0-beta.15.patch
|
||||||
|
|||||||
49
scripts/build-exe-for-python-sdk-native-pty.spec.ts
Normal file
49
scripts/build-exe-for-python-sdk-native-pty.spec.ts
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
||||||
|
import { tmpdir } from 'node:os'
|
||||||
|
import { dirname, join } from 'node:path'
|
||||||
|
import { afterEach, describe, expect, it } from 'vitest'
|
||||||
|
import { resolveLinuxNodePtyAddon } from './build-exe-for-python-sdk-native-pty.ts'
|
||||||
|
|
||||||
|
const roots: string[] = []
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('resolveLinuxNodePtyAddon', () => {
|
||||||
|
it('prefers the manylinux build produced by the release workflow', () => {
|
||||||
|
const root = temporaryPackage()
|
||||||
|
const built = createAddon(root, 'build', 'Release', 'pty.node')
|
||||||
|
createAddon(root, 'prebuilds', 'linux-x64', 'pty.node')
|
||||||
|
|
||||||
|
expect(resolveLinuxNodePtyAddon(root, 'x64')).toBe(built)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('uses the target prebuild after an ordinary beta install', () => {
|
||||||
|
const root = temporaryPackage()
|
||||||
|
const prebuilt = createAddon(root, 'prebuilds', 'linux-arm64', 'pty.node')
|
||||||
|
|
||||||
|
expect(resolveLinuxNodePtyAddon(root, 'arm64')).toBe(prebuilt)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('reports both expected locations when no addon is installed', () => {
|
||||||
|
const root = temporaryPackage()
|
||||||
|
|
||||||
|
expect(() => resolveLinuxNodePtyAddon(root, 'x64')).toThrow(
|
||||||
|
`node-pty addon is absent from both ${join(root, 'build', 'Release', 'pty.node')} and ${join(root, 'prebuilds', 'linux-x64', 'pty.node')}`,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function temporaryPackage(): string {
|
||||||
|
const root = mkdtempSync(join(tmpdir(), 'dsh-node-pty-addon-'))
|
||||||
|
roots.push(root)
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAddon(root: string, ...segments: string[]): string {
|
||||||
|
const path = join(root, ...segments)
|
||||||
|
mkdirSync(dirname(path), { recursive: true })
|
||||||
|
writeFileSync(path, '')
|
||||||
|
return path
|
||||||
|
}
|
||||||
23
scripts/build-exe-for-python-sdk-native-pty.ts
Normal file
23
scripts/build-exe-for-python-sdk-native-pty.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/** Resolve the native node-pty input used by the Python SDK runtime builder. */
|
||||||
|
|
||||||
|
import { existsSync } from 'node:fs'
|
||||||
|
import { join } from 'node:path'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefer the workflow's manylinux build and fall back to node-pty's target prebuild.
|
||||||
|
* @param packageDirectory - installed node-pty package directory.
|
||||||
|
* @param arch - Linux target architecture.
|
||||||
|
* @returns the existing addon path.
|
||||||
|
*/
|
||||||
|
export function resolveLinuxNodePtyAddon(
|
||||||
|
packageDirectory: string,
|
||||||
|
arch: 'x64' | 'arm64',
|
||||||
|
): string {
|
||||||
|
const built = join(packageDirectory, 'build', 'Release', 'pty.node')
|
||||||
|
if (existsSync(built)) return built
|
||||||
|
const prebuilt = join(packageDirectory, 'prebuilds', `linux-${arch}`, 'pty.node')
|
||||||
|
if (existsSync(prebuilt)) return prebuilt
|
||||||
|
throw new Error(
|
||||||
|
`build-exe-for-python-sdk: node-pty addon is absent from both ${built} and ${prebuilt}.`,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import { existsSync, statSync } from 'node:fs'
|
|||||||
import { chmod, copyFile, cp, lstat, mkdir, readFile, readdir, realpath, rm, writeFile } from 'node:fs/promises'
|
import { chmod, copyFile, cp, lstat, mkdir, readFile, readdir, realpath, rm, writeFile } from 'node:fs/promises'
|
||||||
import { basename, dirname, join, resolve, sep } from 'node:path'
|
import { basename, dirname, join, resolve, sep } from 'node:path'
|
||||||
import { parseArgs } from 'node:util'
|
import { parseArgs } from 'node:util'
|
||||||
|
import { resolveLinuxNodePtyAddon } from './build-exe-for-python-sdk-native-pty.ts'
|
||||||
|
|
||||||
const root = resolve(import.meta.dirname, '..')
|
const root = resolve(import.meta.dirname, '..')
|
||||||
|
|
||||||
@@ -409,8 +410,8 @@ class SingleExeBuild {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Put the target node-pty addon in the staged closure. Linux npm installs
|
* Put the target node-pty addon in the staged closure. The release workflow
|
||||||
* build it from source, but legacy deploy omits that side-effect directory.
|
* provides a manylinux build; ordinary installs use node-pty's target prebuild.
|
||||||
* @param target - the pkg target whose native addon is being staged.
|
* @param target - the pkg target whose native addon is being staged.
|
||||||
*/
|
*/
|
||||||
private async prepareNativePty(target: Target): Promise<void> {
|
private async prepareNativePty(target: Target): Promise<void> {
|
||||||
@@ -418,8 +419,16 @@ class SingleExeBuild {
|
|||||||
if (this.cli.dryRun) console.log(`build-exe-for-python-sdk: [dry-run] rm -rf ${stagedBuild}`)
|
if (this.cli.dryRun) console.log(`build-exe-for-python-sdk: [dry-run] rm -rf ${stagedBuild}`)
|
||||||
else await rm(stagedBuild, { recursive: true, force: true })
|
else await rm(stagedBuild, { recursive: true, force: true })
|
||||||
if (target.platform !== 'linux') return
|
if (target.platform !== 'linux') return
|
||||||
const source = join(root, 'packages', 'subprocess', 'subprocess-local', 'node_modules', 'node-pty', 'build', 'Release', 'pty.node')
|
const packageDirectory = join(
|
||||||
|
root,
|
||||||
|
'packages',
|
||||||
|
'subprocess',
|
||||||
|
'subprocess-local',
|
||||||
|
'node_modules',
|
||||||
|
'node-pty',
|
||||||
|
)
|
||||||
const destination = join(stagedBuild, 'Release', 'pty.node')
|
const destination = join(stagedBuild, 'Release', 'pty.node')
|
||||||
|
const source = resolveLinuxNodePtyAddon(packageDirectory, target.arch)
|
||||||
if (this.cli.dryRun) {
|
if (this.cli.dryRun) {
|
||||||
console.log(`build-exe-for-python-sdk: [dry-run] cp ${source} ${destination}`)
|
console.log(`build-exe-for-python-sdk: [dry-run] cp ${source} ${destination}`)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -342,6 +342,7 @@ describe('Python release workflows', () => {
|
|||||||
expect(manylinuxAddon).toMatchObject({ if: "runner.os == 'Linux'" })
|
expect(manylinuxAddon).toMatchObject({ if: "runner.os == 'Linux'" })
|
||||||
expect(JSON.stringify(manylinuxAddon)).toContain('manylinux_2_28_x86_64')
|
expect(JSON.stringify(manylinuxAddon)).toContain('manylinux_2_28_x86_64')
|
||||||
expect(JSON.stringify(manylinuxAddon)).toContain('manylinux_2_28_aarch64')
|
expect(JSON.stringify(manylinuxAddon)).toContain('manylinux_2_28_aarch64')
|
||||||
|
expect(JSON.stringify(manylinuxAddon)).toContain('npm_config_build_from_source=true pnpm run install')
|
||||||
expect(JSON.stringify(manylinuxAddon)).toContain('$HOME/setup-pnpm:$HOME/setup-pnpm:ro')
|
expect(JSON.stringify(manylinuxAddon)).toContain('$HOME/setup-pnpm:$HOME/setup-pnpm:ro')
|
||||||
expect(JSON.stringify(manylinuxAddon)).toContain('node-pty-glibc-versions.txt')
|
expect(JSON.stringify(manylinuxAddon)).toContain('node-pty-glibc-versions.txt')
|
||||||
expect(JSON.stringify(manylinuxAddon)).toContain('le 2.28')
|
expect(JSON.stringify(manylinuxAddon)).toContain('le 2.28')
|
||||||
|
|||||||
Reference in New Issue
Block a user