@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 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
- view: promptLink(promptId),
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 isMissingOutputSchema(data) {
1663
- const schema = data.outputSchema;
1664
- if (schema === null || schema === undefined)
1736
+ function isSchemaEmpty(schema) {
1737
+ if (schema === undefined || schema === null)
1665
1738
  return true;
1666
- if (typeof schema === "object" && Object.keys(schema).length === 0)
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 warnMissingOutputSchema(output) {
1671
- output.warn("No outputSchema provided. Optimization jobs require an outputSchema to validate outputs. " + "Prompts without outputSchema cannot be optimized.");
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 (isMissingOutputSchema(data)) {
1865
- warnMissingOutputSchema(output);
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
- output.output(prompt);
1874
- output.info(`View: ${promptLink(prompt.id)}`);
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
- output.output(prompt);
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: { view: datasetLink(promptId, d.id) }
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 (!isJson) {
2063
- output.success(`Added dataset "${datasetResult.name}" to prompt: ${promptId}`);
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: { view: evaluationLink(promptId, e.id) }
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: { view: evaluationLink(promptId, evalResult.id) }
2374
+ _links: evaluationLinks(promptId, evalResult.id)
2171
2375
  });
2172
2376
  } else {
2173
- output.success(`Created evaluation: ${evalResult.name}`);
2174
- output.output(evalResult);
2175
- output.info(`View: ${evaluationLink(promptId, evalResult.id)}`);
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({ ...job, _links: { optimizer: optimizerLink(job.jobId) } });
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
- output.output(job);
2236
- output.info(`Monitor: ${optimizerLink(job.jobId)}`);
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=33AA6EB433FA7E6264756E2164756E21
5186
+ //# debugId=EDFE2E68EFA4B20A64756E2164756E21
4972
5187
  //# sourceMappingURL=cli.js.map