OpenHands · TypeScript · transpile maintenance
Keeping two transpiles alive
The SDK and agent-server are not one-time ports. They are a continuing relationship with the Python
OpenHands/software-agent-sdk: one pinned upstream commit, two TypeScript targets, and a
repeatable way to discover, classify, port, and prove every bounded change.
The governing rule: hand-write policy, generate discovery, execute evidence, and freeze update history.
1 · The three rings
SDK transpile
enyst/openhands-agent covers the upstream SDK, tools, and workspace packages. Observable Python behavior is the default contract; named deviations are exceptional.
Agent-server transpile
packages/openhands-agent-server preserves the REST/WebSocket boundary. Additive behavior requires an explicit EXT-SERVER-* policy.
Coordinator and bridges
SmolPaws owns durable intake, lane ordering, claims, retries, delivery ambiguity, and channel behavior. This layer borrows useful ideas from Automation but is not a transpile.
2 · One pin, bounded intervals
A machine-readable manifest in the SDK package names the exact upstream repository, full commit SHA, source/test/example scopes, and policy hints. The server consumes the vendored copy and verifies its generated Python oracles against the same SHA.
Work is never “sync to HEAD”. A candidate may be discovered from current upstream, but the review unit
is immutable: OLD_PIN..NEW_PIN. The pin moves only when every relevant change has a disposition
and its required evidence is green.
3 · The update conveyor
PORT, NO_TARGET_CHANGE, DEVIATION, EXCLUDED, or DEFERRED.4 · Why the dispositions differ
| Disposition | Meaning | Maintenance effect |
|---|---|---|
PORT | Target behavior or tests must change. | Tests first, then implementation. |
NO_TARGET_CHANGE | The change was reviewed and needs no TypeScript edit. | A concrete reason is required. |
DEVIATION | The area remains relevant, but target policy intentionally differs. | Upstream changes still require review against the alternative behavior. |
EXCLUDED | The upstream subsystem is outside declared scope. | Changes wholly inside it create no port work unless scope changes. |
DEFERRED | The change is in scope but intentionally postponed. | Tracking, compatibility consequence, and revisit trigger are mandatory. |
5 · Generated oracles
A green target test suite proves implemented behavior, but not that every upstream change was noticed. The maintenance system therefore combines completeness checks with behavioral evidence.
- Drift inventory: deterministic git facts for one bounded interval.
- Python OpenAPI operation oracle: paths, methods, parameters, media types, and status codes generated from the exact pin.
- Semantic OpenAPI schema oracle: dereferenced request and response schemas with presentation-only prose removed.
- SDK wire cases: the same language-neutral fixtures serialized by pinned Python and TypeScript.
- Runtime scenarios: deterministic server and cross-repository behavior, added incrementally where OpenAPI cannot prove semantics.
Live LLM calls remain separate. They prove that a provider currently accepts the request, not that TypeScript matches Python.
6 · Weekly rhythm
The SDK fork owns one scheduled watcher. It publishes a generated summary and artifacts for the drift between the canonical pin and the exact observed upstream commit. The watcher is an alarm panel, not a backlog factory: semantic issues are created only after a bounded interval is selected and reviewed.
7 · Documentation precedence
Code and tests describe current factual behavior. Transpilation contracts describe intended policy. Architecture pages explain the current design. Release notes and historical migration studies preserve their moment in time. A conflict between code and contract is investigated; it is not automatically resolved by rewriting whichever side is less convenient.