Problem
Modern npm packages often publish JavaScript implementation files plus .d.ts declaration sidecars. Perry currently treats node_modules JavaScript implementation files as runtime-JS inputs unless the package is explicitly routed through compilePackages, but the compiler does not yet use the package's .d.ts metadata to type and lower those JS implementations as native Perry code.
This blocks native use of packages like @openai/codex-sdk, which publishes:
dist/index.js
dist/index.d.ts
TypeScript consumers retain API types from dist/index.d.ts, but Perry native codegen sees the executable entry as dist/index.js and routes it into the JS-runtime gate instead of a declaration-guided native package compile.
Context
The architecture Perry likely needs is a declaration-guided npm package compiler path:
- Resolve package exports to both implementation (
.js) and type sidecar (.d.ts / exports.types / types).
- Use declarations as API/type metadata for JS exports, classes, functions, overloads, and object shapes.
- Lower the JS implementation through Perry HIR under the existing
perry.compilePackages + perry.allow.compilePackages trust boundary.
- Route supported Node APIs to Perry-native stdlib shims and emit precise diagnostics for unsupported APIs/patterns.
- Prefer original TS sources when available via source maps or declaration maps.
For @openai/codex-sdk, this would let Perry compile the SDK wrapper natively instead of requiring a Node worker or runtime JS fallback. The SDK's core surface is small (Codex, Thread, startThread, resumeThread, run, runStreamed) and mostly wraps codex exec --experimental-json, so it is a good test case for this architecture.
Verification
Temp project:
mkdir /tmp/perry-codex-sdk-smoke
cd /tmp/perry-codex-sdk-smoke
npm init -y
npm install --save-exact @perryts/perry@0.5.1025 @openai/codex-sdk@0.135.0 typescript@6.0.3
With src/main.ts directly importing the SDK:
import { Codex } from "@openai/codex-sdk";
const codex = new Codex({ codexPathOverride: "./fake-codex.mjs" });
const thread = codex.startThread({ skipGitRepoCheck: true });
console.log(typeof thread.run);
Native compile fails at the package JS boundary:
npx perry compile src/main.ts -o dist/direct
Observed:
Collecting modules...
JS module: @openai/codex-sdk -> .../node_modules/@openai/codex-sdk/dist/index.js
Error: build pulled in `perry-jsruntime` ... [@openai/codex-sdk]
Trying the runtime-JS path also fails with the published package on macOS arm64:
npx perry compile src/main.ts --enable-js-runtime -o dist/direct
Observed:
JavaScript modules found but libperry_jsruntime.a not found
A workaround was verified: compile a native Perry launcher that uses Perry's native child_process.spawnSync to run a tiny Node worker, and let that worker import @openai/codex-sdk. That proves the SDK API and protocol are usable, but it is not native Perry integration.
Useful open-source references
- Google Closure Compiler: externs are the closest mature model for treating declarations as compiler-visible API contracts for JS.
- tsickle: useful prior art for translating TypeScript type information into Closure-compatible metadata/externs.
- Deno: useful reference for resolving JS modules with declaration sidecars in a TypeScript-aware runtime/toolchain.
- Porffor: useful lower-level reference for ahead-of-time JS compilation tradeoffs, although it does not solve the
.d.ts package sidecar architecture directly.
Problem
Modern npm packages often publish JavaScript implementation files plus
.d.tsdeclaration sidecars. Perry currently treatsnode_modulesJavaScript implementation files as runtime-JS inputs unless the package is explicitly routed throughcompilePackages, but the compiler does not yet use the package's.d.tsmetadata to type and lower those JS implementations as native Perry code.This blocks native use of packages like
@openai/codex-sdk, which publishes:TypeScript consumers retain API types from
dist/index.d.ts, but Perry native codegen sees the executable entry asdist/index.jsand routes it into the JS-runtime gate instead of a declaration-guided native package compile.Context
The architecture Perry likely needs is a declaration-guided npm package compiler path:
.js) and type sidecar (.d.ts/exports.types/types).perry.compilePackages+perry.allow.compilePackagestrust boundary.For
@openai/codex-sdk, this would let Perry compile the SDK wrapper natively instead of requiring a Node worker or runtime JS fallback. The SDK's core surface is small (Codex,Thread,startThread,resumeThread,run,runStreamed) and mostly wrapscodex exec --experimental-json, so it is a good test case for this architecture.Verification
Temp project:
mkdir /tmp/perry-codex-sdk-smoke cd /tmp/perry-codex-sdk-smoke npm init -y npm install --save-exact @perryts/perry@0.5.1025 @openai/codex-sdk@0.135.0 typescript@6.0.3With
src/main.tsdirectly importing the SDK:Native compile fails at the package JS boundary:
Observed:
Trying the runtime-JS path also fails with the published package on macOS arm64:
Observed:
A workaround was verified: compile a native Perry launcher that uses Perry's native
child_process.spawnSyncto run a tiny Node worker, and let that worker import@openai/codex-sdk. That proves the SDK API and protocol are usable, but it is not native Perry integration.Useful open-source references
.d.tspackage sidecar architecture directly.