Highlights
TokenCostControl (renamed from CostGuard) with richer budgeting
CostGuardProcessor is now TokenCostControl (id: 'token-cost-control') with better diagnostics/reliability and new budgeting options like warnAtPercent, per-request maxCost functions, new cost scopes (user/organization/session), and optional per-model/provider breakdowns.
Active run introspection for agents/controllers (core, server, client-js)
New Agent.listActiveThreadRuns() / AgentController.listActiveThreadRuns() plus corresponding Server + JS client APIs let you cheaply list in-flight runs from in-memory tracking—ideal for polling activity indicators without creating sessions.
Observability fixes: external-parent traces now show up as trace roots in Studio
Tracing bridges (OTel + Datadog) now mark whether a span’s parent is external vs Mastra, fixing missing traces when runs start under an external parent so they correctly appear as trace roots in Mastra Studio.
Safer/more useful redaction with indexed tokens
SensitiveDataFilter gains redactionStyle: 'indexed', producing stable per-value tokens (e.g. [APIKEY_1]) instead of collapsing all sensitive values to [REDACTED], improving debugging while preserving secrecy.
Memory recall continuation for oversized message parts
The Observational Memory recall tool now supports continuation via nextCharOffset, allowing large message parts to be retrieved across multiple calls instead of repeatedly returning the same truncated prefix.
Breaking Changes
- Factory: automatic agent runs are now opt-in per Factory (
autoRunEnableddefaults off on upgrade); rules proposing runs now park them asproposeddecisions until approved. CostGuardProcessorrenamed toTokenCostControl(deprecated aliases remain for now, but will be removed in a future major version).
Changelog
@mastra/core@1.59.0
Minor Changes
-
Fixed traces that start under an external parent span not appearing in Mastra Studio. Resumed agent and workflow runs keep their link to the suspended run's trace. (#20499)
-
Renamed CostGuardProcessor to TokenCostControl, improved its reliability and diagnostics, and added new budgeting options. (#21372)
Rename
CostGuardProcessoris nowTokenCostControlwith processor id'token-cost-control'. TheCostGuardProcessorexport (and theCostGuardOptions,CostGuardUsage,CostGuardBreakdownEntry,CostGuardTripwireMetadata, andCostGuardViolationDetailtypes) remains available as a deprecated alias for the same class and will be removed in a future major version.
Improvements
- Each cost check now issues fewer queries against observability storage.
- Diagnostics now go through the Mastra logger, and failed cost queries now log diagnostics and allow the request to continue instead of failing silently.
- With the warn strategy, warnings and the onViolation callback now fire at most once per request instead of on every step.
- Violation messages no longer contain float precision artifacts (e.g. 0.30000000000000004 now renders as 0.3).
New options
warnAtPercent: soft threshold that warns (without blocking) when cost reaches a percentage of the limit.maxCostnow also accepts a function of RequestContext for per-tier or per-user budgets.- New scopes
user,organization, andsessiontrack cumulative cost per userId, organizationId, and sessionId (read from the matching RequestContext keys; traces must carry the matching span metadata). includeBreakdown: attaches a per-provider/model cost breakdown to violations.
const tokenCostControl = new TokenCostControl({ maxCost: requestContext => (requestContext?.get('tier') === 'pro' ? 10.0 : 1.0), scope: 'user', warnAtPercent: 80, includeBreakdown: true, });
-
Added
Agent.listActiveThreadRuns()andAgentController.listActiveThreadRuns(). They list every run currently in flight across resources and threads, from the same in-process tracking asgetActiveThreadRunId(). (#21353)const runs = agent.listActiveThreadRuns(); // [{ runId: 'run-1', resourceId: 'workspace-a', threadId: 'thread-1' }]
Patch Changes
-
Update provider registry and model documentation with latest models and providers (
088e41e) -
Fixed session-deleted listeners missing their notification when a session teardown failed while releasing its thread lock. The controller deregisters the session either way, so
onSessionDeletednow always fires and listeners no longer hold on to a dead session. (#21358) -
Fixed model routing to use rotated gateway API keys. (#21364)
-
Fixed CoreToolBuilder dropping the
~standard.jsonSchemaadapter when injecting background/resume fields onto Zod v4 tool input schemas. Invalid tool calls now return structured validation errors instead of crashing during JSON Schema conversion. (#21187) -
Fixed workflow watch events re-publishing stale step state, which could grow to megabytes per event.
workflow-step-startevents spread the step's previous result into their payload, so on loops (including durable agent runs) every start event shipped the previous iteration'soutputnext to a byte-identical inputpayload. On Cloudflare Workers this made the request streaming a durable agent run exceed the 128 MB isolate memory limit and fail, even though the run itself kept executing. Watch events now only carry the fields describing the current transition: the input (payloadorresumePayload), timestamps, andstatuson start events, plus the fresh result onworkflow-step-resultandworkflow-step-suspendedevents. A step's prioroutput,error, and suspend state are no longer re-published on later events. Persisted run snapshots are unchanged. (#20661) -
Fixed memory growth from completed foreground workspace commands retaining process handles and their output. (#21438)
-
Added an option to limit language servers retained by a workspace. Workspaces remain unlimited when the option is omitted. (#21186)
const workspace = new Workspace({ lsp: { maxOpenClients: 4 }, });
When using
workspace.lsp.prepareQuery(), callrelease()on the returned query after closing the file. -
Deprecated
translationQualityonLanguageDetector. The option previously selected prompt-level "Quality Level" guidance, but that behavior was removed when the language detection and translation prompts were streamlined. The option currently has no effect. (#21199)Existing configurations keep working and keep type-checking. The option no longer appears in the processor provider's configuration schema, so configuration UIs stop offering a control that does nothing, and the reference docs now mark it as deprecated.
For model-specific speed and quality controls, use
providerOptionswhen your provider supports them:new LanguageDetector({ model, targetLanguages: ['English'], strategy: 'translate', providerOptions: { openai: { reasoningEffort: 'low' } }, });
-
Send opaque acting-user subjects with Platform sandbox requests, including Factory creation and reattachment flows. (#20754)
import { PlatformSandbox } from '@mastra/platform-workspace'; const sandbox = new PlatformSandbox({ environmentId: 'env_abc', actingUserId: auth.user.id, });
-
Corrected the documentation for
observation.blockAfteron the docs pages and in the editor TSDoc. Above the threshold, buffered activation may overshoot the retention target instead of activating fewer chunks; it does not force a synchronous observation. The docs also give the correct value ranges: values from 1 up to (but not including) 100 are multipliers ofmessageTokens, and values of 100 or more are absolute token counts. No runtime behavior changed. (#21215) -
Fixed output processors being skipped when the model provider throws an error. Output processors now run on failed streams with finishReason set to 'error', restoring the behavior from 1.55.0, so custom processors can observe and react to error terminals. Message history still avoids saving a user message when the provider fails before producing any output, so failed turns don't leave orphaned input in the conversation history. Cancelled (aborted) streams continue to skip output processors. Fixes #21292. (#21370)
-
Couple the blocking wait in get_process_output to the run's abortSignal: ProcessHandle.wait() now accepts abortSignal and kills the process on abort (the same convention the process manager applies at spawn time), and the workspace tool forwards context.abortSignal, so aborting a run no longer leaves the tool blocking on a background process. (#21388)
const controller = new AbortController(); const result = await handle.wait({ abortSignal: controller.signal, }); // controller.abort() kills the process and wait() resolves with its exit result
-
Fixed an issue where multiple agents sharing one storage instance would all respond in a subscribed channel thread instead of just the agent that was mentioned. Each agent now tracks its own channel threads and subscriptions. (#21288)
-
Reduced persisted agent-loop snapshot size by no longer storing duplicated provider request data (measured at 24% of all persisted snapshot bytes in production). Resume behavior and step routing data are unchanged. (#21390)
-
Fixed runEvals TypeScript overloads for Workflow targets so they accept gates and threshold-bearing scorer entries, matching what the runtime already supports. Workflow eval runs can now produce a verdict without type errors. Fixes #21290 (#21380)
-
Fixed file-based agents so setting
workspacetoundefineddisables the default workspace and its automatic file and shell tools. (#21378) -
Fixed legacy Anthropic history that contains a thinking signature without its original thinking text is sanitized before replay, preventing invalid empty signed thinking blocks from being forwarded. (#17602)
Fixes #17457.
-
Fixed schedule errors to preserve actionable HTTP statuses and retained structured agent errors after model fallback exhaustion. (#21449)
-
Fixed gateway authentication so empty header objects fall back to API keys and are not reported as valid credentials. (#21266)
-
Fixed missing TypeScript declarations for the
@mastra/core/test-utils/llm-mockentrypoint.MastraLanguageModelV2Mock,createMockModel, andsimulateReadableStreamare now fully typed when imported in consumer projects — no need for a local ambientdeclare moduleshim. (#21427)import { MastraLanguageModelV2Mock } from '@mastra/core/test-utils/llm-mock'; const mockModel = new MastraLanguageModelV2Mock({ doGenerate: async () => ({ content: [{ type: 'text', text: 'stubbed response' }], finishReason: 'stop', usage: { inputTokens: 1, outputTokens: 1, totalTokens: 2 }, warnings: [], }), }); // Spy arrays are typed as LanguageModelV2CallOptions[] mockModel.doGenerateCalls;
@mastra/blaxel@0.6.1
Patch Changes
- Fixed GCS mounts to accept bucket names containing underscores. (#21391)
@mastra/clickhouse@1.15.1
Patch Changes
- Fixed ClickHouse schema operations to avoid socket warnings from unread responses. (#21363)
@mastra/client-js@1.40.0
Minor Changes
-
Added an active-runs listing for agent controllers. It reports every run currently in flight on the controller from in-memory tracking — a cheap read suited to polling activity indicators, with no session created as a side effect. (#21353)
const runs = await client.getAgentController('code').listActiveRuns(); // [{ runId: 'run-1', resourceId: 'workspace-a', threadId: 'thread-1' }]
-
Declared
bufferingMessagesandbufferingObservationson thedisplay_state_changedevent, which the server has been sending all along. They say which memory budget a background pass is working on, so a client can show that work on the budget it acts on instead of as one shared label. (#21366)client.agentController(id).streamSession(resourceId, event => { if (event.type !== 'display_state_changed') return; // A buffered observation is running: the message window is being read into memory. // A buffered reflection is running: observations are being consolidated. const { bufferingMessages, bufferingObservations } = event.displayState; });
@mastra/code-sdk@1.2.1
Patch Changes
-
Send opaque acting-user subjects with Platform sandbox requests, including Factory creation and reattachment flows. (#20754)
import { PlatformSandbox } from '@mastra/platform-workspace'; const sandbox = new PlatformSandbox({ environmentId: 'env_abc', actingUserId: auth.user.id, });
-
Fixed memory growth from accumulated language servers by limiting retained workspace clients. (#21186)
@mastra/datadog@1.4.0
Minor Changes
- Bridges now report whether a created span's parent is a Mastra span or an external one, so runs that start under an external parent are recorded as trace roots in Mastra Studio. (#20499)
@mastra/daytona@0.7.1
Patch Changes
- Fixed GCS mounts to accept bucket names containing underscores. (#21391)
@mastra/e2b@0.8.2
Patch Changes
- Fixed GCS mounts to accept bucket names containing underscores. (#21391)
@mastra/factory@0.7.0
Minor Changes
-
Automatic agent runs are now opt-in per Factory (#21326)
Factory rules no longer start agent runs on their own. When a rule wants to start one — reviewing a new pull request, triaging an issue, planning work — it is parked as a
proposeddecision, and clicking the card starts it. Rules that only mirror external facts are untouched: a merged pull request still moves its card to Done, a closed issue still lands in Done or Canceled.Automatic runs are switched on and off from the top of the Work and Review boards, and they start off — including for Factories that exist today, so rules stop starting runs on upgrade until someone turns them back on.
A proposal that nobody wants can be turned down from the card menu or the Rules page, and both actions are recorded in the audit log. Through the API:
// Turn automatic runs back on for a Factory. await fetch(`/web/factory/projects/${factoryProjectId}`, { method: 'PATCH', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ autoRunEnabled: true }), }); // Release a parked run, or drop it for good. await fetch(`/web/factory/projects/${factoryProjectId}/decisions/${decisionId}/approve`, { method: 'POST' }); await fetch(`/web/factory/projects/${factoryProjectId}/decisions/${decisionId}/dismiss`, { method: 'POST' });
Why: opening a pull request used to start an agent that checks out and runs its code, with no way to say no. That consent now belongs to the Factory owner, while the board keeps reflecting what happens in GitHub and Linear either way.
-
Added independent GitHub issue and pull request reconciliation controls for Factory, with legacy reconciliation settings preserved as fallbacks. Added Linear issue reconciliation aliases and automatically move linked work cards to Done or Canceled when upstream issues close. (#21342)
For example, run GitHub issue reconciliation every minute while leaving pull-request reconciliation at its existing cadence:
MASTRACODE_GITHUB_ISSUE_RECONCILE_INTERVAL_MS=60000
-
Added Slack channel adapter options to
SlackIntegrationand made concise thinking, typing, and working statuses the default. (#21381)new SlackIntegration({ signingSecret, adapterOptions: { streaming: true, toolDisplay: 'grouped', }, });
Patch Changes
-
Cleaned up the agent transcript in the Factory web UI. Tool calls, tool groups and skill activations now share one row shape: a leading glyph for the kind of call, the label, the live command, and a disclosure chevron that only shows on hover. A collapsed group keeps its
5 stepslabel and stands for what it holds with one glyph per kind of call, instead of a genericFind files · Read · Runlist. (#21321)A skill now looks the same whether you activated it or the agent called the
skilltool itself: both render the instructions as Markdown rather than a raw arguments-and-output dump, and a skill call no longer disappears inside a group of steps.Also fixed two artefacts: a message carrying only internal step markers drew an empty chat bubble, and invisible parts split runs of tool calls into unrelated groups.
-
Factory triage now uses
status:labels so triaged and approval-pending issues remain visible to the Factory workflow. (#21318) -
Route GitHub issue investigation through Factory rules and the bundled
factory-triageskill instead of the legacy triage runner. (#21413) -
Replaced the raw
buffering/observing/reflectingphase label in the Factory status line with two rings, one per memory budget: the message window and the accumulated observations. Each ring shows how full its budget is, and a highlight travels around the ring while memory works through it — background work reads as work instead of leaking an internal phase name. A memory pass that actually holds the turn still says so ("saving memory", "consolidating memory"). Both rings sit in one control, and clicking it opens both budgets in full: an icon each in the budget's own colour, the figures, and a line saying what reaching the threshold sets off. The control speaks both readings to assistive tech, which a button otherwise hides. (#21366)A background pass now shows on the budget it actually acts on, rather than as one word shared by both.
-
Fixed the Mastra client being recreated on every render of MastraClientProvider, which silently reset per-client caches such as endpoint support and capability probes. (#21326)
-
Fixed the Factory error screen rendering its message as a single column of letters down the page when the factories list fails to load. The notice now shows as a centered card with a readable line length. (#21322)
-
Fixed a failed branch push being reported as a token cleanup error. When the push failed and the token cleanup failed too, the cleanup error replaced the push error, so a push blocked by the network was reported with an unrelated error code. The push error is now reported as-is with its own code, and the cleanup error is added to the end of its message. (#21407)
-
Fixed workspace opening failures reporting a confusing
ENOENT/The "cwd" option is invaliderror instead of the real cause. When a repository clone failed and left no working directory behind, the token cleanup that always runs afterwards crashed on the missing directory and replaced the original error. Blocked egress, bad credentials, or a missing repository now surface as the actual failure. (#21338)Token cleanup is also stricter where it matters: once the access token has been written into the checkout's git settings, a failed cleanup is now always reported — even when the update itself failed, and even when a failed clone left a partial checkout behind — instead of being silently ignored.
-
Factory Overview now measures the Factory, not the connected repo. (#21333)
The integrations sync every issue and pull request of a connected repository onto the board, and those cards vastly outnumber the work the Factory actually runs. The Overview counted all of them, so a busy repo reported hundreds of completions, a lead time measured from the moment the poller filed the card, and an automation rate pinned near 100% because the poller stamps itself on every move it makes.
What changed
- Throughput, lead time, in-flight, work intake and stage coverage now cover only cards a Factory run was started on.
- In flight no longer counts the intake inbox, so it covers the same work as the queue-health chart below it, which already excluded it.
- Automation coverage is now Agent coverage: the share of each stage's first passes an agent finished, instead of any move no human made. The near-constant automation ratio card is gone.
- Agents running previously read threads under the wrong resource and always showed 0. The work-item listing now reports which of the cards it returns have a run in flight, so the count and the 'agent running' marker in the queue-health drill-down come from one read and can't disagree.
- Deleting a card whose agent is running clears its running marker with the card, instead of leaving it counted until the next poll.
GET /web/factory/projects/:id/work-itemsgainsrunningSessionIdsalongsideworkItems.FactoryMetricsdropstransitionsand renamesstageAutomationtoagentCoverage(exits→passes,automated→byAgent). -
Fixed MASTRACODE_ENV_DIR being resolved against the UI source directory instead of the working directory, which made the dev server silently load no environment variables when a relative path was given. (#21326)
-
Send opaque acting-user subjects with Platform sandbox requests, including Factory creation and reattachment flows. (#20754)
import { PlatformSandbox } from '@mastra/platform-workspace'; const sandbox = new PlatformSandbox({ environmentId: 'env_abc', actingUserId: auth.user.id, });
-
Improved Factory issue investigations with effort and impact labels. (#21401)
-
Chat messages now carry the time they were sent and a button that copies their text. Both sit under the message and only appear when you hover (or keyboard-focus) it, so the transcript stays clean. (#21350)
-
- Trigger a fresh review when a push arrives after a pull request review finishes. (#21356)
- Cancel an in-flight review when a push or Factory bot re-review request supersedes it.
- Route platform-polled
synchronizeandreview_requestedevents through the same review rules as direct webhooks. - Revive subscribed sessions with the persisted owner identified by the subscription session ID.
- Isolate failed subscription deliveries so stale bindings do not replay events or block newer repository activity.
A push or bot request that returns a card from
donetoreviewnow runsfactory-rereview. The skill reconciles the previous review against the pushed commits, checks for newly introduced defects, and reviews the whole pull request again before publishing its verdict. A canceled first-time review still restarts withfactory-reviewbecause it has no completed pass to reconcile. -
Agent replies now fade in word by word as they stream, instead of snapping whole chunks of text into place. Each word appears whole, so the visible text trails the stream by at most one word. A block that changes shape while it grows — a paragraph turning into a list item — fades again. Text that has finished streaming renders as before. (#21417)
-
Fixed workspace completion sounds and activity indicators to remain synchronized when switching threads. Running indicators no longer require an open workspace session, so they stay live on the board and overview pages too. (#21353)
-
Fixed markdown rendering in the Factory chat. Bullet and numbered lists show their markers again instead of collapsing into blankly indented lines, and task lists, tables and blockquotes now render properly. Fenced code blocks go through the design-system code block, so they get syntax highlighting, a copy button and a readable surface, and inline code is legible on every background. (#21355)
The chat now uses the same markdown renderer as the Studio rather than its own copy, so both stay in sync from here on.
-
Added a Skills page under the Agent section in Factory settings that shows the pipeline stage skills (Triage, Planning, Review, Re-review) with their playbook content, backed by a new GET /web/factory/skills endpoint. Also fixed a noisy checkpoint warning when the sandbox does not support snapshots. (#21369)
-
Improved Factory issue triage to label confirmed direct @mastra/core bugs. (#21179)
-
Improved work session preparation feedback across light and dark themes. (#21382)
@mastra/memory@1.26.2
Patch Changes
-
Corrected the
observation.blockAfterandreflection.blockAfterconfiguration documentation shown in editors. Crossingobservation.blockAfterlets buffered activation overshoot the retention target; it does not force a blocking observation. The documented value ranges now match the runtime: values from 1 up to (but not including) 100 multiply the base threshold, and values of 100 or more are absolute token counts that must be greater than the base threshold. (#21215) -
Added continuation support to the Observational Memory
recalltool. When a single message part is larger than the result budget, the result now includesnextCharOffsetand a note explaining how to fetch the next chunk, so oversized parts can be read across multiple calls instead of returning the same truncated prefix every time. (#19821){ "mode": "messages", "cursor": "<message-id>", "partIndex": 0, "detail": "high", "charOffset": 8000 }Fixes #19817.
@mastra/nestjs@0.2.16
Patch Changes
-
Fixed NestJS auth passing a Web Request to authenticateToken and authorize hooks so cookie-based providers (such as Better Auth) no longer fail with 401 on valid credentials. (#21258)
Resolves #21253
@mastra/observability@1.17.0
Minor Changes
-
Added an
indexedredaction style toSensitiveDataFilter. Instead of collapsing every sensitive value to the same[REDACTED]string, each unique value gets a stable token derived from the first matched field name, like[APIKEY_1]. (#21328)new SensitiveDataFilter({ redactionStyle: 'indexed', });
See #21313
-
Fixed traces that start under an external parent span not appearing in Mastra Studio. (#20499)
@mastra/otel-bridge@1.5.0
Minor Changes
- Bridges now report whether a created span's parent is a Mastra span or an external one, so runs that start under an external parent are recorded as trace roots in Mastra Studio. (#20499)
@mastra/platform-workspace@1.2.1
Patch Changes
-
Send opaque acting-user subjects with Platform sandbox requests, including Factory creation and reattachment flows. (#20754)
import { PlatformSandbox } from '@mastra/platform-workspace'; const sandbox = new PlatformSandbox({ environmentId: 'env_abc', actingUserId: auth.user.id, });
@mastra/playground-ui@49.0.0
Minor Changes
-
Added animated Sankey layout transitions for column changes. Pass a changing perspective key to opt in: (#20768)
<SankeyChart geometryTransitionKey={columns.map(column => column.id).join(':')} />
-
Made the task list collapsible and moved its scrolling to the design system scroll area. (#21337)
Clicking the task list header now collapses it. The collapsed row keeps the completion count and shows the task currently in progress — or the next pending one — with its status icon and color, so the panel can be minimized without losing track of where the agent is. Long lists scroll inside
ScrollArea(overlay scrollbar, edge fades) instead of a rawoverflow-ycontainer.Use
defaultOpento render it collapsed:<TaskList tasks={tasks} defaultOpen={false} />
-
Streamed markdown now renders block by block. A growing reply re-parses only the block still being written instead of the whole message on every chunk, so a long reply no longer costs more per chunk as it gets longer, and a reply that finishes streaming keeps every element it already put on screen instead of remounting. (#21473)
Half-written markdown also renders as what it is about to become:
**boldreads as bold while its closing marker is still in flight, and a link shows its text until the URL lands, instead of flashing raw syntax on screen.One caveat: splitting a text into blocks is deliberately conservative rather than a second full parse. Anything it cannot decide — an unclosed fence, an indented continuation, a link reference or footnote definition — is kept whole, so those replies render exactly as before and simply do not get the speedup.
-
CopyButtontakes ashowToastoption, so a button whose icon already flips to a checkmark on success can skip the toast on top of it. (#21350)<CopyButton content={message} showToast={false} />
-
Added two status-strip pieces so any app showing a chat runtime — Studio, Factory — reads the same way.
TokenBudgetdraws a token budget as a ring with its reading beside it, andTokenBudgetDetailis that budget in full for a popover or panel: (#21366)import { TokenBudget, TokenBudgetDetail } from '@mastra/playground-ui/components/TokenBudget'; <div className="flex items-center gap-1.5"> <TokenBudget label="Message window" tokens={14_900} threshold={30_000} working={isObserving} /> <TokenBudget label="Observations" tokens={5_200} threshold={8_000} tone="memory" /> </div>; <TokenBudgetDetail description="Read into memory once full" icon={<MessageSquare />} label="Messages" projected={6_000} tokens={14_900} threshold={30_000} />;
The two are separate so the app decides how a budget opens — one trigger per budget, or one control for a whole group.
TokenBudgetDetailhatches the slice a pending pass will free (projected) at the end of its bar, so the number and where it goes read together, and takes aniconit tints with the budget's own color so a detail row is recognizable as the ring it came from.workingruns a highlight around the ring, so a pass happening in the background is visible without a word for it.tonepicks the budget's identity color (messages,memory,warning), which the memory panel's own progress bars now share instead of repeating the palette classes.Fixed those same memory panel bars drawing a budget as completely full when its threshold was zero.
-
Improved process step indicators with theme-aware status colors and a plain embedded style. (#21382)
Step labels now come from
title.ProcessStepListItemused to build its heading from the step id and ignore thetitleyou passed, so display copy had to live in kebab-case ids. Give the step the label you want on screen:const step = { id: 'clone-repo', title: 'Cloning repository', status: 'running', description: '', isActive: true }; <ProcessStepListItem step={step} isActive position={1} />; // before: "Clone repo" // after: "Cloning repository"
The
stepIdprop is now optional and ignored; drop it from your call sites.Added a
plainvariant toProcessStepListItem— for step lists that already sit inside a panel, where the boxed active card is one frame too many:<ProcessStepListItem step={step} isActive={step.status === 'running'} position={1} variant="plain" />
-
Added a
streamingprop toMarkdownRenderer. A reply marked as still being written fades each word in as it arrives, instead of snapping whole chunks of text into place. (#21417)<MarkdownRenderer streaming={part.state === 'streaming'}>{part.text}</MarkdownRenderer>
The fade is CSS on words as they land, so the text already on screen stays put while the reply grows. A word fades in once it is whole rather than one character at a time — the word still being typed is held back until its boundary arrives, so the visible text trails the stream by at most one word. One caveat: when a growing block changes shape, a paragraph turning into a list item as the next character lands, that block fades again.
Leave the prop off — the default — for text that is already settled: it renders as plain prose, with no extra markup. The animation is disabled under
prefers-reduced-motion.Markdown no longer sets
text-wrap: pretty. It re-broke the last lines of a block to avoid orphans, which reran on every chunk of a streaming reply and jumped words that were already on screen onto another line.
Patch Changes
-
Fixed code blocks flickering between colored and plain text while an agent streams a fenced snippet. The part already highlighted now keeps its colors, and only the characters that just landed show uncolored until highlighting catches up. (#21415)
-
Improved chat responsiveness on long conversations.
MarkdownRendereris memoized, so a streaming reply no longer re-parses the markdown of every message already on screen on each chunk it receives — only the message actually being written is re-parsed. (#21416) -
Flattened the step markers in the
plainvariant ofProcessStepListItem. A completed step now shows a green check on its own instead of a filled green disc with a glow behind it, and the pending, running and completed markers finally share the same diameter — the dashed pending circle used to be 28px next to an 11px spinner. (#21414) -
Reworked the markdown renderer's typography. Headings, lists, blockquotes, tables and horizontal rules now follow one consistent rhythm, list markers and task-list checkboxes render as expected, and long tables scroll instead of stretching their container. (#21355)
Fenced code blocks now get syntax highlighting, a copy button and a frame of their own, and yaml, diff, css, html, xml and sql joined the highlighted languages, so fences in those languages are no longer plain text.
-
Fixed the composer edge glow so it follows the cursor only when the cursor is actually there. Focusing the composer used to light the moving arc as well, which meant the coloured segment kept sliding around the border while you typed or moved the mouse anywhere on the page. Focus now just brightens the border, and the arc lights on hover. (#21320)
@mastra/react@1.4.3
Patch Changes
-
Fixed the Mastra client being recreated on every render of MastraClientProvider, which silently reset per-client caches such as endpoint support and capability probes. (#21326)
-
Fixed MASTRACODE_ENV_DIR being resolved against the UI source directory instead of the working directory, which made the dev server silently load no environment variables when a relative path was given. (#21326)
@mastra/schema-compat@1.3.7
Patch Changes
- Optional nested JSON Schema properties with multiple types no longer produce exponentially large OpenAI tool payloads. Payload growth now remains linear as these schemas become more deeply nested. (#21190)
@mastra/server@1.59.0
Minor Changes
-
Added an active-runs listing for agent controllers. It reports every run currently in flight on the controller from in-memory tracking — a cheap read suited to polling activity indicators, with no session created as a side effect. (#21353)
const runs = await client.getAgentController('code').listActiveRuns(); // [{ runId: 'run-1', resourceId: 'workspace-a', threadId: 'thread-1' }]
@mastra/stagehand@0.3.3
Patch Changes
- Fixed browser close tracking so agent-initiated Stagehand shutdowns are reported accurately. (#21452)
Other updated packages
The following packages were updated with dependency changes only:
- @mastra/agent-builder@1.1.12
- @mastra/braintrust@1.3.5
- @mastra/deepeval@0.1.2
- @mastra/deployer@1.59.0
- @mastra/deployer-cloud@1.59.0
- @mastra/deployer-cloudflare@1.2.16
- @mastra/deployer-netlify@1.2.16
- @mastra/deployer-sandbox@0.3.1
- @mastra/deployer-vercel@1.2.16
- @mastra/editor@0.13.13
- @mastra/express@1.5.1
- @mastra/fastify@1.5.1
- @mastra/hono@1.6.1
- @mastra/koa@1.7.1
- @mastra/laminar@1.3.10
- @mastra/langsmith@1.3.10
- @mastra/longmemeval@1.1.16
- @mastra/mcp-docs-server@1.2.16
- @mastra/next@0.2.15
- @mastra/opencode@0.1.16
- @mastra/posthog@1.3.2
- @mastra/sentry@1.2.10
- @mastra/tanstack-start@0.2.15
- @mastra/temporal@0.3.1
- @mastra/voice-google-gemini-live@0.14.7
- @mastra/voice-openai-realtime@0.13.7
- @mastra/voice-xai-realtime@0.2.7