@ably/ai-transport 0.0.1 → 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 (167) hide show
  1. package/README.md +114 -116
  2. package/dist/ably-ai-transport.js +1743 -961
  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 +117 -39
  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 +410 -101
  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 +97 -17
  18. package/dist/core/transport/index.d.ts +5 -3
  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 -8
  24. package/dist/core/transport/run-manager.d.ts +78 -0
  25. package/dist/core/transport/tree.d.ts +435 -0
  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 -402
  32. package/dist/core/transport/view.d.ts +354 -0
  33. package/dist/errors.d.ts +37 -9
  34. package/dist/index.d.ts +6 -6
  35. package/dist/logger.d.ts +12 -0
  36. package/dist/react/ably-ai-transport-react.js +1164 -645
  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 +16 -10
  44. package/dist/react/internal/use-resolved-session.d.ts +36 -0
  45. package/dist/react/use-ably-messages.d.ts +20 -11
  46. package/dist/react/use-client-session.d.ts +81 -0
  47. package/dist/react/use-create-view.d.ts +23 -0
  48. package/dist/react/use-tree.d.ts +35 -0
  49. package/dist/react/use-view.d.ts +110 -0
  50. package/dist/utils.d.ts +32 -23
  51. package/dist/vercel/ably-ai-transport-vercel.js +2748 -1625
  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 +50 -0
  61. package/dist/vercel/index.d.ts +4 -2
  62. package/dist/vercel/react/ably-ai-transport-vercel-react.js +10298 -1410
  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 +70 -1
  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 +33 -0
  67. package/dist/vercel/react/contexts/chat-transport-provider.d.ts +96 -0
  68. package/dist/vercel/react/index.d.ts +4 -0
  69. package/dist/vercel/react/use-chat-transport.d.ts +66 -21
  70. package/dist/vercel/react/use-message-sync.d.ts +31 -12
  71. package/dist/vercel/run-end-reason.d.ts +29 -0
  72. package/dist/vercel/transport/chat-transport.d.ts +71 -30
  73. package/dist/vercel/transport/index.d.ts +25 -18
  74. package/dist/vercel/transport/run-output-stream.d.ts +56 -0
  75. package/dist/version.d.ts +2 -0
  76. package/package.json +47 -34
  77. package/src/constants.ts +126 -47
  78. package/src/core/agent.ts +68 -0
  79. package/src/core/codec/decoder.ts +71 -98
  80. package/src/core/codec/encoder.ts +115 -58
  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 +438 -106
  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 +182 -19
  89. package/src/core/transport/index.ts +29 -22
  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 +58 -40
  95. package/src/core/transport/run-manager.ts +249 -0
  96. package/src/core/transport/tree.ts +1167 -0
  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 -527
  103. package/src/core/transport/view.ts +1271 -0
  104. package/src/errors.ts +42 -9
  105. package/src/event-emitter.ts +3 -2
  106. package/src/index.ts +55 -39
  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 +27 -10
  112. package/src/react/internal/use-resolved-session.ts +63 -0
  113. package/src/react/use-ably-messages.ts +47 -19
  114. package/src/react/use-client-session.ts +201 -0
  115. package/src/react/use-create-view.ts +72 -0
  116. package/src/react/use-tree.ts +84 -0
  117. package/src/react/use-view.ts +275 -0
  118. package/src/react/vite.config.ts +4 -1
  119. package/src/utils.ts +63 -45
  120. package/src/vercel/codec/decoder.ts +336 -255
  121. package/src/vercel/codec/encoder.ts +348 -196
  122. package/src/vercel/codec/events.ts +87 -0
  123. package/src/vercel/codec/index.ts +59 -14
  124. package/src/vercel/codec/reducer.ts +977 -0
  125. package/src/vercel/codec/tool-transitions.ts +122 -0
  126. package/src/vercel/index.ts +7 -3
  127. package/src/vercel/react/contexts/chat-transport-context.ts +41 -0
  128. package/src/vercel/react/contexts/chat-transport-provider.tsx +150 -0
  129. package/src/vercel/react/index.ts +13 -1
  130. package/src/vercel/react/use-chat-transport.ts +162 -42
  131. package/src/vercel/react/use-message-sync.ts +121 -22
  132. package/src/vercel/react/vite.config.ts +4 -2
  133. package/src/vercel/run-end-reason.ts +78 -0
  134. package/src/vercel/transport/chat-transport.ts +553 -113
  135. package/src/vercel/transport/index.ts +40 -28
  136. package/src/vercel/transport/run-output-stream.ts +170 -0
  137. package/src/version.ts +2 -0
  138. package/dist/core/transport/client-transport.d.ts +0 -10
  139. package/dist/core/transport/conversation-tree.d.ts +0 -9
  140. package/dist/core/transport/decode-history.d.ts +0 -41
  141. package/dist/core/transport/server-transport.d.ts +0 -7
  142. package/dist/core/transport/stream-router.d.ts +0 -19
  143. package/dist/core/transport/turn-manager.d.ts +0 -34
  144. package/dist/react/use-active-turns.d.ts +0 -8
  145. package/dist/react/use-client-transport.d.ts +0 -7
  146. package/dist/react/use-conversation-tree.d.ts +0 -20
  147. package/dist/react/use-edit.d.ts +0 -7
  148. package/dist/react/use-history.d.ts +0 -19
  149. package/dist/react/use-messages.d.ts +0 -7
  150. package/dist/react/use-regenerate.d.ts +0 -7
  151. package/dist/react/use-send.d.ts +0 -7
  152. package/dist/vercel/codec/accumulator.d.ts +0 -21
  153. package/src/core/transport/client-transport.ts +0 -959
  154. package/src/core/transport/conversation-tree.ts +0 -434
  155. package/src/core/transport/decode-history.ts +0 -337
  156. package/src/core/transport/server-transport.ts +0 -458
  157. package/src/core/transport/stream-router.ts +0 -118
  158. package/src/core/transport/turn-manager.ts +0 -147
  159. package/src/react/use-active-turns.ts +0 -61
  160. package/src/react/use-client-transport.ts +0 -37
  161. package/src/react/use-conversation-tree.ts +0 -71
  162. package/src/react/use-edit.ts +0 -24
  163. package/src/react/use-history.ts +0 -111
  164. package/src/react/use-messages.ts +0 -32
  165. package/src/react/use-regenerate.ts +0 -24
  166. package/src/react/use-send.ts +0 -25
  167. package/src/vercel/codec/accumulator.ts +0 -603
@@ -0,0 +1,36 @@
1
+ import { CodecInputEvent, CodecOutputEvent } from '../../core/codec/types.js';
2
+ import { ClientSession } from '../../core/transport/types.js';
3
+ import type * as Ably from 'ably';
4
+ /**
5
+ * A single entry in the client-session registry, holding the session and any
6
+ * error that occurred during its construction.
7
+ *
8
+ * `session` is `undefined` when construction failed.
9
+ * `sessionError` is set when `createClientSession` threw during provider render.
10
+ */
11
+ export interface ClientSessionSlot {
12
+ /** The constructed session, or `undefined` if construction failed. */
13
+ session: ClientSession<CodecInputEvent, CodecOutputEvent, unknown, unknown> | undefined;
14
+ /** Construction error from `createClientSession`, or `undefined` on success. */
15
+ sessionError?: Ably.ErrorInfo | undefined;
16
+ }
17
+ /**
18
+ * The shape of the {@link ClientSessionContext} value.
19
+ *
20
+ * `nearest` is the slot from the innermost enclosing {@link ClientSessionProvider}.
21
+ * `providers` is the full registry of all enclosing providers, keyed by channelName.
22
+ */
23
+ export interface ClientSessionContextValue {
24
+ /** The innermost {@link ClientSessionProvider}'s slot. `undefined` when no provider is present. */
25
+ nearest: ClientSessionSlot | undefined;
26
+ /** All registered session slots from enclosing providers, keyed by channelName. */
27
+ providers: Readonly<Record<string, ClientSessionSlot>>;
28
+ }
29
+ /**
30
+ * Unified client-session context.
31
+ *
32
+ * Holds the nearest client-session slot and the full registry of all registered
33
+ * slots keyed by channelName. Populated by {@link ClientSessionProvider};
34
+ * read by {@link useClientSession} and internal hooks.
35
+ */
36
+ export declare const ClientSessionContext: import('react').Context<ClientSessionContextValue>;
@@ -0,0 +1,53 @@
1
+ import { PropsWithChildren, ReactNode } from 'react';
2
+ import { CodecInputEvent, CodecOutputEvent } from '../../core/codec/types.js';
3
+ import { ClientSessionOptions } from '../../core/transport/types.js';
4
+ /**
5
+ * Props for {@link ClientSessionProvider}.
6
+ *
7
+ * All {@link ClientSessionOptions} except `client` (read from the surrounding
8
+ * `<AblyProvider>`).
9
+ */
10
+ export interface ClientSessionProviderProps<TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage> extends Omit<ClientSessionOptions<TInput, TOutput, TProjection, TMessage>, 'client'>, PropsWithChildren {
11
+ }
12
+ /**
13
+ * Provide a {@link ClientSession} to descendant components.
14
+ *
15
+ * Reads the Ably Realtime client from the surrounding `<AblyProvider>`,
16
+ * creates a session bound to `channelName`, calls `connect()` on mount,
17
+ * and registers it in `ClientSessionContext` under `channelName`.
18
+ * Descendants call {@link useClientSession} with the same `channelName` to
19
+ * access the session.
20
+ *
21
+ * If `createClientSession` throws during construction, the error is surfaced
22
+ * through `useClientSession` as `sessionError` — the component tree does not
23
+ * crash and children are still rendered.
24
+ *
25
+ * ```tsx
26
+ * <AblyProvider client={ably}>
27
+ * <ClientSessionProvider channelName="ai:demo" codec={UIMessageCodec}>
28
+ * <Chat />
29
+ * </ClientSessionProvider>
30
+ * </AblyProvider>
31
+ *
32
+ * // Inside Chat:
33
+ * const { session, sessionError } = useClientSession({ channelName: 'ai:demo' });
34
+ * ```
35
+ *
36
+ * For multiple sessions, nest providers with distinct channelNames:
37
+ *
38
+ * ```tsx
39
+ * <ClientSessionProvider channelName="ai:main" codec={UIMessageCodec}>
40
+ * <ClientSessionProvider channelName="ai:aux" codec={UIMessageCodec}>
41
+ * <App />
42
+ * </ClientSessionProvider>
43
+ * </ClientSessionProvider>
44
+ *
45
+ * // Inside App:
46
+ * const { session: main } = useClientSession({ channelName: 'ai:main' });
47
+ * const { session: aux } = useClientSession({ channelName: 'ai:aux' });
48
+ * ```
49
+ * @param props - Provider configuration including `channelName`, `codec`, and all other {@link ClientSessionOptions} except `client`.
50
+ * @param props.children - Descendant components that consume the session via {@link useClientSession}.
51
+ * @returns A React element wrapping children with ClientSessionContext.
52
+ */
53
+ export declare const ClientSessionProvider: <TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage>({ children, ...sessionOptions }: ClientSessionProviderProps<TInput, TOutput, TProjection, TMessage>) => ReactNode;
@@ -0,0 +1,116 @@
1
+ import { ComponentType } from 'react';
2
+ import { CodecInputEvent, CodecOutputEvent } from '../core/codec/types.js';
3
+ import { ClientSession, View } from '../core/transport/types.js';
4
+ import { ClientSessionProviderProps } from './contexts/client-session-provider.js';
5
+ import { ClientSessionHandle } from './use-client-session.js';
6
+ import { TreeHandle } from './use-tree.js';
7
+ import { ViewHandle } from './use-view.js';
8
+ /**
9
+ * createSessionHooks: factory that captures the codec's type parameters once and
10
+ * returns a bundle of type-safe hooks + ClientSessionProvider. Hook call sites need
11
+ * no type parameters at every use — just call the hooks directly.
12
+ * @example
13
+ * // Once per app (e.g. in a shared session.ts):
14
+ * export const {
15
+ * ClientSessionProvider,
16
+ * useClientSession,
17
+ * useView,
18
+ * } = createSessionHooks<VercelInput, VercelOutput, VercelProjection, UIMessage>();
19
+ *
20
+ * // In page:
21
+ * <ClientSessionProvider channelName="ai:demo" codec={UIMessageCodec}>
22
+ * <Chat />
23
+ * </ClientSessionProvider>
24
+ *
25
+ * // In Chat — no type params needed, session is implicit from nearest provider:
26
+ * const { nodes } = useView({ limit: 30 });
27
+ */
28
+ import type * as Ably from 'ably';
29
+ /**
30
+ * Bundle of type-safe hooks and provider returned by {@link createSessionHooks}.
31
+ *
32
+ * The codec's `TInput`, `TOutput`, `TProjection`, and `TMessage` are baked in at
33
+ * factory creation time so no type params are needed at hook call sites.
34
+ */
35
+ export interface SessionHooks<TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage> {
36
+ /**
37
+ * `ClientSessionProvider` narrowed to the codec's `TInput`/`TOutput`/`TMessage`. No JSX type params needed.
38
+ */
39
+ ClientSessionProvider: ComponentType<ClientSessionProviderProps<TInput, TOutput, TProjection, TMessage>>;
40
+ /**
41
+ * Read the session from context. No type params needed.
42
+ *
43
+ * Returns `{ session, sessionError }`. When no provider is found (or session
44
+ * construction failed), `sessionError` is set and `session` is a stub that
45
+ * throws on access — the hook never throws during render.
46
+ *
47
+ * Pass `onError` to subscribe to post-construction session errors
48
+ * (e.g. send failures, channel continuity loss) without wiring
49
+ * `session.on('error', …)` manually.
50
+ */
51
+ useClientSession: (props?: {
52
+ /** Channel name to look up; omit to use the nearest {@link ClientSessionProvider}. */
53
+ channelName?: string;
54
+ /** When `true`, return a stub session that throws on any access. */
55
+ skip?: boolean;
56
+ /** Called whenever the resolved session emits an error event. */
57
+ onError?: (error: Ably.ErrorInfo) => void;
58
+ }) => ClientSessionHandle<TInput, TOutput, TProjection, TMessage>;
59
+ /**
60
+ * Subscribe to the nearest session's view and return the visible message list with pagination.
61
+ * Pass `session` to use a session's default view, `view` to subscribe to a specific view
62
+ * directly. Pass `limit` to auto-load on mount. Pass `skip: true` for an empty handle.
63
+ */
64
+ useView: (props?: {
65
+ /** Client session whose default view to subscribe to; defaults to the nearest {@link ClientSessionProvider}. */
66
+ session?: ClientSession<TInput, TOutput, TProjection, TMessage> | null;
67
+ /** A specific {@link View} to subscribe to directly. Takes priority over `session`. */
68
+ view?: View<TInput, TMessage> | null;
69
+ /** When provided, auto-loads the first page on mount. */
70
+ limit?: number;
71
+ /** When `true`, skip all subscriptions and return an empty handle. */
72
+ skip?: boolean;
73
+ }) => ViewHandle<TInput, TMessage>;
74
+ /**
75
+ * Navigate conversation branches in the session tree.
76
+ * Pass `session` to override; defaults to the nearest {@link ClientSessionProvider}.
77
+ */
78
+ useTree: (props?: {
79
+ /** Override session; defaults to the nearest {@link ClientSessionProvider}. */
80
+ session?: ClientSession<TInput, TOutput, TProjection, TMessage>;
81
+ }) => TreeHandle<TProjection>;
82
+ /**
83
+ * Subscribe to raw Ably messages on the session channel.
84
+ * Pass `session` to override; defaults to the nearest {@link ClientSessionProvider}.
85
+ * Pass `skip: true` to return an empty array without subscribing.
86
+ */
87
+ useAblyMessages: (props?: {
88
+ /** Override session; defaults to the nearest {@link ClientSessionProvider}. */
89
+ session?: ClientSession<TInput, TOutput, TProjection, TMessage>;
90
+ /** When `true`, skip all subscriptions and return an empty array. */
91
+ skip?: boolean;
92
+ }) => Ably.InboundMessage[];
93
+ /**
94
+ * Create an independent view over the same tree.
95
+ * Pass `session` to override; defaults to the nearest {@link ClientSessionProvider}.
96
+ * Pass `skip: true` to return an empty handle without creating a view.
97
+ */
98
+ useCreateView: (props?: {
99
+ /** Override session; defaults to the nearest {@link ClientSessionProvider}. */
100
+ session?: ClientSession<TInput, TOutput, TProjection, TMessage> | null;
101
+ /** When provided, auto-loads the first page on mount. */
102
+ limit?: number;
103
+ /** When `true`, skip view creation and return an empty handle. */
104
+ skip?: boolean;
105
+ }) => ViewHandle<TInput, TMessage>;
106
+ }
107
+ /**
108
+ * Create a bundle of type-safe hooks and provider for a given codec's
109
+ * `TInput`/`TOutput`/`TProjection`/`TMessage`.
110
+ *
111
+ * These type parameters are captured at factory creation time; hook call sites need
112
+ * no type parameters. The returned hooks are thin wrappers around the standalone hooks
113
+ * with the types resolved.
114
+ * @returns A {@link SessionHooks} bundle.
115
+ */
116
+ export declare const createSessionHooks: <TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage>() => SessionHooks<TInput, TOutput, TProjection, TMessage>;
@@ -1,11 +1,17 @@
1
+ export type { CodecMessage } from '../core/codec/types.js';
2
+ export type { ActiveRun, BranchSelection, ClientSession, ConversationNode, EventsNode, InputNode, MessageNode, RunInfo, RunNode, SendOptions, } from '../core/transport/types.js';
3
+ export type { ClientSessionSlot } from './contexts/client-session-context.js';
4
+ export type { ClientSessionProviderProps } from './contexts/client-session-provider.js';
5
+ export { ClientSessionProvider } from './contexts/client-session-provider.js';
6
+ export type { SessionHooks } from './create-session-hooks.js';
7
+ export { createSessionHooks } from './create-session-hooks.js';
8
+ export type { UseAblyMessagesOptions } from './use-ably-messages.js';
1
9
  export { useAblyMessages } from './use-ably-messages.js';
2
- export { useActiveTurns } from './use-active-turns.js';
3
- export { useClientTransport } from './use-client-transport.js';
4
- export type { ConversationTreeHandle } from './use-conversation-tree.js';
5
- export { useConversationTree } from './use-conversation-tree.js';
6
- export { useEdit } from './use-edit.js';
7
- export type { HistoryHandle } from './use-history.js';
8
- export { useHistory } from './use-history.js';
9
- export { useMessages } from './use-messages.js';
10
- export { useRegenerate } from './use-regenerate.js';
11
- export { useSend } from './use-send.js';
10
+ export type { ClientSessionHandle } from './use-client-session.js';
11
+ export { useClientSession } from './use-client-session.js';
12
+ export type { UseCreateViewOptions } from './use-create-view.js';
13
+ export { useCreateView } from './use-create-view.js';
14
+ export type { TreeHandle, UseTreeOptions } from './use-tree.js';
15
+ export { useTree } from './use-tree.js';
16
+ export type { UseViewOptions, ViewHandle } from './use-view.js';
17
+ export { useView } from './use-view.js';
@@ -0,0 +1,36 @@
1
+ import { CodecInputEvent, CodecOutputEvent } from '../../core/codec/types.js';
2
+ import { ClientSession } from '../../core/transport/types.js';
3
+ /**
4
+ * Shared base for hook options that accept an explicit session override.
5
+ * Extend this interface for any hook whose `session` option defaults to the
6
+ * nearest {@link ClientSessionProvider} when omitted. Pass `null` to defer
7
+ * resolution (e.g. when a split pane is collapsed) — the helper returns
8
+ * `undefined` rather than falling back to the nearest provider.
9
+ */
10
+ export interface BaseSessionOption<TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage> {
11
+ /**
12
+ * Session to operate on; defaults to the nearest {@link ClientSessionProvider}.
13
+ * Pass `null` to defer (returns undefined; nearest provider is not used).
14
+ */
15
+ session?: ClientSession<TInput, TOutput, TProjection, TMessage> | null;
16
+ }
17
+ /**
18
+ * Resolve the active `ClientSession` for a hook.
19
+ *
20
+ * Reads `ClientSessionContext` and applies the standard three-way
21
+ * priority: explicit `session` argument → nearest provider → `undefined`.
22
+ * When `skip` is `true`, returns `undefined` regardless of context.
23
+ * When `session` is `null`, returns `undefined` (caller is deferring).
24
+ *
25
+ * Internal — not part of the public API.
26
+ * @param root0 - Options.
27
+ * @param root0.session - Explicit session; takes priority over the nearest provider. `null` to defer.
28
+ * @param root0.skip - When `true`, returns `undefined` immediately; context is still read but its value is ignored.
29
+ * @returns The resolved session, or `undefined` if none is available or `skip` is `true`.
30
+ */
31
+ export declare const useResolvedSession: <TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage>({ session, skip, }?: {
32
+ /** Explicit session; takes priority over the nearest provider. `null` to defer. */
33
+ session?: ClientSession<TInput, TOutput, TProjection, TMessage> | null;
34
+ /** When `true`, return `undefined` immediately (context is still read, but ignored). */
35
+ skip?: boolean;
36
+ }) => ClientSession<TInput, TOutput, TProjection, TMessage> | undefined;
@@ -1,18 +1,27 @@
1
- import { ClientTransport } from '../core/transport/types.js';
1
+ import { CodecInputEvent, CodecOutputEvent } from '../core/codec/types.js';
2
+ import { BaseSessionOption } from './internal/use-resolved-session.js';
2
3
  /**
3
- * useAblyMessages — reactive raw Ably message log from a ClientTransport.
4
+ * useAblyMessages — reactive raw Ably message log from a ClientSession.
4
5
  *
5
- * Returns the accumulated raw Ably InboundMessages in chronological order,
6
- * including both live messages (from the channel subscription) and
7
- * history-loaded messages (from transport.history() calls).
6
+ * Accumulates raw Ably InboundMessages from the session's tree
7
+ * 'ably-message' event. Messages are appended in arrival order.
8
8
  *
9
- * Subscribes to the transport's "ably-message" event and re-reads the
10
- * list on each update.
9
+ * When `session` is omitted, defaults to the nearest
10
+ * {@link ClientSessionProvider}'s session via context.
11
+ * Pass `skip: true` to bypass all subscriptions and return an empty array.
11
12
  */
12
13
  import type * as Ably from 'ably';
14
+ /** Options for {@link useAblyMessages}. */
15
+ export interface UseAblyMessagesOptions<TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage> extends BaseSessionOption<TInput, TOutput, TProjection, TMessage> {
16
+ /** When `true`, skip all subscriptions and return an empty array. */
17
+ skip?: boolean;
18
+ }
13
19
  /**
14
- * Subscribe to raw Ably message updates from a client transport.
15
- * @param transport - The client transport to observe.
16
- * @returns The accumulated raw Ably messages in chronological order.
20
+ * Subscribe to raw Ably message updates from a client session's tree.
21
+ * When `session` is omitted, uses the nearest {@link ClientSessionProvider}'s session via context.
22
+ * @param props - Options including optional `session` and `skip`.
23
+ * @param props.session - Session to subscribe to; defaults to the nearest provider.
24
+ * @param props.skip - When `true`, skip all subscriptions and return an empty array.
25
+ * @returns The accumulated raw Ably messages in event-arrival order — older history messages loaded later are appended after the live messages already present, so this is not strictly chronological.
17
26
  */
18
- export declare const useAblyMessages: <TEvent, TMessage>(transport: ClientTransport<TEvent, TMessage>) => Ably.InboundMessage[];
27
+ export declare const useAblyMessages: <TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage>({ session, skip }?: UseAblyMessagesOptions<TInput, TOutput, TProjection, TMessage>) => Ably.InboundMessage[];
@@ -0,0 +1,81 @@
1
+ import { CodecInputEvent, CodecOutputEvent } from '../core/codec/types.js';
2
+ import { ClientSession } from '../core/transport/types.js';
3
+ /**
4
+ * useClientSession — read a ClientSession from the nearest ClientSessionProvider.
5
+ *
6
+ * The session is created by {@link ClientSessionProvider}, which reads the Ably
7
+ * Realtime client from the surrounding `<AblyProvider>`. This hook is a thin
8
+ * context reader — it does not create or manage session state.
9
+ *
10
+ * **Provider lookup**
11
+ * - Omit `channelName` to use the innermost `ClientSessionProvider` in the tree.
12
+ * - Pass `channelName` to look up a specific provider by name.
13
+ * - Pass `skip: true` to receive a stub session that throws on any access —
14
+ * safe to hold in state before auth or other conditions are ready.
15
+ *
16
+ * **Error handling**
17
+ * - When no matching provider is found, or when the provider's `createClientSession`
18
+ * call threw, `sessionError` is set on the returned object instead of throwing.
19
+ * The component can render an error state without an error boundary.
20
+ * - Pass `onError` to receive post-construction session errors (e.g. send failures,
21
+ * channel continuity loss) without wiring `session.on('error', ...)` manually.
22
+ */
23
+ import * as Ably from 'ably';
24
+ /**
25
+ * Return value of {@link useClientSession}.
26
+ *
27
+ * `session` is always a valid object. When `skip` is `true`, when no provider was
28
+ * found, or when the provider's session construction failed, `session` is a stub
29
+ * that throws {@link Ably.ErrorInfo} on every access.
30
+ * Check `sessionError` before using `session` to avoid those throws.
31
+ */
32
+ export interface ClientSessionHandle<TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage> {
33
+ /**
34
+ * The resolved session.
35
+ *
36
+ * A throwing stub when `skip` is `true`, when no matching {@link ClientSessionProvider}
37
+ * was found in the tree, or when session construction failed.
38
+ */
39
+ session: ClientSession<TInput, TOutput, TProjection, TMessage>;
40
+ /**
41
+ * Set when no matching {@link ClientSessionProvider} was found, when session
42
+ * construction failed, and `skip` is `false`.
43
+ * `undefined` when the session resolved successfully or when `skip` is `true`.
44
+ */
45
+ sessionError?: Ably.ErrorInfo | undefined;
46
+ }
47
+ /**
48
+ * Read a {@link ClientSession} from the nearest {@link ClientSessionProvider}.
49
+ *
50
+ * Returns `{ session, sessionError }`. When no provider is found or session
51
+ * construction failed, `sessionError` is set and `session` is a stub that throws
52
+ * on access — the hook never throws during render.
53
+ *
54
+ * Pass `onError` to subscribe to post-construction session errors
55
+ * (e.g. {@link ErrorCode.SessionSendFailed}, {@link ErrorCode.ChannelContinuityLost})
56
+ * without calling `session.on('error', …)` manually. The subscription is
57
+ * created when the session resolves and removed on unmount.
58
+ * @param props - Hook options.
59
+ * @param props.channelName - Look up a specific provider by channel name; omit for the nearest.
60
+ * @param props.skip - When `true`, return the stub session immediately without resolving a provider slot.
61
+ * @param props.onError - Called whenever the resolved session emits an error event.
62
+ * @returns `{ session, sessionError }`.
63
+ */
64
+ export declare const useClientSession: <TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage>({ channelName, skip, onError, }?: {
65
+ /**
66
+ * Channel name passed to the enclosing {@link ClientSessionProvider}.
67
+ * Omit to use the nearest provider in the tree.
68
+ */
69
+ channelName?: string;
70
+ /**
71
+ * When `true`, skip context lookup and return a stub session that throws on
72
+ * any access. Use when a condition (auth, feature flag) is not yet resolved.
73
+ */
74
+ skip?: boolean;
75
+ /**
76
+ * Called whenever the resolved session emits an error event.
77
+ * The subscription is established once the session resolves and
78
+ * automatically removed on unmount or when the session changes.
79
+ */
80
+ onError?: (error: Ably.ErrorInfo) => void;
81
+ }) => ClientSessionHandle<TInput, TOutput, TProjection, TMessage>;
@@ -0,0 +1,23 @@
1
+ import { CodecInputEvent, CodecOutputEvent } from '../core/codec/types.js';
2
+ import { BaseSessionOption } from './internal/use-resolved-session.js';
3
+ import { ViewHandle } from './use-view.js';
4
+ /** Options for {@link useCreateView}. */
5
+ export interface UseCreateViewOptions<TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage> extends BaseSessionOption<TInput, TOutput, TProjection, TMessage> {
6
+ /** When provided, auto-loads the first page on mount. Omit for manual load. */
7
+ limit?: number;
8
+ /** When `true`, skip view creation and return an empty handle immediately. */
9
+ skip?: boolean;
10
+ }
11
+ /**
12
+ * Create an independent {@link View} and subscribe to it.
13
+ * Returns the same {@link ViewHandle} as {@link useView}, but backed by a
14
+ * newly created view with its own branch selections and pagination state.
15
+ * The view is closed on unmount or when the session changes.
16
+ * When `session` is omitted, uses the nearest {@link ClientSessionProvider}'s session via context.
17
+ * @param props - Options including optional `session`, `limit` for auto-load, and `skip`.
18
+ * @param props.session - Session to create a view from; defaults to the nearest provider.
19
+ * @param props.limit - Max older messages per page; when provided, auto-loads on mount.
20
+ * @param props.skip - When `true`, skip view creation and return an empty handle.
21
+ * @returns A {@link ViewHandle} with nodes, pagination, navigation, and write operations.
22
+ */
23
+ export declare const useCreateView: <TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage>({ session, limit, skip, }?: UseCreateViewOptions<TInput, TOutput, TProjection, TMessage>) => ViewHandle<TInput, TMessage>;
@@ -0,0 +1,35 @@
1
+ import { CodecInputEvent, CodecOutputEvent } from '../core/codec/types.js';
2
+ import { ConversationNode, RunNode } from '../core/transport/types.js';
3
+ import { BaseSessionOption } from './internal/use-resolved-session.js';
4
+ /** Handle for querying the conversation tree structure. */
5
+ export interface TreeHandle<TProjection> {
6
+ /**
7
+ * Get the RunNode for `runId`, or undefined if no node is keyed by `runId`
8
+ * (or the keyed node is an input node, not a reply run).
9
+ */
10
+ getRunNode: (runId: string) => RunNode<TProjection> | undefined;
11
+ /**
12
+ * Get the node that owns a given codec-message-id, or undefined if not
13
+ * observed. Returns a {@link ConversationNode} union — narrow on `kind`
14
+ * (`'input'` vs `'run'`) before reading kind-specific fields.
15
+ */
16
+ getNodeByCodecMessageId: (codecMessageId: string) => ConversationNode<TProjection> | undefined;
17
+ /**
18
+ * Get the sibling group (both kinds) the node keyed by `key` belongs to —
19
+ * edit versions for an input node, regenerate runs for a reply run — ordered
20
+ * oldest-first. A single-element array when the node has no siblings; empty
21
+ * when `key` is unknown. `key` is a {@link RunNode.runId} or an
22
+ * {@link InputNode.codecMessageId}.
23
+ */
24
+ getSiblingNodes: (key: string) => ConversationNode<TProjection>[];
25
+ }
26
+ /** Options for {@link useTree}. */
27
+ export type UseTreeOptions<TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage> = BaseSessionOption<TInput, TOutput, TProjection, TMessage>;
28
+ /**
29
+ * Provide stable structural query callbacks backed by the session's tree.
30
+ * When `session` is omitted, uses the nearest {@link ClientSessionProvider}'s session via context.
31
+ * @param props - Options including optional `session`.
32
+ * @param props.session - Session to read tree structure from; defaults to the nearest provider.
33
+ * @returns A {@link TreeHandle} with structural query methods.
34
+ */
35
+ export declare const useTree: <TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage>({ session, }?: UseTreeOptions<TInput, TOutput, TProjection, TMessage>) => TreeHandle<TProjection>;
@@ -0,0 +1,110 @@
1
+ import { CodecInputEvent, CodecMessage, CodecOutputEvent } from '../core/codec/types.js';
2
+ import { ActiveRun, BranchSelection, RunInfo, SendOptions, View } from '../core/transport/types.js';
3
+ import { BaseSessionOption } from './internal/use-resolved-session.js';
4
+ /**
5
+ * useView — reactive paginated view of the conversation.
6
+ *
7
+ * Subscribes to view updates and exposes the visible messages, msg-anchored
8
+ * branch navigation, write operations, pagination state, and a `loadOlder`
9
+ * callback. Pass `session` to use a session's default view, or `view` to
10
+ * subscribe to a specific {@link View} directly. When both are omitted,
11
+ * defaults to the nearest {@link ClientSessionProvider}'s session via context.
12
+ */
13
+ import * as Ably from 'ably';
14
+ /** Options for {@link useView}. */
15
+ export interface UseViewOptions<TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage> extends BaseSessionOption<TInput, TOutput, TProjection, TMessage> {
16
+ /** A specific {@link View} to subscribe to directly. Takes priority over `session`. */
17
+ view?: View<TInput, TMessage> | null;
18
+ /** Maximum number of older Runs to reveal per page (the pagination unit is the Run, not the message). When provided, auto-loads the first page on mount. */
19
+ limit?: number;
20
+ /** When `true`, skip all subscriptions and return an empty handle immediately. */
21
+ skip?: boolean;
22
+ }
23
+ /** Handle for the paginated, branch-aware conversation view. */
24
+ export interface ViewHandle<TInput extends CodecInputEvent, TMessage> {
25
+ /**
26
+ * The visible messages along the selected branch, concatenated across all
27
+ * visible Runs, each paired with its codec-message-id (see
28
+ * {@link CodecMessage}). Read the domain object from each entry's
29
+ * `message` field.
30
+ *
31
+ * Correlate a rendered message back to the View — `runOf`,
32
+ * `branchSelection`, `selectSibling`, `regenerate`, or `edit` — via its
33
+ * `codecMessageId`, which the SDK assigns and tracks independently of any
34
+ * identity the domain `message` may carry. See {@link View.getMessages}.
35
+ */
36
+ messages: CodecMessage<TMessage>[];
37
+ /** Whether there are older Runs that can be revealed via `loadOlder`. */
38
+ hasOlder: boolean;
39
+ /** Whether a page load is currently in progress. */
40
+ loading: boolean;
41
+ /**
42
+ * Set when the most recent `loadOlder` call failed.
43
+ * Cleared automatically on the next successful load.
44
+ * `undefined` when no error has occurred or when `skip` is `true`.
45
+ */
46
+ loadError: Ably.ErrorInfo | undefined;
47
+ /**
48
+ * Load older messages into the view. No-op if already loading.
49
+ * On failure, `loadError` is set; on success, `loadError` is cleared.
50
+ */
51
+ loadOlder: () => Promise<void>;
52
+ /**
53
+ * Look up the {@link RunInfo} for the Run that owns `codecMessageId`.
54
+ * Returns `undefined` when the codec-message-id hasn't been observed.
55
+ * See {@link View.runOf}.
56
+ */
57
+ runOf: (codecMessageId: string) => RunInfo | undefined;
58
+ /**
59
+ * Direct lookup by runId. Returns `undefined` when the Run hasn't been
60
+ * observed. See {@link View.run}.
61
+ */
62
+ run: (runId: string) => RunInfo | undefined;
63
+ /**
64
+ * Snapshot of the visible Runs along the selected branch, in
65
+ * chronological order. Returns `[]` when the view isn't resolved.
66
+ * See {@link View.runs}.
67
+ */
68
+ runs: () => RunInfo[];
69
+ /**
70
+ * Resolve the {@link BranchSelection} bundle anchored at
71
+ * `codecMessageId`. Always returns a safe object — see
72
+ * {@link BranchSelection}. See {@link View.branchSelection}.
73
+ */
74
+ branchSelection: (codecMessageId: string) => BranchSelection<TMessage>;
75
+ /**
76
+ * Select a sibling at the branch point anchored at `codecMessageId`.
77
+ * `index` is clamped to `[0, siblings.length - 1]`. Silent no-op when
78
+ * `codecMessageId` isn't a branch anchor. See {@link View.selectSibling}.
79
+ */
80
+ selectSibling: (codecMessageId: string, index: number) => void;
81
+ /**
82
+ * Send one or more TInputs on the channel and fire a POST. See {@link View.send}.
83
+ * @throws Ably.ErrorInfo with code {@link ErrorCode.InvalidArgument} when no view is resolved (before the session is available, or when `skip` is `true`).
84
+ */
85
+ send: (events: TInput | TInput[], options?: SendOptions) => Promise<ActiveRun>;
86
+ /**
87
+ * Regenerate an assistant message, using this view's branch for history.
88
+ * @throws Ably.ErrorInfo with code {@link ErrorCode.InvalidArgument} when no view is resolved (before the session is available, or when `skip` is `true`).
89
+ */
90
+ regenerate: (messageId: string, options?: SendOptions) => Promise<ActiveRun>;
91
+ /**
92
+ * Edit a user message, forking from this view's branch.
93
+ * Rejects with an `Ably.ErrorInfo` (code {@link ErrorCode.InvalidArgument}) if no view is resolved — e.g. before the session is available, or when `skip` is `true`.
94
+ */
95
+ edit: (messageId: string, inputs: TInput | TInput[], options?: SendOptions) => Promise<ActiveRun>;
96
+ }
97
+ /**
98
+ * Subscribe to a view and return the visible messages with pagination, navigation, and write operations.
99
+ *
100
+ * `view` takes priority over `session`. When neither is provided, the nearest
101
+ * {@link ClientSessionProvider}'s session is used. When `limit` is provided, auto-loads
102
+ * the first page on mount (SWR-style).
103
+ * @param props - Options for selecting the view source and configuring auto-load.
104
+ * @param props.session - Client session whose default view to subscribe to; defaults to the nearest provider.
105
+ * @param props.view - A specific {@link View} to subscribe to directly. Takes priority over `session`.
106
+ * @param props.limit - Max older Runs to reveal per page; when provided, auto-loads the first page on mount.
107
+ * @param props.skip - When `true`, skip all subscriptions and return an empty handle.
108
+ * @returns A {@link ViewHandle} with messages, pagination state, navigation, write operations, and loadOlder.
109
+ */
110
+ export declare const useView: <TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection, TMessage>({ session, view, limit, skip, }?: UseViewOptions<TInput, TOutput, TProjection, TMessage>) => ViewHandle<TInput, TMessage>;