@rimelabs/sdk 0.1.0-alpha.23 → 0.1.0-alpha.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.0-alpha.24](https://github.com/rimelabs/rime-sdk/compare/typescript-v0.1.0-alpha.23...typescript-v0.1.0-alpha.24) (2026-10-27)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * Python and TypeScript SessionEvent payload unions now include ItemTruncated. Update exhaustive event handlers to accept ItemTruncated or the item.truncated kind. Handle unavailable retained text separately from an empty string. Rust's event enum remains non-exhaustive.
9
+
10
+ ### Features
11
+
12
+ * expose realtime truncation events and summaries ([#112](https://github.com/rimelabs/rime-sdk/issues/112)) ([15d6802](https://github.com/rimelabs/rime-sdk/commit/15d6802f71c849ce08b1d0b46e78bd44d5dfc3b7))
13
+
3
14
  ## [0.1.0-alpha.23](https://github.com/rimelabs/rime-sdk/compare/typescript-v0.1.0-alpha.22...typescript-v0.1.0-alpha.23) (2026-10-27)
4
15
 
5
16
 
@@ -76,15 +76,10 @@ export interface ItemDeleted {
76
76
  export interface AudioCleared {
77
77
  kind: "audio.cleared";
78
78
  }
79
- export interface ItemTruncated {
80
- kind: "item.truncated";
81
- itemId: string;
82
- contentIndex: number;
83
- }
84
79
  export interface ResponseEnded extends t.ResponseEnded {
85
80
  drainToken: string | null;
86
81
  }
87
- export type Acknowledgment = SessionUpdated | HistoryListed | ItemDeleted | ItemCreated | ToolResultCreated | AudioCleared | ItemTruncated | t.ResponseStarted | ResponseEnded;
82
+ export type Acknowledgment = SessionUpdated | HistoryListed | ItemDeleted | ItemCreated | ToolResultCreated | AudioCleared | t.ItemTruncated | t.ResponseStarted | ResponseEnded;
88
83
  export type ServerPayload = SessionCreated | Acknowledgment | t.InputEvent<t.NormalizedRealtimeFault> | t.MessageStarted | t.TextDelta | t.TextDone | t.AudioDelta | t.AudioDone | t.ToolCall | t.FaultEvent<t.NormalizedRealtimeFault>;
89
84
  export interface ServerEvent {
90
85
  eventId: string;
@@ -113,7 +108,7 @@ export declare const requests: {
113
108
  text: Request<t.ResponseStarted>;
114
109
  cancel: Request<ResponseEnded>;
115
110
  clear: Request<AudioCleared>;
116
- truncate: Request<ItemTruncated>;
111
+ truncate: Request<t.ItemTruncated>;
117
112
  };
118
113
  export declare function truncationSettings(value: t.Truncation): NonNullable<SessionSettings["truncation"]>;
119
114
  export declare function decode(raw: string, sessionId: string | null): ServerEvent | null;
@@ -77,6 +77,20 @@ function revision(value) {
77
77
  ? null
78
78
  : integer(value.prism_settings_revision, "prism_settings_revision");
79
79
  }
80
+ function responseTruncation(response) {
81
+ if (response.prism_truncation === undefined)
82
+ return null;
83
+ const value = object(response.prism_truncation, "response.prism_truncation");
84
+ const count = integer(value.items_left_out, "prism_truncation.items_left_out");
85
+ if (count === 0)
86
+ return invalid("prism_truncation.items_left_out");
87
+ return Object.freeze({
88
+ itemsLeftOut: count,
89
+ firstKeptItemId: value.first_kept_item_id === undefined
90
+ ? null
91
+ : string(value.first_kept_item_id, "prism_truncation.first_kept_item_id"),
92
+ });
93
+ }
80
94
  function duration(value, field) {
81
95
  if (value == null)
82
96
  return null;
@@ -281,6 +295,10 @@ function decodeValue(value, sessionId) {
281
295
  kind: "item.truncated",
282
296
  itemId: id(event.item_id, "item_id"),
283
297
  contentIndex: integer(event.content_index, "content_index"),
298
+ audioEndMs: integer(event.audio_end_ms, "audio_end_ms"),
299
+ keptText: event.prism_kept_text === undefined
300
+ ? null
301
+ : string(event.prism_kept_text, "prism_kept_text"),
284
302
  };
285
303
  break;
286
304
  case "prism.typed_input.ready":
@@ -396,6 +414,7 @@ function decodeValue(value, sessionId) {
396
414
  payload = {
397
415
  kind: "response.ended",
398
416
  settingsRevision: revision(response),
417
+ truncation: responseTruncation(response),
399
418
  response: ref(response.id),
400
419
  status: status === "completed" ||
401
420
  status === "cancelled" ||
@@ -752,7 +752,7 @@ export class RealtimeSession {
752
752
  pending.target === payload.itemId &&
753
753
  payload.contentIndex === 0)
754
754
  this.settle(key, payload);
755
- return;
755
+ break;
756
756
  case "input.ready":
757
757
  this.readyEpoch++;
758
758
  this.ready.set();
@@ -288,10 +288,20 @@ export interface ResponseAbandoned {
288
288
  readonly kind: "response.abandoned";
289
289
  readonly response: ResponseRef;
290
290
  }
291
+ /** History items excluded from this reply's prompt, not deleted from history. */
292
+ export interface ResponseTruncation {
293
+ /** Number of excluded items, not turns. Already hidden items are not counted. */
294
+ readonly itemsLeftOut: number;
295
+ /** Oldest retained item; null when no earlier item was retained. */
296
+ readonly firstKeptItemId: string | null;
297
+ }
291
298
  export interface ResponseEnded {
292
299
  /** Settings revision published by the server; null when unavailable.
293
300
  * Optional on caller-created values for compatibility. */
294
301
  readonly settingsRevision?: number | null;
302
+ /** Null when the server reports no exclusions or the information is unavailable.
303
+ * Optional on caller-created values for compatibility. */
304
+ readonly truncation?: ResponseTruncation | null;
295
305
  readonly kind: "response.ended";
296
306
  readonly response: ResponseRef;
297
307
  readonly status: "completed" | "cancelled" | "failed" | "unknown";
@@ -303,11 +313,21 @@ export interface FaultEvent<Fault extends RealtimeFault = RealtimeFault> {
303
313
  }
304
314
  export type InputEvent<Fault extends RealtimeFault = RealtimeFault> = InputReady | SpeechHint | SpeechStarted | SpeechStopped | InputCommitted | TranscriptDelta | TranscriptFinal | TranscriptFailed<Fault>;
305
315
  export type ResponseEvent = ResponseStarted | ResponseAbandoned | MessageStarted | TextDelta | TextDone | AudioDelta | AudioDone | ToolCall | ResponseEnded;
316
+ /** A playback report was recorded. Retained history text can differ from audible
317
+ * text: replies with tool calls retain all words. */
318
+ export interface ItemTruncated {
319
+ readonly kind: "item.truncated";
320
+ readonly itemId: string;
321
+ readonly contentIndex: number;
322
+ readonly audioEndMs: number;
323
+ /** Null when unavailable, including during generation; empty if no words remain. */
324
+ readonly keptText: string | null;
325
+ }
306
326
  export interface SessionEvent<Fault extends RealtimeFault = RealtimeFault> {
307
327
  readonly sessionId: string;
308
328
  readonly eventId: string;
309
329
  readonly requestId: string | null;
310
- readonly payload: InputEvent<Fault> | ResponseEvent | FaultEvent<Fault>;
330
+ readonly payload: InputEvent<Fault> | ResponseEvent | ItemTruncated | FaultEvent<Fault>;
311
331
  }
312
332
  export interface PlaybackInterrupted {
313
333
  readonly kind: "interrupted";
package/docs/realtime.md CHANGED
@@ -587,3 +587,52 @@ publish it.
587
587
  ```text
588
588
  await session.update({ truncation: { retentionRatio: 0.9 } });
589
589
  ```
590
+
591
+ ## Retained text after interruption
592
+
593
+ Available in the next SDK release. A `conversation.item.truncated` acknowledgment
594
+ also appears in `session.events` as `ItemTruncated`, with kind `item.truncated`.
595
+ The conversation runner forwards it to `onEvent`. Playback reporting does not
596
+ wait for event consumption.
597
+
598
+ Use `itemId`, `contentIndex`, and `audioEndMs` to identify the reported audio.
599
+ `keptText` is the text retained in server history. An empty string means no words
600
+ remain. `null` means unavailable, including older servers and replies still being
601
+ generated. The event does not promise a later text update. Replies with tool calls
602
+ retain all words, so this field can differ from the words heard during playback.
603
+
604
+ ```typescript
605
+ function onEvent(event: SessionEvent) {
606
+ if (event.payload.kind === "item.truncated") {
607
+ const cut = event.payload;
608
+ if (cut.keptText !== null) {
609
+ console.log("Retained text", cut.itemId, JSON.stringify(cut.keptText));
610
+ }
611
+ }
612
+ }
613
+ ```
614
+
615
+ This event can arrive after `response.ended`. It has no response reference and does
616
+ not require the SDK to retain that response. `text.done` still reports generated
617
+ text. Add `item.truncated` to exhaustive switches on `SessionEvent.payload.kind`.
618
+
619
+ ## History excluded from a reply
620
+
621
+ Available in the next SDK release. `ResponseEnded.truncation` exposes the server's
622
+ `response.prism_truncation` summary. It contains `itemsLeftOut` and nullable
623
+ `firstKeptItemId`. The count refers to conversation items excluded from this
624
+ reply's prompt, not turns or items deleted from history. Already hidden items do
625
+ not count. The first ID is absent when no item from before this turn was retained.
626
+
627
+ Decoded events have `truncation: null` when the server reports no exclusions or the
628
+ information is unavailable, including older servers or a reply that ended before
629
+ usage was counted. Caller-created events may omit the property. This does not change
630
+ the session's truncation policy. Session events and conversation callbacks expose
631
+ the same immutable summary.
632
+
633
+ ```typescript
634
+ if (event.payload.kind === "response.ended" && event.payload.truncation) {
635
+ const summary = event.payload.truncation;
636
+ console.log(summary.itemsLeftOut, summary.firstKeptItemId);
637
+ }
638
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimelabs/sdk",
3
- "version": "0.1.0-alpha.23",
3
+ "version": "0.1.0-alpha.24",
4
4
  "description": "Rime streaming TTS, STT and Prism realtime SDK for Node.js",
5
5
  "license": "MIT",
6
6
  "type": "module",