@belonguniverseai/react-sdk 0.6.0 → 0.6.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/api/client.d.ts +58 -32
- package/dist/api/task-schedules.d.ts +138 -255
- package/dist/component/{arc-DpA4gw3l.js → arc-TLcl3N8_.js} +2 -2
- package/dist/component/{architectureDiagram-3BPJPVTR-C8WjH-Q1.js → architectureDiagram-3BPJPVTR-DYcaPx2M.js} +3 -3
- package/dist/component/{blockDiagram-GPEHLZMM-O9IURu7q.js → blockDiagram-GPEHLZMM-BdjruLO5.js} +4 -4
- package/dist/component/{c4Diagram-AAUBKEIU-B4cFy6te.js → c4Diagram-AAUBKEIU-Bd2ebSgB.js} +3 -3
- package/dist/component/{channel-7qPdE580.js → channel-CYFijF_t.js} +2 -2
- package/dist/component/{chunk-2J33WTMH-CUyqMMUN.js → chunk-2J33WTMH-B06Y_xVy.js} +2 -2
- package/dist/component/{chunk-4BX2VUAB-4MjzMD47.js → chunk-4BX2VUAB-DVpS0I_p.js} +2 -2
- package/dist/component/{chunk-55IACEB6-BOiOLlJY.js → chunk-55IACEB6-DmZctFkK.js} +2 -2
- package/dist/component/{chunk-727SXJPM-D7rQvYjL.js → chunk-727SXJPM-A5r5oL1_.js} +6 -6
- package/dist/component/{chunk-AQP2D5EJ-B4yIZLgM.js → chunk-AQP2D5EJ-D4G4syYu.js} +4 -4
- package/dist/component/{chunk-FMBD7UC4-CHC657o0.js → chunk-FMBD7UC4-CbRxWx_A.js} +2 -2
- package/dist/component/{chunk-ND2GUHAM-BAq6BoPv.js → chunk-ND2GUHAM-OX1-DIU1.js} +2 -2
- package/dist/component/{chunk-QZHKN3VN-DSE2KpkL.js → chunk-QZHKN3VN-DLQ8oUCc.js} +2 -2
- package/dist/component/{classDiagram-4FO5ZUOK-Dp6GpqVA.js → classDiagram-4FO5ZUOK-4S9mdFC1.js} +3 -3
- package/dist/component/{classDiagram-v2-Q7XG4LA2-Dp6GpqVA.js → classDiagram-v2-Q7XG4LA2-4S9mdFC1.js} +3 -3
- package/dist/component/{cose-bilkent-S5V4N54A-D7qy0jl5.js → cose-bilkent-S5V4N54A-BIrVaakt.js} +2 -2
- package/dist/component/{dagre-BM42HDAG-Bp1xKCuc.js → dagre-BM42HDAG-BoPUzTvD.js} +2 -2
- package/dist/component/{diagram-2AECGRRQ-BgnTJHhy.js → diagram-2AECGRRQ-PIXCGxIt.js} +3 -3
- package/dist/component/{diagram-5GNKFQAL-D2Sf6fvv.js → diagram-5GNKFQAL-CbJxbGBh.js} +4 -4
- package/dist/component/{diagram-KO2AKTUF-B6q2Givz.js → diagram-KO2AKTUF-Da1E68Eo.js} +3 -3
- package/dist/component/{diagram-LMA3HP47-Dd-PZ9QO.js → diagram-LMA3HP47-dRbk5sBa.js} +3 -3
- package/dist/component/{diagram-OG6HWLK6-v65-inn8.js → diagram-OG6HWLK6-CcKT8mhn.js} +4 -4
- package/dist/component/{erDiagram-TEJ5UH35-s5ngcfah.js → erDiagram-TEJ5UH35-3ATYT9J-.js} +5 -5
- package/dist/component/{flowDiagram-I6XJVG4X-C-3l7ZN2.js → flowDiagram-I6XJVG4X-D9PLm9Od.js} +7 -7
- package/dist/component/{ganttDiagram-6RSMTGT7-AFajly3C.js → ganttDiagram-6RSMTGT7-F_XUzD1p.js} +3 -3
- package/dist/component/{gitGraphDiagram-PVQCEYII-DLcn7CA-.js → gitGraphDiagram-PVQCEYII-13gVhAGc.js} +4 -4
- package/dist/component/{highlighted-body-OFNGDK62-C7pDeGQU.js → highlighted-body-OFNGDK62-DCxRI4UV.js} +2 -2
- package/dist/component/index.js +2 -2
- package/dist/component/{infoDiagram-5YYISTIA-BuR4-KVY.js → infoDiagram-5YYISTIA-DymxA7AN.js} +2 -2
- package/dist/component/{ishikawaDiagram-YF4QCWOH-DlsfzgFK.js → ishikawaDiagram-YF4QCWOH-C3sTn76C.js} +2 -2
- package/dist/component/{journeyDiagram-JHISSGLW-D0rpdvR5.js → journeyDiagram-JHISSGLW-Cq0hOAfJ.js} +5 -5
- package/dist/component/{kanban-definition-UN3LZRKU-Cz0Dixqc.js → kanban-definition-UN3LZRKU-5tBWjkp7.js} +3 -3
- package/dist/component/{linear-BVVr39mA.js → linear-BT4blD8s.js} +2 -2
- package/dist/component/{mermaid-GHXKKRXX-BEhqkLaB.js → mermaid-GHXKKRXX-DXPXjnb7.js} +38570 -40748
- package/dist/component/{mindmap-definition-RKZ34NQL-wo3l0Jy7.js → mindmap-definition-RKZ34NQL-DO-OuAQQ.js} +4 -4
- package/dist/component/{pieDiagram-4H26LBE5-TtxT_WMN.js → pieDiagram-4H26LBE5-BkEktPwZ.js} +4 -4
- package/dist/component/{quadrantDiagram-W4KKPZXB-DK6ShvdY.js → quadrantDiagram-W4KKPZXB-CaJWg9ep.js} +3 -3
- package/dist/component/{requirementDiagram-4Y6WPE33-Z0IavHMQ.js → requirementDiagram-4Y6WPE33-CmZrtZqe.js} +4 -4
- package/dist/component/{sankeyDiagram-5OEKKPKP-C408nFHk.js → sankeyDiagram-5OEKKPKP-Cp95M1aj.js} +2 -2
- package/dist/component/{sequenceDiagram-3UESZ5HK-CMFVhmkn.js → sequenceDiagram-3UESZ5HK-C0x0WvhR.js} +4 -4
- package/dist/component/{stateDiagram-AJRCARHV-C6Z5V-Yt.js → stateDiagram-AJRCARHV-H10vaGL3.js} +3 -3
- package/dist/component/{stateDiagram-v2-BHNVJYJU-CztCn1yf.js → stateDiagram-v2-BHNVJYJU-rj7ljkc-.js} +3 -3
- package/dist/component/{timeline-definition-PNZ67QCA-D_9a8hKa.js → timeline-definition-PNZ67QCA-Cil1QaqZ.js} +3 -3
- package/dist/component/{vennDiagram-CIIHVFJN-HuWQgr4e.js → vennDiagram-CIIHVFJN-Dk8PKmfb.js} +2 -2
- package/dist/component/{wardleyDiagram-YWT4CUSO-CeUvdi76.js → wardleyDiagram-YWT4CUSO-Xq5Hnmio.js} +3 -3
- package/dist/component/{xychartDiagram-2RQKCTM6-DNmBGn_r.js → xychartDiagram-2RQKCTM6-dinwR4Zm.js} +3 -3
- package/dist/components/embed/BetaBadge.d.ts +12 -0
- package/dist/components/embed/DisclaimerGate.d.ts +16 -0
- package/dist/components/embed/EmbedHeader.d.ts +11 -4
- package/dist/components/embed/LegalShortDisclaimer.d.ts +11 -0
- package/dist/components/embed/LocalePills.d.ts +18 -0
- package/dist/components/embed/WelcomeIntro.d.ts +3 -1
- package/dist/components/embed/rail-flags.d.ts +10 -0
- package/dist/embed/brand-marks.d.ts +5 -5
- package/dist/embed/copy.d.ts +13 -0
- package/dist/embed/legal-disclaimer.d.ts +23 -0
- package/dist/embed/presets.d.ts +5 -1
- package/dist/embed/task-schedule-store.d.ts +3 -13
- package/dist/embed/voice/call-active-marker.d.ts +67 -30
- package/dist/embed/voice/line-dispatch.d.ts +22 -20
- package/dist/embed/voice/realtime-call.d.ts +12 -0
- package/dist/embed/voice/reconnect-offer.d.ts +14 -5
- package/dist/embed/voice/voice-token.d.ts +2 -12
- package/dist/embed/voice-call-lines.d.ts +4 -25
- package/dist/embed/voice-call.d.ts +112 -73
- package/dist/i18n/messages/en.d.ts +12 -6
- package/dist/i18n/messages/surfaces/embedMisc.d.ts +0 -3
- package/dist/i18n/messages/surfaces/stream.d.ts +28 -0
- package/dist/stream/belong-chat-transport.d.ts +101 -587
- package/dist/stream/message-metadata.d.ts +6 -36
- package/dist/stream/run-line-progress.d.ts +6 -5
- package/dist/stream/stream-state-store.d.ts +1 -25
- package/dist/stream/tool-action-label.d.ts +16 -0
- package/package.json +1 -1
- package/dist/components/embed/PoweredByBelong.d.ts +0 -7
- package/dist/embed/voice/agent-queue.d.ts +0 -106
- package/dist/embed/voice/call-roster-store.d.ts +0 -110
|
@@ -2,33 +2,62 @@ import { z } from 'zod';
|
|
|
2
2
|
declare const callActiveMarkerSchema: z.ZodObject<{
|
|
3
3
|
active: z.ZodLiteral<true>;
|
|
4
4
|
startedAtMs: z.ZodNumber;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
updatedAtMs: z.ZodNumber;
|
|
6
|
+
redialCount: z.ZodNumber;
|
|
7
7
|
contextDigest: z.ZodString;
|
|
8
|
-
},
|
|
9
|
-
active: true;
|
|
10
|
-
startedAtMs: number;
|
|
11
|
-
contextDigest: string;
|
|
12
|
-
}, {
|
|
13
|
-
active: true;
|
|
14
|
-
startedAtMs: number;
|
|
15
|
-
contextDigest: string;
|
|
16
|
-
}>;
|
|
8
|
+
}, z.core.$strip>;
|
|
17
9
|
export type CallActiveMarker = z.infer<typeof callActiveMarkerSchema>;
|
|
18
10
|
/** The tab's persisted call marker, or null when absent/malformed — a
|
|
19
11
|
* corrupted or pre-this-feature record just means "nothing to redial". */
|
|
20
12
|
export declare const readCallActiveMarker: () => CallActiveMarker | null;
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Why the call that just reached `in_call` was dialled.
|
|
15
|
+
*
|
|
16
|
+
* `"user"` — a dial the user asked for outright, which is a fresh intent: it
|
|
17
|
+
* inherits nothing from an interrupted call, redial streak included.
|
|
18
|
+
* `"redial"` — a reconnect of an interrupted call, which CONTINUES that
|
|
19
|
+
* streak. `voice-call.ts` maps its `startCall({ isReconnect })` option
|
|
20
|
+
* straight onto this, so the rail's manual "Reconnect" click also continues
|
|
21
|
+
* the streak rather than resetting it: the count only ever gates the
|
|
22
|
+
* AUTOMATIC redial, so continuing it errs toward asking the user again rather
|
|
23
|
+
* than toward reopening the microphone on its own.
|
|
24
|
+
*/
|
|
25
|
+
export type CallDialOrigin = "user" | "redial";
|
|
26
|
+
/** Mark the call live — called on the `in_call` transition. `updatedAtMs`
|
|
27
|
+
* starts equal to `startedAtMs` (no heartbeat has ticked yet). `redialCount`
|
|
28
|
+
* carries over from the interrupted call on a `"redial"` (see the module doc:
|
|
29
|
+
* reaching `in_call` is NOT proof a redial worked — only the 30s healthy-call
|
|
30
|
+
* timer's {@link resetRedialCount} is) and starts at zero on a `"user"` dial.
|
|
31
|
+
* Starts with an empty digest; {@link refreshCallActiveMarkerContext} fills it
|
|
32
|
+
* in as the call progresses. */
|
|
33
|
+
export declare const writeCallActiveMarker: (origin: CallDialOrigin) => void;
|
|
25
34
|
/** Update the persisted digest of an already-active marker. No-op when no
|
|
26
35
|
* marker is active — a digest has nothing to attach itself to once the call
|
|
27
36
|
* has ended. */
|
|
28
37
|
export declare const refreshCallActiveMarkerContext: (contextDigest: string) => void;
|
|
38
|
+
/** How often `voice-call.ts` re-stamps `updatedAtMs` while a call is
|
|
39
|
+
* `in_call` — the proof-of-life cadence a future reload's staleness check is
|
|
40
|
+
* accurate to. */
|
|
41
|
+
export declare const MARKER_HEARTBEAT_MS = 10000;
|
|
42
|
+
/** Refresh the marker's proof-of-life stamp. Called on a
|
|
43
|
+
* `MARKER_HEARTBEAT_MS` interval for as long as the call is live — see the
|
|
44
|
+
* module doc comment for why this can't just ride `refreshCallActiveMarkerContext`.
|
|
45
|
+
* No-op when no marker is active, mirroring `refreshCallActiveMarkerContext`:
|
|
46
|
+
* a heartbeat has nothing left to touch once the call has ended. */
|
|
47
|
+
export declare const touchCallActiveMarker: () => void;
|
|
48
|
+
/** Record one more auto-redial attempt against the persisted marker. No-op
|
|
49
|
+
* when no marker is active — mirrors `refreshCallActiveMarkerContext`. */
|
|
50
|
+
export declare const noteRedialAttempt: () => void;
|
|
51
|
+
/** Zero the redial counter — called once a (re)dialed call has stayed up long
|
|
52
|
+
* enough to call healthy, so it stops counting against the next drop. No-op
|
|
53
|
+
* when no marker is active — mirrors `refreshCallActiveMarkerContext`. */
|
|
54
|
+
export declare const resetRedialCount: () => void;
|
|
29
55
|
/** Call ended (explicit hangup or terminal error) — no reload should redial. */
|
|
30
56
|
export declare const clearCallActiveMarker: () => void;
|
|
31
|
-
|
|
57
|
+
/** What the dock's boot effect should do about an interrupted call: dial it
|
|
58
|
+
* back automatically, put the one-click offer on the rail's call button, or
|
|
59
|
+
* leave the dock alone. */
|
|
60
|
+
export type ReconnectAction = "redial" | "offer" | "skip";
|
|
32
61
|
/**
|
|
33
62
|
* How long after the interrupted call started we still OFFER to reconnect. A
|
|
34
63
|
* reload lands in seconds; a tab the browser restored from a much older session
|
|
@@ -37,29 +66,37 @@ export type ReconnectOfferDecision = "offer" | "skip";
|
|
|
37
66
|
*/
|
|
38
67
|
export declare const RECONNECT_OFFER_MAX_AGE_MS = 600000;
|
|
39
68
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* the
|
|
44
|
-
*
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
|
|
69
|
+
* How stale the marker may be and still earn an AUTOMATIC redial. A reload
|
|
70
|
+
* lands within a couple of seconds; a tab the browser restored from a much
|
|
71
|
+
* older session must not silently reopen the microphone. Read against
|
|
72
|
+
* `updatedAtMs` (the heartbeat), never `startedAtMs` — a call that has been
|
|
73
|
+
* live for 20 minutes must still come back.
|
|
74
|
+
*/
|
|
75
|
+
export declare const REDIAL_MAX_STALENESS_MS = 120000;
|
|
76
|
+
/** Consecutive automatic redials before falling back to the button. A host
|
|
77
|
+
* that crash-loops must not reopen the mic on every load. */
|
|
78
|
+
export declare const MAX_CONSECUTIVE_REDIALS = 2;
|
|
79
|
+
/**
|
|
80
|
+
* What the dock's boot effect should do about a call this tab was in when the
|
|
81
|
+
* page went away.
|
|
50
82
|
*
|
|
51
83
|
* Pure so the branching is unit-testable without React or WebRTC: a marker
|
|
52
84
|
* means a call was live when the page went away; `tokenReady` mirrors the same
|
|
53
85
|
* auth-readiness gate the login screen polls; `alreadyOffered` is the one-shot
|
|
54
|
-
* guard (the
|
|
55
|
-
* consumed against `nowMs` so a stale marker
|
|
86
|
+
* guard (the decision is acted on at most once per page load); and the
|
|
87
|
+
* marker's timestamps are consumed against `nowMs` so a stale marker can
|
|
88
|
+
* neither dial nor offer forever.
|
|
89
|
+
*
|
|
90
|
+
* The gates are what make an unattended `"redial"` acceptable — see the module
|
|
91
|
+
* doc. `"offer"` is the same one-click fallback this file has always decided,
|
|
92
|
+
* now reached only when a redial's gates say no.
|
|
56
93
|
*/
|
|
57
|
-
export declare const
|
|
94
|
+
export declare const decideReconnectAction: (input: {
|
|
58
95
|
readonly marker: CallActiveMarker | null;
|
|
59
96
|
readonly tokenReady: boolean;
|
|
60
97
|
readonly alreadyOffered: boolean;
|
|
61
98
|
readonly nowMs: number;
|
|
62
|
-
}) =>
|
|
99
|
+
}) => ReconnectAction;
|
|
63
100
|
export declare const peekReconnectOffered: () => boolean;
|
|
64
101
|
export declare const markReconnectOffered: () => void;
|
|
65
102
|
/** Test-only: forget the one-shot guard between test cases. */
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
* a workspace must land in THAT workspace, not the shared legacy root — so the
|
|
18
18
|
* create body carries the effective `workspaceExternalId` (absent when the host
|
|
19
19
|
* runs unscoped). The line's registry label seeds the session title when one
|
|
20
|
-
* exists; otherwise (U4 — the common case
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* the
|
|
24
|
-
*
|
|
20
|
+
* exists; otherwise (U4 — the common case, since nothing seeds a freshly
|
|
21
|
+
* materialized line's registry label any more) the REQUEST itself does, so the
|
|
22
|
+
* sessions list still names the background conversation by what it's actually
|
|
23
|
+
* about ("Reconcile the July invoices"), not the agent that happened to run
|
|
24
|
+
* it.
|
|
25
25
|
*
|
|
26
26
|
* BOOT RE-ATTACH (F3/R4): `attachLineReader` below is the ONE seam that wires
|
|
27
|
-
* a
|
|
27
|
+
* a SLOT-tracked line-run reader onto a line, shared by a fresh dispatch
|
|
28
28
|
* (this module, right after a POST accepts a run) and `reattachPendingLineRuns`
|
|
29
29
|
* (called once at boot, after `initAgentLines()` rehydrates the registry)
|
|
30
30
|
* resuming a run that was still going when the page reloaded. Both paths
|
|
@@ -32,26 +32,28 @@
|
|
|
32
32
|
* navigate/artifact/finish/error callbacks — a reload must behave exactly like
|
|
33
33
|
* the live dispatch it is standing in for, not a parallel, easier-to-drift copy.
|
|
34
34
|
*
|
|
35
|
-
* TWO READER KINDS (BEL-90). This module
|
|
36
|
-
*
|
|
35
|
+
* TWO READER KINDS (BEL-90). This module attaches two, and which callback set
|
|
36
|
+
* a caller gets is a correctness question, not a style one. NEITHER speaks —
|
|
37
|
+
* a background line never reaches the call (see voice-call.ts's agent-line
|
|
38
|
+
* section) — but they write different things:
|
|
37
39
|
*
|
|
38
|
-
* - `attachLineReader` — the
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
40
|
+
* - `attachLineReader` — the SLOT reader, for a run this module dispatched.
|
|
41
|
+
* It owns the durable slot runId (`persistSlotRun`, set on dispatch and
|
|
42
|
+
* cleared on terminal), writes the registry through
|
|
43
|
+
* `deliverLineReply`/`deliverLineFailure`/`notifyLinePhase`/
|
|
44
|
+
* `notifyLineApprovalNeeded`, and additionally opens an artifact preview
|
|
45
|
+
* and dispatches host route navigation.
|
|
44
46
|
* - `attachLineProgressReader` — the plain-progress reader, for a run the
|
|
45
47
|
* user started by TYPING that was still in flight at reload. It goes
|
|
46
|
-
* through `reportRunLineProgress
|
|
47
|
-
*
|
|
48
|
-
*
|
|
48
|
+
* through `reportRunLineProgress`, touches only the registry, and — see
|
|
49
|
+
* its own doc — deliberately writes no slot runId, opens no panel, and
|
|
50
|
+
* drives no navigation.
|
|
49
51
|
*/
|
|
50
52
|
/** Abort every live line reader and invalidate their callbacks (call teardown).
|
|
51
53
|
* Subscribed below to fire whenever a call leaves in_call/connecting. */
|
|
52
54
|
export declare const abortAllLineReaders: () => void;
|
|
53
55
|
/** Test-only: drop every plain-progress reader (and the active-session latch)
|
|
54
|
-
* so a case never inherits either from the previous case. The
|
|
56
|
+
* so a case never inherits either from the previous case. The slot
|
|
55
57
|
* readers have `abortAllLineReaders`; these deliberately do NOT ride on it — a
|
|
56
58
|
* voice call ending has nothing to do with a typed run still streaming. */
|
|
57
59
|
export declare const __detachLineProgressReadersForTest: () => void;
|
|
@@ -66,8 +68,8 @@ export declare const __detachLineProgressReadersForTest: () => void;
|
|
|
66
68
|
* TWO paths, because the two dispatch kinds have genuinely different
|
|
67
69
|
* contracts (BEL-90 / B1 — see `attachLineProgressReader`'s doc):
|
|
68
70
|
*
|
|
69
|
-
* - F3/R4, UNCHANGED — a line whose durable SLOT carries a runId
|
|
70
|
-
*
|
|
71
|
+
* - F3/R4, UNCHANGED — a line whose durable SLOT carries a runId went
|
|
72
|
+
* through `dispatchToLine`. It gets the slot reader, on every line that has
|
|
71
73
|
* one, INCLUDING when its session is the one on screen. That last part is
|
|
72
74
|
* load-bearing: `persistSlotRun(line, null)` in that reader's terminal
|
|
73
75
|
* callbacks is the durable slot's clearer, and skipping the on-screen line
|
|
@@ -26,6 +26,12 @@ export type RealtimeCallHandle = {
|
|
|
26
26
|
readonly sendEvent: (event: Record<string, unknown>) => void;
|
|
27
27
|
/** Toggle the local mic track without renegotiating. */
|
|
28
28
|
readonly setMuted: (muted: boolean) => void;
|
|
29
|
+
/** Ask the browser to play the agent's audio again after it refused (see
|
|
30
|
+
* {@link ConnectRealtimeCallInput.onAudioBlocked}). Resolves true only when
|
|
31
|
+
* playback actually started. Call it STRAIGHT from the user's tap handler:
|
|
32
|
+
* the `play()` inside runs before the first await, so the gesture the
|
|
33
|
+
* browser is holding out for is still on the stack. */
|
|
34
|
+
readonly resumeAudio: () => Promise<boolean>;
|
|
29
35
|
/** Tear down mic, peer connection, and audio playback. Idempotent. */
|
|
30
36
|
readonly close: () => void;
|
|
31
37
|
};
|
|
@@ -52,5 +58,11 @@ export type ConnectRealtimeCallInput = {
|
|
|
52
58
|
readonly local: MediaStream;
|
|
53
59
|
readonly remote: MediaStream;
|
|
54
60
|
}) => void;
|
|
61
|
+
/** Fired when the browser REFUSES to play the agent's audio. `autoplay` is
|
|
62
|
+
* a request, not a guarantee — a page that reloaded mid-call has no fresh
|
|
63
|
+
* user gesture behind it — and a refusal we never asked about is completely
|
|
64
|
+
* silent: the call looks connected and says nothing. The store turns this
|
|
65
|
+
* into a one-tap "Tap to hear" control (`resumeAudio` above). */
|
|
66
|
+
readonly onAudioBlocked?: () => void;
|
|
55
67
|
};
|
|
56
68
|
export declare const connectRealtimeCall: (input: ConnectRealtimeCallInput) => Promise<ConnectRealtimeCallResult>;
|
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
* "A call was interrupted — tap to reconnect" — the one-bit store that turns a
|
|
3
3
|
* surviving call marker (`call-active-marker.ts`) into a USER-DRIVEN redial.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* This is the FALLBACK half of reload survival: the dock's boot effect dials
|
|
6
|
+
* an interrupted call back on its own when the marker clears
|
|
7
|
+
* `decideReconnectAction`'s gates, and raises this offer when it does not —
|
|
8
|
+
* a marker too stale to prove the call was live moments ago, or one already
|
|
9
|
+
* redialed up to the consecutive-redial cap. It raises the offer again when a
|
|
10
|
+
* redial the gates DID allow fails to connect, so a flaky call-token endpoint
|
|
11
|
+
* costs the user one automatic attempt rather than the whole call (see
|
|
12
|
+
* `watchRedialForFallback` in BelongDock.tsx). Whenever it stands, the rail's
|
|
13
|
+
* CallButton dials with `{ isReconnect: true }` (carrying the interrupted
|
|
7
14
|
* call's context digest) and labels itself "Reconnect" instead of "Start voice
|
|
8
15
|
* call". That is the whole mechanism: ONE user click, on a control that is
|
|
9
|
-
* already always visible in the rail — no new surface, and
|
|
10
|
-
*
|
|
16
|
+
* already always visible in the rail — no new surface, and no microphone
|
|
17
|
+
* access without a gesture on exactly the marker the gates declined to trust.
|
|
11
18
|
*
|
|
12
19
|
* Why a separate store rather than a field on `CallState`: the call state is
|
|
13
20
|
* rebuilt from `IDLE` on every dial and every terminal error, which would wipe
|
|
@@ -18,7 +25,9 @@
|
|
|
18
25
|
*/
|
|
19
26
|
export declare const peekReconnectOffer: () => boolean;
|
|
20
27
|
export declare const subscribeReconnectOffer: (listener: () => void) => (() => void);
|
|
21
|
-
/** Raise the offer
|
|
28
|
+
/** Raise the offer: at dock boot when `decideReconnectAction` says `"offer"`
|
|
29
|
+
* (a marker too stale, or too many redials deep, to dial back on its own), and
|
|
30
|
+
* when a redial it DID allow ends in `error` without ever reaching the call. */
|
|
22
31
|
export declare const offerReconnect: () => void;
|
|
23
32
|
/**
|
|
24
33
|
* Take the offer down. Called when the user acts on it (the reconnect click),
|
|
@@ -6,20 +6,10 @@ import { z } from 'zod';
|
|
|
6
6
|
*/
|
|
7
7
|
declare const voiceTokensSchema: z.ZodObject<{
|
|
8
8
|
deepgramToken: z.ZodString;
|
|
9
|
-
deepgramWssUrl: z.
|
|
9
|
+
deepgramWssUrl: z.ZodURL;
|
|
10
10
|
elevenlabsToken: z.ZodString;
|
|
11
11
|
voiceId: z.ZodString;
|
|
12
|
-
},
|
|
13
|
-
deepgramToken: string;
|
|
14
|
-
deepgramWssUrl: string;
|
|
15
|
-
elevenlabsToken: string;
|
|
16
|
-
voiceId: string;
|
|
17
|
-
}, {
|
|
18
|
-
deepgramToken: string;
|
|
19
|
-
deepgramWssUrl: string;
|
|
20
|
-
elevenlabsToken: string;
|
|
21
|
-
voiceId: string;
|
|
22
|
-
}>;
|
|
12
|
+
}, z.core.$strip>;
|
|
23
13
|
export type VoiceTokens = z.infer<typeof voiceTokensSchema>;
|
|
24
14
|
export type VoiceTokenResult = {
|
|
25
15
|
ok: true;
|
|
@@ -4,9 +4,9 @@ export declare const MAX_AGENT_LINES = 3;
|
|
|
4
4
|
* "idle" is the not-busy resting state — no work in flight, and nothing
|
|
5
5
|
* completed/failed yet worth reporting (a fresh call, or a line rebound onto
|
|
6
6
|
* a persisted session with no activity this call). "ready" is the DISTINCT
|
|
7
|
-
* terminal state after a run actually finished successfully
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* terminal state after a run actually finished successfully, unlike "idle"
|
|
8
|
+
* which never conflates the two anymore (pre-CallScreen-board, both were
|
|
9
|
+
* folded into "ready").
|
|
10
10
|
*/
|
|
11
11
|
export type AgentLineStatus = "idle" | "working" | "ready" | "failed" | "needs_approval";
|
|
12
12
|
export type AgentLine = {
|
|
@@ -28,7 +28,6 @@ export type AgentLine = {
|
|
|
28
28
|
readonly sessionId: string | null;
|
|
29
29
|
readonly label: string;
|
|
30
30
|
readonly status: AgentLineStatus;
|
|
31
|
-
readonly lastText: string;
|
|
32
31
|
/** The line's current run, for `stop_agent` to target — bound by the
|
|
33
32
|
* line-run reader once a background dispatch's POST returns a runId, and
|
|
34
33
|
* cleared back to `null` when that run reaches a terminal state.
|
|
@@ -158,26 +157,6 @@ export declare const isBoundToAnotherLine: (sessionId: string) => boolean;
|
|
|
158
157
|
*/
|
|
159
158
|
export declare const foregroundLineNumber: (sessionId: string | null) => number;
|
|
160
159
|
export declare const openAgentLine: (label: string) => AgentLine | null;
|
|
161
|
-
/**
|
|
162
|
-
* Materialize a line AT A GIVEN NUMBER, unlike `openAgentLine`'s lowest-FREE
|
|
163
|
-
* allocation. F1: role→line is fixed and positional (main=1, cli=2,
|
|
164
|
-
* consulting=3 — `call-roster-store.ts`), so a background dispatch to a role
|
|
165
|
-
* whose line has never been touched must land EXACTLY on that role's number,
|
|
166
|
-
* never wherever happens to be free. `dispatchToBackgroundLine`
|
|
167
|
-
* (voice-call.ts) is the one production caller: "asking the CLI agent for
|
|
168
|
-
* something IS bringing it on" (design doc) means the line materializes on
|
|
169
|
-
* first use instead of reporting `unknown_line` for a line that simply
|
|
170
|
-
* hasn't been dispatched to yet.
|
|
171
|
-
*
|
|
172
|
-
* Returns `null` when `line` is outside the switchboard's
|
|
173
|
-
* 1..MAX_AGENT_LINES range, or when it is already occupied — the caller's
|
|
174
|
-
* own `getLine(line) === undefined` check is expected to make the second
|
|
175
|
-
* case unreachable in practice (this function is only ever called after
|
|
176
|
-
* that check fails), but the guard keeps the contract sound on its own
|
|
177
|
-
* terms rather than trusting every future caller to get the check right
|
|
178
|
-
* (§28).
|
|
179
|
-
*/
|
|
180
|
-
export declare const openAgentLineAt: (line: number, label: string) => AgentLine | null;
|
|
181
160
|
/**
|
|
182
161
|
* RELEASE a line — the mirror of `persistSlotBinding`'s adoption: clears the
|
|
183
162
|
* in-memory entry AND its durable slot together, so the freed number is
|
|
@@ -266,7 +245,7 @@ export declare const bindLineRun: (line: number, runId: string | null) => void;
|
|
|
266
245
|
* is a harmless no-op, which is what keeps the terminal path above uniform.
|
|
267
246
|
*/
|
|
268
247
|
export declare const persistSlotRun: (line: number, runId: string | null) => void;
|
|
269
|
-
export declare const setLineStatus: (line: number, status: AgentLineStatus
|
|
248
|
+
export declare const setLineStatus: (line: number, status: AgentLineStatus) => void;
|
|
270
249
|
/** CallScreen's agent board reads this as the live "what is it doing right
|
|
271
250
|
* now" line under a working line's status dot — written on every phase
|
|
272
251
|
* notification (`notifyLinePhase`) and cleared (`null`) once the line's run
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AgentLineStatus } from './voice-call-lines.ts';
|
|
2
2
|
import { WorkPhase } from './voice-narration.ts';
|
|
3
|
+
import { CallDialOrigin } from './voice/call-active-marker.ts';
|
|
3
4
|
export type CallStatus = "idle" | "connecting" | "in_call" | "error";
|
|
4
5
|
/**
|
|
5
6
|
* One row of the call's execution timeline (the CallScreen activity card):
|
|
@@ -11,12 +12,15 @@ export type CallTimelineEntry = {
|
|
|
11
12
|
readonly id: number;
|
|
12
13
|
readonly atMs: number;
|
|
13
14
|
readonly kind: "user" | "agent" | "step" | "success" | "error" | "skill" | "schedule";
|
|
15
|
+
/** What the row SAYS. Empty for the two terminal kinds (`success`/`error`),
|
|
16
|
+
* whose whole meaning is the kind itself — CallScreen renders their own
|
|
17
|
+
* label and ignores this. See {@link TEXTLESS_KINDS}. */
|
|
14
18
|
readonly text: string;
|
|
15
19
|
/** The switchboard line this row concerns; `null` for a foreground (line 1)
|
|
16
|
-
* row.
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
+
* row. Bookkeeping only — no surface labels a row with an agent name any
|
|
21
|
+
* more (there is one agent, and it is the chat on screen), so this exists
|
|
22
|
+
* so a marker written for a background line can be told apart from one
|
|
23
|
+
* written for the foreground. */
|
|
20
24
|
readonly line: number | null;
|
|
21
25
|
};
|
|
22
26
|
export type CallState = {
|
|
@@ -39,20 +43,63 @@ export type CallState = {
|
|
|
39
43
|
/** True between the user finishing an utterance and the model responding —
|
|
40
44
|
* the "Thinking…" window on the call screen. */
|
|
41
45
|
readonly thinking: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Why the dial currently in flight (or the call it produced) happened —
|
|
48
|
+
* `"user"` for one the user asked for, `"redial"` for a reconnect. Set on
|
|
49
|
+
* the `connecting` transition and read back by two very different consumers:
|
|
50
|
+
* the marker write below (a reconnect CONTINUES the interrupted call's
|
|
51
|
+
* redial streak) and CallScreen, which says "Reconnecting…" rather than
|
|
52
|
+
* "Connecting…" so a microphone that reopened on its own explains itself.
|
|
53
|
+
*/
|
|
54
|
+
readonly dialOrigin: CallDialOrigin;
|
|
42
55
|
/** Wall-clock start of the current call; 0 while idle. */
|
|
43
56
|
readonly callStartedAtMs: number;
|
|
44
57
|
/** Rolling execution timeline, oldest first (capped). */
|
|
45
58
|
readonly timeline: readonly CallTimelineEntry[];
|
|
59
|
+
/** The browser REFUSED to play the agent's audio (autoplay is a request,
|
|
60
|
+
* not a guarantee — an automatically redialed call after a page reload has
|
|
61
|
+
* no fresh user gesture behind it). Drives CallScreen's one-tap "Tap to
|
|
62
|
+
* hear" control; {@link resumeCallAudio} clears it. */
|
|
63
|
+
readonly audioBlocked: boolean;
|
|
46
64
|
readonly errorMessage?: string;
|
|
47
65
|
};
|
|
48
66
|
/**
|
|
49
|
-
* ChatRoute pushes
|
|
50
|
-
*
|
|
67
|
+
* ChatRoute pushes a call-relevant NOTICE onto the timeline — the sentences
|
|
68
|
+
* that explain why nothing ran (a skill lookup miss, a catalog that hasn't
|
|
69
|
+
* loaded), an artifact that opened on screen, a voice-resolved approval.
|
|
70
|
+
* No-op when no call is active.
|
|
71
|
+
*
|
|
72
|
+
* `step` is the only kind ChatRoute writes: it is the one kind whose TEXT is
|
|
73
|
+
* rendered (a `success`/`error` row is its kind label and nothing else — see
|
|
74
|
+
* {@link TEXTLESS_KINDS}), so a notice pushed as anything else would have its
|
|
75
|
+
* sentence silently dropped.
|
|
76
|
+
*
|
|
77
|
+
* Keeps the consecutive-identical-row window: these are free-form sentences
|
|
78
|
+
* written from event handlers that can fire twice on one underlying fact (the
|
|
79
|
+
* voice re-asking for the same missing skill, say), and a verbatim repeat
|
|
80
|
+
* seconds apart says nothing new. The agent's own ACTION rows are the
|
|
81
|
+
* opposite case and have their own entry point — {@link pushCallAction}.
|
|
51
82
|
*/
|
|
52
83
|
export declare const pushCallStep: (text: string) => void;
|
|
53
|
-
/**
|
|
54
|
-
*
|
|
55
|
-
|
|
84
|
+
/**
|
|
85
|
+
* ChatRoute pushes one ACTION onto the call timeline — one line per thing the
|
|
86
|
+
* agent did ("Read a file", "Ran a command"). No-op when no call is active.
|
|
87
|
+
*
|
|
88
|
+
* Deliberately NOT {@link pushCallStep}: the action vocabulary
|
|
89
|
+
* (`tool-action-label.ts`) is a fixed ~15-string set of parameterless
|
|
90
|
+
* constants, so "read three files" is three BYTE-IDENTICAL rows and the
|
|
91
|
+
* dedupe window folded them into one — an agent that read three files logged
|
|
92
|
+
* one, and five unrecognized tools (all "Worked on it") logged one. On a
|
|
93
|
+
* surface whose whole job is "let me follow along while I listen", that is
|
|
94
|
+
* the difference between working and not.
|
|
95
|
+
*
|
|
96
|
+
* Safe to opt out because this call site is already idempotent at source:
|
|
97
|
+
* chat.tsx's `loggedActionPartIdsRef` keys on the tool-call PART id, so the
|
|
98
|
+
* same call re-arriving as started → completed writes exactly one row. Same
|
|
99
|
+
* reasoning, same opt-out, as the terminal markers in `deliverAgentReply` /
|
|
100
|
+
* `deliverAgentFailure`.
|
|
101
|
+
*/
|
|
102
|
+
export declare const pushCallAction: (text: string) => void;
|
|
56
103
|
/** Hard ceiling on the rendered digest — a compact recap, not a transcript. */
|
|
57
104
|
export declare const CONTEXT_DIGEST_MAX_CHARS = 1000;
|
|
58
105
|
/**
|
|
@@ -116,44 +163,6 @@ declare let lineDispatcher: ((req: {
|
|
|
116
163
|
readonly isNewLine: boolean;
|
|
117
164
|
}) => void) | null;
|
|
118
165
|
export declare const registerCallLineDispatcher: (dispatcher: NonNullable<typeof lineDispatcher>) => (() => void);
|
|
119
|
-
/**
|
|
120
|
-
* Last-resort delivery for `flushLineQueuesOnCallEnd` when no `lineDispatcher`
|
|
121
|
-
* is wired (the M7 gap — ChatRoute unmounted). Self-registered by
|
|
122
|
-
* line-dispatch.ts (see the bottom of that file) with the real
|
|
123
|
-
* `dispatchToLine` — deliberately NOT imported here directly. `line-dispatch.ts`
|
|
124
|
-
* already imports six functions FROM this module (buildCallContextDigest,
|
|
125
|
-
* the deliver/notify callbacks, peekCallState, subscribeCallState), so a
|
|
126
|
-
* static import the other way would close a two-way cycle between
|
|
127
|
-
* voice-call.ts and line-dispatch.ts — forbidden outright by
|
|
128
|
-
* `.dependency-cruiser.cjs`'s `no-circular` rule (severity: error, applies
|
|
129
|
-
* everywhere, not just the hexagonal backend layers). Registering FROM
|
|
130
|
-
* line-dispatch.ts, in the SAME direction its existing dependency already
|
|
131
|
-
* runs, avoids the cycle entirely; that file's own `subscribeCallState`
|
|
132
|
-
* self-subscribe (its module doc, right above `abortAllLineReaders`) is the
|
|
133
|
-
* identical idiom already established there.
|
|
134
|
-
*
|
|
135
|
-
* Investigated and confirmed SOUND as a fallback: chat.tsx's own
|
|
136
|
-
* `registerCallLineDispatcher` wrapper does nothing beyond routing line 1 to
|
|
137
|
-
* `sendCallText` and calling this exact function, unmodified, for any other
|
|
138
|
-
* line — see that effect in chat.tsx. Held/queued items only ever exist for
|
|
139
|
-
* background lines (line 1 never enqueues — see the busy-line branch above),
|
|
140
|
-
* so every item this fallback ever sees is exactly the shape ChatRoute's
|
|
141
|
-
* wrapper would have passed through unchanged. No ChatRoute-specific
|
|
142
|
-
* behavior is lost by calling it directly.
|
|
143
|
-
*
|
|
144
|
-
* Deliberately SEPARATE from `lineDispatcher` — not folded into
|
|
145
|
-
* `releaseHeldRequest` itself — so `pumpLineQueue`'s live-queue draining is
|
|
146
|
-
* UNAFFECTED: it must keep checking `lineDispatcher` and leaving an item
|
|
147
|
-
* queued (not popped) when nothing is wired, per its own doc. Only the
|
|
148
|
-
* end-of-call flush, which has nothing left to leave a drained item queued
|
|
149
|
-
* IN, reaches for this.
|
|
150
|
-
*/
|
|
151
|
-
declare let lineDispatchFallback: ((req: {
|
|
152
|
-
readonly line: number;
|
|
153
|
-
readonly request: string;
|
|
154
|
-
readonly isNewLine: boolean;
|
|
155
|
-
}) => Promise<void>) | null;
|
|
156
|
-
export declare const registerLineDispatchFallback: (dispatcher: NonNullable<typeof lineDispatchFallback>) => (() => void);
|
|
157
166
|
export declare const registerCallLineViewSwitcher: (switcher: (sessionId: string) => void) => (() => void);
|
|
158
167
|
export declare const registerCallClearNotifier: (notifier: (sessionId: string) => void) => (() => void);
|
|
159
168
|
/**
|
|
@@ -174,10 +183,11 @@ export declare const notifyCallProgress: (hint: string) => void;
|
|
|
174
183
|
* small work badge while the agent is busy. */
|
|
175
184
|
export declare const setCallWorkPhase: (phase: CallState["workPhase"]) => void;
|
|
176
185
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
186
|
+
* The lines strip chip on CallScreen calls this directly (no tool-call round
|
|
187
|
+
* trip, no ack — there is no voice tool for it any more, which is why nothing
|
|
188
|
+
* here reports an outcome): switch the chat panel to the line's session and
|
|
189
|
+
* minimize the call screen. No-op when the line is unknown, never bound to a
|
|
190
|
+
* session, or no view switcher is registered (e.g. ChatRoute hasn't mounted).
|
|
181
191
|
*/
|
|
182
192
|
export declare const showLineOnScreen: (line: number) => void;
|
|
183
193
|
/**
|
|
@@ -198,7 +208,41 @@ export declare const showLineOnScreen: (line: number) => void;
|
|
|
198
208
|
export declare const startCall: (options?: {
|
|
199
209
|
readonly isReconnect?: boolean;
|
|
200
210
|
}) => Promise<void>;
|
|
211
|
+
/**
|
|
212
|
+
* The error panel's "Call again". Dials as a RECONNECT whenever an interrupted
|
|
213
|
+
* call's marker is still there — which, by `keepsCallActiveMarker`, is exactly
|
|
214
|
+
* the case worth reconnecting to: a redial that never became a call. Its
|
|
215
|
+
* `contextDigest` is the only surviving record of what the user was doing, so
|
|
216
|
+
* a bare `startCall()` here opened a COLD call the user had to re-explain,
|
|
217
|
+
* while the recap the failure path deliberately preserved went unread.
|
|
218
|
+
*
|
|
219
|
+
* Deliberately does NOT dismiss the error first: `dismissCallError`'s idle
|
|
220
|
+
* transition is one of the two moments allowed to keep the marker, but only
|
|
221
|
+
* because ✕ means "put the panel away" — routing a RETRY through it would
|
|
222
|
+
* still hand `startCall` a marker whose digest it had to re-read after a
|
|
223
|
+
* needless round trip. `startCall`'s own `connecting` patch replaces the error
|
|
224
|
+
* state (and its panel) synchronously, so there is nothing left to dismiss.
|
|
225
|
+
*/
|
|
226
|
+
export declare const retryCall: () => Promise<void>;
|
|
227
|
+
/**
|
|
228
|
+
* Hang up. The one ending that is an explicit GIVE-UP, so it always takes the
|
|
229
|
+
* interrupted call's marker and any standing reconnect offer with it — stated
|
|
230
|
+
* here rather than left to `keepsCallActiveMarker`, whose `error → idle`
|
|
231
|
+
* branch exists for the ✕ that merely puts the error panel away. Both clears
|
|
232
|
+
* run BEFORE the transition, so that branch sees no marker and agrees.
|
|
233
|
+
*/
|
|
201
234
|
export declare const endCall: () => void;
|
|
235
|
+
/**
|
|
236
|
+
* The user tapped "Tap to hear" — ask the browser to play the agent's audio
|
|
237
|
+
* again, now that a real gesture is on the stack, and take the control down
|
|
238
|
+
* only once playback has ACTUALLY started. Clearing it optimistically would
|
|
239
|
+
* leave a silent call with nothing left to tap.
|
|
240
|
+
*
|
|
241
|
+
* Deliberately not `async`: CallScreen calls this straight from the click
|
|
242
|
+
* handler, and the transport's `play()` runs before the first await, so the
|
|
243
|
+
* gesture the browser is holding out for is still on the stack.
|
|
244
|
+
*/
|
|
245
|
+
export declare const resumeCallAudio: () => void;
|
|
202
246
|
export declare const toggleCallMuted: () => void;
|
|
203
247
|
/** Dismiss a sticky error state (the overlay's ✕). */
|
|
204
248
|
export declare const dismissCallError: () => void;
|
|
@@ -218,9 +262,9 @@ export declare const deliverAgentReply: (text: string) => void;
|
|
|
218
262
|
* must tell the user something went wrong and offer to retry.
|
|
219
263
|
*/
|
|
220
264
|
export declare const deliverAgentFailure: (message: string) => void;
|
|
221
|
-
/** A background line finished:
|
|
222
|
-
*
|
|
223
|
-
export declare const deliverLineReply: (line: number
|
|
265
|
+
/** A background line finished: converge its chip. Nothing is spoken — see
|
|
266
|
+
* this section's header. */
|
|
267
|
+
export declare const deliverLineReply: (line: number) => void;
|
|
224
268
|
/**
|
|
225
269
|
* A background line published an artifact: OPEN it on screen, mirroring
|
|
226
270
|
* chat.tsx's foreground auto-open effect exactly — ALWAYS docked (a persisted
|
|
@@ -234,26 +278,21 @@ export declare const deliverLineArtifact: (line: number, artifact: {
|
|
|
234
278
|
readonly title: string;
|
|
235
279
|
readonly mimeType: string;
|
|
236
280
|
}) => void;
|
|
237
|
-
/** A background line failed:
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
|
|
245
|
-
export declare const notifyLineApprovalNeeded: (line: number, timelineText: string, reason: string) => void;
|
|
281
|
+
/** A background line failed: converge its chip. Nothing is spoken — see this
|
|
282
|
+
* section's header. */
|
|
283
|
+
export declare const deliverLineFailure: (line: number) => void;
|
|
284
|
+
/** A background line is blocked on a tool approval — paint its chip. The
|
|
285
|
+
* approval itself is resolved from the rail's typed chat, on screen, where
|
|
286
|
+
* the user can read what is being approved; the call is not told, and takes
|
|
287
|
+
* no `reason`, because it has no way to name whose approval it is. */
|
|
288
|
+
export declare const notifyLineApprovalNeeded: (line: number) => void;
|
|
246
289
|
/** A background line advanced a phase — record it as the line's live step
|
|
247
|
-
* (CallScreen's agent board
|
|
248
|
-
*
|
|
249
|
-
* phase change
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* front. The registry write is unconditional (line-dispatch's own `isStale`
|
|
254
|
-
* guard already keeps a stale-call phase from ever reaching here); the
|
|
255
|
-
* spoken nudge stays guarded like its delivery siblings so a phase that DOES
|
|
256
|
-
* arrive with no live call just updates the board silently. */
|
|
290
|
+
* (CallScreen's agent board and the rail read `currentStepLabel`/
|
|
291
|
+
* `currentPhase` off the registry). X2a: deliberately NO timeline row per
|
|
292
|
+
* phase change — the board's own card already shows the identical string
|
|
293
|
+
* live, and a 12-step run used to write 12 near-identical Activity rows that
|
|
294
|
+
* buried the actual results. The write is unconditional: line-dispatch's own
|
|
295
|
+
* `isStale` guard already keeps a stale-call phase from ever reaching here. */
|
|
257
296
|
export declare const notifyLinePhase: (line: number, phaseLabel: string, phase?: WorkPhase | null) => void;
|
|
258
297
|
/** True while a call holds the audio path — ChatRoute gates TTS autoplay on it. */
|
|
259
298
|
export declare const isCallActive: () => boolean;
|