@moda-ai/cli 1.55.10 → 1.55.12
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/agent-rd9deae9.js +459 -0
- package/dist/cli-09rr5smg.js +30 -0
- package/dist/cli-34zdvcpg.js +811 -0
- package/dist/cli-4qe6n8am.js +345 -0
- package/dist/cli-4x9w6ey7.js +70 -0
- package/dist/{cli-d3c95kks.js → cli-90hb4ng0.js} +18 -1733
- package/dist/cli-97fnztpy.js +140 -0
- package/dist/{cli-7s48d6ty.js → cli-bfmn3bsk.js} +2 -2
- package/dist/cli-k7vwt56h.js +496 -0
- package/dist/{cli-0qnghzg4.js → cli-kwz900s4.js} +95 -85
- package/dist/{cli-v27q5dvh.js → cli-m0fa54ny.js} +189 -970
- package/dist/cli-ryd7nzke.js +159 -0
- package/dist/{cli-4f0p8erk.js → cli-ssqb8bfw.js} +5 -7
- package/dist/cli-y8gbbe9k.js +946 -0
- package/dist/cli.js +1461 -7021
- package/dist/doctor-8yb6r66e.js +23 -0
- package/dist/fix-bt5zn07e.js +1444 -0
- package/dist/{harness-0tnqw849.js → harness-9psndqtm.js} +7 -2
- package/dist/{harness-github-actions-wpkr7jjr.js → harness-github-actions-nph5t2s7.js} +7 -2
- package/dist/{index-jqexf7kn.js → index-qjaprhrv.js} +31 -20
- package/dist/production-intelligence-mg3qp2dg.js +1802 -0
- package/dist/profile-commands-2g5bjzj2.js +481 -0
- package/dist/prompt-source-mcp.js +7 -2
- package/dist/prompts-mzazn8ce.js +40 -0
- package/dist/{provision-5pkn25hh.js → provision-rm0yc08f.js} +7 -5
- package/dist/registry-mbz65bjy.js +1201 -0
- package/dist/skills-sagxq9sc.js +19 -0
- package/dist/sync-gkwexz68.js +54 -0
- package/package.json +6 -6
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +10 -4
|
@@ -576,6 +576,19 @@ class CliAuthError extends Error {
|
|
|
576
576
|
usage;
|
|
577
577
|
}
|
|
578
578
|
|
|
579
|
+
class CliNotFoundError extends Error {
|
|
580
|
+
entity;
|
|
581
|
+
id;
|
|
582
|
+
usage;
|
|
583
|
+
constructor(entity, id, message, usage) {
|
|
584
|
+
super(message ?? `No ${entity} found for id "${id}" in this tenant.`);
|
|
585
|
+
this.entity = entity;
|
|
586
|
+
this.id = id;
|
|
587
|
+
this.usage = usage;
|
|
588
|
+
this.name = "CliNotFoundError";
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
579
592
|
class CliCancellationError extends Error {
|
|
580
593
|
constructor(message) {
|
|
581
594
|
super(message);
|
|
@@ -588,6 +601,12 @@ function isNetworkLikeError(error) {
|
|
|
588
601
|
function isApiLikeError(error) {
|
|
589
602
|
return error instanceof Error && (error.name === "ApiError" || ("statusCode" in error) && typeof error.statusCode === "number");
|
|
590
603
|
}
|
|
604
|
+
function apiErrorStatus(error) {
|
|
605
|
+
if (!isApiLikeError(error))
|
|
606
|
+
return;
|
|
607
|
+
const status = error.statusCode;
|
|
608
|
+
return typeof status === "number" ? status : undefined;
|
|
609
|
+
}
|
|
591
610
|
|
|
592
611
|
// src/config.ts
|
|
593
612
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
@@ -640,9 +659,9 @@ function resolveModaBaseUrl(options = {}) {
|
|
|
640
659
|
}
|
|
641
660
|
function validateConfig() {
|
|
642
661
|
if (!resolveApiKey()) {
|
|
643
|
-
throw new CliAuthError('No Moda API key found. Set MODA_API_KEY or run "moda init".', {
|
|
662
|
+
throw new CliAuthError('No Moda API key found. Set MODA_API_KEY=moda_sk_... in the environment, save one with "moda auth login --api-key", or run "moda init" for interactive setup.', {
|
|
644
663
|
reason: "no_stored_credentials",
|
|
645
|
-
login_command: ["moda", "
|
|
664
|
+
login_command: ["moda", "auth", "login", "--api-key"]
|
|
646
665
|
}, "Get your API key from https://moda.dev/settings");
|
|
647
666
|
}
|
|
648
667
|
}
|
|
@@ -1004,9 +1023,16 @@ import { randomUUID } from "node:crypto";
|
|
|
1004
1023
|
import { lstatSync, mkdirSync as mkdirSync2, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1005
1024
|
import { tmpdir } from "node:os";
|
|
1006
1025
|
import { join as join2 } from "node:path";
|
|
1026
|
+
var agentUpdateNotice;
|
|
1027
|
+
function setAgentUpdateNotice(notice) {
|
|
1028
|
+
agentUpdateNotice = notice;
|
|
1029
|
+
}
|
|
1030
|
+
function resolveAgentUpdateNotice() {
|
|
1031
|
+
return typeof agentUpdateNotice === "function" ? agentUpdateNotice() : agentUpdateNotice;
|
|
1032
|
+
}
|
|
1007
1033
|
var AGENT_SCHEMA_VERSION = "moda.agent.v1";
|
|
1008
1034
|
var AGENT_EVENT_SCHEMA_VERSION = "moda.agent_event.v1";
|
|
1009
|
-
var FEEDBACK_TIP = '
|
|
1035
|
+
var FEEDBACK_TIP = 'If a result looks wrong or is missing data: moda feedback "<what looked wrong>"';
|
|
1010
1036
|
var EXIT_OK = 0;
|
|
1011
1037
|
var EXIT_ERROR = 1;
|
|
1012
1038
|
var EXIT_DEGRADED = 3;
|
|
@@ -1024,7 +1050,8 @@ var AGENT_ERROR_CODES = [
|
|
|
1024
1050
|
"access_denied",
|
|
1025
1051
|
"unknown_error",
|
|
1026
1052
|
"cloud_unavailable",
|
|
1027
|
-
"output_error"
|
|
1053
|
+
"output_error",
|
|
1054
|
+
"not_found"
|
|
1028
1055
|
];
|
|
1029
1056
|
var FALLBACK_RUN_ID = randomUUID();
|
|
1030
1057
|
var fallbackSeq = 0;
|
|
@@ -1139,8 +1166,10 @@ function createCliOutput(options) {
|
|
|
1139
1166
|
startedAt: Date.now(),
|
|
1140
1167
|
lastEventAt: Date.now()
|
|
1141
1168
|
};
|
|
1142
|
-
const emitEvent = (event) => {
|
|
1143
|
-
if (options.
|
|
1169
|
+
const emitEvent = (event, { bypassQuiet = false } = {}) => {
|
|
1170
|
+
if (options.mode !== "agent-stream")
|
|
1171
|
+
return;
|
|
1172
|
+
if (options.quiet && !bypassQuiet)
|
|
1144
1173
|
return;
|
|
1145
1174
|
if (state.terminal)
|
|
1146
1175
|
return;
|
|
@@ -1156,16 +1185,19 @@ function createCliOutput(options) {
|
|
|
1156
1185
|
safeWriteStdout(`${JSON.stringify(createAgentEvent(options.command, event, state))}
|
|
1157
1186
|
`);
|
|
1158
1187
|
};
|
|
1159
|
-
const ensureStarted = () => {
|
|
1160
|
-
if (options.mode !== "agent-stream" || state.started
|
|
1188
|
+
const ensureStarted = ({ bypassQuiet = false } = {}) => {
|
|
1189
|
+
if (options.mode !== "agent-stream" || state.started)
|
|
1161
1190
|
return;
|
|
1162
|
-
|
|
1191
|
+
if (options.quiet && !bypassQuiet)
|
|
1192
|
+
return;
|
|
1193
|
+
if (!options.quiet)
|
|
1194
|
+
startHeartbeat(options.command, state);
|
|
1163
1195
|
emitEvent({
|
|
1164
1196
|
event: "started",
|
|
1165
1197
|
phase: options.command,
|
|
1166
1198
|
message: `Starting ${options.command}.`,
|
|
1167
1199
|
elapsed_ms: 0
|
|
1168
|
-
});
|
|
1200
|
+
}, { bypassQuiet });
|
|
1169
1201
|
};
|
|
1170
1202
|
const writeEnvelope = (data, writeOptions = {}) => {
|
|
1171
1203
|
return createAgentEnvelope({
|
|
@@ -1175,7 +1207,8 @@ function createCliOutput(options) {
|
|
|
1175
1207
|
meta: {
|
|
1176
1208
|
...writeOptions.meta ?? {},
|
|
1177
1209
|
run_id: state.runId,
|
|
1178
|
-
...options.command === "feedback" ? {} : { tip: FEEDBACK_TIP }
|
|
1210
|
+
...options.command === "feedback" ? {} : { tip: FEEDBACK_TIP },
|
|
1211
|
+
...((update) => update ? { update } : {})(resolveAgentUpdateNotice())
|
|
1179
1212
|
},
|
|
1180
1213
|
summary: writeOptions.summary,
|
|
1181
1214
|
findings: writeOptions.findings,
|
|
@@ -1235,12 +1268,12 @@ function createCliOutput(options) {
|
|
|
1235
1268
|
emitEvent(event);
|
|
1236
1269
|
},
|
|
1237
1270
|
writeError(error) {
|
|
1238
|
-
if (
|
|
1271
|
+
if (state.terminal)
|
|
1239
1272
|
return;
|
|
1240
1273
|
const agentError = errorToAgentError(error);
|
|
1241
1274
|
const envelope = createAgentErrorEnvelope(options.command || "unknown", agentError, state.runId, errorWarnings(error));
|
|
1242
1275
|
if (options.mode === "agent-stream") {
|
|
1243
|
-
ensureStarted();
|
|
1276
|
+
ensureStarted({ bypassQuiet: true });
|
|
1244
1277
|
if (error instanceof CliInputRequiredError) {
|
|
1245
1278
|
emitEvent({
|
|
1246
1279
|
event: "needs_input",
|
|
@@ -1249,18 +1282,18 @@ function createCliOutput(options) {
|
|
|
1249
1282
|
error: agentError,
|
|
1250
1283
|
input_request: error.input_request,
|
|
1251
1284
|
result: envelope
|
|
1252
|
-
});
|
|
1285
|
+
}, { bypassQuiet: true });
|
|
1253
1286
|
return;
|
|
1254
1287
|
}
|
|
1255
|
-
if (error instanceof CliAuthError) {
|
|
1288
|
+
if (error instanceof CliAuthError || agentError.code === "auth_required") {
|
|
1256
1289
|
emitEvent({
|
|
1257
1290
|
event: "auth_required",
|
|
1258
1291
|
status: "error",
|
|
1259
|
-
message:
|
|
1292
|
+
message: agentError.message,
|
|
1260
1293
|
error: agentError,
|
|
1261
|
-
auth: error.auth,
|
|
1294
|
+
auth: error instanceof CliAuthError ? error.auth : agentError.auth,
|
|
1262
1295
|
result: envelope
|
|
1263
|
-
});
|
|
1296
|
+
}, { bypassQuiet: true });
|
|
1264
1297
|
return;
|
|
1265
1298
|
}
|
|
1266
1299
|
if (error instanceof CliCancellationError) {
|
|
@@ -1270,7 +1303,7 @@ function createCliOutput(options) {
|
|
|
1270
1303
|
message: error.message,
|
|
1271
1304
|
error: agentError,
|
|
1272
1305
|
result: envelope
|
|
1273
|
-
});
|
|
1306
|
+
}, { bypassQuiet: true });
|
|
1274
1307
|
return;
|
|
1275
1308
|
}
|
|
1276
1309
|
emitEvent({
|
|
@@ -1279,7 +1312,7 @@ function createCliOutput(options) {
|
|
|
1279
1312
|
message: agentError.message,
|
|
1280
1313
|
error: agentError,
|
|
1281
1314
|
result: envelope
|
|
1282
|
-
});
|
|
1315
|
+
}, { bypassQuiet: true });
|
|
1283
1316
|
return;
|
|
1284
1317
|
}
|
|
1285
1318
|
if (options.mode === "agent" || options.mode === "json") {
|
|
@@ -1549,6 +1582,20 @@ function formatValidationMessage(error) {
|
|
|
1549
1582
|
});
|
|
1550
1583
|
return `Validation error — ${[...new Set(parts)].join("; ")}`;
|
|
1551
1584
|
}
|
|
1585
|
+
var API_KEY_RECOVERY = "Set MODA_API_KEY=moda_sk_... in the environment, or save one with `moda auth login --api-key` (reads MODA_API_KEY or --api-key-stdin). Keys: https://moda.dev/settings";
|
|
1586
|
+
function serverErrorMessage(error) {
|
|
1587
|
+
const body = error.responseBody;
|
|
1588
|
+
if (typeof body !== "string" || !body.trimStart().startsWith("{"))
|
|
1589
|
+
return;
|
|
1590
|
+
try {
|
|
1591
|
+
const message = JSON.parse(body).message;
|
|
1592
|
+
if (typeof message === "string" && message.trim())
|
|
1593
|
+
return message.trim().replace(/\.$/, "");
|
|
1594
|
+
if (Array.isArray(message))
|
|
1595
|
+
return message.filter((m) => typeof m === "string").join("; ") || undefined;
|
|
1596
|
+
} catch {}
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1552
1599
|
function errorToAgentError(error) {
|
|
1553
1600
|
if (error instanceof CliInputRequiredError) {
|
|
1554
1601
|
return {
|
|
@@ -1580,6 +1627,15 @@ function errorToAgentError(error) {
|
|
|
1580
1627
|
blocking: true
|
|
1581
1628
|
};
|
|
1582
1629
|
}
|
|
1630
|
+
if (error instanceof CliNotFoundError) {
|
|
1631
|
+
return {
|
|
1632
|
+
code: "not_found",
|
|
1633
|
+
message: error.message,
|
|
1634
|
+
cause: error.usage,
|
|
1635
|
+
suggested_commands: error.usage ? extractSuggestedCommands(error.usage) : undefined,
|
|
1636
|
+
blocking: true
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1583
1639
|
if (error instanceof CliAccessError) {
|
|
1584
1640
|
return {
|
|
1585
1641
|
code: "access_denied",
|
|
@@ -1598,6 +1654,24 @@ function errorToAgentError(error) {
|
|
|
1598
1654
|
blocking: true
|
|
1599
1655
|
};
|
|
1600
1656
|
}
|
|
1657
|
+
if (apiErrorStatus(error) === 401) {
|
|
1658
|
+
return {
|
|
1659
|
+
code: "auth_required",
|
|
1660
|
+
message: "The Moda API rejected the API key (HTTP 401): it is invalid, revoked, or for another environment.",
|
|
1661
|
+
cause: API_KEY_RECOVERY,
|
|
1662
|
+
suggested_commands: ["moda auth login --api-key", "moda auth status --online"],
|
|
1663
|
+
auth: { reason: "api_key_rejected", login_command: ["moda", "auth", "login", "--api-key"] },
|
|
1664
|
+
blocking: true
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
if (apiErrorStatus(error) === 403) {
|
|
1668
|
+
return {
|
|
1669
|
+
code: "access_denied",
|
|
1670
|
+
message: `The Moda API refused this request (HTTP 403): ${serverErrorMessage(error) ?? "the API key does not allow it"}.`,
|
|
1671
|
+
cause: "Read-only keys cannot run writes, and organization keys cannot select another tenant. Use a key with the needed access.",
|
|
1672
|
+
blocking: true
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1601
1675
|
if (isApiLikeError(error)) {
|
|
1602
1676
|
const statusCode = "statusCode" in error ? error.statusCode : undefined;
|
|
1603
1677
|
const typedCode = "code" in error && typeof error.code === "string" ? error.code : undefined;
|
|
@@ -1871,68 +1945,4 @@ function extractSuggestedCommands(text) {
|
|
|
1871
1945
|
return commands.length > 0 ? commands : undefined;
|
|
1872
1946
|
}
|
|
1873
1947
|
|
|
1874
|
-
|
|
1875
|
-
function flagEnabled(flags, key) {
|
|
1876
|
-
return flags[key] === "true";
|
|
1877
|
-
}
|
|
1878
|
-
var BOOLEAN_TRUE_WORDS = new Set(["true", "yes", "1", "on"]);
|
|
1879
|
-
var BOOLEAN_FALSE_WORDS = new Set(["false", "no", "0", "off"]);
|
|
1880
|
-
function parseBooleanFlagValue(value) {
|
|
1881
|
-
if (typeof value === "boolean")
|
|
1882
|
-
return value;
|
|
1883
|
-
if (typeof value === "number")
|
|
1884
|
-
return value === 1 ? true : value === 0 ? false : undefined;
|
|
1885
|
-
if (typeof value !== "string")
|
|
1886
|
-
return;
|
|
1887
|
-
const text = value.trim().toLowerCase();
|
|
1888
|
-
if (BOOLEAN_TRUE_WORDS.has(text))
|
|
1889
|
-
return true;
|
|
1890
|
-
if (BOOLEAN_FALSE_WORDS.has(text))
|
|
1891
|
-
return false;
|
|
1892
|
-
return;
|
|
1893
|
-
}
|
|
1894
|
-
function stringOption(value) {
|
|
1895
|
-
if (value === undefined || value === null)
|
|
1896
|
-
return;
|
|
1897
|
-
const text = String(value).trim();
|
|
1898
|
-
return text.length > 0 ? text : undefined;
|
|
1899
|
-
}
|
|
1900
|
-
function createCommandContext(input, options = {}) {
|
|
1901
|
-
const flags = options.commandFlags ?? input.flags;
|
|
1902
|
-
const rawFlags = options.rawFlags ?? input.flags;
|
|
1903
|
-
const outputMode = options.outputMode ?? outputModeFromFlags(flags);
|
|
1904
|
-
const quiet = flagEnabled(flags, "quiet");
|
|
1905
|
-
const interactive = outputMode === "human" && !quiet && !flagEnabled(flags, "yes") && process.stdin.isTTY === true && process.stderr.isTTY === true;
|
|
1906
|
-
const telemetryMeta = {};
|
|
1907
|
-
return {
|
|
1908
|
-
command: options.commandName ?? input.command,
|
|
1909
|
-
positional: input.positional,
|
|
1910
|
-
positionals: input.positionals,
|
|
1911
|
-
flags,
|
|
1912
|
-
rawFlags,
|
|
1913
|
-
...input.bareFlags ? { bareFlags: input.bareFlags } : {},
|
|
1914
|
-
startedAt: options.startedAt ?? Date.now(),
|
|
1915
|
-
cwd: options.cwd ?? process.cwd(),
|
|
1916
|
-
env: options.env ?? process.env,
|
|
1917
|
-
outputMode,
|
|
1918
|
-
output: createCliOutput({
|
|
1919
|
-
command: options.commandName ?? input.command,
|
|
1920
|
-
mode: outputMode,
|
|
1921
|
-
quiet
|
|
1922
|
-
}),
|
|
1923
|
-
profile: flags.profile,
|
|
1924
|
-
dryRun: flagEnabled(flags, "dry-run"),
|
|
1925
|
-
yes: flagEnabled(flags, "yes"),
|
|
1926
|
-
quiet,
|
|
1927
|
-
verbose: flagEnabled(flags, "verbose"),
|
|
1928
|
-
interactive,
|
|
1929
|
-
recordTelemetry(meta) {
|
|
1930
|
-
Object.assign(telemetryMeta, meta);
|
|
1931
|
-
},
|
|
1932
|
-
getTelemetryMeta() {
|
|
1933
|
-
return telemetryMeta;
|
|
1934
|
-
}
|
|
1935
|
-
};
|
|
1936
|
-
}
|
|
1937
|
-
|
|
1938
|
-
export { PROD_BASE_URL, DEFAULT_INGEST_URL, getModaPaths, getModaDir, isLoopbackBaseUrl, describeBaseUrlSource, loadProfileConfig, saveProfileConfig, getActiveProfile, setActiveProfile, upsertProfile, clearStoredApiKeyCredentials, secretFilePathFromRef, resolveSecretReference, resolveApiKeyFromActiveProfile, resolveTenantIdFromActiveProfile, ensureSecretFilePermissions, writeSecretJsonFile, CliInputError, CliAccessError, CliInputRequiredError, CliAuthError, CliCancellationError, isNetworkLikeError, isApiLikeError, VERSION, MODA_BASE_URL, loadCliConfig, saveCliConfig, resolveApiKey, embeddedTenantIdFromApiKey, resolveIngestUrl2 as resolveIngestUrl, resolveTenantId, resolveApiTenantId, resolveModaBaseUrl, validateConfig, recordApiRequest, getApiRequestCount, resetApiRequestCount, MAX_SCANNED_FILE_BYTES, DEFAULT_MAX_INVENTORY_FILES, DEFAULT_MAX_INVENTORY_TEXT_BYTES, MAX_RECORDED_SKIPS, SKIPPED_DIRS, isSkippedDir, isSkippedPathPrefix, isEvalLikePath, shouldInventoryFile, isTextFile, isSecretishPath, SECRET_KEYS, redactDeep, redactString, packSnapshot, EXIT_OK, EXIT_ERROR, EXIT_DEGRADED, EXIT_AUTH_REQUIRED, EXIT_INPUT_REQUIRED, EXIT_CANCELLED, AGENT_ERROR_CODES, wasOutputCancelled, safeWriteStdout, safeWriteStderr, explicitOutputMode, resolveOutputMode, createCliOutput, agentEnvelopeFits, agentMaxOutputBytes, parseBooleanFlagValue, stringOption, createCommandContext };
|
|
1948
|
+
export { PROD_BASE_URL, DEFAULT_INGEST_URL, getModaPaths, getModaDir, isLoopbackBaseUrl, describeBaseUrlSource, loadProfileConfig, saveProfileConfig, getActiveProfile, setActiveProfile, upsertProfile, clearStoredApiKeyCredentials, secretFilePathFromRef, resolveSecretReference, resolveApiKeyFromActiveProfile, resolveTenantIdFromActiveProfile, ensureSecretFilePermissions, writeSecretJsonFile, CliInputError, CliAccessError, CliInputRequiredError, CliAuthError, CliNotFoundError, CliCancellationError, isNetworkLikeError, isApiLikeError, apiErrorStatus, VERSION, MODA_BASE_URL, loadCliConfig, saveCliConfig, resolveApiKey, embeddedTenantIdFromApiKey, resolveIngestUrl2 as resolveIngestUrl, resolveTenantId, resolveApiTenantId, resolveModaBaseUrl, validateConfig, recordApiRequest, getApiRequestCount, resetApiRequestCount, MAX_SCANNED_FILE_BYTES, DEFAULT_MAX_INVENTORY_FILES, DEFAULT_MAX_INVENTORY_TEXT_BYTES, MAX_RECORDED_SKIPS, SKIPPED_DIRS, isSkippedDir, isSkippedPathPrefix, isEvalLikePath, shouldInventoryFile, isTextFile, isSecretishPath, SECRET_KEYS, redactDeep, redactString, packSnapshot, setAgentUpdateNotice, EXIT_OK, EXIT_ERROR, EXIT_DEGRADED, EXIT_AUTH_REQUIRED, EXIT_INPUT_REQUIRED, EXIT_CANCELLED, AGENT_ERROR_CODES, wasOutputCancelled, safeWriteStdout, safeWriteStderr, explicitOutputMode, outputModeFromFlags, resolveOutputMode, createCliOutput, agentEnvelopeFits, agentMaxOutputBytes };
|