@mutagent/cli 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +254 -39
- package/dist/bin/cli.js.map +7 -6
- package/dist/index.js +4 -4
- package/dist/index.js.map +3 -3
- package/package.json +2 -2
package/dist/bin/cli.js
CHANGED
|
@@ -439,9 +439,9 @@ class SDKClientWrapper {
|
|
|
439
439
|
systemPrompt: data.systemPrompt ?? undefined,
|
|
440
440
|
humanPrompt: data.humanPrompt ?? undefined,
|
|
441
441
|
rawPrompt: data.rawPrompt ?? undefined,
|
|
442
|
-
inputSchema: data.inputSchema ??
|
|
443
|
-
outputSchema: data.outputSchema,
|
|
444
|
-
metadata: data.metadata,
|
|
442
|
+
inputSchema: data.inputSchema ?? undefined,
|
|
443
|
+
outputSchema: data.outputSchema ?? undefined,
|
|
444
|
+
metadata: data.metadata ?? undefined,
|
|
445
445
|
tags: data.tags ?? undefined
|
|
446
446
|
});
|
|
447
447
|
return response;
|
|
@@ -1628,11 +1628,85 @@ function providerSettingsLink() {
|
|
|
1628
1628
|
}
|
|
1629
1629
|
function promptLinks(promptId) {
|
|
1630
1630
|
return {
|
|
1631
|
-
|
|
1631
|
+
dashboard: promptLink(promptId),
|
|
1632
|
+
api: `/api/prompts/${String(promptId)}`,
|
|
1632
1633
|
datasets: promptDatasetsLink(promptId),
|
|
1633
1634
|
evaluations: promptEvaluationsLink(promptId)
|
|
1634
1635
|
};
|
|
1635
1636
|
}
|
|
1637
|
+
function datasetLinks(promptId, datasetId) {
|
|
1638
|
+
return {
|
|
1639
|
+
dashboard: datasetLink(promptId, datasetId),
|
|
1640
|
+
api: `/api/prompts/${String(promptId)}/datasets/${String(datasetId)}`
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
function evaluationLinks(promptId, evalId) {
|
|
1644
|
+
return {
|
|
1645
|
+
dashboard: evaluationLink(promptId, evalId),
|
|
1646
|
+
api: `/api/prompts/${String(promptId)}/evaluations/${String(evalId)}`
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
function formatCreationHints(hint) {
|
|
1650
|
+
const lines = [
|
|
1651
|
+
"",
|
|
1652
|
+
` -> View in dashboard: ${hint.dashboardUrl}`,
|
|
1653
|
+
` -> API: GET ${hint.apiPath}`,
|
|
1654
|
+
"",
|
|
1655
|
+
" Tip: Copy the link above to open in your browser or share with your team."
|
|
1656
|
+
];
|
|
1657
|
+
return lines.join(`
|
|
1658
|
+
`);
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
// src/lib/schema-helpers.ts
|
|
1662
|
+
var SUPPORTED_SCHEMA_TYPES = ["string", "number", "boolean", "array", "object"];
|
|
1663
|
+
function isValidJsonSchema(schema) {
|
|
1664
|
+
if (schema === null || schema === undefined)
|
|
1665
|
+
return false;
|
|
1666
|
+
if (typeof schema !== "object")
|
|
1667
|
+
return false;
|
|
1668
|
+
if (Array.isArray(schema))
|
|
1669
|
+
return false;
|
|
1670
|
+
const obj = schema;
|
|
1671
|
+
if (!("type" in obj) || typeof obj.type !== "string")
|
|
1672
|
+
return false;
|
|
1673
|
+
if (obj.type === "object") {
|
|
1674
|
+
if (!("properties" in obj) || typeof obj.properties !== "object" || obj.properties === null) {
|
|
1675
|
+
return false;
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
return true;
|
|
1679
|
+
}
|
|
1680
|
+
function buildSchemaFromVariables(variables) {
|
|
1681
|
+
const properties = {};
|
|
1682
|
+
for (const variable of variables) {
|
|
1683
|
+
const prop = { type: variable.type };
|
|
1684
|
+
if (variable.description) {
|
|
1685
|
+
prop.description = variable.description;
|
|
1686
|
+
}
|
|
1687
|
+
properties[variable.name] = prop;
|
|
1688
|
+
}
|
|
1689
|
+
return {
|
|
1690
|
+
type: "object",
|
|
1691
|
+
properties
|
|
1692
|
+
};
|
|
1693
|
+
}
|
|
1694
|
+
function formatSchemaWarning(fieldName) {
|
|
1695
|
+
return [
|
|
1696
|
+
`${fieldName} doesn't appear to be a valid JSON Schema.`,
|
|
1697
|
+
"",
|
|
1698
|
+
" Expected format:",
|
|
1699
|
+
" {",
|
|
1700
|
+
' "type": "object",',
|
|
1701
|
+
' "properties": {',
|
|
1702
|
+
' "variable_name": { "type": "string", "description": "Description here" }',
|
|
1703
|
+
" }",
|
|
1704
|
+
" }",
|
|
1705
|
+
"",
|
|
1706
|
+
" You can also provide a schema file: mutagent prompts create --file schema.json"
|
|
1707
|
+
].join(`
|
|
1708
|
+
`);
|
|
1709
|
+
}
|
|
1636
1710
|
|
|
1637
1711
|
// src/commands/prompts.ts
|
|
1638
1712
|
var PREREQUISITES_TEXT = `
|
|
@@ -1659,16 +1733,116 @@ function parseValidationErrors(error) {
|
|
|
1659
1733
|
}
|
|
1660
1734
|
return ["An unknown error occurred"];
|
|
1661
1735
|
}
|
|
1662
|
-
function
|
|
1663
|
-
|
|
1664
|
-
if (schema === null || schema === undefined)
|
|
1736
|
+
function isSchemaEmpty(schema) {
|
|
1737
|
+
if (schema === undefined || schema === null)
|
|
1665
1738
|
return true;
|
|
1666
|
-
if (typeof schema
|
|
1739
|
+
if (typeof schema !== "object")
|
|
1740
|
+
return false;
|
|
1741
|
+
const obj = schema;
|
|
1742
|
+
if (Object.keys(obj).length === 0)
|
|
1667
1743
|
return true;
|
|
1668
1744
|
return false;
|
|
1669
1745
|
}
|
|
1670
|
-
function
|
|
1671
|
-
|
|
1746
|
+
function warnMissingSchemas(data, output) {
|
|
1747
|
+
if (isSchemaEmpty(data.inputSchema)) {
|
|
1748
|
+
output.warn("No inputSchema provided. Optimization requires inputSchema with defined variables.");
|
|
1749
|
+
} else if (!isValidJsonSchema(data.inputSchema)) {
|
|
1750
|
+
output.warn(formatSchemaWarning("inputSchema"));
|
|
1751
|
+
}
|
|
1752
|
+
if (isSchemaEmpty(data.outputSchema)) {
|
|
1753
|
+
output.warn("No outputSchema provided. This may limit optimization effectiveness.");
|
|
1754
|
+
} else if (!isValidJsonSchema(data.outputSchema)) {
|
|
1755
|
+
output.warn(formatSchemaWarning("outputSchema"));
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
async function collectSchemaInteractively() {
|
|
1759
|
+
const inquirer3 = (await import("inquirer")).default;
|
|
1760
|
+
const variables = [];
|
|
1761
|
+
let addMore = true;
|
|
1762
|
+
while (addMore) {
|
|
1763
|
+
const answers = await inquirer3.prompt([
|
|
1764
|
+
{
|
|
1765
|
+
type: "input",
|
|
1766
|
+
name: "name",
|
|
1767
|
+
message: "Variable name:",
|
|
1768
|
+
validate: (input) => {
|
|
1769
|
+
if (!input.trim())
|
|
1770
|
+
return "Variable name is required";
|
|
1771
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(input.trim())) {
|
|
1772
|
+
return "Variable name must start with a letter/underscore and contain only alphanumeric/underscore";
|
|
1773
|
+
}
|
|
1774
|
+
return true;
|
|
1775
|
+
}
|
|
1776
|
+
},
|
|
1777
|
+
{
|
|
1778
|
+
type: "list",
|
|
1779
|
+
name: "type",
|
|
1780
|
+
message: "Variable type:",
|
|
1781
|
+
choices: [...SUPPORTED_SCHEMA_TYPES]
|
|
1782
|
+
},
|
|
1783
|
+
{
|
|
1784
|
+
type: "input",
|
|
1785
|
+
name: "description",
|
|
1786
|
+
message: "Description (optional):"
|
|
1787
|
+
}
|
|
1788
|
+
]);
|
|
1789
|
+
variables.push({
|
|
1790
|
+
name: answers.name.trim(),
|
|
1791
|
+
type: answers.type,
|
|
1792
|
+
description: answers.description.trim() || undefined
|
|
1793
|
+
});
|
|
1794
|
+
const continueAnswer = await inquirer3.prompt([{
|
|
1795
|
+
type: "confirm",
|
|
1796
|
+
name: "addAnother",
|
|
1797
|
+
message: "Add another variable?",
|
|
1798
|
+
default: false
|
|
1799
|
+
}]);
|
|
1800
|
+
addMore = continueAnswer.addAnother;
|
|
1801
|
+
}
|
|
1802
|
+
return buildSchemaFromVariables(variables);
|
|
1803
|
+
}
|
|
1804
|
+
async function promptForInputSchema() {
|
|
1805
|
+
const inquirer3 = (await import("inquirer")).default;
|
|
1806
|
+
const answer = await inquirer3.prompt([{
|
|
1807
|
+
type: "list",
|
|
1808
|
+
name: "choice",
|
|
1809
|
+
message: "Would you like to define input variables for this prompt?",
|
|
1810
|
+
choices: [
|
|
1811
|
+
{ name: "Yes, define variables interactively", value: "interactive" },
|
|
1812
|
+
{ name: "Provide a JSON Schema file path", value: "file" },
|
|
1813
|
+
{ name: "Skip (not recommended for optimization)", value: "skip" }
|
|
1814
|
+
]
|
|
1815
|
+
}]);
|
|
1816
|
+
if (answer.choice === "interactive") {
|
|
1817
|
+
return collectSchemaInteractively();
|
|
1818
|
+
}
|
|
1819
|
+
if (answer.choice === "file") {
|
|
1820
|
+
const fileAnswer = await inquirer3.prompt([{
|
|
1821
|
+
type: "input",
|
|
1822
|
+
name: "path",
|
|
1823
|
+
message: "JSON Schema file path:",
|
|
1824
|
+
validate: (input) => {
|
|
1825
|
+
if (!input.trim())
|
|
1826
|
+
return "File path is required";
|
|
1827
|
+
if (!existsSync2(input.trim()))
|
|
1828
|
+
return `File not found: ${input.trim()}`;
|
|
1829
|
+
return true;
|
|
1830
|
+
}
|
|
1831
|
+
}]);
|
|
1832
|
+
const content = readFileSync2(fileAnswer.path.trim(), "utf-8");
|
|
1833
|
+
try {
|
|
1834
|
+
const parsed = JSON.parse(content);
|
|
1835
|
+
if (!isValidJsonSchema(parsed)) {
|
|
1836
|
+
console.log(chalk4.yellow(`
|
|
1837
|
+
Warning: ${formatSchemaWarning("inputSchema")}
|
|
1838
|
+
`));
|
|
1839
|
+
}
|
|
1840
|
+
return parsed;
|
|
1841
|
+
} catch {
|
|
1842
|
+
throw new MutagentError("INVALID_JSON", `Failed to parse JSON Schema from ${fileAnswer.path.trim()}`, "Ensure the file contains valid JSON");
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
return;
|
|
1672
1846
|
}
|
|
1673
1847
|
function warnSingleBraceVariables(content, output) {
|
|
1674
1848
|
const singleBracePattern = /(?<!\{)\{([a-zA-Z_][a-zA-Z0-9_]*)\}(?!\})/g;
|
|
@@ -1861,17 +2035,31 @@ ${chalk4.dim("Hint: Use --file with JSON or --raw-file for plain text. Get promp
|
|
|
1861
2035
|
if (promptContent && !isJson) {
|
|
1862
2036
|
warnSingleBraceVariables(promptContent, output);
|
|
1863
2037
|
}
|
|
1864
|
-
if (
|
|
1865
|
-
|
|
2038
|
+
if (!isJson && isSchemaEmpty(data.inputSchema)) {
|
|
2039
|
+
if (process.stdin.isTTY) {
|
|
2040
|
+
const schema = await promptForInputSchema();
|
|
2041
|
+
if (schema) {
|
|
2042
|
+
data.inputSchema = schema;
|
|
2043
|
+
}
|
|
2044
|
+
} else {
|
|
2045
|
+
output.warn("No inputSchema provided. Optimization requires inputSchema with defined variables.");
|
|
2046
|
+
}
|
|
1866
2047
|
}
|
|
2048
|
+
warnMissingSchemas(data, output);
|
|
1867
2049
|
const client = getSDKClient();
|
|
1868
2050
|
const prompt = await client.createPrompt(data);
|
|
1869
2051
|
if (isJson) {
|
|
1870
2052
|
output.output({ ...prompt, _links: promptLinks(prompt.id) });
|
|
1871
2053
|
} else {
|
|
1872
|
-
output.success(`Created prompt: ${prompt.name}`);
|
|
1873
|
-
|
|
1874
|
-
|
|
2054
|
+
output.success(`Created prompt: ${prompt.name} (id: ${String(prompt.id)})`);
|
|
2055
|
+
const hints = formatCreationHints({
|
|
2056
|
+
resourceType: "Prompt",
|
|
2057
|
+
id: prompt.id,
|
|
2058
|
+
name: prompt.name,
|
|
2059
|
+
dashboardUrl: promptLink(prompt.id),
|
|
2060
|
+
apiPath: `/api/prompts/${String(prompt.id)}`
|
|
2061
|
+
});
|
|
2062
|
+
console.log(hints);
|
|
1875
2063
|
}
|
|
1876
2064
|
} catch (error) {
|
|
1877
2065
|
handleError(error, isJson);
|
|
@@ -1933,16 +2121,20 @@ Examples:
|
|
|
1933
2121
|
if (promptContent && !isJson) {
|
|
1934
2122
|
warnSingleBraceVariables(promptContent, output);
|
|
1935
2123
|
}
|
|
1936
|
-
if (options.file && isMissingOutputSchema(data)) {
|
|
1937
|
-
warnMissingOutputSchema(output);
|
|
1938
|
-
}
|
|
1939
2124
|
const client = getSDKClient();
|
|
1940
2125
|
const prompt = await client.updatePrompt(id, data);
|
|
1941
2126
|
if (isJson) {
|
|
1942
2127
|
output.output({ ...prompt, _links: promptLinks(prompt.id) });
|
|
1943
2128
|
} else {
|
|
1944
|
-
output.success(`Updated prompt: ${prompt.name}`);
|
|
1945
|
-
|
|
2129
|
+
output.success(`Updated prompt: ${prompt.name} (id: ${String(prompt.id)})`);
|
|
2130
|
+
const hints = formatCreationHints({
|
|
2131
|
+
resourceType: "Prompt",
|
|
2132
|
+
id: prompt.id,
|
|
2133
|
+
name: prompt.name,
|
|
2134
|
+
dashboardUrl: promptLink(prompt.id),
|
|
2135
|
+
apiPath: `/api/prompts/${String(prompt.id)}`
|
|
2136
|
+
});
|
|
2137
|
+
console.log(hints);
|
|
1946
2138
|
}
|
|
1947
2139
|
} catch (error) {
|
|
1948
2140
|
handleError(error, isJson);
|
|
@@ -1998,7 +2190,7 @@ Examples:
|
|
|
1998
2190
|
if (isJson) {
|
|
1999
2191
|
const withLinks = datasets.map((d) => ({
|
|
2000
2192
|
...d,
|
|
2001
|
-
_links:
|
|
2193
|
+
_links: datasetLinks(promptId, d.id)
|
|
2002
2194
|
}));
|
|
2003
2195
|
output.output(withLinks);
|
|
2004
2196
|
} else {
|
|
@@ -2059,13 +2251,25 @@ ${chalk4.dim("Note: --file and -d are mutually exclusive. Provide one or the oth
|
|
|
2059
2251
|
}
|
|
2060
2252
|
const client = getSDKClient();
|
|
2061
2253
|
const datasetResult = await client.addDataset(promptId, content, options.name);
|
|
2062
|
-
if (
|
|
2063
|
-
output.
|
|
2254
|
+
if (isJson) {
|
|
2255
|
+
output.output({
|
|
2256
|
+
...datasetResult,
|
|
2257
|
+
_links: datasetLinks(promptId, datasetResult.id)
|
|
2258
|
+
});
|
|
2259
|
+
} else {
|
|
2260
|
+
output.success(`Added dataset "${datasetResult.name}" to prompt: ${promptId} (id: ${String(datasetResult.id)})`);
|
|
2064
2261
|
if (datasetResult.itemCount !== undefined && datasetResult.itemCount > 0) {
|
|
2065
2262
|
output.info(`Items uploaded: ${String(datasetResult.itemCount)}`);
|
|
2066
2263
|
}
|
|
2264
|
+
const hints = formatCreationHints({
|
|
2265
|
+
resourceType: "Dataset",
|
|
2266
|
+
id: datasetResult.id,
|
|
2267
|
+
name: datasetResult.name,
|
|
2268
|
+
dashboardUrl: datasetLink(promptId, datasetResult.id),
|
|
2269
|
+
apiPath: `/api/prompts/${promptId}/datasets/${String(datasetResult.id)}`
|
|
2270
|
+
});
|
|
2271
|
+
console.log(hints);
|
|
2067
2272
|
}
|
|
2068
|
-
output.output(datasetResult);
|
|
2069
2273
|
} catch (error) {
|
|
2070
2274
|
handleError(error, isJson);
|
|
2071
2275
|
}
|
|
@@ -2104,7 +2308,7 @@ Examples:
|
|
|
2104
2308
|
if (isJson) {
|
|
2105
2309
|
const withLinks = evals.map((e) => ({
|
|
2106
2310
|
...e,
|
|
2107
|
-
_links:
|
|
2311
|
+
_links: evaluationLinks(promptId, e.id)
|
|
2108
2312
|
}));
|
|
2109
2313
|
output.output(withLinks);
|
|
2110
2314
|
} else {
|
|
@@ -2167,12 +2371,18 @@ ${chalk4.dim("Get prompt IDs: mutagent prompts list | Get dataset IDs: mutagent
|
|
|
2167
2371
|
if (isJson) {
|
|
2168
2372
|
output.output({
|
|
2169
2373
|
...evalResult,
|
|
2170
|
-
_links:
|
|
2374
|
+
_links: evaluationLinks(promptId, evalResult.id)
|
|
2171
2375
|
});
|
|
2172
2376
|
} else {
|
|
2173
|
-
output.success(`Created evaluation: ${evalResult.name}`);
|
|
2174
|
-
|
|
2175
|
-
|
|
2377
|
+
output.success(`Created evaluation: ${evalResult.name} (id: ${String(evalResult.id)})`);
|
|
2378
|
+
const hints = formatCreationHints({
|
|
2379
|
+
resourceType: "Evaluation",
|
|
2380
|
+
id: evalResult.id,
|
|
2381
|
+
name: evalResult.name,
|
|
2382
|
+
dashboardUrl: evaluationLink(promptId, evalResult.id),
|
|
2383
|
+
apiPath: `/api/prompts/${promptId}/evaluations/${String(evalResult.id)}`
|
|
2384
|
+
});
|
|
2385
|
+
console.log(hints);
|
|
2176
2386
|
}
|
|
2177
2387
|
} catch (error) {
|
|
2178
2388
|
handleError(error, isJson);
|
|
@@ -2215,12 +2425,6 @@ ${chalk4.dim("Monitor progress with: mutagent prompts optimize status <job-id>")
|
|
|
2215
2425
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
2216
2426
|
try {
|
|
2217
2427
|
const client = getSDKClient();
|
|
2218
|
-
try {
|
|
2219
|
-
const promptData = await client.getPrompt(promptId);
|
|
2220
|
-
if (isMissingOutputSchema(promptData)) {
|
|
2221
|
-
output.warn("This prompt has no outputSchema defined. Optimization jobs require an outputSchema to validate outputs. " + "The job may fail at the dataset analysis stage. " + "Add an outputSchema via: mutagent prompts update " + promptId + " --file prompt-with-schema.json");
|
|
2222
|
-
}
|
|
2223
|
-
} catch {}
|
|
2224
2428
|
const job = await client.startOptimization(promptId, options.dataset, {
|
|
2225
2429
|
maxIterations: options.maxIterations ? parseInt(options.maxIterations, 10) : undefined,
|
|
2226
2430
|
targetScore: options.targetScore ? parseFloat(options.targetScore) : undefined,
|
|
@@ -2229,11 +2433,22 @@ ${chalk4.dim("Monitor progress with: mutagent prompts optimize status <job-id>")
|
|
|
2229
2433
|
evalModel: options.evalModel
|
|
2230
2434
|
});
|
|
2231
2435
|
if (isJson) {
|
|
2232
|
-
output.output({
|
|
2436
|
+
output.output({
|
|
2437
|
+
...job,
|
|
2438
|
+
_links: {
|
|
2439
|
+
dashboard: optimizerLink(job.jobId),
|
|
2440
|
+
api: `/api/prompts/${promptId}/optimizations/${job.jobId}`
|
|
2441
|
+
}
|
|
2442
|
+
});
|
|
2233
2443
|
} else {
|
|
2234
2444
|
output.success(`Started optimization job: ${job.jobId}`);
|
|
2235
|
-
|
|
2236
|
-
|
|
2445
|
+
const hints = formatCreationHints({
|
|
2446
|
+
resourceType: "Optimization",
|
|
2447
|
+
id: job.jobId,
|
|
2448
|
+
dashboardUrl: optimizerLink(job.jobId),
|
|
2449
|
+
apiPath: `/api/prompts/${promptId}/optimizations/${job.jobId}`
|
|
2450
|
+
});
|
|
2451
|
+
console.log(hints);
|
|
2237
2452
|
}
|
|
2238
2453
|
} catch (error) {
|
|
2239
2454
|
if (error instanceof ApiError) {
|
|
@@ -4968,5 +5183,5 @@ program.addCommand(createWorkspacesCommand());
|
|
|
4968
5183
|
program.addCommand(createProvidersCommand());
|
|
4969
5184
|
program.parse();
|
|
4970
5185
|
|
|
4971
|
-
//# debugId=
|
|
5186
|
+
//# debugId=EDFE2E68EFA4B20A64756E2164756E21
|
|
4972
5187
|
//# sourceMappingURL=cli.js.map
|