@moda-ai/cli 1.37.0 → 1.38.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.
- package/dist/{cli-ert1sbbt.js → cli-3kcy61fr.js} +1 -1
- package/dist/{cli-qgf2cz2v.js → cli-k38j2fpq.js} +1 -1
- package/dist/{cli-strngwn3.js → cli-kegd748v.js} +66 -1
- package/dist/cli.js +6 -4
- package/dist/{index-vmmfya6b.js → index-hwfe7gs8.js} +39 -6
- package/dist/{provision-spwn5t41.js → provision-64c2n9aw.js} +2 -2
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
|
@@ -328,6 +328,71 @@ function getCachedLoginContext(options = {}) {
|
|
|
328
328
|
return null;
|
|
329
329
|
return cachedLoginContext.context;
|
|
330
330
|
}
|
|
331
|
+
var MISMATCH_MESSAGE = "The sign-in code is for a different workspace than --tenant-id.";
|
|
332
|
+
var CONNECT_CODE_RE = /^mcc_[A-Za-z0-9_-]{43}$/;
|
|
333
|
+
|
|
334
|
+
class ConnectCodeError extends Error {
|
|
335
|
+
reason;
|
|
336
|
+
constructor(message, reason) {
|
|
337
|
+
super(message);
|
|
338
|
+
this.reason = reason;
|
|
339
|
+
this.name = "ConnectCodeError";
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
async function connectWithCode(code, options = {}) {
|
|
343
|
+
if (!CONNECT_CODE_RE.test(code)) {
|
|
344
|
+
throw new ConnectCodeError("That is not a Moda sign-in code. Copy the command from the Moda onboarding page again.", "rejected");
|
|
345
|
+
}
|
|
346
|
+
let response;
|
|
347
|
+
try {
|
|
348
|
+
response = await fetch(`${resolveModaBaseUrl(options)}/api/cli/auth/connect`, {
|
|
349
|
+
method: "POST",
|
|
350
|
+
headers: { "Content-Type": "application/json" },
|
|
351
|
+
body: JSON.stringify({ code, label: hostname(), ...options.tenantId ? { tenant_id: options.tenantId } : {} }),
|
|
352
|
+
redirect: "manual",
|
|
353
|
+
signal: AbortSignal.timeout(EXCHANGE_TIMEOUT_MS)
|
|
354
|
+
});
|
|
355
|
+
} catch {
|
|
356
|
+
throw new ConnectCodeError("Could not reach Moda to use the sign-in code.", "unreachable");
|
|
357
|
+
}
|
|
358
|
+
if (response.status === 400) {
|
|
359
|
+
const body = await response.json().catch(() => ({}));
|
|
360
|
+
if (body.error === "tenant_mismatch") {
|
|
361
|
+
throw new ConnectCodeError(MISMATCH_MESSAGE, "workspace_mismatch");
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (response.status === 401 || response.status === 400) {
|
|
365
|
+
throw new ConnectCodeError("The sign-in code was rejected: it expired (10 minutes) or was already used.", "rejected");
|
|
366
|
+
}
|
|
367
|
+
if (!response.ok || response.status >= 300 && response.status < 400) {
|
|
368
|
+
throw new ConnectCodeError(`Moda could not use the sign-in code (HTTP ${response.status}).`, "failed");
|
|
369
|
+
}
|
|
370
|
+
const payload = await response.json().catch(() => ({}));
|
|
371
|
+
const cliToken = typeof payload.cli_token === "string" ? payload.cli_token : undefined;
|
|
372
|
+
const expiresAtMs = typeof payload.expires_at === "string" ? Date.parse(payload.expires_at) : NaN;
|
|
373
|
+
const tenantId = typeof payload.tenant_id === "string" ? payload.tenant_id : undefined;
|
|
374
|
+
if (!cliToken || !Number.isFinite(expiresAtMs) || !tenantId) {
|
|
375
|
+
throw new ConnectCodeError("Moda returned an incomplete response for the sign-in code.", "failed");
|
|
376
|
+
}
|
|
377
|
+
if (options.tenantId && tenantId !== options.tenantId) {
|
|
378
|
+
throw new ConnectCodeError(MISMATCH_MESSAGE, "workspace_mismatch");
|
|
379
|
+
}
|
|
380
|
+
const userEmail = typeof payload.user?.email === "string" ? payload.user.email : undefined;
|
|
381
|
+
persistAuthSession({
|
|
382
|
+
access_token: cliToken,
|
|
383
|
+
expires_at: Math.floor(expiresAtMs / 1000),
|
|
384
|
+
profile: resolveStorageProfile(options),
|
|
385
|
+
token_type: "bearer",
|
|
386
|
+
token_kind: "moda_ct",
|
|
387
|
+
...userEmail ? { user_email: userEmail } : {}
|
|
388
|
+
}, options);
|
|
389
|
+
const context = {
|
|
390
|
+
user: { email: userEmail ?? "", name: typeof payload.user?.name === "string" ? payload.user.name : null },
|
|
391
|
+
tenants: Array.isArray(payload.tenants) ? payload.tenants : []
|
|
392
|
+
};
|
|
393
|
+
cachedLoginContext = { profile: resolveStorageProfile(options), context };
|
|
394
|
+
return { ...context, tenantId };
|
|
395
|
+
}
|
|
331
396
|
var SUCCESS_HTML = `<!DOCTYPE html>
|
|
332
397
|
<html><body style="font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#fafafa">
|
|
333
398
|
<div style="text-align:center">
|
|
@@ -761,4 +826,4 @@ function safeResolveUrl(location, base) {
|
|
|
761
826
|
}
|
|
762
827
|
}
|
|
763
828
|
|
|
764
|
-
export { isAuthSessionValid, loadToken, loadAuthSession, clearAuthSession, revokeCliSessionToken, getCachedLoginContext, login, authFetch };
|
|
829
|
+
export { isAuthSessionValid, loadToken, loadAuthSession, clearAuthSession, revokeCliSessionToken, getCachedLoginContext, ConnectCodeError, connectWithCode, login, authFetch };
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
runPromptsCommand,
|
|
9
9
|
runSkillsCommand,
|
|
10
10
|
runStatusCommand
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-3kcy61fr.js";
|
|
12
12
|
import {
|
|
13
13
|
ApiError,
|
|
14
14
|
HARNESS_REPORT_APPROVAL_PATH,
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
loadAuthSession,
|
|
39
39
|
login,
|
|
40
40
|
revokeCliSessionToken
|
|
41
|
-
} from "./cli-
|
|
41
|
+
} from "./cli-kegd748v.js";
|
|
42
42
|
import {
|
|
43
43
|
AGENT_ERROR_CODES,
|
|
44
44
|
CliAccessError,
|
|
@@ -5721,6 +5721,8 @@ Init flags:
|
|
|
5721
5721
|
--no-sdk-integrate Skip SDK integration (alias: --no-sdk-guide)
|
|
5722
5722
|
--verification-id=ID Tag the SDK integration's test trace with this id
|
|
5723
5723
|
(the onb_ id from the Moda onboarding page)
|
|
5724
|
+
--connect-code=CODE Sign in with the one-time mcc_ code from the Moda
|
|
5725
|
+
onboarding page instead of the browser (10 min, single use)
|
|
5724
5726
|
--ci-cd Create GitHub Actions Moda validation workflow
|
|
5725
5727
|
--no-ci-cd Skip CI/CD workflow creation
|
|
5726
5728
|
--autosync Create GitHub Actions workflow to sync prompts + skills to Moda on push to main
|
|
@@ -7084,7 +7086,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
7084
7086
|
resetApiRequestCountBeforeRun: true,
|
|
7085
7087
|
telemetry: "result",
|
|
7086
7088
|
handler: async (context) => {
|
|
7087
|
-
const { runInit } = await import("./index-
|
|
7089
|
+
const { runInit } = await import("./index-hwfe7gs8.js");
|
|
7088
7090
|
if (context.outputMode === "agent-stream") {
|
|
7089
7091
|
context.output.writeEvent({
|
|
7090
7092
|
event: "started",
|
|
@@ -7125,7 +7127,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
7125
7127
|
resetApiRequestCountBeforeRun: true,
|
|
7126
7128
|
telemetry: "result-and-error",
|
|
7127
7129
|
handler: async (context) => {
|
|
7128
|
-
const { runProvision } = await import("./provision-
|
|
7130
|
+
const { runProvision } = await import("./provision-64c2n9aw.js");
|
|
7129
7131
|
return runProvision(context, {
|
|
7130
7132
|
resumeCommand: buildResumeCommand("provision", context.rawFlags)
|
|
7131
7133
|
});
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
initPrompts,
|
|
4
4
|
runPromptSync,
|
|
5
5
|
runSkillSync
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-3kcy61fr.js";
|
|
7
7
|
import {
|
|
8
8
|
codingAgentDisplayName,
|
|
9
9
|
describeCodingAgentEvent,
|
|
@@ -34,11 +34,14 @@ import {
|
|
|
34
34
|
} from "./cli-ssfq84k5.js";
|
|
35
35
|
import {
|
|
36
36
|
selectTenantAndCreateKey
|
|
37
|
-
} from "./cli-
|
|
37
|
+
} from "./cli-k38j2fpq.js";
|
|
38
38
|
import {
|
|
39
|
+
ConnectCodeError,
|
|
40
|
+
connectWithCode,
|
|
41
|
+
loadAuthSession,
|
|
39
42
|
loadToken,
|
|
40
43
|
login
|
|
41
|
-
} from "./cli-
|
|
44
|
+
} from "./cli-kegd748v.js";
|
|
42
45
|
import {
|
|
43
46
|
CliAuthError,
|
|
44
47
|
CliInputError,
|
|
@@ -1643,6 +1646,32 @@ async function runInit(flags, options = {}) {
|
|
|
1643
1646
|
const profile = stringFlag(flags.profile);
|
|
1644
1647
|
log(renderInitStep(1, 5, "Sign in", "No environment variable files are written. File changes are listed before completion."));
|
|
1645
1648
|
let token = loadToken({ profile });
|
|
1649
|
+
const connectCode = stringFlag(flagValue(flags, "connect-code", "connect_code"));
|
|
1650
|
+
let codeTenantId;
|
|
1651
|
+
if (connectCode) {
|
|
1652
|
+
const previousEmail = token ? loadAuthSession({ profile })?.user_email : undefined;
|
|
1653
|
+
try {
|
|
1654
|
+
const connected = await connectWithCode(connectCode, {
|
|
1655
|
+
profile,
|
|
1656
|
+
tenantId: stringFlag(flagValue(flags, "tenant-id", "tenant_id"))
|
|
1657
|
+
});
|
|
1658
|
+
token = loadToken({ profile });
|
|
1659
|
+
codeTenantId = connected.tenantId;
|
|
1660
|
+
const email = connected.user.email || "your Moda account";
|
|
1661
|
+
const replaced = previousEmail && previousEmail !== connected.user.email ? ` (replacing the CLI session for ${previousEmail})` : "";
|
|
1662
|
+
log(renderInitNote(`Signed in as ${email} with the one-time code${replaced}`));
|
|
1663
|
+
emit("auth", `Signed in as ${email} with the one-time code${replaced}.`);
|
|
1664
|
+
} catch (error) {
|
|
1665
|
+
if (!(error instanceof ConnectCodeError))
|
|
1666
|
+
throw error;
|
|
1667
|
+
if (error.reason === "workspace_mismatch") {
|
|
1668
|
+
throw new CliInputError(error.message, "Copy the command again from the Moda onboarding page, or drop --tenant-id.");
|
|
1669
|
+
}
|
|
1670
|
+
const next = token ? `Continuing with your existing CLI session${previousEmail ? ` (${previousEmail})` : ""}.` : "Signing in through the browser instead.";
|
|
1671
|
+
warn(renderInitNote(`${error.message} ${next}`, "warning"));
|
|
1672
|
+
emit("auth", `${error.message} ${next}`, "warning");
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1646
1675
|
if (!token) {
|
|
1647
1676
|
if (json || agent || noPrompts) {
|
|
1648
1677
|
throw new CliAuthError("Browser authentication is required before non-interactive init can continue.", {
|
|
@@ -1652,7 +1681,8 @@ async function runInit(flags, options = {}) {
|
|
|
1652
1681
|
}, "Run `moda auth login`, then re-run `moda init`.");
|
|
1653
1682
|
}
|
|
1654
1683
|
let action = "login";
|
|
1655
|
-
|
|
1684
|
+
const fromDashboard = Boolean(connectCode || stringFlag(flagValue(flags, "tenant-id", "tenant_id")) || stringFlag(flagValue(flags, "verification-id", "verification_id")));
|
|
1685
|
+
if (!yes && !fromDashboard) {
|
|
1656
1686
|
action = await select({
|
|
1657
1687
|
message: "Get started",
|
|
1658
1688
|
choices: [
|
|
@@ -1673,14 +1703,17 @@ async function runInit(flags, options = {}) {
|
|
|
1673
1703
|
log(renderInitStep(2, 5, "Workspace"));
|
|
1674
1704
|
emit("workspace", "Selecting workspace and creating API key.");
|
|
1675
1705
|
const tenantIdFlag = stringFlag(flagValue(flags, "tenant-id", "tenant_id"));
|
|
1706
|
+
if (codeTenantId && tenantIdFlag && tenantIdFlag !== codeTenantId) {
|
|
1707
|
+
throw new CliInputError("The sign-in code is for a different workspace than --tenant-id.", "Copy the command again from the Moda onboarding page, or drop --tenant-id.");
|
|
1708
|
+
}
|
|
1676
1709
|
const verificationId = stringFlag(flagValue(flags, "verification-id", "verification_id"));
|
|
1677
1710
|
if (verificationId !== undefined && !isAcceptedVerificationId(verificationId)) {
|
|
1678
1711
|
throw new CliInputError(`Invalid --verification-id ${JSON.stringify(verificationId).slice(0, 80)}`, "Pass the onb_ id shown in the Moda onboarding page, or omit the flag.");
|
|
1679
1712
|
}
|
|
1680
1713
|
const tenantIdEnv = stringFlag(process.env.MODA_TENANT_ID);
|
|
1681
1714
|
const { apiKey, tenantId: selectedTenantId, tenantName } = await selectTenantAndCreateKey({
|
|
1682
|
-
tenantId: tenantIdFlag ?? tenantIdEnv,
|
|
1683
|
-
tenantIdSource: tenantIdFlag ? "flag" : tenantIdEnv ? "env" : undefined,
|
|
1715
|
+
tenantId: tenantIdFlag ?? codeTenantId ?? tenantIdEnv,
|
|
1716
|
+
tenantIdSource: tenantIdFlag || codeTenantId ? "flag" : tenantIdEnv ? "env" : undefined,
|
|
1684
1717
|
nonInteractive: json || agent || noPrompts,
|
|
1685
1718
|
silent: !human,
|
|
1686
1719
|
resumeCommand: ["moda", "init", ...resumeFlagsForInit(flags)],
|
package/package.json
CHANGED