@ably/ai-transport 0.0.1 → 0.1.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 (110) hide show
  1. package/README.md +54 -47
  2. package/dist/ably-ai-transport.js +1006 -539
  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 +4 -0
  7. package/dist/core/codec/types.d.ts +19 -2
  8. package/dist/core/transport/decode-history.d.ts +8 -6
  9. package/dist/core/transport/headers.d.ts +4 -2
  10. package/dist/core/transport/index.d.ts +4 -1
  11. package/dist/core/transport/pipe-stream.d.ts +3 -2
  12. package/dist/core/transport/stream-router.d.ts +11 -1
  13. package/dist/core/transport/tree.d.ts +171 -0
  14. package/dist/core/transport/turn-manager.d.ts +4 -1
  15. package/dist/core/transport/types.d.ts +270 -119
  16. package/dist/core/transport/view.d.ts +166 -0
  17. package/dist/errors.d.ts +19 -2
  18. package/dist/index.d.ts +3 -1
  19. package/dist/react/ably-ai-transport-react.js +1019 -486
  20. package/dist/react/ably-ai-transport-react.js.map +1 -1
  21. package/dist/react/ably-ai-transport-react.umd.cjs +1 -1
  22. package/dist/react/ably-ai-transport-react.umd.cjs.map +1 -1
  23. package/dist/react/contexts/transport-context.d.ts +31 -0
  24. package/dist/react/contexts/transport-provider.d.ts +49 -0
  25. package/dist/react/create-transport-hooks.d.ts +124 -0
  26. package/dist/react/index.d.ts +14 -8
  27. package/dist/react/use-ably-messages.d.ts +14 -8
  28. package/dist/react/use-active-turns.d.ts +7 -3
  29. package/dist/react/use-client-transport.d.ts +78 -5
  30. package/dist/react/use-create-view.d.ts +22 -0
  31. package/dist/react/use-tree.d.ts +20 -0
  32. package/dist/react/use-view.d.ts +79 -0
  33. package/dist/vercel/ably-ai-transport-vercel.js +1478 -842
  34. package/dist/vercel/ably-ai-transport-vercel.js.map +1 -1
  35. package/dist/vercel/ably-ai-transport-vercel.umd.cjs +1 -1
  36. package/dist/vercel/ably-ai-transport-vercel.umd.cjs.map +1 -1
  37. package/dist/vercel/codec/tool-transitions.d.ts +50 -0
  38. package/dist/vercel/index.d.ts +3 -0
  39. package/dist/vercel/react/ably-ai-transport-vercel-react.js +9099 -852
  40. package/dist/vercel/react/ably-ai-transport-vercel-react.js.map +1 -1
  41. package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs +45 -1
  42. package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs.map +1 -1
  43. package/dist/vercel/react/contexts/chat-transport-context.d.ts +32 -0
  44. package/dist/vercel/react/contexts/chat-transport-provider.d.ts +84 -0
  45. package/dist/vercel/react/index.d.ts +5 -0
  46. package/dist/vercel/react/use-chat-transport.d.ts +61 -20
  47. package/dist/vercel/react/use-message-sync.d.ts +41 -9
  48. package/dist/vercel/react/use-staged-add-tool-approval-response.d.ts +30 -0
  49. package/dist/vercel/tool-approvals.d.ts +124 -0
  50. package/dist/vercel/tool-events.d.ts +26 -0
  51. package/dist/vercel/transport/chat-transport.d.ts +33 -11
  52. package/dist/vercel/transport/index.d.ts +5 -2
  53. package/package.json +23 -17
  54. package/src/constants.ts +6 -0
  55. package/src/core/codec/encoder.ts +10 -1
  56. package/src/core/codec/types.ts +19 -3
  57. package/src/core/transport/client-transport.ts +382 -364
  58. package/src/core/transport/decode-history.ts +229 -81
  59. package/src/core/transport/headers.ts +6 -2
  60. package/src/core/transport/index.ts +13 -5
  61. package/src/core/transport/pipe-stream.ts +8 -5
  62. package/src/core/transport/server-transport.ts +212 -58
  63. package/src/core/transport/stream-router.ts +21 -3
  64. package/src/core/transport/{conversation-tree.ts → tree.ts} +192 -77
  65. package/src/core/transport/turn-manager.ts +28 -10
  66. package/src/core/transport/types.ts +318 -139
  67. package/src/core/transport/view.ts +840 -0
  68. package/src/errors.ts +21 -1
  69. package/src/index.ts +10 -5
  70. package/src/react/contexts/transport-context.ts +37 -0
  71. package/src/react/contexts/transport-provider.tsx +164 -0
  72. package/src/react/create-transport-hooks.ts +144 -0
  73. package/src/react/index.ts +15 -8
  74. package/src/react/use-ably-messages.ts +34 -16
  75. package/src/react/use-active-turns.ts +28 -17
  76. package/src/react/use-client-transport.ts +184 -24
  77. package/src/react/use-create-view.ts +68 -0
  78. package/src/react/use-tree.ts +53 -0
  79. package/src/react/use-view.ts +233 -0
  80. package/src/react/vite.config.ts +4 -1
  81. package/src/vercel/codec/accumulator.ts +64 -79
  82. package/src/vercel/codec/decoder.ts +11 -8
  83. package/src/vercel/codec/encoder.ts +68 -54
  84. package/src/vercel/codec/index.ts +0 -2
  85. package/src/vercel/codec/tool-transitions.ts +122 -0
  86. package/src/vercel/index.ts +17 -0
  87. package/src/vercel/react/contexts/chat-transport-context.ts +40 -0
  88. package/src/vercel/react/contexts/chat-transport-provider.tsx +122 -0
  89. package/src/vercel/react/index.ts +14 -0
  90. package/src/vercel/react/use-chat-transport.ts +164 -42
  91. package/src/vercel/react/use-message-sync.ts +77 -19
  92. package/src/vercel/react/use-staged-add-tool-approval-response.ts +87 -0
  93. package/src/vercel/react/vite.config.ts +4 -2
  94. package/src/vercel/tool-approvals.ts +380 -0
  95. package/src/vercel/tool-events.ts +53 -0
  96. package/src/vercel/transport/chat-transport.ts +225 -79
  97. package/src/vercel/transport/index.ts +14 -3
  98. package/dist/core/transport/conversation-tree.d.ts +0 -9
  99. package/dist/react/use-conversation-tree.d.ts +0 -20
  100. package/dist/react/use-edit.d.ts +0 -7
  101. package/dist/react/use-history.d.ts +0 -19
  102. package/dist/react/use-messages.d.ts +0 -7
  103. package/dist/react/use-regenerate.d.ts +0 -7
  104. package/dist/react/use-send.d.ts +0 -7
  105. package/src/react/use-conversation-tree.ts +0 -71
  106. package/src/react/use-edit.ts +0 -24
  107. package/src/react/use-history.ts +0 -111
  108. package/src/react/use-messages.ts +0 -32
  109. package/src/react/use-regenerate.ts +0 -24
  110. package/src/react/use-send.ts +0 -25
@@ -0,0 +1,166 @@
1
+ import { Logger } from '../../logger.js';
2
+ import { Codec } from '../codec/types.js';
3
+ import { TreeInternal } from './tree.js';
4
+ import { ActiveTurn, EventsNode, MessageNode, SendOptions, TurnLifecycleEvent, View } from './types.js';
5
+ /**
6
+ * DefaultView — a paginated, branch-aware projection over the Tree.
7
+ *
8
+ * Wraps a Tree and manages a pagination window that controls which nodes
9
+ * are visible to the UI. New live messages appear immediately; older messages
10
+ * are revealed progressively via `loadOlder()`.
11
+ *
12
+ * Each View owns its own branch selection state and pagination window,
13
+ * allowing multiple independent Views over the same Tree.
14
+ *
15
+ * Events are scoped to the visible window — 'update' only fires when the
16
+ * visible output changes, 'ably-message' only for messages corresponding to
17
+ * visible nodes, and 'turn' only for turns with visible messages.
18
+ */
19
+ import * as Ably from 'ably';
20
+ /**
21
+ * Internal delegate function provided by the transport for executing sends.
22
+ * The View pre-computes the visible branch history and passes it directly,
23
+ * so the delegate has no back-reference to the View.
24
+ * When `eventNodes` is provided, the transport includes them in the POST body
25
+ * for the server to publish as cross-turn events.
26
+ */
27
+ export type SendDelegate<TEvent, TMessage> = (input: TMessage | TMessage[], options: SendOptions | undefined, history: MessageNode<TMessage>[], eventNodes?: EventsNode<TEvent>[]) => Promise<ActiveTurn<TEvent>>;
28
+ /** Options for creating a View. */
29
+ export interface ViewOptions<TEvent, TMessage> {
30
+ /** The tree to project. */
31
+ tree: TreeInternal<TMessage>;
32
+ /** The Ably channel to load history from. */
33
+ channel: Ably.RealtimeChannel;
34
+ /** The codec for decoding history messages. */
35
+ codec: Codec<TEvent, TMessage>;
36
+ /** Delegate for executing sends through the transport. */
37
+ sendDelegate: SendDelegate<TEvent, TMessage>;
38
+ /** Logger for diagnostic output. */
39
+ logger: Logger;
40
+ /** Called when the view is closed, allowing the owner to clean up references. */
41
+ onClose?: () => void;
42
+ }
43
+ export declare class DefaultView<TEvent, TMessage> implements View<TEvent, TMessage> {
44
+ private readonly _tree;
45
+ private readonly _channel;
46
+ private readonly _codec;
47
+ private readonly _sendDelegate;
48
+ private readonly _logger;
49
+ private readonly _emitter;
50
+ private readonly _onClose?;
51
+ /**
52
+ * View-local branch selections: group root msgId → selection intent.
53
+ * Fork points not present here default to the latest sibling.
54
+ * Replaces the previous numeric-index _selections and _pendingForkSelections
55
+ * with a single tagged-union map that carries the selected msgId (not index)
56
+ * and the reason for the selection.
57
+ */
58
+ private readonly _branchSelections;
59
+ /** Spec: AIT-CT11c — msg-ids loaded from history but not yet revealed to the UI. */
60
+ private readonly _withheldMsgIds;
61
+ /** Snapshot of visible msgIds — used to detect structural changes and for selection pinning. */
62
+ private _lastVisibleIds;
63
+ /** Snapshot of visible message references — used to detect in-place content updates (streaming). */
64
+ private _lastVisibleMessages;
65
+ /** Cached set of turn IDs present on the visible branch — avoids recomputing flattenNodes() on turn events. */
66
+ private _lastVisibleTurnIds;
67
+ /** Whether there are more history pages to fetch from the channel. */
68
+ private _hasMoreHistory;
69
+ /** Internal state for continuing history pagination. */
70
+ private _lastHistoryPage;
71
+ /** Buffer of withheld nodes, drained newest-first by successive loadOlder() calls. */
72
+ private readonly _withheldBuffer;
73
+ /** Unsubscribe functions for tree event subscriptions. */
74
+ private readonly _unsubs;
75
+ /**
76
+ * Cached result of the last flattenNodes computation. Public `flattenNodes()`
77
+ * returns this in O(1); internal callers use `_computeFlatNodes()` when a
78
+ * fresh tree walk is needed (structural changes, selection changes, history reveal).
79
+ */
80
+ private _cachedNodes;
81
+ /** Last seen tree structural version - used to distinguish content-only from structural updates. */
82
+ private _lastStructuralVersion;
83
+ private _loadingOlder;
84
+ private _processingHistory;
85
+ private _closed;
86
+ constructor(options: ViewOptions<TEvent, TMessage>);
87
+ getMessages(): TMessage[];
88
+ flattenNodes(): MessageNode<TMessage>[];
89
+ /**
90
+ * Walk the tree and compute a fresh visible node list, applying branch
91
+ * selections and withheld-message filtering. Use this instead of the
92
+ * public `flattenNodes()` when the cache may be stale (structural
93
+ * changes, selection changes, history reveal).
94
+ * @returns A fresh array of visible nodes.
95
+ */
96
+ private _computeFlatNodes;
97
+ hasOlder(): boolean;
98
+ loadOlder(limit?: number): Promise<void>;
99
+ select(msgId: string, index: number): void;
100
+ getSelectedIndex(msgId: string): number;
101
+ getSiblings(msgId: string): TMessage[];
102
+ hasSiblings(msgId: string): boolean;
103
+ getNode(msgId: string): MessageNode<TMessage> | undefined;
104
+ send(input: TMessage | TMessage[], options?: SendOptions): Promise<ActiveTurn<TEvent>>;
105
+ regenerate(messageId: string, options?: SendOptions): Promise<ActiveTurn<TEvent>>;
106
+ edit(messageId: string, newMessages: TMessage | TMessage[], options?: SendOptions): Promise<ActiveTurn<TEvent>>;
107
+ update(msgId: string, events: TEvent[], options?: SendOptions): Promise<ActiveTurn<TEvent>>;
108
+ private _getHistoryBefore;
109
+ getActiveTurnIds(): Map<string, Set<string>>;
110
+ on(event: 'update', handler: () => void): () => void;
111
+ on(event: 'ably-message', handler: (msg: Ably.InboundMessage) => void): () => void;
112
+ on(event: 'turn', handler: (event: TurnLifecycleEvent) => void): () => void;
113
+ /**
114
+ * Tear down the view — unsubscribe from tree events.
115
+ */
116
+ close(): void;
117
+ private _loadFirstPage;
118
+ private _loadAndReveal;
119
+ private _processHistoryPage;
120
+ private _loadUntilVisible;
121
+ private _releaseWithheld;
122
+ private _updateVisibleSnapshot;
123
+ private _onTreeUpdate;
124
+ /**
125
+ * Build a resolved selections map from `_branchSelections` for passing
126
+ * to `tree.flattenNodes()`. Pending entries (no sibling yet) are omitted,
127
+ * causing the tree to use the default (latest sibling).
128
+ * @returns Resolved map of groupRoot → selectedMsgId.
129
+ */
130
+ private _resolveSelections;
131
+ /**
132
+ * For each previously-visible message that now has siblings but no
133
+ * explicit selection, pin the selection to that message's msgId.
134
+ * This preserves the current branch when new forks appear from
135
+ * other views or external sources.
136
+ *
137
+ * Exception: if the fork was initiated by this view (tracked as a
138
+ * `pending` BranchSelection), select the newest sibling instead of
139
+ * pinning the old one. This handles regenerate, where no optimistic
140
+ * insert was possible at send time.
141
+ */
142
+ private _pinBranchSelections;
143
+ /**
144
+ * Resolve pending selections that are no longer on the visible branch.
145
+ * `_pinBranchSelections` only checks visible nodes, so if the user navigated
146
+ * away before the server response arrived, the pending entry would linger.
147
+ * This pass checks all pending entries against the tree directly.
148
+ */
149
+ private _resolvePendingSelections;
150
+ private _onTreeAblyMessage;
151
+ private _onTreeTurn;
152
+ /**
153
+ * Predict whether a turn-start's messages will be visible on this view's branch
154
+ * using the parent/forkOf metadata from the event.
155
+ * @param event - The turn-start lifecycle event with optional branch metadata.
156
+ * @returns True if the turn's messages are expected to be visible on this view's branch.
157
+ */
158
+ private _isTurnStartVisible;
159
+ private _visibleChanged;
160
+ }
161
+ /**
162
+ * Create a View that projects a paginated window over a Tree.
163
+ * @param options - The tree, channel, codec, and logger to use.
164
+ * @returns A new {@link DefaultView} instance.
165
+ */
166
+ export declare const createView: <TEvent, TMessage>(options: ViewOptions<TEvent, TMessage>) => DefaultView<TEvent, TMessage>;
package/dist/errors.d.ts CHANGED
@@ -25,7 +25,7 @@ export declare enum ErrorCode {
25
25
  */
26
26
  CancelListenerError = 104002,
27
27
  /**
28
- * A turn lifecycle event (turn-start or turn-end) failed to publish.
28
+ * A publish within a turn failed (lifecycle event, message, or event).
29
29
  */
30
30
  TurnLifecycleError = 104003,
31
31
  /**
@@ -35,7 +35,24 @@ export declare enum ErrorCode {
35
35
  /**
36
36
  * The HTTP POST to the server endpoint failed (network error or non-2xx response).
37
37
  */
38
- TransportSendFailed = 104005
38
+ TransportSendFailed = 104005,
39
+ /**
40
+ * The Ably channel lost message continuity — the channel entered FAILED,
41
+ * SUSPENDED, or DETACHED, or re-attached with `resumed: false`. Active
42
+ * streams can no longer be guaranteed to receive all events.
43
+ */
44
+ ChannelContinuityLost = 104006,
45
+ /**
46
+ * An operation was attempted but the channel is not in a usable state
47
+ * (not ATTACHED or ATTACHING).
48
+ */
49
+ ChannelNotReady = 104007,
50
+ /**
51
+ * An error occurred while piping a response stream to the channel — either
52
+ * the source event stream threw (e.g. LLM provider rate limit, model error,
53
+ * network failure) or an underlying publish failed mid-stream.
54
+ */
55
+ StreamError = 104008
39
56
  }
40
57
  /**
41
58
  * Returns true if the {@link Ably.ErrorInfo} code matches the provided ErrorCode value.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- export type { ActiveTurn, AddMessageOptions, AddMessagesResult, CancelFilter, CancelRequest, ClientTransport, ClientTransportOptions, CloseOptions, ConversationNode, ConversationTree, LoadHistoryOptions, MessageWithHeaders, NewTurnOptions, PaginatedMessages, SendOptions, ServerTransport, ServerTransportOptions, StreamResponseOptions, StreamResult, Turn, TurnEndReason, TurnLifecycleEvent, } from './core/transport/index.js';
1
+ export type { ActiveTurn, AddMessageOptions, AddMessagesResult, CancelFilter, CancelRequest, ClientTransport, ClientTransportOptions, CloseOptions, EventsNode, MessageNode, NewTurnOptions, SendOptions, ServerTransport, ServerTransportOptions, StreamResponseOptions, StreamResult, Tree, Turn, TurnEndReason, TurnLifecycleEvent, View, } from './core/transport/index.js';
2
+ export type { EventNode } from './core/transport/index.js';
3
+ export type { TreeNode } from './core/transport/index.js';
2
4
  export { buildTransportHeaders, createClientTransport, createServerTransport } from './core/transport/index.js';
3
5
  export type { ChannelWriter, Codec, DecoderCore, DecoderCoreHooks, DecoderCoreOptions, DecoderOutput, DiscreteEncoder, EncoderCore, EncoderCoreOptions, EncoderOptions, Extras, LifecycleTracker, MessageAccumulator, MessagePayload, PhaseConfig, StreamDecoder, StreamEncoder, StreamPayload, StreamTrackerState, WriteOptions, } from './core/codec/index.js';
4
6
  export { createDecoderCore, createEncoderCore, createLifecycleTracker, eventOutput } from './core/codec/index.js';