@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.
- package/README.md +107 -43
- package/dist/embed.d.ts +18 -0
- package/dist/embed.d.ts.map +1 -0
- package/dist/embed.js +33 -0
- package/dist/embed.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +32 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +163 -0
- package/dist/loader.js.map +1 -0
- package/dist/session/visitor-key-cookie.d.ts +20 -0
- package/dist/session/visitor-key-cookie.d.ts.map +1 -0
- package/dist/session/visitor-key-cookie.js +60 -0
- package/dist/session/visitor-key-cookie.js.map +1 -0
- package/dist/session/widget-session-client.d.ts +74 -0
- package/dist/session/widget-session-client.d.ts.map +1 -0
- package/dist/session/widget-session-client.js +147 -0
- package/dist/session/widget-session-client.js.map +1 -0
- package/dist/transport/mock-widget-transport.d.ts +26 -0
- package/dist/transport/mock-widget-transport.d.ts.map +1 -0
- package/dist/transport/mock-widget-transport.js +42 -0
- package/dist/transport/mock-widget-transport.js.map +1 -0
- package/dist/transport/runtime-widget-transport.d.ts +54 -0
- package/dist/transport/runtime-widget-transport.d.ts.map +1 -0
- package/dist/transport/runtime-widget-transport.js +203 -0
- package/dist/transport/runtime-widget-transport.js.map +1 -0
- package/dist/transport/widget-transport.d.ts +41 -0
- package/dist/transport/widget-transport.d.ts.map +1 -0
- package/dist/transport/widget-transport.js +13 -0
- package/dist/transport/widget-transport.js.map +1 -0
- package/dist/types.d.ts +104 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/browser-capabilities.d.ts +36 -0
- package/dist/ui/browser-capabilities.d.ts.map +1 -0
- package/dist/ui/browser-capabilities.js +30 -0
- package/dist/ui/browser-capabilities.js.map +1 -0
- package/dist/ui/support-widget-element.d.ts +149 -0
- package/dist/ui/support-widget-element.d.ts.map +1 -0
- package/dist/ui/support-widget-element.js +540 -0
- package/dist/ui/support-widget-element.js.map +1 -0
- package/dist/ui/tokens.d.ts +16 -0
- package/dist/ui/tokens.d.ts.map +1 -0
- package/dist/ui/tokens.js +135 -0
- package/dist/ui/tokens.js.map +1 -0
- package/dist/voice/channels/base-widget-channel.d.ts +63 -0
- package/dist/voice/channels/base-widget-channel.d.ts.map +1 -0
- package/dist/voice/channels/base-widget-channel.js +36 -0
- package/dist/voice/channels/base-widget-channel.js.map +1 -0
- package/dist/voice/channels/whiteboard-channel.d.ts +38 -0
- package/dist/voice/channels/whiteboard-channel.d.ts.map +1 -0
- package/dist/voice/channels/whiteboard-channel.js +214 -0
- package/dist/voice/channels/whiteboard-channel.js.map +1 -0
- package/dist/voice/channels/widget-channel-host.d.ts +68 -0
- package/dist/voice/channels/widget-channel-host.d.ts.map +1 -0
- package/dist/voice/channels/widget-channel-host.js +111 -0
- package/dist/voice/channels/widget-channel-host.js.map +1 -0
- package/dist/voice/guest-tool-relay.d.ts +14 -0
- package/dist/voice/guest-tool-relay.d.ts.map +1 -0
- package/dist/voice/guest-tool-relay.js +28 -0
- package/dist/voice/guest-tool-relay.js.map +1 -0
- package/dist/voice/guest-voice-mint.d.ts +23 -0
- package/dist/voice/guest-voice-mint.d.ts.map +1 -0
- package/dist/voice/guest-voice-mint.js +61 -0
- package/dist/voice/guest-voice-mint.js.map +1 -0
- package/dist/voice/mock-voice-controller.d.ts +22 -0
- package/dist/voice/mock-voice-controller.d.ts.map +1 -0
- package/dist/voice/mock-voice-controller.js +42 -0
- package/dist/voice/mock-voice-controller.js.map +1 -0
- package/dist/voice/realtime-voice-controller.d.ts +75 -0
- package/dist/voice/realtime-voice-controller.d.ts.map +1 -0
- package/dist/voice/realtime-voice-controller.js +182 -0
- package/dist/voice/realtime-voice-controller.js.map +1 -0
- package/dist/voice/voice-abuse-guard.d.ts +39 -0
- package/dist/voice/voice-abuse-guard.d.ts.map +1 -0
- package/dist/voice/voice-abuse-guard.js +57 -0
- package/dist/voice/voice-abuse-guard.js.map +1 -0
- package/dist/voice/voice-controller.d.ts +39 -0
- package/dist/voice/voice-controller.d.ts.map +1 -0
- package/dist/voice/voice-controller.js +10 -0
- package/dist/voice/voice-controller.js.map +1 -0
- package/package.json +36 -7
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Design tokens injected into the widget's SHADOW ROOT (not <head>),
|
|
3
|
+
* so the widget is themeable yet fully isolated from — and cannot bleed into — the
|
|
4
|
+
* host page. Mirrors the `--mj-chat-*` token set from
|
|
5
|
+
* `conversations-runtime-bootstrap.service.ts`, plus the minimal base semantic tokens
|
|
6
|
+
* the shadow tree needs (the shadow root does not inherit the host app's `:root`).
|
|
7
|
+
*
|
|
8
|
+
* No hardcoded colors leak into component rules — every rule references a token
|
|
9
|
+
* (CLAUDE design-token rule). Defaults here are the token values; a host can override
|
|
10
|
+
* by setting these custom properties on the mount element.
|
|
11
|
+
*
|
|
12
|
+
* @module @memberjunction/realtime-widget
|
|
13
|
+
*/
|
|
14
|
+
/** The `:host`-scoped token defaults + component CSS for the widget shadow root. */
|
|
15
|
+
export const WIDGET_SHADOW_STYLES = `
|
|
16
|
+
:host {
|
|
17
|
+
/* base semantic tokens (shadow root needs its own — it can't see the app :root) */
|
|
18
|
+
--mj-text-primary: #1f2933;
|
|
19
|
+
--mj-text-secondary: #52606d;
|
|
20
|
+
--mj-text-inverse: #ffffff;
|
|
21
|
+
--mj-bg-surface: #ffffff;
|
|
22
|
+
--mj-bg-surface-card: #f5f7fa;
|
|
23
|
+
--mj-bg-surface-sunken: #eef1f5;
|
|
24
|
+
--mj-border-default: #e2e8f0;
|
|
25
|
+
--mj-brand-primary: #264faf;
|
|
26
|
+
--mj-brand-primary-hover: #1d3f8c;
|
|
27
|
+
--mj-status-error: #dc2626;
|
|
28
|
+
--mj-status-error-text: #b91c1c;
|
|
29
|
+
--mj-status-error-bg: #fef2f2;
|
|
30
|
+
|
|
31
|
+
/* chat tokens (mirror the Angular bootstrap names) */
|
|
32
|
+
--mj-chat-bubble-user-bg: var(--mj-brand-primary);
|
|
33
|
+
--mj-chat-bubble-user-text: var(--mj-text-inverse);
|
|
34
|
+
--mj-chat-bubble-agent-bg: var(--mj-bg-surface-card);
|
|
35
|
+
--mj-chat-bubble-agent-text: var(--mj-text-primary);
|
|
36
|
+
--mj-chat-composer-bg: var(--mj-bg-surface);
|
|
37
|
+
--mj-chat-composer-border: var(--mj-border-default);
|
|
38
|
+
|
|
39
|
+
all: initial;
|
|
40
|
+
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
41
|
+
color: var(--mj-text-primary);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
* { box-sizing: border-box; }
|
|
45
|
+
|
|
46
|
+
.mj-widget-launcher {
|
|
47
|
+
position: fixed; right: 20px; bottom: 20px;
|
|
48
|
+
width: 56px; height: 56px; border-radius: 50%;
|
|
49
|
+
background: var(--mj-brand-primary); color: var(--mj-text-inverse);
|
|
50
|
+
border: none; cursor: pointer; font-size: 24px;
|
|
51
|
+
box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-text-primary) 25%, transparent);
|
|
52
|
+
}
|
|
53
|
+
.mj-widget-launcher:hover { background: var(--mj-brand-primary-hover); }
|
|
54
|
+
|
|
55
|
+
.mj-widget-panel {
|
|
56
|
+
position: fixed; right: 20px; bottom: 88px;
|
|
57
|
+
width: 360px; max-width: calc(100vw - 40px); height: 520px; max-height: calc(100vh - 120px);
|
|
58
|
+
display: flex; flex-direction: column;
|
|
59
|
+
background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default);
|
|
60
|
+
border-radius: 12px; overflow: hidden;
|
|
61
|
+
box-shadow: 0 8px 28px color-mix(in srgb, var(--mj-text-primary) 22%, transparent);
|
|
62
|
+
}
|
|
63
|
+
.mj-widget-panel[hidden] { display: none; }
|
|
64
|
+
|
|
65
|
+
.mj-widget-header {
|
|
66
|
+
padding: 12px 16px; background: var(--mj-brand-primary); color: var(--mj-text-inverse);
|
|
67
|
+
display: flex; align-items: center; justify-content: space-between; font-weight: 600;
|
|
68
|
+
}
|
|
69
|
+
.mj-widget-close { background: none; border: none; color: var(--mj-text-inverse); cursor: pointer; font-size: 18px; }
|
|
70
|
+
|
|
71
|
+
.mj-widget-transcript {
|
|
72
|
+
flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 8px;
|
|
73
|
+
background: var(--mj-bg-surface-sunken);
|
|
74
|
+
}
|
|
75
|
+
.mj-widget-empty { color: var(--mj-text-secondary); text-align: center; margin: auto; padding: 16px; }
|
|
76
|
+
|
|
77
|
+
.mj-widget-msg { max-width: 80%; padding: 8px 12px; border-radius: 12px; white-space: pre-wrap; word-break: break-word; }
|
|
78
|
+
.mj-widget-msg.user { align-self: flex-end; background: var(--mj-chat-bubble-user-bg); color: var(--mj-chat-bubble-user-text); }
|
|
79
|
+
.mj-widget-msg.agent { align-self: flex-start; background: var(--mj-chat-bubble-agent-bg); color: var(--mj-chat-bubble-agent-text); }
|
|
80
|
+
.mj-widget-msg.system { align-self: center; color: var(--mj-status-error-text); font-size: 0.85em; }
|
|
81
|
+
|
|
82
|
+
.mj-widget-progress { align-self: flex-start; color: var(--mj-text-secondary); font-size: 0.85em; font-style: italic; }
|
|
83
|
+
.mj-widget-progress[hidden] { display: none; }
|
|
84
|
+
|
|
85
|
+
/* Interactive-channel demonstration surface (Phase 2 — e.g. the Whiteboard the agent draws on during voice). */
|
|
86
|
+
.mj-widget-surface { display: flex; flex-direction: column; border-bottom: 1px solid var(--mj-border-default); background: var(--mj-bg-surface); }
|
|
87
|
+
.mj-widget-surface[hidden] { display: none; }
|
|
88
|
+
.mj-widget-surface-title { padding: 6px 12px; font-size: 0.8em; font-weight: 600; color: var(--mj-text-secondary); background: var(--mj-bg-surface-card); }
|
|
89
|
+
.mj-widget-surface-host { height: 200px; width: 100%; background: var(--mj-bg-surface); overflow: hidden; }
|
|
90
|
+
.mj-widget-surface-host svg { display: block; width: 100%; height: 100%; }
|
|
91
|
+
|
|
92
|
+
.mj-widget-composer {
|
|
93
|
+
display: flex; gap: 8px; padding: 10px; border-top: 1px solid var(--mj-chat-composer-border);
|
|
94
|
+
background: var(--mj-chat-composer-bg);
|
|
95
|
+
}
|
|
96
|
+
.mj-widget-input {
|
|
97
|
+
flex: 1; resize: none; padding: 8px 10px; border: 1px solid var(--mj-border-default);
|
|
98
|
+
border-radius: 8px; font: inherit; color: var(--mj-text-primary); background: var(--mj-bg-surface);
|
|
99
|
+
}
|
|
100
|
+
.mj-widget-send {
|
|
101
|
+
background: var(--mj-brand-primary); color: var(--mj-text-inverse); border: none;
|
|
102
|
+
border-radius: 8px; padding: 0 14px; cursor: pointer; font: inherit;
|
|
103
|
+
}
|
|
104
|
+
.mj-widget-send:disabled { opacity: 0.5; cursor: default; }
|
|
105
|
+
|
|
106
|
+
/* Connection-lost banner (graceful degradation, W6) */
|
|
107
|
+
.mj-widget-banner {
|
|
108
|
+
display: flex; align-items: center; gap: 8px; padding: 8px 12px;
|
|
109
|
+
background: var(--mj-status-error-bg); color: var(--mj-status-error-text);
|
|
110
|
+
border-bottom: 1px solid color-mix(in srgb, var(--mj-status-error) 35%, transparent);
|
|
111
|
+
font-size: 0.85em;
|
|
112
|
+
}
|
|
113
|
+
.mj-widget-banner[hidden] { display: none; }
|
|
114
|
+
.mj-widget-banner-text { flex: 1; }
|
|
115
|
+
.mj-widget-banner-retry {
|
|
116
|
+
background: var(--mj-status-error); color: var(--mj-text-inverse); border: none;
|
|
117
|
+
border-radius: 6px; padding: 4px 10px; cursor: pointer; font: inherit; font-size: 0.95em;
|
|
118
|
+
}
|
|
119
|
+
.mj-widget-banner-retry:hover { background: var(--mj-status-error-text); }
|
|
120
|
+
.mj-widget-memory-notice {
|
|
121
|
+
display: flex; align-items: center; gap: 8px; padding: 6px 12px;
|
|
122
|
+
background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);
|
|
123
|
+
border-top: 1px solid var(--mj-border-default);
|
|
124
|
+
font-size: 0.75em;
|
|
125
|
+
}
|
|
126
|
+
.mj-widget-memory-notice-text { flex: 1; }
|
|
127
|
+
.mj-widget-forget {
|
|
128
|
+
background: none; color: var(--mj-text-secondary); border: none;
|
|
129
|
+
padding: 2px 4px; cursor: pointer; font: inherit; font-size: 1em;
|
|
130
|
+
text-decoration: underline; white-space: nowrap;
|
|
131
|
+
}
|
|
132
|
+
.mj-widget-forget:hover { color: var(--mj-text-primary); }
|
|
133
|
+
.mj-widget-forget:disabled { opacity: 0.6; cursor: default; }
|
|
134
|
+
`;
|
|
135
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/ui/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,oFAAoF;AACpF,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuHnC,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Framework-free interactive-channel contract for the public web widget.
|
|
3
|
+
*
|
|
4
|
+
* MJ's realtime co-agent stack supports interactive CHANNELS — agent-driven surfaces (Whiteboard,
|
|
5
|
+
* Remote Browser, Media) the model manipulates via client-executed tools while it talks. The shipped
|
|
6
|
+
* channel clients live in `@memberjunction/ng-conversations` and render ANGULAR components, so they
|
|
7
|
+
* can't mount inside this dependency-free, shadow-DOM widget. This module defines the equivalent
|
|
8
|
+
* **framework-free** channel contract: a channel declares client tools, applies the model's tool calls
|
|
9
|
+
* to a surface it renders into a plain `HTMLElement`, and feeds user activity back as perception notes.
|
|
10
|
+
*
|
|
11
|
+
* Channels are resolved at runtime via `MJGlobal.ClassFactory` keyed by channel name — exactly how the
|
|
12
|
+
* voice controller resolves the realtime driver — so adding a channel is a `@RegisterClass` + a Load()
|
|
13
|
+
* call, with no widget-core changes. Which channels a given widget may attach is gated by the widget
|
|
14
|
+
* instance's `EnabledChannels`.
|
|
15
|
+
*
|
|
16
|
+
* @module @memberjunction/realtime-widget
|
|
17
|
+
*/
|
|
18
|
+
/** A client-executed tool a channel exposes to the realtime model (declared at session start). */
|
|
19
|
+
export interface WidgetChannelToolDefinition {
|
|
20
|
+
/** Fully-qualified tool name, MUST start with the channel's {@link BaseWidgetChannel.ToolNamePrefix}. */
|
|
21
|
+
Name: string;
|
|
22
|
+
/** One-line description the model sees. */
|
|
23
|
+
Description: string;
|
|
24
|
+
/** JSON-Schema for the tool's arguments (provider-agnostic; drivers translate it). */
|
|
25
|
+
ParametersSchema: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
/** The seam back to the live voice session a channel uses to feed the model background context. */
|
|
28
|
+
export interface WidgetChannelContext {
|
|
29
|
+
/**
|
|
30
|
+
* Feed a background perception note into the live model (no spoken reply) — e.g. "the user drew a
|
|
31
|
+
* box". Mirrors `BaseRealtimeClient.SendContextNote` so the agent perceives surface activity.
|
|
32
|
+
*/
|
|
33
|
+
SendContextNote(text: string): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Base class for a framework-free widget interactive channel. Concrete channels (e.g. the Whiteboard)
|
|
37
|
+
* subclass this and register with `@RegisterClass(BaseWidgetChannel, '<ChannelName>')`. Resolved via
|
|
38
|
+
* `MJGlobal.ClassFactory.CreateInstance(BaseWidgetChannel, channelName)`.
|
|
39
|
+
*/
|
|
40
|
+
export declare abstract class BaseWidgetChannel {
|
|
41
|
+
protected context: WidgetChannelContext | null;
|
|
42
|
+
/** Channel name (matches the `MJ: AI Agent Channels` row + the EnabledChannels entry), e.g. `'Whiteboard'`. */
|
|
43
|
+
abstract get ChannelName(): string;
|
|
44
|
+
/** Prefix every one of this channel's tool names share, e.g. `'Whiteboard_'`. Used to route tool calls. */
|
|
45
|
+
abstract get ToolNamePrefix(): string;
|
|
46
|
+
/** Human label for the surface's header in the widget. */
|
|
47
|
+
abstract get SurfaceTitle(): string;
|
|
48
|
+
/** The client tools this channel contributes to the realtime session (declared at mint). */
|
|
49
|
+
abstract GetToolDefinitions(): WidgetChannelToolDefinition[];
|
|
50
|
+
/**
|
|
51
|
+
* Applies one model-issued tool call to the channel's surface and returns the result as a JSON
|
|
52
|
+
* string (fed back to the model as the tool result). Must not throw — return an `{ "error": … }`
|
|
53
|
+
* JSON payload on a bad call so the model can recover.
|
|
54
|
+
*/
|
|
55
|
+
abstract ApplyAgentTool(toolName: string, argsJson: string): string;
|
|
56
|
+
/** Renders the channel's surface into the supplied host element (inside the widget's shadow DOM). */
|
|
57
|
+
abstract BindSurface(host: HTMLElement): void;
|
|
58
|
+
/** Wires the perception seam. Called once before the first tool call. */
|
|
59
|
+
Initialize(context: WidgetChannelContext): void;
|
|
60
|
+
/** Tears down the surface + subscriptions. Default: clears the context. */
|
|
61
|
+
Dispose(): void;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=base-widget-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-widget-channel.d.ts","sourceRoot":"","sources":["../../../src/voice/channels/base-widget-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,kGAAkG;AAClG,MAAM,WAAW,2BAA2B;IACxC,yGAAyG;IACzG,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C;AAED,mGAAmG;AACnG,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED;;;;GAIG;AACH,8BAAsB,iBAAiB;IACnC,SAAS,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAQ;IAEtD,+GAA+G;IAC/G,aAAoB,WAAW,IAAI,MAAM,CAAC;IAE1C,2GAA2G;IAC3G,aAAoB,cAAc,IAAI,MAAM,CAAC;IAE7C,0DAA0D;IAC1D,aAAoB,YAAY,IAAI,MAAM,CAAC;IAE3C,4FAA4F;aAC5E,kBAAkB,IAAI,2BAA2B,EAAE;IAEnE;;;;OAIG;aACa,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAE1E,qGAAqG;aACrF,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAEpD,yEAAyE;IAClE,UAAU,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAItD,2EAA2E;IACpE,OAAO,IAAI,IAAI;CAGzB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Framework-free interactive-channel contract for the public web widget.
|
|
3
|
+
*
|
|
4
|
+
* MJ's realtime co-agent stack supports interactive CHANNELS — agent-driven surfaces (Whiteboard,
|
|
5
|
+
* Remote Browser, Media) the model manipulates via client-executed tools while it talks. The shipped
|
|
6
|
+
* channel clients live in `@memberjunction/ng-conversations` and render ANGULAR components, so they
|
|
7
|
+
* can't mount inside this dependency-free, shadow-DOM widget. This module defines the equivalent
|
|
8
|
+
* **framework-free** channel contract: a channel declares client tools, applies the model's tool calls
|
|
9
|
+
* to a surface it renders into a plain `HTMLElement`, and feeds user activity back as perception notes.
|
|
10
|
+
*
|
|
11
|
+
* Channels are resolved at runtime via `MJGlobal.ClassFactory` keyed by channel name — exactly how the
|
|
12
|
+
* voice controller resolves the realtime driver — so adding a channel is a `@RegisterClass` + a Load()
|
|
13
|
+
* call, with no widget-core changes. Which channels a given widget may attach is gated by the widget
|
|
14
|
+
* instance's `EnabledChannels`.
|
|
15
|
+
*
|
|
16
|
+
* @module @memberjunction/realtime-widget
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Base class for a framework-free widget interactive channel. Concrete channels (e.g. the Whiteboard)
|
|
20
|
+
* subclass this and register with `@RegisterClass(BaseWidgetChannel, '<ChannelName>')`. Resolved via
|
|
21
|
+
* `MJGlobal.ClassFactory.CreateInstance(BaseWidgetChannel, channelName)`.
|
|
22
|
+
*/
|
|
23
|
+
export class BaseWidgetChannel {
|
|
24
|
+
constructor() {
|
|
25
|
+
this.context = null;
|
|
26
|
+
}
|
|
27
|
+
/** Wires the perception seam. Called once before the first tool call. */
|
|
28
|
+
Initialize(context) {
|
|
29
|
+
this.context = context;
|
|
30
|
+
}
|
|
31
|
+
/** Tears down the surface + subscriptions. Default: clears the context. */
|
|
32
|
+
Dispose() {
|
|
33
|
+
this.context = null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=base-widget-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-widget-channel.js","sourceRoot":"","sources":["../../../src/voice/channels/base-widget-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAqBH;;;;GAIG;AACH,MAAM,OAAgB,iBAAiB;IAAvC;QACc,YAAO,GAAgC,IAAI,CAAC;IAiC1D,CAAC;IATG,yEAAyE;IAClE,UAAU,CAAC,OAA6B;QAC3C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAED,2EAA2E;IACpE,OAAO;QACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACxB,CAAC;CACJ"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Framework-free **Whiteboard** interactive channel for the public web widget — the
|
|
3
|
+
* worked example that makes "the mic opens MJ channel support" literally true. While voice is active,
|
|
4
|
+
* the agent can sketch/annotate a shared canvas the visitor watches fill in.
|
|
5
|
+
*
|
|
6
|
+
* It speaks the SAME channel protocol as Explorer's `RealtimeWhiteboardChannel` (a `Whiteboard_`-prefixed
|
|
7
|
+
* client tool set the model calls), but renders to a dependency-free inline-SVG surface instead of the
|
|
8
|
+
* Angular host component — so it mounts inside the widget's shadow DOM with zero framework weight. The
|
|
9
|
+
* coordinate space is a fixed 1000×600 viewBox the SVG scales to its container.
|
|
10
|
+
*
|
|
11
|
+
* @module @memberjunction/realtime-widget
|
|
12
|
+
*/
|
|
13
|
+
import { BaseWidgetChannel, type WidgetChannelToolDefinition } from './base-widget-channel.js';
|
|
14
|
+
/**
|
|
15
|
+
* The framework-free Whiteboard channel. Renders agent-issued shapes/text into an inline SVG and
|
|
16
|
+
* reports each applied tool back to the model. Resolved via ClassFactory by the channel name.
|
|
17
|
+
*/
|
|
18
|
+
export declare class WidgetWhiteboardChannel extends BaseWidgetChannel {
|
|
19
|
+
private svg;
|
|
20
|
+
private shapeCount;
|
|
21
|
+
get ChannelName(): string;
|
|
22
|
+
get ToolNamePrefix(): string;
|
|
23
|
+
get SurfaceTitle(): string;
|
|
24
|
+
GetToolDefinitions(): WidgetChannelToolDefinition[];
|
|
25
|
+
ApplyAgentTool(toolName: string, argsJson: string): string;
|
|
26
|
+
BindSurface(host: HTMLElement): void;
|
|
27
|
+
Dispose(): void;
|
|
28
|
+
private addText;
|
|
29
|
+
private drawRect;
|
|
30
|
+
private drawLine;
|
|
31
|
+
private drawCircle;
|
|
32
|
+
private clear;
|
|
33
|
+
/** Appends an SVG node, bumps the shape count, notes the activity, and returns the result JSON. */
|
|
34
|
+
private add;
|
|
35
|
+
}
|
|
36
|
+
/** Tree-shaking guard — importing this module performs the `@RegisterClass` registration as a side effect. */
|
|
37
|
+
export declare function LoadWidgetWhiteboardChannel(): void;
|
|
38
|
+
//# sourceMappingURL=whiteboard-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whiteboard-channel.d.ts","sourceRoot":"","sources":["../../../src/voice/channels/whiteboard-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,iBAAiB,EAAE,KAAK,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAuB/F;;;GAGG;AACH,qBACa,uBAAwB,SAAQ,iBAAiB;IAC1D,OAAO,CAAC,GAAG,CAA8B;IACzC,OAAO,CAAC,UAAU,CAAK;IAEvB,IAAW,WAAW,IAAI,MAAM,CAE/B;IACD,IAAW,cAAc,IAAI,MAAM,CAElC;IACD,IAAW,YAAY,IAAI,MAAM,CAEhC;IAEM,kBAAkB,IAAI,2BAA2B,EAAE;IA4CnD,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IA2B1D,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAa3B,OAAO,IAAI,IAAI;IAQ/B,OAAO,CAAC,OAAO;IAcf,OAAO,CAAC,QAAQ;IAYhB,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,KAAK;IAQb,mGAAmG;IACnG,OAAO,CAAC,GAAG;CAOd;AAED,8GAA8G;AAC9G,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Framework-free **Whiteboard** interactive channel for the public web widget — the
|
|
3
|
+
* worked example that makes "the mic opens MJ channel support" literally true. While voice is active,
|
|
4
|
+
* the agent can sketch/annotate a shared canvas the visitor watches fill in.
|
|
5
|
+
*
|
|
6
|
+
* It speaks the SAME channel protocol as Explorer's `RealtimeWhiteboardChannel` (a `Whiteboard_`-prefixed
|
|
7
|
+
* client tool set the model calls), but renders to a dependency-free inline-SVG surface instead of the
|
|
8
|
+
* Angular host component — so it mounts inside the widget's shadow DOM with zero framework weight. The
|
|
9
|
+
* coordinate space is a fixed 1000×600 viewBox the SVG scales to its container.
|
|
10
|
+
*
|
|
11
|
+
* @module @memberjunction/realtime-widget
|
|
12
|
+
*/
|
|
13
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
14
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
15
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
16
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
17
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
18
|
+
};
|
|
19
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
20
|
+
import { BaseWidgetChannel } from './base-widget-channel.js';
|
|
21
|
+
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
22
|
+
const VIEWBOX_WIDTH = 1000;
|
|
23
|
+
const VIEWBOX_HEIGHT = 600;
|
|
24
|
+
/** Channel name + tool prefix — kept in sync with the `MJ: AI Agent Channels` "Whiteboard" row. */
|
|
25
|
+
const CHANNEL_NAME = 'Whiteboard';
|
|
26
|
+
const TOOL_PREFIX = 'Whiteboard_';
|
|
27
|
+
const DEFAULT_STROKE = '#264FAF';
|
|
28
|
+
/** A number-or-undefined coercion that tolerates the model sending numbers as strings. */
|
|
29
|
+
function num(value, fallback = 0) {
|
|
30
|
+
const n = typeof value === 'string' ? Number(value) : typeof value === 'number' ? value : NaN;
|
|
31
|
+
return Number.isFinite(n) ? n : fallback;
|
|
32
|
+
}
|
|
33
|
+
/** Coerces a model-supplied color to a safe string (rejects anything but a short hex / css-name token). */
|
|
34
|
+
function safeColor(value) {
|
|
35
|
+
return typeof value === 'string' && /^#[0-9a-fA-F]{3,8}$|^[a-zA-Z]{3,20}$/.test(value.trim())
|
|
36
|
+
? value.trim()
|
|
37
|
+
: DEFAULT_STROKE;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The framework-free Whiteboard channel. Renders agent-issued shapes/text into an inline SVG and
|
|
41
|
+
* reports each applied tool back to the model. Resolved via ClassFactory by the channel name.
|
|
42
|
+
*/
|
|
43
|
+
let WidgetWhiteboardChannel = class WidgetWhiteboardChannel extends BaseWidgetChannel {
|
|
44
|
+
constructor() {
|
|
45
|
+
super(...arguments);
|
|
46
|
+
this.svg = null;
|
|
47
|
+
this.shapeCount = 0;
|
|
48
|
+
}
|
|
49
|
+
get ChannelName() {
|
|
50
|
+
return CHANNEL_NAME;
|
|
51
|
+
}
|
|
52
|
+
get ToolNamePrefix() {
|
|
53
|
+
return TOOL_PREFIX;
|
|
54
|
+
}
|
|
55
|
+
get SurfaceTitle() {
|
|
56
|
+
return 'Whiteboard';
|
|
57
|
+
}
|
|
58
|
+
GetToolDefinitions() {
|
|
59
|
+
const xy = { x: { type: 'number' }, y: { type: 'number' } };
|
|
60
|
+
const color = { color: { type: 'string', description: 'Hex (e.g. #264FAF) or CSS color name.' } };
|
|
61
|
+
return [
|
|
62
|
+
{
|
|
63
|
+
Name: `${TOOL_PREFIX}AddText`,
|
|
64
|
+
Description: 'Write a line of text on the shared whiteboard at (x,y) in a 1000x600 canvas.',
|
|
65
|
+
ParametersSchema: { type: 'object', properties: { ...xy, text: { type: 'string' }, ...color }, required: ['x', 'y', 'text'] },
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
Name: `${TOOL_PREFIX}DrawRect`,
|
|
69
|
+
Description: 'Draw a rectangle outline at (x,y) with width/height on the 1000x600 canvas.',
|
|
70
|
+
ParametersSchema: {
|
|
71
|
+
type: 'object',
|
|
72
|
+
properties: { ...xy, width: { type: 'number' }, height: { type: 'number' }, ...color },
|
|
73
|
+
required: ['x', 'y', 'width', 'height'],
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
Name: `${TOOL_PREFIX}DrawLine`,
|
|
78
|
+
Description: 'Draw a line from (x1,y1) to (x2,y2) on the 1000x600 canvas.',
|
|
79
|
+
ParametersSchema: {
|
|
80
|
+
type: 'object',
|
|
81
|
+
properties: { x1: { type: 'number' }, y1: { type: 'number' }, x2: { type: 'number' }, y2: { type: 'number' }, ...color },
|
|
82
|
+
required: ['x1', 'y1', 'x2', 'y2'],
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
Name: `${TOOL_PREFIX}DrawCircle`,
|
|
87
|
+
Description: 'Draw a circle outline centered at (cx,cy) with radius r on the 1000x600 canvas.',
|
|
88
|
+
ParametersSchema: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: { cx: { type: 'number' }, cy: { type: 'number' }, r: { type: 'number' }, ...color },
|
|
91
|
+
required: ['cx', 'cy', 'r'],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
Name: `${TOOL_PREFIX}Clear`,
|
|
96
|
+
Description: 'Erase everything on the whiteboard.',
|
|
97
|
+
ParametersSchema: { type: 'object', properties: {} },
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
ApplyAgentTool(toolName, argsJson) {
|
|
102
|
+
if (!this.svg) {
|
|
103
|
+
return JSON.stringify({ error: 'whiteboard surface not ready' });
|
|
104
|
+
}
|
|
105
|
+
let args;
|
|
106
|
+
try {
|
|
107
|
+
args = argsJson ? JSON.parse(argsJson) : {};
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return JSON.stringify({ error: 'invalid tool arguments JSON' });
|
|
111
|
+
}
|
|
112
|
+
const bare = toolName.startsWith(TOOL_PREFIX) ? toolName.slice(TOOL_PREFIX.length) : toolName;
|
|
113
|
+
switch (bare) {
|
|
114
|
+
case 'AddText':
|
|
115
|
+
return this.addText(args);
|
|
116
|
+
case 'DrawRect':
|
|
117
|
+
return this.drawRect(args);
|
|
118
|
+
case 'DrawLine':
|
|
119
|
+
return this.drawLine(args);
|
|
120
|
+
case 'DrawCircle':
|
|
121
|
+
return this.drawCircle(args);
|
|
122
|
+
case 'Clear':
|
|
123
|
+
return this.clear();
|
|
124
|
+
default:
|
|
125
|
+
return JSON.stringify({ error: `unknown whiteboard tool: ${toolName}` });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
BindSurface(host) {
|
|
129
|
+
host.innerHTML = '';
|
|
130
|
+
const svg = document.createElementNS(SVG_NS, 'svg');
|
|
131
|
+
svg.setAttribute('viewBox', `0 0 ${VIEWBOX_WIDTH} ${VIEWBOX_HEIGHT}`);
|
|
132
|
+
svg.setAttribute('width', '100%');
|
|
133
|
+
svg.setAttribute('height', '100%');
|
|
134
|
+
svg.setAttribute('role', 'img');
|
|
135
|
+
svg.setAttribute('aria-label', 'Shared whiteboard the assistant draws on');
|
|
136
|
+
host.appendChild(svg);
|
|
137
|
+
this.svg = svg;
|
|
138
|
+
this.shapeCount = 0;
|
|
139
|
+
}
|
|
140
|
+
Dispose() {
|
|
141
|
+
this.svg = null;
|
|
142
|
+
this.shapeCount = 0;
|
|
143
|
+
super.Dispose();
|
|
144
|
+
}
|
|
145
|
+
// ── tool handlers ───────────────────────────────────────────────────────────
|
|
146
|
+
addText(args) {
|
|
147
|
+
const text = typeof args.text === 'string' ? args.text : '';
|
|
148
|
+
if (!text) {
|
|
149
|
+
return JSON.stringify({ error: 'text is required' });
|
|
150
|
+
}
|
|
151
|
+
const el = document.createElementNS(SVG_NS, 'text');
|
|
152
|
+
el.setAttribute('x', String(num(args.x)));
|
|
153
|
+
el.setAttribute('y', String(num(args.y)));
|
|
154
|
+
el.setAttribute('fill', safeColor(args.color));
|
|
155
|
+
el.setAttribute('font-size', '24');
|
|
156
|
+
el.textContent = text;
|
|
157
|
+
return this.add(el, `wrote "${text}"`);
|
|
158
|
+
}
|
|
159
|
+
drawRect(args) {
|
|
160
|
+
const el = document.createElementNS(SVG_NS, 'rect');
|
|
161
|
+
el.setAttribute('x', String(num(args.x)));
|
|
162
|
+
el.setAttribute('y', String(num(args.y)));
|
|
163
|
+
el.setAttribute('width', String(num(args.width)));
|
|
164
|
+
el.setAttribute('height', String(num(args.height)));
|
|
165
|
+
el.setAttribute('fill', 'none');
|
|
166
|
+
el.setAttribute('stroke', safeColor(args.color));
|
|
167
|
+
el.setAttribute('stroke-width', '3');
|
|
168
|
+
return this.add(el, 'drew a rectangle');
|
|
169
|
+
}
|
|
170
|
+
drawLine(args) {
|
|
171
|
+
const el = document.createElementNS(SVG_NS, 'line');
|
|
172
|
+
el.setAttribute('x1', String(num(args.x1)));
|
|
173
|
+
el.setAttribute('y1', String(num(args.y1)));
|
|
174
|
+
el.setAttribute('x2', String(num(args.x2)));
|
|
175
|
+
el.setAttribute('y2', String(num(args.y2)));
|
|
176
|
+
el.setAttribute('stroke', safeColor(args.color));
|
|
177
|
+
el.setAttribute('stroke-width', '3');
|
|
178
|
+
return this.add(el, 'drew a line');
|
|
179
|
+
}
|
|
180
|
+
drawCircle(args) {
|
|
181
|
+
const el = document.createElementNS(SVG_NS, 'circle');
|
|
182
|
+
el.setAttribute('cx', String(num(args.cx)));
|
|
183
|
+
el.setAttribute('cy', String(num(args.cy)));
|
|
184
|
+
el.setAttribute('r', String(num(args.r)));
|
|
185
|
+
el.setAttribute('fill', 'none');
|
|
186
|
+
el.setAttribute('stroke', safeColor(args.color));
|
|
187
|
+
el.setAttribute('stroke-width', '3');
|
|
188
|
+
return this.add(el, 'drew a circle');
|
|
189
|
+
}
|
|
190
|
+
clear() {
|
|
191
|
+
if (this.svg) {
|
|
192
|
+
this.svg.innerHTML = '';
|
|
193
|
+
}
|
|
194
|
+
this.shapeCount = 0;
|
|
195
|
+
return JSON.stringify({ ok: true, cleared: true });
|
|
196
|
+
}
|
|
197
|
+
/** Appends an SVG node, bumps the shape count, notes the activity, and returns the result JSON. */
|
|
198
|
+
add(node, description) {
|
|
199
|
+
this.svg.appendChild(node);
|
|
200
|
+
this.shapeCount++;
|
|
201
|
+
// No perception note here: the AGENT issued this, so it already knows. SendContextNote is for
|
|
202
|
+
// USER-originated activity (a later enhancement once the surface accepts visitor input).
|
|
203
|
+
return JSON.stringify({ ok: true, action: description, shapeCount: this.shapeCount });
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
WidgetWhiteboardChannel = __decorate([
|
|
207
|
+
RegisterClass(BaseWidgetChannel, CHANNEL_NAME)
|
|
208
|
+
], WidgetWhiteboardChannel);
|
|
209
|
+
export { WidgetWhiteboardChannel };
|
|
210
|
+
/** Tree-shaking guard — importing this module performs the `@RegisterClass` registration as a side effect. */
|
|
211
|
+
export function LoadWidgetWhiteboardChannel() {
|
|
212
|
+
/* intentional no-op */
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=whiteboard-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whiteboard-channel.js","sourceRoot":"","sources":["../../../src/voice/channels/whiteboard-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Resolves + coordinates the interactive channels a widget voice session may attach.
|
|
3
|
+
*
|
|
4
|
+
* Built from the minted session's `enabledChannels` (which mirrors the widget instance's
|
|
5
|
+
* `EnabledChannels`), it resolves each named channel to a framework-free {@link BaseWidgetChannel}
|
|
6
|
+
* via `MJGlobal.ClassFactory` — exactly how the voice controller resolves the realtime driver — and
|
|
7
|
+
* then: aggregates their client-tool definitions (declared to the model at mint), routes the model's
|
|
8
|
+
* channel-prefixed tool calls to the owning channel (the rest are relayed to the server by the
|
|
9
|
+
* controller), and binds each channel's surface into the widget's demonstration slot on first use.
|
|
10
|
+
*
|
|
11
|
+
* An empty `enabledChannels` (the default for every widget) yields an inert host: no tools, no surface,
|
|
12
|
+
* no behavior change — so channels are strictly opt-in per widget instance.
|
|
13
|
+
*
|
|
14
|
+
* @module @memberjunction/realtime-widget
|
|
15
|
+
*/
|
|
16
|
+
import { BaseWidgetChannel, type WidgetChannelContext, type WidgetChannelToolDefinition } from './base-widget-channel.js';
|
|
17
|
+
/** Result of routing a tool call through the host. */
|
|
18
|
+
export interface ChannelToolRouteResult {
|
|
19
|
+
/** Whether a channel owned (and applied) the tool. When false, the caller relays it to the server. */
|
|
20
|
+
handled: boolean;
|
|
21
|
+
/** The channel's result JSON (present when `handled`). */
|
|
22
|
+
resultJson?: string;
|
|
23
|
+
/** The channel that handled it (present when `handled`) — lets the controller reveal its surface. */
|
|
24
|
+
channel?: BaseWidgetChannel;
|
|
25
|
+
}
|
|
26
|
+
/** Coordinates the set of interactive channels enabled for a voice session. */
|
|
27
|
+
export declare class WidgetChannelHost {
|
|
28
|
+
private readonly context;
|
|
29
|
+
private readonly channels;
|
|
30
|
+
private boundChannels;
|
|
31
|
+
/**
|
|
32
|
+
* @param enabledChannels Channel names the widget instance allows (from the minted session).
|
|
33
|
+
* @param context The perception seam channels use to feed the model (channel → agent notes).
|
|
34
|
+
*/
|
|
35
|
+
constructor(enabledChannels: readonly string[], context: WidgetChannelContext);
|
|
36
|
+
/** True when at least one enabled channel resolved (so the controller declares tools + shows the surface). */
|
|
37
|
+
get HasChannels(): boolean;
|
|
38
|
+
/** The resolved channels (read-only) — used to build/reveal their surfaces. */
|
|
39
|
+
get Channels(): readonly BaseWidgetChannel[];
|
|
40
|
+
/** Every enabled channel's client-tool definitions, flattened — declared to the model at session mint. */
|
|
41
|
+
GetToolDefinitions(): WidgetChannelToolDefinition[];
|
|
42
|
+
/**
|
|
43
|
+
* The channel that owns a tool name (matched by prefix), or `undefined` when none does (the caller
|
|
44
|
+
* then relays the tool to the server). Pure lookup — does NOT apply the tool, so the caller can bind
|
|
45
|
+
* the channel's surface before applying.
|
|
46
|
+
*/
|
|
47
|
+
FindChannel(toolName: string): BaseWidgetChannel | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Routes a model tool call to the owning channel and APPLIES it. Returns `{ handled: false }` when
|
|
50
|
+
* no channel owns it. Convenience for callers that have already bound surfaces (and for tests).
|
|
51
|
+
*/
|
|
52
|
+
RouteTool(toolName: string, argsJson: string): ChannelToolRouteResult;
|
|
53
|
+
/**
|
|
54
|
+
* Binds a channel's surface into a host element, once. The caller supplies a factory that creates/
|
|
55
|
+
* returns the host element for a given channel name (the widget's demonstration slot). Idempotent.
|
|
56
|
+
*/
|
|
57
|
+
BindSurface(channel: BaseWidgetChannel, host: HTMLElement): void;
|
|
58
|
+
/** Disposes every channel (clears surfaces + perception subscriptions). */
|
|
59
|
+
Dispose(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Resolves one channel name to an instance via ClassFactory; returns null (logged) when no channel
|
|
62
|
+
* is registered for the key. The explicit `GetRegistration` check is REQUIRED: ClassFactory falls
|
|
63
|
+
* back to the highest-priority registration for the base class when a key is unknown, so without it
|
|
64
|
+
* an unrecognized channel name would silently resolve to some other channel.
|
|
65
|
+
*/
|
|
66
|
+
private resolveChannel;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=widget-channel-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-channel-host.d.ts","sourceRoot":"","sources":["../../../src/voice/channels/widget-channel-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAE1H,sDAAsD;AACtD,MAAM,WAAW,sBAAsB;IACnC,sGAAsG;IACtG,OAAO,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,+EAA+E;AAC/E,qBAAa,iBAAiB;IAQsB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPxE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,aAAa,CAAqB;IAE1C;;;OAGG;gBACS,eAAe,EAAE,SAAS,MAAM,EAAE,EAAmB,OAAO,EAAE,oBAAoB;IAU9F,8GAA8G;IAC9G,IAAW,WAAW,IAAI,OAAO,CAEhC;IAED,+EAA+E;IAC/E,IAAW,QAAQ,IAAI,SAAS,iBAAiB,EAAE,CAElD;IAED,0GAA0G;IACnG,kBAAkB,IAAI,2BAA2B,EAAE;IAI1D;;;;OAIG;IACI,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAInE;;;OAGG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,sBAAsB;IAQ5E;;;OAGG;IACI,WAAW,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI;IAQvE,2EAA2E;IACpE,OAAO,IAAI,IAAI;IAQtB;;;;;OAKG;IACH,OAAO,CAAC,cAAc;CAkBzB"}
|