Skip to content

fix(node-sdk): protect hand-authored types from napi-rs regen churn#38

Merged
ZhiXiao-Lin merged 1 commit into
mainfrom
fix/sdk-types-stability
May 23, 2026
Merged

fix(node-sdk): protect hand-authored types from napi-rs regen churn#38
ZhiXiao-Lin merged 1 commit into
mainfrom
fix/sdk-types-stability

Conversation

@ZhiXiao-Lin
Copy link
Copy Markdown
Contributor

Stacked on #37#36#35.

The problem

Every `napi build` overwrites `index.d.ts` and silently drops the hand-added types (`ToolErrorKind`, `VerificationStatus`, `VerificationCheck`, `VerificationReport`, `ToolArtifact`). #37 restored them by hand for that PR, but the next person who rebuilds the SDK will hit the same trap.

These types can't just move into Rust source — they describe JSON wire shapes whose field names must stay `snake_case` to match the Rust core's serialization. `napi-derive` would auto-camelCase them and break consumers parsing the JSON.

The fix

Split generated and hand-authored type files:

File Source Touched by `napi build`
`generated.d.ts` napi-rs ✅ (overwritten each build)
`extra-types.d.ts` hand-authored
`index.d.ts` hand-authored aggregator

`index.d.ts` is now ~13 lines:

```ts
export * from './generated'
export * from './extra-types'
```

`package.json` updates:

  • `build` / `build:debug` scripts point napi at `generated.d.ts`.
  • `files[]` ships all three .d.ts files.
  • `types` still points at `index.d.ts` so consumer imports are unchanged.
  • New `test:types` script runs `tsc --noEmit` against `test-types.ts` to fail if the aggregator ever stops resolving a type from either side.

Test plan

  • `npm run build:debug` writes `generated.d.ts` and leaves `index.d.ts` untouched.
  • `npm test` passes (runtime smoke unchanged).
  • `npm run test:types` passes — confirms `Session`, `Agent`, `AgentEvent`, `ToolResult` resolve from `generated.d.ts` AND `ToolErrorKind`, `VerificationStatus`, `VerificationCheck`, `VerificationReport`, `ToolArtifact` resolve from `extra-types.d.ts` — all via the package entry.
  • Exhaustive switch on the `ToolErrorKind` discriminated union compiles, guarding against missing variants on regen.

A pre-existing typing gap around `McpServerConfig` shows up under strict tsc; the test uses `--skipLibCheck` to avoid coupling this PR to that fix.

@ZhiXiao-Lin ZhiXiao-Lin changed the base branch from feat/subagent-node-sdk to main May 23, 2026 15:53
@ZhiXiao-Lin ZhiXiao-Lin force-pushed the fix/sdk-types-stability branch from 4bdefc8 to 49a9ef8 Compare May 23, 2026 16:01
Before this commit, every `napi build` overwrote `index.d.ts` and
silently dropped the hand-added types (`ToolErrorKind`,
`VerificationStatus`, `VerificationCheck`, `VerificationReport`,
`ToolArtifact`). These types aren't generatable from Rust — they
describe JSON wire shapes whose field names must stay snake_case to
match the core's serialization, which napi-derive would auto-camelCase.

Reshape the SDK so generated and hand-authored types live in separate
files:

- napi build now writes to `generated.d.ts` (was `index.d.ts`).
- `extra-types.d.ts` holds the hand-authored types.
- `index.d.ts` becomes a small hand-authored aggregator that re-exports
  both. It is never touched by the build.
- `package.json` `files[]` ships all three .d.ts files; `types` field
  still points at `index.d.ts` so consumers' imports are unchanged.

Adds `test-types.ts` + `npm run test:types` as a tsc-based smoke check
that fails if the aggregator ever drops a type from either file.
@ZhiXiao-Lin ZhiXiao-Lin force-pushed the fix/sdk-types-stability branch from 49a9ef8 to af103c7 Compare May 23, 2026 16:09
@ZhiXiao-Lin ZhiXiao-Lin merged commit 50185f9 into main May 23, 2026
1 check passed
@ZhiXiao-Lin ZhiXiao-Lin deleted the fix/sdk-types-stability branch May 23, 2026 16:10
@ZhiXiao-Lin ZhiXiao-Lin mentioned this pull request May 23, 2026
8 tasks
ZhiXiao-Lin pushed a commit that referenced this pull request May 23, 2026
Bumps Rust core, Node SDK, and Python SDK to 3.2.0 and documents the
subagent task tracker work that landed across #35#41 + #38.

Changes
- Bump all five version files (core/sdk Cargo.toml, sdk/node/package.json,
  sdk/python/pyproject.toml) plus Node lockfiles and Cargo.lock.
- Mark SubagentStatus #[non_exhaustive] so future variants are non-
  breaking. The Cancelled variant added in this release still counts as
  a breaking change for exhaustive matchers — flagged in the CHANGELOG.
- Add a [3.2.0] section to CHANGELOG.md covering: the tracker query
  API, SubagentProgress emission, the Cancelled status and
  cancel_subagent_task entry point, Node + Python SDK exposure of all
  of the above, the regen-stable Node .d.ts split, and the
  TaskExecutor / register_task_with_mcp signature additions.
- Extend README with a "What's new in 3.2" block and a Delegation
  table that lays out the observe + cancel API across Rust, Node, and
  Python.

Preflight done locally
- cargo fmt --all --check
- cargo test -p a3s-code-core --lib  (1661 passed)
- cargo test -p a3s-code-core --tests (all green)
- scripts/check_release_versions.sh  (consistent at 3.2.0)
- (cd sdk/node && npm run build:debug && npm test && npm run test:types)

Not run here: release.sh / git tag. This commit is for review only;
tagging + publishing happens after the PR lands.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants