@mastra/code-sdk 1.12.0-alpha.4 → 1.12.0-alpha.6

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.
@@ -30,7 +30,8 @@ export declare function getCurrentVersion(): string;
30
30
  export declare function fetchLatestVersion(): Promise<string | null>;
31
31
  /**
32
32
  * Simple semver comparison: returns true if `latest` is newer than `current`.
33
- * Handles standard x.y.z versions. Ignores pre-release tags.
33
+ * Handles standard x.y.z versions. Pre-release tags only matter against the
34
+ * matching release; two pre-releases of the same version compare equal.
34
35
  */
35
36
  export declare function isNewerVersion(current: string, latest: string): boolean;
36
37
  /**
@@ -64,15 +65,35 @@ export declare function locateOwnInstall(): {
64
65
  dir: string;
65
66
  version: string | null;
66
67
  } | null;
68
+ /**
69
+ * Result of an update attempt. `message` is a ready-made sentence; the other
70
+ * fields let callers lay the result out themselves.
71
+ */
67
72
  export type UpdateOutcome = {
68
73
  status: 'updated';
69
74
  message: string;
75
+ /** The package manager or tool that installed the update. */
76
+ via: string;
70
77
  } | {
71
78
  status: 'unchanged';
72
79
  message: string;
80
+ /** Command the user can run to update the install they're running. */
81
+ command: string;
82
+ /** Where the running install lives, when known. */
83
+ installDir?: string;
84
+ /** Version still on disk after the update ran, when the update ran at all. */
85
+ runningVersion?: string;
86
+ /** Tool that ran the update (when it ran but didn't change the running install). */
87
+ ranWith?: string;
88
+ /** Tool that owns the install when we only suggest its command (e.g. Homebrew). */
89
+ managedBy?: string;
73
90
  } | {
74
91
  status: 'failed';
75
92
  message: string;
93
+ /** Command the user can run instead, when there is one. */
94
+ command?: string;
95
+ /** Why it failed: the tail of the package manager's stderr, or our own reason. */
96
+ details?: string;
76
97
  };
77
98
  /**
78
99
  * Decide what to tell the user after {@link runUpdate}: `updated` when the
@@ -90,12 +111,41 @@ export declare function resolveUpdateOutcome(opts: {
90
111
  } | null;
91
112
  /** Overrides the suggested manual command, e.g. when the update was delegated to the owning tool. */
92
113
  manualCommand?: string;
114
+ /** Tool that ran the update when it wasn't `pm`, e.g. vite-plus. */
115
+ via?: string;
93
116
  }): UpdateOutcome;
94
117
  /**
95
- * Update mastracode and verify the result: delegates to the tool that owns the
96
- * running install when we recognize it, skips the install when it isn't
97
- * managed by `pm`, otherwise runs the package manager. Every executed update
98
- * is verified against the on-disk version.
118
+ * What an update will do for the running install: run an install (with the
119
+ * tool and command it will use), or nothing, with the result to show instead.
120
+ */
121
+ export type UpdatePlan = {
122
+ willInstall: true;
123
+ /** The package manager or tool that will run the install. */
124
+ via: string;
125
+ /** The install command, as the user would type it. */
126
+ command: string;
127
+ exec: {
128
+ cmd: string;
129
+ args: string[];
130
+ };
131
+ } | {
132
+ willInstall: false;
133
+ outcome: Extract<UpdateOutcome, {
134
+ status: 'unchanged' | 'failed';
135
+ }>;
136
+ };
137
+ /**
138
+ * Decide how to update the running install, without changing anything:
139
+ * delegate to the tool that owns it when we recognize it, only suggest a
140
+ * command when that tool can't be run for the user (Homebrew) or `pm` doesn't
141
+ * manage it, otherwise run `pm`. {@link performUpdate} carries out this plan,
142
+ * so callers can show what will happen before it starts.
143
+ */
144
+ export declare function planUpdate(pm: PackageManager, targetVersion: string): Promise<UpdatePlan>;
145
+ /**
146
+ * Update mastracode following {@link planUpdate} (pass a plan already shown to
147
+ * the user, or let this make one), then verify the result against the version
148
+ * on disk.
99
149
  */
100
- export declare function performUpdate(pm: PackageManager, targetVersion: string): Promise<UpdateOutcome>;
150
+ export declare function performUpdate(pm: PackageManager, targetVersion: string, plan?: UpdatePlan): Promise<UpdateOutcome>;
101
151
  //# sourceMappingURL=update-check.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../../src/utils/update-check.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAW7D;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,cAAc,CAAC,CA+CpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAY9E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAS1C;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcjE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAevE;AAKD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAe5E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiD/E;AAED,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAE1F;AA0CD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CA6BjF;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,EAAE,EAAE,cAAc,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACxD,qGAAqG;IACrG,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,aAAa,CAsBhB;AAuDD;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAoCrG"}
1
+ {"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../../src/utils/update-check.ts"],"names":[],"mappings":"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"}
@@ -106,9 +106,11 @@ async function fetchLatestVersion() {
106
106
  return null;
107
107
  }
108
108
  }
109
+ const isPrerelease = (v) => v.includes("-");
109
110
  /**
110
111
  * Simple semver comparison: returns true if `latest` is newer than `current`.
111
- * Handles standard x.y.z versions. Ignores pre-release tags.
112
+ * Handles standard x.y.z versions. Pre-release tags only matter against the
113
+ * matching release; two pre-releases of the same version compare equal.
112
114
  */
113
115
  function isNewerVersion(current, latest) {
114
116
  const parse = (v) => v.replace(/^v/, "").split("-")[0].split(".").map((s) => {
@@ -119,7 +121,8 @@ function isNewerVersion(current, latest) {
119
121
  const [lMajor = 0, lMinor = 0, lPatch = 0] = parse(latest);
120
122
  if (lMajor !== cMajor) return lMajor > cMajor;
121
123
  if (lMinor !== cMinor) return lMinor > cMinor;
122
- return lPatch > cPatch;
124
+ if (lPatch !== cPatch) return lPatch > cPatch;
125
+ return isPrerelease(current) && !isPrerelease(latest);
123
126
  }
124
127
  /** Max entries to show in the changelog summary. */
125
128
  const MAX_CHANGELOG_ENTRIES = 20;
@@ -274,22 +277,30 @@ function locateOwnInstall() {
274
277
  function resolveUpdateOutcome(opts) {
275
278
  const { pm, targetVersion, result, install } = opts;
276
279
  const cmd = opts.manualCommand ?? getInstallCommand(pm, targetVersion);
280
+ const via = opts.via ?? pm;
277
281
  if (!result.ok) {
278
- const details = formatUpdaterError(result.stderr);
282
+ const details = formatUpdaterError(result.stderr) ?? void 0;
279
283
  let message = `Auto-update failed. Run \`${cmd}\` manually.`;
280
284
  if (details) message += `\n\n${details}`;
281
285
  return {
282
286
  status: "failed",
283
- message
287
+ message,
288
+ command: cmd,
289
+ ...details ? { details } : {}
284
290
  };
285
291
  }
286
292
  if (install?.version != null && install.version !== targetVersion) return {
287
293
  status: "unchanged",
288
- message: opts.manualCommand ? `The update ran, but the Mastra Code you are running (at ${install.dir}) is still v${install.version}. Try \`${cmd}\` manually.` : `The update installed, but the Mastra Code you are running (at ${install.dir}) is still v${install.version} — it looks like it is managed by another tool. Update it with that tool, or try \`${cmd}\`.`
294
+ message: opts.manualCommand ? `The update ran, but the Mastra Code you are running (at ${install.dir}) is still v${install.version}. Try \`${cmd}\` manually.` : `The update installed, but the Mastra Code you are running (at ${install.dir}) is still v${install.version} — it looks like it is managed by another tool. Update it with that tool, or try \`${cmd}\`.`,
295
+ command: cmd,
296
+ installDir: install.dir,
297
+ runningVersion: install.version,
298
+ ranWith: via
289
299
  };
290
300
  return {
291
301
  status: "updated",
292
- message: `Updated to v${targetVersion}. Please restart Mastra Code.`
302
+ message: `Updated to v${targetVersion}. Please restart Mastra Code.`,
303
+ via
293
304
  };
294
305
  }
295
306
  /** Global node_modules directory the package manager installs into, or null when unknown. */
@@ -341,43 +352,81 @@ function findInstallOwner(dir, version) {
341
352
  return null;
342
353
  }
343
354
  /**
344
- * Update mastracode and verify the result: delegates to the tool that owns the
345
- * running install when we recognize it, skips the install when it isn't
346
- * managed by `pm`, otherwise runs the package manager. Every executed update
347
- * is verified against the on-disk version.
355
+ * Decide how to update the running install, without changing anything:
356
+ * delegate to the tool that owns it when we recognize it, only suggest a
357
+ * command when that tool can't be run for the user (Homebrew) or `pm` doesn't
358
+ * manage it, otherwise run `pm`. {@link performUpdate} carries out this plan,
359
+ * so callers can show what will happen before it starts.
348
360
  */
349
- async function performUpdate(pm, targetVersion) {
361
+ async function planUpdate(pm, targetVersion) {
350
362
  if (!/^[\w.+-]+$/.test(targetVersion)) return {
351
- status: "failed",
352
- message: `Auto-update aborted: unexpected version "${targetVersion}".`
363
+ willInstall: false,
364
+ outcome: {
365
+ status: "failed",
366
+ message: `Auto-update aborted: unexpected version "${targetVersion}".`,
367
+ details: `The npm registry returned an unexpected version: "${targetVersion}".`
368
+ }
353
369
  };
354
370
  const install = locateOwnInstall();
355
371
  const owner = install ? findInstallOwner(install.dir, targetVersion) : null;
356
372
  if (owner) {
357
373
  if (!owner.exec) return {
358
- status: "unchanged",
359
- message: `Your Mastra Code install (at ${install.dir}) is managed by ${owner.name}. Update it with \`${owner.command}\`.`
374
+ willInstall: false,
375
+ outcome: {
376
+ status: "unchanged",
377
+ message: `Your Mastra Code install (at ${install.dir}) is managed by ${owner.name}. Update it with \`${owner.command}\`.`,
378
+ command: owner.command,
379
+ installDir: install.dir,
380
+ managedBy: owner.name
381
+ }
382
+ };
383
+ return {
384
+ willInstall: true,
385
+ via: owner.name,
386
+ command: owner.command,
387
+ exec: owner.exec
360
388
  };
361
- return resolveUpdateOutcome({
362
- pm,
363
- targetVersion,
364
- result: await execUpdate(owner.exec.cmd, owner.exec.args),
365
- install: locateOwnInstall(),
366
- manualCommand: owner.command
367
- });
368
389
  }
390
+ const command = getInstallCommand(pm, targetVersion);
369
391
  if (!await isOwnInstallManagedBy(pm, install)) return {
370
- status: "unchanged",
371
- message: `Your Mastra Code install (at ${install.dir}) is not managed by ${pm} — it looks like it was installed by another tool. Update it with that tool, or try \`${getInstallCommand(pm, targetVersion)}\`.`
392
+ willInstall: false,
393
+ outcome: {
394
+ status: "unchanged",
395
+ message: `Your Mastra Code install (at ${install.dir}) is not managed by ${pm} — it looks like it was installed by another tool. Update it with that tool, or try \`${command}\`.`,
396
+ command,
397
+ installDir: install.dir
398
+ }
372
399
  };
400
+ return {
401
+ willInstall: true,
402
+ via: pm,
403
+ command,
404
+ exec: {
405
+ cmd: pm,
406
+ args: buildInstallArgs(pm, targetVersion)
407
+ }
408
+ };
409
+ }
410
+ /**
411
+ * Update mastracode following {@link planUpdate} (pass a plan already shown to
412
+ * the user, or let this make one), then verify the result against the version
413
+ * on disk.
414
+ */
415
+ async function performUpdate(pm, targetVersion, plan) {
416
+ plan ??= await planUpdate(pm, targetVersion);
417
+ if (!plan.willInstall) return plan.outcome;
373
418
  return resolveUpdateOutcome({
374
419
  pm,
375
420
  targetVersion,
376
- result: await runUpdate(pm, targetVersion),
377
- install: locateOwnInstall()
421
+ result: await execUpdate(plan.exec.cmd, plan.exec.args),
422
+ install: locateOwnInstall(),
423
+ ...plan.via === pm ? {} : {
424
+ manualCommand: plan.command,
425
+ via: plan.via
426
+ }
378
427
  });
379
428
  }
380
429
  //#endregion
381
- export { detectPackageManager, fetchChangelog, fetchLatestVersion, getCurrentVersion, getInstallCommand, isNewerVersion, locateOwnInstall, parseChangelog, performUpdate, resolveUpdateOutcome, runUpdate };
430
+ export { detectPackageManager, fetchChangelog, fetchLatestVersion, getCurrentVersion, getInstallCommand, isNewerVersion, locateOwnInstall, parseChangelog, performUpdate, planUpdate, resolveUpdateOutcome, runUpdate };
382
431
 
383
432
  //# sourceMappingURL=update-check.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"update-check.js","names":[],"sources":["../../src/utils/update-check.ts"],"sourcesContent":["/**\n * Check for newer versions of mastracode on npm.\n */\n\nimport { execFile } from 'node:child_process';\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\ndeclare const MASTRACODE_VERSION: string | undefined;\n\nconst PACKAGE_NAME = 'mastracode';\nconst NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;\n\n/** Timeout for the npm registry fetch (ms). */\nconst FETCH_TIMEOUT_MS = 5_000;\n\n// Package managers and vp are .cmd shims on Windows; execFile can't spawn those without a shell (EINVAL).\nconst USE_SHELL = process.platform === 'win32';\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';\n\nfunction matchPM(str: string): PackageManager | null {\n // Order matters: check pnpm before npm since \"npm\" is a substring of some paths\n if (/pnpm/i.test(str)) return 'pnpm';\n if (/\\byarn\\b/i.test(str)) return 'yarn';\n if (/\\bbun\\b/i.test(str)) return 'bun';\n if (/\\bnpm\\b/i.test(str)) return 'npm';\n return null;\n}\n\n/**\n * Detect which package manager was used to install mastracode globally.\n *\n * Uses a multi-tier approach:\n * 1. npm_config_user_agent env var (set when run via `pnpm run`, `npm run`, etc.)\n * 2. npm_execpath env var (fallback for script-based invocation)\n * 3. NODE_PATH env var (set by pnpm global bin stubs)\n * 4. Resolved path of the running script (process.argv[1])\n * 5. Shell-out to `pnpm list -g` to check if pnpm manages the package\n * 6. Falls back to 'npm'\n */\nexport async function detectPackageManager(): Promise<PackageManager> {\n // Tier 1: npm_config_user_agent (most reliable when available)\n const userAgent = process.env.npm_config_user_agent;\n if (userAgent) {\n const pm = matchPM(userAgent);\n if (pm) return pm;\n }\n\n // Tier 2: npm_execpath\n const execPath = process.env.npm_execpath;\n if (execPath) {\n const pm = matchPM(execPath);\n if (pm) return pm;\n }\n\n // Tier 3: NODE_PATH (pnpm global stubs set this to paths containing .pnpm)\n const nodePath = process.env.NODE_PATH;\n if (nodePath) {\n if (/[/\\\\]\\.pnpm[/\\\\]/.test(nodePath) || /[/\\\\]pnpm[/\\\\]/.test(nodePath)) return 'pnpm';\n if (/[/\\\\]\\.yarn[/\\\\]/.test(nodePath)) return 'yarn';\n if (/[/\\\\]\\.bun[/\\\\]/.test(nodePath)) return 'bun';\n }\n\n // Tier 4: Resolved script path\n try {\n const scriptPath = realpathSync(process.argv[1] ?? '');\n if (/[/\\\\]\\.?pnpm[/\\\\]/.test(scriptPath)) return 'pnpm';\n if (/[/\\\\]\\.?yarn[/\\\\]/.test(scriptPath)) return 'yarn';\n if (/[/\\\\]\\.?bun[/\\\\]/.test(scriptPath)) return 'bun';\n } catch {\n // realpathSync can fail if argv[1] is missing/broken — fall through\n }\n\n // Tier 5: Check if the package is in pnpm's global store (non-blocking)\n const pnpmResult = await new Promise<boolean>(resolve => {\n execFile(\n 'pnpm',\n ['list', '-g', '--depth=0', PACKAGE_NAME],\n { timeout: 3_000, shell: USE_SHELL },\n (error, stdout) => {\n resolve(!error && stdout.includes(PACKAGE_NAME));\n },\n );\n });\n if (pnpmResult) return 'pnpm';\n\n return 'npm';\n}\n\n/**\n * Build the shell command string a user would run to install/update globally.\n */\nexport function getInstallCommand(pm: PackageManager, version?: string): string {\n const pkg = version ? `${PACKAGE_NAME}@${version}` : `${PACKAGE_NAME}@latest`;\n switch (pm) {\n case 'pnpm':\n return `pnpm add -g ${pkg}`;\n case 'yarn':\n return `yarn global add ${pkg}`;\n case 'bun':\n return `bun add -g ${pkg}`;\n default:\n return `npm install -g ${pkg}`;\n }\n}\n\n/**\n * Read the current version, injected at build time by tsdown's `define` option.\n * Falls back to reading package.json at runtime (e.g. when running from source with tsx).\n */\nexport function getCurrentVersion(): string {\n if (typeof MASTRACODE_VERSION !== 'undefined') {\n return MASTRACODE_VERSION;\n }\n // Fallback for running from source (e.g. pnpx tsx mastracode/src/main.ts)\n const dir = dirname(fileURLToPath(import.meta.url));\n const pkgPath = resolve(dir, '../../package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.version;\n}\n\n/**\n * Fetch the latest published version from npm.\n * Returns null if the fetch fails (network error, timeout, etc.).\n */\nexport async function fetchLatestVersion(): Promise<string | null> {\n if (process.env.MASTRACODE_UPDATE_LATEST_VERSION) return process.env.MASTRACODE_UPDATE_LATEST_VERSION;\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n const res = await fetch(NPM_REGISTRY_URL, { signal: controller.signal });\n clearTimeout(timeout);\n if (!res.ok) return null;\n const data = (await res.json()) as { version?: string };\n return data.version ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Simple semver comparison: returns true if `latest` is newer than `current`.\n * Handles standard x.y.z versions. Ignores pre-release tags.\n */\nexport function isNewerVersion(current: string, latest: string): boolean {\n const parse = (v: string) =>\n v\n .replace(/^v/, '')\n .split('-')[0]!\n .split('.')\n .map(s => {\n const n = Number(s);\n return Number.isFinite(n) ? n : 0;\n });\n const [cMajor = 0, cMinor = 0, cPatch = 0] = parse(current);\n const [lMajor = 0, lMinor = 0, lPatch = 0] = parse(latest);\n if (lMajor !== cMajor) return lMajor > cMajor;\n if (lMinor !== cMinor) return lMinor > cMinor;\n return lPatch > cPatch;\n}\n\n/** Max entries to show in the changelog summary. */\nconst MAX_CHANGELOG_ENTRIES = 20;\n\n/**\n * Fetch the CHANGELOG.md for a specific published version from the npm CDN\n * and extract a human-readable summary of changes.\n * Returns null if the fetch fails or the changelog can't be parsed.\n */\nexport async function fetchChangelog(version: string): Promise<string | null> {\n if (process.env.MASTRACODE_UPDATE_CHANGELOG) return process.env.MASTRACODE_UPDATE_CHANGELOG;\n\n try {\n const url = `https://unpkg.com/${PACKAGE_NAME}@${version}/CHANGELOG.md`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(timeout);\n if (!res.ok) return null;\n const text = await res.text();\n return parseChangelog(text, version);\n } catch {\n return null;\n }\n}\n\n/**\n * Extract the changelog section for a specific version and format it\n * as a concise bullet list suitable for terminal display.\n */\nexport function parseChangelog(markdown: string, version: string): string | null {\n const versionHeader = `## ${version}`;\n const startIdx = markdown.indexOf(versionHeader);\n if (startIdx === -1) return null;\n\n const afterHeader = startIdx + versionHeader.length;\n const nextHeaderIdx = markdown.indexOf('\\n## ', afterHeader);\n const section = nextHeaderIdx === -1 ? markdown.slice(afterHeader) : markdown.slice(afterHeader, nextHeaderIdx);\n\n const lines = section.split('\\n');\n const entries: string[] = [];\n let skipIndented = false;\n\n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i]!;\n const trimmed = raw.trim();\n\n // Only match top-level entries (no leading whitespace before \"- \")\n const isTopLevel = raw === trimmed && trimmed.startsWith('- ');\n if (!isTopLevel) {\n // Skip indented sub-items (e.g. dependency list entries)\n if (skipIndented && /^\\s+-\\s/.test(raw)) continue;\n skipIndented = false;\n continue;\n }\n\n // Skip dependency update entries and their sub-items\n if (/^- Updated dependenc/i.test(trimmed)) {\n skipIndented = true;\n continue;\n }\n skipIndented = false;\n\n let entry = trimmed.slice(2);\n // Strip markdown links: [text](url) → text\n entry = entry.replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1');\n // Strip PR references like (#15760)\n entry = entry.replace(/\\s*\\(#\\d+\\)\\s*/g, ' ');\n // Strip commit SHA references like (`abc123`)\n entry = entry.replace(/\\s*\\(`[a-f0-9]+`\\)\\s*/g, ' ');\n // Trim trailing periods for cleaner bullet display\n entry = entry.replace(/\\.\\s*$/, '');\n entry = entry.trim();\n if (entry) entries.push(entry);\n if (entries.length >= MAX_CHANGELOG_ENTRIES) break;\n }\n\n if (entries.length === 0) return null;\n return entries.map(e => ` • ${e}`).join('\\n');\n}\n\n/** Result of attempting an auto-update: exit status plus captured stderr. */\nexport interface UpdateResult {\n ok: boolean;\n stderr?: string;\n}\n\n/**\n * Run the appropriate global install command to update mastracode.\n * Exit code 0 does not prove the running binary changed (the install may land\n * in a location the PATH shim doesn't use) — verify with {@link locateOwnInstall}.\n */\nexport function runUpdate(pm: PackageManager, targetVersion: string): Promise<UpdateResult> {\n return execUpdate(pm, buildInstallArgs(pm, targetVersion));\n}\n\nfunction execUpdate(cmd: string, args: string[]): Promise<UpdateResult> {\n return new Promise(resolve => {\n execFile(cmd, args, { timeout: 60_000, shell: USE_SHELL }, (error, _stdout, stderr) => {\n const captured = (stderr ?? '').trim();\n if (error) {\n resolve({ ok: false, stderr: captured || error.message });\n } else {\n resolve({ ok: true, stderr: captured || undefined });\n }\n });\n });\n}\n\nfunction buildInstallArgs(pm: PackageManager, version: string): string[] {\n const pkg = `${PACKAGE_NAME}@${version}`;\n switch (pm) {\n case 'pnpm':\n return ['add', '-g', pkg];\n case 'yarn':\n return ['global', 'add', pkg];\n case 'bun':\n return ['add', '-g', pkg];\n default:\n return ['install', '-g', pkg];\n }\n}\n\n/** Max stderr lines to surface when an update fails. */\nconst MAX_UPDATE_ERROR_LINES = 5;\n\nfunction formatUpdaterError(stderr: string | undefined): string | null {\n if (!stderr) return null;\n const lines = stderr\n .split('\\n')\n .map(line => line.trimEnd())\n .filter(line => line.trim().length > 0);\n if (lines.length === 0) return null;\n return lines.slice(-MAX_UPDATE_ERROR_LINES).join('\\n');\n}\n\n/**\n * Find the installed mastracode package the running binary belongs to (walking\n * up from `process.argv[1]`) and read its version fresh from disk. Returns\n * null when it can't be determined, e.g. when running from source.\n */\nexport function locateOwnInstall(): { dir: string; version: string | null } | null {\n const entry = process.argv[1];\n if (!entry) return null;\n\n let dir: string;\n try {\n dir = dirname(realpathSync(entry));\n } catch {\n return null;\n }\n\n let previous = '';\n while (dir && dir !== previous) {\n try {\n const pkg = JSON.parse(readFileSync(resolve(dir, 'package.json'), 'utf-8')) as {\n name?: string;\n version?: string;\n };\n if (pkg.name === PACKAGE_NAME) {\n return { dir, version: typeof pkg.version === 'string' ? pkg.version : null };\n }\n } catch {\n // Not a readable manifest — keep walking up.\n }\n previous = dir;\n dir = dirname(dir);\n }\n\n return null;\n}\n\nexport type UpdateOutcome =\n | { status: 'updated'; message: string }\n | { status: 'unchanged'; message: string }\n | { status: 'failed'; message: string };\n\n/**\n * Decide what to tell the user after {@link runUpdate}: `updated` when the\n * on-disk version matches the target (or can't be determined), `unchanged`\n * when the package manager succeeded but the running install didn't change,\n * `failed` on error (with the package manager's stderr).\n */\nexport function resolveUpdateOutcome(opts: {\n pm: PackageManager;\n targetVersion: string;\n result: UpdateResult;\n install: { dir: string; version: string | null } | null;\n /** Overrides the suggested manual command, e.g. when the update was delegated to the owning tool. */\n manualCommand?: string;\n}): UpdateOutcome {\n const { pm, targetVersion, result, install } = opts;\n const cmd = opts.manualCommand ?? getInstallCommand(pm, targetVersion);\n\n if (!result.ok) {\n const details = formatUpdaterError(result.stderr);\n let message = `Auto-update failed. Run \\`${cmd}\\` manually.`;\n if (details) message += `\\n\\n${details}`;\n return { status: 'failed', message };\n }\n\n if (install?.version != null && install.version !== targetVersion) {\n const message = opts.manualCommand\n ? `The update ran, but the Mastra Code you are running (at ${install.dir}) is still ` +\n `v${install.version}. Try \\`${cmd}\\` manually.`\n : `The update installed, but the Mastra Code you are running (at ${install.dir}) is still ` +\n `v${install.version} — it looks like it is managed by another tool. Update it with that tool, ` +\n `or try \\`${cmd}\\`.`;\n return { status: 'unchanged', message };\n }\n\n return { status: 'updated', message: `Updated to v${targetVersion}. Please restart Mastra Code.` };\n}\n\n/** Global node_modules directory the package manager installs into, or null when unknown. */\nfunction getGlobalRoot(pm: PackageManager): Promise<string | null> {\n const args = pm === 'yarn' ? ['global', 'dir'] : ['root', '-g'];\n return new Promise(res => {\n execFile(pm, args, { timeout: 10_000, shell: USE_SHELL }, (error, stdout) => {\n const out = (stdout ?? '').trim().split('\\n').pop()?.trim();\n if (error || !out) return res(null);\n res(pm === 'yarn' ? resolve(out, 'node_modules') : out);\n });\n });\n}\n\n/**\n * Whether updating via `pm` would touch the install the running binary uses.\n * Fail-open: returns true when either side can't be determined, so the update\n * proceeds and the post-install verification has the final word.\n */\nasync function isOwnInstallManagedBy(pm: PackageManager, install: { dir: string } | null): Promise<boolean> {\n if (!install) return true;\n const root = await getGlobalRoot(pm);\n if (!root) return true;\n try {\n return realpathSync(resolve(root, PACKAGE_NAME)) === install.dir;\n } catch {\n // Package absent from the pm's global root: installing there can't affect the running binary.\n return false;\n }\n}\n\n/** A tool other than a package manager that owns the running install, matched by path. */\ninterface InstallOwner {\n name: string;\n /** Command to run to delegate the update; omitted when we only suggest `command` to the user. */\n exec?: { cmd: string; args: string[] };\n command: string;\n}\n\nfunction findInstallOwner(dir: string, version: string): InstallOwner | null {\n if (dir.startsWith(join(homedir(), '.vite-plus') + sep)) {\n return {\n name: 'vite-plus',\n exec: { cmd: 'vp', args: ['install', '-g', `${PACKAGE_NAME}@${version}`] },\n command: `vp install -g ${PACKAGE_NAME}@${version}`,\n };\n }\n // Homebrew keeps formulas under <prefix>/Cellar/ whatever the prefix, so match the path segment.\n if (dir.split(sep).includes('Cellar')) {\n // Suggest-only: brew formulas lag npm, and `brew upgrade` can pull unrelated updates.\n return { name: 'Homebrew', command: `brew upgrade ${PACKAGE_NAME}` };\n }\n return null;\n}\n\n/**\n * Update mastracode and verify the result: delegates to the tool that owns the\n * running install when we recognize it, skips the install when it isn't\n * managed by `pm`, otherwise runs the package manager. Every executed update\n * is verified against the on-disk version.\n */\nexport async function performUpdate(pm: PackageManager, targetVersion: string): Promise<UpdateOutcome> {\n // The registry-provided version reaches shell commands on Windows — accept only version tokens.\n if (!/^[\\w.+-]+$/.test(targetVersion)) {\n return { status: 'failed', message: `Auto-update aborted: unexpected version \"${targetVersion}\".` };\n }\n\n const install = locateOwnInstall();\n\n const owner = install ? findInstallOwner(install.dir, targetVersion) : null;\n if (owner) {\n if (!owner.exec) {\n const message =\n `Your Mastra Code install (at ${install!.dir}) is managed by ${owner.name}. ` +\n `Update it with \\`${owner.command}\\`.`;\n return { status: 'unchanged', message };\n }\n const result = await execUpdate(owner.exec.cmd, owner.exec.args);\n return resolveUpdateOutcome({\n pm,\n targetVersion,\n result,\n install: locateOwnInstall(),\n manualCommand: owner.command,\n });\n }\n\n if (!(await isOwnInstallManagedBy(pm, install))) {\n const message =\n `Your Mastra Code install (at ${install!.dir}) is not managed by ${pm} — it looks like it was ` +\n `installed by another tool. Update it with that tool, or try \\`${getInstallCommand(pm, targetVersion)}\\`.`;\n return { status: 'unchanged', message };\n }\n\n const result = await runUpdate(pm, targetVersion);\n // Re-locate so the version reflects what the install just wrote to disk.\n return resolveUpdateOutcome({ pm, targetVersion, result, install: locateOwnInstall() });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"update-check.js","names":[],"sources":["../../src/utils/update-check.ts"],"sourcesContent":["/**\n * Check for newer versions of mastracode on npm.\n */\n\nimport { execFile } from 'node:child_process';\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\ndeclare const MASTRACODE_VERSION: string | undefined;\n\nconst PACKAGE_NAME = 'mastracode';\nconst NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;\n\n/** Timeout for the npm registry fetch (ms). */\nconst FETCH_TIMEOUT_MS = 5_000;\n\n// Package managers and vp are .cmd shims on Windows; execFile can't spawn those without a shell (EINVAL).\nconst USE_SHELL = process.platform === 'win32';\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';\n\nfunction matchPM(str: string): PackageManager | null {\n // Order matters: check pnpm before npm since \"npm\" is a substring of some paths\n if (/pnpm/i.test(str)) return 'pnpm';\n if (/\\byarn\\b/i.test(str)) return 'yarn';\n if (/\\bbun\\b/i.test(str)) return 'bun';\n if (/\\bnpm\\b/i.test(str)) return 'npm';\n return null;\n}\n\n/**\n * Detect which package manager was used to install mastracode globally.\n *\n * Uses a multi-tier approach:\n * 1. npm_config_user_agent env var (set when run via `pnpm run`, `npm run`, etc.)\n * 2. npm_execpath env var (fallback for script-based invocation)\n * 3. NODE_PATH env var (set by pnpm global bin stubs)\n * 4. Resolved path of the running script (process.argv[1])\n * 5. Shell-out to `pnpm list -g` to check if pnpm manages the package\n * 6. Falls back to 'npm'\n */\nexport async function detectPackageManager(): Promise<PackageManager> {\n // Tier 1: npm_config_user_agent (most reliable when available)\n const userAgent = process.env.npm_config_user_agent;\n if (userAgent) {\n const pm = matchPM(userAgent);\n if (pm) return pm;\n }\n\n // Tier 2: npm_execpath\n const execPath = process.env.npm_execpath;\n if (execPath) {\n const pm = matchPM(execPath);\n if (pm) return pm;\n }\n\n // Tier 3: NODE_PATH (pnpm global stubs set this to paths containing .pnpm)\n const nodePath = process.env.NODE_PATH;\n if (nodePath) {\n if (/[/\\\\]\\.pnpm[/\\\\]/.test(nodePath) || /[/\\\\]pnpm[/\\\\]/.test(nodePath)) return 'pnpm';\n if (/[/\\\\]\\.yarn[/\\\\]/.test(nodePath)) return 'yarn';\n if (/[/\\\\]\\.bun[/\\\\]/.test(nodePath)) return 'bun';\n }\n\n // Tier 4: Resolved script path\n try {\n const scriptPath = realpathSync(process.argv[1] ?? '');\n if (/[/\\\\]\\.?pnpm[/\\\\]/.test(scriptPath)) return 'pnpm';\n if (/[/\\\\]\\.?yarn[/\\\\]/.test(scriptPath)) return 'yarn';\n if (/[/\\\\]\\.?bun[/\\\\]/.test(scriptPath)) return 'bun';\n } catch {\n // realpathSync can fail if argv[1] is missing/broken — fall through\n }\n\n // Tier 5: Check if the package is in pnpm's global store (non-blocking)\n const pnpmResult = await new Promise<boolean>(resolve => {\n execFile(\n 'pnpm',\n ['list', '-g', '--depth=0', PACKAGE_NAME],\n { timeout: 3_000, shell: USE_SHELL },\n (error, stdout) => {\n resolve(!error && stdout.includes(PACKAGE_NAME));\n },\n );\n });\n if (pnpmResult) return 'pnpm';\n\n return 'npm';\n}\n\n/**\n * Build the shell command string a user would run to install/update globally.\n */\nexport function getInstallCommand(pm: PackageManager, version?: string): string {\n const pkg = version ? `${PACKAGE_NAME}@${version}` : `${PACKAGE_NAME}@latest`;\n switch (pm) {\n case 'pnpm':\n return `pnpm add -g ${pkg}`;\n case 'yarn':\n return `yarn global add ${pkg}`;\n case 'bun':\n return `bun add -g ${pkg}`;\n default:\n return `npm install -g ${pkg}`;\n }\n}\n\n/**\n * Read the current version, injected at build time by tsdown's `define` option.\n * Falls back to reading package.json at runtime (e.g. when running from source with tsx).\n */\nexport function getCurrentVersion(): string {\n if (typeof MASTRACODE_VERSION !== 'undefined') {\n return MASTRACODE_VERSION;\n }\n // Fallback for running from source (e.g. pnpx tsx mastracode/src/main.ts)\n const dir = dirname(fileURLToPath(import.meta.url));\n const pkgPath = resolve(dir, '../../package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.version;\n}\n\n/**\n * Fetch the latest published version from npm.\n * Returns null if the fetch fails (network error, timeout, etc.).\n */\nexport async function fetchLatestVersion(): Promise<string | null> {\n if (process.env.MASTRACODE_UPDATE_LATEST_VERSION) return process.env.MASTRACODE_UPDATE_LATEST_VERSION;\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n const res = await fetch(NPM_REGISTRY_URL, { signal: controller.signal });\n clearTimeout(timeout);\n if (!res.ok) return null;\n const data = (await res.json()) as { version?: string };\n return data.version ?? null;\n } catch {\n return null;\n }\n}\n\nconst isPrerelease = (v: string) => v.includes('-');\n\n/**\n * Simple semver comparison: returns true if `latest` is newer than `current`.\n * Handles standard x.y.z versions. Pre-release tags only matter against the\n * matching release; two pre-releases of the same version compare equal.\n */\nexport function isNewerVersion(current: string, latest: string): boolean {\n const parse = (v: string) =>\n v\n .replace(/^v/, '')\n .split('-')[0]!\n .split('.')\n .map(s => {\n const n = Number(s);\n return Number.isFinite(n) ? n : 0;\n });\n const [cMajor = 0, cMinor = 0, cPatch = 0] = parse(current);\n const [lMajor = 0, lMinor = 0, lPatch = 0] = parse(latest);\n if (lMajor !== cMajor) return lMajor > cMajor;\n if (lMinor !== cMinor) return lMinor > cMinor;\n if (lPatch !== cPatch) return lPatch > cPatch;\n // Same x.y.z: a release is newer than its own prerelease (1.2.0 > 1.2.0-rc.1).\n return isPrerelease(current) && !isPrerelease(latest);\n}\n\n/** Max entries to show in the changelog summary. */\nconst MAX_CHANGELOG_ENTRIES = 20;\n\n/**\n * Fetch the CHANGELOG.md for a specific published version from the npm CDN\n * and extract a human-readable summary of changes.\n * Returns null if the fetch fails or the changelog can't be parsed.\n */\nexport async function fetchChangelog(version: string): Promise<string | null> {\n if (process.env.MASTRACODE_UPDATE_CHANGELOG) return process.env.MASTRACODE_UPDATE_CHANGELOG;\n\n try {\n const url = `https://unpkg.com/${PACKAGE_NAME}@${version}/CHANGELOG.md`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(timeout);\n if (!res.ok) return null;\n const text = await res.text();\n return parseChangelog(text, version);\n } catch {\n return null;\n }\n}\n\n/**\n * Extract the changelog section for a specific version and format it\n * as a concise bullet list suitable for terminal display.\n */\nexport function parseChangelog(markdown: string, version: string): string | null {\n const versionHeader = `## ${version}`;\n const startIdx = markdown.indexOf(versionHeader);\n if (startIdx === -1) return null;\n\n const afterHeader = startIdx + versionHeader.length;\n const nextHeaderIdx = markdown.indexOf('\\n## ', afterHeader);\n const section = nextHeaderIdx === -1 ? markdown.slice(afterHeader) : markdown.slice(afterHeader, nextHeaderIdx);\n\n const lines = section.split('\\n');\n const entries: string[] = [];\n let skipIndented = false;\n\n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i]!;\n const trimmed = raw.trim();\n\n // Only match top-level entries (no leading whitespace before \"- \")\n const isTopLevel = raw === trimmed && trimmed.startsWith('- ');\n if (!isTopLevel) {\n // Skip indented sub-items (e.g. dependency list entries)\n if (skipIndented && /^\\s+-\\s/.test(raw)) continue;\n skipIndented = false;\n continue;\n }\n\n // Skip dependency update entries and their sub-items\n if (/^- Updated dependenc/i.test(trimmed)) {\n skipIndented = true;\n continue;\n }\n skipIndented = false;\n\n let entry = trimmed.slice(2);\n // Strip markdown links: [text](url) → text\n entry = entry.replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1');\n // Strip PR references like (#15760)\n entry = entry.replace(/\\s*\\(#\\d+\\)\\s*/g, ' ');\n // Strip commit SHA references like (`abc123`)\n entry = entry.replace(/\\s*\\(`[a-f0-9]+`\\)\\s*/g, ' ');\n // Trim trailing periods for cleaner bullet display\n entry = entry.replace(/\\.\\s*$/, '');\n entry = entry.trim();\n if (entry) entries.push(entry);\n if (entries.length >= MAX_CHANGELOG_ENTRIES) break;\n }\n\n if (entries.length === 0) return null;\n return entries.map(e => ` • ${e}`).join('\\n');\n}\n\n/** Result of attempting an auto-update: exit status plus captured stderr. */\nexport interface UpdateResult {\n ok: boolean;\n stderr?: string;\n}\n\n/**\n * Run the appropriate global install command to update mastracode.\n * Exit code 0 does not prove the running binary changed (the install may land\n * in a location the PATH shim doesn't use) — verify with {@link locateOwnInstall}.\n */\nexport function runUpdate(pm: PackageManager, targetVersion: string): Promise<UpdateResult> {\n return execUpdate(pm, buildInstallArgs(pm, targetVersion));\n}\n\nfunction execUpdate(cmd: string, args: string[]): Promise<UpdateResult> {\n return new Promise(resolve => {\n execFile(cmd, args, { timeout: 60_000, shell: USE_SHELL }, (error, _stdout, stderr) => {\n const captured = (stderr ?? '').trim();\n if (error) {\n resolve({ ok: false, stderr: captured || error.message });\n } else {\n resolve({ ok: true, stderr: captured || undefined });\n }\n });\n });\n}\n\nfunction buildInstallArgs(pm: PackageManager, version: string): string[] {\n const pkg = `${PACKAGE_NAME}@${version}`;\n switch (pm) {\n case 'pnpm':\n return ['add', '-g', pkg];\n case 'yarn':\n return ['global', 'add', pkg];\n case 'bun':\n return ['add', '-g', pkg];\n default:\n return ['install', '-g', pkg];\n }\n}\n\n/** Max stderr lines to surface when an update fails. */\nconst MAX_UPDATE_ERROR_LINES = 5;\n\nfunction formatUpdaterError(stderr: string | undefined): string | null {\n if (!stderr) return null;\n const lines = stderr\n .split('\\n')\n .map(line => line.trimEnd())\n .filter(line => line.trim().length > 0);\n if (lines.length === 0) return null;\n return lines.slice(-MAX_UPDATE_ERROR_LINES).join('\\n');\n}\n\n/**\n * Find the installed mastracode package the running binary belongs to (walking\n * up from `process.argv[1]`) and read its version fresh from disk. Returns\n * null when it can't be determined, e.g. when running from source.\n */\nexport function locateOwnInstall(): { dir: string; version: string | null } | null {\n const entry = process.argv[1];\n if (!entry) return null;\n\n let dir: string;\n try {\n dir = dirname(realpathSync(entry));\n } catch {\n return null;\n }\n\n let previous = '';\n while (dir && dir !== previous) {\n try {\n const pkg = JSON.parse(readFileSync(resolve(dir, 'package.json'), 'utf-8')) as {\n name?: string;\n version?: string;\n };\n if (pkg.name === PACKAGE_NAME) {\n return { dir, version: typeof pkg.version === 'string' ? pkg.version : null };\n }\n } catch {\n // Not a readable manifest — keep walking up.\n }\n previous = dir;\n dir = dirname(dir);\n }\n\n return null;\n}\n\n/**\n * Result of an update attempt. `message` is a ready-made sentence; the other\n * fields let callers lay the result out themselves.\n */\nexport type UpdateOutcome =\n | {\n status: 'updated';\n message: string;\n /** The package manager or tool that installed the update. */\n via: string;\n }\n | {\n status: 'unchanged';\n message: string;\n /** Command the user can run to update the install they're running. */\n command: string;\n /** Where the running install lives, when known. */\n installDir?: string;\n /** Version still on disk after the update ran, when the update ran at all. */\n runningVersion?: string;\n /** Tool that ran the update (when it ran but didn't change the running install). */\n ranWith?: string;\n /** Tool that owns the install when we only suggest its command (e.g. Homebrew). */\n managedBy?: string;\n }\n | {\n status: 'failed';\n message: string;\n /** Command the user can run instead, when there is one. */\n command?: string;\n /** Why it failed: the tail of the package manager's stderr, or our own reason. */\n details?: string;\n };\n\n/**\n * Decide what to tell the user after {@link runUpdate}: `updated` when the\n * on-disk version matches the target (or can't be determined), `unchanged`\n * when the package manager succeeded but the running install didn't change,\n * `failed` on error (with the package manager's stderr).\n */\nexport function resolveUpdateOutcome(opts: {\n pm: PackageManager;\n targetVersion: string;\n result: UpdateResult;\n install: { dir: string; version: string | null } | null;\n /** Overrides the suggested manual command, e.g. when the update was delegated to the owning tool. */\n manualCommand?: string;\n /** Tool that ran the update when it wasn't `pm`, e.g. vite-plus. */\n via?: string;\n}): UpdateOutcome {\n const { pm, targetVersion, result, install } = opts;\n const cmd = opts.manualCommand ?? getInstallCommand(pm, targetVersion);\n const via = opts.via ?? pm;\n\n if (!result.ok) {\n const details = formatUpdaterError(result.stderr) ?? undefined;\n let message = `Auto-update failed. Run \\`${cmd}\\` manually.`;\n if (details) message += `\\n\\n${details}`;\n return { status: 'failed', message, command: cmd, ...(details ? { details } : {}) };\n }\n\n if (install?.version != null && install.version !== targetVersion) {\n const message = opts.manualCommand\n ? `The update ran, but the Mastra Code you are running (at ${install.dir}) is still ` +\n `v${install.version}. Try \\`${cmd}\\` manually.`\n : `The update installed, but the Mastra Code you are running (at ${install.dir}) is still ` +\n `v${install.version} — it looks like it is managed by another tool. Update it with that tool, ` +\n `or try \\`${cmd}\\`.`;\n return {\n status: 'unchanged',\n message,\n command: cmd,\n installDir: install.dir,\n runningVersion: install.version,\n ranWith: via,\n };\n }\n\n return { status: 'updated', message: `Updated to v${targetVersion}. Please restart Mastra Code.`, via };\n}\n\n/** Global node_modules directory the package manager installs into, or null when unknown. */\nfunction getGlobalRoot(pm: PackageManager): Promise<string | null> {\n const args = pm === 'yarn' ? ['global', 'dir'] : ['root', '-g'];\n return new Promise(res => {\n execFile(pm, args, { timeout: 10_000, shell: USE_SHELL }, (error, stdout) => {\n const out = (stdout ?? '').trim().split('\\n').pop()?.trim();\n if (error || !out) return res(null);\n res(pm === 'yarn' ? resolve(out, 'node_modules') : out);\n });\n });\n}\n\n/**\n * Whether updating via `pm` would touch the install the running binary uses.\n * Fail-open: returns true when either side can't be determined, so the update\n * proceeds and the post-install verification has the final word.\n */\nasync function isOwnInstallManagedBy(pm: PackageManager, install: { dir: string } | null): Promise<boolean> {\n if (!install) return true;\n const root = await getGlobalRoot(pm);\n if (!root) return true;\n try {\n return realpathSync(resolve(root, PACKAGE_NAME)) === install.dir;\n } catch {\n // Package absent from the pm's global root: installing there can't affect the running binary.\n return false;\n }\n}\n\n/** A tool other than a package manager that owns the running install, matched by path. */\ninterface InstallOwner {\n name: string;\n /** Command to run to delegate the update; omitted when we only suggest `command` to the user. */\n exec?: { cmd: string; args: string[] };\n command: string;\n}\n\nfunction findInstallOwner(dir: string, version: string): InstallOwner | null {\n if (dir.startsWith(join(homedir(), '.vite-plus') + sep)) {\n return {\n name: 'vite-plus',\n exec: { cmd: 'vp', args: ['install', '-g', `${PACKAGE_NAME}@${version}`] },\n command: `vp install -g ${PACKAGE_NAME}@${version}`,\n };\n }\n // Homebrew keeps formulas under <prefix>/Cellar/ whatever the prefix, so match the path segment.\n if (dir.split(sep).includes('Cellar')) {\n // Suggest-only: brew formulas lag npm, and `brew upgrade` can pull unrelated updates.\n return { name: 'Homebrew', command: `brew upgrade ${PACKAGE_NAME}` };\n }\n return null;\n}\n\n/**\n * What an update will do for the running install: run an install (with the\n * tool and command it will use), or nothing, with the result to show instead.\n */\nexport type UpdatePlan =\n | {\n willInstall: true;\n /** The package manager or tool that will run the install. */\n via: string;\n /** The install command, as the user would type it. */\n command: string;\n exec: { cmd: string; args: string[] };\n }\n | { willInstall: false; outcome: Extract<UpdateOutcome, { status: 'unchanged' | 'failed' }> };\n\n/**\n * Decide how to update the running install, without changing anything:\n * delegate to the tool that owns it when we recognize it, only suggest a\n * command when that tool can't be run for the user (Homebrew) or `pm` doesn't\n * manage it, otherwise run `pm`. {@link performUpdate} carries out this plan,\n * so callers can show what will happen before it starts.\n */\nexport async function planUpdate(pm: PackageManager, targetVersion: string): Promise<UpdatePlan> {\n // The registry-provided version reaches shell commands on Windows — accept only version tokens.\n if (!/^[\\w.+-]+$/.test(targetVersion)) {\n return {\n willInstall: false,\n outcome: {\n status: 'failed',\n message: `Auto-update aborted: unexpected version \"${targetVersion}\".`,\n details: `The npm registry returned an unexpected version: \"${targetVersion}\".`,\n },\n };\n }\n\n const install = locateOwnInstall();\n\n const owner = install ? findInstallOwner(install.dir, targetVersion) : null;\n if (owner) {\n if (!owner.exec) {\n const message =\n `Your Mastra Code install (at ${install!.dir}) is managed by ${owner.name}. ` +\n `Update it with \\`${owner.command}\\`.`;\n return {\n willInstall: false,\n outcome: {\n status: 'unchanged',\n message,\n command: owner.command,\n installDir: install!.dir,\n managedBy: owner.name,\n },\n };\n }\n return { willInstall: true, via: owner.name, command: owner.command, exec: owner.exec };\n }\n\n const command = getInstallCommand(pm, targetVersion);\n if (!(await isOwnInstallManagedBy(pm, install))) {\n const message =\n `Your Mastra Code install (at ${install!.dir}) is not managed by ${pm} — it looks like it was ` +\n `installed by another tool. Update it with that tool, or try \\`${command}\\`.`;\n return { willInstall: false, outcome: { status: 'unchanged', message, command, installDir: install!.dir } };\n }\n\n return { willInstall: true, via: pm, command, exec: { cmd: pm, args: buildInstallArgs(pm, targetVersion) } };\n}\n\n/**\n * Update mastracode following {@link planUpdate} (pass a plan already shown to\n * the user, or let this make one), then verify the result against the version\n * on disk.\n */\nexport async function performUpdate(\n pm: PackageManager,\n targetVersion: string,\n plan?: UpdatePlan,\n): Promise<UpdateOutcome> {\n plan ??= await planUpdate(pm, targetVersion);\n if (!plan.willInstall) return plan.outcome;\n\n const result = await execUpdate(plan.exec.cmd, plan.exec.args);\n // Re-locate so the version reflects what the install just wrote to disk.\n return resolveUpdateOutcome({\n pm,\n targetVersion,\n result,\n install: locateOwnInstall(),\n // A delegated update keeps the owning tool's command; `pm` updates keep the default wording.\n ...(plan.via === pm ? {} : { manualCommand: plan.command, via: plan.via }),\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/code-sdk",
3
- "version": "1.12.0-alpha.4",
3
+ "version": "1.12.0-alpha.6",
4
4
  "description": "Mastra Code SDK: the agent core behind Mastra Code (everything except the TUI) — build your own UIs and surfaces on top of it",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -63,18 +63,18 @@
63
63
  "yaml": "^2.7.1",
64
64
  "zod": "^4.6.4",
65
65
  "@mastra/agent-browser": "0.5.3",
66
- "@mastra/fastembed": "1.3.2",
66
+ "@mastra/core": "1.76.0-alpha.6",
67
67
  "@mastra/duckdb": "1.14.0-alpha.0",
68
+ "@mastra/fastembed": "1.3.2",
68
69
  "@mastra/github-signals": "0.5.1",
69
- "@mastra/core": "1.76.0-alpha.4",
70
+ "@mastra/mcp": "2.3.0-alpha.1",
71
+ "@mastra/observability": "1.19.0-alpha.3",
70
72
  "@mastra/libsql": "1.26.0-alpha.2",
71
- "@mastra/parallel": "0.1.2",
72
- "@mastra/mcp": "2.2.1-alpha.0",
73
- "@mastra/observability": "1.19.0-alpha.2",
74
73
  "@mastra/memory": "1.37.0-alpha.2",
74
+ "@mastra/parallel": "0.1.2",
75
75
  "@mastra/pg": "1.31.0-alpha.3",
76
- "@mastra/stagehand": "0.3.5",
77
76
  "@mastra/schema-compat": "1.3.13",
77
+ "@mastra/stagehand": "0.3.5",
78
78
  "@mastra/tavily": "1.1.2"
79
79
  },
80
80
  "devDependencies": {
@@ -86,8 +86,8 @@
86
86
  "typescript": "^6.0.3",
87
87
  "typescript-eslint": "^8.57.0",
88
88
  "vitest": "4.1.11",
89
- "@internal/types-builder": "0.0.116",
90
89
  "@internal/lint": "0.0.141",
90
+ "@internal/types-builder": "0.0.116",
91
91
  "@internal/workspace-test-utils": "0.0.85"
92
92
  },
93
93
  "engines": {