@xema/omni-protocol 0.1.53 → 0.1.54
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 +10 -3
- package/guide.md +11 -2
- package/package.json +1 -1
package/dist/testing.js
CHANGED
|
@@ -902,6 +902,10 @@ async function driveOneCall(drive) {
|
|
|
902
902
|
const declared = capabilities[name];
|
|
903
903
|
return declared !== undefined && !(isRecord(declared) && declared.lockedBy !== undefined);
|
|
904
904
|
};
|
|
905
|
+
// Media may arrive any time after the accept, before or after the task's own update says
|
|
906
|
+
// in-progress: the event is the provider's word that the audio should attach, never a reply to
|
|
907
|
+
// openMedia, so the drive looks for it from the accept rather than from the last update it read.
|
|
908
|
+
const acceptedAt = drive.events.length;
|
|
905
909
|
// 1. Accept the offer, if it is one.
|
|
906
910
|
if (latestTask().phase === "pending") {
|
|
907
911
|
if (await send({ type: drive.channel === "voice" ? "answer" : "accept" }) === undefined)
|
|
@@ -929,10 +933,10 @@ async function driveOneCall(drive) {
|
|
|
929
933
|
const started = await waitFor("task-media-started for the driven task", envelope => {
|
|
930
934
|
const event = envelope.event;
|
|
931
935
|
return event.type === "task-media-started" && event.taskId === taskId ? event : undefined;
|
|
932
|
-
},
|
|
936
|
+
}, acceptedAt);
|
|
933
937
|
if (started === undefined)
|
|
934
938
|
return found;
|
|
935
|
-
cursor = started.at;
|
|
939
|
+
cursor = Math.max(cursor, started.at);
|
|
936
940
|
}
|
|
937
941
|
const opened = await drive.connection.openMedia?.({ taskId, localAudio: drive.localAudio });
|
|
938
942
|
found.push(...validateResult(opened, "openMedia", "drive.openMedia"));
|
|
@@ -972,7 +976,10 @@ async function driveOneCall(drive) {
|
|
|
972
976
|
}
|
|
973
977
|
}
|
|
974
978
|
// 6. Complete, where the agent completes; otherwise the provider does, and the drive waits for it.
|
|
975
|
-
|
|
979
|
+
// A conversation has no media to end and no completing phase to wait for: a chat or an email,
|
|
980
|
+
// and a voice task offering no end-call, is completed from where it stands.
|
|
981
|
+
const completable = latestTask().phase === "completing" || latestTask().phase === "in-progress" || latestTask().phase === "paused";
|
|
982
|
+
if (latestTask().completionMode === "agent-command" && completable) {
|
|
976
983
|
const command = { type: "complete" };
|
|
977
984
|
const dispositions = isRecord(latestTask().capabilities) ? latestTask().capabilities.dispositions : undefined;
|
|
978
985
|
if (isRecord(dispositions) && dispositions.required === true && Array.isArray(dispositions.codes) && isRecord(dispositions.codes[0])) {
|
package/guide.md
CHANGED
|
@@ -4127,6 +4127,9 @@ partial patch.
|
|
|
4127
4127
|
The provider's word that the task's audio should now attach. Omni calls `openMedia` on it — and on
|
|
4128
4128
|
a task carried with `media: "started"`, which is how a reconnect snapshot reattaches audio an
|
|
4129
4129
|
earlier event brought — and renders the call as live from that word, never from its own senses. It
|
|
4130
|
+
precedes `openMedia` and is never a reply to it: a provider whose media state comes from the
|
|
4131
|
+
platform, a station going in use the moment a call is answered, sends it then, before any host has
|
|
4132
|
+
opened anything, and `openMedia` has its own answer for what the host did. It
|
|
4130
4133
|
names a task whose work has begun, and it alternates with `task-media-ended`: media that never
|
|
4131
4134
|
started cannot end, so a live call whose provider says nothing about its audio is a provider in
|
|
4132
4135
|
breach, not a state a desk fills in from its own devices.
|
|
@@ -4338,8 +4341,14 @@ complete it with a disposition where the agent completes -- and holds every step
|
|
|
4338
4341
|
host holds a provider to. Each command is validated against the task as published
|
|
4339
4342
|
(`drive.command.*`), each answer for its method, a refusal of a control the task offered is a
|
|
4340
4343
|
violation (`drive.command.failed`), and an event the provider owes and never sends is one too
|
|
4341
|
-
(`drive.timeout`, after `driveTimeoutMs`, 5000 by default).
|
|
4342
|
-
|
|
4344
|
+
(`drive.timeout`, after `driveTimeoutMs`, 5000 by default). A task the agent completes is
|
|
4345
|
+
completed from wherever it stands once the drive has nothing left to do on it -- from `completing`
|
|
4346
|
+
after an `end-call`, or from `in-progress` where there is no call to end, which is every chat and
|
|
4347
|
+
email and a voice task offering no `endCall` -- so a conversation reaches its end as a call does.
|
|
4348
|
+
The drive stops where the task offers no way on and says nothing about what it could not reach. A
|
|
4349
|
+
softphone adapter written for a browser needs its media APIs supplied by whatever runs the
|
|
4350
|
+
harness: the drive opens media outside a browser, and a provider that quietly stopped carrying audio
|
|
4351
|
+
where `AudioContext` was missing would be lying about the one thing the channel is for. It is off by default because it issues
|
|
4343
4352
|
commands against whatever platform the adapter is connected to: turn it on against a test backend.
|
|
4344
4353
|
|
|
4345
4354
|
```ts
|