@xema/omni-protocol 0.1.50 → 0.1.52
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/validation.js +16 -0
- package/guide.md +27 -1
- package/package.json +1 -1
package/dist/validation.js
CHANGED
|
@@ -956,6 +956,12 @@ function validateTaskInto(task, context, path, into) {
|
|
|
956
956
|
validateTaskAttributes(task.attributes, `${path}.attributes`, into);
|
|
957
957
|
validateHandlingHistory(task.handlingHistory, `${path}.handlingHistory`, into);
|
|
958
958
|
validateOnCall(task.onCall, context.channel, `${path}.onCall`, into);
|
|
959
|
+
// The room is who is on the call now, and a task outlives its call by the whole of wrap-up: a
|
|
960
|
+
// task whose call has ended -- completing, or media ended -- carries nobody, or the last thing the
|
|
961
|
+
// wire said about the call stays true for ever. Empty and absent both say nobody.
|
|
962
|
+
if (Array.isArray(task.onCall) && task.onCall.length > 0 && (task.phase === "completing" || task.media === "ended")) {
|
|
963
|
+
into.add("task.onCall.ended", `${path}.onCall`, `the call has ended (${task.phase === "completing" ? "the task is completing" : "its media ended"}) and onCall still names people on it: the room is who is on the call now, and now nobody is`);
|
|
964
|
+
}
|
|
959
965
|
validateTaskMedia(task.media, context.channel, `${path}.media`, into);
|
|
960
966
|
validateLeadAssist(task.leadAssist, context.channel, `${path}.leadAssist`, into);
|
|
961
967
|
validateAssisting(task.assisting, context.channel, `${path}.assisting`, into);
|
|
@@ -1796,6 +1802,16 @@ export function validateTaskCommand(command, task, path = "command") {
|
|
|
1796
1802
|
}
|
|
1797
1803
|
if (!isPlainObject(task))
|
|
1798
1804
|
return into.violations;
|
|
1805
|
+
// The task the command is held to has to be one the wire published. A host's own mapping of it,
|
|
1806
|
+
// handed in for want of the original, is not, and checking a command against it would be
|
|
1807
|
+
// checking against a task nobody has -- so the task is validated first, and a command is held
|
|
1808
|
+
// only to a task that stands.
|
|
1809
|
+
const published = new Collector();
|
|
1810
|
+
validateTaskInto(task, { channel: channel ?? "voice" }, `${path}.task`, published);
|
|
1811
|
+
if (published.violations.length > 0) {
|
|
1812
|
+
into.add("command.task", `${path}.task`, `the task the command is held to is not one the wire published (${published.violations.map(v => v.rule).join(", ")}): pass the task as the provider sent it, or validate the command's shape alone`);
|
|
1813
|
+
return into.violations;
|
|
1814
|
+
}
|
|
1799
1815
|
// What the task has to offer or be in for the command to be issuable.
|
|
1800
1816
|
const capabilities = isPlainObject(task.capabilities) ? task.capabilities : {};
|
|
1801
1817
|
const offered = (name) => {
|
package/guide.md
CHANGED
|
@@ -2994,6 +2994,26 @@ the platform added itself carries none. `held: true` is presence as claim. A sna
|
|
|
2994
2994
|
after a transfer reads the room from here rather than inferring it from a sequence of outcomes it
|
|
2995
2995
|
never saw.
|
|
2996
2996
|
|
|
2997
|
+
**`onCall` is who is on the call now, and a task outlives its call.** Wrap-up is not an ending:
|
|
2998
|
+
the task is alive, the agent is working, and nothing arrives to say the call ended until they
|
|
2999
|
+
dispose. So the room must not be the last word about a call that has ended. Once the call is over
|
|
3000
|
+
-- the task `completing`, or its `media` ended -- `onCall` is empty, or absent only where the
|
|
3001
|
+
provider never publishes the room at all, and a task carrying people on a call that has ended is
|
|
3002
|
+
refused (`task.onCall.ended`). Empty says nobody is on the call; absent says the provider does not
|
|
3003
|
+
say who is, which is a different claim, so a provider that publishes the room publishes one last
|
|
3004
|
+
change: the empty room.
|
|
3005
|
+
|
|
3006
|
+
**A field that describes the present is cleared by the transition that ends it.** `onCall`,
|
|
3007
|
+
`previewEndsAt` and `atDeadline` are three instances of one shape, and there will be more: each
|
|
3008
|
+
describes a state that is true now, and each is carried past the moment it stops being true by the
|
|
3009
|
+
most natural implementation there is, building the next task by spreading the last one. The
|
|
3010
|
+
provider's own state looks right, the claim on the wire is stale, and only the host sees it. An
|
|
3011
|
+
adapter that builds each transition from what is true after it, rather than from what was true
|
|
3012
|
+
before, needs none of these rules named. Two agents were
|
|
3013
|
+
once shown on calls for the better part of an hour while callers queued, because the last message
|
|
3014
|
+
describing the room live was never followed by one saying it had emptied, and every consumer that
|
|
3015
|
+
derived anything from it was wrong in a way that looked like its own bug.
|
|
3016
|
+
|
|
2997
3017
|
**A dialled entry is listed from the moment the dial is placed, not from the answer.** The entry is
|
|
2998
3018
|
what makes `transfer` `cancel` issuable and what `conference` `remove` names, and a destination the
|
|
2999
3019
|
agent cannot call off while it rings is a parked customer with no way back -- which is the very case
|
|
@@ -3887,7 +3907,13 @@ declared:
|
|
|
3887
3907
|
| Everything else | Its own named capability. |
|
|
3888
3908
|
|
|
3889
3909
|
`validateTaskCommand(command, task)` holds a command to this table at runtime, both ways: the
|
|
3890
|
-
capability it needs, the phase it belongs to, and the state that has to stand.
|
|
3910
|
+
capability it needs, the phase it belongs to, and the state that has to stand. The task it wants
|
|
3911
|
+
is the one the provider published, not a host's own mapping of it: a host that keeps only its
|
|
3912
|
+
mapped shape has nothing honest to pass, and then checks shape alone, which is still worth doing
|
|
3913
|
+
-- it names a command the wire never had -- but is not the table. Keeping the published task
|
|
3914
|
+
beside the mapped one is what the full check costs a host; an adapter has it for free. The
|
|
3915
|
+
validator holds a command only to a task that stands: a task handed in that is not one the wire
|
|
3916
|
+
published is named (`command.task`) rather than checked against.
|
|
3891
3917
|
|
|
3892
3918
|
Declining or rejecting a pending offer ends it without accepting or completing it. The provider
|
|
3893
3919
|
confirms the end with `task-ended` and a `cancelled` outcome.
|