github mastra-ai/mastra @mastra/core@1.61.0
August 21, 2026

4 hours ago

Highlights

Caller-Driven Experiments (Temporal/External Orchestrator Support)

New dataset experiment APIs let external orchestrators own the experiment loop while Mastra remains the system of record: create experiments idempotently, run items server-side (runExperimentItem) or submit externally computed results (submitExperimentResult), then finalize for server-computed succeeded/failed/skipped counts—fully compatible with Studio views and comparisons.

Graceful Shutdown + HTTP Drain Controls for Generated Servers

Generated servers now support configurable shutdown behavior (drain in-flight requests, tune drainTimeout, or disable built-in signal handlers) with improved shutdown draining behavior and cleanup reliability across @mastra/core and @mastra/deployer.

First-Class “While-Active” Message Delivery in Sessions

User messages sent while an agent is already working are now consistently marked delivery: 'while-active' automatically (including steering), simplifying clients and preserving accurate transcripts across reloads while keeping caller overrides supported.

Workflow Resume Concurrency Safety (Atomic Claim + 409 Conflicts)

Concurrent resume() calls are now safe: a resume atomically claims a suspended run (losers get WORKFLOW_RESUME_ALREADY_CLAIMED and HTTP 409), and workflow state updates add an expectedStatus guard to prevent duplicate downstream execution.

Evals: Multi-Turn LLM Judge Scorer

createMultiTurnJudgeScorer enables LLM-judge scoring over an entire multi-turn conversation (not just a single assistant message), unlocking evaluation of multi-turn runEvals inputs against plain-English criteria.

Breaking Changes

  • None called out in this changelog.

Changelog

@mastra/core@1.61.0

Minor Changes

  • Added graceful shutdown options for generated servers (#20678). Configure how long in-flight HTTP requests may drain, or disable Mastra's built-in signal handlers when managing the server lifecycle yourself. (#21990)

    export const mastra = new Mastra({
      server: {
        drainTimeout: 600_000,
        handleShutdownSignals: false,
      },
    });
  • The session now marks a message you send while the agent is working, and every client gets it for free. Any user message submitted with a run in flight — including the one session.steer() sends after interrupting a run — carries delivery: 'while-active', so the agent reads it as context for the work in progress and a reloaded transcript can still tell a steer apart from a normal message. A message that opens a new turn is unmarked, as before. (#21842)

    The attribute used to be resolved from the run state at dispatch time, which reads idle for a steer (a steer aborts its own run before sending), so each client had to describe both delivery routes itself.

    // before
    session.sendSignal({
      content,
      ifActive: { attributes: { delivery: 'while-active' } },
      ifIdle: { attributes: { delivery: 'message' } },
    });
    
    // now
    session.sendSignal({ content });

    A delivery the caller sets on the signal still wins.

  • Added caller-driven experiments so an external orchestrator (for example Temporal workers) can own the experiment loop while Mastra stays the system of record. (#21888)

    Create an experiment with dataset.createExperiment() (idempotent when you pass your own id). With a target, Mastra runs each item for you: call dataset.runExperimentItem() per item and Mastra executes the registered agent or workflow, resolves scorers (experiment scorers, falling back to item scorerIds, then dataset scorerIds), and upserts the result. Without a target, run everything yourself and report per-item results with dataset.submitExperimentResult() (upsert semantics on (experimentId, itemId, attempt) so retried workers converge on a single row). Either way, close the run with dataset.finalizeExperiment() and Mastra computes per-item succeeded/failed/skipped counts from the persisted rows. Results go into the same storage as native runs, so Studio views, comparisons, and review summaries work unchanged.

    // Caller drives the loop, Mastra runs each item
    const { experimentId } = await dataset.createExperiment({
      id: workflowRunId,
      targetType: 'agent',
      targetId: 'support-agent',
      scorers: ['accuracy'],
    });
    
    await dataset.runExperimentItem({ experimentId, itemId });
    
    // Or: caller runs everything, Mastra ingests results
    const ingest = await dataset.createExperiment({ id: workflowRunId });
    await dataset.submitExperimentResult({
      experimentId: ingest.experimentId,
      itemId,
      output,
      scores: [{ scorerId: 'accuracy', score: 0.92 }],
    });
    
    const experiment = await dataset.finalizeExperiment({ experimentId });

    Also in: @mastra/client-js@1.42.0, @mastra/libsql@1.21.1, @mastra/mongodb@1.18.1, @mastra/mysql@0.8.1, @mastra/pg@1.21.1, @mastra/server@1.61.0, @mastra/spanner@1.6.2

Patch Changes

  • Update provider registry and model documentation with latest models and providers (88d14ca)

  • Fixed the coding agent's instructions for a message that arrives while it is already working. They described that message as <user-message delivery="…">, a tag the runtime never emits, so the rule and the wrapper the agent actually receives (<user delivery="…">) never matched by name. (#21879)

    No API change, and no change to how a message is delivered: one that lands mid-work is still marked while-active and still meant as context for the work in flight. The instructions now name it the way it arrives.

  • Added HTTP endpoints for caller-driven experiments: POST /datasets/:datasetId/experiments now accepts start: false to create an experiment without spawning the runner (with an optional target and run-level scorerIds), and new routes POST /datasets/:datasetId/experiments/:experimentId/items/:itemId/run, POST /datasets/:datasetId/experiments/:experimentId/results, and POST /datasets/:datasetId/experiments/:experimentId/finalize let external orchestrators run one item server-side, submit externally computed per-item results (idempotent upsert on retries), and finalize the run with server-computed counts. (#21888)

    Also in: @mastra/client-js@1.42.0, @mastra/libsql@1.21.1, @mastra/mongodb@1.18.1, @mastra/mysql@0.8.1, @mastra/pg@1.21.1, @mastra/server@1.61.0, @mastra/spanner@1.6.2

  • Fixed versioned dataset item lookups to return the item visible in the requested dataset snapshot. (#21979)

    Also in: @mastra/libsql@1.21.1, @mastra/mysql@0.8.1, @mastra/pg@1.21.1, @mastra/spanner@1.6.2

  • Fixed concurrent resume() calls on the same suspended workflow run executing downstream steps more than once. A resume now atomically claims the run before executing anything, so only one caller continues a given suspension. Losing callers throw WORKFLOW_RESUME_ALREADY_CLAIMED without running any steps. Fixes #20443 (#21725)

    Also in: @mastra/convex@1.5.4, @mastra/dsql@1.3.2, @mastra/dynamodb@1.3.1, @mastra/libsql@1.21.1, @mastra/mongodb@1.18.1, @mastra/mssql@1.7.2, @mastra/mysql@0.8.1, @mastra/oracledb@0.2.1, @mastra/pg@1.21.1, @mastra/redis@1.4.2, @mastra/server@1.61.0, @mastra/spanner@1.6.2, @mastra/upstash@1.4.2

  • Added createDatasetExperiment(), runExperimentItem(), submitExperimentResult(), and finalizeExperiment() methods so a caller-owned orchestrator (for example Temporal) can drive an experiment loop while Mastra either executes each item server-side or ingests externally computed results. (#21888)

    Also in: @mastra/client-js@1.42.0, @mastra/libsql@1.21.1, @mastra/mongodb@1.18.1, @mastra/mysql@0.8.1, @mastra/pg@1.21.1, @mastra/server@1.61.0, @mastra/spanner@1.6.2

  • Fixed Code Mode instructions to reference custom tool IDs. (#21920)

  • Reduced agent-controller memory usage during long streamed responses by reusing the live accumulated message across message_start, message_update, and message_end events, including events queued for server-sent event delivery. display_state_changed.currentMessage references the same live message. Consumers that require point-in-time values should copy or serialize before deferring event processing. (#21813)

    Also in: @mastra/server@1.61.0

  • Removed a catch that hid a broken durable run. When a durable run's state could not be read between iterations, the loop kept going and crashed one step later with an error that pointed at the wrong place. It now fails where the unreadable state is found, carrying the real cause. (#21889)

  • Workflow state updates now support an optional expectedStatus guard, so a status change is only applied when the stored run is in an expected state. This is what makes concurrent workflow resumes safe. (#21725)

    Also in: @mastra/convex@1.5.4, @mastra/dsql@1.3.2, @mastra/dynamodb@1.3.1, @mastra/libsql@1.21.1, @mastra/mongodb@1.18.1, @mastra/mssql@1.7.2, @mastra/mysql@0.8.1, @mastra/oracledb@0.2.1, @mastra/pg@1.21.1, @mastra/redis@1.4.2, @mastra/server@1.61.0, @mastra/spanner@1.6.2, @mastra/upstash@1.4.2

  • Preserved plan revision feedback in submit_plan results so hosts can replay resolved approvals. (#21891)

  • Fixed a security issue where the framework-managed auth bearer token (mastra__authToken) was persisted in cleartext in workflow snapshots, score rows, and durable agent workflow inputs. The token is now excluded from all durable persistence; resumed authenticated requests use their own fresh live token. Fixes #21975 (#21996)

  • Added upsertExperimentResult() to the experiments storage domain plus an attempt column on experiment results and a nullable target with an optional scorerIds column on experiments, enabling retry-safe result writes for caller-driven experiments (retried submissions with the same (experimentId, itemId, attempt) key converge on a single row). saveScore() now accepts an optional caller-supplied id and upserts on it, so retried experiment submissions replace their previous score rows (latest wins) instead of accumulating duplicates. (#21888)

    Also in: @mastra/client-js@1.42.0, @mastra/libsql@1.21.1, @mastra/mongodb@1.18.1, @mastra/mysql@0.8.1, @mastra/pg@1.21.1, @mastra/server@1.61.0, @mastra/spanner@1.6.2

  • Resume conflicts now return 409 Conflict. When a suspended workflow run has already been resumed by another caller, the resume endpoints respond with 409 instead of a generic error. (#21725)

    Also in: @mastra/convex@1.5.4, @mastra/dsql@1.3.2, @mastra/dynamodb@1.3.1, @mastra/libsql@1.21.1, @mastra/mongodb@1.18.1, @mastra/mssql@1.7.2, @mastra/mysql@0.8.1, @mastra/oracledb@0.2.1, @mastra/pg@1.21.1, @mastra/redis@1.4.2, @mastra/server@1.61.0, @mastra/spanner@1.6.2, @mastra/upstash@1.4.2

  • Fixed a reply coming back duplicated after an interrupted turn. When an error-retry processor or the durable loop moved the response message id without sealing the stored response, the streamed message split where the stored one did not, so the second half reappeared under its own id on reload. Rotating a response message id now seals the response it leaves behind, so the two can no longer drift apart. (#21868)

    Durable runs now honour the same error-retry hooks as regular runs: processAPIError receives messageId and a working rotateResponseMessageId, so a processor can close the failed response and answer the retry in a message of its own instead of appending to it. The same handler was also working on a throwaway copy of the conversation, so anything it added there was dropped: a signal sent from processAPIError never reached the retried request. It does now.

    const agent = new Agent({
      name: 'support',
      model: 'openai/gpt-5-nano',
      maxProcessorRetries: 1,
      errorProcessors: [
        {
          id: 'retry-in-a-new-message',
          processAPIError: async ({ rotateResponseMessageId }) => {
            rotateResponseMessageId?.();
            return { retry: true };
          },
        },
      ],
    });

    Message ids minted during a durable run also honour a custom generateId configured on Mastra, which some paths silently ignored.

  • Fixed Code Mode sandbox resolution for resolver-backed workspaces. (#21922)

  • Improved Agent Controller session startup by initializing workspaces only when used. (#21874)

    Agent Controller no longer initializes configured workspaces during controller or session creation.

    Before, session creation implicitly initialized the configured workspace:

    const session = await controller.createSession({ id: 'session-id' });

    After, applications that require eager initialization must request it explicitly:

    const session = await controller.createSession({ id: 'session-id' });
    await session.getWorkspace()?.init();

    Workspace operations otherwise initialize their resources lazily.

  • Fixed shared threads running with a stale model in multi-server deployments. The model selected for a mode is now re-read from the thread's persisted settings at the start of every run, so a model switch made in one browser session or server replica is picked up by all others instead of silently diverging until the next mode switch. (#21899)

    Also in: @mastra/code-sdk@1.4.0, @mastra/factory@0.9.0

  • Fixed streaming output processors reacting to errors that the agent recovered from. Previously, an error raised by a single model call (for example a transient rate limit delivered in the response stream) was passed to every output processor immediately, before error processor retries or fallback models had a chance to recover. Processors now only see an error once the run has actually failed on it, and they see it exactly once. (#21738)

  • Fixed the streamed reply splitting differently from the stored one. When the agent's turn was interrupted mid-run — a message sent while it was working, a resumed tool approval, a state signal — the live stream kept everything in one assistant message while storage had already sealed it and opened a new one. Coming back to the thread (tab switch, reload) replayed the second half as an extra copy. The stream now closes its message at the same boundary the run loop does. (#21841)

@mastra/ai-sdk@1.9.1

Patch Changes

  • Forward messageMetadata from chatRoute to the underlying AI SDK stream handler. (#21919)

@mastra/client-js@1.42.0

Patch Changes

  • Added optional plan content fields to PlanResume so hosts can preserve submitted plans in approval history. (#21891)

    const response: PlanResume = {
      action: 'rejected',
      title: 'Add authentication',
      path: '.artifacts/plans/authentication.md',
      plan: '# Add authentication\n\n1. Configure the provider.',
      feedback: 'Use the existing session middleware.',
    };

@mastra/code-sdk@1.4.0

Minor Changes

  • Fixed credential failures that told every interface to run /login, a command only the terminal UI has. A provider fetch without a usable credential now throws ProviderAuthRequiredError, which states the fact and leaves the remedy to the host running the agent. (#21860)

    import { ProviderAuthRequiredError } from '@mastra/code-sdk/auth/provider-auth-error';
    
    try {
      await run();
    } catch (error) {
      // Before: the message hardcoded "Run /login first."
      // Now: match the error and point the user at whatever sign-in path your host offers.
      if (error instanceof ProviderAuthRequiredError) showSignIn();
    }

    The error name is stable across serialization, so a client that only receives { name, message } over the wire can match it too.

  • Added opt-in process memory diagnostics for SDK process adapters. The service records process and V8 heap-space samples, naturally occurring garbage collection events, and periodic allocation profiles without forcing garbage collection or writing heap snapshots. (#21821)

    Start diagnostics before creating Mastra Code, then await the final capture after work-producing services stop:

    import {
      createProcessMemoryDiagnosticsFromEnvironment,
      startConfiguredProcessMemoryDiagnostics,
    } from '@mastra/code-sdk/process-memory-diagnostics';
    
    const setup = createProcessMemoryDiagnosticsFromEnvironment(process.env);
    const diagnostics = await startConfiguredProcessMemoryDiagnostics(setup, console.warn);
    
    try {
      // Create and run the process adapter.
    } finally {
      await diagnostics.stop();
    }

    Allocation profiles remain local and may contain prompts, credentials, file contents, and tool arguments. Keep them private and delete them after analysis.

Patch Changes

  • Factory runs now resolve provider credentials with org > user precedence, so an org-wide "Everyone in org" key takes priority over a run's acting user's personal key. This means factory automation always bills against the org's shared credentials when they exist, regardless of who triggered the run. Interactive (non-factory) sessions keep the existing user > org precedence, so personal plan subscriptions and keys still take priority there. (#21899)

    Also in: @mastra/factory@0.9.0

  • Interactive messages and model switches on factory sessions now resolve provider credentials org-first (org > user), matching board-run kickoff. The credential resolver keys off the session's factoryProjectId in controller state, so any run on a factory-owned session rides the org's shared keys with the caller's personal credentials as fallback — switching to a personal-only model still works through that fallback. Repo-backed Slack channel sessions now stamp the owning factory project onto session state so they get the same behavior. (#21899)

    Also in: @mastra/factory@0.9.0

@mastra/deployer@1.61.0

Minor Changes

  • Improved generated server shutdown to drain in-flight HTTP requests before closing Mastra resources (#20678). Refresh streams now close during shutdown, drain failures no longer skip resource cleanup, and a second shutdown signal exits immediately. (#21990)

Patch Changes

  • Sweep idle HTTP connections periodically during graceful shutdown. A keep-alive socket whose in-flight response finished after the initial closeIdleConnections() call would stall the drain until the full server.drainTimeout expired; the server now exits as soon as in-flight work actually completes. (#21996)

  • Fix ERR_INVALID_ARG_VALUE during bundling when a bare import is resolved from a Rollup virtual module. nodeModulesExtensionResolver now skips NUL-prefixed importers (e.g. \0virtual:#entry) instead of treating them as filesystem paths. (#21998)

@mastra/evals@1.9.0

Minor Changes

  • Added createMultiTurnJudgeScorer to @mastra/evals/scorers/prebuilt, an LLM judge that grades a whole multi-turn conversation against a plain-English criterion. (#21936)

    The other prebuilt LLM judges read a single assistant message, so they cannot grade a conversation run with the multi-turn inputs form of runEvals. This scorer reads every assistant turn accumulated in run.output and returns 1 when the criterion is satisfied, otherwise 0.

    import { runEvals } from '@mastra/core/evals';
    import { createMultiTurnJudgeScorer } from '@mastra/evals/scorers/prebuilt';
    
    const result = await runEvals({
      data: [{ inputs: ["How's the weather in London?", 'And Paris?', 'Should I pack an umbrella?'] }],
      target: weatherAgent,
      scorers: [
        {
          scorer: createMultiTurnJudgeScorer({
            model: 'anthropic/claude-haiku-4-5',
            criterion: 'The agent gave forecasts for London and Paris, and weather-appropriate packing advice.',
          }),
          threshold: 1,
        },
      ],
    });

@mastra/factory@0.9.0

Minor Changes

  • Added a /login command to the web chat composer. Credential errors used to name a command the web UI did not have, leaving no way to act on them from the browser. Typing /login now opens Settings → Models, where providers are connected. (#21860)

Patch Changes

  • Fixed the chat jumping every time a session's stream hiccuped. Losing the connection used to push a banner above the transcript and shove every message down; the reconnect state now lives only in the status line under the composer, where the model and token readouts already are. (#21850)

    The state is also honest during a run: a drop while the agent works used to stay hidden behind the working indicator, and now shows as Reconnecting…. A connection lost for good reads as Disconnected in the alert color.

  • Improved slash commands with a composer-integrated menu and consistent workspace panel elevation. (#21980)

  • Improved loaded Factory conversations with a smooth staggered reveal. (#21937)

  • Fixed assistant turns showing up twice in the chat transcript, with the first copy stripped of the tool cards that belong to it. (#21851)

    Tool cards stay attached to the text they ran under. The double came from the same turn arriving under a second identity after a stream gap; the transcript now recognises that copy as the turn it is already drawing and updates it in place.

  • Improved model selection in Factory chats. The status line now shows one combined picker with the effective model for the current mode. (#21871)

    The picker offers:

    • Model packs as presets, with your personal default marked.
    • Models grouped by provider, to override the model for the current mode.
    • A reset action that returns the chat to your default pack.
    • A link to pack management in settings.
    • Search across packs and models.

    The picker works in draft chats and in active user chats. A pack chosen in a draft applies before the first prompt runs. Live user chats can now switch models directly from the status line.

  • Trimmed what the Factory sidebar fetches while it polls. (#21862)

    The activity dots used to cost one request per user session every five seconds. They now share a single request whatever the sidebar holds, so ten sessions poll once instead of eleven times.

    Work item responses also stop carrying factoryRuleMaterializationKey, an internal field no client reads and the heaviest one on a large board.

  • Fixed Platform GitHub/Linear integrations and the Platform API client ignoring MASTRA_PLATFORM_ACCESS_TOKEN, the credential Mastra Platform injects into deployed projects. Integration auto-detection and the API client now accept MASTRA_PLATFORM_ACCESS_TOKEN (checked first) or MASTRA_PLATFORM_SECRET_KEY, so platform deployments work without manually copying the secret key into the environment. (#21982)

  • Creating a new Factory no longer takes over the whole screen once you already have one. The flow now runs inline at /factories/:factoryId/new-factory, so the sidebar stays in place and you keep the context of the Factory you were in. The full-screen version is still what you get on first run, when no Factory exists yet. (#21932)

    Each step is now a searchable list you type into instead of a form: name the Factory, pick a repository, pick the Linear project that feeds its board (or skip Linear entirely), then choose the provider and model your runs start on. Picking a Linear project routes it to the new Factory and turns its issue sync on, so the board fills up without a detour through Settings. Repository search hits GitHub directly, so large accounts are usable, and keyboard navigation works throughout (arrows to move, Enter to select, Esc to leave).

    Nothing is written to the server until the last step: the name, the repository and the Linear choice stay in the draft, and the Factory is created with all of them at once when you pick its model. Quitting the wizard halfway leaves nothing behind. Back walks the steps in reverse and only leaves the wizard from the first one.

  • Factory projects now have their own configurable observational-memory settings. Board runs and channel sessions hydrate from the factory project's shared settings row (falling back to built-in defaults) instead of any individual user's personal configuration, and the OM config routes accept a factoryId to read and update the factory-scoped row. In settings, a dedicated Memory page shows the factory-wide and personal observational-memory configuration side by side, so factory defaults and personal chat settings are edited separately. (#21899)

    To read or update the factory-scoped configuration, pass the factory project id:

    await fetch(`/web/config/om?factoryId=${factoryId}`);
    await fetch(`/web/config/om/observer/model`, {
      method: 'PUT',
      body: JSON.stringify({ modelId: 'anthropic/claude-haiku-4-5', factoryId }),
    });

    Requests without factoryId keep operating on the caller's personal settings.

  • Provider OAuth sign-in can now be shared with the whole organization. Org admins get a "Just me" / "Everyone in org" toggle on the OAuth provider list; org-scoped sign-ins are stored as shared org credentials, reported with an "Org sign-in" badge, and can be removed at org scope (admin-gated). (#21899)

  • Provider credentials can now be managed per scope after initial setup. The provider listing reports the caller's personal and org credentials independently (userCredential/orgCredential on ProviderInfo), so the settings UI shows separate sign-out actions for each scope and lets org admins add an org-wide OAuth sign-in while personally signed in (and vice versa) without signing out first. (#21899)

  • Provider-aware observational-memory defaults for factories. The factory creation wizard now fills the factory-scoped OM row (POST /web/config/om/provider-defaults accepts factoryId), and factory session hydration derives the OM fallback model from the factory's default model provider (e.g. anthropic/claude-haiku-4-5 when the default model is anthropic) instead of always using google/gemini-3.5-flash. GET/PUT OM routes report the same derived fallback so the settings UI no longer shows "Model credentials required" for factories whose default model provider is credentialed. (#21899)

  • Fixed factory board runs and Slack channel sessions inheriting the GitHub connection owner's personal observational-memory model settings. Factory sessions now always use the project's default model and the built-in observational-memory defaults, so runs no longer fail when the connection owner has a model configured that the workspace has no API key for. Web chat sessions still use each user's own memory settings. (#21899)

    Note: sessions created before this change keep the settings they were hydrated with. Recreate existing factory sessions after deploying to pick up the corrected defaults.

  • Fixed Factory steering messages so they no longer interrupt active work. Pending steering messages now show their delivery state and use the same neutral style as other user messages. (#21983)

  • Fixed pull request cards that stayed marked as open after an approving review. A card that an approving review moved to done was dropped from the GitHub reconcile sweep, so a merge landing afterwards never reached it — the board card kept saying open and the merged marker never appeared on its review session in the sidebar. Cards now stay in the sweep until their pull request is actually closed. (#21870)

  • Split thinking defaults on the Models settings page: the factory defaults section now has a base thinking level widget, and per-mode thinking defaults moved into the personal "Your defaults" section. (#21899)

@mastra/isolated-vm@0.1.1

Patch Changes

  • Updated isolated-vm to version 6.2.0 to fix a critical sandbox escape vulnerability (type confusion in ExternalCopy) that could allow untrusted code to corrupt host memory and escape the sandbox. (#21981)

@mastra/langfuse@1.5.0

Minor Changes

  • Added support for custom headers in Langfuse requests. (#21951)

@mastra/mcp@1.17.1

Patch Changes

  • Fixed MCP tool listing when a tool has no input schema. (#21861)

  • Fixed Cannot find package '@modelcontextprotocol/sdk' when importing @mastra/mcp in projects that skip automatic peer installation (e.g. npm with --legacy-peer-deps), by declaring the MCP SDK v1 peer required by @modelcontextprotocol/ext-apps as a direct dependency. (#21999)

@mastra/platform-workspace@1.4.0

Minor Changes

  • Added provider-selectable Platform Workspace routing through SANDBOX_PROVIDER, with direct E2B command execution and snapshot restore support. (#21991)

    Set SANDBOX_PROVIDER=e2b before constructing PlatformSandbox or PlatformFilesystem to use provider-prefixed E2B routes. Set it to railway for provider-prefixed Railway routes, or leave it unset to preserve the legacy /v1/projects/... Railway API.

@mastra/playground-ui@51.0.0

Minor Changes

  • Added controlled theme selection to Sankey signals so host applications can persist and restore the open theme panel. (#21968)

  • Added flat and factory variants to Section, including standard, view-only, and destructive row compositions. (#21939)

    <Section variant="factory">
      <Section.Header>
        <div>
          <Section.Heading>Security</Section.Heading>
          <Section.Description>Manage sign-in requirements.</Section.Description>
        </div>
      </Section.Header>
      <Section.Content>
        <Section.Row label="Two-factor authentication">
          <Switch />
        </Section.Row>
      </Section.Content>
    </Section>

Patch Changes

  • Improved floating surfaces with softer, consistent elevation. (#21980)

  • Improved plan cards to show expansion controls only when content is clipped and keep approval actions readable. (#21891)

  • Aligned the flat and factory Section layouts so their headings, row content, and actions share consistent horizontal edges. (#21970)

  • Fixed hidden search field labels taking up layout space. (#21918)

Other updated packages

The following packages were updated with dependency changes only:

Don't miss a new mastra release

NewReleases is sending notifications on new releases.