@mastra/deployer 1.79.0-alpha.1 → 1.79.0-alpha.3

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.
Files changed (51) hide show
  1. package/dist/_types/@mastra_hono/dist/browser-stream/index.d.ts +54 -2
  2. package/dist/_types/@mastra_hono/dist/index.d.ts +1 -0
  3. package/dist/{analyze-CcyVW_jJ.cjs → analyze-CPVTLGuy.cjs} +168 -25
  4. package/dist/analyze-CPVTLGuy.cjs.map +1 -0
  5. package/dist/{analyze-BP0cLyWH.js → analyze-Dvzg7NFK.js} +165 -22
  6. package/dist/analyze-Dvzg7NFK.js.map +1 -0
  7. package/dist/build/analyze.cjs +1 -1
  8. package/dist/build/analyze.js +1 -1
  9. package/dist/build/fs-routing/discover.d.ts.map +1 -1
  10. package/dist/build/index.cjs +4 -4
  11. package/dist/build/index.js +4 -4
  12. package/dist/build/shared/extract-mastra-option.d.ts.map +1 -1
  13. package/dist/{build-DGJW5-aB.cjs → build-Bdncb817.cjs} +71 -9
  14. package/dist/build-Bdncb817.cjs.map +1 -0
  15. package/dist/{build-CNYwIKPG.js → build-C8gia-n5.js} +71 -8
  16. package/dist/build-C8gia-n5.js.map +1 -0
  17. package/dist/bundler/find-workspaces.d.ts +52 -0
  18. package/dist/bundler/find-workspaces.d.ts.map +1 -0
  19. package/dist/bundler/index.cjs +3 -3
  20. package/dist/bundler/index.js +3 -3
  21. package/dist/bundler/workspaceDependencies.d.ts.map +1 -1
  22. package/dist/{bundlerOptions-BtMp_x-T.cjs → bundlerOptions-BA9vxjZt.cjs} +51 -1
  23. package/dist/bundlerOptions-BA9vxjZt.cjs.map +1 -0
  24. package/dist/{bundlerOptions-ID9i-l8I.js → bundlerOptions-DpvO59QF.js} +49 -1
  25. package/dist/bundlerOptions-DpvO59QF.js.map +1 -0
  26. package/dist/docs/SKILL.md +1 -1
  27. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  28. package/dist/index.cjs +3 -3
  29. package/dist/index.js +3 -3
  30. package/dist/server/index.cjs +243 -4
  31. package/dist/server/index.cjs.map +1 -1
  32. package/dist/server/index.d.ts.map +1 -1
  33. package/dist/server/index.js +244 -5
  34. package/dist/server/index.js.map +1 -1
  35. package/dist/services/deps.d.ts +9 -0
  36. package/dist/services/deps.d.ts.map +1 -1
  37. package/dist/services/index.cjs +1 -1
  38. package/dist/services/index.js +1 -1
  39. package/dist/{services-D_V7afWX.cjs → services-BQNEW5XJ.cjs} +126 -1
  40. package/dist/services-BQNEW5XJ.cjs.map +1 -0
  41. package/dist/{services-DXqmEy8F.js → services-PUoAjxMD.js} +115 -2
  42. package/dist/services-PUoAjxMD.js.map +1 -0
  43. package/package.json +8 -9
  44. package/dist/analyze-BP0cLyWH.js.map +0 -1
  45. package/dist/analyze-CcyVW_jJ.cjs.map +0 -1
  46. package/dist/build-CNYwIKPG.js.map +0 -1
  47. package/dist/build-DGJW5-aB.cjs.map +0 -1
  48. package/dist/bundlerOptions-BtMp_x-T.cjs.map +0 -1
  49. package/dist/bundlerOptions-ID9i-l8I.js.map +0 -1
  50. package/dist/services-DXqmEy8F.js.map +0 -1
  51. package/dist/services-D_V7afWX.cjs.map +0 -1
@@ -1,5 +1,45 @@
1
+ import type { Mastra } from '@mastra/core/mastra';
1
2
  import type { BrowserStreamConfig, BrowserStreamResult } from '@mastra/server/browser-stream';
2
- import type { Env, Hono, Schema } from 'hono';
3
+ import type { Context, Env, Hono, Schema } from 'hono';
4
+ /**
5
+ * Allowed `Origin` values for browser WebSocket upgrades. Accepts the same shape
6
+ * as Hono's `cors.origin` option.
7
+ */
8
+ export type BrowserStreamOrigin = string | string[] | ((origin: string, c: Context) => Promise<string | undefined | null> | string | undefined | null);
9
+ /**
10
+ * Hono-specific browser stream configuration.
11
+ */
12
+ export interface HonoBrowserStreamConfig extends BrowserStreamConfig {
13
+ /**
14
+ * Mastra instance used to authenticate requests to the browser stream routes.
15
+ *
16
+ * Every route registered by {@link setupBrowserStream} — the WebSocket upgrade,
17
+ * the session probe, the close endpoint, and the upgrade-ticket endpoint — is
18
+ * gated by the server auth middleware. Without this, an unauthenticated caller
19
+ * could watch and drive an agent's browser. When the instance has no
20
+ * `server.auth` configured the middleware is a no-op.
21
+ */
22
+ mastra: Mastra;
23
+ /**
24
+ * Origin allowlist for the browser WebSocket upgrade.
25
+ *
26
+ * Browsers always send an `Origin` header on a WebSocket handshake and attach
27
+ * the session cookie to it, so without an allowlist a page on any origin could
28
+ * open a cookie-authenticated stream and drive the agent's browser. When this is
29
+ * set, an upgrade from an origin that isn't allowed is rejected with `403`.
30
+ *
31
+ * Values are matched the way Hono's `cors.origin` matches them: array entries
32
+ * literally, and a callback only approves an origin when it returns that same
33
+ * origin (or `'*'`). The server's own origin always passes, because a CORS
34
+ * allowlist names the *other* origins and never includes the server itself.
35
+ *
36
+ * Requests without an `Origin` header (non-browser clients) are not affected,
37
+ * and the check is skipped entirely when this is unset. The deployer passes the
38
+ * explicitly configured `server.cors.origin` here; its permissive default is
39
+ * left as-is so cross-origin Studio deployments keep working.
40
+ */
41
+ allowedOrigins?: BrowserStreamOrigin;
42
+ }
3
43
  /**
4
44
  * Set up WebSocket-based browser stream endpoint for real-time screencast viewing.
5
45
  *
@@ -9,6 +49,17 @@ import type { Env, Hono, Schema } from 'hono';
9
49
  * - Broadcasts frames to all connected viewers
10
50
  * - Stops screencast when last viewer disconnects
11
51
  *
52
+ * All routes are authenticated with the server's auth configuration. Browsers
53
+ * cannot attach an `Authorization` header to a WebSocket upgrade, so
54
+ * session-cookie providers authenticate from the upgrade request's cookies.
55
+ * Clients that authenticate with a header token instead request a short-lived,
56
+ * single-use ticket from `POST ${apiPrefix}/agents/:agentId/browser/stream-ticket`
57
+ * and pass it to the upgrade as `?ticket=`, which keeps the reusable credential
58
+ * out of the URL. Non-browser clients can pass the token as the `apiKey` query
59
+ * parameter — use a short-lived token, since a URL can be retained in proxy and
60
+ * access logs, and prefer the `Authorization` header on the HTTP routes where the
61
+ * client can set one.
62
+ *
12
63
  * **Note**: Requires `ws` package to be installed. If not available, returns null
13
64
  * and logs a warning. Browser streaming will be disabled but everything else works.
14
65
  *
@@ -24,6 +75,7 @@ import type { Env, Hono, Schema } from 'hono';
24
75
  *
25
76
  * const app = new Hono();
26
77
  * const browserStream = await setupBrowserStream(app, {
78
+ * mastra,
27
79
  * getToolset: (agentId) => browserToolsets.get(agentId),
28
80
  * });
29
81
  *
@@ -31,5 +83,5 @@ import type { Env, Hono, Schema } from 'hono';
31
83
  * browserStream?.injectWebSocket(server);
32
84
  * ```
33
85
  */
34
- export declare function setupBrowserStream<E extends Env, S extends Schema, B extends string>(app: Hono<E, S, B>, config: BrowserStreamConfig): Promise<BrowserStreamResult | null>;
86
+ export declare function setupBrowserStream<E extends Env, S extends Schema, B extends string>(app: Hono<E, S, B>, config: HonoBrowserStreamConfig): Promise<BrowserStreamResult | null>;
35
87
  //# sourceMappingURL=index.d.ts.map
@@ -8,6 +8,7 @@ import type { Context, HonoRequest, MiddlewareHandler } from 'hono';
8
8
  export { createAuthMiddleware } from './auth-middleware.js';
9
9
  export type { HonoAuthMiddlewareOptions } from './auth-middleware.js';
10
10
  export { setupBrowserStream } from './browser-stream/index.js';
11
+ export type { HonoBrowserStreamConfig } from './browser-stream/index.js';
11
12
  export type HonoVariables = {
12
13
  mastra: Mastra;
13
14
  requestContext: RequestContext;
@@ -1,6 +1,6 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-emK7D4bc.cjs");
2
2
  const require_utils = require("./utils-Bsr_sEcH.cjs");
3
- const require_services = require("./services-D_V7afWX.cjs");
3
+ const require_services = require("./services-BQNEW5XJ.cjs");
4
4
  const require_bundler = require("./bundler-CxslAqI_.cjs");
5
5
  let fs = require("fs");
6
6
  let fs_promises = require("fs/promises");
@@ -11,11 +11,13 @@ let _rollup_plugin_virtual = require("@rollup/plugin-virtual");
11
11
  _rollup_plugin_virtual = require_rolldown_runtime.__toESM(_rollup_plugin_virtual, 1);
12
12
  let empathic_package = require("empathic/package");
13
13
  empathic_package = require_rolldown_runtime.__toESM(empathic_package, 1);
14
+ let tinyglobby = require("tinyglobby");
14
15
  let _babel_core = require("@babel/core");
15
- let find_workspaces = require("find-workspaces");
16
16
  let fs_extra = require("fs-extra");
17
17
  let child_process = require("child_process");
18
18
  let url = require("url");
19
+ let yaml = require("yaml");
20
+ let os = require("os");
19
21
  let _rollup_plugin_commonjs = require("@rollup/plugin-commonjs");
20
22
  _rollup_plugin_commonjs = require_rolldown_runtime.__toESM(_rollup_plugin_commonjs, 1);
21
23
  let _rollup_plugin_json = require("@rollup/plugin-json");
@@ -123,12 +125,148 @@ var require_stack_trace_parser_cjs = /* @__PURE__ */ require_rolldown_runtime.__
123
125
  exports.parse = parse;
124
126
  }));
125
127
  //#endregion
126
- //#region src/bundler/workspaceDependencies.ts
128
+ //#region src/bundler/find-workspaces.ts
127
129
  var import_stack_trace_parser_cjs = /* @__PURE__ */ require_rolldown_runtime.__toESM(require_stack_trace_parser_cjs(), 1);
128
130
  /**
131
+ * Monorepo workspace discovery.
132
+ *
133
+ * Replaces the `find-workspaces` package with the same API, so that the
134
+ * production dependency tree no longer carries `fast-glob` → `micromatch` →
135
+ * `braces` (GHSA-vfj7-8cjw-p6xm, no patched release). Globbing goes through
136
+ * `tinyglobby`, which the deployer already uses for bundling.
137
+ *
138
+ * Root detection order matches `find-workspaces`: `lerna.json`, then
139
+ * `pnpm-workspace.yaml`, then `package.json` (`workspaces` array,
140
+ * `workspaces.packages`, or `bolt.workspaces`).
141
+ */
142
+ function createWorkspacesCache() {
143
+ return {
144
+ root: /* @__PURE__ */ new Map(),
145
+ workspaces: /* @__PURE__ */ new Map(),
146
+ clear() {
147
+ this.root.clear();
148
+ this.workspaces.clear();
149
+ }
150
+ };
151
+ }
152
+ /**
153
+ * Walk up from `dirname` until a directory declaring workspace globs is found.
154
+ * Returns `null` when none is found before `stopDir`.
155
+ */
156
+ function findWorkspacesRoot(dirname, options = {}) {
157
+ const dir = dirname ? (0, path.resolve)(dirname) : process.cwd();
158
+ const stopDir = options.stopDir ? (0, path.resolve)(options.stopDir) : (0, os.homedir)();
159
+ const cache = options.cache;
160
+ if (cache) {
161
+ for (const [key, value] of cache.root.entries()) if ((dir + path.sep).startsWith(key + path.sep)) return value;
162
+ }
163
+ return findRoot(dir, stopDir, cache);
164
+ }
165
+ /**
166
+ * List every workspace package under the root that contains `dirname`.
167
+ * Returns `null` when `dirname` is not inside a workspace.
168
+ */
169
+ async function findWorkspaces(dirname, options = {}) {
170
+ const root = findWorkspacesRoot(dirname, options);
171
+ if (!root) return null;
172
+ const cached = options.cache?.workspaces.get(root.location);
173
+ if (cached) return cached;
174
+ const manifests = await (0, tinyglobby.glob)(toManifestGlobs(root.globs), {
175
+ cwd: root.location,
176
+ absolute: true,
177
+ ignore: ["**/node_modules/**"]
178
+ });
179
+ const workspaces = [];
180
+ for (const manifest of manifests) {
181
+ const location = toPosix((0, path.dirname)(manifest));
182
+ if (location === root.location) continue;
183
+ const pkg = readJsonFile(location, "package.json");
184
+ if (isObject(pkg) && typeof pkg.name === "string") workspaces.push({
185
+ location,
186
+ package: pkg
187
+ });
188
+ }
189
+ options.cache?.workspaces.set(root.location, workspaces);
190
+ return workspaces;
191
+ }
192
+ /**
193
+ * Glob for each pattern's `package.json` instead of for the directory itself. A
194
+ * directory-only glob does not match a symlink to a directory, so a linked workspace
195
+ * package would be dropped and never packed into the build output. Matching the
196
+ * manifest inside it does, and is also how pnpm resolves its workspaces. Negated
197
+ * patterns are mapped the same way so they keep excluding whole packages.
198
+ */
199
+ function toManifestGlobs(globs) {
200
+ return globs.map((pattern) => {
201
+ const negated = pattern.startsWith("!");
202
+ const base = (negated ? pattern.slice(1) : pattern).replace(/[\\/]+$/, "");
203
+ return `${negated ? "!" : ""}${base}/package.json`;
204
+ });
205
+ }
206
+ function findRoot(dir, stopDir, cache) {
207
+ const memo = (value) => {
208
+ cache?.root.set(dir, value);
209
+ return value;
210
+ };
211
+ const globs = findGlobs(dir);
212
+ if (globs) return memo({
213
+ location: toPosix(dir),
214
+ globs
215
+ });
216
+ const next = (0, path.resolve)(dir, "..");
217
+ if (next === stopDir || next === dir) return memo(null);
218
+ return findRoot(next, stopDir, cache);
219
+ }
220
+ function findGlobs(dir) {
221
+ return resolveLernaGlobs(dir) ?? resolvePnpmGlobs(dir) ?? resolvePackageJsonGlobs(dir);
222
+ }
223
+ function resolveLernaGlobs(dir) {
224
+ const lernaJson = readJsonFile(dir, "lerna.json");
225
+ if (lernaJson === void 0) return null;
226
+ return isObject(lernaJson) && isStringArray(lernaJson.packages) ? lernaJson.packages : null;
227
+ }
228
+ function resolvePnpmGlobs(dir) {
229
+ const pnpmWorkspace = readYamlFile(dir, "pnpm-workspace.yaml");
230
+ if (pnpmWorkspace === void 0) return null;
231
+ return isObject(pnpmWorkspace) && isStringArray(pnpmWorkspace.packages) ? pnpmWorkspace.packages : ["**"];
232
+ }
233
+ function resolvePackageJsonGlobs(dir) {
234
+ const packageJson = readJsonFile(dir, "package.json");
235
+ if (!isObject(packageJson)) return null;
236
+ if (isStringArray(packageJson.workspaces)) return packageJson.workspaces;
237
+ if (isObject(packageJson.workspaces) && isStringArray(packageJson.workspaces.packages)) return packageJson.workspaces.packages;
238
+ if (isObject(packageJson.bolt) && isStringArray(packageJson.bolt.workspaces)) return packageJson.bolt.workspaces;
239
+ return null;
240
+ }
241
+ function readJsonFile(dir, file) {
242
+ try {
243
+ return JSON.parse((0, fs.readFileSync)((0, path.join)(dir, file), "utf8"));
244
+ } catch {
245
+ return;
246
+ }
247
+ }
248
+ function readYamlFile(dir, file) {
249
+ try {
250
+ return (0, yaml.parse)((0, fs.readFileSync)((0, path.join)(dir, file), "utf8"));
251
+ } catch {
252
+ return;
253
+ }
254
+ }
255
+ function toPosix(path$1) {
256
+ return path$1.split(path.sep).join(path.posix.sep);
257
+ }
258
+ function isObject(value) {
259
+ return !!value && typeof value === "object" && !Array.isArray(value);
260
+ }
261
+ function isStringArray(value) {
262
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
263
+ }
264
+ //#endregion
265
+ //#region src/bundler/workspaceDependencies.ts
266
+ /**
129
267
  * Create a shared cache for find-workspaces
130
268
  */
131
- const workspacesCache = (0, find_workspaces.createWorkspacesCache)();
269
+ const workspacesCache = createWorkspacesCache();
132
270
  /**
133
271
  * A utility function around find-workspaces to get information about:
134
272
  * - Which workspace packages are available in the project
@@ -143,7 +281,7 @@ const workspacesCache = (0, find_workspaces.createWorkspacesCache)();
143
281
  async function getWorkspaceInformation({ dir = process.cwd(), mastraEntryFile }) {
144
282
  const closestPkgJson = empathic_package.up({ cwd: (0, path.dirname)(mastraEntryFile) });
145
283
  const location = closestPkgJson ? (0, path.dirname)(require_utils.slash(closestPkgJson)) : require_utils.slash(process.cwd());
146
- const workspaces = await (0, find_workspaces.findWorkspaces)(dir, { cache: workspacesCache });
284
+ const workspaces = await findWorkspaces(dir, { cache: workspacesCache });
147
285
  const _workspaceMap = new Map(workspaces?.map((workspace) => [workspace.package.name, {
148
286
  location: workspace.location,
149
287
  dependencies: workspace.package.dependencies,
@@ -151,7 +289,7 @@ async function getWorkspaceInformation({ dir = process.cwd(), mastraEntryFile })
151
289
  exports: workspace.package.exports
152
290
  }]) ?? []);
153
291
  const isWorkspacePackage = (workspaces ?? []).some((ws) => ws.location === location);
154
- const workspaceRoot = isWorkspacePackage ? (0, find_workspaces.findWorkspacesRoot)(dir, { cache: workspacesCache })?.location : void 0;
292
+ const workspaceRoot = isWorkspacePackage ? findWorkspacesRoot(dir, { cache: workspacesCache })?.location : void 0;
155
293
  return {
156
294
  workspaceMap: isWorkspacePackage ? _workspaceMap : /* @__PURE__ */ new Map(),
157
295
  workspaceRoot,
@@ -172,7 +310,7 @@ const collectTransitiveWorkspaceDependencies = async ({ workspaceMap, initialDep
172
310
  if (!pkgName || usedWorkspacePackages.has(pkgName)) continue;
173
311
  const dep = workspaceMap.get(pkgName);
174
312
  if (!dep) continue;
175
- const root = (0, find_workspaces.findWorkspacesRoot)();
313
+ const root = findWorkspacesRoot();
176
314
  if (!root) throw new Error("Could not find workspace root");
177
315
  const depsService = new require_services.DepsService(root.location);
178
316
  depsService.__setLogger(logger);
@@ -180,7 +318,7 @@ const collectTransitiveWorkspaceDependencies = async ({ workspaceMap, initialDep
180
318
  const sanitizedName = slugify(pkgName);
181
319
  resolutions[pkgName] = depsService.getWorkspaceDependencyPath({
182
320
  pkgName: sanitizedName,
183
- version: dep.version
321
+ version: dep.version ?? "0.0.0"
184
322
  });
185
323
  usedWorkspacePackages.add(pkgName);
186
324
  for (const [depName, _depVersion] of Object.entries(dep?.dependencies ?? {})) if (!usedWorkspacePackages.has(depName) && workspaceMap.has(depName)) queue.push(depName);
@@ -195,7 +333,7 @@ const collectTransitiveWorkspaceDependencies = async ({ workspaceMap, initialDep
195
333
  * Creates TGZ packages for workspace dependencies in the workspace-module directory
196
334
  */
197
335
  const packWorkspaceDependencies = async ({ workspaceMap, usedWorkspacePackages, bundleOutputDir, logger }) => {
198
- const root = (0, find_workspaces.findWorkspacesRoot)();
336
+ const root = findWorkspacesRoot();
199
337
  if (!root) throw new Error("Could not find workspace root");
200
338
  const depsService = new require_services.DepsService(root.location);
201
339
  depsService.__setLogger(logger);
@@ -206,21 +344,26 @@ const packWorkspaceDependencies = async ({ workspaceMap, usedWorkspacePackages,
206
344
  logger.info("Packaging workspace dependencies", { count: usedWorkspacePackages.size });
207
345
  const batchSize = 5;
208
346
  const packages = Array.from(usedWorkspacePackages.values());
209
- for (let i = 0; i < packages.length; i += batchSize) {
210
- const batch = packages.slice(i, i + batchSize);
211
- logger.info(`Packaging batch ${Math.floor(i / batchSize) + 1}/${Math.ceil(packages.length / batchSize)}: ${batch.join(", ")}`);
212
- await Promise.all(batch.map(async (pkgName) => {
213
- const dep = workspaceMap.get(pkgName);
214
- const sanitizedName = slugify(pkgName);
215
- if (!dep) return;
216
- await depsService.pack({
217
- dir: dep.location,
218
- destination: workspaceDirPath,
219
- sanitizedName,
220
- version: dep.version
221
- });
222
- }));
223
- }
347
+ await require_services.withPlaceholderVersions(packages.flatMap((pkgName) => {
348
+ const location = workspaceMap.get(pkgName)?.location;
349
+ return location ? [location] : [];
350
+ }), async () => {
351
+ for (let i = 0; i < packages.length; i += batchSize) {
352
+ const batch = packages.slice(i, i + batchSize);
353
+ logger.info(`Packaging batch ${Math.floor(i / batchSize) + 1}/${Math.ceil(packages.length / batchSize)}: ${batch.join(", ")}`);
354
+ await Promise.all(batch.map(async (pkgName) => {
355
+ const dep = workspaceMap.get(pkgName);
356
+ const sanitizedName = slugify(pkgName);
357
+ if (!dep) return;
358
+ await depsService.pack({
359
+ dir: dep.location,
360
+ destination: workspaceDirPath,
361
+ sanitizedName,
362
+ version: dep.version ?? "0.0.0"
363
+ });
364
+ }));
365
+ }
366
+ });
224
367
  logger.info("Successfully packaged workspace dependencies", { count: usedWorkspacePackages.size });
225
368
  }
226
369
  };
@@ -1493,4 +1636,4 @@ Object.defineProperty(exports, "packWorkspaceDependencies", {
1493
1636
  }
1494
1637
  });
1495
1638
 
1496
- //# sourceMappingURL=analyze-CcyVW_jJ.cjs.map
1639
+ //# sourceMappingURL=analyze-CPVTLGuy.cjs.map