@burdenoff/fe-libs 2026.1004.8 → 2026.1005.2
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/shared/assistant/api.d.ts +18 -0
- package/dist/shared/assistant/api.d.ts.map +1 -1
- package/dist/shared/assistant/api.js +169 -147
- package/dist/shared/assistant/capabilities.d.ts +21 -0
- package/dist/shared/assistant/capabilities.d.ts.map +1 -1
- package/dist/shared/assistant/capabilities.js +11 -1
- package/dist/shared/assistant/i18nManifest.d.ts +4 -0
- package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
- package/dist/shared/assistant/i18nManifest.js +4 -0
- package/dist/shared/assistant/index.d.ts +20 -0
- package/dist/shared/assistant/index.d.ts.map +1 -1
- package/dist/shared/assistant/liveDeltas.d.ts +76 -0
- package/dist/shared/assistant/liveDeltas.d.ts.map +1 -0
- package/dist/shared/assistant/liveDeltas.js +196 -0
- package/dist/shared/assistant/liveOverlay.d.ts +62 -0
- package/dist/shared/assistant/liveOverlay.d.ts.map +1 -0
- package/dist/shared/assistant/liveOverlay.js +64 -0
- package/dist/shared/assistant/snapshotPoller.d.ts +48 -0
- package/dist/shared/assistant/snapshotPoller.d.ts.map +1 -0
- package/dist/shared/assistant/snapshotPoller.js +58 -0
- package/dist/shared/assistant/speech/browserSpeechEngine.d.ts.map +1 -1
- package/dist/shared/assistant/speech/browserSpeechEngine.js +46 -45
- package/dist/shared/assistant/speech/hostedTtsSpeechEngine.d.ts.map +1 -1
- package/dist/shared/assistant/speech/hostedTtsSpeechEngine.js +80 -79
- package/dist/shared/assistant/store.d.ts +3 -0
- package/dist/shared/assistant/store.d.ts.map +1 -1
- package/dist/shared/assistant/store.js +43 -35
- package/dist/shared/assistant/turnStream.d.ts +71 -0
- package/dist/shared/assistant/turnStream.d.ts.map +1 -0
- package/dist/shared/assistant/turnStream.js +266 -0
- package/dist/shared/assistant/turnTimeline.d.ts +27 -2
- package/dist/shared/assistant/turnTimeline.d.ts.map +1 -1
- package/dist/shared/assistant/turnTimeline.js +17 -28
- package/dist/shared/assistant/types.d.ts +10 -0
- package/dist/shared/assistant/types.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantChatArea.js +886 -843
- package/dist/shared/assistant/ui/AssistantMessageList.d.ts +2 -0
- package/dist/shared/assistant/ui/AssistantMessageList.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantMessageList.js +48 -32
- package/dist/shared/assistant/ui/AssistantMoreMenu.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantMoreMenu.js +59 -57
- package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.d.ts +17 -0
- package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.d.ts.map +1 -0
- package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.js +34 -0
- package/dist/shared/assistant/ui/useVoiceSession.d.ts +29 -2
- package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/ui/useVoiceSession.js +247 -213
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +2 -0
- package/dist/shared/assistant/voice/handsfree/audioTrackTransport.d.ts +33 -0
- package/dist/shared/assistant/voice/handsfree/audioTrackTransport.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/audioTrackTransport.js +98 -0
- package/dist/shared/assistant/voice/handsfree/backendStreamTransport.d.ts +34 -0
- package/dist/shared/assistant/voice/handsfree/backendStreamTransport.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/backendStreamTransport.js +130 -0
- package/dist/shared/assistant/voice/handsfree/bargeIn.d.ts +43 -0
- package/dist/shared/assistant/voice/handsfree/bargeIn.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/bargeIn.js +32 -0
- package/dist/shared/assistant/voice/handsfree/captureWorklet.d.ts +47 -0
- package/dist/shared/assistant/voice/handsfree/captureWorklet.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/captureWorklet.js +85 -0
- package/dist/shared/assistant/voice/handsfree/echoGate.d.ts +140 -0
- package/dist/shared/assistant/voice/handsfree/echoGate.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/echoGate.js +198 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeController.d.ts +77 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeController.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeController.js +126 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.d.ts +15 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.js +78 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeSetting.d.ts +26 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeSetting.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeSetting.js +25 -0
- package/dist/shared/assistant/voice/handsfree/micCapture.d.ts +21 -0
- package/dist/shared/assistant/voice/handsfree/micCapture.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/micCapture.js +72 -0
- package/dist/shared/assistant/voice/handsfree/playbackReference.d.ts +38 -0
- package/dist/shared/assistant/voice/handsfree/playbackReference.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/playbackReference.js +55 -0
- package/dist/shared/assistant/voice/handsfree/preRollRing.d.ts +32 -0
- package/dist/shared/assistant/voice/handsfree/preRollRing.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/preRollRing.js +34 -0
- package/dist/shared/assistant/voice/handsfree/sttTransport.d.ts +94 -0
- package/dist/shared/assistant/voice/handsfree/sttTransport.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/sttTransport.js +27 -0
- package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.d.ts +33 -0
- package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.js +70 -0
- package/dist/shared/assistant/voice/handsfree/vad.d.ts +55 -0
- package/dist/shared/assistant/voice/handsfree/vad.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/vad.js +41 -0
- package/dist/shared/assistant/voice/handsfree/webSpeechTransport.d.ts +3 -0
- package/dist/shared/assistant/voice/handsfree/webSpeechTransport.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/webSpeechTransport.js +16 -0
- package/dist/shared/assistant/voice/voiceSession.d.ts +9 -0
- package/dist/shared/assistant/voice/voiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/voice/voiceSession.js +2 -2
- package/dist/shared-assistant.js +224 -204
- package/package.json +2 -1
|
@@ -50,5 +50,26 @@ export declare function isUnknownFieldError(error: unknown): boolean;
|
|
|
50
50
|
* found" and "404" are deliberately not matched here.
|
|
51
51
|
*/
|
|
52
52
|
export declare function isMissingGatewayFieldError(error: unknown, field: string, typeNames?: readonly string[]): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* ★★ BOFF-7914 (speed S3): the turn stream's OWN mint backoff, separate from the
|
|
55
|
+
* `sse` capability above. `getAssistantStreamAccess` (the widget transport's
|
|
56
|
+
* mint) latches `sse: unsupported` for the page on any failure; this one must
|
|
57
|
+
* not: a mint that answered 404 because the relay is off in prod, or failed
|
|
58
|
+
* once on a bad network, is retried after a pause, and never disables the
|
|
59
|
+
* stream for the rest of the page (design rule 6).
|
|
60
|
+
*
|
|
61
|
+
* - a 404 (relay off, product not allowlisted, bridge without the projection)
|
|
62
|
+
* backs off 5 minutes: it is a deployment answer, not a blip;
|
|
63
|
+
* - any other failure backs off 60 seconds;
|
|
64
|
+
* - a success clears it.
|
|
65
|
+
*
|
|
66
|
+
* Per page load, like every capability here. It only ever LENGTHENS a backoff.
|
|
67
|
+
*/
|
|
68
|
+
export declare const STREAM_MINT_BACKOFF_UNAVAILABLE_MS: number;
|
|
69
|
+
export declare const STREAM_MINT_BACKOFF_ERROR_MS = 60000;
|
|
70
|
+
/** Is a mint inside its backoff window? */
|
|
71
|
+
export declare function streamMintBackedOff(now?: number): boolean;
|
|
72
|
+
export declare function backOffStreamMint(ms: number, now?: number): void;
|
|
73
|
+
export declare function clearStreamMintBackoff(): void;
|
|
53
74
|
export {};
|
|
54
75
|
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;AAEtE,UAAU,qBAAqB;IAC7B,qBAAqB,EAAE,eAAe,CAAC;IACvC,UAAU,EAAE,eAAe,CAAC;IAC5B,GAAG,EAAE,eAAe,CAAC;IACrB;;;OAGG;IACH,WAAW,EAAE,eAAe,CAAC;IAC7B;;;;OAIG;IACH,yBAAyB,EAAE,eAAe,CAAC;IAC3C,sBAAsB,EAAE,eAAe,CAAC;IACxC,2BAA2B,EAAE,eAAe,CAAC;CAC9C;AAYD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,eAAe,CAE/E;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,IAAI,CAEpE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,IAAI,CAEtE;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK3D;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,SAAS,MAAM,EAAO,GAChC,OAAO,CAWT"}
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;AAEtE,UAAU,qBAAqB;IAC7B,qBAAqB,EAAE,eAAe,CAAC;IACvC,UAAU,EAAE,eAAe,CAAC;IAC5B,GAAG,EAAE,eAAe,CAAC;IACrB;;;OAGG;IACH,WAAW,EAAE,eAAe,CAAC;IAC7B;;;;OAIG;IACH,yBAAyB,EAAE,eAAe,CAAC;IAC3C,sBAAsB,EAAE,eAAe,CAAC;IACxC,2BAA2B,EAAE,eAAe,CAAC;CAC9C;AAYD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,eAAe,CAE/E;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,IAAI,CAEpE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,IAAI,CAEtE;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK3D;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,SAAS,MAAM,EAAO,GAChC,OAAO,CAWT;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kCAAkC,QAAa,CAAC;AAC7D,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAInD,2CAA2C;AAC3C,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAmB,GAAG,OAAO,CAErE;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAE5E;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
|
|
@@ -27,5 +27,15 @@ function s(t, n, r = []) {
|
|
|
27
27
|
let i = t instanceof Error ? t.message : String(t), a = (e) => `["'\u201C]${o(e)}["'\u201D]`;
|
|
28
28
|
return /missing @rbac directive/i.test(i) ? RegExp(`Field ${a(n)}`).test(i) ? !0 : e(t).some((e) => e.code === "FORBIDDEN" && e.field === n) : RegExp(`Cannot query field ${a(n)}`).test(i) ? !0 : r.some((e) => RegExp(`Unknown type ${a(e)}`).test(i));
|
|
29
29
|
}
|
|
30
|
+
var c = 5 * 6e4, l = 6e4, u = 0;
|
|
31
|
+
function d(e = Date.now()) {
|
|
32
|
+
return e < u;
|
|
33
|
+
}
|
|
34
|
+
function f(e, t = Date.now()) {
|
|
35
|
+
u = Math.max(u, t + e);
|
|
36
|
+
}
|
|
37
|
+
function p() {
|
|
38
|
+
u = 0;
|
|
39
|
+
}
|
|
30
40
|
//#endregion
|
|
31
|
-
export { n as getCapability, s as isMissingGatewayFieldError, a as isUnknownFieldError, r as markSupported, i as markUnsupported };
|
|
41
|
+
export { l as STREAM_MINT_BACKOFF_ERROR_MS, c as STREAM_MINT_BACKOFF_UNAVAILABLE_MS, f as backOffStreamMint, p as clearStreamMintBackoff, n as getCapability, s as isMissingGatewayFieldError, a as isUnknownFieldError, r as markSupported, i as markUnsupported, d as streamMintBackedOff };
|
|
@@ -402,6 +402,8 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
402
402
|
readonly "voice.graceLabel": "Wait after I stop talking";
|
|
403
403
|
readonly "voice.graceOption": "{{seconds}} seconds";
|
|
404
404
|
readonly "voice.graceOptionDefault": "{{seconds}} seconds (default)";
|
|
405
|
+
readonly "voice.handsFreeHint": "Let the assistant listen while it answers, so you can speak over it to correct it. Works best with headphones. You can always tap to interrupt.";
|
|
406
|
+
readonly "voice.handsFreeLabel": "Hands-free interrupt (beta)";
|
|
405
407
|
readonly "voice.languageFollowApp": "Same as interface";
|
|
406
408
|
readonly "voice.languageLabel": "Language you speak to the assistant";
|
|
407
409
|
readonly "voice.languageNotSupported": "This browser cannot recognise spoken {{language}}. Try a different browser, or type instead.";
|
|
@@ -440,6 +442,8 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
440
442
|
readonly "voiceSession.newSession": "New voice session";
|
|
441
443
|
readonly "voiceSession.noSpeechSupport": "This browser cannot listen. Try a different browser, or type instead.";
|
|
442
444
|
readonly "voiceSession.noVoiceSupport": "This device has no voice that can speak this language.";
|
|
445
|
+
readonly "voiceSession.noticeHandsFreeFallback": "Hands-free interrupt turned itself off for this conversation. Tap to interrupt still works.";
|
|
446
|
+
readonly "voiceSession.noticeHandsFreeNothingHeard": "Stopped, but I did not catch that. Say it again, or tap to replay.";
|
|
443
447
|
readonly "voiceSession.noticeNetwork": "Speech recognition lost its connection. Check your network — it will retry.";
|
|
444
448
|
readonly "voiceSession.noticeNotCapturing": "The microphone did not start. Check that this site is allowed to use it, then try again.";
|
|
445
449
|
readonly "voiceSession.noticeNothingHeard": "Nothing heard yet. Check your microphone is not muted or in use by another app.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18nManifest.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/i18nManifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAa1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0GG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B
|
|
1
|
+
{"version":3,"file":"i18nManifest.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/i18nManifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAa1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0GG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2dG,CAAC;AAE5C,mDAAmD;AACnD,MAAM,MAAM,uBAAuB,GAAG,MAAM,OAAO,2BAA2B,CAAC;AAW/E;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgCtE,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,+BAA+B;;EAGjC,CAAC;AAEZ;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKjE,CAAC;AAEL,kEAAkE;AAClE,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,mBAAmB,EACnB,IAAI,GAAG,OAAO,GAAG,mBAAmB,CACrC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,uBAAuB,EAAE,GACxC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAexB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAC1C,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC9C,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiCzB"}
|
|
@@ -300,6 +300,8 @@ var p = {
|
|
|
300
300
|
"voice.graceLabel": "Wait after I stop talking",
|
|
301
301
|
"voice.graceOption": "{{seconds}} seconds",
|
|
302
302
|
"voice.graceOptionDefault": "{{seconds}} seconds (default)",
|
|
303
|
+
"voice.handsFreeHint": "Let the assistant listen while it answers, so you can speak over it to correct it. Works best with headphones. You can always tap to interrupt.",
|
|
304
|
+
"voice.handsFreeLabel": "Hands-free interrupt (beta)",
|
|
303
305
|
"voice.languageFollowApp": "Same as interface",
|
|
304
306
|
"voice.languageLabel": "Language you speak to the assistant",
|
|
305
307
|
"voice.languageNotSupported": "This browser cannot recognise spoken {{language}}. Try a different browser, or type instead.",
|
|
@@ -338,6 +340,8 @@ var p = {
|
|
|
338
340
|
"voiceSession.newSession": "New voice session",
|
|
339
341
|
"voiceSession.noSpeechSupport": "This browser cannot listen. Try a different browser, or type instead.",
|
|
340
342
|
"voiceSession.noVoiceSupport": "This device has no voice that can speak this language.",
|
|
343
|
+
"voiceSession.noticeHandsFreeFallback": "Hands-free interrupt turned itself off for this conversation. Tap to interrupt still works.",
|
|
344
|
+
"voiceSession.noticeHandsFreeNothingHeard": "Stopped, but I did not catch that. Say it again, or tap to replay.",
|
|
341
345
|
"voiceSession.noticeNetwork": "Speech recognition lost its connection. Check your network — it will retry.",
|
|
342
346
|
"voiceSession.noticeNotCapturing": "The microphone did not start. Check that this site is allowed to use it, then try again.",
|
|
343
347
|
"voiceSession.noticeNothingHeard": "Nothing heard yet. Check your microphone is not muted or in use by another app.",
|
|
@@ -51,6 +51,21 @@ export * from './voice/voiceStatus';
|
|
|
51
51
|
export * from './voice/rotationClock';
|
|
52
52
|
export * from './voice/voiceSession';
|
|
53
53
|
export * from './voice/handsFree';
|
|
54
|
+
export * from './voice/handsfree/audioTrackTransport';
|
|
55
|
+
export * from './voice/handsfree/backendStreamTransport';
|
|
56
|
+
export * from './voice/handsfree/bargeIn';
|
|
57
|
+
export * from './voice/handsfree/captureWorklet';
|
|
58
|
+
export * from './voice/handsfree/echoGate';
|
|
59
|
+
export * from './voice/handsfree/handsFreeController';
|
|
60
|
+
export * from './voice/handsfree/handsFreeRuntime';
|
|
61
|
+
export * from './voice/handsfree/handsFreeSetting';
|
|
62
|
+
export * from './voice/handsfree/micCapture';
|
|
63
|
+
export * from './voice/handsfree/playbackReference';
|
|
64
|
+
export * from './voice/handsfree/preRollRing';
|
|
65
|
+
export * from './voice/handsfree/sttTransport';
|
|
66
|
+
export * from './voice/handsfree/useHandsFreeInterrupt';
|
|
67
|
+
export * from './voice/handsfree/vad';
|
|
68
|
+
export * from './voice/handsfree/webSpeechTransport';
|
|
54
69
|
export * from './voice/affirmations';
|
|
55
70
|
export * from './voice/supersededTurns';
|
|
56
71
|
export * from './voice/speechVoices';
|
|
@@ -143,6 +158,7 @@ export * from './ui/composer/AssistantModeSelector';
|
|
|
143
158
|
export * from './ui/composer/AssistantVoiceButton';
|
|
144
159
|
export * from './ui/composer/AssistantVoiceSelector';
|
|
145
160
|
export * from './ui/composer/AssistantVoiceGraceSelector';
|
|
161
|
+
export * from './ui/composer/AssistantHandsFreeInterruptToggle';
|
|
146
162
|
export * from './ui/voice/AssistantVoiceOrb';
|
|
147
163
|
export * from './ui/voice/AssistantVoiceSessionButton';
|
|
148
164
|
export * from './ui/voice/VoiceCaption';
|
|
@@ -202,6 +218,10 @@ export * from './permissionError';
|
|
|
202
218
|
export * from './autoRouting';
|
|
203
219
|
export * from './turnOutcome';
|
|
204
220
|
export * from './turnTimeline';
|
|
221
|
+
export * from './turnStream';
|
|
222
|
+
export * from './liveDeltas';
|
|
223
|
+
export * from './liveOverlay';
|
|
224
|
+
export * from './snapshotPoller';
|
|
205
225
|
export * from './turnTimingReport';
|
|
206
226
|
export * from './turnTimingReporter';
|
|
207
227
|
export * from './prewarm';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AAGxB,cAAc,wBAAwB,CAAC;AAKvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAE9C,cAAc,qBAAqB,CAAC;AAGpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AAGxB,cAAc,wBAAwB,CAAC;AAKvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAE9C,cAAc,qBAAqB,CAAC;AAGpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAElC,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AACnD,cAAc,oCAAoC,CAAC;AACnD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yCAAyC,CAAC;AACxD,cAAc,uBAAuB,CAAC;AACtC,cAAc,sCAAsC,CAAC;AACrD,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,gBAAgB,CAAC;AAE/B,cAAc,aAAa,CAAC;AAK5B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAG3C,cAAc,QAAQ,CAAC;AAIvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AAEnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AAGrC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAIhD,cAAc,kCAAkC,CAAC;AACjD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oBAAoB,CAAC;AAGnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qCAAqC,CAAC;AACpD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC;AACvD,cAAc,0CAA0C,CAAC;AACzD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mBAAmB,CAAC;AAClC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,yCAAyC,CAAC;AACxD,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,sCAAsC,CAAC;AACrD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iDAAiD,CAAC;AAChE,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wCAAwC,CAAC;AACvD,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAG9C,cAAc,WAAW,CAAC;AAE1B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAG7C,cAAc,mCAAmC,CAAC;AAElD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AAGrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qCAAqC,CAAC;AACpD,cAAc,iCAAiC,CAAC;AAEhD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,qCAAqC,CAAC;AAEpD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAE3C,cAAc,kCAAkC,CAAC;AAEjD,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAElC,cAAc,SAAS,CAAC;AAExB,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AAIxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mCAAmC,CAAC;AAClD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAE5B,cAAc,kBAAkB,CAAC;AAGjC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,oBAAoB,CAAC;AAEnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,iCAAiC,CAAC;AAGhD,cAAc,OAAO,CAAC;AACtB,cAAc,yBAAyB,CAAC;AACxC,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { AssistantRawMessage } from './types';
|
|
2
|
+
/** One frame as the stream hands it over: the SSE event name and its JSON data. */
|
|
3
|
+
export interface LiveFrame {
|
|
4
|
+
readonly event: string;
|
|
5
|
+
readonly data: unknown;
|
|
6
|
+
}
|
|
7
|
+
/** What the reducer holds about one text part. */
|
|
8
|
+
export interface LivePartState {
|
|
9
|
+
readonly messageId: string;
|
|
10
|
+
/** The stream generation that started the part (`LiveDeltaState.generation`). */
|
|
11
|
+
readonly generation: number;
|
|
12
|
+
/** The redacted text so far — or, once `ended`, the final redacted text. */
|
|
13
|
+
readonly text: string;
|
|
14
|
+
/** Began live: this stream saw the part's start frame. `false` is poll-only. */
|
|
15
|
+
readonly live: boolean;
|
|
16
|
+
/** The part's end frame arrived. */
|
|
17
|
+
readonly ended: boolean;
|
|
18
|
+
/** A delta did not continue the text: no later delta is applied. */
|
|
19
|
+
readonly gapped: boolean;
|
|
20
|
+
/** A new generation began while the part was being written. */
|
|
21
|
+
readonly frozen: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface LiveMessageState {
|
|
24
|
+
readonly created?: number;
|
|
25
|
+
readonly completed?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface LiveDeltaState {
|
|
28
|
+
/** +1 for every re-mint. */
|
|
29
|
+
readonly generation: number;
|
|
30
|
+
readonly parts: ReadonlyMap<string, LivePartState>;
|
|
31
|
+
readonly messages: ReadonlyMap<string, LiveMessageState>;
|
|
32
|
+
}
|
|
33
|
+
/** Bounds on what one turn's stream may make this reducer remember. */
|
|
34
|
+
export declare const LIVE_PART_LIMIT = 256;
|
|
35
|
+
export declare const LIVE_MESSAGE_LIMIT = 256;
|
|
36
|
+
/** The longest live text one part may hold; past it the part is frozen. */
|
|
37
|
+
export declare const LIVE_TEXT_LIMIT: number;
|
|
38
|
+
export declare function createLiveState(): LiveDeltaState;
|
|
39
|
+
/**
|
|
40
|
+
* The stream was lost: whatever arrives next is unknown, so every part still
|
|
41
|
+
* being written is frozen at its text. The generation does not change.
|
|
42
|
+
*/
|
|
43
|
+
export declare function freezeLiveParts(state: LiveDeltaState): LiveDeltaState;
|
|
44
|
+
/**
|
|
45
|
+
* A new generation: the stream was replaced (a re-mint). Every part still being
|
|
46
|
+
* written is frozen at its text — the frames between two streams are unknown —
|
|
47
|
+
* and parts the new stream starts belong to the new generation.
|
|
48
|
+
*/
|
|
49
|
+
export declare function beginLiveGeneration(state: LiveDeltaState): LiveDeltaState;
|
|
50
|
+
/**
|
|
51
|
+
* Fold one frame into the state. Frames that are not about text (a tool part, a
|
|
52
|
+
* reasoning part, `session.idle`, `stream.end`) change nothing here: they wake
|
|
53
|
+
* the poll loop, and that is `turnStream`'s business.
|
|
54
|
+
*/
|
|
55
|
+
export declare function reduceLiveFrame(state: LiveDeltaState, frame: LiveFrame): LiveDeltaState;
|
|
56
|
+
/**
|
|
57
|
+
* The poll's messages with the live text merged in, for DISPLAY ONLY.
|
|
58
|
+
*
|
|
59
|
+
* - Only messages created after `floor` are touched.
|
|
60
|
+
* - A text part the poll already has is rewritten in place (same id); a
|
|
61
|
+
* live-from-start part the poll has not seen yet is appended to its message,
|
|
62
|
+
* or to a synthetic assistant message that is NOT completed.
|
|
63
|
+
* - A part first seen mid-way (`live: false`) is never taken from the stream.
|
|
64
|
+
* - The input is never modified; nothing is removed; nothing but the text of
|
|
65
|
+
* text parts changes.
|
|
66
|
+
*/
|
|
67
|
+
export declare function applyLiveDeltas(polled: readonly AssistantRawMessage[], state: LiveDeltaState, floor: number): AssistantRawMessage[];
|
|
68
|
+
/**
|
|
69
|
+
* How much of the turn's text the stream carried: `full` when every text part
|
|
70
|
+
* it saw was live from its start and none was gapped or frozen, `partial` when
|
|
71
|
+
* the stream carried some but not all, `none` when it carried nothing.
|
|
72
|
+
*/
|
|
73
|
+
export declare function liveCoverage(state: LiveDeltaState): "full" | "partial" | "none";
|
|
74
|
+
/** Has any live text arrived that could be shown? */
|
|
75
|
+
export declare function hasLiveText(state: LiveDeltaState): boolean;
|
|
76
|
+
//# sourceMappingURL=liveDeltas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"liveDeltas.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/liveDeltas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,SAAS,CAAC;AAE5E,mFAAmF;AACnF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iFAAiF;IACjF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,oCAAoC;IACpC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC1D;AAED,uEAAuE;AACvE,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,2EAA2E;AAC3E,eAAO,MAAM,eAAe,QAAa,CAAC;AAE1C,wBAAgB,eAAe,IAAI,cAAc,CAEhD;AAqBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CASrE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAGzE;AA+HD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,SAAS,GACf,cAAc,CAehB;AAoCD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,mBAAmB,EAAE,EACtC,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,MAAM,GACZ,mBAAmB,EAAE,CAmEvB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAa/E;AAED,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAK1D"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
//#region src/shared/assistant/liveDeltas.ts
|
|
2
|
+
var e = 256, t = 256, n = 512 * 1024;
|
|
3
|
+
function r() {
|
|
4
|
+
return {
|
|
5
|
+
generation: 0,
|
|
6
|
+
parts: /* @__PURE__ */ new Map(),
|
|
7
|
+
messages: /* @__PURE__ */ new Map()
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function i(e) {
|
|
11
|
+
return typeof e == "object" && e && !Array.isArray(e) ? e : void 0;
|
|
12
|
+
}
|
|
13
|
+
var a = (e) => typeof e == "string" && e !== "" ? e : void 0, o = (e) => typeof e == "number" && Number.isFinite(e) ? e : void 0;
|
|
14
|
+
function s(e, t, n) {
|
|
15
|
+
let r = new Map(e);
|
|
16
|
+
return r.set(t, n), r;
|
|
17
|
+
}
|
|
18
|
+
function c(e) {
|
|
19
|
+
let t = null;
|
|
20
|
+
for (let [n, r] of e.parts) r.live && !r.ended && !r.frozen && (t ??= new Map(e.parts), t.set(n, {
|
|
21
|
+
...r,
|
|
22
|
+
frozen: !0
|
|
23
|
+
}));
|
|
24
|
+
return t ? {
|
|
25
|
+
...e,
|
|
26
|
+
parts: t
|
|
27
|
+
} : e;
|
|
28
|
+
}
|
|
29
|
+
function l(e) {
|
|
30
|
+
let t = c(e);
|
|
31
|
+
return {
|
|
32
|
+
...t,
|
|
33
|
+
generation: t.generation + 1
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function u(e, t) {
|
|
37
|
+
let n = i(t.info), r = a(n?.id);
|
|
38
|
+
if (!n || !r || n.role !== "assistant" || !e.messages.has(r) && e.messages.size >= 256) return e;
|
|
39
|
+
let c = i(n.time), l = o(c?.created), u = o(c?.completed), d = e.messages.get(r);
|
|
40
|
+
return {
|
|
41
|
+
...e,
|
|
42
|
+
messages: s(e.messages, r, {
|
|
43
|
+
...l === void 0 ? d?.created === void 0 ? {} : { created: d.created } : { created: l },
|
|
44
|
+
...u === void 0 ? d?.completed === void 0 ? {} : { completed: d.completed } : { completed: u }
|
|
45
|
+
})
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function d(e, t) {
|
|
49
|
+
let r = a(t.id), c = a(t.messageID);
|
|
50
|
+
if (!r || !c) return e;
|
|
51
|
+
let l = o(i(t.time)?.end) !== void 0, u = typeof t.text == "string" ? t.text : void 0, d = e.parts.get(r);
|
|
52
|
+
if (!d) {
|
|
53
|
+
if (e.parts.size >= 256) return e;
|
|
54
|
+
let n = t.live === !0 && u === "" && !l;
|
|
55
|
+
return {
|
|
56
|
+
...e,
|
|
57
|
+
parts: s(e.parts, r, {
|
|
58
|
+
messageId: c,
|
|
59
|
+
generation: e.generation,
|
|
60
|
+
text: "",
|
|
61
|
+
live: n,
|
|
62
|
+
ended: l,
|
|
63
|
+
gapped: !1,
|
|
64
|
+
frozen: !1
|
|
65
|
+
})
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return d.ended || !l ? e : !d.live || u === void 0 ? {
|
|
69
|
+
...e,
|
|
70
|
+
parts: s(e.parts, r, {
|
|
71
|
+
...d,
|
|
72
|
+
ended: !0
|
|
73
|
+
})
|
|
74
|
+
} : {
|
|
75
|
+
...e,
|
|
76
|
+
parts: s(e.parts, r, {
|
|
77
|
+
...d,
|
|
78
|
+
text: u.length > 524288 ? u.slice(0, n) : u,
|
|
79
|
+
ended: !0
|
|
80
|
+
})
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function f(e, t) {
|
|
84
|
+
let n = a(t.partID), r = typeof t.delta == "string" ? t.delta : void 0, i = o(t.offset);
|
|
85
|
+
if (!n || r === void 0) return e;
|
|
86
|
+
let c = e.parts.get(n);
|
|
87
|
+
return !c || !c.live || c.ended || c.gapped || c.frozen ? e : c.generation === e.generation ? i !== c.text.length || c.text.length + r.length > 524288 ? {
|
|
88
|
+
...e,
|
|
89
|
+
parts: s(e.parts, n, {
|
|
90
|
+
...c,
|
|
91
|
+
gapped: !0
|
|
92
|
+
})
|
|
93
|
+
} : r === "" ? e : {
|
|
94
|
+
...e,
|
|
95
|
+
parts: s(e.parts, n, {
|
|
96
|
+
...c,
|
|
97
|
+
text: c.text + r
|
|
98
|
+
})
|
|
99
|
+
} : {
|
|
100
|
+
...e,
|
|
101
|
+
parts: s(e.parts, n, {
|
|
102
|
+
...c,
|
|
103
|
+
frozen: !0
|
|
104
|
+
})
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function p(e, t) {
|
|
108
|
+
let n = i(t.data);
|
|
109
|
+
if (!n) return e;
|
|
110
|
+
switch (t.event) {
|
|
111
|
+
case "message.updated": return u(e, n);
|
|
112
|
+
case "message.part.updated": return n.type === "text" ? d(e, n) : e;
|
|
113
|
+
case "message.part.delta": return n.partType === "text" || n.partType === void 0 ? f(e, n) : e;
|
|
114
|
+
default: return e;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function m(e, t) {
|
|
118
|
+
return e.time?.end !== void 0 || t.info?.time?.completed !== void 0;
|
|
119
|
+
}
|
|
120
|
+
function h(e, t, n) {
|
|
121
|
+
return t !== void 0 && n ? t : t === void 0 ? e.text : t.startsWith(e.text) ? t : e.text.startsWith(t) ? e.text : t;
|
|
122
|
+
}
|
|
123
|
+
function g(e, t, n) {
|
|
124
|
+
if (t.parts.size === 0) return [...e];
|
|
125
|
+
let r = /* @__PURE__ */ new Map();
|
|
126
|
+
for (let e of t.parts) {
|
|
127
|
+
let [, t] = e;
|
|
128
|
+
if (!t.live || t.text === "" && !t.ended) continue;
|
|
129
|
+
let n = r.get(t.messageId);
|
|
130
|
+
n ? n.push(e) : r.set(t.messageId, [e]);
|
|
131
|
+
}
|
|
132
|
+
if (r.size === 0) return [...e];
|
|
133
|
+
let i = [], a = /* @__PURE__ */ new Set();
|
|
134
|
+
for (let t of e) {
|
|
135
|
+
let e = t.info?.id, o = e ? r.get(e) : void 0;
|
|
136
|
+
if (!e || !o) {
|
|
137
|
+
i.push(t);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
a.add(e);
|
|
141
|
+
let s = t.info?.time?.created ?? 0;
|
|
142
|
+
if (t.info?.role !== "assistant" || s <= n) {
|
|
143
|
+
i.push(t);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
let c = [...t.parts ?? []];
|
|
147
|
+
for (let [e, n] of o) {
|
|
148
|
+
let r = c.findIndex((t) => t.type === "text" && t.id === e);
|
|
149
|
+
if (r < 0) {
|
|
150
|
+
c.push({
|
|
151
|
+
type: "text",
|
|
152
|
+
id: e,
|
|
153
|
+
text: n.text
|
|
154
|
+
});
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
let i = c[r], a = h(n, typeof i.text == "string" ? i.text : void 0, m(i, t));
|
|
158
|
+
a !== i.text && (c[r] = {
|
|
159
|
+
...i,
|
|
160
|
+
text: a
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
i.push({
|
|
164
|
+
...t,
|
|
165
|
+
parts: c
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
for (let [e, o] of r) {
|
|
169
|
+
if (a.has(e)) continue;
|
|
170
|
+
let r = t.messages.get(e)?.created;
|
|
171
|
+
r === void 0 || r <= n || i.push({
|
|
172
|
+
info: {
|
|
173
|
+
id: e,
|
|
174
|
+
role: "assistant",
|
|
175
|
+
time: { created: r }
|
|
176
|
+
},
|
|
177
|
+
parts: o.map(([e, t]) => ({
|
|
178
|
+
type: "text",
|
|
179
|
+
id: e,
|
|
180
|
+
text: t.text
|
|
181
|
+
}))
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
return i;
|
|
185
|
+
}
|
|
186
|
+
function _(e) {
|
|
187
|
+
let t = 0, n = 0;
|
|
188
|
+
for (let r of e.parts.values()) r.live && r.text !== "" ? (t += 1, (r.gapped || r.frozen) && (n += 1)) : r.live || (n += 1);
|
|
189
|
+
return t === 0 ? "none" : n === 0 ? "full" : "partial";
|
|
190
|
+
}
|
|
191
|
+
function v(e) {
|
|
192
|
+
for (let t of e.parts.values()) if (t.live && t.text !== "") return !0;
|
|
193
|
+
return !1;
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
export { t as LIVE_MESSAGE_LIMIT, e as LIVE_PART_LIMIT, n as LIVE_TEXT_LIMIT, g as applyLiveDeltas, l as beginLiveGeneration, r as createLiveState, c as freezeLiveParts, v as hasLiveText, _ as liveCoverage, p as reduceLiveFrame };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { LiveDeltaState } from './liveDeltas';
|
|
2
|
+
import { AssistantRawMessage } from './types';
|
|
3
|
+
export interface LiveOverlayEntry {
|
|
4
|
+
readonly conversationId: string;
|
|
5
|
+
readonly content: string;
|
|
6
|
+
}
|
|
7
|
+
interface LiveOverlayState {
|
|
8
|
+
readonly byMessageId: Readonly<Record<string, LiveOverlayEntry>>;
|
|
9
|
+
setLive: (messageId: string, conversationId: string, content: string) => void;
|
|
10
|
+
clearLive: (messageId: string) => void;
|
|
11
|
+
}
|
|
12
|
+
/** Not persisted, by construction: there is no `persist` in this file. */
|
|
13
|
+
export declare const useLiveOverlay: import('zustand').UseBoundStore<import('zustand').StoreApi<LiveOverlayState>>;
|
|
14
|
+
/** The live text for one message, or null when there is none. */
|
|
15
|
+
export declare function useLiveOverlayContent(messageId: string | null | undefined): string | null;
|
|
16
|
+
/** What the live renderer needs of the stream. `TurnStream` satisfies it. */
|
|
17
|
+
export interface LiveSource {
|
|
18
|
+
readonly live: LiveDeltaState;
|
|
19
|
+
onLive(listener: () => void): () => void;
|
|
20
|
+
endLive(): void;
|
|
21
|
+
}
|
|
22
|
+
export interface LiveRenderOptions {
|
|
23
|
+
stream: LiveSource;
|
|
24
|
+
conversationId: string;
|
|
25
|
+
/** The turn's own assistant message id: the only key this writes. */
|
|
26
|
+
messageId: string;
|
|
27
|
+
/**
|
|
28
|
+
* The bubble's text for these messages — the SAME builder the poll uses
|
|
29
|
+
* (`buildAssistantProgress` + `sanitizeAssistantResponse`), so the live text
|
|
30
|
+
* and the finished answer are made the same way.
|
|
31
|
+
*/
|
|
32
|
+
build: (messages: AssistantRawMessage[], floor: number) => string;
|
|
33
|
+
/** Called once, when live text first exists for this turn (after arming). */
|
|
34
|
+
onFirstDelta?: () => void;
|
|
35
|
+
/** Called once, when the overlay first shows text. */
|
|
36
|
+
onFirstVisible?: () => void;
|
|
37
|
+
/** Minimum gap between live renders. Leading edge, with a trailing call. */
|
|
38
|
+
throttleMs?: number;
|
|
39
|
+
now?: () => number;
|
|
40
|
+
setTimer?: (run: () => void, ms: number) => unknown;
|
|
41
|
+
clearTimer?: (timer: unknown) => void;
|
|
42
|
+
/** Tests only: a store other than the shared one. */
|
|
43
|
+
overlay?: Pick<LiveOverlayState, "setLive" | "clearLive">;
|
|
44
|
+
}
|
|
45
|
+
export interface LiveRender {
|
|
46
|
+
/**
|
|
47
|
+
* Allow rendering, once the reply floor is known AND the prompt is sent
|
|
48
|
+
* (design rule 3). Frames that arrived earlier were only kept; they render
|
|
49
|
+
* now, if they are this turn's.
|
|
50
|
+
*/
|
|
51
|
+
arm(floor: number): void;
|
|
52
|
+
/** The poll landed: re-merge its messages with the live text, at once. */
|
|
53
|
+
refresh(polled: readonly AssistantRawMessage[]): void;
|
|
54
|
+
/** Synchronous, idempotent. Detaches, cancels the throttle, drops the overlay. */
|
|
55
|
+
end(): void;
|
|
56
|
+
readonly armed: boolean;
|
|
57
|
+
readonly ended: boolean;
|
|
58
|
+
}
|
|
59
|
+
export declare const LIVE_RENDER_THROTTLE_MS = 100;
|
|
60
|
+
export declare function createLiveRender(options: LiveRenderOptions): LiveRender;
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=liveOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"liveOverlay.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/liveOverlay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,UAAU,gBAAgB;IACxB,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACjE,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9E,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,0EAA0E;AAC1E,eAAO,MAAM,cAAc,+EAyBxB,CAAC;AAEJ,iEAAiE;AACjE,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,MAAM,GAAG,IAAI,CAIf;AAED,6EAA6E;AAC7E,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IACzC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,KAAK,EAAE,CAAC,QAAQ,EAAE,mBAAmB,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClE,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,sDAAsD;IACtD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACpD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,qDAAqD;IACrD,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,WAAW,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,UAAU;IACzB;;;;OAIG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,0EAA0E;IAC1E,OAAO,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,GAAG,IAAI,CAAC;IACtD,kFAAkF;IAClF,GAAG,IAAI,IAAI,CAAC;IACZ,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAkGvE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { applyLiveDeltas as e, hasLiveText as t } from "./liveDeltas.js";
|
|
2
|
+
import { create as n } from "zustand";
|
|
3
|
+
//#region src/shared/assistant/liveOverlay.ts
|
|
4
|
+
var r = n()((e) => ({
|
|
5
|
+
byMessageId: {},
|
|
6
|
+
setLive: (t, n, r) => e((e) => {
|
|
7
|
+
let i = e.byMessageId[t];
|
|
8
|
+
return i && i.content === r && i.conversationId === n ? e : { byMessageId: {
|
|
9
|
+
...e.byMessageId,
|
|
10
|
+
[t]: {
|
|
11
|
+
conversationId: n,
|
|
12
|
+
content: r
|
|
13
|
+
}
|
|
14
|
+
} };
|
|
15
|
+
}),
|
|
16
|
+
clearLive: (t) => e((e) => {
|
|
17
|
+
if (!(t in e.byMessageId)) return e;
|
|
18
|
+
let n = { ...e.byMessageId };
|
|
19
|
+
return delete n[t], { byMessageId: n };
|
|
20
|
+
})
|
|
21
|
+
}));
|
|
22
|
+
function i(e) {
|
|
23
|
+
return r((t) => e ? t.byMessageId[e]?.content ?? null : null);
|
|
24
|
+
}
|
|
25
|
+
var a = 100;
|
|
26
|
+
function o(n) {
|
|
27
|
+
let i = n.now ?? Date.now, a = n.setTimer ?? ((e, t) => setTimeout(e, t)), o = n.clearTimer ?? ((e) => {
|
|
28
|
+
clearTimeout(e);
|
|
29
|
+
}), s = n.overlay ?? r.getState(), c = n.throttleMs ?? 100, l = null, u = [], d = !1, f = null, p = -Infinity, m = "", h = !1, g = !1, _ = () => l === null ? "" : n.build(e(u, n.stream.live, l), l), v = () => {
|
|
30
|
+
h || l === null || t(n.stream.live) && _() !== "" && (h = !0, n.onFirstDelta?.());
|
|
31
|
+
}, y = () => {
|
|
32
|
+
if (f = null, d || l === null) return;
|
|
33
|
+
let e = _();
|
|
34
|
+
e === "" || e === m || (p = i(), m = e, s.setLive(n.messageId, n.conversationId, e), g || (g = !0, n.onFirstVisible?.()));
|
|
35
|
+
}, b = n.stream.onLive(() => {
|
|
36
|
+
if (d || l === null) return;
|
|
37
|
+
v();
|
|
38
|
+
let e = p + c - i();
|
|
39
|
+
if (e <= 0) {
|
|
40
|
+
f !== null && (o(f), f = null), y();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
f === null && (f = a(y, e));
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
arm(e) {
|
|
47
|
+
d || l !== null || (l = e, v(), y());
|
|
48
|
+
},
|
|
49
|
+
refresh(e) {
|
|
50
|
+
u = e, !(d || l === null) && y();
|
|
51
|
+
},
|
|
52
|
+
end() {
|
|
53
|
+
d || (d = !0, f !== null && (o(f), f = null), b(), s.clearLive(n.messageId), n.stream.endLive());
|
|
54
|
+
},
|
|
55
|
+
get armed() {
|
|
56
|
+
return l !== null;
|
|
57
|
+
},
|
|
58
|
+
get ended() {
|
|
59
|
+
return d;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { a as LIVE_RENDER_THROTTLE_MS, o as createLiveRender, r as useLiveOverlay, i as useLiveOverlayContent };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ★★ BOFF-7914 (speed S3): the completion fast path.
|
|
3
|
+
*
|
|
4
|
+
* A turn's completion is discovered by a GET of the session's messages — the
|
|
5
|
+
* poll — and only by it. Without a stream the poll is the whole mechanism.
|
|
6
|
+
* With one, the bridge's `session.idle` says the turn is over, and the question
|
|
7
|
+
* becomes how soon after it the poll can SEE that.
|
|
8
|
+
*
|
|
9
|
+
* Take the common case: a GET started just before the idle is still in flight.
|
|
10
|
+
* Its answer was read before the turn settled, so it will probably say "not
|
|
11
|
+
* done", and the loop would then sleep and issue another. Instead, the idle
|
|
12
|
+
* starts ONE extra GET at once, beside the one in flight. Then:
|
|
13
|
+
*
|
|
14
|
+
* - Snapshots are applied in START order. Whichever finishes first is applied;
|
|
15
|
+
* an OLDER snapshot that arrives after a newer one is discarded.
|
|
16
|
+
* - At most one extra request is outstanding, and at most two are started per
|
|
17
|
+
* turn. The cadence of an ordinary poll is unchanged.
|
|
18
|
+
* - A failed request is skipped when a newer one is still pending or has
|
|
19
|
+
* succeeded; it is thrown only when nothing newer can answer.
|
|
20
|
+
* - A snapshot says nothing by itself: the caller applies it exactly as it
|
|
21
|
+
* applies a snapshot without a stream. This module decides nothing about the
|
|
22
|
+
* turn.
|
|
23
|
+
*/
|
|
24
|
+
export interface SnapshotPollerOptions {
|
|
25
|
+
/** Extra requests the idle fast path may start per turn. */
|
|
26
|
+
maxExtra?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface SnapshotPoller<T> {
|
|
29
|
+
/**
|
|
30
|
+
* The next snapshot to apply. Starts a request when none is pending; when a
|
|
31
|
+
* newer request than the one that answered is pending, it stays pending for
|
|
32
|
+
* the next call (`hasPending`).
|
|
33
|
+
*/
|
|
34
|
+
next(): Promise<T>;
|
|
35
|
+
/**
|
|
36
|
+
* The bridge said the turn is idle. If a request is in flight, start one
|
|
37
|
+
* extra now and return true; otherwise (or past the caps) return false and
|
|
38
|
+
* leave it to the next `next()`.
|
|
39
|
+
*/
|
|
40
|
+
startExtra(): boolean;
|
|
41
|
+
/** A started request has not been applied yet: do not sleep before `next()`. */
|
|
42
|
+
hasPending(): boolean;
|
|
43
|
+
/** Requests started in all, for tests and for the timeline. */
|
|
44
|
+
readonly started: number;
|
|
45
|
+
readonly extraStarted: number;
|
|
46
|
+
}
|
|
47
|
+
export declare function createSnapshotPoller<T>(fetch: () => Promise<T>, options?: SnapshotPollerOptions): SnapshotPoller<T>;
|
|
48
|
+
//# sourceMappingURL=snapshotPoller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshotPoller.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/snapshotPoller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B;;;;OAIG;IACH,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IACnB;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC;IACtB,gFAAgF;IAChF,UAAU,IAAI,OAAO,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAUD,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,KAAK,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACvB,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAAC,CAAC,CAAC,CAoGnB"}
|