diff --git a/mini-test.sh b/mini-test.sh index 9ac8c70d5..e4c26721c 100755 --- a/mini-test.sh +++ b/mini-test.sh @@ -23,7 +23,7 @@ for arg in "$@"; do cat <<'USAGE' Usage: ./mini-test.sh [--dist] [--fresh] [--stop] [mini args...] - --dist run built output with plain node instead of tsx on sources + --dist run built output instead of sources --fresh stop the detached session server first, so it picks up your changes --stop stop the detached session server and exit @@ -43,4 +43,6 @@ if [[ "$USE_DIST" == "true" ]]; then exec node "$MINI_DIST" ${ARGS[@]+"${ARGS[@]}"} fi -exec "$SCRIPT_DIR/node_modules/.bin/tsx" --tsconfig "$SCRIPT_DIR/tsconfig.json" "$MINI_SRC" ${ARGS[@]+"${ARGS[@]}"} +# --import takes a module specifier, so pass the resolver as a file URL (raw paths break on #, ?, %). +RESOLVER_URL="$(node -p 'require("node:url").pathToFileURL(process.argv[1]).href' "$SCRIPT_DIR/packages/coding-agent/src/experimental/source-resolver.ts")" +exec node --import "$RESOLVER_URL" "$MINI_SRC" ${ARGS[@]+"${ARGS[@]}"} diff --git a/package-lock.json b/package-lock.json index a4b5de131..08d63a44a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,12 +20,10 @@ "@anthropic-ai/sandbox-runtime": "0.0.26", "@biomejs/biome": "2.3.5", "@types/node": "22.19.19", - "@typescript/native-preview": "7.0.0-dev.20260120.1", "esbuild": "0.28.2", "husky": "9.1.7", "shx": "0.4.0", - "tsx": "4.22.1", - "typescript": "5.9.3" + "typescript": "7.0.2" }, "engines": { "node": ">=22.19.0" @@ -1835,29 +1833,27 @@ "dev": true, "license": "MIT" }, - "node_modules/@typescript/native-preview": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview/-/native-preview-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-nnEf37C9ue7OBRnF2zmV/OCBmV5Y7T/K4mCHa+nxgiXcF/1w8sA0cgdFl+gHQ0mysqUJ+Bu5btAMeWgpLyjrgg==", + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "Apache-2.0", - "bin": { - "tsgo": "bin/tsgo.js" - }, - "optionalDependencies": { - "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-linux-arm": "7.0.0-dev.20260120.1", - "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-linux-x64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-win32-x64": "7.0.0-dev.20260120.1" + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=16.20.0" } }, - "node_modules/@typescript/native-preview-darwin-arm64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-r3pWFuR2H7mn6ScwpH5jJljKQqKto0npVuJSk6pRwFwexpTyxOGmJTZJ1V0AWiisaNxU2+CNAqWFJSJYIE/QTg==", + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", "cpu": [ "arm64" ], @@ -1866,12 +1862,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@typescript/native-preview-darwin-x64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-cuC1+wLbUP+Ip2UT94G134fqRdp5w3b3dhcCO6/FQ4yXxvRNyv/WK+upHBUFDaeSOeHgDTyO9/QFYUWwC4If1A==", + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", "cpu": [ "x64" ], @@ -1880,12 +1879,49 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@typescript/native-preview-linux-arm": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-vN6OYVySol/kQZjJGmAzd6L30SyVlCgmCXS8WjUYtE5clN0YrzQHop16RK29fYZHMxpkOniVBtRPxUYQANZBlQ==", + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", "cpu": [ "arm" ], @@ -1894,12 +1930,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@typescript/native-preview-linux-arm64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-zZGvEGY7wcHYefMZ87KNmvjN3NLIhsCMHEpHZiGCS3khKf+8z6ZsanrzCjOTodvL01VPyBzHxV1EtkSxAcLiQg==", + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", "cpu": [ "arm64" ], @@ -1908,12 +1947,100 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@typescript/native-preview-linux-x64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-JBfNhWd/asd5MDeS3VgRvE24pGKBkmvLub6tsux6ypr+Yhy+o0WaAEzVpmlRYZUqss2ai5tvOu4dzPBXzZAtFw==", + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", "cpu": [ "x64" ], @@ -1922,12 +2049,100 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@typescript/native-preview-win32-arm64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-tTndRtYCq2xwgE0VkTi9ACNiJaV43+PqvBqCxk8ceYi3X36Ve+CCnwlZfZJ4k9NxZthtrAwF/kUmpC9iIYbq1w==", + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", "cpu": [ "arm64" ], @@ -1936,12 +2151,15 @@ "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@typescript/native-preview-win32-x64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-x64/-/native-preview-win32-x64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-oZia7hFL6k9pVepfonuPI86Jmyz6WlJKR57tWCDwRNmpA7odxuTq1PbvcYgy1z4+wHF1nnKKJY0PMAiq6ac18w==", + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", "cpu": [ "x64" ], @@ -1950,7 +2168,10 @@ "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": ">=16.20.0" + } }, "node_modules/@vitest-evals/core": { "version": "0.15.0", @@ -4860,25 +5081,6 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/tsx": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.1.tgz", - "integrity": "sha512-TvncJykhxAzFCk0VQZKBTClall4Pm7qXDSodb6uxi8QFa8X8mT6ABjxxsQ2opDRYxG7AzcRWXaFtruz5HJKuWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.28.0" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -4905,17 +5107,38 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", "dev": true, "license": "Apache-2.0", "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "tsc": "bin/tsc" }, "engines": { - "node": ">=14.17" + "node": ">=16.20.0" + }, + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" } }, "node_modules/undici": { @@ -5294,7 +5517,6 @@ "devDependencies": { "@types/node": "22.19.19", "@vitest/coverage-v8": "4.1.9", - "typescript": "5.9.3", "vitest": "4.1.9" }, "engines": { @@ -5429,7 +5651,6 @@ "@types/semver": "7.7.1", "marked": "18.0.11", "shx": "0.4.0", - "typescript": "5.9.3", "vitest": "4.1.9" }, "engines": { @@ -5541,7 +5762,6 @@ "@vitest-evals/core": "0.15.0", "autoevals": "0.3.0", "shx": "0.4.0", - "typescript": "5.9.3", "vitest": "4.1.9", "vitest-evals": "0.15.0" } diff --git a/package.json b/package.json index 47c163512..d9fe33331 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "build:native:darwin": "npm --prefix packages/tui run build:native:darwin", "build:native:linux": "npm --prefix packages/tui run build:native:linux", "build:native:win32": "npm --prefix packages/tui run build:native:win32", - "check": "biome check --write --error-on-warnings . && npm run check:pinned-deps && npm run check:runtime-deps && npm run check:ts-imports && npm run check:entry-graphs && npm run check:shrinkwrap && npm run check:install-lock:coding-agent && tsgo --noEmit && npm run check:browser-smoke", + "check": "biome check --write --error-on-warnings . && npm run check:pinned-deps && npm run check:runtime-deps && npm run check:ts-imports && npm run check:entry-graphs && npm run check:shrinkwrap && npm run check:install-lock:coding-agent && tsc --noEmit && npm run check:browser-smoke", "check:browser-smoke": "node scripts/check-browser-smoke.mjs", "check:pinned-deps": "node scripts/check-pinned-deps.mjs", "check:runtime-deps": "node scripts/check-runtime-deps.mjs", @@ -58,12 +58,10 @@ "@anthropic-ai/sandbox-runtime": "0.0.26", "@biomejs/biome": "2.3.5", "@types/node": "22.19.19", - "@typescript/native-preview": "7.0.0-dev.20260120.1", "esbuild": "0.28.2", "husky": "9.1.7", "shx": "0.4.0", - "tsx": "4.22.1", - "typescript": "5.9.3" + "typescript": "7.0.2" }, "engines": { "node": ">=22.19.0" diff --git a/packages/agent/benchmark/session/allocation-profile.ts b/packages/agent/benchmark/session/allocation-profile.ts index 435760613..b4f89260d 100644 --- a/packages/agent/benchmark/session/allocation-profile.ts +++ b/packages/agent/benchmark/session/allocation-profile.ts @@ -20,15 +20,16 @@ interface AllocationProfileResult { const execFileAsync = promisify(execFile); const packageRoot = fileURLToPath(new URL("../..", import.meta.url)); const workerPath = fileURLToPath(new URL("./allocation-profile-worker.ts", import.meta.url)); -const tsconfigPath = fileURLToPath(new URL("../tsconfig.json", import.meta.url)); +// Resolve workspace packages to their sources, matching the root tsconfig paths. +const sourceResolverUrl = new URL("../../../coding-agent/src/experimental/source-resolver.ts", import.meta.url).href; const results: AllocationProfileResult[] = []; for (const target of storageBenchmarkTargets) { for (const dataset of STORAGE_BENCHMARK_DATASETS) { const { stdout } = await execFileAsync( process.execPath, - ["--import", "tsx", workerPath, target.name, dataset.name], - { cwd: packageRoot, env: { ...process.env, TSX_TSCONFIG_PATH: tsconfigPath } }, + ["--import", sourceResolverUrl, workerPath, target.name, dataset.name], + { cwd: packageRoot }, ); results.push(JSON.parse(stdout) as AllocationProfileResult); } diff --git a/packages/agent/benchmark/session/loaded-footprint.ts b/packages/agent/benchmark/session/loaded-footprint.ts index 273422c1c..82a8a7eab 100644 --- a/packages/agent/benchmark/session/loaded-footprint.ts +++ b/packages/agent/benchmark/session/loaded-footprint.ts @@ -16,7 +16,8 @@ interface LoadedFootprintResult { const execFileAsync = promisify(execFile); const packageRoot = fileURLToPath(new URL("../..", import.meta.url)); const workerPath = fileURLToPath(new URL("./loaded-footprint-worker.ts", import.meta.url)); -const tsconfigPath = fileURLToPath(new URL("../tsconfig.json", import.meta.url)); +// Resolve workspace packages to their sources, matching the root tsconfig paths. +const sourceResolverUrl = new URL("../../../coding-agent/src/experimental/source-resolver.ts", import.meta.url).href; const results: LoadedFootprintResult[] = []; for (const target of storageBenchmarkTargets) { @@ -26,12 +27,12 @@ for (const target of storageBenchmarkTargets) { [ "--expose-gc", "--import", - "tsx", + sourceResolverUrl, workerPath, target.name, dataset.name, ], - { cwd: packageRoot, env: { ...process.env, TSX_TSCONFIG_PATH: tsconfigPath } }, + { cwd: packageRoot }, ); results.push(JSON.parse(stdout) as LoadedFootprintResult); } diff --git a/packages/agent/benchmark/tsconfig.json b/packages/agent/benchmark/tsconfig.json index 674e8c305..3e78650c6 100644 --- a/packages/agent/benchmark/tsconfig.json +++ b/packages/agent/benchmark/tsconfig.json @@ -1,11 +1,10 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "baseUrl": "../../..", "noEmit": true, "paths": { - "@earendil-works/pi-ai": ["packages/ai/src/index.ts"], - "@earendil-works/pi-ai/*": ["packages/ai/src/*"] + "@earendil-works/pi-ai": ["../../ai/src/index.ts"], + "@earendil-works/pi-ai/*": ["../../ai/src/*"] } }, "include": ["./**/*.ts", "../src/**/*.ts"] diff --git a/packages/agent/package.json b/packages/agent/package.json index b2732d5d9..fa8c6cd78 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -48,10 +48,10 @@ "clean": "shx rm -rf dist", "generate-telemetry-docs": "node scripts/generate-telemetry-docs.ts", "check:telemetry-docs": "node scripts/generate-telemetry-docs.ts --check", - "build": "tsgo -p tsconfig.build.json", + "build": "tsc -p tsconfig.build.json", "bench:session:timing": "vitest bench --config vitest.benchmark.config.ts", - "bench:session:memory": "tsx --tsconfig benchmark/tsconfig.json benchmark/session/loaded-footprint.ts", - "bench:session:allocations": "tsx --tsconfig benchmark/tsconfig.json benchmark/session/allocation-profile.ts", + "bench:session:memory": "node --import ../coding-agent/src/experimental/source-resolver.ts benchmark/session/loaded-footprint.ts", + "bench:session:allocations": "node --import ../coding-agent/src/experimental/source-resolver.ts benchmark/session/allocation-profile.ts", "test": "vitest --run", "test:harness": "vitest --run --config vitest.harness.config.ts", "test:session:conformance": "vitest --run --config vitest.harness.config.ts test/harness/memory-conformance.test.ts", @@ -87,7 +87,6 @@ "devDependencies": { "@types/node": "22.19.19", "@vitest/coverage-v8": "4.1.9", - "typescript": "5.9.3", "vitest": "4.1.9" } } diff --git a/packages/ai/package.json b/packages/ai/package.json index eb4e39663..ebd7865f7 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -58,7 +58,7 @@ "generate-model-catalog": "node scripts/generate-models.ts --strict --json-only --json-output ../../.artifacts/model-catalog", "check:model-data": "node scripts/check-model-data.ts", "build": "npm run generate-models && npm run build:offline", - "build:offline": "npm run check:model-data && tsgo -p tsconfig.build.json && shx rm -rf dist/providers/data && shx cp -r src/providers/data dist/providers/data", + "build:offline": "npm run check:model-data && tsc -p tsconfig.build.json && shx rm -rf dist/providers/data && shx cp -r src/providers/data dist/providers/data", "test": "vitest --run", "prepublishOnly": "npm run clean && npm run build" }, diff --git a/packages/chord/package.json b/packages/chord/package.json index 10dd4270f..e1aacf0a6 100644 --- a/packages/chord/package.json +++ b/packages/chord/package.json @@ -41,7 +41,7 @@ ], "scripts": { "clean": "shx rm -rf dist", - "build": "tsgo -p tsconfig.build.json", + "build": "tsc -p tsconfig.build.json", "test": "vitest --run", "prepublishOnly": "npm run clean && npm run build" }, diff --git a/packages/client/package.json b/packages/client/package.json index 9104494a9..9f6eb7088 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -24,9 +24,9 @@ ], "scripts": { "clean": "shx rm -rf dist", - "build": "tsgo -p tsconfig.build.json", + "build": "tsc -p tsconfig.build.json", "test": "vitest --run", - "typecheck": "tsgo -p tsconfig.test.json", + "typecheck": "tsc -p tsconfig.test.json", "prepublishOnly": "npm run clean && npm run build" }, "keywords": [ diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 4ab640f42..ca85bcf72 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -10,6 +10,10 @@ - Added the `provider_stream_event` extension event for observing parsed provider events before normalization, with an opt-in `/debug-provider` example viewer ([#9784](https://github.com/earendil-works/pi/issues/9784)). - Added a show/hide toggle (`H`) in HTML exports for custom messages marked `display: false`. Messages remain hidden by default and can also be revealed from the sidebar ([#8896](https://github.com/earendil-works/pi/issues/8896)). +### Changed + +- Switched the build from the TypeScript native preview to TypeScript 7.0 with an ES2024 target, and replaced `tsx` with Node's built-in type stripping for running from source ([#9965](https://github.com/earendil-works/pi/issues/9965)). + ### Fixed - Fixed X11 clipboard text being misidentified as an image when the clipboard owner accepts unadvertised image targets ([#9786](https://github.com/earendil-works/pi/issues/9786)). diff --git a/packages/coding-agent/examples/README.md b/packages/coding-agent/examples/README.md index 6783a02f3..80bc5e4e0 100644 --- a/packages/coding-agent/examples/README.md +++ b/packages/coding-agent/examples/README.md @@ -9,7 +9,7 @@ Example code for the pi-coding-agent SDK, process integration, and extensions. Build the coding-agent package before running it from a repository checkout: ```bash -npx tsx examples/rpc-client.ts "Explain this repository" +node examples/rpc-client.ts "Explain this repository" ``` ## Directories diff --git a/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts b/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts index 79ba3d718..ce8a392b2 100644 --- a/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts +++ b/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts @@ -1,16 +1,16 @@ /** * Test script for GitLab Duo extension - * Run: npx tsx test.ts [model-id] [--thinking] + * Run: node test.ts [model-id] [--thinking] * * Examples: - * npx tsx test.ts # Test default (claude-sonnet-4-5-20250929) - * npx tsx test.ts gpt-5-codex # Test GPT-5 Codex - * npx tsx test.ts claude-sonnet-4-5-20250929 --thinking + * node test.ts # Test default (claude-sonnet-4-5-20250929) + * node test.ts gpt-5-codex # Test GPT-5 Codex + * node test.ts claude-sonnet-4-5-20250929 --thinking */ import { type Api, type Context, type Model, registerApiProvider, streamSimple } from "@earendil-works/pi-ai/compat"; +import { getAgentDir } from "@earendil-works/pi-coding-agent"; import { readFileSync } from "fs"; -import { getAgentDir } from "packages/coding-agent/src/config.js"; import { join } from "path"; import { MODELS, streamGitLabDuo } from "./index.ts"; diff --git a/packages/coding-agent/examples/rpc-client.ts b/packages/coding-agent/examples/rpc-client.ts index f31c67944..38eff524e 100644 --- a/packages/coding-agent/examples/rpc-client.ts +++ b/packages/coding-agent/examples/rpc-client.ts @@ -2,7 +2,7 @@ * Run one prompt through a Pi RPC child process. * * Build the coding-agent package first, then run: - * npx tsx examples/rpc-client.ts "Explain this repository" + * node examples/rpc-client.ts "Explain this repository" */ import { dirname, join } from "node:path"; diff --git a/packages/coding-agent/examples/rpc-extension-ui.ts b/packages/coding-agent/examples/rpc-extension-ui.ts index 401b7bb0f..0d2be07a5 100644 --- a/packages/coding-agent/examples/rpc-extension-ui.ts +++ b/packages/coding-agent/examples/rpc-extension-ui.ts @@ -5,7 +5,7 @@ * Demonstrates how to build a custom UI on top of the RPC protocol, * including handling extension UI requests (select, confirm, input, editor). * - * Usage: npx tsx examples/rpc-extension-ui.ts + * Usage: node examples/rpc-extension-ui.ts * * Slash commands: * /select - demo select dialog diff --git a/packages/coding-agent/examples/sdk/README.md b/packages/coding-agent/examples/sdk/README.md index 1f8e89f85..0adfff318 100644 --- a/packages/coding-agent/examples/sdk/README.md +++ b/packages/coding-agent/examples/sdk/README.md @@ -26,7 +26,7 @@ The runtime example shows how to build a recreate function that closes over proc ```bash cd packages/coding-agent -npx tsx examples/sdk/01-minimal.ts +node examples/sdk/01-minimal.ts ``` ## Quick Reference diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index 62c01de66..c6c7a9d11 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -40,7 +40,7 @@ "scripts": { "clean": "shx rm -rf dist", "build": "npm run build:unbundled && node ../../scripts/build-coding-agent-bundle.mjs", - "build:unbundled": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets", + "build:unbundled": "tsc -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets", "build:binary": "npm --prefix ../tui run build && npm --prefix ../telemetry run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm --prefix ../protocol run build && npm --prefix ../client run build && npm run build && bun build --compile --no-compile-autoload-bunfig ./src/bun/cli.ts ./src/utils/image-resize-worker.ts --outfile dist/pi && npm run copy-binary-assets", "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/", "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/assets && shx cp src/modes/interactive/assets/*.png dist/assets/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/", @@ -83,7 +83,6 @@ "@types/semver": "7.7.1", "marked": "18.0.11", "shx": "0.4.0", - "typescript": "5.9.3", "vitest": "4.1.9" }, "keywords": [ diff --git a/packages/coding-agent/src/config.ts b/packages/coding-agent/src/config.ts index 98398db2a..c7fc15d0e 100644 --- a/packages/coding-agent/src/config.ts +++ b/packages/coding-agent/src/config.ts @@ -366,7 +366,7 @@ export function getUpdateInstruction(packageName: string): string { /** * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md). * - For Bun binary: returns the directory containing the executable - * - For Node.js and tsx: returns the package root containing package.json + * - For Node.js: returns the package root containing package.json * - Ignores Bun binary metadata copied into dist/ when the package root is available */ export function findNodePackageDir(startDir: string): string { @@ -404,7 +404,7 @@ export function getPackageDir(): string { * Get path to built-in themes directory (shipped with package) * - For Bun binary: theme/ next to executable * - For Node.js (dist/): dist/modes/interactive/theme/ - * - For tsx (src/): src/modes/interactive/theme/ + * - For source (src/): src/modes/interactive/theme/ */ export function getThemesDir(): string { if (isBunBinary) { @@ -420,7 +420,7 @@ export function getThemesDir(): string { * Get path to HTML export template directory (shipped with package) * - For Bun binary: export-html/ next to executable * - For Node.js (dist/): dist/core/export-html/ - * - For tsx (src/): src/core/export-html/ + * - For source (src/): src/core/export-html/ */ export function getExportTemplateDir(): string { if (isBunBinary) { @@ -460,7 +460,7 @@ export function getChangelogPath(): string { * Get path to built-in interactive assets directory. * - For Bun binary: assets/ next to executable * - For Node.js (dist/): dist/modes/interactive/assets/ - * - For tsx (src/): src/modes/interactive/assets/ + * - For source (src/): src/modes/interactive/assets/ */ export function getInteractiveAssetsDir(): string { if (isBunBinary) { diff --git a/packages/coding-agent/src/experimental/micro/README.md b/packages/coding-agent/src/experimental/micro/README.md index 659f6dd7d..e1dc3a68b 100644 --- a/packages/coding-agent/src/experimental/micro/README.md +++ b/packages/coding-agent/src/experimental/micro/README.md @@ -10,8 +10,8 @@ storage. Command failures and Pico events are folded into the view, so rendering result side channel. ```bash -./node_modules/.bin/tsx --tsconfig tsconfig.json packages/coding-agent/src/experimental/micro/main.ts -./node_modules/.bin/tsx --tsconfig tsconfig.json packages/coding-agent/src/experimental/micro/main.ts --continue +node --import ./packages/coding-agent/src/experimental/source-resolver.ts packages/coding-agent/src/experimental/micro/main.ts +node --import ./packages/coding-agent/src/experimental/source-resolver.ts packages/coding-agent/src/experimental/micro/main.ts --continue ``` New sessions default to `openai-codex/gpt-5.6-sol`. `--continue` keeps the session's stored model and diff --git a/packages/coding-agent/src/experimental/mini/README.md b/packages/coding-agent/src/experimental/mini/README.md index 7552e7b51..d327dd170 100644 --- a/packages/coding-agent/src/experimental/mini/README.md +++ b/packages/coding-agent/src/experimental/mini/README.md @@ -8,7 +8,7 @@ an RPC-shaped presentation actually needs from it. node packages/coding-agent/src/experimental/mini/main.ts [--continue] # while the harness is changing under us, run from source instead of built dist: -./node_modules/.bin/tsx --tsconfig tsconfig.json packages/coding-agent/src/experimental/mini/main.ts +node --import ./packages/coding-agent/src/experimental/source-resolver.ts packages/coding-agent/src/experimental/mini/main.ts ``` `--continue` attaches to the newest session for the current directory. Starting `mini` twice attaches diff --git a/packages/coding-agent/src/experimental/process.ts b/packages/coding-agent/src/experimental/process.ts index 90c4b9eae..cea91b0e7 100644 --- a/packages/coding-agent/src/experimental/process.ts +++ b/packages/coding-agent/src/experimental/process.ts @@ -47,8 +47,9 @@ export function spawnInternalProcess( throw new Error("A compiled Bun executable cannot launch an external internal-process entrypoint"); } const entryUrl = defaultEntryUrl(role, options.entryUrl); + // --import takes a module specifier; a raw path breaks on Windows drives and on `#`, `?`, or `%` in the path. const sourceRuntimeArgs = import.meta.url.endsWith(".ts") - ? ["--import", fileURLToPath(new URL("source-resolver.ts", import.meta.url))] + ? ["--import", new URL("source-resolver.ts", import.meta.url).href] : []; const child = spawn( process.execPath, diff --git a/packages/coding-agent/src/modes/interactive/theme/theme.ts b/packages/coding-agent/src/modes/interactive/theme/theme.ts index 384126ffb..a9070f311 100644 --- a/packages/coding-agent/src/modes/interactive/theme/theme.ts +++ b/packages/coding-agent/src/modes/interactive/theme/theme.ts @@ -740,12 +740,12 @@ export function getDefaultTheme(): string { // Global Theme Instance // ============================================================================ -// Use globalThis to share theme across module loaders (tsx + jiti in dev mode) +// Use globalThis to share theme across module loaders (node + jiti in dev mode) const THEME_KEY = Symbol.for("@earendil-works/pi-coding-agent:theme"); const THEME_KEY_OLD = Symbol.for("@mariozechner/pi-coding-agent:theme"); // Export theme as a getter that reads from globalThis -// This ensures all module instances (tsx, jiti) see the same theme +// This ensures all module instances (node, jiti) see the same theme export const theme: Theme = new Proxy({} as Theme, { get(_target, prop) { const t = (globalThis as Record)[THEME_KEY]; diff --git a/packages/coding-agent/test/experimental-cli-entry.test.ts b/packages/coding-agent/test/experimental-cli-entry.test.ts index c2277e45d..ae3b53906 100644 --- a/packages/coding-agent/test/experimental-cli-entry.test.ts +++ b/packages/coding-agent/test/experimental-cli-entry.test.ts @@ -2,10 +2,12 @@ import { spawnSync } from "node:child_process"; import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; +import { pathToFileURL } from "node:url"; import { afterEach, describe, expect, it } from "vitest"; import { VERSION } from "../src/config.ts"; -const sourceResolverPath = resolve(__dirname, "../src/experimental/source-resolver.ts"); +// --import takes a module specifier, not a filesystem path. +const sourceResolverUrl = pathToFileURL(resolve(__dirname, "../src/experimental/source-resolver.ts")).href; const tempDirs: string[] = []; afterEach(() => { @@ -19,7 +21,7 @@ function runEntry(entry: string, experimental: boolean) { process.execPath, [ "--import", - sourceResolverPath, + sourceResolverUrl, resolve(__dirname, "../src", entry), "server", "--server-id", diff --git a/packages/coding-agent/test/rpc-example.ts b/packages/coding-agent/test/rpc-example.ts index aaa24fb1f..3be21ca55 100644 --- a/packages/coding-agent/test/rpc-example.ts +++ b/packages/coding-agent/test/rpc-example.ts @@ -7,7 +7,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); /** * Interactive example of using coding-agent via RpcClient. - * Usage: npx tsx test/rpc-example.ts + * Usage: node test/rpc-example.ts */ async function main() { diff --git a/packages/coding-agent/test/session-file-invalid.test.ts b/packages/coding-agent/test/session-file-invalid.test.ts index e2eb7015c..915936562 100644 --- a/packages/coding-agent/test/session-file-invalid.test.ts +++ b/packages/coding-agent/test/session-file-invalid.test.ts @@ -2,11 +2,13 @@ import { spawn } from "node:child_process"; import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; +import { pathToFileURL } from "node:url"; import { afterEach, describe, expect, it } from "vitest"; import { ENV_AGENT_DIR } from "../src/config.ts"; const cliPath = resolve(__dirname, "../src/cli.ts"); -const sourceResolverPath = resolve(__dirname, "../src/experimental/source-resolver.ts"); +// --import takes a module specifier, not a filesystem path. +const sourceResolverUrl = pathToFileURL(resolve(__dirname, "../src/experimental/source-resolver.ts")).href; const tempDirs: string[] = []; afterEach(() => { @@ -24,7 +26,7 @@ function createTempDir(): string { async function runCli(args: string[], cwd: string, agentDir: string): Promise<{ code: number | null; stderr: string }> { let stderr = ""; const code = await new Promise((resolvePromise, reject) => { - const child = spawn(process.execPath, ["--import", sourceResolverPath, cliPath, ...args], { + const child = spawn(process.execPath, ["--import", sourceResolverUrl, cliPath, ...args], { cwd, env: { ...process.env, diff --git a/packages/coding-agent/test/session-id-readonly.test.ts b/packages/coding-agent/test/session-id-readonly.test.ts index 15916c6da..a867db789 100644 --- a/packages/coding-agent/test/session-id-readonly.test.ts +++ b/packages/coding-agent/test/session-id-readonly.test.ts @@ -11,6 +11,7 @@ import { } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; +import { pathToFileURL } from "node:url"; import { afterEach, describe, expect, it, vi } from "vitest"; import type { Args } from "../src/cli/args.ts"; import { ENV_AGENT_DIR } from "../src/config.ts"; @@ -19,7 +20,8 @@ import { SettingsManager } from "../src/core/settings-manager.ts"; import { createSessionManager } from "../src/main.ts"; const cliPath = resolve(__dirname, "../src/cli.ts"); -const sourceResolverPath = resolve(__dirname, "../src/experimental/source-resolver.ts"); +// --import takes a module specifier, not a filesystem path. +const sourceResolverUrl = pathToFileURL(resolve(__dirname, "../src/experimental/source-resolver.ts")).href; const tempDirs: string[] = []; afterEach(() => { @@ -64,7 +66,7 @@ async function runCli(args: string[]): Promise<{ code: number | null; agentDir: mkdirSync(projectDir, { recursive: true }); const code = await new Promise((resolvePromise, reject) => { - const child = spawn(process.execPath, ["--import", sourceResolverPath, cliPath, ...args], { + const child = spawn(process.execPath, ["--import", sourceResolverUrl, cliPath, ...args], { cwd: projectDir, env: { ...process.env, diff --git a/packages/coding-agent/test/startup-session-name.test.ts b/packages/coding-agent/test/startup-session-name.test.ts index c953cd1ae..fbb0b1472 100644 --- a/packages/coding-agent/test/startup-session-name.test.ts +++ b/packages/coding-agent/test/startup-session-name.test.ts @@ -2,11 +2,13 @@ import { spawn } from "node:child_process"; import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; +import { pathToFileURL } from "node:url"; import { afterEach, describe, expect, it } from "vitest"; import { ENV_AGENT_DIR } from "../src/config.ts"; const cliPath = resolve(__dirname, "../src/cli.ts"); -const sourceResolverPath = resolve(__dirname, "../src/experimental/source-resolver.ts"); +// --import takes a module specifier, not a filesystem path. +const sourceResolverUrl = pathToFileURL(resolve(__dirname, "../src/experimental/source-resolver.ts")).href; const tempDirs: string[] = []; afterEach(() => { @@ -66,7 +68,7 @@ function readSessionInfoNames(sessionFile: string): string[] { async function runCli(args: string[], dirs: CliDirs): Promise { let stderr = ""; - const child = spawn(process.execPath, ["--import", sourceResolverPath, cliPath, ...args], { + const child = spawn(process.execPath, ["--import", sourceResolverUrl, cliPath, ...args], { cwd: dirs.projectDir, env: { ...process.env, diff --git a/packages/coding-agent/test/stdout-cleanliness.test.ts b/packages/coding-agent/test/stdout-cleanliness.test.ts index baaf296a5..c66b21f16 100644 --- a/packages/coding-agent/test/stdout-cleanliness.test.ts +++ b/packages/coding-agent/test/stdout-cleanliness.test.ts @@ -2,12 +2,14 @@ import { spawn } from "node:child_process"; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; +import { pathToFileURL } from "node:url"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { ENV_AGENT_DIR } from "../src/config.ts"; import { allowNetwork } from "./test-network-env.ts"; const cliPath = resolve(__dirname, "../src/cli.ts"); -const sourceResolverPath = resolve(__dirname, "../src/experimental/source-resolver.ts"); +// --import takes a module specifier, not a filesystem path. +const sourceResolverUrl = pathToFileURL(resolve(__dirname, "../src/experimental/source-resolver.ts")).href; const tempDirs: string[] = []; @@ -60,7 +62,7 @@ async function runCli(args: string[]): Promise<{ stdout: string; stderr: string; ); return await new Promise((resolvePromise, reject) => { - const child = spawn(process.execPath, ["--import", sourceResolverPath, cliPath, ...args], { + const child = spawn(process.execPath, ["--import", sourceResolverUrl, cliPath, ...args], { cwd: projectDir, env: { ...process.env, diff --git a/packages/coding-agent/test/streaming-render-debug.ts b/packages/coding-agent/test/streaming-render-debug.ts index 934782380..2a1e4638b 100644 --- a/packages/coding-agent/test/streaming-render-debug.ts +++ b/packages/coding-agent/test/streaming-render-debug.ts @@ -1,7 +1,7 @@ /** * Debug script to reproduce streaming rendering issues. * Uses real fixture data that caused the bug. - * Run with: npx tsx test/streaming-render-debug.ts + * Run with: node --import ./src/experimental/source-resolver.ts test/streaming-render-debug.ts */ import type { AssistantMessage } from "@earendil-works/pi-ai"; diff --git a/packages/coding-agent/test/test-theme-colors.ts b/packages/coding-agent/test/test-theme-colors.ts index 4e7181f35..3c61a660e 100644 --- a/packages/coding-agent/test/test-theme-colors.ts +++ b/packages/coding-agent/test/test-theme-colors.ts @@ -242,8 +242,11 @@ if (cmd === "contrast") { } else if (cmd === "light" || cmd === "dark") { cmdTheme(cmd); } else { - console.log("Usage:"); - console.log(" npx tsx test-theme-colors.ts light|dark Test built-in theme"); - console.log(" npx tsx test-theme-colors.ts contrast 4.5 Compute colors at ratio"); - console.log(" npx tsx test-theme-colors.ts test file.json Test any JSON file"); + console.log("Usage (from packages/coding-agent):"); + console.log(" node --import ./src/experimental/source-resolver.ts test/test-theme-colors.ts "); + console.log(""); + console.log("Commands:"); + console.log(" light|dark Test built-in theme"); + console.log(" contrast 4.5 Compute colors at ratio"); + console.log(" test file.json Test any JSON file"); } diff --git a/packages/durable/package.json b/packages/durable/package.json index 7e439987f..e7ffc9046 100644 --- a/packages/durable/package.json +++ b/packages/durable/package.json @@ -61,7 +61,7 @@ ], "scripts": { "clean": "shx rm -rf dist", - "build": "tsgo -p tsconfig.build.json", + "build": "tsc -p tsconfig.build.json", "test": "vitest --run", "bench:storage": "vitest bench --config vitest.benchmark.config.ts", "bench:storage:memory": "node --conditions=source --experimental-strip-types test/storage-memory.ts", diff --git a/packages/evals/package.json b/packages/evals/package.json index f7056cbc7..7609c388b 100644 --- a/packages/evals/package.json +++ b/packages/evals/package.json @@ -11,14 +11,13 @@ "test": "vitest run --config vitest.test.config.ts" }, "devDependencies": { - "autoevals": "0.3.0", "@earendil-works/pi-ai": "^0.87.1", "@earendil-works/pi-coding-agent": "^0.87.1", "@types/node": "22.19.19", "@vitest-evals/core": "0.15.0", + "autoevals": "0.3.0", "shx": "0.4.0", - "typescript": "5.9.3", - "vitest-evals": "0.15.0", - "vitest": "4.1.9" + "vitest": "4.1.9", + "vitest-evals": "0.15.0" } } diff --git a/packages/protocol/package.json b/packages/protocol/package.json index 605655f2c..ef7f7a208 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -17,7 +17,7 @@ ], "scripts": { "clean": "shx rm -rf dist", - "build": "tsgo -p tsconfig.build.json", + "build": "tsc -p tsconfig.build.json", "test": "vitest --run", "prepublishOnly": "npm run clean && npm run build" }, diff --git a/packages/server/package.json b/packages/server/package.json index 36cae1657..131d5240e 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -26,10 +26,10 @@ ], "scripts": { "clean": "shx rm -rf dist", - "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput", - "build": "tsgo -p tsconfig.build.json", + "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput", + "build": "tsc -p tsconfig.build.json", "test": "vitest --run", - "typecheck": "tsgo -p tsconfig.test.json", + "typecheck": "tsc -p tsconfig.test.json", "prepublishOnly": "npm run clean && npm run build" }, "keywords": [ diff --git a/packages/session-backends/sqlite-node/package.json b/packages/session-backends/sqlite-node/package.json index dbc91b15e..0e1215a1a 100644 --- a/packages/session-backends/sqlite-node/package.json +++ b/packages/session-backends/sqlite-node/package.json @@ -18,7 +18,7 @@ ], "scripts": { "clean": "node -e \"import('node:fs/promises').then(fs=>fs.rm('dist',{recursive:true,force:true}))\"", - "build": "tsgo -p tsconfig.build.json && node scripts/copy-migrations.mjs", + "build": "tsc -p tsconfig.build.json && node scripts/copy-migrations.mjs", "bench:session:timing": "vitest bench --config vitest.benchmark.config.ts", "test": "vitest --run", "coverage": "vitest --run --coverage", diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index 753286462..9eb8eaf57 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -21,7 +21,7 @@ ], "scripts": { "clean": "shx rm -rf dist", - "build": "tsgo -p tsconfig.build.json", + "build": "tsc -p tsconfig.build.json", "test": "vitest --run", "prepublishOnly": "npm run clean && npm run build" }, diff --git a/packages/tui/README.md b/packages/tui/README.md index 6a3c6427b..20992f87a 100644 --- a/packages/tui/README.md +++ b/packages/tui/README.md @@ -920,7 +920,7 @@ See `test/chat-simple.ts` for a complete chat interface example with: Run it: ```bash -npx tsx test/chat-simple.ts +node test/chat-simple.ts ``` ## Development @@ -933,7 +933,7 @@ npm install npm run check # Run the demo -npx tsx test/chat-simple.ts +node test/chat-simple.ts ``` ### Debug logging @@ -941,5 +941,5 @@ npx tsx test/chat-simple.ts Set `PI_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout. ```bash -PI_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx test/chat-simple.ts +PI_TUI_WRITE_LOG=/tmp/tui-ansi.log node test/chat-simple.ts ``` diff --git a/packages/tui/package.json b/packages/tui/package.json index 90e79d4e5..209f4e6fe 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -6,7 +6,7 @@ "main": "dist/index.js", "scripts": { "clean": "shx rm -rf dist", - "build": "tsgo -p tsconfig.build.json", + "build": "tsc -p tsconfig.build.json", "build:native:darwin": "native/darwin/build.sh", "build:native:linux": "native/linux/build.sh", "build:native:win32": "node native/win32/build.mjs", diff --git a/packages/tui/test/image-test.ts b/packages/tui/test/image-test.ts index 73a26862d..05fb32ac5 100644 --- a/packages/tui/test/image-test.ts +++ b/packages/tui/test/image-test.ts @@ -17,7 +17,7 @@ try { imageBuffer = readFileSync(testImagePath); } catch (_e) { console.error(`Failed to load image: ${testImagePath}`); - console.error("Usage: npx tsx test/image-test.ts [path-to-image.png]"); + console.error("Usage: node test/image-test.ts [path-to-image.png]"); process.exit(1); } diff --git a/packages/tui/test/viewport-overwrite-repro.ts b/packages/tui/test/viewport-overwrite-repro.ts index 1826af068..f4541d5bf 100644 --- a/packages/tui/test/viewport-overwrite-repro.ts +++ b/packages/tui/test/viewport-overwrite-repro.ts @@ -2,11 +2,11 @@ * TUI viewport overwrite repro * * Place this file at: packages/tui/test/viewport-overwrite-repro.ts - * Run from repo root: npx tsx packages/tui/test/viewport-overwrite-repro.ts + * Run from repo root: node packages/tui/test/viewport-overwrite-repro.ts * * For reliable repro, run in a small terminal (8-12 rows) or a tmux session: * tmux new-session -d -s tui-bug -x 80 -y 12 - * tmux send-keys -t tui-bug "npx tsx packages/tui/test/viewport-overwrite-repro.ts" Enter + * tmux send-keys -t tui-bug "node packages/tui/test/viewport-overwrite-repro.ts" Enter * tmux attach -t tui-bug * * Expected behavior: diff --git a/pi-test.ps1 b/pi-test.ps1 index 610aeaeb2..dc3625a57 100644 --- a/pi-test.ps1 +++ b/pi-test.ps1 @@ -58,13 +58,10 @@ if ($noEnv) { Write-Host "Running without API keys..." } -$tsxBin = Join-Path $scriptDir "node_modules/.bin/tsx.cmd" -if (-not (Test-Path -LiteralPath $tsxBin)) { - throw "tsx not found at $tsxBin. Run npm install from the repo root first." -} - +# --import takes a module specifier, so pass the resolver as a file URL (Windows paths are not specifiers). +$resolverUrl = ([System.Uri](Join-Path $scriptDir "packages/coding-agent/src/experimental/source-resolver.ts")).AbsoluteUri $cliPath = Join-Path $scriptDir "packages/coding-agent/src/cli.ts" -& $tsxBin $cliPath @forwardArgs +& node --import $resolverUrl $cliPath @forwardArgs $exitCode = $LASTEXITCODE if ($exitCode -ne 0) { exit $exitCode diff --git a/pi-test.sh b/pi-test.sh index 3f40112bd..29a2510ce 100755 --- a/pi-test.sh +++ b/pi-test.sh @@ -54,4 +54,6 @@ if [[ "$NO_ENV" == "true" ]]; then echo "Running without API keys..." fi -"$SCRIPT_DIR/node_modules/.bin/tsx" --tsconfig "$SCRIPT_DIR/tsconfig.json" "$SCRIPT_DIR/packages/coding-agent/src/experimental/cli.ts" ${ARGS[@]+"${ARGS[@]}"} +# --import takes a module specifier, so pass the resolver as a file URL (raw paths break on #, ?, %). +RESOLVER_URL="$(node -p 'require("node:url").pathToFileURL(process.argv[1]).href' "$SCRIPT_DIR/packages/coding-agent/src/experimental/source-resolver.ts")" +node --import "$RESOLVER_URL" "$SCRIPT_DIR/packages/coding-agent/src/experimental/cli.ts" ${ARGS[@]+"${ARGS[@]}"} diff --git a/scripts/check-runtime-deps.mjs b/scripts/check-runtime-deps.mjs index 7d3850772..e24627be2 100644 --- a/scripts/check-runtime-deps.mjs +++ b/scripts/check-runtime-deps.mjs @@ -3,9 +3,24 @@ import { existsSync, readFileSync } from "node:fs"; import { isBuiltin } from "node:module"; import { isAbsolute, join, relative, resolve } from "node:path"; -import ts from "typescript"; +import { SyntaxKind } from "typescript/unstable/ast"; +import { + isCallExpression, + isExportDeclaration, + isIdentifier, + isImportDeclaration, + isNamedExports, + isNamedImports, + isNoSubstitutionTemplateLiteral, + isPropertyAccessExpression, + isStringLiteral, +} from "typescript/unstable/ast/is"; +import { API } from "typescript/unstable/sync"; import { getPublicWorkspacePackages } from "./release-packages.mjs"; +// Packages without tsconfig.build.json are checked against a synthetic config. +const fallbackConfigName = "tsconfig.runtime-deps-fallback.json"; +const fallbackConfig = JSON.stringify({ include: ["src/**/*"] }); const failures = []; function checkSource(source, manifest) { @@ -18,7 +33,7 @@ function checkSource(source, manifest) { ]); function checkSpecifier(node) { - if (!node || !ts.isStringLiteralLike(node)) return; + if (!node || !(isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node))) return; const specifier = node.text; if (specifier.startsWith(".") || specifier.startsWith("/") || isBuiltin(specifier)) return; const name = specifier.split("/").slice(0, specifier.startsWith("@") ? 2 : 1).join("/"); @@ -28,61 +43,86 @@ function checkSource(source, manifest) { } function visit(node) { - if (ts.isImportDeclaration(node)) { + if (isImportDeclaration(node)) { const clause = node.importClause; const bindings = clause?.namedBindings; if ( !clause || - (!clause.isTypeOnly && - (clause.name || !bindings || !ts.isNamedImports(bindings) || - bindings.elements.length === 0 || bindings.elements.some((element) => !element.isTypeOnly))) + (clause.phaseModifier !== SyntaxKind.TypeKeyword && + (clause.name || + !bindings || + !isNamedImports(bindings) || + bindings.elements.length === 0 || + bindings.elements.some((element) => !element.isTypeOnly))) ) { checkSpecifier(node.moduleSpecifier); } - } else if (ts.isExportDeclaration(node) && !node.isTypeOnly) { + } else if (isExportDeclaration(node) && !node.isTypeOnly) { const clause = node.exportClause; - if (!clause || !ts.isNamedExports(clause) || clause.elements.length === 0 || clause.elements.some((element) => !element.isTypeOnly)) { + if ( + !clause || + !isNamedExports(clause) || + clause.elements.length === 0 || + clause.elements.some((element) => !element.isTypeOnly) + ) { checkSpecifier(node.moduleSpecifier); } } else if ( - ts.isCallExpression(node) && - (node.expression.kind === ts.SyntaxKind.ImportKeyword || - (ts.isIdentifier(node.expression) && node.expression.text === "require") || - (ts.isPropertyAccessExpression(node.expression) && node.expression.getText(source) === "require.resolve")) + isCallExpression(node) && + (node.expression.kind === SyntaxKind.ImportKeyword || + (isIdentifier(node.expression) && node.expression.text === "require") || + (isPropertyAccessExpression(node.expression) && node.expression.getText(source) === "require.resolve")) ) { checkSpecifier(node.arguments[0]); } - ts.forEachChild(node, visit); + node.forEachChild(visit); } visit(source); } -for (const { directory } of getPublicWorkspacePackages()) { - const sourceDirectory = resolve(directory, "src"); - if (!existsSync(sourceDirectory)) continue; - const manifest = JSON.parse(readFileSync(join(directory, "package.json"), "utf8")); - const configPath = join(directory, "tsconfig.build.json"); - const config = existsSync(configPath) - ? ts.readConfigFile(configPath, ts.sys.readFile) - : { config: { include: ["src/**/*"] } }; - if (config.error) throw new Error(ts.flattenDiagnosticMessageText(config.error.messageText, "\n")); - const parsed = ts.parseJsonConfigFileContent(config.config, ts.sys, resolve(directory)); - if (parsed.errors.length > 0) { - throw new Error(parsed.errors.map((error) => ts.flattenDiagnosticMessageText(error.messageText, "\n")).join("\n")); - } - const roots = new Set(parsed.fileNames.map((file) => resolve(file))); - const program = ts.createProgram(parsed.fileNames, parsed.options); - for (const source of program.getSourceFiles()) { - if (source.isDeclarationFile || source.fileName.endsWith(".json")) continue; - const path = relative(sourceDirectory, resolve(source.fileName)); - if (path.startsWith("..") || isAbsolute(path)) continue; - // TypeScript's exclude only filters roots: imports can pull excluded files - // back into the build. Reject that too, including type-only imports. - if (!roots.has(resolve(source.fileName))) { - failures.push(`${source.fileName} is excluded from ${manifest.name}'s build but imported by it`); +const packages = getPublicWorkspacePackages() + .map(({ directory }) => ({ directory, sourceDirectory: resolve(directory, "src") })) + .filter(({ sourceDirectory }) => existsSync(sourceDirectory)) + .map(({ directory, sourceDirectory }) => { + const configPath = resolve(directory, "tsconfig.build.json"); + return { + sourceDirectory, + manifest: JSON.parse(readFileSync(join(directory, "package.json"), "utf8")), + configPath: existsSync(configPath) ? configPath : resolve(directory, fallbackConfigName), + }; + }); + +const fallbackConfigs = new Set( + packages.map(({ configPath }) => configPath).filter((path) => path.endsWith(fallbackConfigName)), +); +const api = new API({ + cwd: process.cwd(), + fs: { + fileExists: (fileName) => (fallbackConfigs.has(resolve(fileName)) ? true : undefined), + readFile: (fileName) => (fallbackConfigs.has(resolve(fileName)) ? fallbackConfig : undefined), + }, +}); +try { + const snapshot = api.updateSnapshot({ openProjects: packages.map(({ configPath }) => configPath) }); + for (const { sourceDirectory, manifest, configPath } of packages) { + const project = snapshot.getProject(configPath); + const diagnostics = project.program.getConfigFileParsingDiagnostics(); + if (diagnostics.length > 0) throw new Error(diagnostics.map((diagnostic) => diagnostic.text).join("\n")); + const roots = new Set(project.rootFiles.map((file) => resolve(file))); + for (const fileName of project.program.getSourceFileNames()) { + if (fileName.endsWith(".d.ts") || fileName.endsWith(".json")) continue; + const path = relative(sourceDirectory, resolve(fileName)); + if (path.startsWith("..") || isAbsolute(path)) continue; + // TypeScript's exclude only filters roots: imports can pull excluded files + // back into the build. Reject that too, including type-only imports. + if (!roots.has(resolve(fileName))) { + failures.push(`${fileName} is excluded from ${manifest.name}'s build but imported by it`); + } + checkSource(project.program.getSourceFile(fileName), manifest); } - checkSource(source, manifest); } +} finally { + api.close(); } if (failures.length > 0) { diff --git a/scripts/check-ts-relative-imports.mjs b/scripts/check-ts-relative-imports.mjs index bf21a5d0a..26ff0a791 100644 --- a/scripts/check-ts-relative-imports.mjs +++ b/scripts/check-ts-relative-imports.mjs @@ -1,6 +1,16 @@ -import { readdirSync, readFileSync } from "node:fs"; -import { join } from "node:path"; -import ts from "typescript"; +import { readdirSync } from "node:fs"; +import { join, relative, resolve } from "node:path"; +import { SyntaxKind } from "typescript/unstable/ast"; +import { + isCallExpression, + isExportDeclaration, + isImportDeclaration, + isImportTypeNode, + isLiteralTypeNode, + isNoSubstitutionTemplateLiteral, + isStringLiteral, +} from "typescript/unstable/ast/is"; +import { API } from "typescript/unstable/sync"; const ignoredDirectories = new Set([".git", "coverage", "dist", "node_modules"]); const files = []; @@ -20,13 +30,17 @@ function collectTypescriptFiles(directory) { } } +function isStringLiteralLike(node) { + return node !== undefined && (isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node)); +} + function isRelativeJavaScriptSpecifier(specifier) { return /^\.\.?\//.test(specifier) && /\.js(?:[?#].*)?$/.test(specifier); } function getImportTypeSpecifier(node) { - if (!ts.isLiteralTypeNode(node.argument)) return undefined; - if (!ts.isStringLiteralLike(node.argument.literal)) return undefined; + if (!isLiteralTypeNode(node.argument)) return undefined; + if (!isStringLiteralLike(node.argument.literal)) return undefined; return node.argument.literal; } @@ -34,37 +48,54 @@ const failures = []; collectTypescriptFiles("."); -for (const file of files.sort()) { - const sourceText = readFileSync(file, "utf8"); - const sourceFile = ts.createSourceFile(file, sourceText, ts.ScriptTarget.Latest, true); +// Parse every file through one synthetic project. noResolve keeps the program to exactly these files. +const configPath = resolve("tsconfig.check-ts-relative-imports.json"); +const config = JSON.stringify({ + compilerOptions: { noResolve: true, noLib: true, types: [] }, + files: files.map((file) => resolve(file)), +}); +const api = new API({ + cwd: process.cwd(), + fs: { + fileExists: (fileName) => (resolve(fileName) === configPath ? true : undefined), + readFile: (fileName) => (resolve(fileName) === configPath ? config : undefined), + }, +}); - function checkSpecifier(node) { - if (!isRelativeJavaScriptSpecifier(node.text)) return; - const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)); - failures.push(`${file}:${line + 1}:${character + 1}: ${node.text}`); - } +try { + const program = api.updateSnapshot({ openProjects: [configPath] }).getProject(configPath).program; + for (const file of files.sort()) { + const sourceFile = program.getSourceFile(resolve(file)); - function visit(node) { - if (ts.isImportDeclaration(node) && ts.isStringLiteralLike(node.moduleSpecifier)) { - checkSpecifier(node.moduleSpecifier); - } else if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteralLike(node.moduleSpecifier)) { - checkSpecifier(node.moduleSpecifier); - } else if ( - ts.isCallExpression(node) && - node.expression.kind === ts.SyntaxKind.ImportKeyword && - node.arguments[0] && - ts.isStringLiteralLike(node.arguments[0]) - ) { - checkSpecifier(node.arguments[0]); - } else if (ts.isImportTypeNode(node)) { - const specifier = getImportTypeSpecifier(node); - if (specifier) checkSpecifier(specifier); + function checkSpecifier(node) { + if (!isRelativeJavaScriptSpecifier(node.text)) return; + const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)); + failures.push(`${relative(".", file)}:${line + 1}:${character + 1}: ${node.text}`); } - ts.forEachChild(node, visit); - } + function visit(node) { + if (isImportDeclaration(node) && isStringLiteralLike(node.moduleSpecifier)) { + checkSpecifier(node.moduleSpecifier); + } else if (isExportDeclaration(node) && isStringLiteralLike(node.moduleSpecifier)) { + checkSpecifier(node.moduleSpecifier); + } else if ( + isCallExpression(node) && + node.expression.kind === SyntaxKind.ImportKeyword && + isStringLiteralLike(node.arguments[0]) + ) { + checkSpecifier(node.arguments[0]); + } else if (isImportTypeNode(node)) { + const specifier = getImportTypeSpecifier(node); + if (specifier) checkSpecifier(specifier); + } - visit(sourceFile); + node.forEachChild(visit); + } + + visit(sourceFile); + } +} finally { + api.close(); } if (failures.length > 0) { diff --git a/tsconfig.base.json b/tsconfig.base.json index 57e97d6e3..4449172b2 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,10 +1,11 @@ { "compilerOptions": { - "target": "ES2022", + "target": "ES2024", "module": "Node16", - "lib": ["ES2022"], + "lib": ["ES2024"], "strict": true, "erasableSyntaxOnly": true, + "verbatimModuleSyntax": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, @@ -17,9 +18,6 @@ "resolveJsonModule": true, "allowImportingTsExtensions": true, "rewriteRelativeImportExtensions": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "useDefineForClassFields": false, "types": ["node"] } } diff --git a/tsconfig.json b/tsconfig.json index 31d343d92..2dd9e0ccf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,6 @@ "module": "NodeNext", "moduleResolution": "NodeNext", "paths": { - "*": ["./*"], "@earendil-works/chord": ["./packages/chord/src/index.ts"], "@earendil-works/chord/bundler": ["./packages/chord/src/bundler.ts"], "@earendil-works/chord/context": ["./packages/chord/src/context/index.ts"],