@memberjunction/ai-agents 6.2.0-edge.3 → 6.2.0-edge.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/AgentRunner.d.ts +49 -2
- package/dist/AgentRunner.d.ts.map +1 -1
- package/dist/AgentRunner.js +114 -21
- package/dist/AgentRunner.js.map +1 -1
- package/dist/ConversationCompactionManager.d.ts +2 -0
- package/dist/ConversationCompactionManager.d.ts.map +1 -1
- package/dist/ConversationCompactionManager.js +2 -2
- package/dist/ConversationCompactionManager.js.map +1 -1
- package/dist/ConversationToolManager.d.ts +13 -2
- package/dist/ConversationToolManager.d.ts.map +1 -1
- package/dist/ConversationToolManager.js +19 -3
- package/dist/ConversationToolManager.js.map +1 -1
- package/dist/KnowledgeAgent.d.ts.map +1 -1
- package/dist/KnowledgeAgent.js +6 -1
- package/dist/KnowledgeAgent.js.map +1 -1
- package/dist/MJAIAgentRequestEntityServer.d.ts +6 -0
- package/dist/MJAIAgentRequestEntityServer.d.ts.map +1 -1
- package/dist/MJAIAgentRequestEntityServer.js +26 -1
- package/dist/MJAIAgentRequestEntityServer.js.map +1 -1
- package/dist/agent-run-watchdog.d.ts +65 -5
- package/dist/agent-run-watchdog.d.ts.map +1 -1
- package/dist/agent-run-watchdog.js +143 -28
- package/dist/agent-run-watchdog.js.map +1 -1
- package/dist/agent-types/loop-agent-prompt-params.d.ts +7 -0
- package/dist/agent-types/loop-agent-prompt-params.d.ts.map +1 -1
- package/dist/agent-types/loop-agent-prompt-params.js +1 -0
- package/dist/agent-types/loop-agent-prompt-params.js.map +1 -1
- package/dist/artifact-tools/SearchResultSetToolLibrary.js +4 -4
- package/dist/artifact-tools/SearchResultSetToolLibrary.js.map +1 -1
- package/dist/base-agent.d.ts +275 -18
- package/dist/base-agent.d.ts.map +1 -1
- package/dist/base-agent.js +761 -216
- package/dist/base-agent.js.map +1 -1
- package/dist/client-tool-results.d.ts +45 -0
- package/dist/client-tool-results.d.ts.map +1 -0
- package/dist/client-tool-results.js +94 -0
- package/dist/client-tool-results.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/prior-turn-tool-result-cache.d.ts +31 -12
- package/dist/prior-turn-tool-result-cache.d.ts.map +1 -1
- package/dist/prior-turn-tool-result-cache.js +59 -16
- package/dist/prior-turn-tool-result-cache.js.map +1 -1
- package/dist/realtime/bridge-realtime-session-factory.d.ts +44 -2
- package/dist/realtime/bridge-realtime-session-factory.d.ts.map +1 -1
- package/dist/realtime/bridge-realtime-session-factory.js +68 -20
- package/dist/realtime/bridge-realtime-session-factory.js.map +1 -1
- package/dist/realtime/bridge-realtime-usage-recorder.d.ts +81 -0
- package/dist/realtime/bridge-realtime-usage-recorder.d.ts.map +1 -0
- package/dist/realtime/bridge-realtime-usage-recorder.js +194 -0
- package/dist/realtime/bridge-realtime-usage-recorder.js.map +1 -0
- package/dist/realtime/client-only-channel-server.d.ts +83 -0
- package/dist/realtime/client-only-channel-server.d.ts.map +1 -0
- package/dist/realtime/client-only-channel-server.js +107 -0
- package/dist/realtime/client-only-channel-server.js.map +1 -0
- package/dist/realtime/identity-verification-channel-server.d.ts +50 -0
- package/dist/realtime/identity-verification-channel-server.d.ts.map +1 -0
- package/dist/realtime/identity-verification-channel-server.js +66 -0
- package/dist/realtime/identity-verification-channel-server.js.map +1 -0
- package/dist/realtime/interactive-component-channel-server.d.ts +39 -0
- package/dist/realtime/interactive-component-channel-server.d.ts.map +1 -0
- package/dist/realtime/interactive-component-channel-server.js +55 -0
- package/dist/realtime/interactive-component-channel-server.js.map +1 -0
- package/dist/realtime/realtime-avatar-resolution.d.ts +194 -0
- package/dist/realtime/realtime-avatar-resolution.d.ts.map +1 -0
- package/dist/realtime/realtime-avatar-resolution.js +208 -0
- package/dist/realtime/realtime-avatar-resolution.js.map +1 -0
- package/dist/realtime/realtime-channel-policy.d.ts +81 -0
- package/dist/realtime/realtime-channel-policy.d.ts.map +1 -0
- package/dist/realtime/realtime-channel-policy.js +91 -0
- package/dist/realtime/realtime-channel-policy.js.map +1 -0
- package/dist/realtime/realtime-channel-server-host.d.ts +14 -0
- package/dist/realtime/realtime-channel-server-host.d.ts.map +1 -1
- package/dist/realtime/realtime-channel-server-host.js +35 -0
- package/dist/realtime/realtime-channel-server-host.js.map +1 -1
- package/dist/realtime/realtime-client-session-service.d.ts +430 -30
- package/dist/realtime/realtime-client-session-service.d.ts.map +1 -1
- package/dist/realtime/realtime-client-session-service.js +766 -111
- package/dist/realtime/realtime-client-session-service.js.map +1 -1
- package/dist/realtime/realtime-coagent-config.d.ts +94 -15
- package/dist/realtime/realtime-coagent-config.d.ts.map +1 -1
- package/dist/realtime/realtime-coagent-config.js +109 -4
- package/dist/realtime/realtime-coagent-config.js.map +1 -1
- package/dist/realtime/realtime-recording-store.d.ts +136 -16
- package/dist/realtime/realtime-recording-store.d.ts.map +1 -1
- package/dist/realtime/realtime-recording-store.js +505 -39
- package/dist/realtime/realtime-recording-store.js.map +1 -1
- package/dist/realtime/realtime-session-runner.js +4 -4
- package/dist/realtime/realtime-session-runner.js.map +1 -1
- package/dist/realtime/realtime-vendor-resolution.d.ts +9 -0
- package/dist/realtime/realtime-vendor-resolution.d.ts.map +1 -1
- package/dist/realtime/realtime-vendor-resolution.js +16 -5
- package/dist/realtime/realtime-vendor-resolution.js.map +1 -1
- package/dist/realtime/realtime-video-output-gate.d.ts +83 -0
- package/dist/realtime/realtime-video-output-gate.d.ts.map +1 -0
- package/dist/realtime/realtime-video-output-gate.js +79 -0
- package/dist/realtime/realtime-video-output-gate.js.map +1 -0
- package/dist/tool-result-format.d.ts +14 -0
- package/dist/tool-result-format.d.ts.map +1 -1
- package/dist/tool-result-format.js.map +1 -1
- package/package.json +19 -19
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { BaseRealtimeModel, MakeAIAPIKeyResolver } from '@memberjunction/ai';
|
|
20
20
|
import { Metadata } from '@memberjunction/core';
|
|
21
|
-
import { MJGlobal, UUIDsEqual } from '@memberjunction/global';
|
|
21
|
+
import { MJGlobal, UUIDsEqual, IndexByUUID } from '@memberjunction/global';
|
|
22
22
|
import { AIEngine } from '@memberjunction/aiengine';
|
|
23
23
|
import { BaseAgent } from '../base-agent.js';
|
|
24
24
|
import { RealtimeClientSessionService } from './realtime-client-session-service.js';
|
|
25
25
|
import { SelectRealtimeVendorForModel } from './realtime-vendor-resolution.js';
|
|
26
|
+
import { RealtimeModelShowsAvatar } from './realtime-video-output-gate.js';
|
|
26
27
|
/**
|
|
27
28
|
* Opens a raw {@link IRealtimeSession} for the agent named in `ctx`. Bind this onto a bridge's
|
|
28
29
|
* session-factory seam (e.g. `LiveKitAgentRoomCoordinator.Instance.SetSessionFactory(CreateBridgeRealtimeSession)`).
|
|
@@ -131,6 +132,9 @@ function buildRealtimeData(ctx) {
|
|
|
131
132
|
if (ctx.HostTools && ctx.HostTools.length > 0) {
|
|
132
133
|
data.realtimeHostTools = ctx.HostTools;
|
|
133
134
|
}
|
|
135
|
+
if (ctx.ResolveHostTools) {
|
|
136
|
+
data.resolveHostTools = ctx.ResolveHostTools;
|
|
137
|
+
}
|
|
134
138
|
if (ctx.HostFraming && ctx.HostFraming.trim().length > 0) {
|
|
135
139
|
data.realtimeHostFraming = ctx.HostFraming.trim();
|
|
136
140
|
}
|
|
@@ -143,6 +147,12 @@ function buildRealtimeData(ctx) {
|
|
|
143
147
|
if (ctx.SelfNames && ctx.SelfNames.length > 0) {
|
|
144
148
|
data.realtimeSelfNames = ctx.SelfNames;
|
|
145
149
|
}
|
|
150
|
+
if (ctx.AvatarDelivery === 'room') {
|
|
151
|
+
data.realtimeAvatarDelivery = 'room';
|
|
152
|
+
}
|
|
153
|
+
if (ctx.PhoneCall === true) {
|
|
154
|
+
data.realtimePhoneCall = true;
|
|
155
|
+
}
|
|
146
156
|
return Object.keys(data).length > 0 ? data : undefined;
|
|
147
157
|
}
|
|
148
158
|
/**
|
|
@@ -168,6 +178,12 @@ export async function FinalizeBridgeCoAgentRuns(agentSessionID, success, context
|
|
|
168
178
|
* model/voice picker. Only models with an Active vendor + resolvable API key + ClassFactory driver are
|
|
169
179
|
* returned (a model you can't actually run isn't worth offering). Voices come from the driver
|
|
170
180
|
* ({@link BaseRealtimeModel.SupportedVoices}) — the near-term, driver-owned source of truth.
|
|
181
|
+
* A persona voice whose persona also has a preset Video binding on the same vendor names that avatar
|
|
182
|
+
* ({@link RealtimeModelVoiceOption.AvatarID}), when the model shows avatars on that vendor
|
|
183
|
+
* ({@link RealtimeModelShowsAvatar}: its Video/Output row allows video or it has none, and the driver
|
|
184
|
+
* renders avatars on its endpoint); driver voices never do. So the picker marks a voice "Comes with an
|
|
185
|
+
* avatar" only where a call can show one. A persona with a face doesn't stand in for its plain voice, so
|
|
186
|
+
* the plain voice is listed too.
|
|
171
187
|
*
|
|
172
188
|
* @param contextUser The user the engine config runs as (server-side).
|
|
173
189
|
* @param provider The request-scoped metadata provider (multi-provider safe).
|
|
@@ -189,30 +205,62 @@ export async function GetRealtimeModelVoices(contextUser, provider, resolveAPIKe
|
|
|
189
205
|
if (!driverClass) {
|
|
190
206
|
continue; // no active vendor with a resolvable key — not runnable, so omit
|
|
191
207
|
}
|
|
192
|
-
// 1. Consult metadata first (Personas & PersonaVendors carry curated names/descriptions)
|
|
193
|
-
const modelPersonas = AIEngine.Instance.GetModelPersonas(model.ID, 'Audio', selection.VendorID);
|
|
194
|
-
const voices = modelPersonas.map((rp) => ({
|
|
195
|
-
ID: rp.PersonaVendor.APIName,
|
|
196
|
-
Name: rp.Persona.Name,
|
|
197
|
-
}));
|
|
198
|
-
// Collect explicitly excluded voice IDs (IsSupported === false) for this model and vendor
|
|
199
|
-
const excludedVoiceApiNames = new Set(AIEngine.Instance.GetModelPersonaExclusions(model.ID, 'Audio', selection.VendorID)
|
|
200
|
-
.map((name) => name.toLowerCase()));
|
|
201
|
-
// 2. Union with driver SupportedVoices: append any driver voices not already present or explicitly excluded
|
|
202
208
|
const instance = MJGlobal.Instance.ClassFactory.CreateInstance(BaseRealtimeModel, driverClass, resolveAPIKey(driverClass));
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
voices.push(dv);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
209
|
+
// 1. Consult metadata first (Personas & PersonaVendors carry curated names/descriptions, and avatars where the
|
|
210
|
+
// model shows them on this vendor)
|
|
211
|
+
const showsAvatar = instance ? RealtimeModelShowsAvatar({ ModelID: model.ID, APIName: selection.APIName, Model: instance }, AIEngine.Instance) : false;
|
|
212
|
+
const voices = personaVoiceOptions(model.ID, selection.VendorID, showsAvatar);
|
|
213
|
+
// 2. Union with driver SupportedVoices: append the driver voices no persona offers plainly, unless excluded
|
|
214
|
+
appendDriverVoices(voices, instance?.SupportedVoices ?? [], model.ID, selection.VendorID);
|
|
212
215
|
out.push({ ModelID: model.ID, ModelName: model.Name ?? '', Voices: voices });
|
|
213
216
|
}
|
|
214
217
|
return out;
|
|
215
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Appends the driver's voices that no persona already offers as a plain voice (without a face), skipping the ones the
|
|
221
|
+
* model explicitly excludes (`IsSupported === false`). A persona with a face doesn't stand in for its plain voice, so the
|
|
222
|
+
* voice stays pickable without the face. Driver voices have no persona: no avatar, no image.
|
|
223
|
+
*/
|
|
224
|
+
function appendDriverVoices(voices, driverVoices, modelID, vendorID) {
|
|
225
|
+
const excluded = new Set(AIEngine.Instance.GetModelPersonaExclusions(modelID, 'Audio', vendorID).map((name) => name.toLowerCase()));
|
|
226
|
+
for (const dv of driverVoices) {
|
|
227
|
+
const id = dv.ID.toLowerCase();
|
|
228
|
+
if (!excluded.has(id) && !voices.some((v) => !v.AvatarID && v.ID.toLowerCase() === id)) {
|
|
229
|
+
voices.push({ ID: dv.ID, Name: dv.Name });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* The model's persona voices on a vendor, one per persona, in persona order. On a model that shows avatars there, a
|
|
235
|
+
* persona whose preset Video binding on the same vendor the model supports carries that binding's `APIName` as its avatar
|
|
236
|
+
* (the face the session asks for when the voice is picked); a binding on any other vendor doesn't count, nor does a custom
|
|
237
|
+
* one, and with no vendor there is nothing to match. On a model that shows none, no voice comes with an avatar.
|
|
238
|
+
*
|
|
239
|
+
* @param showsAvatar Whether the model shows avatars on this vendor ({@link RealtimeModelShowsAvatar}).
|
|
240
|
+
*/
|
|
241
|
+
function personaVoiceOptions(modelID, vendorID, showsAvatar) {
|
|
242
|
+
const faces = vendorID && showsAvatar ? AIEngine.Instance.GetModelPersonas(modelID, 'Video', vendorID).filter(isPresetFace) : [];
|
|
243
|
+
// First face per persona wins, as faces.find() would.
|
|
244
|
+
const facesByPersona = IndexByUUID(faces, (f) => f.Persona.ID);
|
|
245
|
+
return AIEngine.Instance.GetModelPersonas(modelID, 'Audio', vendorID).map((voice) => {
|
|
246
|
+
const face = facesByPersona.Get(voice.Persona.ID);
|
|
247
|
+
const image = voice.Persona.PreviewImageURL?.trim();
|
|
248
|
+
return {
|
|
249
|
+
ID: voice.PersonaVendor.APIName,
|
|
250
|
+
Name: voice.Persona.Name,
|
|
251
|
+
PersonaID: voice.Persona.ID,
|
|
252
|
+
...(face ? { AvatarID: face.PersonaVendor.APIName.trim() } : {}),
|
|
253
|
+
...(image ? { PreviewImageURL: image } : {}),
|
|
254
|
+
};
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Whether a Video binding is a face a picked voice can bring: a preset (`Avatar.Kind` absent or `'preset'`). Custom avatars
|
|
259
|
+
* are not supported, so a session asking for one would stay audio only.
|
|
260
|
+
*/
|
|
261
|
+
function isPresetFace(face) {
|
|
262
|
+
return (face.PersonaVendor.VendorSettingsObject?.Avatar?.Kind ?? 'preset') !== 'custom';
|
|
263
|
+
}
|
|
216
264
|
/** Resolves the agent entity from the engine cache by id (preferred), then by case-insensitive name. */
|
|
217
265
|
function resolveAgentEntity(ctx) {
|
|
218
266
|
const agents = AIEngine.Instance.Agents;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-realtime-session-factory.js","sourceRoot":"","sources":["../../src/realtime/bridge-realtime-session-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAiC,iBAAiB,EAAiE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC3K,OAAO,EAAqB,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAiB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"bridge-realtime-session-factory.js","sourceRoot":"","sources":["../../src/realtime/bridge-realtime-session-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { RealtimeUsage } from '@memberjunction/ai';
|
|
2
|
+
import { type RealtimeUsageRecord } from '@memberjunction/ai-engine-base';
|
|
3
|
+
/** How long after the first unwritten update the recorder writes, in milliseconds. */
|
|
4
|
+
export declare const BRIDGE_USAGE_FLUSH_MS = 10000;
|
|
5
|
+
/** One write: the token amounts since the previous write, and the per-modality usage. */
|
|
6
|
+
export interface BridgeUsageWrite {
|
|
7
|
+
/** Input tokens to add. */
|
|
8
|
+
InputTokens: number;
|
|
9
|
+
/** Output tokens to add. */
|
|
10
|
+
OutputTokens: number;
|
|
11
|
+
/** Per-modality amounts to add, and the latest running totals; absent when the session reported none. */
|
|
12
|
+
Details?: RealtimeUsageRecord;
|
|
13
|
+
}
|
|
14
|
+
/** Stores one {@link BridgeUsageWrite}; resolves `false` when nothing was stored. */
|
|
15
|
+
export type BridgeUsageWriter = (write: BridgeUsageWrite) => Promise<boolean>;
|
|
16
|
+
/** What a recorder has accepted over its life, for the session's closing log line. */
|
|
17
|
+
export interface BridgeUsageTotals {
|
|
18
|
+
InputTokens: number;
|
|
19
|
+
OutputTokens: number;
|
|
20
|
+
/** Seconds of video the model generated (an avatar). */
|
|
21
|
+
OutputVideoSeconds: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Adds up one bridged session's usage and writes it on a timer and at close. A failed write keeps its usage for the
|
|
25
|
+
* next one; the write at close is the last attempt.
|
|
26
|
+
*/
|
|
27
|
+
export declare class BridgeRealtimeUsageRecorder {
|
|
28
|
+
private readonly writer;
|
|
29
|
+
private readonly label;
|
|
30
|
+
private readonly flushMs;
|
|
31
|
+
private inputTokens;
|
|
32
|
+
private outputTokens;
|
|
33
|
+
private details;
|
|
34
|
+
private timer;
|
|
35
|
+
private writeChain;
|
|
36
|
+
private closed;
|
|
37
|
+
private lateUpdateLogged;
|
|
38
|
+
private readonly accepted;
|
|
39
|
+
/**
|
|
40
|
+
* @param writer Stores one write.
|
|
41
|
+
* @param label Names the session in log lines (for example its prompt run id).
|
|
42
|
+
* @param flushMs How long after the first unwritten update to write.
|
|
43
|
+
*/
|
|
44
|
+
constructor(writer: BridgeUsageWriter, label: string, flushMs?: number);
|
|
45
|
+
/** What the recorder has accepted so far. */
|
|
46
|
+
get Totals(): Readonly<BridgeUsageTotals>;
|
|
47
|
+
/** Whether the recorder holds usage that is not written yet. */
|
|
48
|
+
get HasUnwrittenUsage(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Takes one `OnUsage` update. An update that adds nothing is ignored; the first one that does starts the write timer.
|
|
51
|
+
* After {@link Close} an update is dropped, and the first one dropped is logged.
|
|
52
|
+
*
|
|
53
|
+
* @param usage The update the session reported.
|
|
54
|
+
*/
|
|
55
|
+
Add(usage: RealtimeUsage): void;
|
|
56
|
+
/** Writes what is unwritten now, after any write in progress. Never rejects. */
|
|
57
|
+
Flush(): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Stops taking updates and writes what is unwritten. When that last write fails, its amounts are logged and dropped.
|
|
60
|
+
* Safe to call more than once.
|
|
61
|
+
*/
|
|
62
|
+
Close(): Promise<void>;
|
|
63
|
+
/** Adds the update's token totals to the unwritten ones. Returns whether it added anything. */
|
|
64
|
+
private addTokens;
|
|
65
|
+
/** Adds the update's per-modality usage and session duration to the unwritten record. Returns whether it held any. */
|
|
66
|
+
private addDetails;
|
|
67
|
+
/** Starts the write timer unless one is running. The timer never keeps the process alive. */
|
|
68
|
+
private armWrite;
|
|
69
|
+
private clearTimer;
|
|
70
|
+
/** Writes the unwritten usage once; a failed write puts its usage back. */
|
|
71
|
+
private writeUnwritten;
|
|
72
|
+
/** Moves the unwritten usage into a write, or returns `null` when there is none. */
|
|
73
|
+
private takeUnwritten;
|
|
74
|
+
/** Puts a failed write's usage back, together with what arrived since. */
|
|
75
|
+
private putBack;
|
|
76
|
+
/** Forgets the unwritten usage. */
|
|
77
|
+
private clearUnwritten;
|
|
78
|
+
/** Logs the first update dropped after close. */
|
|
79
|
+
private logLateUpdate;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=bridge-realtime-usage-recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-realtime-usage-recorder.d.ts","sourceRoot":"","sources":["../../src/realtime/bridge-realtime-usage-recorder.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAA4C,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAEpH,sFAAsF;AACtF,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C,yFAAyF;AACzF,MAAM,WAAW,gBAAgB;IAC7B,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,yGAAyG;IACzG,OAAO,CAAC,EAAE,mBAAmB,CAAC;CACjC;AAED,qFAAqF;AACrF,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9E,sFAAsF;AACtF,MAAM,WAAW,iBAAiB;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,kBAAkB,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,qBAAa,2BAA2B;IAgBhC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAjB5B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiF;IAE1G;;;;OAIG;gBAEkB,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,MAA8B;IAG5D,6CAA6C;IAC7C,IAAW,MAAM,IAAI,QAAQ,CAAC,iBAAiB,CAAC,CAE/C;IAED,gEAAgE;IAChE,IAAW,iBAAiB,IAAI,OAAO,CAEtC;IAED;;;;;OAKG;IACI,GAAG,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAYtC,gFAAgF;IACzE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM7B;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBnC,+FAA+F;IAC/F,OAAO,CAAC,SAAS;IAejB,sHAAsH;IACtH,OAAO,CAAC,UAAU;IAclB,6FAA6F;IAC7F,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,UAAU;IAOlB,2EAA2E;YAC7D,cAAc;IAgB5B,oFAAoF;IACpF,OAAO,CAAC,aAAa;IAarB,0EAA0E;IAC1E,OAAO,CAAC,OAAO;IAQf,mCAAmC;IACnC,OAAO,CAAC,cAAc;IAMtB,iDAAiD;IACjD,OAAO,CAAC,aAAa;CAUxB"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Records the usage a server-held (bridged) realtime session reports. It adds up the session's `OnUsage`
|
|
3
|
+
* updates and writes them through a writer (the co-agent prompt run's usage accumulation) {@link BRIDGE_USAGE_FLUSH_MS}
|
|
4
|
+
* after the first unwritten update, and once more when it is closed, so the run is priced at finalize from its final
|
|
5
|
+
* counts. After it is closed it stores nothing more. Per-modality usage follows the realtime usage record's rules
|
|
6
|
+
* (`AddRealtimeUsageRecord`): amounts add up, running totals keep the larger value.
|
|
7
|
+
*
|
|
8
|
+
* @module @memberjunction/ai-agents
|
|
9
|
+
*/
|
|
10
|
+
import { LogError, LogStatus, LogStatusEx } from '@memberjunction/core';
|
|
11
|
+
import { AddRealtimeUsageRecord, HasRealtimeUsage } from '@memberjunction/ai-engine-base';
|
|
12
|
+
/** How long after the first unwritten update the recorder writes, in milliseconds. */
|
|
13
|
+
export const BRIDGE_USAGE_FLUSH_MS = 10_000;
|
|
14
|
+
/**
|
|
15
|
+
* Adds up one bridged session's usage and writes it on a timer and at close. A failed write keeps its usage for the
|
|
16
|
+
* next one; the write at close is the last attempt.
|
|
17
|
+
*/
|
|
18
|
+
export class BridgeRealtimeUsageRecorder {
|
|
19
|
+
/**
|
|
20
|
+
* @param writer Stores one write.
|
|
21
|
+
* @param label Names the session in log lines (for example its prompt run id).
|
|
22
|
+
* @param flushMs How long after the first unwritten update to write.
|
|
23
|
+
*/
|
|
24
|
+
constructor(writer, label, flushMs = BRIDGE_USAGE_FLUSH_MS) {
|
|
25
|
+
this.writer = writer;
|
|
26
|
+
this.label = label;
|
|
27
|
+
this.flushMs = flushMs;
|
|
28
|
+
this.inputTokens = 0;
|
|
29
|
+
this.outputTokens = 0;
|
|
30
|
+
this.details = null;
|
|
31
|
+
this.timer = null;
|
|
32
|
+
this.writeChain = Promise.resolve();
|
|
33
|
+
this.closed = false;
|
|
34
|
+
this.lateUpdateLogged = false;
|
|
35
|
+
this.accepted = { InputTokens: 0, OutputTokens: 0, OutputVideoSeconds: 0 };
|
|
36
|
+
}
|
|
37
|
+
/** What the recorder has accepted so far. */
|
|
38
|
+
get Totals() {
|
|
39
|
+
return this.accepted;
|
|
40
|
+
}
|
|
41
|
+
/** Whether the recorder holds usage that is not written yet. */
|
|
42
|
+
get HasUnwrittenUsage() {
|
|
43
|
+
return this.inputTokens > 0 || this.outputTokens > 0 || HasRealtimeUsage(this.details);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Takes one `OnUsage` update. An update that adds nothing is ignored; the first one that does starts the write timer.
|
|
47
|
+
* After {@link Close} an update is dropped, and the first one dropped is logged.
|
|
48
|
+
*
|
|
49
|
+
* @param usage The update the session reported.
|
|
50
|
+
*/
|
|
51
|
+
Add(usage) {
|
|
52
|
+
if (this.closed) {
|
|
53
|
+
this.logLateUpdate(usage);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const addedTokens = this.addTokens(usage);
|
|
57
|
+
const addedDetails = this.addDetails(usage);
|
|
58
|
+
if (addedTokens || addedDetails) {
|
|
59
|
+
this.armWrite();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Writes what is unwritten now, after any write in progress. Never rejects. */
|
|
63
|
+
Flush() {
|
|
64
|
+
this.clearTimer();
|
|
65
|
+
this.writeChain = this.writeChain.then(() => this.writeUnwritten());
|
|
66
|
+
return this.writeChain;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Stops taking updates and writes what is unwritten. When that last write fails, its amounts are logged and dropped.
|
|
70
|
+
* Safe to call more than once.
|
|
71
|
+
*/
|
|
72
|
+
async Close() {
|
|
73
|
+
if (this.closed) {
|
|
74
|
+
await this.writeChain;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.closed = true;
|
|
78
|
+
await this.Flush();
|
|
79
|
+
if (this.HasUnwrittenUsage) {
|
|
80
|
+
LogError(`[Bridged usage] ${this.label}: the last usage write failed; not stored: ${this.inputTokens} input and ` +
|
|
81
|
+
`${this.outputTokens} output tokens.`);
|
|
82
|
+
this.clearUnwritten();
|
|
83
|
+
}
|
|
84
|
+
LogStatusEx({
|
|
85
|
+
message: `[Bridged usage] ${this.label}: ${this.accepted.InputTokens} input and ${this.accepted.OutputTokens} output ` +
|
|
86
|
+
`tokens, ${this.accepted.OutputVideoSeconds} s of generated video.`,
|
|
87
|
+
verboseOnly: true,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/** Adds the update's token totals to the unwritten ones. Returns whether it added anything. */
|
|
91
|
+
addTokens(usage) {
|
|
92
|
+
let added = false;
|
|
93
|
+
if (isAmount(usage.InputTokens)) {
|
|
94
|
+
this.inputTokens += usage.InputTokens;
|
|
95
|
+
this.accepted.InputTokens += usage.InputTokens;
|
|
96
|
+
added = true;
|
|
97
|
+
}
|
|
98
|
+
if (isAmount(usage.OutputTokens)) {
|
|
99
|
+
this.outputTokens += usage.OutputTokens;
|
|
100
|
+
this.accepted.OutputTokens += usage.OutputTokens;
|
|
101
|
+
added = true;
|
|
102
|
+
}
|
|
103
|
+
return added;
|
|
104
|
+
}
|
|
105
|
+
/** Adds the update's per-modality usage and session duration to the unwritten record. Returns whether it held any. */
|
|
106
|
+
addDetails(usage) {
|
|
107
|
+
const update = AddRealtimeUsageRecord(null, {
|
|
108
|
+
Input: usage.InputTokenDetails,
|
|
109
|
+
Output: usage.OutputTokenDetails,
|
|
110
|
+
DurationSeconds: usage.DurationSeconds,
|
|
111
|
+
});
|
|
112
|
+
if (!HasRealtimeUsage(update)) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
this.details = AddRealtimeUsageRecord(this.details, update);
|
|
116
|
+
this.accepted.OutputVideoSeconds += update.Output?.VideoSeconds ?? 0;
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
/** Starts the write timer unless one is running. The timer never keeps the process alive. */
|
|
120
|
+
armWrite() {
|
|
121
|
+
if (this.timer) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
this.timer = setTimeout(() => {
|
|
125
|
+
this.timer = null;
|
|
126
|
+
void this.Flush();
|
|
127
|
+
}, this.flushMs);
|
|
128
|
+
this.timer.unref?.();
|
|
129
|
+
}
|
|
130
|
+
clearTimer() {
|
|
131
|
+
if (this.timer) {
|
|
132
|
+
clearTimeout(this.timer);
|
|
133
|
+
this.timer = null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Writes the unwritten usage once; a failed write puts its usage back. */
|
|
137
|
+
async writeUnwritten() {
|
|
138
|
+
const write = this.takeUnwritten();
|
|
139
|
+
if (!write) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
let stored = false;
|
|
143
|
+
try {
|
|
144
|
+
stored = await this.writer(write);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
LogError(`[Bridged usage] ${this.label}: writing usage failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
148
|
+
}
|
|
149
|
+
if (!stored) {
|
|
150
|
+
this.putBack(write);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** Moves the unwritten usage into a write, or returns `null` when there is none. */
|
|
154
|
+
takeUnwritten() {
|
|
155
|
+
if (!this.HasUnwrittenUsage) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
const write = {
|
|
159
|
+
InputTokens: this.inputTokens,
|
|
160
|
+
OutputTokens: this.outputTokens,
|
|
161
|
+
...(this.details && HasRealtimeUsage(this.details) ? { Details: this.details } : {}),
|
|
162
|
+
};
|
|
163
|
+
this.clearUnwritten();
|
|
164
|
+
return write;
|
|
165
|
+
}
|
|
166
|
+
/** Puts a failed write's usage back, together with what arrived since. */
|
|
167
|
+
putBack(write) {
|
|
168
|
+
this.inputTokens += write.InputTokens;
|
|
169
|
+
this.outputTokens += write.OutputTokens;
|
|
170
|
+
if (write.Details) {
|
|
171
|
+
this.details = AddRealtimeUsageRecord(write.Details, this.details ?? {});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** Forgets the unwritten usage. */
|
|
175
|
+
clearUnwritten() {
|
|
176
|
+
this.inputTokens = 0;
|
|
177
|
+
this.outputTokens = 0;
|
|
178
|
+
this.details = null;
|
|
179
|
+
}
|
|
180
|
+
/** Logs the first update dropped after close. */
|
|
181
|
+
logLateUpdate(usage) {
|
|
182
|
+
if (this.lateUpdateLogged) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
this.lateUpdateLogged = true;
|
|
186
|
+
LogStatus(`[Bridged usage] ${this.label}: usage reported after the session's run was finalized is not stored ` +
|
|
187
|
+
`(first dropped: ${usage.InputTokens} input and ${usage.OutputTokens} output tokens).`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/** Whether a reported token total is one to add: a finite number above zero. */
|
|
191
|
+
function isAmount(value) {
|
|
192
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=bridge-realtime-usage-recorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-realtime-usage-recorder.js","sourceRoot":"","sources":["../../src/realtime/bridge-realtime-usage-recorder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview A generic server half for channels that run entirely in the browser.
|
|
3
|
+
*
|
|
4
|
+
* `MJ: AI Agent Channels.ServerPluginClass` is `NOT NULL`: every channel in the registry names a server plugin, even a
|
|
5
|
+
* channel whose verbs, state and surface all live in the client. Without this class each such channel (an Open App's
|
|
6
|
+
* form channel, a game, a component host) would hand-write the same empty plugin. A client-only channel instead
|
|
7
|
+
* points its registry row at this one:
|
|
8
|
+
*
|
|
9
|
+
* ```json
|
|
10
|
+
* { "fields": { "Name": "YourChannel", "ServerPluginClass": "ClientOnlyChannelServer", "ClientPluginClass": "YourChannel", ... } }
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* The plugin takes its channel name from the registry row it was resolved for (see {@link ClientOnlyChannelServer.BindChannelName}),
|
|
14
|
+
* so one registered class serves any number of channels and `RealtimeChannelServerHost` never reports a name mismatch.
|
|
15
|
+
*
|
|
16
|
+
* ## What it does
|
|
17
|
+
*
|
|
18
|
+
* - Completes the registry pairing, so the channel is discoverable, scoped and killable like every other.
|
|
19
|
+
* - Contributes **no server tools** (`GetServerToolDefinitions()` is `[]`): every verb executes in the browser.
|
|
20
|
+
* - Does **not interpret or rewrite** a state-of-record save (`OnChannelStateSave` returns `null`, which the host reads as
|
|
21
|
+
* "keep what the client sent").
|
|
22
|
+
*
|
|
23
|
+
* ## What it does not do
|
|
24
|
+
*
|
|
25
|
+
* - **It does not decide scope.** Whether the channel is in a session at all is resolved by the channel-scoping cascade
|
|
26
|
+
* (`channels.include` / `exclude` / the registry's `IsActive` kill switch) BEFORE the host creates any plugin, so there is
|
|
27
|
+
* nothing left for a plugin to validate.
|
|
28
|
+
* - **It does not stop a save.** The host treats a plugin's `null` (and any thrown error) as "persist the original", so a
|
|
29
|
+
* server plugin cannot refuse state. Whether anything is persisted is decided by the CLIENT: a channel with no state of
|
|
30
|
+
* record (`SerializeState()` returns `null`, so it never requests a save) persists nothing. A channel that does request
|
|
31
|
+
* saves, such as an `AngularComponentChannel`, has its state stored on the session's channel row as submitted; if that state
|
|
32
|
+
* must not be stored, validate or redact it in a server plugin of your own (return a replacement) or do not save it.
|
|
33
|
+
* - **It does not authorize anything.** If the channel's verbs call server operations, those operations are the security
|
|
34
|
+
* boundary (they run on the session's own principal); a client-only channel adds no door of its own.
|
|
35
|
+
*
|
|
36
|
+
* Use a dedicated server plugin instead when the channel needs server tools, a server-side state normalizer, or
|
|
37
|
+
* session-lifecycle work.
|
|
38
|
+
*
|
|
39
|
+
* @module @memberjunction/ai-agents
|
|
40
|
+
* @author MemberJunction.com
|
|
41
|
+
*/
|
|
42
|
+
import { BaseRealtimeChannelServer, RealtimeToolDefinition } from '@memberjunction/ai';
|
|
43
|
+
/** The `ServerPluginClass` key a client-only channel's registry row uses. */
|
|
44
|
+
export declare const CLIENT_ONLY_CHANNEL_SERVER_KEY = "ClientOnlyChannelServer";
|
|
45
|
+
/**
|
|
46
|
+
* Generic server half for a channel that runs entirely in the browser. One instance per realtime session (created by
|
|
47
|
+
* `RealtimeChannelServerHost` from the channel registry; never construct directly).
|
|
48
|
+
*
|
|
49
|
+
* Subclass it only to pin a fixed {@link ChannelName} under a key of your own (as the built-in Interactive Component and
|
|
50
|
+
* Identity Verification channels do, so their existing registry keys keep resolving); an Open App should simply use the
|
|
51
|
+
* registered `ClientOnlyChannelServer` key.
|
|
52
|
+
*/
|
|
53
|
+
export declare class ClientOnlyChannelServer extends BaseRealtimeChannelServer {
|
|
54
|
+
private boundChannelName;
|
|
55
|
+
/**
|
|
56
|
+
* The channel this instance serves: the registry row's `Name`, once the host has bound it; `''` before that. A subclass
|
|
57
|
+
* that pins a fixed name overrides it.
|
|
58
|
+
*/
|
|
59
|
+
get ChannelName(): string;
|
|
60
|
+
/**
|
|
61
|
+
* Tells the plugin which registry row it was resolved for. Called by `RealtimeChannelServerHost` right after it creates
|
|
62
|
+
* the instance, so a single registered class can serve any client-only channel.
|
|
63
|
+
*
|
|
64
|
+
* @param channelName The registry row's `Name`.
|
|
65
|
+
*/
|
|
66
|
+
BindChannelName(channelName: string): void;
|
|
67
|
+
/** No server-executed tools: every verb runs in the browser. */
|
|
68
|
+
GetServerToolDefinitions(): RealtimeToolDefinition[];
|
|
69
|
+
/**
|
|
70
|
+
* Does not interpret or rewrite a state save. `null` means "persist what the client submitted" (the host cannot refuse a
|
|
71
|
+
* save through a plugin; see the file comment).
|
|
72
|
+
*
|
|
73
|
+
* @returns `null`.
|
|
74
|
+
*/
|
|
75
|
+
OnChannelStateSave(): Promise<string | null>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Tree-shaking prevention for {@link ClientOnlyChannelServer}'s `@RegisterClass` registration. Called from a static code
|
|
79
|
+
* path in the server host (and, for the Interactive Component and Identity Verification plugins, from their own load
|
|
80
|
+
* functions) so the registration always executes.
|
|
81
|
+
*/
|
|
82
|
+
export declare function LoadClientOnlyChannelServer(): void;
|
|
83
|
+
//# sourceMappingURL=client-only-channel-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-only-channel-server.d.ts","sourceRoot":"","sources":["../../src/realtime/client-only-channel-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAGvF,6EAA6E;AAC7E,eAAO,MAAM,8BAA8B,4BAA4B,CAAC;AAExE;;;;;;;GAOG;AACH,qBACa,uBAAwB,SAAQ,yBAAyB;IAClE,OAAO,CAAC,gBAAgB,CAAuB;IAE/C;;;OAGG;IACH,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED;;;;;OAKG;IACI,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAIjD,gEAAgE;IAChD,wBAAwB,IAAI,sBAAsB,EAAE;IAIpE;;;;;OAKG;IACmB,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAGrE;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
|