@ably/ai-transport 0.2.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 +10 -19
- package/dist/ably-ai-transport.js +1790 -1091
- 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 +2 -2
- package/dist/core/agent.d.ts +20 -5
- 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 +4 -1
- package/dist/core/codec/define-codec.d.ts +100 -0
- package/dist/core/codec/encoder.d.ts +2 -7
- 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 -1
- 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/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 +95 -36
- package/dist/core/codec/well-known-inputs.d.ts +52 -0
- package/dist/core/transport/agent-view.d.ts +296 -0
- package/dist/core/transport/decode-fold.d.ts +40 -32
- package/dist/core/transport/headers.d.ts +30 -1
- package/dist/core/transport/index.d.ts +1 -1
- package/dist/core/transport/invocation.d.ts +1 -1
- package/dist/core/transport/load-history-pages.d.ts +71 -0
- package/dist/core/transport/load-history.d.ts +21 -16
- package/dist/core/transport/run-manager.d.ts +9 -11
- package/dist/core/transport/session-support.d.ts +55 -0
- package/dist/core/transport/tree.d.ts +165 -15
- package/dist/core/transport/types/agent.d.ts +120 -98
- package/dist/core/transport/types/client.d.ts +45 -12
- package/dist/core/transport/types/tree.d.ts +52 -10
- package/dist/core/transport/types/view.d.ts +55 -28
- package/dist/core/transport/view.d.ts +176 -58
- package/dist/core/transport/wire-log.d.ts +102 -0
- package/dist/errors.d.ts +10 -4
- package/dist/index.d.ts +6 -5
- package/dist/react/ably-ai-transport-react.js +784 -415
- 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 +2 -1
- package/dist/react/contexts/client-session-provider.d.ts +3 -0
- package/dist/react/index.d.ts +2 -1
- package/dist/react/internal/skipped-session.d.ts +8 -0
- package/dist/react/use-view.d.ts +3 -3
- package/dist/utils.d.ts +22 -54
- package/dist/vercel/ably-ai-transport-vercel.js +2297 -2026
- 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 +1 -2
- 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 +5 -30
- 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 +20 -102
- package/dist/vercel/codec/tool-transitions.d.ts +0 -6
- package/dist/vercel/codec/wire-data.d.ts +34 -0
- package/dist/vercel/index.d.ts +1 -0
- package/dist/vercel/react/ably-ai-transport-vercel-react.js +2013 -9500
- 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 -70
- package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs.map +1 -1
- package/dist/vercel/react/contexts/chat-transport-context.d.ts +2 -1
- package/dist/vercel/run-end-reason.d.ts +66 -11
- package/dist/vercel/tool-part.d.ts +21 -0
- package/dist/vercel/transport/chat-transport.d.ts +0 -2
- package/dist/vercel/transport/index.d.ts +1 -1
- package/dist/vercel/transport/run-output-stream.d.ts +6 -8
- package/dist/version.d.ts +1 -1
- package/package.json +2 -2
- package/src/constants.ts +2 -2
- package/src/core/agent.ts +43 -19
- package/src/core/channel-options.ts +89 -0
- package/src/core/codec/codec-event.ts +27 -0
- package/src/core/codec/decoder.ts +145 -21
- package/src/core/codec/define-codec.ts +432 -0
- package/src/core/codec/encoder.ts +13 -54
- package/src/core/codec/field-bag.ts +142 -0
- package/src/core/codec/fields.ts +193 -0
- package/src/core/codec/index.ts +43 -0
- 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/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 +99 -36
- package/src/core/codec/well-known-inputs.ts +96 -0
- package/src/core/transport/agent-session.ts +330 -589
- package/src/core/transport/agent-view.ts +738 -0
- package/src/core/transport/client-session.ts +74 -69
- package/src/core/transport/decode-fold.ts +57 -47
- package/src/core/transport/headers.ts +57 -4
- package/src/core/transport/index.ts +2 -1
- package/src/core/transport/invocation.ts +1 -1
- package/src/core/transport/load-history-pages.ts +220 -0
- package/src/core/transport/load-history.ts +63 -61
- package/src/core/transport/pipe-stream.ts +10 -1
- package/src/core/transport/run-manager.ts +25 -31
- package/src/core/transport/session-support.ts +96 -0
- package/src/core/transport/tree.ts +414 -47
- package/src/core/transport/types/agent.ts +129 -102
- package/src/core/transport/types/client.ts +49 -13
- package/src/core/transport/types/tree.ts +61 -12
- package/src/core/transport/types/view.ts +57 -28
- package/src/core/transport/view.ts +520 -172
- package/src/core/transport/wire-log.ts +189 -0
- package/src/errors.ts +10 -3
- package/src/index.ts +44 -11
- package/src/react/contexts/client-session-context.ts +1 -1
- package/src/react/contexts/client-session-provider.tsx +38 -2
- package/src/react/index.ts +2 -1
- package/src/react/internal/skipped-session.ts +62 -0
- package/src/react/use-client-session.ts +7 -30
- package/src/react/use-view.ts +3 -3
- package/src/utils.ts +31 -97
- package/src/vercel/codec/decode-lifecycle.ts +70 -0
- package/src/vercel/codec/events.ts +1 -3
- 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 +23 -63
- 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 +52 -838
- package/src/vercel/codec/tool-transitions.ts +1 -12
- package/src/vercel/codec/wire-data.ts +64 -0
- package/src/vercel/index.ts +1 -0
- package/src/vercel/react/contexts/chat-transport-context.ts +1 -1
- package/src/vercel/react/use-chat-transport.ts +8 -28
- package/src/vercel/react/use-message-sync.ts +5 -10
- package/src/vercel/run-end-reason.ts +95 -16
- package/src/vercel/tool-part.ts +25 -0
- package/src/vercel/transport/chat-transport.ts +10 -22
- package/src/vercel/transport/index.ts +1 -1
- package/src/vercel/transport/run-output-stream.ts +7 -8
- package/src/version.ts +1 -1
- package/dist/core/transport/branch-chain.d.ts +0 -43
- package/dist/core/transport/load-conversation.d.ts +0 -128
- package/dist/vercel/codec/decoder.d.ts +0 -9
- package/dist/vercel/codec/encoder.d.ts +0 -11
- package/src/core/transport/branch-chain.ts +0 -58
- package/src/core/transport/load-conversation.ts +0 -355
- package/src/vercel/codec/decoder.ts +0 -696
- package/src/vercel/codec/encoder.ts +0 -548
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CodecInputEvent, CodecOutputEvent, Decoder } from '../codec/types.js';
|
|
2
2
|
import { TreeInternal } from './tree.js';
|
|
3
3
|
import { RunLifecycleEvent } from './types.js';
|
|
4
4
|
/**
|
|
@@ -8,40 +8,48 @@ import { RunLifecycleEvent } from './types.js';
|
|
|
8
8
|
* the conversation Tree from the same raw Ably wire log. This module is the one
|
|
9
9
|
* place that classifies a wire message (run-lifecycle vs codec-decoded), parses
|
|
10
10
|
* or decodes it, and applies it to the Tree — so the two paths can never drift.
|
|
11
|
+
*
|
|
12
|
+
* The engine is exposed as a {@link WireApplier} binding one Tree to one
|
|
13
|
+
* decoder. A Tree has exactly one applier (the session constructs it and hands
|
|
14
|
+
* it to every View), so every route a wire message can arrive by — the live
|
|
15
|
+
* subscription, View history pagination, the agent's hydration walks — feeds
|
|
16
|
+
* the same decoder. The decoder's version-guarded stream trackers then make
|
|
17
|
+
* re-delivery across routes (an attach-boundary in-flight stream, a replayed
|
|
18
|
+
* history page) decode to nothing instead of double-folding. The delivery's
|
|
19
|
+
* `version.serial` is also threaded into the Tree, whose per-entry
|
|
20
|
+
* `decodedThrough` high-water-mark drops whole-wire replays that no decoder
|
|
21
|
+
* state can see (stateless discrete re-decodes).
|
|
11
22
|
*/
|
|
12
23
|
import type * as Ably from 'ably';
|
|
13
24
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* Run-lifecycle messages are turned into a {@link RunLifecycleEvent} via
|
|
17
|
-
* {@link parseRunLifecycle} and applied with `applyRunLifecycle`; everything
|
|
18
|
-
* else is decoded with `decoder` and applied with `applyMessage`, skipping
|
|
19
|
-
* wire-only carriers that decode to no events and carry no run-id (the eventual
|
|
20
|
-
* reply run is created later by its run-start).
|
|
21
|
-
*
|
|
22
|
-
* Does NOT emit the tree's `ably-message` event — the caller owns that, because
|
|
23
|
-
* the live loop emits per message while history replay emits in a batch once
|
|
24
|
-
* the whole page is applied. Returns the parsed lifecycle event so a live
|
|
25
|
-
* caller can run its own side-effects (resolving a pending run-start,
|
|
26
|
-
* surfacing an agent error); returns `undefined` for a codec-decoded message
|
|
27
|
-
* or a lifecycle message that carried no run-id.
|
|
28
|
-
* @param tree - The tree to apply the message to.
|
|
29
|
-
* @param decoder - The codec decoder used for non-lifecycle messages.
|
|
30
|
-
* @param rawMsg - The inbound Ably wire message.
|
|
31
|
-
* @returns The parsed run-lifecycle event, or `undefined`.
|
|
25
|
+
* The decode-and-apply engine for one Tree: a single codec decoder bound to a
|
|
26
|
+
* single Tree, shared by every route that feeds the Tree wire messages.
|
|
32
27
|
*/
|
|
33
|
-
export
|
|
28
|
+
export interface WireApplier {
|
|
29
|
+
/**
|
|
30
|
+
* Apply one inbound wire message to the bound tree.
|
|
31
|
+
*
|
|
32
|
+
* Run-lifecycle messages are turned into a {@link RunLifecycleEvent} via
|
|
33
|
+
* {@link parseRunLifecycle} and applied with `applyRunLifecycle`; everything
|
|
34
|
+
* else is decoded with the bound decoder and applied with `applyMessage`,
|
|
35
|
+
* skipping wire-only carriers that decode to no events and carry no run-id
|
|
36
|
+
* (the eventual reply run is created later by its run-start).
|
|
37
|
+
*
|
|
38
|
+
* Does NOT emit the tree's `ably-message` event — the caller owns that,
|
|
39
|
+
* because the live loop emits per message while history replay emits in a
|
|
40
|
+
* batch once the whole page is applied. Returns the parsed lifecycle event
|
|
41
|
+
* so a live caller can run its own side-effects (resolving a pending
|
|
42
|
+
* run-start, surfacing an agent error); returns `undefined` for a
|
|
43
|
+
* codec-decoded message or a lifecycle message that carried no run-id.
|
|
44
|
+
* @param rawMsg - The inbound Ably wire message.
|
|
45
|
+
* @returns The parsed run-lifecycle event, or `undefined`.
|
|
46
|
+
*/
|
|
47
|
+
apply(rawMsg: Ably.InboundMessage): RunLifecycleEvent | undefined;
|
|
48
|
+
}
|
|
34
49
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* state can span the messages of a run, and chooses the reducer routing key.
|
|
40
|
-
* @param codec - The codec whose inherited Reducer `fold` method folds each decoded event into the projection.
|
|
41
|
-
* @param decoder - The caller-owned codec decoder (reused across a run's wires).
|
|
42
|
-
* @param projection - The projection to fold the message's events into.
|
|
43
|
-
* @param rawMsg - The wire message to decode and fold.
|
|
44
|
-
* @param messageId - The reducer routing key (codec-message-id) for this message.
|
|
45
|
-
* @returns The projection after folding all of the message's decoded events.
|
|
50
|
+
* Bind a Tree and a decoder into the Tree's single {@link WireApplier}.
|
|
51
|
+
* @param tree - The tree the applier feeds.
|
|
52
|
+
* @param decoder - The codec decoder shared by every route into the tree.
|
|
53
|
+
* @returns The applier.
|
|
46
54
|
*/
|
|
47
|
-
export declare const
|
|
55
|
+
export declare const createWireApplier: <TInput extends CodecInputEvent, TOutput extends CodecOutputEvent, TProjection>(tree: TreeInternal<TInput, TOutput, TProjection>, decoder: Decoder<TInput, TOutput>) => WireApplier;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { EVENT_RUN_END, EVENT_RUN_RESUME, EVENT_RUN_START, EVENT_RUN_SUSPEND } from '../../constants.js';
|
|
2
2
|
import { RunEndReason, RunLifecycleEvent } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Transport header builder.
|
|
5
|
+
*
|
|
6
|
+
* Single source of truth for which transport headers every transport
|
|
7
|
+
* message carries. Used by the agent session (pipe) and by
|
|
8
|
+
* the client session (optimistic message stamping).
|
|
9
|
+
*/
|
|
10
|
+
import * as Ably from 'ably';
|
|
3
11
|
/**
|
|
4
12
|
* Build the standard transport header set for a message.
|
|
5
13
|
* @param opts - The header values to include.
|
|
@@ -63,6 +71,11 @@ export declare const buildTransportHeaders: (opts: {
|
|
|
63
71
|
* @param opts.inputClientId - ClientId of the triggering input event.
|
|
64
72
|
* @param opts.inputCodecMessageId - Codec-message-id of the triggering input event.
|
|
65
73
|
* @param opts.reason - Terminal reason; stamped on run-end only.
|
|
74
|
+
* @param opts.errorCode - Numeric error code stamped as `error-code` on
|
|
75
|
+
* run-end. Set only when the run ended in error and the agent supplied an
|
|
76
|
+
* error to surface; gives codec-agnostic consumers a baseline failure detail.
|
|
77
|
+
* @param opts.errorMessage - Error message stamped as `error-message` on
|
|
78
|
+
* run-end. Paired with `errorCode`; set under the same condition.
|
|
66
79
|
* @returns A headers record with the lifecycle headers set.
|
|
67
80
|
*/
|
|
68
81
|
export declare const buildLifecycleHeaders: (opts: {
|
|
@@ -75,6 +88,8 @@ export declare const buildLifecycleHeaders: (opts: {
|
|
|
75
88
|
inputClientId?: string;
|
|
76
89
|
inputCodecMessageId?: string;
|
|
77
90
|
reason?: RunEndReason;
|
|
91
|
+
errorCode?: number;
|
|
92
|
+
errorMessage?: string;
|
|
78
93
|
}) => Record<string, string>;
|
|
79
94
|
/** The four run-lifecycle Ably message names. */
|
|
80
95
|
type RunLifecycleName = typeof EVENT_RUN_START | typeof EVENT_RUN_SUSPEND | typeof EVENT_RUN_RESUME | typeof EVENT_RUN_END;
|
|
@@ -88,6 +103,17 @@ type RunLifecycleName = typeof EVENT_RUN_START | typeof EVENT_RUN_SUSPEND | type
|
|
|
88
103
|
* @returns True when `name` is a run-lifecycle event name.
|
|
89
104
|
*/
|
|
90
105
|
export declare const isRunLifecycleName: (name: string | undefined) => name is RunLifecycleName;
|
|
106
|
+
/**
|
|
107
|
+
* Reconstruct the terminal `Ably.ErrorInfo` for a run that ended in error, from
|
|
108
|
+
* its run-end transport headers. Reads the `error-code` / `error-message`
|
|
109
|
+
* headers the agent stamps (see {@link buildLifecycleHeaders}); falls back to a
|
|
110
|
+
* generic code/message when a run ended in error without detail. Single source
|
|
111
|
+
* of truth for the header→ErrorInfo derivation, shared by the client session's
|
|
112
|
+
* `on('error')` emit and the Tree's `RunInfo.error`.
|
|
113
|
+
* @param headers - Transport headers from the inbound run-end message.
|
|
114
|
+
* @returns The reconstructed terminal error.
|
|
115
|
+
*/
|
|
116
|
+
export declare const buildRunEndError: (headers: Record<string, string>) => Ably.ErrorInfo;
|
|
91
117
|
/**
|
|
92
118
|
* Parse an inbound run-lifecycle Ably message into a {@link RunLifecycleEvent}.
|
|
93
119
|
*
|
|
@@ -99,8 +125,11 @@ export declare const isRunLifecycleName: (name: string | undefined) => name is R
|
|
|
99
125
|
* @param headers - Transport headers from the inbound Ably message.
|
|
100
126
|
* @param serial - Ably channel serial of the message, or `undefined` for an
|
|
101
127
|
* optimistic local event. Stamped onto the returned event.
|
|
128
|
+
* @param timestamp - Ably server timestamp (epoch ms) of the message, or
|
|
129
|
+
* `undefined` for an optimistic local event. Stamped onto the returned
|
|
130
|
+
* event; drives the Tree's event-log retention clock.
|
|
102
131
|
* @returns The lifecycle event, or `undefined` when `name` is not a
|
|
103
132
|
* run-lifecycle event name or the message carries no `run-id`.
|
|
104
133
|
*/
|
|
105
|
-
export declare const parseRunLifecycle: (name: string, headers: Record<string, string>, serial: string | undefined) => RunLifecycleEvent | undefined;
|
|
134
|
+
export declare const parseRunLifecycle: (name: string, headers: Record<string, string>, serial: string | undefined, timestamp: number | undefined) => RunLifecycleEvent | undefined;
|
|
106
135
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { ActiveRun, AgentSession, AgentSessionOptions, BranchSelection, CancelRequest, ClientSession, ClientSessionOptions, ConversationNode,
|
|
1
|
+
export type { ActiveRun, AgentSession, AgentSessionOptions, BranchSelection, CancelRequest, ClientSession, ClientSessionOptions, ConversationNode, InputNode, LoadConversationOptions, MessageNode, OutputEvent, PipeOptions, Run, RunEndParams, RunEndReason, RunInfo, RunLifecycleEvent, RunNode, RunNodeState, RunRuntime, RunView, SendOptions, StreamResult, Tree, View, } from './types.js';
|
|
2
2
|
export type { InvocationData } from './invocation.js';
|
|
3
3
|
export { Invocation } from './invocation.js';
|
|
4
4
|
export { createAgentSession } from './agent-session.js';
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* const invocation = Invocation.fromJSON(data);
|
|
12
12
|
* const run = session.createRun(invocation, { signal: req.signal });
|
|
13
13
|
* await run.start();
|
|
14
|
-
* await run.
|
|
14
|
+
* await run.loadConversation(); // walk channel history into the session tree
|
|
15
15
|
* const messages = run.messages;
|
|
16
16
|
* ```
|
|
17
17
|
*
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Logger } from '../../logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* loadHistoryPages — shared low-level history pagination primitive.
|
|
4
|
+
*
|
|
5
|
+
* Consumed by both client (via `load-history.ts`, which layers a complete-
|
|
6
|
+
* domain-message counter on top) and agent (directly, for input-event lookup
|
|
7
|
+
* and conversation hydration). Returns raw Ably messages; does NOT decode.
|
|
8
|
+
*
|
|
9
|
+
* Behaviour:
|
|
10
|
+
* - Attaches the channel (idempotent) then pages via `channel.history()`,
|
|
11
|
+
* using `untilAttach: true` for gapless continuity with any live subscription.
|
|
12
|
+
* - Exposes the underlying pagination as a cursor with `hasNext()` (cheap,
|
|
13
|
+
* no network) and `next()` (one Ably page per call, newest-first within
|
|
14
|
+
* the page).
|
|
15
|
+
* - Per-page failures are retried with bounded exponential backoff; on
|
|
16
|
+
* exhaustion throws `Ably.ErrorInfo` with code `HistoryFetchFailed`.
|
|
17
|
+
* - `signal.aborted` is checked between pages; rejects with
|
|
18
|
+
* `Ably.ErrorInfo` (InvalidArgument) when aborted.
|
|
19
|
+
*
|
|
20
|
+
* Spec: AIT-CT11 / AIT-ST hydration.
|
|
21
|
+
*/
|
|
22
|
+
import * as Ably from 'ably';
|
|
23
|
+
/** Options for {@link loadHistoryPages}. */
|
|
24
|
+
export interface LoadHistoryPagesOptions {
|
|
25
|
+
/** Wire-message limit per Ably page. */
|
|
26
|
+
pageLimit: number;
|
|
27
|
+
/** Set `untilAttach: true` on the underlying history query for gapless continuity with live subscriptions. Default: true. */
|
|
28
|
+
untilAttach?: boolean;
|
|
29
|
+
/** AbortSignal checked between pages. Rejects with InvalidArgument when aborted. */
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
/** Max retries per `page.next()` / initial `history()` failure. Default: 3. */
|
|
32
|
+
maxRetries?: number;
|
|
33
|
+
/** Initial retry backoff in ms (doubled per attempt). Default: 100. */
|
|
34
|
+
retryBackoffMs?: number;
|
|
35
|
+
/** Logger for diagnostic output. */
|
|
36
|
+
logger?: Logger;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Cursor over the channel's history pages.
|
|
40
|
+
*
|
|
41
|
+
* `hasNext()` is cheap (cursor-only, no network); `next()` issues one Ably
|
|
42
|
+
* page fetch (with retry/backoff) and returns its messages. Once `next()`
|
|
43
|
+
* returns `undefined` the cursor is exhausted.
|
|
44
|
+
*/
|
|
45
|
+
export interface HistoryPagesCursor {
|
|
46
|
+
/** True when another Ably page is available (cheap to check; no network). */
|
|
47
|
+
hasNext(): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Fetch the next Ably page's messages (newest-first within the page).
|
|
50
|
+
* Returns `undefined` when no more pages are available or the abort
|
|
51
|
+
* signal has fired.
|
|
52
|
+
*/
|
|
53
|
+
next(): Promise<readonly Ably.InboundMessage[] | undefined>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Page through channel history, returning a cursor over Ably pages.
|
|
57
|
+
*
|
|
58
|
+
* Newest-first within each yielded page (matching Ably's native ordering).
|
|
59
|
+
* Caller drives the cursor — calling `next()` until it returns `undefined`
|
|
60
|
+
* or stopping early when a domain-specific stop condition is met
|
|
61
|
+
* (e.g. complete-message counter satisfied, target codec-message-id found,
|
|
62
|
+
* parent chain walk reaches root).
|
|
63
|
+
*
|
|
64
|
+
* The initial Ably history call is awaited eagerly so the returned cursor
|
|
65
|
+
* already knows whether there are pages available (via `hasNext()`).
|
|
66
|
+
* @param channel - The Ably channel to read history from.
|
|
67
|
+
* @param options - Pagination options.
|
|
68
|
+
* @returns A cursor with `hasNext()` (cheap, cursor-only) and `next()` (fetches one page with retry).
|
|
69
|
+
* @throws {Ably.ErrorInfo} `HistoryFetchFailed` on exhausted retry of the initial fetch, or `InvalidArgument` on signal abort.
|
|
70
|
+
*/
|
|
71
|
+
export declare const loadHistoryPages: (channel: Ably.RealtimeChannel, options: LoadHistoryPagesOptions) => Promise<HistoryPagesCursor>;
|
|
@@ -2,35 +2,40 @@ import { Logger } from '../../logger.js';
|
|
|
2
2
|
import { HistoryPage, LoadHistoryOptions } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* loadHistory — load conversation history from an Ably channel and return
|
|
5
|
-
* the raw
|
|
5
|
+
* the raw Ably messages as a paginated HistoryPage result.
|
|
6
6
|
*
|
|
7
|
-
* This does NOT decode: it pages back through Ably history
|
|
8
|
-
*
|
|
9
|
-
* (oldest-first) to the caller.
|
|
10
|
-
* itself, so load-history only needs
|
|
11
|
-
* counter to decide when to stop paging
|
|
7
|
+
* This does NOT decode: it pages back through Ably history via the shared
|
|
8
|
+
* {@link loadHistoryPages} primitive until `limit` complete messages are
|
|
9
|
+
* present, then hands the raw Ably messages (oldest-first) to the caller.
|
|
10
|
+
* The View re-decodes them into the Tree itself, so load-history only needs
|
|
11
|
+
* a cheap, header-based completion counter to decide when to stop paging.
|
|
12
12
|
*
|
|
13
13
|
* The `limit` option controls the number of complete **messages** per page,
|
|
14
|
-
* not the number of Ably
|
|
14
|
+
* not the number of Ably messages fetched. A message is complete when
|
|
15
15
|
* its terminal wire signal — `status: "complete"` / `"cancelled"`, or a
|
|
16
|
-
* `discrete` create — has been seen. Runs that span a
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* `discrete` create — has been seen. Runs that span a page boundary are
|
|
17
|
+
* handled by the counter requiring both a start and a terminal signal
|
|
18
|
+
* before counting a message complete.
|
|
19
19
|
*
|
|
20
20
|
* Because Ably history returns newest-first, each page's `rawMessages` are
|
|
21
21
|
* reversed to chronological (oldest-first) so the caller can fold them in
|
|
22
22
|
* order.
|
|
23
|
+
*
|
|
24
|
+
* Spec: AIT-CT11, AIT-CT11b.
|
|
23
25
|
*/
|
|
24
26
|
import type * as Ably from 'ably';
|
|
25
27
|
/**
|
|
26
|
-
* Load conversation history from a channel and return the raw
|
|
28
|
+
* Load conversation history from a channel and return the raw Ably messages.
|
|
27
29
|
*
|
|
28
|
-
*
|
|
29
|
-
* `
|
|
30
|
-
*
|
|
30
|
+
* Drives the shared {@link loadHistoryPages} primitive with
|
|
31
|
+
* `untilAttach: true` (gapless continuity with the live subscription) and a
|
|
32
|
+
* Ably message page limit that overprovisions for the many-Ably-messages-per-domain-message
|
|
33
|
+
* ratio. Each `HistoryPage` returned covers up to `limit` complete domain
|
|
34
|
+
* messages; subsequent pages drain over-collected messages from the buffer
|
|
35
|
+
* before pulling more from the iterator.
|
|
31
36
|
*
|
|
32
|
-
* The `limit` option controls the number of complete messages
|
|
33
|
-
*
|
|
37
|
+
* The `limit` option controls the number of complete messages returned per
|
|
38
|
+
* page, not the number of Ably messages fetched.
|
|
34
39
|
* @param channel - The Ably channel to load history from.
|
|
35
40
|
* @param options - Pagination options.
|
|
36
41
|
* @param logger - Logger for diagnostic output.
|
|
@@ -14,7 +14,7 @@ import type * as Ably from 'ably';
|
|
|
14
14
|
* continuation (re-entering an existing run) sets `continuation` and omits the
|
|
15
15
|
* structural `parent` / `forkOf` / `regenerates` fields.
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
interface StartRunMetadata {
|
|
18
18
|
/** Structural parent codec-message-id (fresh run-start only). */
|
|
19
19
|
parent?: string;
|
|
20
20
|
/** Forked user-prompt codec-message-id for an edit (fresh run-start only). */
|
|
@@ -37,9 +37,9 @@ export interface RunManager {
|
|
|
37
37
|
* `ai-run-start` for a fresh run, or `ai-run-resume` when `metadata.continuation`
|
|
38
38
|
* is set (a subsequent invocation re-entering an existing run). A resume omits
|
|
39
39
|
* the structural `parent` / `forkOf` / `regenerates` headers — the original
|
|
40
|
-
* run-start owns the run's structure.
|
|
40
|
+
* run-start owns the run's structure.
|
|
41
41
|
*/
|
|
42
|
-
startRun(runId: string, clientId?: string, controller?: AbortController, metadata?: StartRunMetadata): Promise<
|
|
42
|
+
startRun(runId: string, clientId?: string, controller?: AbortController, metadata?: StartRunMetadata): Promise<void>;
|
|
43
43
|
/**
|
|
44
44
|
* Suspend a run. Publishes run-suspend on the channel and drops the run's
|
|
45
45
|
* active-run entry — the agent process terminates on suspend, so there is no
|
|
@@ -55,17 +55,14 @@ export interface RunManager {
|
|
|
55
55
|
* run-reason header) and drops the run's active-run entry. Carries the same
|
|
56
56
|
* per-invocation attribution as {@link suspendRun} (`invocationId`,
|
|
57
57
|
* `inputClientId`, `inputCodecMessageId`), since run-end is the terminal event
|
|
58
|
-
* of the ending invocation.
|
|
58
|
+
* of the ending invocation. When `reason` is `'error'` and an `error` is
|
|
59
|
+
* supplied, its `code` and `message` are additionally stamped as the
|
|
60
|
+
* `error-code` / `error-message` headers — a codec-agnostic baseline failure
|
|
61
|
+
* detail for consumers; omitting `error` publishes a bare `reason: 'error'`.
|
|
59
62
|
*/
|
|
60
|
-
endRun(runId: string, reason: RunEndReason, invocationId?: string, inputClientId?: string, inputCodecMessageId?: string): Promise<void>;
|
|
61
|
-
/** Get the AbortSignal for a run. */
|
|
62
|
-
getSignal(runId: string): AbortSignal | undefined;
|
|
63
|
+
endRun(runId: string, reason: RunEndReason, invocationId?: string, inputClientId?: string, inputCodecMessageId?: string, error?: Ably.ErrorInfo): Promise<void>;
|
|
63
64
|
/** Get the clientId that owns a run. */
|
|
64
65
|
getClientId(runId: string): string | undefined;
|
|
65
|
-
/** Fire the AbortSignal for a run to cancel any in-flight work. */
|
|
66
|
-
cancel(runId: string): void;
|
|
67
|
-
/** Get all active run IDs. */
|
|
68
|
-
getActiveRunIds(): string[];
|
|
69
66
|
/** Cancel all active runs and clear state. */
|
|
70
67
|
close(): void;
|
|
71
68
|
}
|
|
@@ -76,3 +73,4 @@ export interface RunManager {
|
|
|
76
73
|
* @returns A new {@link RunManager} instance.
|
|
77
74
|
*/
|
|
78
75
|
export declare const createRunManager: (channel: Ably.RealtimeChannel, logger?: Logger) => RunManager;
|
|
76
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Logger } from '../../logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Shared lifecycle plumbing for the client and agent sessions.
|
|
4
|
+
*
|
|
5
|
+
* Both `DefaultClientSession` and `DefaultAgentSession` gate their writes on
|
|
6
|
+
* `connect()` having run, detach their channel best-effort on close, and react
|
|
7
|
+
* to channel continuity loss with the same detection rule and error shape.
|
|
8
|
+
* These helpers own that common machinery so the two sessions cannot drift on
|
|
9
|
+
* the connection guard, the detach-swallow behaviour, or — most importantly —
|
|
10
|
+
* the continuity-loss predicate, which encodes channel protocol semantics
|
|
11
|
+
* (Spec AIT-CT19 / AIT-ST12). Each session keeps its own divergent reaction to
|
|
12
|
+
* continuity loss (the client emits; the agent aborts runs and swaps its Tree).
|
|
13
|
+
*/
|
|
14
|
+
import * as Ably from 'ably';
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a session's connect guard: return the in-flight/settled connect
|
|
17
|
+
* promise, or reject with `InvalidArgument` when `connect()` has not been
|
|
18
|
+
* called. Callers `await` the result before any write.
|
|
19
|
+
* @param connectPromise - The session's connect promise, or `undefined` when not yet connected.
|
|
20
|
+
* @param method - The method name being guarded, for the error message.
|
|
21
|
+
* @returns The connect promise.
|
|
22
|
+
* @throws {Ably.ErrorInfo} `InvalidArgument` when `connectPromise` is `undefined`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const requireConnected: (connectPromise: Promise<void> | undefined, method: string) => Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Detach the session's channel on close, best-effort. `connect()` subscribes
|
|
27
|
+
* (which implicitly attaches), so a detach is only attempted when `connect()`
|
|
28
|
+
* ran. A detach failure (e.g. the channel is already FAILED) must not throw out
|
|
29
|
+
* of `close()`, so it is swallowed and logged at debug.
|
|
30
|
+
* @param channel - The session's channel.
|
|
31
|
+
* @param connectPromise - The session's connect promise; detach is skipped when `undefined`.
|
|
32
|
+
* @param logger - Logger for the swallowed-failure debug line, or `undefined`.
|
|
33
|
+
* @param component - The owning class name, used as the log message prefix.
|
|
34
|
+
*/
|
|
35
|
+
export declare const bestEffortDetach: (channel: Ably.RealtimeChannel, connectPromise: Promise<void> | undefined, logger: Logger | undefined, component: string) => Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Whether a channel state change breaks message continuity:
|
|
38
|
+
* - FAILED, SUSPENDED, DETACHED — no more messages expected (or a gap)
|
|
39
|
+
* - ATTACHED with `resumed: false` (an UPDATE) — messages were lost
|
|
40
|
+
*
|
|
41
|
+
* The initial attach (ATTACHED with no prior attach) is the caller's concern
|
|
42
|
+
* and is not handled here.
|
|
43
|
+
* @param stateChange - The channel state change to classify.
|
|
44
|
+
* @returns True when continuity was lost.
|
|
45
|
+
*/
|
|
46
|
+
export declare const isContinuityLost: (stateChange: Ably.ChannelStateChange) => boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Build the `ChannelContinuityLost` error for a continuity-breaking state
|
|
49
|
+
* change, attaching the state change's `reason` as `cause`.
|
|
50
|
+
* @param stateChange - The continuity-breaking state change.
|
|
51
|
+
* @param verb - The operation that can no longer proceed, for the
|
|
52
|
+
* `unable to <verb>; ...` message (e.g. "deliver events", "continue").
|
|
53
|
+
* @returns The continuity-loss error.
|
|
54
|
+
*/
|
|
55
|
+
export declare const continuityLostError: (stateChange: Ably.ChannelStateChange, verb: string) => Ably.ErrorInfo;
|