@xema/omni-protocol 0.1.18 → 0.1.19

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.
Files changed (2) hide show
  1. package/guide.md +137 -3
  2. package/package.json +1 -1
package/guide.md CHANGED
@@ -279,6 +279,50 @@ type ConnectContext = {
279
279
  };
280
280
 
281
281
  type ConnectionStatus = "connecting" | "active" | "error";
282
+
283
+ type CredentialField = {
284
+ name: string;
285
+ label: string;
286
+ type: "text" | "password";
287
+ required?: boolean;
288
+ autocomplete?: string;
289
+ };
290
+
291
+ type AuthenticationChallenge =
292
+ | { flowId: string; method: "browser-sso"; authorizationUrl: string; browser: "system" | "omni" }
293
+ | { flowId: string; method: "credentials"; fields: CredentialField[] };
294
+
295
+ type StartAuthenticationRequest =
296
+ | { requestId: string; method: "browser-sso"; callbackUrl: string }
297
+ | { requestId: string; method: "credentials" };
298
+
299
+ type StartAuthenticationResult =
300
+ | { status: "interaction-required"; challenge: AuthenticationChallenge }
301
+ | { status: "rejected"; failure: AuthenticationFailure };
302
+
303
+ type CompleteAuthenticationRequest =
304
+ | { flowId: string; method: "browser-sso"; callbackUrl: string }
305
+ | { flowId: string; method: "credentials"; values: Readonly<Record<string, string>> };
306
+
307
+ type CompleteAuthenticationResult =
308
+ | { status: "authenticated"; identity: User; capabilities: SessionCapabilities; expiresAt?: IsoTimestamp }
309
+ | { status: "rejected"; failure: AuthenticationFailure };
310
+
311
+ type AuthenticationActionResult =
312
+ | { status: "accepted" }
313
+ | { status: "failed"; failure: AuthenticationFailure };
314
+
315
+ type Unsubscribe = () => void;
316
+
317
+ type AuthenticationSession = {
318
+ state(): AuthenticationState | Promise<AuthenticationState>;
319
+ subscribe(listener: (state: AuthenticationState) => void): Unsubscribe;
320
+ start(request: StartAuthenticationRequest): Promise<StartAuthenticationResult>;
321
+ complete(request: CompleteAuthenticationRequest): Promise<CompleteAuthenticationResult>;
322
+ cancelAuthentication(flowId: string): Promise<AuthenticationActionResult>;
323
+ signOut(): Promise<AuthenticationActionResult>;
324
+ close(): Promise<void>;
325
+ };
282
326
  ```
283
327
 
284
328
  ### Provider state
@@ -297,6 +341,10 @@ type Snapshot = {
297
341
  type AgentCapacity = {
298
342
  count: number; // absolute ceiling, at least 1
299
343
  };
344
+
345
+ type CapacityResult =
346
+ | { status: "accepted" }
347
+ | { status: "failed"; failure: ProtocolFailure };
300
348
  ```
301
349
 
302
350
  ### Idle contributions
@@ -317,6 +365,14 @@ type ScheduledActivity = {
317
365
  contact?: Contact;
318
366
  attributes?: Attribute[];
319
367
  };
368
+
369
+ type DialRequest = {
370
+ destination: string;
371
+ };
372
+
373
+ type DialResult =
374
+ | { status: "dialled" }
375
+ | { status: "failed"; failure: ProtocolFailure };
320
376
  ```
321
377
 
322
378
  ### Task capabilities
@@ -393,15 +449,24 @@ const BROWSER_ISOLATION_SCHEMES = {
393
449
  type BrowserIsolationScheme =
394
450
  (typeof BROWSER_ISOLATION_SCHEMES)[keyof typeof BROWSER_ISOLATION_SCHEMES];
395
451
 
396
- type TaskBrowser = {
452
+ type TaskBrowserBase = {
397
453
  id: string;
398
454
  name: string;
399
455
  purpose: string;
400
456
  url: string;
401
- } & (
457
+ };
458
+
459
+ type TaskBrowser = TaskBrowserBase & (
402
460
  | { reuse: false; isolationScheme?: never }
403
461
  | { reuse: true; isolationScheme: BrowserIsolationScheme }
404
462
  );
463
+
464
+ type BrowserSessionKeyInput = {
465
+ providerId: string;
466
+ taskId: TaskId;
467
+ taskType: string;
468
+ browser: TaskBrowser;
469
+ };
405
470
  ```
406
471
 
407
472
  That union is what makes a reusing browser with no scheme fail to compile rather than inherit a
@@ -574,6 +639,10 @@ type TaskCommandRequest<C extends Channel = Channel> = {
574
639
  taskId: TaskId;
575
640
  command: TaskCommand<C>;
576
641
  };
642
+
643
+ type TaskCommandResult =
644
+ | { status: "applied" }
645
+ | { status: "failed"; failure: ProtocolFailure };
577
646
  ```
578
647
 
579
648
  ### Breaks
@@ -613,6 +682,22 @@ type BreakState = {
613
682
  activeReasonId?: string;
614
683
  imposed?: ImposedBreak;
615
684
  };
685
+
686
+ type BreakRequestResult =
687
+ | { status: "requested" }
688
+ | { status: "failed"; failure: ProtocolFailure };
689
+
690
+ type BreakCommitResult =
691
+ | { status: "committed" }
692
+ | { status: "failed"; failure: ProtocolFailure };
693
+
694
+ type BreakCancelResult =
695
+ | { status: "cancelled" }
696
+ | { status: "failed"; failure: ProtocolFailure };
697
+
698
+ type BreakEndResult =
699
+ | { status: "ended" }
700
+ | { status: "failed"; failure: ProtocolFailure };
616
701
  ```
617
702
 
618
703
  ### Team
@@ -649,6 +734,18 @@ type TeamBreakCommand =
649
734
  | { type: "policy"; policy: "ask" | "auto-approve" | "suspended" }
650
735
  | { type: "place"; memberId: UserId; reason?: string }
651
736
  | { type: "release"; memberId: UserId };
737
+
738
+ type TeamBreakCommandRequest = {
739
+ command: TeamBreakCommand;
740
+ };
741
+
742
+ type TeamConsultCommandRequest = {
743
+ command: TeamConsultCommand;
744
+ };
745
+
746
+ type TeamCommandResult =
747
+ | { status: "applied" }
748
+ | { status: "failed"; failure: ProtocolFailure };
652
749
  ```
653
750
 
654
751
  ### Media
@@ -663,6 +760,11 @@ type VoiceMediaSession = {
663
760
  type OpenMediaResult =
664
761
  | { status: "opened"; session: VoiceMediaSession }
665
762
  | { status: "unavailable"; failure: ProtocolFailure };
763
+
764
+ type OpenMediaRequest = {
765
+ taskId: TaskId;
766
+ localAudio?: MediaStream;
767
+ };
666
768
  ```
667
769
 
668
770
  ### Events
@@ -710,12 +812,43 @@ type ProviderEventEnvelope = {
710
812
  reason rather than a naming one: `Event` is a DOM global, and a bare one would shadow it for every
711
813
  adapter compiled against the browser lib.
712
814
 
815
+ ### Adapter and connection
816
+
817
+ ```ts
818
+ type Connection<C extends Channel = Channel> = {
819
+ snapshot(): Snapshot<C> | Promise<Snapshot<C>>;
820
+ subscribe(listener: (envelope: ProviderEventEnvelope<C>) => void): Unsubscribe;
821
+ setCapacity(capacity: AgentCapacity): Promise<CapacityResult>;
822
+ execute(request: TaskCommandRequest<C>): Promise<TaskCommandResult>;
823
+ disconnect(): Promise<void>;
824
+
825
+ describeUsers?(ids: UserId[]): Promise<User[]>;
826
+ dial?(request: DialRequest): Promise<DialResult>;
827
+
828
+ requestBreak?(request: BreakRequest): Promise<BreakRequestResult>;
829
+ commitBreak?(): Promise<BreakCommitResult>;
830
+ cancelBreak?(): Promise<BreakCancelResult>;
831
+ endBreak?(): Promise<BreakEndResult>;
832
+
833
+ executeTeamBreak?(request: TeamBreakCommandRequest): Promise<TeamCommandResult>;
834
+ executeTeamConsult?(request: TeamConsultCommandRequest): Promise<TeamCommandResult>;
835
+ openMedia?(request: OpenMediaRequest): Promise<OpenMediaResult>;
836
+ };
837
+
838
+ type Adapter<C extends Channel = Channel> = {
839
+ manifest: Manifest<C>;
840
+ createAuthenticationSession(context: AuthenticationContext): Promise<AuthenticationSession> | AuthenticationSession;
841
+ connect(context: ConnectContext): Promise<Connection<C>>;
842
+ };
843
+ ```
844
+
713
845
  ### Published constants
714
846
 
715
847
  ```ts
716
848
  const ALLOWED_BROWSER_URL_SCHEMES = ["http:", "https:"] as const;
717
849
 
718
850
  const IDLE_CAPABILITIES = ["dial", "personalBrowser", "calendar", "contacts"] as const;
851
+ type IdleCapability = (typeof IDLE_CAPABILITIES)[number];
719
852
 
720
853
  const IDLE_CAPABILITY_UI = {
721
854
  dial: "Dialpad",
@@ -758,6 +891,7 @@ const OMNI_FAILURE_CODES = [
758
891
  "omni.unavailable",
759
892
  "omni.break-already-committed",
760
893
  ] as const;
894
+ type OmniFailureCode = (typeof OMNI_FAILURE_CODES)[number];
761
895
  ```
762
896
 
763
897
  `HANDLING_STEPS_WITH_A_PERSON` is every `HandlingStep` except `queued`, which is the one nobody
@@ -2863,7 +2997,7 @@ what failed, and reports. It never decides for the adapter what a missing microp
2863
2997
  | --- | --- |
2864
2998
  | `online` | Whether the host has a network interface up. Not a claim that anything is reachable — the adapter knows whether it can reach its own platform far better than the host does — so `false` is a reason not to go ready and `true` is not a reason to. |
2865
2999
  | `audio` | Present on a voice connection, absent where there is no audio. |
2866
- | `audio.input` | `ready` with `localAudio` — the microphone as captured, the same stream `openMedia` receives — and `flowing`, false while the hardware or OS says no audio moves through it (a headset's own mute switch, which Omni's Mute control never touches). `unavailable` with `reason`, since each wants a different fix from the agent: `no-device`; `denied`; `not-asked`, which a host that asks at connect never publishes; `in-use`, a device present and permitted that another application holds — on an agent desktop the commonest of all; `lost`, a capture that ended. `failure` carries the words Omni showed them. |
3000
+ | `audio.input` | `ready` with `localAudio` — the microphone as captured, the same stream `openMedia` receives — and `flowing`, false while the hardware or OS says no audio moves through it (a headset's own mute switch, which Omni's Mute control never touches). `unavailable` with `reason`, since each wants a different fix from the agent: `no-device`; `denied`; `not-asked`, which a host that asks at connect never publishes; `in-use`, a device present and permitted that another application holds — on an agent desktop the commonest of all; `lost`, a capture that ended. A host decides the reason from the devices before the error name: a browser can report a permission error on a machine with no microphone at all, and "grant permission" is the wrong instruction for an agent who needs to plug one in. `failure` carries the words Omni showed them. |
2867
3001
  | `audio.output` | `ready`, or `unavailable` with `reason` — `no-device`, or `lost` for one removed — and `failure`: an agent who cannot hear is as unable to take a call as one who cannot speak. |
2868
3002
 
2869
3003
  Omni republishes the report whenever it changes — a permission granted late, a headset unplugged,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xema/omni-protocol",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "The Omni protocol: the contract every provider adapter implements",
5
5
  "type": "module",
6
6
  "license": "MIT",