create-mastra 1.37.0-alpha.2 → 1.37.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.
- package/dist/{api-CV5-CXEm-Cpd49bi2.js → api-CV5-CXEm-CueiBLg3.js} +1 -1
- package/dist/api-Cdahi7Yf-BlGW3U7e.js +1 -0
- package/dist/{client-JZw8MfpM-zeD5gOhK.js → client-JZw8MfpM-BPeyQaUL.js} +19 -3
- package/dist/credentials-CdkRA-3T-Cagpr0K5.js +1 -0
- package/dist/{credentials-HeXP-kY2-jky92lr5.js → credentials-HeXP-kY2-89ktsX3S.js} +2 -2
- package/dist/index.js +308 -37
- package/package.json +2 -2
- package/dist/api-Cdahi7Yf-BbwhMVLL.js +0 -1
- package/dist/credentials-CdkRA-3T--5O17XQq.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as createApiClient, s as throwApiError } from "./client-JZw8MfpM-BPeyQaUL.js";
|
|
2
2
|
// ../cli/dist/api-CV5-CXEm.js
|
|
3
3
|
async function fetchOrgs(token) {
|
|
4
4
|
const { data, error, response } = await createApiClient(token).GET("/v1/auth/orgs");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as fetchOrgs } from "./api-CV5-CXEm-CueiBLg3.js";
|
|
@@ -388,7 +388,7 @@ function removeTrailingSlash(url) {
|
|
|
388
388
|
}
|
|
389
389
|
// ../cli/dist/client-JZw8MfpM.js
|
|
390
390
|
const MASTRA_PLATFORM_API_URL = process.env.MASTRA_PLATFORM_API_URL || "https://platform.mastra.ai";
|
|
391
|
-
process.env.MASTRA_PROJECTS_URL;
|
|
391
|
+
const MASTRA_PROJECTS_URL = process.env.MASTRA_PROJECTS_URL || "https://projects.mastra.ai";
|
|
392
392
|
/**
|
|
393
393
|
* Derive the gateway URL from the platform URL when not explicitly set.
|
|
394
394
|
* If the platform points at staging, the gateway defaults to staging too.
|
|
@@ -420,6 +420,22 @@ function throwApiError(message, status, detail) {
|
|
|
420
420
|
if (detail) throw new Error(detail);
|
|
421
421
|
throw new Error(`${message}: ${status}`);
|
|
422
422
|
}
|
|
423
|
+
/** Best-effort message from platform JSON error bodies (RFC 7807 `detail`, etc.). */
|
|
424
|
+
function extractApiErrorDetail(error) {
|
|
425
|
+
if (!error || typeof error !== "object") return void 0;
|
|
426
|
+
const o = error;
|
|
427
|
+
let detail;
|
|
428
|
+
if (typeof o.detail === "string" && o.detail.trim()) detail = o.detail;
|
|
429
|
+
else if (typeof o.message === "string" && o.message.trim()) detail = o.message;
|
|
430
|
+
else if (typeof o.error === "string" && o.error.trim()) detail = o.error;
|
|
431
|
+
const fieldErrors = Array.isArray(o.errors) ? o.errors.map((e) => {
|
|
432
|
+
if (!e || typeof e !== "object") return "";
|
|
433
|
+
const fe = e;
|
|
434
|
+
return [typeof fe.field === "string" ? fe.field : "", typeof fe.message === "string" ? fe.message : ""].filter(Boolean).join(" — ");
|
|
435
|
+
}).filter(Boolean).join("; ") : "";
|
|
436
|
+
if (detail && fieldErrors) return `${detail}: ${fieldErrors}`;
|
|
437
|
+
return detail ?? (fieldErrors || void 0);
|
|
438
|
+
}
|
|
423
439
|
let _currentToken = null;
|
|
424
440
|
let _refreshInFlight = null;
|
|
425
441
|
/**
|
|
@@ -444,7 +460,7 @@ async function authenticatedFetch(input, init) {
|
|
|
444
460
|
if (response.status !== 401 || !_currentToken) return response;
|
|
445
461
|
if (!_refreshInFlight) _refreshInFlight = (async () => {
|
|
446
462
|
try {
|
|
447
|
-
const { tryRefreshToken, loadCredentials } = await import("./credentials-CdkRA-3T
|
|
463
|
+
const { tryRefreshToken, loadCredentials } = await import("./credentials-CdkRA-3T-Cagpr0K5.js");
|
|
448
464
|
const creds = await loadCredentials();
|
|
449
465
|
if (!creds) throw new Error("No credentials");
|
|
450
466
|
const newToken = await tryRefreshToken(creds);
|
|
@@ -502,4 +518,4 @@ function authHeaders(token, orgId) {
|
|
|
502
518
|
function platformFetch(input, init) {
|
|
503
519
|
return authenticatedFetch(input, init);
|
|
504
520
|
}
|
|
505
|
-
export {
|
|
521
|
+
export { extractApiErrorDetail as a, createApiClient as i, MASTRA_PROJECTS_URL as n, platformFetch as o, authHeaders as r, throwApiError as s, MASTRA_PLATFORM_API_URL as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { i as loadCredentials, s as tryRefreshToken } from "./credentials-HeXP-kY2-89ktsX3S.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as MASTRA_PLATFORM_API_URL } from "./client-JZw8MfpM-
|
|
1
|
+
import { t as MASTRA_PLATFORM_API_URL } from "./client-JZw8MfpM-BPeyQaUL.js";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import "node:path";
|
|
4
4
|
import process$1, { stdin, stdout } from "node:process";
|
|
@@ -1448,4 +1448,4 @@ async function getToken(signal, options = {}) {
|
|
|
1448
1448
|
if (options.allowLogin === false || !isInteractive()) throw new Error("Session expired. Run `mastra auth login` interactively or set MASTRA_API_TOKEN.");
|
|
1449
1449
|
return (await login(signal, options)).token;
|
|
1450
1450
|
}
|
|
1451
|
-
export {
|
|
1451
|
+
export { __commonJSMin as _, openBrowser as a, cancel as c, outro as d, password as f, isCancel as g, text as h, loadCredentials as i, log as l, spinner as m, getCurrentOrgId as n, setCurrentOrgId as o, select as p, getToken as r, tryRefreshToken as s, LoginCancelledError as t, note as u, __require as v, __toESM as y };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
-
import { _ as
|
|
3
|
-
import {
|
|
4
|
-
import { t as fetchOrgs } from "./api-CV5-CXEm-
|
|
2
|
+
import { _ as __commonJSMin, a as openBrowser, c as cancel, d as outro, f as password, g as isCancel, h as text, l as log, m as spinner, n as getCurrentOrgId, o as setCurrentOrgId, p as select, r as getToken, t as LoginCancelledError, u as note, v as __require, y as __toESM } from "./credentials-HeXP-kY2-89ktsX3S.js";
|
|
3
|
+
import { a as extractApiErrorDetail, n as MASTRA_PROJECTS_URL, o as platformFetch, r as authHeaders, t as MASTRA_PLATFORM_API_URL } from "./client-JZw8MfpM-BPeyQaUL.js";
|
|
4
|
+
import { t as fetchOrgs } from "./api-CV5-CXEm-CueiBLg3.js";
|
|
5
5
|
import { EventEmitter, addAbortListener, on, once, setMaxListeners } from "node:events";
|
|
6
6
|
import { ChildProcess, execFile, spawn, spawnSync } from "node:child_process";
|
|
7
7
|
import path, { basename, delimiter, dirname, isAbsolute, normalize, resolve } from "node:path";
|
|
@@ -17628,8 +17628,13 @@ var require_yocto_spinner = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
17628
17628
|
return new YoctoSpinner(options);
|
|
17629
17629
|
};
|
|
17630
17630
|
}));
|
|
17631
|
-
// ../cli/dist/analytics-
|
|
17631
|
+
// ../cli/dist/analytics-CTFP7R1h.js
|
|
17632
17632
|
const CREATE_LLM_PROVIDERS = [
|
|
17633
|
+
{
|
|
17634
|
+
value: "mastra",
|
|
17635
|
+
label: "Mastra Gateway",
|
|
17636
|
+
hint: "every model with one key, sign in to get it"
|
|
17637
|
+
},
|
|
17633
17638
|
{
|
|
17634
17639
|
value: "openai",
|
|
17635
17640
|
label: "OpenAI"
|
|
@@ -19354,7 +19359,7 @@ var require_semver = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
19354
19359
|
rcompareIdentifiers: identifiers.rcompareIdentifiers
|
|
19355
19360
|
};
|
|
19356
19361
|
}));
|
|
19357
|
-
// ../cli/dist/create-
|
|
19362
|
+
// ../cli/dist/create-4eqEFmGM.js
|
|
19358
19363
|
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
19359
19364
|
var import_yocto_spinner = /* @__PURE__ */ __toESM(require_yocto_spinner(), 1);
|
|
19360
19365
|
var import_semver = /* @__PURE__ */ __toESM(require_semver(), 1);
|
|
@@ -19512,6 +19517,117 @@ function findTemplateByName(templates, templateName) {
|
|
|
19512
19517
|
if (template) return template;
|
|
19513
19518
|
return null;
|
|
19514
19519
|
}
|
|
19520
|
+
const GATEWAY_API_KEY_ENV = "MASTRA_GATEWAY_API_KEY";
|
|
19521
|
+
const STARTER_CREDIT_POOL = "gateway_credits";
|
|
19522
|
+
var GatewayApiError = class extends Error {
|
|
19523
|
+
status;
|
|
19524
|
+
constructor(message, status) {
|
|
19525
|
+
super(message);
|
|
19526
|
+
this.status = status;
|
|
19527
|
+
this.name = "GatewayApiError";
|
|
19528
|
+
}
|
|
19529
|
+
};
|
|
19530
|
+
async function request(token, orgId, path, init = {}, signal) {
|
|
19531
|
+
const res = await platformFetch(`${MASTRA_PLATFORM_API_URL}${path}`, {
|
|
19532
|
+
...init,
|
|
19533
|
+
signal,
|
|
19534
|
+
headers: {
|
|
19535
|
+
...authHeaders(token, orgId),
|
|
19536
|
+
...init.body ? { "Content-Type": "application/json" } : {}
|
|
19537
|
+
}
|
|
19538
|
+
});
|
|
19539
|
+
if (!res.ok) {
|
|
19540
|
+
const body = await res.json().catch(() => void 0);
|
|
19541
|
+
throw new GatewayApiError(extractApiErrorDetail(body) ?? `Request failed (${res.status})`, res.status);
|
|
19542
|
+
}
|
|
19543
|
+
return await res.json();
|
|
19544
|
+
}
|
|
19545
|
+
/**
|
|
19546
|
+
* Create a Gateway API key in the organization. Uses the organization key service and falls back
|
|
19547
|
+
* to provisioning a Gateway project with a key only where that service doesn't exist (404). A 503
|
|
19548
|
+
* means the service failed, so it surfaces instead of leaving a stray project behind.
|
|
19549
|
+
*/
|
|
19550
|
+
async function createGatewayApiKey(token, orgId, label, signal) {
|
|
19551
|
+
try {
|
|
19552
|
+
const result = await request(token, orgId, "/v1/gateway/organization/v2/keys", {
|
|
19553
|
+
method: "POST",
|
|
19554
|
+
body: JSON.stringify({ label })
|
|
19555
|
+
}, signal);
|
|
19556
|
+
return {
|
|
19557
|
+
apiKey: result.apiKey,
|
|
19558
|
+
keyId: result.keyId
|
|
19559
|
+
};
|
|
19560
|
+
} catch (error) {
|
|
19561
|
+
if (!(error instanceof GatewayApiError) || error.status !== 404) throw error;
|
|
19562
|
+
}
|
|
19563
|
+
return { apiKey: (await request(token, orgId, "/v1/gateway/projects/provision", {
|
|
19564
|
+
method: "POST",
|
|
19565
|
+
body: JSON.stringify({
|
|
19566
|
+
name: label,
|
|
19567
|
+
keyLabel: label
|
|
19568
|
+
})
|
|
19569
|
+
}, signal)).apiKey };
|
|
19570
|
+
}
|
|
19571
|
+
/** Revoke an organization key, e.g. one created for a project that was never written. */
|
|
19572
|
+
async function revokeGatewayApiKey(token, orgId, keyId) {
|
|
19573
|
+
await request(token, orgId, `/v1/gateway/organization/v2/keys/${encodeURIComponent(keyId)}`, { method: "DELETE" });
|
|
19574
|
+
}
|
|
19575
|
+
async function getGatewayCredits(token, orgId, signal) {
|
|
19576
|
+
const { customer } = await request(token, orgId, "/v1/billing/customer", {}, signal);
|
|
19577
|
+
const featureId = customer?.creditPool?.featureId ?? STARTER_CREDIT_POOL;
|
|
19578
|
+
const balance = findBalance(customer?.balances, featureId);
|
|
19579
|
+
return {
|
|
19580
|
+
remaining: remainingCredits(balance),
|
|
19581
|
+
unlimited: balance?.unlimited === true
|
|
19582
|
+
};
|
|
19583
|
+
}
|
|
19584
|
+
function findBalance(balances, featureId) {
|
|
19585
|
+
if (!balances) return void 0;
|
|
19586
|
+
return Object.values(balances).find((entry) => entry?.featureId === featureId) ?? balances[featureId];
|
|
19587
|
+
}
|
|
19588
|
+
function remainingCredits(balance) {
|
|
19589
|
+
if (balance?.remaining != null) return Math.max(0, balance.remaining);
|
|
19590
|
+
if (balance?.granted != null) return Math.max(0, balance.granted - (balance.usage ?? 0));
|
|
19591
|
+
return 0;
|
|
19592
|
+
}
|
|
19593
|
+
/** The dashboard's Add credits page for the organization, where credits and auto top-up are bought. */
|
|
19594
|
+
function creditsPageUrl(orgId) {
|
|
19595
|
+
return `${MASTRA_PROJECTS_URL}/add-credits/${orgId}`;
|
|
19596
|
+
}
|
|
19597
|
+
function formatCredits(amount) {
|
|
19598
|
+
return `$${amount.toFixed(2)}`;
|
|
19599
|
+
}
|
|
19600
|
+
/**
|
|
19601
|
+
* Offer to add credits when the organization has none. Credits (and auto top-up) are bought in the
|
|
19602
|
+
* dashboard, which opens in the browser; setup carries on without waiting for the purchase.
|
|
19603
|
+
* Resolves to whether the dashboard was opened.
|
|
19604
|
+
*/
|
|
19605
|
+
async function offerGatewayCredits({ orgId, credits, signal }) {
|
|
19606
|
+
if (credits.unlimited || credits.remaining > 0) return false;
|
|
19607
|
+
const choice = await select({
|
|
19608
|
+
message: `Your Gateway balance is ${formatCredits(credits.remaining)}. Model calls are paid per token from credits.`,
|
|
19609
|
+
options: [{
|
|
19610
|
+
value: "buy",
|
|
19611
|
+
label: "Add credits",
|
|
19612
|
+
hint: "opens the Mastra dashboard"
|
|
19613
|
+
}, {
|
|
19614
|
+
value: "skip",
|
|
19615
|
+
label: "Skip for now"
|
|
19616
|
+
}],
|
|
19617
|
+
initialValue: "buy",
|
|
19618
|
+
showInstructions: false,
|
|
19619
|
+
signal
|
|
19620
|
+
});
|
|
19621
|
+
if (isCancel(choice) || choice === "skip") return false;
|
|
19622
|
+
const url = creditsPageUrl(orgId);
|
|
19623
|
+
try {
|
|
19624
|
+
openBrowser(url);
|
|
19625
|
+
log.info(`Opened the Mastra dashboard. Add credits there. If it didn't open, go to:\n${import_picocolors.default.cyan(url)}`);
|
|
19626
|
+
} catch {
|
|
19627
|
+
log.info(`Add credits in the Mastra dashboard:\n${import_picocolors.default.cyan(url)}`);
|
|
19628
|
+
}
|
|
19629
|
+
return true;
|
|
19630
|
+
}
|
|
19515
19631
|
const DEFAULT_PLATFORM_API_URL = "https://platform.mastra.ai";
|
|
19516
19632
|
/**
|
|
19517
19633
|
* Walk the user through enabling Mastra Observability for a freshly-scaffolded
|
|
@@ -19860,6 +19976,10 @@ async function writeEmptyScaffold({ projectPath, projectName, versionTag, packag
|
|
|
19860
19976
|
await Promise.all(writes);
|
|
19861
19977
|
}
|
|
19862
19978
|
const MANAGED_PROVIDER_CONFIGS = {
|
|
19979
|
+
mastra: {
|
|
19980
|
+
displayName: "Mastra Gateway",
|
|
19981
|
+
apiKeyEnv: "MASTRA_GATEWAY_API_KEY"
|
|
19982
|
+
},
|
|
19863
19983
|
openai: {
|
|
19864
19984
|
displayName: "OpenAI",
|
|
19865
19985
|
apiKeyEnv: "OPENAI_API_KEY"
|
|
@@ -19954,6 +20074,21 @@ function adaptAgentSource(source, provider, config) {
|
|
|
19954
20074
|
applied: true,
|
|
19955
20075
|
content: source
|
|
19956
20076
|
};
|
|
20077
|
+
if (provider === "mastra") {
|
|
20078
|
+
if (findMatches(source, PRIMARY_OPENAI_MODEL).length !== 1) return {
|
|
20079
|
+
applied: false,
|
|
20080
|
+
content: source
|
|
20081
|
+
};
|
|
20082
|
+
if (findMatches(source, OBSERVATIONAL_OPENAI_MODEL).length !== 1) return {
|
|
20083
|
+
applied: false,
|
|
20084
|
+
content: source
|
|
20085
|
+
};
|
|
20086
|
+
const toGateway = (match) => match.replace(/(['"])openai\//, "$1mastra/openai/");
|
|
20087
|
+
return {
|
|
20088
|
+
applied: true,
|
|
20089
|
+
content: source.replace(PRIMARY_OPENAI_MODEL, toGateway).replace(OBSERVATIONAL_OPENAI_MODEL, toGateway)
|
|
20090
|
+
};
|
|
20091
|
+
}
|
|
19957
20092
|
if (!config.primaryModel || !config.observationalModel) return {
|
|
19958
20093
|
applied: false,
|
|
19959
20094
|
content: source
|
|
@@ -20005,6 +20140,22 @@ async function writeSecureEnv(envPath, content) {
|
|
|
20005
20140
|
return false;
|
|
20006
20141
|
}
|
|
20007
20142
|
}
|
|
20143
|
+
/**
|
|
20144
|
+
* Write an API key that arrived after the template was adapted (the Gateway key is created
|
|
20145
|
+
* while the template clones). Starts from `.env`, or `.env.example` when there is no `.env` yet.
|
|
20146
|
+
*/
|
|
20147
|
+
async function writeManagedApiKey({ projectPath, apiKeyEnv, apiKey }) {
|
|
20148
|
+
const envPath = path$1.join(projectPath, ".env");
|
|
20149
|
+
let source = "";
|
|
20150
|
+
for (const candidate of [envPath, path$1.join(projectPath, ".env.example")]) try {
|
|
20151
|
+
source = await fsPromises.readFile(candidate, "utf8");
|
|
20152
|
+
break;
|
|
20153
|
+
} catch (error) {
|
|
20154
|
+
if (error.code !== "ENOENT") return false;
|
|
20155
|
+
}
|
|
20156
|
+
const result = setEnvValue(source, apiKeyEnv, apiKey);
|
|
20157
|
+
return writeSecureEnv(envPath, result.applied ? result.content : `${source}${source && !source.endsWith("\n") ? "\n" : ""}${apiKeyEnv}=${apiKey}\n`);
|
|
20158
|
+
}
|
|
20008
20159
|
async function adaptDefaultTemplate({ projectPath, projectName, packageManager, provider, apiKey, versionTag }) {
|
|
20009
20160
|
const config = MANAGED_PROVIDER_CONFIGS[provider];
|
|
20010
20161
|
let adaptationFailed = false;
|
|
@@ -20232,6 +20383,7 @@ const create = async (args) => {
|
|
|
20232
20383
|
let llmApiKey = options.llmApiKey;
|
|
20233
20384
|
let providerSelectionMethod;
|
|
20234
20385
|
let observabilityEnabled = false;
|
|
20386
|
+
let needsGatewayKey = false;
|
|
20235
20387
|
let platformSetupController;
|
|
20236
20388
|
let platformSetupPromise;
|
|
20237
20389
|
if (mode === "managed") {
|
|
@@ -20241,7 +20393,8 @@ const create = async (args) => {
|
|
|
20241
20393
|
llmProvider = await promptForProvider();
|
|
20242
20394
|
providerSelectionMethod = "interactive";
|
|
20243
20395
|
}
|
|
20244
|
-
if (llmApiKey === void 0 && !providerProvidedByCli) llmApiKey = await promptForApiKey(llmProvider);
|
|
20396
|
+
if (llmApiKey === void 0 && !providerProvidedByCli && llmProvider !== "mastra") llmApiKey = await promptForApiKey(llmProvider);
|
|
20397
|
+
needsGatewayKey = llmProvider === "mastra" && llmApiKey === void 0;
|
|
20245
20398
|
if (options.projectName === void 0 || options.llmProvider === void 0) {
|
|
20246
20399
|
observabilityEnabled = await promptForObservabilityOptIn();
|
|
20247
20400
|
analytics?.trackEvent("cli_observability_selected", {
|
|
@@ -20250,32 +20403,40 @@ const create = async (args) => {
|
|
|
20250
20403
|
answer: observabilityEnabled ? "yes" : "no",
|
|
20251
20404
|
selection_method: "interactive"
|
|
20252
20405
|
});
|
|
20253
|
-
|
|
20254
|
-
|
|
20255
|
-
|
|
20256
|
-
|
|
20257
|
-
|
|
20258
|
-
|
|
20259
|
-
|
|
20260
|
-
|
|
20261
|
-
|
|
20262
|
-
|
|
20406
|
+
}
|
|
20407
|
+
if (observabilityEnabled || needsGatewayKey) {
|
|
20408
|
+
platformSetupController = new AbortController();
|
|
20409
|
+
const signal = platformSetupController.signal;
|
|
20410
|
+
platformSetupPromise = (async () => {
|
|
20411
|
+
try {
|
|
20412
|
+
const token = await getToken(signal, {
|
|
20413
|
+
skipOnInput: true,
|
|
20414
|
+
source: args.loginSource
|
|
20415
|
+
});
|
|
20416
|
+
const org = await resolveCurrentOrg(token, {
|
|
20417
|
+
forcePrompt: true,
|
|
20418
|
+
exitOnCancel: false,
|
|
20419
|
+
signal
|
|
20420
|
+
});
|
|
20421
|
+
return {
|
|
20422
|
+
status: "ready",
|
|
20423
|
+
token,
|
|
20424
|
+
org,
|
|
20425
|
+
gateway: needsGatewayKey ? await setUpGateway({
|
|
20263
20426
|
token,
|
|
20264
|
-
org
|
|
20265
|
-
|
|
20266
|
-
|
|
20267
|
-
|
|
20268
|
-
|
|
20269
|
-
|
|
20270
|
-
|
|
20271
|
-
|
|
20272
|
-
|
|
20273
|
-
|
|
20274
|
-
|
|
20275
|
-
|
|
20276
|
-
|
|
20277
|
-
})();
|
|
20278
|
-
}
|
|
20427
|
+
org,
|
|
20428
|
+
projectName,
|
|
20429
|
+
signal
|
|
20430
|
+
}) : void 0
|
|
20431
|
+
};
|
|
20432
|
+
} catch (error) {
|
|
20433
|
+
if (error instanceof LoginCancelledError || error instanceof OrgSelectionCancelledError) return { status: "cancelled" };
|
|
20434
|
+
return {
|
|
20435
|
+
status: "failed",
|
|
20436
|
+
error
|
|
20437
|
+
};
|
|
20438
|
+
}
|
|
20439
|
+
})();
|
|
20279
20440
|
}
|
|
20280
20441
|
}
|
|
20281
20442
|
const selectedTemplate = mode === "empty" ? void 0 : await resolveTemplate(mode, options.template);
|
|
@@ -20327,7 +20488,7 @@ const create = async (args) => {
|
|
|
20327
20488
|
targetDir: staging.rootPath,
|
|
20328
20489
|
branch,
|
|
20329
20490
|
signal: materializationController.signal,
|
|
20330
|
-
...
|
|
20491
|
+
...platformSetupPromise ? { silent: true } : {}
|
|
20331
20492
|
});
|
|
20332
20493
|
if (isManaged) {
|
|
20333
20494
|
const providerConfig = await adaptDefaultTemplate({
|
|
@@ -20345,7 +20506,7 @@ const create = async (args) => {
|
|
|
20345
20506
|
}
|
|
20346
20507
|
}
|
|
20347
20508
|
if (options.install) {
|
|
20348
|
-
if (
|
|
20509
|
+
if (platformSetupPromise) await installDependencies(staging.projectPath, packageManager, options.timeout, materializationController.signal, true);
|
|
20349
20510
|
else await installDependencies(staging.projectPath, packageManager, options.timeout, materializationController.signal);
|
|
20350
20511
|
}
|
|
20351
20512
|
materializationController.signal.throwIfAborted();
|
|
@@ -20370,7 +20531,7 @@ const create = async (args) => {
|
|
|
20370
20531
|
if (platformSetupPromise) {
|
|
20371
20532
|
platformSetup = await platformSetupPromise;
|
|
20372
20533
|
if (platformSetup.status === "cancelled" && !interruptionSignal) {
|
|
20373
|
-
analytics?.trackEvent("cli_observability_outcome", {
|
|
20534
|
+
if (observabilityEnabled) analytics?.trackEvent("cli_observability_outcome", {
|
|
20374
20535
|
command: "create",
|
|
20375
20536
|
outcome: "skipped"
|
|
20376
20537
|
});
|
|
@@ -20384,6 +20545,7 @@ const create = async (args) => {
|
|
|
20384
20545
|
} else await materializationPromise;
|
|
20385
20546
|
process.removeListener("SIGINT", handleSigint);
|
|
20386
20547
|
process.removeListener("SIGTERM", handleSigterm);
|
|
20548
|
+
if (interruptionSignal || materializationError) await discardUnusedGatewayKey(platformSetup);
|
|
20387
20549
|
if (interruptionSignal === "SIGINT") {
|
|
20388
20550
|
if (observabilityEnabled) analytics?.trackEvent("cli_observability_outcome", {
|
|
20389
20551
|
command: "create",
|
|
@@ -20407,10 +20569,16 @@ const create = async (args) => {
|
|
|
20407
20569
|
const setupSummary = formatPostCreateSetup(postSetup);
|
|
20408
20570
|
if (postSetup.hasFailure) log.warn(setupSummary);
|
|
20409
20571
|
else log.success(setupSummary);
|
|
20572
|
+
let gatewaySummary;
|
|
20573
|
+
if (needsGatewayKey) gatewaySummary = await finishGatewaySetup({
|
|
20574
|
+
projectPath: targetPath,
|
|
20575
|
+
platformSetup,
|
|
20576
|
+
analytics
|
|
20577
|
+
});
|
|
20410
20578
|
let observabilitySummary;
|
|
20411
20579
|
let platformEnvWritten = false;
|
|
20412
|
-
let platformError = platformSetup?.status === "failed" ? platformSetup.error : void 0;
|
|
20413
|
-
if (platformSetup?.status === "ready") try {
|
|
20580
|
+
let platformError = observabilityEnabled && platformSetup?.status === "failed" ? platformSetup.error : void 0;
|
|
20581
|
+
if (observabilityEnabled && platformSetup?.status === "ready") try {
|
|
20414
20582
|
const result = await provisionObservabilityProject({
|
|
20415
20583
|
defaultProjectName: projectName,
|
|
20416
20584
|
mode: "create",
|
|
@@ -20446,7 +20614,7 @@ const create = async (args) => {
|
|
|
20446
20614
|
observabilitySummary = `${import_picocolors.default.yellow("Could not connect this project to Mastra platform automatically:")} ${message}\n\n${placeholderSummary}1. Visit ${import_picocolors.default.cyan("https://projects.mastra.ai")} to create a project and an access token.\n2. Paste the token into ${import_picocolors.default.cyan("MASTRA_PLATFORM_ACCESS_TOKEN")} and the project id into ${import_picocolors.default.cyan("MASTRA_PROJECT_ID")}.`;
|
|
20447
20615
|
}
|
|
20448
20616
|
if (mode === "managed") {
|
|
20449
|
-
const apiKeySummary = llmApiKey ? selectedApiKeyWritten ? `Your ${selectedApiKeyEnv} value was written to ${import_picocolors.default.cyan(".env")}.` : `Set ${selectedApiKeyEnv} in ${import_picocolors.default.cyan(".env")} before starting.` : platformEnvWritten ? `Set ${selectedApiKeyEnv} in ${import_picocolors.default.cyan(".env")} before starting.` : `Copy ${import_picocolors.default.cyan(".env.example")} to ${import_picocolors.default.cyan(".env")} and set ${selectedApiKeyEnv} before starting.`;
|
|
20617
|
+
const apiKeySummary = gatewaySummary ? gatewaySummary : llmApiKey ? selectedApiKeyWritten ? `Your ${selectedApiKeyEnv} value was written to ${import_picocolors.default.cyan(".env")}.` : `Set ${selectedApiKeyEnv} in ${import_picocolors.default.cyan(".env")} before starting.` : platformEnvWritten ? `Set ${selectedApiKeyEnv} in ${import_picocolors.default.cyan(".env")} before starting.` : `Copy ${import_picocolors.default.cyan(".env.example")} to ${import_picocolors.default.cyan(".env")} and set ${selectedApiKeyEnv} before starting.`;
|
|
20450
20618
|
note(`${import_picocolors.default.green("Success!")}\n\n${apiKeySummary}${observabilitySummary ? `\n\n${observabilitySummary}` : ""}`);
|
|
20451
20619
|
} else if (mode === "template") note(`${import_picocolors.default.green("Success!")}\n\nCreate a ${import_picocolors.default.cyan(".env")} file if the template requires environment variables.`);
|
|
20452
20620
|
postCreate({
|
|
@@ -20454,6 +20622,109 @@ const create = async (args) => {
|
|
|
20454
20622
|
packageManager
|
|
20455
20623
|
});
|
|
20456
20624
|
};
|
|
20625
|
+
async function setUpGateway({ token, org, projectName, signal }) {
|
|
20626
|
+
const spinner$2 = spinner();
|
|
20627
|
+
spinner$2.start("Setting up your Gateway key...");
|
|
20628
|
+
let spinning = true;
|
|
20629
|
+
let key;
|
|
20630
|
+
try {
|
|
20631
|
+
key = await createGatewayApiKey(token, org.orgId, projectName, signal);
|
|
20632
|
+
let credits;
|
|
20633
|
+
try {
|
|
20634
|
+
credits = await getGatewayCredits(token, org.orgId, signal);
|
|
20635
|
+
} catch (error) {
|
|
20636
|
+
if (signal.aborted) throw error;
|
|
20637
|
+
}
|
|
20638
|
+
spinner$2.stop(`Created a Gateway key in ${org.orgName}.`);
|
|
20639
|
+
spinning = false;
|
|
20640
|
+
let openedDashboard = false;
|
|
20641
|
+
if (credits) try {
|
|
20642
|
+
openedDashboard = await offerGatewayCredits({
|
|
20643
|
+
orgId: org.orgId,
|
|
20644
|
+
credits,
|
|
20645
|
+
signal
|
|
20646
|
+
});
|
|
20647
|
+
} catch (error) {
|
|
20648
|
+
if (signal.aborted) throw error;
|
|
20649
|
+
}
|
|
20650
|
+
return {
|
|
20651
|
+
status: "ready",
|
|
20652
|
+
apiKey: key.apiKey,
|
|
20653
|
+
keyId: key.keyId,
|
|
20654
|
+
orgName: org.orgName,
|
|
20655
|
+
creditsUrl: creditsPageUrl(org.orgId),
|
|
20656
|
+
remaining: credits?.remaining,
|
|
20657
|
+
unlimited: credits?.unlimited,
|
|
20658
|
+
openedDashboard
|
|
20659
|
+
};
|
|
20660
|
+
} catch (error) {
|
|
20661
|
+
if (spinning) spinner$2.stop("Could not set up a Gateway key.");
|
|
20662
|
+
if (signal.aborted) {
|
|
20663
|
+
await discardGatewayKey({
|
|
20664
|
+
token,
|
|
20665
|
+
orgId: org.orgId,
|
|
20666
|
+
keyId: key?.keyId
|
|
20667
|
+
});
|
|
20668
|
+
throw error;
|
|
20669
|
+
}
|
|
20670
|
+
return {
|
|
20671
|
+
status: "failed",
|
|
20672
|
+
error
|
|
20673
|
+
};
|
|
20674
|
+
}
|
|
20675
|
+
}
|
|
20676
|
+
/** Revoke a key no project ended up with. Best effort: a failure here shouldn't hide the real one. */
|
|
20677
|
+
async function discardGatewayKey({ token, orgId, keyId }) {
|
|
20678
|
+
if (!keyId) return;
|
|
20679
|
+
try {
|
|
20680
|
+
await revokeGatewayApiKey(token, orgId, keyId);
|
|
20681
|
+
} catch {}
|
|
20682
|
+
}
|
|
20683
|
+
/** The Gateway key that was created but won't be written to a project. */
|
|
20684
|
+
async function discardUnusedGatewayKey(platformSetup) {
|
|
20685
|
+
if (platformSetup?.status !== "ready" || platformSetup.gateway?.status !== "ready") return;
|
|
20686
|
+
await discardGatewayKey({
|
|
20687
|
+
token: platformSetup.token,
|
|
20688
|
+
orgId: platformSetup.org.orgId,
|
|
20689
|
+
keyId: platformSetup.gateway.keyId
|
|
20690
|
+
});
|
|
20691
|
+
}
|
|
20692
|
+
async function finishGatewaySetup({ projectPath, platformSetup, analytics }) {
|
|
20693
|
+
const envName = import_picocolors.default.cyan(GATEWAY_API_KEY_ENV);
|
|
20694
|
+
const manualSteps = `Get a key at ${import_picocolors.default.cyan("https://gateway.mastra.ai")} and set ${envName} in ${import_picocolors.default.cyan(".env")}.`;
|
|
20695
|
+
const gateway = platformSetup?.status === "ready" ? platformSetup.gateway : void 0;
|
|
20696
|
+
if (gateway?.status !== "ready") {
|
|
20697
|
+
const error = gateway?.status === "failed" ? gateway.error : platformSetup?.status === "failed" ? platformSetup.error : void 0;
|
|
20698
|
+
analytics?.trackEvent("cli_gateway_outcome", {
|
|
20699
|
+
command: "create",
|
|
20700
|
+
outcome: error ? "failed" : "skipped"
|
|
20701
|
+
});
|
|
20702
|
+
return `${error instanceof Error ? `${import_picocolors.default.yellow("Could not create a Gateway key:")} ${error.message}\n\n` : ""}${manualSteps}`;
|
|
20703
|
+
}
|
|
20704
|
+
if (!await writeManagedApiKey({
|
|
20705
|
+
projectPath,
|
|
20706
|
+
apiKeyEnv: "MASTRA_GATEWAY_API_KEY",
|
|
20707
|
+
apiKey: gateway.apiKey
|
|
20708
|
+
})) {
|
|
20709
|
+
await discardUnusedGatewayKey(platformSetup);
|
|
20710
|
+
analytics?.trackEvent("cli_gateway_outcome", {
|
|
20711
|
+
command: "create",
|
|
20712
|
+
outcome: "failed"
|
|
20713
|
+
});
|
|
20714
|
+
return `${import_picocolors.default.yellow("Could not write the Gateway key to .env.")}\n\n${manualSteps}`;
|
|
20715
|
+
}
|
|
20716
|
+
analytics?.trackEvent("cli_gateway_outcome", {
|
|
20717
|
+
command: "create",
|
|
20718
|
+
outcome: "completed",
|
|
20719
|
+
opened_dashboard: gateway.openedDashboard ?? false
|
|
20720
|
+
});
|
|
20721
|
+
const written = `Your Gateway key was written to ${import_picocolors.default.cyan(".env")} as ${envName}.`;
|
|
20722
|
+
const creditsUrl = import_picocolors.default.cyan(gateway.creditsUrl);
|
|
20723
|
+
if (gateway.unlimited) return `${written}\n${gateway.orgName} has unlimited Gateway credits.`;
|
|
20724
|
+
if (gateway.remaining === void 0) return `${written}\nModel calls are paid per token from Gateway credits. Check your balance in the Mastra dashboard: ${creditsUrl}`;
|
|
20725
|
+
if (gateway.remaining === 0) return `${written}\n${import_picocolors.default.yellow("Model calls fail until you add Gateway credits:")} ${creditsUrl}`;
|
|
20726
|
+
return `${written}\nBalance: ${formatCredits(gateway.remaining)} in ${gateway.orgName}. Model calls are paid per token from these credits.`;
|
|
20727
|
+
}
|
|
20457
20728
|
async function runPostCreateSetup({ projectPath, installSkills, initializeGit, invocationIsGitWorktree }) {
|
|
20458
20729
|
let skillsAgents = [];
|
|
20459
20730
|
let skillsOutcome = "opted_out";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-mastra",
|
|
3
|
-
"version": "1.37.0-alpha.
|
|
3
|
+
"version": "1.37.0-alpha.3",
|
|
4
4
|
"description": "Create Mastra apps with one command",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"typescript": "^7.0.2",
|
|
38
38
|
"vitest": "4.1.12",
|
|
39
39
|
"@internal/lint": "0.0.146",
|
|
40
|
-
"mastra": "^1.37.0-alpha.
|
|
40
|
+
"mastra": "^1.37.0-alpha.3"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=22.13.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { t as fetchOrgs } from "./api-CV5-CXEm-Cpd49bi2.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { i as loadCredentials, o as tryRefreshToken } from "./credentials-HeXP-kY2-jky92lr5.js";
|