@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 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
- }, cursor);
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
- if (latestTask().completionMode === "agent-command" && latestTask().phase === "completing") {
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). The drive stops where the task offers
4342
- no way on and says nothing about what it could not reach. It is off by default because it issues
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xema/omni-protocol",
3
- "version": "0.1.53",
3
+ "version": "0.1.54",
4
4
  "description": "The Omni protocol: the contract every provider adapter implements",
5
5
  "type": "module",
6
6
  "license": "MIT",