@mastra/deployer 1.36.0-alpha.0 → 1.36.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,72 @@
1
1
  # @mastra/deployer
2
2
 
3
+ ## 1.36.0-alpha.2
4
+
5
+ ### Patch Changes
6
+
7
+ - When browser streaming is unavailable (the `ws` and `@hono/node-ws` packages aren't installed, or the deployer is running in a serverless environment), the deployer now registers a fallback `GET /api/agents/:agentId/browser/session` route that returns `{ hasSession: false, screencastAvailable: false }`. This lets clients detect that screencast won't work and skip the WebSocket upgrade instead of triggering a noisy reconnect loop. ([#16668](https://github.com/mastra-ai/mastra/pull/16668))
8
+
9
+ - Bumped the `@mastra/core` peer dependency floor from `>=1.32.0-0` to `>=1.34.0-0`. ([#16666](https://github.com/mastra-ai/mastra/pull/16666))
10
+
11
+ - Updated dependencies [[`5ba7253`](https://github.com/mastra-ai/mastra/commit/5ba7253745c85e8df8012a76d954c640ffa336f7), [`f73980d`](https://github.com/mastra-ai/mastra/commit/f73980d651eb5f7f1ab20582de4615a1b6f10fce), [`f73980d`](https://github.com/mastra-ai/mastra/commit/f73980d651eb5f7f1ab20582de4615a1b6f10fce), [`9c88701`](https://github.com/mastra-ai/mastra/commit/9c8870195b41a38dc40b6ba2aa55eda04df8fa69), [`f73980d`](https://github.com/mastra-ai/mastra/commit/f73980d651eb5f7f1ab20582de4615a1b6f10fce), [`9c88701`](https://github.com/mastra-ai/mastra/commit/9c8870195b41a38dc40b6ba2aa55eda04df8fa69), [`9c88701`](https://github.com/mastra-ai/mastra/commit/9c8870195b41a38dc40b6ba2aa55eda04df8fa69), [`9c88701`](https://github.com/mastra-ai/mastra/commit/9c8870195b41a38dc40b6ba2aa55eda04df8fa69), [`4e88dc6`](https://github.com/mastra-ai/mastra/commit/4e88dc6b89f154c0eae37221c8126be0c23c569f), [`19018f0`](https://github.com/mastra-ai/mastra/commit/19018f05722af74a5978781a7731a654b26f7f2a), [`5ba7253`](https://github.com/mastra-ai/mastra/commit/5ba7253745c85e8df8012a76d954c640ffa336f7)]:
12
+ - @mastra/core@1.36.0-alpha.2
13
+ - @mastra/server@1.36.0-alpha.2
14
+
15
+ ## 1.36.0-alpha.1
16
+
17
+ ### Minor Changes
18
+
19
+ - Added route-specific CORS configuration so credentialed cross-origin access can be limited to selected custom routes and channel webhooks. ([#16689](https://github.com/mastra-ai/mastra/pull/16689))
20
+
21
+ ```ts
22
+ registerApiRoute('/customer-webhook', {
23
+ method: 'POST',
24
+ cors: {
25
+ origin: ['https://customer-saas.example'],
26
+ credentials: true,
27
+ },
28
+ handler: async c => c.json({ ok: true }),
29
+ });
30
+ ```
31
+
32
+ ```ts
33
+ new Agent({
34
+ id: 'support-agent',
35
+ name: 'Support Agent',
36
+ instructions: '...',
37
+ model,
38
+ channels: {
39
+ adapters: {
40
+ web: {
41
+ adapter: createWebAdapter(),
42
+ cors: {
43
+ origin: ['https://customer-saas.example'],
44
+ credentials: true,
45
+ },
46
+ },
47
+ },
48
+ },
49
+ });
50
+ ```
51
+
52
+ Use `server.cors` for one global CORS policy across the server:
53
+
54
+ ```ts
55
+ new Mastra({
56
+ server: {
57
+ cors: {
58
+ origin: '*',
59
+ },
60
+ },
61
+ });
62
+ ```
63
+
64
+ ### Patch Changes
65
+
66
+ - Updated dependencies [[`8cdb86c`](https://github.com/mastra-ai/mastra/commit/8cdb86ceed1137bc2768e147dce85a0692b9fb26), [`eda90c5`](https://github.com/mastra-ai/mastra/commit/eda90c5bfd7de11805ecc9f4552716c895fbaf78), [`afc004f`](https://github.com/mastra-ai/mastra/commit/afc004f5cc7e30697809e7021820b9f5881e6719), [`408be73`](https://github.com/mastra-ai/mastra/commit/408be73449dfab92b51eab8c6623b6c443debc25)]:
67
+ - @mastra/core@1.36.0-alpha.1
68
+ - @mastra/server@1.36.0-alpha.1
69
+
3
70
  ## 1.36.0-alpha.0
4
71
 
5
72
  ### Patch Changes
@@ -3,7 +3,7 @@ name: mastra-deployer
3
3
  description: Documentation for @mastra/deployer. Use when working with @mastra/deployer APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/deployer"
6
- version: "1.36.0-alpha.0"
6
+ version: "1.36.0-alpha.2"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.36.0-alpha.0",
2
+ "version": "1.36.0-alpha.2",
3
3
  "package": "@mastra/deployer",
4
4
  "exports": {
5
5
  "Deps": {
@@ -17,6 +17,7 @@ var tools = require('@mastra/core/tools');
17
17
  var serverAdapter = require('@mastra/server/server-adapter');
18
18
  var util = require('util');
19
19
  var buffer = require('buffer');
20
+ var auth = require('@mastra/server/auth');
20
21
  var browserStream = require('@mastra/server/browser-stream');
21
22
  var store = require('@mastra/server/a2a/store');
22
23
  var hono = require('hono');
@@ -3183,6 +3184,9 @@ async function setupBrowserStream(app, config2) {
3183
3184
  }
3184
3185
  const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });
3185
3186
  const registry2 = new browserStream.ViewerRegistry();
3187
+ const rawPrefix = config2.apiPrefix ?? "/api";
3188
+ const trimmed = rawPrefix.endsWith("/") ? rawPrefix.slice(0, -1) : rawPrefix;
3189
+ const apiPrefix = trimmed || "/api";
3186
3190
  app.get(
3187
3191
  "/browser/:agentId/stream",
3188
3192
  upgradeWebSocket((c) => {
@@ -3210,7 +3214,20 @@ async function setupBrowserStream(app, config2) {
3210
3214
  };
3211
3215
  })
3212
3216
  );
3213
- app.post("/api/agents/:agentId/browser/close", async (c) => {
3217
+ app.get(`${apiPrefix}/agents/:agentId/browser/session`, (c) => {
3218
+ const agentId = c.req.param("agentId");
3219
+ if (!agentId) {
3220
+ return c.json({ error: "Agent ID is required" }, 400);
3221
+ }
3222
+ const threadId = c.req.query("threadId");
3223
+ const toolset = config2.getToolset(agentId);
3224
+ if (!toolset) {
3225
+ return c.json({ hasSession: false, screencastAvailable: true });
3226
+ }
3227
+ const hasSession = threadId ? toolset.hasThreadSession(threadId) : false;
3228
+ return c.json({ hasSession, screencastAvailable: true });
3229
+ });
3230
+ app.post(`${apiPrefix}/agents/:agentId/browser/close`, async (c) => {
3214
3231
  const agentId = c.req.param("agentId");
3215
3232
  if (!agentId) {
3216
3233
  return c.json({ error: "Agent ID is required" }, 400);
@@ -3616,7 +3633,7 @@ var MastraServer = class extends serverAdapter.MastraServer {
3616
3633
  if (authConfig) {
3617
3634
  const hasPermission = await loadHasPermission();
3618
3635
  if (hasPermission) {
3619
- const userPermissions = c.get("requestContext").get("userPermissions");
3636
+ const userPermissions = c.get("requestContext").get("mastra__userPermissions");
3620
3637
  const permissionError = this.checkRoutePermission(route, userPermissions, hasPermission);
3621
3638
  if (permissionError) {
3622
3639
  return c.json(
@@ -3713,7 +3730,7 @@ var MastraServer = class extends serverAdapter.MastraServer {
3713
3730
  if (authConfig) {
3714
3731
  const hasPermission = await loadHasPermission();
3715
3732
  if (hasPermission) {
3716
- const userPermissions = c.get("requestContext").get("userPermissions");
3733
+ const userPermissions = c.get("requestContext").get("mastra__userPermissions");
3717
3734
  const permissionError = this.checkRoutePermission(serverRoute, userPermissions, hasPermission);
3718
3735
  if (permissionError) {
3719
3736
  return c.json(
@@ -4447,6 +4464,27 @@ var getStudioPath = () => {
4447
4464
  const studioPath = process.env.MASTRA_STUDIO_PATH || path.join(__dirname, "studio");
4448
4465
  return studioPath;
4449
4466
  };
4467
+ var DEFAULT_CORS_ALLOW_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"];
4468
+ var DEFAULT_CORS_ALLOW_HEADERS = ["Content-Type", "Authorization", "x-mastra-client-type", "x-mastra-dev-playground"];
4469
+ var DEFAULT_CORS_EXPOSE_HEADERS = ["Content-Length", "X-Requested-With"];
4470
+ function getCorsConfig(serverCors, credentialsDefault) {
4471
+ const userCors = serverCors && typeof serverCors === "object" ? serverCors : void 0;
4472
+ const origin = userCors && "origin" in userCors && userCors.origin ? userCors.origin : credentialsDefault ? (requestOrigin) => requestOrigin || void 0 : "*";
4473
+ const credentials = userCors && "credentials" in userCors ? userCors.credentials : credentialsDefault;
4474
+ return {
4475
+ origin,
4476
+ allowMethods: DEFAULT_CORS_ALLOW_METHODS,
4477
+ credentials,
4478
+ maxAge: 3600,
4479
+ ...userCors,
4480
+ allowHeaders: [...DEFAULT_CORS_ALLOW_HEADERS, ...userCors?.allowHeaders ?? []],
4481
+ exposeHeaders: [...DEFAULT_CORS_EXPOSE_HEADERS, ...userCors?.exposeHeaders ?? []]
4482
+ };
4483
+ }
4484
+ function getRouteCorsConfig(apiRoutes, pathname, method) {
4485
+ const route = auth.findMatchingCustomRoute(pathname, method, apiRoutes)?.route;
4486
+ return route?.cors;
4487
+ }
4450
4488
  function getToolExports(tools$1) {
4451
4489
  try {
4452
4490
  return tools$1.reduce((acc, toolModule) => {
@@ -4533,37 +4571,25 @@ async function createHonoServer(mastra, options = {
4533
4571
  getToolset: (agentId) => {
4534
4572
  const agent = mastra.getAgentById(agentId);
4535
4573
  return agent?.browser;
4536
- }
4574
+ },
4575
+ apiPrefix
4537
4576
  });
4577
+ if (!browserStreamSetup) {
4578
+ app.get(
4579
+ `${apiPrefix}/agents/:agentId/browser/session`,
4580
+ (c) => c.json({ hasSession: false, screencastAvailable: false })
4581
+ );
4582
+ }
4538
4583
  if (server?.cors === false) {
4539
4584
  app.use("*", timeout.timeout(server?.timeout ?? 3 * 60 * 1e3));
4540
4585
  } else {
4541
4586
  const hasAuth = !!server?.auth;
4542
- let corsOrigin;
4543
- if (server?.cors && typeof server.cors === "object" && "origin" in server.cors && server.cors.origin) {
4544
- corsOrigin = server.cors.origin;
4545
- } else if (hasAuth) {
4546
- corsOrigin = (origin) => origin || void 0;
4547
- } else {
4548
- corsOrigin = "*";
4549
- }
4550
- const corsConfig = {
4551
- origin: corsOrigin,
4552
- allowMethods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
4553
- // Enable credentials for cookie-based auth (e.g., Better Auth sessions)
4554
- credentials: hasAuth ? true : false,
4555
- maxAge: 3600,
4556
- ...server?.cors,
4557
- allowHeaders: [
4558
- "Content-Type",
4559
- "Authorization",
4560
- "x-mastra-client-type",
4561
- "x-mastra-dev-playground",
4562
- ...server?.cors?.allowHeaders ?? []
4563
- ],
4564
- exposeHeaders: ["Content-Length", "X-Requested-With", ...server?.cors?.exposeHeaders ?? []]
4565
- };
4566
- app.use("*", timeout.timeout(server?.timeout ?? 3 * 60 * 1e3), cors.cors(corsConfig));
4587
+ app.use("*", timeout.timeout(server?.timeout ?? 3 * 60 * 1e3), async (c, next) => {
4588
+ const pathname = new URL(c.req.url).pathname;
4589
+ const method = c.req.method === "OPTIONS" ? c.req.header("Access-Control-Request-Method") ?? c.req.method : c.req.method;
4590
+ const routeCors = getRouteCorsConfig(processedRoutes, pathname, method);
4591
+ return cors.cors(routeCors ? getCorsConfig(routeCors, false) : getCorsConfig(server?.cors, hasAuth))(c, next);
4592
+ });
4567
4593
  }
4568
4594
  app.get(
4569
4595
  "/health",