Skip to content

feat: typed eval output + assembly-reload/cancel handling#2

Merged
glockyco merged 2 commits into
mainfrom
feat/eval-ax-improvements
Jun 4, 2026
Merged

feat: typed eval output + assembly-reload/cancel handling#2
glockyco merged 2 commits into
mainfrom
feat/eval-ax-improvements

Conversation

@glockyco

@glockyco glockyco commented Jun 4, 2026

Copy link
Copy Markdown
Owner

Two SDK/protocol improvements, each with its own changeset.

Native typed eval/subscription output (protocol + sdk, major)

Eval and subscription results previously emitted value as a JSON-encoded
string, forcing every consumer to parse the payload a second time (confirmed
on the live wire: 1+1 returned "2", productName returned
"\"Ardenfall Demo 2025\""). Results now carry:

  • value as native JSON,
  • valueType with the .NET type name,
  • a truncated / truncatedBytes pair that signals when a result exceeds
    maxResultLength (in which case value is null rather than partial,
    invalid JSON).

Session.eval<T>() / Session.watch<T>() return the typed value directly.
Breaking for anyone who double-parsed value, hence the major bump. Wired
through JsonResultSerializer.ToWireValue, ReplEngine,
SubscriptionManager, protocol records/schemas, the SDK, and FakeRuntime.

Assembly-reload + cancellation (sdk + testing, minor)

  • Session.onAssemblyReload surfaces hot-reload pushes that were previously
    dropped and invalidates the cached command catalog/descriptors so stale
    schemas are never reused.
  • Session.cancel(targetId) cancels an active eval or subscription.
  • watch() auto-cancels its server subscription when the iterator stops
    before final.
  • Server-side subscription cancel handled in ReplEngine Tick.
  • FakeRuntime gains matching helpers (onAssemblyReload/emitAssemblyReload,
    cancel/cancelled).

Optional transport methods only — non-breaking for the transport contract.

Release

After merge, the changesets bump @hotrepl/protocol and @hotrepl/sdk to
4.0.0 (@hotrepl/cli/@hotrepl/mcp get dependency-range patch bumps). The
changesets Release workflow opens the Version PR; merging it publishes via
npm OIDC trusted publishing.

glockyco added 2 commits June 4, 2026 20:48
Eval and subscription results serialized the value to JSON and then sent it as a
JSON-encoded string, so every consumer had to parse it a second time and the
SDK's typed eval<T>/watch<T> actually returned a string rather than T. Emit the
value as native JSON instead, carry the .NET type name in valueType, and signal
oversized results with truncated/truncatedBytes (value null) rather than partial,
invalid JSON.

The SDK now returns the typed value directly and exposes the truncation fields,
and the fake runtime mirrors the truncation contract so tests exercise it.

BREAKING CHANGE: eval_result/subscribe_result value is native JSON instead of a
JSON-encoded string; consumers that double-parsed value must stop.
The SDK silently dropped assembly_reload pushes and never sent the cancel frame,
so hot reloads left stale command schemas cached and there was no way to stop an
eval or an unwanted subscription. Surface reloads via Session.onAssemblyReload
(invalidating the cached catalog and descriptors), add Session.cancel(targetId),
and have watch() cancel its server subscription automatically when the iterator
stops before final.

Wire the server side so a cancel targeting a subscription id actually removes the
subscription during the tick, not just queued/running evals. FakeRuntime gains
matching helpers so the behavior is covered by tests.
@glockyco glockyco force-pushed the feat/eval-ax-improvements branch from a61e192 to c498604 Compare June 4, 2026 18:49
@glockyco glockyco merged commit 74d2b68 into main Jun 4, 2026
5 checks passed
@glockyco glockyco deleted the feat/eval-ax-improvements branch June 4, 2026 19:15
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