@xema/omni-protocol 0.1.122 → 0.1.123

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/GLOSSARY.md CHANGED
@@ -100,7 +100,7 @@ hands only through routing or a lead's take-over.
100
100
 
101
101
  | Term | In plain words | What others call it |
102
102
  | --- | --- | --- |
103
- | **History** | The steps a call went through before and with this agent: arrived, queued, answered, held, handed over. | *Contact trace record* (Amazon Connect), *conversation details* or *segments* (Genesys Cloud), *call detail record*. |
103
+ | **History** | The steps a call went through before and with this agent: arrived, self-service, queued, answered, held, handed over. | *Contact trace record* (Amazon Connect), *conversation details* or *segments* (Genesys Cloud), *call detail record*. |
104
104
  | **Recording** | A recording of one side of the call, the customer's or the agent's. | *Call recording*, *screen and voice recording*. |
105
105
  | **Paused for sensitive details** | Recording stops while card or account details are given. | *Secure pause* (Genesys Cloud), *PCI pause*. |
106
106
 
package/dist/index.d.ts CHANGED
@@ -872,7 +872,7 @@ export type TaskAttribute = TaskAttributeBase & ({
872
872
  type: "timestamp";
873
873
  at: IsoTimestamp;
874
874
  });
875
- export type HistoryStep = "arrived" | "queued" | "offered" | "answered" | "held" | "muted" | "transferred" | "conferenced" | "unanswered" | "callback-requested";
875
+ export type HistoryStep = "arrived" | "self-service" | "queued" | "offered" | "answered" | "held" | "muted" | "transferred" | "conferenced" | "unanswered" | "callback-requested";
876
876
  /**
877
877
  * The call record: the steps that brought the task here, one entry per occurrence and oldest
878
878
  * first, and what they add up to before this agent -- stated by the provider from its own record,
@@ -907,7 +907,7 @@ export interface TaskHistoryStep {
907
907
  */
908
908
  seconds?: DurationSeconds;
909
909
  /**
910
- * Who took part. Absent on `arrived` and `queued`, where nobody does; absent on `callback-requested`, where the
910
+ * Who took part. Absent on `arrived`, `self-service` and `queued`, where nobody does; absent on `callback-requested`, where the
911
911
  * caller chose it in the queue, and present there when an agent arranged it; absent on any other
912
912
  * step means the provider could not attribute it, which is a different claim and a legitimate one.
913
913
  */
@@ -2053,6 +2053,7 @@ export declare const DEFAULT_TASK_TYPE_PRESENTATION: {
2053
2053
  };
2054
2054
  export declare const DEFAULT_HISTORY_STEP_LABELS: {
2055
2055
  readonly arrived: "Incoming call";
2056
+ readonly "self-service": "Self-service";
2056
2057
  readonly queued: "Queued";
2057
2058
  readonly offered: "Offered";
2058
2059
  readonly answered: "Answered";
@@ -2086,8 +2087,8 @@ export declare const assignmentKey: (providerId: string, assignmentId: Assignmen
2086
2087
  */
2087
2088
  export declare const userKey: (providerId: string, userId: UserId) => string;
2088
2089
  /**
2089
- * Every history step somebody from the provider takes part in. `arrived` and `queued` are the ones
2090
- * nobody does, and `callback-requested` is the caller's choice unless an agent arranged it, so none
2090
+ * Every history step somebody from the provider takes part in. `arrived`, `self-service` and
2091
+ * `queued` are the ones nobody does, and `callback-requested` is the caller's choice unless an agent arranged it, so none
2091
2092
  * of them is here.
2092
2093
  */
2093
2094
  export declare const HISTORY_STEPS_WITH_A_PERSON: readonly ["offered", "answered", "held", "muted", "transferred", "conferenced", "unanswered"];
package/dist/index.js CHANGED
@@ -146,7 +146,7 @@ export const DEFAULT_TASK_TYPE_PRESENTATION = {
146
146
  email: { singular: "Email", plural: "Emails", referenceLabel: "Email ID" },
147
147
  };
148
148
  export const DEFAULT_HISTORY_STEP_LABELS = {
149
- arrived: "Incoming call", queued: "Queued", offered: "Offered", answered: "Answered", held: "On hold",
149
+ arrived: "Incoming call", "self-service": "Self-service", queued: "Queued", offered: "Offered", answered: "Answered", held: "On hold",
150
150
  muted: "Muted", transferred: "Transferred", conferenced: "Conferenced", unanswered: "Unanswered",
151
151
  "callback-requested": "Callback requested",
152
152
  };
@@ -188,8 +188,8 @@ export const assignmentKey = (providerId, assignmentId) => `${encodeURIComponent
188
188
  */
189
189
  export const userKey = (providerId, userId) => `${encodeURIComponent(providerId)}:${encodeURIComponent(userId)}`;
190
190
  /**
191
- * Every history step somebody from the provider takes part in. `arrived` and `queued` are the ones
192
- * nobody does, and `callback-requested` is the caller's choice unless an agent arranged it, so none
191
+ * Every history step somebody from the provider takes part in. `arrived`, `self-service` and
192
+ * `queued` are the ones nobody does, and `callback-requested` is the caller's choice unless an agent arranged it, so none
193
193
  * of them is here.
194
194
  */
195
195
  export const HISTORY_STEPS_WITH_A_PERSON = [
@@ -58,7 +58,7 @@ const TEAM_AVAILABILITIES = membersOf({
58
58
  ready: true, "on-task": true, "on-break": true, elsewhere: true, "signed-out": true,
59
59
  });
60
60
  const HISTORY_STEPS = membersOf({
61
- arrived: true, queued: true, offered: true, answered: true, held: true, muted: true, transferred: true, conferenced: true, unanswered: true,
61
+ arrived: true, "self-service": true, queued: true, offered: true, answered: true, held: true, muted: true, transferred: true, conferenced: true, unanswered: true,
62
62
  "callback-requested": true,
63
63
  });
64
64
  const CUSTOM_UI_CONTROLS = membersOf({ button: true, toggle: true, "menu-item": true });
@@ -995,8 +995,8 @@ function validateHistory(value, path, into, task = {}) {
995
995
  }
996
996
  if (entry.by !== undefined) {
997
997
  into.require(isUserId(entry.by), "task.history.by", `${at}.by`, "by must be a non-empty user id; omit it when the person cannot be identified");
998
- // On `arrived` and `queued` nobody takes part, so there is nothing to name.
999
- into.require(entry.step !== "arrived" && entry.step !== "queued", "task.history.by.unexpected", `${at}.by`, `${describeValue(entry.step)} names nobody`);
998
+ // On `arrived`, `self-service` and `queued` nobody takes part, so there is nothing to name.
999
+ into.require(entry.step !== "arrived" && entry.step !== "self-service" && entry.step !== "queued", "task.history.by.unexpected", `${at}.by`, `${describeValue(entry.step)} names nobody`);
1000
1000
  }
1001
1001
  // A step that dialled says where to and, when a host placed it, which dial; no other step dialled.
1002
1002
  const dialled = typeof entry.step === "string" && HISTORY_STEPS_THAT_DIAL.includes(entry.step);
package/guide/agent.md CHANGED
@@ -409,7 +409,8 @@ first, and what they add up to before this agent:
409
409
  ```ts
410
410
  history: {
411
411
  steps: [
412
- { step: "arrived", at: "2026-08-21T00:58:40Z", seconds: 20 },
412
+ { step: "arrived", at: "2026-08-21T00:58:40Z", seconds: 2 },
413
+ { step: "self-service", at: "2026-08-21T00:58:42Z", seconds: 18 },
413
414
  { step: "queued", at: "2026-08-21T00:59:00Z", seconds: 41 },
414
415
  { step: "answered", at: "2026-08-21T00:59:41Z", seconds: 312, by: "a-17" },
415
416
  { step: "held", at: "2026-08-21T01:02:10Z", seconds: 35, by: "a-17" },
@@ -430,7 +431,7 @@ something else, which will arrive under its own name and must not be folded in h
430
431
 
431
432
  It rides in the snapshot and is replaced whole like everything else there.
432
433
 
433
- Steps are `arrived`, `queued`, `offered`, `answered`, `held`, `muted`, `transferred`, `conferenced`,
434
+ Steps are `arrived`, `self-service`, `queued`, `offered`, `answered`, `held`, `muted`, `transferred`, `conferenced`,
434
435
  `unanswered`, `callback-requested`, and each is defined on `TaskHistoryStep`.
435
436
 
436
437
  **The record starts where the call started.** `arrived` is the instant the call reached the
@@ -442,6 +443,14 @@ arrive omits it rather than guessing an instant. Omni shows it as *Incoming call
442
443
  Amazon Connect keeps an initiation time, Genesys Cloud a conversation start and NICE CXone a contact
443
444
  start, separate from the queue.
444
445
 
446
+ **Time with the IVR or a bot is `self-service`.** The caller pressing through a menu, talking to a
447
+ voice bot, or a chat customer with a bot before a person takes over: one step for all of them, on
448
+ every channel, the way Genesys Cloud and NICE CXone report IVR and bot time together as
449
+ self-service. Nobody from the provider takes part, so it has no `by`. `at` is when the customer
450
+ entered it and `seconds`, once it ended, how long they spent there; a customer sent back to a menu
451
+ after a transfer has a second entry, one per visit, as a second queue is a second `queued`. A
452
+ customer that words it *IVR* for its agents does so in `labels.historySteps`.
453
+
445
454
  **A callback carries the call it comes back to.** When a caller asks to be called back, or an agent
446
455
  arranges it, the provider writes a `callback-requested` step: `by` names the agent who arranged it, and
447
456
  is absent when the caller chose it in the queue. The callback reaches an agent as a new task, and that
@@ -551,7 +560,7 @@ Four rules a provider has to keep:
551
560
  wrongly; carrying the name here would also copy it into every task and leave it to go stale.
552
561
 
553
562
  **An absent `by` means different things on different steps, and both are legitimate.** On
554
- `arrived` and `queued` nobody takes part, so there is nothing to name. On every other step somebody did — see
563
+ `arrived`, `self-service` and `queued` nobody takes part, so there is nothing to name. On every other step somebody did — see
555
564
  `HISTORY_STEPS_WITH_A_PERSON` and `historyStepExpectsAPerson()` — so an absent `by` there says
556
565
  *this was handled and the provider cannot say by whom*. The one step that is never unattributed is
557
566
  `muted`: the agent application has exactly one agent and the provider knows who, so `by` is required there
@@ -564,7 +573,7 @@ worse than one saying plainly it could not attribute a leg — and far better th
564
573
  nothing because a single leg could not be named.
565
574
 
566
575
  An agent application must render the two differently. Showing an unattributed `answered` the same way as
567
- `queued` or `arrived` tells the agent nobody was involved, which is not what was said. Omni renders it as
576
+ `queued`, `self-service` or `arrived` tells the agent nobody was involved, which is not what was said. Omni renders it as
568
577
  *"not recorded"* in the place the name would go.
569
578
 
570
579
  Omit `history` entirely when the provider cannot observe the steps. Empty `steps` is a
package/guide.md CHANGED
@@ -696,6 +696,7 @@ type TaskAttribute = TaskAttributeBase & (
696
696
 
697
697
  type HistoryStep =
698
698
  | "arrived"
699
+ | "self-service"
699
700
  | "queued"
700
701
  | "offered"
701
702
  | "answered"
@@ -1362,7 +1363,7 @@ const OMNI_FAILURE_CODES = [
1362
1363
  type OmniFailureCode = (typeof OMNI_FAILURE_CODES)[number];
1363
1364
  ```
1364
1365
 
1365
- `HISTORY_STEPS_WITH_A_PERSON` is every `HistoryStep` except `arrived` and `queued`, which nobody
1366
+ `HISTORY_STEPS_WITH_A_PERSON` is every `HistoryStep` except `arrived`, `self-service` and `queued`, which nobody
1366
1367
  takes part in, and `callback-requested`, which the caller may choose alone. `historyStepExpectsAPerson()` tests membership.
1367
1368
 
1368
1369
  ### Failure and validation
@@ -1445,6 +1446,7 @@ agent's languages:
1445
1446
  ```ts
1446
1447
  const DEFAULT_HISTORY_STEP_LABELS = {
1447
1448
  arrived: "Incoming call",
1449
+ "self-service": "Self-service",
1448
1450
  queued: "Queued",
1449
1451
  offered: "Offered",
1450
1452
  answered: "Answered",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xema/omni-protocol",
3
- "version": "0.1.122",
3
+ "version": "0.1.123",
4
4
  "description": "The Omni protocol: the contract every provider adapter implements",
5
5
  "type": "module",
6
6
  "license": "MIT",