@mastra/platform-workspace 1.7.0 → 1.8.0

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.
@@ -0,0 +1,39 @@
1
+ import type { PublicSchema } from '@mastra/core/schema';
2
+ import { FactorySandbox } from '@mastra/core/workspace';
3
+ import type { FactorySandboxBuilds, FactorySandboxContext } from '@mastra/core/workspace';
4
+ import type { PlatformRepoTemplateResolver } from './repo-template.js';
5
+ import { PlatformSandbox } from './sandbox.js';
6
+ import type { PlatformSandboxOptions } from './sandbox.js';
7
+ /** User-tunable settings of a platform factory sandbox. Every field is optional; absent means the provider default. */
8
+ export interface PlatformFactorySandboxSettings extends Record<string, unknown> {
9
+ /** vCPUs for the sandbox template. Part of the template identity. */
10
+ cpuCount?: number;
11
+ /** Memory in MB for the sandbox template. Part of the template identity. */
12
+ memoryMb?: number;
13
+ /** Minutes idle before the sandbox pauses. Runtime only. */
14
+ idleTimeoutMinutes?: number;
15
+ }
16
+ export interface PlatformFactorySandboxOptions extends Omit<PlatformSandboxOptions, 'id' | 'sandboxId' | 'sessionId' | 'template'> {
17
+ /** Options for the environment's repo template. */
18
+ template?: {
19
+ /** Build-only environment, excluded from template identity and runtime sandboxes. */
20
+ buildEnv?: Record<string, string>;
21
+ };
22
+ /** Provider-side defaults used when a setting is unset. Never stored by factory. */
23
+ defaults?: Partial<PlatformFactorySandboxSettings>;
24
+ }
25
+ /**
26
+ * The platform host contract for factory: every session sandbox is a
27
+ * {@link PlatformSandbox} whose template is {@link createRepoTemplate} over
28
+ * the session's repositories, sized by the factory's environment settings.
29
+ */
30
+ export declare class PlatformFactorySandbox extends FactorySandbox<PlatformFactorySandboxSettings> {
31
+ #private;
32
+ readonly provider = "platform";
33
+ readonly settings: PublicSchema<PlatformFactorySandboxSettings>;
34
+ readonly builds: FactorySandboxBuilds<PlatformFactorySandboxSettings>;
35
+ constructor(options?: PlatformFactorySandboxOptions);
36
+ template(ctx: FactorySandboxContext, settings: PlatformFactorySandboxSettings): PlatformRepoTemplateResolver | undefined;
37
+ create(ctx: FactorySandboxContext, settings: PlatformFactorySandboxSettings): PlatformSandbox;
38
+ }
39
+ //# sourceMappingURL=factory-sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory-sandbox.d.ts","sourceRoot":"","sources":["../src/factory-sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAIV,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAG3D,uHAAuH;AACvH,MAAM,WAAW,8BAA+B,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC7E,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAwDD,MAAM,WAAW,6BAA8B,SAAQ,IAAI,CACzD,sBAAsB,EACtB,IAAI,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,CAC9C;IACC,mDAAmD;IACnD,QAAQ,CAAC,EAAE;QACT,qFAAqF;QACrF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACnC,CAAC;IACF,oFAAoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAC,8BAA8B,CAAC,CAAC;CACpD;AAED;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,cAAc,CAAC,8BAA8B,CAAC;;IACxF,QAAQ,CAAC,QAAQ,cAAc;IAC/B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,8BAA8B,CAAC,CAAC;IAehE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC,8BAA8B,CAAC,CAGnE;IAEF,YAAY,OAAO,GAAE,6BAAkC,EAOtD;IAED,QAAQ,CACN,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,EAAE,8BAA8B,GACvC,4BAA4B,GAAG,SAAS,CAQ1C;IAED,MAAM,CAAC,GAAG,EAAE,qBAAqB,EAAE,QAAQ,EAAE,8BAA8B,GAAG,eAAe,CAiB5F;CA4CF"}
package/dist/index.cjs CHANGED
@@ -25,9 +25,9 @@ let buffer = require("buffer");
25
25
  let path = require("path");
26
26
  path = __toESM(path, 1);
27
27
  let _mastra_core_workspace = require("@mastra/core/workspace");
28
+ let crypto = require("crypto");
28
29
  let e2b = require("e2b");
29
30
  let child_process = require("child_process");
30
- let crypto = require("crypto");
31
31
  let util = require("util");
32
32
  //#region src/client.ts
33
33
  const DEFAULT_PROXY_URL = "https://workspaces.mastra.ai";
@@ -1434,7 +1434,12 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
1434
1434
  sessionId: this._client.sessionId,
1435
1435
  mode,
1436
1436
  totalMs: Date.now() - startedAt,
1437
- requestMs
1437
+ requestMs,
1438
+ ...mode === "provision" && this._templateDefinition ? {
1439
+ templateHash: templateHash(this._templateDefinition),
1440
+ templateBoot: this.templatePending ? "pending" : "exact",
1441
+ ...this.templatePending ? { pendingTemplateId: this.templatePending.templateId } : {}
1442
+ } : {}
1438
1443
  });
1439
1444
  }
1440
1445
  /**
@@ -2021,6 +2026,17 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
2021
2026
  return defaultInstructions;
2022
2027
  }
2023
2028
  };
2029
+ /**
2030
+ * Diagnostic fingerprint of the serialized template a sandbox was provisioned
2031
+ * with: the same definition (repositories, pinned heads, setup commands,
2032
+ * resources) hashes the same on warm and cold boots. `family` is excluded, as
2033
+ * in the server's exact-content identity. Not the server's cache digest, which
2034
+ * also normalizes resources.
2035
+ */
2036
+ function templateHash(definition) {
2037
+ const { family: _family, ...content } = definition;
2038
+ return (0, crypto.createHash)("sha256").update(JSON.stringify(content)).digest("hex").slice(0, 16);
2039
+ }
2024
2040
  //#endregion
2025
2041
  //#region ../../packages/_internals/workspace/dist/index.js
2026
2042
  /** Directory, relative to the template's build cwd, that holds every marker below. */
@@ -2474,6 +2490,157 @@ const platformFilesystemProvider = {
2474
2490
  createFilesystem: (config) => new PlatformFilesystem(config)
2475
2491
  };
2476
2492
  //#endregion
2493
+ //#region src/factory-sandbox.ts
2494
+ /** Applied when neither the environment setting nor a host default is set. */
2495
+ const DEFAULT_SETTINGS = {
2496
+ cpuCount: 2,
2497
+ memoryMb: 1024,
2498
+ idleTimeoutMinutes: 5
2499
+ };
2500
+ const SETTINGS_SCHEMA = {
2501
+ type: "object",
2502
+ properties: {
2503
+ cpuCount: {
2504
+ type: "integer",
2505
+ title: "CPU",
2506
+ description: "vCPUs for the sandbox template",
2507
+ default: DEFAULT_SETTINGS.cpuCount,
2508
+ minimum: 1,
2509
+ maximum: 64
2510
+ },
2511
+ memoryMb: {
2512
+ type: "integer",
2513
+ title: "Memory (MB)",
2514
+ description: "Memory in MB for the sandbox template",
2515
+ default: DEFAULT_SETTINGS.memoryMb,
2516
+ minimum: 512,
2517
+ maximum: 65536
2518
+ },
2519
+ idleTimeoutMinutes: {
2520
+ type: "integer",
2521
+ title: "Idle timeout (minutes)",
2522
+ description: "Minutes idle before the sandbox pauses",
2523
+ default: DEFAULT_SETTINGS.idleTimeoutMinutes,
2524
+ minimum: 1,
2525
+ maximum: 1440
2526
+ }
2527
+ },
2528
+ additionalProperties: false
2529
+ };
2530
+ /**
2531
+ * The settings schema with the provider's effective defaults as `default`:
2532
+ * the built-in values, overridden by the host's `idleTimeoutMinutes` option and
2533
+ * then its `defaults` option. The schema
2534
+ * is what clients show as placeholders, so it must match what the provider
2535
+ * applies when a setting is unset.
2536
+ */
2537
+ function settingsSchema(defaults) {
2538
+ const effective = {
2539
+ ...DEFAULT_SETTINGS,
2540
+ ...defaults
2541
+ };
2542
+ const properties = Object.fromEntries(Object.entries(SETTINGS_SCHEMA.properties).map(([key, property]) => [key, {
2543
+ ...property,
2544
+ default: effective[key]
2545
+ }]));
2546
+ return {
2547
+ ...SETTINGS_SCHEMA,
2548
+ properties
2549
+ };
2550
+ }
2551
+ /**
2552
+ * The platform host contract for factory: every session sandbox is a
2553
+ * {@link PlatformSandbox} whose template is {@link createRepoTemplate} over
2554
+ * the session's repositories, sized by the factory's environment settings.
2555
+ */
2556
+ var PlatformFactorySandbox = class extends _mastra_core_workspace.FactorySandbox {
2557
+ provider = "platform";
2558
+ settings;
2559
+ #options;
2560
+ /**
2561
+ * Builders by template id from this process's `builds.start` calls. Platform
2562
+ * has no build status endpoint; re-calling the same builder's idempotent
2563
+ * `build()` is the status poll. After a restart earlier builds read as
2564
+ * `unknown`.
2565
+ *
2566
+ * TODO: once the platform API exposes build status and build history, read
2567
+ * `get` from the API instead of this in-memory cache and add `builds.list`.
2568
+ */
2569
+ #builders = /* @__PURE__ */ new Map();
2570
+ builds = {
2571
+ start: (ctx, settings) => this.#startBuild(ctx, settings),
2572
+ get: (ctx, settings, buildId) => this.#getBuild(ctx, settings, buildId)
2573
+ };
2574
+ constructor(options = {}) {
2575
+ super();
2576
+ this.#options = options;
2577
+ this.settings = settingsSchema({
2578
+ ...options.idleTimeoutMinutes !== void 0 ? { idleTimeoutMinutes: options.idleTimeoutMinutes } : {},
2579
+ ...options.defaults
2580
+ });
2581
+ }
2582
+ template(ctx, settings) {
2583
+ const { defaults, template } = this.#options;
2584
+ return createRepoTemplate({
2585
+ ...ctx,
2586
+ ...template?.buildEnv ? { buildEnv: template.buildEnv } : {},
2587
+ cpuCount: settings.cpuCount ?? defaults?.cpuCount ?? DEFAULT_SETTINGS.cpuCount,
2588
+ memoryMB: settings.memoryMb ?? defaults?.memoryMb ?? DEFAULT_SETTINGS.memoryMb
2589
+ });
2590
+ }
2591
+ create(ctx, settings) {
2592
+ const { defaults, template: _template, ...options } = this.#options;
2593
+ return new PlatformSandbox({
2594
+ ...options,
2595
+ id: ctx.sessionId,
2596
+ sessionId: ctx.sessionId,
2597
+ sandboxId: ctx.sandboxId,
2598
+ template: this.template(ctx, settings),
2599
+ ...ctx.workingDirectory ? { workingDirectory: ctx.workingDirectory } : {},
2600
+ idleTimeoutMinutes: settings.idleTimeoutMinutes ?? defaults?.idleTimeoutMinutes ?? options.idleTimeoutMinutes ?? DEFAULT_SETTINGS.idleTimeoutMinutes
2601
+ });
2602
+ }
2603
+ async #startBuild(ctx, settings) {
2604
+ const builder = await this.#resolveBuilder(ctx, settings);
2605
+ const result = await builder.build(this.#buildOptions());
2606
+ this.#builders.set(result.templateId, builder);
2607
+ return {
2608
+ buildId: result.templateId,
2609
+ templateId: result.templateId,
2610
+ status: mapStatus(result.status)
2611
+ };
2612
+ }
2613
+ async #getBuild(_ctx, _settings, buildId) {
2614
+ const builder = this.#builders.get(buildId);
2615
+ if (!builder) return {
2616
+ buildId,
2617
+ status: "unknown",
2618
+ error: `Build ${buildId} was not started by this process; its status cannot be read.`
2619
+ };
2620
+ return toBuild(await builder.build(this.#buildOptions()));
2621
+ }
2622
+ async #resolveBuilder(ctx, settings) {
2623
+ const builder = await this.template(ctx, settings)?.();
2624
+ if (!builder) throw new Error("PlatformFactorySandbox.builds: the session context yields no template to build");
2625
+ return builder;
2626
+ }
2627
+ #buildOptions() {
2628
+ const { defaults: _defaults, template: _template, env: _env, ...options } = this.#options;
2629
+ return options;
2630
+ }
2631
+ };
2632
+ function mapStatus(status) {
2633
+ return status;
2634
+ }
2635
+ function toBuild(result) {
2636
+ return {
2637
+ buildId: result.templateId,
2638
+ templateId: result.templateId,
2639
+ status: mapStatus(result.status),
2640
+ ...result.error ? { error: result.error } : {}
2641
+ };
2642
+ }
2643
+ //#endregion
2477
2644
  //#region src/address-registry.ts
2478
2645
  /**
2479
2646
  * Concrete in-process {@link SandboxAddressRegistry}. Backed by a `Map`; no
@@ -2510,6 +2677,7 @@ var InProcessSandboxAddressRegistry = class {
2510
2677
  exports.InProcessSandboxAddressRegistry = InProcessSandboxAddressRegistry;
2511
2678
  exports.PlatformApiError = PlatformApiError;
2512
2679
  exports.PlatformClient = PlatformClient;
2680
+ exports.PlatformFactorySandbox = PlatformFactorySandbox;
2513
2681
  exports.PlatformFilesystem = PlatformFilesystem;
2514
2682
  exports.PlatformSandbox = PlatformSandbox;
2515
2683
  exports.PrivateNetExecHttpError = PrivateNetExecHttpError;