@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 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 transfer, conference, or call back -- and forbidden off voice, where nothing dials.
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. A warm transfer's `complete` is not one: the agent's
184
- * wrap runs after it as after any call. `applied` says the provider
185
- * has completed the task; the ending follows within this, or the host resyncs and shows the
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. While the lead
255
- * has the feature on, a `TeamMembers` object is published to them on every snapshot, `members: []`
256
- * included; to nobody else, ever.
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 transfer or conference control offers. Nothing is typed; the agent picks one. */
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 transfer/takeover. Interaction completion remains separate. */
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
- coldTransfer?: Lockable<DestinationDirectory>;
662
- /** Park the customer and call a destination first; then `complete` or `cancel`. */
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 `previewEndsAt` arrives and `atDeadline` says what the system does instead.
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" | "consulted" | "conferenced";
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", "consulted", "conferenced"];
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; `consulted`
817
- * and `conferenced` someone a dial is bringing in -- listed from the moment the dial is placed, so
818
- * the agent can call it off while it rings -- carrying the dial when a host placed it, the address
819
- * either way, and the `stage` it has reached: `ringing` until the dial is answered, `joined` after,
820
- * stated so a snapshot says who is present without anyone having seen the outcome. Nobody ringing is
821
- * held. `label` names a destination -- a person, a queue -- not a phrase. At most one `party` and
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: "consulted" | "conferenced";
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 no capacity, provided their voice channel is free.
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 target and behavior when it elapses,
956
- * and who acts then -- `provider-dials` makes the provider initiate dialing, `host-dials` makes the
957
- * host issue Call, and `waits` keeps waiting for the agent without dialing or ending the task.
958
- * Absent, the agent has as long as they need, without a preparation countdown.
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
- previewEndsAt?: IsoTimestamp;
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 that lapses at `assignmentExpiresAt` names `pending`. */
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", "transfer", "lead-assist", "conference", "recording", "complete"];
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 channel. Gated by `terminateCall`. */
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
- /** Cold: hand the customer to the directory item `destinationId` with nobody spoken to first. Gated by `coldTransfer`. */
1054
- | {
1055
- type: "transfer";
1056
- action: "cold";
1057
- dialId: DialId;
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: "transfer";
1075
- action: "cancel";
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
- /** A break forced on the agent; the agent must explicitly resume when ready. */
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
- /** A member asking this lead to join their call, named by the member and the assignment. */
1274
- export interface LeadRequest {
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
- /** The lead on this member's call, in the mode they are heard, since when. */
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, on every snapshot, and to nobody else. The provider keeps it
1320
- * current: when a member holds, mutes or is transferred, the list is republished whole.
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
- assignmentExpiresAt?: IsoTimestamp;
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", "consulted", "conferenced"];
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", "transfer", "lead-assist", "conference", "recording", "complete"],
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.requests", "team.tasks", "team.listening", "contacts", "calendar", "team.policies"];
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;