@origonai/web-sdk 0.1.2 → 0.1.4
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/README.md +15 -0
- package/dist/index.d.ts +79 -0
- package/dist/origon-web-sdk.js +1079 -845
- package/dist/origon-web-sdk.js.map +1 -1
- package/docs/backend-integration.md +17 -30
- package/docs/contract.md +21 -0
- package/docs/voice.md +12 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,6 +66,15 @@ await client.endSession(sessionId)
|
|
|
66
66
|
- `getSessions()` — GET `/sessions` (prior sessions; every `SessionSummary`
|
|
67
67
|
includes required live-owner `active: boolean`)
|
|
68
68
|
- `getSession(sessionId)` — GET `/session/{id}` (transcript + control)
|
|
69
|
+
- `getSessionsPage({ pageSize?, cursor?, search?, signal? })` — fetch a strict
|
|
70
|
+
directory page (50 by default, 100 maximum); `search` matches subject,
|
|
71
|
+
contact name, latest visible message text, and attachment names
|
|
72
|
+
- `getSessionPage(sessionId, { pageSize?, cursor?, signal? })` — fetch a strict
|
|
73
|
+
chronological history page (100 by default, 250 maximum)
|
|
74
|
+
- `SessionDirectoryPager` / `SessionHistoryPager` — generation-fenced page
|
|
75
|
+
reducers for dedupe, live-event reconciliation, prepend accumulation, and
|
|
76
|
+
bounded empty-page continuation; keep search state separate from the default
|
|
77
|
+
cached directory
|
|
69
78
|
|
|
70
79
|
### Chat
|
|
71
80
|
- `sendMessage(sessionId, payload)` — post a message with optional `metadata: {audience}`; ordinary participant sends omit it and the server resolves the audience to `all`. The SDK fires `onMessageAdded` immediately with `status: 'sending'`, then `onMessageUpdated` with `'delivered'` or `'failed'` after the server acks
|
|
@@ -175,6 +184,7 @@ client.initialize({
|
|
|
175
184
|
|
|
176
185
|
const { sessionId } = await client.startSession({ channel: 'voice' })
|
|
177
186
|
await client.setMute(sessionId, 'uplink') // 'uplink' | 'downlink' | 'both' | 'none'
|
|
187
|
+
await client.sendDtmf(sessionId, '5') // one of 0-9, *, #, A-D
|
|
178
188
|
|
|
179
189
|
const off = client.subscribeAudioStats(sessionId, ({ outboundLevel, inboundLevel }) => {
|
|
180
190
|
// VU meters at ~5 Hz
|
|
@@ -192,6 +202,11 @@ Voice requires:
|
|
|
192
202
|
|
|
193
203
|
The browser opens a single WebTransport to `<media-server>/web`, sends a B2BUA `Connect` over the control sub-stream, and pumps 20 ms Opus frames as `ObjectDatagram`s with `group_id = floor(Date.now()/1000) - serverEpochUnix`. Reconnect is Tier-3 only (`Resume` verb) with `[100, 250, 500, 1000]` ms backoff.
|
|
194
204
|
|
|
205
|
+
`sendDtmf` resolves when Media acknowledges publication to the active CX flow.
|
|
206
|
+
It rejects while the voice transport is reconnecting and is never queued or
|
|
207
|
+
replayed after `Resume`. The SDK does not play a local tone or expose a peer
|
|
208
|
+
DTMF callback.
|
|
209
|
+
|
|
195
210
|
## Joining a provisioned session
|
|
196
211
|
|
|
197
212
|
`startSession` originates a session by calling `POST /session/start` itself.
|
package/dist/index.d.ts
CHANGED
|
@@ -150,6 +150,9 @@ export declare type DisconnectReason = {
|
|
|
150
150
|
detail: string;
|
|
151
151
|
};
|
|
152
152
|
|
|
153
|
+
/** Complete programmatic DTMF alphabet; lowercase is intentionally invalid. */
|
|
154
|
+
export declare type DtmfDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '*' | '#' | 'A' | 'B' | 'C' | 'D';
|
|
155
|
+
|
|
153
156
|
export declare function getSessionManager(): SessionManager;
|
|
154
157
|
|
|
155
158
|
/**
|
|
@@ -171,6 +174,8 @@ export declare interface JoinSessionOptions {
|
|
|
171
174
|
chat?: ProvisionedChatJoinOptions;
|
|
172
175
|
}
|
|
173
176
|
|
|
177
|
+
export declare const MAX_EMPTY_PAGE_CONTINUATIONS = 8;
|
|
178
|
+
|
|
174
179
|
export declare interface Message {
|
|
175
180
|
role: MessageRole;
|
|
176
181
|
id: string;
|
|
@@ -256,6 +261,8 @@ export declare type MessageStatus = 'sending' | 'delivered' | 'failed';
|
|
|
256
261
|
/** Mirrors `media-server::MuteScope`. */
|
|
257
262
|
export declare type MuteScope = 'none' | 'uplink' | 'downlink' | 'both';
|
|
258
263
|
|
|
264
|
+
export declare function normalizeSearchField(value: string): string;
|
|
265
|
+
|
|
259
266
|
/**
|
|
260
267
|
* A non-OK orpc reply (an ERROR frame). `code` is the wire status — a base code
|
|
261
268
|
* (§5) or a `0x1000+` auth code; `reason` is the server's UTF-8 message.
|
|
@@ -379,11 +386,77 @@ export declare interface SendMessagePayload {
|
|
|
379
386
|
|
|
380
387
|
export declare type SessionControl = 'ai' | 'user';
|
|
381
388
|
|
|
389
|
+
export declare interface SessionDirectoryPage {
|
|
390
|
+
sessions: SessionSummary[];
|
|
391
|
+
nextCursor: string | null;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export declare interface SessionDirectoryPageOptions {
|
|
395
|
+
/** Defaults to 50; server maximum is 100. */
|
|
396
|
+
pageSize?: number;
|
|
397
|
+
cursor?: string;
|
|
398
|
+
search?: string;
|
|
399
|
+
signal?: AbortSignal;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export declare class SessionDirectoryPager {
|
|
403
|
+
private generationValue;
|
|
404
|
+
private query;
|
|
405
|
+
private live;
|
|
406
|
+
private value;
|
|
407
|
+
get generation(): number;
|
|
408
|
+
get search(): string | null;
|
|
409
|
+
get state(): Readonly<SessionDirectoryPageState>;
|
|
410
|
+
begin(search?: string, cached?: SessionSummary[]): number;
|
|
411
|
+
applyLive(summary: SessionSummary): void;
|
|
412
|
+
merge(generation: number, page: SessionDirectoryPage, firstPage: boolean): boolean;
|
|
413
|
+
canLoadMore(): boolean;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export declare interface SessionDirectoryPageState {
|
|
417
|
+
sessions: SessionSummary[];
|
|
418
|
+
nextCursor: string | null;
|
|
419
|
+
emptyContinuations: number;
|
|
420
|
+
}
|
|
421
|
+
|
|
382
422
|
export declare interface SessionHistory {
|
|
383
423
|
history: Message[];
|
|
384
424
|
control: SessionControl;
|
|
385
425
|
}
|
|
386
426
|
|
|
427
|
+
export declare interface SessionHistoryPage {
|
|
428
|
+
history: Message[];
|
|
429
|
+
control: SessionControl;
|
|
430
|
+
nextCursor: string | null;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export declare interface SessionHistoryPageOptions {
|
|
434
|
+
/** Defaults to 100; server maximum is 250. */
|
|
435
|
+
pageSize?: number;
|
|
436
|
+
cursor?: string;
|
|
437
|
+
signal?: AbortSignal;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
export declare class SessionHistoryPager {
|
|
441
|
+
private generationValue;
|
|
442
|
+
private live;
|
|
443
|
+
private value;
|
|
444
|
+
get generation(): number;
|
|
445
|
+
get state(): Readonly<SessionHistoryPageState>;
|
|
446
|
+
begin(cached?: SessionHistory): number;
|
|
447
|
+
applyLive(message: Message): void;
|
|
448
|
+
removeLive(identity: Pick<Message, 'id' | 'localId'>): void;
|
|
449
|
+
merge(generation: number, page: SessionHistoryPage, firstPage: boolean): boolean;
|
|
450
|
+
canLoadMore(): boolean;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export declare interface SessionHistoryPageState {
|
|
454
|
+
history: Message[];
|
|
455
|
+
control: SessionControl;
|
|
456
|
+
nextCursor: string | null;
|
|
457
|
+
emptyContinuations: number;
|
|
458
|
+
}
|
|
459
|
+
|
|
387
460
|
/**
|
|
388
461
|
* Top-level entry point. One instance per app — see `getSessionManager()`
|
|
389
462
|
* for the singleton accessor.
|
|
@@ -415,6 +488,8 @@ export declare class SessionManager {
|
|
|
415
488
|
}>;
|
|
416
489
|
getSessions(): Promise<SessionSummary[]>;
|
|
417
490
|
getSession(sessionId: string): Promise<SessionHistory>;
|
|
491
|
+
getSessionsPage(options?: SessionDirectoryPageOptions): Promise<SessionDirectoryPage>;
|
|
492
|
+
getSessionPage(sessionId: string, options?: SessionHistoryPageOptions): Promise<SessionHistoryPage>;
|
|
418
493
|
startSession(opts: StartSessionOptions): Promise<{
|
|
419
494
|
sessionId: string;
|
|
420
495
|
}>;
|
|
@@ -457,6 +532,8 @@ export declare class SessionManager {
|
|
|
457
532
|
notifyTyping(sessionId: string, metadata?: TypingMetadata): void;
|
|
458
533
|
stopTyping(sessionId: string): void;
|
|
459
534
|
setMute(sessionId: string, scope: MuteScope): Promise<void>;
|
|
535
|
+
/** Send one DTMF symbol to the active CX flow for a voice session. */
|
|
536
|
+
sendDtmf(sessionId: string, digit: DtmfDigit): Promise<void>;
|
|
460
537
|
/** Enable microphone coaching on a receive-only voice join. */
|
|
461
538
|
enableCapture(sessionId: string): Promise<void>;
|
|
462
539
|
/** Return a coaching voice join to Listen and release its microphone. */
|
|
@@ -488,6 +565,8 @@ export declare class SessionManager {
|
|
|
488
565
|
private requireHttp;
|
|
489
566
|
}
|
|
490
567
|
|
|
568
|
+
export declare function sessionMatchesSearch(summary: SessionSummary, normalizedSearch: string): boolean;
|
|
569
|
+
|
|
491
570
|
export declare interface SessionSummary {
|
|
492
571
|
sessionId: string;
|
|
493
572
|
subject: string;
|