Skip to content

fix(agent): make the models-barrel import in turn-context type-only - #111

Open
w0nche0l wants to merge 1 commit into
mainfrom
dennisjeong/dev-823-drop-models-barrel-from-turn-context
Open

fix(agent): make the models-barrel import in turn-context type-only#111
w0nche0l wants to merge 1 commit into
mainfrom
dennisjeong/dev-823-drop-models-barrel-from-turn-context

Conversation

@w0nche0l

Copy link
Copy Markdown
Contributor

Summary

  • turn-context.ts runtime-imported the entire @openrouter/sdk/models namespace to read a single value: EasyInputMessageRoleUser.User, i.e. the string 'user'. Because turn-context sits on the static import path of @openrouter/agent/tool (tool → agent-tool → conversation-state → turn-context, new in 0.9.0), every consumer that statically imports the tool subpath now evaluates the Speakeasy models barrel — hundreds of modules of top-level Zod schema construction — at module load.
  • On Cloudflare Workers this added ~200ms of startup CPU per worker and pushed OpenRouter's large workers past the 1s script-validation ceiling (error 10021), forcing openrouter-web#33740 to revert the 0.9.0 adoption. Independent measurement: evaluating the three hot subpaths in a bare V8 isolate went from 0.007ms (0.7.2) to ~233ms (0.9.0), and back to ~8ms with this import removed. openrouter-web is re-landing 0.9.0 with this same fix as a bun patch in openrouter-web#33860 until it ships here.
  • Fix: make the import type-only (erased at compile time) and inline the 'user' literal — behavior identical, still typechecked against models.EasyInputMessage.

Regression guard

New unit test tests/unit/startup-import-closure.test.ts walks the static runtime import graph of the startup-hot subpaths (/tool, /tool-types, /stop-conditions) from source and fails if any of them reaches @openrouter/sdk at runtime. Type-only imports and dynamic import() are exempt by construction. Verified the test fails when the import is made runtime again.

Test plan

  • pnpm test — 97 files, 1156 tests, no type errors, coverage thresholds met
  • pnpm typecheck, pnpm lint, pnpm build green
  • Negative test: reverting the import to runtime makes the new guard fail with the full offending chain

Made with Cursor

The runtime namespace import of '@openrouter/sdk/models' existed only to
read EasyInputMessageRoleUser.User (the string 'user'), but it put the
entire Speakeasy models barrel — hundreds of modules of top-level Zod
schema construction — on the static import path of '@openrouter/agent/tool'
(tool -> agent-tool -> conversation-state -> turn-context). Consumers that
bundle the tool subpath into Cloudflare Workers paid ~200ms of startup CPU
per worker, which pushed large workers past the 1s script-validation
ceiling (error 10021) and forced OpenRouterTeam/openrouter-web#33740 to
revert the 0.9.0 adoption.

Make the import type-only, inline the role literal (behavior identical,
still typechecked against models.EasyInputMessage), and add a unit test
that walks the static runtime import graph of the hot subpaths (/tool,
/tool-types, /stop-conditions) and fails if any of them reaches
'@openrouter/sdk' at runtime again.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant