@astralform/js 4.9.0 → 5.0.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/dist/index.cjs +468 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +145 -4
- package/dist/index.d.ts +145 -4
- package/dist/index.js +468 -96
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -792,6 +792,24 @@ interface ConversationEvent {
|
|
|
792
792
|
data: Record<string, unknown>;
|
|
793
793
|
}
|
|
794
794
|
interface SendOptions$1 extends ModelChoiceOptions {
|
|
795
|
+
/**
|
|
796
|
+
* Which conversation this turn belongs to. Defaults to the session's current
|
|
797
|
+
* one.
|
|
798
|
+
*
|
|
799
|
+
* ⚠️ BEHAVIOR CHANGE: passing this now RELOCATES the session. A value
|
|
800
|
+
* different from the current one sets `session.conversationId`, DISCARDS
|
|
801
|
+
* `session.messages` (the old conversation's list is not that conversation's
|
|
802
|
+
* history), and invalidates any `loadConversation` still in flight.
|
|
803
|
+
* Previously it addressed a single turn elsewhere and left the session where
|
|
804
|
+
* it was. After a successful send the list holds only that turn, so load the
|
|
805
|
+
* conversation if you need its history.
|
|
806
|
+
*
|
|
807
|
+
* The change is deliberate: `onSessionEvent` tags every emitted event with
|
|
808
|
+
* `session.conversationId`, so a turn sent elsewhere without moving the
|
|
809
|
+
* pointer streamed its events back under the wrong conversation. Addressing
|
|
810
|
+
* one turn away from the session is not something the session can honestly
|
|
811
|
+
* represent while it has a single pointer, so the send now moves it.
|
|
812
|
+
*/
|
|
795
813
|
conversationId?: string;
|
|
796
814
|
enabledClientTools?: string[];
|
|
797
815
|
uploadIds?: string[];
|
|
@@ -1115,6 +1133,17 @@ declare class ChatSession {
|
|
|
1115
1133
|
/** True while ``loadMoreConversations`` is in flight. */
|
|
1116
1134
|
isLoadingConversations: boolean;
|
|
1117
1135
|
messages: Message[];
|
|
1136
|
+
/**
|
|
1137
|
+
* Which conversation ``messages`` currently holds.
|
|
1138
|
+
*
|
|
1139
|
+
* Distinct from ``conversationId``, and the distinction is the point:
|
|
1140
|
+
* ``loadConversation`` moves the POINTER synchronously and installs the LIST
|
|
1141
|
+
* an await later, so for the whole duration of every load the two disagree.
|
|
1142
|
+
* Anything pairing a message with a conversation — ``regenerate`` above all —
|
|
1143
|
+
* has to read this one, or it will pair the previous conversation's last
|
|
1144
|
+
* message with the new conversation's id.
|
|
1145
|
+
*/
|
|
1146
|
+
messagesConversationId: string | null;
|
|
1118
1147
|
isStreaming: boolean;
|
|
1119
1148
|
agentStatus: AgentStatus | null;
|
|
1120
1149
|
agents: AgentInfo[];
|
|
@@ -1147,6 +1176,49 @@ declare class ChatSession {
|
|
|
1147
1176
|
* is discarded instead.
|
|
1148
1177
|
*/
|
|
1149
1178
|
private conversationsGeneration;
|
|
1179
|
+
/**
|
|
1180
|
+
* Bumped by every ``loadConversation`` call, so an out-of-order fetch can
|
|
1181
|
+
* tell it is no longer the newest one and drop its result. Separate from
|
|
1182
|
+
* ``conversationsGeneration``, which guards the conversation LIST.
|
|
1183
|
+
*/
|
|
1184
|
+
private loadGeneration;
|
|
1185
|
+
/**
|
|
1186
|
+
* Ids of locally-created user messages the server has not acknowledged yet.
|
|
1187
|
+
*
|
|
1188
|
+
* Arrival time cannot answer "could the reply have included this?" on its
|
|
1189
|
+
* own. Every `loadConversation` in `StreamManager` sits behind the
|
|
1190
|
+
* active-job probe, so the ORDINARY ordering is that a send lands BEFORE the
|
|
1191
|
+
* load starts — and an arrival-time rule drops exactly those, losing the
|
|
1192
|
+
* prompt the user just sent while its stream is still running. Membership
|
|
1193
|
+
* here is set by `send` and cleared when a server row turns up carrying the
|
|
1194
|
+
* same turn, so the keep-decision no longer depends on which side of the
|
|
1195
|
+
* fetch the push landed on.
|
|
1196
|
+
*
|
|
1197
|
+
* The value is `serverRowsKnown` as of the `message_stop` that proved the
|
|
1198
|
+
* row committed, or 0 until then — including after the job response, which
|
|
1199
|
+
* hands back the id but starts the loop as a background task and so proves
|
|
1200
|
+
* nothing about the row. That stamp is what separates "the snapshot predates
|
|
1201
|
+
* the row" from "the server does not have this row" — see
|
|
1202
|
+
* `loadConversation`.
|
|
1203
|
+
*
|
|
1204
|
+
* It is an ANNOTATION ON `this.messages`: reconciliation only ever consults
|
|
1205
|
+
* entries of that array, so an id whose message has left it is dead weight.
|
|
1206
|
+
* `setMessages` is the single place the array is replaced, and it prunes.
|
|
1207
|
+
*/
|
|
1208
|
+
private pendingUserMessages;
|
|
1209
|
+
/**
|
|
1210
|
+
* Bumped once per completed turn, at `message_stop`, so a fetch can record
|
|
1211
|
+
* what was proven when it was ISSUED. A row proven committed before the
|
|
1212
|
+
* fetch went out must appear in its snapshot; one proven after may
|
|
1213
|
+
* legitimately be missing.
|
|
1214
|
+
*/
|
|
1215
|
+
private serverRowsKnown;
|
|
1216
|
+
/**
|
|
1217
|
+
* Replace the message list, keeping `pendingUserMessages` an annotation on
|
|
1218
|
+
* it. Every removal from the array goes through here — `push` is the only
|
|
1219
|
+
* other mutation and it cannot orphan an id.
|
|
1220
|
+
*/
|
|
1221
|
+
private setMessages;
|
|
1150
1222
|
private accumulatedText;
|
|
1151
1223
|
private currentTextPath;
|
|
1152
1224
|
private handlers;
|
|
@@ -1180,6 +1252,11 @@ declare class ChatSession {
|
|
|
1180
1252
|
* Consume a single SSE stream to exhaustion. Returns whether a terminal
|
|
1181
1253
|
* event (``message_stop`` / ``error``) was seen, so the caller can decide
|
|
1182
1254
|
* whether an ended stream means "turn done" vs "dropped, reconnect".
|
|
1255
|
+
*
|
|
1256
|
+
* ``onStall`` aborts the per-attempt connection: if no event arrives within
|
|
1257
|
+
* SSE_STALL_TIMEOUT_MS (backend keepalives land every 15s), the stream is a
|
|
1258
|
+
* zombie — ``reader.read()`` will never settle — so we kill the fetch and
|
|
1259
|
+
* throw a ConnectionError, feeding the caller's reconnect-from-lastSeq loop.
|
|
1183
1260
|
*/
|
|
1184
1261
|
private pumpStream;
|
|
1185
1262
|
/** Sleep for ``ms``, resolving early if the turn is aborted mid-backoff. */
|
|
@@ -1200,9 +1277,15 @@ declare class ChatSession {
|
|
|
1200
1277
|
* the pure wire → ChatEvent mapping can live in translate.ts and be reused
|
|
1201
1278
|
* by the replay path.
|
|
1202
1279
|
*
|
|
1203
|
-
* ``
|
|
1204
|
-
*
|
|
1205
|
-
*
|
|
1280
|
+
* ``promptMessageId`` is the id of the USER turn that started this job —
|
|
1281
|
+
* `POST /v1/jobs` returns it and the backend tags the prompt with it
|
|
1282
|
+
* (`HumanMessage(content=..., id=message_id)`), which is what lets a restore
|
|
1283
|
+
* pair a job with its prompt by id instead of by position. It was previously
|
|
1284
|
+
* documented here as the ASSISTANT's id and used as one; there is no
|
|
1285
|
+
* server-assigned assistant id on the wire, so that row gets a local one.
|
|
1286
|
+
* Empty in the reconnect and conversation-switch replay paths, where the
|
|
1287
|
+
* messages have already been loaded from REST and must not be re-pushed —
|
|
1288
|
+
* so it doubles as the "is this a live send?" gate.
|
|
1206
1289
|
*/
|
|
1207
1290
|
private applyWireSideEffects;
|
|
1208
1291
|
private executeClientTools;
|
|
@@ -1218,8 +1301,26 @@ declare class ChatSession {
|
|
|
1218
1301
|
reconnectToJob(jobId: string): Promise<void>;
|
|
1219
1302
|
/** Detach from the SSE stream without cancelling the job. */
|
|
1220
1303
|
detach(): void;
|
|
1221
|
-
/**
|
|
1304
|
+
/**
|
|
1305
|
+
* Cancel the running turn: stop the job server-side and tear the stream
|
|
1306
|
+
* down, WITHOUT ending the session. A turn-level cancel is not a
|
|
1307
|
+
* session-level teardown, so unlike `disconnect()` this leaves the protocol
|
|
1308
|
+
* registry alone — the SDK never auto-registers adapters, so clearing them
|
|
1309
|
+
* on a Stop press would silently kill embedded-resource rendering for the
|
|
1310
|
+
* rest of the session with nothing to re-register it.
|
|
1311
|
+
*/
|
|
1312
|
+
cancelTurn(): void;
|
|
1313
|
+
/** Stop the job and end the session's activity (explicit user action). */
|
|
1222
1314
|
disconnect(): void;
|
|
1315
|
+
/**
|
|
1316
|
+
* A pointer move happened above this layer, so any `loadConversation` in
|
|
1317
|
+
* flight must lose to it. `StreamManager` owns a pointer of its own and
|
|
1318
|
+
* moves it before this one; without this the two halves would gate on
|
|
1319
|
+
* counters that bump at different instants — `generation` synchronously in
|
|
1320
|
+
* `setActiveConversation`, `loadGeneration` only once the switch's own load
|
|
1321
|
+
* actually runs, which is behind the active-job probe.
|
|
1322
|
+
*/
|
|
1323
|
+
invalidateLoadsInFlight(): void;
|
|
1223
1324
|
createNewConversation(): Promise<string>;
|
|
1224
1325
|
/**
|
|
1225
1326
|
* Replay one completed turn's already-fetched events, synchronously.
|
|
@@ -1396,6 +1497,12 @@ declare class StreamManager {
|
|
|
1396
1497
|
private _backgroundJobs;
|
|
1397
1498
|
private handlers;
|
|
1398
1499
|
private unsub;
|
|
1500
|
+
/**
|
|
1501
|
+
* Bumped every time the active conversation moves. An async sequence that
|
|
1502
|
+
* captures it can then tell, at each await boundary, whether it is still the
|
|
1503
|
+
* one the user is waiting on — see ``restore``.
|
|
1504
|
+
*/
|
|
1505
|
+
private generation;
|
|
1399
1506
|
constructor(session: ChatSession);
|
|
1400
1507
|
get state(): StreamState;
|
|
1401
1508
|
get activeConversationId(): string | null;
|
|
@@ -1427,6 +1534,15 @@ declare class StreamManager {
|
|
|
1427
1534
|
switchTo(conversationId: string, opts?: {
|
|
1428
1535
|
skipHistoryReplay?: boolean;
|
|
1429
1536
|
}): Promise<void>;
|
|
1537
|
+
/**
|
|
1538
|
+
* Create a conversation and make it active.
|
|
1539
|
+
*
|
|
1540
|
+
* The returned id is NOT guaranteed to be the active conversation: if a
|
|
1541
|
+
* switch lands inside the storage round-trip, this declines the pointer move
|
|
1542
|
+
* so the newer one wins, and no `conversationChanged` fires for the new id.
|
|
1543
|
+
* A caller that routes on the return value should `switchTo(id)` rather than
|
|
1544
|
+
* assume it is current — that call is not a no-op in the declined case.
|
|
1545
|
+
*/
|
|
1430
1546
|
createConversation(): Promise<string>;
|
|
1431
1547
|
/**
|
|
1432
1548
|
* Rename a conversation. Purely a relabel — no active-conversation or
|
|
@@ -1436,6 +1552,31 @@ declare class StreamManager {
|
|
|
1436
1552
|
deleteConversation(id: string): Promise<void>;
|
|
1437
1553
|
stop(): void;
|
|
1438
1554
|
destroy(): void;
|
|
1555
|
+
/**
|
|
1556
|
+
* Park a streaming turn as a background job and detach from its SSE stream.
|
|
1557
|
+
*
|
|
1558
|
+
* Every method that relocates the active conversation has to do this before
|
|
1559
|
+
* announcing a new state. Announcing `idle` while `session.isStreaming` is
|
|
1560
|
+
* still true is worse than announcing nothing: `manager.send` no longer bails
|
|
1561
|
+
* on the streaming state, calls `session.send`, and THAT bails on its own
|
|
1562
|
+
* `isStreaming` — so the message is never posted, no error is emitted, and
|
|
1563
|
+
* the composer looks ready the whole time.
|
|
1564
|
+
*/
|
|
1565
|
+
private detachStreamingTurn;
|
|
1566
|
+
/**
|
|
1567
|
+
* Announce `idle` unless a turn is actually streaming.
|
|
1568
|
+
*
|
|
1569
|
+
* A `send` can land inside any of the switch paths — the fast path most
|
|
1570
|
+
* easily, since it deliberately stays out of `restoring` and so leaves the
|
|
1571
|
+
* composer live for the whole probe. `send` sets `streaming` and does not
|
|
1572
|
+
* bump the generation, so the path resumes, passes its supersession check,
|
|
1573
|
+
* and would announce a ready composer over a running stream. From there
|
|
1574
|
+
* `finalizeStream` and the `message_stop` branch both no-op (they only act
|
|
1575
|
+
* on `streaming`), so it stays `idle` for the whole turn — and the next send
|
|
1576
|
+
* reaches `session.send`, which bails on its own `isStreaming`: message
|
|
1577
|
+
* never posted, no error, composer ready throughout.
|
|
1578
|
+
*/
|
|
1579
|
+
private settleIdle;
|
|
1439
1580
|
private finalizeStream;
|
|
1440
1581
|
private restore;
|
|
1441
1582
|
private setActiveConversation;
|
package/dist/index.d.ts
CHANGED
|
@@ -792,6 +792,24 @@ interface ConversationEvent {
|
|
|
792
792
|
data: Record<string, unknown>;
|
|
793
793
|
}
|
|
794
794
|
interface SendOptions$1 extends ModelChoiceOptions {
|
|
795
|
+
/**
|
|
796
|
+
* Which conversation this turn belongs to. Defaults to the session's current
|
|
797
|
+
* one.
|
|
798
|
+
*
|
|
799
|
+
* ⚠️ BEHAVIOR CHANGE: passing this now RELOCATES the session. A value
|
|
800
|
+
* different from the current one sets `session.conversationId`, DISCARDS
|
|
801
|
+
* `session.messages` (the old conversation's list is not that conversation's
|
|
802
|
+
* history), and invalidates any `loadConversation` still in flight.
|
|
803
|
+
* Previously it addressed a single turn elsewhere and left the session where
|
|
804
|
+
* it was. After a successful send the list holds only that turn, so load the
|
|
805
|
+
* conversation if you need its history.
|
|
806
|
+
*
|
|
807
|
+
* The change is deliberate: `onSessionEvent` tags every emitted event with
|
|
808
|
+
* `session.conversationId`, so a turn sent elsewhere without moving the
|
|
809
|
+
* pointer streamed its events back under the wrong conversation. Addressing
|
|
810
|
+
* one turn away from the session is not something the session can honestly
|
|
811
|
+
* represent while it has a single pointer, so the send now moves it.
|
|
812
|
+
*/
|
|
795
813
|
conversationId?: string;
|
|
796
814
|
enabledClientTools?: string[];
|
|
797
815
|
uploadIds?: string[];
|
|
@@ -1115,6 +1133,17 @@ declare class ChatSession {
|
|
|
1115
1133
|
/** True while ``loadMoreConversations`` is in flight. */
|
|
1116
1134
|
isLoadingConversations: boolean;
|
|
1117
1135
|
messages: Message[];
|
|
1136
|
+
/**
|
|
1137
|
+
* Which conversation ``messages`` currently holds.
|
|
1138
|
+
*
|
|
1139
|
+
* Distinct from ``conversationId``, and the distinction is the point:
|
|
1140
|
+
* ``loadConversation`` moves the POINTER synchronously and installs the LIST
|
|
1141
|
+
* an await later, so for the whole duration of every load the two disagree.
|
|
1142
|
+
* Anything pairing a message with a conversation — ``regenerate`` above all —
|
|
1143
|
+
* has to read this one, or it will pair the previous conversation's last
|
|
1144
|
+
* message with the new conversation's id.
|
|
1145
|
+
*/
|
|
1146
|
+
messagesConversationId: string | null;
|
|
1118
1147
|
isStreaming: boolean;
|
|
1119
1148
|
agentStatus: AgentStatus | null;
|
|
1120
1149
|
agents: AgentInfo[];
|
|
@@ -1147,6 +1176,49 @@ declare class ChatSession {
|
|
|
1147
1176
|
* is discarded instead.
|
|
1148
1177
|
*/
|
|
1149
1178
|
private conversationsGeneration;
|
|
1179
|
+
/**
|
|
1180
|
+
* Bumped by every ``loadConversation`` call, so an out-of-order fetch can
|
|
1181
|
+
* tell it is no longer the newest one and drop its result. Separate from
|
|
1182
|
+
* ``conversationsGeneration``, which guards the conversation LIST.
|
|
1183
|
+
*/
|
|
1184
|
+
private loadGeneration;
|
|
1185
|
+
/**
|
|
1186
|
+
* Ids of locally-created user messages the server has not acknowledged yet.
|
|
1187
|
+
*
|
|
1188
|
+
* Arrival time cannot answer "could the reply have included this?" on its
|
|
1189
|
+
* own. Every `loadConversation` in `StreamManager` sits behind the
|
|
1190
|
+
* active-job probe, so the ORDINARY ordering is that a send lands BEFORE the
|
|
1191
|
+
* load starts — and an arrival-time rule drops exactly those, losing the
|
|
1192
|
+
* prompt the user just sent while its stream is still running. Membership
|
|
1193
|
+
* here is set by `send` and cleared when a server row turns up carrying the
|
|
1194
|
+
* same turn, so the keep-decision no longer depends on which side of the
|
|
1195
|
+
* fetch the push landed on.
|
|
1196
|
+
*
|
|
1197
|
+
* The value is `serverRowsKnown` as of the `message_stop` that proved the
|
|
1198
|
+
* row committed, or 0 until then — including after the job response, which
|
|
1199
|
+
* hands back the id but starts the loop as a background task and so proves
|
|
1200
|
+
* nothing about the row. That stamp is what separates "the snapshot predates
|
|
1201
|
+
* the row" from "the server does not have this row" — see
|
|
1202
|
+
* `loadConversation`.
|
|
1203
|
+
*
|
|
1204
|
+
* It is an ANNOTATION ON `this.messages`: reconciliation only ever consults
|
|
1205
|
+
* entries of that array, so an id whose message has left it is dead weight.
|
|
1206
|
+
* `setMessages` is the single place the array is replaced, and it prunes.
|
|
1207
|
+
*/
|
|
1208
|
+
private pendingUserMessages;
|
|
1209
|
+
/**
|
|
1210
|
+
* Bumped once per completed turn, at `message_stop`, so a fetch can record
|
|
1211
|
+
* what was proven when it was ISSUED. A row proven committed before the
|
|
1212
|
+
* fetch went out must appear in its snapshot; one proven after may
|
|
1213
|
+
* legitimately be missing.
|
|
1214
|
+
*/
|
|
1215
|
+
private serverRowsKnown;
|
|
1216
|
+
/**
|
|
1217
|
+
* Replace the message list, keeping `pendingUserMessages` an annotation on
|
|
1218
|
+
* it. Every removal from the array goes through here — `push` is the only
|
|
1219
|
+
* other mutation and it cannot orphan an id.
|
|
1220
|
+
*/
|
|
1221
|
+
private setMessages;
|
|
1150
1222
|
private accumulatedText;
|
|
1151
1223
|
private currentTextPath;
|
|
1152
1224
|
private handlers;
|
|
@@ -1180,6 +1252,11 @@ declare class ChatSession {
|
|
|
1180
1252
|
* Consume a single SSE stream to exhaustion. Returns whether a terminal
|
|
1181
1253
|
* event (``message_stop`` / ``error``) was seen, so the caller can decide
|
|
1182
1254
|
* whether an ended stream means "turn done" vs "dropped, reconnect".
|
|
1255
|
+
*
|
|
1256
|
+
* ``onStall`` aborts the per-attempt connection: if no event arrives within
|
|
1257
|
+
* SSE_STALL_TIMEOUT_MS (backend keepalives land every 15s), the stream is a
|
|
1258
|
+
* zombie — ``reader.read()`` will never settle — so we kill the fetch and
|
|
1259
|
+
* throw a ConnectionError, feeding the caller's reconnect-from-lastSeq loop.
|
|
1183
1260
|
*/
|
|
1184
1261
|
private pumpStream;
|
|
1185
1262
|
/** Sleep for ``ms``, resolving early if the turn is aborted mid-backoff. */
|
|
@@ -1200,9 +1277,15 @@ declare class ChatSession {
|
|
|
1200
1277
|
* the pure wire → ChatEvent mapping can live in translate.ts and be reused
|
|
1201
1278
|
* by the replay path.
|
|
1202
1279
|
*
|
|
1203
|
-
* ``
|
|
1204
|
-
*
|
|
1205
|
-
*
|
|
1280
|
+
* ``promptMessageId`` is the id of the USER turn that started this job —
|
|
1281
|
+
* `POST /v1/jobs` returns it and the backend tags the prompt with it
|
|
1282
|
+
* (`HumanMessage(content=..., id=message_id)`), which is what lets a restore
|
|
1283
|
+
* pair a job with its prompt by id instead of by position. It was previously
|
|
1284
|
+
* documented here as the ASSISTANT's id and used as one; there is no
|
|
1285
|
+
* server-assigned assistant id on the wire, so that row gets a local one.
|
|
1286
|
+
* Empty in the reconnect and conversation-switch replay paths, where the
|
|
1287
|
+
* messages have already been loaded from REST and must not be re-pushed —
|
|
1288
|
+
* so it doubles as the "is this a live send?" gate.
|
|
1206
1289
|
*/
|
|
1207
1290
|
private applyWireSideEffects;
|
|
1208
1291
|
private executeClientTools;
|
|
@@ -1218,8 +1301,26 @@ declare class ChatSession {
|
|
|
1218
1301
|
reconnectToJob(jobId: string): Promise<void>;
|
|
1219
1302
|
/** Detach from the SSE stream without cancelling the job. */
|
|
1220
1303
|
detach(): void;
|
|
1221
|
-
/**
|
|
1304
|
+
/**
|
|
1305
|
+
* Cancel the running turn: stop the job server-side and tear the stream
|
|
1306
|
+
* down, WITHOUT ending the session. A turn-level cancel is not a
|
|
1307
|
+
* session-level teardown, so unlike `disconnect()` this leaves the protocol
|
|
1308
|
+
* registry alone — the SDK never auto-registers adapters, so clearing them
|
|
1309
|
+
* on a Stop press would silently kill embedded-resource rendering for the
|
|
1310
|
+
* rest of the session with nothing to re-register it.
|
|
1311
|
+
*/
|
|
1312
|
+
cancelTurn(): void;
|
|
1313
|
+
/** Stop the job and end the session's activity (explicit user action). */
|
|
1222
1314
|
disconnect(): void;
|
|
1315
|
+
/**
|
|
1316
|
+
* A pointer move happened above this layer, so any `loadConversation` in
|
|
1317
|
+
* flight must lose to it. `StreamManager` owns a pointer of its own and
|
|
1318
|
+
* moves it before this one; without this the two halves would gate on
|
|
1319
|
+
* counters that bump at different instants — `generation` synchronously in
|
|
1320
|
+
* `setActiveConversation`, `loadGeneration` only once the switch's own load
|
|
1321
|
+
* actually runs, which is behind the active-job probe.
|
|
1322
|
+
*/
|
|
1323
|
+
invalidateLoadsInFlight(): void;
|
|
1223
1324
|
createNewConversation(): Promise<string>;
|
|
1224
1325
|
/**
|
|
1225
1326
|
* Replay one completed turn's already-fetched events, synchronously.
|
|
@@ -1396,6 +1497,12 @@ declare class StreamManager {
|
|
|
1396
1497
|
private _backgroundJobs;
|
|
1397
1498
|
private handlers;
|
|
1398
1499
|
private unsub;
|
|
1500
|
+
/**
|
|
1501
|
+
* Bumped every time the active conversation moves. An async sequence that
|
|
1502
|
+
* captures it can then tell, at each await boundary, whether it is still the
|
|
1503
|
+
* one the user is waiting on — see ``restore``.
|
|
1504
|
+
*/
|
|
1505
|
+
private generation;
|
|
1399
1506
|
constructor(session: ChatSession);
|
|
1400
1507
|
get state(): StreamState;
|
|
1401
1508
|
get activeConversationId(): string | null;
|
|
@@ -1427,6 +1534,15 @@ declare class StreamManager {
|
|
|
1427
1534
|
switchTo(conversationId: string, opts?: {
|
|
1428
1535
|
skipHistoryReplay?: boolean;
|
|
1429
1536
|
}): Promise<void>;
|
|
1537
|
+
/**
|
|
1538
|
+
* Create a conversation and make it active.
|
|
1539
|
+
*
|
|
1540
|
+
* The returned id is NOT guaranteed to be the active conversation: if a
|
|
1541
|
+
* switch lands inside the storage round-trip, this declines the pointer move
|
|
1542
|
+
* so the newer one wins, and no `conversationChanged` fires for the new id.
|
|
1543
|
+
* A caller that routes on the return value should `switchTo(id)` rather than
|
|
1544
|
+
* assume it is current — that call is not a no-op in the declined case.
|
|
1545
|
+
*/
|
|
1430
1546
|
createConversation(): Promise<string>;
|
|
1431
1547
|
/**
|
|
1432
1548
|
* Rename a conversation. Purely a relabel — no active-conversation or
|
|
@@ -1436,6 +1552,31 @@ declare class StreamManager {
|
|
|
1436
1552
|
deleteConversation(id: string): Promise<void>;
|
|
1437
1553
|
stop(): void;
|
|
1438
1554
|
destroy(): void;
|
|
1555
|
+
/**
|
|
1556
|
+
* Park a streaming turn as a background job and detach from its SSE stream.
|
|
1557
|
+
*
|
|
1558
|
+
* Every method that relocates the active conversation has to do this before
|
|
1559
|
+
* announcing a new state. Announcing `idle` while `session.isStreaming` is
|
|
1560
|
+
* still true is worse than announcing nothing: `manager.send` no longer bails
|
|
1561
|
+
* on the streaming state, calls `session.send`, and THAT bails on its own
|
|
1562
|
+
* `isStreaming` — so the message is never posted, no error is emitted, and
|
|
1563
|
+
* the composer looks ready the whole time.
|
|
1564
|
+
*/
|
|
1565
|
+
private detachStreamingTurn;
|
|
1566
|
+
/**
|
|
1567
|
+
* Announce `idle` unless a turn is actually streaming.
|
|
1568
|
+
*
|
|
1569
|
+
* A `send` can land inside any of the switch paths — the fast path most
|
|
1570
|
+
* easily, since it deliberately stays out of `restoring` and so leaves the
|
|
1571
|
+
* composer live for the whole probe. `send` sets `streaming` and does not
|
|
1572
|
+
* bump the generation, so the path resumes, passes its supersession check,
|
|
1573
|
+
* and would announce a ready composer over a running stream. From there
|
|
1574
|
+
* `finalizeStream` and the `message_stop` branch both no-op (they only act
|
|
1575
|
+
* on `streaming`), so it stays `idle` for the whole turn — and the next send
|
|
1576
|
+
* reaches `session.send`, which bails on its own `isStreaming`: message
|
|
1577
|
+
* never posted, no error, composer ready throughout.
|
|
1578
|
+
*/
|
|
1579
|
+
private settleIdle;
|
|
1439
1580
|
private finalizeStream;
|
|
1440
1581
|
private restore;
|
|
1441
1582
|
private setActiveConversation;
|