@ably/ai-transport 0.1.0 → 0.2.0

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.
Files changed (163) hide show
  1. package/README.md +91 -100
  2. package/dist/ably-ai-transport.js +1553 -1238
  3. package/dist/ably-ai-transport.js.map +1 -1
  4. package/dist/ably-ai-transport.umd.cjs +1 -1
  5. package/dist/ably-ai-transport.umd.cjs.map +1 -1
  6. package/dist/constants.d.ts +116 -42
  7. package/dist/core/agent.d.ts +29 -0
  8. package/dist/core/codec/decoder.d.ts +20 -23
  9. package/dist/core/codec/encoder.d.ts +11 -8
  10. package/dist/core/codec/index.d.ts +1 -2
  11. package/dist/core/codec/lifecycle-tracker.d.ts +10 -9
  12. package/dist/core/codec/types.d.ts +407 -115
  13. package/dist/core/transport/agent-session.d.ts +10 -0
  14. package/dist/core/transport/branch-chain.d.ts +43 -0
  15. package/dist/core/transport/client-session.d.ts +13 -0
  16. package/dist/core/transport/decode-fold.d.ts +47 -0
  17. package/dist/core/transport/headers.d.ts +96 -18
  18. package/dist/core/transport/index.d.ts +5 -6
  19. package/dist/core/transport/internal/bounded-map.d.ts +20 -0
  20. package/dist/core/transport/invocation.d.ts +74 -0
  21. package/dist/core/transport/load-conversation.d.ts +128 -0
  22. package/dist/core/transport/load-history.d.ts +39 -0
  23. package/dist/core/transport/pipe-stream.d.ts +9 -9
  24. package/dist/core/transport/run-manager.d.ts +78 -0
  25. package/dist/core/transport/tree.d.ts +373 -109
  26. package/dist/core/transport/types/agent.d.ts +353 -0
  27. package/dist/core/transport/types/client.d.ts +168 -0
  28. package/dist/core/transport/types/shared.d.ts +24 -0
  29. package/dist/core/transport/types/tree.d.ts +315 -0
  30. package/dist/core/transport/types/view.d.ts +222 -0
  31. package/dist/core/transport/types.d.ts +13 -553
  32. package/dist/core/transport/view.d.ts +272 -84
  33. package/dist/errors.d.ts +21 -10
  34. package/dist/index.d.ts +6 -8
  35. package/dist/logger.d.ts +12 -0
  36. package/dist/react/ably-ai-transport-react.js +976 -990
  37. package/dist/react/ably-ai-transport-react.js.map +1 -1
  38. package/dist/react/ably-ai-transport-react.umd.cjs +1 -1
  39. package/dist/react/ably-ai-transport-react.umd.cjs.map +1 -1
  40. package/dist/react/contexts/client-session-context.d.ts +36 -0
  41. package/dist/react/contexts/client-session-provider.d.ts +53 -0
  42. package/dist/react/create-session-hooks.d.ts +116 -0
  43. package/dist/react/index.d.ts +12 -12
  44. package/dist/react/internal/use-resolved-session.d.ts +36 -0
  45. package/dist/react/use-ably-messages.d.ts +17 -14
  46. package/dist/react/use-client-session.d.ts +81 -0
  47. package/dist/react/use-create-view.d.ts +14 -13
  48. package/dist/react/use-tree.d.ts +30 -15
  49. package/dist/react/use-view.d.ts +82 -51
  50. package/dist/utils.d.ts +32 -23
  51. package/dist/vercel/ably-ai-transport-vercel.js +2573 -2086
  52. package/dist/vercel/ably-ai-transport-vercel.js.map +1 -1
  53. package/dist/vercel/ably-ai-transport-vercel.umd.cjs +1 -1
  54. package/dist/vercel/ably-ai-transport-vercel.umd.cjs.map +1 -1
  55. package/dist/vercel/codec/decoder.d.ts +5 -18
  56. package/dist/vercel/codec/encoder.d.ts +6 -36
  57. package/dist/vercel/codec/events.d.ts +51 -0
  58. package/dist/vercel/codec/index.d.ts +24 -12
  59. package/dist/vercel/codec/reducer.d.ts +144 -0
  60. package/dist/vercel/codec/tool-transitions.d.ts +2 -2
  61. package/dist/vercel/index.d.ts +4 -5
  62. package/dist/vercel/react/ably-ai-transport-vercel-react.js +3907 -3266
  63. package/dist/vercel/react/ably-ai-transport-vercel-react.js.map +1 -1
  64. package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs +33 -8
  65. package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs.map +1 -1
  66. package/dist/vercel/react/contexts/chat-transport-context.d.ts +7 -6
  67. package/dist/vercel/react/contexts/chat-transport-provider.d.ts +53 -41
  68. package/dist/vercel/react/index.d.ts +1 -2
  69. package/dist/vercel/react/use-chat-transport.d.ts +30 -26
  70. package/dist/vercel/react/use-message-sync.d.ts +17 -30
  71. package/dist/vercel/run-end-reason.d.ts +29 -0
  72. package/dist/vercel/transport/chat-transport.d.ts +43 -24
  73. package/dist/vercel/transport/index.d.ts +25 -21
  74. package/dist/vercel/transport/run-output-stream.d.ts +56 -0
  75. package/dist/version.d.ts +2 -0
  76. package/package.json +30 -23
  77. package/src/constants.ts +124 -51
  78. package/src/core/agent.ts +68 -0
  79. package/src/core/codec/decoder.ts +71 -98
  80. package/src/core/codec/encoder.ts +113 -65
  81. package/src/core/codec/index.ts +13 -6
  82. package/src/core/codec/lifecycle-tracker.ts +10 -9
  83. package/src/core/codec/types.ts +436 -120
  84. package/src/core/transport/agent-session.ts +1344 -0
  85. package/src/core/transport/branch-chain.ts +58 -0
  86. package/src/core/transport/client-session.ts +775 -0
  87. package/src/core/transport/decode-fold.ts +91 -0
  88. package/src/core/transport/headers.ts +181 -22
  89. package/src/core/transport/index.ts +25 -26
  90. package/src/core/transport/internal/bounded-map.ts +27 -0
  91. package/src/core/transport/invocation.ts +98 -0
  92. package/src/core/transport/load-conversation.ts +355 -0
  93. package/src/core/transport/load-history.ts +269 -0
  94. package/src/core/transport/pipe-stream.ts +54 -39
  95. package/src/core/transport/run-manager.ts +249 -0
  96. package/src/core/transport/tree.ts +926 -308
  97. package/src/core/transport/types/agent.ts +407 -0
  98. package/src/core/transport/types/client.ts +211 -0
  99. package/src/core/transport/types/shared.ts +27 -0
  100. package/src/core/transport/types/tree.ts +344 -0
  101. package/src/core/transport/types/view.ts +259 -0
  102. package/src/core/transport/types.ts +13 -706
  103. package/src/core/transport/view.ts +864 -433
  104. package/src/errors.ts +22 -9
  105. package/src/event-emitter.ts +3 -2
  106. package/src/index.ts +52 -41
  107. package/src/logger.ts +14 -1
  108. package/src/react/contexts/client-session-context.ts +41 -0
  109. package/src/react/contexts/client-session-provider.tsx +186 -0
  110. package/src/react/create-session-hooks.ts +141 -0
  111. package/src/react/index.ts +23 -13
  112. package/src/react/internal/use-resolved-session.ts +63 -0
  113. package/src/react/use-ably-messages.ts +32 -22
  114. package/src/react/use-client-session.ts +201 -0
  115. package/src/react/use-create-view.ts +33 -29
  116. package/src/react/use-tree.ts +61 -30
  117. package/src/react/use-view.ts +139 -97
  118. package/src/utils.ts +63 -45
  119. package/src/vercel/codec/decoder.ts +336 -258
  120. package/src/vercel/codec/encoder.ts +343 -205
  121. package/src/vercel/codec/events.ts +87 -0
  122. package/src/vercel/codec/index.ts +60 -13
  123. package/src/vercel/codec/reducer.ts +977 -0
  124. package/src/vercel/codec/tool-transitions.ts +2 -2
  125. package/src/vercel/index.ts +6 -19
  126. package/src/vercel/react/contexts/chat-transport-context.ts +7 -6
  127. package/src/vercel/react/contexts/chat-transport-provider.tsx +87 -59
  128. package/src/vercel/react/index.ts +3 -5
  129. package/src/vercel/react/use-chat-transport.ts +47 -49
  130. package/src/vercel/react/use-message-sync.ts +80 -39
  131. package/src/vercel/run-end-reason.ts +78 -0
  132. package/src/vercel/transport/chat-transport.ts +392 -98
  133. package/src/vercel/transport/index.ts +39 -38
  134. package/src/vercel/transport/run-output-stream.ts +170 -0
  135. package/src/version.ts +2 -0
  136. package/dist/core/transport/client-transport.d.ts +0 -10
  137. package/dist/core/transport/decode-history.d.ts +0 -43
  138. package/dist/core/transport/server-transport.d.ts +0 -7
  139. package/dist/core/transport/stream-router.d.ts +0 -29
  140. package/dist/core/transport/turn-manager.d.ts +0 -37
  141. package/dist/react/contexts/transport-context.d.ts +0 -31
  142. package/dist/react/contexts/transport-provider.d.ts +0 -49
  143. package/dist/react/create-transport-hooks.d.ts +0 -124
  144. package/dist/react/use-active-turns.d.ts +0 -12
  145. package/dist/react/use-client-transport.d.ts +0 -80
  146. package/dist/vercel/codec/accumulator.d.ts +0 -21
  147. package/dist/vercel/react/use-staged-add-tool-approval-response.d.ts +0 -30
  148. package/dist/vercel/tool-approvals.d.ts +0 -124
  149. package/dist/vercel/tool-events.d.ts +0 -26
  150. package/src/core/transport/client-transport.ts +0 -977
  151. package/src/core/transport/decode-history.ts +0 -485
  152. package/src/core/transport/server-transport.ts +0 -612
  153. package/src/core/transport/stream-router.ts +0 -136
  154. package/src/core/transport/turn-manager.ts +0 -165
  155. package/src/react/contexts/transport-context.ts +0 -37
  156. package/src/react/contexts/transport-provider.tsx +0 -164
  157. package/src/react/create-transport-hooks.ts +0 -144
  158. package/src/react/use-active-turns.ts +0 -72
  159. package/src/react/use-client-transport.ts +0 -197
  160. package/src/vercel/codec/accumulator.ts +0 -588
  161. package/src/vercel/react/use-staged-add-tool-approval-response.ts +0 -87
  162. package/src/vercel/tool-approvals.ts +0 -380
  163. package/src/vercel/tool-events.ts +0 -53
@@ -6,24 +6,18 @@
6
6
  * event decoding.
7
7
  *
8
8
  * Domain decoders call `createDecoderCore(hooks, options)` and provide hooks
9
- * for stream classification, event building, and discrete decoding.
9
+ * for stream classification, event building, and discrete decoding. Hooks
10
+ * return a flat `TEvent[]` — no event-vs-message union. Per-message routing
11
+ * concerns (`codec-message-id`) are handled by the SDK via `ReducerMeta`, not
12
+ * here.
10
13
  */
11
14
 
12
15
  import type * as Ably from 'ably';
13
16
 
14
- import { HEADER_MSG_ID, HEADER_STATUS, HEADER_STREAM, HEADER_STREAM_ID } from '../../constants.js';
17
+ import { HEADER_STATUS, HEADER_STREAM, HEADER_STREAM_ID } from '../../constants.js';
15
18
  import type { Logger } from '../../logger.js';
16
- import { getHeaders } from '../../utils.js';
17
- import type { DecoderOutput, MessagePayload, StreamTrackerState } from './types.js';
18
-
19
- /**
20
- * Wrap a domain event as a single-element decoder output array.
21
- * @param event - The domain event to wrap.
22
- * @returns A single-element array containing the event as a decoder output.
23
- */
24
- export const eventOutput = <TEvent, TMessage>(event: TEvent): DecoderOutput<TEvent, TMessage>[] => [
25
- { kind: 'event', event },
26
- ];
19
+ import { getCodecHeaders, getTransportHeaders } from '../../utils.js';
20
+ import type { MessagePayload, StreamTrackerState } from './types.js';
27
21
 
28
22
  // ---------------------------------------------------------------------------
29
23
  // Options
@@ -44,32 +38,29 @@ export interface DecoderCoreOptions {
44
38
  // ---------------------------------------------------------------------------
45
39
 
46
40
  /** Hooks that a domain codec provides to the decoder core for stream classification and event building. */
47
- export interface DecoderCoreHooks<TEvent, TMessage> {
41
+ export interface DecoderCoreHooks<TEvent> {
48
42
  /**
49
43
  * Build domain events emitted when a new stream starts. May return multiple
50
44
  * events (e.g. a start event and a start-step event).
51
45
  */
52
- buildStartEvents(tracker: StreamTrackerState): DecoderOutput<TEvent, TMessage>[];
46
+ buildStartEvents(tracker: StreamTrackerState): TEvent[];
53
47
 
54
48
  /** Build domain events for a text delta received on a stream. */
55
- buildDeltaEvents(tracker: StreamTrackerState, delta: string): DecoderOutput<TEvent, TMessage>[];
49
+ buildDeltaEvents(tracker: StreamTrackerState, delta: string): TEvent[];
56
50
 
57
51
  /**
58
- * Build domain events emitted when a stream finishes (x-ably-status:finished).
59
- * Not called for aborted streams. The closing headers may differ from
60
- * tracker.headers if the closing append carried updated headers.
52
+ * Build domain events emitted when a stream completes (status:complete).
53
+ * Not called for cancelled streams. The closing codec headers may differ
54
+ * from tracker.codecHeaders if the closing append carried updated headers.
61
55
  */
62
- buildEndEvents(
63
- tracker: StreamTrackerState,
64
- closingHeaders: Record<string, string>,
65
- ): DecoderOutput<TEvent, TMessage>[];
56
+ buildEndEvents(tracker: StreamTrackerState, closingCodecHeaders: Record<string, string>): TEvent[];
66
57
 
67
58
  /**
68
- * Decode a discrete message (message.create where x-ably-stream is "false",
69
- * or a non-streamable first-contact update). Handles user messages, lifecycle
70
- * events, tool lifecycle, data-*, etc.
59
+ * Decode a discrete message (a `message.create` whose stream header is not
60
+ * "true", or a non-streamable first-contact update). Handles user messages,
61
+ * tool lifecycle, data-*, etc.
71
62
  */
72
- decodeDiscrete(input: MessagePayload): DecoderOutput<TEvent, TMessage>[];
63
+ decodeDiscrete(input: MessagePayload): TEvent[];
73
64
  }
74
65
 
75
66
  // ---------------------------------------------------------------------------
@@ -77,9 +68,9 @@ export interface DecoderCoreHooks<TEvent, TMessage> {
77
68
  // ---------------------------------------------------------------------------
78
69
 
79
70
  /** The decoder core returned by {@link createDecoderCore}. */
80
- export interface DecoderCore<TEvent, TMessage> {
81
- /** Decode a single Ably message into zero or more domain outputs. */
82
- decode(message: Ably.InboundMessage): DecoderOutput<TEvent, TMessage>[];
71
+ export interface DecoderCore<TEvent> {
72
+ /** Decode a single Ably message into zero or more domain TEvents. */
73
+ decode(message: Ably.InboundMessage): TEvent[];
83
74
  }
84
75
 
85
76
  // ---------------------------------------------------------------------------
@@ -87,70 +78,50 @@ export interface DecoderCore<TEvent, TMessage> {
87
78
  // ---------------------------------------------------------------------------
88
79
 
89
80
  // Spec: AIT-CD7
90
- class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessage> {
91
- private readonly _hooks: DecoderCoreHooks<TEvent, TMessage>;
81
+ class DefaultDecoderCore<TEvent> implements DecoderCore<TEvent> {
82
+ private readonly _hooks: DecoderCoreHooks<TEvent>;
92
83
  private readonly _logger: Logger | undefined;
93
84
  private readonly _onStreamUpdate: ((tracker: StreamTrackerState) => void) | undefined;
94
85
  private readonly _onStreamDelete: ((serial: string, tracker: StreamTrackerState | undefined) => void) | undefined;
95
86
  private readonly _serialState = new Map<string, StreamTrackerState>();
96
87
 
97
- constructor(hooks: DecoderCoreHooks<TEvent, TMessage>, options: DecoderCoreOptions = {}) {
88
+ constructor(hooks: DecoderCoreHooks<TEvent>, options: DecoderCoreOptions = {}) {
98
89
  this._hooks = hooks;
99
90
  this._onStreamUpdate = options.onStreamUpdate;
100
91
  this._onStreamDelete = options.onStreamDelete;
101
92
  this._logger = options.logger?.withContext({ component: 'DecoderCore' });
102
93
  }
103
94
 
104
- decode(message: Ably.InboundMessage): DecoderOutput<TEvent, TMessage>[] {
95
+ decode(message: Ably.InboundMessage): TEvent[] {
105
96
  const action = message.action;
106
97
 
107
98
  this._logger?.trace('DefaultDecoderCore.decode();', { action, serial: message.serial, name: message.name });
108
99
 
109
- let outputs: DecoderOutput<TEvent, TMessage>[];
110
-
111
100
  switch (action) {
112
101
  // Spec: AIT-CD7a
113
102
  case 'message.create': {
114
103
  const payload = this._toPayload(message);
115
-
116
- outputs =
117
- payload.headers?.[HEADER_STREAM] === 'true'
118
- ? this._decodeStreamedCreate(payload, message.serial)
119
- : this._hooks.decodeDiscrete(payload);
120
- break;
104
+ return payload.transportHeaders?.[HEADER_STREAM] === 'true'
105
+ ? this._decodeStreamedCreate(payload, message.serial)
106
+ : this._hooks.decodeDiscrete(payload);
121
107
  }
122
108
 
123
109
  case 'message.append': {
124
- outputs = this._decodeAppend(message);
125
- break;
110
+ return this._decodeAppend(message);
126
111
  }
127
112
 
128
113
  case 'message.update': {
129
- outputs = this._decodeUpdate(message);
130
- break;
114
+ return this._decodeUpdate(message);
131
115
  }
132
116
 
133
117
  case 'message.delete': {
134
- outputs = this._decodeDelete(message);
135
- break;
118
+ return this._decodeDelete(message);
136
119
  }
137
120
 
138
121
  default: {
139
122
  return [];
140
123
  }
141
124
  }
142
-
143
- // Tag all event outputs with the message ID from x-ably-msg-id for accumulator correlation.
144
- const messageId = getHeaders(message)[HEADER_MSG_ID];
145
- if (messageId) {
146
- for (const output of outputs) {
147
- if (output.kind === 'event') {
148
- output.messageId = messageId;
149
- }
150
- }
151
- }
152
-
153
- return outputs;
154
125
  }
155
126
 
156
127
  // -------------------------------------------------------------------------
@@ -162,7 +133,8 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
162
133
  name: message.name ?? '',
163
134
  // CAST: Ably SDK types `data` as `any`; cast to unknown is the safe boundary type.
164
135
  data: message.data as unknown,
165
- headers: getHeaders(message),
136
+ transportHeaders: getTransportHeaders(message),
137
+ codecHeaders: getCodecHeaders(message),
166
138
  };
167
139
  }
168
140
 
@@ -201,20 +173,17 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
201
173
  // Private: streamed message create
202
174
  // -------------------------------------------------------------------------
203
175
 
204
- private _decodeStreamedCreate(
205
- payload: MessagePayload,
206
- serial: string | undefined,
207
- ): DecoderOutput<TEvent, TMessage>[] {
176
+ private _decodeStreamedCreate(payload: MessagePayload, serial: string | undefined): TEvent[] {
208
177
  if (!serial) return [];
209
178
 
210
- const streamId = payload.headers?.[HEADER_STREAM_ID] ?? '';
211
- const h = payload.headers ?? {};
179
+ const streamId = payload.transportHeaders?.[HEADER_STREAM_ID] ?? '';
212
180
 
213
181
  const tracker: StreamTrackerState = {
214
182
  name: payload.name,
215
183
  streamId,
216
184
  accumulated: '',
217
- headers: { ...h },
185
+ codecHeaders: { ...payload.codecHeaders },
186
+ transportHeaders: { ...payload.transportHeaders },
218
187
  closed: false,
219
188
  };
220
189
  this._serialState.set(serial, tracker);
@@ -233,7 +202,7 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
233
202
  // -------------------------------------------------------------------------
234
203
 
235
204
  // Spec: AIT-CD8
236
- private _decodeAppend(message: Ably.InboundMessage): DecoderOutput<TEvent, TMessage>[] {
205
+ private _decodeAppend(message: Ably.InboundMessage): TEvent[] {
237
206
  const serial = message.serial;
238
207
  if (!serial) return [];
239
208
 
@@ -243,23 +212,24 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
243
212
  return this._decodeUpdate(message);
244
213
  }
245
214
 
246
- const h = getHeaders(message);
215
+ const transport = getTransportHeaders(message);
216
+ const closingCodec = getCodecHeaders(message);
247
217
  const delta = typeof message.data === 'string' ? message.data : '';
248
- const status = h[HEADER_STATUS];
249
- const outputs: DecoderOutput<TEvent, TMessage>[] = [];
218
+ const status = transport[HEADER_STATUS];
219
+ const outputs: TEvent[] = [];
250
220
 
251
221
  if (delta.length > 0) {
252
222
  tracker.accumulated += delta;
253
223
  outputs.push(...this._hooks.buildDeltaEvents(tracker, delta));
254
224
  }
255
225
 
256
- if (status === 'finished' && !tracker.closed) {
226
+ if (status === 'complete' && !tracker.closed) {
257
227
  tracker.closed = true;
258
- outputs.push(...this._hooks.buildEndEvents(tracker, h));
259
- this._logger?.debug('DefaultDecoderCore._decodeAppend(); stream finished', { streamId: tracker.streamId });
260
- } else if (status === 'aborted' && !tracker.closed) {
228
+ outputs.push(...this._hooks.buildEndEvents(tracker, closingCodec));
229
+ this._logger?.debug('DefaultDecoderCore._decodeAppend(); stream complete', { streamId: tracker.streamId });
230
+ } else if (status === 'cancelled' && !tracker.closed) {
261
231
  tracker.closed = true;
262
- this._logger?.debug('DefaultDecoderCore._decodeAppend(); stream aborted', { streamId: tracker.streamId });
232
+ this._logger?.debug('DefaultDecoderCore._decodeAppend(); stream cancelled', { streamId: tracker.streamId });
263
233
  }
264
234
 
265
235
  return outputs;
@@ -270,14 +240,15 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
270
240
  // -------------------------------------------------------------------------
271
241
 
272
242
  // Spec: AIT-CD9
273
- private _decodeUpdate(message: Ably.InboundMessage): DecoderOutput<TEvent, TMessage>[] {
243
+ private _decodeUpdate(message: Ably.InboundMessage): TEvent[] {
274
244
  const serial = message.serial;
275
245
  if (!serial) return [];
276
246
 
277
247
  const payload = this._toPayload(message);
278
- const h = payload.headers ?? {};
279
- const isStreamed = h[HEADER_STREAM] === 'true';
280
- const status = h[HEADER_STATUS];
248
+ const transport = payload.transportHeaders ?? {};
249
+ const codec = payload.codecHeaders ?? {};
250
+ const isStreamed = transport[HEADER_STREAM] === 'true';
251
+ const status = transport[HEADER_STATUS];
281
252
 
282
253
  const tracker = this._serialState.get(serial);
283
254
 
@@ -291,17 +262,17 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
291
262
  // --- Tracker exists: prefix-match or replacement ---
292
263
  if (data.startsWith(tracker.accumulated)) {
293
264
  const delta = data.slice(tracker.accumulated.length);
294
- const outputs: DecoderOutput<TEvent, TMessage>[] = [];
265
+ const outputs: TEvent[] = [];
295
266
 
296
267
  if (delta.length > 0) {
297
268
  tracker.accumulated = data;
298
269
  outputs.push(...this._hooks.buildDeltaEvents(tracker, delta));
299
270
  }
300
271
 
301
- if (status === 'finished' && !tracker.closed) {
272
+ if (status === 'complete' && !tracker.closed) {
302
273
  tracker.closed = true;
303
- outputs.push(...this._hooks.buildEndEvents(tracker, h));
304
- } else if (status === 'aborted' && !tracker.closed) {
274
+ outputs.push(...this._hooks.buildEndEvents(tracker, codec));
275
+ } else if (status === 'cancelled' && !tracker.closed) {
305
276
  tracker.closed = true;
306
277
  }
307
278
 
@@ -310,7 +281,8 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
310
281
 
311
282
  // --- Replacement (NOT a prefix match) ---
312
283
  tracker.accumulated = data;
313
- tracker.headers = { ...h };
284
+ tracker.codecHeaders = { ...codec };
285
+ tracker.transportHeaders = { ...transport };
314
286
 
315
287
  this._invokeOnStreamUpdate(tracker);
316
288
 
@@ -322,14 +294,14 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
322
294
  isStreamed: boolean,
323
295
  status: string | undefined,
324
296
  serial: string,
325
- ): DecoderOutput<TEvent, TMessage>[] {
297
+ ): TEvent[] {
326
298
  // Non-streamed messages are discrete
327
299
  if (!isStreamed) {
328
300
  return this._hooks.decodeDiscrete(payload);
329
301
  }
330
302
 
331
- const streamId = payload.headers?.[HEADER_STREAM_ID] ?? '';
332
- const h = payload.headers ?? {};
303
+ const streamId = payload.transportHeaders?.[HEADER_STREAM_ID] ?? '';
304
+ const codec = payload.codecHeaders ?? {};
333
305
  const data = typeof payload.data === 'string' ? payload.data : '';
334
306
 
335
307
  this._logger?.debug('DefaultDecoderCore._decodeFirstContact(); first-contact stream', {
@@ -343,20 +315,21 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
343
315
  name: payload.name,
344
316
  streamId,
345
317
  accumulated: data,
346
- headers: { ...h },
347
- closed: status === 'finished' || status === 'aborted',
318
+ codecHeaders: { ...codec },
319
+ transportHeaders: { ...payload.transportHeaders },
320
+ closed: status === 'complete' || status === 'cancelled',
348
321
  };
349
322
  this._serialState.set(serial, newTracker);
350
323
 
351
- // Emit start + delta (if any) + end (if finished)
324
+ // Emit start + delta (if any) + end (if complete)
352
325
  const outputs = this._hooks.buildStartEvents(newTracker);
353
326
 
354
327
  if (data.length > 0) {
355
328
  outputs.push(...this._hooks.buildDeltaEvents(newTracker, data));
356
329
  }
357
330
 
358
- if (status === 'finished') {
359
- outputs.push(...this._hooks.buildEndEvents(newTracker, h));
331
+ if (status === 'complete') {
332
+ outputs.push(...this._hooks.buildEndEvents(newTracker, codec));
360
333
  }
361
334
 
362
335
  return outputs;
@@ -367,7 +340,7 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
367
340
  // -------------------------------------------------------------------------
368
341
 
369
342
  // Spec: AIT-CD10
370
- private _decodeDelete(message: Ably.InboundMessage): DecoderOutput<TEvent, TMessage>[] {
343
+ private _decodeDelete(message: Ably.InboundMessage): TEvent[] {
371
344
  const serial = message.serial;
372
345
  if (!serial) return [];
373
346
 
@@ -396,7 +369,7 @@ class DefaultDecoderCore<TEvent, TMessage> implements DecoderCore<TEvent, TMessa
396
369
  * @param options - Decoder configuration (callbacks, logger).
397
370
  * @returns A new {@link DecoderCore} instance.
398
371
  */
399
- export const createDecoderCore = <TEvent, TMessage>(
400
- hooks: DecoderCoreHooks<TEvent, TMessage>,
372
+ export const createDecoderCore = <TEvent>(
373
+ hooks: DecoderCoreHooks<TEvent>,
401
374
  options: DecoderCoreOptions = {},
402
- ): DecoderCore<TEvent, TMessage> => new DefaultDecoderCore(hooks, options);
375
+ ): DecoderCore<TEvent> => new DefaultDecoderCore(hooks, options);