@xema/omni-protocol 0.1.36 → 0.1.37
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/testing.js +21 -4
- package/guide.md +3 -1
- package/package.json +1 -1
package/dist/testing.js
CHANGED
|
@@ -619,7 +619,7 @@ export class TaskStream {
|
|
|
619
619
|
tasks = new Map();
|
|
620
620
|
// Every dial the stream can place an outcome against: one the host said it placed, or one a
|
|
621
621
|
// task carried on `onCall` or in its record -- which is how a dial made before a transfer is known
|
|
622
|
-
// to whoever holds the task now. `ended` once its outcome arrived, since
|
|
622
|
+
// to whoever holds the task now. `answered` or `ended` once its outcome arrived, since it comes once.
|
|
623
623
|
dials = new Map();
|
|
624
624
|
/** The host placed a dial: its outcome, whenever it arrives, is one the stream expects. */
|
|
625
625
|
dialled(dialId) {
|
|
@@ -640,7 +640,16 @@ export class TaskStream {
|
|
|
640
640
|
}
|
|
641
641
|
static stated(task) {
|
|
642
642
|
const media = isRecord(task) && (task.media === "started" || task.media === "ended") ? task.media : "none";
|
|
643
|
-
|
|
643
|
+
// The stage of every dialled entry the room names by its dial, so an update can be held to the
|
|
644
|
+
// outcome that moves it.
|
|
645
|
+
const stages = new Map();
|
|
646
|
+
if (isRecord(task) && Array.isArray(task.onCall)) {
|
|
647
|
+
for (const entry of task.onCall) {
|
|
648
|
+
if (isRecord(entry) && typeof entry.dialId === "string" && typeof entry.stage === "string")
|
|
649
|
+
stages.set(entry.dialId, entry.stage);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return { phase: String(isRecord(task) ? task.phase : undefined), media, stages };
|
|
644
653
|
}
|
|
645
654
|
/** Replaces what is known with a snapshot's tasks, as a snapshot replaces Omni's state. */
|
|
646
655
|
seed(snapshot) {
|
|
@@ -696,6 +705,14 @@ export class TaskStream {
|
|
|
696
705
|
if (known.media !== next.media && !(known.media === "ended" && next.media === "none")) {
|
|
697
706
|
refuse("stream.taskUpdated.media", `${at}.task.media`, `a task-updated re-states media, it does not move it: ${id} held ${known.media} and the update says ${next.media}; audio arrives on task-media-started and ends on task-media-ended`);
|
|
698
707
|
}
|
|
708
|
+
// The same pairing for a dialled entry: the dial-outcome is the transition, the stage is
|
|
709
|
+
// the state, and the outcome comes first. An update that joins an entry on its own is
|
|
710
|
+
// moving what only an answered outcome moves.
|
|
711
|
+
for (const [dialId, stage] of next.stages) {
|
|
712
|
+
if (stage === "joined" && known.stages.get(dialId) === "ringing" && this.dials.get(dialId) !== "answered") {
|
|
713
|
+
refuse("stream.taskUpdated.stage", `${at}.task.onCall`, `a task-updated re-states a stage, it does not move it: ${dialId} was ringing and the update says joined before any answered dial-outcome for it`);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
699
716
|
this.tasks.set(id, next);
|
|
700
717
|
}
|
|
701
718
|
this.noteDials(event.task);
|
|
@@ -746,10 +763,10 @@ export class TaskStream {
|
|
|
746
763
|
if (dial === undefined) {
|
|
747
764
|
refuse("stream.dialOutcome.unknown", `${at}.dialId`, `${event.dialId} is not a dial the host placed or a task carried: an outcome ends a dial somebody made`);
|
|
748
765
|
}
|
|
749
|
-
else if (dial
|
|
766
|
+
else if (dial !== "placed") {
|
|
750
767
|
refuse("stream.dialOutcome.duplicate", `${at}.dialId`, `${event.dialId} already has its outcome; a dial ends once`);
|
|
751
768
|
}
|
|
752
|
-
this.dials.set(event.dialId, "ended");
|
|
769
|
+
this.dials.set(event.dialId, event.outcome === "answered" ? "answered" : "ended");
|
|
753
770
|
break;
|
|
754
771
|
}
|
|
755
772
|
default:
|
package/guide.md
CHANGED
|
@@ -2859,7 +2859,9 @@ still-ringing `destination` calls that dial off, with `cancelled` as its outcome
|
|
|
2859
2859
|
**The entry says where it stands.** A dialled entry carries `stage`: `ringing` until its dial is
|
|
2860
2860
|
answered, `joined` after. The `dial-outcome` is the transition and the stage is the state, the same
|
|
2861
2861
|
pairing as `task-media-started` and `media`: an `answered` outcome and the task restated with the
|
|
2862
|
-
entry `joined` say one thing twice, and any other outcome removes the entry.
|
|
2862
|
+
entry `joined` say one thing twice, and any other outcome removes the entry. The outcome comes
|
|
2863
|
+
first: a `task-updated` that itself moves an entry from `ringing` to `joined` before an `answered`
|
|
2864
|
+
outcome for its dial is refused (`stream.taskUpdated.stage`), as an update that moves `media` is. It is stated rather
|
|
2863
2865
|
than left to whoever placed the dial because that knowledge lives in one process: after a reload,
|
|
2864
2866
|
on a second session, or on a supervisor's screen the snapshot is the only source, and a room that
|
|
2865
2867
|
cannot tell ringing from joined says it contains someone who may never arrive. Nobody ringing is
|