Skip to content

v6.1.0-edge.5: Continuous-media AI pricing, an agent-first CLI, and realtime voice

The sixth Edge build of the 6.1 line, and a broad one — 81 changesets across 305 packages, nearly double its predecessor. Three themes carry it: AI runs can finally be priced by what they actually bill for rather than by tokens, which is what makes speech-to-text and image generation costable at all; the mj CLI is rebuilt agent-first; and realtime voice gains the pieces a real conversation needs — the agent can speak first, a session can be minted separately from the run that drives it, and a live call stops being reaped out from under the caller. Underneath, a sustained run of integration-sync throughput work whose common theme is stop making one round trip per record, and a cluster of PostgreSQL converter fixes for defects that only ever surfaced when a converted migration was applied.

Edge builds are prereleases. They publish under the edge dist-tag and never move latest.

  • Continuous-media AI pricing. Token counts cannot express what a speech-to-text or image model bills for, so such runs recorded zero tokens and were skipped by cost calculation entirely. A new MJ: AI Usage Types entity names the base measure of a quantity — Tokens, Seconds, Characters, Images — while AIModelPriceUnitType owns the billing measure and its arithmetic (UnitsPerBillingUnit: 3600 for per-hour, 1000000 for per-1M-tokens). Audio recorded in Seconds and billed Per Hour is now a join, not a convention. Holding the divisor as data means a new linear billing unit ships by seeding a row, with no driver class and no build. OpenAI joins Groq as a second Whisper provider.
  • The mj CLI is agent-first, following the model the ElevenLabs CLI adopted — structured, machine-readable output and predictable command shapes, so an agent can drive it as a first-class caller rather than by scraping human text.
  • Apollo’s other half: list management, saved-record search and prospecting — seven new actions alongside the two enrichment actions the package has always had, enough to support outbound-campaign workflows end to end.
  • Two web-read actions — Tavily Search and Read RSS Feed — giving agents native web-reading without a custom integration.
  • ERP accounting verbs, as a provider-agnostic dispatcher per verb: CreateJournalEntry, GetChartOfAccounts, GetAccountBalances, GetDimensions, GetGLEntries, GetCustomers, GetSalesInvoices.
  • IS-A promotion — a NEW child record can be attached to an EXISTING parent, rather than requiring the pair to be created together.
  • Clickable record links in Chat. Agents emit @{…} JSON with type: "record"; the renderer turns it into a pill that opens the row via OpenEntityRecord, composite primary keys included.
  • Realtime voice gets its missing pieces. The agent can speak first; mint and run become separable; a bridged seat runs its own agent class instead of silently falling back to plain BaseAgent (#4111); and per-session llm / agent-body temperature overrides on ElevenLabs actually reach the driver.
  • Remote Browser: one agent session, many browsers, named by instanceKey (#3531), with the agent now told when the page moves regardless of who moved it (#3496).
  • Slack and Teams messaging adapters get their first production bring-up.
  • Scoped Search carries the skill principal — and judges it, so a search runs under the identity that asked for it.
  • Open App serverExtensions auto-load from packages listed in host dynamicPackages.server[], declared via the MJ_SERVER_EXTENSIONS export or package.json.
  • The weekly AI model refresh (2026-08-31 report) lands with the release rather than after it.
  • A transaction group can send its items as ONE round trip, and a sync batch can send its writes together instead of one at a time — on a high-latency link this is the difference between a sync that finishes and one that does not. An operator can bound how much a batched apply holds in memory, and syncConcurrency now applies to writes, not just fetches.
  • Pipelined page prefetch for cursor-paged connectors. The fetch loop was strictly serial — fetch page, process page, fetch next — even though the next cursor is known the moment a page arrives. Alongside it: a batch that already proved a row absent stops re-checking it per record, the absence-proof prefetch passes IgnoreMaxRows so a row-limit default cannot truncate it, and writes for different entity maps no longer queue behind each other.
  • Adaptive per-connection fetch concurrency. The engine could fire more simultaneous vendor fetches than the account’s concurrency grant allowed (lanes × prefetch), so a vendor that governs by grant would throttle a run the engine thought was well-behaved.
  • CodeGen treats schema as the incremental unit at 2,000+ entities — per-schema emit with write-if-changed, dirty-schema regeneration, 'schema.table' exclude strings, and schema-parallel file generation.
  • Discovery gets substantially more honest. It samples the union of declared and runtime objects and honours a scoped introspection; it samples every declared object and merges what it sees without overriding what was declared; a sample that degrades to the catalog description now says so; column deactivation requires a source that declared its field list complete; a deselected primary key no longer costs an object its identity; and the default sample is ~50 records per table, not 500.
  • An object the account cannot serve no longer fails loudly on every sync — and no longer advances its watermark, which had been quietly marking unread data as read.
  • Sync-scoped write-side-effect suppression. Record Changes and geocoding are per-write side effects, and the only way to relieve a high-volume writer of them used to be turning the entity flags off globally. SkipRecordChanges / SkipGeoCoding now scope that to the writer.
  • Accessibility (WCAG 2.1 A/AA). Shell landmarks and a skip-to-content link, focus containment, focus-ring token safety, and MJDropdown can finally be given an accessible name (#3860).
  • PostgreSQL migration conversion, four defects deep. The BIT/BOOLEAN registry is seeded from the live catalog when baking; ${mjSchema} is resolved rather than surviving into the emitted file; a hollow .pg.sql — a header and a gap banner over nothing — is never written; and three defects that reported “0 gaps” yet failed on apply are fixed (MERGE/MATCHED quoted as identifiers, T-SQL’s optional MERGE INTO left un-normalised, and BIT literals emitted as integers into entity-registration INSERTs, which broke every migration that registered a new entity).
  • Class-registration manifests are emitted in chunks, so the array stops being one union away from not compiling, and all manifests are regenerated onto that format.
  • The mermaid engine loads when a diagram exists, not on every render.
  • ExecuteSimplePrompt model selection — four stacked defects, each of which reported as something else (#3532).
  • Batched transaction-group submit failed for any group of two or more change-tracked records. T-SQL scopes DECLARE to the batch, so each generated CRUD wrapper’s @ResultTable / @ID / @ResultChangesTable was declared once per item and SQL Server rejected the whole batch. Since nearly every entity tracks record changes, this fired for essentially every group large enough to be worth batching — including IntegrationEngine’s sync writes, which failed and rolled back.
  • A resource leak from the axios → native-fetch migration. Several call sites (SharePoint/Box/Dropbox drivers, GraphQL Query, URL Metadata Extractor, Web Page Content) never drained unused response streams.
  • fnReportCategoryParentID_GetRootID, an orphan of the removed ReportCategory table, is dropped. Its dangling reference made Azure SQL’s database export (bacpac) fail module validation, so any installation carrying it could not be exported.
  • Cross-tab URL corruption — a dashboard in a background tab could rewrite the URL of the tab the user was actually viewing.
  • MJ_TELEMETRY_ENABLED could never take effect.
  • A single unescaped character no longer loses an LLM response — deterministic JSON escaping repair, and an end to misreporting why a response broke.
  • Single quotes in generated entity descriptions are escaped before interpolation into SQL. AI-generated descriptions routinely contain apostrophes, and one unescaped quote aborted the statement.
  • Explorer no longer shows “Unknown error” beside a stuck Running timer when a Skip/sub-agent transport path fails; the real error is passed through invokeSubAgent.
  • The connectivity banner no longer throws NG0100 when the socket drops mid-render.
  • The chat-embedded interactive form stops clipping long text — agent-authored labels are routinely sentence-length, and every option was sized to its content width with no wrapping.
  • Embedded HTML blocks survive blank lines, so SVG charts render.
  • A dead Remote Browser handle heals instead of poisoning the session (#3598).
  • The AI Agent Run timeline lists steps by StartedAt (execution time), not persist time.
  • Storage failures name their cause — driver resolution fails fast and specifically instead of returning an unusable base instance, and a failed upload reports the driver’s real error rather than “Storage upload failed.”
  • A completed sync’s watermark is stored as a Timestamp again, not left typed as a Cursor, and a row whose content hash goes stale is repaired once instead of losing its fast path permanently.
  • The realtime janitor stops reaping live calls — the client now sends a liveness pulse — and a streamed utterance’s transcript corrections are actually persisted.
  • The EntityField sequence park is idempotent across CodeGen passes, and entity fields the base view cannot produce are caught rather than shipped.