@ably/ai-transport 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -111
- package/dist/ably-ai-transport.js +2401 -1387
- package/dist/ably-ai-transport.js.map +1 -1
- package/dist/ably-ai-transport.umd.cjs +1 -1
- package/dist/ably-ai-transport.umd.cjs.map +1 -1
- package/dist/constants.d.ts +116 -42
- package/dist/core/agent.d.ts +44 -0
- package/dist/core/channel-options.d.ts +57 -0
- package/dist/core/codec/codec-event.d.ts +9 -0
- package/dist/core/codec/decoder.d.ts +24 -24
- package/dist/core/codec/define-codec.d.ts +100 -0
- package/dist/core/codec/encoder.d.ts +10 -12
- package/dist/core/codec/field-bag.d.ts +85 -0
- package/dist/core/codec/fields.d.ts +141 -0
- package/dist/core/codec/index.d.ts +8 -2
- package/dist/core/codec/input-descriptor-decoder.d.ts +19 -0
- package/dist/core/codec/input-descriptor-encoder.d.ts +22 -0
- package/dist/core/codec/input-descriptors.d.ts +281 -0
- package/dist/core/codec/lifecycle-tracker.d.ts +10 -9
- package/dist/core/codec/output-descriptor-decoder.d.ts +29 -0
- package/dist/core/codec/output-descriptor-encoder.d.ts +31 -0
- package/dist/core/codec/output-descriptors.d.ts +237 -0
- package/dist/core/codec/types.d.ts +470 -119
- package/dist/core/codec/well-known-inputs.d.ts +52 -0
- package/dist/core/transport/agent-session.d.ts +10 -0
- package/dist/core/transport/agent-view.d.ts +296 -0
- package/dist/core/transport/client-session.d.ts +13 -0
- package/dist/core/transport/decode-fold.d.ts +55 -0
- package/dist/core/transport/headers.d.ts +121 -14
- package/dist/core/transport/index.d.ts +5 -6
- package/dist/core/transport/internal/bounded-map.d.ts +20 -0
- package/dist/core/transport/invocation.d.ts +74 -0
- package/dist/core/transport/load-history-pages.d.ts +71 -0
- package/dist/core/transport/load-history.d.ts +44 -0
- package/dist/core/transport/pipe-stream.d.ts +9 -9
- package/dist/core/transport/run-manager.d.ts +76 -0
- package/dist/core/transport/session-support.d.ts +55 -0
- package/dist/core/transport/tree.d.ts +523 -109
- package/dist/core/transport/types/agent.d.ts +375 -0
- package/dist/core/transport/types/client.d.ts +201 -0
- package/dist/core/transport/types/shared.d.ts +24 -0
- package/dist/core/transport/types/tree.d.ts +357 -0
- package/dist/core/transport/types/view.d.ts +249 -0
- package/dist/core/transport/types.d.ts +13 -553
- package/dist/core/transport/view.d.ts +390 -84
- package/dist/core/transport/wire-log.d.ts +102 -0
- package/dist/errors.d.ts +27 -10
- package/dist/index.d.ts +8 -9
- package/dist/logger.d.ts +12 -0
- package/dist/react/ably-ai-transport-react.js +1365 -1010
- package/dist/react/ably-ai-transport-react.js.map +1 -1
- package/dist/react/ably-ai-transport-react.umd.cjs +1 -1
- package/dist/react/ably-ai-transport-react.umd.cjs.map +1 -1
- package/dist/react/contexts/client-session-context.d.ts +37 -0
- package/dist/react/contexts/client-session-provider.d.ts +56 -0
- package/dist/react/create-session-hooks.d.ts +116 -0
- package/dist/react/index.d.ts +13 -12
- package/dist/react/internal/skipped-session.d.ts +8 -0
- package/dist/react/internal/use-resolved-session.d.ts +36 -0
- package/dist/react/use-ably-messages.d.ts +17 -14
- package/dist/react/use-client-session.d.ts +81 -0
- package/dist/react/use-create-view.d.ts +14 -13
- package/dist/react/use-tree.d.ts +30 -15
- package/dist/react/use-view.d.ts +81 -50
- package/dist/utils.d.ts +48 -71
- package/dist/vercel/ably-ai-transport-vercel.js +3257 -2499
- package/dist/vercel/ably-ai-transport-vercel.js.map +1 -1
- package/dist/vercel/ably-ai-transport-vercel.umd.cjs +1 -1
- package/dist/vercel/ably-ai-transport-vercel.umd.cjs.map +1 -1
- package/dist/vercel/codec/decode-lifecycle.d.ts +9 -0
- package/dist/vercel/codec/events.d.ts +50 -0
- package/dist/vercel/codec/fields.d.ts +44 -0
- package/dist/vercel/codec/fold-content.d.ts +16 -0
- package/dist/vercel/codec/fold-data.d.ts +16 -0
- package/dist/vercel/codec/fold-input.d.ts +67 -0
- package/dist/vercel/codec/fold-lifecycle.d.ts +16 -0
- package/dist/vercel/codec/fold-text.d.ts +16 -0
- package/dist/vercel/codec/fold-tool-input.d.ts +17 -0
- package/dist/vercel/codec/fold-tool-output.d.ts +16 -0
- package/dist/vercel/codec/index.d.ts +7 -20
- package/dist/vercel/codec/inputs.d.ts +11 -0
- package/dist/vercel/codec/outputs.d.ts +11 -0
- package/dist/vercel/codec/reducer-state.d.ts +121 -0
- package/dist/vercel/codec/reducer.d.ts +62 -0
- package/dist/vercel/codec/tool-transitions.d.ts +2 -8
- package/dist/vercel/codec/wire-data.d.ts +34 -0
- package/dist/vercel/index.d.ts +5 -5
- package/dist/vercel/react/ably-ai-transport-vercel-react.js +2859 -9705
- package/dist/vercel/react/ably-ai-transport-vercel-react.js.map +1 -1
- package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs +1 -45
- package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs.map +1 -1
- package/dist/vercel/react/contexts/chat-transport-context.d.ts +9 -7
- package/dist/vercel/react/contexts/chat-transport-provider.d.ts +53 -41
- package/dist/vercel/react/index.d.ts +1 -2
- package/dist/vercel/react/use-chat-transport.d.ts +30 -26
- package/dist/vercel/react/use-message-sync.d.ts +17 -30
- package/dist/vercel/run-end-reason.d.ts +84 -0
- package/dist/vercel/tool-part.d.ts +21 -0
- package/dist/vercel/transport/chat-transport.d.ts +41 -24
- package/dist/vercel/transport/index.d.ts +24 -20
- package/dist/vercel/transport/run-output-stream.d.ts +54 -0
- package/dist/version.d.ts +2 -0
- package/package.json +31 -24
- package/src/constants.ts +124 -51
- package/src/core/agent.ts +92 -0
- package/src/core/channel-options.ts +89 -0
- package/src/core/codec/codec-event.ts +27 -0
- package/src/core/codec/decoder.ts +202 -105
- package/src/core/codec/define-codec.ts +432 -0
- package/src/core/codec/encoder.ts +114 -107
- package/src/core/codec/field-bag.ts +142 -0
- package/src/core/codec/fields.ts +193 -0
- package/src/core/codec/index.ts +56 -6
- package/src/core/codec/input-descriptor-decoder.ts +97 -0
- package/src/core/codec/input-descriptor-encoder.ts +150 -0
- package/src/core/codec/input-descriptors.ts +373 -0
- package/src/core/codec/lifecycle-tracker.ts +10 -9
- package/src/core/codec/output-descriptor-decoder.ts +139 -0
- package/src/core/codec/output-descriptor-encoder.ts +101 -0
- package/src/core/codec/output-descriptors.ts +307 -0
- package/src/core/codec/types.ts +505 -126
- package/src/core/codec/well-known-inputs.ts +96 -0
- package/src/core/transport/agent-session.ts +1085 -0
- package/src/core/transport/agent-view.ts +738 -0
- package/src/core/transport/client-session.ts +780 -0
- package/src/core/transport/decode-fold.ts +101 -0
- package/src/core/transport/headers.ts +234 -22
- package/src/core/transport/index.ts +27 -27
- package/src/core/transport/internal/bounded-map.ts +27 -0
- package/src/core/transport/invocation.ts +98 -0
- package/src/core/transport/load-history-pages.ts +220 -0
- package/src/core/transport/load-history.ts +271 -0
- package/src/core/transport/pipe-stream.ts +63 -39
- package/src/core/transport/run-manager.ts +243 -0
- package/src/core/transport/session-support.ts +96 -0
- package/src/core/transport/tree.ts +1293 -308
- package/src/core/transport/types/agent.ts +434 -0
- package/src/core/transport/types/client.ts +247 -0
- package/src/core/transport/types/shared.ts +27 -0
- package/src/core/transport/types/tree.ts +393 -0
- package/src/core/transport/types/view.ts +288 -0
- package/src/core/transport/types.ts +13 -706
- package/src/core/transport/view.ts +1229 -450
- package/src/core/transport/wire-log.ts +189 -0
- package/src/errors.ts +29 -9
- package/src/event-emitter.ts +3 -2
- package/src/index.ts +86 -42
- package/src/logger.ts +14 -1
- package/src/react/contexts/client-session-context.ts +41 -0
- package/src/react/contexts/client-session-provider.tsx +222 -0
- package/src/react/create-session-hooks.ts +141 -0
- package/src/react/index.ts +24 -13
- package/src/react/internal/skipped-session.ts +62 -0
- package/src/react/internal/use-resolved-session.ts +63 -0
- package/src/react/use-ably-messages.ts +32 -22
- package/src/react/use-client-session.ts +178 -0
- package/src/react/use-create-view.ts +33 -29
- package/src/react/use-tree.ts +61 -30
- package/src/react/use-view.ts +138 -96
- package/src/utils.ts +83 -131
- package/src/vercel/codec/decode-lifecycle.ts +70 -0
- package/src/vercel/codec/events.ts +85 -0
- package/src/vercel/codec/fields.ts +58 -0
- package/src/vercel/codec/fold-content.ts +54 -0
- package/src/vercel/codec/fold-data.ts +46 -0
- package/src/vercel/codec/fold-input.ts +255 -0
- package/src/vercel/codec/fold-lifecycle.ts +85 -0
- package/src/vercel/codec/fold-text.ts +55 -0
- package/src/vercel/codec/fold-tool-input.ts +86 -0
- package/src/vercel/codec/fold-tool-output.ts +79 -0
- package/src/vercel/codec/index.ts +28 -21
- package/src/vercel/codec/inputs.ts +116 -0
- package/src/vercel/codec/outputs.ts +207 -0
- package/src/vercel/codec/reducer-state.ts +169 -0
- package/src/vercel/codec/reducer.ts +191 -0
- package/src/vercel/codec/tool-transitions.ts +3 -14
- package/src/vercel/codec/wire-data.ts +64 -0
- package/src/vercel/index.ts +7 -19
- package/src/vercel/react/contexts/chat-transport-context.ts +8 -7
- package/src/vercel/react/contexts/chat-transport-provider.tsx +87 -59
- package/src/vercel/react/index.ts +3 -5
- package/src/vercel/react/use-chat-transport.ts +44 -66
- package/src/vercel/react/use-message-sync.ts +75 -39
- package/src/vercel/run-end-reason.ts +157 -0
- package/src/vercel/tool-part.ts +25 -0
- package/src/vercel/transport/chat-transport.ts +380 -98
- package/src/vercel/transport/index.ts +38 -37
- package/src/vercel/transport/run-output-stream.ts +169 -0
- package/src/version.ts +2 -0
- package/dist/core/transport/client-transport.d.ts +0 -10
- package/dist/core/transport/decode-history.d.ts +0 -43
- package/dist/core/transport/server-transport.d.ts +0 -7
- package/dist/core/transport/stream-router.d.ts +0 -29
- package/dist/core/transport/turn-manager.d.ts +0 -37
- package/dist/react/contexts/transport-context.d.ts +0 -31
- package/dist/react/contexts/transport-provider.d.ts +0 -49
- package/dist/react/create-transport-hooks.d.ts +0 -124
- package/dist/react/use-active-turns.d.ts +0 -12
- package/dist/react/use-client-transport.d.ts +0 -80
- package/dist/vercel/codec/accumulator.d.ts +0 -21
- package/dist/vercel/codec/decoder.d.ts +0 -22
- package/dist/vercel/codec/encoder.d.ts +0 -41
- package/dist/vercel/react/use-staged-add-tool-approval-response.d.ts +0 -30
- package/dist/vercel/tool-approvals.d.ts +0 -124
- package/dist/vercel/tool-events.d.ts +0 -26
- package/src/core/transport/client-transport.ts +0 -977
- package/src/core/transport/decode-history.ts +0 -485
- package/src/core/transport/server-transport.ts +0 -612
- package/src/core/transport/stream-router.ts +0 -136
- package/src/core/transport/turn-manager.ts +0 -165
- package/src/react/contexts/transport-context.ts +0 -37
- package/src/react/contexts/transport-provider.tsx +0 -164
- package/src/react/create-transport-hooks.ts +0 -144
- package/src/react/use-active-turns.ts +0 -72
- package/src/react/use-client-transport.ts +0 -197
- package/src/vercel/codec/accumulator.ts +0 -588
- package/src/vercel/codec/decoder.ts +0 -618
- package/src/vercel/codec/encoder.ts +0 -410
- package/src/vercel/react/use-staged-add-tool-approval-response.ts +0 -87
- package/src/vercel/tool-approvals.ts +0 -380
- package/src/vercel/tool-events.ts +0 -53
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Types shared across the client, agent, tree, and view layers. */
|
|
2
|
+
|
|
3
|
+
import type * as Ably from 'ably';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Why a run ended.
|
|
7
|
+
*
|
|
8
|
+
* A run-end is terminal — a run that merely pauses awaiting input publishes
|
|
9
|
+
* `ai-run-suspend` instead (see {@link Run.suspend}).
|
|
10
|
+
*
|
|
11
|
+
* - `complete` — the run finished naturally.
|
|
12
|
+
* - `cancelled` — the run was cancelled by a client.
|
|
13
|
+
* - `error` — the run errored.
|
|
14
|
+
*/
|
|
15
|
+
export type RunEndReason = 'complete' | 'cancelled' | 'error';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Passed to a run's `onCancel` hook for authorization decisions.
|
|
19
|
+
* The hook inspects the incoming cancel message and decides whether to
|
|
20
|
+
* allow the targeted run to be cancelled.
|
|
21
|
+
*/
|
|
22
|
+
export interface CancelRequest {
|
|
23
|
+
/** The raw Ably message that carried the cancel signal. */
|
|
24
|
+
message: Ably.InboundMessage;
|
|
25
|
+
/** The runId being cancelled. */
|
|
26
|
+
runId: string;
|
|
27
|
+
}
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/** Conversation-tree types: nodes, the run-lifecycle event, output events, and the Tree contract. */
|
|
2
|
+
|
|
3
|
+
import type * as Ably from 'ably';
|
|
4
|
+
|
|
5
|
+
import type { CodecOutputEvent } from '../../codec/types.js';
|
|
6
|
+
import type { RunEndReason } from './shared.js';
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Run lifecycle events
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Fields common to every {@link RunLifecycleEvent} arm.
|
|
14
|
+
*/
|
|
15
|
+
interface RunLifecycleBase {
|
|
16
|
+
/** The run-id this lifecycle event concerns. */
|
|
17
|
+
runId: string;
|
|
18
|
+
/** The owning client's identity (Ably publisher `clientId`). */
|
|
19
|
+
clientId: string;
|
|
20
|
+
/**
|
|
21
|
+
* The invocation-id this lifecycle event was published under (wire
|
|
22
|
+
* `invocation-id`). Lets consumers correlate the run's lifecycle back to the
|
|
23
|
+
* invocation that drove it; on a run-start the Tree records it on the RunNode
|
|
24
|
+
* at first creation so an optimistic Run exposes the invocation synchronously.
|
|
25
|
+
* Empty string if the wire didn't carry an invocation-id.
|
|
26
|
+
*/
|
|
27
|
+
invocationId: string;
|
|
28
|
+
/**
|
|
29
|
+
* Ably server timestamp (epoch ms) of the lifecycle message; absent for an
|
|
30
|
+
* optimistic local event. Advances the Tree's event-log retention clock and
|
|
31
|
+
* the target run's last-activity time.
|
|
32
|
+
*/
|
|
33
|
+
timestamp?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A structured event describing a run starting, suspending, resuming, or
|
|
38
|
+
* ending. The `type` discriminator (`start` / `suspend` / `resume` / `end`) is
|
|
39
|
+
* the in-memory domain vocabulary and is intentionally distinct from the wire
|
|
40
|
+
* message names (`ai-run-start` / `ai-run-suspend` / `ai-run-resume` /
|
|
41
|
+
* `ai-run-end`) those events are decoded from.
|
|
42
|
+
*/
|
|
43
|
+
export type RunLifecycleEvent =
|
|
44
|
+
| (RunLifecycleBase & {
|
|
45
|
+
type: 'start';
|
|
46
|
+
/**
|
|
47
|
+
* Ably channel serial of the run-start message, or `undefined` for an
|
|
48
|
+
* optimistic local event (no serial assigned yet). The Tree reads it to
|
|
49
|
+
* promote the Run's startSerial.
|
|
50
|
+
*/
|
|
51
|
+
serial: string | undefined;
|
|
52
|
+
/** The codec-message-id of the parent message, if known. Omitted for root runs. */
|
|
53
|
+
parent?: string;
|
|
54
|
+
/**
|
|
55
|
+
* The codec-message-id of the user prompt being forked, when the run is an
|
|
56
|
+
* edit. Carried verbatim from the `fork-of` wire header.
|
|
57
|
+
*/
|
|
58
|
+
forkOf?: string;
|
|
59
|
+
/**
|
|
60
|
+
* The codec-message-id of the assistant message this run regenerates, when
|
|
61
|
+
* the run is a regenerate continuation. Carried verbatim from the
|
|
62
|
+
* `msg-regenerate` wire header. The Tree treats regenerates
|
|
63
|
+
* as continuations (no `forkOf` at the Run level) — the View
|
|
64
|
+
* realises the replacement when materialising messages.
|
|
65
|
+
*/
|
|
66
|
+
regenerates?: string;
|
|
67
|
+
})
|
|
68
|
+
| (RunLifecycleBase & {
|
|
69
|
+
type: 'suspend';
|
|
70
|
+
/**
|
|
71
|
+
* Ably channel serial of the run-suspend message, or `undefined` for an
|
|
72
|
+
* optimistic local event. The Tree reads it to set the Run's endSerial
|
|
73
|
+
* (a suspended run carries the serial at which it paused).
|
|
74
|
+
*/
|
|
75
|
+
serial: string | undefined;
|
|
76
|
+
})
|
|
77
|
+
| (RunLifecycleBase & {
|
|
78
|
+
type: 'resume';
|
|
79
|
+
/**
|
|
80
|
+
* Ably channel serial of the run-resume message, or `undefined` for an
|
|
81
|
+
* optimistic local event. A resume re-enters an existing run; it does not
|
|
82
|
+
* promote the Run's startSerial (the original run-start owns that).
|
|
83
|
+
*/
|
|
84
|
+
serial: string | undefined;
|
|
85
|
+
})
|
|
86
|
+
| (RunLifecycleBase & {
|
|
87
|
+
type: 'end';
|
|
88
|
+
/**
|
|
89
|
+
* Ably channel serial of the run-end message, or `undefined` for an
|
|
90
|
+
* optimistic local event. The Tree reads it to set the Run's endSerial.
|
|
91
|
+
*/
|
|
92
|
+
serial: string | undefined;
|
|
93
|
+
} & (
|
|
94
|
+
| {
|
|
95
|
+
/** Why the run ended — any terminal reason other than `'error'`. */
|
|
96
|
+
reason: Exclude<RunEndReason, 'error'>;
|
|
97
|
+
}
|
|
98
|
+
| {
|
|
99
|
+
/** The run ended in error. */
|
|
100
|
+
reason: 'error';
|
|
101
|
+
/**
|
|
102
|
+
* Terminal error detail, reconstructed from the run-end's
|
|
103
|
+
* `error-code` / `error-message` headers (or a generic fallback
|
|
104
|
+
* when the run ended in error without detail). The Tree records it
|
|
105
|
+
* on the RunNode and exposes it via `RunInfo.error`.
|
|
106
|
+
*/
|
|
107
|
+
error: Ably.ErrorInfo;
|
|
108
|
+
}
|
|
109
|
+
));
|
|
110
|
+
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// Conversation tree (branching history)
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
/** A node in the conversation tree, representing a single domain message. */
|
|
116
|
+
export interface MessageNode<TMessage> {
|
|
117
|
+
/** Discriminator — identifies this as a message node. */
|
|
118
|
+
kind: 'message';
|
|
119
|
+
/** The domain message. */
|
|
120
|
+
message: TMessage;
|
|
121
|
+
/** The codec-message-id of this node — primary key in the tree. */
|
|
122
|
+
codecMessageId: string;
|
|
123
|
+
/** Parent node's codec-message-id (parent), or undefined for root messages. */
|
|
124
|
+
parentId: string | undefined;
|
|
125
|
+
/** The codec-message-id this node forks from (fork-of), or undefined if first version. */
|
|
126
|
+
forkOf: string | undefined;
|
|
127
|
+
/** The transport-tier headers (`extras.ai.transport`) for this message: the run/stream/identity/branching headers set and read by the transport layer. Codec-tier headers (`extras.ai.codec`) are not included. */
|
|
128
|
+
headers: Record<string, string>;
|
|
129
|
+
/**
|
|
130
|
+
* Ably serial for this message. Lexicographically comparable for total order.
|
|
131
|
+
* Used to sort siblings deterministically regardless of delivery/history order.
|
|
132
|
+
* Absent for optimistic messages (set when the server relay arrives).
|
|
133
|
+
*/
|
|
134
|
+
serial: string | undefined;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* A Run's lifecycle state, modelled as one discriminated value so the terminal
|
|
139
|
+
* `error` is carried exactly when `status` is `'error'`. A RunNode is mutated
|
|
140
|
+
* in place, so status and its dependent error move together — transitions
|
|
141
|
+
* reassign `node.state` wholesale rather than setting fields individually.
|
|
142
|
+
*/
|
|
143
|
+
export type RunNodeState =
|
|
144
|
+
| {
|
|
145
|
+
/** `'active'` (streaming), `'suspended'` (paused), or a non-error terminal reason. */
|
|
146
|
+
status: 'active' | 'suspended' | Exclude<RunEndReason, 'error'>;
|
|
147
|
+
}
|
|
148
|
+
| {
|
|
149
|
+
/** Terminal error status. */
|
|
150
|
+
status: 'error';
|
|
151
|
+
/**
|
|
152
|
+
* The run-end's stamped error (or a generic fallback). Exposed to
|
|
153
|
+
* consumers via `RunInfo.error`.
|
|
154
|
+
*/
|
|
155
|
+
error: Ably.ErrorInfo;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* A node in the conversation tree, representing a single Run.
|
|
160
|
+
*
|
|
161
|
+
* A RunNode is keyed by its agent-minted `runId`. Each RunNode owns a per-Run
|
|
162
|
+
* codec {@link TProjection} folded from every event published under that
|
|
163
|
+
* run-id; the SDK extracts the per-message list via {@link Codec.getMessages}
|
|
164
|
+
* when it needs to render messages for that Run.
|
|
165
|
+
*
|
|
166
|
+
* A regenerate is a sibling reply run: it shares its input-node parent
|
|
167
|
+
* ({@link parentCodecMessageId}) with the original reply, so same-parent reply
|
|
168
|
+
* runs form the regenerate group with no `forkOf` involved. (Editing a prompt
|
|
169
|
+
* instead produces a sibling {@link InputNode} via that node's `forkOf`.)
|
|
170
|
+
*/
|
|
171
|
+
export interface RunNode<TProjection> {
|
|
172
|
+
/** Discriminator — identifies this as a reply-run node within {@link ConversationNode}. */
|
|
173
|
+
kind: 'run';
|
|
174
|
+
/** The run-id of this Run — primary key in the tree. */
|
|
175
|
+
runId: string;
|
|
176
|
+
/**
|
|
177
|
+
* The codec-message-id this Run is rooted at — the `parent` header of the
|
|
178
|
+
* first observed message (or the run-start lifecycle event's `parent`
|
|
179
|
+
* field). This is the run's input node's codec-message-id: the user prompt
|
|
180
|
+
* the agent replied to. The Tree uses it for kind-blind reachability and to
|
|
181
|
+
* build the input→reply edge. `undefined` for the root Run.
|
|
182
|
+
*/
|
|
183
|
+
parentCodecMessageId: string | undefined;
|
|
184
|
+
/**
|
|
185
|
+
* The node key of the node this Run replaces, or `undefined` if this Run is
|
|
186
|
+
* not a fork. Populated when the wire's `fork-of` header points at a
|
|
187
|
+
* codec-message-id that has been observed; the Tree resolves it through the
|
|
188
|
+
* codec-message-id → node-key index. Reply-run regenerate siblings do not
|
|
189
|
+
* use this (they group by shared parent) — it carries an explicit fork link
|
|
190
|
+
* when the wire stamps one.
|
|
191
|
+
*/
|
|
192
|
+
forkOf: string | undefined;
|
|
193
|
+
/**
|
|
194
|
+
* The codec-message-id this Run regenerates, or `undefined` for non-regenerate
|
|
195
|
+
* Runs. Populated from the wire's `msg-regenerate` header (and the lifecycle
|
|
196
|
+
* event's `regenerates` field) verbatim — the Tree does not resolve it to a
|
|
197
|
+
* node key because the anchor is a message position, not a node.
|
|
198
|
+
*
|
|
199
|
+
* A regenerate run parents at the SAME input node as the reply it
|
|
200
|
+
* regenerates, so it joins that input's reply runs as a same-parent sibling;
|
|
201
|
+
* the message named by `regeneratesCodecMessageId` is replaced by this Run's
|
|
202
|
+
* content when the View materialises the chain into messages (Spec: AIT-CT13d).
|
|
203
|
+
*/
|
|
204
|
+
regeneratesCodecMessageId: string | undefined;
|
|
205
|
+
/**
|
|
206
|
+
* Identity of the Ably client that started this Run, sourced from the
|
|
207
|
+
* `run-client-id` wire header (or the run-start lifecycle event's
|
|
208
|
+
* `clientId` field). Set once at Run creation and never updated; persists
|
|
209
|
+
* through the Run's lifecycle, including after `run-end`. Empty string if
|
|
210
|
+
* the wire didn't carry a client id.
|
|
211
|
+
*/
|
|
212
|
+
clientId: string;
|
|
213
|
+
/**
|
|
214
|
+
* Run lifecycle state — see {@link RunNodeState}. `'active'` until a terminal
|
|
215
|
+
* event; `'suspended'` while paused (a continuation re-activates it);
|
|
216
|
+
* otherwise the run-end reason, carrying `error` when that reason is
|
|
217
|
+
* `'error'`.
|
|
218
|
+
*/
|
|
219
|
+
state: RunNodeState;
|
|
220
|
+
/** Per-Run codec projection. Folded by the Tree from every event published under this run-id. */
|
|
221
|
+
projection: TProjection;
|
|
222
|
+
/**
|
|
223
|
+
* The agent-minted invocationId observed for this Run (wire `invocation-id`).
|
|
224
|
+
* The agent mints it, so an optimistic Run starts with an empty id; it is
|
|
225
|
+
* adopted from the agent's `ai-run-start` (or set at creation when the Run is
|
|
226
|
+
* first seen from a wire event carrying one) and never reassigned thereafter.
|
|
227
|
+
* Empty string until run-start arrives, or if the wire didn't carry an
|
|
228
|
+
* invocation-id.
|
|
229
|
+
*/
|
|
230
|
+
invocationId: string;
|
|
231
|
+
/** Ably serial of the first observed message tagged with this run-id. Absent for optimistic Runs. */
|
|
232
|
+
startSerial: string | undefined;
|
|
233
|
+
/** Ably serial of the run-end lifecycle event, if observed. */
|
|
234
|
+
endSerial: string | undefined;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* A node in the conversation tree, representing a single user input (prompt).
|
|
239
|
+
*
|
|
240
|
+
* An input node owns the user's prompt for one turn. It is keyed by the
|
|
241
|
+
* client-owned `codec-message-id` and never carries a run-id — the agent mints
|
|
242
|
+
* the run-id for the reply, which becomes a separate {@link RunNode} parented to
|
|
243
|
+
* this input node. An edit of a prompt is a sibling input node (via `forkOf`).
|
|
244
|
+
*
|
|
245
|
+
* Like a {@link RunNode}, it carries its own per-input codec {@link TProjection}
|
|
246
|
+
* folded from the input event(s) published under its codec-message-id; the SDK
|
|
247
|
+
* extracts the per-message list via {@link Codec.getMessages} when rendering.
|
|
248
|
+
*/
|
|
249
|
+
export interface InputNode<TProjection> {
|
|
250
|
+
/** Discriminator — identifies this as an input node within {@link ConversationNode}. */
|
|
251
|
+
kind: 'input';
|
|
252
|
+
/** The codec-message-id of this input — primary key in the tree. */
|
|
253
|
+
codecMessageId: string;
|
|
254
|
+
/**
|
|
255
|
+
* The codec-message-id of the node this input hangs off (its structural
|
|
256
|
+
* parent — the immediately preceding reply run on this chain), or `undefined`
|
|
257
|
+
* for the first input in a conversation. Used for kind-blind tree
|
|
258
|
+
* reachability alongside {@link RunNode.parentCodecMessageId}.
|
|
259
|
+
*/
|
|
260
|
+
parentCodecMessageId: string | undefined;
|
|
261
|
+
/**
|
|
262
|
+
* The codec-message-id this input forks from when it is an edit of an earlier
|
|
263
|
+
* prompt, or `undefined` if it is the first version. Sibling input nodes
|
|
264
|
+
* (alternate prompts) share the same `forkOf` anchor.
|
|
265
|
+
*/
|
|
266
|
+
forkOf: string | undefined;
|
|
267
|
+
/** Per-input codec projection. Folded by the Tree from every input event published under this codec-message-id. */
|
|
268
|
+
projection: TProjection;
|
|
269
|
+
/** Ably serial of the first observed message for this input. Absent for optimistic (locally-created) inputs. */
|
|
270
|
+
serial: string | undefined;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* A node in the conversation tree: either a user {@link InputNode} or an agent
|
|
275
|
+
* {@link RunNode}. Narrow on `kind` (`'input'` vs `'run'`) before reading
|
|
276
|
+
* kind-specific fields.
|
|
277
|
+
*/
|
|
278
|
+
export type ConversationNode<TProjection> = InputNode<TProjection> | RunNode<TProjection>;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Payload of the Tree's `output` event: the decoded agent outputs folded
|
|
282
|
+
* for a Run from a single inbound message, carrying the routing metadata a
|
|
283
|
+
* consumer needs to attribute or stream them.
|
|
284
|
+
*/
|
|
285
|
+
export interface OutputEvent<TOutput extends CodecOutputEvent> {
|
|
286
|
+
/**
|
|
287
|
+
* The runId the outputs were folded into, or `undefined` when the fold was
|
|
288
|
+
* into a user input node (which carries no run-id — the agent mints run-ids).
|
|
289
|
+
* An input fold always has empty {@link events}; consumers route by
|
|
290
|
+
* {@link inputCodecMessageId}, not this.
|
|
291
|
+
*/
|
|
292
|
+
runId: string | undefined;
|
|
293
|
+
/**
|
|
294
|
+
* The codec-message-id of the input event that triggered this run — the
|
|
295
|
+
* agent's `input-codec-message-id` header. This is the stable key the client
|
|
296
|
+
* owns from send time (before the agent mints the runId), so the output
|
|
297
|
+
* stream can attribute outputs to the request that produced them. Distinct
|
|
298
|
+
* from {@link runId}: causal (which input produced these outputs) rather than
|
|
299
|
+
* the run's own identity. `undefined` when the carrying message had no such
|
|
300
|
+
* header — e.g. a purely-optimistic local fold with no wire echo yet.
|
|
301
|
+
*/
|
|
302
|
+
inputCodecMessageId: string | undefined;
|
|
303
|
+
/**
|
|
304
|
+
* The `codec-message-id` the outputs were published under, or `undefined`
|
|
305
|
+
* when the message carried none.
|
|
306
|
+
*/
|
|
307
|
+
codecMessageId: string | undefined;
|
|
308
|
+
/**
|
|
309
|
+
* Ably channel serial of the message that carried the outputs, or
|
|
310
|
+
* `undefined` for an optimistic local fold (no serial assigned yet).
|
|
311
|
+
*/
|
|
312
|
+
serial: string | undefined;
|
|
313
|
+
/**
|
|
314
|
+
* The decoded agent outputs from this message, in wire order. Empty when
|
|
315
|
+
* the folded message carried only inputs (e.g. an optimistic user
|
|
316
|
+
* message); the event still fires so consumers can observe that the Run's
|
|
317
|
+
* projection changed.
|
|
318
|
+
*/
|
|
319
|
+
events: TOutput[];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Materializes a branching conversation tree from a flat oplog of Ably
|
|
324
|
+
* messages. Each turn is two nodes: a user {@link InputNode} keyed by its
|
|
325
|
+
* client-owned codec-message-id and an agent {@link RunNode} keyed by the
|
|
326
|
+
* agent-minted run-id, parented to the input node.
|
|
327
|
+
*
|
|
328
|
+
* The Tree owns the complete conversation state across every observed node.
|
|
329
|
+
* Each node holds a per-node codec {@link TProjection} which the Tree folds
|
|
330
|
+
* from inbound events. The View walks the parent chain to extract a flat
|
|
331
|
+
* message list for rendering.
|
|
332
|
+
*/
|
|
333
|
+
export interface Tree<TOutput extends CodecOutputEvent, TProjection> {
|
|
334
|
+
/** Get a Run by runId, or undefined if not found. */
|
|
335
|
+
getRunNode(runId: string): RunNode<TProjection> | undefined;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Get the node that owns a given codec-message-id (via the Tree's
|
|
339
|
+
* codecMessageId index), or undefined if the codec-message-id hasn't been
|
|
340
|
+
* observed. The result is a {@link ConversationNode} union: narrow on `kind`
|
|
341
|
+
* (`'input'` vs `'run'`) before reading kind-specific fields.
|
|
342
|
+
*/
|
|
343
|
+
getNodeByCodecMessageId(codecMessageId: string): ConversationNode<TProjection> | undefined;
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Get the sibling group (both kinds) the node keyed by `key` belongs to:
|
|
347
|
+
* edit versions for an input node (forkOf-linked, same parent), regenerate
|
|
348
|
+
* runs for a reply run (same input-node parent). Ordered oldest-first by
|
|
349
|
+
* serial; a single-element array when the node has no siblings. Empty when
|
|
350
|
+
* `key` is unknown. Narrow each node on `kind` before reading kind-specific
|
|
351
|
+
* fields.
|
|
352
|
+
* @param key - The node key ({@link RunNode.runId} or {@link InputNode.codecMessageId}).
|
|
353
|
+
* @returns The ordered sibling nodes.
|
|
354
|
+
*/
|
|
355
|
+
getSiblingNodes(key: string): ConversationNode<TProjection>[];
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Look up the raw Ably message that carried the given `event-id` header,
|
|
359
|
+
* if the Tree has observed it. Populated incrementally as messages arrive
|
|
360
|
+
* through the Tree's `ably-message` channel; not bounded except by the
|
|
361
|
+
* Tree's lifetime. Used by the agent's input-event lookup to find a
|
|
362
|
+
* triggering input message by id without scanning a separate buffer.
|
|
363
|
+
* @param eventId - The `event-id` header value to look up.
|
|
364
|
+
* @returns The matching raw Ably message, or undefined when the Tree has
|
|
365
|
+
* not observed an event with that id.
|
|
366
|
+
*/
|
|
367
|
+
findAblyMessageByEventId(eventId: string): Ably.InboundMessage | undefined;
|
|
368
|
+
|
|
369
|
+
// --- Events ---
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Subscribe to tree structural changes (Run insert, delete, sort-reorder,
|
|
373
|
+
* startSerial promotion, run-start metadata backfill). Does NOT fire on
|
|
374
|
+
* content-only folds (streaming chunks) or on run-end status changes —
|
|
375
|
+
* those flow through `output` and `run` respectively.
|
|
376
|
+
*/
|
|
377
|
+
on(event: 'update', handler: () => void): () => void;
|
|
378
|
+
|
|
379
|
+
/** Subscribe to raw Ably messages arriving on the channel. */
|
|
380
|
+
on(event: 'ably-message', handler: (msg: Ably.InboundMessage) => void): () => void;
|
|
381
|
+
|
|
382
|
+
/** Subscribe to run lifecycle events (start, suspend, resume, and end). */
|
|
383
|
+
on(event: 'run', handler: (event: RunLifecycleEvent) => void): () => void;
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Subscribe to decoded agent outputs as they are folded into a Run.
|
|
387
|
+
* Fires once per inbound message after its fold, carrying the message's
|
|
388
|
+
* output events plus routing metadata (runId, codec-message-id, serial).
|
|
389
|
+
* Fires with an empty `events` array for inputs-only folds so it can also
|
|
390
|
+
* serve as a projection-changed signal.
|
|
391
|
+
*/
|
|
392
|
+
on(event: 'output', handler: (event: OutputEvent<TOutput>) => void): () => void;
|
|
393
|
+
}
|