npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@memberjunction/ai-bridge-base

v5.48.0

Published

MemberJunction: Cross-platform base layer for Realtime Bridges — pluggable, capability-gated media transports (audio/video/screen, full duplex) that connect the realtime agent engine to external endpoints (Zoom/Teams/telephony/etc).

Readme

@memberjunction/ai-bridge-base

Cross-platform, metadata-only base layer for MemberJunction Realtime Bridges — pluggable, capability-gated media transports (audio / video / screen, full duplex) that connect the one realtime agent engine to an external endpoint: a Zoom/Teams/Slack/Meet/Webex/Discord meeting or a Twilio/Vonage/RingCentral phone call.

This package holds everything a bridge needs that carries no execution — the provider/identity/ channel cache, the abstract BaseRealtimeBridge driver contract, the media-track types, the platform-agnostic turn-taking policy, and the capability-error type. It is the base half of the AIBridgeEngineBase / AIBridgeEngine pair, exactly mirroring how @memberjunction/ai-engine-base's AIEngineBase underpins @memberjunction/aiengine's AIEngine. The server tier that actually runs a bridged session (the transport seam, bot lifecycle, janitor, the LoopbackBridge) lives in @memberjunction/ai-bridge-server.

See the architecture plan at /plans/realtime/realtime-bridges-architecture.md and the developer guide /guides/REALTIME_BRIDGES_GUIDE.md for the full design (transport seam, capability gating, channel contribution, turn-taking, roadmap).

What's in the box

| Export | Purpose | |---|---| | BaseRealtimeBridge | The abstract driver. A concrete driver (ZoomBridge, TwilioBridge, …) implements only the irreducibly platform-specific primitives (Connect / Disconnect / SendMedia / OnMedia) and overrides the capability-gated virtuals (GetParticipants, SendDTMF, TransferCall, StartRecording, …) its platform supports. Drivers self-register via @RegisterClass(BaseRealtimeBridge, '<X>Bridge'). | | AIBridgeEngineBase | A BaseEngine singleton caching the bridge registry — providers + capability flags, agent identities, the provider→channel junction — with synchronous resolution helpers (ProviderByName, ProviderByDriverClass, IdentityByValue, ChannelsForProvider, …). No execution. | | TurnTakingPolicy + RegexAddressedMatcher | Pure, platform-agnostic turn-taking (Passive / Active / Hybrid) with injected matcher/scorer/clock — fully unit-testable, no I/O. | | BridgeCapabilityNotSupportedError | The defense-in-depth error thrown when a capability-gated method is called on a driver that doesn't support it (carries FeatureName + ProviderName). | | Media-track types | BridgeMediaFrame, BridgeMediaTrackKind (audio-inscreen-out), BridgeParticipantInfo, BridgeParticipantRole — the typed, directional, media-agnostic transport payloads. | | Driver contract types | RealtimeBridgeContext, BridgeConnectResult, BridgeDisconnectReason, IBridgeProviderFeatures (typed alias of the generated MJ: AI Bridge Providers.SupportedFeatures shape). |

Installation

npm install @memberjunction/ai-bridge-base

The driver contract

BaseRealtimeBridge has two tiers of methods:

  • Abstract — every bridge MUST implement: Connect(ctx), Disconnect(reason), SendMedia(track, frame) (outbound — fed from IRealtimeSession.OnOutput), and OnMedia(handler) (inbound — routed to IRealtimeSession.SendInput). Audio is just one track; video/screen ride the same two media methods.
  • Virtual / capability-gated — override only what your platform supports: GetParticipants, OnParticipantChange (gated by SpeakerDiarization), SendDTMF / OnDTMF (DTMF), TransferCall (CallTransfer), StartRecording (Recording). Each throws BridgeCapabilityNotSupportedError by default. The engine checks the matching SupportedFeatures flag first and never calls a method whose feature is off; the throw is the second, defense-in-depth layer for when a metadata flag lies or a caller bypasses the gate.

Protected helpers for driver authors: applyContext(ctx) (capture features + provider name — call it first in Connect), RequireFeature(flag) (re-assert a flag at the top of an overriding method), and notSupported(name) (build the standard error).

Minimal usage — a tiny custom bridge

import { RegisterClass } from '@memberjunction/global';
import {
    BaseRealtimeBridge,
    BridgeConnectResult,
    BridgeDisconnectReason,
    BridgeMediaFrame,
    BridgeMediaTrackKind,
    RealtimeBridgeContext,
} from '@memberjunction/ai-bridge-base';

@RegisterClass(BaseRealtimeBridge, 'EchoBridge')
export class EchoBridge extends BaseRealtimeBridge {
    private inbound?: (frame: BridgeMediaFrame) => void;

    public async Connect(ctx: RealtimeBridgeContext): Promise<BridgeConnectResult> {
        this.applyContext(ctx);                       // capture features + provider name (do this first)
        return { BotParticipantId: 'echo-bot', ExternalConnectionId: `echo:${ctx.Address}` };
    }

    public async Disconnect(_reason: BridgeDisconnectReason): Promise<void> {
        this.inbound = undefined;
    }

    public SendMedia(track: BridgeMediaTrackKind, frame: BridgeMediaFrame): void {
        // echo the agent's outbound audio straight back inbound
        this.inbound?.({ ...frame, Track: 'audio-in' });
    }

    public OnMedia(handler: (frame: BridgeMediaFrame) => void): void {
        this.inbound = handler;
    }

    // SendDTMF / TransferCall / StartRecording / GetParticipants are NOT overridden —
    // they stay capability-gated and throw BridgeCapabilityNotSupportedError if called.
}

A bridge provider row whose DriverClass = 'EchoBridge' and whose SupportedFeatures enables { AudioIn, AudioOut } resolves to this driver through the ClassFactory. (The shipped LoopbackBridge in the server package is a fuller worked example — it also overrides the diarization-gated roster methods.)

Turn-taking

TurnTakingPolicy gates generation (whether the agent speaks / posts to chat / stays silent) — the agent always hears. It operates on diarized transcript segments and is identical for any platform:

import { TurnTakingPolicy, RegexAddressedMatcher } from '@memberjunction/ai-bridge-base';

const policy = new TurnTakingPolicy({
    Mode: 'Passive',                                  // default — speak only when addressed
    Matcher: new RegexAddressedMatcher(['Sage', 'the assistant']),
});

const decision = policy.EvaluateTurn({
    Segment: { Text: 'Hey Sage, what do you think?', IsAgent: false, EndMs: Date.now() },
});
// → { Action: 'Speak', Reason: 'Agent was addressed (passive).' }

Active mode adds an injected "worth saying" scorer that fires only in silence windows (throttled, never barging over a live speaker); Hybrid adds a chat hand-raise when chat is available. Every dependency (matcher, scorer, clock) is injected, so the policy is pure and deterministic in tests.

The capability model

A provider's capabilities live in the MJ: AI Bridge Providers.SupportedFeatures JSON column, strongly typed via IBridgeProviderFeatures. It holds transport/media concerns only — join methods, directional media tracks (AudioIn/Out, VideoIn/Out, ScreenIn/Out), SpeakerDiarization, DTMF, CallTransfer, Recording. New platform features need no schema migration — extend the interface. Interactive surfaces (hand-raise, chat, native whiteboard) are NOT features here — they are channels the bridge contributes (planned Phase 2).

How it composes with the realtime engine

| Layer | Package | Role | |---|---|---| | Metadata cache + abstract driver + turn policy | @memberjunction/ai-bridge-base (this) | provider/identity/channel cache, BaseRealtimeBridge, TurnTakingPolicy, media-track + capability types | | Coordination + execution + transport seam | @memberjunction/ai-bridge-server | AIBridgeEngine (composes this base), the bridge ↔ IRealtimeSession seam, bot lifecycle, janitor, LoopbackBridge | | Realtime session contract | @memberjunction/ai | IRealtimeSession / BaseRealtimeModel — injected into the engine, never constructed by a bridge |

The server AIBridgeEngine composes (does not extend) AIBridgeEngineBase, so the startup manager warms exactly one BaseEngine cache — the same composition-over-inheritance pattern AIEngine uses over AIEngineBase.

Further reading

License

ISC