@astralform/js 4.9.1 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +409 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +154 -4
- package/dist/index.d.ts +154 -4
- package/dist/index.js +409 -75
- 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[];
|
|
@@ -865,6 +883,20 @@ interface ConversationAsset {
|
|
|
865
883
|
* failed or the asset has no stored object.
|
|
866
884
|
*/
|
|
867
885
|
url?: string;
|
|
886
|
+
/**
|
|
887
|
+
* The asset's PERMANENT address. Authorization is resolved per request
|
|
888
|
+
* against the caller's live session, so unlike `url` it never expires — but
|
|
889
|
+
* it needs an `Authorization` header, which a browser will not attach to an
|
|
890
|
+
* `<img src>`. Store and link this one; render from `url`.
|
|
891
|
+
*/
|
|
892
|
+
contentUrl?: string;
|
|
893
|
+
/**
|
|
894
|
+
* A still to show for an asset the browser cannot draw from `url` alone.
|
|
895
|
+
* Present only for video: an `<img src>` pointed at an mp4 renders nothing,
|
|
896
|
+
* so a video row would otherwise have no thumbnail. Signed and expiring
|
|
897
|
+
* exactly like `url` — display, not identity, so never store it.
|
|
898
|
+
*/
|
|
899
|
+
posterUrl?: string;
|
|
868
900
|
createdAt: string;
|
|
869
901
|
}
|
|
870
902
|
|
|
@@ -1115,6 +1147,17 @@ declare class ChatSession {
|
|
|
1115
1147
|
/** True while ``loadMoreConversations`` is in flight. */
|
|
1116
1148
|
isLoadingConversations: boolean;
|
|
1117
1149
|
messages: Message[];
|
|
1150
|
+
/**
|
|
1151
|
+
* Which conversation ``messages`` currently holds.
|
|
1152
|
+
*
|
|
1153
|
+
* Distinct from ``conversationId``, and the distinction is the point:
|
|
1154
|
+
* ``loadConversation`` moves the POINTER synchronously and installs the LIST
|
|
1155
|
+
* an await later, so for the whole duration of every load the two disagree.
|
|
1156
|
+
* Anything pairing a message with a conversation — ``regenerate`` above all —
|
|
1157
|
+
* has to read this one, or it will pair the previous conversation's last
|
|
1158
|
+
* message with the new conversation's id.
|
|
1159
|
+
*/
|
|
1160
|
+
messagesConversationId: string | null;
|
|
1118
1161
|
isStreaming: boolean;
|
|
1119
1162
|
agentStatus: AgentStatus | null;
|
|
1120
1163
|
agents: AgentInfo[];
|
|
@@ -1147,6 +1190,49 @@ declare class ChatSession {
|
|
|
1147
1190
|
* is discarded instead.
|
|
1148
1191
|
*/
|
|
1149
1192
|
private conversationsGeneration;
|
|
1193
|
+
/**
|
|
1194
|
+
* Bumped by every ``loadConversation`` call, so an out-of-order fetch can
|
|
1195
|
+
* tell it is no longer the newest one and drop its result. Separate from
|
|
1196
|
+
* ``conversationsGeneration``, which guards the conversation LIST.
|
|
1197
|
+
*/
|
|
1198
|
+
private loadGeneration;
|
|
1199
|
+
/**
|
|
1200
|
+
* Ids of locally-created user messages the server has not acknowledged yet.
|
|
1201
|
+
*
|
|
1202
|
+
* Arrival time cannot answer "could the reply have included this?" on its
|
|
1203
|
+
* own. Every `loadConversation` in `StreamManager` sits behind the
|
|
1204
|
+
* active-job probe, so the ORDINARY ordering is that a send lands BEFORE the
|
|
1205
|
+
* load starts — and an arrival-time rule drops exactly those, losing the
|
|
1206
|
+
* prompt the user just sent while its stream is still running. Membership
|
|
1207
|
+
* here is set by `send` and cleared when a server row turns up carrying the
|
|
1208
|
+
* same turn, so the keep-decision no longer depends on which side of the
|
|
1209
|
+
* fetch the push landed on.
|
|
1210
|
+
*
|
|
1211
|
+
* The value is `serverRowsKnown` as of the `message_stop` that proved the
|
|
1212
|
+
* row committed, or 0 until then — including after the job response, which
|
|
1213
|
+
* hands back the id but starts the loop as a background task and so proves
|
|
1214
|
+
* nothing about the row. That stamp is what separates "the snapshot predates
|
|
1215
|
+
* the row" from "the server does not have this row" — see
|
|
1216
|
+
* `loadConversation`.
|
|
1217
|
+
*
|
|
1218
|
+
* It is an ANNOTATION ON `this.messages`: reconciliation only ever consults
|
|
1219
|
+
* entries of that array, so an id whose message has left it is dead weight.
|
|
1220
|
+
* `setMessages` is the single place the array is replaced, and it prunes.
|
|
1221
|
+
*/
|
|
1222
|
+
private pendingUserMessages;
|
|
1223
|
+
/**
|
|
1224
|
+
* Bumped once per completed turn, at `message_stop`, so a fetch can record
|
|
1225
|
+
* what was proven when it was ISSUED. A row proven committed before the
|
|
1226
|
+
* fetch went out must appear in its snapshot; one proven after may
|
|
1227
|
+
* legitimately be missing.
|
|
1228
|
+
*/
|
|
1229
|
+
private serverRowsKnown;
|
|
1230
|
+
/**
|
|
1231
|
+
* Replace the message list, keeping `pendingUserMessages` an annotation on
|
|
1232
|
+
* it. Every removal from the array goes through here — `push` is the only
|
|
1233
|
+
* other mutation and it cannot orphan an id.
|
|
1234
|
+
*/
|
|
1235
|
+
private setMessages;
|
|
1150
1236
|
private accumulatedText;
|
|
1151
1237
|
private currentTextPath;
|
|
1152
1238
|
private handlers;
|
|
@@ -1205,9 +1291,15 @@ declare class ChatSession {
|
|
|
1205
1291
|
* the pure wire → ChatEvent mapping can live in translate.ts and be reused
|
|
1206
1292
|
* by the replay path.
|
|
1207
1293
|
*
|
|
1208
|
-
* ``
|
|
1209
|
-
*
|
|
1210
|
-
*
|
|
1294
|
+
* ``promptMessageId`` is the id of the USER turn that started this job —
|
|
1295
|
+
* `POST /v1/jobs` returns it and the backend tags the prompt with it
|
|
1296
|
+
* (`HumanMessage(content=..., id=message_id)`), which is what lets a restore
|
|
1297
|
+
* pair a job with its prompt by id instead of by position. It was previously
|
|
1298
|
+
* documented here as the ASSISTANT's id and used as one; there is no
|
|
1299
|
+
* server-assigned assistant id on the wire, so that row gets a local one.
|
|
1300
|
+
* Empty in the reconnect and conversation-switch replay paths, where the
|
|
1301
|
+
* messages have already been loaded from REST and must not be re-pushed —
|
|
1302
|
+
* so it doubles as the "is this a live send?" gate.
|
|
1211
1303
|
*/
|
|
1212
1304
|
private applyWireSideEffects;
|
|
1213
1305
|
private executeClientTools;
|
|
@@ -1223,8 +1315,26 @@ declare class ChatSession {
|
|
|
1223
1315
|
reconnectToJob(jobId: string): Promise<void>;
|
|
1224
1316
|
/** Detach from the SSE stream without cancelling the job. */
|
|
1225
1317
|
detach(): void;
|
|
1226
|
-
/**
|
|
1318
|
+
/**
|
|
1319
|
+
* Cancel the running turn: stop the job server-side and tear the stream
|
|
1320
|
+
* down, WITHOUT ending the session. A turn-level cancel is not a
|
|
1321
|
+
* session-level teardown, so unlike `disconnect()` this leaves the protocol
|
|
1322
|
+
* registry alone — the SDK never auto-registers adapters, so clearing them
|
|
1323
|
+
* on a Stop press would silently kill embedded-resource rendering for the
|
|
1324
|
+
* rest of the session with nothing to re-register it.
|
|
1325
|
+
*/
|
|
1326
|
+
cancelTurn(): void;
|
|
1327
|
+
/** Stop the job and end the session's activity (explicit user action). */
|
|
1227
1328
|
disconnect(): void;
|
|
1329
|
+
/**
|
|
1330
|
+
* A pointer move happened above this layer, so any `loadConversation` in
|
|
1331
|
+
* flight must lose to it. `StreamManager` owns a pointer of its own and
|
|
1332
|
+
* moves it before this one; without this the two halves would gate on
|
|
1333
|
+
* counters that bump at different instants — `generation` synchronously in
|
|
1334
|
+
* `setActiveConversation`, `loadGeneration` only once the switch's own load
|
|
1335
|
+
* actually runs, which is behind the active-job probe.
|
|
1336
|
+
*/
|
|
1337
|
+
invalidateLoadsInFlight(): void;
|
|
1228
1338
|
createNewConversation(): Promise<string>;
|
|
1229
1339
|
/**
|
|
1230
1340
|
* Replay one completed turn's already-fetched events, synchronously.
|
|
@@ -1401,6 +1511,12 @@ declare class StreamManager {
|
|
|
1401
1511
|
private _backgroundJobs;
|
|
1402
1512
|
private handlers;
|
|
1403
1513
|
private unsub;
|
|
1514
|
+
/**
|
|
1515
|
+
* Bumped every time the active conversation moves. An async sequence that
|
|
1516
|
+
* captures it can then tell, at each await boundary, whether it is still the
|
|
1517
|
+
* one the user is waiting on — see ``restore``.
|
|
1518
|
+
*/
|
|
1519
|
+
private generation;
|
|
1404
1520
|
constructor(session: ChatSession);
|
|
1405
1521
|
get state(): StreamState;
|
|
1406
1522
|
get activeConversationId(): string | null;
|
|
@@ -1432,6 +1548,15 @@ declare class StreamManager {
|
|
|
1432
1548
|
switchTo(conversationId: string, opts?: {
|
|
1433
1549
|
skipHistoryReplay?: boolean;
|
|
1434
1550
|
}): Promise<void>;
|
|
1551
|
+
/**
|
|
1552
|
+
* Create a conversation and make it active.
|
|
1553
|
+
*
|
|
1554
|
+
* The returned id is NOT guaranteed to be the active conversation: if a
|
|
1555
|
+
* switch lands inside the storage round-trip, this declines the pointer move
|
|
1556
|
+
* so the newer one wins, and no `conversationChanged` fires for the new id.
|
|
1557
|
+
* A caller that routes on the return value should `switchTo(id)` rather than
|
|
1558
|
+
* assume it is current — that call is not a no-op in the declined case.
|
|
1559
|
+
*/
|
|
1435
1560
|
createConversation(): Promise<string>;
|
|
1436
1561
|
/**
|
|
1437
1562
|
* Rename a conversation. Purely a relabel — no active-conversation or
|
|
@@ -1441,6 +1566,31 @@ declare class StreamManager {
|
|
|
1441
1566
|
deleteConversation(id: string): Promise<void>;
|
|
1442
1567
|
stop(): void;
|
|
1443
1568
|
destroy(): void;
|
|
1569
|
+
/**
|
|
1570
|
+
* Park a streaming turn as a background job and detach from its SSE stream.
|
|
1571
|
+
*
|
|
1572
|
+
* Every method that relocates the active conversation has to do this before
|
|
1573
|
+
* announcing a new state. Announcing `idle` while `session.isStreaming` is
|
|
1574
|
+
* still true is worse than announcing nothing: `manager.send` no longer bails
|
|
1575
|
+
* on the streaming state, calls `session.send`, and THAT bails on its own
|
|
1576
|
+
* `isStreaming` — so the message is never posted, no error is emitted, and
|
|
1577
|
+
* the composer looks ready the whole time.
|
|
1578
|
+
*/
|
|
1579
|
+
private detachStreamingTurn;
|
|
1580
|
+
/**
|
|
1581
|
+
* Announce `idle` unless a turn is actually streaming.
|
|
1582
|
+
*
|
|
1583
|
+
* A `send` can land inside any of the switch paths — the fast path most
|
|
1584
|
+
* easily, since it deliberately stays out of `restoring` and so leaves the
|
|
1585
|
+
* composer live for the whole probe. `send` sets `streaming` and does not
|
|
1586
|
+
* bump the generation, so the path resumes, passes its supersession check,
|
|
1587
|
+
* and would announce a ready composer over a running stream. From there
|
|
1588
|
+
* `finalizeStream` and the `message_stop` branch both no-op (they only act
|
|
1589
|
+
* on `streaming`), so it stays `idle` for the whole turn — and the next send
|
|
1590
|
+
* reaches `session.send`, which bails on its own `isStreaming`: message
|
|
1591
|
+
* never posted, no error, composer ready throughout.
|
|
1592
|
+
*/
|
|
1593
|
+
private settleIdle;
|
|
1444
1594
|
private finalizeStream;
|
|
1445
1595
|
private restore;
|
|
1446
1596
|
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[];
|
|
@@ -865,6 +883,20 @@ interface ConversationAsset {
|
|
|
865
883
|
* failed or the asset has no stored object.
|
|
866
884
|
*/
|
|
867
885
|
url?: string;
|
|
886
|
+
/**
|
|
887
|
+
* The asset's PERMANENT address. Authorization is resolved per request
|
|
888
|
+
* against the caller's live session, so unlike `url` it never expires — but
|
|
889
|
+
* it needs an `Authorization` header, which a browser will not attach to an
|
|
890
|
+
* `<img src>`. Store and link this one; render from `url`.
|
|
891
|
+
*/
|
|
892
|
+
contentUrl?: string;
|
|
893
|
+
/**
|
|
894
|
+
* A still to show for an asset the browser cannot draw from `url` alone.
|
|
895
|
+
* Present only for video: an `<img src>` pointed at an mp4 renders nothing,
|
|
896
|
+
* so a video row would otherwise have no thumbnail. Signed and expiring
|
|
897
|
+
* exactly like `url` — display, not identity, so never store it.
|
|
898
|
+
*/
|
|
899
|
+
posterUrl?: string;
|
|
868
900
|
createdAt: string;
|
|
869
901
|
}
|
|
870
902
|
|
|
@@ -1115,6 +1147,17 @@ declare class ChatSession {
|
|
|
1115
1147
|
/** True while ``loadMoreConversations`` is in flight. */
|
|
1116
1148
|
isLoadingConversations: boolean;
|
|
1117
1149
|
messages: Message[];
|
|
1150
|
+
/**
|
|
1151
|
+
* Which conversation ``messages`` currently holds.
|
|
1152
|
+
*
|
|
1153
|
+
* Distinct from ``conversationId``, and the distinction is the point:
|
|
1154
|
+
* ``loadConversation`` moves the POINTER synchronously and installs the LIST
|
|
1155
|
+
* an await later, so for the whole duration of every load the two disagree.
|
|
1156
|
+
* Anything pairing a message with a conversation — ``regenerate`` above all —
|
|
1157
|
+
* has to read this one, or it will pair the previous conversation's last
|
|
1158
|
+
* message with the new conversation's id.
|
|
1159
|
+
*/
|
|
1160
|
+
messagesConversationId: string | null;
|
|
1118
1161
|
isStreaming: boolean;
|
|
1119
1162
|
agentStatus: AgentStatus | null;
|
|
1120
1163
|
agents: AgentInfo[];
|
|
@@ -1147,6 +1190,49 @@ declare class ChatSession {
|
|
|
1147
1190
|
* is discarded instead.
|
|
1148
1191
|
*/
|
|
1149
1192
|
private conversationsGeneration;
|
|
1193
|
+
/**
|
|
1194
|
+
* Bumped by every ``loadConversation`` call, so an out-of-order fetch can
|
|
1195
|
+
* tell it is no longer the newest one and drop its result. Separate from
|
|
1196
|
+
* ``conversationsGeneration``, which guards the conversation LIST.
|
|
1197
|
+
*/
|
|
1198
|
+
private loadGeneration;
|
|
1199
|
+
/**
|
|
1200
|
+
* Ids of locally-created user messages the server has not acknowledged yet.
|
|
1201
|
+
*
|
|
1202
|
+
* Arrival time cannot answer "could the reply have included this?" on its
|
|
1203
|
+
* own. Every `loadConversation` in `StreamManager` sits behind the
|
|
1204
|
+
* active-job probe, so the ORDINARY ordering is that a send lands BEFORE the
|
|
1205
|
+
* load starts — and an arrival-time rule drops exactly those, losing the
|
|
1206
|
+
* prompt the user just sent while its stream is still running. Membership
|
|
1207
|
+
* here is set by `send` and cleared when a server row turns up carrying the
|
|
1208
|
+
* same turn, so the keep-decision no longer depends on which side of the
|
|
1209
|
+
* fetch the push landed on.
|
|
1210
|
+
*
|
|
1211
|
+
* The value is `serverRowsKnown` as of the `message_stop` that proved the
|
|
1212
|
+
* row committed, or 0 until then — including after the job response, which
|
|
1213
|
+
* hands back the id but starts the loop as a background task and so proves
|
|
1214
|
+
* nothing about the row. That stamp is what separates "the snapshot predates
|
|
1215
|
+
* the row" from "the server does not have this row" — see
|
|
1216
|
+
* `loadConversation`.
|
|
1217
|
+
*
|
|
1218
|
+
* It is an ANNOTATION ON `this.messages`: reconciliation only ever consults
|
|
1219
|
+
* entries of that array, so an id whose message has left it is dead weight.
|
|
1220
|
+
* `setMessages` is the single place the array is replaced, and it prunes.
|
|
1221
|
+
*/
|
|
1222
|
+
private pendingUserMessages;
|
|
1223
|
+
/**
|
|
1224
|
+
* Bumped once per completed turn, at `message_stop`, so a fetch can record
|
|
1225
|
+
* what was proven when it was ISSUED. A row proven committed before the
|
|
1226
|
+
* fetch went out must appear in its snapshot; one proven after may
|
|
1227
|
+
* legitimately be missing.
|
|
1228
|
+
*/
|
|
1229
|
+
private serverRowsKnown;
|
|
1230
|
+
/**
|
|
1231
|
+
* Replace the message list, keeping `pendingUserMessages` an annotation on
|
|
1232
|
+
* it. Every removal from the array goes through here — `push` is the only
|
|
1233
|
+
* other mutation and it cannot orphan an id.
|
|
1234
|
+
*/
|
|
1235
|
+
private setMessages;
|
|
1150
1236
|
private accumulatedText;
|
|
1151
1237
|
private currentTextPath;
|
|
1152
1238
|
private handlers;
|
|
@@ -1205,9 +1291,15 @@ declare class ChatSession {
|
|
|
1205
1291
|
* the pure wire → ChatEvent mapping can live in translate.ts and be reused
|
|
1206
1292
|
* by the replay path.
|
|
1207
1293
|
*
|
|
1208
|
-
* ``
|
|
1209
|
-
*
|
|
1210
|
-
*
|
|
1294
|
+
* ``promptMessageId`` is the id of the USER turn that started this job —
|
|
1295
|
+
* `POST /v1/jobs` returns it and the backend tags the prompt with it
|
|
1296
|
+
* (`HumanMessage(content=..., id=message_id)`), which is what lets a restore
|
|
1297
|
+
* pair a job with its prompt by id instead of by position. It was previously
|
|
1298
|
+
* documented here as the ASSISTANT's id and used as one; there is no
|
|
1299
|
+
* server-assigned assistant id on the wire, so that row gets a local one.
|
|
1300
|
+
* Empty in the reconnect and conversation-switch replay paths, where the
|
|
1301
|
+
* messages have already been loaded from REST and must not be re-pushed —
|
|
1302
|
+
* so it doubles as the "is this a live send?" gate.
|
|
1211
1303
|
*/
|
|
1212
1304
|
private applyWireSideEffects;
|
|
1213
1305
|
private executeClientTools;
|
|
@@ -1223,8 +1315,26 @@ declare class ChatSession {
|
|
|
1223
1315
|
reconnectToJob(jobId: string): Promise<void>;
|
|
1224
1316
|
/** Detach from the SSE stream without cancelling the job. */
|
|
1225
1317
|
detach(): void;
|
|
1226
|
-
/**
|
|
1318
|
+
/**
|
|
1319
|
+
* Cancel the running turn: stop the job server-side and tear the stream
|
|
1320
|
+
* down, WITHOUT ending the session. A turn-level cancel is not a
|
|
1321
|
+
* session-level teardown, so unlike `disconnect()` this leaves the protocol
|
|
1322
|
+
* registry alone — the SDK never auto-registers adapters, so clearing them
|
|
1323
|
+
* on a Stop press would silently kill embedded-resource rendering for the
|
|
1324
|
+
* rest of the session with nothing to re-register it.
|
|
1325
|
+
*/
|
|
1326
|
+
cancelTurn(): void;
|
|
1327
|
+
/** Stop the job and end the session's activity (explicit user action). */
|
|
1227
1328
|
disconnect(): void;
|
|
1329
|
+
/**
|
|
1330
|
+
* A pointer move happened above this layer, so any `loadConversation` in
|
|
1331
|
+
* flight must lose to it. `StreamManager` owns a pointer of its own and
|
|
1332
|
+
* moves it before this one; without this the two halves would gate on
|
|
1333
|
+
* counters that bump at different instants — `generation` synchronously in
|
|
1334
|
+
* `setActiveConversation`, `loadGeneration` only once the switch's own load
|
|
1335
|
+
* actually runs, which is behind the active-job probe.
|
|
1336
|
+
*/
|
|
1337
|
+
invalidateLoadsInFlight(): void;
|
|
1228
1338
|
createNewConversation(): Promise<string>;
|
|
1229
1339
|
/**
|
|
1230
1340
|
* Replay one completed turn's already-fetched events, synchronously.
|
|
@@ -1401,6 +1511,12 @@ declare class StreamManager {
|
|
|
1401
1511
|
private _backgroundJobs;
|
|
1402
1512
|
private handlers;
|
|
1403
1513
|
private unsub;
|
|
1514
|
+
/**
|
|
1515
|
+
* Bumped every time the active conversation moves. An async sequence that
|
|
1516
|
+
* captures it can then tell, at each await boundary, whether it is still the
|
|
1517
|
+
* one the user is waiting on — see ``restore``.
|
|
1518
|
+
*/
|
|
1519
|
+
private generation;
|
|
1404
1520
|
constructor(session: ChatSession);
|
|
1405
1521
|
get state(): StreamState;
|
|
1406
1522
|
get activeConversationId(): string | null;
|
|
@@ -1432,6 +1548,15 @@ declare class StreamManager {
|
|
|
1432
1548
|
switchTo(conversationId: string, opts?: {
|
|
1433
1549
|
skipHistoryReplay?: boolean;
|
|
1434
1550
|
}): Promise<void>;
|
|
1551
|
+
/**
|
|
1552
|
+
* Create a conversation and make it active.
|
|
1553
|
+
*
|
|
1554
|
+
* The returned id is NOT guaranteed to be the active conversation: if a
|
|
1555
|
+
* switch lands inside the storage round-trip, this declines the pointer move
|
|
1556
|
+
* so the newer one wins, and no `conversationChanged` fires for the new id.
|
|
1557
|
+
* A caller that routes on the return value should `switchTo(id)` rather than
|
|
1558
|
+
* assume it is current — that call is not a no-op in the declined case.
|
|
1559
|
+
*/
|
|
1435
1560
|
createConversation(): Promise<string>;
|
|
1436
1561
|
/**
|
|
1437
1562
|
* Rename a conversation. Purely a relabel — no active-conversation or
|
|
@@ -1441,6 +1566,31 @@ declare class StreamManager {
|
|
|
1441
1566
|
deleteConversation(id: string): Promise<void>;
|
|
1442
1567
|
stop(): void;
|
|
1443
1568
|
destroy(): void;
|
|
1569
|
+
/**
|
|
1570
|
+
* Park a streaming turn as a background job and detach from its SSE stream.
|
|
1571
|
+
*
|
|
1572
|
+
* Every method that relocates the active conversation has to do this before
|
|
1573
|
+
* announcing a new state. Announcing `idle` while `session.isStreaming` is
|
|
1574
|
+
* still true is worse than announcing nothing: `manager.send` no longer bails
|
|
1575
|
+
* on the streaming state, calls `session.send`, and THAT bails on its own
|
|
1576
|
+
* `isStreaming` — so the message is never posted, no error is emitted, and
|
|
1577
|
+
* the composer looks ready the whole time.
|
|
1578
|
+
*/
|
|
1579
|
+
private detachStreamingTurn;
|
|
1580
|
+
/**
|
|
1581
|
+
* Announce `idle` unless a turn is actually streaming.
|
|
1582
|
+
*
|
|
1583
|
+
* A `send` can land inside any of the switch paths — the fast path most
|
|
1584
|
+
* easily, since it deliberately stays out of `restoring` and so leaves the
|
|
1585
|
+
* composer live for the whole probe. `send` sets `streaming` and does not
|
|
1586
|
+
* bump the generation, so the path resumes, passes its supersession check,
|
|
1587
|
+
* and would announce a ready composer over a running stream. From there
|
|
1588
|
+
* `finalizeStream` and the `message_stop` branch both no-op (they only act
|
|
1589
|
+
* on `streaming`), so it stays `idle` for the whole turn — and the next send
|
|
1590
|
+
* reaches `session.send`, which bails on its own `isStreaming`: message
|
|
1591
|
+
* never posted, no error, composer ready throughout.
|
|
1592
|
+
*/
|
|
1593
|
+
private settleIdle;
|
|
1444
1594
|
private finalizeStream;
|
|
1445
1595
|
private restore;
|
|
1446
1596
|
private setActiveConversation;
|