🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@memberjunction/ai

Package Overview
Dependencies
Maintainers
12
Versions
447
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@memberjunction/ai - npm Package Compare versions

Comparing version
5.47.0
to
5.48.0
+88
dist/generic/realtimeProxyRegistry.d.ts
import { BaseSingleton } from '@memberjunction/global';
/**
* The URL path MJAPI's realtime proxy listens on for websocket upgrades, and that provider drivers
* embed in the browser-facing `wss://<mjapi-public><REALTIME_PROXY_PATH>?ticket=<id>` URL. Shared here
* (in Core) so the minting side (driver) and the serving side (MJServer proxy) can never drift.
*/
export declare const REALTIME_PROXY_PATH = "/realtime-proxy";
/**
* A short-lived, one-time authorization to open ONE upstream realtime websocket through the
* MJAPI realtime proxy. Stored server-side only — the upstream URL and (optional) auth header
* NEVER leave the server; the browser only ever receives the opaque ticket id embedded in the
* proxy URL it connects to.
*
* This is the seam that lets a **self-hosted** realtime provider (e.g. HuggingFace
* speech-to-speech) participate in the shipped client-direct audio topology WITHOUT exposing
* the internal endpoint to the browser: the provider driver mints a ticket (via
* {@link RealtimeProxyRegistry.Issue}) pointing at the internal endpoint, hands the browser a
* `wss://<mjapi-public>/realtime-proxy?ticket=<id>` URL, and MJAPI's proxy consumes the ticket
* ({@link RealtimeProxyRegistry.Consume}) to open the authenticated upstream leg and pump frames.
*/
export interface RealtimeProxyTicketEntry {
/** The internal upstream websocket URL to tunnel to (e.g. `ws://hf-s2s.internal:8000/v1/realtime`). */
UpstreamUrl: string;
/**
* Full `Authorization` header value applied on the UPSTREAM socket only (e.g. `Bearer <key>`).
* Optional — many self-hosted endpoints are unauthenticated. Never serialized to the browser.
*/
UpstreamAuthHeader?: string;
/** The MJ user this ticket was minted for (for audit / optional validation at consume time). */
UserID?: string;
/** Epoch-ms after which the ticket is invalid. Enforced on {@link RealtimeProxyRegistry.Consume}. */
ExpiresAtMs: number;
}
/** The parameters for minting a proxy ticket via {@link RealtimeProxyRegistry.Issue}. */
export interface RealtimeProxyIssueParams {
/** The internal upstream websocket URL to tunnel to. */
UpstreamUrl: string;
/** Full `Authorization` header value for the upstream socket (optional). */
UpstreamAuthHeader?: string;
/** The MJ user the ticket is for (optional). */
UserID?: string;
/** Time-to-live, in seconds, for the ONE upstream open this ticket authorizes. */
TTLSeconds: number;
}
/** The result of minting a ticket: the opaque id to embed in the browser proxy URL, plus its expiry. */
export interface RealtimeProxyTicket {
/** The opaque, single-use ticket id (a UUID) — embedded in the browser-facing proxy URL. */
ID: string;
/** ISO-8601 timestamp at which the ticket expires. */
ExpiresAt: string;
}
/**
* Process-wide, in-memory registry of one-time realtime-proxy tickets (Global Object Store backed
* via {@link BaseSingleton}, so the provider driver that mints and the MJAPI proxy that consumes
* share the SAME instance even under bundler code duplication).
*
* Intentionally has **no** background timer: entries are pruned lazily on every {@link Issue} /
* {@link Consume}, so there is nothing to shut down and no `IShutdownable` wiring is required. Tickets
* are short-lived and single-use — the map never grows unbounded in practice.
*
* Deliberately transport-agnostic: it stores plain data (URL + optional auth + expiry) and knows
* nothing about websockets or any specific provider. The proxy transport lives in MJServer; the
* mint logic lives in the provider driver. This is the neutral shared state between them.
*/
export declare class RealtimeProxyRegistry extends BaseSingleton<RealtimeProxyRegistry> {
private readonly _tickets;
protected constructor();
/** Process-wide singleton accessor. */
static get Instance(): RealtimeProxyRegistry;
/**
* Mints a single-use ticket authorizing ONE upstream open within its TTL window, and returns the
* opaque id to embed in the browser-facing proxy URL. Prunes expired tickets as a side effect.
*/
Issue(params: RealtimeProxyIssueParams): RealtimeProxyTicket;
/**
* Consumes a ticket by id: returns its entry and DELETES it (single-use), or `null` if the id is
* unknown or expired. Prunes expired tickets as a side effect. The proxy calls this exactly once,
* during the websocket upgrade, before opening the upstream leg.
*/
Consume(id: string): RealtimeProxyTicketEntry | null;
/** Current number of live (un-consumed, un-expired) tickets — for diagnostics/tests. */
get Count(): number;
/** Drops every ticket whose window has closed. */
private pruneExpired;
/** Generates an opaque ticket id. Uses the platform crypto UUID (Node 16+ / browsers). */
private static newTicketId;
}
//# sourceMappingURL=realtimeProxyRegistry.d.ts.map
{"version":3,"file":"realtimeProxyRegistry.d.ts","sourceRoot":"","sources":["../../src/generic/realtimeProxyRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,wBAAwB;IACrC,uGAAuG;IACvG,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gGAAgG;IAChG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qGAAqG;IACrG,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,yFAAyF;AACzF,MAAM,WAAW,wBAAwB;IACrC,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,wGAAwG;AACxG,MAAM,WAAW,mBAAmB;IAChC,4FAA4F;IAC5F,EAAE,EAAE,MAAM,CAAC;IACX,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,SAAQ,aAAa,CAAC,qBAAqB,CAAC;IAC3E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoD;IAE7E,SAAS;IAIT,uCAAuC;IACvC,WAAkB,QAAQ,IAAI,qBAAqB,CAElD;IAED;;;OAGG;IACI,KAAK,CAAC,MAAM,EAAE,wBAAwB,GAAG,mBAAmB;IAanE;;;;OAIG;IACI,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,wBAAwB,GAAG,IAAI;IAgB3D,wFAAwF;IACxF,IAAW,KAAK,IAAI,MAAM,CAGzB;IAED,kDAAkD;IAClD,OAAO,CAAC,YAAY;IASpB,0FAA0F;IAC1F,OAAO,CAAC,MAAM,CAAC,WAAW;CAY7B"}
import { BaseSingleton } from '@memberjunction/global';
/**
* The URL path MJAPI's realtime proxy listens on for websocket upgrades, and that provider drivers
* embed in the browser-facing `wss://<mjapi-public><REALTIME_PROXY_PATH>?ticket=<id>` URL. Shared here
* (in Core) so the minting side (driver) and the serving side (MJServer proxy) can never drift.
*/
export const REALTIME_PROXY_PATH = '/realtime-proxy';
/**
* Process-wide, in-memory registry of one-time realtime-proxy tickets (Global Object Store backed
* via {@link BaseSingleton}, so the provider driver that mints and the MJAPI proxy that consumes
* share the SAME instance even under bundler code duplication).
*
* Intentionally has **no** background timer: entries are pruned lazily on every {@link Issue} /
* {@link Consume}, so there is nothing to shut down and no `IShutdownable` wiring is required. Tickets
* are short-lived and single-use — the map never grows unbounded in practice.
*
* Deliberately transport-agnostic: it stores plain data (URL + optional auth + expiry) and knows
* nothing about websockets or any specific provider. The proxy transport lives in MJServer; the
* mint logic lives in the provider driver. This is the neutral shared state between them.
*/
export class RealtimeProxyRegistry extends BaseSingleton {
constructor() {
super();
this._tickets = new Map();
}
/** Process-wide singleton accessor. */
static get Instance() {
return super.getInstance();
}
/**
* Mints a single-use ticket authorizing ONE upstream open within its TTL window, and returns the
* opaque id to embed in the browser-facing proxy URL. Prunes expired tickets as a side effect.
*/
Issue(params) {
this.pruneExpired();
const id = RealtimeProxyRegistry.newTicketId();
const expiresAtMs = Date.now() + Math.max(1, params.TTLSeconds) * 1000;
this._tickets.set(id, {
UpstreamUrl: params.UpstreamUrl,
UpstreamAuthHeader: params.UpstreamAuthHeader,
UserID: params.UserID,
ExpiresAtMs: expiresAtMs,
});
return { ID: id, ExpiresAt: new Date(expiresAtMs).toISOString() };
}
/**
* Consumes a ticket by id: returns its entry and DELETES it (single-use), or `null` if the id is
* unknown or expired. Prunes expired tickets as a side effect. The proxy calls this exactly once,
* during the websocket upgrade, before opening the upstream leg.
*/
Consume(id) {
this.pruneExpired();
if (!id) {
return null;
}
const entry = this._tickets.get(id);
if (!entry) {
return null;
}
this._tickets.delete(id); // single-use — always removed on first consume
if (entry.ExpiresAtMs <= Date.now()) {
return null; // expired between prune and lookup — treat as invalid
}
return entry;
}
/** Current number of live (un-consumed, un-expired) tickets — for diagnostics/tests. */
get Count() {
this.pruneExpired();
return this._tickets.size;
}
/** Drops every ticket whose window has closed. */
pruneExpired() {
const now = Date.now();
for (const [id, entry] of this._tickets) {
if (entry.ExpiresAtMs <= now) {
this._tickets.delete(id);
}
}
}
/** Generates an opaque ticket id. Uses the platform crypto UUID (Node 16+ / browsers). */
static newTicketId() {
const cryptoObj = globalThis.crypto;
if (cryptoObj?.randomUUID) {
return cryptoObj.randomUUID();
}
// Fallback: a UUID-shaped random string (only reached on runtimes without crypto.randomUUID).
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = Math.floor(Math.random() * 16);
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
}
//# sourceMappingURL=realtimeProxyRegistry.js.map
{"version":3,"file":"realtimeProxyRegistry.js","sourceRoot":"","sources":["../../src/generic/realtimeProxyRegistry.ts"],"names":[],"mappings":"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"}
+1
-0

@@ -15,2 +15,3 @@ export * from './generic/baseModel.js';

export * from './generic/baseRealtime.js';
export * from './generic/realtimeProxyRegistry.js';
export * from './generic/baseRealtimeChannelServer.js';

@@ -17,0 +18,0 @@ export * from './generic/errorTypes.js';

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}

@@ -15,2 +15,3 @@ export * from './generic/baseModel.js';

export * from './generic/baseRealtime.js';
export * from './generic/realtimeProxyRegistry.js';
export * from './generic/baseRealtimeChannelServer.js';

@@ -17,0 +18,0 @@ export * from './generic/errorTypes.js';

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
{
"name": "@memberjunction/ai",
"type": "module",
"version": "5.47.0",
"version": "5.48.0",
"description": "MemberJunction: AI - core components for abstracting LLMs and other AI model types that are usable anywhere without ANY other MJ dependencies past @memberjunction/global which itself has zero additional dependencies.",

@@ -20,3 +20,3 @@ "main": "dist/index.js",

"dependencies": {
"@memberjunction/global": "5.47.0",
"@memberjunction/global": "5.48.0",
"dotenv": "^17.2.4",

@@ -23,0 +23,0 @@ "rxjs": "^7.8.2"