@memberjunction/realtime-widget 0.0.0 → 5.45.0
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,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Mints + refreshes the guest session by calling MJAPI's public
|
|
3
|
+
* `POST /widget/session` endpoint. The token is auth state (not a user preference),
|
|
4
|
+
* so holding it in memory / sessionStorage is acceptable (CLAUDE rule 9) — but this
|
|
5
|
+
* client keeps it only in memory and refreshes before expiry.
|
|
6
|
+
*
|
|
7
|
+
* @module @memberjunction/realtime-widget
|
|
8
|
+
*/
|
|
9
|
+
import type { WidgetSession } from '../types.js';
|
|
10
|
+
/** Injectable fetch so the client is unit-testable without a network. Defaults to global fetch. */
|
|
11
|
+
export type FetchLike = (input: string, init?: RequestInit) => Promise<{
|
|
12
|
+
ok: boolean;
|
|
13
|
+
status: number;
|
|
14
|
+
json: () => Promise<unknown>;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* Talks to the widget guest-session endpoints. One instance per mounted widget.
|
|
18
|
+
*/
|
|
19
|
+
export declare class WidgetSessionClient {
|
|
20
|
+
private readonly apiUrl;
|
|
21
|
+
private readonly widgetKey;
|
|
22
|
+
private readonly fetchImpl;
|
|
23
|
+
constructor(apiUrl: string, widgetKey: string, fetchImpl?: FetchLike);
|
|
24
|
+
/**
|
|
25
|
+
* Mints a fresh guest session. Throws on a non-2xx / unsuccessful response.
|
|
26
|
+
* @param visitorKey the durable returning-visitor anchor from the first-party cookie, if present —
|
|
27
|
+
* the server uses it to chain this visit to the visitor's prior conversation (gated on the widget's
|
|
28
|
+
* RememberReturningVisitors toggle). Omit on a first visit; the server mints one when remembering is on.
|
|
29
|
+
*/
|
|
30
|
+
Mint(visitorKey?: string): Promise<WidgetSession>;
|
|
31
|
+
/** Refreshes the guest session (server re-mints by the same key). Carries the visitor anchor so the
|
|
32
|
+
* refreshed session keeps the same returning-visitor identity. */
|
|
33
|
+
Refresh(visitorKey?: string): Promise<WidgetSession>;
|
|
34
|
+
/**
|
|
35
|
+
* W5 magic-link upgrade ("Verify it's you"): asks the server to email a verification link scoped to
|
|
36
|
+
* the widget's app. On success the visitor receives an email; clicking it redeems a VERIFIED session
|
|
37
|
+
* JWT (via the existing `/magic-link/redeem`). The host page hands that token back to the widget,
|
|
38
|
+
* which calls `transport.UpdateToken(verifiedToken)` to swap it in — the live conversationId is
|
|
39
|
+
* preserved because the transport holds it. Never throws; returns a structured result for the UI.
|
|
40
|
+
*/
|
|
41
|
+
RequestUpgrade(email: string): Promise<{
|
|
42
|
+
success: boolean;
|
|
43
|
+
emailSent?: boolean;
|
|
44
|
+
error?: string;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* RV5 "forget me": asks the server to archive this visitor's memory and clear the VisitorKey
|
|
48
|
+
* linkage. The caller is responsible for clearing the durable cookie afterward
|
|
49
|
+
* (`clearVisitorKey`). Public endpoint — the durable key is the proof. Never throws.
|
|
50
|
+
*/
|
|
51
|
+
Forget(visitorKey: string): Promise<{
|
|
52
|
+
success: boolean;
|
|
53
|
+
notesArchived?: number;
|
|
54
|
+
error?: string;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* RV4 (magic-link upgrade path): after the visitor verifies and the widget swaps in the VERIFIED
|
|
58
|
+
* token, promote their anonymous returning-visitor trail to the verified record. AUTHENTICATED —
|
|
59
|
+
* the verified token is sent as a Bearer credential; the server reads the verified email from it.
|
|
60
|
+
* Never throws; returns a structured result.
|
|
61
|
+
*/
|
|
62
|
+
ResolveIdentity(verifiedToken: string, visitorKey: string): Promise<{
|
|
63
|
+
success: boolean;
|
|
64
|
+
mergedConversations?: number;
|
|
65
|
+
error?: string;
|
|
66
|
+
}>;
|
|
67
|
+
/** Milliseconds until the given session should be refreshed (never negative). */
|
|
68
|
+
static MsUntilRefresh(session: WidgetSession, nowMs: number): number;
|
|
69
|
+
private call;
|
|
70
|
+
/** Maps the API response to the in-memory session, validating required fields. */
|
|
71
|
+
private toSession;
|
|
72
|
+
private trimmedApiUrl;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=widget-session-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-session-client.d.ts","sourceRoot":"","sources":["../../src/session/widget-session-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAkB,aAAa,EAAyB,MAAM,aAAa,CAAC;AAExF,mGAAmG;AACnG,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC;IACnE,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CAChC,CAAC,CAAC;AAKH;;GAEG;AACH,qBAAa,mBAAmB;IAIxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;gBAGjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EAClC,SAAS,CAAC,EAAE,SAAS;IAMzB;;;;;OAKG;IACU,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAI9D;uEACmE;IACtD,OAAO,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAIjE;;;;;;OAMG;IACU,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAiB9G;;;;OAIG;IACU,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAiB9G;;;;;OAKG;IACU,eAAe,CACxB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAiB9E,iFAAiF;WACnE,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;YAI7D,IAAI;IAalB,kFAAkF;IAClF,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,aAAa;CAGxB"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Mints + refreshes the guest session by calling MJAPI's public
|
|
3
|
+
* `POST /widget/session` endpoint. The token is auth state (not a user preference),
|
|
4
|
+
* so holding it in memory / sessionStorage is acceptable (CLAUDE rule 9) — but this
|
|
5
|
+
* client keeps it only in memory and refreshes before expiry.
|
|
6
|
+
*
|
|
7
|
+
* @module @memberjunction/realtime-widget
|
|
8
|
+
*/
|
|
9
|
+
/** How early (ms before expiry) to proactively refresh the guest token. */
|
|
10
|
+
const REFRESH_LEAD_MS = 60_000;
|
|
11
|
+
/**
|
|
12
|
+
* Talks to the widget guest-session endpoints. One instance per mounted widget.
|
|
13
|
+
*/
|
|
14
|
+
export class WidgetSessionClient {
|
|
15
|
+
constructor(apiUrl, widgetKey, fetchImpl) {
|
|
16
|
+
this.apiUrl = apiUrl;
|
|
17
|
+
this.widgetKey = widgetKey;
|
|
18
|
+
// happy fallback to the platform fetch; explicit in tests.
|
|
19
|
+
this.fetchImpl = fetchImpl ?? ((input, init) => fetch(input, init));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Mints a fresh guest session. Throws on a non-2xx / unsuccessful response.
|
|
23
|
+
* @param visitorKey the durable returning-visitor anchor from the first-party cookie, if present —
|
|
24
|
+
* the server uses it to chain this visit to the visitor's prior conversation (gated on the widget's
|
|
25
|
+
* RememberReturningVisitors toggle). Omit on a first visit; the server mints one when remembering is on.
|
|
26
|
+
*/
|
|
27
|
+
async Mint(visitorKey) {
|
|
28
|
+
return this.call('/widget/session', visitorKey);
|
|
29
|
+
}
|
|
30
|
+
/** Refreshes the guest session (server re-mints by the same key). Carries the visitor anchor so the
|
|
31
|
+
* refreshed session keeps the same returning-visitor identity. */
|
|
32
|
+
async Refresh(visitorKey) {
|
|
33
|
+
return this.call('/widget/session/refresh', visitorKey);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* W5 magic-link upgrade ("Verify it's you"): asks the server to email a verification link scoped to
|
|
37
|
+
* the widget's app. On success the visitor receives an email; clicking it redeems a VERIFIED session
|
|
38
|
+
* JWT (via the existing `/magic-link/redeem`). The host page hands that token back to the widget,
|
|
39
|
+
* which calls `transport.UpdateToken(verifiedToken)` to swap it in — the live conversationId is
|
|
40
|
+
* preserved because the transport holds it. Never throws; returns a structured result for the UI.
|
|
41
|
+
*/
|
|
42
|
+
async RequestUpgrade(email) {
|
|
43
|
+
try {
|
|
44
|
+
const res = await this.fetchImpl(`${this.trimmedApiUrl()}/widget/upgrade`, {
|
|
45
|
+
method: 'POST',
|
|
46
|
+
headers: { 'content-type': 'application/json' },
|
|
47
|
+
body: JSON.stringify({ widgetKey: this.widgetKey, email }),
|
|
48
|
+
});
|
|
49
|
+
const body = (await res.json());
|
|
50
|
+
if (!res.ok || !body?.success) {
|
|
51
|
+
return { success: false, error: body?.error ?? body?.errorCode ?? 'Could not start verification.' };
|
|
52
|
+
}
|
|
53
|
+
return { success: true, emailSent: body.emailSent };
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
return { success: false, error: err instanceof Error ? err.message : 'Could not start verification.' };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* RV5 "forget me": asks the server to archive this visitor's memory and clear the VisitorKey
|
|
61
|
+
* linkage. The caller is responsible for clearing the durable cookie afterward
|
|
62
|
+
* (`clearVisitorKey`). Public endpoint — the durable key is the proof. Never throws.
|
|
63
|
+
*/
|
|
64
|
+
async Forget(visitorKey) {
|
|
65
|
+
try {
|
|
66
|
+
const res = await this.fetchImpl(`${this.trimmedApiUrl()}/widget/forget`, {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
headers: { 'content-type': 'application/json' },
|
|
69
|
+
body: JSON.stringify({ widgetKey: this.widgetKey, visitorKey }),
|
|
70
|
+
});
|
|
71
|
+
const body = (await res.json());
|
|
72
|
+
if (!res.ok || !body?.success) {
|
|
73
|
+
return { success: false, error: body?.error ?? body?.errorCode ?? 'Could not forget this visitor.' };
|
|
74
|
+
}
|
|
75
|
+
return { success: true, notesArchived: body.notesArchived };
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
return { success: false, error: err instanceof Error ? err.message : 'Could not forget this visitor.' };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* RV4 (magic-link upgrade path): after the visitor verifies and the widget swaps in the VERIFIED
|
|
83
|
+
* token, promote their anonymous returning-visitor trail to the verified record. AUTHENTICATED —
|
|
84
|
+
* the verified token is sent as a Bearer credential; the server reads the verified email from it.
|
|
85
|
+
* Never throws; returns a structured result.
|
|
86
|
+
*/
|
|
87
|
+
async ResolveIdentity(verifiedToken, visitorKey) {
|
|
88
|
+
try {
|
|
89
|
+
const res = await this.fetchImpl(`${this.trimmedApiUrl()}/widget/resolve-identity`, {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: { 'content-type': 'application/json', authorization: `Bearer ${verifiedToken}` },
|
|
92
|
+
body: JSON.stringify({ widgetKey: this.widgetKey, visitorKey }),
|
|
93
|
+
});
|
|
94
|
+
const body = (await res.json());
|
|
95
|
+
if (!res.ok || !body?.success) {
|
|
96
|
+
return { success: false, error: body?.error ?? body?.errorCode ?? 'Could not resolve identity.' };
|
|
97
|
+
}
|
|
98
|
+
return { success: true, mergedConversations: body.mergedConversations };
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
return { success: false, error: err instanceof Error ? err.message : 'Could not resolve identity.' };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Milliseconds until the given session should be refreshed (never negative). */
|
|
105
|
+
static MsUntilRefresh(session, nowMs) {
|
|
106
|
+
return Math.max(0, session.expiresAtMs - nowMs - REFRESH_LEAD_MS);
|
|
107
|
+
}
|
|
108
|
+
async call(path, visitorKey) {
|
|
109
|
+
const res = await this.fetchImpl(`${this.trimmedApiUrl()}${path}`, {
|
|
110
|
+
method: 'POST',
|
|
111
|
+
headers: { 'content-type': 'application/json' },
|
|
112
|
+
body: JSON.stringify(visitorKey ? { widgetKey: this.widgetKey, visitorKey } : { widgetKey: this.widgetKey }),
|
|
113
|
+
});
|
|
114
|
+
const body = (await res.json());
|
|
115
|
+
if (!res.ok || !body?.success || !body.token) {
|
|
116
|
+
throw new Error(`Widget session mint failed (${res.status}): ${body?.errorCode ?? body?.error ?? 'unknown'}`);
|
|
117
|
+
}
|
|
118
|
+
return this.toSession(body);
|
|
119
|
+
}
|
|
120
|
+
/** Maps the API response to the in-memory session, validating required fields. */
|
|
121
|
+
toSession(body) {
|
|
122
|
+
if (!body.widgetId || !body.applicationId || !body.pinnedAgentId) {
|
|
123
|
+
throw new Error('Widget session response missing required fields (widgetId/applicationId/pinnedAgentId).');
|
|
124
|
+
}
|
|
125
|
+
const expiresAtMs = body.expiresAt ? Date.parse(body.expiresAt) : Number.NaN;
|
|
126
|
+
return {
|
|
127
|
+
token: body.token,
|
|
128
|
+
expiresAtMs: Number.isFinite(expiresAtMs) ? expiresAtMs : Date.now() + 15 * 60_000,
|
|
129
|
+
widgetId: body.widgetId,
|
|
130
|
+
applicationId: body.applicationId,
|
|
131
|
+
pinnedAgentId: body.pinnedAgentId,
|
|
132
|
+
modality: (body.modality ?? 'Text'),
|
|
133
|
+
sessionId: body.sessionId ?? '',
|
|
134
|
+
voiceMaxSessionMinutes: body.voiceMaxSessionMinutes,
|
|
135
|
+
rememberReturningVisitors: body.rememberReturningVisitors ?? false,
|
|
136
|
+
visitorKey: body.visitorKey,
|
|
137
|
+
lastConversationId: body.lastConversationId,
|
|
138
|
+
linkedEntityId: body.linkedEntityId,
|
|
139
|
+
linkedRecordId: body.linkedRecordId,
|
|
140
|
+
enabledChannels: Array.isArray(body.enabledChannels) ? body.enabledChannels : [],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
trimmedApiUrl() {
|
|
144
|
+
return this.apiUrl.replace(/\/+$/, '');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=widget-session-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-session-client.js","sourceRoot":"","sources":["../../src/session/widget-session-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview An in-memory transport used by unit tests and the offline example
|
|
3
|
+
* page. It echoes a canned support reply so the widget UI can be exercised without a
|
|
4
|
+
* live MJAPI. NOT used in production (the loader wires RuntimeWidgetTransport).
|
|
5
|
+
*
|
|
6
|
+
* @module @memberjunction/realtime-widget
|
|
7
|
+
*/
|
|
8
|
+
import type { WidgetSession } from '../types.js';
|
|
9
|
+
import type { IWidgetTransport, WidgetProgressCallback, WidgetTurnResult } from './widget-transport.js';
|
|
10
|
+
/** Deterministic, dependency-free transport for tests + the demo host page. */
|
|
11
|
+
export declare class MockWidgetTransport implements IWidgetTransport {
|
|
12
|
+
LastExplicitAgentId: string | null;
|
|
13
|
+
SentMessages: string[];
|
|
14
|
+
private session?;
|
|
15
|
+
private replyFor;
|
|
16
|
+
/** When set, the NEXT SendMessage fails with this error (one-shot) — exercises the offline banner. */
|
|
17
|
+
private failNextError;
|
|
18
|
+
constructor(replyFor?: (text: string) => string);
|
|
19
|
+
/** Arms a one-shot failure on the next SendMessage (test helper for graceful-degradation paths). */
|
|
20
|
+
FailNextSend(error: string): void;
|
|
21
|
+
Initialize(session: WidgetSession): Promise<void>;
|
|
22
|
+
UpdateToken(_token: string): void;
|
|
23
|
+
SendMessage(text: string, onProgress?: WidgetProgressCallback): Promise<WidgetTurnResult>;
|
|
24
|
+
Dispose(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=mock-widget-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-widget-transport.d.ts","sourceRoot":"","sources":["../../src/transport/mock-widget-transport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAExG,+EAA+E;AAC/E,qBAAa,mBAAoB,YAAW,gBAAgB;IACjD,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC1C,YAAY,EAAE,MAAM,EAAE,CAAM;IACnC,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,QAAQ,CAA2B;IAC3C,sGAAsG;IACtG,OAAO,CAAC,aAAa,CAAuB;gBAEhC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;IAI/C,oGAAoG;IAC7F,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI3B,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI3B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAYzF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAGxC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview An in-memory transport used by unit tests and the offline example
|
|
3
|
+
* page. It echoes a canned support reply so the widget UI can be exercised without a
|
|
4
|
+
* live MJAPI. NOT used in production (the loader wires RuntimeWidgetTransport).
|
|
5
|
+
*
|
|
6
|
+
* @module @memberjunction/realtime-widget
|
|
7
|
+
*/
|
|
8
|
+
/** Deterministic, dependency-free transport for tests + the demo host page. */
|
|
9
|
+
export class MockWidgetTransport {
|
|
10
|
+
constructor(replyFor) {
|
|
11
|
+
this.LastExplicitAgentId = null;
|
|
12
|
+
this.SentMessages = [];
|
|
13
|
+
/** When set, the NEXT SendMessage fails with this error (one-shot) — exercises the offline banner. */
|
|
14
|
+
this.failNextError = null;
|
|
15
|
+
this.replyFor = replyFor ?? ((t) => `Thanks for your message: "${t}". A support agent will follow up.`);
|
|
16
|
+
}
|
|
17
|
+
/** Arms a one-shot failure on the next SendMessage (test helper for graceful-degradation paths). */
|
|
18
|
+
FailNextSend(error) {
|
|
19
|
+
this.failNextError = error;
|
|
20
|
+
}
|
|
21
|
+
async Initialize(session) {
|
|
22
|
+
this.session = session;
|
|
23
|
+
}
|
|
24
|
+
UpdateToken(_token) {
|
|
25
|
+
/* no-op for the mock */
|
|
26
|
+
}
|
|
27
|
+
async SendMessage(text, onProgress) {
|
|
28
|
+
this.LastExplicitAgentId = this.session?.pinnedAgentId ?? null;
|
|
29
|
+
this.SentMessages.push(text);
|
|
30
|
+
if (this.failNextError) {
|
|
31
|
+
const error = this.failNextError;
|
|
32
|
+
this.failNextError = null; // one-shot: a retry succeeds
|
|
33
|
+
return { reply: '', success: false, error };
|
|
34
|
+
}
|
|
35
|
+
onProgress?.('Thinking…', 50);
|
|
36
|
+
return { reply: this.replyFor(text), success: true };
|
|
37
|
+
}
|
|
38
|
+
async Dispose() {
|
|
39
|
+
this.session = undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=mock-widget-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-widget-transport.js","sourceRoot":"","sources":["../../src/transport/mock-widget-transport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,+EAA+E;AAC/E,MAAM,OAAO,mBAAmB;IAQ5B,YAAY,QAAmC;QAPxC,wBAAmB,GAAkB,IAAI,CAAC;QAC1C,iBAAY,GAAa,EAAE,CAAC;QAGnC,sGAAsG;QAC9F,kBAAa,GAAkB,IAAI,CAAC;QAGxC,IAAI,CAAC,QAAQ,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,6BAA6B,CAAC,oCAAoC,CAAC,CAAC;IAC5G,CAAC;IAED,oGAAoG;IAC7F,YAAY,CAAC,KAAa;QAC7B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;IAC/B,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,OAAsB;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAEM,WAAW,CAAC,MAAc;QAC7B,wBAAwB;IAC5B,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,UAAmC;QACtE,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,OAAO,EAAE,aAAa,IAAI,IAAI,CAAC;QAC/D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC,6BAA6B;YACxD,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAChD,CAAC;QACD,UAAU,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACzD,CAAC;IAEM,KAAK,CAAC,OAAO;QAChB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;IAC7B,CAAC;CACJ"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The production transport: reuses `@memberjunction/graphql-dataprovider`
|
|
3
|
+
* (configured outside Angular with the guest JWT) + `ConversationsRuntime` to hold a
|
|
4
|
+
* text conversation with the pinned support agent. It REUSES the unified pathway — no
|
|
5
|
+
* new chat engine, no new agent dispatch (anti-drift checklist).
|
|
6
|
+
*
|
|
7
|
+
* open-Q #2 (provider reuse): `GraphQLDataProvider` runs fine outside Angular via
|
|
8
|
+
* `setupGraphQLClient` — it is a plain `IMetadataProvider`. This transport uses it
|
|
9
|
+
* directly rather than writing a slimmer client.
|
|
10
|
+
*
|
|
11
|
+
* NOTE: this path requires a live MJAPI; it is exercised by W3's acceptance (gated on
|
|
12
|
+
* Auth0/MJAPI boot). Unit tests cover the UI + session client via the mock transport.
|
|
13
|
+
*
|
|
14
|
+
* @module @memberjunction/realtime-widget
|
|
15
|
+
*/
|
|
16
|
+
import type { WidgetSession } from '../types.js';
|
|
17
|
+
import type { IWidgetTransport, WidgetProgressCallback, WidgetTurnResult } from './widget-transport.js';
|
|
18
|
+
/** Reuses ConversationsRuntime + the GraphQL provider against MJAPI with the guest token. */
|
|
19
|
+
export declare class RuntimeWidgetTransport implements IWidgetTransport {
|
|
20
|
+
private readonly apiUrl;
|
|
21
|
+
private token;
|
|
22
|
+
private session;
|
|
23
|
+
private conversationId;
|
|
24
|
+
private contextUser;
|
|
25
|
+
private provider;
|
|
26
|
+
constructor(apiUrl: string);
|
|
27
|
+
/** Configures the GraphQL provider with the guest token, boots the runtime, opens a conversation. */
|
|
28
|
+
Initialize(session: WidgetSession): Promise<void>;
|
|
29
|
+
/** Swaps in a refreshed token (the next provider call uses it; conversation is preserved). */
|
|
30
|
+
UpdateToken(token: string): void;
|
|
31
|
+
/** Persists the user's message, runs the pinned agent, returns its reply. */
|
|
32
|
+
SendMessage(text: string, onProgress?: WidgetProgressCallback): Promise<WidgetTurnResult>;
|
|
33
|
+
Dispose(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the transport's own GraphQL provider (bound to this widget's guest token), set in
|
|
36
|
+
* {@link Initialize}. All entity work goes through this instance rather than the process-global
|
|
37
|
+
* `Metadata.Provider`, so a page hosting multiple widgets against different servers stays isolated.
|
|
38
|
+
*/
|
|
39
|
+
private requireProvider;
|
|
40
|
+
private buildConfig;
|
|
41
|
+
/** Creates the conversation row the guest's turns attach to. */
|
|
42
|
+
private createConversation;
|
|
43
|
+
/** Saves the visitor's message as a Conversation Detail and returns the entity. */
|
|
44
|
+
private saveUserMessage;
|
|
45
|
+
/**
|
|
46
|
+
* Creates the agent's response detail placeholder (Role='AI', In-Progress) the agent run writes
|
|
47
|
+
* into. Mirrors how the chat UI / AgentRunner pre-create the response row; its id is passed as
|
|
48
|
+
* `conversationDetailId` so the reply lands as an agent turn the widget can read back.
|
|
49
|
+
*/
|
|
50
|
+
private createAgentResponseDetail;
|
|
51
|
+
/** Reads the newest AI Conversation Detail for the conversation (the agent's reply). */
|
|
52
|
+
private readLatestAgentReply;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=runtime-widget-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-widget-transport.d.ts","sourceRoot":"","sources":["../../src/transport/runtime-widget-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAKxG,6FAA6F;AAC7F,qBAAa,sBAAuB,YAAW,gBAAgB;IAO/C,OAAO,CAAC,QAAQ,CAAC,MAAM;IANnC,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,QAAQ,CAAkC;gBAErB,MAAM,EAAE,MAAM;IAE3C,qGAAqG;IACxF,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9D,8FAA8F;IACvF,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvC,6EAA6E;IAChE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmCzF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQrC;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,WAAW;IAMnB,gEAAgE;YAClD,kBAAkB;IA+ChC,mFAAmF;YACrE,eAAe;IAc7B;;;;OAIG;YACW,yBAAyB;IAkBvC,wFAAwF;YAC1E,oBAAoB;CAiBrC"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The production transport: reuses `@memberjunction/graphql-dataprovider`
|
|
3
|
+
* (configured outside Angular with the guest JWT) + `ConversationsRuntime` to hold a
|
|
4
|
+
* text conversation with the pinned support agent. It REUSES the unified pathway — no
|
|
5
|
+
* new chat engine, no new agent dispatch (anti-drift checklist).
|
|
6
|
+
*
|
|
7
|
+
* open-Q #2 (provider reuse): `GraphQLDataProvider` runs fine outside Angular via
|
|
8
|
+
* `setupGraphQLClient` — it is a plain `IMetadataProvider`. This transport uses it
|
|
9
|
+
* directly rather than writing a slimmer client.
|
|
10
|
+
*
|
|
11
|
+
* NOTE: this path requires a live MJAPI; it is exercised by W3's acceptance (gated on
|
|
12
|
+
* Auth0/MJAPI boot). Unit tests cover the UI + session client via the mock transport.
|
|
13
|
+
*
|
|
14
|
+
* @module @memberjunction/realtime-widget
|
|
15
|
+
*/
|
|
16
|
+
import { RunView } from '@memberjunction/core';
|
|
17
|
+
import { setupGraphQLClient, GraphQLProviderConfigData } from '@memberjunction/graphql-dataprovider';
|
|
18
|
+
import { ConversationsRuntime } from '@memberjunction/conversations-runtime';
|
|
19
|
+
const CONVERSATIONS_ENTITY = 'MJ: Conversations';
|
|
20
|
+
const CONVERSATION_DETAILS_ENTITY = 'MJ: Conversation Details';
|
|
21
|
+
/** Reuses ConversationsRuntime + the GraphQL provider against MJAPI with the guest token. */
|
|
22
|
+
export class RuntimeWidgetTransport {
|
|
23
|
+
constructor(apiUrl) {
|
|
24
|
+
this.apiUrl = apiUrl;
|
|
25
|
+
this.token = '';
|
|
26
|
+
this.session = null;
|
|
27
|
+
this.conversationId = null;
|
|
28
|
+
this.contextUser = null;
|
|
29
|
+
this.provider = null;
|
|
30
|
+
}
|
|
31
|
+
/** Configures the GraphQL provider with the guest token, boots the runtime, opens a conversation. */
|
|
32
|
+
async Initialize(session) {
|
|
33
|
+
this.session = session;
|
|
34
|
+
this.token = session.token;
|
|
35
|
+
const provider = await setupGraphQLClient(this.buildConfig());
|
|
36
|
+
this.provider = provider;
|
|
37
|
+
this.contextUser = provider.CurrentUser;
|
|
38
|
+
// No-op when already configured for this process; safe to call per mount.
|
|
39
|
+
await ConversationsRuntime.Instance.Config(false, provider.CurrentUser, provider);
|
|
40
|
+
this.conversationId = await this.createConversation();
|
|
41
|
+
}
|
|
42
|
+
/** Swaps in a refreshed token (the next provider call uses it; conversation is preserved). */
|
|
43
|
+
UpdateToken(token) {
|
|
44
|
+
this.token = token;
|
|
45
|
+
}
|
|
46
|
+
/** Persists the user's message, runs the pinned agent, returns its reply. */
|
|
47
|
+
async SendMessage(text, onProgress) {
|
|
48
|
+
if (!this.session || !this.conversationId) {
|
|
49
|
+
return { reply: '', success: false, error: 'Widget transport not initialized.' };
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const userDetail = await this.saveUserMessage(text);
|
|
53
|
+
if (!userDetail) {
|
|
54
|
+
return { reply: '', success: false, error: 'Could not record your message.' };
|
|
55
|
+
}
|
|
56
|
+
// The agent writes its reply INTO a pre-created response detail whose id is passed as
|
|
57
|
+
// `conversationDetailId` (the AgentRunner contract — see AgentRunner.ts: `options.conversationDetailId`
|
|
58
|
+
// IS the agent response detail). Create it as Role='AI' so the reply is an agent turn, not a
|
|
59
|
+
// second user turn; `message`/`latestMessageId` stays the user's triggering message.
|
|
60
|
+
const agentDetail = await this.createAgentResponseDetail();
|
|
61
|
+
if (!agentDetail) {
|
|
62
|
+
return { reply: '', success: false, error: 'Could not start the agent response.' };
|
|
63
|
+
}
|
|
64
|
+
const result = await ConversationsRuntime.Instance.AgentRunner.processMessage({
|
|
65
|
+
conversationId: this.conversationId,
|
|
66
|
+
message: userDetail,
|
|
67
|
+
conversationDetailId: agentDetail.ID,
|
|
68
|
+
applicationId: this.session.applicationId,
|
|
69
|
+
// D5: ALWAYS pin the support agent — never the unfiltered fallback.
|
|
70
|
+
explicitAgentId: this.session.pinnedAgentId,
|
|
71
|
+
onProgress: (p) => onProgress?.(p.message ?? 'Working…', p.percentage),
|
|
72
|
+
});
|
|
73
|
+
if (!result || !result.success) {
|
|
74
|
+
return { reply: '', success: false, error: result?.agentRun?.ErrorMessage ?? 'The agent could not respond.' };
|
|
75
|
+
}
|
|
76
|
+
return { reply: await this.readLatestAgentReply(), success: true };
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
return { reply: '', success: false, error: err instanceof Error ? err.message : 'Unexpected error.' };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async Dispose() {
|
|
83
|
+
this.session = null;
|
|
84
|
+
this.conversationId = null;
|
|
85
|
+
this.contextUser = null;
|
|
86
|
+
}
|
|
87
|
+
// ── helpers ────────────────────────────────────────────────────────────────
|
|
88
|
+
/**
|
|
89
|
+
* Returns the transport's own GraphQL provider (bound to this widget's guest token), set in
|
|
90
|
+
* {@link Initialize}. All entity work goes through this instance rather than the process-global
|
|
91
|
+
* `Metadata.Provider`, so a page hosting multiple widgets against different servers stays isolated.
|
|
92
|
+
*/
|
|
93
|
+
requireProvider() {
|
|
94
|
+
if (!this.provider) {
|
|
95
|
+
throw new Error('Widget transport not initialized — provider unavailable.');
|
|
96
|
+
}
|
|
97
|
+
return this.provider;
|
|
98
|
+
}
|
|
99
|
+
buildConfig() {
|
|
100
|
+
const base = this.apiUrl.replace(/\/+$/, '');
|
|
101
|
+
const wsUrl = base.replace(/^http/, 'ws');
|
|
102
|
+
return new GraphQLProviderConfigData(this.token, base, wsUrl, async () => this.token);
|
|
103
|
+
}
|
|
104
|
+
/** Creates the conversation row the guest's turns attach to. */
|
|
105
|
+
async createConversation() {
|
|
106
|
+
const md = this.requireProvider();
|
|
107
|
+
const convo = await md.GetEntityObject(CONVERSATIONS_ENTITY, this.contextUser ?? undefined);
|
|
108
|
+
convo.NewRecord();
|
|
109
|
+
convo.Name = 'Web Widget Support';
|
|
110
|
+
if (this.contextUser?.ID) {
|
|
111
|
+
convo.UserID = this.contextUser.ID;
|
|
112
|
+
}
|
|
113
|
+
// Scope the conversation to the widget's Application. The returning-visitor lookup at mint
|
|
114
|
+
// resolves the prior conversation by (VisitorKey AND ApplicationID), so without this the chain
|
|
115
|
+
// never forms (LastConversationID stays null → no recap, no cross-session memory).
|
|
116
|
+
// ApplicationScope must be 'Application' for ApplicationID to be set (CK_Conversation_ScopeAppBinding).
|
|
117
|
+
if (this.session?.applicationId) {
|
|
118
|
+
convo.ApplicationScope = 'Application';
|
|
119
|
+
convo.ApplicationID = this.session.applicationId;
|
|
120
|
+
}
|
|
121
|
+
// Stamp the per-session id so the Widget Guest RLS filters ({{ScopeResourceID}}) isolate
|
|
122
|
+
// this guest's conversation from other anonymous guests sharing the Anonymous principal.
|
|
123
|
+
// Read-isolation is enforced by the SIGNED session scope, so a client mis-stamp can only
|
|
124
|
+
// hide the guest's own rows from itself — never expose another session's rows.
|
|
125
|
+
if (this.session?.sessionId) {
|
|
126
|
+
convo.ExternalID = this.session.sessionId;
|
|
127
|
+
}
|
|
128
|
+
// Returning-visitor chain (RV1): when remembering is on, stamp the durable VisitorKey and link to
|
|
129
|
+
// the visitor's prior conversation (resolved server-side by VisitorKey at mint). Both are null when
|
|
130
|
+
// the widget's RememberReturningVisitors toggle is off, so this is a no-op in the default case.
|
|
131
|
+
if (this.session?.rememberReturningVisitors) {
|
|
132
|
+
if (this.session.visitorKey) {
|
|
133
|
+
convo.VisitorKey = this.session.visitorKey;
|
|
134
|
+
}
|
|
135
|
+
if (this.session.lastConversationId) {
|
|
136
|
+
convo.LastConversationID = this.session.lastConversationId;
|
|
137
|
+
}
|
|
138
|
+
// RV4 (host-identity path): when the mint resolved a polymorphic identity, stamp it so memory
|
|
139
|
+
// injection keys off the resolved record rather than the anonymous cookie chain.
|
|
140
|
+
if (this.session.linkedEntityId && this.session.linkedRecordId) {
|
|
141
|
+
convo.LinkedEntityID = this.session.linkedEntityId;
|
|
142
|
+
convo.LinkedRecordID = this.session.linkedRecordId;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const saved = await convo.Save();
|
|
146
|
+
if (!saved) {
|
|
147
|
+
throw new Error(`Failed to create widget conversation: ${convo.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
148
|
+
}
|
|
149
|
+
return convo.ID;
|
|
150
|
+
}
|
|
151
|
+
/** Saves the visitor's message as a Conversation Detail and returns the entity. */
|
|
152
|
+
async saveUserMessage(text) {
|
|
153
|
+
const md = this.requireProvider();
|
|
154
|
+
const detail = await md.GetEntityObject(CONVERSATION_DETAILS_ENTITY, this.contextUser ?? undefined);
|
|
155
|
+
detail.NewRecord();
|
|
156
|
+
detail.ConversationID = this.conversationId;
|
|
157
|
+
detail.Role = 'User';
|
|
158
|
+
detail.Message = text;
|
|
159
|
+
const saved = await detail.Save();
|
|
160
|
+
if (!saved) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
return detail;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Creates the agent's response detail placeholder (Role='AI', In-Progress) the agent run writes
|
|
167
|
+
* into. Mirrors how the chat UI / AgentRunner pre-create the response row; its id is passed as
|
|
168
|
+
* `conversationDetailId` so the reply lands as an agent turn the widget can read back.
|
|
169
|
+
*/
|
|
170
|
+
async createAgentResponseDetail() {
|
|
171
|
+
const md = this.requireProvider();
|
|
172
|
+
const detail = await md.GetEntityObject(CONVERSATION_DETAILS_ENTITY, this.contextUser ?? undefined);
|
|
173
|
+
detail.NewRecord();
|
|
174
|
+
detail.ConversationID = this.conversationId;
|
|
175
|
+
detail.Role = 'AI';
|
|
176
|
+
detail.Message = '⏳ Starting…';
|
|
177
|
+
detail.Status = 'In-Progress';
|
|
178
|
+
if (this.session?.pinnedAgentId) {
|
|
179
|
+
detail.AgentID = this.session.pinnedAgentId;
|
|
180
|
+
}
|
|
181
|
+
const saved = await detail.Save();
|
|
182
|
+
if (!saved) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
return detail;
|
|
186
|
+
}
|
|
187
|
+
/** Reads the newest AI Conversation Detail for the conversation (the agent's reply). */
|
|
188
|
+
async readLatestAgentReply() {
|
|
189
|
+
const rv = new RunView();
|
|
190
|
+
const result = await rv.RunView({
|
|
191
|
+
EntityName: CONVERSATION_DETAILS_ENTITY,
|
|
192
|
+
ExtraFilter: `ConversationID='${this.conversationId}' AND Role='AI'`,
|
|
193
|
+
OrderBy: '__mj_CreatedAt DESC',
|
|
194
|
+
MaxRows: 1,
|
|
195
|
+
ResultType: 'entity_object',
|
|
196
|
+
}, this.contextUser ?? undefined);
|
|
197
|
+
if (result.Success && result.Results.length > 0) {
|
|
198
|
+
return result.Results[0].Message ?? '';
|
|
199
|
+
}
|
|
200
|
+
return '';
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=runtime-widget-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-widget-transport.js","sourceRoot":"","sources":["../../src/transport/runtime-widget-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The transport seam between the widget UI and the agent pathway.
|
|
3
|
+
*
|
|
4
|
+
* The UI element depends only on this interface, so it is unit-testable with a mock
|
|
5
|
+
* and decoupled from the heavy ConversationsRuntime + GraphQL wiring. The real
|
|
6
|
+
* implementation (`RuntimeWidgetTransport`) reuses `ConversationsRuntime` +
|
|
7
|
+
* `@memberjunction/graphql-dataprovider` against MJAPI with the guest token — it does
|
|
8
|
+
* NOT reimplement chat or agent dispatch (anti-drift checklist).
|
|
9
|
+
*
|
|
10
|
+
* @module @memberjunction/realtime-widget
|
|
11
|
+
*/
|
|
12
|
+
import type { WidgetSession } from '../types.js';
|
|
13
|
+
/** Streaming progress callback while an agent turn runs. */
|
|
14
|
+
export type WidgetProgressCallback = (message: string, percentage?: number) => void;
|
|
15
|
+
/** Result of one user turn → agent reply. */
|
|
16
|
+
export interface WidgetTurnResult {
|
|
17
|
+
/** The agent's reply text (empty string if the agent produced no textual output). */
|
|
18
|
+
reply: string;
|
|
19
|
+
/** True when the turn completed successfully. */
|
|
20
|
+
success: boolean;
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Abstraction over "start a conversation and exchange turns with the pinned agent."
|
|
25
|
+
* One transport instance per mounted widget session.
|
|
26
|
+
*/
|
|
27
|
+
export interface IWidgetTransport {
|
|
28
|
+
/** Initializes the transport with the freshly-minted guest session. */
|
|
29
|
+
Initialize(session: WidgetSession): Promise<void>;
|
|
30
|
+
/** Updates the held token after a refresh (no reconnection of the conversation). */
|
|
31
|
+
UpdateToken(token: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Sends a user message and resolves with the agent's reply. The pinned agent id
|
|
34
|
+
* from the session is ALWAYS passed as explicitAgentId (D5) — the transport never
|
|
35
|
+
* lets the caller pick an arbitrary agent.
|
|
36
|
+
*/
|
|
37
|
+
SendMessage(text: string, onProgress?: WidgetProgressCallback): Promise<WidgetTurnResult>;
|
|
38
|
+
/** Tears down the conversation/session resources. */
|
|
39
|
+
Dispose(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=widget-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-transport.d.ts","sourceRoot":"","sources":["../../src/transport/widget-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,4DAA4D;AAC5D,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpF,6CAA6C;AAC7C,MAAM,WAAW,gBAAgB;IAC7B,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,uEAAuE;IACvE,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD,oFAAoF;IACpF,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC;;;;OAIG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE1F,qDAAqD;IACrD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B"}
|