@xema/omni-protocol 0.1.125 → 0.1.126

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 CHANGED
@@ -1836,7 +1836,7 @@ export type ProviderEvent<C extends Channel = Channel> = {
1836
1836
  type: "transport-status";
1837
1837
  status: "error";
1838
1838
  recovery: TransportRecovery;
1839
- message?: string;
1839
+ message: string;
1840
1840
  } | {
1841
1841
  type: "break-state";
1842
1842
  break: BreakState;
@@ -2070,7 +2070,12 @@ export function validateEventEnvelope(envelope, manifest, path = "event", contex
2070
2070
  else {
2071
2071
  into.require(event.recovery === undefined, "event.transportStatus.recovery.unexpected", `${at}.recovery`, "recovery goes with an error; nothing needs reviving here");
2072
2072
  }
2073
- if (event.message !== undefined) {
2073
+ if (event.status === "error") {
2074
+ if (into.require(event.message !== undefined, "event.transportStatus.message.required", `${at}.message`, "an error says why, in words the agent sees")) {
2075
+ into.filled(event.message, "event.transportStatus.message", `${at}.message`, "a message must not be empty");
2076
+ }
2077
+ }
2078
+ else if (event.message !== undefined) {
2074
2079
  into.filled(event.message, "event.transportStatus.message", `${at}.message`, "a message must not be empty when present");
2075
2080
  }
2076
2081
  break;
package/guide.md CHANGED
@@ -1215,7 +1215,7 @@ type TransportRecovery = "reconnect" | "reauthenticate" | "displaced";
1215
1215
  type ProviderEvent =
1216
1216
  | { type: "snapshot"; reason: "reconnected" | "provider-requested"; snapshot: Snapshot }
1217
1217
  | { type: "transport-status"; status: "connecting" | "active"; message?: string }
1218
- | { type: "transport-status"; status: "error"; recovery: TransportRecovery; message?: string }
1218
+ | { type: "transport-status"; status: "error"; recovery: TransportRecovery; message: string }
1219
1219
  | { type: "break-state"; break: BreakState }
1220
1220
  | {
1221
1221
  type: "task-offered";
@@ -2075,7 +2075,7 @@ reports later changes.
2075
2075
  | `authenticated` | A usable session exists. Includes the provider identity, the login's `capabilities`, and optional token expiry time. |
2076
2076
  | `refreshing` | The adapter is refreshing its session. Existing provider identity and capabilities remain available, unchanged: a change to either is published as `authenticated`. |
2077
2077
  | `expired` | The session's time ran out, or its refresh is failing. It may include an identity and typed failure. The agent signs in again on the same login, and the workspace stays. |
2078
- | `terminated` | The session was ended from outside this agent computer: by a supervisor, by the agent on another screen, or by the platform itself. `by` says who, a person by `UserId` or `provider` where no person was behind it (`authentication.terminated.by`), and `failure` says why and is never retryable (`authentication.terminated.failure`, `.retryable`). It is never reported as `expired`, which would hide who ended it, nor as `signed-out`, which is the agent's own act. |
2078
+ | `terminated` | The session was ended from outside this agent computer: by a supervisor, by the agent on another screen, or by the platform itself. `by` says who, a person by `UserId` or `provider` where no person was behind it (`authentication.terminated.by`), and `failure` says why and is never retryable (`authentication.terminated.failure`, `.retryable`). It is never reported as `expired`, which would hide who ended it, nor as `signed-out`, which is the agent's own act. The session's ending is the whole message: the agent application disposes the connection with `disconnect()` and shows `failure.message` on the sign-in, and the adapter reports no transport `error` beside it -- `reauthenticate` would say this session is restored, and it is not. |
2079
2079
 
2080
2080
  Omni calls `connect()` only after authentication reaches `authenticated`. Token refresh remains
2081
2081
  adapter-owned; the adapter publishes `refreshing`, followed by `authenticated` or `expired`.
@@ -2095,6 +2095,14 @@ calls `connect()` afresh, as for `reconnect` -- see **`transport-status`**. What
2095
2095
  replaces the login" describes is a new `AuthenticationSession` under a new `loginId`, after
2096
2096
  `signed-out`.
2097
2097
 
2098
+ **A sign-in the platform no longer allows is ended, not restored.** A role changed mid-shift can
2099
+ take away what the login was built on -- an agent made a supervisor may no longer have a phone, and
2100
+ the platform refuses to renew the softphone. Retrying cannot help and the same session cannot carry
2101
+ on, so the adapter deletes the secrets and publishes `terminated`, `by: "provider"`, with a failure
2102
+ in the agent's words: `{ code: "phone-not-allowed", message: "Your sign-in no longer allows a phone.
2103
+ Sign in again.", retryable: false }`. The agent application disposes the connection and shows that
2104
+ message on the sign-in.
2105
+
2098
2106
  ### What the login may do
2099
2107
 
2100
2108
  `capabilities` declares provider actions available to this login rather than to one task: whether
@@ -2242,6 +2250,9 @@ short bound the adapter states, and then given up: a provider that cannot be rea
2242
2250
  token on the agent's machine. If it was not told, `signOut()` still deletes and still reaches
2243
2251
  `signed-out`, and answers `failed`, so the agent application can show that a session may remain at
2244
2252
  the provider. `close()` stops authentication-state observation but does not sign the agent out.
2253
+ The agent application ends the connection itself, with `disconnect()`: the sign-out is its own act,
2254
+ so the adapter reports no transport `error` for it, and a connection closed by the platform as the
2255
+ sign-out lands is not news to anyone.
2245
2256
 
2246
2257
  **The final moments are the agent application's to finish.** Its own steps before signing out --
2247
2258
  stopping capacity, putting tasks down -- may be retried within a short bound it states, and then
@@ -2687,7 +2698,7 @@ safe for the agent to see.
2687
2698
  | --- | --- |
2688
2699
  | `connecting` | No usable transport right now, and the adapter expects to recover on its own. Nobody needs to act. Startup and every reconnect pass through this value. |
2689
2700
  | `active` | The transport is up and the provider is serving this session. It is the only value under which work arrives. |
2690
- | `error` | The adapter cannot serve the session and is not simply mid-reconnect. Say why in `message`, and say what revives it in `recovery` — required here, forbidden on any other status. It is not terminal: an adapter that recovers on its own still reports `connecting` and then `active`, and one that cannot is revived as `recovery` says. |
2701
+ | `error` | The adapter cannot serve the session and is not simply mid-reconnect. Say why in `message` (`event.transportStatus.message.required`), and say what revives it in `recovery` — both required here, and `recovery` forbidden on any other status. It is not terminal: an adapter that recovers on its own still reports `connecting` and then `active`, and one that cannot is revived as `recovery` says. |
2691
2702
 
2692
2703
  **An error names its recovery, and the agent application acts on that word.** The adapter knows why its session
2693
2704
  died; the agent application knows how to run a login. `recovery` joins the two:
@@ -2697,7 +2708,10 @@ died; the agent application knows how to run a login. `recovery` joins the two:
2697
2708
  `connect()` again on the same login — same `loginId` — and the fresh connect snapshot
2698
2709
  re-establishes state exactly as a reconnect snapshot does. `connect()` is once per
2699
2710
  `Connection`, not once per login.
2700
- - **`reauthenticate`** — the session under the login died: a token rejected, a remote logout. Omni
2711
+ - **`reauthenticate`** — the session under the login lapsed and the same login can be restored: a
2712
+ token rejected, published as `expired`. A session ended from outside -- a remote logout, a
2713
+ permission withdrawn -- is `terminated`, which is the whole message and gets no transport `error`
2714
+ beside it (see **Authentication state**). Omni
2701
2715
  runs the authentication flow first, on the same session and `loginId`, never through
2702
2716
  `signed-out`; the authentication session decides whether stored material refreshes it silently or
2703
2717
  the agent must act, exactly as at sign-in. Once the state returns to `authenticated`, Omni
@@ -2740,7 +2754,10 @@ adapter that leaves a stale `active` in place is telling Omni to keep waiting fo
2740
2754
  come — see **Liveness**.
2741
2755
 
2742
2756
  **The status is seen, not merely known.** An agent application renders the transport's status where the agent
2743
- works — `connecting` from the moment it is reported, `error` with what revives it — and never a
2757
+ works — `connecting` from the moment it is reported, `error` with what revives it — and shows the
2758
+ provider's `message` as written, never a generic "disconnected" in its place: the provider knows why,
2759
+ and the words are what tell the agent whether to wait, sign in again or call somebody. The same holds
2760
+ for the `failure.message` of an `expired` or `terminated` session. Never a
2744
2761
  healthy workspace over a transport that cannot serve it: an agent talking on an agent computer whose transport
2745
2762
  died was an incident, and it happened because the agent computer knew and did not say. The same obligation
2746
2763
  covers a `diagnostic`: shown where the agent works, and counted.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xema/omni-protocol",
3
- "version": "0.1.125",
3
+ "version": "0.1.126",
4
4
  "description": "The Omni protocol: the contract every provider adapter implements",
5
5
  "type": "module",
6
6
  "license": "MIT",