@coventia/softphone 0.4.0 → 0.5.1
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/{call-C6YpT6uR.d.cts → call-iGvr2ZnO.d.cts} +130 -13
- package/dist/{call-C6YpT6uR.d.ts → call-iGvr2ZnO.d.ts} +130 -13
- package/dist/chunk-3UTUWGVG.js +1891 -0
- package/dist/chunk-3UTUWGVG.js.map +1 -0
- package/dist/chunk-DZRSSZWB.js +39 -0
- package/dist/chunk-DZRSSZWB.js.map +1 -0
- package/dist/{chunk-2ZSOGGPO.js → chunk-FRXHEHQA.js} +15 -2
- package/dist/chunk-FRXHEHQA.js.map +1 -0
- package/dist/{chunk-UHNLEBBO.js → chunk-I3RSC52R.js} +28 -3
- package/dist/chunk-I3RSC52R.js.map +1 -0
- package/dist/chunk-M76SAXXM.js +13 -0
- package/dist/chunk-M76SAXXM.js.map +1 -0
- package/dist/{chunk-7R6LOOAI.js → chunk-N4PLEYFJ.js} +4 -2
- package/dist/chunk-N4PLEYFJ.js.map +1 -0
- package/dist/element/index.d.ts +167 -7
- package/dist/element/index.js +138 -43
- package/dist/element/index.js.map +1 -1
- package/dist/{engine-DPft99Wj.d.ts → engine-BKoT_Pj7.d.cts} +10 -1
- package/dist/{engine-CDdaSojx.d.cts → engine-CeGh5Yai.d.ts} +10 -1
- package/dist/index.cjs +1596 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +618 -42
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +26 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +24 -5
- package/dist/react/index.d.ts +24 -5
- package/dist/react/index.js +2 -2
- package/dist/{softphone-CY5d2WWY.d.cts → softphone-D0ao5W4z.d.ts} +42 -3
- package/dist/{softphone-DXgmTyrX.d.ts → softphone-DRoS0jJR.d.cts} +42 -3
- package/dist/{sources-ONYQW733.js → sources-LGFJG7W2.js} +27 -38
- package/dist/sources-LGFJG7W2.js.map +1 -0
- package/dist/testing/index.cjs +13 -0
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +2 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +1 -1
- package/dist/ui/index.cjs +92 -2
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.cts +2 -2
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.js +69 -4
- package/dist/ui/index.js.map +1 -1
- package/dist/zadarma/index.cjs +950 -104
- package/dist/zadarma/index.cjs.map +1 -1
- package/dist/zadarma/index.d.cts +40 -14
- package/dist/zadarma/index.d.ts +40 -14
- package/dist/zadarma/index.js +4 -2
- package/dist/zadarma-engine-VYIXLBQG.js +7 -0
- package/dist/{zadarma-engine-L5DEFXUS.js.map → zadarma-engine-VYIXLBQG.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-2ZSOGGPO.js.map +0 -1
- package/dist/chunk-7R6LOOAI.js.map +0 -1
- package/dist/chunk-EYEDPD7Y.js +0 -1071
- package/dist/chunk-EYEDPD7Y.js.map +0 -1
- package/dist/chunk-UHNLEBBO.js.map +0 -1
- package/dist/sources-ONYQW733.js.map +0 -1
- package/dist/zadarma-engine-L5DEFXUS.js +0 -5
|
@@ -86,10 +86,10 @@ interface TokenEndpointOptions {
|
|
|
86
86
|
*/
|
|
87
87
|
interface CoventiaBackendConfig {
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* does, which is not the normal case.
|
|
89
|
+
* Coventia's domain, like `SoftphoneConfig.apiBase`: no path, the SDK builds every route.
|
|
90
|
+
* **Optional** — falls back to `SoftphoneConfig.apiBase`, which exists precisely so this and the
|
|
91
|
+
* default call engine name the same backend once instead of twice. Set it here only when
|
|
92
|
+
* contacts/history genuinely live on a DIFFERENT host than calling does, which is not the normal case.
|
|
93
93
|
*/
|
|
94
94
|
readonly baseUrl?: string | undefined;
|
|
95
95
|
/**
|
|
@@ -104,7 +104,10 @@ interface CoventiaBackendConfig {
|
|
|
104
104
|
* That is the CRM today.
|
|
105
105
|
*/
|
|
106
106
|
readonly organizationId?: string;
|
|
107
|
-
/**
|
|
107
|
+
/**
|
|
108
|
+
* Where the phone routes sit under the base URL. Internal: leave it unset (`/phone`). The routes are
|
|
109
|
+
* the SDK's to build, which is why `apiBase` is the domain only.
|
|
110
|
+
*/
|
|
108
111
|
readonly basePath?: string;
|
|
109
112
|
/**
|
|
110
113
|
* **The one thing a provider customises**: their own contact list, searched on their own backend.
|
|
@@ -134,8 +137,11 @@ interface CoventiaBackendConfig {
|
|
|
134
137
|
interface SoftphoneConfig {
|
|
135
138
|
readonly tokenSource: TokenSource;
|
|
136
139
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
140
|
+
* Coventia's domain — **only the domain**, e.g. `https://backend.example.com`, with no path: the SDK
|
|
141
|
+
* builds every route itself. Not the Partner API URL your backend calls: that one ends in `/api/v1`,
|
|
142
|
+
* which does not belong here (it is ignored, with a console warning). **The one field to set** if you
|
|
143
|
+
* want the default call engine (see `provider` below) and are not overriding `coventia.baseUrl`
|
|
144
|
+
* separately.
|
|
139
145
|
*
|
|
140
146
|
* Named once here rather than requiring it on both `coventia` and the engine you construct: they
|
|
141
147
|
* are two independent subsystems (contacts/history/caller ID vs. SIP credential provisioning) that
|
|
@@ -188,8 +194,62 @@ interface CallOptions {
|
|
|
188
194
|
* Zadarma registers on-demand, per call, in response to a push (SPEC §3.2); a persistent UA is
|
|
189
195
|
* ignored by its PBX. Leaking "registered" into the public API would force every future provider —
|
|
190
196
|
* including our own SIP infrastructure, which registers persistently — to fake it.
|
|
197
|
+
*
|
|
198
|
+
* `standby` means started, and this browser's leader, but ANOTHER softphone of the same extension has
|
|
199
|
+
* the line — a tab in another browser, the desktop app, a partner page (`docs/specs/line-owner.md` §5).
|
|
200
|
+
* Its push socket is closed on purpose, so nothing here registers or rings: `line` says where the calls
|
|
201
|
+
* go, and `takeLine()` — or a `call()` — brings them here. A host that reads `online` as "ready"
|
|
202
|
+
* correctly reads this as not ready.
|
|
203
|
+
*/
|
|
204
|
+
type SoftphoneState = 'stopped' | 'starting' | 'online' | 'standby' | 'offline' | 'reconnecting' | 'destroyed';
|
|
205
|
+
/**
|
|
206
|
+
* Where this extension's incoming calls ring, as far as this softphone knows. `here`: it has the line.
|
|
207
|
+
* `elsewhere`: another softphone of the same extension has it, and this one waits in `standby`. `unknown`:
|
|
208
|
+
* nobody has said — no presence source, a backend that predates the line owner, a presence socket that is
|
|
209
|
+
* down — and this softphone listens, exactly as before the line owner existed (§5.1 R7, fail-open).
|
|
191
210
|
*/
|
|
192
|
-
type
|
|
211
|
+
type LineState = 'here' | 'elsewhere' | 'unknown';
|
|
212
|
+
/** Who has the line when it is `elsewhere`: the desktop app, or any other softphone (a browser tab). */
|
|
213
|
+
type LineLocation = 'desktop' | 'browser';
|
|
214
|
+
/**
|
|
215
|
+
* The last attempt to bring the line here — `takeLine()`, or a `call()` from `standby`, whoever made it:
|
|
216
|
+
* `claiming` while it is in flight, `refused` when the user is on a call where the line is, `failed` when
|
|
217
|
+
* nothing could decide. `idle` before any attempt, once the line comes here, and after a `stop()`.
|
|
218
|
+
*/
|
|
219
|
+
type LineClaim = 'idle' | 'claiming' | 'refused' | 'failed';
|
|
220
|
+
/** The server's word on this softphone's line, as a `PresenceSource` hands it over (`PresenceCallbacks.onLine`). */
|
|
221
|
+
interface LineUpdate {
|
|
222
|
+
readonly state: 'here' | 'elsewhere';
|
|
223
|
+
/** Who has the line when it is `elsewhere`; `null` when it is here, or the server did not say. */
|
|
224
|
+
readonly where: LineLocation | null;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* A call offered to this user's line, as the backend announces it over the presence socket
|
|
228
|
+
* (incoming-call-reliability.md §5): `start` each time the call is offered to the extension (a re-offer of the
|
|
229
|
+
* same call repeats it, same `callId`), `end` when the call is over. `callId` is opaque; `from` is the caller,
|
|
230
|
+
* `null` (or, on an `end`, absent) when the backend did not say.
|
|
231
|
+
*
|
|
232
|
+
* The softphone uses it for one thing: after a decline, to know when the declined call's re-offers stop, so a
|
|
233
|
+
* new call from the same number rings (§4.4). A presence source that never sends it loses nothing but that.
|
|
234
|
+
*/
|
|
235
|
+
type CallOffer = {
|
|
236
|
+
readonly state: 'start';
|
|
237
|
+
readonly callId: string;
|
|
238
|
+
readonly from: string | null;
|
|
239
|
+
} | {
|
|
240
|
+
readonly state: 'end';
|
|
241
|
+
readonly callId: string;
|
|
242
|
+
readonly from?: string | null;
|
|
243
|
+
};
|
|
244
|
+
/** The answer to `PresenceConnection.claimLine()`. */
|
|
245
|
+
interface LineClaimResult {
|
|
246
|
+
readonly ok: boolean;
|
|
247
|
+
/**
|
|
248
|
+
* Why it was refused: `'on_call'` while the user is on a call (the line never moves during one). Any
|
|
249
|
+
* other value means nothing was decided. Absent when `ok`.
|
|
250
|
+
*/
|
|
251
|
+
readonly reason?: string;
|
|
252
|
+
}
|
|
193
253
|
interface ContactsPage {
|
|
194
254
|
readonly items: readonly Contact[];
|
|
195
255
|
/**
|
|
@@ -349,6 +409,18 @@ interface PresenceConnection {
|
|
|
349
409
|
* own source that has no such message simply omits it and gets the grace. Sent just before `close()`.
|
|
350
410
|
*/
|
|
351
411
|
readonly bye?: () => void;
|
|
412
|
+
/**
|
|
413
|
+
* The line owner (`docs/specs/line-owner.md` §5.2): says which softphone this connection speaks for, so
|
|
414
|
+
* the server can tell it whether it has the line — through `PresenceCallbacks.onLine`, right after this
|
|
415
|
+
* and on every change. Sent as the FIRST message of every connection. Optional: a source without it never
|
|
416
|
+
* takes part, and its softphone listens exactly as before (fail-open), reading its line as `unknown`.
|
|
417
|
+
*/
|
|
418
|
+
readonly hello?: (clientId: string) => void;
|
|
419
|
+
/**
|
|
420
|
+
* "Recibir aquí": asks for the line. Answered through `PresenceCallbacks.onClaimResult` — and, when it
|
|
421
|
+
* succeeds, by `onLine` saying `here` first. Optional, like `hello`.
|
|
422
|
+
*/
|
|
423
|
+
readonly claimLine?: () => void;
|
|
352
424
|
/**
|
|
353
425
|
* Ends this connection deliberately. Never causes the SAME callbacks' `onClose` to fire — that is
|
|
354
426
|
* reserved for the connection ending on its OWN (a network drop, a server-side close, a rejected
|
|
@@ -368,6 +440,19 @@ interface PresenceCallbacks {
|
|
|
368
440
|
* identical from here, and both get the same treatment (spec §4.4 — quiet retry, nothing surfaced).
|
|
369
441
|
*/
|
|
370
442
|
readonly onClose: () => void;
|
|
443
|
+
/**
|
|
444
|
+
* The line, as the server says it — right after `PresenceConnection.hello`, and on every change after
|
|
445
|
+
* that. Optional, so callbacks written before the line owner existed still type-check.
|
|
446
|
+
*/
|
|
447
|
+
readonly onLine?: (update: LineUpdate) => void;
|
|
448
|
+
/** The answer to `PresenceConnection.claimLine()`. Optional, like `onLine`. */
|
|
449
|
+
readonly onClaimResult?: (result: LineClaimResult) => void;
|
|
450
|
+
/**
|
|
451
|
+
* A call offered to this line started or ended (`CallOffer`). Sent only to the line's owner. Optional, like
|
|
452
|
+
* `onLine`: callbacks written before it existed still type-check, and a source that never calls it leaves the
|
|
453
|
+
* softphone on its fallback after a decline (incoming-call-reliability.md §4.4).
|
|
454
|
+
*/
|
|
455
|
+
readonly onOffer?: (offer: CallOffer) => void;
|
|
371
456
|
}
|
|
372
457
|
/**
|
|
373
458
|
* Opens one live presence connection. Coventia-backed by default (mints a one-time ticket, opens
|
|
@@ -598,6 +683,16 @@ declare const ERROR_CATALOGUE: {
|
|
|
598
683
|
readonly message: "The provider does not support this operation.";
|
|
599
684
|
readonly solution: "Guard the UI on the operation before offering it.";
|
|
600
685
|
};
|
|
686
|
+
readonly 'line/claim-refused': {
|
|
687
|
+
readonly fatal: false;
|
|
688
|
+
readonly message: "The line was not moved here: the user is on a call on the softphone that has it.";
|
|
689
|
+
readonly solution: "Nothing to fix. The line never moves during a call; take it again once that call has ended. Incoming calls keep ringing where they ring now.";
|
|
690
|
+
};
|
|
691
|
+
readonly 'line/unavailable': {
|
|
692
|
+
readonly fatal: false;
|
|
693
|
+
readonly message: "The line could not be taken: nothing decided where it is.";
|
|
694
|
+
readonly solution: "The presence connection is down, the backend predates the line owner, or it did not answer in time. Retry in a moment; incoming calls keep ringing where they ring now.";
|
|
695
|
+
};
|
|
601
696
|
readonly 'provider/provision-failed': {
|
|
602
697
|
readonly fatal: true;
|
|
603
698
|
readonly message: "The provider could not issue SIP credentials.";
|
|
@@ -686,10 +781,25 @@ declare enum SoftphoneEvent {
|
|
|
686
781
|
/**
|
|
687
782
|
* `softphone.presence` changed — the live agent-presence list (Phase B,
|
|
688
783
|
* `docs/specs/transfer-presence-picker.md`) gained a snapshot or an updated entry. Requires a
|
|
689
|
-
* `PresenceSource` (from `coventia`/`apiBase`, or a host override) AND this tab currently being
|
|
690
|
-
* `online
|
|
784
|
+
* `PresenceSource` (from `coventia`/`apiBase`, or a host override) AND this tab currently being a
|
|
785
|
+
* started leader — `online`, or waiting in `standby` for the line; never fires at all otherwise,
|
|
786
|
+
* same reasoning as `TransferOutcome`.
|
|
787
|
+
*/
|
|
788
|
+
PresenceChanged = "presenceChanged",
|
|
789
|
+
/**
|
|
790
|
+
* `softphone.line` / `lineWhere` changed (`docs/specs/line-owner.md` §5): this softphone got the line,
|
|
791
|
+
* lost it to another softphone of the same extension, or stopped knowing (`unknown` — it then listens,
|
|
792
|
+
* as before the line owner existed). A third axis beside `StateChanged` and `LeaderChanged`: losing the
|
|
793
|
+
* line is what takes the softphone to `standby`, but not at once while a call is in progress — the line
|
|
794
|
+
* can read `elsewhere` while the state is still `online`, until that call ends.
|
|
691
795
|
*/
|
|
692
|
-
|
|
796
|
+
LineChanged = "lineChanged",
|
|
797
|
+
/**
|
|
798
|
+
* `softphone.lineClaim` changed: an attempt to bring the line here started, was refused, failed, or ended
|
|
799
|
+
* (the line came here, or the softphone stopped). Kept apart from `LineChanged`, which only ever means the
|
|
800
|
+
* line itself moved.
|
|
801
|
+
*/
|
|
802
|
+
LineClaimChanged = "lineClaimChanged"
|
|
693
803
|
}
|
|
694
804
|
interface SoftphoneEventMap {
|
|
695
805
|
[SoftphoneEvent.StateChanged]: {
|
|
@@ -710,6 +820,13 @@ interface SoftphoneEventMap {
|
|
|
710
820
|
[SoftphoneEvent.PresenceChanged]: {
|
|
711
821
|
readonly agents: readonly PresenceEntry[];
|
|
712
822
|
};
|
|
823
|
+
[SoftphoneEvent.LineChanged]: {
|
|
824
|
+
readonly line: LineState;
|
|
825
|
+
readonly where: LineLocation | null;
|
|
826
|
+
};
|
|
827
|
+
[SoftphoneEvent.LineClaimChanged]: {
|
|
828
|
+
readonly claim: LineClaim;
|
|
829
|
+
};
|
|
713
830
|
}
|
|
714
831
|
declare enum CallEvent {
|
|
715
832
|
/** Any transition. The catch-all; the specific events below are conveniences. */
|
|
@@ -810,7 +927,7 @@ interface TypedEmitter<M> {
|
|
|
810
927
|
*
|
|
811
928
|
* - **`rejecting`.** Today's engine has one, purely to swallow Zadarma's `return_timeout` retries
|
|
812
929
|
* for 35 s after a decline (SPEC §3.4). That is a PROVIDER quirk — it belongs in
|
|
813
|
-
* `providers/zadarma.ts` as `quirks.
|
|
930
|
+
* `providers/zadarma.ts` as `quirks.declinedCallerGuardMs`, not in the shared state machine. A rejected
|
|
814
931
|
* call is simply `ended`. Our own SIP infrastructure would not need it at all (SPEC §2.3).
|
|
815
932
|
*
|
|
816
933
|
* - **A pre-INVITE state.** A Call exists only once an INVITE has landed. The "user answered
|
|
@@ -936,4 +1053,4 @@ interface Call extends TypedEmitter<CallEventMap> {
|
|
|
936
1053
|
cancelConsult(): Promise<void>;
|
|
937
1054
|
}
|
|
938
1055
|
|
|
939
|
-
export {
|
|
1056
|
+
export { type TokenSource as A, type TypedEmitter as B, CALL_TRANSITIONS as C, canTransition as D, ERROR_CATALOGUE as E, type FatalErrorCode as F, isFatal as G, type HangupReason as H, INITIAL_STATES as I, isTerminal as J, type ContactsSource as K, type LineClaim as L, type HistorySource as M, type NonFatalErrorCode as N, type OutboundNumberRefusal as O, type PresenceEntry as P, type AgentsDirectory as Q, type RemoteParty as R, type SoftphoneConfig as S, type TokenEndpointOptions as T, type TransferOutcomesPage as U, type VoiceToken as V, type PresenceSource as W, type CallHistoryEntry as X, type ContactsPage as Y, type CallOffer as Z, type Call as a, type CallDirection as b, CallEvent as c, type CallEventMap as d, type CallOptions as e, type CallState as f, type Contact as g, type FatalSoftphoneError as h, type HoldOriginator as i, type LineLocation as j, type LineState as k, type LogLevel as l, type NonFatalSoftphoneError as m, type OutboundNumber as n, type OutboundNumberKind as o, type OutboundNumberSettings as p, type OutboundNumberState as q, type OutboundNumbersSource as r, type RingtoneOption as s, type RingtoneSettings as t, type RingtoneSource as u, type SoftphoneError as v, type SoftphoneErrorCode as w, SoftphoneEvent as x, type SoftphoneEventMap as y, type SoftphoneState as z };
|
|
@@ -86,10 +86,10 @@ interface TokenEndpointOptions {
|
|
|
86
86
|
*/
|
|
87
87
|
interface CoventiaBackendConfig {
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* does, which is not the normal case.
|
|
89
|
+
* Coventia's domain, like `SoftphoneConfig.apiBase`: no path, the SDK builds every route.
|
|
90
|
+
* **Optional** — falls back to `SoftphoneConfig.apiBase`, which exists precisely so this and the
|
|
91
|
+
* default call engine name the same backend once instead of twice. Set it here only when
|
|
92
|
+
* contacts/history genuinely live on a DIFFERENT host than calling does, which is not the normal case.
|
|
93
93
|
*/
|
|
94
94
|
readonly baseUrl?: string | undefined;
|
|
95
95
|
/**
|
|
@@ -104,7 +104,10 @@ interface CoventiaBackendConfig {
|
|
|
104
104
|
* That is the CRM today.
|
|
105
105
|
*/
|
|
106
106
|
readonly organizationId?: string;
|
|
107
|
-
/**
|
|
107
|
+
/**
|
|
108
|
+
* Where the phone routes sit under the base URL. Internal: leave it unset (`/phone`). The routes are
|
|
109
|
+
* the SDK's to build, which is why `apiBase` is the domain only.
|
|
110
|
+
*/
|
|
108
111
|
readonly basePath?: string;
|
|
109
112
|
/**
|
|
110
113
|
* **The one thing a provider customises**: their own contact list, searched on their own backend.
|
|
@@ -134,8 +137,11 @@ interface CoventiaBackendConfig {
|
|
|
134
137
|
interface SoftphoneConfig {
|
|
135
138
|
readonly tokenSource: TokenSource;
|
|
136
139
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
140
|
+
* Coventia's domain — **only the domain**, e.g. `https://backend.example.com`, with no path: the SDK
|
|
141
|
+
* builds every route itself. Not the Partner API URL your backend calls: that one ends in `/api/v1`,
|
|
142
|
+
* which does not belong here (it is ignored, with a console warning). **The one field to set** if you
|
|
143
|
+
* want the default call engine (see `provider` below) and are not overriding `coventia.baseUrl`
|
|
144
|
+
* separately.
|
|
139
145
|
*
|
|
140
146
|
* Named once here rather than requiring it on both `coventia` and the engine you construct: they
|
|
141
147
|
* are two independent subsystems (contacts/history/caller ID vs. SIP credential provisioning) that
|
|
@@ -188,8 +194,62 @@ interface CallOptions {
|
|
|
188
194
|
* Zadarma registers on-demand, per call, in response to a push (SPEC §3.2); a persistent UA is
|
|
189
195
|
* ignored by its PBX. Leaking "registered" into the public API would force every future provider —
|
|
190
196
|
* including our own SIP infrastructure, which registers persistently — to fake it.
|
|
197
|
+
*
|
|
198
|
+
* `standby` means started, and this browser's leader, but ANOTHER softphone of the same extension has
|
|
199
|
+
* the line — a tab in another browser, the desktop app, a partner page (`docs/specs/line-owner.md` §5).
|
|
200
|
+
* Its push socket is closed on purpose, so nothing here registers or rings: `line` says where the calls
|
|
201
|
+
* go, and `takeLine()` — or a `call()` — brings them here. A host that reads `online` as "ready"
|
|
202
|
+
* correctly reads this as not ready.
|
|
203
|
+
*/
|
|
204
|
+
type SoftphoneState = 'stopped' | 'starting' | 'online' | 'standby' | 'offline' | 'reconnecting' | 'destroyed';
|
|
205
|
+
/**
|
|
206
|
+
* Where this extension's incoming calls ring, as far as this softphone knows. `here`: it has the line.
|
|
207
|
+
* `elsewhere`: another softphone of the same extension has it, and this one waits in `standby`. `unknown`:
|
|
208
|
+
* nobody has said — no presence source, a backend that predates the line owner, a presence socket that is
|
|
209
|
+
* down — and this softphone listens, exactly as before the line owner existed (§5.1 R7, fail-open).
|
|
191
210
|
*/
|
|
192
|
-
type
|
|
211
|
+
type LineState = 'here' | 'elsewhere' | 'unknown';
|
|
212
|
+
/** Who has the line when it is `elsewhere`: the desktop app, or any other softphone (a browser tab). */
|
|
213
|
+
type LineLocation = 'desktop' | 'browser';
|
|
214
|
+
/**
|
|
215
|
+
* The last attempt to bring the line here — `takeLine()`, or a `call()` from `standby`, whoever made it:
|
|
216
|
+
* `claiming` while it is in flight, `refused` when the user is on a call where the line is, `failed` when
|
|
217
|
+
* nothing could decide. `idle` before any attempt, once the line comes here, and after a `stop()`.
|
|
218
|
+
*/
|
|
219
|
+
type LineClaim = 'idle' | 'claiming' | 'refused' | 'failed';
|
|
220
|
+
/** The server's word on this softphone's line, as a `PresenceSource` hands it over (`PresenceCallbacks.onLine`). */
|
|
221
|
+
interface LineUpdate {
|
|
222
|
+
readonly state: 'here' | 'elsewhere';
|
|
223
|
+
/** Who has the line when it is `elsewhere`; `null` when it is here, or the server did not say. */
|
|
224
|
+
readonly where: LineLocation | null;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* A call offered to this user's line, as the backend announces it over the presence socket
|
|
228
|
+
* (incoming-call-reliability.md §5): `start` each time the call is offered to the extension (a re-offer of the
|
|
229
|
+
* same call repeats it, same `callId`), `end` when the call is over. `callId` is opaque; `from` is the caller,
|
|
230
|
+
* `null` (or, on an `end`, absent) when the backend did not say.
|
|
231
|
+
*
|
|
232
|
+
* The softphone uses it for one thing: after a decline, to know when the declined call's re-offers stop, so a
|
|
233
|
+
* new call from the same number rings (§4.4). A presence source that never sends it loses nothing but that.
|
|
234
|
+
*/
|
|
235
|
+
type CallOffer = {
|
|
236
|
+
readonly state: 'start';
|
|
237
|
+
readonly callId: string;
|
|
238
|
+
readonly from: string | null;
|
|
239
|
+
} | {
|
|
240
|
+
readonly state: 'end';
|
|
241
|
+
readonly callId: string;
|
|
242
|
+
readonly from?: string | null;
|
|
243
|
+
};
|
|
244
|
+
/** The answer to `PresenceConnection.claimLine()`. */
|
|
245
|
+
interface LineClaimResult {
|
|
246
|
+
readonly ok: boolean;
|
|
247
|
+
/**
|
|
248
|
+
* Why it was refused: `'on_call'` while the user is on a call (the line never moves during one). Any
|
|
249
|
+
* other value means nothing was decided. Absent when `ok`.
|
|
250
|
+
*/
|
|
251
|
+
readonly reason?: string;
|
|
252
|
+
}
|
|
193
253
|
interface ContactsPage {
|
|
194
254
|
readonly items: readonly Contact[];
|
|
195
255
|
/**
|
|
@@ -349,6 +409,18 @@ interface PresenceConnection {
|
|
|
349
409
|
* own source that has no such message simply omits it and gets the grace. Sent just before `close()`.
|
|
350
410
|
*/
|
|
351
411
|
readonly bye?: () => void;
|
|
412
|
+
/**
|
|
413
|
+
* The line owner (`docs/specs/line-owner.md` §5.2): says which softphone this connection speaks for, so
|
|
414
|
+
* the server can tell it whether it has the line — through `PresenceCallbacks.onLine`, right after this
|
|
415
|
+
* and on every change. Sent as the FIRST message of every connection. Optional: a source without it never
|
|
416
|
+
* takes part, and its softphone listens exactly as before (fail-open), reading its line as `unknown`.
|
|
417
|
+
*/
|
|
418
|
+
readonly hello?: (clientId: string) => void;
|
|
419
|
+
/**
|
|
420
|
+
* "Recibir aquí": asks for the line. Answered through `PresenceCallbacks.onClaimResult` — and, when it
|
|
421
|
+
* succeeds, by `onLine` saying `here` first. Optional, like `hello`.
|
|
422
|
+
*/
|
|
423
|
+
readonly claimLine?: () => void;
|
|
352
424
|
/**
|
|
353
425
|
* Ends this connection deliberately. Never causes the SAME callbacks' `onClose` to fire — that is
|
|
354
426
|
* reserved for the connection ending on its OWN (a network drop, a server-side close, a rejected
|
|
@@ -368,6 +440,19 @@ interface PresenceCallbacks {
|
|
|
368
440
|
* identical from here, and both get the same treatment (spec §4.4 — quiet retry, nothing surfaced).
|
|
369
441
|
*/
|
|
370
442
|
readonly onClose: () => void;
|
|
443
|
+
/**
|
|
444
|
+
* The line, as the server says it — right after `PresenceConnection.hello`, and on every change after
|
|
445
|
+
* that. Optional, so callbacks written before the line owner existed still type-check.
|
|
446
|
+
*/
|
|
447
|
+
readonly onLine?: (update: LineUpdate) => void;
|
|
448
|
+
/** The answer to `PresenceConnection.claimLine()`. Optional, like `onLine`. */
|
|
449
|
+
readonly onClaimResult?: (result: LineClaimResult) => void;
|
|
450
|
+
/**
|
|
451
|
+
* A call offered to this line started or ended (`CallOffer`). Sent only to the line's owner. Optional, like
|
|
452
|
+
* `onLine`: callbacks written before it existed still type-check, and a source that never calls it leaves the
|
|
453
|
+
* softphone on its fallback after a decline (incoming-call-reliability.md §4.4).
|
|
454
|
+
*/
|
|
455
|
+
readonly onOffer?: (offer: CallOffer) => void;
|
|
371
456
|
}
|
|
372
457
|
/**
|
|
373
458
|
* Opens one live presence connection. Coventia-backed by default (mints a one-time ticket, opens
|
|
@@ -598,6 +683,16 @@ declare const ERROR_CATALOGUE: {
|
|
|
598
683
|
readonly message: "The provider does not support this operation.";
|
|
599
684
|
readonly solution: "Guard the UI on the operation before offering it.";
|
|
600
685
|
};
|
|
686
|
+
readonly 'line/claim-refused': {
|
|
687
|
+
readonly fatal: false;
|
|
688
|
+
readonly message: "The line was not moved here: the user is on a call on the softphone that has it.";
|
|
689
|
+
readonly solution: "Nothing to fix. The line never moves during a call; take it again once that call has ended. Incoming calls keep ringing where they ring now.";
|
|
690
|
+
};
|
|
691
|
+
readonly 'line/unavailable': {
|
|
692
|
+
readonly fatal: false;
|
|
693
|
+
readonly message: "The line could not be taken: nothing decided where it is.";
|
|
694
|
+
readonly solution: "The presence connection is down, the backend predates the line owner, or it did not answer in time. Retry in a moment; incoming calls keep ringing where they ring now.";
|
|
695
|
+
};
|
|
601
696
|
readonly 'provider/provision-failed': {
|
|
602
697
|
readonly fatal: true;
|
|
603
698
|
readonly message: "The provider could not issue SIP credentials.";
|
|
@@ -686,10 +781,25 @@ declare enum SoftphoneEvent {
|
|
|
686
781
|
/**
|
|
687
782
|
* `softphone.presence` changed — the live agent-presence list (Phase B,
|
|
688
783
|
* `docs/specs/transfer-presence-picker.md`) gained a snapshot or an updated entry. Requires a
|
|
689
|
-
* `PresenceSource` (from `coventia`/`apiBase`, or a host override) AND this tab currently being
|
|
690
|
-
* `online
|
|
784
|
+
* `PresenceSource` (from `coventia`/`apiBase`, or a host override) AND this tab currently being a
|
|
785
|
+
* started leader — `online`, or waiting in `standby` for the line; never fires at all otherwise,
|
|
786
|
+
* same reasoning as `TransferOutcome`.
|
|
787
|
+
*/
|
|
788
|
+
PresenceChanged = "presenceChanged",
|
|
789
|
+
/**
|
|
790
|
+
* `softphone.line` / `lineWhere` changed (`docs/specs/line-owner.md` §5): this softphone got the line,
|
|
791
|
+
* lost it to another softphone of the same extension, or stopped knowing (`unknown` — it then listens,
|
|
792
|
+
* as before the line owner existed). A third axis beside `StateChanged` and `LeaderChanged`: losing the
|
|
793
|
+
* line is what takes the softphone to `standby`, but not at once while a call is in progress — the line
|
|
794
|
+
* can read `elsewhere` while the state is still `online`, until that call ends.
|
|
691
795
|
*/
|
|
692
|
-
|
|
796
|
+
LineChanged = "lineChanged",
|
|
797
|
+
/**
|
|
798
|
+
* `softphone.lineClaim` changed: an attempt to bring the line here started, was refused, failed, or ended
|
|
799
|
+
* (the line came here, or the softphone stopped). Kept apart from `LineChanged`, which only ever means the
|
|
800
|
+
* line itself moved.
|
|
801
|
+
*/
|
|
802
|
+
LineClaimChanged = "lineClaimChanged"
|
|
693
803
|
}
|
|
694
804
|
interface SoftphoneEventMap {
|
|
695
805
|
[SoftphoneEvent.StateChanged]: {
|
|
@@ -710,6 +820,13 @@ interface SoftphoneEventMap {
|
|
|
710
820
|
[SoftphoneEvent.PresenceChanged]: {
|
|
711
821
|
readonly agents: readonly PresenceEntry[];
|
|
712
822
|
};
|
|
823
|
+
[SoftphoneEvent.LineChanged]: {
|
|
824
|
+
readonly line: LineState;
|
|
825
|
+
readonly where: LineLocation | null;
|
|
826
|
+
};
|
|
827
|
+
[SoftphoneEvent.LineClaimChanged]: {
|
|
828
|
+
readonly claim: LineClaim;
|
|
829
|
+
};
|
|
713
830
|
}
|
|
714
831
|
declare enum CallEvent {
|
|
715
832
|
/** Any transition. The catch-all; the specific events below are conveniences. */
|
|
@@ -810,7 +927,7 @@ interface TypedEmitter<M> {
|
|
|
810
927
|
*
|
|
811
928
|
* - **`rejecting`.** Today's engine has one, purely to swallow Zadarma's `return_timeout` retries
|
|
812
929
|
* for 35 s after a decline (SPEC §3.4). That is a PROVIDER quirk — it belongs in
|
|
813
|
-
* `providers/zadarma.ts` as `quirks.
|
|
930
|
+
* `providers/zadarma.ts` as `quirks.declinedCallerGuardMs`, not in the shared state machine. A rejected
|
|
814
931
|
* call is simply `ended`. Our own SIP infrastructure would not need it at all (SPEC §2.3).
|
|
815
932
|
*
|
|
816
933
|
* - **A pre-INVITE state.** A Call exists only once an INVITE has landed. The "user answered
|
|
@@ -936,4 +1053,4 @@ interface Call extends TypedEmitter<CallEventMap> {
|
|
|
936
1053
|
cancelConsult(): Promise<void>;
|
|
937
1054
|
}
|
|
938
1055
|
|
|
939
|
-
export {
|
|
1056
|
+
export { type TokenSource as A, type TypedEmitter as B, CALL_TRANSITIONS as C, canTransition as D, ERROR_CATALOGUE as E, type FatalErrorCode as F, isFatal as G, type HangupReason as H, INITIAL_STATES as I, isTerminal as J, type ContactsSource as K, type LineClaim as L, type HistorySource as M, type NonFatalErrorCode as N, type OutboundNumberRefusal as O, type PresenceEntry as P, type AgentsDirectory as Q, type RemoteParty as R, type SoftphoneConfig as S, type TokenEndpointOptions as T, type TransferOutcomesPage as U, type VoiceToken as V, type PresenceSource as W, type CallHistoryEntry as X, type ContactsPage as Y, type CallOffer as Z, type Call as a, type CallDirection as b, CallEvent as c, type CallEventMap as d, type CallOptions as e, type CallState as f, type Contact as g, type FatalSoftphoneError as h, type HoldOriginator as i, type LineLocation as j, type LineState as k, type LogLevel as l, type NonFatalSoftphoneError as m, type OutboundNumber as n, type OutboundNumberKind as o, type OutboundNumberSettings as p, type OutboundNumberState as q, type OutboundNumbersSource as r, type RingtoneOption as s, type RingtoneSettings as t, type RingtoneSource as u, type SoftphoneError as v, type SoftphoneErrorCode as w, SoftphoneEvent as x, type SoftphoneEventMap as y, type SoftphoneState as z };
|