Skip to content

Release history

s2-streamstore/s2-sdk-typescript releases

Official MCP server for the S2.dev serverless stream platform.

All releases

27 shown

@s2-dev/[email protected] Breaking risk
Breaking changes
  • CreateBasinInput.scope replaced by location
  • EnsureBasinInput.scope replaced by location
  • BasinInfo.scope replaced by location
Notable features
  • Adds `location` related RPCs
Full changelog

Minor Changes

  • 5c0ed79: - refactor!: BasinScope now Location, and is free string instead of enum

    • feat: adds location related RPCs

    Breaking changes:

    • CreateBasinInput.scope replaced by location
    • EnsureBasinInput.scope replaced by location
    • BasinInfo.scope replaced by location
    • root export BasinScope removed and replaced by LocationName
    • generated API.BasinScope no longer exists because the spec no longer has it
@s2-dev/[email protected] New feature
Notable features
  • Adds `@s2-dev/resumable-stream/tanstack-ai` with `createResumableChat` for TanStack `StreamChunk` streams
  • Adds `@s2-dev/resumable-stream/tanstack-ai/client` exposing `createS2Connection` for `useChat`
  • Session mode stores TanStack stream chunks in S2, claims new turns from the tail, creates replay‑only in‑memory snapshots on first load, supports cursor resume, and provides opt‑in local generation stop via `enableStop`, `stopSession`, and `stopUrl`
Full changelog

Minor Changes

  • 27806e1: Add TanStack AI helpers for S2-backed session replay:

    • @s2-dev/resumable-stream/tanstack-ai exposes createResumableChat for TanStack StreamChunk streams.
    • @s2-dev/resumable-stream/tanstack-ai/client exposes createS2Connection for useChat.
    • Session mode stores TanStack stream chunks in S2, claims new turns from the stream tail, creates replay-only in-memory snapshots on first load, supports cursor resume, and provides opt-in local generation stop via enableStop, stopSession, and stopUrl.
@s2-dev/[email protected] New feature
Notable features
  • Per‑stream encryption via `EncryptionKey`, `EncryptionAlgorithm`, and `EncryptionKeyInput` with basin-level `streamCipher` configuration
Full changelog

Minor Changes

  • cdc822c: - Add stream encryption support to @s2-dev/streamstore, including
    EncryptionKey, EncryptionAlgorithm, and EncryptionKeyInput,
    per-stream encryption keys via basin.stream({ encryptionKey }) and
    • stream.withEncryptionKey(), and basin-level streamCipher
      configuration.

Patch Changes

  • e17c444: Treat truncated fetch SSE reads as retryable errors instead of silently ending the read session.
@s2-dev/[email protected] Breaking risk
Breaking changes
  • makeResumable returns UIMessageChunk stream as SSE directly instead of JSON object
  • replay no longer accepts fromSeqNum argument
  • createS2Transport and S2TransportConfig removed; use DefaultChatTransport from ai package
Full changelog

Major Changes

  • 7ea2cea: - makeResumable now returns the UIMessageChunk stream as SSE directly in the response body (previously returned JSON { stream, fromSeqNum }). The source is teed: one branch streams to the client, the other persists to S2.

    • replay no longer accepts a fromSeqNum argument.
    • createS2Transport and S2TransportConfig are removed. Use new DefaultChatTransport({ api }) from ai; the default reconnect URL (${api}/${chatId}/stream) matches chat.replay(...). Customize via prepareReconnectToStreamRequest if needed.
    • Error chunks no longer forward upstream error messages by default (previously leaked err.message directly). A new ResumableChatConfig.onError?: (error: unknown) => string lets callers opt into sanitized forwarding. Default emits the generic "An error occurred.".
    • Shared-mode streams now use a sliding liveness lease: if an active generation hasn't written any record (fence, data, or trim) for leaseDurationMs (default 5 seconds), a new claim takes it over. Long-running generations that keep streaming are unaffected. The lease slides forward with every record, so leaseDurationMs is the maximum tolerated pause within a generation, not total generation duration. Previously, an abandoned non-terminal fence locked the stream forever.
    • Environment variable S2_LINGER_DURATION renamed to S2_LINGER_DURATION_MS. Default dropped from 5000ms to 500ms on the generic createResumableStreamContext path. The AI SDK path already defaults to 50ms.
    • Single-use streams now write a trim after the terminal fence at end-of-generation. Combined with delete-on-empty on the basin/stream config, completed single-use streams self-GC rather than piling up under the retention policy. Without delete-on-empty, the stream is still emptied by the trim and will expire under the retention policy as before.
    • Single-use opening fences are appended with matchSeqNum: 0, so a re-claim of the same stream name rejects with 409 even after the trim has propagated. The stream's tail seqnum stays above 0 until s2 GCs the stream entirely, which blocks accidental re-use of the same name.
    • Peer range for ai raised from >=4.0.0 to >=5.0.0.

    Migration:

    // before
    const transport = createS2Transport({
      api: "/api/chat",
      reconnectApi: "/api/chat/stream",
    });
    
    // after
    import { DefaultChatTransport } from "ai";
    const transport = new DefaultChatTransport({ api: "/api/chat" });
    

    The server-side chat.makeResumable(...) and chat.replay(...) call sites are unchanged (both still return a Response), but the GET reconnect route should be moved to /api/chat/[id]/stream to match DefaultChatTransport's default shape.

@s2-dev/[email protected] Bug fix

Minor fixes and improvements.

Full changelog

Patch Changes

  • 2d9d79c: misc bugfixes:
    • Enforce 1 MiB minimum for maxInflightBytes (#129)
    • Allow canSetUserAgentHeader in non-browser runtimes (#131)
    • Respect backpressure in EventStream pull() (#161)
    • Stop retry sessions promptly on cancel and abort (#162)
    • Preserve non-plain objects in case conversion (#163)
    • Skip command-only batches when ignoreCommandRecords enabled (#164)
    • Propagate original Producer.close() errors instead of TypeError (#165)
    • Cancel fetch transport iterators on early termination (#166)
    • Reject endpoints with query strings or hash fragments (#167, #178)
    • Fail blocked submits fast when close() races backpressure (#177)
    • Wake idle RetryAppendSession pumps on abort() (#179)
    • Release reader locks and cancel upstream on deserialize errors (#180)
    • Validate S2S frame length to prevent parser desync (#182)
    • Normalize deleteOnEmpty.minAgeSecs during reconfigure (#183)
    • Allow iterator return()/throw() after stream exhaustion (#184)
    • Fall back to manual S2S iterator when native async iteration throws (#184)
    • Drop oversized framed records without crashing FrameAssembler (#192)
    • Reject NaN and non-finite batch configuration values (#193)
    • resumeStream returns null on session creation failure (#194)
    • Validate fencing token length in AppendRecord.fence() (#195)
    • Exclude path params from reconfigure request body (#196)
    • Export BatchSubmitTicket as value, not type-only (#197)
@s2-dev/[email protected] Bug fix

Minor fixes and improvements.

Full changelog

Patch Changes

  • 2d9d79c: misc bugfixes:
    • Enforce 1 MiB minimum for maxInflightBytes (#129)
    • Allow canSetUserAgentHeader in non-browser runtimes (#131)
    • Respect backpressure in EventStream pull() (#161)
    • Stop retry sessions promptly on cancel and abort (#162)
    • Preserve non-plain objects in case conversion (#163)
    • Skip command-only batches when ignoreCommandRecords enabled (#164)
    • Propagate original Producer.close() errors instead of TypeError (#165)
    • Cancel fetch transport iterators on early termination (#166)
    • Reject endpoints with query strings or hash fragments (#167, #178)
    • Fail blocked submits fast when close() races backpressure (#177)
    • Wake idle RetryAppendSession pumps on abort() (#179)
    • Release reader locks and cancel upstream on deserialize errors (#180)
    • Validate S2S frame length to prevent parser desync (#182)
    • Normalize deleteOnEmpty.minAgeSecs during reconfigure (#183)
    • Allow iterator return()/throw() after stream exhaustion (#184)
    • Fall back to manual S2S iterator when native async iteration throws (#184)
    • Drop oversized framed records without crashing FrameAssembler (#192)
    • Reject NaN and non-finite batch configuration values (#193)
    • resumeStream returns null on session creation failure (#194)
    • Validate fencing token length in AppendRecord.fence() (#195)
    • Exclude path params from reconfigure request body (#196)
    • Export BatchSubmitTicket as value, not type-only (#197)
@s2-dev/[email protected] Bug fix

Minor fixes and improvements.

Full changelog

Patch Changes

  • 2d9d79c: misc bugfixes:
    • Enforce 1 MiB minimum for maxInflightBytes (#129)
    • Allow canSetUserAgentHeader in non-browser runtimes (#131)
    • Respect backpressure in EventStream pull() (#161)
    • Stop retry sessions promptly on cancel and abort (#162)
    • Preserve non-plain objects in case conversion (#163)
    • Skip command-only batches when ignoreCommandRecords enabled (#164)
    • Propagate original Producer.close() errors instead of TypeError (#165)
    • Cancel fetch transport iterators on early termination (#166)
    • Reject endpoints with query strings or hash fragments (#167, #178)
    • Fail blocked submits fast when close() races backpressure (#177)
    • Wake idle RetryAppendSession pumps on abort() (#179)
    • Release reader locks and cancel upstream on deserialize errors (#180)
    • Validate S2S frame length to prevent parser desync (#182)
    • Normalize deleteOnEmpty.minAgeSecs during reconfigure (#183)
    • Allow iterator return()/throw() after stream exhaustion (#184)
    • Fall back to manual S2S iterator when native async iteration throws (#184)
    • Drop oversized framed records without crashing FrameAssembler (#192)
    • Reject NaN and non-finite batch configuration values (#193)
    • resumeStream returns null on session creation failure (#194)
    • Validate fencing token length in AppendRecord.fence() (#195)
    • Exclude path params from reconfigure request body (#196)
    • Export BatchSubmitTicket as value, not type-only (#197)
@s2-dev/[email protected] New feature
Notable features
  • Added endpoint support for s2-lite
  • Migrated internals to streamstore v2 SDK APIs
Full changelog

Patch Changes

  • 362c138: Migrate internals to streamstore v2 SDK APIs and add endpoint support for s2-lite.
@s2-dev/[email protected] Bug fix

Minor fixes and improvements.

Full changelog

Patch Changes

  • 9f28893: - Improves decision tree for when to retry failed appends under noSideEffects policy

    • Fixes a bug regarding duplicated acks after append session recovery
  • 12f0903: Bug fixes:

    • Fix Producer.close() to be idempotent, preventing TypeError on concurrent calls (#90)
    • Freeze and unexport Redacted prototype to prevent secret leakage (#91)
    • Re-check closed state after async transport creation in readSession/appendSession (#96)
    • Check all pipelined entries for idempotency under noSideEffects retry policy (#135)
    • Fix BatchTransform cancel hook, 0ms linger, controller init, and safe async flush (#136)
    • Use AppendInput.create in SerializingAppendSession.write for correct meteredBytes (#137)
    • Await pending ack handlers before exiting Producer.runPump (#138)
    • Prevent transport leak by caching creation promise in S2Stream.getTransport (#140)
    • Use exact matching in isConnectionError to prevent false positives (#141)
    • Clean up goaway and abort listeners in S2SReadSession to prevent memory leaks (#142)
    • Validate numeric inputs in AppendRecord.trim and AppendInput.create (#143)
    • Fix EventStream falsy value drops, missing return after done, and no-colon SSE parsing (#144)
    • Count connection failures toward maxAttempts in RetryAppendSession (#150)
    • Recompute meteredBytes after injecting dedupe headers (#151)
    • Add type guard before in operator to handle non-object error responses (#154)
@s2-dev/[email protected] Breaking risk
⚠ Upgrade required
  • Deprecated timeout settings under retry config; migrate to top-level connectionTimeoutMillis and requestTimeoutMillis.
  • Default connection timeout reduced from 5000 ms to 3000 ms.
Breaking changes
  • basins.listAll() and streams.listAll() now accept includeDeleted via options object instead of as first positional argument
Full changelog

Patch Changes

  • 792b99a: - Promote connectionTimeoutMillis and requestTimeoutMillis to top-level client options
    • Deprecate timeout settings under retry config (backwards-compatible)
    • Reduce default connection timeout from 5s to 3s
    • Change basins.listAll() and streams.listAll() to accept includeDeleted in options object instead of as first positional argument
    • Rename delay config options to clarify they apply to base delay
@s2-dev/[email protected] Bug fix

Fixed handling of HTTP 416 responses in the S2 read session.

Changelog

Minor Changes

  • 1c13db6: Minor fix to handle 416 explicitly in s2s read session
@s2-dev/[email protected] Breaking risk
⚠ Upgrade required
  • Public types are now SDK‑native (camelCase + Date); previously re‑exported generated snake_case wire types have been replaced.
  • Wire‑format types moved behind the API: import from `@s2-dev/streamstore` rather than directly importing many snake_case types.
  • Client endpoint configuration changed to use `S2ClientOptions.endpoints` / `S2Endpoints`; added `S2Environment.parse()` for env‑var config.
Breaking changes
  • Removed `retryBackoffDurationMillis` from retry config; replaced with `minDelayMillis`/`maxDelayMillis` and new `connectionTimeoutMillis`.
  • Renamed and reshaped several public types: wire‑format snake_case imports are now behind the SDK's camelCase type layer (`import type { API } from "@s2-dev/streamstore"`).
  • Stream append API changed from `S2Stream.append(records, {match_seq_num,fencing_token})` to `S2Stream.append(input: AppendInput)` with camelCase fields.
Notable features
  • Higher‑level Producer API with per‑record submit/ack interface using a configurable batcher over an append session.
  • Protobuf content‑type used for unary data‑plane requests when appending or reading binary records (base64 still used for SSE read sessions).
  • Explicit `S2Stream.close()` to trigger cleanup of shared transport and consolidated, documented SDK type layer including `AppendRecord` factories and `AppendInput.create(...)` validation.
Full changelog

Minor Changes

  • 0d76a27: Adds a higher level Producer API which provides a per-record submit and ack interface (while using a configurable batcher over an append session)
    • API standardization around append session, in particular by introducing a BatchSubmitTicket type
      • submit(batch) returns Promise<BatchSubmitTicket>
        • this promise resolves only once a batch has been enqueued for submission in the session, and thus has received a deterministic ordering
        • users can separately await the Promise returned by BatchSubmitTicket.ack() to block on durability
    • Switches to use of protobuf content-type for unary data plane requests when appending or reading binary records
      • base64 is still used for SSE read sessions
    • Allows explicit closing of an S2Stream, triggering cleanup of shared transport
    • Introduces a consolidated, documented SDK type layer including AppendRecord factories and AppendInput.create(...) validation
    • Improves transport/mapping internals: dedicated case-conversion utilities, centralized mappers, and protobuf support for bytes paths
    • Expanded docs/examples and test coverage (including retry/session and correctness-focused tests)

Upgrade Notes

  • Public types are now SDK-native (camelCase + Date): many previously re-exported generated (wire) types are replaced by new SDK types in packages/streamstore/src/types.ts
  • Wire-format types moved behind API: instead of importing lots of snake_case types directly, use import type { API } from "@s2-dev/streamstore"
  • Client endpoint config changed: use S2ClientOptions.endpoints / S2Endpoints (and S2Environment.parse() was added for env var config)
  • Retry config renamed/changed: retryBackoffDurationMillis is removed; replaced with minDelayMillis/maxDelayMillis (exponential backoff) and new connectionTimeoutMillis (S2S transport only)
  • Stream append API changed:
    • S2Stream.append(records, { match_seq_num, fencing_token })S2Stream.append(input: AppendInput) with camelCase fields
    • New validation helpers/constants: AppendRecord.string/bytes(...), AppendInput.create(...)
    • String headers are no longer Record<string,string>; use tuple arrays (ReadonlyArray<[string,string]>)
  • Append session API changed:
    • AppendSession.submit(...) no longer returns AppendAck directly; it returns a BatchSubmitTicket and you await ticket.ack() to get the durable AppendAck
    • AppendSession.writable now accepts AppendInput (not AppendArgs)
  • Metrics API timestamps changed: start/end inputs accept Date or milliseconds; timeseries points in responses are now [Date, number] (not epoch seconds)
  • BatchTransform renamed/reshaped: BatchTransformArgsBatchTransformOptions, fencing_token/match_seq_num → camelCase, and the transform output is now an AppendInput (not { records, ... })

Beta — feedback welcome: [email protected]