@xema/omni-protocol 0.1.123 → 0.1.124
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 +14 -0
- package/dist/index.js +17 -0
- package/guide/agent.md +17 -8
- package/guide.md +15 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2095,6 +2095,20 @@ export declare const HISTORY_STEPS_WITH_A_PERSON: readonly ["offered", "answered
|
|
|
2095
2095
|
/** The steps a dial writes, and so the only ones that carry a `dialId` and a `destinationId`. */
|
|
2096
2096
|
export declare const HISTORY_STEPS_THAT_DIAL: readonly ["transferred", "conferenced", "unanswered"];
|
|
2097
2097
|
export declare const historyStepDials: (step: HistoryStep) => boolean;
|
|
2098
|
+
/**
|
|
2099
|
+
* Consecutive entries of one step, shown as one span. The record keeps an entry per occurrence --
|
|
2100
|
+
* two holds are counted as two -- and this is how the agent sees them: once, from the first
|
|
2101
|
+
* entry's `at`, lasting the sum of their `seconds` when every entry states one, and with no
|
|
2102
|
+
* duration when any does not, never a sum that silently leaves a running leg out.
|
|
2103
|
+
*/
|
|
2104
|
+
export interface HistorySpan {
|
|
2105
|
+
step: HistoryStep;
|
|
2106
|
+
at: IsoTimestamp;
|
|
2107
|
+
seconds?: DurationSeconds;
|
|
2108
|
+
entries: TaskHistoryStep[];
|
|
2109
|
+
}
|
|
2110
|
+
/** Groups a record's consecutive same-step entries into spans, oldest first. */
|
|
2111
|
+
export declare function historySpans(steps: readonly TaskHistoryStep[]): HistorySpan[];
|
|
2098
2112
|
/** Whether an absent `by` means "could not attribute" rather than "nobody was involved". */
|
|
2099
2113
|
export declare function historyStepExpectsAPerson(step: HistoryStep): boolean;
|
|
2100
2114
|
export interface BrowserSessionKeyInput {
|
package/dist/index.js
CHANGED
|
@@ -201,6 +201,23 @@ export const historyStepDials = (step) => HISTORY_STEPS_THAT_DIAL.includes(step)
|
|
|
201
201
|
// Pinned both ways: a step added to `HistoryStep` has to be placed here, and a step listed here
|
|
202
202
|
// has to exist there. `satisfies` on the list covers the second; this statement covers the first.
|
|
203
203
|
true;
|
|
204
|
+
/** Groups a record's consecutive same-step entries into spans, oldest first. */
|
|
205
|
+
export function historySpans(steps) {
|
|
206
|
+
const spans = [];
|
|
207
|
+
for (const entry of steps) {
|
|
208
|
+
const last = spans[spans.length - 1];
|
|
209
|
+
if (last !== undefined && last.step === entry.step)
|
|
210
|
+
last.entries.push(entry);
|
|
211
|
+
else
|
|
212
|
+
spans.push({ step: entry.step, at: entry.at, entries: [entry] });
|
|
213
|
+
}
|
|
214
|
+
for (const span of spans) {
|
|
215
|
+
if (span.entries.every(entry => entry.seconds !== undefined)) {
|
|
216
|
+
span.seconds = span.entries.reduce((total, entry) => total + entry.seconds, 0);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return spans;
|
|
220
|
+
}
|
|
204
221
|
/** Whether an absent `by` means "could not attribute" rather than "nobody was involved". */
|
|
205
222
|
export function historyStepExpectsAPerson(step) {
|
|
206
223
|
return HISTORY_STEPS_WITH_A_PERSON.includes(step);
|
package/guide/agent.md
CHANGED
|
@@ -443,13 +443,16 @@ arrive omits it rather than guessing an instant. Omni shows it as *Incoming call
|
|
|
443
443
|
Amazon Connect keeps an initiation time, Genesys Cloud a conversation start and NICE CXone a contact
|
|
444
444
|
start, separate from the queue.
|
|
445
445
|
|
|
446
|
-
**Time
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
446
|
+
**Time the platform handles the customer before a queue is `self-service`.** The caller pressing
|
|
447
|
+
through a menu, talking to a voice bot, hearing an announcement, or waiting while the platform
|
|
448
|
+
looks them up; a chat customer with a bot before a person takes over: one step for all of them, on
|
|
449
|
+
every channel. Genesys Cloud and NICE CXone report IVR and bot time as self-service; here it also
|
|
450
|
+
takes in the routing time Genesys Cloud keeps as a separate system segment, so a provider that
|
|
451
|
+
measures the gap before each queue without knowing what played in it reports it here rather than
|
|
452
|
+
nowhere. It is therefore not evidence that the customer used a menu. Nobody from the provider takes
|
|
453
|
+
part, so it has no `by`. `at` is when it began and `seconds`, once it ended, how long it lasted; a
|
|
454
|
+
customer routed again after a transfer has a second entry, one per visit, as a second queue is a
|
|
455
|
+
second `queued`. A customer that words it *IVR* for its agents does so in `labels.historySteps`.
|
|
453
456
|
|
|
454
457
|
**A callback carries the call it comes back to.** When a caller asks to be called back, or an agent
|
|
455
458
|
arranges it, the provider writes a `callback-requested` step: `by` names the agent who arranged it, and
|
|
@@ -483,7 +486,13 @@ provider closed it. One publisher of the closed leg, and no order between them t
|
|
|
483
486
|
hold, at the entry's `at` plus its `seconds`, and nothing is lost by not naming it twice. The same goes for every step: two mutes are two
|
|
484
487
|
`muted` entries, and a call that joined two queues -- a menu's, then this one -- has two `queued`
|
|
485
488
|
entries, one per join. Order is enforced: an entry earlier than the one before it is refused
|
|
486
|
-
(`task.history.order`).
|
|
489
|
+
(`task.history.order`).
|
|
490
|
+
|
|
491
|
+
**Shown as spans.** The record keeps one entry per occurrence, because leads count them — two holds
|
|
492
|
+
are two holds, the way Amazon Connect counts holds per contact, and two queues say which queue the
|
|
493
|
+
call waited in. The agent sees consecutive entries of one step as one span: `historySpans(steps)`
|
|
494
|
+
groups them, as Genesys Cloud keeps segments apart in its record and joins them in the agent's
|
|
495
|
+
timeline. A provider never merges entries to get that look. **Intervals between steps are the agent application's to subtract**, never a
|
|
487
496
|
total the provider adds: *time to offer*, from the call joining its queue to the agent's screen lighting
|
|
488
497
|
up, is the `offered` entry's `at` minus the last `queued` entry's, and the ring is outside it.
|
|
489
498
|
`queueSeconds` keeps the industry's meaning -- the whole wait until somebody answered -- and is not
|
package/guide.md
CHANGED
|
@@ -725,6 +725,13 @@ type TaskHistoryStep = {
|
|
|
725
725
|
mutedBy?: MutedBy;
|
|
726
726
|
};
|
|
727
727
|
|
|
728
|
+
type HistorySpan = {
|
|
729
|
+
step: HistoryStep;
|
|
730
|
+
at: IsoTimestamp;
|
|
731
|
+
seconds?: DurationSeconds;
|
|
732
|
+
entries: TaskHistoryStep[];
|
|
733
|
+
};
|
|
734
|
+
|
|
728
735
|
type TaskCompletion =
|
|
729
736
|
| { completionMode: "agent-command"; wrapAllowance?: DurationSeconds }
|
|
730
737
|
| { completionMode: "provider-automatic"; wrapAllowance: DurationSeconds };
|
|
@@ -2990,6 +2997,14 @@ Whether two logins declare the same capabilities, field by field — key order a
|
|
|
2990
2997
|
`team: {}` distinct from `team` absent. It is the comparison an adapter makes before republishing
|
|
2991
2998
|
`authenticated`, and the one `testAdapter` holds `refreshing` to.
|
|
2992
2999
|
|
|
3000
|
+
### `historySpans(steps)`
|
|
3001
|
+
|
|
3002
|
+
Groups a record's consecutive entries of one step into a `HistorySpan` each — `step`, the first
|
|
3003
|
+
entry's `at`, `seconds` summed when every entry states one and absent when any does not, and the
|
|
3004
|
+
`entries` themselves — so every agent application shows *Self-service · 30s* once where the
|
|
3005
|
+
record has two self-service entries in a row. Only neighbours are grouped: a hold, an answer and
|
|
3006
|
+
another hold are three spans. See **Shown as spans** in `guide/agent.md`.
|
|
3007
|
+
|
|
2993
3008
|
## Runtime validation
|
|
2994
3009
|
|
|
2995
3010
|
Structural rules in this document are executable through the runtime validators Omni applies to
|