@xema/omni-protocol 0.1.42 → 0.1.43

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/README.md CHANGED
@@ -97,17 +97,16 @@ const task = {
97
97
  };
98
98
  ```
99
99
 
100
- **The blind transfer arm is `action?: never`.** Switch on `command.action` with `case undefined`
101
- for it, never a `default`: a `default` turns a future action into a silent blind transfer, and
102
- switching on `command.action ?? "blind"` loses the narrowing that lets you read `destination`
103
- without a cast. Dropping an arm then fails the build — indirectly, as a missing return.
100
+ **Switch on `command.action` with no `default`.** A `default` turns a future action into whatever
101
+ the default does, silently; naming every arm means dropping one fails the build — indirectly, as a
102
+ missing return — and keeps the narrowing that lets you read `destination` without a cast.
104
103
 
105
104
  ```ts
106
105
  switch (command.action) {
107
- case undefined: return blindTransfer(command.destination);
108
- case "consult": return consultTransfer(command.destination);
109
- case "complete": return completeConsultation();
110
- case "cancel": return cancelConsultation();
106
+ case "cold": return coldTransfer(command.destination);
107
+ case "warm": return warmTransfer(command.destination);
108
+ case "complete": return completeWarmTransfer();
109
+ case "cancel": return cancelWarmTransfer();
111
110
  }
112
111
  ```
113
112
 
package/dist/index.d.ts CHANGED
@@ -451,9 +451,9 @@ export type TaskCapabilities<C extends Channel = Channel> = C extends "voice" ?
451
451
  agentDisconnect?: Lockable<true>;
452
452
  /** Connect back to the party while `completing`, whoever placed the call; the task returns to `in-progress`. */
453
453
  connectBack?: Lockable<true>;
454
- blindTransfer?: Lockable<true | DestinationDirectory>;
454
+ coldTransfer?: Lockable<true | DestinationDirectory>;
455
455
  /** Park the customer and call a destination first; then `complete` or `cancel`. */
456
- consultTransfer?: Lockable<true | DestinationDirectory>;
456
+ warmTransfer?: Lockable<true | DestinationDirectory>;
457
457
  /** Ask a lead to join this call, with a note. The lead's decision arrives on `Task.leadAssist`. */
458
458
  leadAssist?: Lockable<true>;
459
459
  conference?: Lockable<true | DestinationDirectory>;
@@ -787,17 +787,17 @@ export type VoiceTaskCommand = {
787
787
  type: "connect-back";
788
788
  dialId: DialId;
789
789
  }
790
- /** Blind: hand the customer to `destination` with nobody consulted. Gated by `blindTransfer`. */
790
+ /** Cold: hand the customer to `destination` with nobody spoken to first. Gated by `coldTransfer`. */
791
791
  | {
792
792
  type: "transfer";
793
+ action: "cold";
793
794
  dialId: DialId;
794
795
  destination: string;
795
- action?: never;
796
796
  }
797
- /** Park the customer and call `destination` first. Gated by `consultTransfer`. */
797
+ /** Warm: park the customer and call `destination` first. Gated by `warmTransfer`. */
798
798
  | {
799
799
  type: "transfer";
800
- action: "consult";
800
+ action: "warm";
801
801
  dialId: DialId;
802
802
  destination: string;
803
803
  }
package/dist/index.js CHANGED
@@ -80,7 +80,7 @@ export const TASK_COMMAND_NAMES = {
80
80
  export function commandDialId(command) {
81
81
  if (command.type === "connect-back")
82
82
  return command.dialId;
83
- if (command.type === "transfer" && (command.action === undefined || command.action === "consult"))
83
+ if (command.type === "transfer" && (command.action === "cold" || command.action === "warm"))
84
84
  return command.dialId;
85
85
  if (command.type === "conference" && command.action === "add")
86
86
  return command.dialId;
package/dist/testing.js CHANGED
@@ -70,7 +70,7 @@ function observeTask(value, seen) {
70
70
  const capabilities = isRecord(value.capabilities) ? value.capabilities : {};
71
71
  if (isRecord(capabilities.dispositions))
72
72
  seen.add("task.dispositions");
73
- for (const directory of ["blindTransfer", "consultTransfer", "conference"]) {
73
+ for (const directory of ["coldTransfer", "warmTransfer", "conference"]) {
74
74
  const declared = capabilities[directory];
75
75
  if (isRecord(declared) && some(declared.destinations))
76
76
  seen.add("task.destinations");
@@ -73,7 +73,7 @@ const EXPLAINED_FAILURES = ["busy", "no-answer", "unreachable", "rejected", "can
73
73
  const ON_CALL_ROLES = membersOf({ party: true, agent: true, consulted: true, conferenced: true });
74
74
  const ON_CALL_STAGES = membersOf({ ringing: true, joined: true });
75
75
  /** The task capabilities under which a command dials, and so need the manifest to say how a dial ends. */
76
- const DIALLING_CAPABILITIES = ["connectBack", "blindTransfer", "consultTransfer", "conference"];
76
+ const DIALLING_CAPABILITIES = ["connectBack", "coldTransfer", "warmTransfer", "conference"];
77
77
  const SNAPSHOT_REASONS = membersOf({
78
78
  reconnected: true, "provider-requested": true,
79
79
  });
@@ -95,7 +95,7 @@ const ISOLATION_SCHEME_VALUES = Object.values(BROWSER_ISOLATION_SCHEMES);
95
95
  const TASK_CAPABILITIES = {
96
96
  voice: membersOf({
97
97
  browsers: true, dispositions: true, custom: true, decline: true, mute: true, hold: true,
98
- agentDisconnect: true, connectBack: true, blindTransfer: true, consultTransfer: true, leadAssist: true, conference: true, recording: true,
98
+ agentDisconnect: true, connectBack: true, coldTransfer: true, warmTransfer: true, leadAssist: true, conference: true, recording: true,
99
99
  }),
100
100
  chat: membersOf({ browsers: true, dispositions: true, custom: true, decline: true, hold: true }),
101
101
  email: membersOf({ browsers: true, dispositions: true, custom: true, decline: true }),
@@ -948,8 +948,8 @@ function validateTaskInto(task, context, path, into) {
948
948
  case "custom":
949
949
  validateCustomCapabilities(declared, `${path}.capabilities.custom`, into);
950
950
  break;
951
- case "blindTransfer":
952
- case "consultTransfer":
951
+ case "coldTransfer":
952
+ case "warmTransfer":
953
953
  case "conference":
954
954
  validateDestinationDirectory(declared, `${path}.capabilities.${name}`, into);
955
955
  break;
package/guide.md CHANGED
@@ -35,7 +35,7 @@ are used precisely throughout and mean nothing looser here.
35
35
  | **Event** | One completed transaction reported after a snapshot established the baseline. |
36
36
  | **Break** | A reported, supervised state in which the agent is not working — one with a reason, a decision behind it and a return. It covers what a platform may call *not-ready*, including equipment trouble. An agent who is merely at capacity is not on a break. |
37
37
  | **Workspace** | What Omni shows the agent. The **task workspace** holds the selected task, its controls and its browsers; the **idle workspace** holds what a provider contributes when no task is selected — dialpad, contacts, calendar, roster. |
38
- | **Dial** | One outbound call the host asks a provider to place — from the idle dialpad, a transfer, a conference add, or a connect-back. Identified by the host's `dialId`, accepted as `dialling`, and ended by exactly one `dial-outcome`. See **Every dial has an outcome**. |
38
+ | **Dial** | One outbound call the host asks a provider to place — from the idle dialpad, a cold or warm transfer, a conference add, or a connect-back. Identified by the host's `dialId`, accepted as `dialling`, and ended by exactly one `dial-outcome`. See **Every dial has an outcome**. |
39
39
  | **Monitor** | A lead listening to a member's call unasked, from the roster: `monitor` in silence, `whisper` heard by the agent alone, `barge` heard by everyone. Nothing of it reaches the member's task, and there is no take-over in it. See **Monitoring a call**. |
40
40
  | **On the call** | Who a voice task's audio joins, or is bringing in, as the provider states it on `Task.onCall`: the party, the agents, and anyone consulted or conferenced in from the moment their dial is placed. |
41
41
 
@@ -481,8 +481,8 @@ type TaskCapabilities<C extends Channel = Channel> =
481
481
  hold?: Lockable<true>;
482
482
  agentDisconnect?: Lockable<true>;
483
483
  connectBack?: Lockable<true>;
484
- blindTransfer?: Lockable<true | DestinationDirectory>;
485
- consultTransfer?: Lockable<true | DestinationDirectory>;
484
+ coldTransfer?: Lockable<true | DestinationDirectory>;
485
+ warmTransfer?: Lockable<true | DestinationDirectory>;
486
486
  leadAssist?: Lockable<true>;
487
487
  conference?: Lockable<true | DestinationDirectory>;
488
488
  recording?: Lockable<true>;
@@ -707,8 +707,8 @@ type VoiceTaskCommand =
707
707
  | { type: "resume" }
708
708
  | { type: "disconnect" }
709
709
  | { type: "connect-back"; dialId: DialId }
710
- | { type: "transfer"; dialId: DialId; destination: string; action?: never }
711
- | { type: "transfer"; action: "consult"; dialId: DialId; destination: string }
710
+ | { type: "transfer"; action: "cold"; dialId: DialId; destination: string }
711
+ | { type: "transfer"; action: "warm"; dialId: DialId; destination: string }
712
712
  | { type: "transfer"; action: "complete" }
713
713
  | { type: "transfer"; action: "cancel" }
714
714
  | { type: "lead-assist"; action: "request"; note?: string }
@@ -2198,9 +2198,9 @@ The canonical task transitions are:
2198
2198
  | `pending` | Provider withdraws the allocation | Removed by `task-ended` with `cancelled` outcome |
2199
2199
  | No task | Snapshot reports work already underway | `in-progress` |
2200
2200
  | `in-progress` | Provider or agent pauses the task | `paused` |
2201
- | `in-progress` | Agent consults a transfer destination (`transfer` `consult`); the customer is parked | `paused` |
2201
+ | `in-progress` | Agent starts a warm transfer (`transfer` `warm`); the customer is parked | `paused` |
2202
2202
  | `paused` | Provider or agent resumes the task | `in-progress` |
2203
- | `paused` | Agent cancels a consultation (`transfer` `cancel`) | `in-progress` |
2203
+ | `paused` | Agent cancels a warm transfer (`transfer` `cancel`) | `in-progress` |
2204
2204
  | `in-progress` or `paused` | Contact handling ends and follow-up work remains | `completing` |
2205
2205
  | `completing` | Agent connects back to the party (`connect-back`) | `in-progress` |
2206
2206
  | Any phase | Provider emits `task-ended` | Removed |
@@ -2591,8 +2591,8 @@ const taskCapabilities = {
2591
2591
  | `hold` | Primary toggle: Hold | Omni may issue voice-task `hold` and `resume` commands. |
2592
2592
  | `agentDisconnect` | Primary button: Disconnect | Omni may disconnect real-time media without disposing the task. |
2593
2593
  | `connectBack` | Completing-task button: Connect back | Omni may have the provider connect the agent back to the task's party while the task is `completing`, returning it to `in-progress` on the same task. Not offered where there is no `completing` window: `provider-automatic` with a zero allowance disposes at provider end. See **Connecting back during completion**. |
2594
- | `blindTransfer` | Secondary menu item: Blind transfer | Omni may transfer the caller directly to a destination. |
2595
- | `consultTransfer` | Secondary menu item: Consult transfer | Omni may park the customer and call a destination first, then hand the customer over or cancel back. See **Consult transfer**. |
2594
+ | `coldTransfer` | Secondary menu item: Cold transfer | Omni may hand the customer straight to a destination, with nobody spoken to first. |
2595
+ | `warmTransfer` | Secondary menu item: Warm transfer | Omni may park the customer and call a destination first, then hand the customer over or cancel back. See **Warm transfer**. |
2596
2596
  | `leadAssist` | Secondary menu item: Lead assist | Omni may ask a lead to join this call, with a note. The lead's decision reaches the agent on `Task.leadAssist`. See **Lead assist**. |
2597
2597
  | `conference` | Secondary button: Conference | Omni may dial a destination into the active call, and drop a `conferenced` entry from it -- one still ringing included, which calls the dial off. |
2598
2598
  | `recording` | Overflow menu item: Recording | Omni may expose start, pause, resume, and stop recording controls. |
@@ -2627,11 +2627,11 @@ capabilities: {
2627
2627
  With `dispositions: true` Omni shows a Complete control and sends `complete` with no code, because
2628
2628
  the provider published none.
2629
2629
 
2630
- #### `blindTransfer`, `consultTransfer` and `conference`
2630
+ #### `coldTransfer`, `warmTransfer` and `conference`
2631
2631
 
2632
2632
  ```ts
2633
2633
  capabilities: {
2634
- blindTransfer: {
2634
+ coldTransfer: {
2635
2635
  allowManualEntry: false,
2636
2636
  destinations: [
2637
2637
  { id: "tier2", label: "Tier 2 support", address: "+14155550111", kind: "queue" },
@@ -2659,18 +2659,19 @@ A destination the agent types is not in the directory and has no `kind`. Omni tr
2659
2659
  `external` unless the provider says otherwise in its response, because that is the assumption that
2660
2660
  does not overstate what the provider can still see.
2661
2661
 
2662
- #### Consult transfer
2662
+ #### Warm transfer
2663
2663
 
2664
- A consult transfer parks the customer, calls the destination so the agent can speak to it first,
2665
- and then either hands the customer over or returns to them. It is its own capability, distinct
2666
- from `blindTransfer` (a hand-over with nobody consulted) and from `conference` (everybody on one
2667
- call): a queue may offer any of the three without the others, and each is declared on its own.
2664
+ A warm transfer parks the customer, calls the destination so the agent can speak to it first, and
2665
+ then either hands the customer over or returns to them. Cold and warm are the words agents use;
2666
+ telephony says blind and consult. It is its own capability, distinct from `coldTransfer` (a
2667
+ hand-over with nobody spoken to first) and from `conference` (everybody on one call): a queue may
2668
+ offer any of the three without the others, and each is declared on its own.
2668
2669
 
2669
2670
  ```ts
2670
- // 1. Consult. A dial: the provider parks the customer and calls the destination, answers
2671
+ // 1. Warm. A dial: the provider parks the customer and calls the destination, answers
2671
2672
  // `dialling`, and the task reports `paused` with the destination `consulted` on `onCall`
2672
2673
  // while the call to it stands.
2673
- { type: "transfer", action: "consult", dialId: "dial-7f2", destination: "+14155550111" }
2674
+ { type: "transfer", action: "warm", dialId: "dial-7f2", destination: "+14155550111" }
2674
2675
 
2675
2676
  // 2a. Hand the customer to the consulted destination and leave.
2676
2677
  { type: "transfer", action: "complete" }
@@ -2679,7 +2680,7 @@ call): a queue may offer any of the three without the others, and each is declar
2679
2680
  { type: "transfer", action: "cancel" }
2680
2681
  ```
2681
2682
 
2682
- `consult` is gated by the `consultTransfer` capability and takes a destination exactly as a blind
2683
+ `warm` is gated by the `warmTransfer` capability and takes a destination exactly as a cold
2683
2684
  transfer does, from the same kind of directory. It is a dial, so it carries the host's `dialId`
2684
2685
  and is answered `dialling`, and its `dial-outcome` says whether the destination was reached. While
2685
2686
  the destination is on the line the task carries a `consulted` entry on `onCall`, and that presence
@@ -2687,7 +2688,7 @@ is what makes `complete` and `cancel` issuable -- they name no destination becau
2687
2688
  one they could mean, which is why a task carries at most one `consulted` entry
2688
2689
  (`task.onCall.consulted.single`). A consultation that could be started but not finished would
2689
2690
  strand the customer and the destination both, which is why all three are commands and a provider
2690
- that offers `consultTransfer` implements all three.
2691
+ that offers `warmTransfer` implements all three.
2691
2692
 
2692
2693
  `applied` on `complete` says the provider is bridging the customer to the destination and
2693
2694
  dropping the agent's leg. What follows is what follows any transfer: the agent's media ends and
@@ -2836,7 +2837,7 @@ call it belonged to and never against the next one.
2836
2837
  The stream knows a dial from three places: `TaskStream.dialled(dialId)`, which a host calls when it
2837
2838
  places one; an entry on a task's `onCall`; and a step in its `handlingHistory`. Since a dialled entry
2838
2839
  is listed from placement, `dialled()` is load-bearing only for a dial that never has an entry -- a
2839
- blind transfer, a connect-back, an idle dialpad call -- or whose entry has already left the room; an
2840
+ cold transfer, a connect-back, an idle dialpad call -- or whose entry has already left the room; an
2840
2841
  outcome for a dial nobody placed and no task mentions is what `stream.dialOutcome.unknown` refuses.
2841
2842
 
2842
2843
  **`answered` says what happened to the dial; `onCall` says who is in the room.** They are two
@@ -2855,7 +2856,7 @@ provider does report -- `busy`, `no-answer`, `unreachable`, `rejected` or `cance
2855
2856
  switch gave none, while one that reports none would be sending the generic failure this set exists
2856
2857
  to refuse. A provider that dials at all declares it: an idle
2857
2858
  dialpad requires it (`manifest.dialOutcomes.required`), and a task that declares `connectBack`,
2858
- `blindTransfer`, `consultTransfer` or `conference` under a manifest without it is refused
2859
+ `coldTransfer`, `warmTransfer` or `conference` under a manifest without it is refused
2859
2860
  (`task.capability.dialOutcomes.required`). Off voice nothing dials, and the field is a compile
2860
2861
  error there.
2861
2862
 
@@ -3709,7 +3710,7 @@ declared:
3709
3710
  | `start-call` | The `preparing` phase. It starts the contact a preview gave the agent time to read, so the phase is the gate and there is no capability. |
3710
3711
  | `complete` | `completionMode: "agent-command"`. The `dispositions` capability decides whether a code travels with the command, never whether the command exists — a task Omni cannot complete never ends. |
3711
3712
  | `connect-back` | The `connectBack` capability **and** the `completing` phase. It exists to reach the party again after the call, so it has no meaning while the call is up. |
3712
- | `transfer` with `action: "consult"` | The `consultTransfer` capability. Blind `transfer` is gated by `blindTransfer`; the two are declared and offered separately. |
3713
+ | `transfer` with `action: "warm"` | The `warmTransfer` capability. `action: "cold"` is gated by `coldTransfer`; the two are declared and offered separately. |
3713
3714
  | `transfer` with `action: "complete"` or `"cancel"` | A consultation in progress -- a `consulted` entry on `Task.onCall`. Without one there is nothing to complete or cancel, and a provider that receives either answers `failed`. |
3714
3715
  | `lead-assist` with `action: "request"` or `"cancel"` | The `leadAssist` capability. `cancel` needs a request standing -- `Task.leadAssist` with status `requested`. |
3715
3716
  | `lead-assist` with `action: "take-over"` or `"leave"` | The lead's own task, on a call they joined -- `Task.assisting` present. An agent's task never has it, and a provider that receives either without it answers `failed`. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xema/omni-protocol",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "description": "The Omni protocol: the contract every provider adapter implements",
5
5
  "type": "module",
6
6
  "license": "MIT",