@ably/ai-transport 0.1.0 → 0.3.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.
- package/README.md +93 -111
- package/dist/ably-ai-transport.js +2401 -1387
- package/dist/ably-ai-transport.js.map +1 -1
- package/dist/ably-ai-transport.umd.cjs +1 -1
- package/dist/ably-ai-transport.umd.cjs.map +1 -1
- package/dist/constants.d.ts +116 -42
- package/dist/core/agent.d.ts +44 -0
- package/dist/core/channel-options.d.ts +57 -0
- package/dist/core/codec/codec-event.d.ts +9 -0
- package/dist/core/codec/decoder.d.ts +24 -24
- package/dist/core/codec/define-codec.d.ts +100 -0
- package/dist/core/codec/encoder.d.ts +10 -12
- package/dist/core/codec/field-bag.d.ts +85 -0
- package/dist/core/codec/fields.d.ts +141 -0
- package/dist/core/codec/index.d.ts +8 -2
- package/dist/core/codec/input-descriptor-decoder.d.ts +19 -0
- package/dist/core/codec/input-descriptor-encoder.d.ts +22 -0
- package/dist/core/codec/input-descriptors.d.ts +281 -0
- package/dist/core/codec/lifecycle-tracker.d.ts +10 -9
- package/dist/core/codec/output-descriptor-decoder.d.ts +29 -0
- package/dist/core/codec/output-descriptor-encoder.d.ts +31 -0
- package/dist/core/codec/output-descriptors.d.ts +237 -0
- package/dist/core/codec/types.d.ts +470 -119
- package/dist/core/codec/well-known-inputs.d.ts +52 -0
- package/dist/core/transport/agent-session.d.ts +10 -0
- package/dist/core/transport/agent-view.d.ts +296 -0
- package/dist/core/transport/client-session.d.ts +13 -0
- package/dist/core/transport/decode-fold.d.ts +55 -0
- package/dist/core/transport/headers.d.ts +121 -14
- package/dist/core/transport/index.d.ts +5 -6
- package/dist/core/transport/internal/bounded-map.d.ts +20 -0
- package/dist/core/transport/invocation.d.ts +74 -0
- package/dist/core/transport/load-history-pages.d.ts +71 -0
- package/dist/core/transport/load-history.d.ts +44 -0
- package/dist/core/transport/pipe-stream.d.ts +9 -9
- package/dist/core/transport/run-manager.d.ts +76 -0
- package/dist/core/transport/session-support.d.ts +55 -0
- package/dist/core/transport/tree.d.ts +523 -109
- package/dist/core/transport/types/agent.d.ts +375 -0
- package/dist/core/transport/types/client.d.ts +201 -0
- package/dist/core/transport/types/shared.d.ts +24 -0
- package/dist/core/transport/types/tree.d.ts +357 -0
- package/dist/core/transport/types/view.d.ts +249 -0
- package/dist/core/transport/types.d.ts +13 -553
- package/dist/core/transport/view.d.ts +390 -84
- package/dist/core/transport/wire-log.d.ts +102 -0
- package/dist/errors.d.ts +27 -10
- package/dist/index.d.ts +8 -9
- package/dist/logger.d.ts +12 -0
- package/dist/react/ably-ai-transport-react.js +1365 -1010
- package/dist/react/ably-ai-transport-react.js.map +1 -1
- package/dist/react/ably-ai-transport-react.umd.cjs +1 -1
- package/dist/react/ably-ai-transport-react.umd.cjs.map +1 -1
- package/dist/react/contexts/client-session-context.d.ts +37 -0
- package/dist/react/contexts/client-session-provider.d.ts +56 -0
- package/dist/react/create-session-hooks.d.ts +116 -0
- package/dist/react/index.d.ts +13 -12
- package/dist/react/internal/skipped-session.d.ts +8 -0
- package/dist/react/internal/use-resolved-session.d.ts +36 -0
- package/dist/react/use-ably-messages.d.ts +17 -14
- package/dist/react/use-client-session.d.ts +81 -0
- package/dist/react/use-create-view.d.ts +14 -13
- package/dist/react/use-tree.d.ts +30 -15
- package/dist/react/use-view.d.ts +81 -50
- package/dist/utils.d.ts +48 -71
- package/dist/vercel/ably-ai-transport-vercel.js +3257 -2499
- package/dist/vercel/ably-ai-transport-vercel.js.map +1 -1
- package/dist/vercel/ably-ai-transport-vercel.umd.cjs +1 -1
- package/dist/vercel/ably-ai-transport-vercel.umd.cjs.map +1 -1
- package/dist/vercel/codec/decode-lifecycle.d.ts +9 -0
- package/dist/vercel/codec/events.d.ts +50 -0
- package/dist/vercel/codec/fields.d.ts +44 -0
- package/dist/vercel/codec/fold-content.d.ts +16 -0
- package/dist/vercel/codec/fold-data.d.ts +16 -0
- package/dist/vercel/codec/fold-input.d.ts +67 -0
- package/dist/vercel/codec/fold-lifecycle.d.ts +16 -0
- package/dist/vercel/codec/fold-text.d.ts +16 -0
- package/dist/vercel/codec/fold-tool-input.d.ts +17 -0
- package/dist/vercel/codec/fold-tool-output.d.ts +16 -0
- package/dist/vercel/codec/index.d.ts +7 -20
- package/dist/vercel/codec/inputs.d.ts +11 -0
- package/dist/vercel/codec/outputs.d.ts +11 -0
- package/dist/vercel/codec/reducer-state.d.ts +121 -0
- package/dist/vercel/codec/reducer.d.ts +62 -0
- package/dist/vercel/codec/tool-transitions.d.ts +2 -8
- package/dist/vercel/codec/wire-data.d.ts +34 -0
- package/dist/vercel/index.d.ts +5 -5
- package/dist/vercel/react/ably-ai-transport-vercel-react.js +2859 -9705
- package/dist/vercel/react/ably-ai-transport-vercel-react.js.map +1 -1
- package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs +1 -45
- package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs.map +1 -1
- package/dist/vercel/react/contexts/chat-transport-context.d.ts +9 -7
- package/dist/vercel/react/contexts/chat-transport-provider.d.ts +53 -41
- package/dist/vercel/react/index.d.ts +1 -2
- package/dist/vercel/react/use-chat-transport.d.ts +30 -26
- package/dist/vercel/react/use-message-sync.d.ts +17 -30
- package/dist/vercel/run-end-reason.d.ts +84 -0
- package/dist/vercel/tool-part.d.ts +21 -0
- package/dist/vercel/transport/chat-transport.d.ts +41 -24
- package/dist/vercel/transport/index.d.ts +24 -20
- package/dist/vercel/transport/run-output-stream.d.ts +54 -0
- package/dist/version.d.ts +2 -0
- package/package.json +31 -24
- package/src/constants.ts +124 -51
- package/src/core/agent.ts +92 -0
- package/src/core/channel-options.ts +89 -0
- package/src/core/codec/codec-event.ts +27 -0
- package/src/core/codec/decoder.ts +202 -105
- package/src/core/codec/define-codec.ts +432 -0
- package/src/core/codec/encoder.ts +114 -107
- package/src/core/codec/field-bag.ts +142 -0
- package/src/core/codec/fields.ts +193 -0
- package/src/core/codec/index.ts +56 -6
- package/src/core/codec/input-descriptor-decoder.ts +97 -0
- package/src/core/codec/input-descriptor-encoder.ts +150 -0
- package/src/core/codec/input-descriptors.ts +373 -0
- package/src/core/codec/lifecycle-tracker.ts +10 -9
- package/src/core/codec/output-descriptor-decoder.ts +139 -0
- package/src/core/codec/output-descriptor-encoder.ts +101 -0
- package/src/core/codec/output-descriptors.ts +307 -0
- package/src/core/codec/types.ts +505 -126
- package/src/core/codec/well-known-inputs.ts +96 -0
- package/src/core/transport/agent-session.ts +1085 -0
- package/src/core/transport/agent-view.ts +738 -0
- package/src/core/transport/client-session.ts +780 -0
- package/src/core/transport/decode-fold.ts +101 -0
- package/src/core/transport/headers.ts +234 -22
- package/src/core/transport/index.ts +27 -27
- package/src/core/transport/internal/bounded-map.ts +27 -0
- package/src/core/transport/invocation.ts +98 -0
- package/src/core/transport/load-history-pages.ts +220 -0
- package/src/core/transport/load-history.ts +271 -0
- package/src/core/transport/pipe-stream.ts +63 -39
- package/src/core/transport/run-manager.ts +243 -0
- package/src/core/transport/session-support.ts +96 -0
- package/src/core/transport/tree.ts +1293 -308
- package/src/core/transport/types/agent.ts +434 -0
- package/src/core/transport/types/client.ts +247 -0
- package/src/core/transport/types/shared.ts +27 -0
- package/src/core/transport/types/tree.ts +393 -0
- package/src/core/transport/types/view.ts +288 -0
- package/src/core/transport/types.ts +13 -706
- package/src/core/transport/view.ts +1229 -450
- package/src/core/transport/wire-log.ts +189 -0
- package/src/errors.ts +29 -9
- package/src/event-emitter.ts +3 -2
- package/src/index.ts +86 -42
- package/src/logger.ts +14 -1
- package/src/react/contexts/client-session-context.ts +41 -0
- package/src/react/contexts/client-session-provider.tsx +222 -0
- package/src/react/create-session-hooks.ts +141 -0
- package/src/react/index.ts +24 -13
- package/src/react/internal/skipped-session.ts +62 -0
- package/src/react/internal/use-resolved-session.ts +63 -0
- package/src/react/use-ably-messages.ts +32 -22
- package/src/react/use-client-session.ts +178 -0
- package/src/react/use-create-view.ts +33 -29
- package/src/react/use-tree.ts +61 -30
- package/src/react/use-view.ts +138 -96
- package/src/utils.ts +83 -131
- package/src/vercel/codec/decode-lifecycle.ts +70 -0
- package/src/vercel/codec/events.ts +85 -0
- package/src/vercel/codec/fields.ts +58 -0
- package/src/vercel/codec/fold-content.ts +54 -0
- package/src/vercel/codec/fold-data.ts +46 -0
- package/src/vercel/codec/fold-input.ts +255 -0
- package/src/vercel/codec/fold-lifecycle.ts +85 -0
- package/src/vercel/codec/fold-text.ts +55 -0
- package/src/vercel/codec/fold-tool-input.ts +86 -0
- package/src/vercel/codec/fold-tool-output.ts +79 -0
- package/src/vercel/codec/index.ts +28 -21
- package/src/vercel/codec/inputs.ts +116 -0
- package/src/vercel/codec/outputs.ts +207 -0
- package/src/vercel/codec/reducer-state.ts +169 -0
- package/src/vercel/codec/reducer.ts +191 -0
- package/src/vercel/codec/tool-transitions.ts +3 -14
- package/src/vercel/codec/wire-data.ts +64 -0
- package/src/vercel/index.ts +7 -19
- package/src/vercel/react/contexts/chat-transport-context.ts +8 -7
- package/src/vercel/react/contexts/chat-transport-provider.tsx +87 -59
- package/src/vercel/react/index.ts +3 -5
- package/src/vercel/react/use-chat-transport.ts +44 -66
- package/src/vercel/react/use-message-sync.ts +75 -39
- package/src/vercel/run-end-reason.ts +157 -0
- package/src/vercel/tool-part.ts +25 -0
- package/src/vercel/transport/chat-transport.ts +380 -98
- package/src/vercel/transport/index.ts +38 -37
- package/src/vercel/transport/run-output-stream.ts +169 -0
- package/src/version.ts +2 -0
- package/dist/core/transport/client-transport.d.ts +0 -10
- package/dist/core/transport/decode-history.d.ts +0 -43
- package/dist/core/transport/server-transport.d.ts +0 -7
- package/dist/core/transport/stream-router.d.ts +0 -29
- package/dist/core/transport/turn-manager.d.ts +0 -37
- package/dist/react/contexts/transport-context.d.ts +0 -31
- package/dist/react/contexts/transport-provider.d.ts +0 -49
- package/dist/react/create-transport-hooks.d.ts +0 -124
- package/dist/react/use-active-turns.d.ts +0 -12
- package/dist/react/use-client-transport.d.ts +0 -80
- package/dist/vercel/codec/accumulator.d.ts +0 -21
- package/dist/vercel/codec/decoder.d.ts +0 -22
- package/dist/vercel/codec/encoder.d.ts +0 -41
- package/dist/vercel/react/use-staged-add-tool-approval-response.d.ts +0 -30
- package/dist/vercel/tool-approvals.d.ts +0 -124
- package/dist/vercel/tool-events.d.ts +0 -26
- package/src/core/transport/client-transport.ts +0 -977
- package/src/core/transport/decode-history.ts +0 -485
- package/src/core/transport/server-transport.ts +0 -612
- package/src/core/transport/stream-router.ts +0 -136
- package/src/core/transport/turn-manager.ts +0 -165
- package/src/react/contexts/transport-context.ts +0 -37
- package/src/react/contexts/transport-provider.tsx +0 -164
- package/src/react/create-transport-hooks.ts +0 -144
- package/src/react/use-active-turns.ts +0 -72
- package/src/react/use-client-transport.ts +0 -197
- package/src/vercel/codec/accumulator.ts +0 -588
- package/src/vercel/codec/decoder.ts +0 -618
- package/src/vercel/codec/encoder.ts +0 -410
- package/src/vercel/react/use-staged-add-tool-approval-response.ts +0 -87
- package/src/vercel/tool-approvals.ts +0 -380
- package/src/vercel/tool-events.ts +0 -53
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-node event log.
|
|
3
|
+
*
|
|
4
|
+
* Each node retains the decoded events it was folded from, grouped by
|
|
5
|
+
* wire-message serial and ordered ascending by serial. The log captures
|
|
6
|
+
* canonical serial order regardless of delivery order, so a node's event
|
|
7
|
+
* sequence can be re-derived in that order even when wires arrive late
|
|
8
|
+
* (cross-publisher reordering) or out of order (history pages applying older
|
|
9
|
+
* messages after newer ones).
|
|
10
|
+
*
|
|
11
|
+
* Within one serial, deliveries are sequenced by `Message.version.serial`
|
|
12
|
+
* (lexicographically ordered per mutation — platform guarantee): each entry
|
|
13
|
+
* records the highest version decoded into it, so a delivery the entry has
|
|
14
|
+
* already incorporated — a whole-wire replay from a second hydration, a
|
|
15
|
+
* remount, or an agent re-walk — is recognised and dropped at the transport.
|
|
16
|
+
*
|
|
17
|
+
* {@link WireLog} encapsulates the entry list and all of its mutation: the
|
|
18
|
+
* caller hands it a wire and is told only how to fold (see {@link WireLogFold}).
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** One wire message in a node's event log: a serial and its decoded events. */
|
|
22
|
+
interface WireLogEntry<TEvent> {
|
|
23
|
+
/** Ably channel serial of the wire message. */
|
|
24
|
+
serial: string;
|
|
25
|
+
/**
|
|
26
|
+
* The wire's codec-message-id — the reducer routing key the events were
|
|
27
|
+
* folded alongside; undefined when the wire carried none.
|
|
28
|
+
*/
|
|
29
|
+
messageId: string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* The decoded events from this wire message's deliveries, in arrival order.
|
|
32
|
+
* Same-serial deliveries (the create plus each append/update) extend the
|
|
33
|
+
* entry, so the list accumulates across deliveries.
|
|
34
|
+
*/
|
|
35
|
+
events: TEvent[];
|
|
36
|
+
/**
|
|
37
|
+
* The highest `Message.version.serial` decoded into this entry. Versions
|
|
38
|
+
* are lexicographically comparable within one serial, so a delivery at or
|
|
39
|
+
* below this value is already incorporated and must not fold again. In
|
|
40
|
+
* practice every delivery carries a version (a never-mutated message's
|
|
41
|
+
* version serial equals its serial); the message serial is used as the floor
|
|
42
|
+
* only as a defensive fallback for the type-optional absent case.
|
|
43
|
+
*/
|
|
44
|
+
decodedThrough: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** How a {@link WireLog.record} call tells the caller to fold the wire's events. */
|
|
48
|
+
export type WireLogFold =
|
|
49
|
+
/**
|
|
50
|
+
* The version guard rejected a re-delivery the log already incorporated — a
|
|
51
|
+
* whole-wire replay, or a newer version of a non-streamed wire (an edited
|
|
52
|
+
* discrete). Nothing was recorded; fold nothing.
|
|
53
|
+
*/
|
|
54
|
+
| 'dropped'
|
|
55
|
+
/**
|
|
56
|
+
* The events extend the log tail (in-order delivery) or landed on a swept
|
|
57
|
+
* log; fold them onto the node's existing projection.
|
|
58
|
+
*/
|
|
59
|
+
| 'incremental'
|
|
60
|
+
/**
|
|
61
|
+
* An earlier-serial wire arrived late, so incremental folding would corrupt
|
|
62
|
+
* serial order; rebuild the projection from the whole log via {@link replay}.
|
|
63
|
+
*/
|
|
64
|
+
| 'refold';
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A node's event log: one entry per wire-message serial, kept ascending by
|
|
68
|
+
* serial, each accumulating that serial's decoded events in arrival order.
|
|
69
|
+
*/
|
|
70
|
+
export class WireLog<TEvent> {
|
|
71
|
+
private readonly _entries: WireLogEntry<TEvent>[] = [];
|
|
72
|
+
private _swept = false;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Whether the retention sweep has dropped this log's decoded payloads. A
|
|
76
|
+
* swept log keeps each entry's replay key (serial + `decodedThrough`) so it
|
|
77
|
+
* still recognises whole-wire replays, but it can no longer be refolded.
|
|
78
|
+
* @returns True once {@link sweep} has run.
|
|
79
|
+
*/
|
|
80
|
+
get swept(): boolean {
|
|
81
|
+
return this._swept;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Record a wire message's decoded events and report how to fold them.
|
|
86
|
+
*
|
|
87
|
+
* Events for an already-logged serial are guarded by the entry's
|
|
88
|
+
* `decodedThrough` version before being recorded; a new serial is inserted
|
|
89
|
+
* at the position that keeps the log ascending by serial (Ably serials order
|
|
90
|
+
* lexicographically). The version guard fires only for deliveries carrying
|
|
91
|
+
* an explicit `version.serial`: in-contract mutations always do, while a
|
|
92
|
+
* version-less delivery records unguarded (and never advances
|
|
93
|
+
* `decodedThrough`), matching the decoder's convention.
|
|
94
|
+
*
|
|
95
|
+
* On a swept log the payload is not retained (only the replay key is), so
|
|
96
|
+
* the fold is never `refold` — a genuinely-new wire there is outside the
|
|
97
|
+
* reorder window and folds incrementally in arrival order.
|
|
98
|
+
* @param serial - The Ably channel serial of the wire message.
|
|
99
|
+
* @param messageId - The wire's codec-message-id, or undefined.
|
|
100
|
+
* @param events - The decoded events to record, in arrival order.
|
|
101
|
+
* @param version - The delivery's `Message.version.serial`, or undefined
|
|
102
|
+
* when the delivery carried none (guard disabled for this delivery).
|
|
103
|
+
* @param streamed - Whether the delivery is part of a streamed wire; a
|
|
104
|
+
* guarded newer delivery for a non-streamed wire is an edited discrete and
|
|
105
|
+
* is dropped.
|
|
106
|
+
* @returns How the caller should fold the events.
|
|
107
|
+
*/
|
|
108
|
+
record(
|
|
109
|
+
serial: string,
|
|
110
|
+
messageId: string | undefined,
|
|
111
|
+
events: TEvent[],
|
|
112
|
+
version: string | undefined,
|
|
113
|
+
streamed: boolean,
|
|
114
|
+
): WireLogFold {
|
|
115
|
+
// A swept log retains replay keys but not payloads: record an empty event
|
|
116
|
+
// list so the key advances while nothing is stored. The caller folds the
|
|
117
|
+
// events it already holds.
|
|
118
|
+
const index = this._recordEntry(serial, messageId, this._swept ? [] : events, version, streamed);
|
|
119
|
+
if (index === undefined) return 'dropped';
|
|
120
|
+
if (this._swept) return 'incremental';
|
|
121
|
+
return index === this._entries.length - 1 ? 'incremental' : 'refold';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Replay every recorded event in canonical order — wire messages ascending
|
|
126
|
+
* by serial, events within a wire in arrival order — each with its wire's
|
|
127
|
+
* routing metadata, for a refold.
|
|
128
|
+
* @param visit - Called once per event, in canonical order.
|
|
129
|
+
*/
|
|
130
|
+
replay(visit: (event: TEvent, serial: string, messageId: string | undefined) => void): void {
|
|
131
|
+
for (const entry of this._entries) {
|
|
132
|
+
for (const event of entry.events) visit(event, entry.serial, entry.messageId);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Drop the decoded payloads (the unbounded cost) but keep each entry's
|
|
138
|
+
* replay key, so a post-sweep whole-wire replay is still recognised and
|
|
139
|
+
* dropped rather than re-folded. The log becomes {@link swept}; a refold can
|
|
140
|
+
* no longer rebuild the dropped events, which `swept` reflects.
|
|
141
|
+
*/
|
|
142
|
+
sweep(): void {
|
|
143
|
+
this._swept = true;
|
|
144
|
+
for (const entry of this._entries) entry.events.length = 0;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Insert or extend the entry for `serial`, guarding replays by version.
|
|
149
|
+
* @param serial - The Ably channel serial of the wire message.
|
|
150
|
+
* @param messageId - The wire's codec-message-id, or undefined.
|
|
151
|
+
* @param events - The decoded events to store (empty on a swept log).
|
|
152
|
+
* @param version - The delivery's `Message.version.serial`, or undefined.
|
|
153
|
+
* @param streamed - Whether the delivery is part of a streamed wire.
|
|
154
|
+
* @returns The index of the entry the events landed in, or `undefined` when
|
|
155
|
+
* the version guard dropped the delivery.
|
|
156
|
+
*/
|
|
157
|
+
private _recordEntry(
|
|
158
|
+
serial: string,
|
|
159
|
+
messageId: string | undefined,
|
|
160
|
+
events: TEvent[],
|
|
161
|
+
version: string | undefined,
|
|
162
|
+
streamed: boolean,
|
|
163
|
+
): number | undefined {
|
|
164
|
+
// Scan from the tail: live delivery appends at (or extends) the end, so the
|
|
165
|
+
// match is almost always within the last entry or two.
|
|
166
|
+
for (let i = this._entries.length - 1; i >= 0; i--) {
|
|
167
|
+
const entry = this._entries[i];
|
|
168
|
+
if (!entry) break; // unreachable
|
|
169
|
+
if (entry.serial === serial) {
|
|
170
|
+
// Version guard: drop a re-delivery the entry already incorporated — a
|
|
171
|
+
// replay (version at or below the high-water-mark) or an edit to a
|
|
172
|
+
// discrete (a newer version of a non-streamed wire, not propagated).
|
|
173
|
+
if (version !== undefined && (version <= entry.decodedThrough || !streamed)) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
entry.events.push(...events);
|
|
177
|
+
if (version !== undefined) entry.decodedThrough = version;
|
|
178
|
+
return i;
|
|
179
|
+
}
|
|
180
|
+
if (entry.serial < serial) {
|
|
181
|
+
this._entries.splice(i + 1, 0, { serial, messageId, events: [...events], decodedThrough: version ?? serial });
|
|
182
|
+
return i + 1;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Lower than every logged serial (or the log is empty): insert at the head.
|
|
186
|
+
this._entries.unshift({ serial, messageId, events: [...events], decodedThrough: version ?? serial });
|
|
187
|
+
return 0;
|
|
188
|
+
}
|
|
189
|
+
}
|
package/src/errors.ts
CHANGED
|
@@ -14,18 +14,24 @@ export enum ErrorCode {
|
|
|
14
14
|
*/
|
|
15
15
|
InvalidArgument = 40003,
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Operation not permitted with the provided capability (Ably 40160).
|
|
19
|
+
* Used when the Ably channel rejects a publish for a capability reason.
|
|
20
|
+
*/
|
|
21
|
+
InsufficientCapability = 40160,
|
|
22
|
+
|
|
17
23
|
// 104000 - 104999 are reserved for AI Transport SDK errors
|
|
18
24
|
|
|
19
25
|
/**
|
|
20
|
-
* Encoder recovery failed
|
|
26
|
+
* Encoder recovery failed during flush — one or more updateMessage calls
|
|
21
27
|
* could not recover a failed append pipeline.
|
|
22
28
|
*/
|
|
23
29
|
EncoderRecoveryFailed = 104000,
|
|
24
30
|
|
|
25
31
|
/**
|
|
26
|
-
* A
|
|
32
|
+
* A session-level channel subscription callback threw unexpectedly.
|
|
27
33
|
*/
|
|
28
|
-
|
|
34
|
+
SessionSubscriptionError = 104001,
|
|
29
35
|
|
|
30
36
|
/**
|
|
31
37
|
* Cancel listener or onCancel hook threw while processing a cancel message.
|
|
@@ -33,19 +39,19 @@ export enum ErrorCode {
|
|
|
33
39
|
CancelListenerError = 104002,
|
|
34
40
|
|
|
35
41
|
/**
|
|
36
|
-
* A publish within a
|
|
42
|
+
* A publish within a run failed (lifecycle event, message, or event).
|
|
37
43
|
*/
|
|
38
|
-
|
|
44
|
+
RunLifecycleError = 104003,
|
|
39
45
|
|
|
40
46
|
/**
|
|
41
|
-
* An operation was attempted on a
|
|
47
|
+
* An operation was attempted on a session that has already been closed.
|
|
42
48
|
*/
|
|
43
|
-
|
|
49
|
+
SessionClosed = 104004,
|
|
44
50
|
|
|
45
51
|
/**
|
|
46
|
-
* The HTTP POST to the
|
|
52
|
+
* The HTTP POST to the agent endpoint failed (network error or non-2xx response).
|
|
47
53
|
*/
|
|
48
|
-
|
|
54
|
+
SessionSendFailed = 104005,
|
|
49
55
|
|
|
50
56
|
/**
|
|
51
57
|
* The Ably channel lost message continuity — the channel entered FAILED,
|
|
@@ -66,6 +72,20 @@ export enum ErrorCode {
|
|
|
66
72
|
* network failure) or an underlying publish failed mid-stream.
|
|
67
73
|
*/
|
|
68
74
|
StreamError = 104008,
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The agent waited for the input event(s) the invocation points at —
|
|
78
|
+
* across the bounded history scan and the live subscription — but
|
|
79
|
+
* `inputEventLookupTimeoutMs` lapsed without seeing them.
|
|
80
|
+
*/
|
|
81
|
+
InputEventNotFound = 104010,
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Channel history pagination failed after bounded retry — either the initial
|
|
85
|
+
* `channel.history()` call or a subsequent `page.next()` exhausted its
|
|
86
|
+
* retry budget. The original failure is preserved as `cause`.
|
|
87
|
+
*/
|
|
88
|
+
HistoryFetchFailed = 104011,
|
|
69
89
|
}
|
|
70
90
|
|
|
71
91
|
/**
|
package/src/event-emitter.ts
CHANGED
|
@@ -76,8 +76,9 @@ const toAblyLogger = (logger: Logger): unknown => ({
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
// CAST: Access Ably's internal EventEmitter constructor. Not publicly exported
|
|
79
|
-
// but available to other Ably SDKs.
|
|
80
|
-
//
|
|
79
|
+
// but available to other Ably SDKs. Ably always catches listener exceptions
|
|
80
|
+
// internally; the logger parameter ensures those caught exceptions are logged
|
|
81
|
+
// rather than silently swallowed.
|
|
81
82
|
const InternalEventEmitter: new <EventsMap>(logger: unknown) => InterfaceEventEmitter<EventsMap> = (
|
|
82
83
|
Ably.Realtime as unknown as { EventEmitter: new <EventsMap>(logger: unknown) => InterfaceEventEmitter<EventsMap> }
|
|
83
84
|
).EventEmitter;
|
package/src/index.ts
CHANGED
|
@@ -1,87 +1,131 @@
|
|
|
1
1
|
// Core transport
|
|
2
2
|
export type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
ActiveRun,
|
|
4
|
+
AgentSession,
|
|
5
|
+
AgentSessionOptions,
|
|
6
|
+
BranchSelection,
|
|
7
7
|
CancelRequest,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
ClientSession,
|
|
9
|
+
ClientSessionOptions,
|
|
10
|
+
ConversationNode,
|
|
11
|
+
InputNode,
|
|
12
|
+
InvocationData,
|
|
13
|
+
LoadConversationOptions,
|
|
12
14
|
MessageNode,
|
|
13
|
-
|
|
15
|
+
OutputEvent,
|
|
16
|
+
PipeOptions,
|
|
17
|
+
Run,
|
|
18
|
+
RunEndParams,
|
|
19
|
+
RunEndReason,
|
|
20
|
+
RunInfo,
|
|
21
|
+
RunLifecycleEvent,
|
|
22
|
+
RunNode,
|
|
23
|
+
RunNodeState,
|
|
24
|
+
RunRuntime,
|
|
25
|
+
RunView,
|
|
14
26
|
SendOptions,
|
|
15
|
-
ServerTransport,
|
|
16
|
-
ServerTransportOptions,
|
|
17
|
-
StreamResponseOptions,
|
|
18
27
|
StreamResult,
|
|
19
28
|
Tree,
|
|
20
|
-
Turn,
|
|
21
|
-
TurnEndReason,
|
|
22
|
-
TurnLifecycleEvent,
|
|
23
29
|
View,
|
|
24
30
|
} from './core/transport/index.js';
|
|
31
|
+
export { buildTransportHeaders, createAgentSession, createClientSession, Invocation } from './core/transport/index.js';
|
|
25
32
|
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
export type { EventNode } from './core/transport/index.js';
|
|
29
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
30
|
-
export type { TreeNode } from './core/transport/index.js';
|
|
31
|
-
export { buildTransportHeaders, createClientTransport, createServerTransport } from './core/transport/index.js';
|
|
33
|
+
// Channel modes
|
|
34
|
+
export { OBJECT_MODES } from './core/channel-options.js';
|
|
32
35
|
|
|
33
36
|
// Core codec
|
|
34
37
|
export type {
|
|
38
|
+
BatchAssembleContext,
|
|
39
|
+
BatchMessageHeaders,
|
|
40
|
+
BatchSpec,
|
|
35
41
|
ChannelWriter,
|
|
36
42
|
Codec,
|
|
43
|
+
CodecEvent,
|
|
44
|
+
CodecInputEvent,
|
|
45
|
+
CodecMessage,
|
|
46
|
+
CodecOutputEvent,
|
|
47
|
+
CodecReducer,
|
|
48
|
+
DataCodec,
|
|
49
|
+
DecodedMessage,
|
|
50
|
+
Decoder,
|
|
37
51
|
DecoderCore,
|
|
38
52
|
DecoderCoreHooks,
|
|
39
53
|
DecoderCoreOptions,
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
DefineCodecConfig,
|
|
55
|
+
DefinedCodec,
|
|
56
|
+
Encoder,
|
|
42
57
|
EncoderCore,
|
|
43
58
|
EncoderCoreOptions,
|
|
44
59
|
EncoderOptions,
|
|
60
|
+
EscapeHatchCore,
|
|
45
61
|
Extras,
|
|
62
|
+
FieldFor,
|
|
63
|
+
HeaderBuilder,
|
|
64
|
+
HeaderField,
|
|
65
|
+
InputBuilder,
|
|
66
|
+
InputDescriptor,
|
|
67
|
+
InputEventSpec,
|
|
68
|
+
LifecycleDiscreteContext,
|
|
69
|
+
LifecyclePolicy,
|
|
46
70
|
LifecycleTracker,
|
|
47
|
-
MessageAccumulator,
|
|
48
71
|
MessagePayload,
|
|
72
|
+
OutputBuilder,
|
|
73
|
+
OutputDecodeContext,
|
|
74
|
+
OutputDescriptor,
|
|
75
|
+
OutputEncodeHatchContext,
|
|
76
|
+
OutputEventSpec,
|
|
77
|
+
OutputStreamEndContext,
|
|
78
|
+
OutputStreamSpec,
|
|
79
|
+
PartBuilder,
|
|
80
|
+
PartSpec,
|
|
49
81
|
PhaseConfig,
|
|
50
|
-
|
|
51
|
-
|
|
82
|
+
Reducer,
|
|
83
|
+
ReducerMeta,
|
|
84
|
+
Regenerate,
|
|
52
85
|
StreamPayload,
|
|
53
86
|
StreamTrackerState,
|
|
87
|
+
ToolApprovalResponse,
|
|
88
|
+
ToolResult,
|
|
89
|
+
ToolResultError,
|
|
90
|
+
UserMessage,
|
|
91
|
+
WellKnownInputFactories,
|
|
54
92
|
WriteOptions,
|
|
55
93
|
} from './core/codec/index.js';
|
|
56
|
-
export {
|
|
94
|
+
export {
|
|
95
|
+
boolField,
|
|
96
|
+
createDecoderCore,
|
|
97
|
+
createEncoderCore,
|
|
98
|
+
createLifecycleTracker,
|
|
99
|
+
defineCodec,
|
|
100
|
+
enumField,
|
|
101
|
+
jsonField,
|
|
102
|
+
strField,
|
|
103
|
+
} from './core/codec/index.js';
|
|
57
104
|
|
|
58
105
|
// Constants
|
|
59
106
|
export {
|
|
60
|
-
DOMAIN_HEADER_PREFIX,
|
|
61
|
-
EVENT_ABORT,
|
|
62
107
|
EVENT_CANCEL,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
HEADER_CANCEL_OWN,
|
|
69
|
-
HEADER_CANCEL_TURN_ID,
|
|
108
|
+
EVENT_RUN_END,
|
|
109
|
+
EVENT_RUN_START,
|
|
110
|
+
HEADER_CODEC_MESSAGE_ID,
|
|
111
|
+
HEADER_ERROR_CODE,
|
|
112
|
+
HEADER_ERROR_MESSAGE,
|
|
70
113
|
HEADER_FORK_OF,
|
|
71
|
-
|
|
114
|
+
HEADER_INPUT_CLIENT_ID,
|
|
115
|
+
HEADER_MSG_REGENERATE,
|
|
72
116
|
HEADER_PARENT,
|
|
73
117
|
HEADER_ROLE,
|
|
118
|
+
HEADER_RUN_CLIENT_ID,
|
|
119
|
+
HEADER_RUN_ID,
|
|
120
|
+
HEADER_RUN_REASON,
|
|
74
121
|
HEADER_STATUS,
|
|
75
122
|
HEADER_STREAM,
|
|
76
123
|
HEADER_STREAM_ID,
|
|
77
|
-
HEADER_TURN_CLIENT_ID,
|
|
78
|
-
HEADER_TURN_ID,
|
|
79
|
-
HEADER_TURN_REASON,
|
|
80
124
|
} from './constants.js';
|
|
81
125
|
|
|
82
126
|
// Utilities
|
|
83
|
-
export type {
|
|
84
|
-
export {
|
|
127
|
+
export type { Stripped } from './utils.js';
|
|
128
|
+
export { getCodecHeaders, getTransportHeaders, mergeHeaders, stripUndefined } from './utils.js';
|
|
85
129
|
|
|
86
130
|
// Event emitter
|
|
87
131
|
export { EventEmitter } from './event-emitter.js';
|
package/src/logger.ts
CHANGED
|
@@ -143,10 +143,22 @@ export const consoleLogger = (message: string, level: LogLevel, context?: LogCon
|
|
|
143
143
|
* Options for creating a logger.
|
|
144
144
|
*/
|
|
145
145
|
export interface LoggerOptions {
|
|
146
|
+
/**
|
|
147
|
+
* The handler that receives formatted log messages. Defaults to {@link consoleLogger} when omitted.
|
|
148
|
+
*/
|
|
146
149
|
logHandler?: LogHandler;
|
|
150
|
+
/**
|
|
151
|
+
* The minimum level to emit; messages below this level are suppressed. Must be a valid {@link LogLevel}, otherwise logger creation throws.
|
|
152
|
+
*/
|
|
147
153
|
logLevel: LogLevel;
|
|
148
154
|
}
|
|
149
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Creates a {@link Logger} from the given options.
|
|
158
|
+
* @param options The handler and minimum level for the logger.
|
|
159
|
+
* @returns A logger that filters by level and delegates to the handler.
|
|
160
|
+
* @throws {@link Ably.ErrorInfo} with {@link ErrorCode.InvalidArgument} if `options.logLevel` is not a recognised {@link LogLevel}.
|
|
161
|
+
*/
|
|
150
162
|
export const makeLogger = (options: LoggerOptions): Logger => {
|
|
151
163
|
const logHandler = options.logHandler ?? consoleLogger;
|
|
152
164
|
|
|
@@ -218,7 +230,8 @@ class DefaultLogger implements Logger {
|
|
|
218
230
|
}
|
|
219
231
|
|
|
220
232
|
withContext(context: LogContext): Logger {
|
|
221
|
-
// Get the original log level by finding the key in logLevelNumberMap that matches this._levelNumber
|
|
233
|
+
// Get the original log level by finding the key in logLevelNumberMap that matches this._levelNumber.
|
|
234
|
+
// The Error fallback is defensive and unreachable in practice: _levelNumber always originates from the map.
|
|
222
235
|
const originalLevel =
|
|
223
236
|
[...logLevelNumberMap.entries()].find(([, value]) => value === this._levelNumber)?.[0] ?? LogLevel.Error;
|
|
224
237
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type * as Ably from 'ably';
|
|
2
|
+
import { createContext } from 'react';
|
|
3
|
+
|
|
4
|
+
import type { CodecInputEvent, CodecOutputEvent } from '../../core/codec/types.js';
|
|
5
|
+
import type { ClientSession } from '../../core/transport/types.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A single entry in the client-session registry, holding the session and any
|
|
9
|
+
* error that occurred during its construction.
|
|
10
|
+
*
|
|
11
|
+
* `session` is `undefined` when construction failed.
|
|
12
|
+
* `sessionError` is set when `createClientSession` threw during provider render.
|
|
13
|
+
*/
|
|
14
|
+
export interface ClientSessionSlot {
|
|
15
|
+
/** The constructed session, or `undefined` if construction failed. */
|
|
16
|
+
session: ClientSession<CodecInputEvent, CodecOutputEvent, unknown, unknown> | undefined;
|
|
17
|
+
/** Construction error from `createClientSession`, or `undefined` on success. */
|
|
18
|
+
sessionError?: Ably.ErrorInfo | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The shape of the {@link ClientSessionContext} value.
|
|
23
|
+
*
|
|
24
|
+
* `nearest` is the slot from the innermost enclosing {@link ClientSessionProvider}.
|
|
25
|
+
* `providers` is the full registry of all enclosing providers, keyed by channelName.
|
|
26
|
+
*/
|
|
27
|
+
interface ClientSessionContextValue {
|
|
28
|
+
/** The innermost {@link ClientSessionProvider}'s slot. `undefined` when no provider is present. */
|
|
29
|
+
nearest: ClientSessionSlot | undefined;
|
|
30
|
+
/** All registered session slots from enclosing providers, keyed by channelName. */
|
|
31
|
+
providers: Readonly<Record<string, ClientSessionSlot>>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Unified client-session context.
|
|
36
|
+
*
|
|
37
|
+
* Holds the nearest client-session slot and the full registry of all registered
|
|
38
|
+
* slots keyed by channelName. Populated by {@link ClientSessionProvider};
|
|
39
|
+
* read by {@link useClientSession} and internal hooks.
|
|
40
|
+
*/
|
|
41
|
+
export const ClientSessionContext = createContext<ClientSessionContextValue>({ nearest: undefined, providers: {} });
|