@alexkroman1/aai-ui 0.14.1 → 0.14.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/_actor-store.d.ts +16 -0
- package/dist/_recover-run.d.ts +13 -17
- package/dist/_submission-state.d.ts +33 -69
- package/dist/_tap-to-talk-state.d.ts +2 -6
- package/dist/_workflow-form-state.d.ts +117 -0
- package/dist/default-client/assets/{audio-CABEDpag.js → audio-C_FqJApT.js} +1 -1
- package/dist/default-client/assets/{capture-processor-X_vJUkv4.js → capture-processor-C4rOgMnr.js} +1 -1
- package/dist/default-client/assets/{index-DdRGAZxZ.js → index-CRMh5gpc.js} +11 -11
- package/dist/default-client/assets/{playback-processor-DdO-2G6m.js → playback-processor-J74Xm_Cx.js} +1 -1
- package/dist/default-client/index.html +1 -1
- package/dist/define-client.js +1 -1
- package/dist/inbox.d.ts +2 -1
- package/dist/index.js +477 -316
- package/dist/session/connection.d.ts +121 -0
- package/dist/session/handshake.d.ts +20 -33
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.js +1 -1
- package/dist/session/messages.d.ts +6 -0
- package/dist/session/reconnect.d.ts +5 -0
- package/dist/session/types.d.ts +3 -13
- package/dist/{session-6tIQSoak.js → session-CYdjRvbl.js} +277 -147
- package/dist/upload/index.d.ts +2 -2
- package/package.json +2 -2
- package/dist/upload/pause.d.ts +0 -31
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One browser session's CONNECTION — the socket, the handshake deadline over
|
|
3
|
+
* it, and the server's idle retirement — as a statechart.
|
|
4
|
+
*
|
|
5
|
+
* `link` is `closed → open`, and `open` is `dialing → awaitingHandshake → live`:
|
|
6
|
+
*
|
|
7
|
+
* - **The socket belongs to `open`.** Its entry dials and attaches the
|
|
8
|
+
* listeners; its exit is the ONE teardown (detach, release the pre-connect
|
|
9
|
+
* mic, tear the audio path down, close the socket). A hang-up, a terminal
|
|
10
|
+
* close, an exhausted handshake and a fresh `connect()` all leave `open`, so
|
|
11
|
+
* none of them restates it, and exit actions run before the transition's, so
|
|
12
|
+
* the teardown always precedes the snapshot write reporting the end.
|
|
13
|
+
* - **The handshake deadline is an `after` on `awaitingHandshake`** (see
|
|
14
|
+
* `session/handshake.ts` for why there is one). Leaving the state disarms it,
|
|
15
|
+
* so a `config` frame, a close or a teardown cannot leave it armed against
|
|
16
|
+
* the next attempt — there is no timer to clear by hand on abort.
|
|
17
|
+
* - **partysocket owns the reconnect backoff.** A close that partysocket will
|
|
18
|
+
* retry goes back to `dialing` and waits for its next `open`; this machine
|
|
19
|
+
* never schedules an attempt. The deadline forces one only for a socket
|
|
20
|
+
* partysocket thinks is healthy (`forceReconnect`).
|
|
21
|
+
*
|
|
22
|
+
* `retired` is a second region because it outlives a socket: the server's
|
|
23
|
+
* `session.timedOut` marks the close that follows as EXPECTED, so it is not
|
|
24
|
+
* retried. Without it the automatic reconnect would re-open the session the
|
|
25
|
+
* server just reclaimed — a tab left open would cycle forever and the guest
|
|
26
|
+
* would never see zero sessions, which is the point of the timeout. Only a
|
|
27
|
+
* fresh `connect()` (the user asking again) clears it.
|
|
28
|
+
*
|
|
29
|
+
* The machine owns WHEN; every HOW — the socket, the snapshot, the audio path —
|
|
30
|
+
* is an injected {@link ConnectionEffects} call, as in `session/audio-state.ts`.
|
|
31
|
+
*/
|
|
32
|
+
import type { SessionConfigMessage } from "./messages.ts";
|
|
33
|
+
/** The socket shape the session speaks (a partysocket, or an injected `WebSocket`). */
|
|
34
|
+
type Socket = WebSocket;
|
|
35
|
+
/** The session core's side of the machine. */
|
|
36
|
+
export type ConnectionEffects = {
|
|
37
|
+
/** Open the socket for a fresh `connect()` and make it the session's. */
|
|
38
|
+
dial(): Socket;
|
|
39
|
+
/**
|
|
40
|
+
* Let go of everything one connection holds: the pre-connect mic, the audio
|
|
41
|
+
* path and `socket`. Its listeners are already detached, so the close this
|
|
42
|
+
* causes cannot re-enter the machine.
|
|
43
|
+
*/
|
|
44
|
+
release(socket: Socket): void;
|
|
45
|
+
/** The caller's `connect({ signal })` aborted: hang up. */
|
|
46
|
+
abandon(): void;
|
|
47
|
+
/** Interpret a frame; the `config` payload when it completes the handshake. */
|
|
48
|
+
receive(data: unknown): SessionConfigMessage | undefined;
|
|
49
|
+
/** The socket opened; the handshake has not completed yet. */
|
|
50
|
+
opened(): void;
|
|
51
|
+
/** The handshake completed. */
|
|
52
|
+
configured(config: SessionConfigMessage): void;
|
|
53
|
+
/** Is the session fatally over (`session/state.ts`)? Then no close is retried. */
|
|
54
|
+
fatal(): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Will partysocket retry the close being dispatched on `socket`? Asked
|
|
57
|
+
* inside the `close` listener: partysocket schedules its retry before it
|
|
58
|
+
* dispatches.
|
|
59
|
+
*/
|
|
60
|
+
retryPending(socket: Socket): boolean;
|
|
61
|
+
/** Does the socket have reconnect machinery? An injected `WebSocket` does not. */
|
|
62
|
+
canRedial(): boolean;
|
|
63
|
+
/** Force a fresh attempt on a socket that opened but never became a session. */
|
|
64
|
+
redial(): void;
|
|
65
|
+
/** An attempt failed and another is coming: drop the audio path, show `connecting`. */
|
|
66
|
+
retrying(): void;
|
|
67
|
+
/** The socket closed for good — `failure` is what to report, null for a clean end. */
|
|
68
|
+
closed(failure: string | null): void;
|
|
69
|
+
/** The handshake budget is spent. */
|
|
70
|
+
exhausted(): void;
|
|
71
|
+
};
|
|
72
|
+
/** Everything that happens to the connection. */
|
|
73
|
+
export type ConnectionEvent =
|
|
74
|
+
/** `connect()`: tear down whatever is there and dial afresh. */
|
|
75
|
+
{
|
|
76
|
+
type: "DIAL";
|
|
77
|
+
signal?: AbortSignal | undefined;
|
|
78
|
+
}
|
|
79
|
+
/** The caller hung up (`disconnect()`, `end()`). */
|
|
80
|
+
| {
|
|
81
|
+
type: "HANG_UP";
|
|
82
|
+
}
|
|
83
|
+
/** The server retired the session for idleness (`session.timedOut`). */
|
|
84
|
+
| {
|
|
85
|
+
type: "RETIRED";
|
|
86
|
+
}
|
|
87
|
+
/** The socket opened. */
|
|
88
|
+
| {
|
|
89
|
+
type: "OPENED";
|
|
90
|
+
}
|
|
91
|
+
/** The `config` frame arrived. */
|
|
92
|
+
| {
|
|
93
|
+
type: "CONFIGURED";
|
|
94
|
+
config: SessionConfigMessage;
|
|
95
|
+
}
|
|
96
|
+
/** The socket errored; a `close` always follows. */
|
|
97
|
+
| {
|
|
98
|
+
type: "ERRORED";
|
|
99
|
+
}
|
|
100
|
+
/** The socket closed; `reconnecting` is whether partysocket will retry it. */
|
|
101
|
+
| {
|
|
102
|
+
type: "DROPPED";
|
|
103
|
+
event: CloseEvent;
|
|
104
|
+
reconnecting: boolean;
|
|
105
|
+
};
|
|
106
|
+
/** Where the connection is. */
|
|
107
|
+
export type ConnectionPhase = "closed" | "dialing" | "awaitingHandshake" | "live";
|
|
108
|
+
/** The session core's handle on its connection. */
|
|
109
|
+
export type Connection = {
|
|
110
|
+
/** Tear down whatever is there and dial afresh; `signal` aborting hangs up. */
|
|
111
|
+
dial(signal?: AbortSignal): void;
|
|
112
|
+
/** Hang up: the teardown, and no retry. */
|
|
113
|
+
hangUp(): void;
|
|
114
|
+
/** The server retired the session: the close that follows is not retried. */
|
|
115
|
+
retire(): void;
|
|
116
|
+
/** Where the connection is — for specs. */
|
|
117
|
+
phase(): ConnectionPhase;
|
|
118
|
+
};
|
|
119
|
+
/** Create the connection machine for one browser session. */
|
|
120
|
+
export declare function createConnection(effects: ConnectionEffects): Connection;
|
|
121
|
+
export {};
|
|
@@ -17,44 +17,31 @@
|
|
|
17
17
|
* nothing on screen to say so. Measured against a server that accepts and
|
|
18
18
|
* then says nothing: `ready` at 34ms, still `ready` and errorless when the
|
|
19
19
|
* probe gave up.
|
|
20
|
+
*
|
|
21
|
+
* The deadline itself is the `awaitingHandshake` state's `after` delay in
|
|
22
|
+
* `session/connection.ts`, so leaving the state — a `config` frame, a close, a
|
|
23
|
+
* teardown — is what disarms it. This module holds its numbers and its error.
|
|
20
24
|
*/
|
|
21
25
|
import type { SessionError } from "../types.ts";
|
|
22
26
|
/** What the session reports once the budget below is spent. */
|
|
23
27
|
export declare const HANDSHAKE_ERROR: SessionError;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
arm(): void;
|
|
27
|
-
/** Stop it — this socket is closing, or the connection is being torn down. */
|
|
28
|
-
disarm(): void;
|
|
29
|
-
/**
|
|
30
|
-
* The `config` frame arrived: stop the deadline AND spend nothing.
|
|
31
|
-
*
|
|
32
|
-
* Separate from {@link HandshakeGuard.disarm} because the budget is
|
|
33
|
-
* CONSECUTIVE, and only a completed handshake proves the peer is healthy. One
|
|
34
|
-
* guard covers a whole `connect()`, partysocket's retries included, so with a
|
|
35
|
-
* plain disarm the count survived every successful session in between: an
|
|
36
|
-
* hour-long call whose socket dropped three times, each drop timing out once
|
|
37
|
-
* before the next attempt succeeded, surfaced the permanent
|
|
38
|
-
* "Agent did not complete the session handshake" error against a peer that
|
|
39
|
-
* had answered every time. A close must NOT reset it — a wedged peer closes
|
|
40
|
-
* and reopens on its own, and resetting there is the unbounded re-dial loop
|
|
41
|
-
* the budget exists to bound.
|
|
42
|
-
*/
|
|
43
|
-
succeeded(): void;
|
|
44
|
-
};
|
|
28
|
+
/** How long an OPEN socket may go without a `config` frame. */
|
|
29
|
+
export declare const HANDSHAKE_TIMEOUT_MS = 10000;
|
|
45
30
|
/**
|
|
46
|
-
*
|
|
31
|
+
* How many consecutive handshake timeouts to ride out before giving up.
|
|
47
32
|
*
|
|
48
|
-
* `
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
33
|
+
* `forceReconnect` restarts partysocket's own retry budget, so this is the
|
|
34
|
+
* budget for this failure mode — without one, a permanently wedged peer would
|
|
35
|
+
* be re-dialed every ~10s forever, which is the unbounded retry loop
|
|
36
|
+
* `RECONNECT_OPTIONS.maxRetries` exists to prevent.
|
|
52
37
|
*
|
|
53
|
-
*
|
|
38
|
+
* CONSECUTIVE is the whole of it: only a completed handshake resets the count.
|
|
39
|
+
* One `connect()` spans partysocket's retries, so a count that survived a
|
|
40
|
+
* successful session in between turned an hour-long call whose socket dropped
|
|
41
|
+
* three times — each drop timing out once before the next attempt succeeded —
|
|
42
|
+
* into the permanent "did not complete the session handshake" error against a
|
|
43
|
+
* peer that had answered every time. A close must NOT reset it: a wedged peer
|
|
44
|
+
* closes and reopens on its own, and resetting there is the unbounded re-dial
|
|
45
|
+
* loop the budget exists to bound.
|
|
54
46
|
*/
|
|
55
|
-
export declare
|
|
56
|
-
socket: unknown;
|
|
57
|
-
signal: AbortSignal;
|
|
58
|
-
onRetry: () => void;
|
|
59
|
-
onExhausted: () => void;
|
|
60
|
-
}): HandshakeGuard;
|
|
47
|
+
export declare const MAX_HANDSHAKE_TIMEOUTS = 3;
|
package/dist/session/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `createBrowserSession` and the types its handle is described by are what the
|
|
5
5
|
* package builds on; every other module in `session/` (the dialer, the
|
|
6
|
-
* reconnecting socket, the handshake
|
|
6
|
+
* reconnecting socket, the handshake deadline, the three statecharts, the message
|
|
7
7
|
* handlers, the audio path's bring-up) is private to this directory. Private
|
|
8
8
|
* means NOT re-exported here: guard-invariants rule 37 fails an import from
|
|
9
9
|
* outside `session/` that names any module but this one.
|
package/dist/session/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ticketCarriage, i as resolveSessionTokenSync, n as CLEARED_SESSION_STATE, o as loadAudioModules, r as resolveSessionToken, t as createBrowserSession } from "../session-
|
|
1
|
+
import { a as ticketCarriage, i as resolveSessionTokenSync, n as CLEARED_SESSION_STATE, o as loadAudioModules, r as resolveSessionToken, t as createBrowserSession } from "../session-CYdjRvbl.js";
|
|
2
2
|
export { CLEARED_SESSION_STATE, createBrowserSession, loadAudioModules, resolveSessionToken, resolveSessionTokenSync, ticketCarriage };
|
|
@@ -37,6 +37,12 @@ type MessageHandlerDeps = {
|
|
|
37
37
|
* module's.
|
|
38
38
|
*/
|
|
39
39
|
audio: AudioPath;
|
|
40
|
+
/**
|
|
41
|
+
* The server retired the session for idleness: the close that follows is
|
|
42
|
+
* EXPECTED and must not be retried (the `retired` region of
|
|
43
|
+
* `session/connection.ts`).
|
|
44
|
+
*/
|
|
45
|
+
retire: () => void;
|
|
40
46
|
};
|
|
41
47
|
type MessageHandlers = {
|
|
42
48
|
/**
|
|
@@ -8,6 +8,11 @@ import type { WebSocketConstructor } from "../types.ts";
|
|
|
8
8
|
* tick, for each attempt.
|
|
9
9
|
*/
|
|
10
10
|
export declare function openReconnectingSocket(urlProvider: () => Promise<string>, protocolsProvider?: () => Promise<string[] | null>): InstanceType<WebSocketConstructor>;
|
|
11
|
+
/**
|
|
12
|
+
* Does `socket` have reconnect machinery? False for an injected
|
|
13
|
+
* `options.WebSocket` (tests), which a failure then ends for good.
|
|
14
|
+
*/
|
|
15
|
+
export declare function canReconnect(socket: unknown): boolean;
|
|
11
16
|
/**
|
|
12
17
|
* Force a fresh connection attempt on a reconnecting socket, reporting
|
|
13
18
|
* whether it was one. Used for a failure partysocket cannot see: a socket it
|
package/dist/session/types.d.ts
CHANGED
|
@@ -411,22 +411,12 @@ export type BrowserSession = {
|
|
|
411
411
|
* from anywhere. They are the audio path's own statechart now — see
|
|
412
412
|
* `session/audio-state.ts`.
|
|
413
413
|
*
|
|
414
|
-
* What is left is
|
|
415
|
-
* idle retirement
|
|
414
|
+
* What is left is the socket the senders write to and the turn boundary. The
|
|
415
|
+
* socket's lifecycle and the server's idle retirement are the connection's own
|
|
416
|
+
* statechart (`session/connection.ts`), which is the only writer of `ws`.
|
|
416
417
|
*/
|
|
417
418
|
export type ConnState = {
|
|
418
419
|
ws: InstanceType<WebSocketConstructor> | null;
|
|
419
|
-
/**
|
|
420
|
-
* The server retired this session for idleness (`idle_timeout`), so the
|
|
421
|
-
* close that follows is EXPECTED and must not be retried.
|
|
422
|
-
*
|
|
423
|
-
* Without this the automatic reconnect would immediately re-open the
|
|
424
|
-
* session the server just reclaimed — a tab left open would cycle forever
|
|
425
|
-
* and the guest would never see zero sessions, which is the whole point of
|
|
426
|
-
* the timeout. Reconnecting is the user's call from here (the controls
|
|
427
|
-
* reconnect on demand).
|
|
428
|
-
*/
|
|
429
|
-
retiredByServer: boolean;
|
|
430
420
|
/**
|
|
431
421
|
* Turn epoch, bumped at every turn boundary — a committed user turn, a
|
|
432
422
|
* barge-in, a reset, AND every audio-path teardown (`cleanupAudio`).
|