@memberjunction/realtime-widget 0.0.0 → 5.45.1

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 (86) hide show
  1. package/README.md +107 -43
  2. package/dist/embed.d.ts +18 -0
  3. package/dist/embed.d.ts.map +1 -0
  4. package/dist/embed.js +33 -0
  5. package/dist/embed.js.map +1 -0
  6. package/dist/index.d.ts +23 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +37 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/loader.d.ts +32 -0
  11. package/dist/loader.d.ts.map +1 -0
  12. package/dist/loader.js +163 -0
  13. package/dist/loader.js.map +1 -0
  14. package/dist/session/visitor-key-cookie.d.ts +20 -0
  15. package/dist/session/visitor-key-cookie.d.ts.map +1 -0
  16. package/dist/session/visitor-key-cookie.js +60 -0
  17. package/dist/session/visitor-key-cookie.js.map +1 -0
  18. package/dist/session/widget-session-client.d.ts +74 -0
  19. package/dist/session/widget-session-client.d.ts.map +1 -0
  20. package/dist/session/widget-session-client.js +147 -0
  21. package/dist/session/widget-session-client.js.map +1 -0
  22. package/dist/transport/mock-widget-transport.d.ts +26 -0
  23. package/dist/transport/mock-widget-transport.d.ts.map +1 -0
  24. package/dist/transport/mock-widget-transport.js +42 -0
  25. package/dist/transport/mock-widget-transport.js.map +1 -0
  26. package/dist/transport/runtime-widget-transport.d.ts +54 -0
  27. package/dist/transport/runtime-widget-transport.d.ts.map +1 -0
  28. package/dist/transport/runtime-widget-transport.js +203 -0
  29. package/dist/transport/runtime-widget-transport.js.map +1 -0
  30. package/dist/transport/widget-transport.d.ts +41 -0
  31. package/dist/transport/widget-transport.d.ts.map +1 -0
  32. package/dist/transport/widget-transport.js +13 -0
  33. package/dist/transport/widget-transport.js.map +1 -0
  34. package/dist/types.d.ts +104 -0
  35. package/dist/types.d.ts.map +1 -0
  36. package/dist/types.js +6 -0
  37. package/dist/types.js.map +1 -0
  38. package/dist/ui/browser-capabilities.d.ts +36 -0
  39. package/dist/ui/browser-capabilities.d.ts.map +1 -0
  40. package/dist/ui/browser-capabilities.js +30 -0
  41. package/dist/ui/browser-capabilities.js.map +1 -0
  42. package/dist/ui/support-widget-element.d.ts +149 -0
  43. package/dist/ui/support-widget-element.d.ts.map +1 -0
  44. package/dist/ui/support-widget-element.js +540 -0
  45. package/dist/ui/support-widget-element.js.map +1 -0
  46. package/dist/ui/tokens.d.ts +16 -0
  47. package/dist/ui/tokens.d.ts.map +1 -0
  48. package/dist/ui/tokens.js +135 -0
  49. package/dist/ui/tokens.js.map +1 -0
  50. package/dist/voice/channels/base-widget-channel.d.ts +63 -0
  51. package/dist/voice/channels/base-widget-channel.d.ts.map +1 -0
  52. package/dist/voice/channels/base-widget-channel.js +36 -0
  53. package/dist/voice/channels/base-widget-channel.js.map +1 -0
  54. package/dist/voice/channels/whiteboard-channel.d.ts +38 -0
  55. package/dist/voice/channels/whiteboard-channel.d.ts.map +1 -0
  56. package/dist/voice/channels/whiteboard-channel.js +214 -0
  57. package/dist/voice/channels/whiteboard-channel.js.map +1 -0
  58. package/dist/voice/channels/widget-channel-host.d.ts +68 -0
  59. package/dist/voice/channels/widget-channel-host.d.ts.map +1 -0
  60. package/dist/voice/channels/widget-channel-host.js +111 -0
  61. package/dist/voice/channels/widget-channel-host.js.map +1 -0
  62. package/dist/voice/guest-tool-relay.d.ts +14 -0
  63. package/dist/voice/guest-tool-relay.d.ts.map +1 -0
  64. package/dist/voice/guest-tool-relay.js +28 -0
  65. package/dist/voice/guest-tool-relay.js.map +1 -0
  66. package/dist/voice/guest-voice-mint.d.ts +23 -0
  67. package/dist/voice/guest-voice-mint.d.ts.map +1 -0
  68. package/dist/voice/guest-voice-mint.js +61 -0
  69. package/dist/voice/guest-voice-mint.js.map +1 -0
  70. package/dist/voice/mock-voice-controller.d.ts +22 -0
  71. package/dist/voice/mock-voice-controller.d.ts.map +1 -0
  72. package/dist/voice/mock-voice-controller.js +42 -0
  73. package/dist/voice/mock-voice-controller.js.map +1 -0
  74. package/dist/voice/realtime-voice-controller.d.ts +75 -0
  75. package/dist/voice/realtime-voice-controller.d.ts.map +1 -0
  76. package/dist/voice/realtime-voice-controller.js +182 -0
  77. package/dist/voice/realtime-voice-controller.js.map +1 -0
  78. package/dist/voice/voice-abuse-guard.d.ts +39 -0
  79. package/dist/voice/voice-abuse-guard.d.ts.map +1 -0
  80. package/dist/voice/voice-abuse-guard.js +57 -0
  81. package/dist/voice/voice-abuse-guard.js.map +1 -0
  82. package/dist/voice/voice-controller.d.ts +39 -0
  83. package/dist/voice/voice-controller.d.ts.map +1 -0
  84. package/dist/voice/voice-controller.js +10 -0
  85. package/dist/voice/voice-controller.js.map +1 -0
  86. package/package.json +36 -7
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @fileoverview Client-side voice abuse ceilings. Voice is the biggest cost/abuse
3
+ * surface on a PUBLIC endpoint (plan W4 §"Voice abuse controls"), so the widget caps
4
+ * each session locally as defense-in-depth — the authoritative limits are also
5
+ * enforced server-side (SessionJanitor TTL + model-cost ceiling). This guard is pure
6
+ * and unit-tested; the controller polls it and aborts when it trips.
7
+ *
8
+ * @module @memberjunction/realtime-widget
9
+ */
10
+ /** Configurable ceilings for one voice session. */
11
+ export interface VoiceAbuseLimits {
12
+ /** Hard cap on a single voice session's wall-clock duration (minutes). */
13
+ maxSessionMinutes: number;
14
+ /** Optional cap on total output tokens (a proxy for model spend) before aborting. */
15
+ maxOutputTokens?: number;
16
+ }
17
+ /** Why a voice session was aborted by the guard. */
18
+ export type VoiceAbortReason = 'max-minutes' | 'max-cost';
19
+ /** Default limits used when a widget instance doesn't specify its own. */
20
+ export declare const DEFAULT_VOICE_LIMITS: VoiceAbuseLimits;
21
+ /**
22
+ * Tracks elapsed time + accumulated usage for one voice session and decides when to
23
+ * abort. Stateful but trivially testable (inject `now`/usage; no timers inside).
24
+ */
25
+ export declare class VoiceAbuseGuard {
26
+ private readonly limits;
27
+ private startedAtMs;
28
+ private outputTokens;
29
+ constructor(limits?: VoiceAbuseLimits);
30
+ /** Marks the session start. */
31
+ Start(nowMs: number): void;
32
+ /** Accumulates reported output-token usage. */
33
+ AddUsage(outputTokens: number | undefined): void;
34
+ /** Returns an abort reason if a ceiling has been crossed, else null. */
35
+ ShouldAbort(nowMs: number): VoiceAbortReason | null;
36
+ /** A user-facing message for an abort reason. */
37
+ static MessageFor(reason: VoiceAbortReason): string;
38
+ }
39
+ //# sourceMappingURL=voice-abuse-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-abuse-guard.d.ts","sourceRoot":"","sources":["../../src/voice/voice-abuse-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAC7B,0EAA0E;IAC1E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qFAAqF;IACrF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,oDAAoD;AACpD,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,UAAU,CAAC;AAE1D,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB,EAAE,gBAGlC,CAAC;AAEF;;;GAGG;AACH,qBAAa,eAAe;IAIZ,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,YAAY,CAAK;gBAEI,MAAM,GAAE,gBAAuC;IAE5E,+BAA+B;IACxB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKjC,+CAA+C;IACxC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAMvD,wEAAwE;IACjE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAc1D,iDAAiD;WACnC,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM;CAK7D"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @fileoverview Client-side voice abuse ceilings. Voice is the biggest cost/abuse
3
+ * surface on a PUBLIC endpoint (plan W4 §"Voice abuse controls"), so the widget caps
4
+ * each session locally as defense-in-depth — the authoritative limits are also
5
+ * enforced server-side (SessionJanitor TTL + model-cost ceiling). This guard is pure
6
+ * and unit-tested; the controller polls it and aborts when it trips.
7
+ *
8
+ * @module @memberjunction/realtime-widget
9
+ */
10
+ /** Default limits used when a widget instance doesn't specify its own. */
11
+ export const DEFAULT_VOICE_LIMITS = {
12
+ maxSessionMinutes: 10,
13
+ maxOutputTokens: 50_000,
14
+ };
15
+ /**
16
+ * Tracks elapsed time + accumulated usage for one voice session and decides when to
17
+ * abort. Stateful but trivially testable (inject `now`/usage; no timers inside).
18
+ */
19
+ export class VoiceAbuseGuard {
20
+ constructor(limits = DEFAULT_VOICE_LIMITS) {
21
+ this.limits = limits;
22
+ this.startedAtMs = null;
23
+ this.outputTokens = 0;
24
+ }
25
+ /** Marks the session start. */
26
+ Start(nowMs) {
27
+ this.startedAtMs = nowMs;
28
+ this.outputTokens = 0;
29
+ }
30
+ /** Accumulates reported output-token usage. */
31
+ AddUsage(outputTokens) {
32
+ if (outputTokens && outputTokens > 0) {
33
+ this.outputTokens += outputTokens;
34
+ }
35
+ }
36
+ /** Returns an abort reason if a ceiling has been crossed, else null. */
37
+ ShouldAbort(nowMs) {
38
+ if (this.startedAtMs === null) {
39
+ return null;
40
+ }
41
+ const elapsedMin = (nowMs - this.startedAtMs) / 60_000;
42
+ if (elapsedMin >= this.limits.maxSessionMinutes) {
43
+ return 'max-minutes';
44
+ }
45
+ if (this.limits.maxOutputTokens != null && this.outputTokens >= this.limits.maxOutputTokens) {
46
+ return 'max-cost';
47
+ }
48
+ return null;
49
+ }
50
+ /** A user-facing message for an abort reason. */
51
+ static MessageFor(reason) {
52
+ return reason === 'max-minutes'
53
+ ? 'Voice session time limit reached. Please start a new session or continue by text.'
54
+ : 'Voice session usage limit reached. Please continue by text.';
55
+ }
56
+ }
57
+ //# sourceMappingURL=voice-abuse-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-abuse-guard.js","sourceRoot":"","sources":["../../src/voice/voice-abuse-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,oBAAoB,GAAqB;IAClD,iBAAiB,EAAE,EAAE;IACrB,eAAe,EAAE,MAAM;CAC1B,CAAC;AAEF;;;GAGG;AACH,MAAM,OAAO,eAAe;IAIxB,YAA6B,SAA2B,oBAAoB;QAA/C,WAAM,GAAN,MAAM,CAAyC;QAHpE,gBAAW,GAAkB,IAAI,CAAC;QAClC,iBAAY,GAAG,CAAC,CAAC;IAEsD,CAAC;IAEhF,+BAA+B;IACxB,KAAK,CAAC,KAAa;QACtB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,+CAA+C;IACxC,QAAQ,CAAC,YAAgC;QAC5C,IAAI,YAAY,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC;QACtC,CAAC;IACL,CAAC;IAED,wEAAwE;IACjE,WAAW,CAAC,KAAa;QAC5B,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,UAAU,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC;QACvD,IAAI,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAC9C,OAAO,aAAa,CAAC;QACzB,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,IAAI,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;YAC1F,OAAO,UAAU,CAAC;QACtB,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,iDAAiD;IAC1C,MAAM,CAAC,UAAU,CAAC,MAAwB;QAC7C,OAAO,MAAM,KAAK,aAAa;YAC3B,CAAC,CAAC,mFAAmF;YACrF,CAAC,CAAC,6DAA6D,CAAC;IACxE,CAAC;CACJ"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @fileoverview The voice seam. The UI element depends only on this interface, so the
3
+ * voice affordance is unit-testable with a mock and decoupled from the realtime client
4
+ * + mint wiring. The real implementation (`RealtimeVoiceController`) reuses
5
+ * `@memberjunction/ai-realtime-client` (client-direct topology) — no new driver.
6
+ *
7
+ * @module @memberjunction/realtime-widget
8
+ */
9
+ /** Coarse voice UI state surfaced to the widget. */
10
+ export type WidgetVoiceState = 'idle' | 'connecting' | 'listening' | 'speaking' | 'ended' | 'error';
11
+ /** A transcript line delivered to the widget while voice is active. */
12
+ export interface WidgetVoiceTranscript {
13
+ role: 'user' | 'agent';
14
+ text: string;
15
+ isFinal: boolean;
16
+ }
17
+ /** Callbacks the widget supplies when starting voice. */
18
+ export interface VoiceControllerCallbacks {
19
+ onState: (state: WidgetVoiceState) => void;
20
+ onTranscript: (transcript: WidgetVoiceTranscript) => void;
21
+ /** Called when the session ends (incl. an abuse-ceiling abort), with an optional reason. */
22
+ onEnded: (reason?: string) => void;
23
+ /**
24
+ * Reveals (and returns) the demonstration-surface host element for an interactive channel the agent
25
+ * just engaged, so the channel can render into it inside the widget's shadow DOM. Called the first
26
+ * time a channel's tool fires. Omitted when the widget exposes no channel surface.
27
+ */
28
+ getChannelSurface?: (channelName: string, title: string) => HTMLElement;
29
+ }
30
+ /** Starts/stops a client-direct voice session with the pinned agent. */
31
+ export interface IVoiceController {
32
+ /** Begins a voice session (mints, connects, acquires mic, enforces ceilings). */
33
+ Start(callbacks: VoiceControllerCallbacks): Promise<void>;
34
+ /** Ends the active voice session. */
35
+ Stop(): Promise<void>;
36
+ /** Whether a voice session is currently active. */
37
+ readonly IsActive: boolean;
38
+ }
39
+ //# sourceMappingURL=voice-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-controller.d.ts","sourceRoot":"","sources":["../../src/voice/voice-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,oDAAoD;AACpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAEpG,uEAAuE;AACvE,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,yDAAyD;AACzD,MAAM,WAAW,wBAAwB;IACrC,OAAO,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC3C,YAAY,EAAE,CAAC,UAAU,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC1D,4FAA4F;IAC5F,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,WAAW,CAAC;CAC3E;AAED,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC7B,iFAAiF;IACjF,KAAK,CAAC,SAAS,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,qCAAqC;IACrC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC9B"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview The voice seam. The UI element depends only on this interface, so the
3
+ * voice affordance is unit-testable with a mock and decoupled from the realtime client
4
+ * + mint wiring. The real implementation (`RealtimeVoiceController`) reuses
5
+ * `@memberjunction/ai-realtime-client` (client-direct topology) — no new driver.
6
+ *
7
+ * @module @memberjunction/realtime-widget
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=voice-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-controller.js","sourceRoot":"","sources":["../../src/voice/voice-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
package/package.json CHANGED
@@ -1,10 +1,39 @@
1
1
  {
2
2
  "name": "@memberjunction/realtime-widget",
3
- "version": "0.0.0",
4
- "description": "OIDC trusted publishing setup package for @memberjunction/realtime-widget",
5
- "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
3
+ "type": "module",
4
+ "version": "5.45.1",
5
+ "description": "MemberJunction: Droppable, embeddable public customer-support widget (text + voice). A shadow-DOM web component that reuses ConversationsRuntime + the realtime client stack against MJAPI with a guest session JWT. No MJ login required.",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "/dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc && tsc-alias -f",
13
+ "bundle": "esbuild dist/embed.js --bundle --splitting --format=esm --platform=browser --outdir=dist/embed --entry-names=mj-widget --chunk-names=chunks/[name]-[hash]",
14
+ "bundle:min": "esbuild dist/embed.js --bundle --splitting --minify --format=esm --platform=browser --outdir=dist/embed-min --entry-names=mj-widget --chunk-names=chunks/[name]-[hash]",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest"
17
+ },
18
+ "author": "MemberJunction.com",
19
+ "license": "ISC",
20
+ "dependencies": {
21
+ "@memberjunction/global": "5.45.1",
22
+ "@memberjunction/core": "5.45.1",
23
+ "@memberjunction/core-entities": "5.45.1",
24
+ "@memberjunction/conversations-runtime": "5.45.1",
25
+ "@memberjunction/graphql-dataprovider": "5.45.1",
26
+ "@memberjunction/ai": "5.45.1",
27
+ "@memberjunction/ai-realtime-client": "5.45.1"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "24.10.11",
31
+ "esbuild": "^0.26.0",
32
+ "jsdom": "^24.0.0",
33
+ "typescript": "^5.9.3"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/MemberJunction/MJ"
38
+ }
10
39
  }