@xema/omni-protocol 0.1.100 → 0.1.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +100 -88
- package/dist/index.js +5 -4
- package/dist/testing.d.ts +19 -1
- package/dist/testing.js +162 -32
- package/dist/validation.d.ts +6 -3
- package/dist/validation.js +188 -152
- package/guide.md +322 -230
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -164,7 +164,7 @@ export interface Manifest<C extends Channel = Channel> {
|
|
|
164
164
|
/**
|
|
165
165
|
* The outcomes this platform distinguishes when a dial ends, `answered` and at least one way of
|
|
166
166
|
* not reaching the destination. Required of a provider that dials at all -- an idle dialpad, or
|
|
167
|
-
* a task that may
|
|
167
|
+
* a task that may conference or call back -- and forbidden off voice, where nothing dials.
|
|
168
168
|
*/
|
|
169
169
|
dialOutcomes?: C extends "voice" ? DialOutcome[] : never;
|
|
170
170
|
/**
|
|
@@ -180,10 +180,9 @@ export interface Manifest<C extends Channel = Channel> {
|
|
|
180
180
|
runningStepReports?: true;
|
|
181
181
|
/**
|
|
182
182
|
* How long after an applied completion -- `complete`, or a lead's `take-over-call` -- the provider's
|
|
183
|
-
* `task-ended` is owed, in milliseconds.
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* task as unsettled. Stated per provider, since platforms settle at different speeds.
|
|
183
|
+
* `task-ended` is owed, in milliseconds. `applied` says the provider has completed the task;
|
|
184
|
+
* the ending follows within this, or the host resyncs and shows the task as unsettled. Stated
|
|
185
|
+
* per provider, since platforms settle at different speeds.
|
|
187
186
|
*/
|
|
188
187
|
completionSettleMs: number;
|
|
189
188
|
}
|
|
@@ -251,9 +250,10 @@ export interface UserCapabilities {
|
|
|
251
250
|
/**
|
|
252
251
|
* This login leads a team. The flag alone turns on the team feature in the agent application:
|
|
253
252
|
* the lead sees their members with their tasks and stats, and acts on them through `executeTeam`
|
|
254
|
-
* with the authority the flag carries. No per-action permission rides beside it.
|
|
255
|
-
*
|
|
256
|
-
*
|
|
253
|
+
* with the authority the flag carries. No per-action permission rides beside it. The provider
|
|
254
|
+
* assumes nothing of the switch: the application sends `lead-features` on every connect, and
|
|
255
|
+
* only while it is on does the team reach the lead -- `team-updated` whole after the switch and
|
|
256
|
+
* on any snapshot, then one member at a time as members change; to nobody else, ever.
|
|
257
257
|
*/
|
|
258
258
|
lead?: true;
|
|
259
259
|
}
|
|
@@ -458,7 +458,6 @@ export type RecordingState = {
|
|
|
458
458
|
export type RecordingCommand = {
|
|
459
459
|
type: "recording";
|
|
460
460
|
source: RecordingSource;
|
|
461
|
-
requestId: string;
|
|
462
461
|
/** Compare-and-set against current evidence; never act on a replacement recording. */
|
|
463
462
|
observationId: string;
|
|
464
463
|
} & ({
|
|
@@ -622,7 +621,7 @@ export interface Destination {
|
|
|
622
621
|
id: string;
|
|
623
622
|
label: string;
|
|
624
623
|
}
|
|
625
|
-
/** The items a
|
|
624
|
+
/** The items a conference control offers. Nothing is typed; the agent picks one. */
|
|
626
625
|
export interface DestinationDirectory {
|
|
627
626
|
destinations: Destination[];
|
|
628
627
|
}
|
|
@@ -653,14 +652,13 @@ export interface SharedTaskCapabilities {
|
|
|
653
652
|
export type TaskCapabilities<C extends Channel = Channel> = C extends "voice" ? SharedTaskCapabilities & {
|
|
654
653
|
decline?: Lockable<true>;
|
|
655
654
|
hold?: Lockable<true>;
|
|
656
|
-
/** The provider ends the caller connection and agent-added channels owned by this interaction, including inherited channels after
|
|
655
|
+
/** The provider ends the caller connection and agent-added channels owned by this interaction, including inherited channels after a take-over. Interaction completion remains separate. */
|
|
657
656
|
endCall?: Lockable<true>;
|
|
658
657
|
terminateCall?: Lockable<true>;
|
|
659
658
|
/** Connect back to the party while `completing`, whoever placed the call; the task returns to `in-progress`. */
|
|
660
659
|
connectBack?: Lockable<true>;
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
warmTransfer?: Lockable<DestinationDirectory>;
|
|
660
|
+
/** Put a time on the calendar for this party, from the call: a follow-up the agent promised. */
|
|
661
|
+
schedule?: Lockable<true>;
|
|
664
662
|
/** Ask a lead to join this call, with a note. The lead's decision arrives on `Task.leadAssist`. */
|
|
665
663
|
leadAssist?: Lockable<true>;
|
|
666
664
|
conference?: Lockable<DestinationDirectory>;
|
|
@@ -721,7 +719,7 @@ export type TaskPhase =
|
|
|
721
719
|
| "confirmed"
|
|
722
720
|
/**
|
|
723
721
|
* Voice only: the customer's record is available for preparation, then dialing before answer. The agent
|
|
724
|
-
* presses Call, or `
|
|
722
|
+
* presses Call, or `previewEndsInSeconds` runs out and `atDeadline` says what the system does instead.
|
|
725
723
|
*/
|
|
726
724
|
| "preview" | "in-progress" | "paused"
|
|
727
725
|
/** The work is over and the agent is finishing up. */
|
|
@@ -807,19 +805,18 @@ export type TaskCompletion = {
|
|
|
807
805
|
completionMode: "provider-automatic";
|
|
808
806
|
wrapAllowance: DurationSeconds;
|
|
809
807
|
};
|
|
810
|
-
export type OnCallRole = "party" | "agent" | "
|
|
808
|
+
export type OnCallRole = "party" | "agent" | "conferenced";
|
|
811
809
|
/** Where a dialled entry stands: `ringing` until its dial is answered, `joined` after. */
|
|
812
810
|
export type OnCallStage = "ringing" | "joined";
|
|
813
|
-
export declare const ON_CALL_ROLES: readonly ["party", "agent", "
|
|
811
|
+
export declare const ON_CALL_ROLES: readonly ["party", "agent", "conferenced"];
|
|
814
812
|
/**
|
|
815
813
|
* Somebody on the call, or being brought onto it, as the provider states it: who, since when, and
|
|
816
|
-
* whether they are held aside. `party` is the customer; `agent` a person, by user id; `
|
|
817
|
-
*
|
|
818
|
-
*
|
|
819
|
-
*
|
|
820
|
-
*
|
|
821
|
-
*
|
|
822
|
-
* one `consulted`: the consult commands name neither because there is exactly one. The `party`
|
|
814
|
+
* whether they are held aside. `party` is the customer; `agent` a person, by user id; `conferenced`
|
|
815
|
+
* someone a dial is bringing in -- listed from the moment the dial is placed, so the agent can call
|
|
816
|
+
* it off while it rings -- carrying the dial when a host placed it, the address either way, and the
|
|
817
|
+
* `stage` it has reached: `ringing` until the dial is answered, `joined` after, stated so a snapshot
|
|
818
|
+
* says who is present without anyone having seen the outcome. Nobody ringing is held. `label` names
|
|
819
|
+
* a destination -- a person, a queue -- not a phrase. At most one `party`. The `party`
|
|
823
820
|
* carries a `stage` while being dialled -- by any host dial, a dialpad call, a preview Call or a
|
|
824
821
|
* connect-back, carrying its `dialId`, or by a callback the platform places itself, carrying none --
|
|
825
822
|
* `ringing` from the moment the dial is placed, `joined` on the publication that follows its
|
|
@@ -842,7 +839,7 @@ export type OnCall = {
|
|
|
842
839
|
role: "agent";
|
|
843
840
|
userId: UserId;
|
|
844
841
|
} | {
|
|
845
|
-
role: "
|
|
842
|
+
role: "conferenced";
|
|
846
843
|
destinationId: string;
|
|
847
844
|
stage: OnCallStage;
|
|
848
845
|
dialId?: DialId;
|
|
@@ -866,7 +863,7 @@ export type TaskLeadAssist = {
|
|
|
866
863
|
* On a task that reached this agent by a lead's take-over: which member the call was taken from,
|
|
867
864
|
* and when. The provider moves the call from one agent to another, and the lead is the new agent,
|
|
868
865
|
* so the task is an ordinary assignment with the call's history -- offered whatever break the lead
|
|
869
|
-
* is on, counted against
|
|
866
|
+
* is on, counted against their capacity like any other call, provided they are under it and their voice channel is free.
|
|
870
867
|
*/
|
|
871
868
|
export interface TaskTakenOver {
|
|
872
869
|
memberId: UserId;
|
|
@@ -952,12 +949,14 @@ export type Task<C extends Channel = Channel> = {
|
|
|
952
949
|
*/
|
|
953
950
|
acceptance?: AcceptanceMode;
|
|
954
951
|
/**
|
|
955
|
-
* In `preview` only, and together: the preparation
|
|
956
|
-
*
|
|
957
|
-
*
|
|
958
|
-
*
|
|
952
|
+
* In `preview` only, and together: how long the preparation has left, in whole seconds from
|
|
953
|
+
* this publication -- restated on every publication that carries it, so a resync starts the
|
|
954
|
+
* countdown afresh and no clock is compared -- and behavior when it runs out, and who acts then:
|
|
955
|
+
* `provider-dials` makes the provider initiate dialing, `host-dials` makes the host issue Call,
|
|
956
|
+
* and `waits` keeps waiting for the agent without dialing or ending the task. Absent, the agent
|
|
957
|
+
* has as long as they need, without a preparation countdown.
|
|
959
958
|
*/
|
|
960
|
-
|
|
959
|
+
previewEndsInSeconds?: DurationSeconds;
|
|
961
960
|
atDeadline?: PreviewDeadline;
|
|
962
961
|
/** The identifier an agent reads back to a customer, where the provider has one. */
|
|
963
962
|
reference?: string;
|
|
@@ -989,11 +988,6 @@ export type TaskOutcome = {
|
|
|
989
988
|
type: "completed";
|
|
990
989
|
by: "agent" | "provider";
|
|
991
990
|
}
|
|
992
|
-
/** A cold transfer to a destination the agent chose: a directory item's id. */
|
|
993
|
-
| {
|
|
994
|
-
type: "transferred";
|
|
995
|
-
destinationId?: string;
|
|
996
|
-
}
|
|
997
991
|
/** A lead took the call over and the agent has wrapped it: the outcome at the agent's own completion. Named by the lead, since a lead is not a directory item. */
|
|
998
992
|
| {
|
|
999
993
|
type: "taken-over";
|
|
@@ -1005,7 +999,7 @@ export type TaskOutcome = {
|
|
|
1005
999
|
by: "agent" | "provider" | "party";
|
|
1006
1000
|
reason?: string;
|
|
1007
1001
|
}
|
|
1008
|
-
/** Only the phases in which somebody is still being waited on can expire; an offer
|
|
1002
|
+
/** Only the phases in which somebody is still being waited on can expire; an offer whose `expiresInSeconds` runs out names `pending`. */
|
|
1009
1003
|
| {
|
|
1010
1004
|
type: "expired";
|
|
1011
1005
|
phase: "pending" | "confirmed" | "preview";
|
|
@@ -1014,7 +1008,7 @@ export type TaskOutcome = {
|
|
|
1014
1008
|
failure: ProtocolFailure;
|
|
1015
1009
|
};
|
|
1016
1010
|
export declare const TASK_COMMAND_NAMES: {
|
|
1017
|
-
readonly voice: readonly ["answer", "decline", "dial", "hold", "resume", "end-call", "terminate-call", "connect-back", "
|
|
1011
|
+
readonly voice: readonly ["answer", "decline", "dial", "hold", "resume", "end-call", "terminate-call", "connect-back", "lead-assist", "conference", "recording", "schedule", "complete"];
|
|
1018
1012
|
readonly chat: readonly ["accept", "decline", "pause", "resume", "complete"];
|
|
1019
1013
|
readonly email: readonly ["accept", "decline", "complete"];
|
|
1020
1014
|
};
|
|
@@ -1041,7 +1035,7 @@ export type VoiceTaskCommand = {
|
|
|
1041
1035
|
| {
|
|
1042
1036
|
type: "end-call";
|
|
1043
1037
|
}
|
|
1044
|
-
/** End the caller
|
|
1038
|
+
/** End the whole call at the provider: every channel on it, the agent's, the caller's and anyone else's. Gated by `terminateCall`. */
|
|
1045
1039
|
| {
|
|
1046
1040
|
type: "terminate-call";
|
|
1047
1041
|
}
|
|
@@ -1050,29 +1044,15 @@ export type VoiceTaskCommand = {
|
|
|
1050
1044
|
type: "connect-back";
|
|
1051
1045
|
dialId: DialId;
|
|
1052
1046
|
}
|
|
1053
|
-
/**
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
destinationId: string;
|
|
1059
|
-
}
|
|
1060
|
-
/** Warm: park the customer and call the directory item `destinationId` first. Gated by `warmTransfer`. */
|
|
1061
|
-
| {
|
|
1062
|
-
type: "transfer";
|
|
1063
|
-
action: "warm";
|
|
1064
|
-
dialId: DialId;
|
|
1065
|
-
destinationId: string;
|
|
1066
|
-
}
|
|
1067
|
-
/** Hand the customer to the consulted destination and leave. Needs a `consulted` entry on `Task.onCall`. */
|
|
1068
|
-
| {
|
|
1069
|
-
type: "transfer";
|
|
1070
|
-
action: "complete";
|
|
1071
|
-
}
|
|
1072
|
-
/** Drop the consulted destination and return to the customer. Needs a `consulted` entry on `Task.onCall`. */
|
|
1047
|
+
/**
|
|
1048
|
+
* Put a time on the calendar for this party: a follow-up promised on the call. Gated by
|
|
1049
|
+
* `schedule`, issuable in `in-progress`, `paused` or `completing`; the activity arrives on
|
|
1050
|
+
* `calendar-updated`, which is the provider's word that it stands.
|
|
1051
|
+
*/
|
|
1073
1052
|
| {
|
|
1074
|
-
type: "
|
|
1075
|
-
|
|
1053
|
+
type: "schedule";
|
|
1054
|
+
at: IsoTimestamp;
|
|
1055
|
+
note?: string;
|
|
1076
1056
|
}
|
|
1077
1057
|
/** Ask a lead to join, with a note. Gated by `leadAssist`. */
|
|
1078
1058
|
| {
|
|
@@ -1206,9 +1186,13 @@ export interface BreakRequest {
|
|
|
1206
1186
|
/** The chosen `BreakReason.id`, where the provider publishes codes. */
|
|
1207
1187
|
reasonId?: string;
|
|
1208
1188
|
}
|
|
1209
|
-
/**
|
|
1189
|
+
/**
|
|
1190
|
+
* A break forced on the agent; the agent must explicitly resume when ready. `by` is the lead who
|
|
1191
|
+
* forced it, or `provider` where the platform itself did, on its own rule or a schedule: the agent
|
|
1192
|
+
* sees who, and a person is named only when there is one.
|
|
1193
|
+
*/
|
|
1210
1194
|
export type ForcedBreak = {
|
|
1211
|
-
by: UserId;
|
|
1195
|
+
by: UserId | "provider";
|
|
1212
1196
|
/** Optional expected time on break, in milliseconds from actual start. Advisory only. */
|
|
1213
1197
|
expectedDurationMs?: number;
|
|
1214
1198
|
};
|
|
@@ -1269,10 +1253,13 @@ export interface TeamMember {
|
|
|
1269
1253
|
tasks?: MemberTask[];
|
|
1270
1254
|
/** Present while this lead is on the member's call, listening, coaching or joined; absent otherwise. */
|
|
1271
1255
|
listening?: MemberListening;
|
|
1256
|
+
/** The member's own history for the day: sign-in, sign-out, breaks and productivity. Omitted where the provider cannot say. */
|
|
1257
|
+
shift?: MemberShift;
|
|
1258
|
+
/** The member's standing ask for a lead on one of their calls; absent when they are not asking. */
|
|
1259
|
+
request?: MemberRequest;
|
|
1272
1260
|
}
|
|
1273
|
-
/**
|
|
1274
|
-
export interface
|
|
1275
|
-
memberId: UserId;
|
|
1261
|
+
/** This member asking their lead to join a call: which assignment, the note they wrote, since when. */
|
|
1262
|
+
export interface MemberRequest {
|
|
1276
1263
|
assignmentId: AssignmentId;
|
|
1277
1264
|
note?: string;
|
|
1278
1265
|
since: IsoTimestamp;
|
|
@@ -1309,20 +1296,45 @@ export type MemberTask<C extends Channel = Channel> = {
|
|
|
1309
1296
|
takenOver?: never;
|
|
1310
1297
|
audio?: never;
|
|
1311
1298
|
});
|
|
1312
|
-
/**
|
|
1299
|
+
/**
|
|
1300
|
+
* The lead on this member's call: which of the member's calls, in the mode they are heard, since
|
|
1301
|
+
* when. Its appearance on the team member list is the provider's word that the lead's audio is up,
|
|
1302
|
+
* and the application opens `openAudio` on the assignment named; its disappearance closes it.
|
|
1303
|
+
*/
|
|
1313
1304
|
export interface MemberListening {
|
|
1305
|
+
assignmentId: AssignmentId;
|
|
1314
1306
|
mode: ListeningMode;
|
|
1315
1307
|
since: IsoTimestamp;
|
|
1316
1308
|
}
|
|
1309
|
+
export type ShiftEventKind = "signed-in" | "signed-out" | "break-started" | "break-ended";
|
|
1310
|
+
export declare const SHIFT_EVENT_KINDS: readonly ["signed-in", "signed-out", "break-started", "break-ended"];
|
|
1311
|
+
export interface ShiftEvent {
|
|
1312
|
+
at: IsoTimestamp;
|
|
1313
|
+
kind: ShiftEventKind;
|
|
1314
|
+
}
|
|
1315
|
+
/**
|
|
1316
|
+
* The member's own history for the day, about the person rather than any one call: when they
|
|
1317
|
+
* signed in and out, today's totals as the provider counts them, each present only when the
|
|
1318
|
+
* provider knows it, and the day's sign-in, sign-out and break events, oldest first.
|
|
1319
|
+
*/
|
|
1320
|
+
export interface MemberShift {
|
|
1321
|
+
signedInAt: IsoTimestamp;
|
|
1322
|
+
signedOutAt?: IsoTimestamp;
|
|
1323
|
+
talkSeconds?: DurationSeconds;
|
|
1324
|
+
holdSeconds?: DurationSeconds;
|
|
1325
|
+
breakSeconds?: DurationSeconds;
|
|
1326
|
+
tasksHandled?: number;
|
|
1327
|
+
events?: ShiftEvent[];
|
|
1328
|
+
}
|
|
1317
1329
|
/**
|
|
1318
1330
|
* The lead's view of their team: published to a login that declares `capabilities.lead` while the
|
|
1319
|
-
* lead has the team feature on,
|
|
1320
|
-
*
|
|
1331
|
+
* lead has the team feature on, and to nobody else. Whole on `team-updated` -- after the switch,
|
|
1332
|
+
* and on any snapshot -- and from then on one member at a time: `team-member-updated` carries the
|
|
1333
|
+
* member whole, so applying it twice changes nothing, and `team-member-removed` takes one off.
|
|
1334
|
+
* A team of two hundred is never resent because one of them held.
|
|
1321
1335
|
*/
|
|
1322
1336
|
export interface TeamMembers {
|
|
1323
1337
|
members: TeamMember[];
|
|
1324
|
-
/** Members asking a lead to join their call; `[]` when nobody is asking. */
|
|
1325
|
-
requests: LeadRequest[];
|
|
1326
1338
|
/** The team's policy per capability, as it stands. Present where the provider offers policy control; absent where it does not. */
|
|
1327
1339
|
policies?: TeamPolicies;
|
|
1328
1340
|
}
|
|
@@ -1578,7 +1590,8 @@ export type ProviderEvent<C extends Channel = Channel> = {
|
|
|
1578
1590
|
} | {
|
|
1579
1591
|
type: "task-offered";
|
|
1580
1592
|
task: Task<C>;
|
|
1581
|
-
|
|
1593
|
+
/** How long the agent has to answer, in whole seconds from this event; the offer expires when it runs out. Absent, it stands until the provider says otherwise. */
|
|
1594
|
+
expiresInSeconds?: DurationSeconds;
|
|
1582
1595
|
} | {
|
|
1583
1596
|
type: "task-updated";
|
|
1584
1597
|
task: Task<C>;
|
|
@@ -1588,20 +1601,6 @@ export type ProviderEvent<C extends Channel = Channel> = {
|
|
|
1588
1601
|
} | {
|
|
1589
1602
|
type: "task-audio-ended";
|
|
1590
1603
|
assignmentId: AssignmentId;
|
|
1591
|
-
}
|
|
1592
|
-
/**
|
|
1593
|
-
* The lead's channel is in a member's call -- listening, coaching or joined -- and its audio should
|
|
1594
|
-
* attach: on a softphone the application opens audio on the member's assignment as it does for a
|
|
1595
|
-
* task. Voice, to a login that declares `lead`, never to the member.
|
|
1596
|
-
*/
|
|
1597
|
-
| {
|
|
1598
|
-
type: "team-audio-started";
|
|
1599
|
-
memberId: UserId;
|
|
1600
|
-
assignmentId: AssignmentId;
|
|
1601
|
-
} | {
|
|
1602
|
-
type: "team-audio-ended";
|
|
1603
|
-
memberId: UserId;
|
|
1604
|
-
assignmentId: AssignmentId;
|
|
1605
1604
|
} | {
|
|
1606
1605
|
type: "task-ended";
|
|
1607
1606
|
assignmentId: AssignmentId;
|
|
@@ -1635,9 +1634,22 @@ export type ProviderEvent<C extends Channel = Channel> = {
|
|
|
1635
1634
|
expected: string;
|
|
1636
1635
|
observed: string;
|
|
1637
1636
|
assignmentId?: AssignmentId;
|
|
1638
|
-
}
|
|
1637
|
+
}
|
|
1638
|
+
/** The whole team, once: after `lead-features` comes on, and on every snapshot while it is. */
|
|
1639
|
+
| {
|
|
1639
1640
|
type: "team-updated";
|
|
1640
1641
|
team: TeamMembers;
|
|
1642
|
+
}
|
|
1643
|
+
/** One member, whole, as they now stand: replaces the member of that id, or adds them. */
|
|
1644
|
+
| {
|
|
1645
|
+
type: "team-member-updated";
|
|
1646
|
+
member: TeamMember;
|
|
1647
|
+
} | {
|
|
1648
|
+
type: "team-member-removed";
|
|
1649
|
+
memberId: UserId;
|
|
1650
|
+
} | {
|
|
1651
|
+
type: "team-policies-updated";
|
|
1652
|
+
policies: TeamPolicies;
|
|
1641
1653
|
} | {
|
|
1642
1654
|
type: "contacts-updated";
|
|
1643
1655
|
contacts: Contact[];
|
|
@@ -1657,7 +1669,7 @@ export interface ProviderEventEnvelope<C extends Channel = Channel> {
|
|
|
1657
1669
|
occurredAt: IsoTimestamp;
|
|
1658
1670
|
event: ProviderEvent<C>;
|
|
1659
1671
|
}
|
|
1660
|
-
export declare const OMNI_FAILURE_CODES: readonly ["omni.not-authenticated", "omni.capability-not-enabled", "omni.assignment-not-found", "omni.destination-not-permitted", "omni.phone-not-permitted", "omni.rate-limited", "omni.unavailable", "omni.break-already-committed"];
|
|
1672
|
+
export declare const OMNI_FAILURE_CODES: readonly ["omni.not-authenticated", "omni.capability-not-enabled", "omni.assignment-not-found", "omni.destination-not-permitted", "omni.phone-not-permitted", "omni.rate-limited", "omni.unavailable", "omni.break-already-committed", "omni.recording-unsettled"];
|
|
1661
1673
|
export type OmniFailureCode = (typeof OMNI_FAILURE_CODES)[number];
|
|
1662
1674
|
/**
|
|
1663
1675
|
* What the host refused, told to the adapter that published it: a snapshot the host would not
|
package/dist/index.js
CHANGED
|
@@ -56,7 +56,7 @@ export function isAllowedBrowserUrl(url) {
|
|
|
56
56
|
return false;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
export const ON_CALL_ROLES = ["party", "agent", "
|
|
59
|
+
export const ON_CALL_ROLES = ["party", "agent", "conferenced"];
|
|
60
60
|
/**
|
|
61
61
|
* The levels a typical organisation has: the ladder in force when a manifest declares no
|
|
62
62
|
* `orgLevels`. A manifest that declares any states its whole ladder outright.
|
|
@@ -77,7 +77,7 @@ export const CAPABILITY_SOURCES = ["queue", "nobody", "not-yet-read"];
|
|
|
77
77
|
// ---------------------------------------------------------------------------
|
|
78
78
|
export const TASK_COMMAND_NAMES = {
|
|
79
79
|
voice: ["answer", "decline", "dial", "hold", "resume", "end-call", "terminate-call",
|
|
80
|
-
"connect-back", "
|
|
80
|
+
"connect-back", "lead-assist", "conference", "recording", "schedule", "complete"],
|
|
81
81
|
chat: ["accept", "decline", "pause", "resume", "complete"],
|
|
82
82
|
email: ["accept", "decline", "complete"],
|
|
83
83
|
};
|
|
@@ -85,8 +85,6 @@ export const TASK_COMMAND_NAMES = {
|
|
|
85
85
|
export function commandDialId(command) {
|
|
86
86
|
if (command.type === "connect-back" || command.type === "dial")
|
|
87
87
|
return command.dialId;
|
|
88
|
-
if (command.type === "transfer" && (command.action === "cold" || command.action === "warm"))
|
|
89
|
-
return command.dialId;
|
|
90
88
|
if (command.type === "conference" && command.action === "add")
|
|
91
89
|
return command.dialId;
|
|
92
90
|
return undefined;
|
|
@@ -95,6 +93,7 @@ export const BREAK_KINDS = [
|
|
|
95
93
|
"short-break", "meal", "rest", "training", "coaching",
|
|
96
94
|
"meeting", "administrative", "technical", "personal", "other",
|
|
97
95
|
];
|
|
96
|
+
export const SHIFT_EVENT_KINDS = ["signed-in", "signed-out", "break-started", "break-ended"];
|
|
98
97
|
export const OMNI_FAILURE_CODES = [
|
|
99
98
|
"omni.not-authenticated",
|
|
100
99
|
"omni.capability-not-enabled",
|
|
@@ -104,6 +103,8 @@ export const OMNI_FAILURE_CODES = [
|
|
|
104
103
|
"omni.rate-limited",
|
|
105
104
|
"omni.unavailable",
|
|
106
105
|
"omni.break-already-committed",
|
|
106
|
+
/** A recording command the provider could not settle either way: no start, stop, pause or resume it can vouch for. */
|
|
107
|
+
"omni.recording-unsettled",
|
|
107
108
|
];
|
|
108
109
|
/**
|
|
109
110
|
* Preserves the adapter's inferred concrete type while checking it implements `Adapter`.
|
package/dist/testing.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { ProtocolConformanceError, assertNoViolations, type ProtocolViolation }
|
|
|
7
7
|
* rules -- each optional part of a task, each optional part of the break state and team member list, each
|
|
8
8
|
* declared contribution, and each event type.
|
|
9
9
|
*/
|
|
10
|
-
declare const STATE_SUBJECTS: readonly ["tasks", "task.browsers", "task.attributes", "task.history", "task.onCall", "task.leadAssist", "task.takenOver", "task.audio", "task.acceptance", "task.outcomes", "task.destinations", "task.custom", "task.locked", "break.reasons", "break.forced", "team.members", "team.
|
|
10
|
+
declare const STATE_SUBJECTS: readonly ["tasks", "task.browsers", "task.attributes", "task.history", "task.onCall", "task.leadAssist", "task.takenOver", "task.audio", "task.acceptance", "task.outcomes", "task.destinations", "task.custom", "task.locked", "break.reasons", "break.forced", "team.members", "team.request", "team.tasks", "team.listening", "team.shift", "contacts", "calendar", "team.policies"];
|
|
11
11
|
export type ContractSubject = (typeof STATE_SUBJECTS)[number] | `event.${ProviderEvent["type"]}`;
|
|
12
12
|
export interface AdapterContractResult {
|
|
13
13
|
events: ProviderEventEnvelope[];
|
|
@@ -149,6 +149,8 @@ export declare class TaskStream {
|
|
|
149
149
|
private readonly tasks;
|
|
150
150
|
private readonly assignments;
|
|
151
151
|
private readonly endedAssignments;
|
|
152
|
+
/** Every assignment a `task-offered` introduced, as against one a snapshot carried: each is owed its ending. */
|
|
153
|
+
private readonly offered;
|
|
152
154
|
private readonly dials;
|
|
153
155
|
/** The host placed a dial: its outcome, whenever it arrives, is one the stream expects. */
|
|
154
156
|
dialled(dialId: string): void;
|
|
@@ -160,6 +162,8 @@ export declare class TaskStream {
|
|
|
160
162
|
private notOpen;
|
|
161
163
|
/** How many tasks the stream currently holds open. */
|
|
162
164
|
openCount(): number;
|
|
165
|
+
/** The assignments an offer introduced that are still open: each was owed a `task-ended` that has not come. */
|
|
166
|
+
unended(): string[];
|
|
163
167
|
/** Whether an offered task is a dial arriving -- the host's own call, a connect-back -- which counts against no capacity: an entry on its call carrying a dial. */
|
|
164
168
|
static carriesDial(task: unknown): boolean;
|
|
165
169
|
/**
|
|
@@ -188,6 +192,20 @@ export declare class TaskStream {
|
|
|
188
192
|
apply(envelope: unknown, path?: string): ProtocolViolation[];
|
|
189
193
|
}
|
|
190
194
|
/** What a stream has said about the agent's break, and the moves it may not make. */
|
|
195
|
+
/**
|
|
196
|
+
* The team as the events left it: whole on `team-updated` and on any snapshot carrying one, then
|
|
197
|
+
* one member at a time. A member event before the whole team, or a removal of a member the team
|
|
198
|
+
* never carried, is a change to a team the lead was never given.
|
|
199
|
+
*/
|
|
200
|
+
export declare class TeamStream {
|
|
201
|
+
private members;
|
|
202
|
+
private static ids;
|
|
203
|
+
/** A snapshot carrying a team is the team whole; one carrying none leaves the lead with none. */
|
|
204
|
+
seed(snapshot: unknown): void;
|
|
205
|
+
/** Whether the team currently carries this member, as the events left it. */
|
|
206
|
+
has(id: string): boolean;
|
|
207
|
+
apply(envelope: unknown, path?: string): ProtocolViolation[];
|
|
208
|
+
}
|
|
191
209
|
export declare class BreakStream {
|
|
192
210
|
private state;
|
|
193
211
|
private recovery;
|