@xema/omni-protocol 0.1.99 → 0.1.100

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
@@ -106,7 +106,7 @@ export type DialOutcome = "answered" | "busy" | "no-answer" | "unreachable" | "r
106
106
  export declare const DIAL_OUTCOMES: readonly ["answered", "busy", "no-answer", "unreachable", "rejected", "cancelled", "unexplained"];
107
107
  /**
108
108
  * How the agent hears the call: on a `softphone`, where the host owns the audio and opens it
109
- * through `openMedia`, or on a `deskPhone`, a handset the platform rings, where the host opens
109
+ * through `openAudio`, or on a `deskPhone`, a handset the platform rings, where the host opens
110
110
  * nothing and only shows the call. A voice manifest lists the phones its platform supports, and
111
111
  * the host picks one for the login at authentication.
112
112
  */
@@ -433,7 +433,7 @@ export interface RecordingActions {
433
433
  export interface TaskRecordingPolicy {
434
434
  provider?: RecordingActions;
435
435
  host?: RecordingActions & {
436
- destinationId: string;
436
+ storageId: string;
437
437
  };
438
438
  }
439
439
  /** Current evidence only. Expiry/disconnect means unknown, never a historical stop. */
@@ -478,7 +478,7 @@ export interface HostRecording {
478
478
  announcesToCaller?: true;
479
479
  actions: RecordingAction[];
480
480
  /** Explicitly provisioned destinations. A task chooses one; no upload/storage fallback. */
481
- destinationIds: string[];
481
+ storageIds: string[];
482
482
  execute(request: HostRecordingRequest): Promise<RecordingCommandResult>;
483
483
  }
484
484
  /** Recording applies or fails; it never dials. Rejection without result means unknown. */
@@ -729,9 +729,9 @@ export type TaskPhase =
729
729
  /** What the system does when a preview's deadline passes with no Call pressed. */
730
730
  export type PreviewDeadline =
731
731
  /** Provider initiates dialing when preparation ends; never a host timer command. */
732
- "calls"
732
+ "provider-dials"
733
733
  /** Host initiates the ordinary call command when preparation ends. */
734
- | "host-calls"
734
+ | "host-dials"
735
735
  /** Preparation target has elapsed; remain in preview until the agent presses Call. */
736
736
  | "waits";
737
737
  /** Who ends the task: the agent issuing `complete`, or the provider deciding it is over. */
@@ -917,12 +917,12 @@ export interface Locked {
917
917
  */
918
918
  export type Lockable<T> = T | Locked;
919
919
  /**
920
- * Who chose a task's capabilities. `undetermined` is a fault the provider states on the task rather
920
+ * Who chose a task's capabilities. `not-yet-read` is a fault the provider states on the task rather
921
921
  * than hides: the platform's terms could not be read, and the set published is what the provider
922
922
  * will honour, not what the platform permits.
923
923
  */
924
- export type CapabilitySource = "queue" | "ungoverned" | "undetermined";
925
- export declare const CAPABILITY_SOURCES: readonly ["queue", "ungoverned", "undetermined"];
924
+ export type CapabilitySource = "queue" | "nobody" | "not-yet-read";
925
+ export declare const CAPABILITY_SOURCES: readonly ["queue", "nobody", "not-yet-read"];
926
926
  export type Task<C extends Channel = Channel> = {
927
927
  /** The assignment this task is the record of, and its one identity. See `AssignmentId`. */
928
928
  assignmentId: AssignmentId;
@@ -933,8 +933,8 @@ export type Task<C extends Channel = Channel> = {
933
933
  capabilities: TaskCapabilities<C>;
934
934
  /**
935
935
  * Where the capabilities came from before the provider put them on the task, so a host can tell
936
- * a fact from a fault: `queue` when somebody chose these terms, `ungoverned` when nothing handed
937
- * the work over, `undetermined` when a queue was named and its terms could not be read -- the
936
+ * a fact from a fault: `queue` when somebody chose these terms, `nobody` when nothing handed
937
+ * the work over, `not-yet-read` when a queue was named and its terms could not be read -- the
938
938
  * provider then publishes what it will honour and says so here, where the controls are drawn.
939
939
  */
940
940
  capabilitySource: CapabilitySource;
@@ -953,7 +953,7 @@ export type Task<C extends Channel = Channel> = {
953
953
  acceptance?: AcceptanceMode;
954
954
  /**
955
955
  * In `preview` only, and together: the preparation target and behavior when it elapses,
956
- * and who acts then -- `calls` makes the provider initiate dialing, `host-calls` makes the
956
+ * and who acts then -- `provider-dials` makes the provider initiate dialing, `host-dials` makes the
957
957
  * host issue Call, and `waits` keeps waiting for the agent without dialing or ending the task.
958
958
  * Absent, the agent has as long as they need, without a preparation countdown.
959
959
  */
@@ -970,13 +970,13 @@ export type Task<C extends Channel = Channel> = {
970
970
  onCall?: OnCall[];
971
971
  leadAssist?: TaskLeadAssist;
972
972
  takenOver?: TaskTakenOver;
973
- media?: TaskMediaState;
973
+ audio?: TaskAudioState;
974
974
  } : {
975
975
  recording?: never;
976
976
  onCall?: never;
977
977
  leadAssist?: never;
978
978
  takenOver?: never;
979
- media?: never;
979
+ audio?: never;
980
980
  });
981
981
  /**
982
982
  * What the provider wants of Omni's acceptance policy for one offer. On routed work, present only
@@ -1014,7 +1014,7 @@ export type TaskOutcome = {
1014
1014
  failure: ProtocolFailure;
1015
1015
  };
1016
1016
  export declare const TASK_COMMAND_NAMES: {
1017
- readonly voice: readonly ["answer", "decline", "call", "hold", "resume", "end-call", "terminate-call", "connect-back", "transfer", "lead-assist", "conference", "recording", "complete"];
1017
+ readonly voice: readonly ["answer", "decline", "dial", "hold", "resume", "end-call", "terminate-call", "connect-back", "transfer", "lead-assist", "conference", "recording", "complete"];
1018
1018
  readonly chat: readonly ["accept", "decline", "pause", "resume", "complete"];
1019
1019
  readonly email: readonly ["accept", "decline", "complete"];
1020
1020
  };
@@ -1030,7 +1030,7 @@ export type VoiceTaskCommand = {
1030
1030
  }
1031
1031
  /** In `preview`: place the call to the party whose record the agent has read. A dial, gated by the phase alone. */
1032
1032
  | {
1033
- type: "call";
1033
+ type: "dial";
1034
1034
  dialId: DialId;
1035
1035
  } | {
1036
1036
  type: "hold";
@@ -1256,8 +1256,8 @@ export type BreakEndResult = {
1256
1256
  status: "failed";
1257
1257
  failure: ProtocolFailure;
1258
1258
  };
1259
- /** `reserved`: signed in here, and the host holds this agent's capacity for another provider (`count: 0`, host-stopped); not receiving this provider's work. */
1260
- export type TeamMemberAvailability = "ready" | "on-task" | "on-break" | "reserved" | "signed-out";
1259
+ /** `elsewhere`: signed in here, and the host holds this agent's capacity for another provider (`count: 0`, host-stopped); not receiving this provider's work. */
1260
+ export type TeamMemberAvailability = "ready" | "on-task" | "on-break" | "elsewhere" | "signed-out";
1261
1261
  export interface TeamMember {
1262
1262
  id: UserId;
1263
1263
  availability: TeamMemberAvailability;
@@ -1302,12 +1302,12 @@ export type MemberTask<C extends Channel = Channel> = {
1302
1302
  onCall?: OnCall[];
1303
1303
  leadAssist?: TaskLeadAssist;
1304
1304
  takenOver?: TaskTakenOver;
1305
- media?: TaskMediaState;
1305
+ audio?: TaskAudioState;
1306
1306
  } : {
1307
1307
  onCall?: never;
1308
1308
  leadAssist?: never;
1309
1309
  takenOver?: never;
1310
- media?: never;
1310
+ audio?: never;
1311
1311
  });
1312
1312
  /** The lead on this member's call, in the mode they are heard, since when. */
1313
1313
  export interface MemberListening {
@@ -1425,20 +1425,20 @@ export type TeamCommandResult = {
1425
1425
  * `ended` once primary interaction's audio ended, and the field omitted while none should be. The
1426
1426
  * provider's word -- a desk attaches and renders audio from it, never from its own senses.
1427
1427
  */
1428
- export type TaskMediaState = "started" | "ended";
1429
- export interface VoiceMediaSession {
1428
+ export type TaskAudioState = "started" | "ended";
1429
+ export interface CallAudio {
1430
1430
  remoteAudio: MediaStream;
1431
1431
  setMuted(muted: boolean): void;
1432
1432
  close(): void;
1433
1433
  }
1434
- export interface OpenMediaRequest {
1434
+ export interface OpenAudioRequest {
1435
1435
  assignmentId: AssignmentId;
1436
1436
  /** The agent's microphone as Omni captured it, `HostReport.audio.input.localAudio`; absent while that input is `unavailable`. */
1437
1437
  localAudio?: MediaStream;
1438
1438
  }
1439
- export type OpenMediaResult = {
1439
+ export type OpenAudioResult = {
1440
1440
  status: "opened";
1441
- session: VoiceMediaSession;
1441
+ audio: CallAudio;
1442
1442
  } | {
1443
1443
  status: "unavailable";
1444
1444
  failure: ProtocolFailure;
@@ -1530,7 +1530,7 @@ export interface Snapshot<C extends Channel = Channel> {
1530
1530
  /** The provider's own count of those tasks, stated rather than inferred: it must equal `tasks.length`, so a blank or unanswered state can never pass as a confirmed empty. */
1531
1531
  taskCount: number;
1532
1532
  contacts?: Contact[];
1533
- scheduledActivities?: ScheduledActivity[];
1533
+ calendar?: ScheduledActivity[];
1534
1534
  team?: TeamMembers;
1535
1535
  }
1536
1536
  /**
@@ -1540,7 +1540,7 @@ export interface Snapshot<C extends Channel = Channel> {
1540
1540
  * tasks against it and needs no new signal when one ends. The agent is one person on several
1541
1541
  * providers, and the host divides their capacity among them: `0` is host-stopped -- the agent's
1542
1542
  * capacity is elsewhere for now, this provider assigns nothing and shows the member as
1543
- * `reserved` -- and is not a break, which is the agent not working at all. The host restates a
1543
+ * `elsewhere` -- and is not a break, which is the agent not working at all. The host restates a
1544
1544
  * count of one or more when this provider has the agent's capacity again.
1545
1545
  */
1546
1546
  export interface AgentCapacity {
@@ -1583,23 +1583,23 @@ export type ProviderEvent<C extends Channel = Channel> = {
1583
1583
  type: "task-updated";
1584
1584
  task: Task<C>;
1585
1585
  } | {
1586
- type: "task-media-started";
1586
+ type: "task-audio-started";
1587
1587
  assignmentId: AssignmentId;
1588
1588
  } | {
1589
- type: "task-media-ended";
1589
+ type: "task-audio-ended";
1590
1590
  assignmentId: AssignmentId;
1591
1591
  }
1592
1592
  /**
1593
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 media on the member's assignment as it does for a
1594
+ * attach: on a softphone the application opens audio on the member's assignment as it does for a
1595
1595
  * task. Voice, to a login that declares `lead`, never to the member.
1596
1596
  */
1597
1597
  | {
1598
- type: "team-media-started";
1598
+ type: "team-audio-started";
1599
1599
  memberId: UserId;
1600
1600
  assignmentId: AssignmentId;
1601
1601
  } | {
1602
- type: "team-media-ended";
1602
+ type: "team-audio-ended";
1603
1603
  memberId: UserId;
1604
1604
  assignmentId: AssignmentId;
1605
1605
  } | {
@@ -1643,7 +1643,7 @@ export type ProviderEvent<C extends Channel = Channel> = {
1643
1643
  contacts: Contact[];
1644
1644
  } | {
1645
1645
  type: "calendar-updated";
1646
- scheduledActivities: ScheduledActivity[];
1646
+ calendar: ScheduledActivity[];
1647
1647
  };
1648
1648
  /**
1649
1649
  * The `Provider` prefix survives here for a mechanical reason rather than a naming one: `Event`
@@ -1718,7 +1718,7 @@ export interface Connection<C extends Channel = Channel> {
1718
1718
  /** Required when the login declares `capabilities.lead`: every lead act, on the team surface and nowhere else. */
1719
1719
  executeTeam?(request: TeamCommandRequest): Promise<TeamCommandResult>;
1720
1720
  /** Required of a voice adapter whose manifest lists `softphone`: on one, the call's audio lands in Omni. */
1721
- openMedia?(request: OpenMediaRequest): Promise<OpenMediaResult>;
1721
+ openAudio?(request: OpenAudioRequest): Promise<OpenAudioResult>;
1722
1722
  /** Required when the login declares `capabilities.preferences`: the person's own choice, kept by the provider and republished as `authenticated`. */
1723
1723
  setPreference?(request: SetPreferenceRequest): Promise<PreferenceResult>;
1724
1724
  /** Records an interaction leg the host performed. Required of a softphone login's connection: the host mutes its microphone on any call, and the record is the provider's. */
package/dist/index.js CHANGED
@@ -71,19 +71,19 @@ export const DEFAULT_LEVELS = [
71
71
  export function effectiveLevels(declared) {
72
72
  return [...(declared ?? DEFAULT_LEVELS)];
73
73
  }
74
- export const CAPABILITY_SOURCES = ["queue", "ungoverned", "undetermined"];
74
+ export const CAPABILITY_SOURCES = ["queue", "nobody", "not-yet-read"];
75
75
  // ---------------------------------------------------------------------------
76
76
  // Task commands.
77
77
  // ---------------------------------------------------------------------------
78
78
  export const TASK_COMMAND_NAMES = {
79
- voice: ["answer", "decline", "call", "hold", "resume", "end-call", "terminate-call",
79
+ voice: ["answer", "decline", "dial", "hold", "resume", "end-call", "terminate-call",
80
80
  "connect-back", "transfer", "lead-assist", "conference", "recording", "complete"],
81
81
  chat: ["accept", "decline", "pause", "resume", "complete"],
82
82
  email: ["accept", "decline", "complete"],
83
83
  };
84
84
  /** The dial a command places, by the host's identity for it; `undefined` for a command that dials nothing. */
85
85
  export function commandDialId(command) {
86
- if (command.type === "connect-back" || command.type === "call")
86
+ if (command.type === "connect-back" || command.type === "dial")
87
87
  return command.dialId;
88
88
  if (command.type === "transfer" && (command.action === "cold" || command.action === "warm"))
89
89
  return command.dialId;
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.media", "task.acceptance", "task.outcomes", "task.destinations", "task.custom", "task.locked", "break.reasons", "break.forced", "team.members", "team.requests", "team.tasks", "team.listening", "contacts", "scheduledActivities", "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.requests", "team.tasks", "team.listening", "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[];
@@ -41,7 +41,7 @@ export interface ExerciseAdapterOptions {
41
41
  collectOnly?: boolean;
42
42
  /**
43
43
  * Drive one ordinary lifecycle on the first task the provider offers -- accept it, open its
44
- * media on a softphone, hold and resume where offered, end the call where offered, complete it
44
+ * audio on a softphone, hold and resume where offered, end the call where offered, complete it
45
45
  * where the agent completes -- so the rules about a live call are reached rather than listed
46
46
  * under `notExercised`. Off by default, since it issues commands against whatever platform the
47
47
  * adapter is connected to: turn it on against a test backend.
@@ -177,9 +177,9 @@ export declare class TaskStream {
177
177
  * Takes a resync snapshot -- a `snapshot` event, or the read a reloaded client makes -- as the
178
178
  * state now, and first holds it to what the stream knew. A snapshot replaces state; it does not
179
179
  * get to forget it. A task it carries that the stream already held may not go backwards, lose an
180
- * entry of its record, return to undetermined terms, or be at work without the audio the stream
181
- * held up: media ends on task-media-ended and the call moves on, so a task still in-progress or
182
- * paused without its media is a snapshot that lost state, not a call that ended.
180
+ * entry of its record, return to not-yet-read terms, or be at work without the audio the stream
181
+ * held up: audio ends on task-audio-ended and the call moves on, so a task still in-progress or
182
+ * paused without its audio is a snapshot that lost state, not a call that ended.
183
183
  */
184
184
  resync(snapshot: unknown, at: string): ProtocolViolation[];
185
185
  /** Replaces what is known with a snapshot's tasks, as a snapshot replaces Omni's state. */
@@ -205,12 +205,12 @@ export declare class BreakStream {
205
205
  */
206
206
  export declare function assertBreakFollowsItsRequests(envelopes: readonly ProviderEventEnvelope[], snapshot?: Snapshot): void;
207
207
  /**
208
- * The media follows the task and never decides it. Given a provider's stream -- optionally seeded
209
- * with the snapshot it began from -- every task is introduced once, `task-media-started` and
210
- * `task-media-ended` alternate on work that has begun, media ends only where it arrived, and what
211
- * follows the media ending is `completing` or `task-ended`.
208
+ * The audio follows the task and never decides it. Given a provider's stream -- optionally seeded
209
+ * with the snapshot it began from -- every task is introduced once, `task-audio-started` and
210
+ * `task-audio-ended` alternate on work that has begun, audio ends only where it arrived, and what
211
+ * follows the audio ending is `completing` or `task-ended`.
212
212
  */
213
- export declare function assertMediaFollowsTheTask(envelopes: readonly ProviderEventEnvelope[], snapshot?: Snapshot): void;
213
+ export declare function assertAudioFollowsTheTask(envelopes: readonly ProviderEventEnvelope[], snapshot?: Snapshot): void;
214
214
  /** A login store that lives in memory for the test: what most adapter tests hand `exerciseAdapter` as `context.store`. */
215
215
  export declare function memoryStore(): LoginStore;
216
216
  /**
@@ -252,14 +252,14 @@ export interface BreakOnTaskStep {
252
252
  */
253
253
  export declare function assertBreakBeginsAfterTask(steps: readonly BreakOnTaskStep[]): void;
254
254
  /**
255
- * Validates the deadline derived from media end and the task's fixed wrap allowance.
255
+ * Validates the deadline derived from audio end and the task's fixed wrap allowance.
256
256
  *
257
257
  * A task with no allowance has no deadline, so `observedDeadline` must then be `undefined`: a
258
258
  * host counting down what the provider left open is the violation, and so is a host counting
259
259
  * nothing down when the provider set a clock. `toleranceMs` absorbs scheduler jitter in a real
260
260
  * implementation; pass 0 to demand an exact match.
261
261
  */
262
- export declare function assertWrapTimeout(task: Pick<TaskCompletion, "completionMode" | "wrapAllowance">, mediaEndedAt: string, observedDeadline: string | undefined, toleranceMs?: number): void;
262
+ export declare function assertWrapTimeout(task: Pick<TaskCompletion, "completionMode" | "wrapAllowance">, audioEndedAt: string, observedDeadline: string | undefined, toleranceMs?: number): void;
263
263
  /** One browser in one task of one provider. `providerId` is `Manifest.id`, never `displayName`. */
264
264
  export type BrowserIsolationScenario = BrowserSessionKeyInput;
265
265
  /** Validates whether two task-browser definitions should share one browser session. */