v6.2.0-edge.3: Work queues, form contributions, and telephony rooms
The Durable Work Queue and Messaging Framework, form contributions that users can add, place and share from the form itself, and telephony with LiveKit rooms, human hand-off, meetings and an operations dashboard. Plus binary vector storage that loads about 14× faster, live JSONType accessors with opt-in validation, and fixes to Redis outage recovery, record-name security and saved-query rendering.
Upgrade Notes apply: six migrations apply on mj migrate, inbound phone calls stop until telephony.inboundRunAsUserEmail is set, RunView now omits binary fields by default, and server code must deploy before the metadata sync.
Edge builds are prereleases.
MemberJunction 6.x is released under the Business Source License 1.1; 5.x and earlier stay ISC. What the licence grants, and what needs certification, is in the licence section of the v6 upgrade guide.
New Features
Section titled “New Features”- Durable Work Queue and Messaging Framework (
@memberjunction/work-queue-core,@memberjunction/work-queue-engine,@memberjunction/work-queue-server,@memberjunction/work-queue-aws,@memberjunction/ng-dashboards,@memberjunction/cli): Topics, subscriptions, messages and deliveries with leases, retries, dead letters, deduplication and partitioned ordering (ExclusiveorOrderedper key). A database transport works on SQL Server and PostgreSQL through guarded-write stored procedures; an AWS transport uses SNS and SQS FIFO.WorkQueueHostruns competing consumers as a daemon or one-shot, andWorkQueueSweeperexpires leases and purges retained rows. Messages can be published overPOST /work-queue/topics/{topic}/messages. Explorer gains a Work Queue dashboard (overview, dead letters with replay and discard, partitions, binding validation), andmj queuecovers the same operations from the command line. - Form contributions from metadata (
@memberjunction/ng-base-forms,@memberjunction/ng-core-entity-forms,@memberjunction/core-entities,@memberjunction/core-actions,@memberjunction/ng-artifacts): AMJ: Entity Form Contributionsrow mounts a form-panel component on an entity’s form, either at a slot or in place of a related grid, a set of sections or a group of fields, at User, Role or Global scope. A form-panel artifact can be added to the user’s own form through a placement dialog that previews the real form, and a “Manage this form” drawer lets a user hide shared panels and remove their own. Publishing a panel or a full custom form to a role or to everyone requires the newManage Form Defaultsauthorization. New actions create, modify, activate and list contributions, and agents receive the form’s composition in their context. - Telephony in LiveKit rooms (
@memberjunction/livekit-room-server,@memberjunction/telephony-adapters,@memberjunction/server): Phone calls can arrive in a LiveKit room over SIP, and an agent can bring a person, a phone number or another agent into that room. Calls are recorded asMJ: Interactionswith an append-only event log, outbound calls draw from a number pool, and hand-off offers are stored durably. A newmj-conversation-offerswidget and an Explorer Conversation Console let a person accept or decline a hand-off. - Meetings and a telephony operations dashboard (
@memberjunction/ng-mj-livekit-room,@memberjunction/ng-explorer-core,@memberjunction/ng-dashboards): Multi-party meetings with scheduling, a lobby and a participant picker, and a dashboard of call volume, answer and abandonment rates, handle time, transfers, cost and live calls. - Phone calls use the same agent as the browser (
@memberjunction/ai-bridge-twilio,@memberjunction/ai-bridge-vonage,@memberjunction/ai-bridge-ringcentral,@memberjunction/ai-agents): Twilio, Vonage and RingCentral calls resolve the co-agent the same way the browser does, recover once from a dropped model connection, and can transfer to a configured directory, send DTMF and hang up. A host can identify inbound callers throughBaseCallerIdentityResolver. - Turn-taking for full-duplex realtime models (
@memberjunction/ai-bridge-server,@memberjunction/livekit-room-server,@memberjunction/ng-mj-livekit-room): Multi-agent rooms let the model judge whether it is being addressed, keep acknowledgements off the floor, let a person interrupt, and cap agent-to-agent turns. The Live Room shows turn state for testing. - Hold music and announcements in rooms (
@memberjunction/livekit-room-server):RoomAudioPlayerplays a file, URL or generated tone into a room, with loop, pause and announcements. - Binary fields and binary vector storage (
@memberjunction/core,@memberjunction/global, the database providers,@memberjunction/ai-vectors-memory): A binary column is a base64 string everywhere above the database. Every persisted embedding gains a binary float32 copy, which loads 20,000 × 1,536 vectors in 0.28 s against 3.9 s for the JSON copy; readers fall back to JSON for older rows. - Faster in-memory vector search (
@memberjunction/ai-vectors-memory,@memberjunction/ai-vectors-memory-server): Packed storage, faster kernels, an index that applies saves in place, and on a server a worker-thread pool that keeps searches off the event loop. - Live JSONType accessors with opt-in validation (
@memberjunction/core,@memberjunction/codegen-lib): Editing a JSONType accessor in place now dirties and persists the field.@mjValidateon a JSONType interface generates a Zod schema and aValidate()check. - Pluggable rubric evaluators (
@memberjunction/rubrics,@memberjunction/testing-engine): Hosts can register their own evaluator. ADecisionevaluator scores criteria with typed decisions, and the LLM evaluator’s prompts are now metadata, with a judge prompt per core agent. - Restrict a run to the caller’s credentials (
@memberjunction/ai,@memberjunction/ai-prompts,@memberjunction/ai-agents):CredentialScope: 'RuntimeOnly'limits a prompt or agent run to the API keys its caller supplied, so a failed customer key fails the run instead of falling back to the platform’s. - Token-only identity claims (
@memberjunction/core-entities-server): A claim can be issued without a recipient email when its type requires a token, and with an exactExpiresAt. - AI model catalog (
@memberjunction/aiengine): Corrects two Cohere reranker IDs, Claude Sonnet 4.5’s output cap and three prices, fills prompt-cache rates on eight cost rows, and deactivates retired routes and models.
Improvements
Section titled “Improvements”- Records preview tabs are kept once edited (
@memberjunction/ng-explorer-core,@memberjunction/ng-base-forms): A preview tab is pinned the moment its form enters edit mode, so the next row click no longer replaces it after a save. - Streamed replies render in place (
@memberjunction/ng-conversations): A streamed delta refreshes only its own message instead of rebuilding the conversation. - Saved and ad-hoc queries render correctly on both platforms (
@memberjunction/sql-parser,@memberjunction/generic-database-provider,@memberjunction/postgresql-dataprovider,@memberjunction/server): A query’s own row limit is kept, composed queries with CTEs, hints and template tags compose correctly, and ad-hoc SQL runs through the read-only login on PostgreSQL too, with a per-call timeout. mj sync push --dry-runreports what a push would do (@memberjunction/metadata-sync): It runs the same change detection as a real push, and a push straight after a pull no longer rewrites every record.- CodeGen reports when no integrity check ran (
@memberjunction/codegen-lib): A run with every integrity check disabled warns instead of showing a success tick. mj app upgraderefreshes an app’s schema name (@memberjunction/open-app-engine): A corrected schema-name casing in the manifest now reaches the database, which fixes GraphQL operations that failed validation.
Bug Fixes
Section titled “Bug Fixes”- Loop agents without tools render their system prompt (
@memberjunction/ai-prompts): Every such run failed with “Parameter _NATIVE_TOOL_CALLING is required”. - Redis outages no longer leave a server cache-blind (
@memberjunction/redis-provider): The client stopped reconnecting after about 11 seconds. It now reconnects indefinitely, fails commands fast while disconnected, and on reconnect keeps or drops the local cache depending on whether anything was invalidated meanwhile. - Record names respect field-level security on the server (
@memberjunction/core,@memberjunction/server): A name built from a read-denied field is withheld, and servers no longer share a record-name cache across users. - Metadata refreshes no longer exhaust the heap (
@memberjunction/core,@memberjunction/redis-provider): Without Redis, the server serialized the whole metadata graph on every refresh into a store nothing could read back. That step is skipped, and telemetry collections are now bounded. - Native tool calling (
@memberjunction/ai-agents,@memberjunction/ai-gemini,@memberjunction/ai-anthropic): Object action parameters are sent as objects, acomplete_tasktool finishes an implicit-mode run in one turn, and a Gemini failover between AI Studio and Vertex AI no longer fails on a thought signature. - Realtime sessions keep their persona (
@memberjunction/ai-realtime-client,@memberjunction/ai-openai): A spoken update replaced the session’s instructions for that turn, so the agent spoke without its identity; and OpenAI-protocol sessions rejected a whole session update over one unknown parameter. - A failed whiteboard edit is reported as failed (
@memberjunction/ai-realtime-client): The model was told an edit had landed when the tool failed. - Durable Execute Agent steps complete (
@memberjunction/core-actions): Their result could not be stored on the task and the step failed. - Workflow steps resolve their input mappings (
@memberjunction/task-graph): Dispatched steps receiveddata.*references as literal text. - Data Explorer keeps its search when a row is clicked (
@memberjunction/ng-dashboards). - Memory leaks (
@memberjunction/ng-core-entity-forms,@memberjunction/testing-engine,@memberjunction/codegen-lib,@memberjunction/code-execution): Twelve custom forms stayed subscribed after closing, and three other process-lifetime collections or timers are now bounded or cleared. - Data-layer hardening (
@memberjunction/core,@memberjunction/server,@memberjunction/sqlserver-dataprovider,@memberjunction/sql-dialect): Composite-key values are escaped before SQL, read permission is enforced on subquery targets, and SQL Server identifiers quote]safely.
Upgrade Notes
Section titled “Upgrade Notes”- Six migrations apply on
mj migrate: the telephony schema, form contributions, binary vector columns, the work queue schema and its stored procedures, and the release metadata sync. - Inbound phone calls stop until
telephony.inboundRunAsUserEmailis set (@memberjunction/telephony-adapters): Inbound calls now run as that user instead of the System or Owner user, and are rejected when it is missing. RunViewomits binary fields by default (@memberjunction/core): PassIncludeBinaryFields: true, or name the field inFields, to get them.Load()still includes them.- Deploy the server before the metadata sync (
@memberjunction/server): The UI role gains Create and Update onMJ: Componentsand write access to form contributions through metadata, and only the new server-side guards keep that to a user’s own rows. Apply the release’s metadata-sync migration together with the server deploy, never before it. - Editing a shared form needs
Manage Form Defaults(@memberjunction/core-entities-server): After upgrade, changing or deleting an existing Role or Global custom form requires that authorization, and anmj sync pushof Global rows needs a sync user who holds it or is an Owner. - On PostgreSQL, duplicate shared form contributions are not refused yet: The two
EntityFormContributionunique indexes include nullable columns. SQL Server treats NULLs as equal in a unique index and PostgreSQL does not, so on PostgreSQL two Active Role or Global rows with the same key are both accepted. A later release adds the PostgreSQL index fix. - Record-name cache on servers (
@memberjunction/core): Server code that relied onGetCachedRecordNameOnlyIfCachedreturning a name now getsundefined; no MJ server code does.