@memberjunction/conversations-runtime 0.0.1 → 5.41.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 +99 -43
- package/dist/ConversationsRuntime.d.ts +193 -0
- package/dist/ConversationsRuntime.d.ts.map +1 -0
- package/dist/ConversationsRuntime.js +268 -0
- package/dist/ConversationsRuntime.js.map +1 -0
- package/dist/adapters/IActiveTaskTracker.d.ts +49 -0
- package/dist/adapters/IActiveTaskTracker.d.ts.map +1 -0
- package/dist/adapters/IActiveTaskTracker.js +26 -0
- package/dist/adapters/IActiveTaskTracker.js.map +1 -0
- package/dist/adapters/INotificationAdapter.d.ts +60 -0
- package/dist/adapters/INotificationAdapter.d.ts.map +1 -0
- package/dist/adapters/INotificationAdapter.js +45 -0
- package/dist/adapters/INotificationAdapter.js.map +1 -0
- package/dist/adapters/ISessionsAdapter.d.ts +124 -0
- package/dist/adapters/ISessionsAdapter.d.ts.map +1 -0
- package/dist/adapters/ISessionsAdapter.js +44 -0
- package/dist/adapters/ISessionsAdapter.js.map +1 -0
- package/dist/agent-runner/ConversationAgentRunner.d.ts +121 -0
- package/dist/agent-runner/ConversationAgentRunner.d.ts.map +1 -0
- package/dist/agent-runner/ConversationAgentRunner.js +191 -0
- package/dist/agent-runner/ConversationAgentRunner.js.map +1 -0
- package/dist/bridge/ConversationBridge.d.ts +93 -0
- package/dist/bridge/ConversationBridge.d.ts.map +1 -0
- package/dist/bridge/ConversationBridge.js +105 -0
- package/dist/bridge/ConversationBridge.js.map +1 -0
- package/dist/context/IConversationsRuntimeContext.d.ts +29 -0
- package/dist/context/IConversationsRuntimeContext.d.ts.map +1 -0
- package/dist/context/IConversationsRuntimeContext.js +21 -0
- package/dist/context/IConversationsRuntimeContext.js.map +1 -0
- package/dist/default-agent/DefaultAgentResolver.d.ts +87 -0
- package/dist/default-agent/DefaultAgentResolver.d.ts.map +1 -0
- package/dist/default-agent/DefaultAgentResolver.js +103 -0
- package/dist/default-agent/DefaultAgentResolver.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/mentions/MentionParser.d.ts +109 -0
- package/dist/mentions/MentionParser.d.ts.map +1 -0
- package/dist/mentions/MentionParser.js +276 -0
- package/dist/mentions/MentionParser.js.map +1 -0
- package/dist/sessions/SessionsObserver.d.ts +87 -0
- package/dist/sessions/SessionsObserver.d.ts.map +1 -0
- package/dist/sessions/SessionsObserver.js +103 -0
- package/dist/sessions/SessionsObserver.js.map +1 -0
- package/dist/streaming/ConversationStreaming.d.ts +169 -0
- package/dist/streaming/ConversationStreaming.d.ts.map +1 -0
- package/dist/streaming/ConversationStreaming.js +355 -0
- package/dist/streaming/ConversationStreaming.js.map +1 -0
- package/package.json +33 -7
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure-TypeScript agent-run pipeline for conversations.
|
|
3
|
+
*
|
|
4
|
+
* Ported from `@memberjunction/ng-conversations/src/lib/services/conversation-agent.service.ts`,
|
|
5
|
+
* scoped to the core `processMessage` flow. The Angular service's other helpers
|
|
6
|
+
* (intent checking, sub-agent invocation, artifact lookup, configuration-preset
|
|
7
|
+
* lookup) stay in the widget for now and can move in a follow-up — they aren't
|
|
8
|
+
* needed to invoke an agent end-to-end.
|
|
9
|
+
*
|
|
10
|
+
* Replaces three Angular bindings from the original:
|
|
11
|
+
* - `MJNotificationService.Instance.CreateSimpleNotification(...)` →
|
|
12
|
+
* {@link IConversationsRuntimeContext.Notification}.
|
|
13
|
+
* - `AgentClientService` (Angular wrapper over `AgentClientSession`) →
|
|
14
|
+
* `AgentClientSession` used directly (already pure-TS).
|
|
15
|
+
* - Hardcoded `Agents.find(a => a.Name === 'Sage')` → {@link DefaultAgentResolver}.
|
|
16
|
+
*
|
|
17
|
+
* @module @memberjunction/conversations-runtime
|
|
18
|
+
*/
|
|
19
|
+
import { BehaviorSubject } from 'rxjs';
|
|
20
|
+
import { Metadata } from '@memberjunction/core';
|
|
21
|
+
import { UUIDsEqual } from '@memberjunction/global';
|
|
22
|
+
import { AgentClientSession, } from '@memberjunction/ai-agent-client';
|
|
23
|
+
import { AIEngineBase, AIAgentPermissionHelper, } from '@memberjunction/ai-engine-base';
|
|
24
|
+
/**
|
|
25
|
+
* Core agent-run orchestrator. Wraps {@link AgentClientSession.RunAgentFromConversationDetail}
|
|
26
|
+
* with conversation-aware glue: default-agent resolution, permission-filtered
|
|
27
|
+
* candidate list for Sage's routing decisions, processing-state observable, and
|
|
28
|
+
* adapter-routed user notifications.
|
|
29
|
+
*
|
|
30
|
+
* Usually accessed via `ConversationsRuntime.Instance.AgentRunner`.
|
|
31
|
+
*/
|
|
32
|
+
export class ConversationAgentRunner {
|
|
33
|
+
/**
|
|
34
|
+
* @param context Runtime context — used for notifications. Read on each call
|
|
35
|
+
* so adapter swaps after construction are picked up immediately.
|
|
36
|
+
* @param toolRegistry Shared `ClientToolRegistry` — the runner's internal
|
|
37
|
+
* `AgentClientSession` uses this so tools registered on
|
|
38
|
+
* `ConversationsRuntime.Tools` are visible to the agent.
|
|
39
|
+
* @param resolver The runtime's `DefaultAgentResolver` — used to pick the
|
|
40
|
+
* conversation manager agent when no explicit ID is supplied.
|
|
41
|
+
*/
|
|
42
|
+
constructor(context, toolRegistry, resolver) {
|
|
43
|
+
this.context = context;
|
|
44
|
+
this.resolver = resolver;
|
|
45
|
+
this._isProcessing$ = new BehaviorSubject(false);
|
|
46
|
+
this._provider = null;
|
|
47
|
+
/** Emits `true` while an agent run is in flight, `false` otherwise. */
|
|
48
|
+
this.isProcessing$ = this._isProcessing$.asObservable();
|
|
49
|
+
this.session = new AgentClientSession(toolRegistry);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Metadata provider — falls back to `Metadata.Provider` when unset. Setting
|
|
53
|
+
* this forwards the provider to the internal `AgentClientSession` so GraphQL
|
|
54
|
+
* calls target the right server in multi-provider scenarios.
|
|
55
|
+
*/
|
|
56
|
+
get Provider() {
|
|
57
|
+
return this._provider ?? Metadata.Provider;
|
|
58
|
+
}
|
|
59
|
+
set Provider(value) {
|
|
60
|
+
this._provider = value;
|
|
61
|
+
this.session.Provider = value;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Process a user message through the default conversation manager agent. Mirrors
|
|
65
|
+
* the original service's `processMessage(...)` flow, but with the three Angular
|
|
66
|
+
* deps replaced (notification adapter, default-agent resolver, direct
|
|
67
|
+
* `AgentClientSession`).
|
|
68
|
+
*
|
|
69
|
+
* @returns The agent's `ExecuteAgentResult`, or `null` if the agent failed and
|
|
70
|
+
* a notification was surfaced.
|
|
71
|
+
*/
|
|
72
|
+
async processMessage(input) {
|
|
73
|
+
const agent = await this.resolveAgent(input);
|
|
74
|
+
if (!agent)
|
|
75
|
+
return null;
|
|
76
|
+
try {
|
|
77
|
+
this._isProcessing$.next(true);
|
|
78
|
+
const currentUser = this.Provider.CurrentUser;
|
|
79
|
+
if (!currentUser) {
|
|
80
|
+
console.warn('[ConversationAgentRunner] No current user available for permission filtering; using unfiltered agent list.');
|
|
81
|
+
}
|
|
82
|
+
const candidateAgents = AIEngineBase.Instance.Agents.filter((a) => !UUIDsEqual(a.ID, agent.ID) &&
|
|
83
|
+
!a.ParentID &&
|
|
84
|
+
a.Status === 'Active' &&
|
|
85
|
+
a.InvocationMode !== 'Sub-Agent');
|
|
86
|
+
const availableAgents = currentUser
|
|
87
|
+
? await this.filterAgentsByPermissions(candidateAgents, currentUser)
|
|
88
|
+
: candidateAgents;
|
|
89
|
+
console.log(`[ConversationAgentRunner] Available agents for routing: ${availableAgents.length} (filtered from ${candidateAgents.length} candidates)`);
|
|
90
|
+
const agentParams = {
|
|
91
|
+
ConversationDetailId: input.conversationDetailId,
|
|
92
|
+
AgentId: agent.ID,
|
|
93
|
+
MaxHistoryMessages: 20,
|
|
94
|
+
Data: {
|
|
95
|
+
ALL_AVAILABLE_AGENTS: availableAgents.map((a) => ({
|
|
96
|
+
ID: a.ID,
|
|
97
|
+
Name: a.Name,
|
|
98
|
+
Description: a.Description,
|
|
99
|
+
})),
|
|
100
|
+
conversationId: input.conversationId,
|
|
101
|
+
latestMessageId: input.message.ID,
|
|
102
|
+
...(input.appContext ? { appContext: input.appContext } : {}),
|
|
103
|
+
// Forward registered client tools so the LLM sees them in the prompt.
|
|
104
|
+
clientTools: this.session
|
|
105
|
+
.GetRegisteredTools()
|
|
106
|
+
.map((t) => ({
|
|
107
|
+
Name: t.Name,
|
|
108
|
+
Description: t.Description,
|
|
109
|
+
InputSchema: t.ParameterSchema,
|
|
110
|
+
})),
|
|
111
|
+
},
|
|
112
|
+
CreateArtifacts: true,
|
|
113
|
+
CreateNotification: true,
|
|
114
|
+
OnProgress: input.onProgress
|
|
115
|
+
? (progress) => input.onProgress({
|
|
116
|
+
step: progress.CurrentStep,
|
|
117
|
+
percentage: progress.Percentage,
|
|
118
|
+
message: progress.Message,
|
|
119
|
+
metadata: progress.Metadata,
|
|
120
|
+
})
|
|
121
|
+
: undefined,
|
|
122
|
+
};
|
|
123
|
+
const runResult = await this.session.RunAgentFromConversationDetail(agentParams);
|
|
124
|
+
if (runResult.Success && runResult.Result) {
|
|
125
|
+
return runResult.Result;
|
|
126
|
+
}
|
|
127
|
+
if (!runResult.Success) {
|
|
128
|
+
const errorMsg = runResult.ErrorMessage ?? 'Agent execution failed';
|
|
129
|
+
console.error('[ConversationAgentRunner] Agent execution failed:', errorMsg);
|
|
130
|
+
this.context.Notification.Notify('error', errorMsg, 5_000);
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
const errorMsg = 'Error processing message through agent: ' +
|
|
137
|
+
(error instanceof Error ? error.message : String(error));
|
|
138
|
+
console.error('[ConversationAgentRunner] Error processing message:', error);
|
|
139
|
+
this.context.Notification.Notify('error', errorMsg, 5_000);
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
this._isProcessing$.next(false);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Resolve the agent that should handle this turn — explicit ID wins, then the
|
|
148
|
+
* Application Settings chain, then the Sage code-const fallback. Surfaces a
|
|
149
|
+
* notification on failure rather than throwing, so the caller (UI thread)
|
|
150
|
+
* sees a friendly message.
|
|
151
|
+
*/
|
|
152
|
+
async resolveAgent(input) {
|
|
153
|
+
try {
|
|
154
|
+
return await this.resolver.resolve({
|
|
155
|
+
explicitAgentId: input.explicitAgentId,
|
|
156
|
+
applicationId: input.applicationId,
|
|
157
|
+
contextUser: this.Provider.CurrentUser ?? undefined,
|
|
158
|
+
provider: this.Provider,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
const errorMsg = 'Could not resolve a default conversation manager agent: ' +
|
|
163
|
+
(error instanceof Error ? error.message : String(error));
|
|
164
|
+
console.error('[ConversationAgentRunner] Agent resolution failed:', error);
|
|
165
|
+
this.context.Notification.Notify('error', errorMsg, 5_000);
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Filter agents by the user's `run` permission. Identical to the original
|
|
171
|
+
* service's helper — fails closed on per-agent error so we never expose an
|
|
172
|
+
* agent the user shouldn't see.
|
|
173
|
+
*/
|
|
174
|
+
async filterAgentsByPermissions(agents, user) {
|
|
175
|
+
const permittedAgents = [];
|
|
176
|
+
for (const agent of agents) {
|
|
177
|
+
try {
|
|
178
|
+
const hasPermission = await AIAgentPermissionHelper.HasPermission(agent.ID, user, 'run');
|
|
179
|
+
if (hasPermission) {
|
|
180
|
+
permittedAgents.push(agent);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
console.error(`[ConversationAgentRunner] Error checking permission for agent ${agent.Name}:`, error);
|
|
185
|
+
// Fail closed — exclude on error.
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return permittedAgents;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=ConversationAgentRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationAgentRunner.js","sourceRoot":"","sources":["../../src/agent-runner/ConversationAgentRunner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure-TypeScript bridge between conversation surfaces.
|
|
3
|
+
*
|
|
4
|
+
* Ported from `@memberjunction/ng-conversations/src/lib/services/conversation-bridge.service.ts`.
|
|
5
|
+
* The original was pure RxJS — the `@Injectable()` decorator was the only Angular dep. Stripped
|
|
6
|
+
* that, kept the API identical, renamed `ConversationBridgeService` → `ConversationBridge`
|
|
7
|
+
* (no "Service" suffix since this layer doesn't use Angular DI).
|
|
8
|
+
*
|
|
9
|
+
* Coordinates active-conversation state across multiple surfaces:
|
|
10
|
+
* - the corner overlay (`mj-chat-agents-overlay`)
|
|
11
|
+
* - the full-page Chat workspace (`mj-chat-conversations-resource`)
|
|
12
|
+
* - any future composite surface (e.g., embedded panels in dashboards)
|
|
13
|
+
*
|
|
14
|
+
* @module @memberjunction/conversations-runtime
|
|
15
|
+
*/
|
|
16
|
+
import { BehaviorSubject, Subject } from 'rxjs';
|
|
17
|
+
/** Event emitted when switching between overlay and workspace surfaces. */
|
|
18
|
+
export interface ConversationSwitchEvent {
|
|
19
|
+
/** The conversation ID being transferred. */
|
|
20
|
+
ConversationID: string | null;
|
|
21
|
+
/** Surface initiating the switch. */
|
|
22
|
+
Source: 'overlay' | 'workspace' | 'deep-link';
|
|
23
|
+
/** Surface that should pick up the conversation. */
|
|
24
|
+
Target: 'overlay' | 'workspace';
|
|
25
|
+
}
|
|
26
|
+
/** Deep-link parameters for navigating directly to a conversation. */
|
|
27
|
+
export interface ConversationDeepLink {
|
|
28
|
+
ConversationID: string;
|
|
29
|
+
/** Optional: scroll to a specific message after opening. */
|
|
30
|
+
MessageID?: string;
|
|
31
|
+
/** Optional: auto-open the overlay or workspace. */
|
|
32
|
+
OpenIn?: 'overlay' | 'workspace';
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Shared state between conversation surfaces. Pure observable hub — knows nothing about
|
|
36
|
+
* any specific UI framework. Consumers subscribe to the streams they care about.
|
|
37
|
+
*
|
|
38
|
+
* Usually accessed via `ConversationsRuntime.Instance.Bridge`.
|
|
39
|
+
*/
|
|
40
|
+
export declare class ConversationBridge {
|
|
41
|
+
/** The currently active conversation ID shared between overlay and workspace. */
|
|
42
|
+
ActiveConversationID$: BehaviorSubject<string | null>;
|
|
43
|
+
/** Whether the overlay surface is currently active (expanded). */
|
|
44
|
+
OverlayActive$: BehaviorSubject<boolean>;
|
|
45
|
+
/** Whether the full workspace surface is currently active (visible). */
|
|
46
|
+
WorkspaceActive$: BehaviorSubject<boolean>;
|
|
47
|
+
/** Events emitted when switching between overlay and workspace. */
|
|
48
|
+
SwitchEvent$: Subject<ConversationSwitchEvent>;
|
|
49
|
+
/** Deep-link navigation requests. */
|
|
50
|
+
DeepLinkRequest$: Subject<ConversationDeepLink>;
|
|
51
|
+
/**
|
|
52
|
+
* "Expand the overlay" requests from anywhere in the app — typically a dashboard's
|
|
53
|
+
* "Refine with AI" button that wants to pop the chat after setting fresh AppContext.
|
|
54
|
+
* The mounted overlay subscribes and calls its own `Expand()` in response. Decoupled
|
|
55
|
+
* this way because the overlay component reference isn't reachable from arbitrary
|
|
56
|
+
* callers, and we don't want everyone to take a hard dep on the overlay class.
|
|
57
|
+
*/
|
|
58
|
+
ExpandOverlayRequested$: Subject<void>;
|
|
59
|
+
/** Ask the overlay to expand. Idempotent if already expanded. */
|
|
60
|
+
RequestExpandOverlay(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Set the active conversation from the overlay. The workspace picks up the change
|
|
63
|
+
* automatically via the shared `ActiveConversationID$` stream.
|
|
64
|
+
*/
|
|
65
|
+
SetActiveFromOverlay(conversationId: string | null): void;
|
|
66
|
+
/**
|
|
67
|
+
* Set the active conversation from the workspace. The overlay picks up the change
|
|
68
|
+
* automatically via the shared `ActiveConversationID$` stream.
|
|
69
|
+
*/
|
|
70
|
+
SetActiveFromWorkspace(conversationId: string | null): void;
|
|
71
|
+
/**
|
|
72
|
+
* Request switching from overlay to full workspace. The overlay should minimize;
|
|
73
|
+
* the workspace should open with the same conversation.
|
|
74
|
+
*/
|
|
75
|
+
SwitchToWorkspace(conversationId: string | null): void;
|
|
76
|
+
/**
|
|
77
|
+
* Request switching from workspace to overlay. The workspace can stay open, but the
|
|
78
|
+
* overlay resumes the conversation.
|
|
79
|
+
*/
|
|
80
|
+
SwitchToOverlay(conversationId: string | null): void;
|
|
81
|
+
/** Navigate to a specific conversation via deep link. */
|
|
82
|
+
NavigateToConversation(deepLink: ConversationDeepLink): void;
|
|
83
|
+
/** Notify that the overlay is now active (or inactive). */
|
|
84
|
+
NotifyOverlayActive(active: boolean): void;
|
|
85
|
+
/** Notify that the workspace is now active (or inactive). */
|
|
86
|
+
NotifyWorkspaceActive(active: boolean): void;
|
|
87
|
+
/**
|
|
88
|
+
* `true` when the workspace is not active but there's an active conversation —
|
|
89
|
+
* i.e., the overlay should resume that conversation when expanded.
|
|
90
|
+
*/
|
|
91
|
+
ShouldResumeInOverlay(): boolean;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=ConversationBridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationBridge.d.ts","sourceRoot":"","sources":["../../src/bridge/ConversationBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEhD,2EAA2E;AAC3E,MAAM,WAAW,uBAAuB;IACpC,6CAA6C;IAC7C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,qCAAqC;IACrC,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAC9C,oDAAoD;IACpD,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;CACnC;AAED,sEAAsE;AACtE,MAAM,WAAW,oBAAoB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,MAAM,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;CACpC;AAED;;;;;GAKG;AACH,qBAAa,kBAAkB;IAC3B,iFAAiF;IAC1E,qBAAqB,iCAA4C;IAExE,kEAAkE;IAC3D,cAAc,2BAAuC;IAE5D,wEAAwE;IACjE,gBAAgB,2BAAuC;IAE9D,mEAAmE;IAC5D,YAAY,mCAA0C;IAE7D,qCAAqC;IAC9B,gBAAgB,gCAAuC;IAE9D;;;;;;OAMG;IACI,uBAAuB,gBAAuB;IAErD,iEAAiE;IAC1D,oBAAoB,IAAI,IAAI;IAInC;;;OAGG;IACI,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIhE;;;OAGG;IACI,sBAAsB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIlE;;;OAGG;IACI,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAQ7D;;;OAGG;IACI,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAQ3D,yDAAyD;IAClD,sBAAsB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI;IAKnE,2DAA2D;IACpD,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAIjD,6DAA6D;IACtD,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAInD;;;OAGG;IACI,qBAAqB,IAAI,OAAO;CAG1C"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure-TypeScript bridge between conversation surfaces.
|
|
3
|
+
*
|
|
4
|
+
* Ported from `@memberjunction/ng-conversations/src/lib/services/conversation-bridge.service.ts`.
|
|
5
|
+
* The original was pure RxJS — the `@Injectable()` decorator was the only Angular dep. Stripped
|
|
6
|
+
* that, kept the API identical, renamed `ConversationBridgeService` → `ConversationBridge`
|
|
7
|
+
* (no "Service" suffix since this layer doesn't use Angular DI).
|
|
8
|
+
*
|
|
9
|
+
* Coordinates active-conversation state across multiple surfaces:
|
|
10
|
+
* - the corner overlay (`mj-chat-agents-overlay`)
|
|
11
|
+
* - the full-page Chat workspace (`mj-chat-conversations-resource`)
|
|
12
|
+
* - any future composite surface (e.g., embedded panels in dashboards)
|
|
13
|
+
*
|
|
14
|
+
* @module @memberjunction/conversations-runtime
|
|
15
|
+
*/
|
|
16
|
+
import { BehaviorSubject, Subject } from 'rxjs';
|
|
17
|
+
/**
|
|
18
|
+
* Shared state between conversation surfaces. Pure observable hub — knows nothing about
|
|
19
|
+
* any specific UI framework. Consumers subscribe to the streams they care about.
|
|
20
|
+
*
|
|
21
|
+
* Usually accessed via `ConversationsRuntime.Instance.Bridge`.
|
|
22
|
+
*/
|
|
23
|
+
export class ConversationBridge {
|
|
24
|
+
constructor() {
|
|
25
|
+
/** The currently active conversation ID shared between overlay and workspace. */
|
|
26
|
+
this.ActiveConversationID$ = new BehaviorSubject(null);
|
|
27
|
+
/** Whether the overlay surface is currently active (expanded). */
|
|
28
|
+
this.OverlayActive$ = new BehaviorSubject(false);
|
|
29
|
+
/** Whether the full workspace surface is currently active (visible). */
|
|
30
|
+
this.WorkspaceActive$ = new BehaviorSubject(false);
|
|
31
|
+
/** Events emitted when switching between overlay and workspace. */
|
|
32
|
+
this.SwitchEvent$ = new Subject();
|
|
33
|
+
/** Deep-link navigation requests. */
|
|
34
|
+
this.DeepLinkRequest$ = new Subject();
|
|
35
|
+
/**
|
|
36
|
+
* "Expand the overlay" requests from anywhere in the app — typically a dashboard's
|
|
37
|
+
* "Refine with AI" button that wants to pop the chat after setting fresh AppContext.
|
|
38
|
+
* The mounted overlay subscribes and calls its own `Expand()` in response. Decoupled
|
|
39
|
+
* this way because the overlay component reference isn't reachable from arbitrary
|
|
40
|
+
* callers, and we don't want everyone to take a hard dep on the overlay class.
|
|
41
|
+
*/
|
|
42
|
+
this.ExpandOverlayRequested$ = new Subject();
|
|
43
|
+
}
|
|
44
|
+
/** Ask the overlay to expand. Idempotent if already expanded. */
|
|
45
|
+
RequestExpandOverlay() {
|
|
46
|
+
this.ExpandOverlayRequested$.next();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Set the active conversation from the overlay. The workspace picks up the change
|
|
50
|
+
* automatically via the shared `ActiveConversationID$` stream.
|
|
51
|
+
*/
|
|
52
|
+
SetActiveFromOverlay(conversationId) {
|
|
53
|
+
this.ActiveConversationID$.next(conversationId);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Set the active conversation from the workspace. The overlay picks up the change
|
|
57
|
+
* automatically via the shared `ActiveConversationID$` stream.
|
|
58
|
+
*/
|
|
59
|
+
SetActiveFromWorkspace(conversationId) {
|
|
60
|
+
this.ActiveConversationID$.next(conversationId);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Request switching from overlay to full workspace. The overlay should minimize;
|
|
64
|
+
* the workspace should open with the same conversation.
|
|
65
|
+
*/
|
|
66
|
+
SwitchToWorkspace(conversationId) {
|
|
67
|
+
this.SwitchEvent$.next({
|
|
68
|
+
ConversationID: conversationId,
|
|
69
|
+
Source: 'overlay',
|
|
70
|
+
Target: 'workspace',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Request switching from workspace to overlay. The workspace can stay open, but the
|
|
75
|
+
* overlay resumes the conversation.
|
|
76
|
+
*/
|
|
77
|
+
SwitchToOverlay(conversationId) {
|
|
78
|
+
this.SwitchEvent$.next({
|
|
79
|
+
ConversationID: conversationId,
|
|
80
|
+
Source: 'workspace',
|
|
81
|
+
Target: 'overlay',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/** Navigate to a specific conversation via deep link. */
|
|
85
|
+
NavigateToConversation(deepLink) {
|
|
86
|
+
this.ActiveConversationID$.next(deepLink.ConversationID);
|
|
87
|
+
this.DeepLinkRequest$.next(deepLink);
|
|
88
|
+
}
|
|
89
|
+
/** Notify that the overlay is now active (or inactive). */
|
|
90
|
+
NotifyOverlayActive(active) {
|
|
91
|
+
this.OverlayActive$.next(active);
|
|
92
|
+
}
|
|
93
|
+
/** Notify that the workspace is now active (or inactive). */
|
|
94
|
+
NotifyWorkspaceActive(active) {
|
|
95
|
+
this.WorkspaceActive$.next(active);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* `true` when the workspace is not active but there's an active conversation —
|
|
99
|
+
* i.e., the overlay should resume that conversation when expanded.
|
|
100
|
+
*/
|
|
101
|
+
ShouldResumeInOverlay() {
|
|
102
|
+
return !this.WorkspaceActive$.value && this.ActiveConversationID$.value !== null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=ConversationBridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationBridge.js","sourceRoot":"","sources":["../../src/bridge/ConversationBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAqBhD;;;;;GAKG;AACH,MAAM,OAAO,kBAAkB;IAA/B;QACI,iFAAiF;QAC1E,0BAAqB,GAAG,IAAI,eAAe,CAAgB,IAAI,CAAC,CAAC;QAExE,kEAAkE;QAC3D,mBAAc,GAAG,IAAI,eAAe,CAAU,KAAK,CAAC,CAAC;QAE5D,wEAAwE;QACjE,qBAAgB,GAAG,IAAI,eAAe,CAAU,KAAK,CAAC,CAAC;QAE9D,mEAAmE;QAC5D,iBAAY,GAAG,IAAI,OAAO,EAA2B,CAAC;QAE7D,qCAAqC;QAC9B,qBAAgB,GAAG,IAAI,OAAO,EAAwB,CAAC;QAE9D;;;;;;WAMG;QACI,4BAAuB,GAAG,IAAI,OAAO,EAAQ,CAAC;IAsEzD,CAAC;IApEG,iEAAiE;IAC1D,oBAAoB;QACvB,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC;IACxC,CAAC;IAED;;;OAGG;IACI,oBAAoB,CAAC,cAA6B;QACrD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACpD,CAAC;IAED;;;OAGG;IACI,sBAAsB,CAAC,cAA6B;QACvD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACpD,CAAC;IAED;;;OAGG;IACI,iBAAiB,CAAC,cAA6B;QAClD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;YACnB,cAAc,EAAE,cAAc;YAC9B,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,WAAW;SACtB,CAAC,CAAC;IACP,CAAC;IAED;;;OAGG;IACI,eAAe,CAAC,cAA6B;QAChD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;YACnB,cAAc,EAAE,cAAc;YAC9B,MAAM,EAAE,WAAW;YACnB,MAAM,EAAE,SAAS;SACpB,CAAC,CAAC;IACP,CAAC;IAED,yDAAyD;IAClD,sBAAsB,CAAC,QAA8B;QACxD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QACzD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,2DAA2D;IACpD,mBAAmB,CAAC,MAAe;QACtC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,6DAA6D;IACtD,qBAAqB,CAAC,MAAe;QACxC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED;;;OAGG;IACI,qBAAqB;QACxB,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,IAAI,IAAI,CAAC,qBAAqB,CAAC,KAAK,KAAK,IAAI,CAAC;IACrF,CAAC;CACJ"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared context interface — what sub-components see of the runtime.
|
|
3
|
+
*
|
|
4
|
+
* Sub-components (`ConversationStreaming`, `ConversationAgentRunner`, etc.) need to
|
|
5
|
+
* reach the currently-registered adapters at the moment they fire, NOT at the
|
|
6
|
+
* moment they were constructed. The host may call
|
|
7
|
+
* `runtime.UseNotificationAdapter(...)` after sub-components already exist.
|
|
8
|
+
*
|
|
9
|
+
* Rather than have each sub-component import `ConversationsRuntime` (which would
|
|
10
|
+
* create a circular module import — runtime imports sub-component to construct it,
|
|
11
|
+
* sub-component imports runtime to read adapters), we extract this narrow contract.
|
|
12
|
+
* The runtime implements it; sub-components take it as a constructor parameter.
|
|
13
|
+
*
|
|
14
|
+
* Because the runtime is passed by reference and the methods are getters, every
|
|
15
|
+
* sub-component call reads the *current* adapter — adapter swaps take effect
|
|
16
|
+
* immediately without rebuilding sub-components.
|
|
17
|
+
*
|
|
18
|
+
* @module @memberjunction/conversations-runtime
|
|
19
|
+
*/
|
|
20
|
+
import { INotificationAdapter } from '../adapters/INotificationAdapter.js';
|
|
21
|
+
import { IActiveTaskTracker } from '../adapters/IActiveTaskTracker.js';
|
|
22
|
+
/** Read-only view of the runtime's adapter slots, as seen by sub-components. */
|
|
23
|
+
export interface IConversationsRuntimeContext {
|
|
24
|
+
/** Currently registered notification adapter (or the console default). */
|
|
25
|
+
readonly Notification: INotificationAdapter;
|
|
26
|
+
/** Currently registered active-task tracker (or the no-op default). */
|
|
27
|
+
readonly Tasks: IActiveTaskTracker;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=IConversationsRuntimeContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IConversationsRuntimeContext.d.ts","sourceRoot":"","sources":["../../src/context/IConversationsRuntimeContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,gFAAgF;AAChF,MAAM,WAAW,4BAA4B;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAE5C,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;CACtC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared context interface — what sub-components see of the runtime.
|
|
3
|
+
*
|
|
4
|
+
* Sub-components (`ConversationStreaming`, `ConversationAgentRunner`, etc.) need to
|
|
5
|
+
* reach the currently-registered adapters at the moment they fire, NOT at the
|
|
6
|
+
* moment they were constructed. The host may call
|
|
7
|
+
* `runtime.UseNotificationAdapter(...)` after sub-components already exist.
|
|
8
|
+
*
|
|
9
|
+
* Rather than have each sub-component import `ConversationsRuntime` (which would
|
|
10
|
+
* create a circular module import — runtime imports sub-component to construct it,
|
|
11
|
+
* sub-component imports runtime to read adapters), we extract this narrow contract.
|
|
12
|
+
* The runtime implements it; sub-components take it as a constructor parameter.
|
|
13
|
+
*
|
|
14
|
+
* Because the runtime is passed by reference and the methods are getters, every
|
|
15
|
+
* sub-component call reads the *current* adapter — adapter swaps take effect
|
|
16
|
+
* immediately without rebuilding sub-components.
|
|
17
|
+
*
|
|
18
|
+
* @module @memberjunction/conversations-runtime
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=IConversationsRuntimeContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IConversationsRuntimeContext.js","sourceRoot":"","sources":["../../src/context/IConversationsRuntimeContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Default-agent resolution chain.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the hardcoded `Agents.find(a => a.Name === 'Sage')` lookup that previously lived
|
|
5
|
+
* in three places inside `@memberjunction/ng-conversations` with a metadata-driven chain
|
|
6
|
+
* routed through `MJ: Application Settings`.
|
|
7
|
+
*
|
|
8
|
+
* Resolution order on every {@link DefaultAgentResolver.resolve} call:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Explicit `explicitAgentId`** on the call (matches the widget's `[DefaultAgentId]`
|
|
11
|
+
* `@Input` — already works today, preserved here for layering).
|
|
12
|
+
* 2. **App-scoped `MJ: Application Settings`** row (`ApplicationID = <current app>`,
|
|
13
|
+
* `Name = 'Conversations.DefaultAgentID'`, `Value = <agent ID>`).
|
|
14
|
+
* 3. **Global `MJ: Application Settings`** row (`ApplicationID IS NULL`, same name).
|
|
15
|
+
* Ships as a metadata seed pointing at Sage on a fresh install.
|
|
16
|
+
* 4. **Code-const fallback** — `Agents.find(a => a.Name === 'Sage')`. Safety net for
|
|
17
|
+
* installs where the seed was skipped; preserves today's behavior so the system never
|
|
18
|
+
* silently fails to route a turn.
|
|
19
|
+
*
|
|
20
|
+
* Steps 2 and 3 are handled by `ApplicationSettingEngine.GetSetting` in one call — that API
|
|
21
|
+
* already does app-scoped-first / global-fallback resolution internally.
|
|
22
|
+
*
|
|
23
|
+
* @module @memberjunction/conversations-runtime
|
|
24
|
+
*/
|
|
25
|
+
import { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
26
|
+
import { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';
|
|
27
|
+
/**
|
|
28
|
+
* Options accepted by {@link DefaultAgentResolver.resolve}. Every field is optional;
|
|
29
|
+
* callers typically pass `applicationId` when an embedder has app context, and the rest
|
|
30
|
+
* fall through to defaults.
|
|
31
|
+
*/
|
|
32
|
+
export interface DefaultAgentResolveOptions {
|
|
33
|
+
/**
|
|
34
|
+
* If supplied AND a matching agent exists, this wins immediately (step 1).
|
|
35
|
+
* Mirrors the widget's `[DefaultAgentId]` `@Input` — used by Form Builder, Component
|
|
36
|
+
* Studio AI Assistant, and any future embedder that pins a specific agent.
|
|
37
|
+
*/
|
|
38
|
+
explicitAgentId?: string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Application context for the conversation. When supplied, an app-scoped Application
|
|
41
|
+
* Setting (step 2) takes precedence over the global default (step 3).
|
|
42
|
+
*/
|
|
43
|
+
applicationId?: string | null;
|
|
44
|
+
/** Context user — passed to engines that need it on the server side. */
|
|
45
|
+
contextUser?: UserInfo;
|
|
46
|
+
/** Metadata provider to bind to — falls back to `Metadata.Provider`. */
|
|
47
|
+
provider?: IMetadataProvider;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolves the default agent for a conversation turn.
|
|
51
|
+
*
|
|
52
|
+
* Usually accessed via `ConversationsRuntime.Instance.DefaultAgent`. Stateless beyond
|
|
53
|
+
* lazy delegation to `ApplicationSettingEngine` and `AIEngineBase`.
|
|
54
|
+
*/
|
|
55
|
+
export declare class DefaultAgentResolver {
|
|
56
|
+
/** Application Setting key consulted in steps 2 and 3. */
|
|
57
|
+
static readonly SETTING_NAME = "Conversations.DefaultAgentID";
|
|
58
|
+
/**
|
|
59
|
+
* Last-resort fallback agent name (step 4). Kept as a constant rather than another
|
|
60
|
+
* setting so the system has a hard floor even if metadata sync has never run on a
|
|
61
|
+
* fresh install — preserves today's "Sage is the default" behavior unconditionally.
|
|
62
|
+
*/
|
|
63
|
+
static readonly FALLBACK_AGENT_NAME = "Sage";
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the default agent for this turn. Walks the 4-step chain; throws a descriptive
|
|
66
|
+
* error if every step misses (vs. the previous code path's silent `null` return, which
|
|
67
|
+
* made misconfigurations hard to spot at the call site).
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const agent = await runtime.DefaultAgent.resolve({
|
|
72
|
+
* explicitAgentId: widgetInput.DefaultAgentId, // wins if non-null and matches
|
|
73
|
+
* applicationId: currentAppId, // scopes the settings lookup
|
|
74
|
+
* contextUser: this.ProviderToUse.CurrentUser,
|
|
75
|
+
* provider: this.ProviderToUse,
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
resolve(options?: DefaultAgentResolveOptions): Promise<MJAIAgentEntityExtended>;
|
|
80
|
+
/**
|
|
81
|
+
* Find an agent by ID from the AIEngineBase cache. Returns `undefined` if not found.
|
|
82
|
+
* Uses {@link UUIDsEqual} per the standing rule about comparing UUIDs across
|
|
83
|
+
* SQL Server / Postgres (case differences would silently miss).
|
|
84
|
+
*/
|
|
85
|
+
private findAgentById;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=DefaultAgentResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DefaultAgentResolver.d.ts","sourceRoot":"","sources":["../../src/default-agent/DefaultAgentResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAGvE;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACvC;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B,wEAAwE;IACxE,WAAW,CAAC,EAAE,QAAQ,CAAC;IAEvB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAED;;;;;GAKG;AACH,qBAAa,oBAAoB;IAC7B,0DAA0D;IAC1D,gBAAuB,YAAY,kCAAkC;IAErE;;;;OAIG;IACH,gBAAuB,mBAAmB,UAAU;IAEpD;;;;;;;;;;;;;;OAcG;IACU,OAAO,CAAC,OAAO,GAAE,0BAA+B,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAkDhG;;;;OAIG;IACH,OAAO,CAAC,aAAa;CAGxB"}
|