@mutagent/cli 0.1.12 → 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 +260 -22
- 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,6 +1733,117 @@ function parseValidationErrors(error) {
|
|
|
1659
1733
|
}
|
|
1660
1734
|
return ["An unknown error occurred"];
|
|
1661
1735
|
}
|
|
1736
|
+
function isSchemaEmpty(schema) {
|
|
1737
|
+
if (schema === undefined || schema === null)
|
|
1738
|
+
return true;
|
|
1739
|
+
if (typeof schema !== "object")
|
|
1740
|
+
return false;
|
|
1741
|
+
const obj = schema;
|
|
1742
|
+
if (Object.keys(obj).length === 0)
|
|
1743
|
+
return true;
|
|
1744
|
+
return false;
|
|
1745
|
+
}
|
|
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;
|
|
1846
|
+
}
|
|
1662
1847
|
function warnSingleBraceVariables(content, output) {
|
|
1663
1848
|
const singleBracePattern = /(?<!\{)\{([a-zA-Z_][a-zA-Z0-9_]*)\}(?!\})/g;
|
|
1664
1849
|
const matches = [...content.matchAll(singleBracePattern)];
|
|
@@ -1850,14 +2035,31 @@ ${chalk4.dim("Hint: Use --file with JSON or --raw-file for plain text. Get promp
|
|
|
1850
2035
|
if (promptContent && !isJson) {
|
|
1851
2036
|
warnSingleBraceVariables(promptContent, output);
|
|
1852
2037
|
}
|
|
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
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
warnMissingSchemas(data, output);
|
|
1853
2049
|
const client = getSDKClient();
|
|
1854
2050
|
const prompt = await client.createPrompt(data);
|
|
1855
2051
|
if (isJson) {
|
|
1856
2052
|
output.output({ ...prompt, _links: promptLinks(prompt.id) });
|
|
1857
2053
|
} else {
|
|
1858
|
-
output.success(`Created prompt: ${prompt.name}`);
|
|
1859
|
-
|
|
1860
|
-
|
|
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);
|
|
1861
2063
|
}
|
|
1862
2064
|
} catch (error) {
|
|
1863
2065
|
handleError(error, isJson);
|
|
@@ -1924,8 +2126,15 @@ Examples:
|
|
|
1924
2126
|
if (isJson) {
|
|
1925
2127
|
output.output({ ...prompt, _links: promptLinks(prompt.id) });
|
|
1926
2128
|
} else {
|
|
1927
|
-
output.success(`Updated prompt: ${prompt.name}`);
|
|
1928
|
-
|
|
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);
|
|
1929
2138
|
}
|
|
1930
2139
|
} catch (error) {
|
|
1931
2140
|
handleError(error, isJson);
|
|
@@ -1981,7 +2190,7 @@ Examples:
|
|
|
1981
2190
|
if (isJson) {
|
|
1982
2191
|
const withLinks = datasets.map((d) => ({
|
|
1983
2192
|
...d,
|
|
1984
|
-
_links:
|
|
2193
|
+
_links: datasetLinks(promptId, d.id)
|
|
1985
2194
|
}));
|
|
1986
2195
|
output.output(withLinks);
|
|
1987
2196
|
} else {
|
|
@@ -2042,13 +2251,25 @@ ${chalk4.dim("Note: --file and -d are mutually exclusive. Provide one or the oth
|
|
|
2042
2251
|
}
|
|
2043
2252
|
const client = getSDKClient();
|
|
2044
2253
|
const datasetResult = await client.addDataset(promptId, content, options.name);
|
|
2045
|
-
if (
|
|
2046
|
-
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)})`);
|
|
2047
2261
|
if (datasetResult.itemCount !== undefined && datasetResult.itemCount > 0) {
|
|
2048
2262
|
output.info(`Items uploaded: ${String(datasetResult.itemCount)}`);
|
|
2049
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);
|
|
2050
2272
|
}
|
|
2051
|
-
output.output(datasetResult);
|
|
2052
2273
|
} catch (error) {
|
|
2053
2274
|
handleError(error, isJson);
|
|
2054
2275
|
}
|
|
@@ -2087,7 +2308,7 @@ Examples:
|
|
|
2087
2308
|
if (isJson) {
|
|
2088
2309
|
const withLinks = evals.map((e) => ({
|
|
2089
2310
|
...e,
|
|
2090
|
-
_links:
|
|
2311
|
+
_links: evaluationLinks(promptId, e.id)
|
|
2091
2312
|
}));
|
|
2092
2313
|
output.output(withLinks);
|
|
2093
2314
|
} else {
|
|
@@ -2150,12 +2371,18 @@ ${chalk4.dim("Get prompt IDs: mutagent prompts list | Get dataset IDs: mutagent
|
|
|
2150
2371
|
if (isJson) {
|
|
2151
2372
|
output.output({
|
|
2152
2373
|
...evalResult,
|
|
2153
|
-
_links:
|
|
2374
|
+
_links: evaluationLinks(promptId, evalResult.id)
|
|
2154
2375
|
});
|
|
2155
2376
|
} else {
|
|
2156
|
-
output.success(`Created evaluation: ${evalResult.name}`);
|
|
2157
|
-
|
|
2158
|
-
|
|
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);
|
|
2159
2386
|
}
|
|
2160
2387
|
} catch (error) {
|
|
2161
2388
|
handleError(error, isJson);
|
|
@@ -2206,11 +2433,22 @@ ${chalk4.dim("Monitor progress with: mutagent prompts optimize status <job-id>")
|
|
|
2206
2433
|
evalModel: options.evalModel
|
|
2207
2434
|
});
|
|
2208
2435
|
if (isJson) {
|
|
2209
|
-
output.output({
|
|
2436
|
+
output.output({
|
|
2437
|
+
...job,
|
|
2438
|
+
_links: {
|
|
2439
|
+
dashboard: optimizerLink(job.jobId),
|
|
2440
|
+
api: `/api/prompts/${promptId}/optimizations/${job.jobId}`
|
|
2441
|
+
}
|
|
2442
|
+
});
|
|
2210
2443
|
} else {
|
|
2211
2444
|
output.success(`Started optimization job: ${job.jobId}`);
|
|
2212
|
-
|
|
2213
|
-
|
|
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);
|
|
2214
2452
|
}
|
|
2215
2453
|
} catch (error) {
|
|
2216
2454
|
if (error instanceof ApiError) {
|
|
@@ -4945,5 +5183,5 @@ program.addCommand(createWorkspacesCommand());
|
|
|
4945
5183
|
program.addCommand(createProvidersCommand());
|
|
4946
5184
|
program.parse();
|
|
4947
5185
|
|
|
4948
|
-
//# debugId=
|
|
5186
|
+
//# debugId=EDFE2E68EFA4B20A64756E2164756E21
|
|
4949
5187
|
//# sourceMappingURL=cli.js.map
|