@mutagent/cli 0.1.89 → 0.1.91
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/README.md +13 -8
- package/dist/bin/cli.js +1103 -1057
- package/dist/bin/cli.js.map +10 -9
- package/dist/index.js +15 -1
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -616,6 +616,20 @@ class SDKClientWrapper {
|
|
|
616
616
|
this.handleError(error);
|
|
617
617
|
}
|
|
618
618
|
}
|
|
619
|
+
async getDataset(datasetId) {
|
|
620
|
+
try {
|
|
621
|
+
return await this.request(`/api/prompts/datasets/${String(datasetId)}`);
|
|
622
|
+
} catch (error) {
|
|
623
|
+
this.handleError(error);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
async getDatasetItem(itemId) {
|
|
627
|
+
try {
|
|
628
|
+
return await this.request(`/api/prompts/dataset-items/${String(itemId)}`);
|
|
629
|
+
} catch (error) {
|
|
630
|
+
this.handleError(error);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
619
633
|
async listDatasets(promptId) {
|
|
620
634
|
try {
|
|
621
635
|
const response = await this.request(`/api/prompt/${promptId}/datasets`);
|
|
@@ -1142,7 +1156,7 @@ var init_sdk_client = __esm(() => {
|
|
|
1142
1156
|
|
|
1143
1157
|
// src/bin/cli.ts
|
|
1144
1158
|
import { Command as Command20 } from "commander";
|
|
1145
|
-
import
|
|
1159
|
+
import chalk32 from "chalk";
|
|
1146
1160
|
import { readFileSync as readFileSync12 } from "fs";
|
|
1147
1161
|
import { join as join10, dirname as dirname2 } from "path";
|
|
1148
1162
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -1151,9 +1165,7 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
1151
1165
|
init_config();
|
|
1152
1166
|
init_sdk_client();
|
|
1153
1167
|
import { Command } from "commander";
|
|
1154
|
-
import
|
|
1155
|
-
import chalk3 from "chalk";
|
|
1156
|
-
import ora from "ora";
|
|
1168
|
+
import chalk4 from "chalk";
|
|
1157
1169
|
import { existsSync as existsSync3 } from "fs";
|
|
1158
1170
|
import { join as join4 } from "path";
|
|
1159
1171
|
|
|
@@ -1304,143 +1316,6 @@ function createSpinner(text, isJson) {
|
|
|
1304
1316
|
// src/commands/auth.ts
|
|
1305
1317
|
init_errors();
|
|
1306
1318
|
|
|
1307
|
-
// src/lib/browser-auth.ts
|
|
1308
|
-
import { hostname, platform } from "os";
|
|
1309
|
-
function generateCliToken() {
|
|
1310
|
-
return crypto.randomUUID();
|
|
1311
|
-
}
|
|
1312
|
-
async function initBrowserAuth(endpoint, cliToken) {
|
|
1313
|
-
const response = await fetch(`${endpoint}/api/auth/cli/init`, {
|
|
1314
|
-
method: "POST",
|
|
1315
|
-
headers: { "Content-Type": "application/json" },
|
|
1316
|
-
body: JSON.stringify({
|
|
1317
|
-
cliToken,
|
|
1318
|
-
hostname: hostname(),
|
|
1319
|
-
platform: platform()
|
|
1320
|
-
})
|
|
1321
|
-
});
|
|
1322
|
-
if (!response.ok) {
|
|
1323
|
-
const errorText = await response.text();
|
|
1324
|
-
throw new BrowserAuthError("INIT_FAILED", "Failed to initialize browser auth: " + String(response.status) + " " + errorText);
|
|
1325
|
-
}
|
|
1326
|
-
const data = await response.json();
|
|
1327
|
-
return data;
|
|
1328
|
-
}
|
|
1329
|
-
async function pollAuthStatus(endpoint, cliToken) {
|
|
1330
|
-
const response = await fetch(`${endpoint}/api/auth/cli/status?token=${encodeURIComponent(cliToken)}`);
|
|
1331
|
-
if (!response.ok) {
|
|
1332
|
-
const errorText = await response.text();
|
|
1333
|
-
throw new BrowserAuthError("POLL_FAILED", "Failed to poll auth status: " + String(response.status) + " " + errorText);
|
|
1334
|
-
}
|
|
1335
|
-
const data = await response.json();
|
|
1336
|
-
return data;
|
|
1337
|
-
}
|
|
1338
|
-
async function openBrowser(url) {
|
|
1339
|
-
if (process.env.MUTAGENT_TEST_MODE === "true") {
|
|
1340
|
-
console.log(`AUTH_URL:${url}`);
|
|
1341
|
-
return;
|
|
1342
|
-
}
|
|
1343
|
-
try {
|
|
1344
|
-
const { default: open } = await import("open");
|
|
1345
|
-
await open(url);
|
|
1346
|
-
} catch {
|
|
1347
|
-
throw new BrowserAuthError("BROWSER_OPEN_FAILED", `Could not open browser automatically. Please visit: ${url}`);
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
function sleep(ms) {
|
|
1351
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1352
|
-
}
|
|
1353
|
-
async function performBrowserAuth(options, onStatusUpdate) {
|
|
1354
|
-
const {
|
|
1355
|
-
endpoint,
|
|
1356
|
-
timeout = 300000,
|
|
1357
|
-
pollInterval = 2000,
|
|
1358
|
-
skipBrowserOpen = false
|
|
1359
|
-
} = options;
|
|
1360
|
-
const cliToken = generateCliToken();
|
|
1361
|
-
onStatusUpdate?.("Initializing browser authentication...");
|
|
1362
|
-
const initResponse = await initBrowserAuth(endpoint, cliToken);
|
|
1363
|
-
const { authUrl } = initResponse;
|
|
1364
|
-
if (!skipBrowserOpen) {
|
|
1365
|
-
onStatusUpdate?.("Opening browser for authentication...");
|
|
1366
|
-
try {
|
|
1367
|
-
await openBrowser(authUrl);
|
|
1368
|
-
} catch (error) {
|
|
1369
|
-
if (error instanceof BrowserAuthError && error.code === "BROWSER_OPEN_FAILED") {
|
|
1370
|
-
onStatusUpdate?.(error.message);
|
|
1371
|
-
} else {
|
|
1372
|
-
throw error;
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
console.log("");
|
|
1377
|
-
console.log(" Open this URL to authenticate:");
|
|
1378
|
-
console.log("");
|
|
1379
|
-
console.log(" " + authUrl);
|
|
1380
|
-
console.log("");
|
|
1381
|
-
onStatusUpdate?.("Waiting for browser authentication...");
|
|
1382
|
-
const startTime = Date.now();
|
|
1383
|
-
while (Date.now() - startTime < timeout) {
|
|
1384
|
-
await sleep(pollInterval);
|
|
1385
|
-
const status = await pollAuthStatus(endpoint, cliToken);
|
|
1386
|
-
switch (status.status) {
|
|
1387
|
-
case "pending":
|
|
1388
|
-
continue;
|
|
1389
|
-
case "completed":
|
|
1390
|
-
if (!status.apiKey || !status.workspaceId || !status.workspaceName || !status.organizationId || !status.organizationName) {
|
|
1391
|
-
throw new BrowserAuthError("INCOMPLETE_RESPONSE", "Server returned incomplete auth response");
|
|
1392
|
-
}
|
|
1393
|
-
return {
|
|
1394
|
-
apiKey: status.apiKey,
|
|
1395
|
-
workspaceId: status.workspaceId,
|
|
1396
|
-
workspaceName: status.workspaceName,
|
|
1397
|
-
organizationId: status.organizationId,
|
|
1398
|
-
organizationName: status.organizationName,
|
|
1399
|
-
expiresAt: status.expiresAt
|
|
1400
|
-
};
|
|
1401
|
-
case "expired":
|
|
1402
|
-
throw new BrowserAuthError("AUTH_EXPIRED", "Browser authentication expired. Please try again.");
|
|
1403
|
-
case "denied":
|
|
1404
|
-
throw new BrowserAuthError("AUTH_DENIED", status.error ?? "Browser authentication was denied.");
|
|
1405
|
-
case "not_found":
|
|
1406
|
-
throw new BrowserAuthError("TOKEN_NOT_FOUND", "Authentication token not found. Please try again.");
|
|
1407
|
-
default:
|
|
1408
|
-
throw new BrowserAuthError("UNKNOWN_STATUS", "Unknown auth status: " + String(status.status));
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
throw new BrowserAuthError("AUTH_TIMEOUT", "Browser authentication timed out after 5 minutes. Please try again.");
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
class BrowserAuthError extends Error {
|
|
1415
|
-
code;
|
|
1416
|
-
constructor(code, message) {
|
|
1417
|
-
super(message);
|
|
1418
|
-
this.name = "BrowserAuthError";
|
|
1419
|
-
this.code = code;
|
|
1420
|
-
}
|
|
1421
|
-
getSuggestion() {
|
|
1422
|
-
switch (this.code) {
|
|
1423
|
-
case "INIT_FAILED":
|
|
1424
|
-
return "Check your endpoint configuration and network connection.";
|
|
1425
|
-
case "POLL_FAILED":
|
|
1426
|
-
return "Check your network connection and try again.";
|
|
1427
|
-
case "BROWSER_OPEN_FAILED":
|
|
1428
|
-
return "Copy the URL above and open it manually in your browser.";
|
|
1429
|
-
case "AUTH_EXPIRED":
|
|
1430
|
-
case "AUTH_TIMEOUT":
|
|
1431
|
-
return 'Run "mutagent auth login" again to restart authentication.';
|
|
1432
|
-
case "AUTH_DENIED":
|
|
1433
|
-
return "Ensure you have access to the workspace and try again.";
|
|
1434
|
-
case "TOKEN_NOT_FOUND":
|
|
1435
|
-
case "INCOMPLETE_RESPONSE":
|
|
1436
|
-
case "UNKNOWN_STATUS":
|
|
1437
|
-
return "Please try again. If the issue persists, contact support.";
|
|
1438
|
-
default:
|
|
1439
|
-
return "Please try again.";
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
1319
|
// src/lib/mutation-context.ts
|
|
1445
1320
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
1446
1321
|
import { join as join2, resolve } from "path";
|
|
@@ -2059,266 +1934,424 @@ function runOptimizationPath(promptCount, datasetCount) {
|
|
|
2059
1934
|
console.log(chalk2.dim(` Upload one: mutagent prompts create --name "my-prompt" --raw-file <path>`));
|
|
2060
1935
|
console.log("");
|
|
2061
1936
|
}
|
|
2062
|
-
if (datasetCount === 0) {
|
|
2063
|
-
console.log(` ${String(step)}. ${chalk2.green(`mutagent prompts dataset add <prompt-id> -d '[{"input":{...},"expectedOutput":{...}}]' --name "my-dataset"`)}`);
|
|
2064
|
-
console.log(" Upload a dataset with input/output pairs");
|
|
2065
|
-
console.log("");
|
|
2066
|
-
step++;
|
|
2067
|
-
} else {
|
|
2068
|
-
console.log(chalk2.dim(` ${chalk2.green("✓")} Datasets detected in codebase (${String(datasetCount)} found)`));
|
|
2069
|
-
console.log(chalk2.dim(` Upload one: mutagent prompts dataset add <prompt-id> -d '[...]' --name "my-dataset"`));
|
|
2070
|
-
console.log("");
|
|
1937
|
+
if (datasetCount === 0) {
|
|
1938
|
+
console.log(` ${String(step)}. ${chalk2.green(`mutagent prompts dataset add <prompt-id> -d '[{"input":{...},"expectedOutput":{...}}]' --name "my-dataset"`)}`);
|
|
1939
|
+
console.log(" Upload a dataset with input/output pairs");
|
|
1940
|
+
console.log("");
|
|
1941
|
+
step++;
|
|
1942
|
+
} else {
|
|
1943
|
+
console.log(chalk2.dim(` ${chalk2.green("✓")} Datasets detected in codebase (${String(datasetCount)} found)`));
|
|
1944
|
+
console.log(chalk2.dim(` Upload one: mutagent prompts dataset add <prompt-id> -d '[...]' --name "my-dataset"`));
|
|
1945
|
+
console.log("");
|
|
1946
|
+
}
|
|
1947
|
+
console.log(` ${String(step)}. ${chalk2.green(`mutagent prompts evaluation create <prompt-id> --name "My Eval" -d '{"evalConfig":{"criteria":[...]}}'`)}`);
|
|
1948
|
+
console.log(" Define evaluation criteria");
|
|
1949
|
+
console.log("");
|
|
1950
|
+
step++;
|
|
1951
|
+
console.log(` ${String(step)}. ${chalk2.green("mutagent prompts optimize start <prompt-id> --dataset <dataset-id>")}`);
|
|
1952
|
+
console.log(" Start the optimization loop");
|
|
1953
|
+
console.log("");
|
|
1954
|
+
console.log(chalk2.dim(" Tip: Use `mutagent prompts list` to see your prompt IDs."));
|
|
1955
|
+
console.log("");
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
// src/lib/auth-flow.ts
|
|
1959
|
+
init_config();
|
|
1960
|
+
init_sdk_client();
|
|
1961
|
+
init_errors();
|
|
1962
|
+
import inquirer from "inquirer";
|
|
1963
|
+
import chalk3 from "chalk";
|
|
1964
|
+
import ora from "ora";
|
|
1965
|
+
|
|
1966
|
+
// src/lib/browser-auth.ts
|
|
1967
|
+
import { hostname, platform } from "os";
|
|
1968
|
+
function generateCliToken() {
|
|
1969
|
+
return crypto.randomUUID();
|
|
1970
|
+
}
|
|
1971
|
+
async function initBrowserAuth(endpoint, cliToken) {
|
|
1972
|
+
const response = await fetch(`${endpoint}/api/auth/cli/init`, {
|
|
1973
|
+
method: "POST",
|
|
1974
|
+
headers: { "Content-Type": "application/json" },
|
|
1975
|
+
body: JSON.stringify({
|
|
1976
|
+
cliToken,
|
|
1977
|
+
hostname: hostname(),
|
|
1978
|
+
platform: platform()
|
|
1979
|
+
})
|
|
1980
|
+
});
|
|
1981
|
+
if (!response.ok) {
|
|
1982
|
+
const errorText = await response.text();
|
|
1983
|
+
throw new BrowserAuthError("INIT_FAILED", "Failed to initialize browser auth: " + String(response.status) + " " + errorText);
|
|
1984
|
+
}
|
|
1985
|
+
const data = await response.json();
|
|
1986
|
+
return data;
|
|
1987
|
+
}
|
|
1988
|
+
async function pollAuthStatus(endpoint, cliToken) {
|
|
1989
|
+
const response = await fetch(`${endpoint}/api/auth/cli/status?token=${encodeURIComponent(cliToken)}`);
|
|
1990
|
+
if (!response.ok) {
|
|
1991
|
+
const errorText = await response.text();
|
|
1992
|
+
throw new BrowserAuthError("POLL_FAILED", "Failed to poll auth status: " + String(response.status) + " " + errorText);
|
|
1993
|
+
}
|
|
1994
|
+
const data = await response.json();
|
|
1995
|
+
return data;
|
|
1996
|
+
}
|
|
1997
|
+
async function openBrowser(url) {
|
|
1998
|
+
if (process.env.MUTAGENT_TEST_MODE === "true") {
|
|
1999
|
+
console.log(`AUTH_URL:${url}`);
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
try {
|
|
2003
|
+
const { default: open } = await import("open");
|
|
2004
|
+
await open(url);
|
|
2005
|
+
} catch {
|
|
2006
|
+
throw new BrowserAuthError("BROWSER_OPEN_FAILED", `Could not open browser automatically. Please visit: ${url}`);
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
function sleep(ms) {
|
|
2010
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
2011
|
+
}
|
|
2012
|
+
async function performBrowserAuth(options, onStatusUpdate) {
|
|
2013
|
+
const {
|
|
2014
|
+
endpoint,
|
|
2015
|
+
timeout = 300000,
|
|
2016
|
+
pollInterval = 2000,
|
|
2017
|
+
skipBrowserOpen = false
|
|
2018
|
+
} = options;
|
|
2019
|
+
const cliToken = generateCliToken();
|
|
2020
|
+
onStatusUpdate?.("Initializing browser authentication...");
|
|
2021
|
+
const initResponse = await initBrowserAuth(endpoint, cliToken);
|
|
2022
|
+
const { authUrl } = initResponse;
|
|
2023
|
+
if (!skipBrowserOpen) {
|
|
2024
|
+
onStatusUpdate?.("Opening browser for authentication...");
|
|
2025
|
+
try {
|
|
2026
|
+
await openBrowser(authUrl);
|
|
2027
|
+
} catch (error) {
|
|
2028
|
+
if (error instanceof BrowserAuthError && error.code === "BROWSER_OPEN_FAILED") {
|
|
2029
|
+
onStatusUpdate?.(error.message);
|
|
2030
|
+
} else {
|
|
2031
|
+
throw error;
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
console.log("");
|
|
2036
|
+
console.log(" Open this URL to authenticate:");
|
|
2037
|
+
console.log("");
|
|
2038
|
+
console.log(" " + authUrl);
|
|
2039
|
+
console.log("");
|
|
2040
|
+
onStatusUpdate?.("Waiting for browser authentication...");
|
|
2041
|
+
const startTime = Date.now();
|
|
2042
|
+
while (Date.now() - startTime < timeout) {
|
|
2043
|
+
await sleep(pollInterval);
|
|
2044
|
+
const status = await pollAuthStatus(endpoint, cliToken);
|
|
2045
|
+
switch (status.status) {
|
|
2046
|
+
case "pending":
|
|
2047
|
+
continue;
|
|
2048
|
+
case "completed":
|
|
2049
|
+
if (!status.apiKey || !status.workspaceId || !status.workspaceName || !status.organizationId || !status.organizationName) {
|
|
2050
|
+
throw new BrowserAuthError("INCOMPLETE_RESPONSE", "Server returned incomplete auth response");
|
|
2051
|
+
}
|
|
2052
|
+
return {
|
|
2053
|
+
apiKey: status.apiKey,
|
|
2054
|
+
workspaceId: status.workspaceId,
|
|
2055
|
+
workspaceName: status.workspaceName,
|
|
2056
|
+
organizationId: status.organizationId,
|
|
2057
|
+
organizationName: status.organizationName,
|
|
2058
|
+
expiresAt: status.expiresAt
|
|
2059
|
+
};
|
|
2060
|
+
case "expired":
|
|
2061
|
+
throw new BrowserAuthError("AUTH_EXPIRED", "Browser authentication expired. Please try again.");
|
|
2062
|
+
case "denied":
|
|
2063
|
+
throw new BrowserAuthError("AUTH_DENIED", status.error ?? "Browser authentication was denied.");
|
|
2064
|
+
case "not_found":
|
|
2065
|
+
throw new BrowserAuthError("TOKEN_NOT_FOUND", "Authentication token not found. Please try again.");
|
|
2066
|
+
default:
|
|
2067
|
+
throw new BrowserAuthError("UNKNOWN_STATUS", "Unknown auth status: " + String(status.status));
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
throw new BrowserAuthError("AUTH_TIMEOUT", "Browser authentication timed out after 5 minutes. Please try again.");
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
class BrowserAuthError extends Error {
|
|
2074
|
+
code;
|
|
2075
|
+
constructor(code, message) {
|
|
2076
|
+
super(message);
|
|
2077
|
+
this.name = "BrowserAuthError";
|
|
2078
|
+
this.code = code;
|
|
2079
|
+
}
|
|
2080
|
+
getSuggestion() {
|
|
2081
|
+
switch (this.code) {
|
|
2082
|
+
case "INIT_FAILED":
|
|
2083
|
+
return "Check your endpoint configuration and network connection.";
|
|
2084
|
+
case "POLL_FAILED":
|
|
2085
|
+
return "Check your network connection and try again.";
|
|
2086
|
+
case "BROWSER_OPEN_FAILED":
|
|
2087
|
+
return "Copy the URL above and open it manually in your browser.";
|
|
2088
|
+
case "AUTH_EXPIRED":
|
|
2089
|
+
case "AUTH_TIMEOUT":
|
|
2090
|
+
return 'Run "mutagent auth login" again to restart authentication.';
|
|
2091
|
+
case "AUTH_DENIED":
|
|
2092
|
+
return "Ensure you have access to the workspace and try again.";
|
|
2093
|
+
case "TOKEN_NOT_FOUND":
|
|
2094
|
+
case "INCOMPLETE_RESPONSE":
|
|
2095
|
+
case "UNKNOWN_STATUS":
|
|
2096
|
+
return "Please try again. If the issue persists, contact support.";
|
|
2097
|
+
default:
|
|
2098
|
+
return "Please try again.";
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
// src/lib/auth-flow.ts
|
|
2104
|
+
async function performLoginAction(opts) {
|
|
2105
|
+
const { isJson, output } = opts;
|
|
2106
|
+
const wasFirstLogin = !hasCredentials();
|
|
2107
|
+
const envApiKey = process.env.MUTAGENT_API_KEY;
|
|
2108
|
+
const endpoint = process.env.MUTAGENT_ENDPOINT ?? opts.endpoint;
|
|
2109
|
+
if (envApiKey) {
|
|
2110
|
+
return loginWithExistingKey(envApiKey, endpoint, output, wasFirstLogin);
|
|
2111
|
+
}
|
|
2112
|
+
const isNonInteractive = opts.nonInteractive === true || process.env.MUTAGENT_NON_INTERACTIVE === "true" || process.env.CI === "true" || !process.stdin.isTTY;
|
|
2113
|
+
if (isJson && !opts.browser && isNonInteractive) {
|
|
2114
|
+
throw new MutagentError("INTERACTIVE_REQUIRED", "No API key provided. Set MUTAGENT_API_KEY env var or add --browser for browser auth.", "Run: export MUTAGENT_API_KEY=<key> or mutagent login --browser --non-interactive");
|
|
2115
|
+
}
|
|
2116
|
+
if (!isNonInteractive && wasFirstLogin) {
|
|
2117
|
+
console.log(`
|
|
2118
|
+
` + chalk3.bold.cyan(" Welcome to MutagenT CLI!") + `
|
|
2119
|
+
`);
|
|
2120
|
+
console.log(` No credentials found. Please authenticate to continue.
|
|
2121
|
+
`);
|
|
2122
|
+
}
|
|
2123
|
+
let useBrowserAuth = opts.browser === true;
|
|
2124
|
+
if (!useBrowserAuth && isNonInteractive) {
|
|
2125
|
+
output.info("Non-interactive environment detected. Using browser authentication.");
|
|
2126
|
+
useBrowserAuth = true;
|
|
2127
|
+
}
|
|
2128
|
+
if (!useBrowserAuth) {
|
|
2129
|
+
const methodAnswer = await inquirer.prompt([
|
|
2130
|
+
{
|
|
2131
|
+
type: "list",
|
|
2132
|
+
name: "method",
|
|
2133
|
+
message: "How would you like to authenticate?",
|
|
2134
|
+
choices: [
|
|
2135
|
+
{ name: "Login (opens browser)", value: "browser" },
|
|
2136
|
+
{ name: "API Key (paste existing key)", value: "apiKey" }
|
|
2137
|
+
]
|
|
2138
|
+
}
|
|
2139
|
+
]);
|
|
2140
|
+
useBrowserAuth = methodAnswer.method === "browser";
|
|
2141
|
+
}
|
|
2142
|
+
if (useBrowserAuth) {
|
|
2143
|
+
return loginWithBrowser(endpoint, output, wasFirstLogin);
|
|
2144
|
+
}
|
|
2145
|
+
return loginWithPastedKey(endpoint, output, wasFirstLogin);
|
|
2146
|
+
}
|
|
2147
|
+
function buildLoginJsonResponse(result) {
|
|
2148
|
+
return {
|
|
2149
|
+
success: true,
|
|
2150
|
+
authenticated: result.authenticated,
|
|
2151
|
+
endpoint: result.endpoint,
|
|
2152
|
+
workspace: result.workspace,
|
|
2153
|
+
organization: result.organization,
|
|
2154
|
+
_directive: {
|
|
2155
|
+
instruction: "Verify workspace. Run: mutagent workspaces list --json",
|
|
2156
|
+
next: ["mutagent workspaces list --json", "mutagent prompts list --json"]
|
|
2157
|
+
}
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2160
|
+
async function loginWithExistingKey(apiKey, endpoint, output, wasFirstLogin) {
|
|
2161
|
+
output.info("Validating API key...");
|
|
2162
|
+
const isValid = await validateApiKey(apiKey, endpoint);
|
|
2163
|
+
if (!isValid) {
|
|
2164
|
+
throw new MutagentError("INVALID_API_KEY", "Invalid API key or endpoint", "Check your API key and try again");
|
|
2165
|
+
}
|
|
2166
|
+
const orgs = await fetchOrganizations(apiKey, endpoint);
|
|
2167
|
+
let orgId;
|
|
2168
|
+
let orgName;
|
|
2169
|
+
let wsId;
|
|
2170
|
+
let wsName;
|
|
2171
|
+
if (orgs.length >= 1 && orgs[0]) {
|
|
2172
|
+
orgId = orgs[0].id;
|
|
2173
|
+
orgName = orgs[0].name;
|
|
2174
|
+
const workspaces = await fetchWorkspaces(apiKey, endpoint, orgId);
|
|
2175
|
+
const defaultWs = workspaces.find((w) => w.isDefault) ?? workspaces[0];
|
|
2176
|
+
if (defaultWs) {
|
|
2177
|
+
wsId = defaultWs.id;
|
|
2178
|
+
wsName = defaultWs.name;
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
saveFullCredentials({
|
|
2182
|
+
apiKey,
|
|
2183
|
+
endpoint,
|
|
2184
|
+
workspaceId: wsId,
|
|
2185
|
+
organizationId: orgId
|
|
2186
|
+
});
|
|
2187
|
+
return {
|
|
2188
|
+
authenticated: true,
|
|
2189
|
+
apiKey,
|
|
2190
|
+
endpoint,
|
|
2191
|
+
workspace: wsId ? { id: wsId, name: wsName } : null,
|
|
2192
|
+
organization: orgId ? { id: orgId, name: orgName } : null,
|
|
2193
|
+
wasFirstLogin
|
|
2194
|
+
};
|
|
2195
|
+
}
|
|
2196
|
+
async function loginWithBrowser(endpoint, output, wasFirstLogin) {
|
|
2197
|
+
const spinner = ora({ text: "Opening browser for authentication...", spinner: "dots" });
|
|
2198
|
+
try {
|
|
2199
|
+
spinner.start();
|
|
2200
|
+
const result = await performBrowserAuth({ endpoint, timeout: 300000, pollInterval: 2000 }, (message) => {
|
|
2201
|
+
spinner.text = message;
|
|
2202
|
+
});
|
|
2203
|
+
spinner.succeed("Authenticated successfully!");
|
|
2204
|
+
saveFullCredentials({
|
|
2205
|
+
apiKey: result.apiKey,
|
|
2206
|
+
endpoint,
|
|
2207
|
+
workspaceId: result.workspaceId,
|
|
2208
|
+
organizationId: result.organizationId,
|
|
2209
|
+
expiresAt: result.expiresAt
|
|
2210
|
+
});
|
|
2211
|
+
if (result.workspaceName)
|
|
2212
|
+
output.info(`Workspace: ${result.workspaceName}`);
|
|
2213
|
+
if (result.organizationName)
|
|
2214
|
+
output.info(`Organization: ${result.organizationName}`);
|
|
2215
|
+
return {
|
|
2216
|
+
authenticated: true,
|
|
2217
|
+
apiKey: result.apiKey,
|
|
2218
|
+
endpoint,
|
|
2219
|
+
workspace: result.workspaceId ? { id: result.workspaceId, name: result.workspaceName } : null,
|
|
2220
|
+
organization: result.organizationId ? { id: result.organizationId, name: result.organizationName } : null,
|
|
2221
|
+
wasFirstLogin
|
|
2222
|
+
};
|
|
2223
|
+
} catch (error) {
|
|
2224
|
+
spinner.fail("Authentication failed");
|
|
2225
|
+
if (error instanceof BrowserAuthError) {
|
|
2226
|
+
throw new MutagentError(error.code, error.message, error.getSuggestion());
|
|
2227
|
+
}
|
|
2228
|
+
throw error;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
async function loginWithPastedKey(initialEndpoint, output, wasFirstLogin) {
|
|
2232
|
+
const answers = await inquirer.prompt([
|
|
2233
|
+
{
|
|
2234
|
+
type: "input",
|
|
2235
|
+
name: "endpoint",
|
|
2236
|
+
message: "MutagenT endpoint:",
|
|
2237
|
+
default: initialEndpoint
|
|
2238
|
+
},
|
|
2239
|
+
{
|
|
2240
|
+
type: "password",
|
|
2241
|
+
name: "apiKey",
|
|
2242
|
+
message: "API Key:",
|
|
2243
|
+
mask: "*",
|
|
2244
|
+
validate: (input) => input.length > 0 || "API key is required"
|
|
2245
|
+
}
|
|
2246
|
+
]);
|
|
2247
|
+
const apiKey = answers.apiKey;
|
|
2248
|
+
const endpoint = answers.endpoint;
|
|
2249
|
+
output.info("Validating API key...");
|
|
2250
|
+
const isValid = await validateApiKey(apiKey, endpoint);
|
|
2251
|
+
if (!isValid) {
|
|
2252
|
+
throw new MutagentError("INVALID_API_KEY", "Invalid API key or endpoint", "Check your API key and try again");
|
|
2253
|
+
}
|
|
2254
|
+
let selectedOrgId;
|
|
2255
|
+
let selectedOrgName;
|
|
2256
|
+
let selectedWsId;
|
|
2257
|
+
let selectedWsName;
|
|
2258
|
+
const orgs = await fetchOrganizations(apiKey, endpoint);
|
|
2259
|
+
if (orgs.length === 1 && orgs[0]) {
|
|
2260
|
+
selectedOrgId = orgs[0].id;
|
|
2261
|
+
selectedOrgName = orgs[0].name;
|
|
2262
|
+
} else if (orgs.length > 1) {
|
|
2263
|
+
const orgAnswer = await inquirer.prompt([
|
|
2264
|
+
{
|
|
2265
|
+
type: "list",
|
|
2266
|
+
name: "orgId",
|
|
2267
|
+
message: "Select organization:",
|
|
2268
|
+
choices: orgs.map((o) => ({ name: o.name, value: o.id }))
|
|
2269
|
+
}
|
|
2270
|
+
]);
|
|
2271
|
+
selectedOrgId = orgAnswer.orgId;
|
|
2272
|
+
selectedOrgName = orgs.find((o) => o.id === selectedOrgId)?.name;
|
|
2273
|
+
}
|
|
2274
|
+
if (selectedOrgId) {
|
|
2275
|
+
const workspaces = await fetchWorkspaces(apiKey, endpoint, selectedOrgId);
|
|
2276
|
+
const defaultWs = workspaces.find((w) => w.isDefault);
|
|
2277
|
+
if (workspaces.length === 1 && workspaces[0]) {
|
|
2278
|
+
selectedWsId = workspaces[0].id;
|
|
2279
|
+
selectedWsName = workspaces[0].name;
|
|
2280
|
+
} else if (defaultWs) {
|
|
2281
|
+
selectedWsId = defaultWs.id;
|
|
2282
|
+
selectedWsName = defaultWs.name;
|
|
2283
|
+
} else if (workspaces.length > 1) {
|
|
2284
|
+
const wsAnswer = await inquirer.prompt([
|
|
2285
|
+
{
|
|
2286
|
+
type: "list",
|
|
2287
|
+
name: "wsId",
|
|
2288
|
+
message: "Select workspace:",
|
|
2289
|
+
choices: workspaces.map((w) => ({
|
|
2290
|
+
name: w.name + (w.isDefault ? " (default)" : ""),
|
|
2291
|
+
value: w.id
|
|
2292
|
+
}))
|
|
2293
|
+
}
|
|
2294
|
+
]);
|
|
2295
|
+
selectedWsId = wsAnswer.wsId;
|
|
2296
|
+
selectedWsName = workspaces.find((w) => w.id === selectedWsId)?.name;
|
|
2297
|
+
}
|
|
2071
2298
|
}
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2299
|
+
saveFullCredentials({
|
|
2300
|
+
apiKey,
|
|
2301
|
+
endpoint,
|
|
2302
|
+
workspaceId: selectedWsId,
|
|
2303
|
+
organizationId: selectedOrgId
|
|
2304
|
+
});
|
|
2305
|
+
return {
|
|
2306
|
+
authenticated: true,
|
|
2307
|
+
apiKey,
|
|
2308
|
+
endpoint,
|
|
2309
|
+
workspace: selectedWsId ? { id: selectedWsId, name: selectedWsName } : null,
|
|
2310
|
+
organization: selectedOrgId ? { id: selectedOrgId, name: selectedOrgName } : null,
|
|
2311
|
+
wasFirstLogin
|
|
2312
|
+
};
|
|
2081
2313
|
}
|
|
2082
2314
|
|
|
2083
2315
|
// src/commands/auth.ts
|
|
2084
2316
|
function createAuthCommand() {
|
|
2085
2317
|
const auth = new Command("auth").description("Authenticate with MutagenT platform").addHelpText("after", `
|
|
2086
2318
|
Examples:
|
|
2087
|
-
${
|
|
2088
|
-
${
|
|
2089
|
-
${
|
|
2090
|
-
${
|
|
2319
|
+
${chalk4.dim("$")} mutagent auth login
|
|
2320
|
+
${chalk4.dim("$")} mutagent auth login --browser
|
|
2321
|
+
${chalk4.dim("$")} mutagent auth status
|
|
2322
|
+
${chalk4.dim("$")} mutagent auth logout
|
|
2091
2323
|
`);
|
|
2092
2324
|
auth.command("login").description("Authenticate and store API key").option("--browser", "Force browser-based authentication").option("--non-interactive", "Disable interactive prompts (auto-selects browser auth)").option("--endpoint <url>", "API endpoint", "https://api.mutagent.io").addHelpText("after", `
|
|
2093
2325
|
Examples:
|
|
2094
|
-
${
|
|
2095
|
-
${
|
|
2096
|
-
${
|
|
2326
|
+
${chalk4.dim("$")} mutagent auth login ${chalk4.dim("# Interactive (choose method)")}
|
|
2327
|
+
${chalk4.dim("$")} mutagent auth login --browser ${chalk4.dim("# Browser OAuth flow")}
|
|
2328
|
+
${chalk4.dim("$")} mutagent auth login --non-interactive ${chalk4.dim("# Auto browser flow (AI agents)")}
|
|
2097
2329
|
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
MUTAGENT_ENDPOINT Custom API endpoint
|
|
2101
|
-
MUTAGENT_NON_INTERACTIVE=true Non-interactive mode (auto browser auth)
|
|
2102
|
-
CI=true Enables non-interactive mode
|
|
2330
|
+
${chalk4.dim("Note: this command is an alias for `mutagent login`.")}
|
|
2331
|
+
${chalk4.dim("See `mutagent login --help` for full documentation.")}
|
|
2103
2332
|
`).action(async (options) => {
|
|
2104
2333
|
const isJson = getJsonFlag(auth);
|
|
2105
2334
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
2106
2335
|
try {
|
|
2107
|
-
const
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
if (apiKey) {
|
|
2115
|
-
output.info("Validating API key...");
|
|
2116
|
-
const isValid = await validateApiKey(apiKey, endpoint);
|
|
2117
|
-
if (!isValid) {
|
|
2118
|
-
throw new MutagentError("INVALID_API_KEY", "Invalid API key or endpoint", "Check your API key and try again");
|
|
2119
|
-
}
|
|
2120
|
-
const orgs = await fetchOrganizations(apiKey, endpoint);
|
|
2121
|
-
let orgId;
|
|
2122
|
-
let wsId;
|
|
2123
|
-
if (orgs.length >= 1 && orgs[0]) {
|
|
2124
|
-
orgId = orgs[0].id;
|
|
2125
|
-
const workspaces = await fetchWorkspaces(apiKey, endpoint, orgId);
|
|
2126
|
-
const defaultWs = workspaces.find((w) => w.isDefault);
|
|
2127
|
-
wsId = defaultWs?.id ?? workspaces[0]?.id;
|
|
2128
|
-
}
|
|
2129
|
-
saveFullCredentials({
|
|
2130
|
-
apiKey,
|
|
2131
|
-
endpoint,
|
|
2132
|
-
workspaceId: wsId,
|
|
2133
|
-
organizationId: orgId
|
|
2134
|
-
});
|
|
2135
|
-
output.success("Authenticated successfully");
|
|
2136
|
-
if (isJson) {
|
|
2137
|
-
output.output({
|
|
2138
|
-
success: true,
|
|
2139
|
-
authenticated: true,
|
|
2140
|
-
endpoint,
|
|
2141
|
-
workspace: wsId ? { id: wsId } : null,
|
|
2142
|
-
organization: orgId ? { id: orgId } : null,
|
|
2143
|
-
_directive: {
|
|
2144
|
-
instruction: "Verify workspace. Run: mutagent workspaces list --json",
|
|
2145
|
-
next: ["mutagent workspaces list --json", "mutagent prompts list --json"]
|
|
2146
|
-
}
|
|
2147
|
-
});
|
|
2148
|
-
} else {
|
|
2149
|
-
output.info(`Endpoint: ${endpoint}`);
|
|
2150
|
-
output.info("Next: mutagent workspaces list --json");
|
|
2151
|
-
}
|
|
2152
|
-
return;
|
|
2153
|
-
}
|
|
2154
|
-
const isNonInteractive = options.nonInteractive === true || process.env.MUTAGENT_NON_INTERACTIVE === "true" || process.env.CI === "true" || !process.stdin.isTTY;
|
|
2155
|
-
if (isJson && !options.browser && isNonInteractive) {
|
|
2156
|
-
throw new MutagentError("INTERACTIVE_REQUIRED", "No API key provided. Set MUTAGENT_API_KEY env var or add --browser for browser auth.", "Run: export MUTAGENT_API_KEY=<key> or mutagent auth login --browser --non-interactive");
|
|
2157
|
-
}
|
|
2158
|
-
if (!isNonInteractive && !hasCredentials()) {
|
|
2159
|
-
console.log(`
|
|
2160
|
-
` + chalk3.bold.cyan(" Welcome to MutagenT CLI!") + `
|
|
2161
|
-
`);
|
|
2162
|
-
console.log(` No credentials found. Please authenticate to continue.
|
|
2163
|
-
`);
|
|
2164
|
-
}
|
|
2165
|
-
let useLocalBrowserAuth = options.browser === true;
|
|
2166
|
-
if (!useLocalBrowserAuth && isNonInteractive) {
|
|
2167
|
-
output.info("Non-interactive environment detected. Using browser authentication.");
|
|
2168
|
-
useLocalBrowserAuth = true;
|
|
2169
|
-
}
|
|
2170
|
-
if (!useLocalBrowserAuth) {
|
|
2171
|
-
const methodAnswer = await inquirer.prompt([
|
|
2172
|
-
{
|
|
2173
|
-
type: "list",
|
|
2174
|
-
name: "method",
|
|
2175
|
-
message: "How would you like to authenticate?",
|
|
2176
|
-
choices: [
|
|
2177
|
-
{
|
|
2178
|
-
name: "Login (opens browser)",
|
|
2179
|
-
value: "browser"
|
|
2180
|
-
},
|
|
2181
|
-
{
|
|
2182
|
-
name: "API Key (paste existing key)",
|
|
2183
|
-
value: "apiKey"
|
|
2184
|
-
}
|
|
2185
|
-
]
|
|
2186
|
-
}
|
|
2187
|
-
]);
|
|
2188
|
-
useLocalBrowserAuth = methodAnswer.method === "browser";
|
|
2189
|
-
}
|
|
2190
|
-
if (useLocalBrowserAuth) {
|
|
2191
|
-
const spinner = ora({
|
|
2192
|
-
text: "Opening browser for authentication...",
|
|
2193
|
-
spinner: "dots"
|
|
2194
|
-
});
|
|
2195
|
-
try {
|
|
2196
|
-
spinner.start();
|
|
2197
|
-
const result = await performBrowserAuth({
|
|
2198
|
-
endpoint,
|
|
2199
|
-
timeout: 300000,
|
|
2200
|
-
pollInterval: 2000
|
|
2201
|
-
}, (message) => {
|
|
2202
|
-
spinner.text = message;
|
|
2203
|
-
});
|
|
2204
|
-
spinner.succeed("Authenticated successfully!");
|
|
2205
|
-
saveFullCredentials({
|
|
2206
|
-
apiKey: result.apiKey,
|
|
2207
|
-
endpoint,
|
|
2208
|
-
workspaceId: result.workspaceId,
|
|
2209
|
-
organizationId: result.organizationId,
|
|
2210
|
-
expiresAt: result.expiresAt
|
|
2211
|
-
});
|
|
2212
|
-
apiKey = result.apiKey;
|
|
2213
|
-
workspaceName = result.workspaceName;
|
|
2214
|
-
organizationName = result.organizationName;
|
|
2215
|
-
loginWorkspaceId = result.workspaceId;
|
|
2216
|
-
loginOrgId = result.organizationId;
|
|
2217
|
-
console.log("");
|
|
2218
|
-
output.info("Workspace: " + workspaceName);
|
|
2219
|
-
output.info("Organization: " + organizationName);
|
|
2220
|
-
output.info("Endpoint: " + endpoint);
|
|
2221
|
-
} catch (error) {
|
|
2222
|
-
spinner.fail("Authentication failed");
|
|
2223
|
-
if (error instanceof BrowserAuthError) {
|
|
2224
|
-
throw new MutagentError(error.code, error.message, error.getSuggestion());
|
|
2225
|
-
}
|
|
2226
|
-
throw error;
|
|
2227
|
-
}
|
|
2228
|
-
} else {
|
|
2229
|
-
const answers = await inquirer.prompt([
|
|
2230
|
-
{
|
|
2231
|
-
type: "input",
|
|
2232
|
-
name: "endpoint",
|
|
2233
|
-
message: "MutagenT endpoint:",
|
|
2234
|
-
default: endpoint
|
|
2235
|
-
},
|
|
2236
|
-
{
|
|
2237
|
-
type: "password",
|
|
2238
|
-
name: "apiKey",
|
|
2239
|
-
message: "API Key:",
|
|
2240
|
-
mask: "*",
|
|
2241
|
-
validate: (input) => input.length > 0 || "API key is required"
|
|
2242
|
-
}
|
|
2243
|
-
]);
|
|
2244
|
-
apiKey = answers.apiKey;
|
|
2245
|
-
endpoint = answers.endpoint;
|
|
2246
|
-
output.info("Validating API key...");
|
|
2247
|
-
const isValid = await validateApiKey(apiKey, endpoint);
|
|
2248
|
-
if (!isValid) {
|
|
2249
|
-
throw new MutagentError("INVALID_API_KEY", "Invalid API key or endpoint", "Check your API key and try again");
|
|
2250
|
-
}
|
|
2251
|
-
let selectedOrgId;
|
|
2252
|
-
let selectedOrgName;
|
|
2253
|
-
let selectedWsId;
|
|
2254
|
-
let selectedWsName;
|
|
2255
|
-
const orgs = await fetchOrganizations(apiKey, endpoint);
|
|
2256
|
-
if (orgs.length === 1 && orgs[0]) {
|
|
2257
|
-
selectedOrgId = orgs[0].id;
|
|
2258
|
-
selectedOrgName = orgs[0].name;
|
|
2259
|
-
} else if (orgs.length > 1) {
|
|
2260
|
-
const orgAnswer = await inquirer.prompt([{
|
|
2261
|
-
type: "list",
|
|
2262
|
-
name: "orgId",
|
|
2263
|
-
message: "Select organization:",
|
|
2264
|
-
choices: orgs.map((o) => ({ name: o.name, value: o.id }))
|
|
2265
|
-
}]);
|
|
2266
|
-
selectedOrgId = orgAnswer.orgId;
|
|
2267
|
-
selectedOrgName = orgs.find((o) => o.id === selectedOrgId)?.name;
|
|
2268
|
-
}
|
|
2269
|
-
if (selectedOrgId) {
|
|
2270
|
-
const workspaces = await fetchWorkspaces(apiKey, endpoint, selectedOrgId);
|
|
2271
|
-
const defaultWs = workspaces.find((w) => w.isDefault);
|
|
2272
|
-
if (workspaces.length === 1 && workspaces[0]) {
|
|
2273
|
-
selectedWsId = workspaces[0].id;
|
|
2274
|
-
selectedWsName = workspaces[0].name;
|
|
2275
|
-
} else if (defaultWs) {
|
|
2276
|
-
selectedWsId = defaultWs.id;
|
|
2277
|
-
selectedWsName = defaultWs.name;
|
|
2278
|
-
} else if (workspaces.length > 1) {
|
|
2279
|
-
const wsAnswer = await inquirer.prompt([{
|
|
2280
|
-
type: "list",
|
|
2281
|
-
name: "wsId",
|
|
2282
|
-
message: "Select workspace:",
|
|
2283
|
-
choices: workspaces.map((w) => ({ name: w.name + (w.isDefault ? " (default)" : ""), value: w.id }))
|
|
2284
|
-
}]);
|
|
2285
|
-
selectedWsId = wsAnswer.wsId;
|
|
2286
|
-
selectedWsName = workspaces.find((w) => w.id === selectedWsId)?.name;
|
|
2287
|
-
}
|
|
2288
|
-
}
|
|
2289
|
-
saveFullCredentials({
|
|
2290
|
-
apiKey,
|
|
2291
|
-
endpoint,
|
|
2292
|
-
workspaceId: selectedWsId,
|
|
2293
|
-
organizationId: selectedOrgId
|
|
2294
|
-
});
|
|
2295
|
-
workspaceName = selectedWsName;
|
|
2296
|
-
organizationName = selectedOrgName;
|
|
2297
|
-
loginWorkspaceId = selectedWsId;
|
|
2298
|
-
loginOrgId = selectedOrgId;
|
|
2299
|
-
output.success("Authenticated successfully");
|
|
2300
|
-
if (selectedOrgName)
|
|
2301
|
-
output.info("Organization: " + selectedOrgName);
|
|
2302
|
-
if (selectedWsName)
|
|
2303
|
-
output.info("Workspace: " + selectedWsName);
|
|
2304
|
-
output.info("Endpoint: " + endpoint);
|
|
2305
|
-
}
|
|
2336
|
+
const result = await performLoginAction({
|
|
2337
|
+
endpoint: options.endpoint,
|
|
2338
|
+
browser: options.browser,
|
|
2339
|
+
nonInteractive: options.nonInteractive,
|
|
2340
|
+
isJson,
|
|
2341
|
+
output
|
|
2342
|
+
});
|
|
2306
2343
|
if (isJson) {
|
|
2307
|
-
output.output(
|
|
2308
|
-
success: true,
|
|
2309
|
-
authenticated: true,
|
|
2310
|
-
endpoint,
|
|
2311
|
-
workspace: loginWorkspaceId ? { id: loginWorkspaceId, name: workspaceName } : null,
|
|
2312
|
-
organization: loginOrgId ? { id: loginOrgId, name: organizationName } : null,
|
|
2313
|
-
_directive: {
|
|
2314
|
-
instruction: "Verify workspace. Run: mutagent workspaces list --json",
|
|
2315
|
-
next: ["mutagent workspaces list --json", "mutagent prompts list --json"]
|
|
2316
|
-
}
|
|
2317
|
-
});
|
|
2344
|
+
output.output(buildLoginJsonResponse(result));
|
|
2318
2345
|
} else {
|
|
2346
|
+
output.success("Authenticated successfully");
|
|
2347
|
+
if (result.organization?.name)
|
|
2348
|
+
output.info(`Organization: ${result.organization.name}`);
|
|
2349
|
+
if (result.workspace?.name)
|
|
2350
|
+
output.info(`Workspace: ${result.workspace.name}`);
|
|
2351
|
+
output.info(`Endpoint: ${result.endpoint}`);
|
|
2319
2352
|
output.info("Next: mutagent workspaces list --json");
|
|
2320
2353
|
}
|
|
2321
|
-
if (wasFirstLogin && process.stdin.isTTY && !isJson) {
|
|
2354
|
+
if (result.wasFirstLogin && process.stdin.isTTY && !isJson) {
|
|
2322
2355
|
await runPostOnboarding();
|
|
2323
2356
|
}
|
|
2324
2357
|
} catch (error) {
|
|
@@ -2331,8 +2364,8 @@ Environment Variables:
|
|
|
2331
2364
|
});
|
|
2332
2365
|
auth.command("status").description("Check authentication status").addHelpText("after", `
|
|
2333
2366
|
Examples:
|
|
2334
|
-
${
|
|
2335
|
-
${
|
|
2367
|
+
${chalk4.dim("$")} mutagent auth status
|
|
2368
|
+
${chalk4.dim("$")} mutagent auth status --json
|
|
2336
2369
|
`).action(async () => {
|
|
2337
2370
|
const isJson = getJsonFlag(auth);
|
|
2338
2371
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -2425,7 +2458,7 @@ Examples:
|
|
|
2425
2458
|
});
|
|
2426
2459
|
auth.command("logout").description("Clear stored credentials").addHelpText("after", `
|
|
2427
2460
|
Examples:
|
|
2428
|
-
${
|
|
2461
|
+
${chalk4.dim("$")} mutagent auth logout
|
|
2429
2462
|
`).action(() => {
|
|
2430
2463
|
const isJson = getJsonFlag(auth);
|
|
2431
2464
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -2436,179 +2469,70 @@ Examples:
|
|
|
2436
2469
|
}
|
|
2437
2470
|
|
|
2438
2471
|
// src/commands/login.ts
|
|
2439
|
-
init_config();
|
|
2440
|
-
init_sdk_client();
|
|
2441
2472
|
import { Command as Command2 } from "commander";
|
|
2442
|
-
import
|
|
2443
|
-
import chalk4 from "chalk";
|
|
2444
|
-
import ora2 from "ora";
|
|
2473
|
+
import chalk5 from "chalk";
|
|
2445
2474
|
init_errors();
|
|
2446
2475
|
function createLoginCommand() {
|
|
2447
|
-
const login = new Command2("login").description("Login to MutagenT
|
|
2476
|
+
const login = new Command2("login").description("Login to MutagenT (browser OAuth — signup, onboard, authorize CLI in one flow)").option("--browser", "Force browser-based authentication").option("--non-interactive", "Disable interactive prompts (auto-selects browser auth)").option("--endpoint <url>", "API endpoint", "https://api.mutagent.io").addHelpText("after", `
|
|
2448
2477
|
Examples:
|
|
2449
|
-
${
|
|
2450
|
-
${
|
|
2451
|
-
${
|
|
2478
|
+
${chalk5.dim("$")} mutagent login ${chalk5.dim("# Browser OAuth (recommended — handles signup + onboarding)")}
|
|
2479
|
+
${chalk5.dim("$")} mutagent login --browser ${chalk5.dim("# Force browser flow (skip method prompt)")}
|
|
2480
|
+
${chalk5.dim("$")} mutagent login --non-interactive ${chalk5.dim("# Auto-browser for AI agents and CI")}
|
|
2481
|
+
|
|
2482
|
+
${chalk5.yellow("Browser OAuth flow (recommended for end users):")}
|
|
2483
|
+
Opens app.mutagent.io in your browser. You will:
|
|
2484
|
+
1. Sign in or sign up with your account
|
|
2485
|
+
2. Complete onboarding (workspace, provider config)
|
|
2486
|
+
3. Authorize this CLI session
|
|
2487
|
+
The CLI polls for completion and saves credentials when you authorize.
|
|
2488
|
+
|
|
2489
|
+
${chalk5.yellow("Automation / CI / AI Agents:")}
|
|
2490
|
+
Set MUTAGENT_API_KEY environment variable before running:
|
|
2491
|
+
${chalk5.dim("$")} export MUTAGENT_API_KEY=mt_...
|
|
2492
|
+
${chalk5.dim("$")} mutagent login --json
|
|
2493
|
+
When MUTAGENT_API_KEY is set, login skips the browser flow entirely and
|
|
2494
|
+
validates the key directly. This is the canonical CI / agent path.
|
|
2452
2495
|
|
|
2453
2496
|
Environment Variables:
|
|
2454
|
-
MUTAGENT_API_KEY API key (skips interactive
|
|
2497
|
+
MUTAGENT_API_KEY Pre-existing API key (skips interactive flow)
|
|
2455
2498
|
MUTAGENT_ENDPOINT Custom API endpoint
|
|
2499
|
+
MUTAGENT_NON_INTERACTIVE=true Treat environment as non-interactive
|
|
2500
|
+
CI=true Automatically enables non-interactive mode
|
|
2501
|
+
|
|
2502
|
+
Verify after login:
|
|
2503
|
+
${chalk5.dim("$")} mutagent auth status ${chalk5.dim("# Show session, workspace, org")}
|
|
2504
|
+
${chalk5.dim("$")} mutagent workspaces list --json ${chalk5.dim("# List available workspaces")}
|
|
2505
|
+
|
|
2506
|
+
${chalk5.dim("Note: `mutagent auth login` is a back-compat alias and behaves identically.")}
|
|
2456
2507
|
`).action(async (options) => {
|
|
2457
2508
|
const isJson = getJsonFlag(login);
|
|
2458
2509
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
2459
2510
|
try {
|
|
2460
|
-
const
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
const org = orgs[0];
|
|
2470
|
-
let workspaceId;
|
|
2471
|
-
if (org) {
|
|
2472
|
-
const workspaces = await fetchWorkspaces(apiKey, endpoint, org.id);
|
|
2473
|
-
const defaultWs = workspaces.find((ws) => ws.isDefault) ?? workspaces[0];
|
|
2474
|
-
if (defaultWs)
|
|
2475
|
-
workspaceId = defaultWs.id;
|
|
2476
|
-
}
|
|
2477
|
-
saveFullCredentials({
|
|
2478
|
-
apiKey,
|
|
2479
|
-
endpoint,
|
|
2480
|
-
organizationId: org?.id,
|
|
2481
|
-
workspaceId
|
|
2482
|
-
});
|
|
2483
|
-
output.success("Logged in successfully");
|
|
2484
|
-
if (!isJson) {
|
|
2485
|
-
output.info(`Endpoint: ${endpoint}`);
|
|
2486
|
-
if (org)
|
|
2487
|
-
output.info(`Organization: ${org.name}`);
|
|
2488
|
-
}
|
|
2489
|
-
return;
|
|
2490
|
-
}
|
|
2491
|
-
const isNonInteractive = options.nonInteractive === true || process.env.MUTAGENT_NON_INTERACTIVE === "true" || process.env.CI === "true" || !process.stdin.isTTY;
|
|
2492
|
-
if (isJson && !options.browser && isNonInteractive) {
|
|
2493
|
-
throw new MutagentError("INTERACTIVE_REQUIRED", "No API key provided. Set MUTAGENT_API_KEY env var or add --browser for browser auth.", "Run: export MUTAGENT_API_KEY=<key> or mutagent login --browser --non-interactive");
|
|
2494
|
-
}
|
|
2495
|
-
if (!isNonInteractive && !hasCredentials()) {
|
|
2496
|
-
console.log(`
|
|
2497
|
-
` + chalk4.bold.cyan(" Welcome to MutagenT CLI!") + `
|
|
2498
|
-
`);
|
|
2499
|
-
console.log(` No credentials found. Please authenticate to continue.
|
|
2500
|
-
`);
|
|
2501
|
-
}
|
|
2502
|
-
let useBrowserAuth = options.browser === true;
|
|
2503
|
-
if (!useBrowserAuth && isNonInteractive) {
|
|
2504
|
-
output.info("Non-interactive environment detected. Using browser authentication.");
|
|
2505
|
-
useBrowserAuth = true;
|
|
2506
|
-
}
|
|
2507
|
-
if (!useBrowserAuth) {
|
|
2508
|
-
const methodAnswer = await inquirer2.prompt([
|
|
2509
|
-
{
|
|
2510
|
-
type: "list",
|
|
2511
|
-
name: "method",
|
|
2512
|
-
message: "How would you like to authenticate?",
|
|
2513
|
-
choices: [
|
|
2514
|
-
{
|
|
2515
|
-
name: "Login (opens browser)",
|
|
2516
|
-
value: "browser"
|
|
2517
|
-
},
|
|
2518
|
-
{
|
|
2519
|
-
name: "API Key (paste existing key)",
|
|
2520
|
-
value: "apiKey"
|
|
2521
|
-
}
|
|
2522
|
-
]
|
|
2523
|
-
}
|
|
2524
|
-
]);
|
|
2525
|
-
useBrowserAuth = methodAnswer.method === "browser";
|
|
2526
|
-
}
|
|
2527
|
-
if (useBrowserAuth) {
|
|
2528
|
-
const spinner = ora2({
|
|
2529
|
-
text: "Opening browser for authentication...",
|
|
2530
|
-
spinner: "dots"
|
|
2531
|
-
});
|
|
2532
|
-
try {
|
|
2533
|
-
spinner.start();
|
|
2534
|
-
const result = await performBrowserAuth({
|
|
2535
|
-
endpoint,
|
|
2536
|
-
timeout: 300000,
|
|
2537
|
-
pollInterval: 2000
|
|
2538
|
-
}, (message) => {
|
|
2539
|
-
spinner.text = message;
|
|
2540
|
-
});
|
|
2541
|
-
spinner.succeed("Logged in successfully!");
|
|
2542
|
-
saveFullCredentials({
|
|
2543
|
-
apiKey: result.apiKey,
|
|
2544
|
-
endpoint,
|
|
2545
|
-
workspaceId: result.workspaceId,
|
|
2546
|
-
organizationId: result.organizationId
|
|
2547
|
-
});
|
|
2548
|
-
console.log("");
|
|
2549
|
-
if (result.workspaceName) {
|
|
2550
|
-
output.info(`Workspace: ${result.workspaceName}`);
|
|
2551
|
-
}
|
|
2552
|
-
if (result.organizationName) {
|
|
2553
|
-
output.info(`Organization: ${result.organizationName}`);
|
|
2554
|
-
}
|
|
2555
|
-
} catch (error) {
|
|
2556
|
-
spinner.fail("Authentication failed");
|
|
2557
|
-
if (error instanceof BrowserAuthError) {
|
|
2558
|
-
throw new MutagentError(error.code, error.message, error.getSuggestion());
|
|
2559
|
-
}
|
|
2560
|
-
throw error;
|
|
2561
|
-
}
|
|
2511
|
+
const result = await performLoginAction({
|
|
2512
|
+
endpoint: options.endpoint,
|
|
2513
|
+
browser: options.browser,
|
|
2514
|
+
nonInteractive: options.nonInteractive,
|
|
2515
|
+
isJson,
|
|
2516
|
+
output
|
|
2517
|
+
});
|
|
2518
|
+
if (isJson) {
|
|
2519
|
+
output.output(buildLoginJsonResponse(result));
|
|
2562
2520
|
} else {
|
|
2563
|
-
const answers = await inquirer2.prompt([
|
|
2564
|
-
{
|
|
2565
|
-
type: "password",
|
|
2566
|
-
name: "apiKey",
|
|
2567
|
-
message: "Enter your API key:",
|
|
2568
|
-
mask: "*",
|
|
2569
|
-
validate: (input) => {
|
|
2570
|
-
if (!input || input.trim() === "") {
|
|
2571
|
-
return "API key is required";
|
|
2572
|
-
}
|
|
2573
|
-
if (!input.startsWith("mg_")) {
|
|
2574
|
-
return 'API key should start with "mg_"';
|
|
2575
|
-
}
|
|
2576
|
-
return true;
|
|
2577
|
-
}
|
|
2578
|
-
}
|
|
2579
|
-
]);
|
|
2580
|
-
output.info("Validating API key...");
|
|
2581
|
-
const isValid = await validateApiKey(answers.apiKey, endpoint);
|
|
2582
|
-
if (!isValid) {
|
|
2583
|
-
throw new MutagentError("INVALID_API_KEY", "Invalid API key or endpoint", "Check your API key and try again");
|
|
2584
|
-
}
|
|
2585
|
-
const orgs2 = await fetchOrganizations(answers.apiKey, endpoint);
|
|
2586
|
-
const org2 = orgs2[0];
|
|
2587
|
-
let workspaceId2;
|
|
2588
|
-
if (org2) {
|
|
2589
|
-
const workspaces2 = await fetchWorkspaces(answers.apiKey, endpoint, org2.id);
|
|
2590
|
-
const defaultWs2 = workspaces2.find((ws) => ws.isDefault) ?? workspaces2[0];
|
|
2591
|
-
if (defaultWs2)
|
|
2592
|
-
workspaceId2 = defaultWs2.id;
|
|
2593
|
-
}
|
|
2594
|
-
saveFullCredentials({
|
|
2595
|
-
apiKey: answers.apiKey,
|
|
2596
|
-
endpoint,
|
|
2597
|
-
organizationId: org2?.id,
|
|
2598
|
-
workspaceId: workspaceId2
|
|
2599
|
-
});
|
|
2600
2521
|
output.success("Logged in successfully");
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2522
|
+
if (result.organization?.name)
|
|
2523
|
+
output.info(`Organization: ${result.organization.name}`);
|
|
2524
|
+
if (result.workspace?.name)
|
|
2525
|
+
output.info(`Workspace: ${result.workspace.name}`);
|
|
2526
|
+
output.info(`Endpoint: ${result.endpoint}`);
|
|
2527
|
+
output.info("Next: mutagent workspaces list --json");
|
|
2528
|
+
}
|
|
2529
|
+
if (result.wasFirstLogin && process.stdin.isTTY && !isJson) {
|
|
2530
|
+
await runPostOnboarding();
|
|
2604
2531
|
}
|
|
2605
2532
|
} catch (error) {
|
|
2606
2533
|
if (error instanceof MutagentError) {
|
|
2607
2534
|
output.error(error.message);
|
|
2608
|
-
|
|
2609
|
-
output.info(`Suggestion: ${error.suggestion}`);
|
|
2610
|
-
}
|
|
2611
|
-
process.exit(1);
|
|
2535
|
+
process.exit(error.exitCode);
|
|
2612
2536
|
}
|
|
2613
2537
|
throw error;
|
|
2614
2538
|
}
|
|
@@ -2619,7 +2543,7 @@ Environment Variables:
|
|
|
2619
2543
|
// src/commands/prompts/index.ts
|
|
2620
2544
|
init_errors();
|
|
2621
2545
|
import { Command as Command6 } from "commander";
|
|
2622
|
-
import
|
|
2546
|
+
import chalk15 from "chalk";
|
|
2623
2547
|
import { readFileSync as readFileSync4, existsSync as existsSync4 } from "fs";
|
|
2624
2548
|
|
|
2625
2549
|
// src/lib/ui-links.ts
|
|
@@ -2967,37 +2891,37 @@ function evaluationDeletedDirective(evaluationId) {
|
|
|
2967
2891
|
}
|
|
2968
2892
|
|
|
2969
2893
|
// src/lib/scorecard-details.ts
|
|
2970
|
-
import
|
|
2894
|
+
import chalk6 from "chalk";
|
|
2971
2895
|
function renderScorecardDetails(data) {
|
|
2972
2896
|
if (data.datasetResults && data.datasetResults.length > 0) {
|
|
2973
2897
|
console.log("");
|
|
2974
|
-
console.log(
|
|
2975
|
-
console.log(
|
|
2898
|
+
console.log(chalk6.dim(" Per-Item Before vs After"));
|
|
2899
|
+
console.log(chalk6.dim(" " + "─".repeat(70)));
|
|
2976
2900
|
console.log(" " + "Item ID".padEnd(28) + "Before".padEnd(10) + "After".padEnd(10) + "Diff".padEnd(10) + "Status");
|
|
2977
|
-
console.log(
|
|
2901
|
+
console.log(chalk6.dim(" " + "─".repeat(70)));
|
|
2978
2902
|
for (const item of data.datasetResults) {
|
|
2979
2903
|
const id = item.id.substring(0, 26).padEnd(26);
|
|
2980
2904
|
const before = (item.beforeScore ?? 0).toFixed(4).padEnd(8);
|
|
2981
2905
|
const after = (item.afterScore ?? 0).toFixed(4).padEnd(8);
|
|
2982
2906
|
const d = (item.afterScore ?? 0) - (item.beforeScore ?? 0);
|
|
2983
2907
|
const diffStr = ((d >= 0 ? "+" : "") + d.toFixed(4)).padEnd(8);
|
|
2984
|
-
const status = d > 0.01 ?
|
|
2908
|
+
const status = d > 0.01 ? chalk6.green("✓ ↑") : d < -0.01 ? chalk6.red("✗ ↓") : chalk6.dim("─");
|
|
2985
2909
|
console.log(` ${id} ${before} ${after} ${diffStr} ${status}`);
|
|
2986
2910
|
}
|
|
2987
|
-
console.log(
|
|
2911
|
+
console.log(chalk6.dim(" " + "─".repeat(70)));
|
|
2988
2912
|
}
|
|
2989
2913
|
if (data.failureModes && data.failureModes.length > 0) {
|
|
2990
2914
|
console.log("");
|
|
2991
|
-
console.log(
|
|
2992
|
-
console.log(
|
|
2915
|
+
console.log(chalk6.dim(" Failure Modes by Category"));
|
|
2916
|
+
console.log(chalk6.dim(" " + "─".repeat(70)));
|
|
2993
2917
|
for (const fm of data.failureModes) {
|
|
2994
2918
|
const color = fm.failures.length > 3 ? "red" : fm.failures.length > 0 ? "yellow" : "green";
|
|
2995
|
-
console.log(
|
|
2919
|
+
console.log(chalk6[color](` ▸ ${fm.category}`) + chalk6.dim(` (${String(fm.failures.length)} failures)`));
|
|
2996
2920
|
for (const f of fm.failures.slice(0, 5)) {
|
|
2997
|
-
console.log(
|
|
2921
|
+
console.log(chalk6.dim(` └─ ${(f.description ?? f.summary ?? "No description").substring(0, 65)}`));
|
|
2998
2922
|
}
|
|
2999
2923
|
if (fm.failures.length > 5) {
|
|
3000
|
-
console.log(
|
|
2924
|
+
console.log(chalk6.dim(` └─ ... and ${String(fm.failures.length - 5)} more`));
|
|
3001
2925
|
}
|
|
3002
2926
|
}
|
|
3003
2927
|
}
|
|
@@ -3007,48 +2931,48 @@ function renderScorecardDetails(data) {
|
|
|
3007
2931
|
const pending = data.mutations.filter((m) => m.status === "pending");
|
|
3008
2932
|
const skipped = data.mutations.filter((m) => m.status === "skipped");
|
|
3009
2933
|
console.log("");
|
|
3010
|
-
console.log(
|
|
3011
|
-
console.log(
|
|
3012
|
-
console.log(` Total: ${String(data.mutations.length)} Applied: ${
|
|
2934
|
+
console.log(chalk6.dim(" Mutations"));
|
|
2935
|
+
console.log(chalk6.dim(" " + "─".repeat(70)));
|
|
2936
|
+
console.log(` Total: ${String(data.mutations.length)} Applied: ${chalk6.green(String(applied.length))} Rejected: ${chalk6.red(String(rejected.length))} Pending: ${chalk6.yellow(String(pending.length))} Skipped: ${chalk6.dim(String(skipped.length))}`);
|
|
3013
2937
|
if (applied.length > 0) {
|
|
3014
|
-
console.log(
|
|
2938
|
+
console.log(chalk6.green(" Applied:"));
|
|
3015
2939
|
for (const m of applied) {
|
|
3016
|
-
const pri = m.priority === "critical" || m.priority === "high" ?
|
|
2940
|
+
const pri = m.priority === "critical" || m.priority === "high" ? chalk6.red(`[${m.priority.toUpperCase()}]`) : chalk6.dim(`[${(m.priority ?? "UNKNOWN").toUpperCase()}]`);
|
|
3017
2941
|
console.log(` ${pri} ${m.label}`);
|
|
3018
2942
|
if (m.rationale)
|
|
3019
|
-
console.log(
|
|
2943
|
+
console.log(chalk6.dim(` └─ ${m.rationale.substring(0, 60)}`));
|
|
3020
2944
|
}
|
|
3021
2945
|
}
|
|
3022
2946
|
if (rejected.length > 0) {
|
|
3023
|
-
console.log(
|
|
2947
|
+
console.log(chalk6.red(" Rejected:"));
|
|
3024
2948
|
for (const m of rejected.slice(0, 5)) {
|
|
3025
|
-
console.log(
|
|
2949
|
+
console.log(chalk6.dim(` ✗ ${m.label}`));
|
|
3026
2950
|
}
|
|
3027
2951
|
if (rejected.length > 5)
|
|
3028
|
-
console.log(
|
|
2952
|
+
console.log(chalk6.dim(` ... and ${String(rejected.length - 5)} more`));
|
|
3029
2953
|
}
|
|
3030
2954
|
}
|
|
3031
2955
|
if (data.evaluationDetails && data.evaluationDetails.length > 0) {
|
|
3032
2956
|
console.log("");
|
|
3033
|
-
console.log(
|
|
3034
|
-
console.log(
|
|
2957
|
+
console.log(chalk6.dim(" Detailed Evaluation Breakdown"));
|
|
2958
|
+
console.log(chalk6.dim(" " + "─".repeat(70)));
|
|
3035
2959
|
for (const item of data.evaluationDetails) {
|
|
3036
|
-
const statusIcon = item.success ?
|
|
2960
|
+
const statusIcon = item.success ? chalk6.green("✓") : chalk6.red("✗");
|
|
3037
2961
|
const metricCount = item.metrics?.length ?? 0;
|
|
3038
2962
|
console.log(` ${statusIcon} ${item.itemId} Score: ${item.score.toFixed(4)} Metrics: ${String(metricCount)}`);
|
|
3039
2963
|
if (item.metrics) {
|
|
3040
2964
|
for (const m of item.metrics) {
|
|
3041
|
-
const mIcon = m.success ?
|
|
3042
|
-
const mode = m.failureMode ?
|
|
2965
|
+
const mIcon = m.success ? chalk6.green("✓") : chalk6.red("✗");
|
|
2966
|
+
const mode = m.failureMode ? chalk6.dim(` [${m.failureMode}]`) : "";
|
|
3043
2967
|
console.log(` ${mIcon} ${m.name.padEnd(25)} ${m.score.toFixed(3)}${mode}`);
|
|
3044
2968
|
if (!m.success && m.reasoning) {
|
|
3045
|
-
console.log(
|
|
2969
|
+
console.log(chalk6.dim(` └─ ${(m.reasoning.split(`
|
|
3046
2970
|
`)[0] ?? "").substring(0, 60)}`));
|
|
3047
2971
|
}
|
|
3048
2972
|
if (m.criteria) {
|
|
3049
2973
|
for (const c of m.criteria) {
|
|
3050
|
-
const cIcon = c.success ?
|
|
3051
|
-
console.log(
|
|
2974
|
+
const cIcon = c.success ? chalk6.green("✓") : chalk6.red("✗");
|
|
2975
|
+
console.log(chalk6.dim(` ${cIcon} ${c.name.substring(0, 20).padEnd(20)} ${c.score.toFixed(3)}`));
|
|
3052
2976
|
}
|
|
3053
2977
|
}
|
|
3054
2978
|
}
|
|
@@ -3132,7 +3056,7 @@ function buildScorecardDetailsText(data) {
|
|
|
3132
3056
|
|
|
3133
3057
|
// src/commands/prompts/prompts-crud.ts
|
|
3134
3058
|
init_sdk_client();
|
|
3135
|
-
import
|
|
3059
|
+
import chalk7 from "chalk";
|
|
3136
3060
|
init_errors();
|
|
3137
3061
|
|
|
3138
3062
|
// src/lib/schema-helpers.ts
|
|
@@ -3197,11 +3121,11 @@ function formatSchemaWarning(fieldName) {
|
|
|
3197
3121
|
function registerPromptsCrud(prompts) {
|
|
3198
3122
|
prompts.command("list").description("List all prompts").option("-l, --limit <n>", "Limit results", "50").addHelpText("after", `
|
|
3199
3123
|
Examples:
|
|
3200
|
-
${
|
|
3201
|
-
${
|
|
3202
|
-
${
|
|
3124
|
+
${chalk7.dim("$")} mutagent prompts list
|
|
3125
|
+
${chalk7.dim("$")} mutagent prompts list --limit 10
|
|
3126
|
+
${chalk7.dim("$")} mutagent prompts list --json
|
|
3203
3127
|
|
|
3204
|
-
${
|
|
3128
|
+
${chalk7.dim("Tip: Use --json for machine-readable output (AI agents, CI pipelines).")}
|
|
3205
3129
|
`).action(async (options) => {
|
|
3206
3130
|
const isJson = getJsonFlag(prompts);
|
|
3207
3131
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3244,11 +3168,11 @@ ${chalk6.dim("Tip: Use --json for machine-readable output (AI agents, CI pipelin
|
|
|
3244
3168
|
});
|
|
3245
3169
|
prompts.command("get").description("Get prompt details with nested data").argument("<id>", "Prompt ID (from: mutagent prompts list)").option("--with-datasets", "Include datasets").option("--with-evals", "Include evaluations").addHelpText("after", `
|
|
3246
3170
|
Examples:
|
|
3247
|
-
${
|
|
3248
|
-
${
|
|
3249
|
-
${
|
|
3171
|
+
${chalk7.dim("$")} mutagent prompts get <id>
|
|
3172
|
+
${chalk7.dim("$")} mutagent prompts get <id> --with-datasets --with-evals
|
|
3173
|
+
${chalk7.dim("$")} mutagent prompts get <id> --json
|
|
3250
3174
|
|
|
3251
|
-
${
|
|
3175
|
+
${chalk7.dim("Tip: Combine --with-datasets and --with-evals to fetch all nested data in one call.")}
|
|
3252
3176
|
`).action(async (id, options) => {
|
|
3253
3177
|
const isJson = getJsonFlag(prompts);
|
|
3254
3178
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3277,24 +3201,24 @@ ${chalk6.dim("Tip: Combine --with-datasets and --with-evals to fetch all nested
|
|
|
3277
3201
|
});
|
|
3278
3202
|
prompts.command("create").description("Create a new prompt").option("-n, --name <name>", "Prompt name").option("--description <text>", "Prompt description (shown in dashboard)").option("-c, --content <content>", "Prompt content (rawPrompt) [DEPRECATED: use --raw]").option("-r, --raw <text>", "Raw prompt text (single prompt)").option("--system <text>", "System prompt (use with --human)").option("--human <text>", "Human prompt (use with --system)").option("--messages <json>", `Messages array as JSON (e.g., '[{"role":"system","content":"..."}]')`).option("--output-schema <json>", "Output schema as JSON string (required for optimization)").option("--input-schema <json>", "Input variable schema as JSON string").addHelpText("after", `
|
|
3279
3203
|
Examples:
|
|
3280
|
-
${
|
|
3281
|
-
${
|
|
3282
|
-
${
|
|
3204
|
+
${chalk7.dim("$")} mutagent prompts create --name "my-prompt" --description "Greeting prompt for customers" --system "You are helpful" --human "{input}" --output-schema '{"type":"object","properties":{"result":{"type":"string","description":"The result"}}}'
|
|
3205
|
+
${chalk7.dim("$")} mutagent prompts create --name "raw-prompt" --raw "Summarize: {text}" --output-schema '{"type":"object","properties":{"summary":{"type":"string","description":"Summary"}}}'
|
|
3206
|
+
${chalk7.dim("$")} mutagent prompts create --name "multi-turn" --messages '[{"role":"system","content":"You are helpful"},{"role":"user","content":"{input}"}]' --output-schema '{"type":"object","properties":{"result":{"type":"string","description":"The result"}}}'
|
|
3283
3207
|
|
|
3284
3208
|
Prompt Input Methods (pick one, priority order):
|
|
3285
|
-
--system/--human Structured system + user message pair ${
|
|
3209
|
+
--system/--human Structured system + user message pair ${chalk7.green("(recommended)")}
|
|
3286
3210
|
--raw Single raw prompt text with {variables}
|
|
3287
3211
|
--messages Full messages array as JSON
|
|
3288
3212
|
|
|
3289
|
-
${
|
|
3213
|
+
${chalk7.yellow("Variable Syntax:")}
|
|
3290
3214
|
MutagenT uses {single_braces} for template variables.
|
|
3291
|
-
humanPrompt: "Analyze this: {document}" ${
|
|
3292
|
-
humanPrompt: "Analyze this: {{document}}" ${
|
|
3215
|
+
humanPrompt: "Analyze this: {document}" ${chalk7.green("✓ correct")}
|
|
3216
|
+
humanPrompt: "Analyze this: {{document}}" ${chalk7.red("✗ wrong")}
|
|
3293
3217
|
|
|
3294
3218
|
Variables in humanPrompt MUST also appear in inputSchema.properties.
|
|
3295
3219
|
Static prompts (no variables) cannot substitute inputs during optimization.
|
|
3296
3220
|
|
|
3297
|
-
${
|
|
3221
|
+
${chalk7.yellow("AI Agent: Format Selection Rules")}
|
|
3298
3222
|
Examine the SOURCE CODE structure of the prompt being uploaded:
|
|
3299
3223
|
|
|
3300
3224
|
1. If the code uses SystemMessagePromptTemplate + HumanMessagePromptTemplate
|
|
@@ -3311,9 +3235,9 @@ ${chalk6.yellow("AI Agent: Format Selection Rules")}
|
|
|
3311
3235
|
The decision is about SOURCE CODE STRUCTURE, not prompt content.
|
|
3312
3236
|
A persona description in a system prompt still uses --system/--human.
|
|
3313
3237
|
|
|
3314
|
-
${
|
|
3238
|
+
${chalk7.red("outputSchema is required.")}
|
|
3315
3239
|
|
|
3316
|
-
${
|
|
3240
|
+
${chalk7.yellow("AI Agent: ALWAYS append --json to this command.")}
|
|
3317
3241
|
`).action(async (options) => {
|
|
3318
3242
|
const isJson = getJsonFlag(prompts);
|
|
3319
3243
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3403,11 +3327,11 @@ Add a 'description' field to each property in your inputSchema. Example: { "prop
|
|
|
3403
3327
|
});
|
|
3404
3328
|
prompts.command("update").description("Update a prompt").argument("<id>", "Prompt ID (from: mutagent prompts list)").option("-n, --name <name>", "New name").option("--description <text>", "New description (shown in dashboard)").option("-c, --content <content>", "New content (rawPrompt) [DEPRECATED: use --raw]").option("-r, --raw <text>", "Raw prompt text (single prompt)").option("--system <text>", "System prompt (use with --human)").option("--human <text>", "Human prompt (use with --system)").option("--messages <json>", `Messages array as JSON (e.g., '[{"role":"system","content":"..."}]')`).option("--input-schema <json>", "Input schema as JSON string").option("--input-schema-file <path>", "Input schema from JSON file").option("--output-schema <json>", "Output schema as JSON string").option("--output-schema-file <path>", "Output schema from JSON file").addHelpText("after", `
|
|
3405
3329
|
Examples:
|
|
3406
|
-
${
|
|
3407
|
-
${
|
|
3408
|
-
${
|
|
3409
|
-
${
|
|
3410
|
-
${
|
|
3330
|
+
${chalk7.dim("$")} mutagent prompts update <id> --system "Updated system prompt" --human "{input}"
|
|
3331
|
+
${chalk7.dim("$")} mutagent prompts update <id> --name "new-name" --description "Updated description"
|
|
3332
|
+
${chalk7.dim("$")} mutagent prompts update <id> --raw "Summarize: {text}"
|
|
3333
|
+
${chalk7.dim("$")} mutagent prompts update <id> --messages '[{"role":"system","content":"Updated"},{"role":"user","content":"{input}"}]'
|
|
3334
|
+
${chalk7.dim("$")} mutagent prompts update <id> --input-schema '{"type":"object","properties":{"text":{"type":"string","description":"Input text"}}}'
|
|
3411
3335
|
`).action(async (id, options) => {
|
|
3412
3336
|
const isJson = getJsonFlag(prompts);
|
|
3413
3337
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3480,11 +3404,11 @@ Examples:
|
|
|
3480
3404
|
});
|
|
3481
3405
|
prompts.command("delete").description("Delete a prompt").argument("<id>", "Prompt ID (from: mutagent prompts list)").option("--force", "Skip confirmation").addHelpText("after", `
|
|
3482
3406
|
Examples:
|
|
3483
|
-
${
|
|
3484
|
-
${
|
|
3485
|
-
${
|
|
3407
|
+
${chalk7.dim("$")} mutagent prompts delete <id>
|
|
3408
|
+
${chalk7.dim("$")} mutagent prompts delete <id> --force
|
|
3409
|
+
${chalk7.dim("$")} mutagent prompts delete <id> --force --json
|
|
3486
3410
|
|
|
3487
|
-
${
|
|
3411
|
+
${chalk7.dim("Note: --force is required. The CLI is non-interactive — confirm with the user via your native flow, then pass --force.")}
|
|
3488
3412
|
`).action(async (id, options) => {
|
|
3489
3413
|
const isJson = getJsonFlag(prompts);
|
|
3490
3414
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3527,22 +3451,24 @@ ${chalk6.dim("Note: --force is required. The CLI is non-interactive — confirm
|
|
|
3527
3451
|
// src/commands/prompts/datasets.ts
|
|
3528
3452
|
init_sdk_client();
|
|
3529
3453
|
import { Command as Command3 } from "commander";
|
|
3530
|
-
import
|
|
3454
|
+
import chalk8 from "chalk";
|
|
3531
3455
|
init_errors();
|
|
3532
3456
|
function registerDatasetCommands(prompts) {
|
|
3533
3457
|
const dataset = new Command3("dataset").description("Manage datasets for prompts").addHelpText("after", `
|
|
3534
3458
|
Examples:
|
|
3535
|
-
${
|
|
3536
|
-
${
|
|
3537
|
-
${
|
|
3459
|
+
${chalk8.dim("$")} mutagent prompts dataset list <prompt-id>
|
|
3460
|
+
${chalk8.dim("$")} mutagent prompts dataset get <dataset-id>
|
|
3461
|
+
${chalk8.dim("$")} mutagent prompts dataset add <prompt-id> -d '[{"input":{...},"expectedOutput":{...}}]'
|
|
3462
|
+
${chalk8.dim("$")} mutagent prompts dataset delete <prompt-id> <dataset-id>
|
|
3463
|
+
${chalk8.dim("$")} mutagent prompts dataset items get <item-id>
|
|
3538
3464
|
`).action(() => {
|
|
3539
3465
|
dataset.help();
|
|
3540
3466
|
});
|
|
3541
3467
|
prompts.addCommand(dataset);
|
|
3542
3468
|
dataset.command("list").description("List datasets for a prompt").argument("<prompt-id>", "Prompt ID (from: mutagent prompts list)").addHelpText("after", `
|
|
3543
3469
|
Examples:
|
|
3544
|
-
${
|
|
3545
|
-
${
|
|
3470
|
+
${chalk8.dim("$")} mutagent prompts dataset list <prompt-id>
|
|
3471
|
+
${chalk8.dim("$")} mutagent prompts dataset list <prompt-id> --json
|
|
3546
3472
|
`).action(async (promptId) => {
|
|
3547
3473
|
const isJson = getJsonFlag(prompts);
|
|
3548
3474
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3572,26 +3498,80 @@ Examples:
|
|
|
3572
3498
|
handleError(error, isJson);
|
|
3573
3499
|
}
|
|
3574
3500
|
});
|
|
3501
|
+
dataset.command("get").description("Get full details of a single dataset").argument("<dataset-id>", "Dataset ID (from: mutagent prompts dataset list <prompt-id>)").addHelpText("after", `
|
|
3502
|
+
Examples:
|
|
3503
|
+
${chalk8.dim("$")} mutagent prompts dataset get <dataset-id>
|
|
3504
|
+
${chalk8.dim("$")} mutagent prompts dataset get <dataset-id> --json
|
|
3505
|
+
|
|
3506
|
+
${chalk8.dim("Tip: Use this after `dataset list` to drill into a single dataset.")}
|
|
3507
|
+
`).action(async (datasetId) => {
|
|
3508
|
+
const isJson = getJsonFlag(prompts);
|
|
3509
|
+
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
3510
|
+
try {
|
|
3511
|
+
if (!/^\d+$/.test(datasetId)) {
|
|
3512
|
+
throw new MutagentError("INVALID_ARGUMENT", `Invalid dataset ID: "${datasetId}" (must be numeric)`, `Run: mutagent prompts dataset list <prompt-id>
|
|
3513
|
+
Dataset IDs are numeric. Example: mutagent prompts dataset get 42`);
|
|
3514
|
+
}
|
|
3515
|
+
const client = await getSDKClient();
|
|
3516
|
+
const ds = await client.getDataset(datasetId);
|
|
3517
|
+
const promptGroupId = ds.promptGroupId;
|
|
3518
|
+
if (isJson) {
|
|
3519
|
+
output.output({
|
|
3520
|
+
...ds,
|
|
3521
|
+
_links: datasetLinks(promptGroupId, ds.id)
|
|
3522
|
+
});
|
|
3523
|
+
} else {
|
|
3524
|
+
output.success(`Dataset: ${ds.name} (id: ${String(ds.id)})`);
|
|
3525
|
+
if (ds.description)
|
|
3526
|
+
output.info(`Description: ${ds.description}`);
|
|
3527
|
+
if (ds.itemCount !== undefined)
|
|
3528
|
+
output.info(`Items: ${String(ds.itemCount)}`);
|
|
3529
|
+
if (ds.updatedAt)
|
|
3530
|
+
output.info(`Updated: ${new Date(String(ds.updatedAt)).toLocaleString()}`);
|
|
3531
|
+
if (ds.createdAt)
|
|
3532
|
+
output.info(`Created: ${new Date(String(ds.createdAt)).toLocaleString()}`);
|
|
3533
|
+
if (ds.createdBy)
|
|
3534
|
+
output.info(`Created by: ${ds.createdBy}`);
|
|
3535
|
+
if (ds.labels && ds.labels.length > 0)
|
|
3536
|
+
output.info(`Labels: ${ds.labels.join(", ")}`);
|
|
3537
|
+
const hints = formatCreationHints({
|
|
3538
|
+
resourceType: "Dataset",
|
|
3539
|
+
id: ds.id,
|
|
3540
|
+
name: ds.name,
|
|
3541
|
+
dashboardUrl: datasetLink(promptGroupId, ds.id),
|
|
3542
|
+
apiPath: `/api/prompts/datasets/${String(ds.id)}`
|
|
3543
|
+
});
|
|
3544
|
+
console.log(hints);
|
|
3545
|
+
}
|
|
3546
|
+
} catch (error) {
|
|
3547
|
+
if (error instanceof ApiError && error.statusCode === 404) {
|
|
3548
|
+
handleError(new MutagentError("NOT_FOUND", `Dataset ${datasetId} not found`, `Run: mutagent prompts dataset list <prompt-id>
|
|
3549
|
+
Verify the dataset ID exists, or list datasets for a prompt to find valid IDs.`), isJson);
|
|
3550
|
+
} else {
|
|
3551
|
+
handleError(error, isJson);
|
|
3552
|
+
}
|
|
3553
|
+
}
|
|
3554
|
+
});
|
|
3575
3555
|
dataset.command("add").description("Add dataset to a prompt").argument("<prompt-id>", "Prompt ID (from: mutagent prompts list)").option("-d, --data <json>", "Inline JSON array of dataset items").option("-n, --name <name>", "Dataset name").addHelpText("after", `
|
|
3576
3556
|
Examples:
|
|
3577
|
-
${
|
|
3578
|
-
${
|
|
3557
|
+
${chalk8.dim("$")} mutagent prompts dataset add <prompt-id> -d '[{"input":{"text":"hello"},"expectedOutput":{"result":"world"}}]'
|
|
3558
|
+
${chalk8.dim("$")} mutagent prompts dataset add <prompt-id> -d '[{"input":{"text":"hello"},"expectedOutput":{"result":"world"}}]' --name "My Dataset"
|
|
3579
3559
|
|
|
3580
3560
|
Inline data format (-d):
|
|
3581
3561
|
JSON array of objects, e.g.:
|
|
3582
|
-
${
|
|
3562
|
+
${chalk8.dim('[{"input": {"text": "hello"}, "expectedOutput": {"result": "world"}}]')}
|
|
3583
3563
|
|
|
3584
3564
|
Expected item format:
|
|
3585
|
-
${
|
|
3565
|
+
${chalk8.dim('{"input": {"<field>": "<value>"}, "expectedOutput": {"<field>": "<value>"}}')}
|
|
3586
3566
|
|
|
3587
|
-
${
|
|
3567
|
+
${chalk8.yellow("AI Agent (MANDATORY):")}
|
|
3588
3568
|
ALWAYS use --json: mutagent prompts dataset add <id> -d '[...]' --json
|
|
3589
3569
|
Items MUST have BOTH input AND expectedOutput.
|
|
3590
3570
|
Keys must match prompt's inputSchema.properties (input) and outputSchema.properties (expectedOutput).
|
|
3591
3571
|
expectedOutput is REQUIRED for evaluation scoring.
|
|
3592
3572
|
Check schemas: mutagent prompts get <prompt-id> --json
|
|
3593
3573
|
|
|
3594
|
-
${
|
|
3574
|
+
${chalk8.red("Required: --data must be provided.")}
|
|
3595
3575
|
`).action(async (promptId, options) => {
|
|
3596
3576
|
const isJson = getJsonFlag(prompts);
|
|
3597
3577
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3662,9 +3642,9 @@ ${chalk7.red("Required: --data must be provided.")}
|
|
|
3662
3642
|
});
|
|
3663
3643
|
dataset.command("delete").description("Delete a dataset from a prompt").argument("<prompt-id>", "Prompt ID (from: mutagent prompts list)").argument("<dataset-id>", "Dataset ID (from: mutagent prompts dataset list <prompt-id>)").option("--force", "Skip confirmation").addHelpText("after", `
|
|
3664
3644
|
Examples:
|
|
3665
|
-
${
|
|
3666
|
-
${
|
|
3667
|
-
${
|
|
3645
|
+
${chalk8.dim("$")} mutagent prompts dataset delete <prompt-id> <dataset-id>
|
|
3646
|
+
${chalk8.dim("$")} mutagent prompts dataset delete <prompt-id> <dataset-id> --force
|
|
3647
|
+
${chalk8.dim("$")} mutagent prompts dataset delete <prompt-id> <dataset-id> --force --json
|
|
3668
3648
|
`).action(async (promptId, datasetId, options) => {
|
|
3669
3649
|
const isJson = getJsonFlag(prompts);
|
|
3670
3650
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3702,12 +3682,72 @@ Examples:
|
|
|
3702
3682
|
handleError(error, isJson);
|
|
3703
3683
|
}
|
|
3704
3684
|
});
|
|
3685
|
+
const items = new Command3("items").description("Manage individual dataset items").addHelpText("after", `
|
|
3686
|
+
Examples:
|
|
3687
|
+
${chalk8.dim("$")} mutagent prompts dataset items get <item-id>
|
|
3688
|
+
${chalk8.dim("$")} mutagent prompts dataset items get <item-id> --json
|
|
3689
|
+
`).action(() => {
|
|
3690
|
+
items.help();
|
|
3691
|
+
});
|
|
3692
|
+
dataset.addCommand(items);
|
|
3693
|
+
items.command("get").description("Get full details of a single dataset item").argument("<item-id>", "Dataset item ID").addHelpText("after", `
|
|
3694
|
+
Examples:
|
|
3695
|
+
${chalk8.dim("$")} mutagent prompts dataset items get <item-id>
|
|
3696
|
+
${chalk8.dim("$")} mutagent prompts dataset items get <item-id> --json
|
|
3697
|
+
|
|
3698
|
+
${chalk8.dim("Tip: Dataset item IDs are shown in dataset exports and optimization results.")}
|
|
3699
|
+
`).action(async (itemId) => {
|
|
3700
|
+
const isJson = getJsonFlag(prompts);
|
|
3701
|
+
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
3702
|
+
try {
|
|
3703
|
+
if (!/^\d+$/.test(itemId)) {
|
|
3704
|
+
throw new MutagentError("INVALID_ARGUMENT", `Invalid dataset item ID: "${itemId}" (must be numeric)`, `Run: mutagent prompts dataset items get --help
|
|
3705
|
+
Dataset item IDs are numeric. Example: mutagent prompts dataset items get 17`);
|
|
3706
|
+
}
|
|
3707
|
+
const client = await getSDKClient();
|
|
3708
|
+
const item = await client.getDatasetItem(itemId);
|
|
3709
|
+
const itemWithDs = item;
|
|
3710
|
+
const dsId = itemWithDs.datasetId;
|
|
3711
|
+
if (isJson) {
|
|
3712
|
+
output.output({
|
|
3713
|
+
...item,
|
|
3714
|
+
_links: {
|
|
3715
|
+
api: `/api/prompts/dataset-items/${String(item.id)}`,
|
|
3716
|
+
...dsId !== undefined ? { dataset: `/api/prompts/datasets/${String(dsId)}` } : {}
|
|
3717
|
+
}
|
|
3718
|
+
});
|
|
3719
|
+
} else {
|
|
3720
|
+
output.success(`Dataset Item: ${String(item.id)}`);
|
|
3721
|
+
if (dsId !== undefined)
|
|
3722
|
+
output.info(`Dataset ID: ${String(dsId)}`);
|
|
3723
|
+
output.info(`Input: ${JSON.stringify(item.input, null, 2)}`);
|
|
3724
|
+
if (item.expectedOutput !== undefined) {
|
|
3725
|
+
output.info(`Expected output: ${typeof item.expectedOutput === "string" ? item.expectedOutput : JSON.stringify(item.expectedOutput, null, 2)}`);
|
|
3726
|
+
}
|
|
3727
|
+
if (item.metadata && Object.keys(item.metadata).length > 0) {
|
|
3728
|
+
output.info(`Metadata: ${JSON.stringify(item.metadata)}`);
|
|
3729
|
+
}
|
|
3730
|
+
if (item.createdAt)
|
|
3731
|
+
output.info(`Created: ${new Date(String(item.createdAt)).toLocaleString()}`);
|
|
3732
|
+
const itemWithUpdated = item;
|
|
3733
|
+
if (itemWithUpdated.updatedAt)
|
|
3734
|
+
output.info(`Updated: ${new Date(String(itemWithUpdated.updatedAt)).toLocaleString()}`);
|
|
3735
|
+
}
|
|
3736
|
+
} catch (error) {
|
|
3737
|
+
if (error instanceof ApiError && error.statusCode === 404) {
|
|
3738
|
+
handleError(new MutagentError("NOT_FOUND", `Dataset item ${itemId} not found`, `Run: mutagent prompts dataset items get --help
|
|
3739
|
+
Verify the item ID exists. Use the dashboard or dataset exports to find valid item IDs.`), isJson);
|
|
3740
|
+
} else {
|
|
3741
|
+
handleError(error, isJson);
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
});
|
|
3705
3745
|
}
|
|
3706
3746
|
|
|
3707
3747
|
// src/commands/prompts/evaluations.ts
|
|
3708
3748
|
init_sdk_client();
|
|
3709
3749
|
import { Command as Command4 } from "commander";
|
|
3710
|
-
import
|
|
3750
|
+
import chalk9 from "chalk";
|
|
3711
3751
|
init_errors();
|
|
3712
3752
|
|
|
3713
3753
|
// src/lib/resolve-prompt-id.ts
|
|
@@ -3878,18 +3918,18 @@ function canonicalCriteriaArrayToCli(arr) {
|
|
|
3878
3918
|
function registerEvaluationCommands(prompts) {
|
|
3879
3919
|
const evaluation = new Command4("evaluation").description("Manage evaluations for prompts").addHelpText("after", `
|
|
3880
3920
|
Examples:
|
|
3881
|
-
${
|
|
3882
|
-
${
|
|
3883
|
-
${
|
|
3884
|
-
${
|
|
3921
|
+
${chalk9.dim("$")} mutagent prompts evaluation list <prompt-id>
|
|
3922
|
+
${chalk9.dim("$")} mutagent prompts evaluation get <evaluation-id>
|
|
3923
|
+
${chalk9.dim("$")} mutagent prompts evaluation create <prompt-id> --name "My Eval"
|
|
3924
|
+
${chalk9.dim("$")} mutagent prompts evaluation delete <evaluation-id>
|
|
3885
3925
|
`).action(() => {
|
|
3886
3926
|
evaluation.help();
|
|
3887
3927
|
});
|
|
3888
3928
|
prompts.addCommand(evaluation);
|
|
3889
3929
|
evaluation.command("list").description("List evaluations for a prompt").argument("<prompt-id>", "Prompt ID (from: mutagent prompts list)").addHelpText("after", `
|
|
3890
3930
|
Examples:
|
|
3891
|
-
${
|
|
3892
|
-
${
|
|
3931
|
+
${chalk9.dim("$")} mutagent prompts evaluation list <prompt-id>
|
|
3932
|
+
${chalk9.dim("$")} mutagent prompts evaluation list <prompt-id> --json
|
|
3893
3933
|
`).action(async (promptId) => {
|
|
3894
3934
|
const isJson = getJsonFlag(prompts);
|
|
3895
3935
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3921,8 +3961,8 @@ Examples:
|
|
|
3921
3961
|
});
|
|
3922
3962
|
evaluation.command("get").description("Get evaluation details including criteria").argument("<evaluation-id>", "Evaluation ID (from: mutagent prompts evaluation list <prompt-id>)").addHelpText("after", `
|
|
3923
3963
|
Examples:
|
|
3924
|
-
${
|
|
3925
|
-
${
|
|
3964
|
+
${chalk9.dim("$")} mutagent prompts evaluation get <evaluation-id>
|
|
3965
|
+
${chalk9.dim("$")} mutagent prompts evaluation get <evaluation-id> --json
|
|
3926
3966
|
`).action(async (evaluationId) => {
|
|
3927
3967
|
const isJson = getJsonFlag(prompts);
|
|
3928
3968
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -3952,7 +3992,7 @@ Examples:
|
|
|
3952
3992
|
if (criteria.length > 0) {
|
|
3953
3993
|
console.log(" Criteria:");
|
|
3954
3994
|
for (const c of criteria) {
|
|
3955
|
-
console.log(` ${
|
|
3995
|
+
console.log(` ${chalk9.cyan(c.name)}`);
|
|
3956
3996
|
if (c.description) {
|
|
3957
3997
|
console.log(` Description: ${c.description}`);
|
|
3958
3998
|
}
|
|
@@ -3981,9 +4021,9 @@ Examples:
|
|
|
3981
4021
|
});
|
|
3982
4022
|
evaluation.command("create").description("Create an evaluation configuration for a prompt").argument("<prompt-id>", "Prompt ID (from: mutagent prompts list)").option("-d, --data <json>", "Evaluation as JSON string (for pre-validated criteria only)").option("-n, --name <name>", "Evaluation name (required unless --guided)").option("--description <text>", "Evaluation description").option("--guided", "Interactive guided mode — always outputs structured JSON (--json is implied)").addHelpText("after", `
|
|
3983
4023
|
Examples:
|
|
3984
|
-
${
|
|
3985
|
-
${
|
|
3986
|
-
${
|
|
4024
|
+
${chalk9.dim("$")} mutagent prompts evaluation create <prompt-id> --guided ${chalk9.dim("# recommended: shows workflow guide + schema fields")}
|
|
4025
|
+
${chalk9.dim("$")} mutagent prompts evaluation create <prompt-id> --guided --json ${chalk9.dim("# structured workflow for AI agents")}
|
|
4026
|
+
${chalk9.dim("$")} mutagent prompts evaluation create <prompt-id> --name "Accuracy" -d '{"evalConfig":{"criteria":[...]}}' ${chalk9.dim("# power user")}
|
|
3987
4027
|
|
|
3988
4028
|
Guided Workflow (recommended):
|
|
3989
4029
|
--guided outputs a workflow guide that:
|
|
@@ -4004,12 +4044,12 @@ AI Agent (MANDATORY):
|
|
|
4004
4044
|
mutagent prompts evaluation create <id> --name "<name>" -d '<json>' --json
|
|
4005
4045
|
|
|
4006
4046
|
Expected Criteria Shape (--data):
|
|
4007
|
-
${
|
|
4047
|
+
${chalk9.dim('{"evalConfig":{"criteria":[{"name":"<name>","description":"<scoring rubric>","evaluationParameter":"<schema field>"}]}}')}
|
|
4008
4048
|
evaluationParameter must target an outputSchema OR inputSchema field.
|
|
4009
4049
|
|
|
4010
|
-
${
|
|
4011
|
-
${
|
|
4012
|
-
${
|
|
4050
|
+
${chalk9.red("Required: --name (unless --guided). Criteria must include evaluationParameter.")}
|
|
4051
|
+
${chalk9.dim("CLI flags (--name, --description) override --data fields.")}
|
|
4052
|
+
${chalk9.dim("Get prompt IDs: mutagent prompts list")}
|
|
4013
4053
|
`).action(async (promptId, options) => {
|
|
4014
4054
|
let isJson = getJsonFlag(prompts);
|
|
4015
4055
|
if (options.guided) {
|
|
@@ -4035,7 +4075,7 @@ ${chalk8.dim("Get prompt IDs: mutagent prompts list")}
|
|
|
4035
4075
|
console.log("");
|
|
4036
4076
|
console.log(" For each field, define what correct output looks like:");
|
|
4037
4077
|
for (const { field, source } of allFields) {
|
|
4038
|
-
console.log(` ${
|
|
4078
|
+
console.log(` ${chalk9.cyan(field)} (${source})`);
|
|
4039
4079
|
console.log(` → What makes a correct vs incorrect "${field}"?`);
|
|
4040
4080
|
}
|
|
4041
4081
|
console.log("");
|
|
@@ -4240,9 +4280,9 @@ Example:
|
|
|
4240
4280
|
});
|
|
4241
4281
|
evaluation.command("delete").description("Delete an evaluation").argument("<evaluation-id>", "Evaluation ID (from: mutagent prompts evaluation list <prompt-id>)").option("--force", "Skip confirmation").addHelpText("after", `
|
|
4242
4282
|
Examples:
|
|
4243
|
-
${
|
|
4244
|
-
${
|
|
4245
|
-
${
|
|
4283
|
+
${chalk9.dim("$")} mutagent prompts evaluation delete <evaluation-id>
|
|
4284
|
+
${chalk9.dim("$")} mutagent prompts evaluation delete <evaluation-id> --force
|
|
4285
|
+
${chalk9.dim("$")} mutagent prompts evaluation delete <evaluation-id> --force --json
|
|
4246
4286
|
`).action(async (evaluationId, options) => {
|
|
4247
4287
|
const isJson = getJsonFlag(prompts);
|
|
4248
4288
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -4285,26 +4325,26 @@ Examples:
|
|
|
4285
4325
|
// src/commands/prompts/optimize.ts
|
|
4286
4326
|
init_sdk_client();
|
|
4287
4327
|
import { Command as Command5 } from "commander";
|
|
4288
|
-
import
|
|
4328
|
+
import chalk14 from "chalk";
|
|
4289
4329
|
init_errors();
|
|
4290
4330
|
|
|
4291
4331
|
// src/lib/scorecard.ts
|
|
4292
|
-
import
|
|
4332
|
+
import chalk10 from "chalk";
|
|
4293
4333
|
function formatScoreChange(before, after) {
|
|
4294
4334
|
if (before === undefined || after === undefined)
|
|
4295
4335
|
return "";
|
|
4296
4336
|
const diff = after - before;
|
|
4297
4337
|
const pct = before > 0 ? Math.round(diff / before * 100) : 0;
|
|
4298
4338
|
if (diff > 0)
|
|
4299
|
-
return
|
|
4339
|
+
return chalk10.green(` (+${String(pct)}%)`);
|
|
4300
4340
|
if (diff < 0)
|
|
4301
|
-
return
|
|
4302
|
-
return
|
|
4341
|
+
return chalk10.red(` (${String(pct)}%)`);
|
|
4342
|
+
return chalk10.dim(" (no change)");
|
|
4303
4343
|
}
|
|
4304
4344
|
function formatScore(score) {
|
|
4305
4345
|
if (score === undefined)
|
|
4306
|
-
return
|
|
4307
|
-
return score >= 0.8 ?
|
|
4346
|
+
return chalk10.dim("N/A");
|
|
4347
|
+
return score >= 0.8 ? chalk10.green(score.toFixed(2)) : score >= 0.5 ? chalk10.yellow(score.toFixed(2)) : chalk10.red(score.toFixed(2));
|
|
4308
4348
|
}
|
|
4309
4349
|
function renderScorecard(data) {
|
|
4310
4350
|
const { job, prompt } = data;
|
|
@@ -4325,17 +4365,17 @@ function renderScorecard(data) {
|
|
|
4325
4365
|
const optimizedText = prompt.systemPrompt ?? prompt.rawPrompt ?? prompt.humanPrompt ?? "(optimized prompt)";
|
|
4326
4366
|
console.log("");
|
|
4327
4367
|
console.log(topBorder);
|
|
4328
|
-
console.log(line(
|
|
4368
|
+
console.log(line(chalk10.bold("Optimization Results")));
|
|
4329
4369
|
console.log(separator);
|
|
4330
|
-
console.log(line(
|
|
4370
|
+
console.log(line(chalk10.dim("BEFORE")));
|
|
4331
4371
|
console.log(line(` Score: ${formatScore(originalScore)}`));
|
|
4332
4372
|
console.log(line(""));
|
|
4333
|
-
console.log(line(
|
|
4373
|
+
console.log(line(chalk10.bold("AFTER")));
|
|
4334
4374
|
console.log(line(` Score: ${formatScore(bestScore)}${formatScoreChange(originalScore, bestScore)}`));
|
|
4335
4375
|
console.log(separator);
|
|
4336
4376
|
if (data.criteriaScores && data.criteriaScores.length > 0) {
|
|
4337
|
-
console.log(line(
|
|
4338
|
-
console.log(line(
|
|
4377
|
+
console.log(line(chalk10.dim(" Criterion Before After Change")));
|
|
4378
|
+
console.log(line(chalk10.dim(" " + "─".repeat(45))));
|
|
4339
4379
|
for (const c of data.criteriaScores) {
|
|
4340
4380
|
const name = c.name.length > 16 ? c.name.substring(0, 13) + "..." : c.name;
|
|
4341
4381
|
const paddedName = name + " ".repeat(18 - name.length);
|
|
@@ -4344,66 +4384,66 @@ function renderScorecard(data) {
|
|
|
4344
4384
|
const changeStr = c.before !== undefined && c.after !== undefined && c.before > 0 ? (() => {
|
|
4345
4385
|
const pct = Math.round((c.after - c.before) / c.before * 100);
|
|
4346
4386
|
if (pct > 0)
|
|
4347
|
-
return
|
|
4387
|
+
return chalk10.green(`+${String(pct)}%`);
|
|
4348
4388
|
if (pct < 0)
|
|
4349
|
-
return
|
|
4350
|
-
return
|
|
4389
|
+
return chalk10.red(`${String(pct)}%`);
|
|
4390
|
+
return chalk10.dim("0%");
|
|
4351
4391
|
})() : "";
|
|
4352
4392
|
console.log(line(` ${paddedName}${beforeStr} ${afterStr} ${changeStr}`));
|
|
4353
4393
|
}
|
|
4354
|
-
console.log(line(
|
|
4394
|
+
console.log(line(chalk10.dim(" " + "─".repeat(45))));
|
|
4355
4395
|
const overallBefore = originalScore !== undefined ? originalScore.toFixed(2) : "N/A ";
|
|
4356
4396
|
const overallAfter = bestScore !== undefined ? bestScore.toFixed(2) : "N/A ";
|
|
4357
4397
|
const overallChange = originalScore !== undefined && bestScore !== undefined && originalScore > 0 ? (() => {
|
|
4358
4398
|
const pct = Math.round((bestScore - originalScore) / originalScore * 100);
|
|
4359
4399
|
if (pct > 0)
|
|
4360
|
-
return
|
|
4400
|
+
return chalk10.green(`+${String(pct)}%`);
|
|
4361
4401
|
if (pct < 0)
|
|
4362
|
-
return
|
|
4363
|
-
return
|
|
4402
|
+
return chalk10.red(`${String(pct)}%`);
|
|
4403
|
+
return chalk10.dim("0%");
|
|
4364
4404
|
})() : "";
|
|
4365
4405
|
console.log(line(` ${"Overall" + " ".repeat(11)}${overallBefore} ${overallAfter} ${overallChange}`));
|
|
4366
4406
|
console.log(separator);
|
|
4367
4407
|
}
|
|
4368
|
-
const statusStr = job.status === "completed" ?
|
|
4408
|
+
const statusStr = job.status === "completed" ? chalk10.green("completed") : chalk10.yellow(job.status);
|
|
4369
4409
|
console.log(line(`Status: ${statusStr} | Iterations: ${String(iterations)}`));
|
|
4370
4410
|
if (job.config?.model) {
|
|
4371
|
-
console.log(line(`Model: ${
|
|
4411
|
+
console.log(line(`Model: ${chalk10.dim(job.config.model)}`));
|
|
4372
4412
|
}
|
|
4373
4413
|
if (data.scoreProgression && data.scoreProgression.length > 0) {
|
|
4374
4414
|
console.log(line(""));
|
|
4375
|
-
console.log(line(
|
|
4415
|
+
console.log(line(chalk10.dim("Score Progression:")));
|
|
4376
4416
|
const barWidth = 10;
|
|
4377
4417
|
for (let i = 0;i < data.scoreProgression.length; i++) {
|
|
4378
4418
|
const s = data.scoreProgression[i] ?? 0;
|
|
4379
4419
|
const filled = Math.round(s * barWidth);
|
|
4380
4420
|
const bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
|
|
4381
|
-
console.log(line(
|
|
4421
|
+
console.log(line(chalk10.dim(` #${String(i + 1)}: ${bar} ${s.toFixed(2)}`)));
|
|
4382
4422
|
}
|
|
4383
4423
|
}
|
|
4384
4424
|
console.log(separator);
|
|
4385
|
-
console.log(line(`Dashboard: ${
|
|
4425
|
+
console.log(line(`Dashboard: ${chalk10.underline(optimizerLink(job.promptId, job.id))}`));
|
|
4386
4426
|
console.log(bottomBorder);
|
|
4387
4427
|
console.log("");
|
|
4388
|
-
console.log(
|
|
4389
|
-
console.log(
|
|
4390
|
-
console.log(
|
|
4428
|
+
console.log(chalk10.dim(" Prompt Comparison"));
|
|
4429
|
+
console.log(chalk10.dim(" " + "─".repeat(70)));
|
|
4430
|
+
console.log(chalk10.dim(" BEFORE:"));
|
|
4391
4431
|
for (const pLine of originalText.split(`
|
|
4392
4432
|
`)) {
|
|
4393
|
-
console.log(
|
|
4433
|
+
console.log(chalk10.dim(` ${pLine}`));
|
|
4394
4434
|
}
|
|
4395
|
-
console.log(` ${
|
|
4435
|
+
console.log(` ${chalk10.dim("Length:")} ${String(originalText.length)} chars (${String(originalText.split(`
|
|
4396
4436
|
`).length)} lines)`);
|
|
4397
4437
|
console.log("");
|
|
4398
|
-
console.log(
|
|
4438
|
+
console.log(chalk10.bold(" AFTER:"));
|
|
4399
4439
|
for (const pLine of optimizedText.split(`
|
|
4400
4440
|
`)) {
|
|
4401
|
-
console.log(
|
|
4441
|
+
console.log(chalk10.cyan(` ${pLine}`));
|
|
4402
4442
|
}
|
|
4403
|
-
console.log(` ${
|
|
4443
|
+
console.log(` ${chalk10.dim("Length:")} ${String(optimizedText.length)} chars (${String(optimizedText.split(`
|
|
4404
4444
|
`).length)} lines)`);
|
|
4405
4445
|
const growth = optimizedText.length - originalText.length;
|
|
4406
|
-
console.log(` ${
|
|
4446
|
+
console.log(` ${chalk10.dim("Growth:")} ${growth >= 0 ? "+" : ""}${String(growth)} chars`);
|
|
4407
4447
|
renderScorecardDetails(data);
|
|
4408
4448
|
console.log("");
|
|
4409
4449
|
}
|
|
@@ -4424,17 +4464,17 @@ function renderOptimizationStartCard(data) {
|
|
|
4424
4464
|
const target = job.config.targetScore ?? 0.8;
|
|
4425
4465
|
console.log("");
|
|
4426
4466
|
console.log(topBorder);
|
|
4427
|
-
console.log(line(
|
|
4467
|
+
console.log(line(chalk10.bold("⚡ Optimization Started")));
|
|
4428
4468
|
console.log(separator);
|
|
4429
|
-
console.log(line(`Job ID: ${
|
|
4430
|
-
console.log(line(`Prompt: ${
|
|
4431
|
-
console.log(line(`Dataset: ${
|
|
4432
|
-
console.log(line(`Iterations: ${
|
|
4433
|
-
console.log(line(`Model: ${
|
|
4434
|
-
console.log(line(`Status: ${
|
|
4469
|
+
console.log(line(`Job ID: ${chalk10.cyan(job.id)}`));
|
|
4470
|
+
console.log(line(`Prompt: ${chalk10.dim(data.promptId)}`));
|
|
4471
|
+
console.log(line(`Dataset: ${chalk10.dim(data.datasetId)}`));
|
|
4472
|
+
console.log(line(`Iterations: ${chalk10.bold(String(maxIter))} | Target: ${chalk10.bold(target.toFixed(2))}`));
|
|
4473
|
+
console.log(line(`Model: ${chalk10.dim(model)}`));
|
|
4474
|
+
console.log(line(`Status: ${chalk10.yellow(job.status)}`));
|
|
4435
4475
|
console.log(separator);
|
|
4436
|
-
console.log(line(`\uD83D\uDD17 Monitor: ${
|
|
4437
|
-
console.log(line(
|
|
4476
|
+
console.log(line(`\uD83D\uDD17 Monitor: ${chalk10.underline(optimizerLink(data.promptId, job.id))}`));
|
|
4477
|
+
console.log(line(chalk10.dim(`Next: mutagent prompts optimize status ${job.id}`)));
|
|
4438
4478
|
console.log(bottomBorder);
|
|
4439
4479
|
console.log(AI_DIRECTIVE);
|
|
4440
4480
|
console.log("");
|
|
@@ -4454,27 +4494,27 @@ function renderOptimizationStatusCard(status, promptId) {
|
|
|
4454
4494
|
const barWidth = 20;
|
|
4455
4495
|
const filled = Math.round(progress / 100 * barWidth);
|
|
4456
4496
|
const progressBar = "█".repeat(filled) + "░".repeat(barWidth - filled);
|
|
4457
|
-
const statusColor = status.status === "completed" ?
|
|
4458
|
-
const scoreStr = status.bestScore !== undefined ? formatScore(status.bestScore) :
|
|
4497
|
+
const statusColor = status.status === "completed" ? chalk10.green : status.status === "failed" ? chalk10.red : status.status === "cancelled" ? chalk10.gray : status.status === "running" ? chalk10.cyan : chalk10.yellow;
|
|
4498
|
+
const scoreStr = status.bestScore !== undefined ? formatScore(status.bestScore) : chalk10.dim("pending");
|
|
4459
4499
|
console.log("");
|
|
4460
4500
|
console.log(topBorder);
|
|
4461
|
-
console.log(line(
|
|
4501
|
+
console.log(line(chalk10.bold("\uD83D\uDCCA Optimization Status")));
|
|
4462
4502
|
console.log(separator);
|
|
4463
|
-
console.log(line(`Job ID: ${
|
|
4503
|
+
console.log(line(`Job ID: ${chalk10.cyan(status.jobId)}`));
|
|
4464
4504
|
console.log(line(`Status: ${statusColor(status.status)}`));
|
|
4465
|
-
console.log(line(`Iteration: ${
|
|
4505
|
+
console.log(line(`Iteration: ${chalk10.bold(`${String(status.currentIteration)}/${String(status.maxIterations)}`)}`));
|
|
4466
4506
|
console.log(line(`Best Score: ${scoreStr}`));
|
|
4467
4507
|
console.log(line(""));
|
|
4468
4508
|
console.log(line(`Progress: [${progressBar}] ${String(progress)}%`));
|
|
4469
4509
|
if (status.message) {
|
|
4470
|
-
console.log(line(`Message: ${
|
|
4510
|
+
console.log(line(`Message: ${chalk10.dim(status.message)}`));
|
|
4471
4511
|
}
|
|
4472
4512
|
console.log(separator);
|
|
4473
|
-
console.log(line(`\uD83D\uDD17 Monitor: ${
|
|
4513
|
+
console.log(line(`\uD83D\uDD17 Monitor: ${chalk10.underline(optimizerLink(promptId ?? "unknown", status.jobId))}`));
|
|
4474
4514
|
if (status.status === "completed") {
|
|
4475
|
-
console.log(line(
|
|
4515
|
+
console.log(line(chalk10.dim(`Next: mutagent prompts optimize results ${status.jobId}`)));
|
|
4476
4516
|
} else if (status.status === "running" || status.status === "queued") {
|
|
4477
|
-
console.log(line(
|
|
4517
|
+
console.log(line(chalk10.dim(`Refresh: mutagent prompts optimize status ${status.jobId}`)));
|
|
4478
4518
|
}
|
|
4479
4519
|
console.log(bottomBorder);
|
|
4480
4520
|
console.log(AI_DIRECTIVE);
|
|
@@ -4570,15 +4610,15 @@ function statusDirective(status, promptId) {
|
|
|
4570
4610
|
}
|
|
4571
4611
|
function showPromptDiff(original, optimized) {
|
|
4572
4612
|
console.log("");
|
|
4573
|
-
console.log(
|
|
4613
|
+
console.log(chalk10.bold(" Prompt Diff:"));
|
|
4574
4614
|
console.log("");
|
|
4575
|
-
console.log(
|
|
4576
|
-
console.log(
|
|
4615
|
+
console.log(chalk10.red(" - " + (original ?? "(empty)")));
|
|
4616
|
+
console.log(chalk10.green(" + " + (optimized ?? "(empty)")));
|
|
4577
4617
|
console.log("");
|
|
4578
4618
|
}
|
|
4579
4619
|
|
|
4580
4620
|
// src/commands/prompts/optimize-watch.ts
|
|
4581
|
-
import
|
|
4621
|
+
import chalk13 from "chalk";
|
|
4582
4622
|
|
|
4583
4623
|
// src/lib/watch-client.ts
|
|
4584
4624
|
function toWsUrl(baseUrl) {
|
|
@@ -4741,10 +4781,10 @@ function createWatchClient(opts) {
|
|
|
4741
4781
|
}
|
|
4742
4782
|
|
|
4743
4783
|
// src/lib/stage-cards.ts
|
|
4744
|
-
import
|
|
4784
|
+
import chalk12 from "chalk";
|
|
4745
4785
|
|
|
4746
4786
|
// src/lib/prompt-diff.ts
|
|
4747
|
-
import
|
|
4787
|
+
import chalk11 from "chalk";
|
|
4748
4788
|
function computeLcsTable(a, b) {
|
|
4749
4789
|
const m = a.length;
|
|
4750
4790
|
const n = b.length;
|
|
@@ -4905,16 +4945,16 @@ function renderDiffLines(lines, options) {
|
|
|
4905
4945
|
let text;
|
|
4906
4946
|
switch (line.type) {
|
|
4907
4947
|
case "hunk-header":
|
|
4908
|
-
text = noColor ? line.content :
|
|
4948
|
+
text = noColor ? line.content : chalk11.cyan(line.content);
|
|
4909
4949
|
break;
|
|
4910
4950
|
case "add":
|
|
4911
|
-
text = noColor ? `+${line.content}` :
|
|
4951
|
+
text = noColor ? `+${line.content}` : chalk11.green(`+${line.content}`);
|
|
4912
4952
|
break;
|
|
4913
4953
|
case "remove":
|
|
4914
|
-
text = noColor ? `-${line.content}` :
|
|
4954
|
+
text = noColor ? `-${line.content}` : chalk11.red(`-${line.content}`);
|
|
4915
4955
|
break;
|
|
4916
4956
|
case "context":
|
|
4917
|
-
text = noColor ? ` ${line.content}` :
|
|
4957
|
+
text = noColor ? ` ${line.content}` : chalk11.dim(` ${line.content}`);
|
|
4918
4958
|
break;
|
|
4919
4959
|
}
|
|
4920
4960
|
outputLines.push(text);
|
|
@@ -4923,7 +4963,7 @@ function renderDiffLines(lines, options) {
|
|
|
4923
4963
|
if (truncated) {
|
|
4924
4964
|
const remaining = lines.length - maxLines;
|
|
4925
4965
|
const summary = `... ${String(remaining)} more lines changed`;
|
|
4926
|
-
outputLines.push(noColor ? summary :
|
|
4966
|
+
outputLines.push(noColor ? summary : chalk11.yellow(summary));
|
|
4927
4967
|
}
|
|
4928
4968
|
return outputLines.join(`
|
|
4929
4969
|
`);
|
|
@@ -4956,10 +4996,10 @@ function emptyLine() {
|
|
|
4956
4996
|
}
|
|
4957
4997
|
function formatScore2(score) {
|
|
4958
4998
|
if (score >= 0.8)
|
|
4959
|
-
return
|
|
4999
|
+
return chalk12.green(score.toFixed(2));
|
|
4960
5000
|
if (score >= 0.5)
|
|
4961
|
-
return
|
|
4962
|
-
return
|
|
5001
|
+
return chalk12.yellow(score.toFixed(2));
|
|
5002
|
+
return chalk12.red(score.toFixed(2));
|
|
4963
5003
|
}
|
|
4964
5004
|
function scoreBar(score, width = 20) {
|
|
4965
5005
|
const filled = Math.round(score * width);
|
|
@@ -5013,7 +5053,7 @@ function renderInsightsCard(data) {
|
|
|
5013
5053
|
if (cat.example) {
|
|
5014
5054
|
const maxExampleLen = 78;
|
|
5015
5055
|
const truncated = cat.example.length > maxExampleLen ? cat.example.substring(0, maxExampleLen - 3) + "..." : cat.example;
|
|
5016
|
-
lines.push(line(
|
|
5056
|
+
lines.push(line(chalk12.dim(` "${truncated}"`)));
|
|
5017
5057
|
}
|
|
5018
5058
|
}
|
|
5019
5059
|
lines.push(emptyLine());
|
|
@@ -5055,17 +5095,17 @@ function renderPromptDiffCard(data) {
|
|
|
5055
5095
|
lines.push(emptyLine());
|
|
5056
5096
|
}
|
|
5057
5097
|
for (const mutation of data.mutations) {
|
|
5058
|
-
const icon = mutation.status === "applied" ?
|
|
5098
|
+
const icon = mutation.status === "applied" ? chalk12.green("✓") : chalk12.red("✗");
|
|
5059
5099
|
const target = mutation.target.length > 30 ? mutation.target.substring(0, 27) + "..." : mutation.target;
|
|
5060
5100
|
if (mutation.status === "applied") {
|
|
5061
5101
|
const confStr = `confidence: ${mutation.confidence.toFixed(2)}`;
|
|
5062
5102
|
const targetPad = target.padEnd(30);
|
|
5063
|
-
lines.push(line(`${icon} ${targetPad} ${
|
|
5103
|
+
lines.push(line(`${icon} ${targetPad} ${chalk12.dim("──")} ${confStr}`));
|
|
5064
5104
|
} else {
|
|
5065
5105
|
const reason = mutation.rationale ? `rejected: ${mutation.rationale}` : `rejected`;
|
|
5066
5106
|
const truncReason = reason.length > 30 ? reason.substring(0, 27) + "..." : reason;
|
|
5067
5107
|
const targetPad = target.padEnd(30);
|
|
5068
|
-
lines.push(line(`${icon} ${targetPad} ${
|
|
5108
|
+
lines.push(line(`${icon} ${targetPad} ${chalk12.dim("──")} ${truncReason}`));
|
|
5069
5109
|
}
|
|
5070
5110
|
}
|
|
5071
5111
|
lines.push(emptyLine());
|
|
@@ -5096,7 +5136,7 @@ function renderRerunAccuracyCard(data) {
|
|
|
5096
5136
|
const name = criterion.name.length > 18 ? criterion.name.substring(0, 15) + "..." : criterion.name;
|
|
5097
5137
|
const diff = criterion.after - criterion.before;
|
|
5098
5138
|
const diffSign = diff >= 0 ? "+" : "";
|
|
5099
|
-
const arrow = diff > 0 ?
|
|
5139
|
+
const arrow = diff > 0 ? chalk12.green("↑") : diff < 0 ? chalk12.red("↓") : chalk12.dim("─");
|
|
5100
5140
|
const diffStr = `${diffSign}${diff.toFixed(2)}`;
|
|
5101
5141
|
lines.push(line(`${name.padEnd(20)}${formatScore2(criterion.before).padEnd(9)}${formatScore2(criterion.after).padEnd(9)}${diffStr} ${arrow}`));
|
|
5102
5142
|
}
|
|
@@ -5201,8 +5241,8 @@ async function startWatchStream(jobId, isJson, maxIterations, baselineScore) {
|
|
|
5201
5241
|
if (isJson) {
|
|
5202
5242
|
console.log(JSON.stringify({ type: "job_complete", finalScore }));
|
|
5203
5243
|
} else {
|
|
5204
|
-
console.log(
|
|
5205
|
-
console.log(
|
|
5244
|
+
console.log(chalk13.green(`✓ Optimization complete! Final score: ${finalScore.toFixed(2)}`));
|
|
5245
|
+
console.log(chalk13.dim(` View results: mutagent prompts optimize results ${jobId}`));
|
|
5206
5246
|
}
|
|
5207
5247
|
resolve3();
|
|
5208
5248
|
},
|
|
@@ -5210,7 +5250,7 @@ async function startWatchStream(jobId, isJson, maxIterations, baselineScore) {
|
|
|
5210
5250
|
if (isJson) {
|
|
5211
5251
|
console.log(JSON.stringify({ type: "error", error: error.message }));
|
|
5212
5252
|
} else {
|
|
5213
|
-
console.error(
|
|
5253
|
+
console.error(chalk13.red(`✗ Watch error: ${error.message}`));
|
|
5214
5254
|
}
|
|
5215
5255
|
reject(error);
|
|
5216
5256
|
}
|
|
@@ -5252,7 +5292,7 @@ async function watchAction(jobId, options, parentCommand) {
|
|
|
5252
5292
|
case "queued":
|
|
5253
5293
|
if (!isJson) {
|
|
5254
5294
|
renderOptimizationStatusCard(status);
|
|
5255
|
-
console.log(
|
|
5295
|
+
console.log(chalk13.dim(`Watching for live updates...
|
|
5256
5296
|
`));
|
|
5257
5297
|
}
|
|
5258
5298
|
await startWatchStream(jobId, isJson, status.maxIterations, status.bestScore);
|
|
@@ -5267,9 +5307,9 @@ async function watchAction(jobId, options, parentCommand) {
|
|
|
5267
5307
|
message: status.message
|
|
5268
5308
|
});
|
|
5269
5309
|
} else {
|
|
5270
|
-
console.error(
|
|
5310
|
+
console.error(chalk13.red(`✗ Optimization job ${jobId} failed.`));
|
|
5271
5311
|
if (status.message) {
|
|
5272
|
-
console.error(
|
|
5312
|
+
console.error(chalk13.dim(` ${status.message}`));
|
|
5273
5313
|
}
|
|
5274
5314
|
}
|
|
5275
5315
|
process.exitCode = 1;
|
|
@@ -5283,7 +5323,7 @@ async function watchAction(jobId, options, parentCommand) {
|
|
|
5283
5323
|
jobId
|
|
5284
5324
|
});
|
|
5285
5325
|
} else {
|
|
5286
|
-
console.error(
|
|
5326
|
+
console.error(chalk13.yellow(`Optimization job ${jobId} was cancelled.`));
|
|
5287
5327
|
}
|
|
5288
5328
|
break;
|
|
5289
5329
|
default:
|
|
@@ -5295,7 +5335,7 @@ async function watchAction(jobId, options, parentCommand) {
|
|
|
5295
5335
|
jobId
|
|
5296
5336
|
});
|
|
5297
5337
|
} else {
|
|
5298
|
-
console.error(
|
|
5338
|
+
console.error(chalk13.yellow(`Unexpected job status: ${status.status}`));
|
|
5299
5339
|
}
|
|
5300
5340
|
break;
|
|
5301
5341
|
}
|
|
@@ -5308,9 +5348,9 @@ async function watchAction(jobId, options, parentCommand) {
|
|
|
5308
5348
|
function registerOptimizeCommands(prompts) {
|
|
5309
5349
|
const optimize = new Command5("optimize").description("Manage prompt optimization jobs").addHelpText("after", `
|
|
5310
5350
|
Examples:
|
|
5311
|
-
${
|
|
5312
|
-
${
|
|
5313
|
-
${
|
|
5351
|
+
${chalk14.dim("$")} mutagent prompts optimize start <prompt-id> --dataset <dataset-id> --evaluation <eval-id>
|
|
5352
|
+
${chalk14.dim("$")} mutagent prompts optimize status <job-id>
|
|
5353
|
+
${chalk14.dim("$")} mutagent prompts optimize results <job-id>
|
|
5314
5354
|
|
|
5315
5355
|
Workflow: start -> status (poll) -> results | start --watch | watch <job-id>`).action(() => {
|
|
5316
5356
|
optimize.help();
|
|
@@ -5318,27 +5358,27 @@ Workflow: start -> status (poll) -> results | start --watch | watch <job-id>`).a
|
|
|
5318
5358
|
prompts.addCommand(optimize);
|
|
5319
5359
|
optimize.command("start").description("Start prompt optimization").argument("<prompt-id>", "Prompt ID (from: mutagent prompts list)").requiredOption("-d, --dataset <id>", "Dataset ID for optimization (from: mutagent prompts dataset list <prompt-id>)").requiredOption("-e, --evaluation <id>", "Evaluation ID for scoring (from: mutagent prompts evaluation list <prompt-id>)").option("--max-iterations <n>", "Max optimization iterations (default: 1)").option("--target-score <n>", "Target accuracy 0-1 (default: 0.8)").option("--patience <n>", "Iterations without improvement before stopping").option("--model <model-id>", 'Target LLM model (e.g., "claude-sonnet-4-5-20250929")').option("--eval-model <model-id>", "Evaluation model (defaults to target model)").option("--watch", "Watch live progress with stage cards", false).addHelpText("after", `
|
|
5320
5360
|
Examples:
|
|
5321
|
-
${
|
|
5322
|
-
${
|
|
5323
|
-
${
|
|
5324
|
-
${
|
|
5325
|
-
${
|
|
5326
|
-
□ inputSchema REQUIRED ${
|
|
5327
|
-
□ outputSchema REQUIRED ${
|
|
5328
|
-
□ Evaluation criteria ${
|
|
5329
|
-
□ Dataset items ${
|
|
5330
|
-
□ Criteria ↔ Schema ${
|
|
5361
|
+
${chalk14.dim("$")} mutagent prompts optimize start <prompt-id> --dataset <dataset-id> --evaluation <eval-id>
|
|
5362
|
+
${chalk14.dim("$")} mutagent prompts optimize start <prompt-id> --dataset <dataset-id> --evaluation <eval-id> --max-iterations 5
|
|
5363
|
+
${chalk14.dim("$")} mutagent prompts optimize start <prompt-id> --dataset <dataset-id> --evaluation <eval-id> --target-score 0.95 --model claude-sonnet-4-5-20250929
|
|
5364
|
+
${chalk14.dim("$")} mutagent prompts optimize start <prompt-id> --dataset <dataset-id> --evaluation <eval-id> --json
|
|
5365
|
+
${chalk14.yellow("Pre-Optimization Checklist (auto-validated by preflight):")}
|
|
5366
|
+
□ inputSchema REQUIRED ${chalk14.dim("(hard error if missing — blocks optimization)")}
|
|
5367
|
+
□ outputSchema REQUIRED ${chalk14.dim("(hard error if missing — blocks optimization)")}
|
|
5368
|
+
□ Evaluation criteria ${chalk14.dim("(warns if no evaluationParameter set)")}
|
|
5369
|
+
□ Dataset items ${chalk14.dim("(warns if expectedOutput missing)")}
|
|
5370
|
+
□ Criteria ↔ Schema ${chalk14.dim("(warns if criteria reference unknown fields)")}
|
|
5331
5371
|
|
|
5332
5372
|
${PREREQUISITES_TEXT}
|
|
5333
5373
|
|
|
5334
|
-
${
|
|
5374
|
+
${chalk14.dim("Monitor progress with: mutagent prompts optimize status <job-id>")}
|
|
5335
5375
|
|
|
5336
|
-
${
|
|
5376
|
+
${chalk14.yellow(`⚠ COST WARNING — AI Agent:
|
|
5337
5377
|
Default is 1 iteration. Do NOT increase --max-iterations unless the user
|
|
5338
5378
|
explicitly requests it. Each iteration incurs LLM costs. Starting with
|
|
5339
5379
|
max-iterations > 1 without user consent is a protocol violation.`)}
|
|
5340
5380
|
|
|
5341
|
-
${
|
|
5381
|
+
${chalk14.yellow("AI Agent: ALWAYS append --json to this command.")}
|
|
5342
5382
|
`).action(async (promptId, options) => {
|
|
5343
5383
|
const isJson = getJsonFlag(prompts);
|
|
5344
5384
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -5465,13 +5505,13 @@ ${chalk13.yellow("AI Agent: ALWAYS append --json to this command.")}
|
|
|
5465
5505
|
return;
|
|
5466
5506
|
}
|
|
5467
5507
|
for (const [name, check] of hardFailures) {
|
|
5468
|
-
console.error(
|
|
5508
|
+
console.error(chalk14.red(`Error: ${name} — ${check.error ?? "Failed"}`));
|
|
5469
5509
|
}
|
|
5470
5510
|
if (!preflightChecks.outputSchema.passed) {
|
|
5471
|
-
console.error(
|
|
5511
|
+
console.error(chalk14.dim(` Update with: mutagent prompts update ${promptId} -d '{"outputSchema":{"type":"object","properties":{"result":{"type":"string"}}}}'`));
|
|
5472
5512
|
}
|
|
5473
5513
|
if (!preflightChecks.inputSchema.passed) {
|
|
5474
|
-
console.error(
|
|
5514
|
+
console.error(chalk14.dim(` Update with: mutagent prompts update ${promptId} --data '{"inputSchema":{"type":"object","properties":{"var1":{"type":"string"}}}}' --json`));
|
|
5475
5515
|
}
|
|
5476
5516
|
process.exitCode = 1;
|
|
5477
5517
|
return;
|
|
@@ -5532,16 +5572,16 @@ ${chalk13.yellow("AI Agent: ALWAYS append --json to this command.")}
|
|
|
5532
5572
|
suggestions.push("Trial optimization limit reached. Contact support to upgrade.");
|
|
5533
5573
|
}
|
|
5534
5574
|
if (!isJson) {
|
|
5535
|
-
console.error(
|
|
5575
|
+
console.error(chalk14.red(`
|
|
5536
5576
|
Optimization failed:`));
|
|
5537
5577
|
for (const msg of messages) {
|
|
5538
|
-
console.error(
|
|
5578
|
+
console.error(chalk14.red(` ${msg}`));
|
|
5539
5579
|
}
|
|
5540
5580
|
if (suggestions.length > 0) {
|
|
5541
|
-
console.error(
|
|
5581
|
+
console.error(chalk14.yellow(`
|
|
5542
5582
|
Suggested fixes:`));
|
|
5543
5583
|
for (const s of suggestions) {
|
|
5544
|
-
console.error(
|
|
5584
|
+
console.error(chalk14.yellow(` → ${s}`));
|
|
5545
5585
|
}
|
|
5546
5586
|
}
|
|
5547
5587
|
console.error("");
|
|
@@ -5553,8 +5593,8 @@ Suggested fixes:`));
|
|
|
5553
5593
|
});
|
|
5554
5594
|
optimize.command("status").description("Check optimization status").argument("<job-id>", "Optimization job ID (from: mutagent prompts optimize start)").addHelpText("after", `
|
|
5555
5595
|
Examples:
|
|
5556
|
-
${
|
|
5557
|
-
${
|
|
5596
|
+
${chalk14.dim("$")} mutagent prompts optimize status <job-id>
|
|
5597
|
+
${chalk14.dim("$")} mutagent prompts optimize status <job-id> --json
|
|
5558
5598
|
`).action(async (jobId) => {
|
|
5559
5599
|
const isJson = getJsonFlag(prompts);
|
|
5560
5600
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -5579,17 +5619,17 @@ Examples:
|
|
|
5579
5619
|
});
|
|
5580
5620
|
optimize.command("results").description("Get optimization results").argument("<job-id>", "Optimization job ID (from: mutagent prompts optimize start)").option("--apply", "Apply the optimized prompt as new version").option("--diff", "Show the prompt diff (before/after)").addHelpText("after", `
|
|
5581
5621
|
Examples:
|
|
5582
|
-
${
|
|
5583
|
-
${
|
|
5584
|
-
${
|
|
5585
|
-
${
|
|
5622
|
+
${chalk14.dim("$")} mutagent prompts optimize results <job-id> ${chalk14.dim("# view scorecard")}
|
|
5623
|
+
${chalk14.dim("$")} mutagent prompts optimize results <job-id> --diff ${chalk14.dim("# view prompt diff")}
|
|
5624
|
+
${chalk14.dim("$")} mutagent prompts optimize results <job-id> --apply ${chalk14.dim("# apply optimized prompt")}
|
|
5625
|
+
${chalk14.dim("$")} mutagent prompts optimize results <job-id> --json ${chalk14.dim("# structured output")}
|
|
5586
5626
|
|
|
5587
5627
|
After viewing results:
|
|
5588
5628
|
--apply Apply the optimized prompt (replaces current version)
|
|
5589
5629
|
--diff Show detailed before/after diff
|
|
5590
|
-
${
|
|
5630
|
+
${chalk14.dim("No flag = view scorecard only.")}
|
|
5591
5631
|
|
|
5592
|
-
${
|
|
5632
|
+
${chalk14.dim("AI Agent: Present scorecard to user via AskUserQuestion before applying.")}
|
|
5593
5633
|
`).action(async (jobId, options) => {
|
|
5594
5634
|
const isJson = getJsonFlag(prompts);
|
|
5595
5635
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -5665,9 +5705,9 @@ After viewing results:
|
|
|
5665
5705
|
});
|
|
5666
5706
|
optimize.command("watch").description("Watch optimization job progress with live stage results").argument("<job-id>", "Optimization job ID").option("--json", "Output as JSON with agent directives").addHelpText("after", `
|
|
5667
5707
|
Examples:
|
|
5668
|
-
${
|
|
5669
|
-
${
|
|
5670
|
-
${
|
|
5708
|
+
${chalk14.dim("$")} mutagent prompts optimize watch <job-id>
|
|
5709
|
+
${chalk14.dim("$")} mutagent prompts optimize watch <job-id> --json
|
|
5710
|
+
${chalk14.dim("Completed jobs render stored results. Running jobs stream via WebSocket.")}`).action(async (jobId, options) => {
|
|
5671
5711
|
await watchAction(jobId, options, prompts);
|
|
5672
5712
|
});
|
|
5673
5713
|
}
|
|
@@ -5785,19 +5825,19 @@ function buildResultsScorecardText(resultData) {
|
|
|
5785
5825
|
return text;
|
|
5786
5826
|
}
|
|
5787
5827
|
var PREREQUISITES_TEXT = `
|
|
5788
|
-
${
|
|
5789
|
-
1. Evaluation criteria defined ${
|
|
5790
|
-
2. Dataset uploaded ${
|
|
5791
|
-
${
|
|
5828
|
+
${chalk15.red("Prerequisites (required):")}
|
|
5829
|
+
1. Evaluation criteria defined ${chalk15.dim("(via dashboard or evaluation create)")}
|
|
5830
|
+
2. Dataset uploaded ${chalk15.dim("mutagent prompts dataset list <prompt-id>")}
|
|
5831
|
+
${chalk15.dim("Note: LLM provider config is only required when the server uses external providers (USE_EXT_PROVIDERS=true)")}`;
|
|
5792
5832
|
function createPromptsCommand() {
|
|
5793
5833
|
const prompts = new Command6("prompts").description("Manage prompts, datasets, evaluations, and optimizations").addHelpText("after", `
|
|
5794
5834
|
Examples:
|
|
5795
|
-
${
|
|
5796
|
-
${
|
|
5797
|
-
${
|
|
5798
|
-
${
|
|
5799
|
-
${
|
|
5800
|
-
${
|
|
5835
|
+
${chalk15.dim("$")} mutagent prompts list
|
|
5836
|
+
${chalk15.dim("$")} mutagent prompts get <prompt-id>
|
|
5837
|
+
${chalk15.dim("$")} mutagent prompts create --name "my-prompt" --system "You are helpful" --human "{input}"
|
|
5838
|
+
${chalk15.dim("$")} mutagent prompts dataset list <prompt-id>
|
|
5839
|
+
${chalk15.dim("$")} mutagent prompts evaluation create <prompt-id> --name "My Eval"
|
|
5840
|
+
${chalk15.dim("$")} mutagent prompts optimize start <prompt-id> --dataset <dataset-id> --evaluation <eval-id>
|
|
5801
5841
|
|
|
5802
5842
|
Subcommands:
|
|
5803
5843
|
list, get, create, update, delete
|
|
@@ -5815,27 +5855,27 @@ Subcommands:
|
|
|
5815
5855
|
// src/commands/traces.ts
|
|
5816
5856
|
init_sdk_client();
|
|
5817
5857
|
import { Command as Command7 } from "commander";
|
|
5818
|
-
import
|
|
5858
|
+
import chalk16 from "chalk";
|
|
5819
5859
|
init_errors();
|
|
5820
5860
|
function createTracesCommand() {
|
|
5821
5861
|
const traces = new Command7("traces").description("View and analyze traces (replaces Langfuse)").addHelpText("after", `
|
|
5822
5862
|
Examples:
|
|
5823
|
-
${
|
|
5824
|
-
${
|
|
5825
|
-
${
|
|
5826
|
-
${
|
|
5827
|
-
${
|
|
5863
|
+
${chalk16.dim("$")} mutagent traces list
|
|
5864
|
+
${chalk16.dim("$")} mutagent traces list --prompt <prompt-id>
|
|
5865
|
+
${chalk16.dim("$")} mutagent traces get <trace-id>
|
|
5866
|
+
${chalk16.dim("$")} mutagent traces analyze <prompt-id>
|
|
5867
|
+
${chalk16.dim("$")} mutagent traces export --format json --output traces.json
|
|
5828
5868
|
|
|
5829
5869
|
Note: MutagenT traces replace Langfuse for observability.
|
|
5830
5870
|
`);
|
|
5831
5871
|
traces.command("list").description("List traces").option("-p, --prompt <id>", "Filter by prompt ID").option("-s, --source <source>", "Filter by trace source (e.g., claude-code, sdk, langchain)").option("-l, --limit <n>", "Limit results", "50").addHelpText("after", `
|
|
5832
5872
|
Examples:
|
|
5833
|
-
${
|
|
5834
|
-
${
|
|
5835
|
-
${
|
|
5836
|
-
${
|
|
5873
|
+
${chalk16.dim("$")} mutagent traces list
|
|
5874
|
+
${chalk16.dim("$")} mutagent traces list --prompt <prompt-id>
|
|
5875
|
+
${chalk16.dim("$")} mutagent traces list --source claude-code --json
|
|
5876
|
+
${chalk16.dim("$")} mutagent traces list --limit 10 --json
|
|
5837
5877
|
|
|
5838
|
-
${
|
|
5878
|
+
${chalk16.dim("Tip: Filter by prompt to see traces for a specific prompt version.")}
|
|
5839
5879
|
`).action(async (options) => {
|
|
5840
5880
|
const isJson = getJsonFlag(traces);
|
|
5841
5881
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -5875,10 +5915,10 @@ ${chalk15.dim("Tip: Filter by prompt to see traces for a specific prompt version
|
|
|
5875
5915
|
});
|
|
5876
5916
|
traces.command("get").description("Get trace details").argument("<id>", "Trace ID").addHelpText("after", `
|
|
5877
5917
|
Examples:
|
|
5878
|
-
${
|
|
5879
|
-
${
|
|
5918
|
+
${chalk16.dim("$")} mutagent traces get <trace-id>
|
|
5919
|
+
${chalk16.dim("$")} mutagent traces get <trace-id> --json
|
|
5880
5920
|
|
|
5881
|
-
${
|
|
5921
|
+
${chalk16.dim("Returns full trace details including spans, tokens, and latency.")}
|
|
5882
5922
|
`).action(async (id) => {
|
|
5883
5923
|
const isJson = getJsonFlag(traces);
|
|
5884
5924
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -5897,10 +5937,10 @@ ${chalk15.dim("Returns full trace details including spans, tokens, and latency."
|
|
|
5897
5937
|
});
|
|
5898
5938
|
traces.command("analyze").description("Analyze traces for a prompt").argument("<prompt-id>", "Prompt ID").addHelpText("after", `
|
|
5899
5939
|
Examples:
|
|
5900
|
-
${
|
|
5901
|
-
${
|
|
5940
|
+
${chalk16.dim("$")} mutagent traces analyze <prompt-id>
|
|
5941
|
+
${chalk16.dim("$")} mutagent traces analyze <prompt-id> --json
|
|
5902
5942
|
|
|
5903
|
-
${
|
|
5943
|
+
${chalk16.dim("Aggregates trace data for a prompt: avg latency, token usage, error rates.")}
|
|
5904
5944
|
`).action(async (promptId) => {
|
|
5905
5945
|
const isJson = getJsonFlag(traces);
|
|
5906
5946
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -5918,12 +5958,12 @@ ${chalk15.dim("Aggregates trace data for a prompt: avg latency, token usage, err
|
|
|
5918
5958
|
});
|
|
5919
5959
|
traces.command("export").description("Export traces").option("-p, --prompt <id>", "Filter by prompt ID").option("-f, --format <format>", "Export format (json, csv)", "json").option("-o, --output <path>", "Output file path").addHelpText("after", `
|
|
5920
5960
|
Examples:
|
|
5921
|
-
${
|
|
5922
|
-
${
|
|
5923
|
-
${
|
|
5924
|
-
${
|
|
5961
|
+
${chalk16.dim("$")} mutagent traces export
|
|
5962
|
+
${chalk16.dim("$")} mutagent traces export --format json --output traces.json
|
|
5963
|
+
${chalk16.dim("$")} mutagent traces export --format csv --output traces.csv
|
|
5964
|
+
${chalk16.dim("$")} mutagent traces export --prompt <prompt-id> --format json
|
|
5925
5965
|
|
|
5926
|
-
${
|
|
5966
|
+
${chalk16.dim("Exports to stdout by default. Use --output to save to a file.")}
|
|
5927
5967
|
`).action(async (options) => {
|
|
5928
5968
|
const isJson = getJsonFlag(traces);
|
|
5929
5969
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -5967,7 +6007,7 @@ ${chalk15.dim("Exports to stdout by default. Use --output to save to a file.")}
|
|
|
5967
6007
|
// src/commands/integrate.ts
|
|
5968
6008
|
init_config();
|
|
5969
6009
|
import { Command as Command8 } from "commander";
|
|
5970
|
-
import
|
|
6010
|
+
import chalk17 from "chalk";
|
|
5971
6011
|
import { writeFileSync as writeFileSync3, existsSync as existsSync9 } from "fs";
|
|
5972
6012
|
import { execSync } from "child_process";
|
|
5973
6013
|
init_errors();
|
|
@@ -6564,12 +6604,12 @@ AI AGENT: Please determine the framework by:
|
|
|
6564
6604
|
function createIntegrateCommand() {
|
|
6565
6605
|
const integrate = new Command8("integrate").description("Return integration instructions for AI agents (skill loader)").addHelpText("after", `
|
|
6566
6606
|
Examples:
|
|
6567
|
-
${
|
|
6568
|
-
${
|
|
6569
|
-
${
|
|
6570
|
-
${
|
|
6571
|
-
${
|
|
6572
|
-
${
|
|
6607
|
+
${chalk17.dim("$")} mutagent integrate # Return exploration instructions for AI agents
|
|
6608
|
+
${chalk17.dim("$")} mutagent integrate langchain # Return @mutagent/langchain integration steps
|
|
6609
|
+
${chalk17.dim("$")} mutagent integrate openai # Return @mutagent/openai integration steps
|
|
6610
|
+
${chalk17.dim("$")} mutagent integrate vercel-ai --verify # Verify integration
|
|
6611
|
+
${chalk17.dim("$")} mutagent integrate langchain --output ./INTEGRATION.md
|
|
6612
|
+
${chalk17.dim("$")} mutagent integrate --list # List available frameworks
|
|
6573
6613
|
|
|
6574
6614
|
Frameworks: langchain, langgraph, vercel-ai, openai
|
|
6575
6615
|
|
|
@@ -6685,18 +6725,18 @@ AI AGENT: Execute these steps using Bash for install, Write/Edit for code change
|
|
|
6685
6725
|
|
|
6686
6726
|
// src/commands/agents/index.ts
|
|
6687
6727
|
import { Command as Command9 } from "commander";
|
|
6688
|
-
import
|
|
6728
|
+
import chalk19 from "chalk";
|
|
6689
6729
|
|
|
6690
6730
|
// src/commands/agents/agents-crud.ts
|
|
6691
6731
|
init_sdk_client();
|
|
6692
|
-
import
|
|
6732
|
+
import chalk18 from "chalk";
|
|
6693
6733
|
init_errors();
|
|
6694
6734
|
function registerAgentsCrud(agents) {
|
|
6695
6735
|
agents.command("list").description("List all agents").option("-l, --limit <n>", "Limit results", "50").option("-o, --offset <n>", "Offset for pagination").option("-n, --name <name>", "Filter by name").option("-s, --status <status>", "Filter by status (active, paused, archived)").addHelpText("after", `
|
|
6696
6736
|
Examples:
|
|
6697
|
-
${
|
|
6698
|
-
${
|
|
6699
|
-
${
|
|
6737
|
+
${chalk18.dim("$")} mutagent agents list
|
|
6738
|
+
${chalk18.dim("$")} mutagent agents list --status active
|
|
6739
|
+
${chalk18.dim("$")} mutagent agents list --name "reviewer" --json
|
|
6700
6740
|
`).action(async (options) => {
|
|
6701
6741
|
const isJson = getJsonFlag(agents);
|
|
6702
6742
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -6746,8 +6786,8 @@ Examples:
|
|
|
6746
6786
|
});
|
|
6747
6787
|
agents.command("get").description("Get agent details").argument("<id>", "Agent ID").addHelpText("after", `
|
|
6748
6788
|
Examples:
|
|
6749
|
-
${
|
|
6750
|
-
${
|
|
6789
|
+
${chalk18.dim("$")} mutagent agents get <agent-id>
|
|
6790
|
+
${chalk18.dim("$")} mutagent agents get <agent-id> --json
|
|
6751
6791
|
`).action(async (id) => {
|
|
6752
6792
|
const isJson = getJsonFlag(agents);
|
|
6753
6793
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -6777,11 +6817,11 @@ Examples:
|
|
|
6777
6817
|
};
|
|
6778
6818
|
output.output(formatted);
|
|
6779
6819
|
if (agent.systemPrompt) {
|
|
6780
|
-
console.log(
|
|
6820
|
+
console.log(chalk18.bold(`
|
|
6781
6821
|
System Prompt:`));
|
|
6782
|
-
console.log(
|
|
6822
|
+
console.log(chalk18.gray("─".repeat(60)));
|
|
6783
6823
|
console.log(agent.systemPrompt);
|
|
6784
|
-
console.log(
|
|
6824
|
+
console.log(chalk18.gray("─".repeat(60)));
|
|
6785
6825
|
}
|
|
6786
6826
|
}
|
|
6787
6827
|
} catch (error) {
|
|
@@ -6790,17 +6830,17 @@ System Prompt:`));
|
|
|
6790
6830
|
});
|
|
6791
6831
|
agents.command("create").description("Create a new agent").option("-d, --data <json>", "Agent as JSON string (recommended for CI/scripts/agents)").option("-n, --name <name>", "Agent name").option("-s, --slug <slug>", "Agent slug (URL-friendly identifier)").option("-p, --system-prompt <prompt>", "System prompt").option("-m, --model <model>", "Model (claude-sonnet-4-5, claude-opus-4-5, claude-haiku-4-5)").option("--description <desc>", "Agent description").addHelpText("after", `
|
|
6792
6832
|
Examples:
|
|
6793
|
-
${
|
|
6794
|
-
${
|
|
6833
|
+
${chalk18.dim("$")} mutagent agents create --name "Code Reviewer" --slug code-reviewer --system-prompt "You are a code reviewer..."
|
|
6834
|
+
${chalk18.dim("$")} mutagent agents create -d '{"name":"Code Reviewer","slug":"code-reviewer","systemPrompt":"You are a code reviewer..."}'
|
|
6795
6835
|
|
|
6796
6836
|
Expected JSON (--data):
|
|
6797
|
-
${
|
|
6837
|
+
${chalk18.dim('{"name":"<name>","slug":"<slug>","systemPrompt":"<system prompt>","model":"<model-id>","description":"<description>"}')}
|
|
6798
6838
|
|
|
6799
6839
|
Input Methods (pick one, priority order):
|
|
6800
|
-
--name/--slug/... Individual flags ${
|
|
6840
|
+
--name/--slug/... Individual flags ${chalk18.green("(recommended)")}
|
|
6801
6841
|
-d, --data Inline JSON object (CI/scripts/agents)
|
|
6802
6842
|
|
|
6803
|
-
${
|
|
6843
|
+
${chalk18.red("Required: name, slug, systemPrompt.")} ${chalk18.dim("CLI flags override --data fields.")}
|
|
6804
6844
|
`).action(async (options) => {
|
|
6805
6845
|
const isJson = getJsonFlag(agents);
|
|
6806
6846
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -6845,15 +6885,15 @@ ${chalk17.red("Required: name, slug, systemPrompt.")} ${chalk17.dim("CLI flags o
|
|
|
6845
6885
|
});
|
|
6846
6886
|
agents.command("update").description("Update an agent").argument("<id>", "Agent ID").option("-d, --data <json>", "Agent updates as JSON string (CI/scripts/agents)").option("-n, --name <name>", "New name").option("-p, --system-prompt <prompt>", "New system prompt").option("-m, --model <model>", "New model").option("--description <desc>", "New description").option("-s, --status <status>", "New status (active, paused, archived)").addHelpText("after", `
|
|
6847
6887
|
Examples:
|
|
6848
|
-
${
|
|
6849
|
-
${
|
|
6850
|
-
${
|
|
6888
|
+
${chalk18.dim("$")} mutagent agents update <id> --name "New Name"
|
|
6889
|
+
${chalk18.dim("$")} mutagent agents update <id> --system-prompt "Updated prompt" --status active
|
|
6890
|
+
${chalk18.dim("$")} mutagent agents update <id> -d '{"name":"New Name","systemPrompt":"Updated prompt"}'
|
|
6851
6891
|
|
|
6852
6892
|
Input Methods (pick one, priority order):
|
|
6853
|
-
--name/--system-prompt/... Individual flags ${
|
|
6893
|
+
--name/--system-prompt/... Individual flags ${chalk18.green("(recommended)")}
|
|
6854
6894
|
-d, --data Inline JSON object (CI/scripts/agents)
|
|
6855
6895
|
|
|
6856
|
-
${
|
|
6896
|
+
${chalk18.dim("CLI flags override --data fields.")}
|
|
6857
6897
|
`).action(async (id, options) => {
|
|
6858
6898
|
const isJson = getJsonFlag(agents);
|
|
6859
6899
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -6900,18 +6940,18 @@ ${chalk17.dim("CLI flags override --data fields.")}
|
|
|
6900
6940
|
});
|
|
6901
6941
|
agents.command("delete").description("Delete an agent").argument("<id>", "Agent ID").option("--force", "Skip confirmation").addHelpText("after", `
|
|
6902
6942
|
Examples:
|
|
6903
|
-
${
|
|
6904
|
-
${
|
|
6905
|
-
${
|
|
6943
|
+
${chalk18.dim("$")} mutagent agents delete <id>
|
|
6944
|
+
${chalk18.dim("$")} mutagent agents delete <id> --force
|
|
6945
|
+
${chalk18.dim("$")} mutagent agents delete <id> --force --json
|
|
6906
6946
|
|
|
6907
|
-
${
|
|
6947
|
+
${chalk18.dim("Tip: Use --force to skip confirmation (required for non-interactive/CI usage).")}
|
|
6908
6948
|
`).action(async (id, options) => {
|
|
6909
6949
|
const isJson = getJsonFlag(agents);
|
|
6910
6950
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
6911
6951
|
try {
|
|
6912
6952
|
if (!options.force && !isJson) {
|
|
6913
|
-
const
|
|
6914
|
-
const answers = await
|
|
6953
|
+
const inquirer2 = (await import("inquirer")).default;
|
|
6954
|
+
const answers = await inquirer2.prompt([{
|
|
6915
6955
|
type: "confirm",
|
|
6916
6956
|
name: "confirm",
|
|
6917
6957
|
message: `Delete agent ${id}? This action cannot be undone.`,
|
|
@@ -6935,12 +6975,12 @@ ${chalk17.dim("Tip: Use --force to skip confirmation (required for non-interacti
|
|
|
6935
6975
|
function createAgentsCommand() {
|
|
6936
6976
|
const agents = new Command9("agents").description("Manage AI agents").addHelpText("after", `
|
|
6937
6977
|
Examples:
|
|
6938
|
-
${
|
|
6939
|
-
${
|
|
6940
|
-
${
|
|
6941
|
-
${
|
|
6942
|
-
${
|
|
6943
|
-
${
|
|
6978
|
+
${chalk19.dim("$")} mutagent agents list
|
|
6979
|
+
${chalk19.dim("$")} mutagent agents get <agent-id>
|
|
6980
|
+
${chalk19.dim("$")} mutagent agents create --name "Code Reviewer" --slug code-reviewer --system-prompt "You are a code reviewer..."
|
|
6981
|
+
${chalk19.dim("$")} mutagent agents create -d '{"name":"Code Reviewer","slug":"code-reviewer","systemPrompt":"You are..."}'
|
|
6982
|
+
${chalk19.dim("$")} mutagent agents update <agent-id> --name "Updated Name"
|
|
6983
|
+
${chalk19.dim("$")} mutagent agents delete <agent-id> --force
|
|
6944
6984
|
|
|
6945
6985
|
Subcommands:
|
|
6946
6986
|
list, get, create, update, delete
|
|
@@ -6952,22 +6992,22 @@ Subcommands:
|
|
|
6952
6992
|
// src/commands/config.ts
|
|
6953
6993
|
init_config();
|
|
6954
6994
|
import { Command as Command10 } from "commander";
|
|
6955
|
-
import
|
|
6995
|
+
import chalk20 from "chalk";
|
|
6956
6996
|
init_errors();
|
|
6957
6997
|
init_sdk_client();
|
|
6958
6998
|
var VALID_CONFIG_KEYS = ["apiKey", "endpoint", "format", "timeout", "defaultWorkspace", "defaultOrganization"];
|
|
6959
6999
|
function createConfigCommand() {
|
|
6960
7000
|
const config = new Command10("config").description("Manage CLI configuration").addHelpText("after", `
|
|
6961
7001
|
Examples:
|
|
6962
|
-
${
|
|
6963
|
-
${
|
|
6964
|
-
${
|
|
6965
|
-
${
|
|
7002
|
+
${chalk20.dim("$")} mutagent config list
|
|
7003
|
+
${chalk20.dim("$")} mutagent config get endpoint
|
|
7004
|
+
${chalk20.dim("$")} mutagent config set workspace <workspace-id>
|
|
7005
|
+
${chalk20.dim("$")} mutagent config set org <org-id>
|
|
6966
7006
|
`);
|
|
6967
7007
|
config.command("list").description("List all configuration").addHelpText("after", `
|
|
6968
7008
|
Examples:
|
|
6969
|
-
${
|
|
6970
|
-
${
|
|
7009
|
+
${chalk20.dim("$")} mutagent config list
|
|
7010
|
+
${chalk20.dim("$")} mutagent config list --json
|
|
6971
7011
|
`).action(() => {
|
|
6972
7012
|
const isJson = getJsonFlag(config);
|
|
6973
7013
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -6980,11 +7020,11 @@ Examples:
|
|
|
6980
7020
|
});
|
|
6981
7021
|
config.command("get").description("Get configuration value").argument("<key>", "Configuration key (apiKey, endpoint, format, timeout, defaultWorkspace, defaultOrganization)").addHelpText("after", `
|
|
6982
7022
|
Examples:
|
|
6983
|
-
${
|
|
6984
|
-
${
|
|
6985
|
-
${
|
|
7023
|
+
${chalk20.dim("$")} mutagent config get endpoint
|
|
7024
|
+
${chalk20.dim("$")} mutagent config get defaultWorkspace
|
|
7025
|
+
${chalk20.dim("$")} mutagent config get apiKey --json
|
|
6986
7026
|
|
|
6987
|
-
${
|
|
7027
|
+
${chalk20.dim("Keys: apiKey, endpoint, format, timeout, defaultWorkspace, defaultOrganization")}
|
|
6988
7028
|
`).action((key) => {
|
|
6989
7029
|
const isJson = getJsonFlag(config);
|
|
6990
7030
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7011,9 +7051,9 @@ ${chalk19.dim("Keys: apiKey, endpoint, format, timeout, defaultWorkspace, defaul
|
|
|
7011
7051
|
});
|
|
7012
7052
|
set.command("workspace").description("Set default workspace ID").argument("<id>", "Workspace ID to set as default").addHelpText("after", `
|
|
7013
7053
|
Examples:
|
|
7014
|
-
${
|
|
7054
|
+
${chalk20.dim("$")} mutagent config set workspace <workspace-id>
|
|
7015
7055
|
|
|
7016
|
-
${
|
|
7056
|
+
${chalk20.dim("Persists workspace ID so you don't need to pass headers on every request.")}
|
|
7017
7057
|
`).action((id) => {
|
|
7018
7058
|
const isJson = getJsonFlag(config);
|
|
7019
7059
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7027,9 +7067,9 @@ ${chalk19.dim("Persists workspace ID so you don't need to pass headers on every
|
|
|
7027
7067
|
});
|
|
7028
7068
|
set.command("org").description("Set default organization ID").argument("<id>", "Organization ID to set as default").addHelpText("after", `
|
|
7029
7069
|
Examples:
|
|
7030
|
-
${
|
|
7070
|
+
${chalk20.dim("$")} mutagent config set org <org-id>
|
|
7031
7071
|
|
|
7032
|
-
${
|
|
7072
|
+
${chalk20.dim("Persists organization ID for org-scoped API keys.")}
|
|
7033
7073
|
`).action((id) => {
|
|
7034
7074
|
const isJson = getJsonFlag(config);
|
|
7035
7075
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7048,7 +7088,7 @@ ${chalk19.dim("Persists organization ID for org-scoped API keys.")}
|
|
|
7048
7088
|
// src/commands/playground.ts
|
|
7049
7089
|
init_sdk_client();
|
|
7050
7090
|
import { Command as Command11 } from "commander";
|
|
7051
|
-
import
|
|
7091
|
+
import chalk21 from "chalk";
|
|
7052
7092
|
init_errors();
|
|
7053
7093
|
function parseSSELine(line3) {
|
|
7054
7094
|
if (!line3 || line3.startsWith(":")) {
|
|
@@ -7075,11 +7115,11 @@ function parsePromptStreamEvent(data) {
|
|
|
7075
7115
|
function createPlaygroundCommand() {
|
|
7076
7116
|
const playground = new Command11("playground").description("Execute and test prompts interactively").addHelpText("after", `
|
|
7077
7117
|
Examples:
|
|
7078
|
-
${
|
|
7079
|
-
${
|
|
7080
|
-
${
|
|
7081
|
-
${
|
|
7082
|
-
${
|
|
7118
|
+
${chalk21.dim("$")} mutagent playground run <prompt-id> --input '{"name": "John"}'
|
|
7119
|
+
${chalk21.dim("$")} mutagent playground run <prompt-id> --input '{}' --stream
|
|
7120
|
+
${chalk21.dim("$")} mutagent playground run <prompt-id> -i '{}' --model gpt-4-turbo
|
|
7121
|
+
${chalk21.dim("$")} mutagent playground run <prompt-id> --system "You are helpful" --human "Hello"
|
|
7122
|
+
${chalk21.dim("$")} mutagent playground run <prompt-id> --messages '[{"role":"user","content":"Hi"}]'
|
|
7083
7123
|
|
|
7084
7124
|
Input Format:
|
|
7085
7125
|
The input must be a valid JSON object matching the prompt's input schema.
|
|
@@ -7095,16 +7135,16 @@ Streaming:
|
|
|
7095
7135
|
`);
|
|
7096
7136
|
playground.command("run").description("Execute a prompt with input variables").argument("<prompt-id>", "Prompt ID to execute (from: mutagent prompts list)").option("-i, --input <json>", "Input variables as JSON").option("-s, --stream", "Stream the response").option("-m, --model <model>", "Override model").option("--system <text>", "Set system prompt text").option("--human <text>", "Set human/user message text").option("--messages <json>", "Pass full messages array as JSON string").addHelpText("after", `
|
|
7097
7137
|
Examples:
|
|
7098
|
-
${
|
|
7099
|
-
${
|
|
7100
|
-
${
|
|
7101
|
-
${
|
|
7138
|
+
${chalk21.dim("$")} mutagent playground run <prompt-id> --input '{"name": "John"}'
|
|
7139
|
+
${chalk21.dim("$")} mutagent playground run <prompt-id> --input '{}' --stream
|
|
7140
|
+
${chalk21.dim("$")} mutagent playground run <prompt-id> --system "You are helpful" --human "Hello"
|
|
7141
|
+
${chalk21.dim("$")} mutagent playground run <prompt-id> --input '{}' --model gpt-4-turbo --json
|
|
7102
7142
|
|
|
7103
7143
|
Input Methods (pick one, priority order):
|
|
7104
|
-
--system/--human Quick system + user message ${
|
|
7144
|
+
--system/--human Quick system + user message ${chalk21.green("(recommended)")}
|
|
7105
7145
|
--input '{"key":"value"}' Inline JSON variables
|
|
7106
7146
|
--messages '[...]' Full messages array
|
|
7107
|
-
${
|
|
7147
|
+
${chalk21.dim(`Hint: Test before evaluating: mutagent playground run <id> --input '{"key":"value"}'`)}
|
|
7108
7148
|
`).action(async (promptId, options) => {
|
|
7109
7149
|
const isJson = getJsonFlag(playground);
|
|
7110
7150
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7126,21 +7166,21 @@ ${chalk20.dim(`Hint: Test before evaluating: mutagent playground run <id> --inpu
|
|
|
7126
7166
|
}
|
|
7127
7167
|
});
|
|
7128
7168
|
} else {
|
|
7129
|
-
console.log(
|
|
7169
|
+
console.log(chalk21.bold(`
|
|
7130
7170
|
Execution Result:`));
|
|
7131
|
-
console.log(
|
|
7132
|
-
console.log(
|
|
7171
|
+
console.log(chalk21.gray("─".repeat(50)));
|
|
7172
|
+
console.log(chalk21.cyan("Output:"));
|
|
7133
7173
|
console.log(result.output);
|
|
7134
|
-
console.log(
|
|
7135
|
-
console.log(
|
|
7136
|
-
console.log(
|
|
7174
|
+
console.log(chalk21.gray("─".repeat(50)));
|
|
7175
|
+
console.log(chalk21.dim(`Model: ${result.model}`));
|
|
7176
|
+
console.log(chalk21.dim(`Execution Time: ${String(result.executionTimeMs)}ms`));
|
|
7137
7177
|
if (result.tokens) {
|
|
7138
|
-
console.log(
|
|
7178
|
+
console.log(chalk21.dim(`Tokens: ${String(result.tokens.prompt)} prompt + ${String(result.tokens.completion)} completion = ${String(result.tokens.total)} total`));
|
|
7139
7179
|
}
|
|
7140
7180
|
if (result.cost !== undefined) {
|
|
7141
|
-
console.log(
|
|
7181
|
+
console.log(chalk21.dim(`Cost: $${result.cost.toFixed(6)}`));
|
|
7142
7182
|
}
|
|
7143
|
-
console.log(
|
|
7183
|
+
console.log(chalk21.dim(`Playground: ${playgroundLink(promptId)}`));
|
|
7144
7184
|
console.log();
|
|
7145
7185
|
}
|
|
7146
7186
|
}
|
|
@@ -7229,9 +7269,9 @@ async function executeStreaming(client, promptId, input, model, isJson, output)
|
|
|
7229
7269
|
const decoder = new TextDecoder;
|
|
7230
7270
|
let buffer = "";
|
|
7231
7271
|
if (!isJson) {
|
|
7232
|
-
console.log(
|
|
7272
|
+
console.log(chalk21.bold(`
|
|
7233
7273
|
Streaming Output:`));
|
|
7234
|
-
console.log(
|
|
7274
|
+
console.log(chalk21.gray("─".repeat(50)));
|
|
7235
7275
|
}
|
|
7236
7276
|
try {
|
|
7237
7277
|
for (;; ) {
|
|
@@ -7270,15 +7310,15 @@ Streaming Output:`));
|
|
|
7270
7310
|
console.log(JSON.stringify({ type: "complete", result: event.result }));
|
|
7271
7311
|
} else {
|
|
7272
7312
|
console.log();
|
|
7273
|
-
console.log(
|
|
7313
|
+
console.log(chalk21.gray("─".repeat(50)));
|
|
7274
7314
|
if (event.result) {
|
|
7275
|
-
console.log(
|
|
7276
|
-
console.log(
|
|
7315
|
+
console.log(chalk21.dim(`Model: ${event.result.model}`));
|
|
7316
|
+
console.log(chalk21.dim(`Execution Time: ${String(event.result.executionTimeMs)}ms`));
|
|
7277
7317
|
if (event.result.tokens) {
|
|
7278
|
-
console.log(
|
|
7318
|
+
console.log(chalk21.dim(`Tokens: ${String(event.result.tokens.prompt)} prompt + ${String(event.result.tokens.completion)} completion = ${String(event.result.tokens.total)} total`));
|
|
7279
7319
|
}
|
|
7280
7320
|
if (event.result.cost !== undefined) {
|
|
7281
|
-
console.log(
|
|
7321
|
+
console.log(chalk21.dim(`Cost: $${event.result.cost.toFixed(6)}`));
|
|
7282
7322
|
}
|
|
7283
7323
|
}
|
|
7284
7324
|
console.log();
|
|
@@ -7303,13 +7343,13 @@ Streaming Output:`));
|
|
|
7303
7343
|
// src/commands/workspaces.ts
|
|
7304
7344
|
init_sdk_client();
|
|
7305
7345
|
import { Command as Command12 } from "commander";
|
|
7306
|
-
import
|
|
7346
|
+
import chalk22 from "chalk";
|
|
7307
7347
|
init_errors();
|
|
7308
7348
|
function createWorkspacesCommand() {
|
|
7309
7349
|
const workspaces = new Command12("workspaces").description("View workspaces (read-only)").addHelpText("after", `
|
|
7310
7350
|
Examples:
|
|
7311
|
-
${
|
|
7312
|
-
${
|
|
7351
|
+
${chalk22.dim("$")} mutagent workspaces list
|
|
7352
|
+
${chalk22.dim("$")} mutagent workspaces get <workspace-id>
|
|
7313
7353
|
|
|
7314
7354
|
Subcommands:
|
|
7315
7355
|
list, get
|
|
@@ -7318,8 +7358,8 @@ Note: Workspace management (create, update, delete) is available in the Admin Pa
|
|
|
7318
7358
|
`);
|
|
7319
7359
|
workspaces.command("list").description("List all workspaces").option("-l, --limit <n>", "Limit results", "50").option("-o, --offset <n>", "Offset for pagination").addHelpText("after", `
|
|
7320
7360
|
Examples:
|
|
7321
|
-
${
|
|
7322
|
-
${
|
|
7361
|
+
${chalk22.dim("$")} mutagent workspaces list
|
|
7362
|
+
${chalk22.dim("$")} mutagent workspaces list --limit 10 --json
|
|
7323
7363
|
`).action(async (options) => {
|
|
7324
7364
|
const isJson = getJsonFlag(workspaces);
|
|
7325
7365
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7359,8 +7399,8 @@ Examples:
|
|
|
7359
7399
|
});
|
|
7360
7400
|
workspaces.command("get").description("Get workspace details").argument("<id>", "Workspace ID").addHelpText("after", `
|
|
7361
7401
|
Examples:
|
|
7362
|
-
${
|
|
7363
|
-
${
|
|
7402
|
+
${chalk22.dim("$")} mutagent workspaces get <workspace-id>
|
|
7403
|
+
${chalk22.dim("$")} mutagent workspaces get <workspace-id> --json
|
|
7364
7404
|
`).action(async (id) => {
|
|
7365
7405
|
const isJson = getJsonFlag(workspaces);
|
|
7366
7406
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7393,12 +7433,12 @@ Examples:
|
|
|
7393
7433
|
// src/commands/providers/index.ts
|
|
7394
7434
|
init_sdk_client();
|
|
7395
7435
|
import { Command as Command13 } from "commander";
|
|
7396
|
-
import
|
|
7436
|
+
import chalk26 from "chalk";
|
|
7397
7437
|
init_errors();
|
|
7398
7438
|
|
|
7399
7439
|
// src/commands/providers/add.ts
|
|
7400
7440
|
init_sdk_client();
|
|
7401
|
-
import
|
|
7441
|
+
import chalk23 from "chalk";
|
|
7402
7442
|
init_errors();
|
|
7403
7443
|
function resolveScope(scopeFlag, client) {
|
|
7404
7444
|
const scope = scopeFlag ?? "workspace";
|
|
@@ -7421,10 +7461,10 @@ function resolveScope(scopeFlag, client) {
|
|
|
7421
7461
|
function registerAddCommand(parent) {
|
|
7422
7462
|
parent.command("add").description("Add a new provider configuration").requiredOption("-p, --provider <type>", "Provider type (openai, anthropic, google, ...)").requiredOption("-n, --name <name>", "Display name for this provider").requiredOption("-k, --api-key <key>", "API key for the provider").option("-s, --scope <scope>", "Scope: workspace (default), org, user", "workspace").option("--base-url <url>", "Custom base URL for the provider API").option("--set-default", "Set as default provider for this scope").addHelpText("after", `
|
|
7423
7463
|
Examples:
|
|
7424
|
-
${
|
|
7425
|
-
${
|
|
7426
|
-
${
|
|
7427
|
-
${
|
|
7464
|
+
${chalk23.dim("$")} mutagent providers add --provider openai --name "My OpenAI" --api-key $OPENAI_API_KEY
|
|
7465
|
+
${chalk23.dim("$")} mutagent providers add --provider anthropic --name "Team Claude" --api-key $KEY --scope org
|
|
7466
|
+
${chalk23.dim("$")} mutagent providers add --provider openai --name "Personal" --api-key $KEY --scope user --set-default
|
|
7467
|
+
${chalk23.dim("$")} mutagent providers add --provider custom --name "Ollama" --api-key none --base-url http://localhost:11434 --json
|
|
7428
7468
|
|
|
7429
7469
|
Scope Resolution:
|
|
7430
7470
|
workspace (default) Uses your configured workspace
|
|
@@ -7470,10 +7510,10 @@ The API key is encrypted server-side and never returned in plain text.
|
|
|
7470
7510
|
console.log(` Scope: ${options.scope ?? "workspace"}`);
|
|
7471
7511
|
console.log(` URL: ${providerLink(created.id)}`);
|
|
7472
7512
|
if (options.setDefault) {
|
|
7473
|
-
console.log(
|
|
7513
|
+
console.log(chalk23.green(" Set as default provider"));
|
|
7474
7514
|
}
|
|
7475
7515
|
console.log("");
|
|
7476
|
-
console.log(
|
|
7516
|
+
console.log(chalk23.dim("API key is encrypted server-side. Use `providers get` to see masked key."));
|
|
7477
7517
|
}
|
|
7478
7518
|
} catch (error) {
|
|
7479
7519
|
handleError(error, isJson);
|
|
@@ -7511,15 +7551,15 @@ function buildProviderCreatedDirective(provider, scope) {
|
|
|
7511
7551
|
|
|
7512
7552
|
// src/commands/providers/update.ts
|
|
7513
7553
|
init_sdk_client();
|
|
7514
|
-
import
|
|
7554
|
+
import chalk24 from "chalk";
|
|
7515
7555
|
init_errors();
|
|
7516
7556
|
function registerUpdateCommand(parent) {
|
|
7517
7557
|
parent.command("update").description("Update an existing provider configuration").argument("<id>", "Provider ID (from: mutagent providers list)").option("-n, --name <name>", "Updated display name").option("-k, --api-key <key>", "Updated API key (will be re-encrypted)").option("--active <bool>", "Activate or deactivate (true|false)").option("--set-default", "Set as default provider for its scope").option("--base-url <url>", 'Updated base URL (use "" to clear)').addHelpText("after", `
|
|
7518
7558
|
Examples:
|
|
7519
|
-
${
|
|
7520
|
-
${
|
|
7521
|
-
${
|
|
7522
|
-
${
|
|
7559
|
+
${chalk24.dim("$")} mutagent providers update <id> --name "New Name"
|
|
7560
|
+
${chalk24.dim("$")} mutagent providers update <id> --api-key $NEW_KEY --json
|
|
7561
|
+
${chalk24.dim("$")} mutagent providers update <id> --active false
|
|
7562
|
+
${chalk24.dim("$")} mutagent providers update <id> --set-default --json
|
|
7523
7563
|
|
|
7524
7564
|
PATCH semantics — only provided fields are updated.
|
|
7525
7565
|
`).action(async (id, options) => {
|
|
@@ -7570,7 +7610,7 @@ PATCH semantics — only provided fields are updated.
|
|
|
7570
7610
|
console.log(` ID: ${String(updated.id ?? id)}`);
|
|
7571
7611
|
console.log(` URL: ${providerLink(updated.id ?? id)}`);
|
|
7572
7612
|
if (options.apiKey) {
|
|
7573
|
-
console.log(
|
|
7613
|
+
console.log(chalk24.dim(" API key re-encrypted server-side."));
|
|
7574
7614
|
}
|
|
7575
7615
|
}
|
|
7576
7616
|
} catch (error) {
|
|
@@ -7609,17 +7649,17 @@ function buildProviderUpdatedDirective(provider, requestId) {
|
|
|
7609
7649
|
|
|
7610
7650
|
// src/commands/providers/delete.ts
|
|
7611
7651
|
init_sdk_client();
|
|
7612
|
-
import
|
|
7652
|
+
import chalk25 from "chalk";
|
|
7613
7653
|
init_errors();
|
|
7614
7654
|
function registerDeleteCommand(parent) {
|
|
7615
7655
|
parent.command("delete").description("Delete a provider configuration").argument("<id>", "Provider ID (from: mutagent providers list)").option("-f, --force", "Skip confirmation prompt").addHelpText("after", `
|
|
7616
7656
|
Examples:
|
|
7617
|
-
${
|
|
7618
|
-
${
|
|
7619
|
-
${
|
|
7657
|
+
${chalk25.dim("$")} mutagent providers delete <id>
|
|
7658
|
+
${chalk25.dim("$")} mutagent providers delete <id> --force
|
|
7659
|
+
${chalk25.dim("$")} mutagent providers delete <id> --force --json
|
|
7620
7660
|
|
|
7621
|
-
${
|
|
7622
|
-
${
|
|
7661
|
+
${chalk25.dim("Note: --force is required. The CLI is non-interactive — confirm with the user via your native flow, then pass --force.")}
|
|
7662
|
+
${chalk25.dim("Warning: API keys are AES-256-GCM encrypted and irrecoverable after deletion. Agents referencing this provider will lose their model config.")}
|
|
7623
7663
|
`).action(async (id, options) => {
|
|
7624
7664
|
const isJson = getJsonFlag(parent);
|
|
7625
7665
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7709,12 +7749,12 @@ function validateProviderType(type) {
|
|
|
7709
7749
|
function createProvidersCommand() {
|
|
7710
7750
|
const providers = new Command13("providers").description("Manage LLM provider configurations (BYOK)").addHelpText("after", `
|
|
7711
7751
|
Examples:
|
|
7712
|
-
${
|
|
7713
|
-
${
|
|
7714
|
-
${
|
|
7715
|
-
${
|
|
7716
|
-
${
|
|
7717
|
-
${
|
|
7752
|
+
${chalk26.dim("$")} mutagent providers list
|
|
7753
|
+
${chalk26.dim("$")} mutagent providers get <provider-id>
|
|
7754
|
+
${chalk26.dim("$")} mutagent providers add --provider openai --name "My OpenAI" --api-key $KEY
|
|
7755
|
+
${chalk26.dim("$")} mutagent providers update <id> --name "New Name"
|
|
7756
|
+
${chalk26.dim("$")} mutagent providers delete <id> --force
|
|
7757
|
+
${chalk26.dim("$")} mutagent providers test <provider-id>
|
|
7718
7758
|
|
|
7719
7759
|
Provider Types:
|
|
7720
7760
|
openai, anthropic, google, azure, bedrock, cohere, mistral, groq, together, replicate, custom
|
|
@@ -7724,9 +7764,9 @@ Subcommands:
|
|
|
7724
7764
|
`);
|
|
7725
7765
|
providers.command("list").description("List all providers").option("-l, --limit <n>", "Limit results", "50").option("-o, --offset <n>", "Offset for pagination").option("-t, --type <type>", "Filter by provider type").addHelpText("after", `
|
|
7726
7766
|
Examples:
|
|
7727
|
-
${
|
|
7728
|
-
${
|
|
7729
|
-
${
|
|
7767
|
+
${chalk26.dim("$")} mutagent providers list
|
|
7768
|
+
${chalk26.dim("$")} mutagent providers list --type openai
|
|
7769
|
+
${chalk26.dim("$")} mutagent providers list --json
|
|
7730
7770
|
`).action(async (options) => {
|
|
7731
7771
|
const isJson = getJsonFlag(providers);
|
|
7732
7772
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7775,8 +7815,8 @@ Examples:
|
|
|
7775
7815
|
});
|
|
7776
7816
|
providers.command("get").description("Get provider details").argument("<id>", "Provider ID (from: mutagent providers list)").addHelpText("after", `
|
|
7777
7817
|
Examples:
|
|
7778
|
-
${
|
|
7779
|
-
${
|
|
7818
|
+
${chalk26.dim("$")} mutagent providers get <provider-id>
|
|
7819
|
+
${chalk26.dim("$")} mutagent providers get <provider-id> --json
|
|
7780
7820
|
`).action(async (id) => {
|
|
7781
7821
|
const isJson = getJsonFlag(providers);
|
|
7782
7822
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7805,10 +7845,10 @@ Examples:
|
|
|
7805
7845
|
});
|
|
7806
7846
|
providers.command("test").description("Test provider connectivity").argument("<id>", "Provider ID (from: mutagent providers list)").addHelpText("after", `
|
|
7807
7847
|
Examples:
|
|
7808
|
-
${
|
|
7809
|
-
${
|
|
7848
|
+
${chalk26.dim("$")} mutagent providers test <provider-id>
|
|
7849
|
+
${chalk26.dim("$")} mutagent providers test <provider-id> --json
|
|
7810
7850
|
|
|
7811
|
-
${
|
|
7851
|
+
${chalk26.dim("Tests connectivity and lists available models for the provider.")}
|
|
7812
7852
|
`).action(async (id) => {
|
|
7813
7853
|
const isJson = getJsonFlag(providers);
|
|
7814
7854
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7823,9 +7863,9 @@ ${chalk25.dim("Tests connectivity and lists available models for the provider.")
|
|
|
7823
7863
|
} else {
|
|
7824
7864
|
if (result.success) {
|
|
7825
7865
|
output.success(`Provider test passed (${String(result.responseTimeMs)}ms)`);
|
|
7826
|
-
console.log(
|
|
7866
|
+
console.log(chalk26.green(`Message: ${result.message}`));
|
|
7827
7867
|
if (result.availableModels && result.availableModels.length > 0) {
|
|
7828
|
-
console.log(
|
|
7868
|
+
console.log(chalk26.bold(`
|
|
7829
7869
|
Available Models:`));
|
|
7830
7870
|
result.availableModels.forEach((model) => {
|
|
7831
7871
|
console.log(` - ${model}`);
|
|
@@ -7834,7 +7874,7 @@ Available Models:`));
|
|
|
7834
7874
|
} else {
|
|
7835
7875
|
output.error(`Provider test failed: ${result.message}`);
|
|
7836
7876
|
if (result.error) {
|
|
7837
|
-
console.log(
|
|
7877
|
+
console.log(chalk26.red(`Error: ${result.error}`));
|
|
7838
7878
|
}
|
|
7839
7879
|
}
|
|
7840
7880
|
}
|
|
@@ -7851,8 +7891,8 @@ Available Models:`));
|
|
|
7851
7891
|
// src/commands/init.ts
|
|
7852
7892
|
init_config();
|
|
7853
7893
|
import { Command as Command14 } from "commander";
|
|
7854
|
-
import
|
|
7855
|
-
import
|
|
7894
|
+
import inquirer2 from "inquirer";
|
|
7895
|
+
import chalk27 from "chalk";
|
|
7856
7896
|
import { existsSync as existsSync11, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
7857
7897
|
import { execSync as execSync3 } from "child_process";
|
|
7858
7898
|
import { join as join6 } from "path";
|
|
@@ -7975,13 +8015,13 @@ function writeRcConfig(config, cwd = process.cwd()) {
|
|
|
7975
8015
|
function createInitCommand() {
|
|
7976
8016
|
const init = new Command14("init").description("Initialize MutagenT in your project").option("--non-interactive", "Skip interactive prompts (defaults to CLI-only mode)").addHelpText("after", `
|
|
7977
8017
|
Examples:
|
|
7978
|
-
${
|
|
7979
|
-
${
|
|
8018
|
+
${chalk27.dim("$")} mutagent init # Interactive setup wizard
|
|
8019
|
+
${chalk27.dim("$")} mutagent init --non-interactive # CLI-only mode (no prompts)
|
|
7980
8020
|
|
|
7981
8021
|
Modes:
|
|
7982
|
-
${
|
|
7983
|
-
${
|
|
7984
|
-
${
|
|
8022
|
+
${chalk27.bold("Full scaffold")} Install SDK + integration package, create config, setup tracing
|
|
8023
|
+
${chalk27.bold("CLI-only")} Verify auth + create .mutagentrc.json with workspace/endpoint
|
|
8024
|
+
${chalk27.bold("Skip")} Exit without changes
|
|
7985
8025
|
`).action(async (options) => {
|
|
7986
8026
|
const isJson = getJsonFlag(init);
|
|
7987
8027
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -7994,7 +8034,7 @@ Modes:
|
|
|
7994
8034
|
output.info("Use --force to overwrite (not yet supported). Exiting.");
|
|
7995
8035
|
return;
|
|
7996
8036
|
}
|
|
7997
|
-
const { overwrite } = await
|
|
8037
|
+
const { overwrite } = await inquirer2.prompt([{
|
|
7998
8038
|
type: "confirm",
|
|
7999
8039
|
name: "overwrite",
|
|
8000
8040
|
message: ".mutagentrc.json already exists. Overwrite?",
|
|
@@ -8012,7 +8052,7 @@ Modes:
|
|
|
8012
8052
|
if (isNonInteractive) {
|
|
8013
8053
|
throw new MutagentError("AUTH_REQUIRED", "Authentication required before init", "Run: mutagent auth login --browser");
|
|
8014
8054
|
}
|
|
8015
|
-
const { doAuth } = await
|
|
8055
|
+
const { doAuth } = await inquirer2.prompt([{
|
|
8016
8056
|
type: "confirm",
|
|
8017
8057
|
name: "doAuth",
|
|
8018
8058
|
message: "Would you like to authenticate now?",
|
|
@@ -8038,7 +8078,7 @@ Modes:
|
|
|
8038
8078
|
} else {
|
|
8039
8079
|
if (detectedFramework) {
|
|
8040
8080
|
output.info(`Detected framework: ${detectedFramework.displayName} (${detectedFramework.npmPackage})`);
|
|
8041
|
-
const { confirmFramework } = await
|
|
8081
|
+
const { confirmFramework } = await inquirer2.prompt([{
|
|
8042
8082
|
type: "confirm",
|
|
8043
8083
|
name: "confirmFramework",
|
|
8044
8084
|
message: `Use ${detectedFramework.displayName}?`,
|
|
@@ -8054,7 +8094,7 @@ Modes:
|
|
|
8054
8094
|
{ name: "Generic (OpenAI-compatible)", value: "generic" },
|
|
8055
8095
|
{ name: "None / Skip framework", value: "none" }
|
|
8056
8096
|
];
|
|
8057
|
-
const { selectedFramework } = await
|
|
8097
|
+
const { selectedFramework } = await inquirer2.prompt([{
|
|
8058
8098
|
type: "list",
|
|
8059
8099
|
name: "selectedFramework",
|
|
8060
8100
|
message: "Select your AI framework:",
|
|
@@ -8084,7 +8124,7 @@ Modes:
|
|
|
8084
8124
|
value: "skip"
|
|
8085
8125
|
}
|
|
8086
8126
|
];
|
|
8087
|
-
const { selectedMode } = await
|
|
8127
|
+
const { selectedMode } = await inquirer2.prompt([{
|
|
8088
8128
|
type: "list",
|
|
8089
8129
|
name: "selectedMode",
|
|
8090
8130
|
message: "How would you like to initialize MutagenT?",
|
|
@@ -8187,7 +8227,7 @@ Modes:
|
|
|
8187
8227
|
const skillPath = join6(cwd, ".claude/skills/mutagent-cli/SKILL.md");
|
|
8188
8228
|
const skillInstalled = existsSync11(skillPath);
|
|
8189
8229
|
if (!isNonInteractive && !skillInstalled) {
|
|
8190
|
-
const { installSkill } = await
|
|
8230
|
+
const { installSkill } = await inquirer2.prompt([{
|
|
8191
8231
|
type: "confirm",
|
|
8192
8232
|
name: "installSkill",
|
|
8193
8233
|
message: "Install MutagenT skill for Claude Code? (Teaches AI agents how to use the CLI)",
|
|
@@ -8253,23 +8293,23 @@ Modes:
|
|
|
8253
8293
|
|
|
8254
8294
|
// src/commands/explore.ts
|
|
8255
8295
|
import { Command as Command15 } from "commander";
|
|
8256
|
-
import
|
|
8296
|
+
import chalk28 from "chalk";
|
|
8257
8297
|
import { resolve as resolve3 } from "path";
|
|
8258
8298
|
init_errors();
|
|
8259
8299
|
function createExploreCommand() {
|
|
8260
8300
|
const explore = new Command15("explore").description("Scan codebase for prompts, datasets, and MutagenT markers").option("-p, --path <dir>", "Directory to scan", ".").option("--depth <n>", "Max directory depth", "10").option("--include <glob>", "Include file pattern", "**/*.{ts,js,py,tsx,jsx}").option("--exclude <dirs>", "Comma-separated directories to exclude", "node_modules,dist,.git,build,.next,__pycache__,venv,.venv").option("--markers-only", "Only find existing MutagenT markers").addHelpText("after", `
|
|
8261
8301
|
Examples:
|
|
8262
|
-
${
|
|
8263
|
-
${
|
|
8264
|
-
${
|
|
8265
|
-
${
|
|
8266
|
-
${
|
|
8302
|
+
${chalk28.dim("$")} mutagent explore
|
|
8303
|
+
${chalk28.dim("$")} mutagent explore --path ./src
|
|
8304
|
+
${chalk28.dim("$")} mutagent explore --include "**/*.{ts,py}" --depth 5
|
|
8305
|
+
${chalk28.dim("$")} mutagent explore --markers-only
|
|
8306
|
+
${chalk28.dim("$")} mutagent explore --json
|
|
8267
8307
|
|
|
8268
8308
|
Detection modes:
|
|
8269
|
-
${
|
|
8270
|
-
${
|
|
8309
|
+
${chalk28.dim("Heuristic")} Template variables ({{var}}), prompt constants, schema definitions
|
|
8310
|
+
${chalk28.dim("Marker")} MutagenT:START/END comment markers from previous uploads
|
|
8271
8311
|
|
|
8272
|
-
${
|
|
8312
|
+
${chalk28.dim("Results are saved to .mutagent/mutation-context.md for use by other commands.")}
|
|
8273
8313
|
`).action((options) => {
|
|
8274
8314
|
const isJson = getJsonFlag(explore);
|
|
8275
8315
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -8287,7 +8327,7 @@ ${chalk27.dim("Results are saved to .mutagent/mutation-context.md for use by oth
|
|
|
8287
8327
|
markersOnly
|
|
8288
8328
|
};
|
|
8289
8329
|
if (!isJson) {
|
|
8290
|
-
console.log(
|
|
8330
|
+
console.log(chalk28.cyan(`
|
|
8291
8331
|
Scanning ${scanPath}...
|
|
8292
8332
|
`));
|
|
8293
8333
|
}
|
|
@@ -8316,41 +8356,41 @@ Scanning ${scanPath}...
|
|
|
8316
8356
|
const totalFindings = result.prompts.length + result.datasets.length + result.markers.length;
|
|
8317
8357
|
if (totalFindings === 0) {
|
|
8318
8358
|
output.info("No prompts, datasets, or markers found.");
|
|
8319
|
-
console.log(
|
|
8359
|
+
console.log(chalk28.dim(`
|
|
8320
8360
|
Tip: Create a prompt with template variables like {{input}} to get started.`));
|
|
8321
8361
|
return;
|
|
8322
8362
|
}
|
|
8323
8363
|
if (result.prompts.length > 0) {
|
|
8324
|
-
console.log(
|
|
8364
|
+
console.log(chalk28.bold(` Prompts Found (${String(result.prompts.length)}):`));
|
|
8325
8365
|
console.log();
|
|
8326
8366
|
for (const p of result.prompts) {
|
|
8327
|
-
const confidenceTag = p.confidence === "high" ?
|
|
8328
|
-
const reasonTag =
|
|
8329
|
-
console.log(` ${confidenceTag} ${
|
|
8330
|
-
console.log(` ${
|
|
8367
|
+
const confidenceTag = p.confidence === "high" ? chalk28.green("[high]") : p.confidence === "medium" ? chalk28.yellow("[medium]") : chalk28.dim("[low]");
|
|
8368
|
+
const reasonTag = chalk28.dim(`[${p.reason}]`);
|
|
8369
|
+
console.log(` ${confidenceTag} ${chalk28.green(p.file)}:${chalk28.yellow(String(p.line))} ${reasonTag}`);
|
|
8370
|
+
console.log(` ${chalk28.dim(p.preview)}`);
|
|
8331
8371
|
}
|
|
8332
8372
|
console.log();
|
|
8333
8373
|
}
|
|
8334
8374
|
if (result.datasets.length > 0) {
|
|
8335
|
-
console.log(
|
|
8375
|
+
console.log(chalk28.bold(` Datasets Found (${String(result.datasets.length)}):`));
|
|
8336
8376
|
console.log();
|
|
8337
8377
|
for (const d of result.datasets) {
|
|
8338
|
-
console.log(` ${
|
|
8378
|
+
console.log(` ${chalk28.green(d.file)} ${chalk28.dim(`(${String(d.items)} items)`)}`);
|
|
8339
8379
|
}
|
|
8340
8380
|
console.log();
|
|
8341
8381
|
}
|
|
8342
8382
|
if (result.markers.length > 0) {
|
|
8343
|
-
console.log(
|
|
8383
|
+
console.log(chalk28.bold(` MutagenT Markers (${String(result.markers.length)}):`));
|
|
8344
8384
|
console.log();
|
|
8345
8385
|
for (const m of result.markers) {
|
|
8346
|
-
const idPart = m.platformId ?
|
|
8347
|
-
console.log(` ${
|
|
8386
|
+
const idPart = m.platformId ? chalk28.cyan(` id=${m.platformId}`) : "";
|
|
8387
|
+
console.log(` ${chalk28.green(m.file)}:${chalk28.yellow(String(m.line))} ${chalk28.magenta(m.type)}${idPart}`);
|
|
8348
8388
|
}
|
|
8349
8389
|
console.log();
|
|
8350
8390
|
}
|
|
8351
|
-
console.log(
|
|
8352
|
-
console.log(` ${
|
|
8353
|
-
console.log(
|
|
8391
|
+
console.log(chalk28.dim(" ─────────────────────────────────"));
|
|
8392
|
+
console.log(` ${chalk28.bold("Summary:")} ${String(result.prompts.length)} prompts, ${String(result.datasets.length)} datasets, ${String(result.markers.length)} markers`);
|
|
8393
|
+
console.log(chalk28.dim(` Saved to .mutagent/mutation-context.md`));
|
|
8354
8394
|
console.log();
|
|
8355
8395
|
}
|
|
8356
8396
|
} catch (error) {
|
|
@@ -8362,7 +8402,7 @@ Scanning ${scanPath}...
|
|
|
8362
8402
|
|
|
8363
8403
|
// src/commands/skills.ts
|
|
8364
8404
|
import { Command as Command16 } from "commander";
|
|
8365
|
-
import
|
|
8405
|
+
import chalk29 from "chalk";
|
|
8366
8406
|
import { existsSync as existsSync12, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
8367
8407
|
import { join as join7 } from "path";
|
|
8368
8408
|
import { execSync as execSync4 } from "child_process";
|
|
@@ -8486,7 +8526,7 @@ function createSkillsCommand() {
|
|
|
8486
8526
|
const skills = new Command16("skills").description("Manage MutagenT CLI skills for coding agents");
|
|
8487
8527
|
skills.command("install").description("Install MutagenT CLI skill for Claude Code").addHelpText("after", `
|
|
8488
8528
|
Examples:
|
|
8489
|
-
${
|
|
8529
|
+
${chalk29.dim("$")} mutagent skills install
|
|
8490
8530
|
|
|
8491
8531
|
This creates a Claude Code skill at .claude/skills/mutagent-cli/SKILL.md
|
|
8492
8532
|
that teaches coding agents how to use the MutagenT CLI effectively.
|
|
@@ -8513,10 +8553,10 @@ ${SKILL_BODY}
|
|
|
8513
8553
|
});
|
|
8514
8554
|
} else {
|
|
8515
8555
|
output.success(`Installed MutagenT CLI skill`);
|
|
8516
|
-
console.log(` ${
|
|
8556
|
+
console.log(` ${chalk29.dim("Path:")} ${skillPath}`);
|
|
8517
8557
|
console.log("");
|
|
8518
|
-
console.log(` ${
|
|
8519
|
-
console.log(` ${
|
|
8558
|
+
console.log(` ${chalk29.dim("This skill teaches coding agents how to use the MutagenT CLI.")}`);
|
|
8559
|
+
console.log(` ${chalk29.dim("It will be automatically loaded by Claude Code when relevant triggers match.")}`);
|
|
8520
8560
|
}
|
|
8521
8561
|
});
|
|
8522
8562
|
return skills;
|
|
@@ -8525,7 +8565,7 @@ ${SKILL_BODY}
|
|
|
8525
8565
|
// src/commands/usage.ts
|
|
8526
8566
|
init_config();
|
|
8527
8567
|
import { Command as Command17 } from "commander";
|
|
8528
|
-
import
|
|
8568
|
+
import chalk30 from "chalk";
|
|
8529
8569
|
init_errors();
|
|
8530
8570
|
init_sdk_client();
|
|
8531
8571
|
var TRIAL_OPTIMIZATION_LIMIT = 5;
|
|
@@ -8541,8 +8581,8 @@ function renderProgressBar(used, limit, width = 30) {
|
|
|
8541
8581
|
function createUsageCommand() {
|
|
8542
8582
|
const usage = new Command17("usage").description("Show resource counts and optimization run limits").addHelpText("after", `
|
|
8543
8583
|
Examples:
|
|
8544
|
-
${
|
|
8545
|
-
${
|
|
8584
|
+
${chalk30.dim("$")} mutagent usage
|
|
8585
|
+
${chalk30.dim("$")} mutagent usage --json
|
|
8546
8586
|
`);
|
|
8547
8587
|
usage.action(async () => {
|
|
8548
8588
|
const isJson = getJsonFlag(usage);
|
|
@@ -8597,21 +8637,21 @@ Examples:
|
|
|
8597
8637
|
});
|
|
8598
8638
|
} else {
|
|
8599
8639
|
console.log("");
|
|
8600
|
-
console.log(
|
|
8601
|
-
console.log(
|
|
8640
|
+
console.log(chalk30.bold("\uD83D\uDCCA MutagenT Usage"));
|
|
8641
|
+
console.log(chalk30.dim("─".repeat(45)));
|
|
8602
8642
|
console.log("");
|
|
8603
|
-
console.log(
|
|
8604
|
-
console.log(` Prompts: ${
|
|
8605
|
-
console.log(` Datasets: ${
|
|
8606
|
-
console.log(` Evaluations: ${
|
|
8643
|
+
console.log(chalk30.bold("Resources:"));
|
|
8644
|
+
console.log(` Prompts: ${chalk30.cyan(String(promptCount))}`);
|
|
8645
|
+
console.log(` Datasets: ${chalk30.cyan(String(datasetCount))}`);
|
|
8646
|
+
console.log(` Evaluations: ${chalk30.cyan(String(evaluationCount))}`);
|
|
8607
8647
|
console.log("");
|
|
8608
|
-
console.log(
|
|
8609
|
-
console.log(` Remaining: ${
|
|
8648
|
+
console.log(chalk30.bold(`Optimization Runs (${chalk30.yellow("trial")} plan):`));
|
|
8649
|
+
console.log(` Remaining: ${chalk30.cyan(String(optimizationRemaining))} / ${String(optimizationLimit)}`);
|
|
8610
8650
|
console.log(` ${renderProgressBar(optimizationUsed, optimizationLimit)}`);
|
|
8611
8651
|
console.log("");
|
|
8612
|
-
console.log(
|
|
8613
|
-
console.log(
|
|
8614
|
-
console.log(` Upgrade: ${
|
|
8652
|
+
console.log(chalk30.yellow(` ⚠ ${String(optimizationRemaining)} optimization runs remaining`));
|
|
8653
|
+
console.log(chalk30.dim(` ℹ Optimization run counts are approximate`));
|
|
8654
|
+
console.log(` Upgrade: ${chalk30.underline(BILLING_URL)}`);
|
|
8615
8655
|
console.log("");
|
|
8616
8656
|
}
|
|
8617
8657
|
} catch (error) {
|
|
@@ -8899,7 +8939,7 @@ Claude Code Session Telemetry:
|
|
|
8899
8939
|
|
|
8900
8940
|
// src/commands/feedback.ts
|
|
8901
8941
|
import { Command as Command19 } from "commander";
|
|
8902
|
-
import
|
|
8942
|
+
import chalk31 from "chalk";
|
|
8903
8943
|
init_errors();
|
|
8904
8944
|
init_config();
|
|
8905
8945
|
import { readFileSync as readFileSync11 } from "fs";
|
|
@@ -8953,12 +8993,12 @@ async function postToServer(payload, endpoint, apiKey, workspaceId, organization
|
|
|
8953
8993
|
}
|
|
8954
8994
|
function createFeedbackCommand() {
|
|
8955
8995
|
const feedback = new Command19("feedback").description("Send product feedback to MutagenT").addHelpText("after", `
|
|
8956
|
-
${
|
|
8957
|
-
${
|
|
8958
|
-
${
|
|
8959
|
-
${
|
|
8996
|
+
${chalk31.bold("Examples:")}
|
|
8997
|
+
${chalk31.cyan('mutagent feedback send -m "Great optimization results!"')}
|
|
8998
|
+
${chalk31.cyan('mutagent feedback send -m "CLI crashed on export" --category bug')}
|
|
8999
|
+
${chalk31.cyan('mutagent feedback send -m "Need batch operations" --category feature --json')}
|
|
8960
9000
|
|
|
8961
|
-
${
|
|
9001
|
+
${chalk31.yellow("AI Agent (MANDATORY):")}
|
|
8962
9002
|
ALWAYS use --json: mutagent feedback send -m "..." --category improvement --json
|
|
8963
9003
|
Use this command to report bugs, request features, or share UX feedback.
|
|
8964
9004
|
`).action(() => {
|
|
@@ -8969,18 +9009,18 @@ ${chalk30.yellow("AI Agent (MANDATORY):")}
|
|
|
8969
9009
|
}
|
|
8970
9010
|
function registerFeedbackSend(feedback) {
|
|
8971
9011
|
feedback.command("send").description("Send feedback about the MutagenT platform").requiredOption("-m, --message <text>", "Feedback message").option("--category <type>", `Feedback category: ${VALID_CATEGORIES.join(", ")}`, "improvement").option("--session <id>", "Link feedback to a specific session").addHelpText("after", `
|
|
8972
|
-
${
|
|
8973
|
-
${
|
|
8974
|
-
${
|
|
8975
|
-
${
|
|
8976
|
-
|
|
8977
|
-
${
|
|
8978
|
-
${
|
|
8979
|
-
${
|
|
8980
|
-
${
|
|
8981
|
-
${
|
|
8982
|
-
|
|
8983
|
-
${
|
|
9012
|
+
${chalk31.bold("Examples:")}
|
|
9013
|
+
${chalk31.dim("$")} mutagent feedback send -m "The optimization UX could show progress better"
|
|
9014
|
+
${chalk31.dim("$")} mutagent feedback send -m "CLI errored on traces export" --category bug
|
|
9015
|
+
${chalk31.dim("$")} mutagent feedback send -m "Love the guided eval!" --category praise --json
|
|
9016
|
+
|
|
9017
|
+
${chalk31.bold("Categories:")}
|
|
9018
|
+
${chalk31.bold("bug")} Something is broken or not working as expected
|
|
9019
|
+
${chalk31.bold("feature")} Request a new capability
|
|
9020
|
+
${chalk31.bold("improvement")} Suggest a UX or workflow enhancement (default)
|
|
9021
|
+
${chalk31.bold("praise")} Share what you love about the platform
|
|
9022
|
+
|
|
9023
|
+
${chalk31.yellow("AI Agent (MANDATORY):")}
|
|
8984
9024
|
ALWAYS use --json: mutagent feedback send -m "..." --json
|
|
8985
9025
|
Auto-captured context (CLI version, platform, node version) is included automatically.
|
|
8986
9026
|
`).action(async (options) => {
|
|
@@ -9052,103 +9092,109 @@ program.name("mutagent").description(`MutagenT CLI - AI-native prompt optimizati
|
|
|
9052
9092
|
showGlobalOptions: true
|
|
9053
9093
|
});
|
|
9054
9094
|
program.addHelpText("after", `
|
|
9055
|
-
${
|
|
9056
|
-
export MUTAGENT_API_KEY=mt_... ${
|
|
9057
|
-
--json ${
|
|
9058
|
-
|
|
9059
|
-
${
|
|
9060
|
-
mutagent
|
|
9061
|
-
mutagent auth status ${
|
|
9062
|
-
mutagent init ${
|
|
9063
|
-
mutagent explore ${
|
|
9064
|
-
mutagent workspaces list --json ${
|
|
9065
|
-
mutagent config set workspace <id> ${
|
|
9066
|
-
mutagent usage --json ${
|
|
9067
|
-
|
|
9068
|
-
mutagent prompts create --help ${
|
|
9069
|
-
mutagent prompts list --json ${
|
|
9070
|
-
mutagent prompts get <id> --json ${
|
|
9071
|
-
|
|
9072
|
-
mutagent prompts dataset add --help ${
|
|
9073
|
-
mutagent prompts dataset list <id> ${
|
|
9074
|
-
|
|
9075
|
-
mutagent prompts evaluation create --help ${
|
|
9076
|
-
mutagent prompts evaluation create <id> --guided --json ${
|
|
9077
|
-
mutagent prompts evaluation list <id> --json ${
|
|
9078
|
-
|
|
9079
|
-
mutagent prompts optimize start --help ${
|
|
9080
|
-
mutagent prompts optimize status <job-id> ${
|
|
9081
|
-
mutagent prompts optimize results <job-id> ${
|
|
9082
|
-
|
|
9083
|
-
mutagent feedback send -m "..." ${
|
|
9084
|
-
mutagent feedback send -m "..." --category bug ${
|
|
9085
|
-
|
|
9086
|
-
mutagent integrate <framework> ${
|
|
9087
|
-
mutagent hooks --help ${
|
|
9088
|
-
mutagent playground run <id> --input '{...}' ${
|
|
9089
|
-
|
|
9090
|
-
${
|
|
9091
|
-
1. mutagent explore ${
|
|
9092
|
-
2. mutagent integrate <framework> ${
|
|
9093
|
-
3. Apply tracing code to your codebase ${
|
|
9094
|
-
4. mutagent traces list --json ${
|
|
9095
|
-
|
|
9096
|
-
${
|
|
9097
|
-
1. mutagent prompts create --help ${
|
|
9098
|
-
2. mutagent prompts create ... --json ${
|
|
9099
|
-
3. mutagent prompts dataset add --help ${
|
|
9100
|
-
4. mutagent prompts dataset add <id> ... --json ${
|
|
9101
|
-
5. mutagent prompts evaluation create <id> --guided --json ${
|
|
9095
|
+
${chalk32.yellow("Non-Interactive Mode (CI/CD & Coding Agents):")}
|
|
9096
|
+
export MUTAGENT_API_KEY=mt_... ${chalk32.dim("or")} --api-key mt_...
|
|
9097
|
+
--json ${chalk32.dim("for structured output")} --non-interactive ${chalk32.dim("to disable prompts")}
|
|
9098
|
+
|
|
9099
|
+
${chalk32.yellow("Command Navigation:")}
|
|
9100
|
+
mutagent login ${chalk32.dim("Login (browser OAuth — recommended)")}
|
|
9101
|
+
mutagent auth status ${chalk32.dim("Check auth + workspace")}
|
|
9102
|
+
mutagent init ${chalk32.dim("Initialize project (.mutagentrc.json)")}
|
|
9103
|
+
mutagent explore ${chalk32.dim("Discover prompts in codebase")}
|
|
9104
|
+
mutagent workspaces list --json ${chalk32.dim("List workspaces (verify ID)")}
|
|
9105
|
+
mutagent config set workspace <id> ${chalk32.dim("Set active workspace")}
|
|
9106
|
+
mutagent usage --json ${chalk32.dim("Check plan limits")}
|
|
9107
|
+
|
|
9108
|
+
mutagent prompts create --help ${chalk32.dim("Upload prompt (read help first!)")}
|
|
9109
|
+
mutagent prompts list --json ${chalk32.dim("List prompts")}
|
|
9110
|
+
mutagent prompts get <id> --json ${chalk32.dim("Full prompt details + schemas")}
|
|
9111
|
+
|
|
9112
|
+
mutagent prompts dataset add --help ${chalk32.dim("Upload dataset (read help first!)")}
|
|
9113
|
+
mutagent prompts dataset list <id> ${chalk32.dim("List datasets")}
|
|
9114
|
+
|
|
9115
|
+
mutagent prompts evaluation create --help ${chalk32.dim("Create eval (read help first!)")}
|
|
9116
|
+
mutagent prompts evaluation create <id> --guided --json ${chalk32.dim("Guided eval workflow")}
|
|
9117
|
+
mutagent prompts evaluation list <id> --json ${chalk32.dim("List evaluations")}
|
|
9118
|
+
|
|
9119
|
+
mutagent prompts optimize start --help ${chalk32.dim("Run optimization (read help first!)")}
|
|
9120
|
+
mutagent prompts optimize status <job-id> ${chalk32.dim("Poll progress")}
|
|
9121
|
+
mutagent prompts optimize results <job-id> ${chalk32.dim("View scorecard")}
|
|
9122
|
+
|
|
9123
|
+
mutagent feedback send -m "..." ${chalk32.dim("Send product feedback")}
|
|
9124
|
+
mutagent feedback send -m "..." --category bug ${chalk32.dim("Report a bug")}
|
|
9125
|
+
|
|
9126
|
+
mutagent integrate <framework> ${chalk32.dim("Framework integration guide")}
|
|
9127
|
+
mutagent hooks --help ${chalk32.dim("Hook setup for Claude Code telemetry")}
|
|
9128
|
+
mutagent playground run <id> --input '{...}' ${chalk32.dim("Quick test")}
|
|
9129
|
+
|
|
9130
|
+
${chalk32.yellow("★ Workflow: Framework Integration (Tracing):")}
|
|
9131
|
+
1. mutagent explore ${chalk32.dim("← discover prompts/agents in codebase")}
|
|
9132
|
+
2. mutagent integrate <framework> ${chalk32.dim("← get integration instructions")}
|
|
9133
|
+
3. Apply tracing code to your codebase ${chalk32.dim("← follow the guide output")}
|
|
9134
|
+
4. mutagent traces list --json ${chalk32.dim("← verify traces are arriving")}
|
|
9135
|
+
|
|
9136
|
+
${chalk32.yellow("★ Workflow: Evaluate → Optimize:")}
|
|
9137
|
+
1. mutagent prompts create --help ${chalk32.dim("← read help")}
|
|
9138
|
+
2. mutagent prompts create ... --json ${chalk32.dim("← upload prompt with {variables} + inputSchema")}
|
|
9139
|
+
3. mutagent prompts dataset add --help ${chalk32.dim("← read help")}
|
|
9140
|
+
4. mutagent prompts dataset add <id> ... --json ${chalk32.dim("← upload dataset")}
|
|
9141
|
+
5. mutagent prompts evaluation create <id> --guided --json ${chalk32.dim("← guided eval")}
|
|
9102
9142
|
6. mutagent prompts optimize start <id> --dataset <d> --evaluation <e> --json
|
|
9103
9143
|
|
|
9104
|
-
${
|
|
9105
|
-
After ${
|
|
9106
|
-
${
|
|
9107
|
-
${
|
|
9108
|
-
${
|
|
9144
|
+
${chalk32.yellow("Post-Onboarding Decision Tree:")}
|
|
9145
|
+
After ${chalk32.bold("mutagent auth login")}, users land in one of 3 paths:
|
|
9146
|
+
${chalk32.bold("Path A")} (Tracing): explore → integrate <framework> → apply tracing → verify
|
|
9147
|
+
${chalk32.bold("Path B")} (Optimization): explore → prompts create → dataset add → eval create → optimize
|
|
9148
|
+
${chalk32.bold("Path C")} (Manual): Use CLI commands directly — run mutagent <command> --help
|
|
9109
9149
|
|
|
9110
|
-
${
|
|
9150
|
+
${chalk32.yellow("Directive System:")}
|
|
9111
9151
|
Every --json response may include:
|
|
9112
|
-
${
|
|
9113
|
-
${
|
|
9114
|
-
${
|
|
9115
|
-
${
|
|
9152
|
+
${chalk32.bold("_directive.renderedCard")} Pre-formatted card for the user ${chalk32.red("(MUST be shown in chat)")}
|
|
9153
|
+
${chalk32.bold("_directive.instruction")} Next step for the agent
|
|
9154
|
+
${chalk32.bold("_directive.next")} Array of suggested follow-up commands
|
|
9155
|
+
${chalk32.bold("_links")} Dashboard/API URLs (format as markdown links)
|
|
9116
9156
|
|
|
9117
|
-
${
|
|
9118
|
-
Each criterion MUST have: ${
|
|
9157
|
+
${chalk32.yellow("Evaluation Criteria Format:")}
|
|
9158
|
+
Each criterion MUST have: ${chalk32.bold("name")}, ${chalk32.bold("description")} (scoring rubric), ${chalk32.bold("evaluationParameter")}
|
|
9119
9159
|
evaluationParameter MUST match an inputSchema or outputSchema field name
|
|
9120
9160
|
No duplicate evaluationParameter values — each criterion targets a unique field
|
|
9121
9161
|
ALL schema fields must be covered (missing fields = error)
|
|
9122
|
-
Use ${
|
|
9162
|
+
Use ${chalk32.bold("--guided --json")} to generate criteria templates from prompt schemas
|
|
9123
9163
|
|
|
9124
|
-
${
|
|
9125
|
-
Default max-iterations is 1. ${
|
|
9164
|
+
${chalk32.yellow("Optimization Cost Control:")}
|
|
9165
|
+
Default max-iterations is 1. ${chalk32.red("NEVER increase without explicit user request.")}
|
|
9126
9166
|
Each iteration incurs LLM costs — confirm with user before starting >1.
|
|
9127
9167
|
|
|
9128
|
-
${
|
|
9129
|
-
After ${
|
|
9130
|
-
Then offer choices: ${
|
|
9168
|
+
${chalk32.yellow("Post-Optimization:")}
|
|
9169
|
+
After ${chalk32.bold("optimize results")}: ALWAYS show the before/after diff to the user first.
|
|
9170
|
+
Then offer choices: ${chalk32.bold("Apply")} / ${chalk32.bold("Reject")}.
|
|
9131
9171
|
|
|
9132
|
-
${
|
|
9172
|
+
${chalk32.yellow("State Tracking:")}
|
|
9133
9173
|
.mutagent/mutation-context.md — Codebase index of discovered/uploaded prompts
|
|
9134
9174
|
Update after explore, create, and dataset operations
|
|
9135
9175
|
mutagent auth status — Auth + workspace state
|
|
9136
9176
|
Comment markers (// MutagenT:START ... // MutagenT:END) in source files
|
|
9137
9177
|
|
|
9138
|
-
${
|
|
9139
|
-
1.
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9178
|
+
${chalk32.yellow("AI Agent Rules (MANDATORY for coding agents):")}
|
|
9179
|
+
1. Login (two paths):
|
|
9180
|
+
- CI / fully automated: export MUTAGENT_API_KEY=mt_... then mutagent login --json
|
|
9181
|
+
- Helping a user onboard: mutagent login --browser --json
|
|
9182
|
+
(CLI prints an auth URL — surface it to the user verbatim, then the CLI
|
|
9183
|
+
polls for up to 5 minutes while the user authorizes in their browser.
|
|
9184
|
+
This IS agent-compatible. --non-interactive is NOT needed with --browser.)
|
|
9185
|
+
2. EVERY command MUST include --json (no exceptions)
|
|
9186
|
+
3. Run <command> --help BEFORE first use of any command
|
|
9187
|
+
4. Use --guided --json for evaluation creation (NEVER --guided alone)
|
|
9188
|
+
5. Parse _directive.renderedCard and copy it into your CHAT RESPONSE verbatim
|
|
9189
|
+
${chalk32.red("HARD STOP")}: do NOT run further commands until the card is rendered in chat
|
|
9190
|
+
6. After mutagent init, verify workspace: mutagent workspaces list --json
|
|
9191
|
+
7. Use {single_braces} for template variables in prompts
|
|
9192
|
+
8. Collect evaluation criteria from the user — NEVER auto-generate
|
|
9193
|
+
9. ALL user interaction via AskUserQuestion — CLI is non-interactive
|
|
9148
9194
|
${!hasCredentials() ? `
|
|
9149
|
-
` +
|
|
9195
|
+
` + chalk32.yellow(" Warning: Not authenticated. Run: mutagent login") + `
|
|
9150
9196
|
` : ""}${!hasRcConfig() ? `
|
|
9151
|
-
` +
|
|
9197
|
+
` + chalk32.green(" Get started: mutagent init") + `
|
|
9152
9198
|
` : ""}`);
|
|
9153
9199
|
var rawArgs = process.argv.slice(2);
|
|
9154
9200
|
if (rawArgs.includes("-v") || rawArgs.includes("--version")) {
|
|
@@ -9189,5 +9235,5 @@ program.addCommand(createHooksCommand());
|
|
|
9189
9235
|
program.addCommand(createFeedbackCommand());
|
|
9190
9236
|
program.parse();
|
|
9191
9237
|
|
|
9192
|
-
//# debugId=
|
|
9238
|
+
//# debugId=A84DFC92DB1ED69764756E2164756E21
|
|
9193
9239
|
//# sourceMappingURL=cli.js.map
|