feat(ts): native TypeScript server — parity with the Rust/C# server#60
Merged
Conversation
…consuming @smooai/smooth-operator-core
Adds typescript/server/ (@smooai/smooth-operator-server): a WebSocket service
that speaks the smooth-operator wire protocol and runs the published
@smooai/smooth-operator-core engine in-process per turn. The TS sibling of
rust/smooth-operator-server and dotnet/server; the published client in
typescript/ is untouched.
Ported file-by-file from the C# server, verified against the Rust reference:
- protocol.ts ← ProtocolEvents.cs / protocol.rs (byte-for-byte shapes,
incl. the triple-nested eventual_response.data.data)
- sessionStore.ts ← SessionStore.cs (in-memory sessions + message logs)
- auth.ts ← Auth.cs + Rust LocalTokenVerifier (none/trusted/jwt,
fail-closed)
- turnRunner.ts ← TurnRunner.cs / run_streaming_turn (SmoothAgent.runStream
→ stream_token + stream_chunk; auto-context citations)
- frameDispatcher.ts ← FrameDispatcher.cs / handle_frame
- server.ts ← SmoothOperatorWebSocketExtensions.cs + Rust server loop +
local.rs: per-connection read loop, single outbound writer,
graceful SIGTERM/SIGINT drain (shared AbortController; turn
awaited inside the frame branch so in-flight turns finish;
detach-after-loop), serveLocal() embeddable entrypoint
- backplane.ts ← Rust backplane attach/detach seam (in-memory stub)
Tests (27, all green): protocol conformance round-tripping the
spec/conformance/fixtures.json golden messages; boot; turn round-trip over a real
WebSocket (tokens, tool chunks, citations, multi-turn history replay); graceful
drain (in-flight turn finishes after cancel, then detach runs); the auth seam.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U7Mn93HpqhSgEmX6tRdPAv
|
brentrager
added a commit
that referenced
this pull request
Jun 24, 2026
… shared parity corpus (#69) The TS/Python/Go servers landed (#59/#60/#61) and all five now run the shared spec/conformance/scenarios corpus (#62-#67) — tested protocol parity. Updates the servers row + tests section from 'in progress' to the real state. Claude-Session: https://claude.ai/code/session_01U7Mn93HpqhSgEmX6tRdPAv Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this builds
A native TypeScript server for the smooth-operator wire protocol — the missing polyglot-server piece (until now only Rust + C# had servers; TS/Py/Go were clients only). New package
typescript/server/(@smooai/smooth-operator-server); the published client intypescript/is untouched.It speaks the same protocol (
spec/) and runs the published@smooai/smooth-operator-coreengine in-process, oneSmoothAgentper turn.Ported file-by-file from the C# server, behavior verified against the Rust reference:
protocol.tsProtocolEvents.csprotocol.rssessionStore.tsSessionStore.csStorageAdaptersession surfaceauth.tsAuth.csLocalTokenVerifierturnRunner.tsTurnRunner.csrun_streaming_turn(runner.rs)frameDispatcher.tsFrameDispatcher.cshandle_frame(handler.rs)server.tsSmoothOperatorWebSocketExtensions.csserver.rsloop +local.rsbackplane.tsattach/detachseamDone
ws): per-connection read loop + a single outbound writer (one socket = one writer;ws.sendnever concurrent). A level-triggered signal makes the writer/reader lost-wakeup-safe.create_conversation_session→ SessionStore,send_message(with requestId) → TurnRunner,ping→ pong. Unknown/invalid frames error without dropping the connection.SmoothAgent.runStream, mapsStreamEvents (text→stream_token,tool_call/tool_result→stream_chunkwith theisErrorconvention) onto protocol events, and returns the final reply + auto-context citations.none(default) /trusted(base64url JSON) /jwt(HS256). Fail-closed: anything missing/malformed/expired → anonymous.AbortControlleron server state (single source, default uncancelled); each connection's read loop races "cancel fired" vs "next inbound frame" with the turn dispatch awaited inside the frame branch so an in-flight turn finishes (prefer cancel on ties); detach-after-loop always runs the backplane deregister.serveLocal()embeddable entrypoint + amain.tsbinary (in-memory local flavor;SMOOAI_GATEWAY_URL/SMOOAI_GATEWAY_KEYenable live turns, keyless errors cleanly — mirrors the Rust path).Stubbed / follow-on
AccessKnowledge.forAccess) — seam present; the MVP provider is unscoped, a group-filtered view drops in.attach/detachstub; the seam is wired.SessionStoreinterface.Tests — 27, all green
spec/conformance/fixtures.jsongolden messages (create/response, send, stream_chunk, eventual_response with + without citations) through the protocol builders; matches the contract every server speaks.serveLocal()starts on an ephemeral port + accepts a connection; unknown-action and invalid-JSON error without dropping the socket.stream_token(s)→eventual_response; tool-call + tool-result chunks; citations from scoped knowledge (url present/omitted); multi-turn history replay; unknown-session error. (MirrorsWebSocketProtocolIntegrationTests.cs.)Workspace-wide
pnpm -r typecheckandpnpm -r testare green (the published client's 26 tests still pass). The package isprivate(not published); version pinned to the lockstep1.2.0.🤖 Generated with Claude Code