这个包是什么What this package ispi-server 是远程 pi 会话的服务端一端:它接受任何 ServerListener 交来的字节连接,完成握手,核对每个请求的路由,再把调用原样交给应用——服务器级调用交给 serverServices,Session 调用交给应用打开的 RoutedSessionHandle 为这次附着发的租约。它不解析服务契约、不保存 Session;它负责的是路由、附着的生命周期、取消、订阅更新的顺序,以及关闭时的清理。pi-server is the server end of remote pi sessions: it accepts byte connections from any ServerListener, completes the handshake, checks every request's route and hands the call to the application unchanged; server-wide calls go to serverServices, Session calls to the lease that the app's RoutedSessionHandle issued for this attachment. It parses no service contract and stores no Session; it owns routing, the attachment lifecycle, cancellation, the order of subscription updates, and cleanup on shutdown.
1,958 行 TypeScript,三个导入路径:根入口 "."、Unix socket 传输 "./unix" 和测试工具 "./testing"。依赖 chord 与 pi-protocol;用到 node:crypto(attachmentId)。唯一的使用者是 coding-agent 的 experimental/ 服务器:每个 Session 跑在自己的 worker 进程里。1,958 lines of TypeScript, three import paths: the root ".", the Unix-socket transport "./unix" and the testing kit "./testing". Depends on chord and pi-protocol; uses node:crypto (attachment ids). Its only user is coding-agent's experimental/ server, where every Session runs in its own worker process.
Server、SessionRouter 与可替换的监听器Server, SessionRouter and pluggable listeners#
一句话结论TakeawayServer(server.ts)管连接、握手和请求分派;内部的 SessionRouter(session-router.ts)管托管的 Session、每个连接的附着和释放;ServerListener 只负责把已建立的字节连接交给 server.accept()。根入口用 export * 公开 errors、listener、server、types 四个模块;SessionRouter 与 ByteConnection 不公开。Server (server.ts) owns connections, the handshake and request dispatch; the internal SessionRouter (session-router.ts) owns hosted Sessions, each connection's attachment and its release; a ServerListener only hands established byte connections to server.accept(). The root uses export * to publish four modules: errors, listener, server and types; SessionRouter and ByteConnection stay private.
要点Key points
- 监听器负责传输层的认证;实验性的 Unix 监听器不做认证,只依靠文件权限。Listeners own transport-level authentication; the experimental Unix listener does none and relies on file permissions.
- coding-agent 的 radius-relay.ts 只用到
Pick<Server, "accept">:中继来的连接与本地 socket 进入同一个 Server。coding-agent's radius-relay.ts only needsPick<Server, "accept">: relayed connections enter the same Server as local sockets. Server.closed在关闭后 resolve,监听器或 Session 清理失败时 reject。Server.closedresolves after shutdown and rejects when listener or Session cleanup fails.
工作原理How it works
const server = new Server(host, { listeners, serverId }),然后await server.start()。const server = new Server(host, { listeners, serverId }), thenawait server.start().- 本机:
createUnixServer(host, { serverId, path: getUnixSocketPath(serverId, dir) })。Locally:createUnixServer(host, { serverId, path: getUnixSocketPath(serverId, dir) }). onConnectionCountChanged(count)观察连接数,onError(error)收集诊断。Observe connections withonConnectionCountChanged(count), collect diagnostics withonError(error).
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/server/src/index.tsL3 | export * | 根入口the root entry |
| packages/server/src/server.tsL46 | Server | 连接与分派connections and dispatch |
| packages/server/src/session-router.tsL34 | SessionRouter | Session 与附着Sessions and attachments |
| packages/server/src/listener.tsL4 | ServerListener | 监听器契约the listener contract |
| packages/server/src/transports/unix/preset.tsL7 | createUnixServer() | Unix 预设the Unix preset |
公共 APIPublic API#
一句话结论Takeaway3 个导入路径。根入口 index.ts 用 export * 公开 4 个模块里的 8 个值和 10 个类型:Server、六个错误类、INTERNAL_SERVER_ERROR_MESSAGE,其余是宿主与监听器的契约;SessionRouter 和 ByteConnection 不公开。Unix 传输在 ./unix,测试工具在 ./testing。3 import paths. The root index.ts uses export * to publish 8 values and 10 types from 4 modules: Server, six error classes and INTERNAL_SERVER_ERROR_MESSAGE, the rest host and listener contracts; SessionRouter and ByteConnection stay private. The Unix transport lives in ./unix, the testing kit in ./testing.
| 导入路径Import path | 目标Target | 说明Notes |
|---|---|---|
@earendil-works/pi-server | ./dist/index.js | Server、ServerHost 契约、监听器契约与错误类Server, the ServerHost contract, the listener contract and error classes |
@earendil-works/pi-server/testing | ./dist/testing/index.js | 测试服务器、内存宿主与帧级协议客户端a test server, an in-memory host and a frame-level protocol client |
@earendil-works/pi-server/unix | ./dist/transports/unix/index.js | Node 专用:Unix socket 监听器与预设Node only: the Unix-socket listener and preset |
常用导出Key exports
| 模块Module | 常用导出Key exports | 用途Use |
|---|---|---|
| packages/server/src/server.ts | Server | 连接、握手与请求分派connections, handshake and dispatch |
| packages/server/src/types.ts | ServerHost SessionMetadata | 应用要实现的宿主the host an app implements |
| packages/server/src/types.ts | RoutedSessionHandle RoutedSessionAttachment | Session 句柄与附着租约Session handle and attachment lease |
| packages/server/src/types.ts | RoutedServerServiceHost RoutedServerPresentation | 服务器级服务与附着能力server-wide services and attach capabilities |
| packages/server/src/listener.ts | ServerListener | 接入传输plug in a transport |
| packages/server/src/errors.ts | ServerError SessionNotFoundError SessionAmbiguousError | 可越过边界的错误boundary-safe errors |
子路径 ./unixSubpath ./unix
| 模块Module | 常用导出Key exports | 用途Use |
|---|---|---|
| packages/server/src/transports/unix/preset.ts | createUnixServer | Server + 一个 Unix 监听器Server + one Unix listener |
| packages/server/src/transports/unix/listener.ts | createUnixListener | 单独的 Unix 监听器a Unix listener on its own |
| packages/server/src/transports/unix/address.ts | getUnixSocketPath | <dir>/<serverId>.sock<dir>/<serverId>.sock |
| packages/server/src/transports/unix/types.ts | UnixListenerOptions UnixServerOptions | 选项options |
子路径 ./testingSubpath ./testing
| 模块Module | 常用导出Key exports | 用途Use |
|---|---|---|
| packages/server/src/testing/server.ts | createTestServer | 未启动的测试服务器an unstarted test server |
| packages/server/src/testing/host.ts | TestServerHost TestHarness createTestServerServices Deferred | 内存宿主与时序控制in-memory host and timing control |
| packages/server/src/testing/client.ts | ProtocolTestClient connectUnixTestClient | 帧级协议客户端frame-level protocol client |
根入口的全部导出(按声明所在模块,逐行链接)Every root export, by declaring module (line-linked)
由构建脚本展开 index.ts 的 export * 与 export { … } from 并扫描声明生成;每个符号链接到 v1.1.0 中的定义行。Generated at build time by expanding the export * and export { … } from statements in index.ts and scanning the declarations; each symbol links to its definition at v1.1.0.
ServerHost:应用提供的能力ServerHost: capabilities the app provides#
一句话结论Takeaway应用只实现三样东西:serverServices(握手时为每个连接建一个服务器级端点)、resolveSession(id)(把 id 解析成元数据,或抛出有界的路由错误)和 openSession(metadata)(返回一个 RoutedSessionHandle)。句柄的 attachClient() 为每次附着发一个租约,租约的 invokeService() 接收不透明的服务调用。The app implements just three things: serverServices (one server-wide endpoint per connection, built at the handshake), resolveSession(id) (resolve an id to metadata, or throw a bounded routing error) and openSession(metadata) (return a RoutedSessionHandle). The handle's attachClient() issues one lease per attachment, and the lease's invokeService() takes opaque service calls.
要点Key points
- 服务器级端点拿到一个
RoutedServerPresentation:attachSession、detachSession、prepareSessionRemoval——应用的管理服务就是用它们 attach 的。The server-wide endpoint receives aRoutedServerPresentation:attachSession,detachSession,prepareSessionRemoval; the app's management service attaches through these. terminated是可选的 Promise:意外退出时以错误 resolve,Server 随即让该 Session 的附着全部失效。terminatedis an optional promise: it resolves with an error on unexpected exit, and the Server then invalidates every attachment to that Session.SessionMetadata只要求id;应用可以扩展它(coding-agent 带上了path)。SessionMetadataonly requires anid; apps may extend it (coding-agent adds apath).
工作原理How it works
const host: ServerHost<StoredSession> = { serverServices, resolveSession, openSession }。const host: ServerHost<StoredSession> = { serverServices, resolveSession, openSession }.- 找不到时
throw new SessionNotFoundError(Unknown session: ${id})。When missing,throw new SessionNotFoundError(Unknown session: ${id}). invokeService(call, publish, ctx):订阅的更新经publish(subscriptionId, update)回到 Server。invokeService(call, publish, ctx): subscription updates return throughpublish(subscriptionId, update).
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/server/src/types.tsL63 | ServerHost | 应用能力app capabilities |
| packages/server/src/types.tsL55 | RoutedSessionHandle | 每个 Sessionper Session |
| packages/server/src/types.tsL22 | RoutedSessionAttachment | 每次附着的租约per-attachment lease |
| packages/server/src/types.tsL33 | RoutedServerPresentation | 交给应用的附着能力attach capabilities for the app |
| packages/coding-agent/src/experimental/session-worker-manager.tsL194 | #routedHandle() | coding-agent:worker 句柄coding-agent: the worker handle |
连接的五个阶段Five connection stages#
一句话结论Takeaway每条连接经历 awaitingHello → handshaking → ready → closing → closed。第一条消息必须是 hello,而且整个握手要在 5 s 内完成;finishHandshake() 检查版本、为连接建服务器级端点、发回 hello { version, serverId },然后才进入 ready。协议错误走 failProtocol():把 hello_error 作为最后一帧发出,再关闭。Every connection goes awaitingHello → handshaking → ready → closing → closed. The first message must be hello and the whole handshake must finish within 5 s; finishHandshake() checks the version, builds the connection's server-wide endpoint and sends back hello { version, serverId } before entering ready. Protocol errors go through failProtocol(): hello_error is sent as the final frame, then the connection closes.
要点Key points
- 握手期间到达的请求挂在
state.handshake之后,ready 时才处理,不会丢。Requests that arrive during the handshake wait onstate.handshakeand run once ready; none are lost. disconnect()只执行一次:abort 所有进行中的请求、清空订阅编码器,并行释放 Session 附着与服务器级端点。disconnect()runs once: it aborts every active request, clears subscription encoders, and releases the Session attachment and server-wide endpoint in parallel.- 关闭中的 Server 对新连接直接 close,不建任何状态。A closing Server closes new connections at once without creating any state.
工作原理How it works
handshakeTimeoutMs与maxFrameLength都是 1 … 上限之间的整数,构造时检查。handshakeTimeoutMsandmaxFrameLengthare integers within bounds, checked by the constructor.await server.close():先关监听器,再关连接,最后关所有托管的 Session。await server.close(): listeners first, then connections, then every hosted Session.- 自定义监听器:
start(accept)里对每个连接调用accept(connection),把返回的 handler 接到传输事件上。A custom listener: instart(accept), callaccept(connection)per connection and wire the returned handler to transport events.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/server/src/server.tsL136 | accept() | 新连接与握手定时器new connection, handshake timer |
| packages/server/src/server.tsL223 | dispatchMessage() | 按阶段分派dispatch by stage |
| packages/server/src/server.tsL262 | finishHandshake() | 完成握手finish the handshake |
| packages/server/src/server.tsL474 | failProtocol() | hello_error 作最后一帧hello_error as final frame |
| packages/server/src/server.tsL417 | disconnect() | 断开清理disconnect cleanup |
| packages/server/src/connection.tsL21 | ConnectionStage | 五个阶段five stages |
一个请求的处理Handling one request#
一句话结论TakeawayhandleRequest() 先拒绝重复的请求 id 和不合法的调用,再登记一个 AbortController;然后核对 serverId,按 target 是否带 sessionId 路由到 SessionRouter 或服务器级端点。订阅必须返回快照:Server 为它装上 ServiceStateEncoder,先发回应,再冲刷期间排队的更新。handleRequest() first rejects duplicate request ids and invalid calls, then registers an AbortController; it checks the serverId and routes to the SessionRouter or the server-wide endpoint depending on whether the target has a sessionId. A subscription must return a snapshot: the Server installs a ServiceStateEncoder for it, sends the response first, then flushes the updates queued meanwhile.
要点Key points
- 错误回应用
toProtocolError()映射:ServerError/RemoteServiceError原样,ProtocolValidationError→invalid_request,其它 →internal_error。Error responses are mapped bytoProtocolError():ServerError/RemoteServiceErroras is,ProtocolValidationError→invalid_request, anything else →internal_error. - 已 abort 的请求一律回应
cancelled;cancel本身从不单独回应。An aborted request always answerscancelled; acancelnever gets its own response. - 回应已发出后才出错(例如冲刷更新时),Server 关闭这条连接:订阅流不能半途断掉。If something fails after the response was sent (flushing updates, say), the Server closes the connection: a stream must not break halfway.
工作原理How it works
- 同一连接上的请求并发处理;需要顺序时由应用在服务里自己排队。Requests on one connection run concurrently; apps that need ordering queue inside their services.
- 在服务里尊重
context的 abort 信号,取消才会尽快生效。Honour thecontextabort signal in services so cancellation takes effect quickly. - 退订成功后编码器被删掉,之后对该订阅的
publish静默丢弃。After a successful unsubscribe the encoder is deleted, and laterpublishcalls for it are silently dropped.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/server/src/server.tsL306 | handleRequest() | 核对、路由、回应check, route, respond |
| packages/server/src/server.tsL298 | handleCancel() | 按 id 与 target 取消cancel by id and target |
| packages/server/src/server.tsL438 | sendServiceUpdate() | 编码更新encode an update |
| packages/server/src/server.tsL512 | toProtocolError() | 错误映射error mapping |
| packages/server/src/server.tsL547 | sameTarget() | target 比较target comparison |
SessionRouter:attach 与准入SessionRouter: attach and admission#
一句话结论Takeawayattach 按连接串行(runForClient):已附着同一 Session 就直接返回;否则 acquire()——已托管、正在打开或新打开(resolveSession + openSession)——释放当前附着、为新附着生成 randomUUID() 并向句柄取租约,最后带外推送 attachment 路由。Session 调用也在同一队列里“准入”:路由必须与本连接的当前附着完全一致。Attach is serialised per connection (runForClient): if already attached to that Session it returns at once; otherwise acquire()s it (hosted, opening, or freshly opened via resolveSession + openSession), releases the current attachment, generates a randomUUID() for the new one, takes a lease from the handle, and finally pushes the attachment route out of band. Session calls are admitted through the same queue: the route must exactly match this connection's current attachment.
要点Key points
- 只有准入排队;调用结果在队列外等待,所以同一 Session 上的调用可以并发。Only admission is queued; results are awaited outside the queue, so calls on one Session run concurrently.
openingSessions让并发的 attach 共享同一次打开;失败时一起失败,之后可以重试。openingSessionslets concurrent attaches share one open; on failure they fail together, and a later retry may succeed.- 打开期间服务器开始关闭:立即
handle.close()并以server_draining拒绝。If the server starts closing during an open,handle.close()runs at once and the attach rejects withserver_draining.
工作原理How it works
- 应用的管理服务调用
presentation.attachSession(sessionId, ctx);结果里不带任何路由 id。The app's management service callspresentation.attachSession(sessionId, ctx); its result carries no route ids. - 一个 Session 可以有多个连接的附着;每个附着各自有租约。One Session may have attachments from several connections, each with its own lease.
- 要彻底删除 Session,先调用
prepareSessionRemoval(sessionId),再删应用自己的元数据。To delete a Session, callprepareSessionRemoval(sessionId)first, then delete the app's own metadata.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/server/src/session-router.tsL146 | runForClient() | 按连接串行per-connection queue |
| packages/server/src/session-router.tsL160 | attachClientNow() | attach 的步骤the attach steps |
| packages/server/src/session-router.tsL262 | acquire() | 共享打开shared opening |
| packages/server/src/session-router.tsL276 | open() | resolve + openresolve + open |
| packages/server/src/session-router.tsL224 | requireAttachment() | 路由核对route check |
附着的结束How attachments end#
一句话结论Takeawaydetach、切换 Session、连接断开、句柄 terminated、prepareSessionRemoval() 和 Server.close() 最终都走 releaseAttachment():同一附着只释放一次,先等已准入的调用结算,再 lease.release(),最后摘掉路由——只有 detach 与失效会推送 attachment: null。删除和关闭服务器还会 handle.close()。Detach, switching Sessions, a dropped connection, a terminated handle, prepareSessionRemoval() and Server.close() all end in releaseAttachment(): each attachment is released once, admitted calls settle first, then lease.release(), then the route is cleared; only detach and invalidation push attachment: null. Removal and shutdown also call handle.close().
要点Key points
- 连接断开只释放附着,Session 仍被托管;什么时候让 worker 退役由应用决定。A dropped connection only releases the attachment; the Session stays hosted, and the app decides when its worker retires.
- 句柄终止后 Session 从
hostedSessions删除;下次 attach 会重新打开它。After a handle terminates, the Session leaveshostedSessions; the next attach reopens it. - 释放失败也一定清掉路由(finally),否则连接会永远占着它。The route is cleared even if release fails (finally); otherwise the connection would hold it forever.
工作原理How it works
- 在租约的
release(ctx)里放掉 Session 级资源;它可能在调用仍在完成时被等待。Free Session-level resources in the lease'srelease(ctx); it may be awaited while calls are still completing. - 用
terminated报告 worker 意外退出,让客户端尽快看到attachment: null。Report unexpected worker exits throughterminatedso clients seeattachment: nullquickly. - 关闭失败时
server.close()与server.closed以 AggregateError 拒绝。On cleanup failureserver.close()andserver.closedreject with an AggregateError.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/server/src/session-router.tsL234 | releaseAttachment() | 唯一的释放路径the one release path |
| packages/server/src/session-router.tsL254 | clearAttachment() | 摘掉路由clear the route |
| packages/server/src/session-router.tsL302 | invalidate() | 句柄终止handle termination |
| packages/server/src/session-router.tsL72 | removeSession() | 删除前释放release before removal |
| packages/server/src/session-router.tsL108 | closeInternal() | 关闭全部close everything |
Unix 监听器The Unix listener#
一句话结论TakeawayUnixListener.start() 建 0700 目录,清理陈旧 socket(还活着就拒绝启动),先在 bind-<sha256 前 8 位> 上监听,记下 socket 的 dev/ino,再用 link() 原子地发布到公共路径、chmod 0600、删掉 bind 路径。关闭时只删除身份仍然匹配的 socket,所以接替它的新服务器不会被误删。UnixListener.start() creates a 0700 directory, cleans up stale sockets (refusing to start if one is alive), listens first on bind-<first 8 hex of sha256>, records the socket's dev/ino, then publishes it atomically to the public path with link(), chmod 0600s it and unlinks the bind path. On close it removes the socket only while its identity still matches, so a server that replaced it is never removed by mistake.
要点Key points
- 活性探测:连得上或 1000 ms 没反应都算“还活着”——宁可启动失败,也不删别人的 socket。Liveness probe: connecting, or no answer within 1000 ms, both count as alive; better to fail start-up than delete another server's socket.
- 删除前总是先改名(stale- / cleanup-)再核对 dev/ino:避免与并发的替换竞争。Removal always renames first (stale- / cleanup-) and then checks dev/ino, to avoid racing a concurrent replacement.
UnixByteConnection把排队字节限制在maxPendingBytes(默认 4 × 帧上限,至少帧上限 + 4),超过就断开慢的对端。UnixByteConnectioncaps queued bytes atmaxPendingBytes(4 × the frame limit by default, at least limit + 4) and drops a slow peer beyond it.
工作原理How it works
getUnixSocketPath(serverId, dir)得到<dir>/<serverId>.sock;README 建议用一个短的私有运行时目录。getUnixSocketPath(serverId, dir)gives<dir>/<serverId>.sock; the README recommends a short private runtime directory.createUnixListener({ path, mode, maxPendingBytes, gracefulCloseTimeoutMs })可以和其它监听器一起交给new Server()。createUnixListener({ path, mode, maxPendingBytes, gracefulCloseTimeoutMs })can go tonew Server()alongside other listeners.- coding-agent:目录默认
~/.pi/server,可用PI_SERVER_DIR覆盖。coding-agent: the directory defaults to~/.pi/server, overridable withPI_SERVER_DIR.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/server/src/transports/unix/listener.tsL47 | start() | 绑定与发布bind and publish |
| packages/server/src/transports/unix/listener.tsL299 | removeStaleSocket() | 陈旧 socketstale sockets |
| packages/server/src/transports/unix/listener.tsL147 | cleanupOwnedSocket() | 按身份清理identity-checked cleanup |
| packages/server/src/transports/unix/listener.tsL191 | UnixByteConnection | 写队列与优雅关闭write queue, graceful close |
| packages/server/src/transports/unix/address.tsL4 | getUnixSocketPath() | 路径约定path convention |
错误码与测试工具Error codes and the testing kit#
一句话结论Takeaway能越过协议边界的错误都是 ServerError:五个子类覆盖 wrong_server、session_not_found、session_ambiguous、session_not_attached 和 server_draining,应用也可以用 Chord 的 RemoteServiceErrorCode。其它异常一律变成 internal_error "Internal server error",细节只交给 onError。./testing 提供测试服务器、内存宿主与帧级协议客户端。Errors that may cross the protocol boundary are ServerErrors: five subclasses cover wrong_server, session_not_found, session_ambiguous, session_not_attached and server_draining, and apps may also use Chord's RemoteServiceErrorCodes. Any other exception becomes internal_error "Internal server error", with details only in onError. ./testing provides a test server, an in-memory host and a frame-level protocol client.
要点Key points
wrong_server在访问任何仓库之前检查:发错服务器的请求不会触发resolveSession。wrong_serveris checked before any repository access: a request for another server never triggersresolveSession.- 只有
ServerError与RemoteServiceError的消息会被转发;其它异常的消息和堆栈不会离开服务器。OnlyServerErrorandRemoteServiceErrormessages are forwarded; other exceptions' messages and stacks never leave the server. - conformance.test.ts 是最大的测试文件:多附着、过期路由、未知 / 有歧义的 Session、Harness 终止与关闭时的清理。conformance.test.ts is the largest test file: multiple attachments, stale routes, unknown / ambiguous Sessions, Harness termination and shutdown cleanup.
工作原理How it works
- 在
resolveSession里throw new SessionNotFoundError()或new SessionAmbiguousError()。InresolveSession,throw new SessionNotFoundError()ornew SessionAmbiguousError(). const { server, host } = createTestServer({ listeners })得到一个未启动的测试服务器。const { server, host } = createTestServer({ listeners })gives an unstarted test server.const c = await connectUnixTestClient(path),用ProtocolTestClient按帧断言。const c = await connectUnixTestClient(path), then assert frame by frame withProtocolTestClient.
关键文件Key files · v1.1.0
| 文件File | 符号Symbol | 作用Role |
|---|---|---|
| packages/server/src/errors.tsL14 | ServerError | 可越界的错误boundary-safe errors |
| packages/server/src/errors.tsL24 | WrongServerError | wrong_serverwrong_server |
| packages/server/src/errors.tsL11 | INTERNAL_SERVER_ERROR_MESSAGE | 内部错误的固定消息the fixed internal message |
| packages/server/src/testing/server.tsL16 | createTestServer() | 测试服务器the test server |
| packages/server/src/testing/client.tsL27 | ProtocolTestClient | 帧级客户端frame-level client |
扩展点Extension points#
ServerHost应用接入点:serverServices、resolveSession、openSession。The app's entry point: serverServices, resolveSession, openSession.RoutedSessionHandle · RoutedSessionAttachment把 Session 放在任何地方:同进程、worker 进程或远端。Host a Session anywhere: in process, in a worker process, or remotely.ServerListener接入新的传输:start(accept) 交出已认证的字节连接。Add a transport: start(accept) hands over authenticated byte connections.ServerError(code, message)给客户端一个可识别的错误码和消息。Give clients a recognisable error code and message../testing用 createTestServer 与 ProtocolTestClient 测试你的宿主或传输。Test your host or transport with createTestServer and ProtocolTestClient.测试Tests#
一句话结论Takeaway六个测试文件:conformance.test.ts(20 个用例)用 ./testing 覆盖 Session 协议——多附着、过期路由、跨服务器请求、未知 / 有歧义的 Session、Harness 终止与关闭时的清理;protocol.test.ts 覆盖握手与分帧(分片、合并、截断);server.test.ts 覆盖选项校验、并发启动、握手超时与关闭失败;unix*.test.ts 与 listener.test.ts 覆盖 socket 绑定、陈旧清理、身份检查,以及排在待发数据之后的最终错误帧。Six test files: conformance.test.ts (20 cases) uses ./testing to cover the Session protocol: multiple attachments, stale routes, cross-server requests, unknown / ambiguous Sessions, Harness termination and shutdown cleanup; protocol.test.ts covers the handshake and framing (fragmented, coalesced, truncated); server.test.ts covers option checks, concurrent start, the handshake timeout and shutdown failures; unix*.test.ts and listener.test.ts cover socket binding, stale cleanup, identity checks, and a final error frame queued behind pending output.
用例数 = 源码中 it( / test( 的出现次数(静态统计,不运行测试)。Cases = occurrences of it( / test( in the source (static count; tests were not run).
交叉链接Cross-links#
线上格式:信封、分帧与 CBORthe wire format: envelopes, framing and CBOR
client已完成Done另一端:握手、请求、订阅与附着the other end: handshake, requests, subscriptions, attachments
chord已完成Done服务控制调用、状态编码器与 RemoteServiceErrorservice-control calls, the state encoder and RemoteServiceError
coding-agent已完成Doneexperimental/ 下的服务器与 Session workerthe server and Session workers under experimental/